@@ -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 ;
@@ -380,42 +380,38 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
380
380
let first_borrow_desc;
381
381
let mut err = match (
382
382
gen_borrow_kind,
383
- "immutable" ,
384
- "mutable" ,
385
383
issued_borrow. kind ,
386
- "immutable" ,
387
- "mutable" ,
388
384
) {
389
- ( BorrowKind :: Shared , lft , _ , BorrowKind :: Mut { .. } , _ , rgt ) => {
385
+ ( BorrowKind :: Shared , BorrowKind :: Mut { .. } ) => {
390
386
first_borrow_desc = "mutable " ;
391
387
self . cannot_reborrow_already_borrowed (
392
388
span,
393
389
& desc_place,
394
390
& msg_place,
395
- lft ,
391
+ "immutable" ,
396
392
issued_span,
397
393
"it" ,
398
- rgt ,
394
+ "mutable" ,
399
395
& msg_borrow,
400
396
None ,
401
397
)
402
398
}
403
- ( BorrowKind :: Mut { .. } , _ , lft , BorrowKind :: Shared , rgt , _ ) => {
399
+ ( BorrowKind :: Mut { .. } , BorrowKind :: Shared ) => {
404
400
first_borrow_desc = "immutable " ;
405
401
self . cannot_reborrow_already_borrowed (
406
402
span,
407
403
& desc_place,
408
404
& msg_place,
409
- lft ,
405
+ "mutable" ,
410
406
issued_span,
411
407
"it" ,
412
- rgt ,
408
+ "immutable" ,
413
409
& msg_borrow,
414
410
None ,
415
411
)
416
412
}
417
413
418
- ( BorrowKind :: Mut { .. } , _ , _ , BorrowKind :: Mut { .. } , _ , _ ) => {
414
+ ( BorrowKind :: Mut { .. } , BorrowKind :: Mut { .. } ) => {
419
415
first_borrow_desc = "first " ;
420
416
self . cannot_mutably_borrow_multiply (
421
417
span,
@@ -427,7 +423,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
427
423
)
428
424
}
429
425
430
- ( BorrowKind :: Unique , _ , _ , BorrowKind :: Unique , _ , _ ) => {
426
+ ( BorrowKind :: Unique , BorrowKind :: Unique ) => {
431
427
first_borrow_desc = "first " ;
432
428
self . cannot_uniquely_borrow_by_two_closures (
433
429
span,
@@ -437,25 +433,45 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
437
433
)
438
434
}
439
435
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
+ ) ;
454
456
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
+ }
456
472
}
457
473
458
- ( BorrowKind :: Unique , _, _ , _ , _ , _ ) => {
474
+ ( BorrowKind :: Unique , _) => {
459
475
first_borrow_desc = "first " ;
460
476
self . cannot_uniquely_borrow_by_one_closure (
461
477
span,
@@ -469,42 +485,42 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
469
485
)
470
486
} ,
471
487
472
- ( BorrowKind :: Shared , lft , _ , BorrowKind :: Unique , _ , _ ) => {
488
+ ( BorrowKind :: Shared , BorrowKind :: Unique ) => {
473
489
first_borrow_desc = "first " ;
474
490
self . cannot_reborrow_already_uniquely_borrowed (
475
491
span,
476
492
container_name,
477
493
& desc_place,
478
494
"" ,
479
- lft ,
495
+ "immutable" ,
480
496
issued_span,
481
497
"" ,
482
498
None ,
483
499
second_borrow_desc,
484
500
)
485
501
}
486
502
487
- ( BorrowKind :: Mut { .. } , _ , lft , BorrowKind :: Unique , _ , _ ) => {
503
+ ( BorrowKind :: Mut { .. } , BorrowKind :: Unique ) => {
488
504
first_borrow_desc = "first " ;
489
505
self . cannot_reborrow_already_uniquely_borrowed (
490
506
span,
491
507
container_name,
492
508
& desc_place,
493
509
"" ,
494
- lft ,
510
+ "mutable" ,
495
511
issued_span,
496
512
"" ,
497
513
None ,
498
514
second_borrow_desc,
499
515
)
500
516
}
501
517
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 ! ( ) ,
508
524
} ;
509
525
510
526
if issued_spans == borrow_spans {
@@ -1429,20 +1445,23 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
1429
1445
let loan_span = loan_spans. args_or_use ( ) ;
1430
1446
1431
1447
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
+ ) ;
1442
1460
1443
- err. buffer ( & mut self . errors_buffer ) ;
1461
+ err. buffer ( & mut self . errors_buffer ) ;
1444
1462
1445
- return ;
1463
+ return ;
1464
+ }
1446
1465
}
1447
1466
1448
1467
let mut err = self . cannot_assign_to_borrowed (
@@ -1593,6 +1612,35 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
1593
1612
}
1594
1613
}
1595
1614
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
+
1596
1644
/// Annotate argument and return type of function and closure with (synthesized) lifetime for
1597
1645
/// borrow of local value that does not live long enough.
1598
1646
fn annotate_argument_and_return_for_borrow (
0 commit comments