]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/ty/wf.rs
Fixes issue #43205: ICE in Rvalue::Len evaluation.
[rust.git] / src / librustc / ty / wf.rs
index aa2c9802e54737bff9bf52eb372ee1740f704129..c24c583ad1e19a384056197b4f1fe579040562c8 100644 (file)
@@ -10,7 +10,6 @@
 
 use hir::def_id::DefId;
 use infer::InferCtxt;
-use ty::outlives::Component;
 use ty::subst::Substs;
 use traits;
 use ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
@@ -32,10 +31,10 @@ pub fn obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
                                    span: Span)
                                    -> Option<Vec<traits::PredicateObligation<'tcx>>>
 {
-    let mut wf = WfPredicates { infcx: infcx,
-                                param_env: param_env,
-                                body_id: body_id,
-                                span: span,
+    let mut wf = WfPredicates { infcx,
+                                param_env,
+                                body_id,
+                                span,
                                 out: vec![] };
     if wf.compute(ty) {
         debug!("wf::obligations({:?}, body_id={:?}) = {:?}", ty, body_id, wf.out);
@@ -107,133 +106,6 @@ pub fn predicate_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
     wf.normalize()
 }
 
-/// Implied bounds are region relationships that we deduce
-/// automatically.  The idea is that (e.g.) a caller must check that a
-/// function's argument types are well-formed immediately before
-/// calling that fn, and hence the *callee* can assume that its
-/// argument types are well-formed. This may imply certain relationships
-/// between generic parameters. For example:
-///
-///     fn foo<'a,T>(x: &'a T)
-///
-/// can only be called with a `'a` and `T` such that `&'a T` is WF.
-/// For `&'a T` to be WF, `T: 'a` must hold. So we can assume `T: 'a`.
-#[derive(Debug)]
-pub enum ImpliedBound<'tcx> {
-    RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>),
-    RegionSubParam(ty::Region<'tcx>, ty::ParamTy),
-    RegionSubProjection(ty::Region<'tcx>, ty::ProjectionTy<'tcx>),
-}
-
-/// Compute the implied bounds that a callee/impl can assume based on
-/// the fact that caller/projector has ensured that `ty` is WF.  See
-/// the `ImpliedBound` type for more details.
-pub fn implied_bounds<'a, 'gcx, 'tcx>(
-    infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    body_id: ast::NodeId,
-    ty: Ty<'tcx>,
-    span: Span)
-    -> Vec<ImpliedBound<'tcx>>
-{
-    // Sometimes when we ask what it takes for T: WF, we get back that
-    // U: WF is required; in that case, we push U onto this stack and
-    // process it next. Currently (at least) these resulting
-    // predicates are always guaranteed to be a subset of the original
-    // type, so we need not fear non-termination.
-    let mut wf_types = vec![ty];
-
-    let mut implied_bounds = vec![];
-
-    while let Some(ty) = wf_types.pop() {
-        // Compute the obligations for `ty` to be well-formed. If `ty` is
-        // an unresolved inference variable, just substituted an empty set
-        // -- because the return type here is going to be things we *add*
-        // to the environment, it's always ok for this set to be smaller
-        // than the ultimate set. (Note: normally there won't be
-        // unresolved inference variables here anyway, but there might be
-        // during typeck under some circumstances.)
-        let obligations = obligations(infcx, param_env, body_id, ty, span).unwrap_or(vec![]);
-
-        // From the full set of obligations, just filter down to the
-        // region relationships.
-        implied_bounds.extend(
-            obligations
-            .into_iter()
-            .flat_map(|obligation| {
-                assert!(!obligation.has_escaping_regions());
-                match obligation.predicate {
-                    ty::Predicate::Trait(..) |
-                    ty::Predicate::Equate(..) |
-                    ty::Predicate::Subtype(..) |
-                    ty::Predicate::Projection(..) |
-                    ty::Predicate::ClosureKind(..) |
-                    ty::Predicate::ObjectSafe(..) =>
-                        vec![],
-
-                    ty::Predicate::WellFormed(subty) => {
-                        wf_types.push(subty);
-                        vec![]
-                    }
-
-                    ty::Predicate::RegionOutlives(ref data) =>
-                        match infcx.tcx.no_late_bound_regions(data) {
-                            None =>
-                                vec![],
-                            Some(ty::OutlivesPredicate(r_a, r_b)) =>
-                                vec![ImpliedBound::RegionSubRegion(r_b, r_a)],
-                        },
-
-                    ty::Predicate::TypeOutlives(ref data) =>
-                        match infcx.tcx.no_late_bound_regions(data) {
-                            None => vec![],
-                            Some(ty::OutlivesPredicate(ty_a, r_b)) => {
-                                let ty_a = infcx.resolve_type_vars_if_possible(&ty_a);
-                                let components = infcx.tcx.outlives_components(ty_a);
-                                implied_bounds_from_components(r_b, components)
-                            }
-                        },
-                }}));
-    }
-
-    implied_bounds
-}
-
-/// When we have an implied bound that `T: 'a`, we can further break
-/// this down to determine what relationships would have to hold for
-/// `T: 'a` to hold. We get to assume that the caller has validated
-/// those relationships.
-fn implied_bounds_from_components<'tcx>(sub_region: ty::Region<'tcx>,
-                                        sup_components: Vec<Component<'tcx>>)
-                                        -> Vec<ImpliedBound<'tcx>>
-{
-    sup_components
-        .into_iter()
-        .flat_map(|component| {
-            match component {
-                Component::Region(r) =>
-                    vec![ImpliedBound::RegionSubRegion(sub_region, r)],
-                Component::Param(p) =>
-                    vec![ImpliedBound::RegionSubParam(sub_region, p)],
-                Component::Projection(p) =>
-                    vec![ImpliedBound::RegionSubProjection(sub_region, p)],
-                Component::EscapingProjection(_) =>
-                    // If the projection has escaping regions, don't
-                    // try to infer any implied bounds even for its
-                    // free components. This is conservative, because
-                    // the caller will still have to prove that those
-                    // free components outlive `sub_region`. But the
-                    // idea is that the WAY that the caller proves
-                    // that may change in the future and we want to
-                    // give ourselves room to get smarter here.
-                    vec![],
-                Component::UnresolvedInferenceVariable(..) =>
-                    vec![],
-            }
-        })
-        .collect()
-}
-
 struct WfPredicates<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
@@ -283,11 +155,11 @@ fn compute_projection(&mut self, data: ty::ProjectionTy<'tcx>) {
         // A projection is well-formed if (a) the trait ref itself is
         // WF and (b) the trait-ref holds.  (It may also be
         // normalizable and be WF that way.)
-
-        self.compute_trait_ref(&data.trait_ref);
+        let trait_ref = data.trait_ref(self.infcx.tcx);
+        self.compute_trait_ref(&trait_ref);
 
         if !data.has_escaping_regions() {
-            let predicate = data.trait_ref.to_predicate();
+            let predicate = trait_ref.to_predicate();
             let cause = self.cause(traits::ProjectionWf(data));
             self.out.push(traits::Obligation::new(cause, self.param_env, predicate));
         }