Skip to content

[nll] optimize + fix check_if_reassignment_to_immutable_state #53189

Closed
@nikomatsakis

Description

@nikomatsakis

check_if_reassignment_to_immutable_state has the of handling assignments to immutable local variables. These are a bit tricky: you are allowed to assign to an immutable local variable, but only if it has never been assigned to before. Actually, the logic implemented in the NLL borrow checker is kind of wrong (or at least inconsistent with the AST checker). It's also just slow.

Here is an example of the sort of assignments that should be accepted (playground):

#![feature(nll)]

fn main() {
    let x: (u32, u32);
    
    if true {
        x = (1, 2);
    } else {
        x = (3, 4);
    }
    
    drop(x);
}

This example is rightly rejected (but we should check to ensure we have a test) (playground):

#![feature(nll)]

fn main() {
    let x: (u32, u32);
    x = (1, 2);
    x = (3, 4);
    drop(x);
}

This example should be rejected but currently is not (playground):

#![feature(nll)]

fn main() {
    let x: (u32, u32);
    
    x.0 = 22;
}

In addition to being slightly wrong, the current implementation is also slow. It iterates over all initialized paths and checks that the path being assigned to (e.g., x.0 in the third example) is disjoint from all of them:

for i in flow_state.ever_inits.iter_incoming() {
let init = self.move_data.inits[i];
let init_place = &self.move_data.move_paths[init.path].place;
if places_conflict::places_conflict(self.tcx, self.mir, &init_place, place, Deep) {
self.report_illegal_reassignment(context, (place, span), init.span, err_place);
break;
}
}

I will write below how I think it should work.

Metadata

Metadata

Assignees

Labels

A-NLLArea: Non-lexical lifetimes (NLL)NLL-performantWorking towards the "performance is good" goalNLL-soundWorking towards the "invalid code does not compile" goalT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions