From 1390498caafecf60060023b88aac0033e9636c64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 17 Aug 2024 05:45:10 +0000 Subject: [PATCH] Detect more `cfg`d out items in resolution errors Use a visitor to collect *all* items (including those nested) that were stripped behind a `cfg` condition. ``` error[E0425]: cannot find function `f` in this scope --> $DIR/nested-cfg-attrs.rs:4:13 | LL | fn main() { f() } | ^ not found in this scope | note: found an item that was configured out --> $DIR/nested-cfg-attrs.rs:2:4 | LL | fn f() {} | ^ note: the item is gated here --> $DIR/nested-cfg-attrs.rs:1:35 | LL | #[cfg_attr(all(), cfg_attr(all(), cfg(FALSE)))] | ^^^^^^^^^^ ``` --- compiler/rustc_expand/src/expand.rs | 34 ++++++++++++------- compiler/rustc_resolve/src/diagnostics.rs | 14 +++++--- compiler/rustc_resolve/src/late.rs | 10 +++++- .../rustc_resolve/src/late/diagnostics.rs | 5 ++- tests/ui/cfg/diagnostics-reexport.rs | 4 +-- tests/ui/cfg/diagnostics-reexport.stderr | 10 ++++++ tests/ui/cfg/diagnostics-same-crate.rs | 4 +-- tests/ui/cfg/diagnostics-same-crate.stderr | 11 ++++++ tests/ui/conditional-compilation/test-cfg.rs | 4 ++- .../conditional-compilation/test-cfg.stderr | 13 ++++++- tests/ui/macros/macro-inner-attributes.stderr | 16 +++++++++ tests/ui/nested-cfg-attrs.rs | 5 +-- tests/ui/nested-cfg-attrs.stderr | 11 ++++++ tests/ui/rustdoc/cfg-rustdoc.rs | 7 ++-- tests/ui/rustdoc/cfg-rustdoc.stderr | 11 ++++++ 15 files changed, 126 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 37679e17b90a8..592098e203062 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1260,25 +1260,33 @@ impl InvocationCollectorNode for P { res } fn declared_names(&self) -> Vec { - if let ItemKind::Use(ut) = &self.kind { - fn collect_use_tree_leaves(ut: &ast::UseTree, idents: &mut Vec) { - match &ut.kind { - ast::UseTreeKind::Glob => {} - ast::UseTreeKind::Simple(_) => idents.push(ut.ident()), - ast::UseTreeKind::Nested { items, .. } => { - for (ut, _) in items { - collect_use_tree_leaves(ut, idents); + struct ItemNameVisitor(Vec); + impl Visitor<'_> for ItemNameVisitor { + fn visit_item(&mut self, i: &ast::Item) { + if let ItemKind::Use(ut) = &i.kind { + fn collect_use_tree_leaves(ut: &ast::UseTree, idents: &mut Vec) { + match &ut.kind { + ast::UseTreeKind::Glob => {} + ast::UseTreeKind::Simple(_) => idents.push(ut.ident()), + ast::UseTreeKind::Nested { items, .. } => { + for (ut, _) in items { + collect_use_tree_leaves(ut, idents); + } + } } } + + collect_use_tree_leaves(ut, &mut self.0); + } else { + self.0.push(i.ident); } + visit::walk_item(self, i); } - - let mut idents = Vec::new(); - collect_use_tree_leaves(ut, &mut idents); - return idents; } - vec![self.ident] + let mut v = ItemNameVisitor(vec![]); + v.visit_item(self); + v.0 } } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 942026ef01223..58be905dc2b8e 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -813,11 +813,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { err.multipart_suggestion(msg, suggestions, applicability); } - if let Some(ModuleOrUniformRoot::Module(module)) = module - && let Some(module) = module.opt_def_id() - && let Some(segment) = segment - { - self.find_cfg_stripped(&mut err, &segment, module); + if let Some(segment) = segment { + if let Some(ModuleOrUniformRoot::Module(module)) = module { + let module = + module.opt_def_id().unwrap_or_else(|| CRATE_DEF_ID.to_def_id()); + self.find_cfg_stripped(&mut err, &segment, module); + } else { + let module = CRATE_DEF_ID.to_def_id(); + self.find_cfg_stripped(&mut err, &segment, module); + } } err diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 4a70fc0f30847..ba4276a391027 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3980,13 +3980,21 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // // And that's what happens below - we're just mixing both messages // into a single one. + let failed_to_resolve = match parent_err.node { + ResolutionError::FailedToResolve { .. } => true, + _ => false, + }; let mut parent_err = this.r.into_struct_error(parent_err.span, parent_err.node); // overwrite all properties with the parent's error message err.messages = take(&mut parent_err.messages); err.code = take(&mut parent_err.code); swap(&mut err.span, &mut parent_err.span); - err.children = take(&mut parent_err.children); + if failed_to_resolve { + err.children = take(&mut parent_err.children); + } else { + err.children.append(&mut parent_err.children); + } err.sort_span = parent_err.sort_span; err.is_lint = parent_err.is_lint.clone(); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index f778b0ee3acc0..55bd83f4ff3c4 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -478,9 +478,8 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } self.err_code_special_cases(&mut err, source, path, span); - if let Some(module) = base_error.module { - self.r.find_cfg_stripped(&mut err, &path.last().unwrap().ident.name, module); - } + let module = base_error.module.unwrap_or_else(|| CRATE_DEF_ID.to_def_id()); + self.r.find_cfg_stripped(&mut err, &path.last().unwrap().ident.name, module); (err, candidates) } diff --git a/tests/ui/cfg/diagnostics-reexport.rs b/tests/ui/cfg/diagnostics-reexport.rs index 9ae7d931fcb8f..59b2fa7f0e2ae 100644 --- a/tests/ui/cfg/diagnostics-reexport.rs +++ b/tests/ui/cfg/diagnostics-reexport.rs @@ -1,7 +1,7 @@ pub mod inner { - #[cfg(FALSE)] + #[cfg(FALSE)] //~ NOTE the item is gated here mod gone { - pub fn uwu() {} + pub fn uwu() {} //~ NOTE found an item that was configured out } #[cfg(FALSE)] //~ NOTE the item is gated here diff --git a/tests/ui/cfg/diagnostics-reexport.stderr b/tests/ui/cfg/diagnostics-reexport.stderr index 737202fdf9ad9..2ef1cf71eeaec 100644 --- a/tests/ui/cfg/diagnostics-reexport.stderr +++ b/tests/ui/cfg/diagnostics-reexport.stderr @@ -50,6 +50,16 @@ error[E0425]: cannot find function `uwu` in module `inner` LL | inner::uwu(); | ^^^ not found in `inner` | +note: found an item that was configured out + --> $DIR/diagnostics-reexport.rs:4:16 + | +LL | pub fn uwu() {} + | ^^^ +note: the item is gated here + --> $DIR/diagnostics-reexport.rs:2:5 + | +LL | #[cfg(FALSE)] + | ^^^^^^^^^^^^^ note: found an item that was configured out --> $DIR/diagnostics-reexport.rs:8:20 | diff --git a/tests/ui/cfg/diagnostics-same-crate.rs b/tests/ui/cfg/diagnostics-same-crate.rs index d6f8dd21a9221..31114457d095c 100644 --- a/tests/ui/cfg/diagnostics-same-crate.rs +++ b/tests/ui/cfg/diagnostics-same-crate.rs @@ -37,8 +37,8 @@ mod placeholder { //~| NOTE could not find `doesnt_exist` in `inner` } -#[cfg(i_dont_exist_and_you_can_do_nothing_about_it)] -pub fn vanished() {} +#[cfg(i_dont_exist_and_you_can_do_nothing_about_it)] //~ NOTE the item is gated here +pub fn vanished() {} //~ NOTE found an item that was configured out fn main() { // There is no uwu at this path - no diagnostic. diff --git a/tests/ui/cfg/diagnostics-same-crate.stderr b/tests/ui/cfg/diagnostics-same-crate.stderr index dd0d10c6567ea..ef9e7563bad2f 100644 --- a/tests/ui/cfg/diagnostics-same-crate.stderr +++ b/tests/ui/cfg/diagnostics-same-crate.stderr @@ -94,6 +94,17 @@ error[E0425]: cannot find function `vanished` in this scope | LL | vanished(); | ^^^^^^^^ not found in this scope + | +note: found an item that was configured out + --> $DIR/diagnostics-same-crate.rs:41:8 + | +LL | pub fn vanished() {} + | ^^^^^^^^ +note: the item is gated here + --> $DIR/diagnostics-same-crate.rs:40:1 + | +LL | #[cfg(i_dont_exist_and_you_can_do_nothing_about_it)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 7 previous errors diff --git a/tests/ui/conditional-compilation/test-cfg.rs b/tests/ui/conditional-compilation/test-cfg.rs index adbbc309be447..b3fff26a8fd45 100644 --- a/tests/ui/conditional-compilation/test-cfg.rs +++ b/tests/ui/conditional-compilation/test-cfg.rs @@ -1,8 +1,10 @@ //@ compile-flags: --cfg foo --check-cfg=cfg(foo,bar) #[cfg(all(foo, bar))] // foo AND bar -fn foo() {} +//~^ NOTE the item is gated here +fn foo() {} //~ NOTE found an item that was configured out fn main() { foo(); //~ ERROR cannot find function `foo` in this scope + //~^ NOTE not found in this scope } diff --git a/tests/ui/conditional-compilation/test-cfg.stderr b/tests/ui/conditional-compilation/test-cfg.stderr index 9715f16acc20c..50cee1a68fdf7 100644 --- a/tests/ui/conditional-compilation/test-cfg.stderr +++ b/tests/ui/conditional-compilation/test-cfg.stderr @@ -1,8 +1,19 @@ error[E0425]: cannot find function `foo` in this scope - --> $DIR/test-cfg.rs:7:5 + --> $DIR/test-cfg.rs:8:5 | LL | foo(); | ^^^ not found in this scope + | +note: found an item that was configured out + --> $DIR/test-cfg.rs:5:4 + | +LL | fn foo() {} + | ^^^ +note: the item is gated here + --> $DIR/test-cfg.rs:3:1 + | +LL | #[cfg(all(foo, bar))] // foo AND bar + | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/macros/macro-inner-attributes.stderr b/tests/ui/macros/macro-inner-attributes.stderr index b6e10f45e3810..355183a64a8f6 100644 --- a/tests/ui/macros/macro-inner-attributes.stderr +++ b/tests/ui/macros/macro-inner-attributes.stderr @@ -4,6 +4,22 @@ error[E0433]: failed to resolve: use of undeclared crate or module `a` LL | a::bar(); | ^ use of undeclared crate or module `a` | +note: found an item that was configured out + --> $DIR/macro-inner-attributes.rs:7:7 + | +LL | test!(a, + | ^ +note: the item is gated here + --> $DIR/macro-inner-attributes.rs:5:45 + | +LL | $i:item) => (mod $nm { #![$a] $i }); } + | ^^^^^^ +LL | +LL | / test!(a, +LL | | #[cfg(FALSE)], +LL | | pub fn bar() { }); + | |_______________________- in this macro invocation + = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) help: there is a crate or module with a similar name | LL | b::bar(); diff --git a/tests/ui/nested-cfg-attrs.rs b/tests/ui/nested-cfg-attrs.rs index 0af28fc3d8ec6..5a2d35cd04709 100644 --- a/tests/ui/nested-cfg-attrs.rs +++ b/tests/ui/nested-cfg-attrs.rs @@ -1,4 +1,5 @@ -#[cfg_attr(all(), cfg_attr(all(), cfg(FALSE)))] -fn f() {} +#[cfg_attr(all(), cfg_attr(all(), cfg(FALSE)))] //~ NOTE the item is gated here +fn f() {} //~ NOTE found an item that was configured out fn main() { f() } //~ ERROR cannot find function `f` in this scope +//~^ NOTE not found in this scope diff --git a/tests/ui/nested-cfg-attrs.stderr b/tests/ui/nested-cfg-attrs.stderr index 16c2930714353..49b7f57ffdc87 100644 --- a/tests/ui/nested-cfg-attrs.stderr +++ b/tests/ui/nested-cfg-attrs.stderr @@ -3,6 +3,17 @@ error[E0425]: cannot find function `f` in this scope | LL | fn main() { f() } | ^ not found in this scope + | +note: found an item that was configured out + --> $DIR/nested-cfg-attrs.rs:2:4 + | +LL | fn f() {} + | ^ +note: the item is gated here + --> $DIR/nested-cfg-attrs.rs:1:35 + | +LL | #[cfg_attr(all(), cfg_attr(all(), cfg(FALSE)))] + | ^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/rustdoc/cfg-rustdoc.rs b/tests/ui/rustdoc/cfg-rustdoc.rs index dd8e1ed97c4d2..11c48d075520f 100644 --- a/tests/ui/rustdoc/cfg-rustdoc.rs +++ b/tests/ui/rustdoc/cfg-rustdoc.rs @@ -1,6 +1,7 @@ -#[cfg(doc)] -pub struct Foo; +#[cfg(doc)] //~ NOTE the item is gated here +pub struct Foo; //~ NOTE found an item that was configured out fn main() { - let f = Foo; //~ ERROR + let f = Foo; //~ ERROR cannot find value `Foo` in this scope + //~^ NOTE not found in this scope } diff --git a/tests/ui/rustdoc/cfg-rustdoc.stderr b/tests/ui/rustdoc/cfg-rustdoc.stderr index 340a8e22482ce..8e856fbd4bf73 100644 --- a/tests/ui/rustdoc/cfg-rustdoc.stderr +++ b/tests/ui/rustdoc/cfg-rustdoc.stderr @@ -3,6 +3,17 @@ error[E0425]: cannot find value `Foo` in this scope | LL | let f = Foo; | ^^^ not found in this scope + | +note: found an item that was configured out + --> $DIR/cfg-rustdoc.rs:2:12 + | +LL | pub struct Foo; + | ^^^ +note: the item is gated here + --> $DIR/cfg-rustdoc.rs:1:1 + | +LL | #[cfg(doc)] + | ^^^^^^^^^^^ error: aborting due to 1 previous error