Skip to content

Commit 1e6cef9

Browse files
committed
fix: Fix build scripts not being rebuilt in some occasions
1 parent a02a219 commit 1e6cef9

File tree

16 files changed

+121
-77
lines changed

16 files changed

+121
-77
lines changed

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,9 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeI
101101
if it.disabled {
102102
CustomProcMacroExpander::disabled()
103103
} else {
104-
CustomProcMacroExpander::new(hir_expand::proc_macro::ProcMacroId(
105-
idx as u32,
106-
))
104+
CustomProcMacroExpander::new(
105+
hir_expand::proc_macro::ProcMacroId::new(idx as u32),
106+
)
107107
},
108108
)
109109
})
@@ -2354,7 +2354,7 @@ impl ModCollector<'_, '_> {
23542354
resolved_res.resolved_def.take_macros().map(|it| db.macro_def(it))
23552355
},
23562356
) {
2357-
// FIXME: if there were errors, this mightve been in the eager expansion from an
2357+
// FIXME: if there were errors, this might've been in the eager expansion from an
23582358
// unresolved macro, so we need to push this into late macro resolution. see fixme above
23592359
if res.err.is_none() {
23602360
// Legacy macros need to be expanded immediately, so that any macros they produce

crates/hir-expand/src/lib.rs

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

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/ide/src/parent_module.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<Na
5454
}
5555
}
5656

57-
/// Returns `Vec` for the same reason as `parent_module`
57+
/// This returns `Vec` because a module may be included from several places.
5858
pub(crate) fn crates_for(db: &RootDatabase, file_id: FileId) -> Vec<CrateId> {
5959
db.relevant_crates(file_id)
6060
.iter()

crates/project-model/src/build_scripts.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use toolchain::Tool;
2424

2525
use crate::{
2626
cfg_flag::CfgFlag, utf8_stdout, CargoConfig, CargoFeatures, CargoWorkspace, InvocationLocation,
27-
InvocationStrategy, Package, Sysroot,
27+
InvocationStrategy, Package, Sysroot, TargetKind,
2828
};
2929

3030
#[derive(Debug, Default, Clone, PartialEq, Eq)]
@@ -467,7 +467,11 @@ impl WorkspaceBuildScripts {
467467
.collect();
468468
for p in rustc.packages() {
469469
let package = &rustc[p];
470-
if package.targets.iter().any(|&it| rustc[it].is_proc_macro) {
470+
if package
471+
.targets
472+
.iter()
473+
.any(|&it| matches!(rustc[it].kind, TargetKind::Lib { is_proc_macro: true }))
474+
{
471475
if let Some((_, path)) = proc_macro_dylibs
472476
.iter()
473477
.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
@@ -189,8 +189,6 @@ pub struct TargetData {
189189
pub root: AbsPathBuf,
190190
/// Kind of target
191191
pub kind: TargetKind,
192-
/// Is this target a proc-macro
193-
pub is_proc_macro: bool,
194192
/// Required features of the target without which it won't build
195193
pub required_features: Vec<String>,
196194
}
@@ -199,7 +197,10 @@ pub struct TargetData {
199197
pub enum TargetKind {
200198
Bin,
201199
/// Any kind of Cargo lib crate-type (dylib, rlib, proc-macro, ...).
202-
Lib,
200+
Lib {
201+
/// Is this target a proc-macro
202+
is_proc_macro: bool,
203+
},
203204
Example,
204205
Test,
205206
Bench,
@@ -216,8 +217,8 @@ impl TargetKind {
216217
"bench" => TargetKind::Bench,
217218
"example" => TargetKind::Example,
218219
"custom-build" => TargetKind::BuildScript,
219-
"proc-macro" => TargetKind::Lib,
220-
_ if kind.contains("lib") => TargetKind::Lib,
220+
"proc-macro" => TargetKind::Lib { is_proc_macro: true },
221+
_ if kind.contains("lib") => TargetKind::Lib { is_proc_macro: false },
221222
_ => continue,
222223
};
223224
}
@@ -370,7 +371,6 @@ impl CargoWorkspace {
370371
name,
371372
root: AbsPathBuf::assert(src_path.into()),
372373
kind: TargetKind::new(&kind),
373-
is_proc_macro: *kind == ["proc-macro"],
374374
required_features,
375375
});
376376
pkg_data.targets.push(tgt);

crates/project-model/src/workspace.rs

+18-18
Original file line numberDiff line numberDiff line change
@@ -619,7 +619,7 @@ impl ProjectWorkspace {
619619
let extra_targets = cargo[pkg]
620620
.targets
621621
.iter()
622-
.filter(|&&tgt| cargo[tgt].kind == TargetKind::Lib)
622+
.filter(|&&tgt| matches!(cargo[tgt].kind, TargetKind::Lib { .. }))
623623
.filter_map(|&tgt| cargo[tgt].root.parent())
624624
.map(|tgt| tgt.normalize().to_path_buf())
625625
.filter(|path| !path.starts_with(&pkg_root));
@@ -985,15 +985,15 @@ fn cargo_to_crate_graph(
985985

986986
let mut lib_tgt = None;
987987
for &tgt in cargo[pkg].targets.iter() {
988-
if cargo[tgt].kind != TargetKind::Lib && !cargo[pkg].is_member {
988+
if !matches!(cargo[tgt].kind, TargetKind::Lib { .. }) && !cargo[pkg].is_member {
989989
// For non-workspace-members, Cargo does not resolve dev-dependencies, so we don't
990990
// add any targets except the library target, since those will not work correctly if
991991
// they use dev-dependencies.
992992
// In fact, they can break quite badly if multiple client workspaces get merged:
993993
// https://github.com/rust-lang/rust-analyzer/issues/11300
994994
continue;
995995
}
996-
let &TargetData { ref name, kind, is_proc_macro, ref root, .. } = &cargo[tgt];
996+
let &TargetData { ref name, kind, ref root, .. } = &cargo[tgt];
997997

998998
let Some(file_id) = load(root) else { continue };
999999

@@ -1005,19 +1005,24 @@ fn cargo_to_crate_graph(
10051005
cfg_options.clone(),
10061006
file_id,
10071007
name,
1008-
is_proc_macro,
1008+
kind,
10091009
target_layout.clone(),
10101010
false,
10111011
toolchain.cloned(),
10121012
);
1013-
if kind == TargetKind::Lib {
1013+
if let TargetKind::Lib { .. } = kind {
10141014
lib_tgt = Some((crate_id, name.clone()));
10151015
pkg_to_lib_crate.insert(pkg, crate_id);
10161016
}
10171017
// Even crates that don't set proc-macro = true are allowed to depend on proc_macro
10181018
// (just none of the APIs work when called outside of a proc macro).
10191019
if let Some(proc_macro) = libproc_macro {
1020-
add_proc_macro_dep(crate_graph, crate_id, proc_macro, is_proc_macro);
1020+
add_proc_macro_dep(
1021+
crate_graph,
1022+
crate_id,
1023+
proc_macro,
1024+
matches!(kind, TargetKind::Lib { is_proc_macro: true }),
1025+
);
10211026
}
10221027

10231028
pkg_crates.entry(pkg).or_insert_with(Vec::new).push((crate_id, kind));
@@ -1215,9 +1220,9 @@ fn handle_rustc_crates(
12151220
};
12161221

12171222
for &tgt in rustc_workspace[pkg].targets.iter() {
1218-
if rustc_workspace[tgt].kind != TargetKind::Lib {
1223+
let kind @ TargetKind::Lib { is_proc_macro } = rustc_workspace[tgt].kind else {
12191224
continue;
1220-
}
1225+
};
12211226
if let Some(file_id) = load(&rustc_workspace[tgt].root) {
12221227
let crate_id = add_target_crate_root(
12231228
crate_graph,
@@ -1227,7 +1232,7 @@ fn handle_rustc_crates(
12271232
cfg_options.clone(),
12281233
file_id,
12291234
&rustc_workspace[tgt].name,
1230-
rustc_workspace[tgt].is_proc_macro,
1235+
kind,
12311236
target_layout.clone(),
12321237
true,
12331238
toolchain.cloned(),
@@ -1236,12 +1241,7 @@ fn handle_rustc_crates(
12361241
// Add dependencies on core / std / alloc for this crate
12371242
public_deps.add_to_crate_graph(crate_graph, crate_id);
12381243
if let Some(proc_macro) = libproc_macro {
1239-
add_proc_macro_dep(
1240-
crate_graph,
1241-
crate_id,
1242-
proc_macro,
1243-
rustc_workspace[tgt].is_proc_macro,
1244-
);
1244+
add_proc_macro_dep(crate_graph, crate_id, proc_macro, is_proc_macro);
12451245
}
12461246
rustc_pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id);
12471247
}
@@ -1303,7 +1303,7 @@ fn add_target_crate_root(
13031303
cfg_options: CfgOptions,
13041304
file_id: FileId,
13051305
cargo_name: &str,
1306-
is_proc_macro: bool,
1306+
kind: TargetKind,
13071307
target_layout: TargetLayoutLoadResult,
13081308
rustc_crate: bool,
13091309
toolchain: Option<Version>,
@@ -1353,7 +1353,7 @@ fn add_target_crate_root(
13531353
cfg_options,
13541354
potential_cfg_options,
13551355
env,
1356-
is_proc_macro,
1356+
matches!(kind, TargetKind::Lib { is_proc_macro: true }),
13571357
if rustc_crate {
13581358
CrateOrigin::Rustc { name: pkg.name.clone() }
13591359
} else if pkg.is_member {
@@ -1364,7 +1364,7 @@ fn add_target_crate_root(
13641364
target_layout,
13651365
toolchain,
13661366
);
1367-
if is_proc_macro {
1367+
if let TargetKind::Lib { is_proc_macro: true } = kind {
13681368
let proc_macro = match build_data.as_ref().map(|it| it.proc_macro_dylib_path.as_ref()) {
13691369
Some(it) => it.cloned().map(|path| Ok((Some(cargo_name.to_owned()), path))),
13701370
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
@@ -112,7 +112,7 @@ config_data! {
112112
cargo_buildScripts_overrideCommand: Option<Vec<String>> = "null",
113113
/// Rerun proc-macros building/build-scripts running when proc-macro
114114
/// or build-script sources change and are saved.
115-
cargo_buildScripts_rebuildOnSave: bool = "false",
115+
cargo_buildScripts_rebuildOnSave: bool = "true",
116116
/// Use `RUSTC_WRAPPER=rust-analyzer` when running build scripts to
117117
/// avoid checking unnecessary things.
118118
cargo_buildScripts_useRustcWrapper: bool = "true",

crates/rust-analyzer/src/global_state.rs

+27-14
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ 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::{CrateId, ProcMacroPaths};
1313
use load_cargo::SourceRootConfig;
1414
use lsp_types::{SemanticTokens, Url};
1515
use nohash_hasher::IntMap;
@@ -74,8 +74,8 @@ pub(crate) struct GlobalState {
7474
pub(crate) last_reported_status: Option<lsp_ext::ServerStatusParams>,
7575

7676
// proc macros
77-
pub(crate) proc_macro_changed: bool,
7877
pub(crate) proc_macro_clients: Arc<[anyhow::Result<ProcMacroServer>]>,
78+
pub(crate) build_deps_changed: bool,
7979

8080
// Flycheck
8181
pub(crate) flycheck: Arc<[FlycheckHandle]>,
@@ -203,9 +203,10 @@ impl GlobalState {
203203
source_root_config: SourceRootConfig::default(),
204204
config_errors: Default::default(),
205205

206-
proc_macro_changed: false,
207206
proc_macro_clients: Arc::from_iter([]),
208207

208+
build_deps_changed: false,
209+
209210
flycheck: Arc::from_iter([]),
210211
flycheck_sender,
211212
flycheck_receiver,
@@ -300,12 +301,19 @@ impl GlobalState {
300301
if let Some(path) = vfs_path.as_path() {
301302
let path = path.to_path_buf();
302303
if reload::should_refresh_for_change(&path, file.kind()) {
303-
workspace_structure_change = Some((path.clone(), false));
304+
workspace_structure_change = Some((
305+
path.clone(),
306+
false,
307+
AsRef::<std::path::Path>::as_ref(&path).ends_with("build.rs"),
308+
));
304309
}
305310
if file.is_created_or_deleted() {
306311
has_structure_changes = true;
307-
workspace_structure_change =
308-
Some((path, self.crate_graph_file_dependencies.contains(vfs_path)));
312+
workspace_structure_change = Some((
313+
path,
314+
self.crate_graph_file_dependencies.contains(vfs_path),
315+
false,
316+
));
309317
} else if path.extension() == Some("rs".as_ref()) {
310318
modified_rust_files.push(file.file_id);
311319
}
@@ -346,23 +354,28 @@ impl GlobalState {
346354
};
347355

348356
self.analysis_host.apply_change(change);
357+
349358
{
350-
let raw_database = self.analysis_host.raw_database();
359+
if !matches!(&workspace_structure_change, Some((.., true))) {
360+
_ = self
361+
.deferred_task_queue
362+
.sender
363+
.send(crate::main_loop::QueuedTask::CheckProcMacroSources(modified_rust_files));
364+
}
351365
// FIXME: ideally we should only trigger a workspace fetch for non-library changes
352366
// but something's going wrong with the source root business when we add a new local
353367
// crate see https://github.com/rust-lang/rust-analyzer/issues/13029
354-
if let Some((path, force_crate_graph_reload)) = workspace_structure_change {
368+
if let Some((path, force_crate_graph_reload, build_scripts_touched)) =
369+
workspace_structure_change
370+
{
355371
self.fetch_workspaces_queue.request_op(
356372
format!("workspace vfs file change: {path}"),
357373
force_crate_graph_reload,
358374
);
375+
if build_scripts_touched {
376+
self.fetch_build_data_queue.request_op(format!("build.rs changed: {path}"), ());
377+
}
359378
}
360-
self.proc_macro_changed = modified_rust_files.into_iter().any(|file_id| {
361-
let crates = raw_database.relevant_crates(file_id);
362-
let crate_graph = raw_database.crate_graph();
363-
364-
crates.iter().any(|&krate| crate_graph[krate].is_proc_macro)
365-
});
366379
}
367380

368381
true

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

+6-6
Original file line numberDiff line numberDiff line change
@@ -145,11 +145,11 @@ pub(crate) fn handle_did_save_text_document(
145145
state: &mut GlobalState,
146146
params: DidSaveTextDocumentParams,
147147
) -> anyhow::Result<()> {
148-
if state.config.script_rebuild_on_save() && state.proc_macro_changed {
149-
// reset the flag
150-
state.proc_macro_changed = false;
151-
// rebuild the proc macros
152-
state.fetch_build_data_queue.request_op("ScriptRebuildOnSave".to_owned(), ());
148+
if state.config.script_rebuild_on_save() && state.build_deps_changed {
149+
state.build_deps_changed = false;
150+
state
151+
.fetch_build_data_queue
152+
.request_op("build_deps_changed - save notification".to_owned(), ());
153153
}
154154

155155
if let Ok(vfs_path) = from_proto::vfs_path(&params.text_document.uri) {
@@ -158,7 +158,7 @@ pub(crate) fn handle_did_save_text_document(
158158
if reload::should_refresh_for_change(abs_path, ChangeKind::Modify) {
159159
state
160160
.fetch_workspaces_queue
161-
.request_op(format!("DidSaveTextDocument {abs_path}"), false);
161+
.request_op(format!("workspace vfs file change saved {abs_path}"), false);
162162
}
163163
}
164164

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_deps_changed = false;
5656

5757
state.fetch_workspaces_queue.request_op("reload workspace request".to_owned(), 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_deps_changed = false;
6464

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

0 commit comments

Comments
 (0)