]> git.lizzy.rs Git - rust.git/commitdiff
Implement "perfect forwarding" for HR impls (#19730).
authorNiko Matsakis <niko@alum.mit.edu>
Sun, 14 Dec 2014 12:17:23 +0000 (07:17 -0500)
committerNiko Matsakis <niko@alum.mit.edu>
Fri, 19 Dec 2014 08:29:31 +0000 (03:29 -0500)
38 files changed:
src/librustc/lint/builtin.rs
src/librustc/metadata/csearch.rs
src/librustc/metadata/decoder.rs
src/librustc/middle/astencode.rs
src/librustc/middle/dead.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/infer/error_reporting.rs
src/librustc/middle/infer/higher_ranked/mod.rs
src/librustc/middle/infer/mod.rs
src/librustc/middle/privacy.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/middle/traits/coherence.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_trans/save/mod.rs
src/librustc_trans/trans/callee.rs
src/librustc_trans/trans/meth.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/method/confirm.rs
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/wf.rs
src/librustc_typeck/coherence/mod.rs
src/librustc_typeck/coherence/unsafety.rs
src/librustc_typeck/collect.rs
src/librustdoc/clean/inline.rs
src/test/compile-fail/hrtb-conflate-regions.rs [new file with mode: 0644]
src/test/compile-fail/hrtb-just-for-static.rs [new file with mode: 0644]
src/test/compile-fail/hrtb-perfect-forwarding.rs [new file with mode: 0644]
src/test/compile-fail/hrtb-type-outlives.rs [new file with mode: 0644]
src/test/compile-fail/issue-14366.rs
src/test/compile-fail/kindck-inherited-copy-bound.rs
src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs
src/test/compile-fail/unboxed-closures-wrong-abi.rs
src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs

index ca8eee847d3f9352af5607dd007dd77961c79ccd..f6fd9f60e5c3f666337675029dce02d35d10cb8c 100644 (file)
@@ -1784,9 +1784,7 @@ fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
                                 method_num: index,
                                 ..
                             }) => {
-                                ty::trait_item(cx.tcx,
-                                               trait_ref.def_id(),
-                                               index).def_id()
+                                ty::trait_item(cx.tcx, trait_ref.def_id, index).def_id()
                             }
                         }
                     }
index 1a1c810b2781410d7d0ae70985e696d7dbfb969c..4cbb1babf9a2cbf8e9b5bc01790a8b14e78f440d 100644 (file)
@@ -262,7 +262,7 @@ pub fn get_field_type<'tcx>(tcx: &ty::ctxt<'tcx>, class_id: ast::DefId,
 // if there is one.
 pub fn get_impl_trait<'tcx>(tcx: &ty::ctxt<'tcx>,
                             def: ast::DefId)
-                            -> Option<Rc<ty::PolyTraitRef<'tcx>>> {
+                            -> Option<Rc<ty::TraitRef<'tcx>>> {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
     decoder::get_impl_trait(&*cdata, def.node, tcx)
index 0625c50d6721f4910b7482f83c7fbcdf2174052b..7f1df80da3c8fa9dcdf94f1cf1086a529673e8d9 100644 (file)
@@ -425,11 +425,11 @@ pub fn get_repr_attrs(cdata: Cmd, id: ast::NodeId) -> Vec<attr::ReprAttr> {
 pub fn get_impl_trait<'tcx>(cdata: Cmd,
                             id: ast::NodeId,
                             tcx: &ty::ctxt<'tcx>)
-                            -> Option<Rc<ty::PolyTraitRef<'tcx>>>
+                            -> Option<Rc<ty::TraitRef<'tcx>>>
 {
     let item_doc = lookup_item(id, cdata.data());
     reader::maybe_get_doc(item_doc, tag_item_trait_ref).map(|tp| {
-        Rc::new(ty::Binder(doc_trait_ref(tp, tcx, cdata)))
+        Rc::new(doc_trait_ref(tp, tcx, cdata))
     })
 }
 
index 0021533a2bbe6f914e69388e57ccbad943083346..69fbd59fd924142ae2dd9d26d33515b8a098aab4 100644 (file)
@@ -887,7 +887,7 @@ fn emit_method_origin<'b>(&mut self,
                     this.emit_enum_variant("MethodTypeParam", 2, 1, |this| {
                         this.emit_struct("MethodParam", 2, |this| {
                             try!(this.emit_struct_field("trait_ref", 0, |this| {
-                                Ok(this.emit_trait_ref(ecx, &p.trait_ref.0))
+                                Ok(this.emit_trait_ref(ecx, &*p.trait_ref))
                             }));
                             try!(this.emit_struct_field("method_num", 0, |this| {
                                 this.emit_uint(p.method_num)
@@ -901,7 +901,7 @@ fn emit_method_origin<'b>(&mut self,
                     this.emit_enum_variant("MethodTraitObject", 3, 1, |this| {
                         this.emit_struct("MethodObject", 2, |this| {
                             try!(this.emit_struct_field("trait_ref", 0, |this| {
-                                Ok(this.emit_trait_ref(ecx, &o.trait_ref.0))
+                                Ok(this.emit_trait_ref(ecx, &*o.trait_ref))
                             }));
                             try!(this.emit_struct_field("object_trait_id", 0, |this| {
                                 Ok(this.emit_def_id(o.object_trait_id))
@@ -1457,7 +1457,7 @@ fn read_method_origin<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
                                 ty::MethodParam {
                                     trait_ref: {
                                         this.read_struct_field("trait_ref", 0, |this| {
-                                            Ok(this.read_poly_trait_ref(dcx))
+                                            Ok(this.read_trait_ref(dcx))
                                         }).unwrap()
                                     },
                                     method_num: {
@@ -1475,7 +1475,7 @@ fn read_method_origin<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
                                 ty::MethodObject {
                                     trait_ref: {
                                         this.read_struct_field("trait_ref", 0, |this| {
-                                            Ok(this.read_poly_trait_ref(dcx))
+                                            Ok(this.read_trait_ref(dcx))
                                         }).unwrap()
                                     },
                                     object_trait_id: {
index 46c4de5c35ed0286dcb8a052f73407bc5dddfb68..939775e7507130eeec8b011f904d370eb5beb696 100644 (file)
@@ -112,7 +112,7 @@ fn lookup_and_handle_method(&mut self, id: ast::NodeId,
                         ..
                     }) => {
                         let trait_item = ty::trait_item(self.tcx,
-                                                        trait_ref.def_id(),
+                                                        trait_ref.def_id,
                                                         index);
                         match trait_item {
                             ty::MethodTraitItem(method) => {
index 8b0df4e69cd8e61c91643c0501956ecaa0f7dc8b..901944cd0168e2b0d90c8285f7d95e6291c252f2 100644 (file)
@@ -265,7 +265,7 @@ fn from_method_id(tcx: &ty::ctxt, method_id: ast::DefId)
             }
             Some(ref trait_ref) => (*trait_ref).clone(),
         };
-        OverloadedCallType::from_trait_id(tcx, trait_ref.def_id())
+        OverloadedCallType::from_trait_id(tcx, trait_ref.def_id)
     }
 
     fn from_unboxed_closure(tcx: &ty::ctxt, closure_did: ast::DefId)
@@ -292,7 +292,7 @@ fn from_method_origin(tcx: &ty::ctxt, origin: &MethodOrigin)
             }
             MethodTypeParam(MethodParam { ref trait_ref, .. }) |
             MethodTraitObject(MethodObject { ref trait_ref, .. }) => {
-                OverloadedCallType::from_trait_id(tcx, trait_ref.def_id())
+                OverloadedCallType::from_trait_id(tcx, trait_ref.def_id)
             }
         }
     }
index d1253e0b6976bbfb79328be4dc97de5766ecf271..b4c1c0b396b64ceb15284e4662ca500b36be8fac 100644 (file)
@@ -395,7 +395,8 @@ fn report_and_explain_type_error(&self,
     fn values_str(&self, values: &ValuePairs<'tcx>) -> Option<String> {
         match *values {
             infer::Types(ref exp_found) => self.expected_found_str(exp_found),
-            infer::TraitRefs(ref exp_found) => self.expected_found_str(exp_found)
+            infer::TraitRefs(ref exp_found) => self.expected_found_str(exp_found),
+            infer::PolyTraitRefs(ref exp_found) => self.expected_found_str(exp_found)
         }
     }
 
@@ -1647,6 +1648,16 @@ fn contains_error(&self) -> bool {
     }
 }
 
+impl<'tcx> Resolvable<'tcx> for Rc<ty::TraitRef<'tcx>> {
+    fn resolve<'a>(&self, infcx: &InferCtxt<'a, 'tcx>)
+                   -> Rc<ty::TraitRef<'tcx>> {
+        Rc::new(infcx.resolve_type_vars_if_possible(&**self))
+    }
+    fn contains_error(&self) -> bool {
+        ty::trait_ref_contains_error(&**self)
+    }
+}
+
 impl<'tcx> Resolvable<'tcx> for Rc<ty::PolyTraitRef<'tcx>> {
     fn resolve<'a>(&self, infcx: &InferCtxt<'a, 'tcx>)
                    -> Rc<ty::PolyTraitRef<'tcx>> {
index 3a84890de4f4baa6b5b5928bb5955be2dc25a71b..ab0f98ec74a7fe9e8e0bdf4f1973081840f5f466 100644 (file)
@@ -219,7 +219,7 @@ fn higher_ranked_glb<T>(&self, a: &Binder<T>, b: &Binder<T>) -> cres<'tcx, Binde
                 self.infcx().resolve_type_vars_if_possible(&result0);
             debug!("glb result0 = {}", result0.repr(self.tcx()));
 
-            // Generalize the regions appearing in fn_ty0 if possible
+            // Generalize the regions appearing in result0 if possible
             let new_vars = self.infcx().region_vars_confined_to_snapshot(snapshot);
             let span = self.trace().origin.span();
             let result1 =
@@ -358,7 +358,7 @@ fn fold_regions_in<'tcx, T, F>(tcx: &ty::ctxt<'tcx>,
     where T : Combineable<'tcx>,
           F : FnMut(ty::Region, ty::DebruijnIndex) -> ty::Region,
 {
-    unbound_value.fold_with(&mut ty_fold::RegionFolder::new(tcx, |region, current_depth| {
+    unbound_value.fold_with(&mut ty_fold::RegionFolder::new(tcx, &mut |region, current_depth| {
         // we should only be encountering "escaping" late-bound regions here,
         // because the ones at the current level should have been replaced
         // with fresh variables
@@ -414,11 +414,11 @@ fn region_vars_confined_to_snapshot(&self,
          *
          * The reason is that when we walk through the subtyping
          * algorith, we begin by replacing `'a` with a skolemized
-         * variable `'0`. We then have `fn(_#0t) <: fn(&'0 int)`. This
-         * can be made true by unifying `_#0t` with `&'0 int`. In the
+         * variable `'1`. We then have `fn(_#0t) <: fn(&'1 int)`. This
+         * can be made true by unifying `_#0t` with `&'1 int`. In the
          * process, we create a fresh variable for the skolemized
-         * region, `'$0`, and hence we have that `_#0t == &'$0
-         * int`. However, because `'$0` was created during the sub
+         * region, `'$2`, and hence we have that `_#0t == &'$2
+         * int`. However, because `'$2` was created during the sub
          * computation, if we're not careful we will erroneously
          * assume it is one of the transient region variables
          * representing a lub/glb internally. Not good.
@@ -522,3 +522,93 @@ pub fn leak_check<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
     }
     Ok(())
 }
+
+/// This code converts from skolemized regions back to late-bound
+/// regions. It works by replacing each region in the taint set of a
+/// skolemized region with a bound-region. The bound region will be bound
+/// by the outer-most binder in `value`; the caller must ensure that there is
+/// such a binder and it is the right place.
+///
+/// This routine is only intended to be used when the leak-check has
+/// passed; currently, it's used in the trait matching code to create
+/// a set of nested obligations frmo an impl that matches against
+/// something higher-ranked.  More details can be found in
+/// `middle::traits::doc.rs`.
+///
+/// As a brief example, consider the obligation `for<'a> Fn(&'a int)
+/// -> &'a int`, and the impl:
+///
+///     impl<A,R> Fn<A,R> for SomethingOrOther
+///         where A : Clone
+///     { ... }
+///
+/// Here we will have replaced `'a` with a skolemized region
+/// `'0`. This means that our substitution will be `{A=>&'0
+/// int, R=>&'0 int}`.
+///
+/// When we apply the substitution to the bounds, we will wind up with
+/// `&'0 int : Clone` as a predicate. As a last step, we then go and
+/// replace `'0` with a late-bound region `'a`.  The depth is matched
+/// to the depth of the predicate, in this case 1, so that the final
+/// predicate is `for<'a> &'a int : Clone`.
+pub fn plug_leaks<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
+                             skol_map: SkolemizationMap,
+                             snapshot: &CombinedSnapshot,
+                             value: &T)
+                             -> T
+    where T : TypeFoldable<'tcx> + Repr<'tcx>
+{
+    debug_assert!(leak_check(infcx, &skol_map, snapshot).is_ok());
+
+    debug!("plug_leaks(skol_map={}, value={})",
+           skol_map.repr(infcx.tcx),
+           value.repr(infcx.tcx));
+
+    // Compute a mapping from the "taint set" of each skolemized
+    // region back to the `ty::BoundRegion` that it originally
+    // represented. Because `leak_check` passed, we know that that
+    // these taint sets are mutually disjoint.
+    let inv_skol_map: FnvHashMap<ty::Region, ty::BoundRegion> =
+        skol_map
+        .into_iter()
+        .flat_map(|(skol_br, skol)| {
+            infcx.tainted_regions(snapshot, skol)
+                .into_iter()
+                .map(move |tainted_region| (tainted_region, skol_br))
+        })
+        .collect();
+
+    debug!("plug_leaks: inv_skol_map={}",
+           inv_skol_map.repr(infcx.tcx));
+
+    // Remove any instantiated type variables from `value`; those can hide
+    // references to regions from the `fold_regions` code below.
+    let value = infcx.resolve_type_vars_if_possible(value);
+
+    // Map any skolemization byproducts back to a late-bound
+    // region. Put that late-bound region at whatever the outermost
+    // binder is that we encountered in `value`. The caller is
+    // responsible for ensuring that (a) `value` contains at least one
+    // binder and (b) that binder is the one we want to use.
+    let result = ty_fold::fold_regions(infcx.tcx, &value, |r, current_depth| {
+        match inv_skol_map.get(&r) {
+            None => r,
+            Some(br) => {
+                // It is the responsibility of the caller to ensure
+                // that each skolemized region appears within a
+                // binder. In practice, this routine is only used by
+                // trait checking, and all of the skolemized regions
+                // appear inside predicates, which always have
+                // binders, so this assert is satisfied.
+                assert!(current_depth > 1);
+
+                ty::ReLateBound(ty::DebruijnIndex::new(current_depth - 1), br.clone())
+            }
+        }
+    });
+
+    debug!("plug_leaks: result={}",
+           result.repr(infcx.tcx));
+
+    result
+}
index 29021c0cca6b9a8f3b0a993080dc6dd0ea112037..f419f050cf5943f9b3d4cde20a1bac5809c4d93b 100644 (file)
@@ -137,7 +137,8 @@ impl Copy for TypeOrigin {}
 #[deriving(Clone, Show)]
 pub enum ValuePairs<'tcx> {
     Types(ty::expected_found<Ty<'tcx>>),
-    TraitRefs(ty::expected_found<Rc<ty::PolyTraitRef<'tcx>>>),
+    TraitRefs(ty::expected_found<Rc<ty::TraitRef<'tcx>>>),
+    PolyTraitRefs(ty::expected_found<Rc<ty::PolyTraitRef<'tcx>>>),
 }
 
 /// The trace designates the path through inference that we took to
@@ -349,7 +350,7 @@ pub fn can_mk_subty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
                               b: Ty<'tcx>)
                               -> ures<'tcx> {
     debug!("can_mk_subty({} <: {})", a.repr(cx.tcx), b.repr(cx.tcx));
-    cx.probe(|| {
+    cx.probe(|_| {
         let trace = TypeTrace {
             origin: Misc(codemap::DUMMY_SP),
             values: Types(expected_found(true, a, b))
@@ -362,7 +363,7 @@ pub fn can_mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
                              a: Ty<'tcx>, b: Ty<'tcx>)
                              -> ures<'tcx> {
     debug!("can_mk_subty({} <: {})", a.repr(cx.tcx), b.repr(cx.tcx));
-    cx.probe(|| {
+    cx.probe(|_| {
         let trace = TypeTrace {
             origin: Misc(codemap::DUMMY_SP),
             values: Types(expected_found(true, a, b))
@@ -634,11 +635,11 @@ pub fn try<T, E, F>(&self, f: F) -> Result<T, E> where
 
     /// Execute `f` then unroll any bindings it creates
     pub fn probe<R, F>(&self, f: F) -> R where
-        F: FnOnce() -> R,
+        F: FnOnce(&CombinedSnapshot) -> R,
     {
         debug!("probe()");
         let snapshot = self.start_snapshot();
-        let r = f();
+        let r = f(&snapshot);
         self.rollback_to(snapshot);
         r
     }
@@ -683,6 +684,25 @@ pub fn eq_types(&self,
         })
     }
 
+    pub fn sub_trait_refs(&self,
+                          a_is_expected: bool,
+                          origin: TypeOrigin,
+                          a: Rc<ty::TraitRef<'tcx>>,
+                          b: Rc<ty::TraitRef<'tcx>>)
+                          -> ures<'tcx>
+    {
+        debug!("sub_trait_refs({} <: {})",
+               a.repr(self.tcx),
+               b.repr(self.tcx));
+        self.commit_if_ok(|| {
+            let trace = TypeTrace {
+                origin: origin,
+                values: TraitRefs(expected_found(a_is_expected, a.clone(), b.clone()))
+            };
+            self.sub(a_is_expected, trace).trait_refs(&*a, &*b).to_ures()
+        })
+    }
+
     pub fn sub_poly_trait_refs(&self,
                                a_is_expected: bool,
                                origin: TypeOrigin,
@@ -690,14 +710,13 @@ pub fn sub_poly_trait_refs(&self,
                                b: Rc<ty::PolyTraitRef<'tcx>>)
                                -> ures<'tcx>
     {
-        debug!("sub_trait_refs({} <: {})",
+        debug!("sub_poly_trait_refs({} <: {})",
                a.repr(self.tcx),
                b.repr(self.tcx));
         self.commit_if_ok(|| {
             let trace = TypeTrace {
                 origin: origin,
-                values: TraitRefs(expected_found(a_is_expected,
-                                                 a.clone(), b.clone()))
+                values: PolyTraitRefs(expected_found(a_is_expected, a.clone(), b.clone()))
             };
             self.sub(a_is_expected, trace).binders(&*a, &*b).to_ures()
         })
@@ -727,6 +746,18 @@ pub fn leak_check(&self,
         }
     }
 
+    pub fn plug_leaks<T>(&self,
+                         skol_map: SkolemizationMap,
+                         snapshot: &CombinedSnapshot,
+                         value: &T)
+                         -> T
+        where T : TypeFoldable<'tcx> + Repr<'tcx>
+    {
+        /*! See `higher_ranked::leak_check` */
+
+        higher_ranked::plug_leaks(self, skol_map, snapshot, value)
+    }
+
     pub fn equality_predicate(&self,
                               span: Span,
                               predicate: &ty::PolyEquatePredicate<'tcx>)
index 67e9d2fee58f48a516e59100381176f536a4d8a6..8cce1321d728bdc7b9ae770f35cd219b01aaf0c9 100644 (file)
@@ -257,8 +257,8 @@ fn visit_item(&mut self, item: &ast::Item) {
                 };
                 let tr = ty::impl_trait_ref(self.tcx, local_def(item.id));
                 let public_trait = tr.clone().map_or(false, |tr| {
-                    !is_local(tr.def_id()) ||
-                     self.exported_items.contains(&tr.def_id().node)
+                    !is_local(tr.def_id) ||
+                     self.exported_items.contains(&tr.def_id.node)
                 });
 
                 if public_ty || public_trait {
@@ -407,7 +407,7 @@ fn def_privacy(&self, did: ast::DefId) -> PrivacyResult {
                             match ty::impl_trait_ref(self.tcx, id) {
                                 Some(t) => {
                                     debug!("privacy - impl of trait {}", id);
-                                    self.def_privacy(t.def_id())
+                                    self.def_privacy(t.def_id)
                                 }
                                 None => {
                                     debug!("privacy - found a method {}",
@@ -432,7 +432,7 @@ fn def_privacy(&self, did: ast::DefId) -> PrivacyResult {
                             match ty::impl_trait_ref(self.tcx, id) {
                                 Some(t) => {
                                     debug!("privacy - impl of trait {}", id);
-                                    self.def_privacy(t.def_id())
+                                    self.def_privacy(t.def_id)
                                 }
                                 None => {
                                     debug!("privacy - found a typedef {}",
@@ -811,7 +811,7 @@ fn check_method(&mut self, span: Span, origin: &MethodOrigin,
             // is whether the trait itself is accessible or not.
             MethodTypeParam(MethodParam { ref trait_ref, .. }) |
             MethodTraitObject(MethodObject { ref trait_ref, .. }) => {
-                self.report_error(self.ensure_public(span, trait_ref.def_id(),
+                self.report_error(self.ensure_public(span, trait_ref.def_id,
                                                      None, "source trait"));
             }
         }
index 1923142be9e3fcb9b9de509dc50d7bb85d5ea3a1..33701905aa11098a68f963b355b728138c39d340 100644 (file)
@@ -108,7 +108,8 @@ fn visit_item(&mut self, item: &ast::Item) {
                 ast::ItemTy(_, ref generics) |
                 ast::ItemEnum(_, ref generics) |
                 ast::ItemStruct(_, ref generics) |
-                ast::ItemTrait(_, ref generics, _, _, _) => {
+                ast::ItemTrait(_, ref generics, _, _, _) |
+                ast::ItemImpl(_, ref generics, _, _, _) => {
                     // These kinds of items have only early bound lifetime parameters.
                     let lifetimes = &generics.lifetimes;
                     let early_scope = EarlyScope(subst::TypeSpace, lifetimes, &ROOT_SCOPE);
@@ -117,12 +118,6 @@ fn visit_item(&mut self, item: &ast::Item) {
                         visit::walk_item(this, item);
                     });
                 }
-                ast::ItemImpl(_, ref generics, _, _, _) => {
-                    // Impls have both early- and late-bound lifetimes.
-                    this.visit_early_late(subst::TypeSpace, generics, |this| {
-                        visit::walk_item(this, item);
-                    })
-                }
             }
         });
     }
index 3b759b042f2acd83b671bee6189052b7c3344f60..9804f6d222afde9513661697da44141411ac3ef0 100644 (file)
@@ -17,7 +17,7 @@
 use middle::subst;
 use middle::subst::Subst;
 use middle::ty::{mod, Ty};
-use middle::infer::{mod, InferCtxt};
+use middle::infer::InferCtxt;
 use std::rc::Rc;
 use syntax::ast;
 use syntax::codemap::DUMMY_SP;
@@ -38,12 +38,7 @@ pub fn impl_can_satisfy(infcx: &InferCtxt,
     let impl1_substs =
         util::fresh_substs_for_impl(infcx, DUMMY_SP, impl1_def_id);
     let impl1_trait_ref =
-        ty::impl_trait_ref(infcx.tcx, impl1_def_id).unwrap()
-                                                   .subst(infcx.tcx, &impl1_substs);
-    let impl1_trait_ref =
-        infcx.replace_late_bound_regions_with_fresh_var(DUMMY_SP,
-                                                        infer::FnCall,
-                                                        &*impl1_trait_ref).0;
+        (*ty::impl_trait_ref(infcx.tcx, impl1_def_id).unwrap()).subst(infcx.tcx, &impl1_substs);
 
     // Determine whether `impl2` can provide an implementation for those
     // same types.
@@ -67,15 +62,15 @@ pub fn impl_is_local(tcx: &ty::ctxt,
     debug!("trait_ref={}", trait_ref.repr(tcx));
 
     // If the trait is local to the crate, ok.
-    if trait_ref.def_id().krate == ast::LOCAL_CRATE {
+    if trait_ref.def_id.krate == ast::LOCAL_CRATE {
         debug!("trait {} is local to current crate",
-               trait_ref.def_id().repr(tcx));
+               trait_ref.def_id.repr(tcx));
         return true;
     }
 
     // Otherwise, at least one of the input types must be local to the
     // crate.
-    trait_ref.0.input_types().iter().any(|&t| ty_is_local(tcx, t))
+    trait_ref.input_types().iter().any(|&t| ty_is_local(tcx, t))
 }
 
 pub fn ty_is_local<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
index 32d9056f7b778ec212c6e70db74b8407b7ed8ed7..213d97b4b344aecd851b8bfa1bf6387e49fc891b 100644 (file)
@@ -360,10 +360,7 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
             // For now, we just check that there are no higher-ranked
             // regions.  If there are, we will call this obligation an
             // error. Eventually we should be able to support some
-            // cases here, I imagine (e.g., `for<'a> &'a int : 'a`).
-            //
-            // TODO This is overly conservative, but good enough for
-            // now.
+            // cases here, I imagine (e.g., `for<'a> int : 'a`).
             if ty::count_late_bound_regions(selcx.tcx(), binder) != 0 {
                 errors.push(
                     FulfillmentError::new(
index 0bda04237b631b187b8b8506c95c5e1ff46ef86d..6c7ae666ae06cdc9e80f1ce9dac1f36e9316d483 100644 (file)
@@ -289,7 +289,7 @@ fn evaluate_predicate_recursively<'o>(&mut self,
             }
 
             ty::Predicate::Equate(ref p) => {
-                let result = self.infcx.probe(|| {
+                let result = self.infcx.probe(|_| {
                     self.infcx.equality_predicate(obligation.cause.span, p)
                 });
                 match result {
@@ -410,13 +410,18 @@ pub fn evaluate_impl(&mut self,
                impl_def_id.repr(self.tcx()),
                obligation.repr(self.tcx()));
 
-        self.infcx.probe(|| {
-            match self.match_impl(impl_def_id, obligation) {
+        self.infcx.probe(|snapshot| {
+            let (skol_obligation_trait_ref, skol_map) =
+                self.infcx().skolemize_late_bound_regions(&*obligation.trait_ref, snapshot);
+            match self.match_impl(impl_def_id, obligation, snapshot,
+                                  &skol_map, Rc::new(skol_obligation_trait_ref)) {
                 Ok(substs) => {
                     let vtable_impl = self.vtable_impl(impl_def_id,
                                                        substs,
                                                        obligation.cause,
-                                                       obligation.recursion_depth + 1);
+                                                       obligation.recursion_depth + 1,
+                                                       skol_map,
+                                                       snapshot);
                     self.winnow_selection(None, VtableImpl(vtable_impl)).may_apply()
                 }
                 Err(()) => {
@@ -711,8 +716,7 @@ fn assemble_candidates_from_caller_bounds(&mut self,
         let matching_bounds =
             all_bounds.filter(
                 |bound| self.infcx.probe(
-                    || self.match_trait_refs(obligation,
-                                             (*bound).clone())).is_ok());
+                    |_| self.match_where_clause(obligation, bound.clone())).is_ok());
 
         let param_candidates =
             matching_bounds.map(
@@ -819,8 +823,11 @@ fn assemble_candidates_from_impls(&mut self,
     {
         let all_impls = self.all_impls(obligation.trait_ref.def_id());
         for &impl_def_id in all_impls.iter() {
-            self.infcx.probe(|| {
-                match self.match_impl(impl_def_id, obligation) {
+            self.infcx.probe(|snapshot| {
+                let (skol_obligation_trait_ref, skol_map) =
+                    self.infcx().skolemize_late_bound_regions(&*obligation.trait_ref, snapshot);
+                match self.match_impl(impl_def_id, obligation, snapshot,
+                                      &skol_map, Rc::new(skol_obligation_trait_ref)) {
                     Ok(_) => {
                         candidates.vec.push(ImplCandidate(impl_def_id));
                     }
@@ -848,15 +855,8 @@ fn winnow_candidate<'o>(&mut self,
                             candidate: &Candidate<'tcx>)
                             -> EvaluationResult<'tcx>
     {
-        /*!
-         * Further evaluate `candidate` to decide whether all type parameters match
-         * and whether nested obligations are met. Returns true if `candidate` remains
-         * viable after this further scrutiny.
-         */
-
-        debug!("winnow_candidate: depth={} candidate={}",
-               stack.obligation.recursion_depth, candidate.repr(self.tcx()));
-        let result = self.infcx.probe(|| {
+        debug!("winnow_candidate: candidate={}", candidate.repr(self.tcx()));
+        let result = self.infcx.probe(|_| {
             let candidate = (*candidate).clone();
             match self.confirm_candidate(stack.obligation, candidate) {
                 Ok(selection) => self.winnow_selection(Some(stack), selection),
@@ -919,17 +919,23 @@ fn candidate_should_be_dropped_in_favor_of<'o>(&mut self,
                        candidate_i.repr(self.tcx()),
                        candidate_j.repr(self.tcx()));
 
-                self.infcx.probe(|| {
+                self.infcx.probe(|snapshot| {
+                    let (skol_obligation_trait_ref, skol_map) =
+                        self.infcx().skolemize_late_bound_regions(
+                            &*stack.obligation.trait_ref, snapshot);
                     let impl_substs =
-                        self.rematch_impl(impl_def_id, stack.obligation);
+                        self.rematch_impl(impl_def_id, stack.obligation, snapshot,
+                                          &skol_map, Rc::new(skol_obligation_trait_ref));
                     let impl_trait_ref =
                         ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap();
                     let impl_trait_ref =
                         impl_trait_ref.subst(self.tcx(), &impl_substs);
+                    let poly_impl_trait_ref =
+                        Rc::new(ty::Binder((*impl_trait_ref).clone()));
                     let origin =
                         infer::RelateOutputImplTypes(stack.obligation.cause.span);
                     self.infcx
-                        .sub_poly_trait_refs(false, origin, impl_trait_ref, vt.bound.clone())
+                        .sub_poly_trait_refs(false, origin, poly_impl_trait_ref, vt.bound.clone())
                         .is_ok()
                 })
             }
@@ -1400,10 +1406,21 @@ fn confirm_param_candidate(&mut self,
                obligation.repr(self.tcx()),
                param.repr(self.tcx()));
 
-        let () = try!(self.confirm(obligation.cause,
-                                   obligation.trait_ref.clone(),
-                                   param.bound.clone()));
-        Ok(param)
+        // During evaluation, we already checked that this
+        // where-clause trait-ref could be unified with the obligation
+        // trait-ref. Repeat that unification now without any
+        // transactional boundary; it should not fail.
+        match self.confirm_poly_trait_refs(obligation.cause,
+                                           obligation.trait_ref.clone(),
+                                           param.bound.clone()) {
+            Ok(()) => Ok(param),
+            Err(_) => {
+                self.tcx().sess.bug(
+                    format!("Where clause `{}` was applicable to `{}` but now is not",
+                            param.bound.repr(self.tcx()),
+                            obligation.repr(self.tcx())).as_slice());
+            }
+        }
     }
 
     fn confirm_builtin_candidate(&mut self,
@@ -1476,23 +1493,44 @@ fn confirm_impl_candidate(&mut self,
 
         // First, create the substitutions by matching the impl again,
         // this time not in a probe.
-        let substs = self.rematch_impl(impl_def_id, obligation);
-        debug!("confirm_impl_candidate substs={}", substs);
-        Ok(self.vtable_impl(impl_def_id, substs, obligation.cause, obligation.recursion_depth + 1))
+        self.infcx.try(|snapshot| {
+            let (skol_obligation_trait_ref, skol_map) =
+                self.infcx().skolemize_late_bound_regions(&*obligation.trait_ref, snapshot);
+            let substs = self.rematch_impl(impl_def_id, obligation,
+                                           snapshot, &skol_map, Rc::new(skol_obligation_trait_ref));
+            debug!("confirm_impl_candidate substs={}", substs);
+            Ok(self.vtable_impl(impl_def_id, substs, obligation.cause,
+                                obligation.recursion_depth + 1, skol_map, snapshot))
+        })
     }
 
     fn vtable_impl(&mut self,
                    impl_def_id: ast::DefId,
                    substs: Substs<'tcx>,
                    cause: ObligationCause<'tcx>,
-                   recursion_depth: uint)
+                   recursion_depth: uint,
+                   skol_map: infer::SkolemizationMap,
+                   snapshot: &infer::CombinedSnapshot)
                    -> VtableImplData<'tcx, PredicateObligation<'tcx>>
     {
+        debug!("vtable_impl(impl_def_id={}, substs={}, recursion_depth={}, skol_map={})",
+               impl_def_id.repr(self.tcx()),
+               substs.repr(self.tcx()),
+               recursion_depth,
+               skol_map.repr(self.tcx()));
+
         let impl_predicates =
             self.impl_predicates(cause,
                                  recursion_depth,
                                  impl_def_id,
-                                 &substs);
+                                 &substs,
+                                 skol_map,
+                                 snapshot);
+
+        debug!("vtable_impl: impl_def_id={} impl_predicates={}",
+               impl_def_id.repr(self.tcx()),
+               impl_predicates.repr(self.tcx()));
+
         VtableImplData { impl_def_id: impl_def_id,
                          substs: substs,
                          nested: impl_predicates }
@@ -1535,10 +1573,9 @@ fn confirm_fn_pointer_candidate(&mut self,
             substs: substs,
         }));
 
-        let () =
-            try!(self.confirm(obligation.cause,
-                              obligation.trait_ref.clone(),
-                              trait_ref));
+        try!(self.confirm_poly_trait_refs(obligation.cause,
+                                          obligation.trait_ref.clone(),
+                                          trait_ref));
 
         Ok(self_ty)
     }
@@ -1582,9 +1619,52 @@ fn confirm_unboxed_closure_candidate(&mut self,
                closure_def_id.repr(self.tcx()),
                trait_ref.repr(self.tcx()));
 
-        self.confirm(obligation.cause,
-                     obligation.trait_ref.clone(),
-                     trait_ref)
+        self.confirm_poly_trait_refs(obligation.cause,
+                                     obligation.trait_ref.clone(),
+                                     trait_ref)
+    }
+
+    /// In the case of unboxed closure types and fn pointers,
+    /// we currently treat the input type parameters on the trait as
+    /// outputs. This means that when we have a match we have only
+    /// considered the self type, so we have to go back and make sure
+    /// to relate the argument types too.  This is kind of wrong, but
+    /// since we control the full set of impls, also not that wrong,
+    /// and it DOES yield better error messages (since we don't report
+    /// errors as if there is no applicable impl, but rather report
+    /// errors are about mismatched argument types.
+    ///
+    /// Here is an example. Imagine we have an unboxed closure expression
+    /// and we desugared it so that the type of the expression is
+    /// `Closure`, and `Closure` expects an int as argument. Then it
+    /// is "as if" the compiler generated this impl:
+    ///
+    ///     impl Fn(int) for Closure { ... }
+    ///
+    /// Now imagine our obligation is `Fn(uint) for Closure`. So far
+    /// we have matched the self-type `Closure`. At this point we'll
+    /// compare the `int` to `uint` and generate an error.
+    ///
+    /// Note that this checking occurs *after* the impl has selected,
+    /// because these output type parameters should not affect the
+    /// selection of the impl. Therefore, if there is a mismatch, we
+    /// report an error to the user.
+    fn confirm_poly_trait_refs(&mut self,
+                               obligation_cause: ObligationCause,
+                               obligation_trait_ref: Rc<ty::PolyTraitRef<'tcx>>,
+                               expected_trait_ref: Rc<ty::PolyTraitRef<'tcx>>)
+                               -> Result<(), SelectionError<'tcx>>
+    {
+        let origin = infer::RelateOutputImplTypes(obligation_cause.span);
+
+        let obligation_trait_ref = obligation_trait_ref.clone();
+        match self.infcx.sub_poly_trait_refs(false,
+                                             origin,
+                                             expected_trait_ref.clone(),
+                                             obligation_trait_ref.clone()) {
+            Ok(()) => Ok(()),
+            Err(e) => Err(OutputTypeParameterMismatch(expected_trait_ref, obligation_trait_ref, e))
+        }
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -1599,10 +1679,14 @@ fn confirm_unboxed_closure_candidate(&mut self,
 
     fn rematch_impl(&mut self,
                     impl_def_id: ast::DefId,
-                    obligation: &TraitObligation<'tcx>)
+                    obligation: &TraitObligation<'tcx>,
+                    snapshot: &infer::CombinedSnapshot,
+                    skol_map: &infer::SkolemizationMap,
+                    skol_obligation_trait_ref: Rc<ty::TraitRef<'tcx>>)
                     -> Substs<'tcx>
     {
-        match self.match_impl(impl_def_id, obligation) {
+        match self.match_impl(impl_def_id, obligation, snapshot,
+                              skol_map, skol_obligation_trait_ref) {
             Ok(substs) => {
                 substs
             }
@@ -1618,11 +1702,13 @@ fn rematch_impl(&mut self,
 
     fn match_impl(&mut self,
                   impl_def_id: ast::DefId,
-                  obligation: &TraitObligation<'tcx>)
+                  obligation: &TraitObligation<'tcx>,
+                  snapshot: &infer::CombinedSnapshot,
+                  skol_map: &infer::SkolemizationMap,
+                  skol_obligation_trait_ref: Rc<ty::TraitRef<'tcx>>)
                   -> Result<Substs<'tcx>, ()>
     {
-        let impl_trait_ref = ty::impl_trait_ref(self.tcx(),
-                                                impl_def_id).unwrap();
+        let impl_trait_ref = ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap();
 
         // Before we create the substitutions and everything, first
         // consider a "quick reject". This avoids creating more types
@@ -1638,15 +1724,42 @@ fn match_impl(&mut self,
         let impl_trait_ref = impl_trait_ref.subst(self.tcx(),
                                                   &impl_substs);
 
-        match self.match_trait_refs(obligation, impl_trait_ref) {
-            Ok(()) => Ok(impl_substs),
-            Err(()) => Err(())
+        debug!("match_impl(impl_def_id={}, obligation={}, \
+               impl_trait_ref={}, skol_obligation_trait_ref={})",
+               impl_def_id.repr(self.tcx()),
+               obligation.repr(self.tcx()),
+               impl_trait_ref.repr(self.tcx()),
+               skol_obligation_trait_ref.repr(self.tcx()));
+
+        let origin = infer::RelateOutputImplTypes(obligation.cause.span);
+        match self.infcx.sub_trait_refs(false,
+                                        origin,
+                                        impl_trait_ref,
+                                        skol_obligation_trait_ref) {
+            Ok(()) => { }
+            Err(e) => {
+                debug!("match_impl: failed sub_trait_refs due to `{}`",
+                       ty::type_err_to_str(self.tcx(), &e));
+                return Err(());
+            }
+        }
+
+        match self.infcx.leak_check(skol_map, snapshot) {
+            Ok(()) => { }
+            Err(e) => {
+                debug!("match_impl: failed leak check due to `{}`",
+                       ty::type_err_to_str(self.tcx(), &e));
+                return Err(());
+            }
         }
+
+        debug!("match_impl: success impl_substs={}", impl_substs.repr(self.tcx()));
+        Ok(impl_substs)
     }
 
     fn fast_reject_trait_refs(&mut self,
                               obligation: &TraitObligation,
-                              impl_trait_ref: &ty::PolyTraitRef)
+                              impl_trait_ref: &ty::TraitRef)
                               -> bool
     {
         // We can avoid creating type variables and doing the full
@@ -1667,19 +1780,19 @@ fn fast_reject_trait_refs(&mut self,
             })
     }
 
-    fn match_trait_refs(&mut self,
-                        obligation: &TraitObligation<'tcx>,
-                        trait_ref: Rc<ty::PolyTraitRef<'tcx>>)
+    fn match_where_clause(&mut self,
+                          obligation: &TraitObligation<'tcx>,
+                          where_clause_trait_ref: Rc<ty::PolyTraitRef<'tcx>>)
                         -> Result<(),()>
     {
-        debug!("match_trait_refs: obligation={} trait_ref={}",
+        debug!("match_where_clause: obligation={} where_clause_trait_ref={}",
                obligation.repr(self.tcx()),
-               trait_ref.repr(self.tcx()));
+               where_clause_trait_ref.repr(self.tcx()));
 
         let origin = infer::RelateOutputImplTypes(obligation.cause.span);
         match self.infcx.sub_poly_trait_refs(false,
                                              origin,
-                                             trait_ref,
+                                             where_clause_trait_ref,
                                              obligation.trait_ref.clone()) {
             Ok(()) => Ok(()),
             Err(_) => Err(()),
@@ -1754,78 +1867,6 @@ fn match_self_types(&mut self,
         }
     }
 
-    ///////////////////////////////////////////////////////////////////////////
-    // Confirmation
-    //
-    // The final step of selection: once we know how an obligation is
-    // is resolved, we confirm that selection in order to have
-    // side-effects on the typing environment. This step also unifies
-    // the output type parameters from the obligation with those found
-    // on the impl/bound, which may yield type errors.
-
-    /// Relates the output type parameters from an impl to the
-    /// trait.  This may lead to type errors. The confirmation step
-    /// is separated from the main match procedure because these
-    /// type errors do not cause us to select another impl.
-    ///
-    /// As an example, consider matching the obligation
-    /// `Iterator<char> for Elems<int>` using the following impl:
-    ///
-    ///    impl<T> Iterator<T> for Elems<T> { ... }
-    ///
-    /// The match phase will succeed with substitution `T=int`.
-    /// The confirm step will then try to unify `int` and `char`
-    /// and yield an error.
-    fn confirm_impl_vtable(&mut self,
-                           impl_def_id: ast::DefId,
-                           obligation_cause: ObligationCause<'tcx>,
-                           obligation_trait_ref: Rc<ty::PolyTraitRef<'tcx>>,
-                           substs: &Substs<'tcx>)
-                           -> Result<(), SelectionError<'tcx>>
-    {
-        let impl_trait_ref = ty::impl_trait_ref(self.tcx(),
-                                                impl_def_id).unwrap();
-        let impl_trait_ref = impl_trait_ref.subst(self.tcx(),
-                                                  substs);
-        self.confirm(obligation_cause, obligation_trait_ref, impl_trait_ref)
-    }
-
-    /// After we have determined which impl applies, and with what substitutions, there is one last
-    /// step. We have to go back and relate the "output" type parameters from the obligation to the
-    /// types that are specified in the impl.
-    ///
-    /// For example, imagine we have:
-    ///
-    ///     impl<T> Iterator<T> for Vec<T> { ... }
-    ///
-    /// and our obligation is `Iterator<Foo> for Vec<int>` (note the mismatch in the obligation
-    /// types). Up until this step, no error would be reported: the self type is `Vec<int>`, and
-    /// that matches `Vec<T>` with the substitution `T=int`. At this stage, we could then go and
-    /// check that the type parameters to the `Iterator` trait match. (In terms of the parameters,
-    /// the `expected_trait_ref` here would be `Iterator<int> for Vec<int>`, and the
-    /// `obligation_trait_ref` would be `Iterator<Foo> for Vec<int>`.
-    ///
-    /// Note that this checking occurs *after* the impl has selected, because these output type
-    /// parameters should not affect the selection of the impl. Therefore, if there is a mismatch,
-    /// we report an error to the user.
-    fn confirm(&mut self,
-               obligation_cause: ObligationCause,
-               obligation_trait_ref: Rc<ty::PolyTraitRef<'tcx>>,
-               expected_trait_ref: Rc<ty::PolyTraitRef<'tcx>>)
-               -> Result<(), SelectionError<'tcx>>
-    {
-        let origin = infer::RelateOutputImplTypes(obligation_cause.span);
-
-        let obligation_trait_ref = obligation_trait_ref.clone();
-        match self.infcx.sub_poly_trait_refs(false,
-                                             origin,
-                                             expected_trait_ref.clone(),
-                                             obligation_trait_ref.clone()) {
-            Ok(()) => Ok(()),
-            Err(e) => Err(OutputTypeParameterMismatch(expected_trait_ref, obligation_trait_ref, e))
-        }
-    }
-
     ///////////////////////////////////////////////////////////////////////////
     // Miscellany
 
@@ -1857,11 +1898,14 @@ fn impl_predicates(&self,
                        cause: ObligationCause<'tcx>,
                        recursion_depth: uint,
                        impl_def_id: ast::DefId,
-                       impl_substs: &Substs<'tcx>)
+                       impl_substs: &Substs<'tcx>,
+                       skol_map: infer::SkolemizationMap,
+                       snapshot: &infer::CombinedSnapshot)
                        -> VecPerParamSpace<PredicateObligation<'tcx>>
     {
         let impl_generics = ty::lookup_item_type(self.tcx(), impl_def_id).generics;
         let bounds = impl_generics.to_bounds(self.tcx(), impl_substs);
+        let bounds = self.infcx().plug_leaks(skol_map, snapshot, &bounds);
         util::predicates_for_generics(self.tcx(), cause, recursion_depth, &bounds)
     }
 
index 91247d8b73e41babf68b30ee463d01cb96524734..ee56d919fefc7159aad7e25c63d4e64e789e5903 100644 (file)
@@ -478,8 +478,10 @@ pub enum MethodOrigin<'tcx> {
 #[deriving(Clone, Show)]
 pub struct MethodParam<'tcx> {
     // the precise trait reference that occurs as a bound -- this may
-    // be a supertrait of what the user actually typed.
-    pub trait_ref: Rc<ty::PolyTraitRef<'tcx>>,
+    // be a supertrait of what the user actually typed. Note that it
+    // never contains bound regions; those regions should have been
+    // instantiated with fresh variables at this point.
+    pub trait_ref: Rc<ty::TraitRef<'tcx>>,
 
     // index of uint in the list of methods for the trait
     pub method_num: uint,
@@ -489,7 +491,7 @@ pub struct MethodParam<'tcx> {
 #[deriving(Clone, Show)]
 pub struct MethodObject<'tcx> {
     // the (super)trait containing the method to be invoked
-    pub trait_ref: Rc<ty::PolyTraitRef<'tcx>>,
+    pub trait_ref: Rc<ty::TraitRef<'tcx>>,
 
     // the actual base trait id of the object
     pub object_trait_id: ast::DefId,
@@ -665,7 +667,7 @@ pub struct ctxt<'tcx> {
     /// A cache for the trait_items() routine
     pub trait_items_cache: RefCell<DefIdMap<Rc<Vec<ImplOrTraitItem<'tcx>>>>>,
 
-    pub impl_trait_cache: RefCell<DefIdMap<Option<Rc<ty::PolyTraitRef<'tcx>>>>>,
+    pub impl_trait_cache: RefCell<DefIdMap<Option<Rc<ty::TraitRef<'tcx>>>>>,
 
     pub trait_refs: RefCell<NodeMap<Rc<TraitRef<'tcx>>>>,
     pub trait_defs: RefCell<DefIdMap<Rc<TraitDef<'tcx>>>>,
@@ -1306,7 +1308,7 @@ pub enum sty<'tcx> {
 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
 pub struct TyTrait<'tcx> {
     // Principal trait reference.
-    pub principal: PolyTraitRef<'tcx>, // would use Rc<TraitRef>, but it runs afoul of some static rules
+    pub principal: PolyTraitRef<'tcx>,
     pub bounds: ExistentialBounds
 }
 
@@ -1315,7 +1317,9 @@ impl<'tcx> TyTrait<'tcx> {
     /// we convert the principal trait-ref into a normal trait-ref,
     /// you must give *some* self-type. A common choice is `mk_err()`
     /// or some skolemized type.
-    pub fn principal_trait_ref_with_self_ty(&self, self_ty: Ty<'tcx>) -> Rc<ty::PolyTraitRef<'tcx>> {
+    pub fn principal_trait_ref_with_self_ty(&self, self_ty: Ty<'tcx>)
+                                            -> Rc<ty::PolyTraitRef<'tcx>>
+    {
         Rc::new(ty::Binder(ty::TraitRef {
             def_id: self.principal.def_id(),
             substs: self.principal.substs().with_self_ty(self_ty),
@@ -4818,7 +4822,7 @@ pub fn trait_item_def_ids(cx: &ctxt, id: ast::DefId)
 }
 
 pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
-                            -> Option<Rc<PolyTraitRef<'tcx>>> {
+                            -> Option<Rc<TraitRef<'tcx>>> {
     memoized(&cx.impl_trait_cache, id, |id: ast::DefId| {
         if id.krate == ast::LOCAL_CRATE {
             debug!("(impl_trait_ref) searching for trait impl {}", id);
@@ -4828,9 +4832,8 @@ pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
                         ast::ItemImpl(_, _, ref opt_trait, _, _) => {
                             match opt_trait {
                                 &Some(ref t) => {
-                                    let trait_ref =
-                                        (*ty::node_id_to_trait_ref(cx, t.ref_id)).clone();
-                                    Some(Rc::new(ty::Binder(trait_ref)))
+                                    let trait_ref = ty::node_id_to_trait_ref(cx, t.ref_id);
+                                    Some(trait_ref)
                                 }
                                 &None => None
                             }
@@ -5736,7 +5739,7 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
         // Record the trait->implementation mappings, if applicable.
         let associated_traits = csearch::get_impl_trait(tcx, impl_def_id);
         for trait_ref in associated_traits.iter() {
-            record_trait_implementation(tcx, trait_ref.def_id(), impl_def_id);
+            record_trait_implementation(tcx, trait_ref.def_id, impl_def_id);
         }
 
         // For any methods that use a default implementation, add them to
@@ -6432,26 +6435,24 @@ pub fn replace_late_bound_regions<'tcx, T, F>(
     debug!("replace_late_bound_regions({})", binder.repr(tcx));
 
     let mut map = FnvHashMap::new();
-    let value = {
-        let mut f = ty_fold::RegionFolder::new(tcx, |region, current_depth| {
-            debug!("region={}", region.repr(tcx));
-            match region {
-                ty::ReLateBound(debruijn, br) if debruijn.depth == current_depth => {
-                    * match map.entry(br) {
-                        Vacant(entry) => entry.set(mapf(br, debruijn)),
-                        Occupied(entry) => entry.into_mut(),
-                    }
-                }
-                _ => {
-                    region
+
+    // Note: fold the field `0`, not the binder, so that late-bound
+    // regions bound by `binder` are considered free.
+    let value = ty_fold::fold_regions(tcx, &binder.0, |region, current_depth| {
+        debug!("region={}", region.repr(tcx));
+        match region {
+            ty::ReLateBound(debruijn, br) if debruijn.depth == current_depth => {
+                * match map.entry(br) {
+                    Vacant(entry) => entry.set(mapf(br, debruijn)),
+                    Occupied(entry) => entry.into_mut(),
                 }
             }
-        });
+            _ => {
+                region
+            }
+        }
+    });
 
-        // Note: fold the field `0`, not the binder, so that late-bound
-        // regions bound by `binder` are considered free.
-        binder.0.fold_with(&mut f)
-    };
     debug!("resulting map: {} value: {}", map, value.repr(tcx));
     (value, map)
 }
index 496a0badd82368532948f68e5cbb7801018c3dbe..cde0470ff48e2ce76c9ea114d82479ca16fa2d7e 100644 (file)
@@ -730,14 +730,17 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
 /// regions (aka "lifetimes") that are bound within a type are not
 /// visited by this folder; only regions that occur free will be
 /// visited by `fld_r`.
-pub struct RegionFolder<'a, 'tcx: 'a, F> where F: FnMut(ty::Region, uint) -> ty::Region {
+
+pub struct RegionFolder<'a, 'tcx: 'a> {
     tcx: &'a ty::ctxt<'tcx>,
     current_depth: uint,
-    fld_r: F,
+    fld_r: &'a mut (FnMut(ty::Region, uint) -> ty::Region + 'a),
 }
 
-impl<'a, 'tcx, F> RegionFolder<'a, 'tcx, F> where F: FnMut(ty::Region, uint) -> ty::Region {
-    pub fn new(tcx: &'a ty::ctxt<'tcx>, fld_r: F) -> RegionFolder<'a, 'tcx, F> {
+impl<'a, 'tcx> RegionFolder<'a, 'tcx> {
+    pub fn new<F>(tcx: &'a ty::ctxt<'tcx>, fld_r: &'a mut F) -> RegionFolder<'a, 'tcx>
+        where F : FnMut(ty::Region, uint) -> ty::Region
+    {
         RegionFolder {
             tcx: tcx,
             current_depth: 1,
@@ -750,15 +753,21 @@ pub fn collect_regions<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> Vec<ty::Regio
     where T : TypeFoldable<'tcx>
 {
     let mut vec = Vec::new();
-    {
-        let mut folder = RegionFolder::new(tcx, |r, _| { vec.push(r); r });
-        value.fold_with(&mut folder);
-    }
+    fold_regions(tcx, value, |r, _| { vec.push(r); r });
     vec
 }
 
-impl<'a, 'tcx, F> TypeFolder<'tcx> for RegionFolder<'a, 'tcx, F> where
-    F: FnMut(ty::Region, uint) -> ty::Region,
+pub fn fold_regions<'tcx,T,F>(tcx: &ty::ctxt<'tcx>,
+                              value: &T,
+                              mut f: F)
+                              -> T
+    where F : FnMut(ty::Region, uint) -> ty::Region,
+          T : TypeFoldable<'tcx>,
+{
+    value.fold_with(&mut RegionFolder::new(tcx, &mut f))
+}
+
+impl<'a, 'tcx> TypeFolder<'tcx> for RegionFolder<'a, 'tcx>
 {
     fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.tcx }
 
@@ -780,7 +789,7 @@ fn fold_region(&mut self, r: ty::Region) -> ty::Region {
             _ => {
                 debug!("RegionFolder.fold_region({}) folding free region (current_depth={})",
                        r.repr(self.tcx()), self.current_depth);
-                (self.fld_r)(r, self.current_depth)
+                self.fld_r.call_mut((r, self.current_depth))
             }
         }
     }
@@ -836,7 +845,7 @@ pub fn shift_regions<'tcx, T:TypeFoldable<'tcx>+Repr<'tcx>>(tcx: &ty::ctxt<'tcx>
     debug!("shift_regions(value={}, amount={})",
            value.repr(tcx), amount);
 
-    value.fold_with(&mut RegionFolder::new(tcx, |region, _current_depth| {
+    value.fold_with(&mut RegionFolder::new(tcx, &mut |region, _current_depth| {
         shift_region(region, amount)
     }))
 }
index 2162055f287826ee497758a37003a799a28d0b1d..1a4f06663ef3b694089e7ea544022df20ea6056b 100644 (file)
@@ -941,14 +941,14 @@ fn process_method_call(&mut self,
             ty::MethodTypeParam(ref mp) => {
                 // method invoked on a type parameter
                 let trait_item = ty::trait_item(&self.analysis.ty_cx,
-                                                mp.trait_ref.def_id(),
+                                                mp.trait_ref.def_id,
                                                 mp.method_num);
                 (None, Some(trait_item.def_id()))
             }
             ty::MethodTraitObject(ref mo) => {
                 // method invoked on a trait instance
                 let trait_item = ty::trait_item(&self.analysis.ty_cx,
-                                                mo.trait_ref.def_id(),
+                                                mo.trait_ref.def_id,
                                                 mo.method_num);
                 (None, Some(trait_item.def_id()))
             }
index 192b0d6342100e08c79950675a08db8847ecc3d6..f8303a6f030809effcfc022516fb2a46eb022dcb 100644 (file)
@@ -421,12 +421,11 @@ pub fn trans_fn_ref_with_substs<'blk, 'tcx>(
             let impl_or_trait_item = ty::impl_or_trait_item(tcx, source_id);
             match impl_or_trait_item {
                 ty::MethodTraitItem(method) => {
-                    let poly_trait_ref = ty::impl_trait_ref(tcx, impl_id).unwrap();
-                    let trait_ref = ty::erase_late_bound_regions(tcx, &*poly_trait_ref);
+                    let trait_ref = ty::impl_trait_ref(tcx, impl_id).unwrap();
 
                     // Compute the first substitution
                     let first_subst =
-                        ty::make_substs_for_receiver_types(tcx, &trait_ref, &*method)
+                        ty::make_substs_for_receiver_types(tcx, &*trait_ref, &*method)
                         .erase_regions();
 
                     // And compose them
index a8f7323b4ae03c64927a5251c272aaeaa27167bd..f1c3c9be396af0c93d7d4a17f729b51bf22080ea 100644 (file)
@@ -133,14 +133,14 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             method_num
         }) => {
             let trait_ref =
-                Rc::new(trait_ref.subst(bcx.tcx(), bcx.fcx.param_substs));
+                Rc::new(ty::Binder((**trait_ref).subst(bcx.tcx(), bcx.fcx.param_substs)));
             let span = bcx.tcx().map.span(method_call.expr_id);
             debug!("method_call={} trait_ref={}",
                    method_call,
                    trait_ref.repr(bcx.tcx()));
             let origin = fulfill_obligation(bcx.ccx(),
                                             span,
-                                            (*trait_ref).clone());
+                                            trait_ref.clone());
             debug!("origin = {}", origin.repr(bcx.tcx()));
             trans_monomorphized_callee(bcx, method_call, trait_ref.def_id(),
                                        method_num, origin)
@@ -618,7 +618,7 @@ fn emit_vtable_methods<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let tcx = ccx.tcx();
 
     let trt_id = match ty::impl_trait_ref(tcx, impl_id) {
-        Some(t_id) => t_id.def_id(),
+        Some(t_id) => t_id.def_id,
         None       => ccx.sess().bug("make_impl_vtable: don't know how to \
                                       make a vtable for a type impl!")
     };
index d6438c4062e3219b273ffe8328dae0b39501cd44..4f4bebabead2cf538ed1228faeb71adb8611dcbb 100644 (file)
@@ -53,8 +53,7 @@
 use middle::resolve_lifetime as rl;
 use middle::subst::{FnSpace, TypeSpace, AssocSpace, SelfSpace, Subst, Substs};
 use middle::subst::{VecPerParamSpace};
-use middle::ty::{mod, Ty};
-use middle::ty_fold;
+use middle::ty::{mod, RegionEscape, Ty};
 use rscope::{mod, UnelidableRscope, RegionScope, SpecificRscope,
              ShiftedRscope, BindingRscope};
 use TypeAndSubsts;
@@ -533,7 +532,8 @@ pub fn instantiate_poly_trait_ref<'tcx,AC,RS>(
     -> Rc<ty::PolyTraitRef<'tcx>>
     where AC: AstConv<'tcx>, RS: RegionScope
 {
-    let trait_ref = instantiate_trait_ref(this, rscope, &ast_trait_ref.trait_ref, self_ty, allow_eq);
+    let trait_ref =
+        instantiate_trait_ref(this, rscope, &ast_trait_ref.trait_ref, self_ty, allow_eq);
     let trait_ref = (*trait_ref).clone();
     Rc::new(ty::Binder(trait_ref)) // Ugh.
 }
@@ -1200,10 +1200,9 @@ fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>(
     let (self_ty, mut implied_output_region) = match opt_self_info {
         None => (None, None),
         Some(self_info) => {
-            // Shift regions in the self type by 1 to account for the binding
-            // level introduced by the function itself.
-            let untransformed_self_ty =
-                ty_fold::shift_regions(this.tcx(), 1, &self_info.untransformed_self_ty);
+            // This type comes from an impl or trait; no late-bound
+            // regions should be present.
+            assert!(!self_info.untransformed_self_ty.has_escaping_regions());
 
             // Figure out and record the explicit self category.
             let explicit_self_category =
@@ -1214,19 +1213,19 @@ fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>(
                     (None, None)
                 }
                 ty::ByValueExplicitSelfCategory => {
-                    (Some(untransformed_self_ty), None)
+                    (Some(self_info.untransformed_self_ty), None)
                 }
                 ty::ByReferenceExplicitSelfCategory(region, mutability) => {
                     (Some(ty::mk_rptr(this.tcx(),
                                       region,
                                       ty::mt {
-                                        ty: untransformed_self_ty,
+                                        ty: self_info.untransformed_self_ty,
                                         mutbl: mutability
                                       })),
                      Some(region))
                 }
                 ty::ByBoxExplicitSelfCategory => {
-                    (Some(ty::mk_uniq(this.tcx(), untransformed_self_ty)), None)
+                    (Some(ty::mk_uniq(this.tcx(), self_info.untransformed_self_ty)), None)
                 }
             }
         }
index 8ac58736f54b496a94f07a397b4e43158d2fa6a0..2c220f298262fdb40d603809c818da0ae8e31f0a 100644 (file)
@@ -222,17 +222,19 @@ fn fresh_receiver_substs(&mut self,
                     // argument type), but those cases have already
                     // been ruled out when we deemed the trait to be
                     // "object safe".
-                    let original_trait_ref =
+                    let original_poly_trait_ref =
                         data.principal_trait_ref_with_self_ty(object_ty);
+                    let upcast_poly_trait_ref =
+                        this.upcast(original_poly_trait_ref.clone(), trait_def_id);
                     let upcast_trait_ref =
-                        this.upcast(original_trait_ref.clone(), trait_def_id);
-                    debug!("original_trait_ref={} upcast_trait_ref={} target_trait={}",
-                           original_trait_ref.repr(this.tcx()),
+                        this.replace_late_bound_regions_with_fresh_var(&*upcast_poly_trait_ref);
+                    debug!("original_poly_trait_ref={} upcast_trait_ref={} target_trait={}",
+                           original_poly_trait_ref.repr(this.tcx()),
                            upcast_trait_ref.repr(this.tcx()),
                            trait_def_id.repr(this.tcx()));
-                    let substs = upcast_trait_ref.substs().clone();
+                    let substs = upcast_trait_ref.substs.clone();
                     let origin = MethodTraitObject(MethodObject {
-                        trait_ref: upcast_trait_ref,
+                        trait_ref: Rc::new(upcast_trait_ref),
                         object_trait_id: trait_def_id,
                         method_num: method_num,
                         real_index: real_index,
@@ -257,7 +259,7 @@ fn fresh_receiver_substs(&mut self,
                                      .subst(self.tcx(), &impl_polytype.substs);
                 let origin = MethodTypeParam(MethodParam { trait_ref: impl_trait_ref.clone(),
                                                            method_num: method_num });
-                (impl_trait_ref.substs().clone(), origin)
+                (impl_trait_ref.substs.clone(), origin)
             }
 
             probe::TraitPick(trait_def_id, method_num) => {
@@ -273,16 +275,20 @@ fn fresh_receiver_substs(&mut self,
                                                                  self.infcx().next_ty_var());
 
                 let trait_ref =
-                    Rc::new(ty::Binder(ty::TraitRef::new(trait_def_id, substs.clone())));
+                    Rc::new(ty::TraitRef::new(trait_def_id, substs.clone()));
                 let origin = MethodTypeParam(MethodParam { trait_ref: trait_ref,
                                                            method_num: method_num });
                 (substs, origin)
             }
 
-            probe::WhereClausePick(ref trait_ref, method_num) => {
-                let origin = MethodTypeParam(MethodParam { trait_ref: trait_ref.clone(),
+            probe::WhereClausePick(ref poly_trait_ref, method_num) => {
+                // Where clauses can have bound regions in them. We need to instantiate
+                // those to convert from a poly-trait-ref to a trait-ref.
+                let trait_ref = self.replace_late_bound_regions_with_fresh_var(&**poly_trait_ref);
+                let substs = trait_ref.substs.clone();
+                let origin = MethodTypeParam(MethodParam { trait_ref: Rc::new(trait_ref),
                                                            method_num: method_num });
-                (trait_ref.substs().clone(), origin)
+                (substs, origin)
             }
         }
     }
@@ -379,25 +385,9 @@ fn instantiate_method_sig(&mut self,
                               all_substs: subst::Substs<'tcx>)
                               -> InstantiatedMethodSig<'tcx>
     {
-        // If this method comes from an impl (as opposed to a trait),
-        // it may have late-bound regions from the impl that appear in
-        // the substitutions, method signature, and
-        // bounds. Instantiate those at this point. (If it comes from
-        // a trait, this step has no effect, as there are no
-        // late-bound regions to instantiate.)
-        //
-        // The binder level here corresponds to the impl.
-        let (all_substs, (method_sig, method_generics)) =
-            self.replace_late_bound_regions_with_fresh_var(
-                &ty::Binder((all_substs,
-                             (pick.method_ty.fty.sig.clone(),
-                              pick.method_ty.generics.clone()))));
-
-        debug!("late-bound lifetimes from impl instantiated, \
-                all_substs={} method_sig={} method_generics={}",
-               all_substs.repr(self.tcx()),
-               method_sig.repr(self.tcx()),
-               method_generics.repr(self.tcx()));
+        debug!("instantiate_method_sig(pick={}, all_substs={})",
+               pick.repr(self.tcx()),
+               all_substs.repr(self.tcx()));
 
         // Instantiate the bounds on the method with the
         // type/early-bound-regions substitutions performed.  The only
@@ -427,8 +417,7 @@ fn instantiate_method_sig(&mut self,
                 all_substs.clone()
             }
         };
-        let method_bounds =
-            method_generics.to_bounds(self.tcx(), &method_bounds_substs);
+        let method_bounds = pick.method_ty.generics.to_bounds(self.tcx(), &method_bounds_substs);
 
         debug!("method_bounds after subst = {}",
                method_bounds.repr(self.tcx()));
@@ -436,7 +425,7 @@ fn instantiate_method_sig(&mut self,
         // Substitute the type/early-bound-regions into the method
         // signature. In addition, the method signature may bind
         // late-bound regions, so instantiate those.
-        let method_sig = method_sig.subst(self.tcx(), &all_substs);
+        let method_sig = pick.method_ty.fty.sig.subst(self.tcx(), &all_substs);
         let method_sig = self.replace_late_bound_regions_with_fresh_var(&method_sig);
 
         debug!("late-bound lifetimes from method instantiated, method_sig={}",
index 451058e5e21a0b1d73ac363ccbad93041cde3600..ffaeceb3eed11a84111fb991ebfd02f9120f6f03 100644 (file)
@@ -166,12 +166,13 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
 
     // Construct a trait-reference `self_ty : Trait<input_tys>`
     let substs = subst::Substs::new_trait(input_types, Vec::new(), assoc_types, self_ty);
-    let trait_ref = Rc::new(ty::Binder(ty::TraitRef::new(trait_def_id, substs)));
+    let trait_ref = Rc::new(ty::TraitRef::new(trait_def_id, substs));
 
     // Construct an obligation
+    let poly_trait_ref = Rc::new(ty::Binder((*trait_ref).clone()));
     let obligation = traits::Obligation::misc(span,
                                               fcx.body_id,
-                                              ty::Predicate::Trait(trait_ref.clone()));
+                                              poly_trait_ref.as_predicate());
 
     // Now we want to know if this can be matched
     let mut selcx = traits::SelectionContext::new(fcx.infcx(),
@@ -194,11 +195,8 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
 
     // Substitute the trait parameters into the method type and
     // instantiate late-bound regions to get the actual method type.
-    //
-    // Note that as the method comes from a trait, it can only have
-    // late-bound regions from the fn itself, not the impl.
     let ref bare_fn_ty = method_ty.fty;
-    let fn_sig = bare_fn_ty.sig.subst(tcx, trait_ref.substs());
+    let fn_sig = bare_fn_ty.sig.subst(tcx, &trait_ref.substs);
     let fn_sig = fcx.infcx().replace_late_bound_regions_with_fresh_var(span,
                                                                        infer::FnCall,
                                                                        &fn_sig).0;
@@ -221,7 +219,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
     //
     // Note that as the method comes from a trait, it should not have
     // any late-bound regions appearing in its bounds.
-    let method_bounds = method_ty.generics.to_bounds(fcx.tcx(), trait_ref.substs());
+    let method_bounds = method_ty.generics.to_bounds(fcx.tcx(), &trait_ref.substs);
     assert!(!method_bounds.has_escaping_regions());
     fcx.add_obligations_for_parameters(
         traits::ObligationCause::misc(span, fcx.body_id),
@@ -293,7 +291,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
         origin: MethodTypeParam(MethodParam{trait_ref: trait_ref.clone(),
                                             method_num: method_num}),
         ty: fty,
-        substs: trait_ref.substs().clone()
+        substs: trait_ref.substs.clone()
     };
 
     debug!("callee = {}", callee.repr(fcx.tcx()));
@@ -379,7 +377,7 @@ fn report_candidates(fcx: &FnCtxt,
                         None => format!(""),
                         Some(trait_ref) => format!(" of the trait `{}`",
                                                    ty::item_path_str(fcx.tcx(),
-                                                                     trait_ref.def_id())),
+                                                                     trait_ref.def_id)),
                     };
 
                     span_note!(fcx.sess(), method_span,
index fc1aa59c4deb3c4851cec7ce73f840fb1cf5e2b6..b5776f9aeb34ac158fece9de0fd969014ac8d620 100644 (file)
@@ -19,7 +19,6 @@
 use middle::subst::Subst;
 use middle::traits;
 use middle::ty::{mod, Ty};
-use middle::ty::{MethodObject};
 use middle::ty_fold::TypeFoldable;
 use middle::infer;
 use middle::infer::InferCtxt;
@@ -58,8 +57,8 @@ struct Candidate<'tcx> {
 
 enum CandidateKind<'tcx> {
     InherentImplCandidate(/* Impl */ ast::DefId, subst::Substs<'tcx>),
-    ObjectCandidate(MethodObject<'tcx>),
-    ExtensionImplCandidate(/* Impl */ ast::DefId, Rc<ty::PolyTraitRef<'tcx>>,
+    ObjectCandidate(/* Trait */ ast::DefId, /* method_num */ uint, /* real_index */ uint),
+    ExtensionImplCandidate(/* Impl */ ast::DefId, Rc<ty::TraitRef<'tcx>>,
                            subst::Substs<'tcx>, MethodIndex),
     UnboxedClosureCandidate(/* Trait */ ast::DefId, MethodIndex),
     WhereClauseCandidate(Rc<ty::PolyTraitRef<'tcx>>, MethodIndex),
@@ -149,7 +148,7 @@ pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     // this creates one big transaction so that all type variables etc
     // that we create during the probe process are removed later
     let mut dummy = Some((steps, opt_simplified_steps)); // FIXME(#18101) need once closures
-    fcx.infcx().probe(|| {
+    fcx.infcx().probe(|_| {
         let (steps, opt_simplified_steps) = dummy.take().unwrap();
         let mut probe_cx = ProbeContext::new(fcx, span, method_name, steps, opt_simplified_steps);
         probe_cx.assemble_inherent_candidates();
@@ -313,12 +312,7 @@ fn assemble_inherent_candidates_from_object(&mut self,
             this.inherent_candidates.push(Candidate {
                 xform_self_ty: xform_self_ty,
                 method_ty: m,
-                kind: ObjectCandidate(MethodObject {
-                    trait_ref: new_trait_ref,
-                    object_trait_id: trait_ref.def_id(),
-                    method_num: method_num,
-                    real_index: vtable_index
-                })
+                kind: ObjectCandidate(new_trait_ref.def_id(), method_num, vtable_index)
             });
         });
     }
@@ -502,7 +496,7 @@ fn assemble_extension_candidates_for_trait_impls(&mut self,
 
             // Determine the receiver type that the method itself expects.
             let xform_self_ty =
-                self.xform_self_ty(&method, impl_trait_ref.substs());
+                self.xform_self_ty(&method, &impl_trait_ref.substs);
 
             debug!("xform_self_ty={}", xform_self_ty.repr(self.tcx()));
 
@@ -748,7 +742,7 @@ fn consider_probe(&self, self_ty: Ty<'tcx>, probe: &Candidate<'tcx>) -> bool {
                self_ty.repr(self.tcx()),
                probe.repr(self.tcx()));
 
-        self.infcx().probe(|| {
+        self.infcx().probe(|_| {
             // First check that the self type can be related.
             match self.make_sub_ty(self_ty, probe.xform_self_ty) {
                 Ok(()) => { }
@@ -1033,8 +1027,8 @@ fn to_unadjusted_pick(&self) -> Pick<'tcx> {
                 InherentImplCandidate(def_id, _) => {
                     InherentImplPick(def_id)
                 }
-                ObjectCandidate(ref data) => {
-                    ObjectPick(data.trait_ref.def_id(), data.method_num, data.real_index)
+                ObjectCandidate(def_id, method_num, real_index) => {
+                    ObjectPick(def_id, method_num, real_index)
                 }
                 ExtensionImplCandidate(def_id, _, _, index) => {
                     ExtensionImplPick(def_id, index)
@@ -1059,7 +1053,7 @@ fn to_unadjusted_pick(&self) -> Pick<'tcx> {
     fn to_source(&self) -> CandidateSource {
         match self.kind {
             InherentImplCandidate(def_id, _) => ImplSource(def_id),
-            ObjectCandidate(ref obj) => TraitSource(obj.trait_ref.def_id()),
+            ObjectCandidate(def_id, _, _) => TraitSource(def_id),
             ExtensionImplCandidate(def_id, _, _, _) => ImplSource(def_id),
             UnboxedClosureCandidate(trait_def_id, _) => TraitSource(trait_def_id),
             WhereClauseCandidate(ref trait_ref, _) => TraitSource(trait_ref.def_id()),
@@ -1075,7 +1069,9 @@ fn to_trait_data(&self) -> Option<(ast::DefId,MethodIndex)> {
             UnboxedClosureCandidate(trait_def_id, method_num) => {
                 Some((trait_def_id, method_num))
             }
-            ExtensionImplCandidate(_, ref trait_ref, _, method_num) |
+            ExtensionImplCandidate(_, ref trait_ref, _, method_num) => {
+                Some((trait_ref.def_id, method_num))
+            }
             WhereClauseCandidate(ref trait_ref, method_num) => {
                 Some((trait_ref.def_id(), method_num))
             }
@@ -1096,8 +1092,8 @@ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
         match *self {
             InherentImplCandidate(ref a, ref b) =>
                 format!("InherentImplCandidate({},{})", a.repr(tcx), b.repr(tcx)),
-            ObjectCandidate(ref a) =>
-                format!("ObjectCandidate({})", a.repr(tcx)),
+            ObjectCandidate(a, b, c) =>
+                format!("ObjectCandidate({},{},{})", a.repr(tcx), b, c),
             ExtensionImplCandidate(ref a, ref b, ref c, ref d) =>
                 format!("ExtensionImplCandidate({},{},{},{})", a.repr(tcx), b.repr(tcx),
                         c.repr(tcx), d),
index 18f009fe6c479f56ddfe169bc7bf16c93f3978fd..9e249cc449d0749b66be3bcade9d01d55f3313bf 100644 (file)
@@ -719,12 +719,7 @@ fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     let param_env = ParameterEnvironment::for_item(ccx.tcx, method.id);
 
     let fty = ty::node_id_to_type(ccx.tcx, method.id);
-    debug!("fty (raw): {}", fty.repr(ccx.tcx));
-
-    let body_id = method.pe_body().id;
-    let fty = liberate_late_bound_regions(
-        ccx.tcx, CodeExtent::from_node_id(body_id), &ty::Binder(fty));
-    debug!("fty (liberated): {}", fty.repr(ccx.tcx));
+    debug!("check_method_body: fty={}", fty.repr(ccx.tcx));
 
     check_bare_fn(ccx,
                   &*method.pe_fn_decl(),
@@ -736,11 +731,11 @@ fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
 fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                             impl_span: Span,
-                                            impl_trait_ref: &ty::PolyTraitRef<'tcx>,
+                                            impl_trait_ref: &ty::TraitRef<'tcx>,
                                             impl_items: &[ast::ImplItem]) {
     // Locate trait methods
     let tcx = ccx.tcx;
-    let trait_items = ty::trait_items(tcx, impl_trait_ref.def_id());
+    let trait_items = ty::trait_items(tcx, impl_trait_ref.def_id);
 
     // Check existing impl methods to see if they are both present in trait
     // and compatible with trait signature
@@ -834,8 +829,7 @@ trait `{}`",
     }
 
     // Check for missing items from trait
-    let provided_methods = ty::provided_trait_methods(tcx,
-                                                      impl_trait_ref.def_id());
+    let provided_methods = ty::provided_trait_methods(tcx, impl_trait_ref.def_id);
     let mut missing_methods = Vec::new();
     for trait_item in trait_items.iter() {
         match *trait_item {
@@ -894,37 +888,16 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
                              impl_m_span: Span,
                              impl_m_body_id: ast::NodeId,
                              trait_m: &ty::Method<'tcx>,
-                             impl_trait_ref: &ty::PolyTraitRef<'tcx>) {
+                             impl_trait_ref: &ty::TraitRef<'tcx>) {
     debug!("compare_impl_method(impl_trait_ref={})",
            impl_trait_ref.repr(tcx));
 
-    let impl_m_body_scope = CodeExtent::from_node_id(impl_m_body_id);
-
-    // The impl's trait ref may bind late-bound regions from the impl.
-    // Liberate them and assign them the scope of the method body.
-    //
-    // An example would be:
-    //
-    //     impl<'a> Foo<&'a T> for &'a U { ... }
-    //
-    // Here, the region parameter `'a` is late-bound, so the
-    // trait reference associated with the impl will be
-    //
-    //     for<'a> Foo<&'a T>
-    //
-    // liberating will convert this into:
-    //
-    //     Foo<&'A T>
-    //
-    // where `'A` is the `ReFree` version of `'a`.
-    let impl_trait_ref = liberate_late_bound_regions(tcx, impl_m_body_scope, impl_trait_ref);
-
     debug!("impl_trait_ref (liberated) = {}",
            impl_trait_ref.repr(tcx));
 
     let infcx = infer::new_infer_ctxt(tcx);
 
-    let trait_to_impl_substs = impl_trait_ref.substs;
+    let trait_to_impl_substs = &impl_trait_ref.substs;
 
     // Try to give more informative error messages about self typing
     // mismatches.  Note that any mismatch will also be detected
@@ -1060,7 +1033,6 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
     if !check_region_bounds_on_impl_method(tcx,
                                            impl_m_span,
                                            impl_m,
-                                           impl_m_body_scope,
                                            &trait_m.generics,
                                            &impl_m.generics,
                                            &trait_to_skol_substs,
@@ -1099,11 +1071,7 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
         .map(|trait_param_def| &trait_param_def.bounds);
     let impl_bounds =
         impl_m.generics.types.get_slice(subst::FnSpace).iter()
-        .map(|impl_param_def|
-             liberate_late_bound_regions(
-                 tcx,
-                 impl_m_body_scope,
-                 &ty::Binder(ty::Binder(impl_param_def.bounds.clone()))).0);
+        .map(|impl_param_def| &impl_param_def.bounds);
     for (i, (trait_param_bounds, impl_param_bounds)) in
         trait_bounds.zip(impl_bounds).enumerate()
     {
@@ -1164,12 +1132,9 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
         }
     }
 
-    // Compute skolemized form of impl and trait method tys. Note
-    // that we must liberate the late-bound regions from the impl.
+    // Compute skolemized form of impl and trait method tys.
     let impl_fty = ty::mk_bare_fn(tcx, impl_m.fty.clone());
     let impl_fty = impl_fty.subst(tcx, &impl_to_skol_substs);
-    let impl_fty = liberate_late_bound_regions(
-        tcx, impl_m_body_scope, &ty::Binder(impl_fty));
     let trait_fty = ty::mk_bare_fn(tcx, trait_m.fty.clone());
     let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
 
@@ -1231,7 +1196,6 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
     fn check_region_bounds_on_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
                                                 span: Span,
                                                 impl_m: &ty::Method<'tcx>,
-                                                impl_m_body_scope: CodeExtent,
                                                 trait_generics: &ty::Generics<'tcx>,
                                                 impl_generics: &ty::Generics<'tcx>,
                                                 trait_to_skol_substs: &Substs<'tcx>,
@@ -1281,16 +1245,6 @@ fn check_region_bounds_on_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
             let impl_bounds =
                 impl_param.bounds.subst(tcx, impl_to_skol_substs);
 
-            // The bounds may reference late-bound regions from the
-            // impl declaration. In that case, we want to replace
-            // those with the liberated variety so as to match the
-            // versions appearing in the `trait_to_skol_substs`.
-            // There are two-levels of binder to be aware of: the
-            // impl, and the method.
-            let impl_bounds =
-                ty::liberate_late_bound_regions(
-                    tcx, impl_m_body_scope, &ty::Binder(ty::Binder(impl_bounds))).0;
-
             debug!("check_region_bounds_on_impl_method: \
                    trait_param={} \
                    impl_param={} \
index a90422cd309745a51c48d8a592288900ed0b9ff9..c09ce3db6ddd21ed15b47c0f5c6b6be0c97e032a 100644 (file)
@@ -166,11 +166,9 @@ fn check_impl(&mut self,
 
             // Find the impl self type as seen from the "inside" --
             // that is, with all type parameters converted from bound
-            // to free, and any late-bound regions on the impl
-            // liberated.
+            // to free.
             let self_ty = ty::node_id_to_type(fcx.tcx(), item.id);
             let self_ty = self_ty.subst(fcx.tcx(), &fcx.inh.param_env.free_substs);
-            let self_ty = liberate_late_bound_regions(fcx.tcx(), item_scope, &ty::Binder(self_ty));
 
             bounds_checker.check_traits_in_ty(self_ty);
 
@@ -181,7 +179,6 @@ fn check_impl(&mut self,
                 Some(t) => { t }
             };
             let trait_ref = (*trait_ref).subst(fcx.tcx(), &fcx.inh.param_env.free_substs);
-            let trait_ref = liberate_late_bound_regions(fcx.tcx(), item_scope, &trait_ref);
 
             // There are special rules that apply to drop.
             if
index e79eac90508e9f0ee3f2292e1cb85520dd4a691b..5d0bb6622c2e144667664f5983c2c33e7b43347a 100644 (file)
@@ -18,8 +18,8 @@
 
 use metadata::csearch::{each_impl, get_impl_trait};
 use metadata::csearch;
-use middle::region;
 use middle::subst::{mod, Subst};
+use middle::ty::RegionEscape;
 use middle::ty::{ImplContainer, ImplOrTraitItemId, MethodTraitItemId};
 use middle::ty::{ParameterEnvironment, TypeTraitItemId, lookup_item_type};
 use middle::ty::{Ty, ty_bool, ty_char, ty_closure, ty_enum, ty_err};
@@ -339,7 +339,7 @@ fn add_external_impl(&self,
 
         // Record all the trait items.
         for trait_ref in associated_traits.iter() {
-            self.add_trait_impl(trait_ref.def_id(), impl_def_id);
+            self.add_trait_impl(trait_ref.def_id, impl_def_id);
         }
 
         // For any methods that use a default implementation, add them to
@@ -459,6 +459,9 @@ fn check_implementations_of_copy(&self) {
         let trait_impls = trait_impls.borrow().clone();
 
         for &impl_did in trait_impls.iter() {
+            debug!("check_implementations_of_copy: impl_did={}",
+                   impl_did.repr(tcx));
+
             if impl_did.krate != ast::LOCAL_CRATE {
                 debug!("check_implementations_of_copy(): impl not in this \
                         crate");
@@ -466,20 +469,15 @@ fn check_implementations_of_copy(&self) {
             }
 
             let self_type = self.get_self_type_for_implementation(impl_did);
+            debug!("check_implementations_of_copy: self_type={} (bound)",
+                   self_type.repr(tcx));
+
             let span = tcx.map.span(impl_did.node);
-            let param_env = ParameterEnvironment::for_item(tcx,
-                                                           impl_did.node);
+            let param_env = ParameterEnvironment::for_item(tcx, impl_did.node);
             let self_type = self_type.ty.subst(tcx, &param_env.free_substs);
+            assert!(!self_type.has_escaping_regions());
 
-            // the self-type may have late-bound regions bound in the
-            // impl; liberate them.
-            let item_scope = region::CodeExtent::from_node_id(impl_did.node);
-            let self_type =
-                ty::liberate_late_bound_regions(tcx,
-                                                item_scope,
-                                                &ty::Binder(self_type));
-
-            debug!("can_type_implement_copy(self_type={})",
+            debug!("check_implementations_of_copy: self_type={} (free)",
                    self_type.repr(tcx));
 
             match ty::can_type_implement_copy(tcx, self_type, &param_env) {
index 6a24bdbb9f0ed7f21f237581cf3efb13d84b593e..07a84846c47ad26d96192b791939b2030dff9a84 100644 (file)
@@ -45,7 +45,7 @@ fn visit_item(&mut self, item: &'v ast::Item) {
                     }
 
                     Some(trait_ref) => {
-                        let trait_def = ty::lookup_trait_def(self.tcx, trait_ref.def_id());
+                        let trait_def = ty::lookup_trait_def(self.tcx, trait_ref.def_id);
                         match (trait_def.unsafety, unsafety) {
                             (ast::Unsafety::Normal, ast::Unsafety::Unsafe) => {
                                 self.tcx.sess.span_err(
index 485f0ca84304debebcd5e9ca1c73c4078ecbd410..280b42f0959d28839182f2cff7a1fb70646d2406 100644 (file)
@@ -43,8 +43,8 @@
 use middle::subst;
 use middle::subst::{Substs};
 use middle::ty::{AsPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
-use middle::ty::{mod, Ty, Polytype};
-use middle::ty_fold::{mod, TypeFolder};
+use middle::ty::{mod, RegionEscape, Ty, Polytype};
+use middle::ty_fold::{mod, TypeFolder, TypeFoldable};
 use middle::infer;
 use rscope::*;
 use {CrateCtxt, lookup_def_tcx, no_params, write_ty_to_tcx};
@@ -226,7 +226,7 @@ pub fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
             ast::StructVariantKind(ref struct_def) => {
                 let pty = Polytype {
-                    generics: ty_generics_for_type(
+                    generics: ty_generics_for_type_or_impl(
                         ccx,
                         generics,
                         DontCreateTypeParametersForAssociatedTypes),
@@ -239,7 +239,7 @@ pub fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         };
 
         let pty = Polytype {
-            generics: ty_generics_for_type(
+            generics: ty_generics_for_type_or_impl(
                           ccx,
                           generics,
                           DontCreateTypeParametersForAssociatedTypes),
@@ -1050,7 +1050,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
                       ref selfty,
                       ref impl_items) => {
             // Create generics from the generics specified in the impl head.
-            let ty_generics = ty_generics_for_impl(
+            let ty_generics = ty_generics_for_type_or_impl(
                     ccx,
                     generics,
                     CreateTypeParametersForAssociatedTypes);
@@ -1482,7 +1482,7 @@ pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item)
             let pty = {
                 let ty = ccx.to_ty(&ExplicitRscope, &**t);
                 Polytype {
-                    generics: ty_generics_for_type(
+                    generics: ty_generics_for_type_or_impl(
                                   ccx,
                                   generics,
                                   DontCreateTypeParametersForAssociatedTypes),
@@ -1495,7 +1495,7 @@ pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item)
         }
         ast::ItemEnum(_, ref generics) => {
             // Create a new generic polytype.
-            let ty_generics = ty_generics_for_type(
+            let ty_generics = ty_generics_for_type_or_impl(
                 ccx,
                 generics,
                 DontCreateTypeParametersForAssociatedTypes);
@@ -1513,7 +1513,7 @@ pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item)
             tcx.sess.span_bug(it.span, "invoked ty_of_item on trait");
         }
         ast::ItemStruct(_, ref generics) => {
-            let ty_generics = ty_generics_for_type(
+            let ty_generics = ty_generics_for_type_or_impl(
                 ccx,
                 generics,
                 DontCreateTypeParametersForAssociatedTypes);
@@ -1580,11 +1580,11 @@ fn ty_of_trait_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     }
 }
 
-fn ty_generics_for_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                                  generics: &ast::Generics,
-                                  create_type_parameters_for_associated_types:
-                                      CreateTypeParametersForAssociatedTypesFlag)
-                                  -> ty::Generics<'tcx> {
+fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+                                          generics: &ast::Generics,
+                                          create_type_parameters_for_associated_types:
+                                          CreateTypeParametersForAssociatedTypesFlag)
+                                          -> ty::Generics<'tcx> {
     ty_generics(ccx,
                 subst::TypeSpace,
                 generics.lifetimes.as_slice(),
@@ -1664,24 +1664,6 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     generics
 }
 
-fn ty_generics_for_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                                  generics: &ast::Generics,
-                                  create_type_parameters_for_associated_types:
-                                      CreateTypeParametersForAssociatedTypesFlag)
-                                  -> ty::Generics<'tcx>
-{
-    let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
-    debug!("ty_generics_for_impl: early_lifetimes={}",
-           early_lifetimes);
-    ty_generics(ccx,
-                subst::TypeSpace,
-                early_lifetimes.as_slice(),
-                generics.ty_params.as_slice(),
-                ty::Generics::empty(),
-                &generics.where_clause,
-                create_type_parameters_for_associated_types)
-}
-
 fn ty_generics_for_fn_or_method<'tcx,AC>(
         this: &AC,
         generics: &ast::Generics,
@@ -2186,8 +2168,12 @@ pub fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     subst::Substs::new(types, regions)
 }
 
-/// Verifies that the explicit self type of a method matches the impl or
-/// trait.
+/// Verifies that the explicit self type of a method matches the impl
+/// or trait. This is a bit weird but basically because right now we
+/// don't handle the general case, but instead map it to one of
+/// several pre-defined options using various heuristics, this method
+/// comes back to check after the fact that explicit type the user
+/// wrote actually matches what the pre-defined option said.
 fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
     crate_context: &CrateCtxt<'a, 'tcx>,
     rs: &RS,
@@ -2209,19 +2195,21 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
         // contain late-bound regions from the method, but not the
         // trait (since traits only have early-bound region
         // parameters).
-        assert!(!ty::type_escapes_depth(required_type, 1));
+        assert!(!base_type.has_regions_escaping_depth(1));
         let required_type_free =
-            ty::liberate_late_bound_regions(
-                crate_context.tcx, body_scope, &ty::Binder(required_type));
+            liberate_early_bound_regions(
+                crate_context.tcx, body_scope,
+                &ty::liberate_late_bound_regions(
+                    crate_context.tcx, body_scope, &ty::Binder(required_type)));
 
-        // The "base type" comes from the impl. It may have late-bound
-        // regions from the impl or the method.
+        // The "base type" comes from the impl. It too may have late-bound
+        // regions from the method.
+        assert!(!base_type.has_regions_escaping_depth(1));
         let base_type_free =
-            ty::liberate_late_bound_regions( // liberate impl regions:
+            liberate_early_bound_regions(
                 crate_context.tcx, body_scope,
-                &ty::liberate_late_bound_regions( // liberate method regions:
-                    crate_context.tcx, body_scope,
-                    &ty::Binder(ty::Binder(base_type))));
+                &ty::liberate_late_bound_regions(
+                    crate_context.tcx, body_scope, &ty::Binder(base_type)));
 
         debug!("required_type={} required_type_free={} \
                 base_type={} base_type_free={}",
@@ -2242,4 +2230,30 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
         }));
         infcx.resolve_regions_and_report_errors(body_id);
     }
+
+    fn liberate_early_bound_regions<'tcx,T>(
+        tcx: &ty::ctxt<'tcx>,
+        scope: region::CodeExtent,
+        value: &T)
+        -> T
+        where T : TypeFoldable<'tcx> + Repr<'tcx>
+    {
+        /*!
+         * Convert early-bound regions into free regions; normally this is done by
+         * applying the `free_substs` from the `ParameterEnvironment`, but this particular
+         * method-self-type check is kind of hacky and done very early in the process,
+         * before we really have a `ParameterEnvironment` to check.
+         */
+
+        ty_fold::fold_regions(tcx, value, |region, _| {
+            match region {
+                ty::ReEarlyBound(id, _, _, name) => {
+                    let def_id = local_def(id);
+                    ty::ReFree(ty::FreeRegion { scope: scope,
+                                                bound_region: ty::BrNamed(def_id, name) })
+                }
+                _ => region
+            }
+        })
+    }
 }
index 49e45c9e56ca4fb7c9cd3183368d0bb75f145689..d0988af1cb473f9b857fe069a88a5dd79e3d26e4 100644 (file)
@@ -281,7 +281,7 @@ fn build_impl(cx: &DocContext, tcx: &ty::ctxt,
     // If this is an impl for a #[doc(hidden)] trait, be sure to not inline it.
     match associated_trait {
         Some(ref t) => {
-            let trait_attrs = load_attrs(cx, tcx, t.def_id());
+            let trait_attrs = load_attrs(cx, tcx, t.def_id);
             if trait_attrs.iter().any(|a| is_doc_hidden(a)) {
                 return None
             }
diff --git a/src/test/compile-fail/hrtb-conflate-regions.rs b/src/test/compile-fail/hrtb-conflate-regions.rs
new file mode 100644 (file)
index 0000000..670e871
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test what an impl with only one bound region `'a` cannot be used to
+// satisfy a constraint whre there are two bound regions.
+
+trait Foo<X> {
+    fn foo(&self, x: X) { }
+}
+
+fn want_foo2<T>()
+    where T : for<'a,'b> Foo<(&'a int, &'b int)>
+{
+}
+
+fn want_foo1<T>()
+    where T : for<'z> Foo<(&'z int, &'z int)>
+{
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Expressed as a where clause
+
+struct SomeStruct;
+
+impl<'a> Foo<(&'a int, &'a int)> for SomeStruct
+{
+}
+
+fn a() { want_foo1::<SomeStruct>(); } // OK -- foo wants just one region
+fn b() { want_foo2::<SomeStruct>(); } //~ ERROR not implemented
+
+fn main() { }
diff --git a/src/test/compile-fail/hrtb-just-for-static.rs b/src/test/compile-fail/hrtb-just-for-static.rs
new file mode 100644 (file)
index 0000000..b21bae5
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test a case where you have an impl of `Foo<X>` for all `X` that
+// is being applied to `for<'a> Foo<&'a mut X>`. Issue #19730.
+
+trait Foo<X> {
+    fn foo(&self, x: X) { }
+}
+
+fn want_hrtb<T>()
+    where T : for<'a> Foo<&'a int>
+{
+}
+
+// AnyInt implements Foo<&'a int> for any 'a, so it is a match.
+struct AnyInt;
+impl<'a> Foo<&'a int> for AnyInt { }
+fn give_any() {
+    want_hrtb::<AnyInt>()
+}
+
+// StaticInt only implements Foo<&'a int> for 'a, so it is an error.
+struct StaticInt;
+impl Foo<&'static int> for StaticInt { }
+fn give_static() {
+    want_hrtb::<StaticInt>() //~ ERROR `for<'a> Foo<&'a int>` is not implemented
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/hrtb-perfect-forwarding.rs b/src/test/compile-fail/hrtb-perfect-forwarding.rs
new file mode 100644 (file)
index 0000000..a8ee215
--- /dev/null
@@ -0,0 +1,66 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test a case where you have an impl of `Foo<X>` for all `X` that
+// is being applied to `for<'a> Foo<&'a mut X>`. Issue #19730.
+
+trait Foo<X> {
+    fn foo(&mut self, x: X) { }
+}
+
+trait Bar<X> {
+    fn bar(&mut self, x: X) { }
+}
+
+impl<'a,X,F> Foo<X> for &'a mut F
+    where F : Foo<X> + Bar<X>
+{
+}
+
+impl<'a,X,F> Bar<X> for &'a mut F
+    where F : Bar<X>
+{
+}
+
+fn no_hrtb<'b,T>(mut t: T)
+    where T : Bar<&'b int>
+{
+    // OK -- `T : Bar<&'b int>`, and thus the impl above ensures that
+    // `&mut T : Bar<&'b int>`.
+    no_hrtb(&mut t);
+}
+
+fn bar_hrtb<T>(mut t: T)
+    where T : for<'b> Bar<&'b int>
+{
+    // OK -- `T : for<'b> Bar<&'b int>`, and thus the impl above
+    // ensures that `&mut T : for<'b> Bar<&'b int>`.  This is an
+    // example of a "perfect forwarding" impl.
+    bar_hrtb(&mut t);
+}
+
+fn foo_hrtb_bar_not<'b,T>(mut t: T)
+    where T : for<'a> Foo<&'a int> + Bar<&'b int>
+{
+    // Not OK -- The forwarding impl for `Foo` requires that `Bar` also
+    // be implemented. Thus to satisfy `&mut T : for<'a> Foo<&'a
+    // int>`, we require `T : for<'a> Bar<&'a int>`, but the where
+    // clause only specifies `T : Bar<&'b int>`.
+    foo_hrtb_bar_not(&mut t); //~ ERROR `for<'a> Bar<&'a int>` is not implemented for the type `T`
+}
+
+fn foo_hrtb_bar_hrtb<T>(mut t: T)
+    where T : for<'a> Foo<&'a int> + for<'b> Bar<&'b int>
+{
+    // OK -- now we have `T : for<'b> Bar&'b int>`.
+    foo_hrtb_bar_hrtb(&mut t);
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/hrtb-type-outlives.rs b/src/test/compile-fail/hrtb-type-outlives.rs
new file mode 100644 (file)
index 0000000..9a326aa
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test what happens when a HR obligation is applie to an impl with
+// "outlives" bounds. Currently we're pretty conservative here; this
+// will probably improve in time.
+
+trait Foo<X> {
+    fn foo(&self, x: X) { }
+}
+
+fn want_foo<T>()
+    where T : for<'a> Foo<&'a int>
+{
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Expressed as a where clause
+
+struct SomeStruct<X> {
+    x: X
+}
+
+impl<'a,X> Foo<&'a int> for SomeStruct<X>
+    where X : 'a
+{
+}
+
+fn one() {
+    // In fact there is no good reason for this to be an error, but
+    // whatever, I'm mostly concerned it doesn't ICE right now:
+    want_foo::<SomeStruct<uint>>();
+    //~^ ERROR requirement `for<'a> uint : 'a` is not satisfied
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Expressed as shorthand
+
+struct AnotherStruct<X> {
+    x: X
+}
+
+impl<'a,X:'a> Foo<&'a int> for AnotherStruct<X>
+{
+}
+
+fn two() {
+    want_foo::<AnotherStruct<uint>>();
+    //~^ ERROR requirement `for<'a> uint : 'a` is not satisfied
+}
+
+fn main() { }
index 01a15023fbaada5f68e74d61ceb027b95b5d2c00..d03885ca7133c57609af0bbb094a4baaa4c37525 100644 (file)
@@ -11,5 +11,4 @@
 fn main() {
     let _x = "test" as &::std::any::Any;
 //~^ ERROR the trait `core::kinds::Sized` is not implemented for the type `str`
-//~^^ ERROR the trait `core::kinds::Sized` is not implemented for the type `str`
 }
index 51ee38d5cfed2af9c3a4483e0e8461b914cfcd55..f5740992af48eadba48e8fd4b2103f5b0d684950 100644 (file)
@@ -21,10 +21,15 @@ impl<T:Copy> Foo for T {
 
 fn take_param<T:Foo>(foo: &T) { }
 
-fn main() {
+fn a() {
     let x = box 3i;
     take_param(&x); //~ ERROR `core::kinds::Copy` is not implemented
+}
 
+fn b() {
+    let x = box 3i;
     let y = &x;
     let z = &x as &Foo; //~ ERROR `core::kinds::Copy` is not implemented
 }
+
+fn main() { }
index a82689b16491ea048b4fef78840bf74298454727..b0b37d077c1709f3d5dfb75614c089aced53abb6 100644 (file)
@@ -20,9 +20,16 @@ fn call_it<F:Fn(&int)->int>(_: &F, _: int) -> int { 0 }
 fn call_it_mut<F:FnMut(&int)->int>(_: &mut F, _: int) -> int { 0 }
 fn call_it_once<F:FnOnce(&int)->int>(_: F, _: int) -> int { 0 }
 
-fn main() {
+fn a() {
     let x = call_it(&square, 22); //~ ERROR not implemented
+}
+
+fn b() {
     let y = call_it_mut(&mut square, 22); //~ ERROR not implemented
+}
+
+fn c() {
     let z = call_it_once(square, 22); //~ ERROR not implemented
 }
 
+fn main() { }
index 920e91958ee9e002079502650fcd679cf099a349..20a4ab85d7ba8e434688e27333fb15bfde997d58 100644 (file)
@@ -20,9 +20,17 @@ fn call_it<F:Fn(&int)->int>(_: &F, _: int) -> int { 0 }
 fn call_it_mut<F:FnMut(&int)->int>(_: &mut F, _: int) -> int { 0 }
 fn call_it_once<F:FnOnce(&int)->int>(_: F, _: int) -> int { 0 }
 
-fn main() {
+fn a() {
     let x = call_it(&square, 22); //~ ERROR not implemented
+}
+
+fn b() {
     let y = call_it_mut(&mut square, 22); //~ ERROR not implemented
+}
+
+fn c() {
     let z = call_it_once(square, 22); //~ ERROR not implemented
 }
 
+fn main() { }
+
index a7a7b1c676267a97ac0eb42e4699c00b72450424..f08cff3cd682137ac517bda985cff47e5081edf8 100644 (file)
@@ -21,9 +21,16 @@ fn call_it<F:Fn(&int)->int>(_: &F, _: int) -> int { 0 }
 fn call_it_mut<F:FnMut(&int)->int>(_: &mut F, _: int) -> int { 0 }
 fn call_it_once<F:FnOnce(&int)->int>(_: F, _: int) -> int { 0 }
 
-fn main() {
+fn a() {
     let x = call_it(&square, 22); //~ ERROR not implemented
+}
+
+fn b() {
     let y = call_it_mut(&mut square, 22); //~ ERROR not implemented
+}
+
+fn c() {
     let z = call_it_once(square, 22); //~ ERROR not implemented
 }
 
+fn main() { }