Skip to content

Commit

Permalink
add an interesting test; make const-check understand that empty array…
Browse files Browse the repository at this point in the history
…s are not interior mutable
  • Loading branch information
RalfJung committed Mar 1, 2024
1 parent 3ad70a1 commit ac1ed22
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 1 deletion.
17 changes: 16 additions & 1 deletion compiler/rustc_const_eval/src/transform/check_consts/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,21 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
}
}
}

fn has_interior_mut(&self, ty: Ty<'tcx>) -> bool {
match ty.kind() {
// Empty arrays have no interior mutability no matter their element type.
ty::Array(_elem, count)
if count
.try_eval_target_usize(self.tcx, self.param_env)
.is_some_and(|v| v == 0) =>
{
false
}
// Fallback to checking `Freeze`.
_ => !ty.is_freeze(self.tcx, self.param_env),
}
}
}

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

// If the place is indirect, this is basically a reborrow. We have a reborrow
// special case above, but for raw pointers and pointers/references to `static` and
Expand Down
16 changes: 16 additions & 0 deletions tests/ui/consts/enclosing-scope-rule.rs
Original file line number Diff line number Diff line change
@@ -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() {}

0 comments on commit ac1ed22

Please sign in to comment.