@@ -45,15 +45,31 @@ pub enum DefRegion {
45
45
/* lifetime decl */ ast:: NodeId ) ,
46
46
}
47
47
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.
50
50
pub type NamedRegionMap = NodeMap < DefRegion > ;
51
51
52
52
struct LifetimeContext < ' a > {
53
53
sess : & ' a Session ,
54
54
named_region_map : & ' a mut NamedRegionMap ,
55
55
scope : Scope < ' a > ,
56
56
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 ,
57
73
}
58
74
59
75
enum ScopeChain < ' a > {
@@ -80,6 +96,7 @@ pub fn krate(sess: &Session, krate: &ast::Crate, def_map: &DefMap) -> NamedRegio
80
96
named_region_map : & mut named_region_map,
81
97
scope : & ROOT_SCOPE ,
82
98
def_map : def_map,
99
+ trait_ref_hack : false ,
83
100
} , krate) ;
84
101
sess. abort_if_errors ( ) ;
85
102
named_region_map
@@ -198,9 +215,22 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
198
215
match predicate {
199
216
& ast:: WherePredicate :: BoundPredicate ( ast:: WhereBoundPredicate { ref bounded_ty,
200
217
ref bounds,
218
+ ref bound_lifetimes,
201
219
.. } ) => {
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
+ }
204
234
}
205
235
& ast:: WherePredicate :: RegionPredicate ( ast:: WhereRegionPredicate { ref lifetime,
206
236
ref bounds,
@@ -222,18 +252,27 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
222
252
}
223
253
}
224
254
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 ,
227
257
_modifier : & ast:: TraitBoundModifier ) {
228
258
debug ! ( "visit_poly_trait_ref trait_ref={:?}" , trait_ref) ;
229
259
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" ) ;
234
265
}
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
+ }
237
276
}
238
277
239
278
fn visit_trait_ref ( & mut self , trait_ref : & ast:: TraitRef ) {
@@ -251,6 +290,7 @@ impl<'a> LifetimeContext<'a> {
251
290
named_region_map : * named_region_map,
252
291
scope : & wrap_scope,
253
292
def_map : self . def_map ,
293
+ trait_ref_hack : self . trait_ref_hack ,
254
294
} ;
255
295
debug ! ( "entering scope {:?}" , this. scope) ;
256
296
f ( self . scope , & mut this) ;
0 commit comments