From ad47bd8a0f6f5284a8f937f5cd8a0a7e3df96991 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 7 Aug 2015 10:37:17 -0400 Subject: [PATCH] Extend ParameterEnvironment to remember the free_id, and to be usable on more kind of items --- src/librustc/middle/ty.rs | 103 +++++++++++++++++++++------------ src/librustc/middle/ty_fold.rs | 1 + 2 files changed, 67 insertions(+), 37 deletions(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 393bb83067cc..9ccfce8d3049 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 809ee8928afd..09c50804e836 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, } } }