Skip to content

Commit 3e7a6e4

Browse files
committed
also ensure MIR assignment validity during codegen
1 parent a4f714b commit 3e7a6e4

14 files changed

Lines changed: 79 additions & 45 deletions

File tree

Cargo.lock

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3774,6 +3774,7 @@ dependencies = [
37743774
"rustc_symbol_mangling",
37753775
"rustc_target",
37763776
"rustc_trait_selection",
3777+
"rustc_ty_utils",
37773778
"serde_json",
37783779
"smallvec",
37793780
"tempfile",
@@ -3803,6 +3804,7 @@ dependencies = [
38033804
"rustc_span",
38043805
"rustc_target",
38053806
"rustc_trait_selection",
3807+
"rustc_ty_utils",
38063808
"tracing",
38073809
]
38083810

@@ -4407,6 +4409,7 @@ dependencies = [
44074409
"rustc_span",
44084410
"rustc_target",
44094411
"rustc_trait_selection",
4412+
"rustc_ty_utils",
44104413
"smallvec",
44114414
"tracing",
44124415
]

compiler/rustc_codegen_ssa/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ rustc_span = { path = "../rustc_span" }
3333
rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
3434
rustc_target = { path = "../rustc_target" }
3535
rustc_trait_selection = { path = "../rustc_trait_selection" }
36+
rustc_ty_utils = { path = "../rustc_ty_utils" }
3637
serde_json = "1.0.59"
3738
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
3839
tempfile = "3.2"

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout};
55
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
66
use rustc_middle::{bug, mir, span_bug};
77
use rustc_session::config::OptLevel;
8+
use rustc_ty_utils::compare_types;
89
use tracing::{debug, instrument};
910

1011
use super::FunctionCx;
@@ -22,6 +23,27 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
2223
dest: PlaceRef<'tcx, Bx::Value>,
2324
rvalue: &mir::Rvalue<'tcx>,
2425
) {
26+
if cfg!(debug_assertions) {
27+
// Ensure the rvalue can be assigned to this place. MIR validation ensures that the LHS
28+
// and RHS agree on the type, but only here (post-monomorphization) can we check that
29+
// they actually have the same layout. This serves as sanity check for subtyping.
30+
let rvalue_ty = self.monomorphize(rvalue.ty(&self.mir.local_decls, self.cx.tcx()));
31+
let rvalue_layout = self.cx.layout_of(rvalue_ty);
32+
if !compare_types::mir_assign_valid_types(
33+
self.cx.tcx(),
34+
self.cx.typing_env(),
35+
rvalue_layout,
36+
dest.layout,
37+
) {
38+
span_bug!(
39+
self.mir.span, // this is a terrible span but we have nothing better...
40+
"invalid MIR assignment: place has type {}, rvalue has type {}",
41+
dest.layout.ty,
42+
rvalue_ty,
43+
)
44+
}
45+
}
46+
2547
match *rvalue {
2648
mir::Rvalue::Use(ref operand) => {
2749
if let mir::Operand::Constant(const_op) = operand {
@@ -244,6 +266,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
244266
if let abi::BackendRepr::Memory { .. } = cast.backend_repr
245267
&& !cast.is_zst()
246268
{
269+
// This is a terrible span but we have nothing better...
247270
span_bug!(self.mir.span, "Use `codegen_transmute` to transmute to {cast:?}");
248271
}
249272

compiler/rustc_const_eval/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,6 @@ rustc_session = { path = "../rustc_session" }
2121
rustc_span = { path = "../rustc_span" }
2222
rustc_target = { path = "../rustc_target" }
2323
rustc_trait_selection = { path = "../rustc_trait_selection" }
24+
rustc_ty_utils = { path = "../rustc_ty_utils" }
2425
tracing = "0.1"
2526
# tidy-alphabetical-end

compiler/rustc_const_eval/src/interpret/eval_context.rs

Lines changed: 2 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,19 @@ use rustc_middle::ty::layout::{
1010
};
1111
use rustc_middle::ty::{
1212
self, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, TypingEnv, TypingMode,
13-
Variance,
1413
};
1514
use rustc_middle::{bug, mir, span_bug};
1615
use rustc_span::Span;
1716
use rustc_target::callconv::FnAbi;
17+
use rustc_ty_utils::compare_types::mir_assign_valid_types;
1818
use tracing::{debug, trace};
1919

2020
use super::{
2121
Frame, FrameInfo, GlobalId, InterpErrorInfo, InterpErrorKind, InterpResult, MPlaceTy, Machine,
2222
MemPlaceMeta, Memory, OpTy, Place, PlaceTy, PointerArithmetic, Projectable, Provenance,
2323
err_inval, interp_ok, throw_inval, throw_ub, throw_ub_format,
2424
};
25-
use crate::{enter_trace_span, util};
25+
use crate::enter_trace_span;
2626

2727
pub struct InterpCx<'tcx, M: Machine<'tcx>> {
2828
/// Stores the `Machine` instance.
@@ -164,37 +164,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
164164
}
165165
}
166166

167-
/// Test if it is valid for a MIR assignment to assign `src`-typed place to `dest`-typed value.
168-
/// This test should be symmetric, as it is primarily about layout compatibility.
169-
pub(super) fn mir_assign_valid_types<'tcx>(
170-
tcx: TyCtxt<'tcx>,
171-
typing_env: TypingEnv<'tcx>,
172-
src: TyAndLayout<'tcx>,
173-
dest: TyAndLayout<'tcx>,
174-
) -> bool {
175-
// We relate types invariantly because after borrowck subtyping should be fully explicit via
176-
// `Subtype` projections.
177-
if util::relate_types(tcx, typing_env, Variance::Invariant, src.ty, dest.ty) {
178-
// Make sure the layout is equal, too -- just to be safe. Miri really
179-
// needs layout equality. For performance reason we skip this check when
180-
// the types are equal. Equal types *can* have different layouts when
181-
// enum downcast is involved (as enum variants carry the type of the
182-
// enum), but those should never occur in assignments.
183-
if cfg!(debug_assertions) || src.ty != dest.ty {
184-
assert_eq!(
185-
src.layout,
186-
dest.layout,
187-
"{src} and {dest} are subtypes of each other but have different layout",
188-
src = src.ty,
189-
dest = dest.ty,
190-
);
191-
}
192-
true
193-
} else {
194-
false
195-
}
196-
}
197-
198167
/// Use the already known layout if given (but sanity check in debug mode),
199168
/// or compute the layout.
200169
#[cfg_attr(not(debug_assertions), inline(always))]

compiler/rustc_const_eval/src/interpret/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ mod visitor;
2323
pub use rustc_middle::mir::interpret::*; // have all the `interpret` symbols in one place: here
2424

2525
pub use self::call::FnArg;
26+
use self::eval_context::from_known_layout;
2627
pub use self::eval_context::{InterpCx, format_interp_error};
27-
use self::eval_context::{from_known_layout, mir_assign_valid_types};
2828
pub use self::intern::{
2929
HasStaticRootDefId, InternError, InternKind, intern_const_alloc_for_constprop,
3030
intern_const_alloc_recursive,

compiler/rustc_const_eval/src/interpret/operand.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,14 @@ use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter};
1313
use rustc_middle::ty::{ConstInt, ScalarInt, Ty, TyCtxt};
1414
use rustc_middle::{bug, mir, span_bug, ty};
1515
use rustc_span::DUMMY_SP;
16+
use rustc_ty_utils::compare_types::mir_assign_valid_types;
1617
use tracing::field::Empty;
1718
use tracing::trace;
1819

1920
use super::{
2021
CtfeProvenance, Frame, InterpCx, InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta,
2122
OffsetMode, PlaceTy, Pointer, Projectable, Provenance, Scalar, alloc_range, err_ub,
22-
from_known_layout, interp_ok, mir_assign_valid_types, throw_ub,
23+
from_known_layout, interp_ok, throw_ub,
2324
};
2425
use crate::enter_trace_span;
2526

compiler/rustc_const_eval/src/interpret/place.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ use rustc_abi::{BackendRepr, HasDataLayout, Size};
99
use rustc_middle::ty::layout::TyAndLayout;
1010
use rustc_middle::ty::{self, Ty};
1111
use rustc_middle::{bug, mir, span_bug};
12+
use rustc_ty_utils::compare_types::mir_assign_valid_types;
1213
use tracing::field::Empty;
1314
use tracing::{instrument, trace};
1415

1516
use super::{
1617
AllocInit, AllocRef, AllocRefMut, CheckAlignMsg, CtfeProvenance, ImmTy, Immediate, InterpCx,
1718
InterpResult, Machine, MemoryKind, Misalignment, OffsetMode, OpTy, Operand, Pointer,
18-
Projectable, Provenance, Scalar, alloc_range, interp_ok, mir_assign_valid_types,
19+
Projectable, Provenance, Scalar, alloc_range, interp_ok,
1920
};
2021
use crate::enter_trace_span;
2122

compiler/rustc_const_eval/src/util/mod.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,11 @@ use rustc_middle::mir;
33
mod alignment;
44
pub(crate) mod caller_location;
55
mod check_validity_requirement;
6-
mod compare_types;
76
mod type_name;
87

98
pub use self::alignment::{most_packed_projection, place_unalignment};
109
pub use self::check_validity_requirement::check_validity_requirement;
1110
pub(crate) use self::check_validity_requirement::validate_scalar_in_layout;
12-
pub use self::compare_types::{relate_types, sub_types};
1311
pub use self::type_name::type_name;
1412

1513
/// Classify whether an operator is "left-homogeneous", i.e., the LHS has the

compiler/rustc_mir_transform/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ rustc_session = { path = "../rustc_session" }
2323
rustc_span = { path = "../rustc_span" }
2424
rustc_target = { path = "../rustc_target" }
2525
rustc_trait_selection = { path = "../rustc_trait_selection" }
26+
rustc_ty_utils = { path = "../rustc_ty_utils" }
2627
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
2728
tracing = "0.1"
2829
# tidy-alphabetical-end

0 commit comments

Comments
 (0)