Skip to content

Commit 959ac4f

Browse files
Rollup merge of rust-lang#108364 - Nilstrieb:validity-checks-refactor, r=compiler-errors
Unify validity checks into a single query Previously, there were two queries to check whether a type allows the 0x01 or zeroed bitpattern. I am planning on adding a further initness to check in rust-lang#100423, truly uninit for MaybeUninit, which would make this three queries. This seems overkill for such a small feature, so this PR unifies them into one. I am not entirely happy with the naming and key type and open for improvements. r? oli-obk
2 parents 7559549 + 025d2a1 commit 959ac4f

File tree

11 files changed

+89
-67
lines changed

11 files changed

+89
-67
lines changed

compiler/rustc_abi/src/lib.rs

-8
Original file line numberDiff line numberDiff line change
@@ -1505,14 +1505,6 @@ pub struct PointeeInfo {
15051505
pub safe: Option<PointerKind>,
15061506
}
15071507

1508-
/// Used in `might_permit_raw_init` to indicate the kind of initialisation
1509-
/// that is checked to be valid
1510-
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1511-
pub enum InitKind {
1512-
Zero,
1513-
UninitMitigated0x01Fill,
1514-
}
1515-
15161508
impl LayoutS {
15171509
/// Returns `true` if the layout corresponds to an unsized type.
15181510
pub fn is_unsized(&self) -> bool {

compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ mod simd;
2121
pub(crate) use cpuid::codegen_cpuid_call;
2222
pub(crate) use llvm::codegen_llvm_intrinsic_call;
2323

24-
use rustc_middle::ty::layout::HasParamEnv;
24+
use rustc_middle::ty;
25+
use rustc_middle::ty::layout::{HasParamEnv, InitKind};
2526
use rustc_middle::ty::print::with_no_trimmed_paths;
2627
use rustc_middle::ty::subst::SubstsRef;
2728
use rustc_span::symbol::{kw, sym, Symbol};
@@ -642,7 +643,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
642643
if intrinsic == sym::assert_zero_valid
643644
&& !fx
644645
.tcx
645-
.permits_zero_init(fx.param_env().and(ty))
646+
.check_validity_of_init((InitKind::Zero, fx.param_env().and(ty)))
646647
.expect("expected to have layout during codegen")
647648
{
648649
with_no_trimmed_paths!({
@@ -661,7 +662,10 @@ fn codegen_regular_intrinsic_call<'tcx>(
661662
if intrinsic == sym::assert_mem_uninitialized_valid
662663
&& !fx
663664
.tcx
664-
.permits_uninit_init(fx.param_env().and(ty))
665+
.check_validity_of_init((
666+
InitKind::UninitMitigated0x01Fill,
667+
fx.param_env().and(ty),
668+
))
665669
.expect("expected to have layout during codegen")
666670
{
667671
with_no_trimmed_paths!({

compiler/rustc_codegen_ssa/src/mir/block.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
1414
use rustc_hir::lang_items::LangItem;
1515
use rustc_index::vec::Idx;
1616
use rustc_middle::mir::{self, AssertKind, SwitchTargets};
17-
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
17+
use rustc_middle::ty::layout::{HasTyCtxt, InitKind, LayoutOf};
1818
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
1919
use rustc_middle::ty::{self, Instance, Ty, TypeVisitableExt};
2020
use rustc_session::config::OptLevel;
@@ -676,11 +676,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
676676
Inhabited => layout.abi.is_uninhabited(),
677677
ZeroValid => !bx
678678
.tcx()
679-
.permits_zero_init(bx.param_env().and(ty))
679+
.check_validity_of_init((InitKind::Zero, bx.param_env().and(ty)))
680680
.expect("expected to have layout during codegen"),
681681
MemUninitializedValid => !bx
682682
.tcx()
683-
.permits_uninit_init(bx.param_env().and(ty))
683+
.check_validity_of_init((
684+
InitKind::UninitMitigated0x01Fill,
685+
bx.param_env().and(ty),
686+
))
684687
.expect("expected to have layout during codegen"),
685688
};
686689
Some(if do_panic {

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_middle::mir::{
1111
BinOp, NonDivergingIntrinsic,
1212
};
1313
use rustc_middle::ty;
14-
use rustc_middle::ty::layout::LayoutOf as _;
14+
use rustc_middle::ty::layout::{InitKind, LayoutOf as _};
1515
use rustc_middle::ty::subst::SubstsRef;
1616
use rustc_middle::ty::{Ty, TyCtxt};
1717
use rustc_span::symbol::{sym, Symbol};
@@ -437,7 +437,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
437437
if intrinsic_name == sym::assert_zero_valid {
438438
let should_panic = !self
439439
.tcx
440-
.permits_zero_init(self.param_env.and(ty))
440+
.check_validity_of_init((InitKind::Zero, self.param_env.and(ty)))
441441
.map_err(|_| err_inval!(TooGeneric))?;
442442

443443
if should_panic {
@@ -454,7 +454,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
454454
if intrinsic_name == sym::assert_mem_uninitialized_valid {
455455
let should_panic = !self
456456
.tcx
457-
.permits_uninit_init(self.param_env.and(ty))
457+
.check_validity_of_init((
458+
InitKind::UninitMitigated0x01Fill,
459+
self.param_env.and(ty),
460+
))
458461
.map_err(|_| err_inval!(TooGeneric))?;
459462

460463
if should_panic {

compiler/rustc_const_eval/src/lib.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
3838
use rustc_macros::fluent_messages;
3939
use rustc_middle::ty;
4040
use rustc_middle::ty::query::Providers;
41-
use rustc_target::abi::InitKind;
4241

4342
fluent_messages! { "../locales/en-US.ftl" }
4443

@@ -62,9 +61,7 @@ pub fn provide(providers: &mut Providers) {
6261
let (param_env, value) = param_env_and_value.into_parts();
6362
const_eval::deref_mir_constant(tcx, param_env, value)
6463
};
65-
providers.permits_uninit_init = |tcx, param_env_and_ty| {
66-
util::might_permit_raw_init(tcx, param_env_and_ty, InitKind::UninitMitigated0x01Fill)
64+
providers.check_validity_of_init = |tcx, (init_kind, param_env_and_ty)| {
65+
util::might_permit_raw_init(tcx, init_kind, param_env_and_ty)
6766
};
68-
providers.permits_zero_init =
69-
|tcx, param_env_and_ty| util::might_permit_raw_init(tcx, param_env_and_ty, InitKind::Zero);
7067
}

compiler/rustc_const_eval/src/util/might_permit_raw_init.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
use rustc_middle::ty::layout::{LayoutCx, LayoutError, LayoutOf, TyAndLayout};
1+
use rustc_middle::ty::layout::{InitKind, LayoutCx, LayoutError, LayoutOf, TyAndLayout};
22
use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Ty, TyCtxt};
33
use rustc_session::Limit;
4-
use rustc_target::abi::{Abi, FieldsShape, InitKind, Scalar, Variants};
4+
use rustc_target::abi::{Abi, FieldsShape, Scalar, Variants};
55

66
use crate::const_eval::{CheckAlignment, CompileTimeInterpreter};
77
use crate::interpret::{InterpCx, MemoryKind, OpTy};
@@ -20,8 +20,8 @@ use crate::interpret::{InterpCx, MemoryKind, OpTy};
2020
/// to the full uninit check).
2121
pub fn might_permit_raw_init<'tcx>(
2222
tcx: TyCtxt<'tcx>,
23-
param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>,
2423
kind: InitKind,
24+
param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>,
2525
) -> Result<bool, LayoutError<'tcx>> {
2626
if tcx.sess.opts.unstable_opts.strict_init_checks {
2727
might_permit_raw_init_strict(tcx.layout_of(param_env_and_ty)?, tcx, kind)

compiler/rustc_middle/src/query/keys.rs

+23-1
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ use crate::infer::canonical::Canonical;
44
use crate::mir;
55
use crate::traits;
66
use crate::ty::fast_reject::SimplifiedType;
7+
use crate::ty::layout::{InitKind, TyAndLayout};
78
use crate::ty::subst::{GenericArg, SubstsRef};
8-
use crate::ty::{self, layout::TyAndLayout, Ty, TyCtxt};
9+
use crate::ty::{self, Ty, TyCtxt};
910
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
1011
use rustc_hir::hir_id::{HirId, OwnerId};
1112
use rustc_query_system::query::{DefaultCacheSelector, SingleCacheSelector, VecCacheSelector};
@@ -696,3 +697,24 @@ impl Key for HirId {
696697
None
697698
}
698699
}
700+
701+
impl<'tcx> Key for (InitKind, ty::ParamEnvAnd<'tcx, Ty<'tcx>>) {
702+
type CacheSelector = DefaultCacheSelector<Self>;
703+
704+
// Just forward to `Ty<'tcx>`
705+
#[inline(always)]
706+
fn query_crate_is_local(&self) -> bool {
707+
true
708+
}
709+
710+
fn default_span(&self, _: TyCtxt<'_>) -> Span {
711+
DUMMY_SP
712+
}
713+
714+
fn ty_adt_id(&self) -> Option<DefId> {
715+
match self.1.value.kind() {
716+
ty::Adt(adt, _) => Some(adt.did()),
717+
_ => None,
718+
}
719+
}
720+
}

compiler/rustc_middle/src/query/mod.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -2173,12 +2173,8 @@ rustc_queries! {
21732173
separate_provide_extern
21742174
}
21752175

2176-
query permits_uninit_init(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> Result<bool, ty::layout::LayoutError<'tcx>> {
2177-
desc { "checking to see if `{}` permits being left uninit", key.value }
2178-
}
2179-
2180-
query permits_zero_init(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> Result<bool, ty::layout::LayoutError<'tcx>> {
2181-
desc { "checking to see if `{}` permits being left zeroed", key.value }
2176+
query check_validity_of_init(key: (InitKind, ty::ParamEnvAnd<'tcx, Ty<'tcx>>)) -> Result<bool, ty::layout::LayoutError<'tcx>> {
2177+
desc { "checking to see if `{}` permits being left {}", key.1.value, key.0 }
21822178
}
21832179

21842180
query compare_impl_const(

compiler/rustc_middle/src/ty/layout.rs

+17
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,23 @@ pub const FAT_PTR_EXTRA: usize = 1;
169169
/// * Cranelift stores the base-2 log of the lane count in a 4 bit integer.
170170
pub const MAX_SIMD_LANES: u64 = 1 << 0xF;
171171

172+
/// Used in `might_permit_raw_init` to indicate the kind of initialisation
173+
/// that is checked to be valid
174+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
175+
pub enum InitKind {
176+
Zero,
177+
UninitMitigated0x01Fill,
178+
}
179+
180+
impl fmt::Display for InitKind {
181+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
182+
match self {
183+
Self::Zero => f.write_str("zeroed"),
184+
Self::UninitMitigated0x01Fill => f.write_str("filled with 0x01"),
185+
}
186+
}
187+
}
188+
172189
#[derive(Copy, Clone, Debug, HashStable, TyEncodable, TyDecodable)]
173190
pub enum LayoutError<'tcx> {
174191
Unknown(Ty<'tcx>),

compiler/rustc_middle/src/ty/query.rs

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use crate::traits::specialization_graph;
3232
use crate::traits::{self, ImplSource};
3333
use crate::ty::context::TyCtxtFeed;
3434
use crate::ty::fast_reject::SimplifiedType;
35+
use crate::ty::layout::InitKind;
3536
use crate::ty::subst::{GenericArg, SubstsRef};
3637
use crate::ty::util::AlwaysRequiresDrop;
3738
use crate::ty::GeneratorDiagnosticData;

compiler/rustc_mir_transform/src/instcombine.rs

+22-35
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use rustc_middle::mir::{
66
BinOp, Body, Constant, ConstantKind, LocalDecls, Operand, Place, ProjectionElem, Rvalue,
77
SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UnOp,
88
};
9-
use rustc_middle::ty::layout::LayoutError;
10-
use rustc_middle::ty::{self, ParamEnv, ParamEnvAnd, SubstsRef, Ty, TyCtxt};
9+
use rustc_middle::ty::layout::InitKind;
10+
use rustc_middle::ty::{self, ParamEnv, SubstsRef, Ty, TyCtxt};
1111
use rustc_span::symbol::{sym, Symbol};
1212

1313
pub struct InstCombine;
@@ -234,16 +234,15 @@ impl<'tcx> InstCombineContext<'tcx, '_> {
234234
}
235235
let ty = substs.type_at(0);
236236

237-
// Check this is a foldable intrinsic before we query the layout of our generic parameter
238-
let Some(assert_panics) = intrinsic_assert_panics(intrinsic_name) else { return; };
239-
match assert_panics(self.tcx, self.param_env.and(ty)) {
240-
// We don't know the layout, don't touch the assertion
241-
Err(_) => {}
242-
Ok(true) => {
237+
let known_is_valid = intrinsic_assert_panics(self.tcx, self.param_env, ty, intrinsic_name);
238+
match known_is_valid {
239+
// We don't know the layout or it's not validity assertion at all, don't touch it
240+
None => {}
241+
Some(true) => {
243242
// If we know the assert panics, indicate to later opts that the call diverges
244243
*target = None;
245244
}
246-
Ok(false) => {
245+
Some(false) => {
247246
// If we know the assert does not panic, turn the call into a Goto
248247
terminator.kind = TerminatorKind::Goto { target: *target_block };
249248
}
@@ -252,33 +251,21 @@ impl<'tcx> InstCombineContext<'tcx, '_> {
252251
}
253252

254253
fn intrinsic_assert_panics<'tcx>(
254+
tcx: TyCtxt<'tcx>,
255+
param_env: ty::ParamEnv<'tcx>,
256+
ty: Ty<'tcx>,
255257
intrinsic_name: Symbol,
256-
) -> Option<fn(TyCtxt<'tcx>, ParamEnvAnd<'tcx, Ty<'tcx>>) -> Result<bool, LayoutError<'tcx>>> {
257-
fn inhabited_predicate<'tcx>(
258-
tcx: TyCtxt<'tcx>,
259-
param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>,
260-
) -> Result<bool, LayoutError<'tcx>> {
261-
Ok(tcx.layout_of(param_env_and_ty)?.abi.is_uninhabited())
262-
}
263-
fn zero_valid_predicate<'tcx>(
264-
tcx: TyCtxt<'tcx>,
265-
param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>,
266-
) -> Result<bool, LayoutError<'tcx>> {
267-
Ok(!tcx.permits_zero_init(param_env_and_ty)?)
268-
}
269-
fn mem_uninitialized_valid_predicate<'tcx>(
270-
tcx: TyCtxt<'tcx>,
271-
param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>,
272-
) -> Result<bool, LayoutError<'tcx>> {
273-
Ok(!tcx.permits_uninit_init(param_env_and_ty)?)
274-
}
275-
276-
match intrinsic_name {
277-
sym::assert_inhabited => Some(inhabited_predicate),
278-
sym::assert_zero_valid => Some(zero_valid_predicate),
279-
sym::assert_mem_uninitialized_valid => Some(mem_uninitialized_valid_predicate),
280-
_ => None,
281-
}
258+
) -> Option<bool> {
259+
Some(match intrinsic_name {
260+
sym::assert_inhabited => tcx.layout_of(param_env.and(ty)).ok()?.abi.is_uninhabited(),
261+
sym::assert_zero_valid => {
262+
!tcx.check_validity_of_init((InitKind::Zero, param_env.and(ty))).ok()?
263+
}
264+
sym::assert_mem_uninitialized_valid => !tcx
265+
.check_validity_of_init((InitKind::UninitMitigated0x01Fill, param_env.and(ty)))
266+
.ok()?,
267+
_ => return None,
268+
})
282269
}
283270

284271
fn resolve_rust_intrinsic<'tcx>(

0 commit comments

Comments
 (0)