Only look at trait impls in the current crate when looking for Drop
impls
This commit is contained in:
parent
51184c70c8
commit
ca32447c0c
3 changed files with 30 additions and 18 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 => {
|
||||||
|
|
|
@ -390,23 +390,28 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
pub fn calculate_dtor(
|
pub fn calculate_dtor(
|
||||||
self,
|
self,
|
||||||
adt_did: LocalDefId,
|
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 {
|
||||||
|
@ -417,7 +422,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
dtor_candidate = Some((*item_id, self.impl_trait_header(impl_did).unwrap().constness));
|
dtor_candidate = Some((*item_id, self.impl_trait_header(impl_did).unwrap().constness));
|
||||||
});
|
}
|
||||||
|
|
||||||
let (did, constness) = dtor_candidate?;
|
let (did, constness) = dtor_candidate?;
|
||||||
Some(ty::Destructor { did, constness })
|
Some(ty::Destructor { did, constness })
|
||||||
|
@ -427,17 +432,22 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
pub fn calculate_async_dtor(
|
pub fn calculate_async_dtor(
|
||||||
self,
|
self,
|
||||||
adt_did: LocalDefId,
|
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.adt_destructor(def_id) {
|
// 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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue