Auto merge of #53258 - nikomatsakis:issue-53189-optimize-reassignment-immutable-state, r=pnkfelix

optimize reassignment immutable state

This is the "simple fix" when it comes to checking for reassignment. We just shoot for compatibility with the AST-based checker. Makes no attempt to solve #21232.

I opted for this simpler fix because I didn't want to think about complications [like the ones described here](https://github.com/rust-lang/rust/issues/21232#issuecomment-412219247).

Let's do some profiling measurements.

Fixes #53189

r? @pnkfelix
This commit is contained in:
bors 2018-08-19 17:44:43 +00:00
commit 3ac79c7184
18 changed files with 424 additions and 89 deletions

View file

@ -0,0 +1,9 @@
error[E0381]: use of possibly uninitialized variable: `x`
--> $DIR/assign_mutable_fields.rs:29:10
|
LL | drop(x); //~ ERROR
| ^ use of possibly uninitialized `x`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0381`.

View file

@ -0,0 +1,32 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Currently, we permit you to assign to individual fields of a mut
// var, but we do not permit you to use the complete var afterwards.
// We hope to fix this at some point.
//
// FIXME(#21232)
fn assign_both_fields_and_use() {
let mut x: (u32, u32);
x.0 = 1;
x.1 = 22;
drop(x.0); //~ ERROR
drop(x.1); //~ ERROR
}
fn assign_both_fields_the_use_var() {
let mut x: (u32, u32);
x.0 = 1;
x.1 = 22;
drop(x); //~ ERROR
}
fn main() { }

View file

@ -0,0 +1,21 @@
error[E0381]: use of possibly uninitialized variable: `x.0`
--> $DIR/assign_mutable_fields.rs:21:10
|
LL | drop(x.0); //~ ERROR
| ^^^ use of possibly uninitialized `x.0`
error[E0381]: use of possibly uninitialized variable: `x.1`
--> $DIR/assign_mutable_fields.rs:22:10
|
LL | drop(x.1); //~ ERROR
| ^^^ use of possibly uninitialized `x.1`
error[E0381]: use of possibly uninitialized variable: `x`
--> $DIR/assign_mutable_fields.rs:29:10
|
LL | drop(x); //~ ERROR
| ^ use of possibly uninitialized `x`
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0381`.

View file

@ -0,0 +1,44 @@
error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable
--> $DIR/reassignment_immutable_fields.rs:17:5
|
LL | let x: (u32, u32);
| - help: consider changing this to be mutable: `mut x`
LL | x.0 = 1; //~ ERROR
| ^^^^^^^ cannot assign
error[E0594]: cannot assign to `x.1`, as `x` is not declared as mutable
--> $DIR/reassignment_immutable_fields.rs:18:5
|
LL | let x: (u32, u32);
| - help: consider changing this to be mutable: `mut x`
LL | x.0 = 1; //~ ERROR
LL | x.1 = 22; //~ ERROR
| ^^^^^^^^ cannot assign
error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable
--> $DIR/reassignment_immutable_fields.rs:25:5
|
LL | let x: (u32, u32);
| - help: consider changing this to be mutable: `mut x`
LL | x.0 = 1; //~ ERROR
| ^^^^^^^ cannot assign
error[E0594]: cannot assign to `x.1`, as `x` is not declared as mutable
--> $DIR/reassignment_immutable_fields.rs:26:5
|
LL | let x: (u32, u32);
| - help: consider changing this to be mutable: `mut x`
LL | x.0 = 1; //~ ERROR
LL | x.1 = 22; //~ ERROR
| ^^^^^^^^ cannot assign
error[E0381]: use of possibly uninitialized variable: `x`
--> $DIR/reassignment_immutable_fields.rs:27:10
|
LL | drop(x); //~ ERROR
| ^ use of possibly uninitialized `x`
error: aborting due to 5 previous errors
Some errors occurred: E0381, E0594.
For more information about an error, try `rustc --explain E0381`.

View file

@ -0,0 +1,30 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// This test is currently disallowed, but we hope someday to support it.
//
// FIXME(#21232)
fn assign_both_fields_and_use() {
let x: (u32, u32);
x.0 = 1; //~ ERROR
x.1 = 22; //~ ERROR
drop(x.0); //~ ERROR
drop(x.1); //~ ERROR
}
fn assign_both_fields_the_use_var() {
let x: (u32, u32);
x.0 = 1; //~ ERROR
x.1 = 22; //~ ERROR
drop(x); //~ ERROR
}
fn main() { }

View file

@ -0,0 +1,56 @@
error[E0594]: cannot assign to field `x.0` of immutable binding
--> $DIR/reassignment_immutable_fields.rs:17:5
|
LL | let x: (u32, u32);
| - consider changing this to `mut x`
LL | x.0 = 1; //~ ERROR
| ^^^^^^^ cannot mutably borrow field of immutable binding
error[E0594]: cannot assign to field `x.1` of immutable binding
--> $DIR/reassignment_immutable_fields.rs:18:5
|
LL | let x: (u32, u32);
| - consider changing this to `mut x`
LL | x.0 = 1; //~ ERROR
LL | x.1 = 22; //~ ERROR
| ^^^^^^^^ cannot mutably borrow field of immutable binding
error[E0381]: use of possibly uninitialized variable: `x.0`
--> $DIR/reassignment_immutable_fields.rs:19:10
|
LL | drop(x.0); //~ ERROR
| ^^^ use of possibly uninitialized `x.0`
error[E0381]: use of possibly uninitialized variable: `x.1`
--> $DIR/reassignment_immutable_fields.rs:20:10
|
LL | drop(x.1); //~ ERROR
| ^^^ use of possibly uninitialized `x.1`
error[E0594]: cannot assign to field `x.0` of immutable binding
--> $DIR/reassignment_immutable_fields.rs:25:5
|
LL | let x: (u32, u32);
| - consider changing this to `mut x`
LL | x.0 = 1; //~ ERROR
| ^^^^^^^ cannot mutably borrow field of immutable binding
error[E0594]: cannot assign to field `x.1` of immutable binding
--> $DIR/reassignment_immutable_fields.rs:26:5
|
LL | let x: (u32, u32);
| - consider changing this to `mut x`
LL | x.0 = 1; //~ ERROR
LL | x.1 = 22; //~ ERROR
| ^^^^^^^^ cannot mutably borrow field of immutable binding
error[E0381]: use of possibly uninitialized variable: `x`
--> $DIR/reassignment_immutable_fields.rs:27:10
|
LL | drop(x); //~ ERROR
| ^ use of possibly uninitialized `x`
error: aborting due to 7 previous errors
Some errors occurred: E0381, E0594.
For more information about an error, try `rustc --explain E0381`.

View file

@ -0,0 +1,20 @@
error[E0594]: cannot assign to `x.a`, as `x` is not declared as mutable
--> $DIR/reassignment_immutable_fields_overlapping.rs:22:5
|
LL | let x: Foo;
| - help: consider changing this to be mutable: `mut x`
LL | x.a = 1; //~ ERROR
| ^^^^^^^ cannot assign
error[E0594]: cannot assign to `x.b`, as `x` is not declared as mutable
--> $DIR/reassignment_immutable_fields_overlapping.rs:23:5
|
LL | let x: Foo;
| - help: consider changing this to be mutable: `mut x`
LL | x.a = 1; //~ ERROR
LL | x.b = 22; //~ ERROR
| ^^^^^^^^ cannot assign
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0594`.

View file

@ -0,0 +1,26 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// This should never be allowed -- `foo.a` and `foo.b` are
// overlapping, so since `x` is not `mut` we should not permit
// reassignment.
union Foo {
a: u32,
b: u32,
}
unsafe fn overlapping_fields() {
let x: Foo;
x.a = 1; //~ ERROR
x.b = 22; //~ ERROR
}
fn main() { }

View file

@ -0,0 +1,20 @@
error[E0594]: cannot assign to field `x.a` of immutable binding
--> $DIR/reassignment_immutable_fields_overlapping.rs:22:5
|
LL | let x: Foo;
| - consider changing this to `mut x`
LL | x.a = 1; //~ ERROR
| ^^^^^^^ cannot mutably borrow field of immutable binding
error[E0594]: cannot assign to field `x.b` of immutable binding
--> $DIR/reassignment_immutable_fields_overlapping.rs:23:5
|
LL | let x: Foo;
| - consider changing this to `mut x`
LL | x.a = 1; //~ ERROR
LL | x.b = 22; //~ ERROR
| ^^^^^^^^ cannot mutably borrow field of immutable binding
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0594`.

View file

@ -0,0 +1,38 @@
error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable
--> $DIR/reassignment_immutable_fields_twice.rs:17:5
|
LL | let x: (u32, u32);
| - help: consider changing this to be mutable: `mut x`
LL | x = (22, 44);
LL | x.0 = 1; //~ ERROR
| ^^^^^^^ cannot assign
error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable
--> $DIR/reassignment_immutable_fields_twice.rs:22:5
|
LL | let x: (u32, u32);
| - help: consider changing this to be mutable: `mut x`
LL | x.0 = 1; //~ ERROR
| ^^^^^^^ cannot assign
error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable
--> $DIR/reassignment_immutable_fields_twice.rs:23:5
|
LL | let x: (u32, u32);
| - help: consider changing this to be mutable: `mut x`
LL | x.0 = 1; //~ ERROR
LL | x.0 = 22; //~ ERROR
| ^^^^^^^^ cannot assign
error[E0594]: cannot assign to `x.1`, as `x` is not declared as mutable
--> $DIR/reassignment_immutable_fields_twice.rs:24:5
|
LL | let x: (u32, u32);
| - help: consider changing this to be mutable: `mut x`
...
LL | x.1 = 44; //~ ERROR
| ^^^^^^^^ cannot assign
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0594`.

View file

@ -0,0 +1,27 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// This should never be allowed -- since `x` is not `mut`, so `x.0`
// cannot be assigned twice.
fn var_then_field() {
let x: (u32, u32);
x = (22, 44);
x.0 = 1; //~ ERROR
}
fn same_field_twice() {
let x: (u32, u32);
x.0 = 1; //~ ERROR
x.0 = 22; //~ ERROR
x.1 = 44; //~ ERROR
}
fn main() { }

View file

@ -0,0 +1,38 @@
error[E0594]: cannot assign to field `x.0` of immutable binding
--> $DIR/reassignment_immutable_fields_twice.rs:17:5
|
LL | let x: (u32, u32);
| - consider changing this to `mut x`
LL | x = (22, 44);
LL | x.0 = 1; //~ ERROR
| ^^^^^^^ cannot mutably borrow field of immutable binding
error[E0594]: cannot assign to field `x.0` of immutable binding
--> $DIR/reassignment_immutable_fields_twice.rs:22:5
|
LL | let x: (u32, u32);
| - consider changing this to `mut x`
LL | x.0 = 1; //~ ERROR
| ^^^^^^^ cannot mutably borrow field of immutable binding
error[E0594]: cannot assign to field `x.0` of immutable binding
--> $DIR/reassignment_immutable_fields_twice.rs:23:5
|
LL | let x: (u32, u32);
| - consider changing this to `mut x`
LL | x.0 = 1; //~ ERROR
LL | x.0 = 22; //~ ERROR
| ^^^^^^^^ cannot mutably borrow field of immutable binding
error[E0594]: cannot assign to field `x.1` of immutable binding
--> $DIR/reassignment_immutable_fields_twice.rs:24:5
|
LL | let x: (u32, u32);
| - consider changing this to `mut x`
...
LL | x.1 = 44; //~ ERROR
| ^^^^^^^^ cannot mutably borrow field of immutable binding
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0594`.

View file

@ -6,26 +6,23 @@ LL | let f = Foo { v: Vec::new() };
LL | f.v.push("cat".to_string()); //~ ERROR cannot borrow
| ^^^ cannot borrow as mutable
error[E0384]: cannot assign twice to immutable variable `s`
error[E0594]: cannot assign to `s.x`, as `s` is not declared as mutable
--> $DIR/issue-35937.rs:26:5
|
LL | let s = S { x: 42 };
| -
| |
| first assignment to `s`
| consider changing this to `mut s`
| - help: consider changing this to be mutable: `mut s`
LL | s.x += 1; //~ ERROR cannot assign
| ^^^^^^^^ cannot assign twice to immutable variable
| ^^^^^^^^ cannot assign
error[E0384]: cannot assign to immutable argument `s`
error[E0594]: cannot assign to `s.x`, as `s` is not declared as mutable
--> $DIR/issue-35937.rs:30:5
|
LL | fn bar(s: S) {
| - consider changing this to `mut s`
| - help: consider changing this to be mutable: `mut s`
LL | s.x += 1; //~ ERROR cannot assign
| ^^^^^^^^ cannot assign to immutable argument
| ^^^^^^^^ cannot assign
error: aborting due to 3 previous errors
Some errors occurred: E0384, E0596.
For more information about an error, try `rustc --explain E0384`.
Some errors occurred: E0594, E0596.
For more information about an error, try `rustc --explain E0594`.

View file

@ -1,19 +1,19 @@
error[E0384]: cannot assign to immutable argument `y`
error[E0594]: cannot assign to `*y`, as `y` is not declared as mutable
--> $DIR/immut-function-arguments.rs:15:5
|
LL | fn f(y: Box<isize>) {
| - consider changing this to `mut y`
| - help: consider changing this to be mutable: `mut y`
LL | *y = 5; //[ast]~ ERROR cannot assign
| ^^^^^^ cannot assign to immutable argument
| ^^^^^^ cannot assign
error[E0384]: cannot assign to immutable argument `q`
error[E0594]: cannot assign to `*q`, as `q` is not declared as mutable
--> $DIR/immut-function-arguments.rs:20:35
|
LL | let _frob = |q: Box<isize>| { *q = 2; }; //[ast]~ ERROR cannot assign
| - ^^^^^^ cannot assign to immutable argument
| - ^^^^^^ cannot assign
| |
| consider changing this to `mut q`
| help: consider changing this to be mutable: `mut q`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0384`.
For more information about this error, try `rustc --explain E0594`.

View file

@ -1,19 +1,19 @@
error[E0384]: cannot assign to immutable argument `y`
error[E0594]: cannot assign to `*y`, as `y` is not declared as mutable
--> $DIR/immut-function-arguments.rs:15:5
|
LL | fn f(y: Box<isize>) {
| - consider changing this to `mut y`
| - help: consider changing this to be mutable: `mut y`
LL | *y = 5; //[ast]~ ERROR cannot assign
| ^^^^^^ cannot assign to immutable argument
| ^^^^^^ cannot assign
error[E0384]: cannot assign to immutable argument `q`
error[E0594]: cannot assign to `*q`, as `q` is not declared as mutable
--> $DIR/immut-function-arguments.rs:20:35
|
LL | let _frob = |q: Box<isize>| { *q = 2; }; //[ast]~ ERROR cannot assign
| - ^^^^^^ cannot assign to immutable argument
| - ^^^^^^ cannot assign
| |
| consider changing this to `mut q`
| help: consider changing this to be mutable: `mut q`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0384`.
For more information about this error, try `rustc --explain E0594`.

View file

@ -1,14 +1,11 @@
error[E0384]: cannot assign twice to immutable variable `nyan`
error[E0594]: cannot assign to `nyan.how_hungry`, as `nyan` is not declared as mutable
--> $DIR/mutable-class-fields.rs:28:3
|
LL | let nyan : cat = cat(52, 99);
| ----
| |
| first assignment to `nyan`
| consider changing this to `mut nyan`
| ---- help: consider changing this to be mutable: `mut nyan`
LL | nyan.how_hungry = 0; //[ast]~ ERROR cannot assign
| ^^^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable
| ^^^^^^^^^^^^^^^^^^^ cannot assign
error: aborting due to previous error
For more information about this error, try `rustc --explain E0384`.
For more information about this error, try `rustc --explain E0594`.

View file

@ -1,14 +1,11 @@
error[E0384]: cannot assign twice to immutable variable `nyan`
error[E0594]: cannot assign to `nyan.how_hungry`, as `nyan` is not declared as mutable
--> $DIR/mutable-class-fields.rs:28:3
|
LL | let nyan : cat = cat(52, 99);
| ----
| |
| first assignment to `nyan`
| consider changing this to `mut nyan`
| ---- help: consider changing this to be mutable: `mut nyan`
LL | nyan.how_hungry = 0; //[ast]~ ERROR cannot assign
| ^^^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable
| ^^^^^^^^^^^^^^^^^^^ cannot assign
error: aborting due to previous error
For more information about this error, try `rustc --explain E0384`.
For more information about this error, try `rustc --explain E0594`.