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

Various local trait item iteration cleanups #139018

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open
8 changes: 3 additions & 5 deletions compiler/rustc_hir_analysis/src/check/always_applicable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,8 @@ use crate::hir::def_id::{DefId, LocalDefId};
/// cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
pub(crate) fn check_drop_impl(
tcx: TyCtxt<'_>,
drop_impl_did: DefId,
drop_impl_did: LocalDefId,
) -> Result<(), ErrorGuaranteed> {
let drop_impl_did = drop_impl_did.expect_local();

match tcx.impl_polarity(drop_impl_did) {
ty::ImplPolarity::Positive => {}
ty::ImplPolarity::Negative => {
Expand All @@ -56,9 +54,9 @@ pub(crate) fn check_drop_impl(

tcx.ensure_ok().orphan_check_impl(drop_impl_did)?;

let dtor_impl_trait_ref = tcx.impl_trait_ref(drop_impl_did).unwrap().instantiate_identity();
let self_ty = tcx.type_of(drop_impl_did).instantiate_identity();

match dtor_impl_trait_ref.self_ty().kind() {
match self_ty.kind() {
ty::Adt(adt_def, adt_to_impl_args) => {
ensure_impl_params_and_item_params_correspond(
tcx,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_analysis/src/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,11 @@ pub fn provide(providers: &mut Providers) {
}

fn adt_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::Destructor> {
tcx.calculate_dtor(def_id.to_def_id(), always_applicable::check_drop_impl)
tcx.calculate_dtor(def_id, always_applicable::check_drop_impl)
}

fn adt_async_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::AsyncDestructor> {
tcx.calculate_async_dtor(def_id.to_def_id(), always_applicable::check_drop_impl)
tcx.calculate_async_dtor(def_id, always_applicable::check_drop_impl)
}

/// Given a `DefId` for an opaque type in return position, find its parent item's return
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_hir_analysis/src/coherence/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,12 @@ pub(crate) fn provide(providers: &mut Providers) {
}

fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed> {
let impls = tcx.local_trait_impls(def_id);
// If there are no impls for the trait, then "all impls" are trivially coherent and we won't check anything
// anyway. Thus we bail out even before the specialization graph, avoiding the dep_graph edge.
let Some(impls) = tcx.all_local_trait_impls(()).get(&def_id) else { return Ok(()) };
if impls.is_empty() {
return Ok(());
}
// Trigger building the specialization graph for the trait. This will detect and report any
// overlap errors.
let mut res = tcx.ensure_ok().specialization_graph_of(def_id);
Expand Down
36 changes: 17 additions & 19 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1730,25 +1730,23 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
.is_accessible_from(self.item_def_id(), tcx)
&& tcx.all_impls(*trait_def_id)
.any(|impl_def_id| {
let impl_header = tcx.impl_trait_header(impl_def_id);
impl_header.is_some_and(|header| {
let trait_ref = header.trait_ref.instantiate(
tcx,
infcx.fresh_args_for_item(DUMMY_SP, impl_def_id),
);

let value = fold_regions(tcx, qself_ty, |_, _| tcx.lifetimes.re_erased);
// FIXME: Don't bother dealing with non-lifetime binders here...
if value.has_escaping_bound_vars() {
return false;
}
infcx
.can_eq(
ty::ParamEnv::empty(),
trait_ref.self_ty(),
value,
) && header.polarity != ty::ImplPolarity::Negative
})
let header = tcx.impl_trait_header(impl_def_id).unwrap();
let trait_ref = header.trait_ref.instantiate(
tcx,
infcx.fresh_args_for_item(DUMMY_SP, impl_def_id),
);

let value = fold_regions(tcx, qself_ty, |_, _| tcx.lifetimes.re_erased);
// FIXME: Don't bother dealing with non-lifetime binders here...
if value.has_escaping_bound_vars() {
return false;
}
infcx
.can_eq(
ty::ParamEnv::empty(),
trait_ref.self_ty(),
value,
) && header.polarity != ty::ImplPolarity::Negative
})
})
.map(|trait_def_id| tcx.def_path_str(trait_def_id))
Expand Down
10 changes: 2 additions & 8 deletions compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,14 +330,8 @@ provide! { tcx, def_id, other, cdata,

visibility => { cdata.get_visibility(def_id.index) }
adt_def => { cdata.get_adt_def(def_id.index, tcx) }
adt_destructor => {
let _ = cdata;
tcx.calculate_dtor(def_id, |_,_| Ok(()))
}
adt_async_destructor => {
let _ = cdata;
tcx.calculate_async_dtor(def_id, |_,_| Ok(()))
}
adt_destructor => { table }
adt_async_destructor => { table }
associated_item_def_ids => {
tcx.arena.alloc_from_iter(cdata.get_associated_item_or_field_def_ids(def_id.index))
}
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1633,6 +1633,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
record!(self.tables.fn_sig[variant.def_id] <- fn_sig);
}
}

if let Some(destructor) = tcx.adt_destructor(local_def_id) {
record!(self.tables.adt_destructor[def_id] <- destructor);
}

if let Some(destructor) = tcx.adt_async_destructor(local_def_id) {
record!(self.tables.adt_async_destructor[def_id] <- destructor);
}
}

#[instrument(level = "debug", skip(self))]
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_metadata/src/rmeta/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,8 @@ define_tables! {
fn_arg_names: Table<DefIndex, LazyArray<Option<Ident>>>,
coroutine_kind: Table<DefIndex, hir::CoroutineKind>,
coroutine_for_closure: Table<DefIndex, RawDefId>,
adt_destructor: Table<DefIndex, LazyValue<ty::Destructor>>,
adt_async_destructor: Table<DefIndex, LazyValue<ty::AsyncDestructor>>,
coroutine_by_move_body_def_id: Table<DefIndex, RawDefId>,
eval_static_initializer: Table<DefIndex, LazyValue<mir::interpret::ConstAllocation<'static>>>,
trait_def: Table<DefIndex, LazyValue<ty::TraitDef>>,
Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_middle/src/hir/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,10 +367,6 @@ impl<'tcx> TyCtxt<'tcx> {
}
}

pub fn hir_trait_impls(self, trait_did: DefId) -> &'tcx [LocalDefId] {
self.all_local_trait_impls(()).get(&trait_did).map_or(&[], |xs| &xs[..])
}

/// Gets the attributes on the crate. This is preferable to
/// invoking `krate.attrs` because it registers a tighter
/// dep-graph access.
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_middle/src/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,8 @@ pub fn provide(providers: &mut Providers) {
}
};
providers.all_local_trait_impls = |tcx, ()| &tcx.resolutions(()).trait_impls;
providers.local_trait_impls =
|tcx, trait_id| tcx.resolutions(()).trait_impls.get(&trait_id).map_or(&[], |xs| &xs[..]);
providers.expn_that_defined =
|tcx, id| tcx.resolutions(()).expn_that_defined.get(&id).copied().unwrap_or(ExpnId::root());
providers.in_scope_traits_map = |tcx, id| {
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1502,6 +1502,11 @@ rustc_queries! {
desc { "finding local trait impls" }
}

/// Return all `impl` blocks of the given trait in the current crate.
query local_trait_impls(trait_id: DefId) -> &'tcx [LocalDefId] {
desc { "finding local trait impls of `{}`", tcx.def_path_str(trait_id) }
}

/// Given a trait `trait_id`, return all known `impl` blocks.
query trait_impls_of(trait_id: DefId) -> &'tcx ty::trait_def::TraitImpls {
arena_cache
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/adt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ impl<'tcx> rustc_type_ir::inherent::AdtDef<TyCtxt<'tcx>> for AdtDef<'tcx> {
}

fn destructor(self, tcx: TyCtxt<'tcx>) -> Option<AdtDestructorKind> {
Some(match self.destructor(tcx)?.constness {
Some(match tcx.constness(self.destructor(tcx)?.did) {
hir::Constness::Const => AdtDestructorKind::Const,
hir::Constness::NotConst => AdtDestructorKind::NotConst,
})
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1119,8 +1119,6 @@ pub struct PseudoCanonicalInput<'tcx, T> {
pub struct Destructor {
/// The `DefId` of the destructor method
pub did: DefId,
/// The constness of the destructor method
pub constness: hir::Constness,
}

// FIXME: consider combining this definition with regular `Destructor`
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_middle/src/ty/parameterized.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,11 @@ trivially_parameterized_over_tcx! {
crate::middle::lib_features::FeatureStability,
crate::middle::resolve_bound_vars::ObjectLifetimeDefault,
crate::mir::ConstQualifs,
ty::AsyncDestructor,
ty::AssocItemContainer,
ty::Asyncness,
ty::DeducedParamAttrs,
ty::Destructor,
ty::Generics,
ty::ImplPolarity,
ty::ImplTraitInTraitData,
Expand Down
17 changes: 1 addition & 16 deletions compiler/rustc_middle/src/ty/trait_def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,21 +129,6 @@ impl<'tcx> TraitDef {
}

impl<'tcx> TyCtxt<'tcx> {
/// `trait_def_id` MUST BE the `DefId` of a trait.
pub fn for_each_impl<F: FnMut(DefId)>(self, trait_def_id: DefId, mut f: F) {
let impls = self.trait_impls_of(trait_def_id);

for &impl_def_id in impls.blanket_impls.iter() {
f(impl_def_id);
}

for v in impls.non_blanket_impls.values() {
for &impl_def_id in v {
f(impl_def_id);
}
}
}

/// Iterate over every impl that could possibly match the self type `self_ty`.
///
/// `trait_def_id` MUST BE the `DefId` of a trait.
Expand Down Expand Up @@ -235,7 +220,7 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
}
}

for &impl_def_id in tcx.hir_trait_impls(trait_id) {
for &impl_def_id in tcx.local_trait_impls(trait_id) {
let impl_def_id = impl_def_id.to_def_id();

let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity();
Expand Down
46 changes: 28 additions & 18 deletions compiler/rustc_middle/src/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -389,63 +389,73 @@ impl<'tcx> TyCtxt<'tcx> {
/// Calculate the destructor of a given type.
pub fn calculate_dtor(
self,
adt_did: DefId,
validate: impl Fn(Self, DefId) -> Result<(), ErrorGuaranteed>,
adt_did: LocalDefId,
validate: impl Fn(Self, LocalDefId) -> Result<(), ErrorGuaranteed>,
) -> Option<ty::Destructor> {
let drop_trait = self.lang_items().drop_trait()?;
self.ensure_ok().coherent_trait(drop_trait).ok()?;

let ty = self.type_of(adt_did).instantiate_identity();
let mut dtor_candidate = None;
self.for_each_relevant_impl(drop_trait, ty, |impl_did| {
// `Drop` impls can only be written in the same crate as the adt, and cannot be blanket impls
for &impl_did in self.local_trait_impls(drop_trait) {
let Some(adt_def) = self.type_of(impl_did).skip_binder().ty_adt_def() else { continue };
if adt_def.did() != adt_did.to_def_id() {
continue;
}

if validate(self, impl_did).is_err() {
// Already `ErrorGuaranteed`, no need to delay a span bug here.
return;
continue;
}

let Some(item_id) = self.associated_item_def_ids(impl_did).first() else {
self.dcx()
.span_delayed_bug(self.def_span(impl_did), "Drop impl without drop function");
return;
continue;
};

if let Some((old_item_id, _)) = dtor_candidate {
if let Some(old_item_id) = dtor_candidate {
self.dcx()
.struct_span_err(self.def_span(item_id), "multiple drop impls found")
.with_span_note(self.def_span(old_item_id), "other impl here")
.delay_as_bug();
}

dtor_candidate = Some((*item_id, self.impl_trait_header(impl_did).unwrap().constness));
});
dtor_candidate = Some(*item_id);
}

let (did, constness) = dtor_candidate?;
Some(ty::Destructor { did, constness })
let did = dtor_candidate?;
Some(ty::Destructor { did })
}

/// Calculate the async destructor of a given type.
pub fn calculate_async_dtor(
self,
adt_did: DefId,
validate: impl Fn(Self, DefId) -> Result<(), ErrorGuaranteed>,
adt_did: LocalDefId,
validate: impl Fn(Self, LocalDefId) -> Result<(), ErrorGuaranteed>,
) -> Option<ty::AsyncDestructor> {
let async_drop_trait = self.lang_items().async_drop_trait()?;
self.ensure_ok().coherent_trait(async_drop_trait).ok()?;

let ty = self.type_of(adt_did).instantiate_identity();
let mut dtor_candidate = None;
self.for_each_relevant_impl(async_drop_trait, ty, |impl_did| {
// `AsyncDrop` impls can only be written in the same crate as the adt, and cannot be blanket impls
for &impl_did in self.local_trait_impls(async_drop_trait) {
let Some(adt_def) = self.type_of(impl_did).skip_binder().ty_adt_def() else { continue };
if adt_def.did() != adt_did.to_def_id() {
continue;
}

if validate(self, impl_did).is_err() {
// Already `ErrorGuaranteed`, no need to delay a span bug here.
return;
continue;
}

let [future, ctor] = self.associated_item_def_ids(impl_did) else {
self.dcx().span_delayed_bug(
self.def_span(impl_did),
"AsyncDrop impl without async_drop function or Dropper type",
);
return;
continue;
};

if let Some((_, _, old_impl_did)) = dtor_candidate {
Expand All @@ -456,7 +466,7 @@ impl<'tcx> TyCtxt<'tcx> {
}

dtor_candidate = Some((*future, *ctor, impl_did));
});
}

let (future, ctor, _) = dtor_candidate?;
Some(ty::AsyncDestructor { future, ctor })
Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_mir_transform/src/check_const_item_mutation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,10 @@ impl<'tcx> ConstMutationChecker<'_, 'tcx> {
//
// #[const_mutation_allowed]
// pub const LOG: Log = Log { msg: "" };
match self.tcx.calculate_dtor(def_id, |_, _| Ok(())) {
Some(_) => None,
None => Some(def_id),
match self.tcx.type_of(def_id).skip_binder().ty_adt_def().map(|adt| adt.has_dtor(self.tcx))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

previously this was using the def_id of the const, which accidentally worked because the query invoked type_of on it internally.

{
Some(true) => None,
Some(false) | None => Some(def_id),
}
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_monomorphize/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ monomorphize_large_assignments =
.note = The current maximum size is {$limit}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`

monomorphize_no_optimized_mir =
missing optimized MIR for an item in the crate `{$crate_name}`
missing optimized MIR for `{$instance}` in the crate `{$crate_name}`
.note = missing optimized MIR for this item (was the crate `{$crate_name}` compiled with `--emit=metadata`?)

monomorphize_recursion_limit =
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_monomorphize/src/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -989,6 +989,7 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) ->
tcx.dcx().emit_fatal(NoOptimizedMir {
span: tcx.def_span(def_id),
crate_name: tcx.crate_name(def_id.krate),
instance: instance.to_string(),
});
}

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_monomorphize/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub(crate) struct NoOptimizedMir {
#[note]
pub span: Span,
pub crate_name: Symbol,
pub instance: String,
}

#[derive(LintDiagnostic)]
Expand Down
6 changes: 2 additions & 4 deletions compiler/rustc_passes/src/dead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -421,10 +421,8 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
}
hir::ItemKind::ForeignMod { .. } => {}
hir::ItemKind::Trait(..) => {
for impl_def_id in self.tcx.all_impls(item.owner_id.to_def_id()) {
if let Some(local_def_id) = impl_def_id.as_local()
&& let ItemKind::Impl(impl_ref) =
self.tcx.hir_expect_item(local_def_id).kind
for &impl_def_id in self.tcx.local_trait_impls(item.owner_id.def_id) {
if let ItemKind::Impl(impl_ref) = self.tcx.hir_expect_item(impl_def_id).kind
{
// skip items
// mark dependent traits live
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
// obligation comes from the `impl`. Find that `impl` so that we can point
// at it in the suggestion.
let trait_did = trait_id.to_def_id();
tcx.hir_trait_impls(trait_did).iter().find_map(|&impl_did| {
tcx.local_trait_impls(trait_did).iter().find_map(|&impl_did| {
if let Node::Item(Item {
kind: ItemKind::Impl(hir::Impl { self_ty, .. }), ..
}) = tcx.hir_node_by_def_id(impl_did)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/traits/effects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ fn evaluate_host_effect_for_destruct_goal<'tcx>(
.all_fields()
.map(|field| ty::TraitRef::new(tcx, destruct_def_id, [field.ty(tcx, args)]))
.collect();
match adt_def.destructor(tcx).map(|dtor| dtor.constness) {
match adt_def.destructor(tcx).map(|dtor| tcx.constness(dtor.did)) {
// `Drop` impl exists, but it's not const. Type cannot be `~const Destruct`.
Some(hir::Constness::NotConst) => return Err(EvaluationFailure::NoSolution),
// `Drop` impl exists, and it's const. Require `Ty: ~const Drop` to hold.
Expand Down
Loading
Loading