infcx: &InferCtxt<'a, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
body_id: hir::HirId,
- trait_ref: &ty::TraitRef<'tcx>,
+ trait_pred: &ty::TraitPredicate<'tcx>,
span: Span,
item: &'tcx hir::Item<'tcx>,
) -> Vec<traits::PredicateObligation<'tcx>> {
recursion_depth: 0,
item: Some(item),
};
- wf.compute_trait_ref(trait_ref, Elaborate::All);
+ wf.compute_trait_pred(trait_pred, Elaborate::All);
debug!(obligations = ?wf.out);
wf.normalize(infcx)
}
// It's ok to skip the binder here because wf code is prepared for it
match predicate.kind().skip_binder() {
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::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => {
}
/// 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 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 depth = self.recursion_depth;
}
#[instrument(level = "debug", skip(self))]
- fn nominal_obligations(
+ fn nominal_obligations_inner(
&mut self,
def_id: DefId,
substs: SubstsRef<'tcx>,
+ remap_constness: bool,
) -> Vec<traits::PredicateObligation<'tcx>> {
let predicates = self.tcx.predicates_of(def_id);
let mut origins = vec![def_id; predicates.predicates.len()];
debug_assert_eq!(predicates.predicates.len(), origins.len());
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() {
traits::MiscObligation
} else {
traits::BindingObligation(origin_def_id, span)
};
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)
})
.filter(|pred| !pred.has_escaping_bound_vars())
.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(
&mut self,
ty: Ty<'tcx>,
// We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span.
match (tcx.impl_polarity(def_id), impl_.polarity) {
(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)) => {
// FIXME(#27579): what amount of WF checking do we need for neg impls?
item: &'tcx hir::Item<'tcx>,
ast_self_ty: &hir::Ty<'_>,
ast_trait_ref: &Option<hir::TraitRef<'_>>,
+ constness: hir::Constness,
) {
enter_wf_checking_ctxt(tcx, item.span, item.def_id, |wfcx| {
match *ast_trait_ref {
// won't hold).
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_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(
wfcx.infcx,
wfcx.param_env,
wfcx.body_id,
- &trait_ref,
+ &trait_pred,
ast_trait_ref.path.span,
item,
);