Skip to content

Commit 3af335e

Browse files
committed
wip: add test
1 parent e245c52 commit 3af335e

7 files changed

+420
-534
lines changed

compiler/rustc_resolve/src/ident.rs

Lines changed: 27 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)]
@@ -327,14 +327,32 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
327327

328328
module = match rib.kind {
329329
RibKind::Module(module) => module,
330-
RibKind::MacroDefinition(def) | RibKind::LookAheadMacroDefinition(def)
331-
if def == self.macro_def(ident.span.ctxt()) =>
332-
{
330+
RibKind::MacroDefinition(def) if def == self.macro_def(ident.span.ctxt()) => {
333331
// If an invocation of this macro created `ident`, give up on `ident`
334332
// and switch to `ident`'s source from the macro definition.
335333
ident.span.remove_mark();
336334
continue;
337335
}
336+
RibKind::BlockItem { block, resolving } => {
337+
tracing::debug!("------- try resolving {ident:#?} in {ns:#?}");
338+
tracing::debug!("-----resolving in block rib: {block:#?}");
339+
tracing::debug!(
340+
"-----bindings in block rib: {:#?}",
341+
self.lookahead_items_in_block[&block]
342+
);
343+
tracing::debug!("-----resolving: {resolving:#?}",);
344+
match self.lookahead_items_in_block.get(&block).and_then(|b| b.get(&resolving))
345+
{
346+
Some(LookaheadItemInBlock::Binding { name }) => {
347+
tracing::debug!("-----found binding in block rib: {name:#?}")
348+
}
349+
Some(LookaheadItemInBlock::MacroDef { name }) => {
350+
tracing::debug!("-----found macro def in block rib: {name:#?}")
351+
}
352+
_ => {}
353+
}
354+
continue;
355+
}
338356
_ => continue,
339357
};
340358

@@ -1149,10 +1167,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
11491167
for rib in ribs {
11501168
match rib.kind {
11511169
RibKind::Normal
1170+
| RibKind::BlockItem { .. }
11521171
| RibKind::FnOrCoroutine
11531172
| RibKind::Module(..)
11541173
| RibKind::MacroDefinition(..)
1155-
| RibKind::LookAheadMacroDefinition(..)
11561174
| RibKind::ForwardGenericParamBan(_) => {
11571175
// Nothing to do. Continue.
11581176
}
@@ -1242,10 +1260,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
12421260
for rib in ribs {
12431261
let (has_generic_params, def_kind) = match rib.kind {
12441262
RibKind::Normal
1263+
| RibKind::BlockItem { .. }
12451264
| RibKind::FnOrCoroutine
12461265
| RibKind::Module(..)
12471266
| RibKind::MacroDefinition(..)
1248-
| RibKind::LookAheadMacroDefinition(..)
12491267
| RibKind::InlineAsmSym
12501268
| RibKind::AssocItem
12511269
| RibKind::ForwardGenericParamBan(_) => {
@@ -1336,10 +1354,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
13361354
for rib in ribs {
13371355
let (has_generic_params, def_kind) = match rib.kind {
13381356
RibKind::Normal
1357+
| RibKind::BlockItem { .. }
13391358
| RibKind::FnOrCoroutine
13401359
| RibKind::Module(..)
13411360
| RibKind::MacroDefinition(..)
1342-
| RibKind::LookAheadMacroDefinition(..)
13431361
| RibKind::InlineAsmSym
13441362
| RibKind::AssocItem
13451363
| RibKind::ForwardGenericParamBan(_) => continue,

compiler/rustc_resolve/src/late.rs

Lines changed: 91 additions & 67 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;
@@ -193,6 +193,26 @@ 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+
/// let f = || -> i16 { 42 };
210+
/// let a: i16 = m!(); // use the local `f` rather than throw an error
211+
/// macro_rules! m {() => ( f() )}
212+
/// use m;
213+
/// ```
214+
BlockItem { block: NodeId, resolving: NodeId },
215+
196216
/// We passed through an impl or trait and are now in one of its
197217
/// methods or associated types. Allow references to ty params that impl or trait
198218
/// binds. Disallow any other upvars (including other ty params that are
@@ -217,41 +237,6 @@ pub(crate) enum RibKind<'ra> {
217237
/// We passed through a `macro_rules!` statement
218238
MacroDefinition(DefId),
219239

220-
/// Collects `macro_rules!` statements prior to resolution.
221-
/// For example:
222-
///
223-
/// ```ignore (illustrative)
224-
/// let f = || -> i16 { 42 }; // <1>
225-
/// let a: i16 = m!(); // <2>
226-
/// macro_rules! m {() => ( f() )} // <3>
227-
/// use m; // <4>
228-
/// ```
229-
///
230-
/// We record `<1>` when resolving the value of `<2>` (the expansion
231-
/// result of `<3>`), enabling the system to recognize that `<1>` is
232-
/// referenced in `<3>`.
233-
///
234-
/// ### Why Not Use `MacroDefinition` Directly?
235-
///
236-
/// This prevents edge cases like:
237-
///
238-
/// ```ignore (illustrative)
239-
/// fn f() {
240-
/// let x = 0; // <1>
241-
/// macro_rules! foo {
242-
/// () => {
243-
/// assert_eq!(x, 0);
244-
/// }
245-
/// }
246-
/// let x = 1; // <2>
247-
/// foo!();
248-
/// }
249-
/// ```
250-
///
251-
/// Using `MacroDefinition` would incorrectly record both `<1>` and `<2>` as
252-
/// potential resolutions for `x` within the macro, leading to assertion failed.
253-
LookAheadMacroDefinition(DefId),
254-
255240
/// All bindings in this rib are generic parameters that can't be used
256241
/// from the default of a generic parameter because they're not declared
257242
/// before said generic parameter. Also see the `visit_generics` override.
@@ -278,11 +263,11 @@ impl RibKind<'_> {
278263
pub(crate) fn contains_params(&self) -> bool {
279264
match self {
280265
RibKind::Normal
266+
| RibKind::BlockItem { .. }
281267
| RibKind::FnOrCoroutine
282268
| RibKind::ConstantItem(..)
283269
| RibKind::Module(_)
284270
| RibKind::MacroDefinition(_)
285-
| RibKind::LookAheadMacroDefinition(_)
286271
| RibKind::InlineAsmSym => false,
287272
RibKind::ConstParamTy
288273
| RibKind::AssocItem
@@ -294,9 +279,7 @@ impl RibKind<'_> {
294279
/// This rib forbids referring to labels defined in upwards ribs.
295280
fn is_label_barrier(self) -> bool {
296281
match self {
297-
RibKind::Normal
298-
| RibKind::MacroDefinition(..)
299-
| RibKind::LookAheadMacroDefinition(..) => false,
282+
RibKind::Normal | RibKind::BlockItem { .. } | RibKind::MacroDefinition(..) => false,
300283

301284
RibKind::AssocItem
302285
| RibKind::FnOrCoroutine
@@ -3818,21 +3801,16 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
38183801

38193802
/// Apply the bindings from a pattern to the innermost rib of the current scope.
38203803
fn apply_pattern_bindings(&mut self, mut pat_bindings: PatternBindings) {
3804+
let rib_bindings = self.innermost_rib_bindings(ValueNS);
38213805
let Some((_, pat_bindings)) = pat_bindings.pop() else {
38223806
bug!("tried applying nonexistent bindings from pattern");
38233807
};
3824-
for rib in self.ribs[ValueNS].iter_mut().rev() {
3825-
let stop = !matches!(rib.kind, RibKind::LookAheadMacroDefinition(_));
3826-
if rib.bindings.is_empty() {
3827-
// Often, such as for match arms, the bindings are introduced into a new rib.
3828-
// In this case, we can move the bindings over directly.
3829-
rib.bindings = pat_bindings.clone();
3830-
} else {
3831-
rib.bindings.extend(pat_bindings.clone());
3832-
}
3833-
if stop {
3834-
break;
3835-
}
3808+
if rib_bindings.is_empty() {
3809+
// Often, such as for match arms, the bindings are introduced into a new rib.
3810+
// In this case, we can move the bindings over directly.
3811+
*rib_bindings = pat_bindings;
3812+
} else {
3813+
rib_bindings.extend(pat_bindings);
38363814
}
38373815
}
38383816

@@ -3888,9 +3866,20 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
38883866
// First try to resolve the identifier as some existing entity,
38893867
// then fall back to a fresh binding.
38903868
let has_sub = sub.is_some();
3869+
if let Some(RibKind::BlockItem { resolving, .. }) =
3870+
self.label_ribs.last_mut().map(|rib| &mut rib.kind)
3871+
{
3872+
debug_assert_eq!(*resolving, DUMMY_NODE_ID);
3873+
*resolving = pat.id;
3874+
}
38913875
let res = self
38923876
.try_resolve_as_non_binding(pat_src, bmode, ident, has_sub)
38933877
.unwrap_or_else(|| self.fresh_binding(ident, pat.id, pat_src, bindings));
3878+
if let Some(RibKind::BlockItem { resolving, .. }) =
3879+
self.label_ribs.last_mut().map(|rib| &mut rib.kind)
3880+
{
3881+
*resolving = DUMMY_NODE_ID;
3882+
}
38943883
self.r.record_partial_res(pat.id, PartialRes::new(res));
38953884
self.r.record_pat_span(pat.id, pat.span);
38963885
}
@@ -4712,15 +4701,6 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
47124701
}
47134702

47144703
// Descend into the block.
4715-
for stmt in &block.stmts {
4716-
if let StmtKind::Item(ref item) = stmt.kind
4717-
&& let ItemKind::MacroDef(..) = item.kind
4718-
{
4719-
let res = self.r.local_def_id(item.id).to_def_id();
4720-
self.ribs[ValueNS].push(Rib::new(RibKind::LookAheadMacroDefinition(res)));
4721-
}
4722-
}
4723-
47244704
for stmt in &block.stmts {
47254705
if let StmtKind::Item(ref item) = stmt.kind
47264706
&& let ItemKind::MacroDef(..) = item.kind
@@ -4731,14 +4711,22 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
47314711
self.label_ribs.push(Rib::new(RibKind::MacroDefinition(res)));
47324712
}
47334713

4714+
4715+
self.with_rib(
4716+
ValueNS,
4717+
RibKind::BlockItem { block: block.id, resolving: DUMMY_NODE_ID },
4718+
|this| {
4719+
this.visit_stmt(stmt);
4720+
},
4721+
);
4722+
47344723
self.visit_stmt(stmt);
47354724
}
47364725

47374726
// Move back up.
47384727
self.parent_scope.module = orig_module;
47394728
for _ in 0..num_macro_definition_ribs {
4740-
// pop `LookAheadMacroDefinition` and `MacroDefinition`
4741-
self.ribs[ValueNS].pop();
4729+
// pop `MacroDefinition`
47424730
self.ribs[ValueNS].pop();
47434731
self.label_ribs.pop();
47444732
}
@@ -5199,6 +5187,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
51995187
/// lifetime generic parameters and function parameters.
52005188
struct ItemInfoCollector<'a, 'ra, 'tcx> {
52015189
r: &'a mut Resolver<'ra, 'tcx>,
5190+
current_block: Option<NodeId>,
52025191
}
52035192

52045193
impl ItemInfoCollector<'_, '_, '_> {
@@ -5218,6 +5207,26 @@ impl ItemInfoCollector<'_, '_, '_> {
52185207
};
52195208
self.r.delegation_fn_sigs.insert(self.r.local_def_id(id), sig);
52205209
}
5210+
5211+
fn collect_fresh_binding(&mut self, binding: NodeId, name: Ident) {
5212+
let block_id = self.current_block.unwrap();
5213+
let items = self.r.lookahead_items_in_block.entry(block_id).or_default();
5214+
items.insert(binding, LookaheadItemInBlock::Binding { name });
5215+
}
5216+
5217+
fn collect_macro_def_in_block(&mut self, block_id: NodeId, node_id: NodeId, name: Symbol) {
5218+
let items = self.r.lookahead_items_in_block.entry(block_id).or_default();
5219+
items.insert(node_id, LookaheadItemInBlock::MacroDef { name });
5220+
}
5221+
5222+
fn collect_fresh_binding_in_pat(&mut self, pat: &ast::Pat) {
5223+
pat.walk(&mut |pat| {
5224+
if let PatKind::Ident(_, name, _) = &pat.kind {
5225+
self.collect_fresh_binding(pat.id, *name);
5226+
}
5227+
true
5228+
});
5229+
}
52215230
}
52225231

52235232
impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
@@ -5255,11 +5264,15 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
52555264
}
52565265
}
52575266

5267+
ItemKind::MacroDef(m, _) => {
5268+
if let Some(block_id) = self.current_block {
5269+
self.collect_macro_def_in_block(block_id, item.id, m.name);
5270+
}
5271+
}
52585272
ItemKind::Mod(..)
52595273
| ItemKind::Static(..)
52605274
| ItemKind::Use(..)
52615275
| ItemKind::ExternCrate(..)
5262-
| ItemKind::MacroDef(..)
52635276
| ItemKind::GlobalAsm(..)
52645277
| ItemKind::MacCall(..)
52655278
| ItemKind::DelegationMac(..) => {}
@@ -5279,11 +5292,22 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
52795292
}
52805293
visit::walk_assoc_item(self, item, ctxt);
52815294
}
5295+
5296+
fn visit_local(&mut self, node: &'ast Local) -> Self::Result {
5297+
self.collect_fresh_binding_in_pat(&node.pat);
5298+
visit::walk_local(self, node)
5299+
}
5300+
5301+
fn visit_block(&mut self, node: &'ast Block) -> Self::Result {
5302+
let saved_block_id = self.current_block.replace(node.id);
5303+
visit::walk_block(self, node);
5304+
self.current_block = saved_block_id;
5305+
}
52825306
}
52835307

52845308
impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
52855309
pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) {
5286-
visit::walk_crate(&mut ItemInfoCollector { r: self }, krate);
5310+
visit::walk_crate(&mut ItemInfoCollector { r: self, current_block: None }, krate);
52875311
let mut late_resolution_visitor = LateResolutionVisitor::new(self);
52885312
late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID));
52895313
visit::walk_crate(&mut late_resolution_visitor, krate);

compiler/rustc_resolve/src/lib.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,6 +1042,14 @@ pub struct ResolverOutputs {
10421042
pub ast_lowering: ResolverAstLowering,
10431043
}
10441044

1045+
#[derive(Debug)]
1046+
enum LookaheadItemInBlock {
1047+
/// such as `let x = 1;`
1048+
Binding { name: Ident },
1049+
/// such as `macro_rules! foo { ... }`
1050+
MacroDef { name: Symbol },
1051+
}
1052+
10451053
/// The main resolver class.
10461054
///
10471055
/// This is the visitor that walks the whole crate.
@@ -1106,6 +1114,7 @@ pub struct Resolver<'ra, 'tcx> {
11061114
/// There will be an anonymous module created around `g` with the ID of the
11071115
/// entry block for `f`.
11081116
block_map: NodeMap<Module<'ra>>,
1117+
lookahead_items_in_block: NodeMap<FxIndexMap<NodeId, LookaheadItemInBlock>>,
11091118
/// A fake module that contains no definition and no prelude. Used so that
11101119
/// some AST passes can generate identifiers that only resolve to local or
11111120
/// lang items.
@@ -1629,6 +1638,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
16291638
current_crate_outer_attr_insert_span,
16301639
mods_with_parse_errors: Default::default(),
16311640
impl_trait_names: Default::default(),
1641+
lookahead_items_in_block: Default::default(),
16321642
};
16331643

16341644
let root_parent_scope = ParentScope::module(graph_root, &resolver);

0 commit comments

Comments
 (0)