Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Visitors track whether an assoc item is in a trait impl or an inherent impl #138929

Merged
merged 3 commits into from
Mar 25, 2025
Merged
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
4 changes: 3 additions & 1 deletion compiler/rustc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1318,7 +1318,9 @@ impl WalkItemKind for ItemKind {
visit_polarity(vis, polarity);
visit_opt(of_trait, |trait_ref| vis.visit_trait_ref(trait_ref));
vis.visit_ty(self_ty);
items.flat_map_in_place(|item| vis.flat_map_assoc_item(item, AssocCtxt::Impl));
items.flat_map_in_place(|item| {
vis.flat_map_assoc_item(item, AssocCtxt::Impl { of_trait: of_trait.is_some() })
});
}
ItemKind::Trait(box Trait { safety, is_auto: _, generics, bounds, items }) => {
visit_safety(vis, safety);
Expand Down
9 changes: 7 additions & 2 deletions compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use crate::ptr::P;
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum AssocCtxt {
Trait,
Impl,
Impl { of_trait: bool },
}

#[derive(Copy, Clone, Debug, PartialEq)]
Expand Down Expand Up @@ -422,7 +422,12 @@ impl WalkItemKind for ItemKind {
try_visit!(visitor.visit_generics(generics));
visit_opt!(visitor, visit_trait_ref, of_trait);
try_visit!(visitor.visit_ty(self_ty));
walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Impl);
walk_list!(
visitor,
visit_assoc_item,
items,
AssocCtxt::Impl { of_trait: of_trait.is_some() }
);
}
ItemKind::Struct(struct_definition, generics)
| ItemKind::Union(struct_definition, generics) => {
Expand Down
16 changes: 12 additions & 4 deletions compiler/rustc_ast_lowering/src/delegation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,14 @@ pub(crate) struct DelegationResults<'hir> {

impl<'hir> LoweringContext<'_, 'hir> {
/// Defines whether the delegatee is an associated function whose first parameter is `self`.
pub(crate) fn delegatee_is_method(&self, item_id: NodeId, path_id: NodeId, span: Span) -> bool {
let sig_id = self.get_delegation_sig_id(item_id, path_id, span);
pub(crate) fn delegatee_is_method(
&self,
item_id: NodeId,
path_id: NodeId,
span: Span,
is_in_trait_impl: bool,
) -> bool {
let sig_id = self.get_delegation_sig_id(item_id, path_id, span, is_in_trait_impl);
let Ok(sig_id) = sig_id else {
return false;
};
Expand All @@ -88,9 +94,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
&mut self,
delegation: &Delegation,
item_id: NodeId,
is_in_trait_impl: bool,
) -> DelegationResults<'hir> {
let span = self.lower_span(delegation.path.segments.last().unwrap().ident.span);
let sig_id = self.get_delegation_sig_id(item_id, delegation.id, span);
let sig_id = self.get_delegation_sig_id(item_id, delegation.id, span, is_in_trait_impl);
match sig_id {
Ok(sig_id) => {
let (param_count, c_variadic) = self.param_count(sig_id);
Expand All @@ -110,8 +117,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
item_id: NodeId,
path_id: NodeId,
span: Span,
is_in_trait_impl: bool,
) -> Result<DefId, ErrorGuaranteed> {
let sig_id = if self.is_in_trait_impl { item_id } else { path_id };
let sig_id = if is_in_trait_impl { item_id } else { path_id };
self.get_resolution_id(sig_id, span)
}

Expand Down
62 changes: 27 additions & 35 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
use rustc_hir::{self as hir, HirId, PredicateOrigin};
use rustc_index::{IndexSlice, IndexVec};
use rustc_middle::span_bug;
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::{DUMMY_SP, DesugaringKind, Ident, Span, Symbol, kw, sym};
Expand Down Expand Up @@ -104,10 +103,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
}

fn lower_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) {
let def_id = self.resolver.node_id_to_def_id[&item.id];
let parent_id = self.tcx.local_parent(def_id);
let parent_hir = self.lower_node(parent_id).unwrap();
self.with_lctx(item.id, |lctx| lctx.lower_assoc_item(item, ctxt, parent_hir))
self.with_lctx(item.id, |lctx| lctx.lower_assoc_item(item, ctxt))
}

fn lower_foreign_item(&mut self, item: &ForeignItem) {
Expand Down Expand Up @@ -408,10 +404,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
(trait_ref, lowered_ty)
});

self.is_in_trait_impl = trait_ref.is_some();
let new_impl_items = self
.arena
.alloc_from_iter(impl_items.iter().map(|item| self.lower_impl_item_ref(item)));
let new_impl_items = self.arena.alloc_from_iter(
impl_items
.iter()
.map(|item| self.lower_impl_item_ref(item, trait_ref.is_some())),
);

// `defaultness.has_value()` is never called for an `impl`, always `true` in order
// to not cause an assertion failure inside the `lower_defaultness` function.
Expand Down Expand Up @@ -488,7 +485,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ItemKind::Delegation(box delegation) => {
debug_assert_ne!(ident.name, kw::Empty);
let ident = self.lower_ident(ident);
let delegation_results = self.lower_delegation(delegation, id);
let delegation_results = self.lower_delegation(delegation, id, false);
hir::ItemKind::Fn {
ident,
sig: delegation_results.sig,
Expand Down Expand Up @@ -631,29 +628,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
}

fn lower_assoc_item(
&mut self,
item: &AssocItem,
ctxt: AssocCtxt,
parent_hir: &'hir hir::OwnerInfo<'hir>,
) -> hir::OwnerNode<'hir> {
let parent_item = parent_hir.node().expect_item();
match parent_item.kind {
hir::ItemKind::Impl(impl_) => {
self.is_in_trait_impl = impl_.of_trait.is_some();
}
hir::ItemKind::Trait(..) => {}
kind => {
span_bug!(item.span, "assoc item has unexpected kind of parent: {}", kind.descr())
}
}

fn lower_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) -> hir::OwnerNode<'hir> {
// Evaluate with the lifetimes in `params` in-scope.
// This is used to track which lifetimes have already been defined,
// and which need to be replicated when lowering an async fn.
match ctxt {
AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item)),
AssocCtxt::Impl => hir::OwnerNode::ImplItem(self.lower_impl_item(item)),
AssocCtxt::Impl { of_trait } => {
hir::OwnerNode::ImplItem(self.lower_impl_item(item, of_trait))
}
}
}

Expand Down Expand Up @@ -894,7 +877,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
(generics, kind, ty.is_some())
}
AssocItemKind::Delegation(box delegation) => {
let delegation_results = self.lower_delegation(delegation, i.id);
let delegation_results = self.lower_delegation(delegation, i.id, false);
let item_kind = hir::TraitItemKind::Fn(
delegation_results.sig,
hir::TraitFn::Provided(delegation_results.body_id),
Expand Down Expand Up @@ -925,7 +908,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
}
AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn {
has_self: self.delegatee_is_method(i.id, delegation.id, i.span),
has_self: self.delegatee_is_method(i.id, delegation.id, i.span, false),
},
AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
panic!("macros should have been expanded by now")
Expand All @@ -945,7 +928,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.expr(span, hir::ExprKind::Err(guar))
}

fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
fn lower_impl_item(
&mut self,
i: &AssocItem,
is_in_trait_impl: bool,
) -> &'hir hir::ImplItem<'hir> {
debug_assert_ne!(i.ident.name, kw::Empty);
// Since `default impl` is not yet implemented, this is always true in impls.
let has_value = true;
Expand Down Expand Up @@ -981,7 +968,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
generics,
sig,
i.id,
if self.is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent },
if is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent },
sig.header.coroutine_kind,
attrs,
);
Expand Down Expand Up @@ -1021,7 +1008,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
)
}
AssocItemKind::Delegation(box delegation) => {
let delegation_results = self.lower_delegation(delegation, i.id);
let delegation_results = self.lower_delegation(delegation, i.id, is_in_trait_impl);
(
delegation_results.generics,
hir::ImplItemKind::Fn(delegation_results.sig, delegation_results.body_id),
Expand All @@ -1044,7 +1031,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.arena.alloc(item)
}

fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef {
fn lower_impl_item_ref(&mut self, i: &AssocItem, is_in_trait_impl: bool) -> hir::ImplItemRef {
hir::ImplItemRef {
id: hir::ImplItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } },
ident: self.lower_ident(i.ident),
Expand All @@ -1056,7 +1043,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
}
AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn {
has_self: self.delegatee_is_method(i.id, delegation.id, i.span),
has_self: self.delegatee_is_method(
i.id,
delegation.id,
i.span,
is_in_trait_impl,
),
},
AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
panic!("macros should have been expanded by now")
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ struct LoweringContext<'a, 'hir> {
catch_scope: Option<HirId>,
loop_scope: Option<HirId>,
is_in_loop_condition: bool,
is_in_trait_impl: bool,
is_in_dyn_type: bool,

current_hir_id_owner: hir::OwnerId,
Expand Down Expand Up @@ -173,7 +172,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
catch_scope: None,
loop_scope: None,
is_in_loop_condition: false,
is_in_trait_impl: false,
is_in_dyn_type: false,
coroutine_kind: None,
task_context: None,
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -860,7 +860,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
this.visit_trait_ref(t);
this.visit_ty(self_ty);

walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl);
walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl { of_trait: true });
});
walk_list!(self, visit_attribute, &item.attrs);
return; // Avoid visiting again.
Expand Down Expand Up @@ -913,7 +913,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|this| this.visit_generics(generics),
);
this.visit_ty(self_ty);
walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl);
walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl { of_trait: false });
});
walk_list!(self, visit_attribute, &item.attrs);
return; // Avoid visiting again.
Expand Down Expand Up @@ -1414,7 +1414,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
self.check_defaultness(item.span, item.kind.defaultness());
}

if ctxt == AssocCtxt::Impl {
if let AssocCtxt::Impl { .. } = ctxt {
match &item.kind {
AssocItemKind::Const(box ConstItem { expr: None, .. }) => {
self.dcx().emit_err(errors::AssocConstWithoutBody {
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_builtin_macros/src/autodiff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ mod llvm_enzyme {
};
(sig.clone(), false)
}
Annotatable::AssocItem(assoc_item, _) => {
Annotatable::AssocItem(assoc_item, Impl { of_trait: false }) => {
let sig = match &assoc_item.kind {
ast::AssocItemKind::Fn(box ast::Fn { sig, .. }) => sig,
_ => {
Expand Down Expand Up @@ -296,7 +296,7 @@ mod llvm_enzyme {
}
Annotatable::Item(iitem.clone())
}
Annotatable::AssocItem(ref mut assoc_item, i @ Impl) => {
Annotatable::AssocItem(ref mut assoc_item, i @ Impl { of_trait: false }) => {
if !assoc_item.attrs.iter().any(|a| same_attribute(&a.kind, &attr.kind)) {
assoc_item.attrs.push(attr);
}
Expand Down Expand Up @@ -327,7 +327,7 @@ mod llvm_enzyme {
kind: assoc_item,
tokens: None,
});
Annotatable::AssocItem(d_fn, Impl)
Annotatable::AssocItem(d_fn, Impl { of_trait: false })
} else {
let mut d_fn =
ecx.item(span, d_ident, thin_vec![d_attr, inline_never], ItemKind::Fn(asdf));
Expand Down
13 changes: 3 additions & 10 deletions compiler/rustc_builtin_macros/src/cfg_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,18 +121,11 @@ impl CfgEval<'_> {
let item = parser.parse_item(ForceCollect::Yes)?.unwrap();
Annotatable::Item(self.flat_map_item(item).pop().unwrap())
}
Annotatable::AssocItem(_, AssocCtxt::Trait) => {
Annotatable::AssocItem(_, ctxt) => {
let item = parser.parse_trait_item(ForceCollect::Yes)?.unwrap().unwrap();
Annotatable::AssocItem(
self.flat_map_assoc_item(item, AssocCtxt::Trait).pop().unwrap(),
AssocCtxt::Trait,
)
}
Annotatable::AssocItem(_, AssocCtxt::Impl) => {
let item = parser.parse_impl_item(ForceCollect::Yes)?.unwrap().unwrap();
Annotatable::AssocItem(
self.flat_map_assoc_item(item, AssocCtxt::Impl).pop().unwrap(),
AssocCtxt::Impl,
self.flat_map_assoc_item(item, ctxt).pop().unwrap(),
ctxt,
)
}
Annotatable::ForeignItem(_) => {
Expand Down
15 changes: 14 additions & 1 deletion compiler/rustc_expand/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ impl Annotatable {

pub fn expect_impl_item(self) -> P<ast::AssocItem> {
match self {
Annotatable::AssocItem(i, AssocCtxt::Impl) => i,
Annotatable::AssocItem(i, AssocCtxt::Impl { .. }) => i,
_ => panic!("expected Item"),
}
}
Expand Down Expand Up @@ -403,6 +403,11 @@ pub trait MacResult {
None
}

/// Creates zero or more impl items.
fn make_trait_impl_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
None
}

/// Creates zero or more trait items.
fn make_trait_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
None
Expand Down Expand Up @@ -516,6 +521,10 @@ impl MacResult for MacEager {
self.impl_items
}

fn make_trait_impl_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
self.impl_items
}

fn make_trait_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
self.trait_items
}
Expand Down Expand Up @@ -613,6 +622,10 @@ impl MacResult for DummyResult {
Some(SmallVec::new())
}

fn make_trait_impl_items(self: Box<DummyResult>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
Some(SmallVec::new())
}

fn make_trait_items(self: Box<DummyResult>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
Some(SmallVec::new())
}
Expand Down
Loading
Loading