From 7cd4b673d050508544f0b200ab6a840bebc38f0f Mon Sep 17 00:00:00 2001 From: yukang Date: Fri, 25 Nov 2022 13:19:21 +0800 Subject: [PATCH 1/2] fix #104700, account for item-local in inner scope for E0425 --- compiler/rustc_resolve/src/late.rs | 6 +++++- .../rustc_resolve/src/late/diagnostics.rs | 16 ++++++++++++++ .../ui/resolve/issue-104700-inner_scope.rs | 11 ++++++++++ .../resolve/issue-104700-inner_scope.stderr | 21 +++++++++++++++++++ 4 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/resolve/issue-104700-inner_scope.rs create mode 100644 src/test/ui/resolve/issue-104700-inner_scope.stderr diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 93b0f5814de..8faef4c6374 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -566,6 +566,9 @@ struct LateResolutionVisitor<'a, 'b, 'ast> { /// FIXME #4948: Reuse ribs to avoid allocation. ribs: PerNS>>, + /// Previous poped `rib`, only used for diagnostic. + last_block_rib: Option>, + /// The current set of local scopes, for labels. label_ribs: Vec>, @@ -1168,6 +1171,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { type_ns: vec![Rib::new(start_rib_kind)], macro_ns: vec![Rib::new(start_rib_kind)], }, + last_block_rib: None, label_ribs: Vec::new(), lifetime_ribs: Vec::new(), lifetime_elision_candidates: None, @@ -3756,7 +3760,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { self.ribs[ValueNS].pop(); self.label_ribs.pop(); } - self.ribs[ValueNS].pop(); + self.last_block_rib = self.ribs[ValueNS].pop(); if anonymous_module.is_some() { self.ribs[TypeNS].pop(); } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index b340bee28c3..b3dd5bb28a7 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -614,6 +614,22 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { return (true, candidates); } } + + // Try to find in last block rib + if let Some(rib) = &self.last_block_rib { + for (ident, &res) in &rib.bindings { + if let Res::Local(_) = res && path.len() == 1 && + ident.span.eq_ctxt(path[0].ident.span) && + ident.name == path[0].ident.name { + err.span_help( + ident.span, + &format!("the binding `{}` is available in a different scope in the same function", path_str), + ); + return (true, candidates); + } + } + } + return (false, candidates); } diff --git a/src/test/ui/resolve/issue-104700-inner_scope.rs b/src/test/ui/resolve/issue-104700-inner_scope.rs new file mode 100644 index 00000000000..e8f28c113e3 --- /dev/null +++ b/src/test/ui/resolve/issue-104700-inner_scope.rs @@ -0,0 +1,11 @@ +fn main() { + let foo = 1; + { + let bar = 2; + let test_func = |x| x > 3; + } + if bar == 2 { //~ ERROR cannot find value + println!("yes"); + } + test_func(1); //~ ERROR cannot find function +} diff --git a/src/test/ui/resolve/issue-104700-inner_scope.stderr b/src/test/ui/resolve/issue-104700-inner_scope.stderr new file mode 100644 index 00000000000..051b234fc72 --- /dev/null +++ b/src/test/ui/resolve/issue-104700-inner_scope.stderr @@ -0,0 +1,21 @@ +error[E0425]: cannot find value `bar` in this scope + --> $DIR/issue-104700-inner_scope.rs:7:8 + | +LL | if bar == 2 { + | ^^^ + | +help: the binding `bar` is available in a different scope in the same function + --> $DIR/issue-104700-inner_scope.rs:4:13 + | +LL | let bar = 2; + | ^^^ + +error[E0425]: cannot find function `test_func` in this scope + --> $DIR/issue-104700-inner_scope.rs:10:5 + | +LL | test_func(1); + | ^^^^^^^^^ not found in this scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. From 68ea51602a492a02ed5d23580ac06f9c4cc830f5 Mon Sep 17 00:00:00 2001 From: yukang Date: Fri, 25 Nov 2022 15:25:04 +0800 Subject: [PATCH 2/2] fix the crossing function issue --- compiler/rustc_resolve/src/late.rs | 2 ++ compiler/rustc_resolve/src/late/diagnostics.rs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 8faef4c6374..18dabfe8993 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -876,6 +876,8 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { // Ignore errors in function bodies if this is rustdoc // Be sure not to set this until the function signature has been resolved. let previous_state = replace(&mut this.in_func_body, true); + // We only care block in the same function + this.last_block_rib = None; // Resolve the function body, potentially inside the body of an async closure this.with_lifetime_rib( LifetimeRibKind::Elided(LifetimeRes::Infer), diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index b3dd5bb28a7..d82aecaadc3 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -616,7 +616,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { } // Try to find in last block rib - if let Some(rib) = &self.last_block_rib { + if let Some(rib) = &self.last_block_rib && let RibKind::NormalRibKind = rib.kind { for (ident, &res) in &rib.bindings { if let Res::Local(_) = res && path.len() == 1 && ident.span.eq_ctxt(path[0].ident.span) &&