diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 571fe99897058..399c6dbcb7ca6 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -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; diff --git a/src/test/ui/consts/qualif_overwrite.rs b/src/test/ui/consts/qualif_overwrite.rs index 65e182945bf79..806a74ee4530b 100644 --- a/src/test/ui/consts/qualif_overwrite.rs +++ b/src/test/ui/consts/qualif_overwrite.rs @@ -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> = { 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() {} diff --git a/src/test/ui/consts/qualif_overwrite.stderr b/src/test/ui/consts/qualif_overwrite.stderr index b24c0fa70f063..4fac64bf8063f 100644 --- a/src/test/ui/consts/qualif_overwrite.stderr +++ b/src/test/ui/consts/qualif_overwrite.stderr @@ -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 | ^^^^ diff --git a/src/test/ui/consts/qualif_overwrite_2.rs b/src/test/ui/consts/qualif_overwrite_2.rs new file mode 100644 index 0000000000000..29557a3da4781 --- /dev/null +++ b/src/test/ui/consts/qualif_overwrite_2.rs @@ -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> = { + 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() {} diff --git a/src/test/ui/consts/qualif_overwrite_2.stderr b/src/test/ui/consts/qualif_overwrite_2.stderr new file mode 100644 index 0000000000000..181b728c7b76f --- /dev/null +++ b/src/test/ui/consts/qualif_overwrite_2.stderr @@ -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`.