@@ -2,9 +2,9 @@ use rustc::hir;
2
2
use rustc:: hir:: def_id:: DefId ;
3
3
use rustc:: hir:: { AsyncGeneratorKind , GeneratorKind } ;
4
4
use 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 ,
8
8
} ;
9
9
use rustc:: ty:: { self , Ty } ;
10
10
use rustc_data_structures:: fx:: FxHashSet ;
@@ -385,42 +385,38 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
385
385
let first_borrow_desc;
386
386
let mut err = match (
387
387
gen_borrow_kind,
388
- "immutable" ,
389
- "mutable" ,
390
388
issued_borrow. kind ,
391
- "immutable" ,
392
- "mutable" ,
393
389
) {
394
- ( BorrowKind :: Shared , lft , _ , BorrowKind :: Mut { .. } , _ , rgt ) => {
390
+ ( BorrowKind :: Shared , BorrowKind :: Mut { .. } ) => {
395
391
first_borrow_desc = "mutable " ;
396
392
self . cannot_reborrow_already_borrowed (
397
393
span,
398
394
& desc_place,
399
395
& msg_place,
400
- lft ,
396
+ "immutable" ,
401
397
issued_span,
402
398
"it" ,
403
- rgt ,
399
+ "mutable" ,
404
400
& msg_borrow,
405
401
None ,
406
402
)
407
403
}
408
- ( BorrowKind :: Mut { .. } , _ , lft , BorrowKind :: Shared , rgt , _ ) => {
404
+ ( BorrowKind :: Mut { .. } , BorrowKind :: Shared ) => {
409
405
first_borrow_desc = "immutable " ;
410
406
self . cannot_reborrow_already_borrowed (
411
407
span,
412
408
& desc_place,
413
409
& msg_place,
414
- lft ,
410
+ "mutable" ,
415
411
issued_span,
416
412
"it" ,
417
- rgt ,
413
+ "immutable" ,
418
414
& msg_borrow,
419
415
None ,
420
416
)
421
417
}
422
418
423
- ( BorrowKind :: Mut { .. } , _ , _ , BorrowKind :: Mut { .. } , _ , _ ) => {
419
+ ( BorrowKind :: Mut { .. } , BorrowKind :: Mut { .. } ) => {
424
420
first_borrow_desc = "first " ;
425
421
self . cannot_mutably_borrow_multiply (
426
422
span,
@@ -432,7 +428,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
432
428
)
433
429
}
434
430
435
- ( BorrowKind :: Unique , _ , _ , BorrowKind :: Unique , _ , _ ) => {
431
+ ( BorrowKind :: Unique , BorrowKind :: Unique ) => {
436
432
first_borrow_desc = "first " ;
437
433
self . cannot_uniquely_borrow_by_two_closures (
438
434
span,
@@ -442,25 +438,45 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
442
438
)
443
439
}
444
440
445
- ( BorrowKind :: Mut { .. } , _, _, BorrowKind :: Shallow , _, _)
446
- | ( BorrowKind :: Unique , _, _, BorrowKind :: Shallow , _, _) => {
447
- let mut err = self . cannot_mutate_in_match_guard (
448
- span,
449
- issued_span,
450
- & desc_place,
451
- "mutably borrow" ,
452
- ) ;
453
- borrow_spans. var_span_label (
454
- & mut err,
455
- format ! (
456
- "borrow occurs due to use of `{}`{}" , desc_place, borrow_spans. describe( )
457
- ) ,
458
- ) ;
441
+ ( BorrowKind :: Mut { .. } , BorrowKind :: Shallow )
442
+ | ( BorrowKind :: Unique , BorrowKind :: Shallow ) => {
443
+ if let Some ( immutable_section_description) = self . classify_immutable_section (
444
+ & issued_borrow. assigned_place ,
445
+ ) {
446
+ let mut err = self . cannot_mutate_in_immutable_section (
447
+ span,
448
+ issued_span,
449
+ & desc_place,
450
+ immutable_section_description,
451
+ "mutably borrow" ,
452
+ ) ;
453
+ borrow_spans. var_span_label (
454
+ & mut err,
455
+ format ! (
456
+ "borrow occurs due to use of `{}`{}" ,
457
+ desc_place,
458
+ borrow_spans. describe( ) ,
459
+ ) ,
460
+ ) ;
459
461
460
- return err;
462
+ return err;
463
+ } else {
464
+ first_borrow_desc = "immutable " ;
465
+ self . cannot_reborrow_already_borrowed (
466
+ span,
467
+ & desc_place,
468
+ & msg_place,
469
+ "mutable" ,
470
+ issued_span,
471
+ "it" ,
472
+ "immutable" ,
473
+ & msg_borrow,
474
+ None ,
475
+ )
476
+ }
461
477
}
462
478
463
- ( BorrowKind :: Unique , _, _ , _ , _ , _ ) => {
479
+ ( BorrowKind :: Unique , _) => {
464
480
first_borrow_desc = "first " ;
465
481
self . cannot_uniquely_borrow_by_one_closure (
466
482
span,
@@ -474,42 +490,42 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
474
490
)
475
491
} ,
476
492
477
- ( BorrowKind :: Shared , lft , _ , BorrowKind :: Unique , _ , _ ) => {
493
+ ( BorrowKind :: Shared , BorrowKind :: Unique ) => {
478
494
first_borrow_desc = "first " ;
479
495
self . cannot_reborrow_already_uniquely_borrowed (
480
496
span,
481
497
container_name,
482
498
& desc_place,
483
499
"" ,
484
- lft ,
500
+ "immutable" ,
485
501
issued_span,
486
502
"" ,
487
503
None ,
488
504
second_borrow_desc,
489
505
)
490
506
}
491
507
492
- ( BorrowKind :: Mut { .. } , _ , lft , BorrowKind :: Unique , _ , _ ) => {
508
+ ( BorrowKind :: Mut { .. } , BorrowKind :: Unique ) => {
493
509
first_borrow_desc = "first " ;
494
510
self . cannot_reborrow_already_uniquely_borrowed (
495
511
span,
496
512
container_name,
497
513
& desc_place,
498
514
"" ,
499
- lft ,
515
+ "mutable" ,
500
516
issued_span,
501
517
"" ,
502
518
None ,
503
519
second_borrow_desc,
504
520
)
505
521
}
506
522
507
- ( BorrowKind :: Shared , _ , _ , BorrowKind :: Shared , _ , _ )
508
- | ( BorrowKind :: Shared , _ , _ , BorrowKind :: Shallow , _ , _ )
509
- | ( BorrowKind :: Shallow , _ , _ , BorrowKind :: Mut { .. } , _ , _ )
510
- | ( BorrowKind :: Shallow , _ , _ , BorrowKind :: Unique , _ , _ )
511
- | ( BorrowKind :: Shallow , _ , _ , BorrowKind :: Shared , _ , _ )
512
- | ( BorrowKind :: Shallow , _ , _ , BorrowKind :: Shallow , _ , _ ) => unreachable ! ( ) ,
523
+ ( BorrowKind :: Shared , BorrowKind :: Shared )
524
+ | ( BorrowKind :: Shared , BorrowKind :: Shallow )
525
+ | ( BorrowKind :: Shallow , BorrowKind :: Mut { .. } )
526
+ | ( BorrowKind :: Shallow , BorrowKind :: Unique )
527
+ | ( BorrowKind :: Shallow , BorrowKind :: Shared )
528
+ | ( BorrowKind :: Shallow , BorrowKind :: Shallow ) => unreachable ! ( ) ,
513
529
} ;
514
530
515
531
if issued_spans == borrow_spans {
@@ -1436,20 +1452,23 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
1436
1452
let loan_span = loan_spans. args_or_use ( ) ;
1437
1453
1438
1454
if loan. kind == BorrowKind :: Shallow {
1439
- let mut err = self . cannot_mutate_in_match_guard (
1440
- span,
1441
- loan_span,
1442
- & self . describe_place ( place. as_ref ( ) ) . unwrap_or_else ( || "_" . to_owned ( ) ) ,
1443
- "assign" ,
1444
- ) ;
1445
- loan_spans. var_span_label (
1446
- & mut err,
1447
- format ! ( "borrow occurs due to use{}" , loan_spans. describe( ) ) ,
1448
- ) ;
1455
+ if let Some ( section) = self . classify_immutable_section ( & loan. assigned_place ) {
1456
+ let mut err = self . cannot_mutate_in_immutable_section (
1457
+ span,
1458
+ loan_span,
1459
+ & self . describe_place ( place. as_ref ( ) ) . unwrap_or_else ( || "_" . to_owned ( ) ) ,
1460
+ section,
1461
+ "assign" ,
1462
+ ) ;
1463
+ loan_spans. var_span_label (
1464
+ & mut err,
1465
+ format ! ( "borrow occurs due to use{}" , loan_spans. describe( ) ) ,
1466
+ ) ;
1449
1467
1450
- err. buffer ( & mut self . errors_buffer ) ;
1468
+ err. buffer ( & mut self . errors_buffer ) ;
1451
1469
1452
- return ;
1470
+ return ;
1471
+ }
1453
1472
}
1454
1473
1455
1474
let mut err = self . cannot_assign_to_borrowed (
@@ -1603,6 +1622,35 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
1603
1622
}
1604
1623
}
1605
1624
1625
+ /// Describe the reason for the fake borrow that was assigned to `place`.
1626
+ fn classify_immutable_section ( & self , place : & Place < ' tcx > ) -> Option < & ' static str > {
1627
+ use rustc:: mir:: visit:: Visitor ;
1628
+ struct FakeReadCauseFinder < ' a , ' tcx > {
1629
+ place : & ' a Place < ' tcx > ,
1630
+ cause : Option < FakeReadCause > ,
1631
+ }
1632
+ impl < ' tcx > Visitor < ' tcx > for FakeReadCauseFinder < ' _ , ' tcx > {
1633
+ fn visit_statement ( & mut self , statement : & Statement < ' tcx > , _: Location ) {
1634
+ match statement {
1635
+ Statement {
1636
+ kind : StatementKind :: FakeRead ( cause, box ref place) ,
1637
+ ..
1638
+ } if * place == * self . place => {
1639
+ self . cause = Some ( * cause) ;
1640
+ }
1641
+ _ => ( ) ,
1642
+ }
1643
+ }
1644
+ }
1645
+ let mut visitor = FakeReadCauseFinder { place, cause : None } ;
1646
+ visitor. visit_body ( & self . body ) ;
1647
+ match visitor. cause {
1648
+ Some ( FakeReadCause :: ForMatchGuard ) => Some ( "match guard" ) ,
1649
+ Some ( FakeReadCause :: ForIndex ) => Some ( "indexing expression" ) ,
1650
+ _ => None ,
1651
+ }
1652
+ }
1653
+
1606
1654
/// Annotate argument and return type of function and closure with (synthesized) lifetime for
1607
1655
/// borrow of local value that does not live long enough.
1608
1656
fn annotate_argument_and_return_for_borrow (
0 commit comments