Skip to content

Commit 3353199

Browse files
committed
fresh binding should shadow the def after expand
1 parent 99ba556 commit 3353199

12 files changed

+968
-46
lines changed

compiler/rustc_resolve/src/ident.rs

Lines changed: 73 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ use crate::late::{ConstantHasGenerics, NoConstantGenericsReason, PathSource, Rib
1717
use crate::macros::{MacroRulesScope, sub_namespace_match};
1818
use crate::{
1919
AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingKey, CmResolver, Determinacy,
20-
Finalize, ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot,
21-
NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError, Res, ResolutionError,
22-
Resolver, Scope, ScopeSet, Segment, Used, Weak, errors,
20+
Finalize, ImportKind, LexicalScopeBinding, LookaheadItemInBlock, Module, ModuleKind,
21+
ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError, Res,
22+
ResolutionError, Resolver, Scope, ScopeSet, Segment, Used, Weak, errors,
2323
};
2424

2525
#[derive(Copy, Clone)]
@@ -333,20 +333,73 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
333333
*original_rib_ident_def,
334334
ribs,
335335
)));
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));
336+
} else if let RibKind::Block { module, id: block_id } = rib.kind {
337+
if let Some(items) = self.lookahead_items_in_block.get(&block_id) {
338+
let mut expansion = None;
339+
for (node_id, item) in items
340+
.iter()
341+
.rev()
342+
.filter(|(_, item)| matches!(item, LookaheadItemInBlock::MacroDef { .. }))
343+
{
344+
let LookaheadItemInBlock::MacroDef { def_id, bindings, .. } = item else {
345+
unreachable!();
346+
};
347+
if *def_id != self.macro_def(ident.span.ctxt()) {
348+
continue;
349+
}
350+
expansion.get_or_insert(node_id);
351+
ident.span.remove_mark();
352+
if let Some((original_rib_ident_def, res)) = bindings.get_key_value(&ident)
353+
{
354+
// The ident resolves to a type parameter or local variable.
355+
return Some(LexicalScopeBinding::Res(self.validate_res_from_ribs(
356+
i,
357+
ident,
358+
*res,
359+
finalize.map(|finalize| finalize.path_span),
360+
*original_rib_ident_def,
361+
ribs,
362+
)));
363+
}
364+
}
365+
if let Some(expansion) = expansion
366+
&& items.iter().take_while(|(item_id, _)| !expansion.eq(item_id)).any(
367+
|(_, item)| {
368+
if let LookaheadItemInBlock::Binding { name } = item {
369+
name.name == ident.name
370+
} else {
371+
false
372+
}
373+
},
374+
)
375+
{
376+
// return `None` for this case:
377+
//
378+
// ```
379+
// let a = m!();
380+
// let b = 1;
381+
// macro_rules! m { () => { b } }
382+
// use b;
383+
// ```
384+
return None;
385+
}
386+
}
387+
388+
if let Some(module) = module
389+
&& let Ok(binding) = self.cm().resolve_ident_in_module_unadjusted(
390+
ModuleOrUniformRoot::Module(module),
391+
ident,
392+
ns,
393+
parent_scope,
394+
Shadowing::Unrestricted,
395+
finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }),
396+
ignore_binding,
397+
None,
398+
)
399+
{
400+
// The ident resolves to an item in a block.
401+
return Some(LexicalScopeBinding::Item(binding));
402+
}
350403
} else if let RibKind::Module(module) = rib.kind {
351404
// Encountered a module item, abandon ribs and look into that module and preludes.
352405
return self
@@ -1166,7 +1219,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
11661219
for rib in ribs {
11671220
match rib.kind {
11681221
RibKind::Normal
1169-
| RibKind::Block(..)
1222+
| RibKind::Block { .. }
11701223
| RibKind::FnOrCoroutine
11711224
| RibKind::Module(..)
11721225
| RibKind::MacroDefinition(..)
@@ -1259,7 +1312,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
12591312
for rib in ribs {
12601313
let (has_generic_params, def_kind) = match rib.kind {
12611314
RibKind::Normal
1262-
| RibKind::Block(..)
1315+
| RibKind::Block { .. }
12631316
| RibKind::FnOrCoroutine
12641317
| RibKind::Module(..)
12651318
| RibKind::MacroDefinition(..)
@@ -1353,7 +1406,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
13531406
for rib in ribs {
13541407
let (has_generic_params, def_kind) = match rib.kind {
13551408
RibKind::Normal
1356-
| RibKind::Block(..)
1409+
| RibKind::Block { .. }
13571410
| RibKind::FnOrCoroutine
13581411
| RibKind::Module(..)
13591412
| RibKind::MacroDefinition(..)

compiler/rustc_resolve/src/late.rs

Lines changed: 111 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ use thin_vec::ThinVec;
3939
use tracing::{debug, instrument, trace};
4040

4141
use crate::{
42-
BindingError, BindingKey, Finalize, LexicalScopeBinding, Module, ModuleOrUniformRoot,
43-
NameBinding, ParentScope, PathResult, ResolutionError, Resolver, Segment, TyCtxt, UseError,
44-
Used, errors, path_names_to_string, rustdoc,
42+
BindingError, BindingKey, Finalize, LexicalScopeBinding, LookaheadItemInBlock, Module,
43+
ModuleOrUniformRoot, NameBinding, ParentScope, PathResult, ResolutionError, Resolver, Segment,
44+
TyCtxt, UseError, Used, errors, path_names_to_string, rustdoc,
4545
};
4646

4747
mod diagnostics;
@@ -102,7 +102,7 @@ impl IntoDiagArg for PatternSource {
102102
/// Denotes whether the context for the set of already bound bindings is a `Product`
103103
/// or `Or` context. This is used in e.g., `fresh_binding` and `resolve_pattern_inner`.
104104
/// See those functions for more information.
105-
#[derive(PartialEq)]
105+
#[derive(PartialEq, Debug)]
106106
enum PatBoundCtx {
107107
/// A product pattern context, e.g., `Variant(a, b)`.
108108
Product,
@@ -197,7 +197,29 @@ pub(crate) enum RibKind<'ra> {
197197
/// `Block(None)` must be always processed in the same way as `Block(Some(module))`
198198
/// with empty `module`. The module can be `None` only because creation of some definitely
199199
/// empty modules is skipped as an optimization.
200-
Block(Option<Module<'ra>>),
200+
Block {
201+
module: Option<Module<'ra>>,
202+
/// The node id of block kind, which stores all bindings defined in
203+
/// this local scope, for these features:
204+
///
205+
/// - Forward reference detection:
206+
///
207+
/// ```ignore (illustrative)
208+
/// let a = b; // displays '`b` is defined at <span>' instead of ''b' not found'
209+
/// let b = 42;
210+
/// ```
211+
///
212+
/// - Correctly resolves the hoisting bindings within macro expand:
213+
///
214+
/// ```ignore (illustrative)
215+
/// fn f() {}
216+
/// let a: i16 = m!(); // throw error because it should use the local `f` rather than `fn f`
217+
/// let f = || -> i16 { 42 };
218+
/// macro_rules! m {() => ( f() )}
219+
/// use m;
220+
/// ```
221+
id: NodeId,
222+
},
201223

202224
/// We passed through an impl or trait and are now in one of its
203225
/// methods or associated types. Allow references to ty params that impl or trait
@@ -249,7 +271,7 @@ impl RibKind<'_> {
249271
pub(crate) fn contains_params(&self) -> bool {
250272
match self {
251273
RibKind::Normal
252-
| RibKind::Block(..)
274+
| RibKind::Block { .. }
253275
| RibKind::FnOrCoroutine
254276
| RibKind::ConstantItem(..)
255277
| RibKind::Module(_)
@@ -2816,7 +2838,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
28162838
for parent_rib in self.ribs[ns].iter().rev() {
28172839
// Break at module or block level, to account for nested items which are
28182840
// allowed to shadow generic param names.
2819-
if matches!(parent_rib.kind, RibKind::Module(..) | RibKind::Block(..)) {
2841+
if matches!(parent_rib.kind, RibKind::Module(..) | RibKind::Block { .. }) {
28202842
break;
28212843
}
28222844

@@ -3769,6 +3791,52 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
37693791
fn resolve_pattern_top(&mut self, pat: &'ast Pat, pat_src: PatternSource) {
37703792
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
37713793
self.resolve_pattern(pat, pat_src, &mut bindings);
3794+
3795+
let mut last_pat_id = None;
3796+
pat.walk(&mut |pat| {
3797+
if let PatKind::Ident(..) = pat.kind {
3798+
last_pat_id = Some(pat.id);
3799+
}
3800+
true
3801+
});
3802+
3803+
if let Some(last_pat_id) = last_pat_id
3804+
&& let RibKind::Block { id: block, .. } = self.ribs[ValueNS].last_mut().unwrap().kind
3805+
&& let Some(items) = self.r.lookahead_items_in_block.get_mut(&block)
3806+
{
3807+
let start = items.get_index_of(&last_pat_id).unwrap_or_else(|| {
3808+
panic!("pattern({pat:#?}) not found in lookahead items");
3809+
});
3810+
// let mut first_macro: Option<SyntaxContext> = None;
3811+
// `need_removed` used for avoid injecting masked names into macro definition bindings:
3812+
//
3813+
// ```
3814+
// let x = 0;
3815+
// macro_rules! m0 {() => { x; }} // Injects `let x = 0` into `m0`
3816+
// let x = 1;
3817+
// macro_rules! m1 {() => { x; }} // Should NOT inject `let x = 0` into `m1`
3818+
// ```
3819+
let mut need_removed = FxHashSet::default();
3820+
for (_, item) in items.iter_mut().skip(start + 1) {
3821+
match item {
3822+
LookaheadItemInBlock::Binding { name } => {
3823+
need_removed.insert(name.normalize_to_macro_rules());
3824+
}
3825+
LookaheadItemInBlock::MacroDef { bindings: macro_bindings, .. } => {
3826+
let bindings =
3827+
bindings.last().unwrap().1.iter().filter_map(|(name, res)| {
3828+
if !need_removed.contains(&name) {
3829+
Some((*name, *res))
3830+
} else {
3831+
None
3832+
}
3833+
});
3834+
macro_bindings.extend(bindings);
3835+
}
3836+
}
3837+
}
3838+
}
3839+
37723840
self.apply_pattern_bindings(bindings);
37733841
}
37743842

@@ -4650,11 +4718,12 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
46504718
let mut num_macro_definition_ribs = 0;
46514719
if let Some(anonymous_module) = anonymous_module {
46524720
debug!("(resolving block) found anonymous module, moving down");
4653-
self.ribs[ValueNS].push(Rib::new(RibKind::Block(Some(anonymous_module))));
4654-
self.ribs[TypeNS].push(Rib::new(RibKind::Block(Some(anonymous_module))));
4721+
let rib_kind = RibKind::Block { module: Some(anonymous_module), id: block.id };
4722+
self.ribs[ValueNS].push(Rib::new(rib_kind));
4723+
self.ribs[TypeNS].push(Rib::new(rib_kind));
46554724
self.parent_scope.module = anonymous_module;
46564725
} else {
4657-
self.ribs[ValueNS].push(Rib::new(RibKind::Block(None)));
4726+
self.ribs[ValueNS].push(Rib::new(RibKind::Block { module: None, id: block.id }));
46584727
}
46594728

46604729
// Descend into the block.
@@ -4664,7 +4733,6 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
46644733
{
46654734
num_macro_definition_ribs += 1;
46664735
let res = self.r.local_def_id(item.id).to_def_id();
4667-
self.ribs[ValueNS].push(Rib::new(RibKind::MacroDefinition(res)));
46684736
self.label_ribs.push(Rib::new(RibKind::MacroDefinition(res)));
46694737
}
46704738

@@ -4674,7 +4742,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
46744742
// Move back up.
46754743
self.parent_scope.module = orig_module;
46764744
for _ in 0..num_macro_definition_ribs {
4677-
self.ribs[ValueNS].pop();
4745+
// pop `MacroDefinition`
46784746
self.label_ribs.pop();
46794747
}
46804748
self.last_block_rib = self.ribs[ValueNS].pop();
@@ -5134,6 +5202,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
51345202
/// lifetime generic parameters and function parameters.
51355203
struct ItemInfoCollector<'a, 'ra, 'tcx> {
51365204
r: &'a mut Resolver<'ra, 'tcx>,
5205+
current_block: Option<NodeId>,
51375206
}
51385207

51395208
impl ItemInfoCollector<'_, '_, '_> {
@@ -5189,12 +5258,20 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
51895258
}
51905259
}
51915260
}
5192-
5261+
ItemKind::MacroDef(_, _) => {
5262+
if let Some(block_id) = self.current_block {
5263+
let def_id = self.r.local_def_id(item.id).to_def_id();
5264+
let items = self.r.lookahead_items_in_block.entry(block_id).or_default();
5265+
items.insert(
5266+
item.id,
5267+
LookaheadItemInBlock::MacroDef { bindings: Default::default(), def_id },
5268+
);
5269+
}
5270+
}
51935271
ItemKind::Mod(..)
51945272
| ItemKind::Static(..)
51955273
| ItemKind::Use(..)
51965274
| ItemKind::ExternCrate(..)
5197-
| ItemKind::MacroDef(..)
51985275
| ItemKind::GlobalAsm(..)
51995276
| ItemKind::MacCall(..)
52005277
| ItemKind::DelegationMac(..) => {}
@@ -5214,11 +5291,30 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
52145291
}
52155292
visit::walk_assoc_item(self, item, ctxt);
52165293
}
5294+
5295+
fn visit_local(&mut self, node: &'ast Local) -> Self::Result {
5296+
// collect local bindings into block
5297+
node.pat.walk(&mut |pat| {
5298+
if let PatKind::Ident(_, name, _) = &pat.kind {
5299+
let block_id = self.current_block.unwrap();
5300+
let items = self.r.lookahead_items_in_block.entry(block_id).or_default();
5301+
items.insert(pat.id, LookaheadItemInBlock::Binding { name: *name });
5302+
}
5303+
true
5304+
});
5305+
visit::walk_local(self, node)
5306+
}
5307+
5308+
fn visit_block(&mut self, node: &'ast Block) -> Self::Result {
5309+
let saved_block_id = self.current_block.replace(node.id);
5310+
visit::walk_block(self, node);
5311+
self.current_block = saved_block_id;
5312+
}
52175313
}
52185314

52195315
impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
52205316
pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) {
5221-
visit::walk_crate(&mut ItemInfoCollector { r: self }, krate);
5317+
visit::walk_crate(&mut ItemInfoCollector { r: self, current_block: None }, krate);
52225318
let mut late_resolution_visitor = LateResolutionVisitor::new(self);
52235319
late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID));
52245320
visit::walk_crate(&mut late_resolution_visitor, krate);

compiler/rustc_resolve/src/late/diagnostics.rs

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -898,7 +898,8 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
898898
if path.len() == 1 {
899899
for rib in self.ribs[ns].iter().rev() {
900900
let item = path[0].ident;
901-
if let RibKind::Module(module) | RibKind::Block(Some(module)) = rib.kind
901+
if let RibKind::Module(module) | RibKind::Block { module: Some(module), .. } =
902+
rib.kind
902903
&& let Some(did) = find_doc_alias_name(self.r, module, item.name)
903904
{
904905
return Some((did, item));
@@ -2438,7 +2439,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
24382439
) -> TypoCandidate {
24392440
let mut names = Vec::new();
24402441
if let [segment] = path {
2441-
let mut ctxt = segment.ident.span.ctxt();
2442+
let ctxt = segment.ident.span.ctxt();
24422443

24432444
// Search in lexical scope.
24442445
// Walk backwards up the ribs in scope and collect candidates.
@@ -2456,7 +2457,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
24562457
}
24572458
}
24582459

2459-
if let RibKind::Block(Some(module)) = rib.kind {
2460+
if let RibKind::Block { module: Some(module), .. } = rib.kind {
24602461
self.r.add_module_candidates(module, &mut names, &filter_fn, Some(ctxt));
24612462
} else if let RibKind::Module(module) = rib.kind {
24622463
// Encountered a module item, abandon ribs and look into that module and preludes.
@@ -2469,14 +2470,6 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
24692470
);
24702471
break;
24712472
}
2472-
2473-
if let RibKind::MacroDefinition(def) = rib.kind
2474-
&& def == self.r.macro_def(ctxt)
2475-
{
2476-
// If an invocation of this macro created `ident`, give up on `ident`
2477-
// and switch to `ident`'s source from the macro definition.
2478-
ctxt.remove_mark();
2479-
}
24802473
}
24812474
} else {
24822475
// Search in module.

0 commit comments

Comments
 (0)