Auto merge of #139018 - oli-obk:incremental-trait-impls, r=compiler-errors
Various local trait item iteration cleanups
Adding a trait impl for `Foo` unconditionally affected all queries that are interested in a completely independent trait `Bar`. Perf has no effect on this. We probably don't have a good perf test for this tho.
r? `@compiler-errors`
I am unsure about https://github.com/rust-lang/rust/pull/139018/commits/9d05efb66f7b599eeacb5d2456f844fe4768e865 as it doesn't improve anything wrt incremental, because we still do all the checks for valid `Drop` impls, which subsequently will still invoke many queries and basically keep the depgraph the same.
I want to do
9549077a47/compiler/rustc_middle/src/ty/trait_def.rs (L141)
but would leave that to a follow-up PR, this one changes enough things as it is
This commit is contained in:
commit
ae9173d7dd
26 changed files with 96 additions and 93 deletions
|
@ -36,10 +36,8 @@ use crate::hir::def_id::{DefId, LocalDefId};
|
||||||
/// cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
|
/// cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
|
||||||
pub(crate) fn check_drop_impl(
|
pub(crate) fn check_drop_impl(
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
drop_impl_did: DefId,
|
drop_impl_did: LocalDefId,
|
||||||
) -> Result<(), ErrorGuaranteed> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
let drop_impl_did = drop_impl_did.expect_local();
|
|
||||||
|
|
||||||
match tcx.impl_polarity(drop_impl_did) {
|
match tcx.impl_polarity(drop_impl_did) {
|
||||||
ty::ImplPolarity::Positive => {}
|
ty::ImplPolarity::Positive => {}
|
||||||
ty::ImplPolarity::Negative => {
|
ty::ImplPolarity::Negative => {
|
||||||
|
@ -56,9 +54,9 @@ pub(crate) fn check_drop_impl(
|
||||||
|
|
||||||
tcx.ensure_ok().orphan_check_impl(drop_impl_did)?;
|
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) => {
|
ty::Adt(adt_def, adt_to_impl_args) => {
|
||||||
ensure_impl_params_and_item_params_correspond(
|
ensure_impl_params_and_item_params_correspond(
|
||||||
tcx,
|
tcx,
|
||||||
|
|
|
@ -114,11 +114,11 @@ pub fn provide(providers: &mut Providers) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn adt_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::Destructor> {
|
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> {
|
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
|
/// Given a `DefId` for an opaque type in return position, find its parent item's return
|
||||||
|
|
|
@ -153,9 +153,12 @@ pub(crate) fn provide(providers: &mut Providers) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed> {
|
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
|
// 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.
|
// 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
|
// Trigger building the specialization graph for the trait. This will detect and report any
|
||||||
// overlap errors.
|
// overlap errors.
|
||||||
let mut res = tcx.ensure_ok().specialization_graph_of(def_id);
|
let mut res = tcx.ensure_ok().specialization_graph_of(def_id);
|
||||||
|
|
|
@ -1730,8 +1730,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
.is_accessible_from(self.item_def_id(), tcx)
|
.is_accessible_from(self.item_def_id(), tcx)
|
||||||
&& tcx.all_impls(*trait_def_id)
|
&& tcx.all_impls(*trait_def_id)
|
||||||
.any(|impl_def_id| {
|
.any(|impl_def_id| {
|
||||||
let impl_header = tcx.impl_trait_header(impl_def_id);
|
let header = tcx.impl_trait_header(impl_def_id).unwrap();
|
||||||
impl_header.is_some_and(|header| {
|
|
||||||
let trait_ref = header.trait_ref.instantiate(
|
let trait_ref = header.trait_ref.instantiate(
|
||||||
tcx,
|
tcx,
|
||||||
infcx.fresh_args_for_item(DUMMY_SP, impl_def_id),
|
infcx.fresh_args_for_item(DUMMY_SP, impl_def_id),
|
||||||
|
@ -1750,7 +1749,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
) && header.polarity != ty::ImplPolarity::Negative
|
) && header.polarity != ty::ImplPolarity::Negative
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
|
||||||
.map(|trait_def_id| tcx.def_path_str(trait_def_id))
|
.map(|trait_def_id| tcx.def_path_str(trait_def_id))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
|
@ -330,14 +330,8 @@ provide! { tcx, def_id, other, cdata,
|
||||||
|
|
||||||
visibility => { cdata.get_visibility(def_id.index) }
|
visibility => { cdata.get_visibility(def_id.index) }
|
||||||
adt_def => { cdata.get_adt_def(def_id.index, tcx) }
|
adt_def => { cdata.get_adt_def(def_id.index, tcx) }
|
||||||
adt_destructor => {
|
adt_destructor => { table }
|
||||||
let _ = cdata;
|
adt_async_destructor => { table }
|
||||||
tcx.calculate_dtor(def_id, |_,_| Ok(()))
|
|
||||||
}
|
|
||||||
adt_async_destructor => {
|
|
||||||
let _ = cdata;
|
|
||||||
tcx.calculate_async_dtor(def_id, |_,_| Ok(()))
|
|
||||||
}
|
|
||||||
associated_item_def_ids => {
|
associated_item_def_ids => {
|
||||||
tcx.arena.alloc_from_iter(cdata.get_associated_item_or_field_def_ids(def_id.index))
|
tcx.arena.alloc_from_iter(cdata.get_associated_item_or_field_def_ids(def_id.index))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1634,6 +1634,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
record!(self.tables.fn_sig[variant.def_id] <- fn_sig);
|
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))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
|
|
|
@ -452,6 +452,8 @@ define_tables! {
|
||||||
fn_arg_names: Table<DefIndex, LazyArray<Option<Ident>>>,
|
fn_arg_names: Table<DefIndex, LazyArray<Option<Ident>>>,
|
||||||
coroutine_kind: Table<DefIndex, hir::CoroutineKind>,
|
coroutine_kind: Table<DefIndex, hir::CoroutineKind>,
|
||||||
coroutine_for_closure: Table<DefIndex, RawDefId>,
|
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>,
|
coroutine_by_move_body_def_id: Table<DefIndex, RawDefId>,
|
||||||
eval_static_initializer: Table<DefIndex, LazyValue<mir::interpret::ConstAllocation<'static>>>,
|
eval_static_initializer: Table<DefIndex, LazyValue<mir::interpret::ConstAllocation<'static>>>,
|
||||||
trait_def: Table<DefIndex, LazyValue<ty::TraitDef>>,
|
trait_def: Table<DefIndex, LazyValue<ty::TraitDef>>,
|
||||||
|
|
|
@ -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
|
/// Gets the attributes on the crate. This is preferable to
|
||||||
/// invoking `krate.attrs` because it registers a tighter
|
/// invoking `krate.attrs` because it registers a tighter
|
||||||
/// dep-graph access.
|
/// dep-graph access.
|
||||||
|
|
|
@ -238,6 +238,8 @@ pub fn provide(providers: &mut Providers) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
providers.all_local_trait_impls = |tcx, ()| &tcx.resolutions(()).trait_impls;
|
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 =
|
providers.expn_that_defined =
|
||||||
|tcx, id| tcx.resolutions(()).expn_that_defined.get(&id).copied().unwrap_or(ExpnId::root());
|
|tcx, id| tcx.resolutions(()).expn_that_defined.get(&id).copied().unwrap_or(ExpnId::root());
|
||||||
providers.in_scope_traits_map = |tcx, id| {
|
providers.in_scope_traits_map = |tcx, id| {
|
||||||
|
|
|
@ -1502,6 +1502,11 @@ rustc_queries! {
|
||||||
desc { "finding local trait impls" }
|
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.
|
/// Given a trait `trait_id`, return all known `impl` blocks.
|
||||||
query trait_impls_of(trait_id: DefId) -> &'tcx ty::trait_def::TraitImpls {
|
query trait_impls_of(trait_id: DefId) -> &'tcx ty::trait_def::TraitImpls {
|
||||||
arena_cache
|
arena_cache
|
||||||
|
|
|
@ -236,7 +236,7 @@ impl<'tcx> rustc_type_ir::inherent::AdtDef<TyCtxt<'tcx>> for AdtDef<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn destructor(self, tcx: TyCtxt<'tcx>) -> Option<AdtDestructorKind> {
|
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::Const => AdtDestructorKind::Const,
|
||||||
hir::Constness::NotConst => AdtDestructorKind::NotConst,
|
hir::Constness::NotConst => AdtDestructorKind::NotConst,
|
||||||
})
|
})
|
||||||
|
|
|
@ -1119,8 +1119,6 @@ pub struct PseudoCanonicalInput<'tcx, T> {
|
||||||
pub struct Destructor {
|
pub struct Destructor {
|
||||||
/// The `DefId` of the destructor method
|
/// The `DefId` of the destructor method
|
||||||
pub did: DefId,
|
pub did: DefId,
|
||||||
/// The constness of the destructor method
|
|
||||||
pub constness: hir::Constness,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: consider combining this definition with regular `Destructor`
|
// FIXME: consider combining this definition with regular `Destructor`
|
||||||
|
|
|
@ -65,9 +65,11 @@ trivially_parameterized_over_tcx! {
|
||||||
crate::middle::lib_features::FeatureStability,
|
crate::middle::lib_features::FeatureStability,
|
||||||
crate::middle::resolve_bound_vars::ObjectLifetimeDefault,
|
crate::middle::resolve_bound_vars::ObjectLifetimeDefault,
|
||||||
crate::mir::ConstQualifs,
|
crate::mir::ConstQualifs,
|
||||||
|
ty::AsyncDestructor,
|
||||||
ty::AssocItemContainer,
|
ty::AssocItemContainer,
|
||||||
ty::Asyncness,
|
ty::Asyncness,
|
||||||
ty::DeducedParamAttrs,
|
ty::DeducedParamAttrs,
|
||||||
|
ty::Destructor,
|
||||||
ty::Generics,
|
ty::Generics,
|
||||||
ty::ImplPolarity,
|
ty::ImplPolarity,
|
||||||
ty::ImplTraitInTraitData,
|
ty::ImplTraitInTraitData,
|
||||||
|
|
|
@ -129,21 +129,6 @@ impl<'tcx> TraitDef {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> TyCtxt<'tcx> {
|
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`.
|
/// Iterate over every impl that could possibly match the self type `self_ty`.
|
||||||
///
|
///
|
||||||
/// `trait_def_id` MUST BE the `DefId` of a trait.
|
/// `trait_def_id` MUST BE the `DefId` of a trait.
|
||||||
|
@ -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_def_id = impl_def_id.to_def_id();
|
||||||
|
|
||||||
let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity();
|
let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity();
|
||||||
|
|
|
@ -389,55 +389,65 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
/// Calculate the destructor of a given type.
|
/// Calculate the destructor of a given type.
|
||||||
pub fn calculate_dtor(
|
pub fn calculate_dtor(
|
||||||
self,
|
self,
|
||||||
adt_did: DefId,
|
adt_did: LocalDefId,
|
||||||
validate: impl Fn(Self, DefId) -> Result<(), ErrorGuaranteed>,
|
validate: impl Fn(Self, LocalDefId) -> Result<(), ErrorGuaranteed>,
|
||||||
) -> Option<ty::Destructor> {
|
) -> Option<ty::Destructor> {
|
||||||
let drop_trait = self.lang_items().drop_trait()?;
|
let drop_trait = self.lang_items().drop_trait()?;
|
||||||
self.ensure_ok().coherent_trait(drop_trait).ok()?;
|
self.ensure_ok().coherent_trait(drop_trait).ok()?;
|
||||||
|
|
||||||
let ty = self.type_of(adt_did).instantiate_identity();
|
|
||||||
let mut dtor_candidate = None;
|
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() {
|
if validate(self, impl_did).is_err() {
|
||||||
// Already `ErrorGuaranteed`, no need to delay a span bug here.
|
// 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 {
|
let Some(item_id) = self.associated_item_def_ids(impl_did).first() else {
|
||||||
self.dcx()
|
self.dcx()
|
||||||
.span_delayed_bug(self.def_span(impl_did), "Drop impl without drop function");
|
.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()
|
self.dcx()
|
||||||
.struct_span_err(self.def_span(item_id), "multiple drop impls found")
|
.struct_span_err(self.def_span(item_id), "multiple drop impls found")
|
||||||
.with_span_note(self.def_span(old_item_id), "other impl here")
|
.with_span_note(self.def_span(old_item_id), "other impl here")
|
||||||
.delay_as_bug();
|
.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?;
|
let did = dtor_candidate?;
|
||||||
Some(ty::Destructor { did, constness })
|
Some(ty::Destructor { did })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate the async destructor of a given type.
|
/// Calculate the async destructor of a given type.
|
||||||
pub fn calculate_async_dtor(
|
pub fn calculate_async_dtor(
|
||||||
self,
|
self,
|
||||||
adt_did: DefId,
|
adt_did: LocalDefId,
|
||||||
validate: impl Fn(Self, DefId) -> Result<(), ErrorGuaranteed>,
|
validate: impl Fn(Self, LocalDefId) -> Result<(), ErrorGuaranteed>,
|
||||||
) -> Option<ty::AsyncDestructor> {
|
) -> Option<ty::AsyncDestructor> {
|
||||||
let async_drop_trait = self.lang_items().async_drop_trait()?;
|
let async_drop_trait = self.lang_items().async_drop_trait()?;
|
||||||
self.ensure_ok().coherent_trait(async_drop_trait).ok()?;
|
self.ensure_ok().coherent_trait(async_drop_trait).ok()?;
|
||||||
|
|
||||||
let ty = self.type_of(adt_did).instantiate_identity();
|
|
||||||
let mut dtor_candidate = None;
|
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() {
|
if validate(self, impl_did).is_err() {
|
||||||
// Already `ErrorGuaranteed`, no need to delay a span bug here.
|
// Already `ErrorGuaranteed`, no need to delay a span bug here.
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let [future, ctor] = self.associated_item_def_ids(impl_did) else {
|
let [future, ctor] = self.associated_item_def_ids(impl_did) else {
|
||||||
|
@ -445,7 +455,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
self.def_span(impl_did),
|
self.def_span(impl_did),
|
||||||
"AsyncDrop impl without async_drop function or Dropper type",
|
"AsyncDrop impl without async_drop function or Dropper type",
|
||||||
);
|
);
|
||||||
return;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some((_, _, old_impl_did)) = dtor_candidate {
|
if let Some((_, _, old_impl_did)) = dtor_candidate {
|
||||||
|
@ -456,7 +466,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
dtor_candidate = Some((*future, *ctor, impl_did));
|
dtor_candidate = Some((*future, *ctor, impl_did));
|
||||||
});
|
}
|
||||||
|
|
||||||
let (future, ctor, _) = dtor_candidate?;
|
let (future, ctor, _) = dtor_candidate?;
|
||||||
Some(ty::AsyncDestructor { future, ctor })
|
Some(ty::AsyncDestructor { future, ctor })
|
||||||
|
|
|
@ -53,9 +53,13 @@ impl<'tcx> ConstMutationChecker<'_, 'tcx> {
|
||||||
//
|
//
|
||||||
// #[const_mutation_allowed]
|
// #[const_mutation_allowed]
|
||||||
// pub const LOG: Log = Log { msg: "" };
|
// pub const LOG: Log = Log { msg: "" };
|
||||||
match self.tcx.calculate_dtor(def_id, |_, _| Ok(())) {
|
// FIXME: this should not be checking for `Drop` impls,
|
||||||
Some(_) => None,
|
// but whether it or any field has a Drop impl (`needs_drop`)
|
||||||
None => Some(def_id),
|
// as fields' Drop impls may make this observable, too.
|
||||||
|
match self.tcx.type_of(def_id).skip_binder().ty_adt_def().map(|adt| adt.has_dtor(self.tcx))
|
||||||
|
{
|
||||||
|
Some(true) => None,
|
||||||
|
Some(false) | None => Some(def_id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 = "..."]`
|
.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 =
|
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`?)
|
.note = missing optimized MIR for this item (was the crate `{$crate_name}` compiled with `--emit=metadata`?)
|
||||||
|
|
||||||
monomorphize_recursion_limit =
|
monomorphize_recursion_limit =
|
||||||
|
|
|
@ -989,6 +989,7 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) ->
|
||||||
tcx.dcx().emit_fatal(NoOptimizedMir {
|
tcx.dcx().emit_fatal(NoOptimizedMir {
|
||||||
span: tcx.def_span(def_id),
|
span: tcx.def_span(def_id),
|
||||||
crate_name: tcx.crate_name(def_id.krate),
|
crate_name: tcx.crate_name(def_id.krate),
|
||||||
|
instance: instance.to_string(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ pub(crate) struct NoOptimizedMir {
|
||||||
#[note]
|
#[note]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub crate_name: Symbol,
|
pub crate_name: Symbol,
|
||||||
|
pub instance: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(LintDiagnostic)]
|
#[derive(LintDiagnostic)]
|
||||||
|
|
|
@ -421,10 +421,8 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
|
||||||
}
|
}
|
||||||
hir::ItemKind::ForeignMod { .. } => {}
|
hir::ItemKind::ForeignMod { .. } => {}
|
||||||
hir::ItemKind::Trait(..) => {
|
hir::ItemKind::Trait(..) => {
|
||||||
for impl_def_id in self.tcx.all_impls(item.owner_id.to_def_id()) {
|
for &impl_def_id in self.tcx.local_trait_impls(item.owner_id.def_id) {
|
||||||
if let Some(local_def_id) = impl_def_id.as_local()
|
if let ItemKind::Impl(impl_ref) = self.tcx.hir_expect_item(impl_def_id).kind
|
||||||
&& let ItemKind::Impl(impl_ref) =
|
|
||||||
self.tcx.hir_expect_item(local_def_id).kind
|
|
||||||
{
|
{
|
||||||
// skip items
|
// skip items
|
||||||
// mark dependent traits live
|
// mark dependent traits live
|
||||||
|
|
|
@ -365,7 +365,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
// obligation comes from the `impl`. Find that `impl` so that we can point
|
// obligation comes from the `impl`. Find that `impl` so that we can point
|
||||||
// at it in the suggestion.
|
// at it in the suggestion.
|
||||||
let trait_did = trait_id.to_def_id();
|
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 {
|
if let Node::Item(Item {
|
||||||
kind: ItemKind::Impl(hir::Impl { self_ty, .. }), ..
|
kind: ItemKind::Impl(hir::Impl { self_ty, .. }), ..
|
||||||
}) = tcx.hir_node_by_def_id(impl_did)
|
}) = tcx.hir_node_by_def_id(impl_did)
|
||||||
|
|
|
@ -259,7 +259,7 @@ fn evaluate_host_effect_for_destruct_goal<'tcx>(
|
||||||
.all_fields()
|
.all_fields()
|
||||||
.map(|field| ty::TraitRef::new(tcx, destruct_def_id, [field.ty(tcx, args)]))
|
.map(|field| ty::TraitRef::new(tcx, destruct_def_id, [field.ty(tcx, args)]))
|
||||||
.collect();
|
.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`.
|
// `Drop` impl exists, but it's not const. Type cannot be `~const Destruct`.
|
||||||
Some(hir::Constness::NotConst) => return Err(EvaluationFailure::NoSolution),
|
Some(hir::Constness::NotConst) => return Err(EvaluationFailure::NoSolution),
|
||||||
// `Drop` impl exists, and it's const. Require `Ty: ~const Drop` to hold.
|
// `Drop` impl exists, and it's const. Require `Ty: ~const Drop` to hold.
|
||||||
|
|
|
@ -324,11 +324,9 @@ fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &h
|
||||||
// there's a Copy impl for any instance of the adt.
|
// there's a Copy impl for any instance of the adt.
|
||||||
if !is_copy(cx, ty) {
|
if !is_copy(cx, ty) {
|
||||||
if ty_subs.non_erasable_generics().next().is_some() {
|
if ty_subs.non_erasable_generics().next().is_some() {
|
||||||
let has_copy_impl = cx.tcx.all_local_trait_impls(()).get(©_id).is_some_and(|impls| {
|
let has_copy_impl = cx.tcx.local_trait_impls(copy_id).iter().any(|&id| {
|
||||||
impls.iter().any(|&id| {
|
|
||||||
matches!(cx.tcx.type_of(id).instantiate_identity().kind(), ty::Adt(adt, _)
|
matches!(cx.tcx.type_of(id).instantiate_identity().kind(), ty::Adt(adt, _)
|
||||||
if ty_adt.did() == adt.did())
|
if ty_adt.did() == adt.did())
|
||||||
})
|
|
||||||
});
|
});
|
||||||
if !has_copy_impl {
|
if !has_copy_impl {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -97,14 +97,14 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
|
||||||
{
|
{
|
||||||
if self.impling_types.is_none() {
|
if self.impling_types.is_none() {
|
||||||
let mut impls = HirIdSet::default();
|
let mut impls = HirIdSet::default();
|
||||||
cx.tcx.for_each_impl(default_trait_id, |d| {
|
for &d in cx.tcx.local_trait_impls(default_trait_id) {
|
||||||
let ty = cx.tcx.type_of(d).instantiate_identity();
|
let ty = cx.tcx.type_of(d).instantiate_identity();
|
||||||
if let Some(ty_def) = ty.ty_adt_def() {
|
if let Some(ty_def) = ty.ty_adt_def() {
|
||||||
if let Some(local_def_id) = ty_def.did().as_local() {
|
if let Some(local_def_id) = ty_def.did().as_local() {
|
||||||
impls.insert(cx.tcx.local_def_id_to_hir_id(local_def_id));
|
impls.insert(cx.tcx.local_def_id_to_hir_id(local_def_id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
self.impling_types = Some(impls);
|
self.impling_types = Some(impls);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,4 +10,4 @@ fn main() {
|
||||||
rmeta_meta::missing_optimized_mir();
|
rmeta_meta::missing_optimized_mir();
|
||||||
}
|
}
|
||||||
|
|
||||||
//~? ERROR missing optimized MIR for an item in the crate `rmeta_meta`
|
//~? ERROR missing optimized MIR for `missing_optimized_mir` in the crate `rmeta_meta`
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: missing optimized MIR for an item in the crate `rmeta_meta`
|
error: missing optimized MIR for `missing_optimized_mir` in the crate `rmeta_meta`
|
||||||
|
|
|
|
||||||
note: missing optimized MIR for this item (was the crate `rmeta_meta` compiled with `--emit=metadata`?)
|
note: missing optimized MIR for this item (was the crate `rmeta_meta` compiled with `--emit=metadata`?)
|
||||||
--> $DIR/auxiliary/rmeta-meta.rs:10:1
|
--> $DIR/auxiliary/rmeta-meta.rs:10:1
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue