Skip to content

Commit 842d9ca

Browse files
committed
fresh binding should shadow the def after expand
1 parent 0f35336 commit 842d9ca

12 files changed

+960
-36
lines changed

compiler/rustc_resolve/src/ident.rs

Lines changed: 58 additions & 9 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, Determinacy, Finalize,
20-
ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot, NameBinding,
21-
NameBindingKind, ParentScope, PathResult, PrivacyError, Res, ResolutionError, Resolver, Scope,
22-
ScopeSet, Segment, Used, Weak, errors,
20+
ImportKind, LexicalScopeBinding, LookaheadItemInBlock, Module, ModuleKind, ModuleOrUniformRoot,
21+
NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError, Res, ResolutionError,
22+
Resolver, Scope, ScopeSet, Segment, Used, Weak, errors,
2323
};
2424

2525
#[derive(Copy, Clone)]
@@ -325,14 +325,60 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
325325
)));
326326
}
327327

328-
module = match rib.kind {
329-
RibKind::Module(module) => module,
330-
RibKind::MacroDefinition(def) if def == self.macro_def(ident.span.ctxt()) => {
331-
// If an invocation of this macro created `ident`, give up on `ident`
332-
// and switch to `ident`'s source from the macro definition.
328+
if let RibKind::Block { id: block_id, .. } = &rib.kind
329+
&& let Some(items) = self.lookahead_items_in_block.get(block_id)
330+
{
331+
let mut expansion = None;
332+
for (node_id, item) in items
333+
.iter()
334+
.rev()
335+
.filter(|(_, item)| matches!(item, LookaheadItemInBlock::MacroDef { .. }))
336+
{
337+
let LookaheadItemInBlock::MacroDef { def_id, bindings, .. } = item else {
338+
unreachable!();
339+
};
340+
if *def_id != self.macro_def(ident.span.ctxt()) {
341+
continue;
342+
}
343+
expansion.get_or_insert(node_id);
333344
ident.span.remove_mark();
334-
continue;
345+
if let Some((original_rib_ident_def, res)) = bindings.get_key_value(&ident) {
346+
// The ident resolves to a type parameter or local variable.
347+
return Some(LexicalScopeBinding::Res(self.validate_res_from_ribs(
348+
i,
349+
ident,
350+
*res,
351+
finalize.map(|finalize| finalize.path_span),
352+
*original_rib_ident_def,
353+
ribs,
354+
)));
355+
}
335356
}
357+
if let Some(expansion) = expansion
358+
&& items.iter().take_while(|(item_id, _)| !expansion.eq(item_id)).any(
359+
|(_, item)| {
360+
if let LookaheadItemInBlock::Binding { name } = item {
361+
name.name == ident.name
362+
} else {
363+
false
364+
}
365+
},
366+
)
367+
{
368+
// return `None` for this case:
369+
//
370+
// ```
371+
// let a = m!();
372+
// let b = 1;
373+
// macro_rules! m { () => { b } }
374+
// use b;
375+
// ```
376+
return None;
377+
}
378+
}
379+
380+
module = match rib.kind {
381+
RibKind::Module(module) => module,
336382
_ => continue,
337383
};
338384

@@ -1147,6 +1193,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
11471193
for rib in ribs {
11481194
match rib.kind {
11491195
RibKind::Normal
1196+
| RibKind::Block { .. }
11501197
| RibKind::FnOrCoroutine
11511198
| RibKind::Module(..)
11521199
| RibKind::MacroDefinition(..)
@@ -1239,6 +1286,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
12391286
for rib in ribs {
12401287
let (has_generic_params, def_kind) = match rib.kind {
12411288
RibKind::Normal
1289+
| RibKind::Block { .. }
12421290
| RibKind::FnOrCoroutine
12431291
| RibKind::Module(..)
12441292
| RibKind::MacroDefinition(..)
@@ -1332,6 +1380,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
13321380
for rib in ribs {
13331381
let (has_generic_params, def_kind) = match rib.kind {
13341382
RibKind::Normal
1383+
| RibKind::Block { .. }
13351384
| RibKind::FnOrCoroutine
13361385
| RibKind::Module(..)
13371386
| RibKind::MacroDefinition(..)

compiler/rustc_resolve/src/late.rs

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

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

4848
mod diagnostics;
@@ -103,7 +103,7 @@ impl IntoDiagArg for PatternSource {
103103
/// Denotes whether the context for the set of already bound bindings is a `Product`
104104
/// or `Or` context. This is used in e.g., `fresh_binding` and `resolve_pattern_inner`.
105105
/// See those functions for more information.
106-
#[derive(PartialEq)]
106+
#[derive(PartialEq, Debug)]
107107
enum PatBoundCtx {
108108
/// A product pattern context, e.g., `Variant(a, b)`.
109109
Product,
@@ -193,6 +193,27 @@ pub(crate) enum RibKind<'ra> {
193193
/// No restriction needs to be applied.
194194
Normal,
195195

196+
/// During resolving an item in a block, we had records all bindings defined
197+
/// in this local scope, for these features:
198+
///
199+
/// - Forward reference detection:
200+
///
201+
/// ```ignore (illustrative)
202+
/// let a = b; // displays '`b` is defined at <span>' instead of ''b' not found'
203+
/// let b = 42;
204+
/// ```
205+
///
206+
/// - Correctly resolves the hoisting bindings within macro expand:
207+
///
208+
/// ```ignore (illustrative)
209+
/// fn f() {}
210+
/// let a: i16 = m!(); // throw error because it should use the local `f` rather than `fn f`
211+
/// let f = || -> i16 { 42 };
212+
/// macro_rules! m {() => ( f() )}
213+
/// use m;
214+
/// ```
215+
Block { id: NodeId, is_module: bool },
216+
196217
/// We passed through an impl or trait and are now in one of its
197218
/// methods or associated types. Allow references to ty params that impl or trait
198219
/// binds. Disallow any other upvars (including other ty params that are
@@ -243,6 +264,7 @@ impl RibKind<'_> {
243264
pub(crate) fn contains_params(&self) -> bool {
244265
match self {
245266
RibKind::Normal
267+
| RibKind::Block { .. }
246268
| RibKind::FnOrCoroutine
247269
| RibKind::ConstantItem(..)
248270
| RibKind::Module(_)
@@ -258,7 +280,7 @@ impl RibKind<'_> {
258280
/// This rib forbids referring to labels defined in upwards ribs.
259281
fn is_label_barrier(self) -> bool {
260282
match self {
261-
RibKind::Normal | RibKind::MacroDefinition(..) => false,
283+
RibKind::Normal | RibKind::Block { .. } | RibKind::MacroDefinition(..) => false,
262284

263285
RibKind::AssocItem
264286
| RibKind::FnOrCoroutine
@@ -740,7 +762,7 @@ struct LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
740762
ribs: PerNS<Vec<Rib<'ra>>>,
741763

742764
/// Previous popped `rib`, only used for diagnostic.
743-
last_block_rib: Option<Rib<'ra>>,
765+
last_normal_block_rib: Option<Rib<'ra>>,
744766

745767
/// The current set of local scopes, for labels.
746768
label_ribs: Vec<Rib<'ra, NodeId>>,
@@ -1086,7 +1108,7 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc
10861108
// Be sure not to set this until the function signature has been resolved.
10871109
let previous_state = replace(&mut this.in_func_body, true);
10881110
// We only care block in the same function
1089-
this.last_block_rib = None;
1111+
this.last_normal_block_rib = None;
10901112
// Resolve the function body, potentially inside the body of an async closure
10911113
this.with_lifetime_rib(
10921114
LifetimeRibKind::Elided(LifetimeRes::Infer),
@@ -1434,7 +1456,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
14341456
type_ns: vec![Rib::new(start_rib_kind)],
14351457
macro_ns: vec![Rib::new(start_rib_kind)],
14361458
},
1437-
last_block_rib: None,
1459+
last_normal_block_rib: None,
14381460
label_ribs: Vec::new(),
14391461
lifetime_ribs: Vec::new(),
14401462
lifetime_elision_candidates: None,
@@ -2822,7 +2844,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
28222844
for parent_rib in self.ribs[ns].iter().rev() {
28232845
// Break at mod level, to account for nested items which are
28242846
// allowed to shadow generic param names.
2825-
if matches!(parent_rib.kind, RibKind::Module(..)) {
2847+
if matches!(
2848+
parent_rib.kind,
2849+
RibKind::Module(..) | RibKind::Block { is_module: true, .. }
2850+
) {
28262851
break;
28272852
}
28282853

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

@@ -4658,6 +4729,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
46584729
// Move down in the graph, if there's an anonymous module rooted here.
46594730
let orig_module = self.parent_scope.module;
46604731
let anonymous_module = self.r.block_map.get(&block.id).cloned(); // clones a reference
4732+
let is_module_block = anonymous_module.is_some();
46614733

46624734
let mut num_macro_definition_ribs = 0;
46634735
if let Some(anonymous_module) = anonymous_module {
@@ -4669,14 +4741,15 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
46694741
self.ribs[ValueNS].push(Rib::new(RibKind::Normal));
46704742
}
46714743

4744+
self.ribs[ValueNS]
4745+
.push(Rib::new(RibKind::Block { id: block.id, is_module: is_module_block }));
46724746
// Descend into the block.
46734747
for stmt in &block.stmts {
46744748
if let StmtKind::Item(ref item) = stmt.kind
46754749
&& let ItemKind::MacroDef(..) = item.kind
46764750
{
46774751
num_macro_definition_ribs += 1;
46784752
let res = self.r.local_def_id(item.id).to_def_id();
4679-
self.ribs[ValueNS].push(Rib::new(RibKind::MacroDefinition(res)));
46804753
self.label_ribs.push(Rib::new(RibKind::MacroDefinition(res)));
46814754
}
46824755

@@ -4686,10 +4759,14 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
46864759
// Move back up.
46874760
self.parent_scope.module = orig_module;
46884761
for _ in 0..num_macro_definition_ribs {
4689-
self.ribs[ValueNS].pop();
4762+
// pop `MacroDefinition`
46904763
self.label_ribs.pop();
46914764
}
4692-
self.last_block_rib = self.ribs[ValueNS].pop();
4765+
let block_rib = self.ribs[ValueNS].pop(); // pop `RibKind::Block`
4766+
if !is_module_block {
4767+
self.last_normal_block_rib = block_rib;
4768+
}
4769+
self.ribs[ValueNS].pop(); // pop `RibKind::Module` or `RibKind::Normal`
46934770
if anonymous_module.is_some() {
46944771
self.ribs[TypeNS].pop();
46954772
}
@@ -5146,6 +5223,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
51465223
/// lifetime generic parameters and function parameters.
51475224
struct ItemInfoCollector<'a, 'ra, 'tcx> {
51485225
r: &'a mut Resolver<'ra, 'tcx>,
5226+
current_block: Option<NodeId>,
51495227
}
51505228

51515229
impl ItemInfoCollector<'_, '_, '_> {
@@ -5165,6 +5243,30 @@ impl ItemInfoCollector<'_, '_, '_> {
51655243
};
51665244
self.r.delegation_fn_sigs.insert(self.r.local_def_id(id), sig);
51675245
}
5246+
5247+
fn collect_fresh_binding(&mut self, binding: NodeId, name: Ident) {
5248+
let block_id = self.current_block.unwrap();
5249+
let items = self.r.lookahead_items_in_block.entry(block_id).or_default();
5250+
items.insert(binding, LookaheadItemInBlock::Binding { name });
5251+
}
5252+
5253+
fn collect_macro_def_in_block(&mut self, block_id: NodeId, node_id: NodeId) {
5254+
let def_id = self.r.local_def_id(node_id).to_def_id();
5255+
let items = self.r.lookahead_items_in_block.entry(block_id).or_default();
5256+
items.insert(
5257+
node_id,
5258+
LookaheadItemInBlock::MacroDef { bindings: Default::default(), def_id },
5259+
);
5260+
}
5261+
5262+
fn collect_fresh_binding_in_pat(&mut self, pat: &ast::Pat) {
5263+
pat.walk(&mut |pat| {
5264+
if let PatKind::Ident(_, name, _) = &pat.kind {
5265+
self.collect_fresh_binding(pat.id, *name);
5266+
}
5267+
true
5268+
});
5269+
}
51685270
}
51695271

51705272
impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
@@ -5201,12 +5303,15 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
52015303
}
52025304
}
52035305
}
5204-
5306+
ItemKind::MacroDef(_, _) => {
5307+
if let Some(block_id) = self.current_block {
5308+
self.collect_macro_def_in_block(block_id, item.id);
5309+
}
5310+
}
52055311
ItemKind::Mod(..)
52065312
| ItemKind::Static(..)
52075313
| ItemKind::Use(..)
52085314
| ItemKind::ExternCrate(..)
5209-
| ItemKind::MacroDef(..)
52105315
| ItemKind::GlobalAsm(..)
52115316
| ItemKind::MacCall(..)
52125317
| ItemKind::DelegationMac(..) => {}
@@ -5226,11 +5331,22 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
52265331
}
52275332
visit::walk_assoc_item(self, item, ctxt);
52285333
}
5334+
5335+
fn visit_local(&mut self, node: &'ast Local) -> Self::Result {
5336+
self.collect_fresh_binding_in_pat(&node.pat);
5337+
visit::walk_local(self, node)
5338+
}
5339+
5340+
fn visit_block(&mut self, node: &'ast Block) -> Self::Result {
5341+
let saved_block_id = self.current_block.replace(node.id);
5342+
visit::walk_block(self, node);
5343+
self.current_block = saved_block_id;
5344+
}
52295345
}
52305346

52315347
impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
52325348
pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) {
5233-
visit::walk_crate(&mut ItemInfoCollector { r: self }, krate);
5349+
visit::walk_crate(&mut ItemInfoCollector { r: self, current_block: None }, krate);
52345350
let mut late_resolution_visitor = LateResolutionVisitor::new(self);
52355351
late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID));
52365352
visit::walk_crate(&mut late_resolution_visitor, krate);

0 commit comments

Comments
 (0)