1
Fork 0

Foreign types are trivially drop

- Also rename a trivial_const_drop to match style of other functions in
  the util module.
- Also add a test for `const Drop` that doesn't depend on a `~const`
  bound.
- Also comment a bit why we remove the const bound during dropck impl
  check.
This commit is contained in:
Michael Goulet 2022-01-19 20:07:04 -08:00
parent 8547f5732c
commit b7e4433974
6 changed files with 31 additions and 17 deletions

View file

@ -148,7 +148,7 @@ impl Qualif for NeedsNonConstDrop {
fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
// Avoid selecting for simple cases, such as builtin types. // Avoid selecting for simple cases, such as builtin types.
if ty::util::trivial_const_drop(ty) { if ty::util::is_trivially_const_drop(ty) {
return false; return false;
} }

View file

@ -1041,7 +1041,7 @@ pub fn needs_drop_components<'tcx>(
} }
} }
pub fn trivial_const_drop<'tcx>(ty: Ty<'tcx>) -> bool { pub fn is_trivially_const_drop<'tcx>(ty: Ty<'tcx>) -> bool {
match *ty.kind() { match *ty.kind() {
ty::Bool ty::Bool
| ty::Char | ty::Char
@ -1055,7 +1055,8 @@ pub fn trivial_const_drop<'tcx>(ty: Ty<'tcx>) -> bool {
| ty::Ref(..) | ty::Ref(..)
| ty::FnDef(..) | ty::FnDef(..)
| ty::FnPtr(_) | ty::FnPtr(_)
| ty::Never => true, | ty::Never
| ty::Foreign(_) => true,
ty::Opaque(..) ty::Opaque(..)
| ty::Dynamic(..) | ty::Dynamic(..)
@ -1063,7 +1064,6 @@ pub fn trivial_const_drop<'tcx>(ty: Ty<'tcx>) -> bool {
| ty::Bound(..) | ty::Bound(..)
| ty::Param(_) | ty::Param(_)
| ty::Placeholder(_) | ty::Placeholder(_)
| ty::Foreign(_)
| ty::Projection(_) | ty::Projection(_)
| ty::Infer(_) => false, | ty::Infer(_) => false,
@ -1071,9 +1071,9 @@ pub fn trivial_const_drop<'tcx>(ty: Ty<'tcx>) -> bool {
// we'll just perform trait selection. // we'll just perform trait selection.
ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(_) | ty::Adt(..) => false, ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(_) | ty::Adt(..) => false,
ty::Array(ty, _) | ty::Slice(ty) => trivial_const_drop(ty), ty::Array(ty, _) | ty::Slice(ty) => is_trivially_const_drop(ty),
ty::Tuple(tys) => tys.iter().all(|ty| trivial_const_drop(ty.expect_ty())), ty::Tuple(tys) => tys.iter().all(|ty| is_trivially_const_drop(ty.expect_ty())),
} }
} }

View file

@ -932,7 +932,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::Bound(..) | ty::Bound(..)
| ty::Param(_) | ty::Param(_)
| ty::Placeholder(_) | ty::Placeholder(_)
| ty::Foreign(_)
| ty::Projection(_) => { | ty::Projection(_) => {
// We don't know if these are `~const Drop`, at least // We don't know if these are `~const Drop`, at least
// not structurally... so don't push a candidate. // not structurally... so don't push a candidate.
@ -951,6 +950,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::FnDef(..) | ty::FnDef(..)
| ty::FnPtr(_) | ty::FnPtr(_)
| ty::Never | ty::Never
| ty::Foreign(_)
| ty::Array(..) | ty::Array(..)
| ty::Slice(_) | ty::Slice(_)
| ty::Closure(..) | ty::Closure(..)

View file

@ -1133,7 +1133,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::Ref(..) | ty::Ref(..)
| ty::FnDef(..) | ty::FnDef(..)
| ty::FnPtr(_) | ty::FnPtr(_)
| ty::Never => {} | ty::Never
| ty::Foreign(_) => {}
// These types are built-in, so we can fast-track by registering // These types are built-in, so we can fast-track by registering
// nested predicates for their constituient type(s) // nested predicates for their constituient type(s)

View file

@ -228,15 +228,15 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
let predicate = predicate.kind(); let predicate = predicate.kind();
let p = p.kind(); let p = p.kind();
match (predicate.skip_binder(), p.skip_binder()) { match (predicate.skip_binder(), p.skip_binder()) {
(ty::PredicateKind::Trait(a), ty::PredicateKind::Trait(b)) => relator (ty::PredicateKind::Trait(a), ty::PredicateKind::Trait(b)) => {
.relate( // Since struct predicates cannot have ~const, project the impl predicate
predicate.rebind(ty::TraitPredicate { // onto one that ignores the constness. This is equivalent to saying that
constness: ty::BoundConstness::NotConst, // we match a `Trait` bound on the struct with a `Trait` or `~const Trait`
..a // in the impl.
}), let non_const_a =
p.rebind(b), ty::TraitPredicate { constness: ty::BoundConstness::NotConst, ..a };
) relator.relate(predicate.rebind(non_const_a), p.rebind(b)).is_ok()
.is_ok(), }
(ty::PredicateKind::Projection(a), ty::PredicateKind::Projection(b)) => { (ty::PredicateKind::Projection(a), ty::PredicateKind::Projection(b)) => {
relator.relate(predicate.rebind(a), p.rebind(b)).is_ok() relator.relate(predicate.rebind(a), p.rebind(b)).is_ok()
} }

View file

@ -53,6 +53,10 @@ mod t {
impl const SomeTrait for () { impl const SomeTrait for () {
fn foo() {} fn foo() {}
} }
// non-const impl
impl SomeTrait for i32 {
fn foo() {}
}
pub struct ConstDropWithBound<T: SomeTrait>(pub core::marker::PhantomData<T>); pub struct ConstDropWithBound<T: SomeTrait>(pub core::marker::PhantomData<T>);
@ -61,6 +65,14 @@ mod t {
T::foo(); T::foo();
} }
} }
pub struct ConstDropWithNonconstBound<T: SomeTrait>(pub core::marker::PhantomData<T>);
impl<T: SomeTrait> const Drop for ConstDropWithNonconstBound<T> {
fn drop(&mut self) {
// Note: we DON'T use the `T: SomeTrait` bound
}
}
} }
use t::*; use t::*;
@ -78,6 +90,7 @@ implements_const_drop! {
&1, &1,
&1 as *const i32, &1 as *const i32,
ConstDropWithBound::<()>, ConstDropWithBound::<()>,
ConstDropWithNonconstBound::<i32>,
Result::<i32, !>::Ok(1), Result::<i32, !>::Ok(1),
} }