Skip to content

Commit 4697d4e

Browse files
committed
const-checking: add some corner case tests, and fix some nits
1 parent d9a2886 commit 4697d4e

File tree

5 files changed

+46
-6
lines changed

5 files changed

+46
-6
lines changed

compiler/rustc_const_eval/src/const_eval/eval_queries.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -412,10 +412,10 @@ pub fn const_validate_mplace<'mir, 'tcx>(
412412
_ if cid.promoted.is_some() => CtfeValidationMode::Promoted,
413413
Some(mutbl) => CtfeValidationMode::Static { mutbl }, // a `static`
414414
None => {
415-
// In normal `const` (not promoted), the outermost allocation is always only copied,
416-
// so having `UnsafeCell` in there is okay despite them being in immutable memory.
417-
let allow_immutable_unsafe_cell = cid.promoted.is_none() && !inner;
418-
CtfeValidationMode::Const { allow_immutable_unsafe_cell }
415+
// This is a normal `const` (not promoted).
416+
// The outermost allocation is always only copied, so having `UnsafeCell` in there
417+
// is okay despite them being in immutable memory.
418+
CtfeValidationMode::Const { allow_immutable_unsafe_cell: !inner }
419419
}
420420
};
421421
ecx.const_validate_operand(&mplace.into(), path, &mut ref_tracking, mode)?;

compiler/rustc_const_eval/src/transform/check_consts/check.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ type QualifResults<'mir, 'tcx, Q> =
3030
rustc_mir_dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'mir, 'mir, 'tcx, Q>>;
3131

3232
#[derive(Default)]
33-
pub struct Qualifs<'mir, 'tcx> {
33+
pub(crate) struct Qualifs<'mir, 'tcx> {
3434
has_mut_interior: Option<QualifResults<'mir, 'tcx, HasMutInterior>>,
3535
needs_drop: Option<QualifResults<'mir, 'tcx, NeedsDrop>>,
3636
needs_non_const_drop: Option<QualifResults<'mir, 'tcx, NeedsNonConstDrop>>,
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//@build-pass
2+
// Some code that looks like it might be relying on promotion, but actually this is using the
3+
// enclosing-scope rule, meaning the reference is "extended" to outlive its block and live as long
4+
// as the surrounding block (which in this case is the entire program). There are multiple
5+
// allocations being interned at once.
6+
7+
struct Gen<T>(T);
8+
impl<'a, T> Gen<&'a T> {
9+
// Can't be promoted because `T` might not be `'static`.
10+
const C: &'a [T] = &[];
11+
}
12+
13+
// Can't be promoted because of `Drop`.
14+
const V: &Vec<i32> = &Vec::new();
15+
16+
fn main() {}

tests/ui/consts/refs-to-cell-in-final.rs

+18
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,22 @@ static RAW_SYNC_S: SyncPtr<Cell<i32>> = SyncPtr { x: &Cell::new(42) };
1515
const RAW_SYNC_C: SyncPtr<Cell<i32>> = SyncPtr { x: &Cell::new(42) };
1616
//~^ ERROR: cannot refer to interior mutable data
1717

18+
// This one does not get promoted because of `Drop`, and then enters interesting codepaths because
19+
// as a value it has no interior mutability, but as a type it does. See
20+
// <https://github.com/rust-lang/rust/issues/121610>. Value-based reasoning for interior mutability
21+
// is questionable (https://github.com/rust-lang/unsafe-code-guidelines/issues/493) so for now we
22+
// reject this, though not with a great error message.
23+
pub enum JsValue {
24+
Undefined,
25+
Object(Cell<bool>),
26+
}
27+
impl Drop for JsValue {
28+
fn drop(&mut self) {}
29+
}
30+
const UNDEFINED: &JsValue = &JsValue::Undefined;
31+
//~^ERROR: mutable pointer in final value of constant
32+
33+
// In contrast, this one works since it is being promoted.
34+
const NONE: &'static Option<Cell<i32>> = &None;
35+
1836
fn main() {}

tests/ui/consts/refs-to-cell-in-final.stderr

+7-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ error[E0492]: constants cannot refer to interior mutable data
1212
LL | const RAW_SYNC_C: SyncPtr<Cell<i32>> = SyncPtr { x: &Cell::new(42) };
1313
| ^^^^^^^^^^^^^^ this borrow of an interior mutable value may end up in the final value
1414

15-
error: aborting due to 2 previous errors
15+
error: encountered mutable pointer in final value of constant
16+
--> $DIR/refs-to-cell-in-final.rs:30:1
17+
|
18+
LL | const UNDEFINED: &JsValue = &JsValue::Undefined;
19+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
20+
21+
error: aborting due to 3 previous errors
1622

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

0 commit comments

Comments
 (0)