]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_trait_selection/traits/wf.rs
introduce PredicateAtom
[rust.git] / src / librustc_trait_selection / traits / wf.rs
index 30ba49ed2d8fea2671ae69e722deeec584a80958..0ca69c0f76e7a273b865e4ea8c2ff2e2292edb2f 100644 (file)
@@ -93,41 +93,45 @@ pub fn predicate_obligations<'a, 'tcx>(
 ) -> Vec<traits::PredicateObligation<'tcx>> {
     let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None };
 
-    // (*) ok to skip binders, because wf code is prepared for it
     match predicate.kind() {
-        ty::PredicateKind::Trait(t, _) => {
-            wf.compute_trait_ref(&t.skip_binder().trait_ref, Elaborate::None); // (*)
+        ty::PredicateKind::ForAll(binder) => {
+            // It's ok to skip the binder here because wf code is prepared for it
+            return predicate_obligations(infcx, param_env, body_id, binder.skip_binder(), span);
         }
-        ty::PredicateKind::RegionOutlives(..) => {}
-        ty::PredicateKind::TypeOutlives(t) => {
-            wf.compute(t.skip_binder().0.into());
-        }
-        ty::PredicateKind::Projection(t) => {
-            let t = t.skip_binder(); // (*)
-            wf.compute_projection(t.projection_ty);
-            wf.compute(t.ty.into());
-        }
-        &ty::PredicateKind::WellFormed(arg) => {
-            wf.compute(arg);
-        }
-        ty::PredicateKind::ObjectSafe(_) => {}
-        ty::PredicateKind::ClosureKind(..) => {}
-        ty::PredicateKind::Subtype(data) => {
-            wf.compute(data.skip_binder().a.into()); // (*)
-            wf.compute(data.skip_binder().b.into()); // (*)
-        }
-        &ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
-            let obligations = wf.nominal_obligations(def_id, substs);
-            wf.out.extend(obligations);
-
-            for arg in substs.iter() {
+        &ty::PredicateKind::Atom(atom) => match atom {
+            ty::PredicateAtom::Trait(t, _) => {
+                wf.compute_trait_ref(&t.trait_ref, Elaborate::None);
+            }
+            ty::PredicateAtom::RegionOutlives(..) => {}
+            ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => {
+                wf.compute(ty.into());
+            }
+            ty::PredicateAtom::Projection(t) => {
+                wf.compute_projection(t.projection_ty);
+                wf.compute(t.ty.into());
+            }
+            ty::PredicateAtom::WellFormed(arg) => {
                 wf.compute(arg);
             }
-        }
-        &ty::PredicateKind::ConstEquate(c1, c2) => {
-            wf.compute(c1.into());
-            wf.compute(c2.into());
-        }
+            ty::PredicateAtom::ObjectSafe(_) => {}
+            ty::PredicateAtom::ClosureKind(..) => {}
+            ty::PredicateAtom::Subtype(ty::SubtypePredicate { a, b, a_is_expected: _ }) => {
+                wf.compute(a.into());
+                wf.compute(b.into());
+            }
+            ty::PredicateAtom::ConstEvaluatable(def, substs) => {
+                let obligations = wf.nominal_obligations(def.did, substs);
+                wf.out.extend(obligations);
+
+                for arg in substs.iter() {
+                    wf.compute(arg);
+                }
+            }
+            ty::PredicateAtom::ConstEquate(c1, c2) => {
+                wf.compute(c1.into());
+                wf.compute(c2.into());
+            }
+        },
     }
 
     wf.normalize()
@@ -176,7 +180,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
     trait_ref: &ty::TraitRef<'tcx>,
     item: Option<&hir::Item<'tcx>>,
     cause: &mut traits::ObligationCause<'tcx>,
-    pred: &ty::Predicate<'_>,
+    pred: &ty::Predicate<'tcx>,
     mut trait_assoc_items: impl Iterator<Item = &'tcx ty::AssocItem>,
 ) {
     debug!(
@@ -192,15 +196,16 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
             hir::ImplItemKind::Const(ty, _) | hir::ImplItemKind::TyAlias(ty) => ty.span,
             _ => impl_item_ref.span,
         };
-    match pred.kind() {
-        ty::PredicateKind::Projection(proj) => {
+
+    // It is fine to skip the binder as we don't care about regions here.
+    match pred.skip_binders() {
+        ty::PredicateAtom::Projection(proj) => {
             // The obligation comes not from the current `impl` nor the `trait` being implemented,
             // but rather from a "second order" obligation, where an associated type has a
             // projection coming from another associated type. See
             // `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs` and
             // `traits-assoc-type-in-supertrait-bad.rs`.
-            let kind = &proj.ty().skip_binder().kind;
-            if let ty::Projection(projection_ty) = kind {
+            if let ty::Projection(projection_ty) = proj.ty.kind {
                 let trait_assoc_item = tcx.associated_item(projection_ty.item_def_id);
                 if let Some(impl_item_span) =
                     items.iter().find(|item| item.ident == trait_assoc_item.ident).map(fix_span)
@@ -209,15 +214,13 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
                 }
             }
         }
-        ty::PredicateKind::Trait(pred, _) => {
+        ty::PredicateAtom::Trait(pred, _) => {
             // An associated item obligation born out of the `trait` failed to be met. An example
             // can be seen in `ui/associated-types/point-at-type-on-obligation-failure-2.rs`.
             debug!("extended_cause_with_original_assoc_item_obligation trait proj {:?}", pred);
-            if let ty::Projection(ty::ProjectionTy { item_def_id, .. }) =
-                &pred.skip_binder().self_ty().kind
-            {
+            if let ty::Projection(ty::ProjectionTy { item_def_id, .. }) = pred.self_ty().kind {
                 if let Some(impl_item_span) = trait_assoc_items
-                    .find(|i| i.def_id == *item_def_id)
+                    .find(|i| i.def_id == item_def_id)
                     .and_then(|trait_assoc_item| {
                         items.iter().find(|i| i.ident == trait_assoc_item.ident).map(fix_span)
                     })
@@ -300,15 +303,23 @@ fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, elaborate: Elabo
             trait_ref
                 .substs
                 .iter()
-                .filter(|arg| {
+                .enumerate()
+                .filter(|(_, arg)| {
                     matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..))
                 })
-                .filter(|arg| !arg.has_escaping_bound_vars())
-                .map(|arg| {
+                .filter(|(_, arg)| !arg.has_escaping_bound_vars())
+                .map(|(i, arg)| {
+                    let mut new_cause = cause.clone();
+                    // The first subst is the self ty - use the correct span for it.
+                    if i == 0 {
+                        if let Some(hir::ItemKind::Impl { self_ty, .. }) = item.map(|i| &i.kind) {
+                            new_cause.make_mut().span = self_ty.span;
+                        }
+                    }
                     traits::Obligation::new(
-                        cause.clone(),
+                        new_cause,
                         param_env,
-                        ty::PredicateKind::WellFormed(arg).to_predicate(tcx),
+                        ty::PredicateAtom::WellFormed(arg).to_predicate(tcx),
                     )
                 }),
         );
@@ -365,7 +376,7 @@ fn compute(&mut self, arg: GenericArg<'tcx>) {
                             let obligations = self.nominal_obligations(def.did, substs);
                             self.out.extend(obligations);
 
-                            let predicate = ty::PredicateKind::ConstEvaluatable(def.did, substs)
+                            let predicate = ty::PredicateAtom::ConstEvaluatable(def, substs)
                                 .to_predicate(self.tcx());
                             let cause = self.cause(traits::MiscObligation);
                             self.out.push(traits::Obligation::new(
@@ -387,7 +398,7 @@ fn compute(&mut self, arg: GenericArg<'tcx>) {
                                 self.out.push(traits::Obligation::new(
                                     cause,
                                     self.param_env,
-                                    ty::PredicateKind::WellFormed(resolved_constant.into())
+                                    ty::PredicateAtom::WellFormed(resolved_constant.into())
                                         .to_predicate(self.tcx()),
                                 ));
                             }
@@ -473,10 +484,8 @@ fn compute(&mut self, arg: GenericArg<'tcx>) {
                         self.out.push(traits::Obligation::new(
                             cause,
                             param_env,
-                            ty::PredicateKind::TypeOutlives(ty::Binder::dummy(
-                                ty::OutlivesPredicate(rty, r),
-                            ))
-                            .to_predicate(self.tcx()),
+                            ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(rty, r))
+                                .to_predicate(self.tcx()),
                         ));
                     }
                 }
@@ -566,7 +575,7 @@ fn compute(&mut self, arg: GenericArg<'tcx>) {
                             traits::Obligation::new(
                                 cause.clone(),
                                 param_env,
-                                ty::PredicateKind::ObjectSafe(did).to_predicate(tcx),
+                                ty::PredicateAtom::ObjectSafe(did).to_predicate(tcx),
                             )
                         }));
                     }
@@ -592,7 +601,7 @@ fn compute(&mut self, arg: GenericArg<'tcx>) {
                         self.out.push(traits::Obligation::new(
                             cause,
                             param_env,
-                            ty::PredicateKind::WellFormed(ty.into()).to_predicate(self.tcx()),
+                            ty::PredicateAtom::WellFormed(ty.into()).to_predicate(self.tcx()),
                         ));
                     } else {
                         // Yes, resolved, proceed with the result.