Skip to content

Commit

Permalink
Explain why we do not overwrite qualification of locals
Browse files Browse the repository at this point in the history
  • Loading branch information
oli-obk committed Nov 21, 2018
1 parent 22aebd5 commit 6db8c6c
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 7 deletions.
7 changes: 5 additions & 2 deletions src/librustc_mir/transform/qualify_consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,9 +277,12 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
};
debug!("store to var {:?}", index);
match &mut self.local_qualif[index] {
// update
// this is overly restrictive, because even full assignments do not clear the qualif
// While we could special case full assignments, this would be inconsistent with
// aggregates where we overwrite all fields via assignments, which would not get
// that feature.
Some(ref mut qualif) => *qualif = *qualif | self.qualif,
// or insert
// insert new qualification
qualif @ None => *qualif = Some(self.qualif),
}
return;
Expand Down
10 changes: 6 additions & 4 deletions src/test/ui/consts/qualif_overwrite.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
// compile-pass

#![feature(const_let)]

use std::cell::Cell;

// this is overly conservative. The reset to `None` should clear `a` of all qualifications
// while we could fix this, it would be inconsistent with `qualif_overwrite_2.rs`.
// We can fix this properly in the future by allowing constants that do not depend on generics
// to be checked by an analysis on the final value instead of looking at the body.
const FOO: &Option<Cell<usize>> = {
let mut a = Some(Cell::new(0));
a = None; // resets `qualif(a)` to `qualif(None)`
&{a}
a = None; // sets `qualif(a)` to `qualif(a) | qualif(None)`
&{a} //~ ERROR cannot borrow a constant which may contain interior mutability
};

fn main() {}
2 changes: 1 addition & 1 deletion src/test/ui/consts/qualif_overwrite.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
--> $DIR/qualif_overwrite.rs:8:5
--> $DIR/qualif_overwrite.rs:12:5
|
LL | &{a} //~ ERROR cannot borrow a constant which may contain interior mutability
| ^^^^
Expand Down
13 changes: 13 additions & 0 deletions src/test/ui/consts/qualif_overwrite_2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#![feature(const_let)]

use std::cell::Cell;

// const qualification is not smart enough to know about fields and always assumes that there might
// be other fields that caused the qualification
const FOO: &Option<Cell<usize>> = {
let mut a = (Some(Cell::new(0)),);
a.0 = None; // sets `qualif(a)` to `qualif(a) | qualif(None)`
&{a.0} //~ ERROR cannot borrow a constant which may contain interior mutability
};

fn main() {}
9 changes: 9 additions & 0 deletions src/test/ui/consts/qualif_overwrite_2.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
--> $DIR/qualif_overwrite_2.rs:10:5
|
LL | &{a.0} //~ ERROR cannot borrow a constant which may contain interior mutability
| ^^^^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0492`.

0 comments on commit 6db8c6c

Please sign in to comment.