@@ -45,15 +45,31 @@ pub enum DefRegion {
4545 /* lifetime decl */ ast:: NodeId ) ,
4646}
4747
48- // maps the id of each lifetime reference to the lifetime decl
49- // that it corresponds to
48+ // Maps the id of each lifetime reference to the lifetime decl
49+ // that it corresponds to.
5050pub type NamedRegionMap = NodeMap < DefRegion > ;
5151
5252struct LifetimeContext < ' a > {
5353 sess : & ' a Session ,
5454 named_region_map : & ' a mut NamedRegionMap ,
5555 scope : Scope < ' a > ,
5656 def_map : & ' a DefMap ,
57+ // Deep breath. Our representation for poly trait refs contains a single
58+ // binder and thus we only allow a single level of quantification. However,
59+ // the syntax of Rust permits quantification in two places, e.g., `T: for <'a> Foo<'a>`
60+ // and `for <'a, 'b> &'b T: Foo<'a>`. In order to get the de Bruijn indices
61+ // correct when representing these constraints, we should only introduce one
62+ // scope. However, we want to support both locations for the quantifier and
63+ // during lifetime resolution we want precise information (so we can't
64+ // desugar in an earlier phase).
65+
66+ // SO, if we encounter a quantifier at the outer scope, we set
67+ // trait_ref_hack to true (and introduce a scope), and then if we encounter
68+ // a quantifier at the inner scope, we error. If trait_ref_hack is false,
69+ // then we introduce the scope at the inner quantifier.
70+
71+ // I'm sorry.
72+ trait_ref_hack : bool ,
5773}
5874
5975enum ScopeChain < ' a > {
@@ -80,6 +96,7 @@ pub fn krate(sess: &Session, krate: &ast::Crate, def_map: &DefMap) -> NamedRegio
8096 named_region_map : & mut named_region_map,
8197 scope : & ROOT_SCOPE ,
8298 def_map : def_map,
99+ trait_ref_hack : false ,
83100 } , krate) ;
84101 sess. abort_if_errors ( ) ;
85102 named_region_map
@@ -198,9 +215,22 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
198215 match predicate {
199216 & ast:: WherePredicate :: BoundPredicate ( ast:: WhereBoundPredicate { ref bounded_ty,
200217 ref bounds,
218+ ref bound_lifetimes,
201219 .. } ) => {
202- self . visit_ty ( & * * bounded_ty) ;
203- visit:: walk_ty_param_bounds_helper ( self , bounds) ;
220+ if bound_lifetimes. len ( ) > 0 {
221+ self . trait_ref_hack = true ;
222+ let result = self . with ( LateScope ( bound_lifetimes, self . scope ) ,
223+ |old_scope, this| {
224+ this. check_lifetime_defs ( old_scope, bound_lifetimes) ;
225+ this. visit_ty ( & * * bounded_ty) ;
226+ visit:: walk_ty_param_bounds_helper ( this, bounds) ;
227+ } ) ;
228+ self . trait_ref_hack = false ;
229+ result
230+ } else {
231+ self . visit_ty ( & * * bounded_ty) ;
232+ visit:: walk_ty_param_bounds_helper ( self , bounds) ;
233+ }
204234 }
205235 & ast:: WherePredicate :: RegionPredicate ( ast:: WhereRegionPredicate { ref lifetime,
206236 ref bounds,
@@ -222,18 +252,27 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
222252 }
223253 }
224254
225- fn visit_poly_trait_ref ( & mut self , trait_ref :
226- & ast:: PolyTraitRef ,
255+ fn visit_poly_trait_ref ( & mut self ,
256+ trait_ref : & ast:: PolyTraitRef ,
227257 _modifier : & ast:: TraitBoundModifier ) {
228258 debug ! ( "visit_poly_trait_ref trait_ref={:?}" , trait_ref) ;
229259
230- self . with ( LateScope ( & trait_ref. bound_lifetimes , self . scope ) , |old_scope, this| {
231- this. check_lifetime_defs ( old_scope, & trait_ref. bound_lifetimes ) ;
232- for lifetime in & trait_ref. bound_lifetimes {
233- this. visit_lifetime_def ( lifetime) ;
260+ if !self . trait_ref_hack || trait_ref. bound_lifetimes . len ( ) > 0 {
261+ if self . trait_ref_hack {
262+ println ! ( "{:?}" , trait_ref. span) ;
263+ span_err ! ( self . sess, trait_ref. span, E0316 ,
264+ "nested quantification of lifetimes" ) ;
234265 }
235- this. visit_trait_ref ( & trait_ref. trait_ref )
236- } )
266+ self . with ( LateScope ( & trait_ref. bound_lifetimes , self . scope ) , |old_scope, this| {
267+ this. check_lifetime_defs ( old_scope, & trait_ref. bound_lifetimes ) ;
268+ for lifetime in & trait_ref. bound_lifetimes {
269+ this. visit_lifetime_def ( lifetime) ;
270+ }
271+ this. visit_trait_ref ( & trait_ref. trait_ref )
272+ } )
273+ } else {
274+ self . visit_trait_ref ( & trait_ref. trait_ref )
275+ }
237276 }
238277
239278 fn visit_trait_ref ( & mut self , trait_ref : & ast:: TraitRef ) {
@@ -251,6 +290,7 @@ impl<'a> LifetimeContext<'a> {
251290 named_region_map : * named_region_map,
252291 scope : & wrap_scope,
253292 def_map : self . def_map ,
293+ trait_ref_hack : self . trait_ref_hack ,
254294 } ;
255295 debug ! ( "entering scope {:?}" , this. scope) ;
256296 f ( self . scope , & mut this) ;
0 commit comments