9
9
// except according to those terms.
10
10
11
11
use syntax_pos:: Span ;
12
+ use rustc:: middle:: region:: ScopeTree ;
12
13
use rustc:: mir:: { BorrowKind , Field , Local , Location , Operand } ;
13
14
use rustc:: mir:: { Place , ProjectionElem , Rvalue , StatementKind } ;
14
- use rustc:: ty;
15
+ use rustc:: ty:: { self , RegionKind } ;
15
16
use rustc_data_structures:: indexed_vec:: Idx ;
16
17
18
+ use std:: rc:: Rc ;
19
+
17
20
use super :: { MirBorrowckCtxt , Context } ;
18
21
use super :: { InitializationRequiringAction , PrefixSet } ;
19
22
use dataflow:: { BorrowData , Borrows , FlowAtLocation , MovingOutStatements } ;
@@ -324,6 +327,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
324
327
borrows : & Borrows < ' cx , ' gcx , ' tcx >
325
328
) {
326
329
let end_span = borrows. opt_region_end_span ( & borrow. region ) ;
330
+ let scope_tree = borrows. scope_tree ( ) ;
327
331
let root_place = self . prefixes ( & borrow. place , PrefixSet :: All ) . last ( ) . unwrap ( ) ;
328
332
329
333
match root_place {
@@ -347,21 +351,103 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
347
351
unreachable ! ( "root_place is an unreachable???" )
348
352
} ;
349
353
354
+ let borrow_span = self . mir . source_info ( borrow. location ) . span ;
350
355
let proper_span = match * root_place {
351
356
Place :: Local ( local) => self . mir . local_decls [ local] . source_info . span ,
352
357
_ => drop_span,
353
358
} ;
354
359
355
- let mut err = self . tcx
356
- . path_does_not_live_long_enough ( drop_span, "borrowed value" , Origin :: Mir ) ;
360
+ match ( borrow. region , & self . describe_place ( & borrow. place ) ) {
361
+ ( RegionKind :: ReScope ( _) , Some ( name) ) => {
362
+ self . report_scoped_local_value_does_not_live_long_enough (
363
+ name, & scope_tree, & borrow, drop_span, borrow_span, proper_span, end_span) ;
364
+ } ,
365
+ ( RegionKind :: ReScope ( _) , None ) => {
366
+ self . report_scoped_temporary_value_does_not_live_long_enough (
367
+ & scope_tree, & borrow, drop_span, borrow_span, proper_span, end_span) ;
368
+ } ,
369
+ ( RegionKind :: ReEarlyBound ( _) , Some ( name) ) |
370
+ ( RegionKind :: ReFree ( _) , Some ( name) ) |
371
+ ( RegionKind :: ReStatic , Some ( name) ) |
372
+ ( RegionKind :: ReEmpty , Some ( name) ) |
373
+ ( RegionKind :: ReVar ( _) , Some ( name) ) => {
374
+ self . report_unscoped_local_value_does_not_live_long_enough (
375
+ name, & scope_tree, & borrow, drop_span, borrow_span, proper_span, end_span) ;
376
+ } ,
377
+ ( RegionKind :: ReEarlyBound ( _) , None ) |
378
+ ( RegionKind :: ReFree ( _) , None ) |
379
+ ( RegionKind :: ReStatic , None ) |
380
+ ( RegionKind :: ReEmpty , None ) |
381
+ ( RegionKind :: ReVar ( _) , None ) => {
382
+ self . report_unscoped_temporary_value_does_not_live_long_enough (
383
+ & scope_tree, & borrow, drop_span, borrow_span, proper_span, end_span) ;
384
+ } ,
385
+ ( RegionKind :: ReLateBound ( _, _) , _) |
386
+ ( RegionKind :: ReSkolemized ( _, _) , _) |
387
+ ( RegionKind :: ReErased , _) => {
388
+ span_bug ! ( drop_span, "region does not make sense in this context" ) ;
389
+ } ,
390
+ }
391
+ }
392
+
393
+ fn report_scoped_local_value_does_not_live_long_enough (
394
+ & mut self , name : & String , _scope_tree : & Rc < ScopeTree > , _borrow : & BorrowData < ' tcx > ,
395
+ drop_span : Span , borrow_span : Span , _proper_span : Span , end_span : Option < Span >
396
+ ) {
397
+ let mut err = self . tcx . path_does_not_live_long_enough ( drop_span,
398
+ & format ! ( "`{}`" , name) ,
399
+ Origin :: Mir ) ;
400
+ err. span_label ( borrow_span, "borrow occurs here" ) ;
401
+ err. span_label ( drop_span, format ! ( "`{}` dropped here while still borrowed" , name) ) ;
402
+ if let Some ( end) = end_span {
403
+ err. span_label ( end, "borrowed value needs to live until here" ) ;
404
+ }
405
+ err. emit ( ) ;
406
+ }
407
+
408
+ fn report_scoped_temporary_value_does_not_live_long_enough (
409
+ & mut self , _scope_tree : & Rc < ScopeTree > , _borrow : & BorrowData < ' tcx > ,
410
+ drop_span : Span , borrow_span : Span , proper_span : Span , end_span : Option < Span >
411
+ ) {
412
+ let mut err = self . tcx . path_does_not_live_long_enough ( borrow_span,
413
+ "borrowed value" ,
414
+ Origin :: Mir ) ;
357
415
err. span_label ( proper_span, "temporary value created here" ) ;
358
416
err. span_label ( drop_span, "temporary value dropped here while still borrowed" ) ;
359
417
err. note ( "consider using a `let` binding to increase its lifetime" ) ;
360
-
361
418
if let Some ( end) = end_span {
362
419
err. span_label ( end, "temporary value needs to live until here" ) ;
363
420
}
421
+ err. emit ( ) ;
422
+ }
423
+
424
+ fn report_unscoped_local_value_does_not_live_long_enough (
425
+ & mut self , name : & String , scope_tree : & Rc < ScopeTree > , borrow : & BorrowData < ' tcx > ,
426
+ drop_span : Span , borrow_span : Span , _proper_span : Span , _end_span : Option < Span >
427
+ ) {
428
+ let mut err = self . tcx . path_does_not_live_long_enough ( borrow_span,
429
+ & format ! ( "`{}`" , name) ,
430
+ Origin :: Mir ) ;
431
+ err. span_label ( borrow_span, "does not live long enough" ) ;
432
+ err. span_label ( drop_span, "borrowed value only lives until here" ) ;
433
+ self . tcx . note_and_explain_region ( scope_tree, & mut err,
434
+ "borrowed value must be valid for " ,
435
+ borrow. region , "..." ) ;
436
+ err. emit ( ) ;
437
+ }
364
438
439
+ fn report_unscoped_temporary_value_does_not_live_long_enough (
440
+ & mut self , scope_tree : & Rc < ScopeTree > , borrow : & BorrowData < ' tcx > ,
441
+ drop_span : Span , _borrow_span : Span , proper_span : Span , _end_span : Option < Span >
442
+ ) {
443
+ let mut err = self . tcx . path_does_not_live_long_enough ( proper_span,
444
+ "borrowed value" ,
445
+ Origin :: Mir ) ;
446
+ err. span_label ( proper_span, "does not live long enough" ) ;
447
+ err. span_label ( drop_span, "temporary value only lives until here" ) ;
448
+ self . tcx . note_and_explain_region ( scope_tree, & mut err,
449
+ "borrowed value must be valid for " ,
450
+ borrow. region , "..." ) ;
365
451
err. emit ( ) ;
366
452
}
367
453
0 commit comments