Skip to content

Commit 39637d7

Browse files
committed
fix: Fix build scripts not being rebuilt in some occasions
1 parent 57fda12 commit 39637d7

File tree

17 files changed

+114
-74
lines changed

17 files changed

+114
-74
lines changed

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

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

crates/hir-expand/src/lib.rs

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

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
@@ -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)]
@@ -458,7 +458,11 @@ impl WorkspaceBuildScripts {
458458
.collect();
459459
for p in rustc.packages() {
460460
let package = &rustc[p];
461-
if package.targets.iter().any(|&it| rustc[it].is_proc_macro) {
461+
if package
462+
.targets
463+
.iter()
464+
.any(|&it| matches!(rustc[it].kind, TargetKind::Lib { is_proc_macro: true }))
465+
{
462466
if let Some((_, path)) = proc_macro_dylibs
463467
.iter()
464468
.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
@@ -188,8 +188,6 @@ pub struct TargetData {
188188
pub root: AbsPathBuf,
189189
/// Kind of target
190190
pub kind: TargetKind,
191-
/// Is this target a proc-macro
192-
pub is_proc_macro: bool,
193191
/// Required features of the target without which it won't build
194192
pub required_features: Vec<String>,
195193
}
@@ -198,7 +196,10 @@ pub struct TargetData {
198196
pub enum TargetKind {
199197
Bin,
200198
/// Any kind of Cargo lib crate-type (dylib, rlib, proc-macro, ...).
201-
Lib,
199+
Lib {
200+
/// Is this target a proc-macro
201+
is_proc_macro: bool,
202+
},
202203
Example,
203204
Test,
204205
Bench,
@@ -215,8 +216,8 @@ impl TargetKind {
215216
"bench" => TargetKind::Bench,
216217
"example" => TargetKind::Example,
217218
"custom-build" => TargetKind::BuildScript,
218-
"proc-macro" => TargetKind::Lib,
219-
_ if kind.contains("lib") => TargetKind::Lib,
219+
"proc-macro" => TargetKind::Lib { is_proc_macro: true },
220+
_ if kind.contains("lib") => TargetKind::Lib { is_proc_macro: false },
220221
_ => continue,
221222
};
222223
}
@@ -368,7 +369,6 @@ impl CargoWorkspace {
368369
name,
369370
root: AbsPathBuf::assert(src_path.into()),
370371
kind: TargetKind::new(&kind),
371-
is_proc_macro: *kind == ["proc-macro"],
372372
required_features,
373373
});
374374
pkg_data.targets.push(tgt);

crates/project-model/src/workspace.rs

+19-19
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,7 @@ impl ProjectWorkspace {
586586
let extra_targets = cargo[pkg]
587587
.targets
588588
.iter()
589-
.filter(|&&tgt| cargo[tgt].kind == TargetKind::Lib)
589+
.filter(|&&tgt| matches!(cargo[tgt].kind, TargetKind::Lib { .. }))
590590
.filter_map(|&tgt| cargo[tgt].root.parent())
591591
.map(|tgt| tgt.normalize().to_path_buf())
592592
.filter(|path| !path.starts_with(&pkg_root));
@@ -949,17 +949,17 @@ fn cargo_to_crate_graph(
949949

950950
let mut lib_tgt = None;
951951
for &tgt in cargo[pkg].targets.iter() {
952-
if cargo[tgt].kind != TargetKind::Lib && !cargo[pkg].is_member {
952+
if !matches!(cargo[tgt].kind, TargetKind::Lib { .. }) && !cargo[pkg].is_member {
953953
// For non-workspace-members, Cargo does not resolve dev-dependencies, so we don't
954954
// add any targets except the library target, since those will not work correctly if
955955
// they use dev-dependencies.
956956
// In fact, they can break quite badly if multiple client workspaces get merged:
957957
// https://github.com/rust-lang/rust-analyzer/issues/11300
958958
continue;
959959
}
960-
let &TargetData { ref name, kind, is_proc_macro, ref root, .. } = &cargo[tgt];
960+
let &TargetData { ref name, kind, ref root, .. } = &cargo[tgt];
961961

962-
if kind == TargetKind::Lib
962+
if matches!(kind, TargetKind::Lib { .. })
963963
&& sysroot.map_or(false, |sysroot| root.starts_with(sysroot.src_root()))
964964
{
965965
if let Some(&(_, crate_id, _)) =
@@ -984,19 +984,24 @@ fn cargo_to_crate_graph(
984984
cfg_options.clone(),
985985
file_id,
986986
name,
987-
is_proc_macro,
987+
kind,
988988
target_layout.clone(),
989989
false,
990990
toolchain.cloned(),
991991
);
992-
if kind == TargetKind::Lib {
992+
if let TargetKind::Lib { .. } = kind {
993993
lib_tgt = Some((crate_id, name.clone()));
994994
pkg_to_lib_crate.insert(pkg, crate_id);
995995
}
996996
// Even crates that don't set proc-macro = true are allowed to depend on proc_macro
997997
// (just none of the APIs work when called outside of a proc macro).
998998
if let Some(proc_macro) = libproc_macro {
999-
add_proc_macro_dep(crate_graph, crate_id, proc_macro, is_proc_macro);
999+
add_proc_macro_dep(
1000+
crate_graph,
1001+
crate_id,
1002+
proc_macro,
1003+
matches!(kind, TargetKind::Lib { is_proc_macro: true }),
1004+
);
10001005
}
10011006

10021007
pkg_crates.entry(pkg).or_insert_with(Vec::new).push((crate_id, kind));
@@ -1194,9 +1199,9 @@ fn handle_rustc_crates(
11941199
};
11951200

11961201
for &tgt in rustc_workspace[pkg].targets.iter() {
1197-
if rustc_workspace[tgt].kind != TargetKind::Lib {
1202+
let kind @ TargetKind::Lib { is_proc_macro } = rustc_workspace[tgt].kind else {
11981203
continue;
1199-
}
1204+
};
12001205
if let Some(file_id) = load(&rustc_workspace[tgt].root) {
12011206
let crate_id = add_target_crate_root(
12021207
crate_graph,
@@ -1206,7 +1211,7 @@ fn handle_rustc_crates(
12061211
cfg_options.clone(),
12071212
file_id,
12081213
&rustc_workspace[tgt].name,
1209-
rustc_workspace[tgt].is_proc_macro,
1214+
kind,
12101215
target_layout.clone(),
12111216
true,
12121217
toolchain.cloned(),
@@ -1215,12 +1220,7 @@ fn handle_rustc_crates(
12151220
// Add dependencies on core / std / alloc for this crate
12161221
public_deps.add_to_crate_graph(crate_graph, crate_id);
12171222
if let Some(proc_macro) = libproc_macro {
1218-
add_proc_macro_dep(
1219-
crate_graph,
1220-
crate_id,
1221-
proc_macro,
1222-
rustc_workspace[tgt].is_proc_macro,
1223-
);
1223+
add_proc_macro_dep(crate_graph, crate_id, proc_macro, is_proc_macro);
12241224
}
12251225
rustc_pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id);
12261226
}
@@ -1282,7 +1282,7 @@ fn add_target_crate_root(
12821282
cfg_options: CfgOptions,
12831283
file_id: FileId,
12841284
cargo_name: &str,
1285-
is_proc_macro: bool,
1285+
kind: TargetKind,
12861286
target_layout: TargetLayoutLoadResult,
12871287
rustc_crate: bool,
12881288
toolchain: Option<Version>,
@@ -1332,7 +1332,7 @@ fn add_target_crate_root(
13321332
cfg_options,
13331333
potential_cfg_options,
13341334
env,
1335-
is_proc_macro,
1335+
matches!(kind, TargetKind::Lib { is_proc_macro: true }),
13361336
if rustc_crate {
13371337
CrateOrigin::Rustc { name: pkg.name.clone() }
13381338
} else if pkg.is_member {
@@ -1343,7 +1343,7 @@ fn add_target_crate_root(
13431343
target_layout,
13441344
toolchain,
13451345
);
1346-
if is_proc_macro {
1346+
if let TargetKind::Lib { is_proc_macro: true } = kind {
13471347
let proc_macro = match build_data.as_ref().map(|it| it.proc_macro_dylib_path.as_ref()) {
13481348
Some(it) => it.cloned().map(|path| Ok((Some(cargo_name.to_owned()), path))),
13491349
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

+25-13
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) proc_macros_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+
proc_macros_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,27 @@ impl GlobalState {
346354
};
347355

348356
self.analysis_host.apply_change(change);
357+
349358
{
350-
let raw_database = self.analysis_host.raw_database();
351359
// FIXME: ideally we should only trigger a workspace fetch for non-library changes
352360
// but something's going wrong with the source root business when we add a new local
353361
// crate see https://github.com/rust-lang/rust-analyzer/issues/13029
354-
if let Some((path, force_crate_graph_reload)) = workspace_structure_change {
362+
if let Some((path, force_crate_graph_reload, build_scripts_touched)) =
363+
workspace_structure_change
364+
{
355365
self.fetch_workspaces_queue.request_op(
356366
format!("workspace vfs file change: {path}"),
357367
force_crate_graph_reload,
358368
);
369+
if build_scripts_touched {
370+
self.fetch_build_data_queue.request_op(format!("build.rs changed: {path}"), ());
371+
}
359372
}
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();
363373

364-
crates.iter().any(|&krate| crate_graph[krate].is_proc_macro)
365-
});
374+
_ = self
375+
.deferred_task_queue
376+
.sender
377+
.send(crate::main_loop::QueuedTask::CheckProcMacroSources(modified_rust_files));
366378
}
367379

368380
true

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

+5-7
Original file line numberDiff line numberDiff line change
@@ -145,11 +145,9 @@ 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.proc_macros_changed {
149+
state.proc_macros_changed = false;
150+
state.fetch_build_data_queue.request_op("proc macros changed".to_owned(), ());
153151
}
154152

155153
if let Ok(vfs_path) = from_proto::vfs_path(&params.text_document.uri) {
@@ -158,7 +156,7 @@ pub(crate) fn handle_did_save_text_document(
158156
if reload::should_refresh_for_change(abs_path, ChangeKind::Modify) {
159157
state
160158
.fetch_workspaces_queue
161-
.request_op(format!("DidSaveTextDocument {abs_path}"), false);
159+
.request_op(format!("workspace vfs file change saved {abs_path}"), false);
162160
}
163161
}
164162

@@ -236,7 +234,7 @@ pub(crate) fn handle_did_change_workspace_folders(
236234

237235
if !config.has_linked_projects() && config.detached_files().is_empty() {
238236
config.rediscover_workspaces();
239-
state.fetch_workspaces_queue.request_op("client workspaces changed".to_string(), false)
237+
state.fetch_workspaces_queue.request_op("workspaces folders changed".to_string(), false)
240238
}
241239

242240
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.proc_macros_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.proc_macros_changed = false;
6464

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

0 commit comments

Comments
 (0)