Skip to content

NLL diagnostics for ref mut z @ &mut Some(ref a) uses _ as binding name #67565

Closed

Description

@Centril

Context: #66296 (comment)

The _ below should be z instead.

error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable
  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:11:31
   |
LL |         ref mut z @ &mut Some(ref a) => {
   |         ----------------------^^^^^-
   |         |                     |
   |         |                     immutable borrow occurs here
   |         mutable borrow occurs here
...
LL |             **z = None;
   |             ---------- mutable borrow later used here

cc @mark-i-m @pnkfelix @matthewjasper

cc #65490


Minimal reproducer:

#![feature(bindings_after_at)]

fn foo() {
    let ref mut _z @ ref _a = &mut 1;
    **_z = 0;
}

Activity

  1. added
    A-diagnosticsArea: Messages for errors, warnings, and lints
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    C-bugCategory: This is a bug.
    requires-nightlyThis issue requires a nightly compiler in some way. When possible, use a F-* label instead.
    D-confusingDiagnostics: Confusing error or lint that should be reworked.
    A-NLLArea: Non-lexical lifetimes (NLL)
    NLL-diagnosticsWorking towards the "diagnostic parity" goal
    on Dec 23, 2019
  2. mark-i-m commented on Dec 28, 2019

    @mark-i-m
    Contributor

    I feel like the internal use of _ as a default name for things is a bit undisciplined, and it's leaking into diagnostics in annoying ways. There is also this: #66679

    I feel like internally, we should keep a strong separation between names that we get from the source code being compiled and names being generated by the compiler...

  3. Centril commented on Dec 28, 2019

    @Centril
    ContributorAuthor

    I think this issue is about the narrow issue of why this happens in the case of ref mut x @ Some(ref y) though whereas it doesn't happen in other cases.

  4. mark-i-m commented on Dec 29, 2019

    @mark-i-m
    Contributor

    @Centril Sure, but I think it stems from a larger problem of undisciplined use of _ in various places... If we don't fix that, then we will get weird bugs like this showing up again later even if we fix this particular example....

  5. Centril commented on Dec 29, 2019

    @Centril
    ContributorAuthor

    @mark-i-m I don't mind fixing this by fixing the root cause, but can we discuss the bigger issue in a issue made for that and cc this one?

  6. Centril commented on Feb 17, 2020

    @Centril
    ContributorAuthor

    Investigation

    Source input:

    #![feature(bindings_after_at)]
    
    fn foo() {
        let ref mut _z @ ref _a = &mut 1;
        **_z = 0;
    }

    Results in the following MIR:

    fn  foo() -> () {
        let mut _0: ();                      // return place in scope 0 at foo.rs:5:10: 5:10
        let _1: &mut &mut i32;               // in scope 0 at foo.rs:6:9: 6:28
        let _2: &&mut i32;                   // in scope 0 at foo.rs:6:22: 6:28
        let mut _3: &mut i32;                // in scope 0 at foo.rs:6:31: 6:37
        let mut _4: i32;                     // in scope 0 at foo.rs:6:36: 6:37
        scope 1 {
            debug _z => _1;                  // in scope 1 at foo.rs:6:9: 6:28
            debug _a => _2;                  // in scope 1 at foo.rs:6:22: 6:28
        }
    
        bb0: {
            StorageLive(_3);                 // bb0[0]: scope 0 at foo.rs:6:31: 6:37
            StorageLive(_4);                 // bb0[1]: scope 0 at foo.rs:6:36: 6:37
            _4 = const 1i32;                 // bb0[2]: scope 0 at foo.rs:6:36: 6:37
                                             // ty::Const
                                             // + ty: i32
                                             // + val: Value(Scalar(0x00000001))
                                             // mir::Constant
                                             // + span: foo.rs:6:36: 6:37
                                             // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) }   
            _3 = &mut _4;                    // bb0[3]: scope 0 at foo.rs:6:31: 6:37
            StorageLive(_1);                 // bb0[4]: scope 0 at foo.rs:6:9: 6:28
            _1 = &mut _3;                    // bb0[5]: scope 0 at foo.rs:6:9: 6:28
            StorageLive(_2);                 // bb0[6]: scope 0 at foo.rs:6:22: 6:28
            _2 = &_3;                        // bb0[7]: scope 0 at foo.rs:6:22: 6:28
            (*(*_1)) = const 0i32;           // bb0[8]: scope 1 at foo.rs:7:5: 7:13
                                             // ty::Const
                                             // + ty: i32
                                             // + val: Value(Scalar(0x00000000))
                                             // mir::Constant
                                             // + span: foo.rs:7:12: 7:13
                                             // + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) }   
            _0 = ();                         // bb0[9]: scope 0 at foo.rs:5:10: 8:2
            StorageDead(_2);                 // bb0[10]: scope 0 at foo.rs:8:1: 8:2
            StorageDead(_1);                 // bb0[11]: scope 0 at foo.rs:8:1: 8:2
            StorageDead(_4);                 // bb0[12]: scope 0 at foo.rs:8:1: 8:2
            StorageDead(_3);                 // bb0[13]: scope 0 at foo.rs:8:1: 8:2
            return;                          // bb0[14]: scope 0 at foo.rs:8:2: 8:2
        }
    }

    And we double check with some debug!s in ast_block_stmts (in the if let Some(init) = initializer { branch):

                            debug!("ast_block_stmts: local_decls={:#?}", this.local_decls);
                            debug!("ast_block_stmts: var_debug_info={:#?}", this.var_debug_info);
                            debug!("ast_block_stmts: var_indices={:#?}", this.var_indices);

    using RUSTC_LOG=rustc_mir_build::build::block=debug rustc +gamma-stage1 -Z dump-mir=nll foo.rs we get:

    [DEBUG rustc_mir_build::build::block] ast_block_stmts: local_decls=[                                       
            LocalDecl {                                                                                        
                mutability: Mut,                                                                               
                local_info: Other,                                                                             
                internal: false,                                                                               
                is_block_tail: None,                                                                           
                ty: (),                                                                                        
                user_ty: UserTypeProjections {                                                                 
                    contents: [],                                                                              
                },                                                                                             
                source_info: SourceInfo {                                                                      
                    span: foo.rs:5:10: 5:10,                                                                   
                    scope: scope[0],                                                                           
                },                                                                                             
            },                                                                                                 
            LocalDecl {                                                                                        
                mutability: Not,                                                                               
                local_info: User(                                                                              
                    Set(                                                                                       
                        Var(                                                                                   
                            VarBindingForm {                                                                   
                                binding_mode: BindByReference(                                                 
                                    Not,                                                                       
                                ),                                                                             
                                opt_ty_info: None,                                                             
                                opt_match_place: Some(                                                         
                                    (                                                                          
                                        Some(                                                                  
                                            _3,                                                                
                                        ),                                                                     
                                        foo.rs:6:31: 6:37,                                                     
                                    ),                                                                         
                                ),                                                                             
                                pat_span: foo.rs:6:9: 6:28,                                                    
                            },                                                                                 
                        ),                                                                                     
                    ),                                                                                         
                ),                                                                                             
                internal: false,                                                                               
                is_block_tail: None,                                                                           
                ty: &mut &mut i32,                                                                             
                user_ty: UserTypeProjections {                                                                 
                    contents: [],                                                                              
                },                                                                                             
                source_info: SourceInfo {                                                                      
                    span: foo.rs:6:9: 6:28,                                                                    
                    scope: scope[0],                                                                           
                },                                                                                             
            },
            LocalDecl {                                                                                        
                mutability: Not,                                                                               
                local_info: User(                                                                              
                    Set(                                                                                       
                        Var(                                                                                   
                            VarBindingForm {                                                                   
                                binding_mode: BindByReference(                                                 
                                    Not,                                                                       
                                ),                                                                             
                                opt_ty_info: None,                                                             
                                opt_match_place: Some(                                                         
                                    (
                                        Some(
                                            _3,
                                        ),
                                        foo.rs:6:31: 6:37,
                                    ),
                                ),
                                pat_span: foo.rs:6:9: 6:28,
                            },
                        ),
                    ),
                ),
                internal: false,
                is_block_tail: None,
                ty: &&mut i32,
                user_ty: UserTypeProjections {
                    contents: [],
                },
                source_info: SourceInfo {
                    span: foo.rs:6:22: 6:28,
                    scope: scope[0],
                },
            },
            LocalDecl {
                mutability: Mut,
                local_info: Other,
                internal: false,
                is_block_tail: None,
                ty: &mut i32,
                user_ty: UserTypeProjections {
                    contents: [],
                },
                source_info: SourceInfo {
                    span: foo.rs:6:31: 6:37,
                    scope: scope[0],
                },
            },
            LocalDecl {
                mutability: Mut,
                local_info: Other,
                internal: false,
                is_block_tail: None,
                ty: i32,
                user_ty: UserTypeProjections {
                    contents: [],
                },
                source_info: SourceInfo {
                    span: foo.rs:6:36: 6:37,
                    scope: scope[0],
                },
            },
        ]
    [DEBUG rustc_mir_build::build::block] ast_block_stmts: var_debug_info=[
            VarDebugInfo {
                name: "_z",
                source_info: SourceInfo {
                    span: foo.rs:6:9: 6:28,
                    scope: scope[1],
                },
                place: _1,
            },
            VarDebugInfo {
                name: "_a",
                source_info: SourceInfo {
                    span: foo.rs:6:22: 6:28,
                    scope: scope[1],
                },
                place: _2,
            },
        ]
    [DEBUG rustc_mir_build::build::block] ast_block_stmts: var_indices={
            HirId {
                owner: DefIndex(4),
                local_id: 1,
            }: One(
                _1,
            ),
            HirId {
                owner: DefIndex(4),
                local_id: 2,
            }: One(
                _2,
            ),
        }

    Borrow checking trace:

    The error comes from describe_place_for_conflicting_borrow, which is fed:

    [DEBUG rustc_mir::borrow_check::diagnostics::conflict_errors] describe_place_for_conflicting_borrow(first = _3, second, _3)
    

    We eventually end up in append_local_to_string, where we have (with some changes to the code):

    [DEBUG rustc_mir::borrow_check::diagnostics] append_local_to_string; self.local_names = [
            None,
            Some(
                "_z",
            ),
            Some(
                "_a",
            ),
            None,
            None,
        ]
    

    and so it tries to compute self.local_names[_3] which gives us None and hence there is no name.

    The unchanged log output on master is:

    [DEBUG rustc_mir::borrow_check] MirBorrowckCtxt::process_statement(bb0[0], StorageLive(_3)): BorrowckAnalyses { borrows: [], uninits: [mp0, mp1, mp2, mp3, mp4], ever_inits: [] }
    [DEBUG rustc_mir::borrow_check] MirBorrowckCtxt::process_statement(bb0[1], StorageLive(_4)): BorrowckAnalyses { borrows: [], uninits: [mp0, mp1, mp2, mp3, mp4], ever_inits: [] }
    [DEBUG rustc_mir::borrow_check] MirBorrowckCtxt::process_statement(bb0[2], _4 = const 1i32): BorrowckAnalyses { borrows: [], uninits: [mp0, mp1, mp2, mp3, mp4], ever_inits: [] }
    [DEBUG rustc_mir::borrow_check] check_if_assigned_path_is_moved place: _4                                                       
    [DEBUG rustc_mir::borrow_check] check_access_permissions(_4, Write(Mutate), is_local_mutation_allowed: No)
    [DEBUG rustc_mir::borrow_check] check_access_for_conflict(location=bb0[2], place_span=(_4, foo.rs:6:36: 6:37), sd=Shallow(None), rw=Write(Mutate))
    [DEBUG rustc_mir::borrow_check] MirBorrowckCtxt::process_statement(bb0[3], _3 = &mut _4): BorrowckAnalyses { borrows: [], uninits: [mp0, mp1, mp2, mp3], ever_inits: [in0] }
    [DEBUG rustc_mir::borrow_check] check_access_permissions(_4, Write(MutableBorrow(Mut { allow_two_phase_borrow: false })), is_local_mutation_allowed: No)
    [DEBUG rustc_mir::borrow_check] check_access_for_conflict(location=bb0[3], place_span=(_4, foo.rs:6:31: 6:37), sd=Deep, rw=Write(MutableBorrow(Mut { allow_two_phase_borrow: false })))
    [DEBUG rustc_mir::borrow_check] check_if_full_path_is_moved place: PlaceRef { local: _4, projection: [] }
    [DEBUG rustc_mir::borrow_check] check_if_path_or_subpath_is_moved place: PlaceRef { local: _4, projection: [] }
    [DEBUG rustc_mir::borrow_check] check_if_assigned_path_is_moved place: _3
    [DEBUG rustc_mir::borrow_check] check_access_permissions(_3, Write(Mutate), is_local_mutation_allowed: No)
    [DEBUG rustc_mir::borrow_check] check_access_for_conflict(location=bb0[3], place_span=(_3, foo.rs:6:31: 6:37), sd=Shallow(None), rw=Write(Mutate))
    [DEBUG rustc_mir::borrow_check] MirBorrowckCtxt::process_statement(bb0[4], StorageLive(_1)): BorrowckAnalyses { borrows: [bw0], uninits: [mp0, mp1, mp2], ever_inits: [in0, in1] }
    [DEBUG rustc_mir::borrow_check] MirBorrowckCtxt::process_statement(bb0[5], _1 = &mut _3): BorrowckAnalyses { borrows: [bw0], uninits: [mp0, mp1, mp2], ever_inits: [in0, in1] }
    [DEBUG rustc_mir::borrow_check] check_access_permissions(_3, Write(MutableBorrow(Mut { allow_two_phase_borrow: false })), is_local_mutation_allowed: No)
    [DEBUG rustc_mir::borrow_check] check_access_for_conflict(location=bb0[5], place_span=(_3, foo.rs:6:9: 6:28), sd=Deep, rw=Write(MutableBorrow(Mut { allow_two_phase_borrow: false })))
    [DEBUG rustc_mir::borrow_check::places_conflict] borrow_conflicts_with_place(_4, PlaceRef { local: _3, projection: [] }, Deep, Overlap)
    [DEBUG rustc_mir::borrow_check] check_if_full_path_is_moved place: PlaceRef { local: _3, projection: [] }
    [DEBUG rustc_mir::borrow_check] check_if_path_or_subpath_is_moved place: PlaceRef { local: _3, projection: [] }
    [DEBUG rustc_mir::borrow_check] check_if_assigned_path_is_moved place: _1
    [DEBUG rustc_mir::borrow_check] check_if_reassignment_to_immutable_state(_1)
    [DEBUG rustc_mir::borrow_check] MirBorrowckCtxt::process_statement(bb0[6], StorageLive(_2)): BorrowckAnalyses { borrows: [bw0, bw1], uninits: [mp0, mp2], ever_inits: [in0, in1, in2] }
    [DEBUG rustc_mir::borrow_check] MirBorrowckCtxt::process_statement(bb0[7], _2 = &_3): BorrowckAnalyses { borrows: [bw0, bw1], uninits: [mp0, mp2], ever_inits: [in0, in1, in2] }
    [DEBUG rustc_mir::borrow_check] check_access_permissions(_3, Read(Borrow(Shared)), is_local_mutation_allowed: No)
    [DEBUG rustc_mir::borrow_check] check_access_for_conflict(location=bb0[7], place_span=(_3, foo.rs:6:22: 6:28), sd=Deep, rw=Read(Borrow(Shared)))
    [DEBUG rustc_mir::borrow_check::places_conflict] borrow_conflicts_with_place(_4, PlaceRef { local: _3, projection: [] }, Deep, Overlap)
    [DEBUG rustc_mir::borrow_check::places_conflict] borrow_conflicts_with_place(_3, PlaceRef { local: _3, projection: [] }, Deep, Overlap)
    [DEBUG rustc_mir::borrow_check::path_utils] each_borrow_involving_path: bw1 @ BorrowData { reserve_location: bb0[5], activation_location: NotTwoPhase, kind: Mut { allow_two_phase_borrow: false }, region: '_#3r, borrowed_place: _3, 
    assigned_place: _1 } vs. _3/Deep
    [DEBUG rustc_mir::borrow_check::path_utils] is_active(borrow_data=BorrowData { reserve_location: bb0[5], activation_location: NotTwoPhase, kind: Mut { allow_two_phase_borrow: false }, region: '_#3r, borrowed_place: _3, assigned_place: _1 }, location=bb0[7])
    [DEBUG rustc_mir::borrow_check::diagnostics] borrow_spans: use_span=foo.rs:6:9: 6:28 location=bb0[5]
    [DEBUG rustc_mir::borrow_check::diagnostics] borrow_spans: use_span=foo.rs:6:22: 6:28 location=bb0[7]
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] explain_why_borrow_contains_point(location=bb0[7], borrow=BorrowData { reserve_location: bb0[5], activation_location: NotTwoPhase, kind: Mut { allow_two_phase_borrow: false }, region: '_#3r, borrowed_place: _3, assigned_place: _1 }, kind_place=None)
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] explain_why_borrow_contains_point: borrow_region_vid='_#3r
    [DEBUG rustc_mir::borrow_check::region_infer] find_sub_region_live_at(fr1='_#3r, elem=bb0[7])
    [DEBUG rustc_mir::borrow_check::region_infer] find_constraint_paths_between_regions: from_region='_#3r r='_#3r value={bb0[5..=8]}
    [DEBUG rustc_mir::borrow_check::region_infer] find_sub_region_live_at: liveness_constraints for '_#3r are "{bb0[5]}"
    [DEBUG rustc_mir::borrow_check::region_infer] find_constraint_paths_between_regions: from_region='_#3r r='_#5r value={bb0[6..=8]}
    [DEBUG rustc_mir::borrow_check::region_infer] find_sub_region_live_at: liveness_constraints for '_#5r are "{bb0[6..=8]}"
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] explain_why_borrow_contains_point: region_sub='_#5r
    [DEBUG rustc_mir::borrow_check::diagnostics] move_spans: moved_place=PlaceRef { local: _1, projection: [] } location=bb0[8] stmt=(*(*_1)) = const 0i32
    [DEBUG rustc_mir::borrow_check::diagnostics] borrow_spans: use_span=foo.rs:7:5: 7:13 location=bb0[8]
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] reach_through_backedge: from=bb0[8] to=bb0[8]
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] reach_through_backedge: location=bb0[8] outmost_back_edge=None
                           pending_locations=[] visited_locations={bb0[8]}
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] reach_through_backedge: location=bb0[9] outmost_back_edge=None
                           pending_locations=[] visited_locations={bb0[8], bb0[9]}
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] reach_through_backedge: location=bb0[10] outmost_back_edge=None
                           pending_locations=[] visited_locations={bb0[8], bb0[9], bb0[10]}
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] reach_through_backedge: location=bb0[11] outmost_back_edge=None
                           pending_locations=[] visited_locations={bb0[8], bb0[10], bb0[9], bb0[11]}
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] reach_through_backedge: location=bb0[12] outmost_back_edge=None
                           pending_locations=[] visited_locations={bb0[8], bb0[10], bb0[12], bb0[9], bb0[11]}
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] reach_through_backedge: location=bb0[13] outmost_back_edge=None
                           pending_locations=[] visited_locations={bb0[8], bb0[13], bb0[10], bb0[12], bb0[9], bb0[11]}
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] reach_through_backedge: location=bb0[14] outmost_back_edge=None
                           pending_locations=[] visited_locations={bb0[8], bb0[13], bb0[10], bb0[12], bb0[9], bb0[14], bb0[11]}
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait_object: location=bb0[5] stmt=Some(_1 = &mut _3)
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait: target=_1 queue=[bb0[5]]
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait: target=_1
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait_object: stmt=_1 = &mut _3
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait: queue=[bb0[6]]
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait: target=_1
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait_object: stmt=StorageLive(_2)
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait: queue=[bb0[7]]
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait: target=_1
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait_object: stmt=_2 = &_3
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait: queue=[bb0[8]]
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait: target=_1
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait_object: stmt=(*(*_1)) = const 0i32
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait: target=_1
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait_object: stmt=_0 = ()
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait: queue=[bb0[10]]
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait: target=_1
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait_object: stmt=StorageDead(_2)
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait: queue=[bb0[11]]
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait: target=_1
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait_object: stmt=StorageDead(_1)
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait: queue=[bb0[12]]
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait: target=_1
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait_object: stmt=StorageDead(_4)
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait: queue=[bb0[13]]
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait: target=_1
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait_object: stmt=StorageDead(_3)
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait: queue=[bb0[14]]
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait: target=_1
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait_object: terminator=Terminator { source_info: SourceInfo { span: foo.rs:8:2: 8:2, scope: scope[0] }, kind: return }
    [DEBUG rustc_mir::borrow_check::diagnostics::explain_borrow] was_captured_by_trait: queue=[]
    [DEBUG rustc_mir::borrow_check] access_place: logging error place_span=`(_3, foo.rs:6:22: 6:28)` kind=`(Deep, Read(Borrow(Shared)))`
    [DEBUG rustc_mir::borrow_check] check_if_full_path_is_moved place: PlaceRef { local: _3, projection: [] }
    [DEBUG rustc_mir::borrow_check] check_if_path_or_subpath_is_moved place: PlaceRef { local: _3, projection: [] }
    [DEBUG rustc_mir::borrow_check] check_if_assigned_path_is_moved place: _2
    [DEBUG rustc_mir::borrow_check] check_if_reassignment_to_immutable_state(_2)
    [DEBUG rustc_mir::borrow_check] MirBorrowckCtxt::process_statement(bb0[8], (*(*_1)) = const 0i32): BorrowckAnalyses { borrows: [bw0, bw1], uninits: [mp0], ever_inits: [in0, in1, in2, in3] }
    [DEBUG rustc_mir::borrow_check] check_if_assigned_path_is_moved place: (*(*_1))
    [DEBUG rustc_mir::borrow_check] check_if_full_path_is_moved place: PlaceRef { local: _1, projection: [Deref] }
    [DEBUG rustc_mir::borrow_check] check_access_permissions((*(*_1)), Write(Mutate), is_local_mutation_allowed: No)
    [DEBUG rustc_mir::borrow_check] check_access_for_conflict(location=bb0[8], place_span=((*(*_1)), foo.rs:7:5: 7:13), sd=Shallow(None), rw=Write(Mutate))
    [DEBUG rustc_mir::borrow_check::places_conflict] borrow_conflicts_with_place(_4, PlaceRef { local: _1, projection: [Deref, Deref] }, Shallow(None), Overlap)
    [DEBUG rustc_mir::borrow_check::places_conflict] place_element_conflict: DISJOINT-LOCAL
    [DEBUG rustc_mir::borrow_check::places_conflict] borrow_conflicts_with_place: disjoint
    [DEBUG rustc_mir::borrow_check::places_conflict] borrow_conflicts_with_place(_3, PlaceRef { local: _1, projection: [Deref, Deref] }, Shallow(None), Overlap)
    [DEBUG rustc_mir::borrow_check::places_conflict] place_element_conflict: DISJOINT-LOCAL
    [DEBUG rustc_mir::borrow_check::places_conflict] borrow_conflicts_with_place: disjoint
    [DEBUG rustc_mir::borrow_check] MirBorrowckCtxt::process_statement(bb0[9], _0 = ()): BorrowckAnalyses { borrows: [], uninits: [mp0], ever_inits: [in0, in1, in2, in3] }
    [DEBUG rustc_mir::borrow_check] check_if_assigned_path_is_moved place: _0
    [DEBUG rustc_mir::borrow_check] check_access_permissions(_0, Write(Mutate), is_local_mutation_allowed: No)
    [DEBUG rustc_mir::borrow_check] check_access_for_conflict(location=bb0[9], place_span=(_0, foo.rs:5:12: 8:2), sd=Shallow(None), rw=Write(Mutate))
    [DEBUG rustc_mir::borrow_check] MirBorrowckCtxt::process_statement(bb0[10], StorageDead(_2)): BorrowckAnalyses { borrows: [], uninits: [], ever_inits: [in0, in1, in2, in3, in4] }
    [DEBUG rustc_mir::borrow_check] check_access_permissions(_2, Write(StorageDeadOrDrop), is_local_mutation_allowed: Yes)
    [DEBUG rustc_mir::borrow_check] check_access_for_conflict(location=bb0[10], place_span=(_2, foo.rs:8:1: 8:2), sd=Shallow(None), rw=Write(StorageDeadOrDrop))
    [DEBUG rustc_mir::borrow_check] MirBorrowckCtxt::process_statement(bb0[11], StorageDead(_1)): BorrowckAnalyses { borrows: [], uninits: [mp2], ever_inits: [in0, in1, in2, in4] }
    [DEBUG rustc_mir::borrow_check] check_access_permissions(_1, Write(StorageDeadOrDrop), is_local_mutation_allowed: Yes)
    [DEBUG rustc_mir::borrow_check] check_access_for_conflict(location=bb0[11], place_span=(_1, foo.rs:8:1: 8:2), sd=Shallow(None), rw=Write(StorageDeadOrDrop))
    [DEBUG rustc_mir::borrow_check] MirBorrowckCtxt::process_statement(bb0[12], StorageDead(_4)): BorrowckAnalyses { borrows: [], uninits: [mp1, mp2], ever_inits: [in0, in1, in4] }
    [DEBUG rustc_mir::borrow_check] check_access_permissions(_4, Write(StorageDeadOrDrop), is_local_mutation_allowed: Yes)
    [DEBUG rustc_mir::borrow_check] check_access_for_conflict(location=bb0[12], place_span=(_4, foo.rs:8:1: 8:2), sd=Shallow(None), rw=Write(StorageDeadOrDrop))
    [DEBUG rustc_mir::borrow_check] MirBorrowckCtxt::process_statement(bb0[13], StorageDead(_3)): BorrowckAnalyses { borrows: [], uninits: [mp1, mp2, mp4], ever_inits: [in1, in4] }
    [DEBUG rustc_mir::borrow_check] check_access_permissions(_3, Write(StorageDeadOrDrop), is_local_mutation_allowed: Yes)
    [DEBUG rustc_mir::borrow_check] check_access_for_conflict(location=bb0[13], place_span=(_3, foo.rs:8:1: 8:2), sd=Shallow(None), rw=Write(StorageDeadOrDrop))
    [DEBUG rustc_mir::borrow_check] MirBorrowckCtxt::process_terminator(bb0[14], Terminator { source_info: SourceInfo { span: foo.rs:8:2: 8:2, scope: scope[0] }, kind: return }): BorrowckAnalyses { borrows: [], uninits: [mp1, mp2, mp3, mp4], ever_inits: [in4] }
    [DEBUG rustc_mir::borrow_check::used_muts] visit_statement: statement=_4 = const 1i32 local=_4 never_initialized_mut_locals={}
    [DEBUG rustc_mir::borrow_check::used_muts] visit_statement: statement=_3 = &mut _4 local=_3 never_initialized_mut_locals={}
    [DEBUG rustc_mir::borrow_check::used_muts] visit_statement: statement=_1 = &mut _3 local=_1 never_initialized_mut_locals={}
    [DEBUG rustc_mir::borrow_check::used_muts] visit_statement: statement=_2 = &_3 local=_2 never_initialized_mut_locals={}
    [DEBUG rustc_mir::borrow_check::used_muts] visit_statement: statement=(*(*_1)) = const 0i32 local=_1 never_initialized_mut_locals={}
    [DEBUG rustc_mir::borrow_check::used_muts] visit_statement: statement=_0 = () local=_0 never_initialized_mut_locals={}
    [DEBUG rustc_mir::borrow_check::used_muts] visit_terminator_kind: kind=return
    [DEBUG rustc_mir::borrow_check::used_muts] gather_used_muts: never_initialized_mut_locals={}
    [DEBUG rustc_mir::borrow_check] mbcx.used_mut: {_4, _3}
    
  7. added a commit that references this issue on Mar 26, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-NLLArea: Non-lexical lifetimes (NLL)A-diagnosticsArea: Messages for errors, warnings, and lintsC-bugCategory: This is a bug.D-confusingDiagnostics: Confusing error or lint that should be reworked.F-bindings_after_at`#![feature(bindings_after_at)]`NLL-diagnosticsWorking towards the "diagnostic parity" goalT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.requires-nightlyThis issue requires a nightly compiler in some way. When possible, use a F-* label instead.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions