@@ -2,9 +2,9 @@ use rustc::hir;
22use rustc:: hir:: def_id:: DefId ;
33use rustc:: hir:: { AsyncGeneratorKind , GeneratorKind } ;
44use rustc:: mir:: {
5- self , AggregateKind , BindingForm , BorrowKind , ClearCrossCrate , ConstraintCategory , Local ,
6- LocalDecl , LocalKind , Location , Operand , Place , PlaceBase , PlaceRef , ProjectionElem , Rvalue ,
7- Statement , StatementKind , TerminatorKind , VarBindingForm ,
5+ self , AggregateKind , BindingForm , BorrowKind , ClearCrossCrate , ConstraintCategory ,
6+ FakeReadCause , Local , LocalDecl , LocalKind , Location , Operand , Place , PlaceBase , PlaceRef ,
7+ ProjectionElem , Rvalue , Statement , StatementKind , TerminatorKind , VarBindingForm ,
88} ;
99use rustc:: ty:: { self , Ty } ;
1010use rustc_data_structures:: fx:: FxHashSet ;
@@ -380,42 +380,38 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
380380 let first_borrow_desc;
381381 let mut err = match (
382382 gen_borrow_kind,
383- "immutable" ,
384- "mutable" ,
385383 issued_borrow. kind ,
386- "immutable" ,
387- "mutable" ,
388384 ) {
389- ( BorrowKind :: Shared , lft , _ , BorrowKind :: Mut { .. } , _ , rgt ) => {
385+ ( BorrowKind :: Shared , BorrowKind :: Mut { .. } ) => {
390386 first_borrow_desc = "mutable " ;
391387 self . cannot_reborrow_already_borrowed (
392388 span,
393389 & desc_place,
394390 & msg_place,
395- lft ,
391+ "immutable" ,
396392 issued_span,
397393 "it" ,
398- rgt ,
394+ "mutable" ,
399395 & msg_borrow,
400396 None ,
401397 )
402398 }
403- ( BorrowKind :: Mut { .. } , _ , lft , BorrowKind :: Shared , rgt , _ ) => {
399+ ( BorrowKind :: Mut { .. } , BorrowKind :: Shared ) => {
404400 first_borrow_desc = "immutable " ;
405401 self . cannot_reborrow_already_borrowed (
406402 span,
407403 & desc_place,
408404 & msg_place,
409- lft ,
405+ "mutable" ,
410406 issued_span,
411407 "it" ,
412- rgt ,
408+ "immutable" ,
413409 & msg_borrow,
414410 None ,
415411 )
416412 }
417413
418- ( BorrowKind :: Mut { .. } , _ , _ , BorrowKind :: Mut { .. } , _ , _ ) => {
414+ ( BorrowKind :: Mut { .. } , BorrowKind :: Mut { .. } ) => {
419415 first_borrow_desc = "first " ;
420416 self . cannot_mutably_borrow_multiply (
421417 span,
@@ -427,7 +423,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
427423 )
428424 }
429425
430- ( BorrowKind :: Unique , _ , _ , BorrowKind :: Unique , _ , _ ) => {
426+ ( BorrowKind :: Unique , BorrowKind :: Unique ) => {
431427 first_borrow_desc = "first " ;
432428 self . cannot_uniquely_borrow_by_two_closures (
433429 span,
@@ -437,25 +433,45 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
437433 )
438434 }
439435
440- ( BorrowKind :: Mut { .. } , _, _, BorrowKind :: Shallow , _, _)
441- | ( BorrowKind :: Unique , _, _, BorrowKind :: Shallow , _, _) => {
442- let mut err = self . cannot_mutate_in_match_guard (
443- span,
444- issued_span,
445- & desc_place,
446- "mutably borrow" ,
447- ) ;
448- borrow_spans. var_span_label (
449- & mut err,
450- format ! (
451- "borrow occurs due to use of `{}`{}" , desc_place, borrow_spans. describe( )
452- ) ,
453- ) ;
436+ ( BorrowKind :: Mut { .. } , BorrowKind :: Shallow )
437+ | ( BorrowKind :: Unique , BorrowKind :: Shallow ) => {
438+ if let Some ( immutable_section_description) = self . classify_immutable_section (
439+ & issued_borrow. assigned_place ,
440+ ) {
441+ let mut err = self . cannot_mutate_in_immutable_section (
442+ span,
443+ issued_span,
444+ & desc_place,
445+ immutable_section_description,
446+ "mutably borrow" ,
447+ ) ;
448+ borrow_spans. var_span_label (
449+ & mut err,
450+ format ! (
451+ "borrow occurs due to use of `{}`{}" ,
452+ desc_place,
453+ borrow_spans. describe( ) ,
454+ ) ,
455+ ) ;
454456
455- return err;
457+ return err;
458+ } else {
459+ first_borrow_desc = "immutable " ;
460+ self . cannot_reborrow_already_borrowed (
461+ span,
462+ & desc_place,
463+ & msg_place,
464+ "mutable" ,
465+ issued_span,
466+ "it" ,
467+ "immutable" ,
468+ & msg_borrow,
469+ None ,
470+ )
471+ }
456472 }
457473
458- ( BorrowKind :: Unique , _, _ , _ , _ , _ ) => {
474+ ( BorrowKind :: Unique , _) => {
459475 first_borrow_desc = "first " ;
460476 self . cannot_uniquely_borrow_by_one_closure (
461477 span,
@@ -469,42 +485,42 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
469485 )
470486 } ,
471487
472- ( BorrowKind :: Shared , lft , _ , BorrowKind :: Unique , _ , _ ) => {
488+ ( BorrowKind :: Shared , BorrowKind :: Unique ) => {
473489 first_borrow_desc = "first " ;
474490 self . cannot_reborrow_already_uniquely_borrowed (
475491 span,
476492 container_name,
477493 & desc_place,
478494 "" ,
479- lft ,
495+ "immutable" ,
480496 issued_span,
481497 "" ,
482498 None ,
483499 second_borrow_desc,
484500 )
485501 }
486502
487- ( BorrowKind :: Mut { .. } , _ , lft , BorrowKind :: Unique , _ , _ ) => {
503+ ( BorrowKind :: Mut { .. } , BorrowKind :: Unique ) => {
488504 first_borrow_desc = "first " ;
489505 self . cannot_reborrow_already_uniquely_borrowed (
490506 span,
491507 container_name,
492508 & desc_place,
493509 "" ,
494- lft ,
510+ "mutable" ,
495511 issued_span,
496512 "" ,
497513 None ,
498514 second_borrow_desc,
499515 )
500516 }
501517
502- ( BorrowKind :: Shared , _ , _ , BorrowKind :: Shared , _ , _ )
503- | ( BorrowKind :: Shared , _ , _ , BorrowKind :: Shallow , _ , _ )
504- | ( BorrowKind :: Shallow , _ , _ , BorrowKind :: Mut { .. } , _ , _ )
505- | ( BorrowKind :: Shallow , _ , _ , BorrowKind :: Unique , _ , _ )
506- | ( BorrowKind :: Shallow , _ , _ , BorrowKind :: Shared , _ , _ )
507- | ( BorrowKind :: Shallow , _ , _ , BorrowKind :: Shallow , _ , _ ) => unreachable ! ( ) ,
518+ ( BorrowKind :: Shared , BorrowKind :: Shared )
519+ | ( BorrowKind :: Shared , BorrowKind :: Shallow )
520+ | ( BorrowKind :: Shallow , BorrowKind :: Mut { .. } )
521+ | ( BorrowKind :: Shallow , BorrowKind :: Unique )
522+ | ( BorrowKind :: Shallow , BorrowKind :: Shared )
523+ | ( BorrowKind :: Shallow , BorrowKind :: Shallow ) => unreachable ! ( ) ,
508524 } ;
509525
510526 if issued_spans == borrow_spans {
@@ -1429,20 +1445,23 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
14291445 let loan_span = loan_spans. args_or_use ( ) ;
14301446
14311447 if loan. kind == BorrowKind :: Shallow {
1432- let mut err = self . cannot_mutate_in_match_guard (
1433- span,
1434- loan_span,
1435- & self . describe_place ( place. as_ref ( ) ) . unwrap_or_else ( || "_" . to_owned ( ) ) ,
1436- "assign" ,
1437- ) ;
1438- loan_spans. var_span_label (
1439- & mut err,
1440- format ! ( "borrow occurs due to use{}" , loan_spans. describe( ) ) ,
1441- ) ;
1448+ if let Some ( section) = self . classify_immutable_section ( & loan. assigned_place ) {
1449+ let mut err = self . cannot_mutate_in_immutable_section (
1450+ span,
1451+ loan_span,
1452+ & self . describe_place ( place. as_ref ( ) ) . unwrap_or_else ( || "_" . to_owned ( ) ) ,
1453+ section,
1454+ "assign" ,
1455+ ) ;
1456+ loan_spans. var_span_label (
1457+ & mut err,
1458+ format ! ( "borrow occurs due to use{}" , loan_spans. describe( ) ) ,
1459+ ) ;
14421460
1443- err. buffer ( & mut self . errors_buffer ) ;
1461+ err. buffer ( & mut self . errors_buffer ) ;
14441462
1445- return ;
1463+ return ;
1464+ }
14461465 }
14471466
14481467 let mut err = self . cannot_assign_to_borrowed (
@@ -1593,6 +1612,35 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
15931612 }
15941613 }
15951614
1615+ /// Describe the reason for the fake borrow that was assigned to `place`.
1616+ fn classify_immutable_section ( & self , place : & Place < ' tcx > ) -> Option < & ' static str > {
1617+ use rustc:: mir:: visit:: Visitor ;
1618+ struct FakeReadCauseFinder < ' a , ' tcx > {
1619+ place : & ' a Place < ' tcx > ,
1620+ cause : Option < FakeReadCause > ,
1621+ }
1622+ impl < ' tcx > Visitor < ' tcx > for FakeReadCauseFinder < ' _ , ' tcx > {
1623+ fn visit_statement ( & mut self , statement : & Statement < ' tcx > , _: Location ) {
1624+ match statement {
1625+ Statement {
1626+ kind : StatementKind :: FakeRead ( cause, box ref place) ,
1627+ ..
1628+ } if * place == * self . place => {
1629+ self . cause = Some ( * cause) ;
1630+ }
1631+ _ => ( ) ,
1632+ }
1633+ }
1634+ }
1635+ let mut visitor = FakeReadCauseFinder { place, cause : None } ;
1636+ visitor. visit_body ( & self . body ) ;
1637+ match visitor. cause {
1638+ Some ( FakeReadCause :: ForMatchGuard ) => Some ( "match guard" ) ,
1639+ Some ( FakeReadCause :: ForIndex ) => Some ( "indexing expression" ) ,
1640+ _ => None ,
1641+ }
1642+ }
1643+
15961644 /// Annotate argument and return type of function and closure with (synthesized) lifetime for
15971645 /// borrow of local value that does not live long enough.
15981646 fn annotate_argument_and_return_for_borrow (
0 commit comments