Skip to content

Commit ac1ed22

Browse files
committed
add an interesting test; make const-check understand that empty arrays are not interior mutable
1 parent 3ad70a1 commit ac1ed22

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

Diff for: compiler/rustc_const_eval/src/transform/check_consts/check.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,21 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
373373
}
374374
}
375375
}
376+
377+
fn has_interior_mut(&self, ty: Ty<'tcx>) -> bool {
378+
match ty.kind() {
379+
// Empty arrays have no interior mutability no matter their element type.
380+
ty::Array(_elem, count)
381+
if count
382+
.try_eval_target_usize(self.tcx, self.param_env)
383+
.is_some_and(|v| v == 0) =>
384+
{
385+
false
386+
}
387+
// Fallback to checking `Freeze`.
388+
_ => !ty.is_freeze(self.tcx, self.param_env),
389+
}
390+
}
376391
}
377392

378393
impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
@@ -487,7 +502,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
487502
// We don't do value-based reasoning here, since the rules for interior mutability
488503
// are not finalized yet and they seem likely to not be full value-based in the end.
489504
let borrowed_place_has_mut_interior =
490-
!place.ty(self.body, self.tcx).ty.is_freeze(self.tcx, self.param_env);
505+
self.has_interior_mut(place.ty(self.body, self.tcx).ty);
491506

492507
// If the place is indirect, this is basically a reborrow. We have a reborrow
493508
// special case above, but for raw pointers and pointers/references to `static` and

Diff for: tests/ui/consts/enclosing-scope-rule.rs

+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() {}

0 commit comments

Comments
 (0)