99// except according to those terms.
1010
1111use syntax_pos:: Span ;
12+ use rustc:: middle:: region:: ScopeTree ;
1213use rustc:: mir:: { BorrowKind , Field , Local , Location , Operand } ;
1314use rustc:: mir:: { Place , ProjectionElem , Rvalue , StatementKind } ;
14- use rustc:: ty;
15+ use rustc:: ty:: { self , RegionKind } ;
1516use rustc_data_structures:: indexed_vec:: Idx ;
1617
18+ use std:: rc:: Rc ;
19+
1720use super :: { MirBorrowckCtxt , Context } ;
1821use super :: { InitializationRequiringAction , PrefixSet } ;
1922use dataflow:: { BorrowData , Borrows , FlowAtLocation , MovingOutStatements } ;
@@ -324,6 +327,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
324327 borrows : & Borrows < ' cx , ' gcx , ' tcx >
325328 ) {
326329 let end_span = borrows. opt_region_end_span ( & borrow. region ) ;
330+ let scope_tree = borrows. scope_tree ( ) ;
327331 let root_place = self . prefixes ( & borrow. place , PrefixSet :: All ) . last ( ) . unwrap ( ) ;
328332
329333 match root_place {
@@ -347,21 +351,103 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
347351 unreachable ! ( "root_place is an unreachable???" )
348352 } ;
349353
354+ let borrow_span = self . mir . source_info ( borrow. location ) . span ;
350355 let proper_span = match * root_place {
351356 Place :: Local ( local) => self . mir . local_decls [ local] . source_info . span ,
352357 _ => drop_span,
353358 } ;
354359
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 ) ;
357415 err. span_label ( proper_span, "temporary value created here" ) ;
358416 err. span_label ( drop_span, "temporary value dropped here while still borrowed" ) ;
359417 err. note ( "consider using a `let` binding to increase its lifetime" ) ;
360-
361418 if let Some ( end) = end_span {
362419 err. span_label ( end, "temporary value needs to live until here" ) ;
363420 }
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+ }
364438
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 , "..." ) ;
365451 err. emit ( ) ;
366452 }
367453
0 commit comments