Skip to content

Commit 57bc227

Browse files
authored
Rollup merge of rust-lang#145065 - petrochenkov:riblock, r=davidtwco
resolve: Introduce `RibKind::Block` to avoid confusing module items, blocks with items, and blocks without items. Addresses rust-lang#143141 (comment) and rust-lang#143141 (comment). A couple of related cleanups are also added on top.
2 parents e2a2a77 + f369e06 commit 57bc227

File tree

5 files changed

+99
-93
lines changed

5 files changed

+99
-93
lines changed

compiler/rustc_resolve/src/ident.rs

Lines changed: 40 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
318318
let normalized_ident = Ident { span: normalized_span, ..ident };
319319

320320
// Walk backwards up the ribs in scope.
321-
let mut module = self.graph_root;
322321
for (i, rib) in ribs.iter().enumerate().rev() {
323322
debug!("walk rib\n{:?}", rib.bindings);
324323
// Use the rib kind to determine whether we are resolving parameters
@@ -334,51 +333,47 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
334333
*original_rib_ident_def,
335334
ribs,
336335
)));
336+
} else if let RibKind::Block(Some(module)) = rib.kind
337+
&& let Ok(binding) = self.cm().resolve_ident_in_module_unadjusted(
338+
ModuleOrUniformRoot::Module(module),
339+
ident,
340+
ns,
341+
parent_scope,
342+
Shadowing::Unrestricted,
343+
finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }),
344+
ignore_binding,
345+
None,
346+
)
347+
{
348+
// The ident resolves to an item in a block.
349+
return Some(LexicalScopeBinding::Item(binding));
350+
} else if let RibKind::Module(module) = rib.kind {
351+
// Encountered a module item, abandon ribs and look into that module and preludes.
352+
return self
353+
.cm()
354+
.early_resolve_ident_in_lexical_scope(
355+
orig_ident,
356+
ScopeSet::Late(ns, module, finalize.map(|finalize| finalize.node_id)),
357+
parent_scope,
358+
finalize,
359+
finalize.is_some(),
360+
ignore_binding,
361+
None,
362+
)
363+
.ok()
364+
.map(LexicalScopeBinding::Item);
337365
}
338366

339-
module = match rib.kind {
340-
RibKind::Module(module) => module,
341-
RibKind::MacroDefinition(def) if def == self.macro_def(ident.span.ctxt()) => {
342-
// If an invocation of this macro created `ident`, give up on `ident`
343-
// and switch to `ident`'s source from the macro definition.
344-
ident.span.remove_mark();
345-
continue;
346-
}
347-
_ => continue,
348-
};
349-
350-
match module.kind {
351-
ModuleKind::Block => {} // We can see through blocks
352-
_ => break,
353-
}
354-
355-
let item = self.cm().resolve_ident_in_module_unadjusted(
356-
ModuleOrUniformRoot::Module(module),
357-
ident,
358-
ns,
359-
parent_scope,
360-
Shadowing::Unrestricted,
361-
finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }),
362-
ignore_binding,
363-
None,
364-
);
365-
if let Ok(binding) = item {
366-
// The ident resolves to an item.
367-
return Some(LexicalScopeBinding::Item(binding));
367+
if let RibKind::MacroDefinition(def) = rib.kind
368+
&& def == self.macro_def(ident.span.ctxt())
369+
{
370+
// If an invocation of this macro created `ident`, give up on `ident`
371+
// and switch to `ident`'s source from the macro definition.
372+
ident.span.remove_mark();
368373
}
369374
}
370-
self.cm()
371-
.early_resolve_ident_in_lexical_scope(
372-
orig_ident,
373-
ScopeSet::Late(ns, module, finalize.map(|finalize| finalize.node_id)),
374-
parent_scope,
375-
finalize,
376-
finalize.is_some(),
377-
ignore_binding,
378-
None,
379-
)
380-
.ok()
381-
.map(LexicalScopeBinding::Item)
375+
376+
unreachable!()
382377
}
383378

384379
/// Resolve an identifier in lexical scope.
@@ -1171,6 +1166,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
11711166
for rib in ribs {
11721167
match rib.kind {
11731168
RibKind::Normal
1169+
| RibKind::Block(..)
11741170
| RibKind::FnOrCoroutine
11751171
| RibKind::Module(..)
11761172
| RibKind::MacroDefinition(..)
@@ -1263,6 +1259,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
12631259
for rib in ribs {
12641260
let (has_generic_params, def_kind) = match rib.kind {
12651261
RibKind::Normal
1262+
| RibKind::Block(..)
12661263
| RibKind::FnOrCoroutine
12671264
| RibKind::Module(..)
12681265
| RibKind::MacroDefinition(..)
@@ -1356,6 +1353,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
13561353
for rib in ribs {
13571354
let (has_generic_params, def_kind) = match rib.kind {
13581355
RibKind::Normal
1356+
| RibKind::Block(..)
13591357
| RibKind::FnOrCoroutine
13601358
| RibKind::Module(..)
13611359
| RibKind::MacroDefinition(..)

compiler/rustc_resolve/src/late.rs

Lines changed: 35 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,13 @@ pub(crate) enum RibKind<'ra> {
192192
/// No restriction needs to be applied.
193193
Normal,
194194

195+
/// We passed through an `ast::Block`.
196+
/// Behaves like `Normal`, but also partially like `Module` if the block contains items.
197+
/// `Block(None)` must be always processed in the same way as `Block(Some(module))`
198+
/// with empty `module`. The module can be `None` only because creation of some definitely
199+
/// empty modules is skipped as an optimization.
200+
Block(Option<Module<'ra>>),
201+
195202
/// We passed through an impl or trait and are now in one of its
196203
/// methods or associated types. Allow references to ty params that impl or trait
197204
/// binds. Disallow any other upvars (including other ty params that are
@@ -210,7 +217,7 @@ pub(crate) enum RibKind<'ra> {
210217
/// All other constants aren't allowed to use generic params at all.
211218
ConstantItem(ConstantHasGenerics, Option<(Ident, ConstantItemKind)>),
212219

213-
/// We passed through a module.
220+
/// We passed through a module item.
214221
Module(Module<'ra>),
215222

216223
/// We passed through a `macro_rules!` statement
@@ -242,6 +249,7 @@ impl RibKind<'_> {
242249
pub(crate) fn contains_params(&self) -> bool {
243250
match self {
244251
RibKind::Normal
252+
| RibKind::Block(..)
245253
| RibKind::FnOrCoroutine
246254
| RibKind::ConstantItem(..)
247255
| RibKind::Module(_)
@@ -258,15 +266,8 @@ impl RibKind<'_> {
258266
fn is_label_barrier(self) -> bool {
259267
match self {
260268
RibKind::Normal | RibKind::MacroDefinition(..) => false,
261-
262-
RibKind::AssocItem
263-
| RibKind::FnOrCoroutine
264-
| RibKind::Item(..)
265-
| RibKind::ConstantItem(..)
266-
| RibKind::Module(..)
267-
| RibKind::ForwardGenericParamBan(_)
268-
| RibKind::ConstParamTy
269-
| RibKind::InlineAsmSym => true,
269+
RibKind::FnOrCoroutine | RibKind::ConstantItem(..) => true,
270+
kind => bug!("unexpected rib kind: {kind:?}"),
270271
}
271272
}
272273
}
@@ -1527,19 +1528,6 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
15271528
ret
15281529
}
15291530

1530-
fn with_mod_rib<T>(&mut self, id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
1531-
let module = self.r.expect_module(self.r.local_def_id(id).to_def_id());
1532-
// Move down in the graph.
1533-
let orig_module = replace(&mut self.parent_scope.module, module);
1534-
self.with_rib(ValueNS, RibKind::Module(module), |this| {
1535-
this.with_rib(TypeNS, RibKind::Module(module), |this| {
1536-
let ret = f(this);
1537-
this.parent_scope.module = orig_module;
1538-
ret
1539-
})
1540-
})
1541-
}
1542-
15431531
fn visit_generic_params(&mut self, params: &'ast [GenericParam], add_self_upper: bool) {
15441532
// For type parameter defaults, we have to ban access
15451533
// to following type parameters, as the GenericArgs can only
@@ -2677,20 +2665,25 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
26772665
}
26782666

26792667
ItemKind::Mod(..) => {
2680-
self.with_mod_rib(item.id, |this| {
2681-
if mod_inner_docs {
2682-
this.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
2683-
}
2684-
let old_macro_rules = this.parent_scope.macro_rules;
2685-
visit::walk_item(this, item);
2686-
// Maintain macro_rules scopes in the same way as during early resolution
2687-
// for diagnostics and doc links.
2688-
if item.attrs.iter().all(|attr| {
2689-
!attr.has_name(sym::macro_use) && !attr.has_name(sym::macro_escape)
2690-
}) {
2691-
this.parent_scope.macro_rules = old_macro_rules;
2692-
}
2668+
let module = self.r.expect_module(self.r.local_def_id(item.id).to_def_id());
2669+
let orig_module = replace(&mut self.parent_scope.module, module);
2670+
self.with_rib(ValueNS, RibKind::Module(module), |this| {
2671+
this.with_rib(TypeNS, RibKind::Module(module), |this| {
2672+
if mod_inner_docs {
2673+
this.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
2674+
}
2675+
let old_macro_rules = this.parent_scope.macro_rules;
2676+
visit::walk_item(this, item);
2677+
// Maintain macro_rules scopes in the same way as during early resolution
2678+
// for diagnostics and doc links.
2679+
if item.attrs.iter().all(|attr| {
2680+
!attr.has_name(sym::macro_use) && !attr.has_name(sym::macro_escape)
2681+
}) {
2682+
this.parent_scope.macro_rules = old_macro_rules;
2683+
}
2684+
})
26932685
});
2686+
self.parent_scope.module = orig_module;
26942687
}
26952688

26962689
ItemKind::Static(box ast::StaticItem {
@@ -2821,9 +2814,9 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
28212814
// We also can't shadow bindings from associated parent items.
28222815
for ns in [ValueNS, TypeNS] {
28232816
for parent_rib in self.ribs[ns].iter().rev() {
2824-
// Break at mod level, to account for nested items which are
2817+
// Break at module or block level, to account for nested items which are
28252818
// allowed to shadow generic param names.
2826-
if matches!(parent_rib.kind, RibKind::Module(..)) {
2819+
if matches!(parent_rib.kind, RibKind::Module(..) | RibKind::Block(..)) {
28272820
break;
28282821
}
28292822

@@ -4652,16 +4645,16 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
46524645
debug!("(resolving block) entering block");
46534646
// Move down in the graph, if there's an anonymous module rooted here.
46544647
let orig_module = self.parent_scope.module;
4655-
let anonymous_module = self.r.block_map.get(&block.id).cloned(); // clones a reference
4648+
let anonymous_module = self.r.block_map.get(&block.id).copied();
46564649

46574650
let mut num_macro_definition_ribs = 0;
46584651
if let Some(anonymous_module) = anonymous_module {
46594652
debug!("(resolving block) found anonymous module, moving down");
4660-
self.ribs[ValueNS].push(Rib::new(RibKind::Module(anonymous_module)));
4661-
self.ribs[TypeNS].push(Rib::new(RibKind::Module(anonymous_module)));
4653+
self.ribs[ValueNS].push(Rib::new(RibKind::Block(Some(anonymous_module))));
4654+
self.ribs[TypeNS].push(Rib::new(RibKind::Block(Some(anonymous_module))));
46624655
self.parent_scope.module = anonymous_module;
46634656
} else {
4664-
self.ribs[ValueNS].push(Rib::new(RibKind::Normal));
4657+
self.ribs[ValueNS].push(Rib::new(RibKind::Block(None)));
46654658
}
46664659

46674660
// Descend into the block.

compiler/rustc_resolve/src/late/diagnostics.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -849,9 +849,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
849849
}
850850

851851
// Try to find in last block rib
852-
if let Some(rib) = &self.last_block_rib
853-
&& let RibKind::Normal = rib.kind
854-
{
852+
if let Some(rib) = &self.last_block_rib {
855853
for (ident, &res) in &rib.bindings {
856854
if let Res::Local(_) = res
857855
&& path.len() == 1
@@ -900,7 +898,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
900898
if path.len() == 1 {
901899
for rib in self.ribs[ns].iter().rev() {
902900
let item = path[0].ident;
903-
if let RibKind::Module(module) = rib.kind
901+
if let RibKind::Module(module) | RibKind::Block(Some(module)) = rib.kind
904902
&& let Some(did) = find_doc_alias_name(self.r, module, item.name)
905903
{
906904
return Some((did, item));
@@ -2458,9 +2456,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
24582456
}
24592457
}
24602458

2461-
if let RibKind::Module(module) = rib.kind
2462-
&& let ModuleKind::Block = module.kind
2463-
{
2459+
if let RibKind::Block(Some(module)) = rib.kind {
24642460
self.r.add_module_candidates(module, &mut names, &filter_fn, Some(ctxt));
24652461
} else if let RibKind::Module(module) = rib.kind {
24662462
// Encountered a module item, abandon ribs and look into that module and preludes.

tests/ui/resolve/issue-104700-inner_scope.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,12 @@ fn main() {
77
if bar == 2 { //~ ERROR cannot find value
88
println!("yes");
99
}
10+
{
11+
let baz = 3;
12+
struct S;
13+
}
14+
if baz == 3 { //~ ERROR cannot find value
15+
println!("yes");
16+
}
1017
test_func(1); //~ ERROR cannot find function
1118
}

tests/ui/resolve/issue-104700-inner_scope.stderr

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,24 @@ help: the binding `bar` is available in a different scope in the same function
1010
LL | let bar = 2;
1111
| ^^^
1212

13+
error[E0425]: cannot find value `baz` in this scope
14+
--> $DIR/issue-104700-inner_scope.rs:14:8
15+
|
16+
LL | if baz == 3 {
17+
| ^^^
18+
|
19+
help: the binding `baz` is available in a different scope in the same function
20+
--> $DIR/issue-104700-inner_scope.rs:11:13
21+
|
22+
LL | let baz = 3;
23+
| ^^^
24+
1325
error[E0425]: cannot find function `test_func` in this scope
14-
--> $DIR/issue-104700-inner_scope.rs:10:5
26+
--> $DIR/issue-104700-inner_scope.rs:17:5
1527
|
1628
LL | test_func(1);
1729
| ^^^^^^^^^ not found in this scope
1830

19-
error: aborting due to 2 previous errors
31+
error: aborting due to 3 previous errors
2032

2133
For more information about this error, try `rustc --explain E0425`.

0 commit comments

Comments
 (0)