diff options
Diffstat (limited to '')
-rw-r--r-- | compiler/rustc_trait_selection/src/traits/wf.rs | 81 |
1 files changed, 42 insertions, 39 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 414857f0a..fc0a9f690 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -14,8 +14,8 @@ use std::iter; /// inference variable, returns `None`, because we are not able to /// make any progress at all. This is to prevent "livelock" where we /// say "$0 is WF if $0 is WF". -pub fn obligations<'a, 'tcx>( - infcx: &InferCtxt<'a, 'tcx>, +pub fn obligations<'tcx>( + infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, body_id: hir::HirId, recursion_depth: usize, @@ -31,9 +31,9 @@ pub fn obligations<'a, 'tcx>( if resolved_ty == ty { // No progress, bail out to prevent "livelock". return None; + } else { + resolved_ty } - - resolved_ty } _ => ty, } @@ -41,16 +41,14 @@ pub fn obligations<'a, 'tcx>( } GenericArgKind::Const(ct) => { match ct.kind() { - ty::ConstKind::Infer(infer) => { - let resolved = infcx.shallow_resolve(infer); - if resolved == infer { + ty::ConstKind::Infer(_) => { + let resolved = infcx.shallow_resolve(ct); + if resolved == ct { // No progress. return None; + } else { + resolved } - - infcx - .tcx - .mk_const(ty::ConstS { kind: ty::ConstKind::Infer(resolved), ty: ct.ty() }) } _ => ct, } @@ -81,8 +79,8 @@ pub fn obligations<'a, 'tcx>( /// well-formed. For example, if there is a trait `Set` defined like /// `trait Set<K:Eq>`, then the trait reference `Foo: Set<Bar>` is WF /// if `Bar: Eq`. -pub fn trait_obligations<'a, 'tcx>( - infcx: &InferCtxt<'a, 'tcx>, +pub fn trait_obligations<'tcx>( + infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, body_id: hir::HirId, trait_pred: &ty::TraitPredicate<'tcx>, @@ -103,8 +101,9 @@ pub fn trait_obligations<'a, 'tcx>( wf.normalize(infcx) } -pub fn predicate_obligations<'a, 'tcx>( - infcx: &InferCtxt<'a, 'tcx>, +#[instrument(skip(infcx), ret)] +pub fn predicate_obligations<'tcx>( + infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, body_id: hir::HirId, predicate: ty::Predicate<'tcx>, @@ -131,9 +130,9 @@ pub fn predicate_obligations<'a, 'tcx>( } ty::PredicateKind::Projection(t) => { wf.compute_projection(t.projection_ty); - wf.compute(match t.term { - ty::Term::Ty(ty) => ty.into(), - ty::Term::Const(c) => c.into(), + wf.compute(match t.term.unpack() { + ty::TermKind::Ty(ty) => ty.into(), + ty::TermKind::Const(c) => c.into(), }) } ty::PredicateKind::WellFormed(arg) => { @@ -149,13 +148,8 @@ pub fn predicate_obligations<'a, 'tcx>( wf.compute(a.into()); wf.compute(b.into()); } - ty::PredicateKind::ConstEvaluatable(uv) => { - let obligations = wf.nominal_obligations(uv.def.did, uv.substs); - wf.out.extend(obligations); - - for arg in uv.substs.iter() { - wf.compute(arg); - } + ty::PredicateKind::ConstEvaluatable(ct) => { + wf.compute(ct.into()); } ty::PredicateKind::ConstEquate(c1, c2) => { wf.compute(c1.into()); @@ -220,12 +214,14 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>( trait_ref, item, cause, pred ); let (items, impl_def_id) = match item { - Some(hir::Item { kind: hir::ItemKind::Impl(impl_), def_id, .. }) => (impl_.items, *def_id), + Some(hir::Item { kind: hir::ItemKind::Impl(impl_), owner_id, .. }) => { + (impl_.items, *owner_id) + } _ => return, }; let fix_span = |impl_item_ref: &hir::ImplItemRef| match tcx.hir().impl_item(impl_item_ref.id).kind { - hir::ImplItemKind::Const(ty, _) | hir::ImplItemKind::TyAlias(ty) => ty.span, + hir::ImplItemKind::Const(ty, _) | hir::ImplItemKind::Type(ty) => ty.span, _ => impl_item_ref.span, }; @@ -242,7 +238,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>( tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.item_def_id) && let Some(impl_item_span) = items .iter() - .find(|item| item.id.def_id.to_def_id() == impl_item_id) + .find(|item| item.id.owner_id.to_def_id() == impl_item_id) .map(fix_span) { cause.span = impl_item_span; @@ -257,7 +253,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>( tcx.impl_item_implementor_ids(impl_def_id).get(&item_def_id) && let Some(impl_item_span) = items .iter() - .find(|item| item.id.def_id.to_def_id() == impl_item_id) + .find(|item| item.id.owner_id.to_def_id() == impl_item_id) .map(fix_span) { cause.span = impl_item_span; @@ -276,7 +272,7 @@ impl<'tcx> WfPredicates<'tcx> { traits::ObligationCause::new(self.span, self.body_id, code) } - fn normalize(self, infcx: &InferCtxt<'_, 'tcx>) -> Vec<traits::PredicateObligation<'tcx>> { + fn normalize(self, infcx: &InferCtxt<'tcx>) -> Vec<traits::PredicateObligation<'tcx>> { let cause = self.cause(traits::WellFormed(None)); let param_env = self.param_env; let mut obligations = Vec::with_capacity(self.out.len()); @@ -393,7 +389,8 @@ impl<'tcx> WfPredicates<'tcx> { // `i32: Clone` // `i32: Copy` // ] - let obligations = self.nominal_obligations(data.item_def_id, data.substs); + // Projection types do not require const predicates. + let obligations = self.nominal_obligations_without_const(data.item_def_id, data.substs); self.out.extend(obligations); let tcx = self.tcx(); @@ -436,11 +433,13 @@ impl<'tcx> WfPredicates<'tcx> { } /// Pushes all the predicates needed to validate that `ty` is WF into `out`. + #[instrument(level = "debug", skip(self))] fn compute(&mut self, arg: GenericArg<'tcx>) { let mut walker = arg.walk(); let param_env = self.param_env; let depth = self.recursion_depth; while let Some(arg) = walker.next() { + debug!(?arg, ?self.out); let ty = match arg.unpack() { GenericArgKind::Type(ty) => ty, @@ -448,14 +447,14 @@ impl<'tcx> WfPredicates<'tcx> { // obligations are handled by the parent (e.g. `ty::Ref`). GenericArgKind::Lifetime(_) => continue, - GenericArgKind::Const(constant) => { - match constant.kind() { + GenericArgKind::Const(ct) => { + match ct.kind() { ty::ConstKind::Unevaluated(uv) => { let obligations = self.nominal_obligations(uv.def.did, uv.substs); self.out.extend(obligations); let predicate = - ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv.shrink())) + ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct)) .to_predicate(self.tcx()); let cause = self.cause(traits::WellFormed(None)); self.out.push(traits::Obligation::with_depth( @@ -472,7 +471,7 @@ impl<'tcx> WfPredicates<'tcx> { cause, self.recursion_depth, self.param_env, - ty::Binder::dummy(ty::PredicateKind::WellFormed(constant.into())) + ty::Binder::dummy(ty::PredicateKind::WellFormed(ct.into())) .to_predicate(self.tcx()), )); } @@ -490,6 +489,8 @@ impl<'tcx> WfPredicates<'tcx> { } }; + debug!("wf bounds for ty={:?} ty.kind={:#?}", ty, ty.kind()); + match *ty.kind() { ty::Bool | ty::Char @@ -546,7 +547,7 @@ impl<'tcx> WfPredicates<'tcx> { } ty::FnDef(did, substs) => { - let obligations = self.nominal_obligations(did, substs); + let obligations = self.nominal_obligations_without_const(did, substs); self.out.extend(obligations); } @@ -636,7 +637,7 @@ impl<'tcx> WfPredicates<'tcx> { } } - ty::Dynamic(data, r) => { + ty::Dynamic(data, r, _) => { // WfObject // // Here, we defer WF checking due to higher-ranked @@ -688,6 +689,8 @@ impl<'tcx> WfPredicates<'tcx> { )); } } + + debug!(?self.out); } } @@ -713,7 +716,7 @@ impl<'tcx> WfPredicates<'tcx> { iter::zip(iter::zip(predicates.predicates, predicates.spans), origins.into_iter().rev()) .map(|((mut pred, span), origin_def_id)| { let code = if span.is_dummy() { - traits::MiscObligation + traits::ItemObligation(origin_def_id) } else { traits::BindingObligation(origin_def_id, span) }; @@ -843,7 +846,7 @@ pub fn object_region_bounds<'tcx>( /// /// Requires that trait definitions have been processed so that we can /// elaborate predicates and walk supertraits. -#[instrument(skip(tcx, predicates), level = "debug")] +#[instrument(skip(tcx, predicates), level = "debug", ret)] pub(crate) fn required_region_bounds<'tcx>( tcx: TyCtxt<'tcx>, erased_self_ty: Ty<'tcx>, |