Skip to content

Commit 7cdd24d

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

File tree

5 files changed

+99
-91
lines changed

5 files changed

+99
-91
lines changed

compiler/rustc_resolve/src/ident.rs

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

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

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

378373
/// Resolve an identifier in lexical scope.
@@ -1157,6 +1152,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
11571152
for rib in ribs {
11581153
match rib.kind {
11591154
RibKind::Normal
1155+
| RibKind::Block(..)
11601156
| RibKind::FnOrCoroutine
11611157
| RibKind::Module(..)
11621158
| RibKind::MacroDefinition(..)
@@ -1249,6 +1245,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
12491245
for rib in ribs {
12501246
let (has_generic_params, def_kind) = match rib.kind {
12511247
RibKind::Normal
1248+
| RibKind::Block(..)
12521249
| RibKind::FnOrCoroutine
12531250
| RibKind::Module(..)
12541251
| RibKind::MacroDefinition(..)
@@ -1342,6 +1339,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
13421339
for rib in ribs {
13431340
let (has_generic_params, def_kind) = match rib.kind {
13441341
RibKind::Normal
1342+
| RibKind::Block(..)
13451343
| RibKind::FnOrCoroutine
13461344
| RibKind::Module(..)
13471345
| 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

@@ -4664,16 +4657,16 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
46644657
debug!("(resolving block) entering block");
46654658
// Move down in the graph, if there's an anonymous module rooted here.
46664659
let orig_module = self.parent_scope.module;
4667-
let anonymous_module = self.r.block_map.get(&block.id).cloned(); // clones a reference
4660+
let anonymous_module = self.r.block_map.get(&block.id).copied();
46684661

46694662
let mut num_macro_definition_ribs = 0;
46704663
if let Some(anonymous_module) = anonymous_module {
46714664
debug!("(resolving block) found anonymous module, moving down");
4672-
self.ribs[ValueNS].push(Rib::new(RibKind::Module(anonymous_module)));
4673-
self.ribs[TypeNS].push(Rib::new(RibKind::Module(anonymous_module)));
4665+
self.ribs[ValueNS].push(Rib::new(RibKind::Block(Some(anonymous_module))));
4666+
self.ribs[TypeNS].push(Rib::new(RibKind::Block(Some(anonymous_module))));
46744667
self.parent_scope.module = anonymous_module;
46754668
} else {
4676-
self.ribs[ValueNS].push(Rib::new(RibKind::Normal));
4669+
self.ribs[ValueNS].push(Rib::new(RibKind::Block(None)));
46774670
}
46784671

46794672
// Descend into the block.

compiler/rustc_resolve/src/late/diagnostics.rs

Lines changed: 3 additions & 5 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));
@@ -2468,7 +2466,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
24682466
}
24692467

24702468
// Items in scope
2471-
if let RibKind::Module(module) = rib.kind {
2469+
if let RibKind::Module(module) | RibKind::Block(Some(module)) = rib.kind {
24722470
// Items from this module
24732471
self.r.add_module_candidates(module, &mut names, &filter_fn, Some(ctxt));
24742472

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)