Skip to content

Commit f06b317

Browse files
committed
Collect hirless def ids and skip them when iterating parents
1 parent db6bc0f commit f06b317

File tree

7 files changed

+178
-4
lines changed

7 files changed

+178
-4
lines changed

compiler/rustc_ast/src/visit.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,6 @@ macro_rules! common_visitor_and_walkers {
442442
FormatArgumentKind,
443443
FormatArguments,
444444
FormatPlaceholder,
445-
GenericParamKind,
446445
Impl,
447446
ImplPolarity,
448447
Inline,
@@ -485,7 +484,6 @@ macro_rules! common_visitor_and_walkers {
485484
UnsafeSource,
486485
UseTreeKind,
487486
VisibilityKind,
488-
WhereBoundPredicate,
489487
WhereClause,
490488
WhereEqPredicate,
491489
WhereRegionPredicate,
@@ -577,6 +575,7 @@ macro_rules! common_visitor_and_walkers {
577575
fn visit_generic_arg(GenericArg);
578576
fn visit_generic_args(GenericArgs);
579577
fn visit_generic_param(GenericParam);
578+
fn visit_generic_param_kind(GenericParamKind);
580579
fn visit_generics(Generics);
581580
fn visit_inline_asm(InlineAsm);
582581
fn visit_inline_asm_sym(InlineAsmSym);
@@ -604,6 +603,7 @@ macro_rules! common_visitor_and_walkers {
604603
fn visit_vis(Visibility);
605604
fn visit_where_predicate_kind(WherePredicateKind);
606605
fn visit_where_predicate(WherePredicate);
606+
fn visit_where_bound_predicate(WhereBoundPredicate);
607607
);
608608

609609
// We want `Visitor` to take the `NodeId` by value.
@@ -1097,6 +1097,7 @@ macro_rules! common_visitor_and_walkers {
10971097
pub fn walk_generic_arg(GenericArg);
10981098
pub fn walk_generic_args(GenericArgs);
10991099
pub fn walk_generic_param(GenericParam);
1100+
pub fn walk_generic_param_kind(GenericParamKind);
11001101
pub fn walk_generics(Generics);
11011102
pub fn walk_inline_asm(InlineAsm);
11021103
pub fn walk_inline_asm_sym(InlineAsmSym);
@@ -1124,6 +1125,7 @@ macro_rules! common_visitor_and_walkers {
11241125
pub fn walk_vis(Visibility);
11251126
pub fn walk_where_predicate_kind(WherePredicateKind);
11261127
pub fn walk_where_predicate(WherePredicate);
1128+
pub fn walk_where_bound_predicate(WhereBoundPredicate);
11271129
);
11281130
};
11291131
}

compiler/rustc_middle/src/hir/map.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use rustc_hir::*;
1717
use rustc_hir_pretty as pprust_hir;
1818
use rustc_span::def_id::StableCrateId;
1919
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, with_metavar_spans};
20+
use tracing::debug;
2021

2122
use crate::hir::{ModuleItems, nested_filter};
2223
use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
@@ -50,6 +51,13 @@ impl<'tcx> Iterator for ParentHirIterator<'tcx> {
5051
let HirId { owner, local_id } = self.current_id;
5152

5253
let parent_id = if local_id == ItemLocalId::ZERO {
54+
if let Some(parent_def_id) = self.tcx.opt_local_parent(owner.def_id)
55+
&& self.tcx.resolutions(()).hirless_def_ids.contains(&parent_def_id)
56+
{
57+
debug!("{:?} has hirless parent {:?}", owner, parent_def_id);
58+
return None;
59+
}
60+
5361
// We go from an owner to its parent, so clear the cache.
5462
self.current_owner_nodes = None;
5563
self.tcx.hir_owner_parent(owner)

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ pub struct ResolverGlobalCtxt {
190190
pub doc_link_traits_in_scope: FxIndexMap<LocalDefId, Vec<DefId>>,
191191
pub all_macro_rules: UnordSet<Symbol>,
192192
pub stripped_cfg_items: Vec<StrippedCfgItem>,
193+
pub hirless_def_ids: UnordSet<LocalDefId>,
193194
}
194195

195196
/// Resolutions that should only be used for lowering.

compiler/rustc_resolve/src/def_collector.rs

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::mem;
22

3-
use rustc_ast::visit::FnKind;
3+
use rustc_ast::visit::{BoundKind, FnKind};
44
use rustc_ast::*;
55
use rustc_attr_parsing::{AttributeParser, Early, OmitDoc, ShouldEmit};
66
use rustc_expand::expand::AstFragment;
@@ -311,6 +311,19 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
311311
}
312312
}
313313

314+
fn visit_where_bound_predicate(&mut self, pred: &'a WhereBoundPredicate) {
315+
let prev = self.resolver.visit_non_lifetime_binder.enter_where_bound_predicate();
316+
for generic_param in &pred.bound_generic_params {
317+
self.visit_generic_param(&generic_param);
318+
}
319+
self.resolver.visit_non_lifetime_binder = prev;
320+
321+
self.visit_ty(&pred.bounded_ty);
322+
for generic_bound in &pred.bounds {
323+
self.visit_param_bound(generic_bound, BoundKind::Bound);
324+
}
325+
}
326+
314327
fn visit_variant_data(&mut self, data: &'a VariantData) {
315328
// The assumption here is that non-`cfg` macro expansion cannot change field indices.
316329
// It currently holds because only inert attributes are accepted on fields,
@@ -339,10 +352,32 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
339352
//
340353
// In that case, the impl-trait is lowered as an additional generic parameter.
341354
self.with_impl_trait(ImplTraitContext::Universal, |this| {
342-
visit::walk_generic_param(this, param)
355+
this.visit_id(param.id);
356+
this.visit_ident(&param.ident);
357+
for attr in &param.attrs {
358+
this.visit_attribute(attr)
359+
}
360+
361+
let prev = this.resolver.visit_non_lifetime_binder.enter_generic_bound();
362+
for bound in &param.bounds {
363+
this.visit_param_bound(bound, BoundKind::Bound);
364+
}
365+
this.resolver.visit_non_lifetime_binder = prev;
366+
367+
this.visit_generic_param_kind(&param.kind);
343368
});
344369
}
345370

371+
fn visit_poly_trait_ref(&mut self, poly_trait_ref: &'a PolyTraitRef) {
372+
let prev = self.resolver.visit_non_lifetime_binder.enter_where_bound_predicate();
373+
for generic_param in &poly_trait_ref.bound_generic_params {
374+
self.visit_generic_param(&generic_param);
375+
}
376+
self.resolver.visit_non_lifetime_binder = prev;
377+
378+
self.visit_trait_ref(&poly_trait_ref.trait_ref);
379+
}
380+
346381
fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) {
347382
let (ident, def_kind) = match &i.kind {
348383
AssocItemKind::Fn(box Fn { ident, .. })
@@ -372,6 +407,12 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
372407
if !self.resolver.tcx.features().min_generic_const_args() {
373408
let parent =
374409
self.create_def(constant.id, None, DefKind::AnonConst, constant.value.span);
410+
411+
if self.resolver.visit_non_lifetime_binder.in_generic_bound() {
412+
// Record anno const blocks inside non-lifetime binders, e.g., `for<T: Trait<{ ... }>>`.
413+
self.resolver.hirless_def_ids.insert(parent);
414+
}
415+
375416
return self.with_parent(parent, |this| visit::walk_anon_const(this, constant));
376417
}
377418

compiler/rustc_resolve/src/lib.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,6 +1122,35 @@ pub struct ResolverOutputs {
11221122
pub ast_lowering: ResolverAstLowering,
11231123
}
11241124

1125+
#[derive(Copy, Clone, Debug)]
1126+
pub enum VisitNonLifetimeBinder {
1127+
No,
1128+
WhereBoundPredicate,
1129+
GenericBound,
1130+
}
1131+
1132+
impl VisitNonLifetimeBinder {
1133+
pub fn in_generic_bound(&self) -> bool {
1134+
matches!(self, VisitNonLifetimeBinder::GenericBound)
1135+
}
1136+
1137+
pub fn enter_where_bound_predicate(&mut self) -> Self {
1138+
let prev = *self;
1139+
if let VisitNonLifetimeBinder::No = prev {
1140+
*self = VisitNonLifetimeBinder::WhereBoundPredicate;
1141+
}
1142+
prev
1143+
}
1144+
1145+
pub fn enter_generic_bound(&mut self) -> Self {
1146+
let prev = *self;
1147+
if let VisitNonLifetimeBinder::WhereBoundPredicate = prev {
1148+
*self = VisitNonLifetimeBinder::GenericBound;
1149+
}
1150+
prev
1151+
}
1152+
}
1153+
11251154
/// The main resolver class.
11261155
///
11271156
/// This is the visitor that walks the whole crate.
@@ -1342,6 +1371,9 @@ pub struct Resolver<'ra, 'tcx> {
13421371
// that were encountered during resolution. These names are used to generate item names
13431372
// for APITs, so we don't want to leak details of resolution into these names.
13441373
impl_trait_names: FxHashMap<NodeId, Symbol> = default::fx_hash_map(),
1374+
1375+
visit_non_lifetime_binder: VisitNonLifetimeBinder = VisitNonLifetimeBinder::No,
1376+
hirless_def_ids: UnordSet<LocalDefId> = Default::default(),
13451377
}
13461378

13471379
/// This provides memory for the rest of the crate. The `'ra` lifetime that is
@@ -1774,6 +1806,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
17741806
doc_link_traits_in_scope: self.doc_link_traits_in_scope,
17751807
all_macro_rules: self.all_macro_rules,
17761808
stripped_cfg_items,
1809+
hirless_def_ids: self.hirless_def_ids,
17771810
};
17781811
let ast_lowering = ty::ResolverAstLowering {
17791812
partial_res_map: self.partial_res_map,
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//@ edition: 2024
2+
3+
#![feature(non_lifetime_binders)]
4+
#![expect(incomplete_features)]
5+
6+
fn produce() -> for<A: A<{ //~ ERROR expected trait, found type parameter `A`
7+
//~^ ERROR bounds cannot be used in this context
8+
//~^^ ERROR late-bound type parameter not allowed on trait object types
9+
//~^^^ ERROR expected a type, found a trait
10+
#[derive(Hash)] //~ ERROR missing generics for struct `produce::{constant#0}::A`
11+
enum A {}
12+
struct A<A>; //~ ERROR the name `A` is defined multiple times
13+
}>> Trait {} //~ ERROR cannot find trait `Trait` in this scope
14+
15+
fn main() {}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
error[E0428]: the name `A` is defined multiple times
2+
--> $DIR/bad-bounds.rs:12:5
3+
|
4+
LL | enum A {}
5+
| ------ previous definition of the type `A` here
6+
LL | struct A<A>;
7+
| ^^^^^^^^^^^^ `A` redefined here
8+
|
9+
= note: `A` must be defined only once in the type namespace of this block
10+
11+
error[E0404]: expected trait, found type parameter `A`
12+
--> $DIR/bad-bounds.rs:6:24
13+
|
14+
LL | fn produce() -> for<A: A<{
15+
| _____________________-__^
16+
| | |
17+
| | found this type parameter
18+
... |
19+
LL | | struct A<A>;
20+
LL | | }>> Trait {}
21+
| |__^ not a trait
22+
23+
error[E0405]: cannot find trait `Trait` in this scope
24+
--> $DIR/bad-bounds.rs:13:5
25+
|
26+
LL | }>> Trait {}
27+
| ^^^^^ not found in this scope
28+
29+
error: bounds cannot be used in this context
30+
--> $DIR/bad-bounds.rs:6:24
31+
|
32+
LL | fn produce() -> for<A: A<{
33+
| ________________________^
34+
... |
35+
LL | | struct A<A>;
36+
LL | | }>> Trait {}
37+
| |__^
38+
39+
error: late-bound type parameter not allowed on trait object types
40+
--> $DIR/bad-bounds.rs:6:21
41+
|
42+
LL | fn produce() -> for<A: A<{
43+
| ^
44+
45+
error[E0782]: expected a type, found a trait
46+
--> $DIR/bad-bounds.rs:6:17
47+
|
48+
LL | fn produce() -> for<A: A<{
49+
| _________________^
50+
... |
51+
LL | | struct A<A>;
52+
LL | | }>> Trait {}
53+
| |_________^
54+
55+
error[E0107]: missing generics for struct `produce::{constant#0}::A`
56+
--> $DIR/bad-bounds.rs:10:14
57+
|
58+
LL | #[derive(Hash)]
59+
| ^^^^ expected 1 generic argument
60+
|
61+
note: struct defined here, with 1 generic parameter: `A`
62+
--> $DIR/bad-bounds.rs:12:12
63+
|
64+
LL | struct A<A>;
65+
| ^ -
66+
help: add missing generic argument
67+
|
68+
LL | #[derive(Hash<A>)]
69+
| +++
70+
71+
error: aborting due to 7 previous errors
72+
73+
Some errors have detailed explanations: E0107, E0404, E0405, E0428, E0782.
74+
For more information about an error, try `rustc --explain E0107`.

0 commit comments

Comments
 (0)