Check const Drop impls considering ConstIfConst bounds

This commit is contained in:
Michael Goulet
2022-01-18 01:43:49 -08:00
parent f9eb0b3b7b
commit 6ed42a7ca4
7 changed files with 227 additions and 167 deletions

View File

@@ -4,11 +4,12 @@
use rustc_errors::ErrorReported;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::TraitEngine;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty};
use rustc_span::DUMMY_SP;
use rustc_trait_selection::traits::{
self, ImplSource, Obligation, ObligationCause, SelectionContext,
self, FulfillmentContext, ImplSource, Obligation, ObligationCause, SelectionContext,
};
use super::ConstCx;
@@ -161,28 +162,46 @@ impl Qualif for NeedsNonConstDrop {
// without having the lang item present.
return false;
};
let trait_ref =
ty::TraitRef { def_id: drop_trait, substs: cx.tcx.mk_substs_trait(ty, &[]) };
let obligation = Obligation::new(
ObligationCause::dummy(),
cx.param_env,
ty::Binder::dummy(ty::TraitPredicate {
trait_ref,
trait_ref: ty::TraitRef {
def_id: drop_trait,
substs: cx.tcx.mk_substs_trait(ty, &[]),
},
constness: ty::BoundConstness::ConstIfConst,
polarity: ty::ImplPolarity::Positive,
}),
);
let implsrc = cx.tcx.infer_ctxt().enter(|infcx| {
cx.tcx.infer_ctxt().enter(|infcx| {
let mut selcx = SelectionContext::new(&infcx);
selcx.select(&obligation)
});
!matches!(
implsrc,
Ok(Some(
let Some(impl_src) = selcx.select(&obligation).ok().flatten() else {
// If we couldn't select a const drop candidate, then it's bad
return true;
};
if !matches!(
impl_src,
ImplSource::ConstDrop(_) | ImplSource::Param(_, ty::BoundConstness::ConstIfConst)
))
)
) {
// If our const drop candidate is not ConstDrop or implied by param,
// then it's bad
return true;
}
// If we successfully found one, then select all of the predicates
// implied by our const drop impl.
let mut fcx = FulfillmentContext::new();
for nested in impl_src.nested_obligations() {
fcx.register_predicate_obligation(&infcx, nested);
}
// If we had any errors, then it's bad
!fcx.select_all_or_error(&infcx).is_empty()
})
}
fn in_adt_inherently<'tcx>(