]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_typeck/astconv.rs
Fix impl Trait Lifetime Handling
[rust.git] / src / librustc_typeck / astconv.rs
index 7aaf65e1fd07d583e28febabc244132cc064070f..2405461741daa7c75f4334df6f5e94e7837a63d3 100644 (file)
@@ -21,7 +21,7 @@
 use namespace::Namespace;
 use rustc::ty::subst::{Kind, Subst, Substs};
 use rustc::traits;
-use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
+use rustc::ty::{self, RegionKind, Ty, TyCtxt, ToPredicate, TypeFoldable};
 use rustc::ty::wf::object_region_bounds;
 use rustc_back::slice;
 use require_c_abi_if_variadic;
@@ -1034,9 +1034,9 @@ pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> {
             hir::TyTraitObject(ref bounds, ref lifetime) => {
                 self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime)
             }
-            hir::TyImplTraitExistential(_) => {
+            hir::TyImplTraitExistential(_, ref lifetimes) => {
                 let def_id = tcx.hir.local_def_id(ast_ty.id);
-                tcx.mk_anon(def_id, Substs::identity_for_item(tcx, def_id))
+                self.impl_trait_ty_to_ty(def_id, lifetimes)
             }
             hir::TyImplTraitUniversal(fn_def_id, _) => {
                 let impl_trait_def_id = tcx.hir.local_def_id(ast_ty.id);
@@ -1097,6 +1097,43 @@ pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> {
         result_ty
     }
 
+    pub fn impl_trait_ty_to_ty(&self, def_id: DefId, lifetimes: &[hir::Lifetime]) -> Ty<'tcx> {
+        debug!("impl_trait_ty_to_ty(def_id={:?}, lifetimes={:?})", def_id, lifetimes);
+        let tcx = self.tcx();
+        let generics = tcx.generics_of(def_id);
+
+        // Fill in the substs of the parent generics
+        debug!("impl_trait_ty_to_ty: generics={:?}", generics);
+        let mut substs = Vec::with_capacity(generics.count());
+        if let Some(parent_id) = generics.parent {
+            let parent_generics = tcx.generics_of(parent_id);
+            Substs::fill_item(
+                &mut substs, tcx, parent_generics,
+                &mut |def, _| tcx.mk_region(
+                    ty::ReEarlyBound(def.to_early_bound_region_data())),
+                &mut |def, _| tcx.mk_param_from_def(def)
+            );
+
+            // Replace all lifetimes with 'static
+            for subst in &mut substs {
+                if let Some(_) = subst.as_region() {
+                    *subst = Kind::from(&RegionKind::ReStatic);
+                }
+            }
+            debug!("impl_trait_ty_to_ty: substs from parent = {:?}", substs);
+        }
+        assert_eq!(substs.len(), generics.parent_count());
+
+        // Fill in our own generics with the resolved lifetimes
+        assert_eq!(lifetimes.len(), generics.own_count());
+        substs.extend(lifetimes.iter().map(|lt|
+            Kind::from(self.ast_region_to_region(lt, None))));
+
+        debug!("impl_trait_ty_to_ty: final substs = {:?}", substs);
+
+        tcx.mk_anon(def_id, tcx.intern_substs(&substs))
+    }
+
     pub fn ty_of_arg(&self,
                      ty: &hir::Ty,
                      expected_ty: Option<Ty<'tcx>>)