Skip to content

Commit 1e02262

Browse files
committed
ty::layout: implement layout_of automatically as a default method.
1 parent 4ce933f commit 1e02262

File tree

8 files changed

+105
-54
lines changed

8 files changed

+105
-54
lines changed

compiler/rustc_codegen_cranelift/src/common.rs

+11-11
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use rustc_index::vec::IndexVec;
2+
use rustc_middle::ty::layout::LayoutError;
23
use rustc_middle::ty::SymbolName;
34
use rustc_target::abi::call::FnAbi;
45
use rustc_target::abi::{Integer, Primitive};
@@ -259,8 +260,9 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> {
259260
impl<'tcx> LayoutOf<'tcx> for FunctionCx<'_, '_, 'tcx> {
260261
type LayoutOfResult = TyAndLayout<'tcx>;
261262

262-
fn layout_of(&self, ty: Ty<'tcx>) -> TyAndLayout<'tcx> {
263-
RevealAllLayoutCx(self.tcx).layout_of(ty)
263+
#[inline]
264+
fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
265+
RevealAllLayoutCx(self.tcx).handle_layout_err(err, span, ty)
264266
}
265267
}
266268

@@ -366,15 +368,13 @@ pub(crate) struct RevealAllLayoutCx<'tcx>(pub(crate) TyCtxt<'tcx>);
366368
impl<'tcx> LayoutOf<'tcx> for RevealAllLayoutCx<'tcx> {
367369
type LayoutOfResult = TyAndLayout<'tcx>;
368370

369-
fn layout_of(&self, ty: Ty<'tcx>) -> TyAndLayout<'tcx> {
370-
assert!(!ty.still_further_specializable());
371-
self.0.layout_of(ParamEnv::reveal_all().and(&ty)).unwrap_or_else(|e| {
372-
if let layout::LayoutError::SizeOverflow(_) = e {
373-
self.0.sess.fatal(&e.to_string())
374-
} else {
375-
bug!("failed to get layout for `{}`: {}", ty, e)
376-
}
377-
})
371+
#[inline]
372+
fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
373+
if let layout::LayoutError::SizeOverflow(_) = err {
374+
self.0.sess.span_fatal(span, &err.to_string())
375+
} else {
376+
span_bug!(span, "failed to get layout for `{}`: {}", ty, err)
377+
}
378378
}
379379
}
380380

compiler/rustc_codegen_llvm/src/builder.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc_codegen_ssa::traits::*;
1515
use rustc_codegen_ssa::MemFlags;
1616
use rustc_data_structures::small_c_str::SmallCStr;
1717
use rustc_hir::def_id::DefId;
18-
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
18+
use rustc_middle::ty::layout::{LayoutError, LayoutOf, TyAndLayout};
1919
use rustc_middle::ty::{self, Ty, TyCtxt};
2020
use rustc_span::Span;
2121
use rustc_target::abi::{self, Align, Size};
@@ -91,8 +91,9 @@ impl HasTargetSpec for Builder<'_, '_, 'tcx> {
9191
impl LayoutOf<'tcx> for Builder<'_, '_, 'tcx> {
9292
type LayoutOfResult = TyAndLayout<'tcx>;
9393

94-
fn layout_of(&self, ty: Ty<'tcx>) -> Self::LayoutOfResult {
95-
self.cx.layout_of(ty)
94+
#[inline]
95+
fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
96+
self.cx.handle_layout_err(err, span, ty)
9697
}
9798
}
9899

compiler/rustc_codegen_llvm/src/context.rs

+9-14
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ use rustc_codegen_ssa::traits::*;
1414
use rustc_data_structures::base_n;
1515
use rustc_data_structures::fx::FxHashMap;
1616
use rustc_data_structures::small_c_str::SmallCStr;
17-
use rustc_middle::bug;
1817
use rustc_middle::mir::mono::CodegenUnit;
1918
use rustc_middle::ty::layout::{HasParamEnv, LayoutError, LayoutOf, TyAndLayout};
2019
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
20+
use rustc_middle::{bug, span_bug};
2121
use rustc_session::config::{CFGuard, CrateType, DebugInfo};
2222
use rustc_session::Session;
23-
use rustc_span::source_map::{Span, DUMMY_SP};
23+
use rustc_span::source_map::Span;
2424
use rustc_span::symbol::Symbol;
2525
use rustc_target::abi::{HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
2626
use rustc_target::spec::{HasTargetSpec, RelocModel, Target, TlsModel};
@@ -838,18 +838,13 @@ impl ty::layout::HasTyCtxt<'tcx> for CodegenCx<'ll, 'tcx> {
838838
impl LayoutOf<'tcx> for CodegenCx<'ll, 'tcx> {
839839
type LayoutOfResult = TyAndLayout<'tcx>;
840840

841-
fn layout_of(&self, ty: Ty<'tcx>) -> Self::LayoutOfResult {
842-
self.spanned_layout_of(ty, DUMMY_SP)
843-
}
844-
845-
fn spanned_layout_of(&self, ty: Ty<'tcx>, span: Span) -> Self::LayoutOfResult {
846-
self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)).unwrap_or_else(|e| {
847-
if let LayoutError::SizeOverflow(_) = e {
848-
self.sess().span_fatal(span, &e.to_string())
849-
} else {
850-
bug!("failed to get layout for `{}`: {}", ty, e)
851-
}
852-
})
841+
#[inline]
842+
fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
843+
if let LayoutError::SizeOverflow(_) = err {
844+
self.sess().span_fatal(span, &err.to_string())
845+
} else {
846+
span_bug!(span, "failed to get layout for `{}`: {}", ty, err)
847+
}
853848
}
854849
}
855850

compiler/rustc_lint/src/context.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1083,8 +1083,9 @@ impl<'tcx> ty::layout::HasParamEnv<'tcx> for LateContext<'tcx> {
10831083
impl<'tcx> LayoutOf<'tcx> for LateContext<'tcx> {
10841084
type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
10851085

1086-
fn layout_of(&self, ty: Ty<'tcx>) -> Self::LayoutOfResult {
1087-
self.tcx.layout_of(self.param_env.and(ty))
1086+
#[inline]
1087+
fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> {
1088+
err
10881089
}
10891090
}
10901091

compiler/rustc_middle/src/ty/layout.rs

+50-11
Original file line numberDiff line numberDiff line change
@@ -2095,35 +2095,74 @@ pub type TyAndLayout<'tcx> = rustc_target::abi::TyAndLayout<'tcx, Ty<'tcx>>;
20952095

20962096
/// Trait for contexts that can compute layouts of types.
20972097
pub trait LayoutOf<'tcx>: HasDataLayout + HasTyCtxt<'tcx> + HasParamEnv<'tcx> {
2098+
/// The `TyAndLayout`-wrapping type (or `TyAndLayout` itself), which will be
2099+
/// returned from `layout_of` (see also `handle_layout_err`).
20982100
type LayoutOfResult: MaybeResult<TyAndLayout<'tcx>>;
20992101

2100-
fn layout_of(&self, ty: Ty<'tcx>) -> Self::LayoutOfResult;
2102+
/// `Span` to use for `tcx.at(span)`, from `layout_of`.
2103+
// FIXME(eddyb) perhaps make this mandatory to get contexts to track it better?
2104+
#[inline]
2105+
fn layout_tcx_at_span(&self) -> Span {
2106+
DUMMY_SP
2107+
}
2108+
2109+
/// Helper used for `layout_of`, to adapt `tcx.layout_of(...)` into a
2110+
/// `Self::LayoutOfResult` (which does not need to be a `Result<...>`).
2111+
///
2112+
/// Most `impl`s, which propagate `LayoutError`s, should simply return `err`,
2113+
/// but this hook allows e.g. codegen to return only `TyAndLayout` from its
2114+
/// `cx.layout_of(...)`, without any `Result<...>` around it to deal with
2115+
/// (and any `LayoutError`s are turned into fatal errors or ICEs).
2116+
fn handle_layout_err(
2117+
&self,
2118+
err: LayoutError<'tcx>,
2119+
span: Span,
2120+
ty: Ty<'tcx>,
2121+
) -> <Self::LayoutOfResult as MaybeResult<TyAndLayout<'tcx>>>::Error;
2122+
2123+
/// Computes the layout of a type. Note that this implicitly
2124+
/// executes in "reveal all" mode, and will normalize the input type.
2125+
#[inline]
2126+
fn layout_of(&self, ty: Ty<'tcx>) -> Self::LayoutOfResult {
2127+
self.spanned_layout_of(ty, DUMMY_SP)
2128+
}
2129+
2130+
/// Computes the layout of a type, at `span`. Note that this implicitly
2131+
/// executes in "reveal all" mode, and will normalize the input type.
21012132
// FIXME(eddyb) avoid passing information like this, and instead add more
21022133
// `TyCtxt::at`-like APIs to be able to do e.g. `cx.at(span).layout_of(ty)`.
2103-
fn spanned_layout_of(&self, ty: Ty<'tcx>, _span: Span) -> Self::LayoutOfResult {
2104-
self.layout_of(ty)
2134+
#[inline]
2135+
fn spanned_layout_of(&self, ty: Ty<'tcx>, span: Span) -> Self::LayoutOfResult {
2136+
let span = if !span.is_dummy() { span } else { self.layout_tcx_at_span() };
2137+
MaybeResult::from(
2138+
self.tcx()
2139+
.at(span)
2140+
.layout_of(self.param_env().and(ty))
2141+
.map_err(|err| self.handle_layout_err(err, span, ty)),
2142+
)
21052143
}
21062144
}
21072145

21082146
impl LayoutOf<'tcx> for LayoutCx<'tcx, TyCtxt<'tcx>> {
21092147
type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
21102148

2111-
/// Computes the layout of a type. Note that this implicitly
2112-
/// executes in "reveal all" mode, and will normalize the input type.
21132149
#[inline]
2114-
fn layout_of(&self, ty: Ty<'tcx>) -> Self::LayoutOfResult {
2115-
self.tcx.layout_of(self.param_env.and(ty))
2150+
fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> {
2151+
err
21162152
}
21172153
}
21182154

21192155
impl LayoutOf<'tcx> for LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> {
21202156
type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
21212157

2122-
/// Computes the layout of a type. Note that this implicitly
2123-
/// executes in "reveal all" mode, and will normalize the input type.
21242158
#[inline]
2125-
fn layout_of(&self, ty: Ty<'tcx>) -> Self::LayoutOfResult {
2126-
self.tcx.layout_of(self.param_env.and(ty))
2159+
fn layout_tcx_at_span(&self) -> Span {
2160+
self.tcx.span
2161+
}
2162+
2163+
#[inline]
2164+
fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> {
2165+
err
21272166
}
21282167
}
21292168

compiler/rustc_mir/src/interpret/eval_context.rs

+16-8
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_index::vec::IndexVec;
88
use rustc_macros::HashStable;
99
use rustc_middle::ich::StableHashingContext;
1010
use rustc_middle::mir;
11-
use rustc_middle::ty::layout::{self, LayoutOf, TyAndLayout};
11+
use rustc_middle::ty::layout::{self, LayoutError, LayoutOf, TyAndLayout};
1212
use rustc_middle::ty::{
1313
self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable,
1414
};
@@ -17,9 +17,9 @@ use rustc_span::{Pos, Span};
1717
use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout};
1818

1919
use super::{
20-
AllocId, GlobalId, Immediate, InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory,
21-
MemoryKind, Operand, Place, PlaceTy, Pointer, Provenance, Scalar, ScalarMaybeUninit,
22-
StackPopJump,
20+
AllocId, GlobalId, Immediate, InterpErrorInfo, InterpResult, MPlaceTy, Machine, MemPlace,
21+
MemPlaceMeta, Memory, MemoryKind, Operand, Place, PlaceTy, Pointer, Provenance, Scalar,
22+
ScalarMaybeUninit, StackPopJump,
2323
};
2424
use crate::transform::validate::equal_up_to_regions;
2525
use crate::util::storage::AlwaysLiveLocals;
@@ -316,10 +316,18 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> LayoutOf<'tcx> for InterpCx<'mir,
316316
type LayoutOfResult = InterpResult<'tcx, TyAndLayout<'tcx>>;
317317

318318
#[inline]
319-
fn layout_of(&self, ty: Ty<'tcx>) -> Self::LayoutOfResult {
320-
self.tcx
321-
.layout_of(self.param_env.and(ty))
322-
.map_err(|layout| err_inval!(Layout(layout)).into())
319+
fn layout_tcx_at_span(&self) -> Span {
320+
self.tcx.span
321+
}
322+
323+
#[inline]
324+
fn handle_layout_err(
325+
&self,
326+
err: LayoutError<'tcx>,
327+
_: Span,
328+
_: Ty<'tcx>,
329+
) -> InterpErrorInfo<'tcx> {
330+
err_inval!(Layout(err)).into()
323331
}
324332
}
325333

compiler/rustc_mir/src/transform/const_prop.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -333,8 +333,9 @@ struct ConstPropagator<'mir, 'tcx> {
333333
impl<'mir, 'tcx> LayoutOf<'tcx> for ConstPropagator<'mir, 'tcx> {
334334
type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
335335

336-
fn layout_of(&self, ty: Ty<'tcx>) -> Self::LayoutOfResult {
337-
self.tcx.layout_of(self.param_env.and(ty))
336+
#[inline]
337+
fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> {
338+
err
338339
}
339340
}
340341

compiler/rustc_passes/src/layout_test.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ use rustc_hir as hir;
33
use rustc_hir::def_id::LocalDefId;
44
use rustc_hir::itemlikevisit::ItemLikeVisitor;
55
use rustc_hir::ItemKind;
6-
use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutOf, TyAndLayout};
6+
use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutError, LayoutOf, TyAndLayout};
77
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
88
use rustc_span::symbol::sym;
9+
use rustc_span::Span;
910
use rustc_target::abi::{HasDataLayout, TargetDataLayout};
1011

1112
pub fn test_layout(tcx: TyCtxt<'_>) {
@@ -116,8 +117,13 @@ struct UnwrapLayoutCx<'tcx> {
116117
impl LayoutOf<'tcx> for UnwrapLayoutCx<'tcx> {
117118
type LayoutOfResult = TyAndLayout<'tcx>;
118119

119-
fn layout_of(&self, ty: Ty<'tcx>) -> Self::LayoutOfResult {
120-
self.tcx.layout_of(self.param_env.and(ty)).unwrap()
120+
fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
121+
span_bug!(
122+
span,
123+
"`#[rustc_layout(..)]` test resulted in `layout_of({}) = Err({})`",
124+
ty,
125+
err
126+
);
121127
}
122128
}
123129

0 commit comments

Comments
 (0)