Skip to content

Commit 443fc29

Browse files
committed
fix: Fix build scripts not being rebuilt in some occasions
1 parent 9279c65 commit 443fc29

File tree

15 files changed

+102
-70
lines changed

15 files changed

+102
-70
lines changed

crates/hir-def/src/nameres/collector.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeI
9999
};
100100
(
101101
name.as_name(),
102-
CustomProcMacroExpander::new(hir_expand::proc_macro::ProcMacroId(
102+
CustomProcMacroExpander::new(hir_expand::proc_macro::ProcMacroId::new(
103103
idx as u32,
104104
)),
105105
)

crates/hir-expand/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -220,8 +220,8 @@ pub enum MacroCallKind {
220220
},
221221
Attr {
222222
ast_id: AstId<ast::Item>,
223-
// FIXME: This is being interned, subtrees can very quickly differ just slightly causing
224-
// leakage problems here
223+
// FIXME: This shouldn't be here, we can derive this from `invoc_attr_index`
224+
// but we need to fix the `cfg_attr` handling first.
225225
attr_args: Option<Arc<tt::Subtree>>,
226226
/// Syntactical index of the invoking `#[attribute]`.
227227
///

crates/hir-expand/src/proc_macro.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,13 @@ use syntax::SmolStr;
1212
use crate::{db::ExpandDatabase, tt, ExpandError, ExpandResult};
1313

1414
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
15-
pub struct ProcMacroId(pub u32);
15+
pub struct ProcMacroId(u32);
16+
17+
impl ProcMacroId {
18+
pub fn new(u32: u32) -> Self {
19+
ProcMacroId(u32)
20+
}
21+
}
1622

1723
#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
1824
pub enum ProcMacroKind {

crates/project-model/src/build_scripts.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use serde::Deserialize;
2323

2424
use crate::{
2525
cfg_flag::CfgFlag, utf8_stdout, CargoConfig, CargoFeatures, CargoWorkspace, InvocationLocation,
26-
InvocationStrategy, Package,
26+
InvocationStrategy, Package, TargetKind,
2727
};
2828

2929
#[derive(Debug, Default, Clone, PartialEq, Eq)]
@@ -445,7 +445,11 @@ impl WorkspaceBuildScripts {
445445
.collect();
446446
for p in rustc.packages() {
447447
let package = &rustc[p];
448-
if package.targets.iter().any(|&it| rustc[it].is_proc_macro) {
448+
if package
449+
.targets
450+
.iter()
451+
.any(|&it| matches!(rustc[it].kind, TargetKind::Lib { is_proc_macro: true }))
452+
{
449453
if let Some((_, path)) = proc_macro_dylibs
450454
.iter()
451455
.find(|(name, _)| *name.trim_start_matches("lib") == package.name)

crates/project-model/src/cargo_workspace.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,6 @@ pub struct TargetData {
186186
pub root: AbsPathBuf,
187187
/// Kind of target
188188
pub kind: TargetKind,
189-
/// Is this target a proc-macro
190-
pub is_proc_macro: bool,
191189
/// Required features of the target without which it won't build
192190
pub required_features: Vec<String>,
193191
}
@@ -196,7 +194,10 @@ pub struct TargetData {
196194
pub enum TargetKind {
197195
Bin,
198196
/// Any kind of Cargo lib crate-type (dylib, rlib, proc-macro, ...).
199-
Lib,
197+
Lib {
198+
/// Is this target a proc-macro
199+
is_proc_macro: bool,
200+
},
200201
Example,
201202
Test,
202203
Bench,
@@ -213,8 +214,8 @@ impl TargetKind {
213214
"bench" => TargetKind::Bench,
214215
"example" => TargetKind::Example,
215216
"custom-build" => TargetKind::BuildScript,
216-
"proc-macro" => TargetKind::Lib,
217-
_ if kind.contains("lib") => TargetKind::Lib,
217+
"proc-macro" => TargetKind::Lib { is_proc_macro: true },
218+
_ if kind.contains("lib") => TargetKind::Lib { is_proc_macro: false },
218219
_ => continue,
219220
};
220221
}
@@ -366,7 +367,6 @@ impl CargoWorkspace {
366367
name,
367368
root: AbsPathBuf::assert(src_path.into()),
368369
kind: TargetKind::new(&kind),
369-
is_proc_macro: &*kind == ["proc-macro"],
370370
required_features,
371371
});
372372
pkg_data.targets.push(tgt);

crates/project-model/src/workspace.rs

+19-19
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ impl ProjectWorkspace {
547547
let extra_targets = cargo[pkg]
548548
.targets
549549
.iter()
550-
.filter(|&&tgt| cargo[tgt].kind == TargetKind::Lib)
550+
.filter(|&&tgt| matches!(cargo[tgt].kind, TargetKind::Lib { .. }))
551551
.filter_map(|&tgt| cargo[tgt].root.parent())
552552
.map(|tgt| tgt.normalize().to_path_buf())
553553
.filter(|path| !path.starts_with(&pkg_root));
@@ -912,17 +912,17 @@ fn cargo_to_crate_graph(
912912

913913
let mut lib_tgt = None;
914914
for &tgt in cargo[pkg].targets.iter() {
915-
if cargo[tgt].kind != TargetKind::Lib && !cargo[pkg].is_member {
915+
if !matches!(cargo[tgt].kind, TargetKind::Lib { .. }) && !cargo[pkg].is_member {
916916
// For non-workspace-members, Cargo does not resolve dev-dependencies, so we don't
917917
// add any targets except the library target, since those will not work correctly if
918918
// they use dev-dependencies.
919919
// In fact, they can break quite badly if multiple client workspaces get merged:
920920
// https://github.com/rust-lang/rust-analyzer/issues/11300
921921
continue;
922922
}
923-
let &TargetData { ref name, kind, is_proc_macro, ref root, .. } = &cargo[tgt];
923+
let &TargetData { ref name, kind, ref root, .. } = &cargo[tgt];
924924

925-
if kind == TargetKind::Lib
925+
if matches!(kind, TargetKind::Lib { .. })
926926
&& sysroot.map_or(false, |sysroot| root.starts_with(sysroot.src_root()))
927927
{
928928
if let Some(&(_, crate_id, _)) =
@@ -947,19 +947,24 @@ fn cargo_to_crate_graph(
947947
cfg_options.clone(),
948948
file_id,
949949
name,
950-
is_proc_macro,
950+
kind,
951951
target_layout.clone(),
952952
false,
953953
toolchain.cloned(),
954954
);
955-
if kind == TargetKind::Lib {
955+
if let TargetKind::Lib { .. } = kind {
956956
lib_tgt = Some((crate_id, name.clone()));
957957
pkg_to_lib_crate.insert(pkg, crate_id);
958958
}
959959
// Even crates that don't set proc-macro = true are allowed to depend on proc_macro
960960
// (just none of the APIs work when called outside of a proc macro).
961961
if let Some(proc_macro) = libproc_macro {
962-
add_proc_macro_dep(crate_graph, crate_id, proc_macro, is_proc_macro);
962+
add_proc_macro_dep(
963+
crate_graph,
964+
crate_id,
965+
proc_macro,
966+
matches!(kind, TargetKind::Lib { is_proc_macro: true }),
967+
);
963968
}
964969

965970
pkg_crates.entry(pkg).or_insert_with(Vec::new).push((crate_id, kind));
@@ -1157,9 +1162,9 @@ fn handle_rustc_crates(
11571162
};
11581163

11591164
for &tgt in rustc_workspace[pkg].targets.iter() {
1160-
if rustc_workspace[tgt].kind != TargetKind::Lib {
1165+
let kind @ TargetKind::Lib { is_proc_macro } = rustc_workspace[tgt].kind else {
11611166
continue;
1162-
}
1167+
};
11631168
if let Some(file_id) = load(&rustc_workspace[tgt].root) {
11641169
let crate_id = add_target_crate_root(
11651170
crate_graph,
@@ -1169,7 +1174,7 @@ fn handle_rustc_crates(
11691174
cfg_options.clone(),
11701175
file_id,
11711176
&rustc_workspace[tgt].name,
1172-
rustc_workspace[tgt].is_proc_macro,
1177+
kind,
11731178
target_layout.clone(),
11741179
true,
11751180
toolchain.cloned(),
@@ -1178,12 +1183,7 @@ fn handle_rustc_crates(
11781183
// Add dependencies on core / std / alloc for this crate
11791184
public_deps.add_to_crate_graph(crate_graph, crate_id);
11801185
if let Some(proc_macro) = libproc_macro {
1181-
add_proc_macro_dep(
1182-
crate_graph,
1183-
crate_id,
1184-
proc_macro,
1185-
rustc_workspace[tgt].is_proc_macro,
1186-
);
1186+
add_proc_macro_dep(crate_graph, crate_id, proc_macro, is_proc_macro);
11871187
}
11881188
rustc_pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id);
11891189
}
@@ -1245,7 +1245,7 @@ fn add_target_crate_root(
12451245
cfg_options: CfgOptions,
12461246
file_id: FileId,
12471247
cargo_name: &str,
1248-
is_proc_macro: bool,
1248+
kind: TargetKind,
12491249
target_layout: TargetLayoutLoadResult,
12501250
rustc_crate: bool,
12511251
toolchain: Option<Version>,
@@ -1295,7 +1295,7 @@ fn add_target_crate_root(
12951295
cfg_options,
12961296
potential_cfg_options,
12971297
env,
1298-
is_proc_macro,
1298+
matches!(kind, TargetKind::Lib { is_proc_macro: true }),
12991299
if rustc_crate {
13001300
CrateOrigin::Rustc { name: pkg.name.clone() }
13011301
} else if pkg.is_member {
@@ -1306,7 +1306,7 @@ fn add_target_crate_root(
13061306
target_layout,
13071307
toolchain,
13081308
);
1309-
if is_proc_macro {
1309+
if let TargetKind::Lib { is_proc_macro: true } = kind {
13101310
let proc_macro = match build_data.as_ref().map(|it| it.proc_macro_dylib_path.as_ref()) {
13111311
Some(it) => it.cloned().map(|path| Ok((Some(cargo_name.to_owned()), path))),
13121312
None => Some(Err("crate has not yet been built".to_owned())),

crates/rust-analyzer/src/cargo_target_spec.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ impl CargoTargetSpec {
174174
buf.push("--example".to_owned());
175175
buf.push(self.target);
176176
}
177-
TargetKind::Lib => {
177+
TargetKind::Lib { is_proc_macro: _ } => {
178178
buf.push("--lib".to_owned());
179179
}
180180
TargetKind::Other | TargetKind::BuildScript => (),

crates/rust-analyzer/src/config.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ config_data! {
111111
cargo_buildScripts_overrideCommand: Option<Vec<String>> = "null",
112112
/// Rerun proc-macros building/build-scripts running when proc-macro
113113
/// or build-script sources change and are saved.
114-
cargo_buildScripts_rebuildOnSave: bool = "false",
114+
cargo_buildScripts_rebuildOnSave: bool = "true",
115115
/// Use `RUSTC_WRAPPER=rust-analyzer` when running build scripts to
116116
/// avoid checking unnecessary things.
117117
cargo_buildScripts_useRustcWrapper: bool = "true",

crates/rust-analyzer/src/global_state.rs

+28-11
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ use crossbeam_channel::{unbounded, Receiver, Sender};
99
use flycheck::FlycheckHandle;
1010
use hir::Change;
1111
use ide::{Analysis, AnalysisHost, Cancellable, FileId};
12-
use ide_db::base_db::{CrateId, FileLoader, ProcMacroPaths, SourceDatabase};
12+
use ide_db::base_db::{
13+
salsa::ParallelDatabase, CrateId, FileLoader, ProcMacroPaths, SourceDatabase,
14+
};
1315
use load_cargo::SourceRootConfig;
1416
use lsp_types::{SemanticTokens, Url};
1517
use nohash_hasher::IntMap;
@@ -74,9 +76,11 @@ pub(crate) struct GlobalState {
7476
pub(crate) last_reported_status: Option<lsp_ext::ServerStatusParams>,
7577

7678
// proc macros
77-
pub(crate) proc_macro_changed: bool,
7879
pub(crate) proc_macro_clients: Arc<[anyhow::Result<ProcMacroServer>]>,
7980

81+
// build scripts
82+
pub(crate) build_script_changed: bool,
83+
8084
// Flycheck
8185
pub(crate) flycheck: Arc<[FlycheckHandle]>,
8286
pub(crate) flycheck_sender: Sender<flycheck::Message>,
@@ -187,9 +191,10 @@ impl GlobalState {
187191
source_root_config: SourceRootConfig::default(),
188192
config_errors: Default::default(),
189193

190-
proc_macro_changed: false,
191194
proc_macro_clients: Arc::from_iter([]),
192195

196+
build_script_changed: false,
197+
193198
flycheck: Arc::from_iter([]),
194199
flycheck_sender,
195200
flycheck_receiver,
@@ -287,6 +292,9 @@ impl GlobalState {
287292
if reload::should_refresh_for_change(&path, file.change_kind) {
288293
workspace_structure_change = Some((path.clone(), false));
289294
}
295+
if AsRef::<std::path::Path>::as_ref(&path).ends_with("build.rs") {
296+
self.build_script_changed = true;
297+
}
290298
if file.is_created_or_deleted() {
291299
has_structure_changes = true;
292300
workspace_structure_change =
@@ -333,7 +341,6 @@ impl GlobalState {
333341
self.analysis_host.apply_change(change);
334342

335343
{
336-
let raw_database = self.analysis_host.raw_database();
337344
// FIXME: ideally we should only trigger a workspace fetch for non-library changes
338345
// but something's going wrong with the source root business when we add a new local
339346
// crate see https://github.com/rust-lang/rust-analyzer/issues/13029
@@ -343,13 +350,23 @@ impl GlobalState {
343350
force_crate_graph_reload,
344351
);
345352
}
346-
self.proc_macro_changed =
347-
changed_files.iter().filter(|file| !file.is_created_or_deleted()).any(|file| {
348-
let crates = raw_database.relevant_crates(file.file_id);
349-
let crate_graph = raw_database.crate_graph();
350-
351-
crates.iter().any(|&krate| crate_graph[krate].is_proc_macro)
352-
});
353+
self.task_pool.handle.spawn(stdx::thread::ThreadIntent::Worker, {
354+
let db = self.analysis_host.raw_database().snapshot();
355+
move || {
356+
Task::BuildScriptsMayHaveChanged(
357+
changed_files.iter().filter(|file| !file.is_created_or_deleted()).any(
358+
|file| {
359+
// FIXME: We should check for build script related changes as well
360+
// but thats a lot more tricky to pull off.
361+
let crates = db.relevant_crates(file.file_id);
362+
let crate_graph = db.crate_graph();
363+
364+
crates.iter().any(|&krate| crate_graph[krate].is_proc_macro)
365+
},
366+
),
367+
)
368+
}
369+
});
353370
}
354371

355372
true

crates/rust-analyzer/src/handlers/notification.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -130,11 +130,9 @@ pub(crate) fn handle_did_save_text_document(
130130
state: &mut GlobalState,
131131
params: DidSaveTextDocumentParams,
132132
) -> anyhow::Result<()> {
133-
if state.config.script_rebuild_on_save() && state.proc_macro_changed {
134-
// reset the flag
135-
state.proc_macro_changed = false;
136-
// rebuild the proc macros
137-
state.fetch_build_data_queue.request_op("ScriptRebuildOnSave".to_owned(), ());
133+
if state.config.script_rebuild_on_save() && state.build_script_changed {
134+
state.build_script_changed = false;
135+
state.fetch_build_data_queue.request_op("buildScriptsRebuildOnSave".to_owned(), ());
138136
}
139137

140138
if let Ok(vfs_path) = from_proto::vfs_path(&params.text_document.uri) {
@@ -143,7 +141,7 @@ pub(crate) fn handle_did_save_text_document(
143141
if reload::should_refresh_for_change(abs_path, ChangeKind::Modify) {
144142
state
145143
.fetch_workspaces_queue
146-
.request_op(format!("DidSaveTextDocument {abs_path}"), false);
144+
.request_op(format!("workspace vfs file change saved {abs_path}"), false);
147145
}
148146
}
149147

@@ -221,7 +219,7 @@ pub(crate) fn handle_did_change_workspace_folders(
221219

222220
if !config.has_linked_projects() && config.detached_files().is_empty() {
223221
config.rediscover_workspaces();
224-
state.fetch_workspaces_queue.request_op("client workspaces changed".to_string(), false)
222+
state.fetch_workspaces_queue.request_op("workspaces folders changed".to_string(), false)
225223
}
226224

227225
Ok(())

crates/rust-analyzer/src/handlers/request.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,15 @@ use crate::{
5252

5353
pub(crate) fn handle_workspace_reload(state: &mut GlobalState, _: ()) -> anyhow::Result<()> {
5454
state.proc_macro_clients = Arc::from_iter([]);
55-
state.proc_macro_changed = false;
55+
state.build_script_changed = false;
5656

5757
state.fetch_workspaces_queue.request_op("reload workspace request".to_string(), false);
5858
Ok(())
5959
}
6060

6161
pub(crate) fn handle_proc_macros_rebuild(state: &mut GlobalState, _: ()) -> anyhow::Result<()> {
6262
state.proc_macro_clients = Arc::from_iter([]);
63-
state.proc_macro_changed = false;
63+
state.build_script_changed = false;
6464

6565
state.fetch_build_data_queue.request_op("rebuild proc macros request".to_string(), ());
6666
Ok(())

0 commit comments

Comments
 (0)