]> git.lizzy.rs Git - rust.git/commitdiff
Introduce machinery for higher-ranked TraitRefs
authorNiko Matsakis <niko@alum.mit.edu>
Sat, 15 Nov 2014 22:09:51 +0000 (17:09 -0500)
committerNiko Matsakis <niko@alum.mit.edu>
Tue, 18 Nov 2014 17:32:38 +0000 (12:32 -0500)
15 files changed:
src/librustc/middle/resolve_lifetime.rs
src/librustc/middle/traits/fulfill.rs
src/librustc/middle/traits/select.rs
src/librustc/middle/ty.rs
src/librustc/middle/ty_fold.rs
src/librustc/middle/typeck/astconv.rs
src/librustc/middle/typeck/collect.rs
src/librustc/middle/typeck/infer/combine.rs
src/librustc/middle/typeck/infer/equate.rs
src/librustc/middle/typeck/infer/lattice.rs
src/librustc/middle/typeck/infer/lub.rs
src/librustc/middle/typeck/infer/mod.rs
src/librustc/middle/typeck/infer/sub.rs
src/librustc/middle/typeck/rscope.rs
src/librustc_trans/driver/driver.rs

index 7b2ff6d4b7db42b8817e621a57411874f33bbf89..20a29465bbd29b5f9fde6e2332c06cd5cf2f79fb 100644 (file)
 use self::ScopeChain::*;
 
 use session::Session;
+use middle::def;
+use middle::resolve::DefMap;
 use middle::subst;
+use middle::ty;
 use std::fmt;
 use syntax::ast;
 use syntax::codemap::Span;
-use syntax::owned_slice::OwnedSlice;
 use syntax::parse::token::special_idents;
 use syntax::parse::token;
 use syntax::print::pprust::{lifetime_to_string};
@@ -52,7 +54,8 @@ pub enum DefRegion {
 struct LifetimeContext<'a> {
     sess: &'a Session,
     named_region_map: &'a mut NamedRegionMap,
-    scope: Scope<'a>
+    scope: Scope<'a>,
+    def_map: &'a DefMap,
 }
 
 enum ScopeChain<'a> {
@@ -72,12 +75,13 @@ enum ScopeChain<'a> {
 
 static ROOT_SCOPE: ScopeChain<'static> = RootScope;
 
-pub fn krate(sess: &Session, krate: &ast::Crate) -> NamedRegionMap {
+pub fn krate(sess: &Session, krate: &ast::Crate, def_map: &DefMap) -> NamedRegionMap {
     let mut named_region_map = NodeMap::new();
     visit::walk_crate(&mut LifetimeContext {
         sess: sess,
         named_region_map: &mut named_region_map,
-        scope: &ROOT_SCOPE
+        scope: &ROOT_SCOPE,
+        def_map: def_map,
     }, krate);
     sess.abort_if_errors();
     named_region_map
@@ -151,6 +155,27 @@ fn visit_ty(&mut self, ty: &ast::Ty) {
                     visit::walk_ty(this, ty);
                 });
             }
+            ast::TyPath(ref path, ref opt_bounds, id) => {
+                // if this path references a trait, then this will resolve to
+                // a trait ref, which introduces a binding scope.
+                match self.def_map.borrow().get(&id) {
+                    Some(&def::DefTrait(..)) => {
+                        self.with(LateScope(&Vec::new(), self.scope), |this| {
+                            this.visit_path(path, id);
+                        });
+
+                        match *opt_bounds {
+                            Some(ref bounds) => {
+                                visit::walk_ty_param_bounds_helper(self, bounds);
+                            }
+                            None => { }
+                        }
+                    }
+                    _ => {
+                        visit::walk_ty(self, ty);
+                    }
+                }
+            }
             _ => {
                 visit::walk_ty(self, ty)
             }
@@ -177,7 +202,7 @@ fn visit_lifetime_ref(&mut self, lifetime_ref: &ast::Lifetime) {
 
     fn visit_generics(&mut self, generics: &ast::Generics) {
         for ty_param in generics.ty_params.iter() {
-            self.visit_ty_param_bounds(&ty_param.bounds);
+            visit::walk_ty_param_bounds_helper(self, &ty_param.bounds);
             match ty_param.default {
                 Some(ref ty) => self.visit_ty(&**ty),
                 None => {}
@@ -185,41 +210,14 @@ fn visit_generics(&mut self, generics: &ast::Generics) {
         }
         for predicate in generics.where_clause.predicates.iter() {
             self.visit_ident(predicate.span, predicate.ident);
-            self.visit_ty_param_bounds(&predicate.bounds);
-        }
-    }
-}
-
-impl<'a> LifetimeContext<'a> {
-    fn with(&mut self, wrap_scope: ScopeChain, f: |&mut LifetimeContext|) {
-        let LifetimeContext {sess, ref mut named_region_map, ..} = *self;
-        let mut this = LifetimeContext {
-            sess: sess,
-            named_region_map: *named_region_map,
-            scope: &wrap_scope
-        };
-        debug!("entering scope {}", this.scope);
-        f(&mut this);
-        debug!("exiting scope {}", this.scope);
-    }
-
-    fn visit_ty_param_bounds(&mut self,
-                             bounds: &OwnedSlice<ast::TyParamBound>) {
-        for bound in bounds.iter() {
-            match *bound {
-                ast::TraitTyParamBound(ref trait_ref) => {
-                    self.visit_poly_trait_ref(trait_ref);
-                }
-                ast::RegionTyParamBound(ref lifetime) => {
-                    self.visit_lifetime_ref(lifetime);
-                }
-            }
+            visit::walk_ty_param_bounds_helper(self, &predicate.bounds);
         }
     }
 
     fn visit_poly_trait_ref(&mut self, trait_ref: &ast::PolyTraitRef) {
-        let ref_id = trait_ref.trait_ref.ref_id;
-        self.with(LateScope(ref_id, &trait_ref.bound_lifetimes, self.scope), |this| {
+        debug!("visit_poly_trait_ref trait_ref={}", trait_ref);
+
+        self.with(LateScope(&trait_ref.bound_lifetimes, self.scope), |this| {
             this.check_lifetime_defs(&trait_ref.bound_lifetimes);
             for lifetime in trait_ref.bound_lifetimes.iter() {
                 this.visit_lifetime_decl(lifetime);
index 6baf4e6c048903f9b517b4933e9f37a936f3588b..ff5d80c8a16a21fa9d5c86bb8be57aa52ecdb17e 100644 (file)
@@ -55,6 +55,7 @@ pub fn register_obligation(&mut self,
                                obligation: Obligation)
     {
         debug!("register_obligation({})", obligation.repr(tcx));
+        assert!(!obligation.trait_ref.has_escaping_regions());
         self.trait_obligations.push(obligation);
     }
 
index bb0db874b675f9f27258282c321ade7ebf4fd8a3..38e70ec389e94e578e8ec32299e29d1a70352890 100644 (file)
@@ -31,9 +31,7 @@
 use middle::mem_categorization::Typer;
 use middle::subst::{Subst, Substs, VecPerParamSpace};
 use middle::ty;
-use middle::typeck::check::regionmanip;
 use middle::typeck::infer;
-use middle::typeck::infer::LateBoundRegionConversionTime::*;
 use middle::typeck::infer::{InferCtxt, TypeSkolemizer};
 use middle::ty_fold::TypeFoldable;
 use std::cell::RefCell;
@@ -211,6 +209,7 @@ pub fn select(&mut self, obligation: &Obligation) -> SelectionResult<Selection>
          */
 
         debug!("select({})", obligation.repr(self.tcx()));
+        assert!(!obligation.trait_ref.has_escaping_regions());
 
         let stack = self.push_stack(None, obligation);
         match try!(self.candidate_from_obligation(&stack)) {
@@ -263,6 +262,7 @@ pub fn evaluate_obligation(&mut self,
 
         debug!("evaluate_obligation({})",
                obligation.repr(self.tcx()));
+        assert!(!obligation.trait_ref.has_escaping_regions());
 
         let stack = self.push_stack(None, obligation);
         self.evaluate_stack(&stack).may_apply()
@@ -747,6 +747,7 @@ fn candidate_from_obligation(&mut self,
         debug!("candidate_from_obligation(cache_skol_trait_ref={}, obligation={})",
                cache_skol_trait_ref.repr(self.tcx()),
                stack.repr(self.tcx()));
+        assert!(!stack.obligation.trait_ref.has_escaping_regions());
 
         match self.check_candidate_cache(cache_skol_trait_ref.clone()) {
             Some(c) => {
@@ -1707,27 +1708,18 @@ fn confirm_unboxed_closure_candidate(&mut self,
             }
         };
 
-        // FIXME(pcwalton): This is a bogus thing to do, but
-        // it'll do for now until we get the new trait-bound
-        // region skolemization working.
-        let (_, new_signature) =
-            regionmanip::replace_late_bound_regions(
-                self.tcx(),
-                closure_type.sig.binder_id,
-                &closure_type.sig,
-                |br| self.infcx.next_region_var(
-                         infer::LateBoundRegion(obligation.cause.span, br,
-                                                infer::FnCall)));
-
-        let arguments_tuple = new_signature.inputs[0];
-        let trait_ref = Rc::new(ty::TraitRef {
-            def_id: obligation.trait_ref.def_id,
-            substs: Substs::new_trait(
+        let closure_sig = &closure_type.sig;
+        let arguments_tuple = closure_sig.inputs[0];
+        let substs =
+            Substs::new_trait(
                 vec![arguments_tuple.subst(self.tcx(), substs),
-                     new_signature.output.unwrap().subst(self.tcx(), substs)],
+                     closure_sig.output.unwrap().subst(self.tcx(), substs)],
                 vec![],
                 vec![],
-                obligation.self_ty())
+                obligation.self_ty());
+        let trait_ref = Rc::new(ty::TraitRef {
+            def_id: obligation.trait_ref.def_id,
+            substs: substs,
         });
 
         self.confirm(obligation.cause,
index 2662d6ef1908cf0c8fdb69a9a0e620034b5c7bcf..ec8285c33de762230529b4207c04ad771bd965cb 100644 (file)
@@ -1105,6 +1105,23 @@ pub struct TyTrait {
     pub bounds: ExistentialBounds
 }
 
+/**
+ * A complete reference to a trait. These take numerous guises in syntax,
+ * but perhaps the most recognizable form is in a where clause:
+ *
+ *     T : Foo<U>
+ *
+ * This would be represented by a trait-reference where the def-id is the
+ * def-id for the trait `Foo` and the substs defines `T` as parameter 0 in the
+ * `SelfSpace` and `U` as parameter 0 in the `TypeSpace`.
+ *
+ * Trait references also appear in object types like `Foo<U>`, but in
+ * that case the `Self` parameter is absent from the substitutions.
+ *
+ * Note that a `TraitRef` introduces a level of region binding, to
+ * account for higher-ranked trait bounds like `T : for<'a> Foo<&'a
+ * U>` or higher-ranked object types.
+ */
 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
 pub struct TraitRef {
     pub def_id: DefId,
@@ -1410,6 +1427,14 @@ pub fn input_types(&self) -> &[ty::t] {
         // associated types.
         self.substs.types.as_slice()
     }
+
+    pub fn has_escaping_regions(&self) -> bool {
+        self.substs.has_regions_escaping_depth(1)
+    }
+
+    pub fn has_bound_regions(&self) -> bool {
+        self.substs.has_regions_escaping_depth(0)
+    }
 }
 
 /// When type checking, we use the `ParameterEnvironment` to track
@@ -1826,7 +1851,10 @@ fn add_sty(&mut self, st: &sty) {
             }
 
             &ty_trait(box TyTrait { ref principal, ref bounds }) => {
-                self.add_substs(&principal.substs);
+                let mut computation = FlagComputation::new();
+                computation.add_substs(&principal.substs);
+                self.add_bound_computation(&computation);
+
                 self.add_bounds(bounds);
             }
 
@@ -4708,9 +4736,99 @@ pub fn bounds_for_trait_ref(tcx: &ctxt,
                             -> ty::ParamBounds
 {
     let trait_def = lookup_trait_def(tcx, trait_ref.def_id);
+
     debug!("bounds_for_trait_ref(trait_def={}, trait_ref={})",
            trait_def.repr(tcx), trait_ref.repr(tcx));
-    trait_def.bounds.subst(tcx, &trait_ref.substs)
+
+    // The interaction between HRTB and supertraits is not entirely
+    // obvious. Let me walk you (and myself) through an example.
+    //
+    // Let's start with an easy case. Consider two traits:
+    //
+    //     trait Foo<'a> : Bar<'a,'a> { }
+    //     trait Bar<'b,'c> { }
+    //
+    // Now, if we have a trait reference `for<'x> T : Foo<'x>`, then
+    // we can deduce that `for<'x> T : Bar<'x,'x>`. Basically, if we
+    // knew that `Foo<'x>` (for any 'x) then we also know that
+    // `Bar<'x,'x>` (for any 'x). This more-or-less falls out from
+    // normal substitution.
+    //
+    // In terms of why this is sound, the idea is that whenever there
+    // is an impl of `T:Foo<'a>`, it must show that `T:Bar<'a,'a>`
+    // holds.  So if there is an impl of `T:Foo<'a>` that applies to
+    // all `'a`, then we must know that `T:Bar<'a,'a>` holds for all
+    // `'a`.
+    //
+    // Another example to be careful of is this:
+    //
+    //     trait Foo1<'a> : for<'b> Bar1<'a,'b> { }
+    //     trait Bar1<'b,'c> { }
+    //
+    // Here, if we have `for<'x> T : Foo1<'x>`, then what do we know?
+    // The answer is that we know `for<'x,'b> T : Bar1<'x,'b>`. The
+    // reason is similar to the previous example: any impl of
+    // `T:Foo1<'x>` must show that `for<'b> T : Bar1<'x, 'b>`.  So
+    // basically we would want to collapse the bound lifetimes from
+    // the input (`trait_ref`) and the supertraits.
+    //
+    // To achieve this in practice is fairly straightforward. Let's
+    // consider the more complicated scenario:
+    //
+    // - We start out with `for<'x> T : Foo1<'x>`. In this case, `'x`
+    //   has a De Bruijn index of 1. We want to produce `for<'x,'b> T : Bar1<'x,'b>`,
+    //   where both `'x` and `'b` would have a DB index of 1.
+    //   The substitution from the input trait-ref is therefore going to be
+    //   `'a => 'x` (where `'x` has a DB index of 1).
+    // - The super-trait-ref is `for<'b> Bar1<'a,'b>`, where `'a` is an
+    //   early-bound parameter and `'b' is a late-bound parameter with a
+    //   DB index of 1.
+    // - If we replace `'a` with `'x` from the input, it too will have
+    //   a DB index of 1, and thus we'll have `for<'x,'b> Bar1<'x,'b>`
+    //   just as we wanted.
+    //
+    // There is only one catch. If we just apply the substitution `'a
+    // => 'x` to `for<'b> Bar1<'a,'b>`, the substitution code will
+    // adjust the DB index because we substituting into a binder (it
+    // tries to be so smart...) resulting in `for<'x> for<'b>
+    // Bar1<'x,'b>` (we have no syntax for this, so use your
+    // imagination). Basically the 'x will have DB index of 2 and 'b
+    // will have DB index of 1. Not quite what we want. So we apply
+    // the substitution to the *contents* of the trait reference,
+    // rather than the trait reference itself (put another way, the
+    // substitution code expects equal binding levels in the values
+    // from the substitution and the value being substituted into, and
+    // this trick achieves that).
+
+    // Carefully avoid the binder introduced by each trait-ref by
+    // substituting over the substs, not the trait-refs themselves,
+    // thus achieving the "collapse" described in the big comment
+    // above.
+    let trait_bounds: Vec<_> =
+        trait_def.bounds.trait_bounds
+        .iter()
+        .map(|bound_trait_ref| {
+            ty::TraitRef::new(bound_trait_ref.def_id,
+                              bound_trait_ref.substs.subst(tcx, &trait_ref.substs))
+        })
+        .map(|bound_trait_ref| Rc::new(bound_trait_ref))
+        .collect();
+
+    debug!("bounds_for_trait_ref: trait_bounds={}",
+           trait_bounds.repr(tcx));
+
+    // The region bounds and builtin bounds do not currently introduce
+    // binders so we can just substitute in a straightforward way here.
+    let region_bounds =
+        trait_def.bounds.region_bounds.subst(tcx, &trait_ref.substs);
+    let builtin_bounds =
+        trait_def.bounds.builtin_bounds.subst(tcx, &trait_ref.substs);
+
+    ty::ParamBounds {
+        trait_bounds: trait_bounds,
+        region_bounds: region_bounds,
+        builtin_bounds: builtin_bounds,
+    }
 }
 
 /// Iterate over attributes of a definition.
index c0686e1c8fcc35880706f6732169ca14877b2bf7..52e6bcf5b6d913f1acadb1054f6d0bb4fe8c4205 100644 (file)
@@ -42,7 +42,6 @@
 use middle::traits;
 use middle::typeck;
 use std::rc::Rc;
-use syntax::ast;
 use syntax::owned_slice::OwnedSlice;
 use util::ppaux::Repr;
 
@@ -477,6 +476,7 @@ fn fold_with<'tcx, F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableP
 // "super" routines: these are the default implementations for TypeFolder.
 //
 // They should invoke `foo.fold_with()` to do recursive folding.
+
 pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
                                                 t: ty::t)
                                                 -> ty::t {
@@ -550,9 +550,21 @@ pub fn super_fold_closure_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
         abi: fty.abi,
     }
 }
+
 pub fn super_fold_trait_ref<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
                                                        t: &ty::TraitRef)
-                                                       -> ty::TraitRef {
+                                                       -> ty::TraitRef
+{
+    this.enter_region_binder();
+    let result = super_fold_trait_ref_contents(this, t);
+    this.exit_region_binder();
+    result
+}
+
+pub fn super_fold_trait_ref_contents<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
+                                                                t: &ty::TraitRef)
+                                                                -> ty::TraitRef
+{
     ty::TraitRef {
         def_id: t.def_id,
         substs: t.substs.fold_with(this),
@@ -691,11 +703,26 @@ fn fold_contents<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::FnSig
         super_fold_fn_sig_contents(folder, self)
     }
 }
+
+impl HigherRankedFoldable for ty::TraitRef {
+    fn fold_contents<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::TraitRef {
+        super_fold_trait_ref_contents(folder, self)
+    }
+}
+
 impl<T:TypeFoldable+Repr> HigherRankedFoldable for ty::Binder<T> {
     fn fold_contents<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::Binder<T> {
         ty::bind(self.value.fold_with(folder))
     }
 }
+
+impl<T:HigherRankedFoldable> HigherRankedFoldable for Rc<T> {
+    fn fold_contents<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Rc<T> {
+        Rc::new((**self).fold_contents(folder))
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////
 // Some sample folders
 
 pub struct BottomUpFolder<'a, 'tcx: 'a> {
index 90238f7913558ff65df7468c80976a153be8fd96..68677492649615936600652419b19e1af03cc29e 100644 (file)
 use middle::subst::{VecPerParamSpace};
 use middle::ty;
 use middle::typeck::lookup_def_tcx;
-use middle::typeck::infer;
-use middle::typeck::rscope::{UnelidableRscope, RegionScope, SpecificRscope, BindingRscope};
+use middle::typeck::rscope::{UnelidableRscope, RegionScope, SpecificRscope,
+                             ShiftedRscope, BindingRscope};
 use middle::typeck::rscope;
 use middle::typeck::TypeAndSubsts;
-use middle::typeck;
 use util::nodemap::DefIdMap;
 use util::ppaux::{Repr, UserString};
 
@@ -414,6 +413,16 @@ fn convert_parenthesized_parameters<'tcx,AC>(this: &AC,
     vec![input_ty, output]
 }
 
+pub fn instantiate_poly_trait_ref<'tcx,AC,RS>(
+    this: &AC,
+    rscope: &RS,
+    ast_trait_ref: &ast::PolyTraitRef,
+    self_ty: Option<ty::t>,
+    associated_type: Option<ty::t>)
+    -> Rc<ty::TraitRef>
+    where AC: AstConv<'tcx>, RS: RegionScope
+{
+    instantiate_trait_ref(this, rscope, &ast_trait_ref.trait_ref, self_ty, associated_type)
 }
 
 pub fn instantiate_trait_ref<'tcx,AC,RS>(this: &AC,
@@ -434,16 +443,9 @@ pub fn instantiate_trait_ref<'tcx,AC,RS>(this: &AC,
     match lookup_def_tcx(this.tcx(),
                          ast_trait_ref.path.span,
                          ast_trait_ref.ref_id) {
-        def::DefTrait(trait_did) => {
-            let trait_ref =
-                Rc::new(ast_path_to_trait_ref(this,
-                                              rscope,
-                                              trait_did,
-                                              self_ty,
-                                              associated_type,
-                                              &ast_trait_ref.path,
-                                              ast_trait_ref.ref_id));
-
+        def::DefTrait(trait_def_id) => {
+            let trait_ref = Rc::new(ast_path_to_trait_ref(this, rscope, trait_def_id, self_ty,
+                                                          associated_type, &ast_trait_ref.path));
             this.tcx().trait_refs.borrow_mut().insert(ast_trait_ref.ref_id,
                                                       trait_ref.clone());
             trait_ref
@@ -456,28 +458,45 @@ pub fn instantiate_trait_ref<'tcx,AC,RS>(this: &AC,
     }
 }
 
-pub fn ast_path_to_trait_ref<'tcx,AC,RS>(this: &AC,
-                                         rscope: &RS,
-                                         trait_def_id: ast::DefId,
-                                         self_ty: Option<ty::t>,
-                                         associated_type: Option<ty::t>,
-                                         path: &ast::Path,
-                                         binder_id: ast::NodeId)
-                                         -> ty::TraitRef
-                                         where AC: AstConv<'tcx>,
-                                               RS: RegionScope {
+fn ast_path_to_trait_ref<'tcx,AC,RS>(
+    this: &AC,
+    rscope: &RS,
+    trait_def_id: ast::DefId,
+    self_ty: Option<ty::t>,
+    associated_type: Option<ty::t>,
+    path: &ast::Path)
+    -> ty::TraitRef
+    where AC: AstConv<'tcx>, RS: RegionScope
+{
     let trait_def = this.get_trait_def(trait_def_id);
-    ty::TraitRef {
-        def_id: trait_def_id,
-        substs: ast_path_substs(this,
-                                rscope,
-                                trait_def_id,
-                                &trait_def.generics,
-                                self_ty,
-                                associated_type,
-                                path,
-                                binder_id)
-    }
+
+    // the trait reference introduces a binding level here, so
+    // we need to shift the `rscope`. It'd be nice if we could
+    // do away with this rscope stuff and work this knowledge
+    // into resolve_lifetimes, as we do with non-omitted
+    // lifetimes. Oh well, not there yet.
+    let shifted_rscope = ShiftedRscope::new(rscope);
+
+    let (regions, types) = match path.segments.last().unwrap().parameters {
+        ast::AngleBracketedParameters(ref data) => {
+            convert_angle_bracketed_parameters(this, &shifted_rscope, data)
+        }
+        ast::ParenthesizedParameters(ref data) => {
+            (Vec::new(), convert_parenthesized_parameters(this, data))
+        }
+    };
+
+    let substs = create_substs_for_ast_path(this,
+                                            &shifted_rscope,
+                                            path.span,
+                                            trait_def_id,
+                                            &trait_def.generics,
+                                            self_ty,
+                                            types,
+                                            regions,
+                                            associated_type);
+
+    ty::TraitRef::new(trait_def_id, substs)
 }
 
 pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
@@ -923,9 +942,9 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
                                                              ast_ty.span,
                                                              &[Rc::new(result.clone())],
                                                              ast_bounds);
-                        ty::mk_trait(tcx,
-                                     result,
-                                     bounds)
+                        let result_ty = ty::mk_trait(tcx, result, bounds);
+                        debug!("ast_ty_to_ty: result_ty={}", result_ty.repr(this.tcx()));
+                        result_ty
                     }
                     def::DefTy(did, _) | def::DefStruct(did) => {
                         ast_path_to_ty(this, rscope, did, path).ty
@@ -1562,7 +1581,7 @@ fn compute_region_bound<'tcx, AC: AstConv<'tcx>, RS:RegionScope>(
 
 pub struct PartitionedBounds<'a> {
     pub builtin_bounds: ty::BuiltinBounds,
-    pub trait_bounds: Vec<&'a ast::TraitRef>,
+    pub trait_bounds: Vec<&'a ast::PolyTraitRef>,
     pub region_bounds: Vec<&'a ast::Lifetime>,
 }
 
@@ -1584,8 +1603,7 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
     for &ast_bound in ast_bounds.iter() {
         match *ast_bound {
             ast::TraitTyParamBound(ref b) => {
-                let b = &b.trait_ref; // FIXME
-                match lookup_def_tcx(tcx, b.path.span, b.ref_id) {
+                match lookup_def_tcx(tcx, b.trait_ref.path.span, b.trait_ref.ref_id) {
                     def::DefTrait(trait_did) => {
                         match trait_def_ids.get(&trait_did) {
                             // Already seen this trait. We forbid
@@ -1593,10 +1611,10 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
                             // reason).
                             Some(span) => {
                                 span_err!(
-                                    tcx.sess, b.path.span, E0127,
+                                    tcx.sess, b.trait_ref.path.span, E0127,
                                     "trait `{}` already appears in the \
                                      list of bounds",
-                                    b.path.user_string(tcx));
+                                    b.trait_ref.path.user_string(tcx));
                                 tcx.sess.span_note(
                                     *span,
                                     "previous appearance is here");
@@ -1607,7 +1625,7 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
                             None => { }
                         }
 
-                        trait_def_ids.insert(trait_did, b.path.span);
+                        trait_def_ids.insert(trait_did, b.trait_ref.path.span);
 
                         if ty::try_add_builtin_trait(tcx,
                                                      trait_did,
index 3f90f59247393f01143442b0df82ed4e7a4568e4..55ed6720dba690be760f2ca4c1a3f0e4908a0a89 100644 (file)
@@ -2006,12 +2006,12 @@ fn conv_param_bounds<'tcx,AC>(this: &AC,
         astconv::partition_bounds(this.tcx(), span, all_bounds.as_slice());
     let trait_bounds: Vec<Rc<ty::TraitRef>> =
         trait_bounds.into_iter()
-        .map(|b| {
-            astconv::instantiate_trait_ref(this,
-                                           &ExplicitRscope,
-                                           b,
-                                           Some(param_ty.to_ty(this.tcx())),
-                                           Some(param_ty.to_ty(this.tcx())))
+        .map(|bound| {
+            astconv::instantiate_poly_trait_ref(this,
+                                                &ExplicitRscope,
+                                                bound,
+                                                Some(param_ty.to_ty(this.tcx())),
+                                                Some(param_ty.to_ty(this.tcx())))
         })
         .collect();
     let region_bounds: Vec<ty::Region> =
index f0d480c719a9bdeb047db015681f0978a961bee9..0f9554cd417f7fa8ae46555902650a93176541e2 100644 (file)
@@ -59,6 +59,7 @@
 
 pub trait Combine<'tcx> {
     fn infcx<'a>(&'a self) -> &'a InferCtxt<'a, 'tcx>;
+    fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.infcx().tcx }
     fn tag(&self) -> String;
     fn a_is_expected(&self) -> bool;
     fn trace(&self) -> TypeTrace;
@@ -296,26 +297,14 @@ fn trait_stores(&self,
                 Err(ty::terr_trait_stores_differ(vk, expected_found(self, a, b)))
             }
         }
-
     }
 
     fn trait_refs(&self,
                   a: &ty::TraitRef,
                   b: &ty::TraitRef)
-                  -> cres<ty::TraitRef> {
-        // Different traits cannot be related
-
-        // - NOTE in the future, expand out subtraits!
-
-        if a.def_id != b.def_id {
-            Err(ty::terr_traits(
-                                expected_found(self, a.def_id, b.def_id)))
-        } else {
-            let substs = try!(self.substs(a.def_id, &a.substs, &b.substs));
-            Ok(ty::TraitRef { def_id: a.def_id,
-                              substs: substs })
-        }
-    }
+                  -> cres<ty::TraitRef>;
+    // this must be overridden to do correctly, so as to account for higher-ranked
+    // behavior
 }
 
 #[deriving(Clone)]
index 97453dc86efd442ed6fe769fedf33fd721212d07..3874f5fc5e4aaa2ca4fb0e7386513fa08c661c7b 100644 (file)
@@ -137,4 +137,9 @@ fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
         try!(self.sub().fn_sigs(a, b));
         self.sub().fn_sigs(b, a)
     }
+
+    fn trait_refs(&self, a: &ty::TraitRef, b: &ty::TraitRef) -> cres<ty::TraitRef> {
+        try!(self.sub().trait_refs(a, b));
+        self.sub().trait_refs(b, a)
+    }
 }
index 5dbcaadf0df67283b9f0612c0f3da15ed9ca50d1..f7e6cef99af93660c4521a97c96e18aa8e66560f 100644 (file)
  * a lattice.
  */
 
-use middle::ty::{RegionVid, TyVar};
+use middle::ty::{TyVar};
 use middle::ty;
 use middle::typeck::infer::*;
 use middle::typeck::infer::combine::*;
 use middle::typeck::infer::glb::Glb;
 use middle::typeck::infer::lub::Lub;
-use util::nodemap::FnvHashMap;
 use util::ppaux::Repr;
 
 pub trait LatticeDir {
@@ -101,27 +100,3 @@ pub fn super_lattice_tys<'tcx, L:LatticeDir+Combine<'tcx>>(this: &L,
         }
     }
 }
-
-///////////////////////////////////////////////////////////////////////////
-// Random utility functions used by LUB/GLB when computing LUB/GLB of
-// fn types
-
-pub fn var_ids<'tcx, T: Combine<'tcx>>(this: &T,
-                                       map: &FnvHashMap<ty::BoundRegion, ty::Region>)
-                                       -> Vec<RegionVid> {
-    map.iter().map(|(_, r)| match *r {
-            ty::ReInfer(ty::ReVar(r)) => { r }
-            r => {
-                this.infcx().tcx.sess.span_bug(
-                    this.trace().origin.span(),
-                    format!("found non-region-vid: {}", r).as_slice());
-            }
-        }).collect()
-}
-
-pub fn is_var_in_set(new_vars: &[RegionVid], r: ty::Region) -> bool {
-    match r {
-        ty::ReInfer(ty::ReVar(ref v)) => new_vars.iter().any(|x| x == v),
-        _ => false
-    }
-}
index 492ac5e92d3cf97777a1c5e5754cd8cb5eaadffb..8856f42d1f5ab6d0fa5366a95dc409193012f58a 100644 (file)
@@ -47,7 +47,7 @@ fn lub<'a>(&'a self) -> Lub<'a, 'tcx> { Lub(self.fields.clone()) }
     fn glb<'a>(&'a self) -> Glb<'a, 'tcx> { Glb(self.fields.clone()) }
 
     fn mts(&self, a: &ty::mt, b: &ty::mt) -> cres<ty::mt> {
-        let tcx = self.fields.infcx.tcx;
+        let tcx = self.tcx();
 
         debug!("{}.mts({}, {})",
                self.tag(),
@@ -107,10 +107,10 @@ fn contraregions(&self, a: ty::Region, b: ty::Region)
     fn regions(&self, a: ty::Region, b: ty::Region) -> cres<ty::Region> {
         debug!("{}.regions({}, {})",
                self.tag(),
-               a.repr(self.fields.infcx.tcx),
-               b.repr(self.fields.infcx.tcx));
+               a.repr(self.tcx()),
+               b.repr(self.tcx()));
 
-        Ok(self.fields.infcx.region_vars.lub_regions(Subtype(self.trace()), a, b))
+        Ok(self.infcx().region_vars.lub_regions(Subtype(self.trace()), a, b))
     }
 
     fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
@@ -120,4 +120,8 @@ fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
     fn tys(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
         super_lattice_tys(self, a, b)
     }
+
+    fn trait_refs(&self, a: &ty::TraitRef, b: &ty::TraitRef) -> cres<ty::TraitRef> {
+        self.higher_ranked_lub(a, b)
+    }
 }
index 6f75192e6019d750be432da354d7b6d56cb9d0d1..b4689ae098c98ef11814c267c59130fc0fee97a7 100644 (file)
 use middle::subst;
 use middle::subst::Substs;
 use middle::ty::{TyVid, IntVid, FloatVid, RegionVid};
+use middle::ty::replace_late_bound_regions;
 use middle::ty;
-use middle::ty_fold;
-use middle::ty_fold::{TypeFolder, TypeFoldable};
-use middle::typeck::check::regionmanip::replace_late_bound_regions;
+use middle::ty_fold::{HigherRankedFoldable, TypeFolder, TypeFoldable};
 use std::cell::{RefCell};
 use std::rc::Rc;
 use syntax::ast;
@@ -816,8 +815,8 @@ pub fn tys_to_string(&self, ts: &[ty::t]) -> String {
         format!("({})", tstrs.connect(", "))
     }
 
-    pub fn trait_ref_to_string(&self, t: &ty::TraitRef) -> String {
-        let t = self.resolve_type_vars_in_trait_ref_if_possible(t);
+    pub fn trait_ref_to_string(&self, t: &Rc<ty::TraitRef>) -> String {
+        let t = self.resolve_type_vars_in_trait_ref_if_possible(&**t);
         trait_ref_to_string(self.tcx, &t)
     }
 
index f3df33f7b0e6d953ccce5ea102f4a007b84c2e97..f85cb85ff21a231c0e64c1d9d46c0ffaf5ed1aab 100644 (file)
@@ -63,16 +63,16 @@ fn contraregions(&self, a: ty::Region, b: ty::Region)
     fn regions(&self, a: ty::Region, b: ty::Region) -> cres<ty::Region> {
         debug!("{}.regions({}, {})",
                self.tag(),
-               a.repr(self.fields.infcx.tcx),
-               b.repr(self.fields.infcx.tcx));
-        self.fields.infcx.region_vars.make_subregion(Subtype(self.trace()), a, b);
+               a.repr(self.tcx()),
+               b.repr(self.tcx()));
+        self.infcx().region_vars.make_subregion(Subtype(self.trace()), a, b);
         Ok(a)
     }
 
     fn mts(&self, a: &ty::mt, b: &ty::mt) -> cres<ty::mt> {
         debug!("mts({} <: {})",
-               a.repr(self.fields.infcx.tcx),
-               b.repr(self.fields.infcx.tcx));
+               a.repr(self.tcx()),
+               b.repr(self.tcx()));
 
         if a.mutbl != b.mutbl {
             return Err(ty::terr_mutability);
@@ -121,7 +121,7 @@ fn builtin_bounds(&self, a: BuiltinBounds, b: BuiltinBounds)
 
     fn tys(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
         debug!("{}.tys({}, {})", self.tag(),
-               a.repr(self.fields.infcx.tcx), b.repr(self.fields.infcx.tcx));
+               a.repr(self.tcx()), b.repr(self.tcx()));
         if a == b { return Ok(a); }
 
         let infcx = self.fields.infcx;
@@ -158,5 +158,9 @@ fn tys(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
     fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
         self.higher_ranked_sub(a, b)
     }
+
+    fn trait_refs(&self, a: &ty::TraitRef, b: &ty::TraitRef) -> cres<ty::TraitRef> {
+        self.higher_ranked_sub(a, b)
+    }
 }
 
index 745c76eb77f581831c47ab3aa0952705487a8b75..2f72d3cf50db1853dc64d35b903f313849f3d581 100644 (file)
@@ -10,9 +10,9 @@
 
 
 use middle::ty;
+use middle::ty_fold;
 
 use std::cell::Cell;
-use syntax::ast;
 use syntax::codemap::Span;
 
 /// Defines strategies for handling regions that are omitted.  For
@@ -136,3 +136,40 @@ fn anon_regions(&self,
     }
 }
 
+/// A scope which simply shifts the Debruijn index of other scopes
+/// to account for binding levels.
+pub struct ShiftedRscope<'r> {
+    base_scope: &'r RegionScope+'r
+}
+
+impl<'r> ShiftedRscope<'r> {
+    pub fn new(base_scope: &'r RegionScope+'r) -> ShiftedRscope<'r> {
+        ShiftedRscope { base_scope: base_scope }
+    }
+}
+
+impl<'r> RegionScope for ShiftedRscope<'r> {
+    fn default_region_bound(&self, span: Span) -> Option<ty::Region>
+    {
+        self.base_scope.default_region_bound(span)
+            .map(|r| ty_fold::shift_region(r, 1))
+    }
+
+    fn anon_regions(&self,
+                    span: Span,
+                    count: uint)
+                    -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>>
+    {
+        match self.base_scope.anon_regions(span, count) {
+            Ok(mut v) => {
+                for r in v.iter_mut() {
+                    *r = ty_fold::shift_region(*r, 1);
+                }
+                Ok(v)
+            }
+            Err(errs) => {
+                Err(errs)
+            }
+        }
+    }
+}
index ca70a37bf3d218a8b7bb075272ca30a9fce8699d..a0e2bf07b830f94dc505173126b74530ac4959e5 100644 (file)
@@ -385,7 +385,7 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
     syntax::ext::mtwt::clear_tables();
 
     let named_region_map = time(time_passes, "lifetime resolution", (),
-                                |_| middle::resolve_lifetime::krate(&sess, krate));
+                                |_| middle::resolve_lifetime::krate(&sess, krate, &def_map));
 
     time(time_passes, "looking for entry point", (),
          |_| middle::entry::find_entry_point(&sess, &ast_map));