|
1 | 1 | use super::{CompileTimeEvalContext, CompileTimeInterpreter, ConstEvalErr, MemoryExtra};
|
2 | 2 | use crate::interpret::eval_nullary_intrinsic;
|
3 | 3 | use crate::interpret::{
|
4 |
| - intern_const_alloc_recursive, Allocation, ConstAlloc, ConstValue, GlobalId, Immediate, |
5 |
| - InternKind, InterpCx, InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, Scalar, |
| 4 | + intern_const_alloc_recursive, Allocation, ConstAlloc, ConstValue, CtfeValidationMode, GlobalId, |
| 5 | + Immediate, InternKind, InterpCx, InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, Scalar, |
6 | 6 | ScalarMaybeUninit, StackPopCleanup,
|
7 | 7 | };
|
8 | 8 |
|
@@ -59,23 +59,15 @@ fn eval_body_using_ecx<'mir, 'tcx>(
|
59 | 59 | ecx.run()?;
|
60 | 60 |
|
61 | 61 | // Intern the result
|
62 |
| - // FIXME: since the DefId of a promoted is the DefId of its owner, this |
63 |
| - // means that promoteds in statics are actually interned like statics! |
64 |
| - // However, this is also currently crucial because we promote mutable |
65 |
| - // non-empty slices in statics to extend their lifetime, and this |
66 |
| - // ensures that they are put into a mutable allocation. |
67 |
| - // For other kinds of promoteds in statics (like array initializers), this is rather silly. |
68 |
| - let intern_kind = match tcx.static_mutability(cid.instance.def_id()) { |
69 |
| - Some(m) => InternKind::Static(m), |
70 |
| - None if cid.promoted.is_some() => InternKind::Promoted, |
71 |
| - _ => InternKind::Constant, |
| 62 | + let intern_kind = if cid.promoted.is_some() { |
| 63 | + InternKind::Promoted |
| 64 | + } else { |
| 65 | + match tcx.static_mutability(cid.instance.def_id()) { |
| 66 | + Some(m) => InternKind::Static(m), |
| 67 | + None => InternKind::Constant, |
| 68 | + } |
72 | 69 | };
|
73 |
| - intern_const_alloc_recursive( |
74 |
| - ecx, |
75 |
| - intern_kind, |
76 |
| - ret, |
77 |
| - body.ignore_interior_mut_in_const_validation, |
78 |
| - ); |
| 70 | + intern_const_alloc_recursive(ecx, intern_kind, ret); |
79 | 71 |
|
80 | 72 | debug!("eval_body_using_ecx done: {:?}", *ret);
|
81 | 73 | Ok(ret)
|
@@ -376,16 +368,23 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
|
376 | 368 | // Since evaluation had no errors, valiate the resulting constant:
|
377 | 369 | let validation = try {
|
378 | 370 | // FIXME do not validate promoteds until a decision on
|
379 |
| - // https://github.com/rust-lang/rust/issues/67465 is made |
| 371 | + // https://github.com/rust-lang/rust/issues/67465 and |
| 372 | + // https://github.com/rust-lang/rust/issues/67534 is made. |
| 373 | + // Promoteds can contain unexpected `UnsafeCell` and reference `static`s, but their |
| 374 | + // otherwise restricted form ensures that this is still sound. We just lose the |
| 375 | + // extra safety net of some of the dynamic checks. They can also contain invalid |
| 376 | + // values, but since we do not usually check intermediate results of a computation |
| 377 | + // for validity, it might be surprising to do that here. |
380 | 378 | if cid.promoted.is_none() {
|
381 | 379 | let mut ref_tracking = RefTracking::new(mplace);
|
| 380 | + let mut inner = false; |
382 | 381 | while let Some((mplace, path)) = ref_tracking.todo.pop() {
|
383 |
| - ecx.const_validate_operand( |
384 |
| - mplace.into(), |
385 |
| - path, |
386 |
| - &mut ref_tracking, |
387 |
| - /*may_ref_to_static*/ ecx.memory.extra.can_access_statics, |
388 |
| - )?; |
| 382 | + let mode = match tcx.static_mutability(cid.instance.def_id()) { |
| 383 | + Some(_) => CtfeValidationMode::Regular, // a `static` |
| 384 | + None => CtfeValidationMode::Const { inner }, |
| 385 | + }; |
| 386 | + ecx.const_validate_operand(mplace.into(), path, &mut ref_tracking, mode)?; |
| 387 | + inner = true; |
389 | 388 | }
|
390 | 389 | }
|
391 | 390 | };
|
|
0 commit comments