about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2015-08-07 10:37:17 -0400
committerNiko Matsakis <niko@alum.mit.edu>2015-08-12 17:57:57 -0400
commitad47bd8a0f6f5284a8f937f5cd8a0a7e3df96991 (patch)
tree08fe52bdcdee4946cff232ae64c5751d1f8fc337
parentb1963154a10fd22d16a5eddd751046cc897e909c (diff)
Extend ParameterEnvironment to remember the free_id, and to be usable
on more kind of items
-rw-r--r--src/librustc/middle/ty.rs103
-rw-r--r--src/librustc/middle/ty_fold.rs1
2 files changed, 67 insertions, 37 deletions
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 393bb83067c..9ccfce8d304 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -2833,6 +2833,15 @@ pub struct ParameterEnvironment<'a, 'tcx:'a> {
     /// Caches the results of trait selection. This cache is used
     /// for things that have to do with the parameters in scope.
     pub selection_cache: traits::SelectionCache<'tcx>,
+
+    /// Scope that is attached to free regions for this scope. This
+    /// is usually the id of the fn body, but for more abstract scopes
+    /// like structs we often use the node-id of the struct.
+    ///
+    /// FIXME(#3696). It would be nice to refactor so that free
+    /// regions don't have this implicit scope and instead introduce
+    /// relationships in the environment.
+    pub free_id: ast::NodeId,
 }
 
 impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
@@ -2846,6 +2855,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
             implicit_region_bound: self.implicit_region_bound,
             caller_bounds: caller_bounds,
             selection_cache: traits::SelectionCache::new(),
+            free_id: self.free_id,
         }
     }
 
@@ -2853,6 +2863,18 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
         match cx.map.find(id) {
             Some(ast_map::NodeImplItem(ref impl_item)) => {
                 match impl_item.node {
+                    ast::TypeImplItem(_) => {
+                        // associated types don't have their own entry (for some reason),
+                        // so for now just grab environment for the impl
+                        let impl_id = cx.map.get_parent(id);
+                        let impl_def_id = ast_util::local_def(impl_id);
+                        let scheme = cx.lookup_item_type(impl_def_id);
+                        let predicates = cx.lookup_predicates(impl_def_id);
+                        cx.construct_parameter_environment(impl_item.span,
+                                                           &scheme.generics,
+                                                           &predicates,
+                                                           id)
+                    }
                     ast::ConstImplItem(_, _) => {
                         let def_id = ast_util::local_def(id);
                         let scheme = cx.lookup_item_type(def_id);
@@ -2881,42 +2903,37 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                             }
                         }
                     }
-                    ast::TypeImplItem(_) => {
-                        cx.sess.bug("ParameterEnvironment::for_item(): \
-                                     can't create a parameter environment \
-                                     for type impl items")
-                    }
                     ast::MacImplItem(_) => cx.sess.bug("unexpanded macro")
                 }
             }
             Some(ast_map::NodeTraitItem(trait_item)) => {
                 match trait_item.node {
-                    ast::ConstTraitItem(_, ref default) => {
-                        match *default {
-                            Some(_) => {
-                                let def_id = ast_util::local_def(id);
-                                let scheme = cx.lookup_item_type(def_id);
-                                let predicates = cx.lookup_predicates(def_id);
-                                cx.construct_parameter_environment(trait_item.span,
-                                                                   &scheme.generics,
-                                                                   &predicates,
-                                                                   id)
-                            }
-                            None => {
-                                cx.sess.bug("ParameterEnvironment::from_item(): \
-                                             can't create a parameter environment \
-                                             for const trait items without defaults")
-                            }
-                        }
+                    ast::TypeTraitItem(..) => {
+                        // associated types don't have their own entry (for some reason),
+                        // so for now just grab environment for the trait
+                        let trait_id = cx.map.get_parent(id);
+                        let trait_def_id = ast_util::local_def(trait_id);
+                        let trait_def = cx.lookup_trait_def(trait_def_id);
+                        let predicates = cx.lookup_predicates(trait_def_id);
+                        cx.construct_parameter_environment(trait_item.span,
+                                                           &trait_def.generics,
+                                                           &predicates,
+                                                           id)
                     }
-                    ast::MethodTraitItem(_, None) => {
-                        cx.sess.span_bug(trait_item.span,
-                                         "ParameterEnvironment::for_item():
-                                          can't create a parameter \
-                                          environment for required trait \
-                                          methods")
+                    ast::ConstTraitItem(..) => {
+                        let def_id = ast_util::local_def(id);
+                        let scheme = cx.lookup_item_type(def_id);
+                        let predicates = cx.lookup_predicates(def_id);
+                        cx.construct_parameter_environment(trait_item.span,
+                                                           &scheme.generics,
+                                                           &predicates,
+                                                           id)
                     }
-                    ast::MethodTraitItem(_, Some(ref body)) => {
+                    ast::MethodTraitItem(_, ref body) => {
+                        // for the body-id, use the id of the body
+                        // block, unless this is a trait method with
+                        // no default, then fallback to the method id.
+                        let body_id = body.as_ref().map(|b| b.id).unwrap_or(id);
                         let method_def_id = ast_util::local_def(id);
                         match cx.impl_or_trait_item(method_def_id) {
                             MethodTraitItem(ref method_ty) => {
@@ -2926,7 +2943,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                                     trait_item.span,
                                     method_generics,
                                     method_bounds,
-                                    body.id)
+                                    body_id)
                             }
                             _ => {
                                 cx.sess
@@ -2936,11 +2953,6 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                             }
                         }
                     }
-                    ast::TypeTraitItem(..) => {
-                        cx.sess.bug("ParameterEnvironment::from_item(): \
-                                     can't create a parameter environment \
-                                     for type trait items")
-                    }
                 }
             }
             Some(ast_map::NodeItem(item)) => {
@@ -2969,6 +2981,15 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                                                            &predicates,
                                                            id)
                     }
+                    ast::ItemTrait(..) => {
+                        let def_id = ast_util::local_def(id);
+                        let trait_def = cx.lookup_trait_def(def_id);
+                        let predicates = cx.lookup_predicates(def_id);
+                        cx.construct_parameter_environment(item.span,
+                                                           &trait_def.generics,
+                                                           &predicates,
+                                                           id)
+                    }
                     _ => {
                         cx.sess.span_bug(item.span,
                                          "ParameterEnvironment::from_item():
@@ -6587,12 +6608,19 @@ impl<'tcx> ctxt<'tcx> {
 
     /// Construct a parameter environment suitable for static contexts or other contexts where there
     /// are no free type/lifetime parameters in scope.
-    pub fn empty_parameter_environment<'a>(&'a self) -> ParameterEnvironment<'a,'tcx> {
+    pub fn empty_parameter_environment<'a>(&'a self)
+                                           -> ParameterEnvironment<'a,'tcx> {
         ty::ParameterEnvironment { tcx: self,
                                    free_substs: Substs::empty(),
                                    caller_bounds: Vec::new(),
                                    implicit_region_bound: ty::ReEmpty,
-                                   selection_cache: traits::SelectionCache::new(), }
+                                   selection_cache: traits::SelectionCache::new(),
+
+                                   // for an empty parameter
+                                   // environment, there ARE no free
+                                   // regions, so it shouldn't matter
+                                   // what we use for the free id
+                                   free_id: ast::DUMMY_NODE_ID }
     }
 
     /// Constructs and returns a substitution that can be applied to move from
@@ -6676,6 +6704,7 @@ impl<'tcx> ctxt<'tcx> {
             implicit_region_bound: ty::ReScope(free_id_outlive.to_code_extent()),
             caller_bounds: predicates,
             selection_cache: traits::SelectionCache::new(),
+            free_id: free_id,
         };
 
         let cause = traits::ObligationCause::misc(span, free_id);
diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs
index 809ee8928af..09c50804e83 100644
--- a/src/librustc/middle/ty_fold.rs
+++ b/src/librustc/middle/ty_fold.rs
@@ -547,6 +547,7 @@ impl<'a, 'tcx> TypeFoldable<'tcx> for ty::ParameterEnvironment<'a, 'tcx> where '
             implicit_region_bound: self.implicit_region_bound.fold_with(folder),
             caller_bounds: self.caller_bounds.fold_with(folder),
             selection_cache: traits::SelectionCache::new(),
+            free_id: self.free_id,
         }
     }
 }