@@ -64,7 +64,7 @@ use require_c_abi_if_variadic;
64
64
use rscope:: { self , UnelidableRscope , RegionScope , ElidableRscope ,
65
65
ObjectLifetimeDefaultRscope , ShiftedRscope , BindingRscope ,
66
66
ElisionFailureInfo , ElidedLifetime } ;
67
- use rscope:: { AnonTypeScope , MaybeWithAnonTypes } ;
67
+ use rscope:: { AnonTypeScope , MaybeWithAnonTypes , ExplicitRscope } ;
68
68
use util:: common:: { ErrorReported , FN_OUTPUT_NAME } ;
69
69
use util:: nodemap:: { NodeMap , FxHashSet } ;
70
70
@@ -161,70 +161,6 @@ struct ConvertedBinding<'tcx> {
161
161
/// This type must not appear anywhere in other converted types.
162
162
const TRAIT_OBJECT_DUMMY_SELF : ty:: TypeVariants < ' static > = ty:: TyInfer ( ty:: FreshTy ( 0 ) ) ;
163
163
164
- pub fn ast_region_to_region < ' a , ' gcx , ' tcx > ( tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
165
- lifetime : & hir:: Lifetime )
166
- -> & ' tcx ty:: Region {
167
- let r = match tcx. named_region_map . defs . get ( & lifetime. id ) {
168
- None => {
169
- // should have been recorded by the `resolve_lifetime` pass
170
- span_bug ! ( lifetime. span, "unresolved lifetime" ) ;
171
- }
172
-
173
- Some ( & rl:: DefStaticRegion ) => {
174
- ty:: ReStatic
175
- }
176
-
177
- Some ( & rl:: DefLateBoundRegion ( debruijn, id) ) => {
178
- // If this region is declared on a function, it will have
179
- // an entry in `late_bound`, but if it comes from
180
- // `for<'a>` in some type or something, it won't
181
- // necessarily have one. In that case though, we won't be
182
- // changed from late to early bound, so we can just
183
- // substitute false.
184
- let issue_32330 = tcx. named_region_map
185
- . late_bound
186
- . get ( & id)
187
- . cloned ( )
188
- . unwrap_or ( ty:: Issue32330 :: WontChange ) ;
189
- ty:: ReLateBound ( debruijn, ty:: BrNamed ( tcx. hir . local_def_id ( id) ,
190
- lifetime. name ,
191
- issue_32330) )
192
- }
193
-
194
- Some ( & rl:: DefEarlyBoundRegion ( index, _) ) => {
195
- ty:: ReEarlyBound ( ty:: EarlyBoundRegion {
196
- index : index,
197
- name : lifetime. name
198
- } )
199
- }
200
-
201
- Some ( & rl:: DefFreeRegion ( scope, id) ) => {
202
- // As in DefLateBoundRegion above, could be missing for some late-bound
203
- // regions, but also for early-bound regions.
204
- let issue_32330 = tcx. named_region_map
205
- . late_bound
206
- . get ( & id)
207
- . cloned ( )
208
- . unwrap_or ( ty:: Issue32330 :: WontChange ) ;
209
- ty:: ReFree ( ty:: FreeRegion {
210
- scope : scope. to_code_extent ( & tcx. region_maps ) ,
211
- bound_region : ty:: BrNamed ( tcx. hir . local_def_id ( id) ,
212
- lifetime. name ,
213
- issue_32330)
214
- } )
215
-
216
- // (*) -- not late-bound, won't change
217
- }
218
- } ;
219
-
220
- debug ! ( "ast_region_to_region(lifetime={:?} id={}) yields {:?}" ,
221
- lifetime,
222
- lifetime. id,
223
- r) ;
224
-
225
- tcx. mk_region ( r)
226
- }
227
-
228
164
fn report_elision_failure (
229
165
tcx : TyCtxt ,
230
166
db : & mut DiagnosticBuilder ,
@@ -296,38 +232,98 @@ fn report_elision_failure(
296
232
}
297
233
298
234
impl < ' o , ' gcx : ' tcx , ' tcx > AstConv < ' gcx , ' tcx > +' o {
299
- pub fn opt_ast_region_to_region ( & self ,
235
+ pub fn ast_region_to_region ( & self , lifetime : & hir:: Lifetime ) -> & ' tcx ty:: Region {
236
+ self . opt_ast_region_to_region ( & ExplicitRscope , lifetime. span , Some ( lifetime) , None )
237
+ }
238
+
239
+ fn try_opt_ast_region_to_region ( & self ,
300
240
rscope : & RegionScope ,
301
241
default_span : Span ,
302
- opt_lifetime : & Option < hir:: Lifetime > ) -> & ' tcx ty:: Region
242
+ opt_lifetime : Option < & hir:: Lifetime > ,
243
+ def : Option < & ty:: RegionParameterDef > )
244
+ -> Result < & ' tcx ty:: Region , Option < Vec < ElisionFailureInfo > > >
303
245
{
304
- let r = match * opt_lifetime {
305
- Some ( ref lifetime) => {
306
- ast_region_to_region ( self . tcx ( ) , lifetime)
246
+ let tcx = self . tcx ( ) ;
247
+ let name = opt_lifetime. map ( |l| l. name ) ;
248
+ let resolved = opt_lifetime. and_then ( |l| tcx. named_region_map . defs . get ( & l. id ) ) ;
249
+ let r = tcx. mk_region ( match resolved {
250
+ Some ( & rl:: DefStaticRegion ) => {
251
+ ty:: ReStatic
307
252
}
308
253
309
- None => {
310
- self . tcx ( ) . mk_region ( rscope. anon_region ( default_span) . unwrap_or_else ( |params| {
311
- let ampersand_span = Span { hi : default_span. lo , ..default_span} ;
254
+ Some ( & rl:: DefLateBoundRegion ( debruijn, id) ) => {
255
+ // If this region is declared on a function, it will have
256
+ // an entry in `late_bound`, but if it comes from
257
+ // `for<'a>` in some type or something, it won't
258
+ // necessarily have one. In that case though, we won't be
259
+ // changed from late to early bound, so we can just
260
+ // substitute false.
261
+ let issue_32330 = tcx. named_region_map
262
+ . late_bound
263
+ . get ( & id)
264
+ . cloned ( )
265
+ . unwrap_or ( ty:: Issue32330 :: WontChange ) ;
266
+ ty:: ReLateBound ( debruijn, ty:: BrNamed ( tcx. hir . local_def_id ( id) ,
267
+ name. unwrap ( ) ,
268
+ issue_32330) )
269
+ }
270
+
271
+ Some ( & rl:: DefEarlyBoundRegion ( index, _) ) => {
272
+ ty:: ReEarlyBound ( ty:: EarlyBoundRegion {
273
+ index : index,
274
+ name : name. unwrap ( )
275
+ } )
276
+ }
312
277
313
- let mut err = struct_span_err ! ( self . tcx( ) . sess, ampersand_span, E0106 ,
314
- "missing lifetime specifier" ) ;
315
- err. span_label ( ampersand_span, & format ! ( "expected lifetime parameter" ) ) ;
278
+ Some ( & rl:: DefFreeRegion ( scope, id) ) => {
279
+ // As in DefLateBoundRegion above, could be missing for some late-bound
280
+ // regions, but also for early-bound regions.
281
+ let issue_32330 = tcx. named_region_map
282
+ . late_bound
283
+ . get ( & id)
284
+ . cloned ( )
285
+ . unwrap_or ( ty:: Issue32330 :: WontChange ) ;
286
+ ty:: ReFree ( ty:: FreeRegion {
287
+ scope : scope. to_code_extent ( & tcx. region_maps ) ,
288
+ bound_region : ty:: BrNamed ( tcx. hir . local_def_id ( id) ,
289
+ name. unwrap ( ) ,
290
+ issue_32330)
291
+ } )
316
292
317
- if let Some ( params) = params {
318
- report_elision_failure ( self . tcx ( ) , & mut err, params) ;
319
- }
320
- err. emit ( ) ;
321
- ty:: ReStatic
322
- } ) )
293
+ // (*) -- not late-bound, won't change
323
294
}
324
- } ;
295
+
296
+ None => rscope. anon_region ( default_span, def) ?
297
+ } ) ;
325
298
326
299
debug ! ( "opt_ast_region_to_region(opt_lifetime={:?}) yields {:?}" ,
327
300
opt_lifetime,
328
301
r) ;
329
302
330
- r
303
+ Ok ( r)
304
+ }
305
+
306
+ pub fn opt_ast_region_to_region ( & self ,
307
+ rscope : & RegionScope ,
308
+ default_span : Span ,
309
+ opt_lifetime : Option < & hir:: Lifetime > ,
310
+ def : Option < & ty:: RegionParameterDef > ) -> & ' tcx ty:: Region
311
+ {
312
+ let tcx = self . tcx ( ) ;
313
+ self . try_opt_ast_region_to_region ( rscope, default_span, opt_lifetime, def)
314
+ . unwrap_or_else ( |params| {
315
+ let ampersand_span = Span { hi : default_span. lo , ..default_span} ;
316
+
317
+ let mut err = struct_span_err ! ( tcx. sess, ampersand_span, E0106 ,
318
+ "missing lifetime specifier" ) ;
319
+ err. span_label ( ampersand_span, & format ! ( "expected lifetime parameter" ) ) ;
320
+
321
+ if let Some ( params) = params {
322
+ report_elision_failure ( tcx, & mut err, params) ;
323
+ }
324
+ err. emit ( ) ;
325
+ tcx. mk_region ( ty:: ReStatic )
326
+ } )
331
327
}
332
328
333
329
/// Given a path `path` that refers to an item `I` with the declared generics `decl_generics`,
@@ -408,25 +404,21 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
408
404
} ;
409
405
let expected_num_region_params = decl_generics. regions . len ( ) ;
410
406
let supplied_num_region_params = lifetimes. len ( ) ;
411
- let regions = if expected_num_region_params == supplied_num_region_params {
412
- lifetimes. iter ( ) . map ( |l| * ast_region_to_region ( tcx, l) ) . collect ( )
413
- } else {
414
- let anon_regions = ( 0 ..expected_num_region_params) . map ( |_| {
415
- rscope. anon_region ( span)
416
- } ) . collect :: < Result < Vec < _ > , _ > > ( ) ;
417
-
418
- if supplied_num_region_params != 0 || anon_regions. is_err ( ) {
407
+ let has_exact_lifetimes = expected_num_region_params == supplied_num_region_params;
408
+ let mut can_report_lifetime_count_mismatch = !has_exact_lifetimes;
409
+ let mut maybe_report_lifetime_count_mismatch = || {
410
+ if can_report_lifetime_count_mismatch {
411
+ can_report_lifetime_count_mismatch = false ;
419
412
report_lifetime_number_error ( tcx, span,
420
413
supplied_num_region_params,
421
414
expected_num_region_params) ;
422
415
}
423
-
424
- match anon_regions {
425
- Ok ( anon_regions) => anon_regions,
426
- Err ( _) => ( 0 ..expected_num_region_params) . map ( |_| ty:: ReStatic ) . collect ( )
427
- }
428
416
} ;
429
417
418
+ if supplied_num_region_params != 0 {
419
+ maybe_report_lifetime_count_mismatch ( ) ;
420
+ }
421
+
430
422
// If a self-type was declared, one should be provided.
431
423
assert_eq ! ( decl_generics. has_self, self_ty. is_some( ) ) ;
432
424
@@ -452,7 +444,15 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
452
444
let mut output_assoc_binding = None ;
453
445
let substs = Substs :: for_item ( tcx, def_id, |def, _| {
454
446
let i = def. index as usize - self_ty. is_some ( ) as usize ;
455
- tcx. mk_region ( regions[ i] )
447
+ let l = if has_exact_lifetimes {
448
+ Some ( & lifetimes[ i] )
449
+ } else {
450
+ None
451
+ } ;
452
+ self . try_opt_ast_region_to_region ( rscope, span, l, Some ( def) ) . unwrap_or_else ( |_| {
453
+ maybe_report_lifetime_count_mismatch ( ) ;
454
+ tcx. mk_region ( ty:: ReStatic )
455
+ } )
456
456
} , |def, substs| {
457
457
let i = def. index as usize ;
458
458
@@ -1472,7 +1472,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
1472
1472
} )
1473
1473
}
1474
1474
hir:: TyRptr ( ref region, ref mt) => {
1475
- let r = self . opt_ast_region_to_region ( rscope, ast_ty. span , region) ;
1475
+ let r = self . opt_ast_region_to_region ( rscope, ast_ty. span , region. as_ref ( ) , None ) ;
1476
1476
debug ! ( "TyRef r={:?}" , r) ;
1477
1477
let rscope1 =
1478
1478
& ObjectLifetimeDefaultRscope :: new (
@@ -1823,7 +1823,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
1823
1823
1824
1824
if let Some ( & r) = explicit_region_bounds. get ( 0 ) {
1825
1825
// Explicitly specified region bound. Use that.
1826
- return Some ( ast_region_to_region ( tcx , r) ) ;
1826
+ return Some ( self . ast_region_to_region ( r) ) ;
1827
1827
}
1828
1828
1829
1829
if let Some ( principal) = existential_predicates. principal ( ) {
0 commit comments