Instantiate constness in wfcheck
This commit is contained in:
parent
05bb26fdb6
commit
666022730f
2 changed files with 46 additions and 10 deletions
|
@ -85,7 +85,7 @@ pub fn trait_obligations<'a, 'tcx>(
|
||||||
infcx: &InferCtxt<'a, 'tcx>,
|
infcx: &InferCtxt<'a, 'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
body_id: hir::HirId,
|
body_id: hir::HirId,
|
||||||
trait_ref: &ty::TraitRef<'tcx>,
|
trait_pred: &ty::TraitPredicate<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
item: &'tcx hir::Item<'tcx>,
|
item: &'tcx hir::Item<'tcx>,
|
||||||
) -> Vec<traits::PredicateObligation<'tcx>> {
|
) -> Vec<traits::PredicateObligation<'tcx>> {
|
||||||
|
@ -98,7 +98,7 @@ pub fn trait_obligations<'a, 'tcx>(
|
||||||
recursion_depth: 0,
|
recursion_depth: 0,
|
||||||
item: Some(item),
|
item: Some(item),
|
||||||
};
|
};
|
||||||
wf.compute_trait_ref(trait_ref, Elaborate::All);
|
wf.compute_trait_pred(trait_pred, Elaborate::All);
|
||||||
debug!(obligations = ?wf.out);
|
debug!(obligations = ?wf.out);
|
||||||
wf.normalize(infcx)
|
wf.normalize(infcx)
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,7 @@ pub fn predicate_obligations<'a, 'tcx>(
|
||||||
// It's ok to skip the binder here because wf code is prepared for it
|
// It's ok to skip the binder here because wf code is prepared for it
|
||||||
match predicate.kind().skip_binder() {
|
match predicate.kind().skip_binder() {
|
||||||
ty::PredicateKind::Trait(t) => {
|
ty::PredicateKind::Trait(t) => {
|
||||||
wf.compute_trait_ref(&t.trait_ref, Elaborate::None);
|
wf.compute_trait_pred(&t, Elaborate::None);
|
||||||
}
|
}
|
||||||
ty::PredicateKind::RegionOutlives(..) => {}
|
ty::PredicateKind::RegionOutlives(..) => {}
|
||||||
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => {
|
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => {
|
||||||
|
@ -301,11 +301,18 @@ impl<'tcx> WfPredicates<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pushes the obligations required for `trait_ref` to be WF into `self.out`.
|
/// Pushes the obligations required for `trait_ref` to be WF into `self.out`.
|
||||||
fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, elaborate: Elaborate) {
|
fn compute_trait_pred(&mut self, trait_pred: &ty::TraitPredicate<'tcx>, elaborate: Elaborate) {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let obligations = self.nominal_obligations(trait_ref.def_id, trait_ref.substs);
|
let trait_ref = &trait_pred.trait_ref;
|
||||||
|
|
||||||
debug!("compute_trait_ref obligations {:?}", obligations);
|
// if the trait predicate is not const, the wf obligations should not be const as well.
|
||||||
|
let obligations = if trait_pred.constness == ty::BoundConstness::NotConst {
|
||||||
|
self.nominal_obligations_without_const(trait_ref.def_id, trait_ref.substs)
|
||||||
|
} else {
|
||||||
|
self.nominal_obligations(trait_ref.def_id, trait_ref.substs)
|
||||||
|
};
|
||||||
|
|
||||||
|
debug!("compute_trait_pred obligations {:?}", obligations);
|
||||||
let param_env = self.param_env;
|
let param_env = self.param_env;
|
||||||
let depth = self.recursion_depth;
|
let depth = self.recursion_depth;
|
||||||
|
|
||||||
|
@ -685,10 +692,11 @@ impl<'tcx> WfPredicates<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
fn nominal_obligations(
|
fn nominal_obligations_inner(
|
||||||
&mut self,
|
&mut self,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
substs: SubstsRef<'tcx>,
|
substs: SubstsRef<'tcx>,
|
||||||
|
remap_constness: bool,
|
||||||
) -> Vec<traits::PredicateObligation<'tcx>> {
|
) -> Vec<traits::PredicateObligation<'tcx>> {
|
||||||
let predicates = self.tcx.predicates_of(def_id);
|
let predicates = self.tcx.predicates_of(def_id);
|
||||||
let mut origins = vec![def_id; predicates.predicates.len()];
|
let mut origins = vec![def_id; predicates.predicates.len()];
|
||||||
|
@ -703,19 +711,38 @@ impl<'tcx> WfPredicates<'tcx> {
|
||||||
debug_assert_eq!(predicates.predicates.len(), origins.len());
|
debug_assert_eq!(predicates.predicates.len(), origins.len());
|
||||||
|
|
||||||
iter::zip(iter::zip(predicates.predicates, predicates.spans), origins.into_iter().rev())
|
iter::zip(iter::zip(predicates.predicates, predicates.spans), origins.into_iter().rev())
|
||||||
.map(|((pred, span), origin_def_id)| {
|
.map(|((mut pred, span), origin_def_id)| {
|
||||||
let code = if span.is_dummy() {
|
let code = if span.is_dummy() {
|
||||||
traits::MiscObligation
|
traits::MiscObligation
|
||||||
} else {
|
} else {
|
||||||
traits::BindingObligation(origin_def_id, span)
|
traits::BindingObligation(origin_def_id, span)
|
||||||
};
|
};
|
||||||
let cause = self.cause(code);
|
let cause = self.cause(code);
|
||||||
|
if remap_constness {
|
||||||
|
pred = pred.without_const(self.tcx);
|
||||||
|
}
|
||||||
traits::Obligation::with_depth(cause, self.recursion_depth, self.param_env, pred)
|
traits::Obligation::with_depth(cause, self.recursion_depth, self.param_env, pred)
|
||||||
})
|
})
|
||||||
.filter(|pred| !pred.has_escaping_bound_vars())
|
.filter(|pred| !pred.has_escaping_bound_vars())
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn nominal_obligations(
|
||||||
|
&mut self,
|
||||||
|
def_id: DefId,
|
||||||
|
substs: SubstsRef<'tcx>,
|
||||||
|
) -> Vec<traits::PredicateObligation<'tcx>> {
|
||||||
|
self.nominal_obligations_inner(def_id, substs, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn nominal_obligations_without_const(
|
||||||
|
&mut self,
|
||||||
|
def_id: DefId,
|
||||||
|
substs: SubstsRef<'tcx>,
|
||||||
|
) -> Vec<traits::PredicateObligation<'tcx>> {
|
||||||
|
self.nominal_obligations_inner(def_id, substs, true)
|
||||||
|
}
|
||||||
|
|
||||||
fn from_object_ty(
|
fn from_object_ty(
|
||||||
&mut self,
|
&mut self,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
|
|
|
@ -183,7 +183,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
|
||||||
// We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span.
|
// We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span.
|
||||||
match (tcx.impl_polarity(def_id), impl_.polarity) {
|
match (tcx.impl_polarity(def_id), impl_.polarity) {
|
||||||
(ty::ImplPolarity::Positive, _) => {
|
(ty::ImplPolarity::Positive, _) => {
|
||||||
check_impl(tcx, item, impl_.self_ty, &impl_.of_trait);
|
check_impl(tcx, item, impl_.self_ty, &impl_.of_trait, impl_.constness);
|
||||||
}
|
}
|
||||||
(ty::ImplPolarity::Negative, ast::ImplPolarity::Negative(span)) => {
|
(ty::ImplPolarity::Negative, ast::ImplPolarity::Negative(span)) => {
|
||||||
// FIXME(#27579): what amount of WF checking do we need for neg impls?
|
// FIXME(#27579): what amount of WF checking do we need for neg impls?
|
||||||
|
@ -1242,6 +1242,7 @@ fn check_impl<'tcx>(
|
||||||
item: &'tcx hir::Item<'tcx>,
|
item: &'tcx hir::Item<'tcx>,
|
||||||
ast_self_ty: &hir::Ty<'_>,
|
ast_self_ty: &hir::Ty<'_>,
|
||||||
ast_trait_ref: &Option<hir::TraitRef<'_>>,
|
ast_trait_ref: &Option<hir::TraitRef<'_>>,
|
||||||
|
constness: hir::Constness,
|
||||||
) {
|
) {
|
||||||
enter_wf_checking_ctxt(tcx, item.span, item.def_id, |wfcx| {
|
enter_wf_checking_ctxt(tcx, item.span, item.def_id, |wfcx| {
|
||||||
match *ast_trait_ref {
|
match *ast_trait_ref {
|
||||||
|
@ -1251,11 +1252,19 @@ fn check_impl<'tcx>(
|
||||||
// won't hold).
|
// won't hold).
|
||||||
let trait_ref = tcx.impl_trait_ref(item.def_id).unwrap();
|
let trait_ref = tcx.impl_trait_ref(item.def_id).unwrap();
|
||||||
let trait_ref = wfcx.normalize(ast_trait_ref.path.span, None, trait_ref);
|
let trait_ref = wfcx.normalize(ast_trait_ref.path.span, None, trait_ref);
|
||||||
|
let trait_pred = ty::TraitPredicate {
|
||||||
|
trait_ref,
|
||||||
|
constness: match constness {
|
||||||
|
hir::Constness::Const => ty::BoundConstness::ConstIfConst,
|
||||||
|
hir::Constness::NotConst => ty::BoundConstness::NotConst,
|
||||||
|
},
|
||||||
|
polarity: ty::ImplPolarity::Positive,
|
||||||
|
};
|
||||||
let obligations = traits::wf::trait_obligations(
|
let obligations = traits::wf::trait_obligations(
|
||||||
wfcx.infcx,
|
wfcx.infcx,
|
||||||
wfcx.param_env,
|
wfcx.param_env,
|
||||||
wfcx.body_id,
|
wfcx.body_id,
|
||||||
&trait_ref,
|
&trait_pred,
|
||||||
ast_trait_ref.path.span,
|
ast_trait_ref.path.span,
|
||||||
item,
|
item,
|
||||||
);
|
);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue