about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2017-01-13 15:10:37 +0200
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2017-01-28 02:56:46 +0200
commit9783947c2adfcadba3c0e036548cf6fd3e12553a (patch)
tree1f63beb28b7bc1b10a11ea0f8ad671e1343dbb1e
parentba1849daecf0ae8fee54cc32f378809a9531e5ed (diff)
downloadrust-9783947c2adfcadba3c0e036548cf6fd3e12553a.tar.gz
rust-9783947c2adfcadba3c0e036548cf6fd3e12553a.zip
rustc_typeck: move impl Trait checks out of RegionScope.
-rw-r--r--src/librustc_typeck/astconv.rs94
-rw-r--r--src/librustc_typeck/collect.rs32
-rw-r--r--src/librustc_typeck/lib.rs1
-rw-r--r--src/librustc_typeck/rscope.rs79
-rw-r--r--src/test/compile-fail/impl-trait/disallowed.rs2
5 files changed, 65 insertions, 143 deletions
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 42a220e1b9b..90efe7cad39 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -62,7 +62,7 @@ use rustc::ty::wf::object_region_bounds;
 use rustc_back::slice;
 use require_c_abi_if_variadic;
 use rscope::{RegionScope, ObjectLifetimeDefaultRscope, ShiftedRscope};
-use rscope::{AnonTypeScope, MaybeWithAnonTypes, ExplicitRscope};
+use rscope::ExplicitRscope;
 use util::common::{ErrorReported, FN_OUTPUT_NAME};
 use util::nodemap::{NodeMap, FxHashSet};
 
@@ -361,8 +361,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                     }
                     hir::ParenthesizedParameters(ref data) => {
                         assert_eq!(i, 0);
-                        let (ty, assoc) =
-                            self.convert_parenthesized_parameters(rscope, substs, data);
+                        let (ty, assoc) = self.convert_parenthesized_parameters(substs, data);
                         output_assoc_binding = Some(assoc);
                         ty
                     }
@@ -416,7 +415,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                 vec![output_assoc_binding.unwrap_or_else(|| {
                     // This is an error condition, but we should
                     // get the associated type binding anyway.
-                    self.convert_parenthesized_parameters(rscope, substs, data).1
+                    self.convert_parenthesized_parameters(substs, data).1
                 })]
             }
         };
@@ -428,20 +427,17 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
     }
 
     fn convert_parenthesized_parameters(&self,
-                                        rscope: &RegionScope,
                                         region_substs: &[Kind<'tcx>],
                                         data: &hir::ParenthesizedParameterData)
                                         -> (Ty<'tcx>, ConvertedBinding<'tcx>)
     {
-        let anon_scope = rscope.anon_type_scope();
-        let rscope = MaybeWithAnonTypes::new(ExplicitRscope, anon_scope);
         let inputs = self.tcx().mk_type_list(data.inputs.iter().map(|a_t| {
-            self.ast_ty_arg_to_ty(&rscope, None, region_substs, a_t)
+            self.ast_ty_arg_to_ty(&ExplicitRscope, None, region_substs, a_t)
         }));
 
         let (output, output_span) = match data.output {
             Some(ref output_ty) => {
-                (self.ast_ty_to_ty(&rscope, output_ty), output_ty.span)
+                (self.ast_ty_to_ty(&ExplicitRscope, output_ty), output_ty.span)
             }
             None => {
                 (self.tcx().mk_nil(), data.span)
@@ -1309,12 +1305,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
             }
             hir::TyBareFn(ref bf) => {
                 require_c_abi_if_variadic(tcx, &bf.decl, bf.abi, ast_ty.span);
-                let anon_scope = rscope.anon_type_scope();
-                let bare_fn_ty = self.ty_of_method_or_bare_fn(bf.unsafety,
-                                                              bf.abi,
-                                                              &bf.decl,
-                                                              anon_scope,
-                                                              anon_scope);
+                let bare_fn_ty = self.ty_of_fn(bf.unsafety, bf.abi, &bf.decl);
 
                 // Find any late-bound regions declared in return type that do
                 // not appear in the arguments. These are not wellformed.
@@ -1361,16 +1352,54 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
             hir::TyImplTrait(ref bounds) => {
                 use collect::{compute_bounds, SizedByDefault};
 
+                // Figure out if we can allow an `impl Trait` here, by walking up
+                // to a `fn` or inherent `impl` method, going only through `Ty`
+                // or `TraitRef` nodes (as nothing else should be in types) and
+                // ensuring that we reach the `fn`/method signature's return type.
+                let mut node_id = ast_ty.id;
+                let fn_decl = loop {
+                    let parent = tcx.hir.get_parent_node(node_id);
+                    match tcx.hir.get(parent) {
+                        hir::map::NodeItem(&hir::Item {
+                            node: hir::ItemFn(ref fn_decl, ..), ..
+                        }) => break Some(fn_decl),
+
+                        hir::map::NodeImplItem(&hir::ImplItem {
+                            node: hir::ImplItemKind::Method(ref sig, _), ..
+                        }) => {
+                            match tcx.hir.expect_item(tcx.hir.get_parent(parent)).node {
+                                hir::ItemImpl(.., None, _, _) => {
+                                    break Some(&sig.decl)
+                                }
+                                _ => break None
+                            }
+                        }
+
+                        hir::map::NodeTy(_) | hir::map::NodeTraitRef(_) => {}
+
+                        _ => break None
+                    }
+                    node_id = parent;
+                };
+                let allow = fn_decl.map_or(false, |fd| {
+                    match fd.output {
+                        hir::DefaultReturn(_) => false,
+                        hir::Return(ref ty) => ty.id == node_id
+                    }
+                });
+
                 // Create the anonymized type.
-                let def_id = tcx.hir.local_def_id(ast_ty.id);
-                if let Some(anon_scope) = rscope.anon_type_scope() {
-                    let substs = anon_scope.fresh_substs(self, ast_ty.span);
+                if allow {
+                    let def_id = tcx.hir.local_def_id(ast_ty.id);
+                    if let Err(ErrorReported) = self.get_generics(ast_ty.span, def_id) {
+                        return tcx.types.err;
+                    }
+                    let substs = Substs::identity_for_item(tcx, def_id);
                     let ty = tcx.mk_anon(tcx.hir.local_def_id(ast_ty.id), substs);
 
                     // Collect the bounds, i.e. the `A+B+'c` in `impl A+B+'c`.
                     let bounds = compute_bounds(self, ty, bounds,
                                                 SizedByDefault::Yes,
-                                                Some(anon_scope),
                                                 ast_ty.span);
                     let predicates = bounds.predicates(tcx, ty);
                     let predicates = tcx.lift_to_global(&predicates).unwrap();
@@ -1450,36 +1479,19 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
     pub fn ty_of_fn(&self,
                     unsafety: hir::Unsafety,
                     abi: abi::Abi,
-                    decl: &hir::FnDecl,
-                    anon_scope: Option<AnonTypeScope>)
+                    decl: &hir::FnDecl)
                     -> &'tcx ty::BareFnTy<'tcx> {
-        self.ty_of_method_or_bare_fn(unsafety, abi, decl, None, anon_scope)
-    }
-
-    fn ty_of_method_or_bare_fn(&self,
-                               unsafety: hir::Unsafety,
-                               abi: abi::Abi,
-                               decl: &hir::FnDecl,
-                               arg_anon_scope: Option<AnonTypeScope>,
-                               ret_anon_scope: Option<AnonTypeScope>)
-                               -> &'tcx ty::BareFnTy<'tcx>
-    {
-        debug!("ty_of_method_or_bare_fn");
-
-        // New region names that appear inside of the arguments of the function
-        // declaration are bound to that function type.
-        let rb = MaybeWithAnonTypes::new(ExplicitRscope, arg_anon_scope);
+        debug!("ty_of_fn");
 
         let input_tys: Vec<Ty> =
-            decl.inputs.iter().map(|a| self.ty_of_arg(&rb, a, None)).collect();
+            decl.inputs.iter().map(|a| self.ty_of_arg(&ExplicitRscope, a, None)).collect();
 
         let output_ty = match decl.output {
-            hir::Return(ref output) =>
-                self.ast_ty_to_ty(&MaybeWithAnonTypes::new(ExplicitRscope, ret_anon_scope), output),
+            hir::Return(ref output) => self.ast_ty_to_ty(&ExplicitRscope, output),
             hir::DefaultReturn(..) => self.tcx().mk_nil(),
         };
 
-        debug!("ty_of_method_or_bare_fn: output_ty={:?}", output_ty);
+        debug!("ty_of_fn: output_ty={:?}", output_ty);
 
         self.tcx().mk_bare_fn(ty::BareFnTy {
             unsafety: unsafety,
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 70bd43751eb..1bfa4fc7b68 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -641,7 +641,6 @@ fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 }
 
 fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                            container: AssociatedItemContainer,
                             id: ast::NodeId,
                             sig: &hir::MethodSig,
                             rcvr_ty_predicates: &ty::GenericPredicates<'tcx>,) {
@@ -651,12 +650,8 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     let ty_generic_predicates =
         ty_generic_predicates(ccx, &sig.generics, ty_generics.parent, vec![], false);
 
-    let anon_scope = match container {
-        ImplContainer(_) => Some(AnonTypeScope::new(def_id)),
-        TraitContainer(_) => None
-    };
     let fty = AstConv::ty_of_fn(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
-                                sig.unsafety, sig.abi, &sig.decl, anon_scope);
+                                sig.unsafety, sig.abi, &sig.decl);
 
     let substs = mk_item_substs(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
                                 ccx.tcx.hir.span(id), def_id);
@@ -874,8 +869,7 @@ fn convert_trait_item(ccx: &CrateCtxt, trait_item: &hir::TraitItem) {
         }
 
         hir::TraitItemKind::Method(ref sig, _) => {
-            convert_method(ccx, TraitContainer(trait_def_id),
-                           trait_item.id, sig, &trait_predicates);
+            convert_method(ccx, trait_item.id, sig, &trait_predicates);
         }
     }
 }
@@ -915,7 +909,7 @@ fn convert_impl_item(ccx: &CrateCtxt, impl_item: &hir::ImplItem) {
         }
 
         hir::ImplItemKind::Method(ref sig, _) => {
-            convert_method(ccx, ImplContainer(impl_def_id), impl_item.id, sig, &impl_predicates);
+            convert_method(ccx, impl_item.id, sig, &impl_predicates);
         }
     }
 }
@@ -1186,7 +1180,6 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt,
                                           self_param_ty,
                                           bounds,
                                           SizedByDefault::No,
-                                          None,
                                           item.span);
 
         let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
@@ -1323,7 +1316,6 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item)
                                         assoc_ty,
                                         bounds,
                                         SizedByDefault::Yes,
-                                        None,
                                         trait_item.span);
 
             bounds.predicates(ccx.tcx, assoc_ty).into_iter()
@@ -1537,8 +1529,7 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                         ccx.icx(&()).to_ty(&ExplicitRscope, &t)
                     }
                     ItemFn(ref decl, unsafety, _, abi, ref generics, _) => {
-                        let tofd = AstConv::ty_of_fn(&ccx.icx(generics), unsafety, abi, &decl,
-                                                     Some(AnonTypeScope::new(def_id)));
+                        let tofd = AstConv::ty_of_fn(&ccx.icx(generics), unsafety, abi, &decl);
                         let substs = mk_item_substs(&ccx.icx(generics), item.span, def_id);
                         ccx.tcx.mk_fn_def(def_id, substs, tofd)
                     }
@@ -1770,7 +1761,6 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                                     param_ty,
                                     &param.bounds,
                                     SizedByDefault::Yes,
-                                    None,
                                     param.span);
         predicates.extend(bounds.predicates(ccx.tcx, param_ty));
     }
@@ -1968,7 +1958,6 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
                                         param_ty: ty::Ty<'tcx>,
                                         ast_bounds: &[hir::TyParamBound],
                                         sized_by_default: SizedByDefault,
-                                        anon_scope: Option<AnonTypeScope>,
                                         span: Span)
                                         -> Bounds<'tcx>
 {
@@ -1979,9 +1968,8 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
 
     let mut projection_bounds = vec![];
 
-    let rscope = MaybeWithAnonTypes::new(ExplicitRscope, anon_scope);
     let mut trait_bounds: Vec<_> = trait_bounds.iter().map(|&bound| {
-        astconv.instantiate_poly_trait_ref(&rscope,
+        astconv.instantiate_poly_trait_ref(&ExplicitRscope,
                                            bound,
                                            param_ty,
                                            &mut projection_bounds)
@@ -2048,7 +2036,7 @@ fn compute_type_of_foreign_fn_decl<'a, 'tcx>(
     abi: abi::Abi)
     -> Ty<'tcx>
 {
-    let fty = AstConv::ty_of_fn(&ccx.icx(ast_generics), hir::Unsafety::Unsafe, abi, decl, None);
+    let fty = AstConv::ty_of_fn(&ccx.icx(ast_generics), hir::Unsafety::Unsafe, abi, decl);
 
     // feature gate SIMD types in FFI, since I (huonw) am not sure the
     // ABIs are handled at all correctly.
@@ -2077,10 +2065,10 @@ fn compute_type_of_foreign_fn_decl<'a, 'tcx>(
     ccx.tcx.mk_fn_def(def_id, substs, fty)
 }
 
-pub fn mk_item_substs<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
-                                        span: Span,
-                                        def_id: DefId)
-                                        -> &'tcx Substs<'tcx> {
+fn mk_item_substs<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
+                        span: Span,
+                        def_id: DefId)
+                        -> &'tcx Substs<'tcx> {
     let tcx = astconv.tcx();
     // FIXME(eddyb) Do this request from Substs::for_item in librustc.
     if let Err(ErrorReported) = astconv.get_generics(span, def_id) {
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 0e7daa03404..90ce77cc5f4 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -77,6 +77,7 @@ This API is completely unstable and subject to change.
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(conservative_impl_trait)]
+#![feature(loop_break_value)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
diff --git a/src/librustc_typeck/rscope.rs b/src/librustc_typeck/rscope.rs
index 3ac917c396c..d982c91e388 100644
--- a/src/librustc_typeck/rscope.rs
+++ b/src/librustc_typeck/rscope.rs
@@ -8,11 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc::hir::def_id::DefId;
 use rustc::ty;
-use rustc::ty::subst::Substs;
-
-use astconv::AstConv;
 
 use syntax_pos::Span;
 
@@ -38,73 +34,6 @@ pub trait RegionScope {
     /// computing `object_lifetime_default` (in particular, in legacy
     /// modes, it may not be relevant).
     fn base_object_lifetime_default(&self, span: Span) -> ty::Region;
-
-    /// If this scope allows anonymized types, return the generics in
-    /// scope, that anonymized types will close over. For example,
-    /// if you have a function like:
-    ///
-    ///     fn foo<'a, T>() -> impl Trait { ... }
-    ///
-    /// then, for the rscope that is used when handling the return type,
-    /// `anon_type_scope()` would return a `Some(AnonTypeScope {...})`,
-    /// on which `.fresh_substs(...)` can be used to obtain identity
-    /// Substs for `'a` and `T`, to track them in `TyAnon`. This property
-    /// is controlled by the region scope because it's fine-grained enough
-    /// to allow restriction of anonymized types to the syntactical extent
-    /// of a function's return type.
-    fn anon_type_scope(&self) -> Option<AnonTypeScope> {
-        None
-    }
-}
-
-#[derive(Copy, Clone)]
-pub struct AnonTypeScope {
-    enclosing_item: DefId
-}
-
-impl<'gcx: 'tcx, 'tcx> AnonTypeScope {
-    pub fn new(enclosing_item: DefId) -> AnonTypeScope {
-        AnonTypeScope {
-            enclosing_item: enclosing_item
-        }
-    }
-
-    pub fn fresh_substs(&self, astconv: &AstConv<'gcx, 'tcx>, span: Span)
-                        -> &'tcx Substs<'tcx> {
-        use collect::mk_item_substs;
-
-        mk_item_substs(astconv, span, self.enclosing_item)
-    }
-}
-
-/// A scope wrapper which optionally allows anonymized types.
-#[derive(Copy, Clone)]
-pub struct MaybeWithAnonTypes<R> {
-    base_scope: R,
-    anon_scope: Option<AnonTypeScope>
-}
-
-impl<R: RegionScope> MaybeWithAnonTypes<R>  {
-    pub fn new(base_scope: R, anon_scope: Option<AnonTypeScope>) -> Self {
-        MaybeWithAnonTypes {
-            base_scope: base_scope,
-            anon_scope: anon_scope
-        }
-    }
-}
-
-impl<R: RegionScope> RegionScope for MaybeWithAnonTypes<R> {
-    fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
-        self.base_scope.object_lifetime_default(span)
-    }
-
-    fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
-        self.base_scope.base_object_lifetime_default(span)
-    }
-
-    fn anon_type_scope(&self) -> Option<AnonTypeScope> {
-        self.anon_scope
-    }
 }
 
 // A scope in which all regions must be explicitly named. This is used
@@ -158,10 +87,6 @@ impl<'r> RegionScope for ObjectLifetimeDefaultRscope<'r> {
     fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
         self.base_scope.base_object_lifetime_default(span)
     }
-
-    fn anon_type_scope(&self) -> Option<AnonTypeScope> {
-        self.base_scope.anon_type_scope()
-    }
 }
 
 /// A scope which simply shifts the Debruijn index of other scopes
@@ -185,8 +110,4 @@ impl<'r> RegionScope for ShiftedRscope<'r> {
     fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
         ty::fold::shift_region(self.base_scope.base_object_lifetime_default(span), 1)
     }
-
-    fn anon_type_scope(&self) -> Option<AnonTypeScope> {
-        self.base_scope.anon_type_scope()
-    }
 }
diff --git a/src/test/compile-fail/impl-trait/disallowed.rs b/src/test/compile-fail/impl-trait/disallowed.rs
index 09aba5d8c91..0467c49b031 100644
--- a/src/test/compile-fail/impl-trait/disallowed.rs
+++ b/src/test/compile-fail/impl-trait/disallowed.rs
@@ -26,9 +26,9 @@ trait LazyToString {
     //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
 }
 
-// Note that the following impl doesn't error, because the trait is invalid.
 impl LazyToString for String {
     fn lazy_to_string<'a>(&'a self) -> impl Fn() -> String {
+    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
         || self.clone()
     }
 }