1
Fork 0

Rollup merge of #128720 - y21:issue119620, r=compiler-errors

Pass the right `ParamEnv` to `might_permit_raw_init_strict`

Fixes #119620

`might_permit_raw_init_strict` currently passes an empty `ParamEnv` to the `InterpCx`, instead of the actual `ParamEnv` that was passed in to `check_validity_requirement` at callsite.

This leads to ICEs such as the linked issue where for `UnsafeCell<*mut T>` we initially get the layout with the right `ParamEnv` (which suceeds because it can prove that `T: Sized` and therefore `UnsafeCell<*mut T>` has a known layout) but then do the rest with an empty `ParamEnv` where `T: Sized` is not known to hold so getting the layout for `*mut T` later fails.

This runs into an assertion in other layout code where it's making the (valid) assumption that, when we already have a layout for a struct (`UnsafeCell<*mut T>`), getting the layout of one of its fields (`*mut T`) should also succeed, which wasn't the case here due to using the wrong `ParamEnv`.

So, this PR changes it to just use the same `ParamEnv` all the way throughout.
This commit is contained in:
Matthias Krüger 2024-08-06 20:23:41 +02:00 committed by GitHub
commit 8912318a4c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 36 additions and 19 deletions

View file

@ -1,6 +1,6 @@
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::ty::layout::{LayoutCx, LayoutError, LayoutOf, TyAndLayout, ValidityRequirement}; use rustc_middle::ty::layout::{LayoutCx, LayoutError, LayoutOf, TyAndLayout, ValidityRequirement};
use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Ty, TyCtxt}; use rustc_middle::ty::{ParamEnvAnd, Ty, TyCtxt};
use rustc_target::abi::{Abi, FieldsShape, Scalar, Variants}; use rustc_target::abi::{Abi, FieldsShape, Scalar, Variants};
use crate::const_eval::{CanAccessMutGlobal, CheckAlignment, CompileTimeMachine}; use crate::const_eval::{CanAccessMutGlobal, CheckAlignment, CompileTimeMachine};
@ -30,10 +30,10 @@ pub fn check_validity_requirement<'tcx>(
return Ok(!layout.abi.is_uninhabited()); return Ok(!layout.abi.is_uninhabited());
} }
let layout_cx = LayoutCx { tcx, param_env: param_env_and_ty.param_env };
if kind == ValidityRequirement::Uninit || tcx.sess.opts.unstable_opts.strict_init_checks { if kind == ValidityRequirement::Uninit || tcx.sess.opts.unstable_opts.strict_init_checks {
might_permit_raw_init_strict(layout, tcx, kind) might_permit_raw_init_strict(layout, &layout_cx, kind)
} else { } else {
let layout_cx = LayoutCx { tcx, param_env: param_env_and_ty.param_env };
might_permit_raw_init_lax(layout, &layout_cx, kind) might_permit_raw_init_lax(layout, &layout_cx, kind)
} }
} }
@ -42,12 +42,12 @@ pub fn check_validity_requirement<'tcx>(
/// details. /// details.
fn might_permit_raw_init_strict<'tcx>( fn might_permit_raw_init_strict<'tcx>(
ty: TyAndLayout<'tcx>, ty: TyAndLayout<'tcx>,
tcx: TyCtxt<'tcx>, cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
kind: ValidityRequirement, kind: ValidityRequirement,
) -> Result<bool, &'tcx LayoutError<'tcx>> { ) -> Result<bool, &'tcx LayoutError<'tcx>> {
let machine = CompileTimeMachine::new(CanAccessMutGlobal::No, CheckAlignment::Error); let machine = CompileTimeMachine::new(CanAccessMutGlobal::No, CheckAlignment::Error);
let mut cx = InterpCx::new(tcx, rustc_span::DUMMY_SP, ParamEnv::reveal_all(), machine); let mut cx = InterpCx::new(cx.tcx, rustc_span::DUMMY_SP, cx.param_env, machine);
let allocated = cx let allocated = cx
.allocate(ty, MemoryKind::Machine(crate::const_eval::MemoryKind::Heap)) .allocate(ty, MemoryKind::Machine(crate::const_eval::MemoryKind::Heap))

View file

@ -1,6 +1,7 @@
#![warn(clippy::uninit_vec)] #![warn(clippy::uninit_vec)]
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use std::cell::UnsafeCell;
#[derive(Default)] #[derive(Default)]
struct MyVec { struct MyVec {
@ -12,6 +13,12 @@ union MyOwnMaybeUninit {
uninit: (), uninit: (),
} }
// https://github.com/rust-lang/rust/issues/119620
unsafe fn requires_paramenv<S>() {
let mut vec = Vec::<UnsafeCell<*mut S>>::with_capacity(1);
vec.set_len(1);
}
fn main() { fn main() {
// with_capacity() -> set_len() should be detected // with_capacity() -> set_len() should be detected
let mut vec: Vec<u8> = Vec::with_capacity(1000); let mut vec: Vec<u8> = Vec::with_capacity(1000);

View file

@ -1,5 +1,17 @@
error: calling `set_len()` immediately after reserving a buffer creates uninitialized values error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
--> tests/ui/uninit_vec.rs:17:5 --> tests/ui/uninit_vec.rs:18:5
|
LL | let mut vec = Vec::<UnsafeCell<*mut S>>::with_capacity(1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | vec.set_len(1);
| ^^^^^^^^^^^^^^
|
= help: initialize the buffer or wrap the content in `MaybeUninit`
= note: `-D clippy::uninit-vec` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::uninit_vec)]`
error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
--> tests/ui/uninit_vec.rs:24:5
| |
LL | let mut vec: Vec<u8> = Vec::with_capacity(1000); LL | let mut vec: Vec<u8> = Vec::with_capacity(1000);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -8,11 +20,9 @@ LL | vec.set_len(200);
| ^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
| |
= help: initialize the buffer or wrap the content in `MaybeUninit` = help: initialize the buffer or wrap the content in `MaybeUninit`
= note: `-D clippy::uninit-vec` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::uninit_vec)]`
error: calling `set_len()` immediately after reserving a buffer creates uninitialized values error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
--> tests/ui/uninit_vec.rs:24:5 --> tests/ui/uninit_vec.rs:31:5
| |
LL | vec.reserve(1000); LL | vec.reserve(1000);
| ^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^
@ -23,7 +33,7 @@ LL | vec.set_len(200);
= help: initialize the buffer or wrap the content in `MaybeUninit` = help: initialize the buffer or wrap the content in `MaybeUninit`
error: calling `set_len()` on empty `Vec` creates out-of-bound values error: calling `set_len()` on empty `Vec` creates out-of-bound values
--> tests/ui/uninit_vec.rs:31:5 --> tests/ui/uninit_vec.rs:38:5
| |
LL | let mut vec: Vec<u8> = Vec::new(); LL | let mut vec: Vec<u8> = Vec::new();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -32,7 +42,7 @@ LL | vec.set_len(200);
| ^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
error: calling `set_len()` on empty `Vec` creates out-of-bound values error: calling `set_len()` on empty `Vec` creates out-of-bound values
--> tests/ui/uninit_vec.rs:38:5 --> tests/ui/uninit_vec.rs:45:5
| |
LL | let mut vec: Vec<u8> = Default::default(); LL | let mut vec: Vec<u8> = Default::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -41,7 +51,7 @@ LL | vec.set_len(200);
| ^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
error: calling `set_len()` on empty `Vec` creates out-of-bound values error: calling `set_len()` on empty `Vec` creates out-of-bound values
--> tests/ui/uninit_vec.rs:44:5 --> tests/ui/uninit_vec.rs:51:5
| |
LL | let mut vec: Vec<u8> = Vec::default(); LL | let mut vec: Vec<u8> = Vec::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -50,7 +60,7 @@ LL | vec.set_len(200);
| ^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
error: calling `set_len()` immediately after reserving a buffer creates uninitialized values error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
--> tests/ui/uninit_vec.rs:61:5 --> tests/ui/uninit_vec.rs:68:5
| |
LL | let mut vec: Vec<u8> = Vec::with_capacity(1000); LL | let mut vec: Vec<u8> = Vec::with_capacity(1000);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -61,7 +71,7 @@ LL | vec.set_len(200);
= help: initialize the buffer or wrap the content in `MaybeUninit` = help: initialize the buffer or wrap the content in `MaybeUninit`
error: calling `set_len()` immediately after reserving a buffer creates uninitialized values error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
--> tests/ui/uninit_vec.rs:71:5 --> tests/ui/uninit_vec.rs:78:5
| |
LL | my_vec.vec.reserve(1000); LL | my_vec.vec.reserve(1000);
| ^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^
@ -72,7 +82,7 @@ LL | my_vec.vec.set_len(200);
= help: initialize the buffer or wrap the content in `MaybeUninit` = help: initialize the buffer or wrap the content in `MaybeUninit`
error: calling `set_len()` immediately after reserving a buffer creates uninitialized values error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
--> tests/ui/uninit_vec.rs:77:5 --> tests/ui/uninit_vec.rs:84:5
| |
LL | my_vec.vec = Vec::with_capacity(1000); LL | my_vec.vec = Vec::with_capacity(1000);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -83,7 +93,7 @@ LL | my_vec.vec.set_len(200);
= help: initialize the buffer or wrap the content in `MaybeUninit` = help: initialize the buffer or wrap the content in `MaybeUninit`
error: calling `set_len()` immediately after reserving a buffer creates uninitialized values error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
--> tests/ui/uninit_vec.rs:52:9 --> tests/ui/uninit_vec.rs:59:9
| |
LL | let mut vec: Vec<u8> = Vec::with_capacity(1000); LL | let mut vec: Vec<u8> = Vec::with_capacity(1000);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -94,7 +104,7 @@ LL | vec.set_len(200);
= help: initialize the buffer or wrap the content in `MaybeUninit` = help: initialize the buffer or wrap the content in `MaybeUninit`
error: calling `set_len()` immediately after reserving a buffer creates uninitialized values error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
--> tests/ui/uninit_vec.rs:56:9 --> tests/ui/uninit_vec.rs:63:9
| |
LL | vec.reserve(1000); LL | vec.reserve(1000);
| ^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^
@ -105,7 +115,7 @@ LL | vec.set_len(200);
= help: initialize the buffer or wrap the content in `MaybeUninit` = help: initialize the buffer or wrap the content in `MaybeUninit`
error: calling `set_len()` immediately after reserving a buffer creates uninitialized values error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
--> tests/ui/uninit_vec.rs:132:9 --> tests/ui/uninit_vec.rs:139:9
| |
LL | let mut vec: Vec<T> = Vec::with_capacity(1000); LL | let mut vec: Vec<T> = Vec::with_capacity(1000);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -115,5 +125,5 @@ LL | vec.set_len(10);
| |
= help: initialize the buffer or wrap the content in `MaybeUninit` = help: initialize the buffer or wrap the content in `MaybeUninit`
error: aborting due to 11 previous errors error: aborting due to 12 previous errors