const-checking: add some corner case tests, and fix some nits
This commit is contained in:
parent
d9a2886ef8
commit
279465b5e8
@ -412,10 +412,10 @@ pub fn const_validate_mplace<'mir, 'tcx>(
|
|||||||
_ if cid.promoted.is_some() => CtfeValidationMode::Promoted,
|
_ if cid.promoted.is_some() => CtfeValidationMode::Promoted,
|
||||||
Some(mutbl) => CtfeValidationMode::Static { mutbl }, // a `static`
|
Some(mutbl) => CtfeValidationMode::Static { mutbl }, // a `static`
|
||||||
None => {
|
None => {
|
||||||
// In normal `const` (not promoted), the outermost allocation is always only copied,
|
// This is a normal `const` (not promoted).
|
||||||
// so having `UnsafeCell` in there is okay despite them being in immutable memory.
|
// The outermost allocation is always only copied, so having `UnsafeCell` in there
|
||||||
let allow_immutable_unsafe_cell = cid.promoted.is_none() && !inner;
|
// is okay despite them being in immutable memory.
|
||||||
CtfeValidationMode::Const { allow_immutable_unsafe_cell }
|
CtfeValidationMode::Const { allow_immutable_unsafe_cell: !inner }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
ecx.const_validate_operand(&mplace.into(), path, &mut ref_tracking, mode)?;
|
ecx.const_validate_operand(&mplace.into(), path, &mut ref_tracking, mode)?;
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
rustc_mir_dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'mir, 'mir, 'tcx, Q>>;
|
rustc_mir_dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'mir, 'mir, 'tcx, Q>>;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Qualifs<'mir, 'tcx> {
|
pub(crate) struct Qualifs<'mir, 'tcx> {
|
||||||
has_mut_interior: Option<QualifResults<'mir, 'tcx, HasMutInterior>>,
|
has_mut_interior: Option<QualifResults<'mir, 'tcx, HasMutInterior>>,
|
||||||
needs_drop: Option<QualifResults<'mir, 'tcx, NeedsDrop>>,
|
needs_drop: Option<QualifResults<'mir, 'tcx, NeedsDrop>>,
|
||||||
needs_non_const_drop: Option<QualifResults<'mir, 'tcx, NeedsNonConstDrop>>,
|
needs_non_const_drop: Option<QualifResults<'mir, 'tcx, NeedsNonConstDrop>>,
|
||||||
|
16
tests/ui/consts/enclosing-scope-rule.rs
Normal file
16
tests/ui/consts/enclosing-scope-rule.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
//@build-pass
|
||||||
|
// Some code that looks like it might be relying on promotion, but actually this is using the
|
||||||
|
// enclosing-scope rule, meaning the reference is "extended" to outlive its block and live as long
|
||||||
|
// as the surrounding block (which in this case is the entire program). There are multiple
|
||||||
|
// allocations being interned at once.
|
||||||
|
|
||||||
|
struct Gen<T>(T);
|
||||||
|
impl<'a, T> Gen<&'a T> {
|
||||||
|
// Can't be promoted because `T` might not be `'static`.
|
||||||
|
const C: &'a [T] = &[];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can't be promoted because of `Drop`.
|
||||||
|
const V: &Vec<i32> = &Vec::new();
|
||||||
|
|
||||||
|
fn main() {}
|
@ -15,4 +15,27 @@ unsafe impl<T> Sync for SyncPtr<T> {}
|
|||||||
const RAW_SYNC_C: SyncPtr<Cell<i32>> = SyncPtr { x: &Cell::new(42) };
|
const RAW_SYNC_C: SyncPtr<Cell<i32>> = SyncPtr { x: &Cell::new(42) };
|
||||||
//~^ ERROR: cannot refer to interior mutable data
|
//~^ ERROR: cannot refer to interior mutable data
|
||||||
|
|
||||||
|
// This one does not get promoted because of `Drop`, and then enters interesting codepaths because
|
||||||
|
// as a value it has no interior mutability, but as a type it does. See
|
||||||
|
// <https://github.com/rust-lang/rust/issues/121610>. Value-based reasoning for interior mutability
|
||||||
|
// is questionable (https://github.com/rust-lang/unsafe-code-guidelines/issues/493) so for now we
|
||||||
|
// reject this, though not with a great error message.
|
||||||
|
pub enum JsValue {
|
||||||
|
Undefined,
|
||||||
|
Object(Cell<bool>),
|
||||||
|
}
|
||||||
|
impl Drop for JsValue {
|
||||||
|
fn drop(&mut self) {}
|
||||||
|
}
|
||||||
|
const UNDEFINED: &JsValue = &JsValue::Undefined;
|
||||||
|
//~^ERROR: mutable pointer in final value of constant
|
||||||
|
|
||||||
|
// In contrast, this one works since it is being promoted.
|
||||||
|
const NONE: &'static Option<Cell<i32>> = &None;
|
||||||
|
// Making it clear that this is promotion, not "outer scope".
|
||||||
|
const NONE_EXPLICIT_PROMOTED: &'static Option<Cell<i32>> = {
|
||||||
|
let x = &None;
|
||||||
|
x
|
||||||
|
};
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -12,6 +12,12 @@ error[E0492]: constants cannot refer to interior mutable data
|
|||||||
LL | const RAW_SYNC_C: SyncPtr<Cell<i32>> = SyncPtr { x: &Cell::new(42) };
|
LL | const RAW_SYNC_C: SyncPtr<Cell<i32>> = SyncPtr { x: &Cell::new(42) };
|
||||||
| ^^^^^^^^^^^^^^ this borrow of an interior mutable value may end up in the final value
|
| ^^^^^^^^^^^^^^ this borrow of an interior mutable value may end up in the final value
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: encountered mutable pointer in final value of constant
|
||||||
|
--> $DIR/refs-to-cell-in-final.rs:30:1
|
||||||
|
|
|
||||||
|
LL | const UNDEFINED: &JsValue = &JsValue::Undefined;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0492`.
|
For more information about this error, try `rustc --explain E0492`.
|
||||||
|
Loading…
Reference in New Issue
Block a user