Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,6 @@ macro_rules! common_visitor_and_walkers {
FormatArgumentKind,
FormatArguments,
FormatPlaceholder,
GenericParamKind,
Impl,
ImplPolarity,
Inline,
Expand Down Expand Up @@ -485,7 +484,6 @@ macro_rules! common_visitor_and_walkers {
UnsafeSource,
UseTreeKind,
VisibilityKind,
WhereBoundPredicate,
WhereClause,
WhereEqPredicate,
WhereRegionPredicate,
Expand Down Expand Up @@ -577,6 +575,7 @@ macro_rules! common_visitor_and_walkers {
fn visit_generic_arg(GenericArg);
fn visit_generic_args(GenericArgs);
fn visit_generic_param(GenericParam);
fn visit_generic_param_kind(GenericParamKind);
fn visit_generics(Generics);
fn visit_inline_asm(InlineAsm);
fn visit_inline_asm_sym(InlineAsmSym);
Expand Down Expand Up @@ -604,6 +603,7 @@ macro_rules! common_visitor_and_walkers {
fn visit_vis(Visibility);
fn visit_where_predicate_kind(WherePredicateKind);
fn visit_where_predicate(WherePredicate);
fn visit_where_bound_predicate(WhereBoundPredicate);
);

// We want `Visitor` to take the `NodeId` by value.
Expand Down Expand Up @@ -1097,6 +1097,7 @@ macro_rules! common_visitor_and_walkers {
pub fn walk_generic_arg(GenericArg);
pub fn walk_generic_args(GenericArgs);
pub fn walk_generic_param(GenericParam);
pub fn walk_generic_param_kind(GenericParamKind);
pub fn walk_generics(Generics);
pub fn walk_inline_asm(InlineAsm);
pub fn walk_inline_asm_sym(InlineAsmSym);
Expand Down Expand Up @@ -1124,6 +1125,7 @@ macro_rules! common_visitor_and_walkers {
pub fn walk_vis(Visibility);
pub fn walk_where_predicate_kind(WherePredicateKind);
pub fn walk_where_predicate(WherePredicate);
pub fn walk_where_bound_predicate(WhereBoundPredicate);
);
};
}
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_middle/src/hir/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use rustc_hir::*;
use rustc_hir_pretty as pprust_hir;
use rustc_span::def_id::StableCrateId;
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, with_metavar_spans};
use tracing::debug;

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

let parent_id = if local_id == ItemLocalId::ZERO {
if let Some(parent_def_id) = self.tcx.opt_local_parent(owner.def_id)
&& self.tcx.resolutions(()).hirless_def_ids.contains(&parent_def_id)
{
debug!("{:?} has hirless parent {:?}", owner, parent_def_id);
return None;
}

// We go from an owner to its parent, so clear the cache.
self.current_owner_nodes = None;
self.tcx.hir_owner_parent(owner)
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ pub struct ResolverGlobalCtxt {
pub doc_link_traits_in_scope: FxIndexMap<LocalDefId, Vec<DefId>>,
pub all_macro_rules: UnordSet<Symbol>,
pub stripped_cfg_items: Vec<StrippedCfgItem>,
pub hirless_def_ids: UnordSet<LocalDefId>,
}

/// Resolutions that should only be used for lowering.
Expand Down
45 changes: 43 additions & 2 deletions compiler/rustc_resolve/src/def_collector.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::mem;

use rustc_ast::visit::FnKind;
use rustc_ast::visit::{BoundKind, FnKind};
use rustc_ast::*;
use rustc_attr_parsing::{AttributeParser, Early, OmitDoc, ShouldEmit};
use rustc_expand::expand::AstFragment;
Expand Down Expand Up @@ -311,6 +311,19 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
}
}

fn visit_where_bound_predicate(&mut self, pred: &'a WhereBoundPredicate) {
let prev = self.resolver.visit_non_lifetime_binder.enter_where_bound_predicate();
for generic_param in &pred.bound_generic_params {
self.visit_generic_param(&generic_param);
}
self.resolver.visit_non_lifetime_binder = prev;

self.visit_ty(&pred.bounded_ty);
for generic_bound in &pred.bounds {
self.visit_param_bound(generic_bound, BoundKind::Bound);
}
}

fn visit_variant_data(&mut self, data: &'a VariantData) {
// The assumption here is that non-`cfg` macro expansion cannot change field indices.
// It currently holds because only inert attributes are accepted on fields,
Expand Down Expand Up @@ -339,10 +352,32 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
//
// In that case, the impl-trait is lowered as an additional generic parameter.
self.with_impl_trait(ImplTraitContext::Universal, |this| {
visit::walk_generic_param(this, param)
this.visit_id(param.id);
this.visit_ident(&param.ident);
for attr in &param.attrs {
this.visit_attribute(attr)
}

let prev = this.resolver.visit_non_lifetime_binder.enter_generic_bound();
for bound in &param.bounds {
this.visit_param_bound(bound, BoundKind::Bound);
}
this.resolver.visit_non_lifetime_binder = prev;

this.visit_generic_param_kind(&param.kind);
});
}

fn visit_poly_trait_ref(&mut self, poly_trait_ref: &'a PolyTraitRef) {
let prev = self.resolver.visit_non_lifetime_binder.enter_where_bound_predicate();
for generic_param in &poly_trait_ref.bound_generic_params {
self.visit_generic_param(&generic_param);
}
self.resolver.visit_non_lifetime_binder = prev;

self.visit_trait_ref(&poly_trait_ref.trait_ref);
}

fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) {
let (ident, def_kind) = match &i.kind {
AssocItemKind::Fn(box Fn { ident, .. })
Expand Down Expand Up @@ -372,6 +407,12 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
if !self.resolver.tcx.features().min_generic_const_args() {
let parent =
self.create_def(constant.id, None, DefKind::AnonConst, constant.value.span);

if self.resolver.visit_non_lifetime_binder.in_generic_bound() {
// Record anno const blocks inside non-lifetime binders, e.g., `for<T: Trait<{ ... }>>`.
self.resolver.hirless_def_ids.insert(parent);
}

return self.with_parent(parent, |this| visit::walk_anon_const(this, constant));
}

Expand Down
33 changes: 33 additions & 0 deletions compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1122,6 +1122,35 @@ pub struct ResolverOutputs {
pub ast_lowering: ResolverAstLowering,
}

#[derive(Copy, Clone, Debug)]
pub enum VisitNonLifetimeBinder {
No,
WhereBoundPredicate,
GenericBound,
}

impl VisitNonLifetimeBinder {
pub fn in_generic_bound(&self) -> bool {
matches!(self, VisitNonLifetimeBinder::GenericBound)
}

pub fn enter_where_bound_predicate(&mut self) -> Self {
let prev = *self;
if let VisitNonLifetimeBinder::No = prev {
*self = VisitNonLifetimeBinder::WhereBoundPredicate;
}
prev
}

pub fn enter_generic_bound(&mut self) -> Self {
let prev = *self;
if let VisitNonLifetimeBinder::WhereBoundPredicate = prev {
*self = VisitNonLifetimeBinder::GenericBound;
}
prev
}
}

/// The main resolver class.
///
/// This is the visitor that walks the whole crate.
Expand Down Expand Up @@ -1342,6 +1371,9 @@ pub struct Resolver<'ra, 'tcx> {
// that were encountered during resolution. These names are used to generate item names
// for APITs, so we don't want to leak details of resolution into these names.
impl_trait_names: FxHashMap<NodeId, Symbol> = default::fx_hash_map(),

visit_non_lifetime_binder: VisitNonLifetimeBinder = VisitNonLifetimeBinder::No,
hirless_def_ids: UnordSet<LocalDefId> = Default::default(),
}

/// This provides memory for the rest of the crate. The `'ra` lifetime that is
Expand Down Expand Up @@ -1774,6 +1806,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
doc_link_traits_in_scope: self.doc_link_traits_in_scope,
all_macro_rules: self.all_macro_rules,
stripped_cfg_items,
hirless_def_ids: self.hirless_def_ids,
};
let ast_lowering = ty::ResolverAstLowering {
partial_res_map: self.partial_res_map,
Expand Down
15 changes: 15 additions & 0 deletions tests/ui/traits/non_lifetime_binders/bad-bounds.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//@ edition: 2024

#![feature(non_lifetime_binders)]
#![expect(incomplete_features)]

fn produce() -> for<A: A<{ //~ ERROR expected trait, found type parameter `A`
//~^ ERROR bounds cannot be used in this context
//~^^ ERROR late-bound type parameter not allowed on trait object types
//~^^^ ERROR expected a type, found a trait
#[derive(Hash)] //~ ERROR missing generics for struct `produce::{constant#0}::A`
enum A {}
struct A<A>; //~ ERROR the name `A` is defined multiple times
}>> Trait {} //~ ERROR cannot find trait `Trait` in this scope

fn main() {}
74 changes: 74 additions & 0 deletions tests/ui/traits/non_lifetime_binders/bad-bounds.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
error[E0428]: the name `A` is defined multiple times
--> $DIR/bad-bounds.rs:12:5
|
LL | enum A {}
| ------ previous definition of the type `A` here
LL | struct A<A>;
| ^^^^^^^^^^^^ `A` redefined here
|
= note: `A` must be defined only once in the type namespace of this block

error[E0404]: expected trait, found type parameter `A`
--> $DIR/bad-bounds.rs:6:24
|
LL | fn produce() -> for<A: A<{
| _____________________-__^
| | |
| | found this type parameter
... |
LL | | struct A<A>;
LL | | }>> Trait {}
| |__^ not a trait

error[E0405]: cannot find trait `Trait` in this scope
--> $DIR/bad-bounds.rs:13:5
|
LL | }>> Trait {}
| ^^^^^ not found in this scope

error: bounds cannot be used in this context
--> $DIR/bad-bounds.rs:6:24
|
LL | fn produce() -> for<A: A<{
| ________________________^
... |
LL | | struct A<A>;
LL | | }>> Trait {}
| |__^

error: late-bound type parameter not allowed on trait object types
--> $DIR/bad-bounds.rs:6:21
|
LL | fn produce() -> for<A: A<{
| ^

error[E0782]: expected a type, found a trait
--> $DIR/bad-bounds.rs:6:17
|
LL | fn produce() -> for<A: A<{
| _________________^
... |
LL | | struct A<A>;
LL | | }>> Trait {}
| |_________^

error[E0107]: missing generics for struct `produce::{constant#0}::A`
--> $DIR/bad-bounds.rs:10:14
|
LL | #[derive(Hash)]
| ^^^^ expected 1 generic argument
|
note: struct defined here, with 1 generic parameter: `A`
--> $DIR/bad-bounds.rs:12:12
|
LL | struct A<A>;
| ^ -
help: add missing generic argument
|
LL | #[derive(Hash<A>)]
| +++

error: aborting due to 7 previous errors

Some errors have detailed explanations: E0107, E0404, E0405, E0428, E0782.
For more information about an error, try `rustc --explain E0107`.
Loading