Inherited use constness and assoc change predicate

This commit is contained in:
Deadbeef 2021-07-24 14:34:53 +08:00
parent d356cd10f7
commit 7e6db83b14
No known key found for this signature in database
GPG Key ID: 027DF9338862ADDD
4 changed files with 61 additions and 6 deletions

View File

@ -255,7 +255,7 @@ checksum = "81a18687293a1546b67c246452202bbbf143d239cb43494cc163da14979082da"
[[package]]
name = "cargo"
version = "0.57.0"
version = "0.56.0"
dependencies = [
"anyhow",
"atty",
@ -388,7 +388,7 @@ dependencies = [
[[package]]
name = "cargo-util"
version = "0.1.1"
version = "0.1.0"
dependencies = [
"anyhow",
"core-foundation",

View File

@ -16,6 +16,15 @@ pub enum AssocItemContainer {
}
impl AssocItemContainer {
/// Asserts that this is the `DefId` of an associated item declared
/// in an impl, and returns the trait `DefId`.
pub fn assert_impl(&self) -> DefId {
match *self {
ImplContainer(id) => id,
_ => bug!("associated item has wrong container type: {:?}", self),
}
}
/// Asserts that this is the `DefId` of an associated item declared
/// in a trait, and returns the trait `DefId`.
pub fn assert_trait(&self) -> DefId {

View File

@ -1292,7 +1292,24 @@ pub fn check_type_bounds<'tcx>(
};
tcx.infer_ctxt().enter(move |infcx| {
let inh = Inherited::new(infcx, impl_ty.def_id.expect_local());
// if the item is inside a const impl, we transform the predicates to be const.
let constness = tcx.impl_constness(impl_ty.container.assert_impl());
let pred_map = match constness {
hir::Constness::NotConst => |p, _| p,
hir::Constness::Const => |p: ty::Predicate<'tcx>, tcx: TyCtxt<'tcx>| {
p.kind()
.map_bound(|kind| match kind {
ty::PredicateKind::Trait(mut tp) => {
tp.constness = hir::Constness::Const;
ty::PredicateKind::Trait(tp)
}
kind => kind,
})
.to_predicate(tcx)
},
};
let inh = Inherited::with_constness(infcx, impl_ty.def_id.expect_local(), constness);
let infcx = &inh.infcx;
let mut selcx = traits::SelectionContext::new(&infcx);
@ -1310,7 +1327,7 @@ pub fn check_type_bounds<'tcx>(
.explicit_item_bounds(trait_ty.def_id)
.iter()
.map(|&(bound, span)| {
let concrete_ty_bound = bound.subst(tcx, rebased_substs);
let concrete_ty_bound = pred_map(bound.subst(tcx, rebased_substs), tcx);
debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
traits::Obligation::new(mk_cause(span), param_env, concrete_ty_bound)
@ -1328,7 +1345,10 @@ pub fn check_type_bounds<'tcx>(
debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate);
obligation.predicate = normalized_predicate;
inh.register_predicates(obligations);
inh.register_predicates(obligations.into_iter().map(|mut o| {
o.predicate = pred_map(o.predicate, tcx);
o
}));
inh.register_predicate(obligation);
}

View File

@ -52,6 +52,9 @@ pub struct Inherited<'a, 'tcx> {
pub(super) deferred_generator_interiors:
RefCell<Vec<(hir::BodyId, Ty<'tcx>, hir::GeneratorKind)>>,
/// Reports whether this is in a const context.
pub(super) constness: hir::Constness,
pub(super) body_id: Option<hir::BodyId>,
}
@ -93,6 +96,12 @@ impl<'tcx> InheritedBuilder<'tcx> {
impl Inherited<'a, 'tcx> {
pub(super) fn new(infcx: InferCtxt<'a, 'tcx>, def_id: LocalDefId) -> Self {
let tcx = infcx.tcx;
let item_id = tcx.hir().local_def_id_to_hir_id(def_id);
Self::with_constness(infcx, def_id, tcx.hir().get(item_id).constness())
}
pub(super) fn with_constness(infcx: InferCtxt<'a, 'tcx>, def_id: LocalDefId, constness: hir::Constness) -> Self {
let tcx = infcx.tcx;
let item_id = tcx.hir().local_def_id_to_hir_id(def_id);
let body_id = tcx.hir().maybe_body_owned_by(item_id);
@ -108,12 +117,29 @@ impl Inherited<'a, 'tcx> {
deferred_call_resolutions: RefCell::new(Default::default()),
deferred_cast_checks: RefCell::new(Vec::new()),
deferred_generator_interiors: RefCell::new(Vec::new()),
constness,
body_id,
}
}
pub(super) fn register_predicate(&self, obligation: traits::PredicateObligation<'tcx>) {
#[instrument(level = "debug", skip(self))]
fn transform_predicate(&self, p: &mut ty::Predicate<'tcx>) {
// Don't transform non-const bounds into const bounds,
// but transform const bounds to non-const when we are
// not in a const context.
if let hir::Constness::NotConst = self.constness {
let kind = p.kind();
if let ty::PredicateKind::Trait(pred) = kind.as_ref().skip_binder() {
let mut pred = *pred;
pred.constness = hir::Constness::NotConst;
*p = kind.rebind(ty::PredicateKind::Trait(pred)).to_predicate(self.tcx);
}
}
}
pub(super) fn register_predicate(&self, mut obligation: traits::PredicateObligation<'tcx>) {
debug!("register_predicate({:?})", obligation);
self.transform_predicate(&mut obligation.predicate);
if obligation.has_escaping_bound_vars() {
span_bug!(obligation.cause.span, "escaping bound vars in predicate {:?}", obligation);
}