ty::layout: implement layout_of
automatically as a default method.
This commit is contained in:
parent
4ce933f13f
commit
1e02262dcc
8 changed files with 105 additions and 54 deletions
|
@ -1,4 +1,5 @@
|
||||||
use rustc_index::vec::IndexVec;
|
use rustc_index::vec::IndexVec;
|
||||||
|
use rustc_middle::ty::layout::LayoutError;
|
||||||
use rustc_middle::ty::SymbolName;
|
use rustc_middle::ty::SymbolName;
|
||||||
use rustc_target::abi::call::FnAbi;
|
use rustc_target::abi::call::FnAbi;
|
||||||
use rustc_target::abi::{Integer, Primitive};
|
use rustc_target::abi::{Integer, Primitive};
|
||||||
|
@ -259,8 +260,9 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> {
|
||||||
impl<'tcx> LayoutOf<'tcx> for FunctionCx<'_, '_, 'tcx> {
|
impl<'tcx> LayoutOf<'tcx> for FunctionCx<'_, '_, 'tcx> {
|
||||||
type LayoutOfResult = TyAndLayout<'tcx>;
|
type LayoutOfResult = TyAndLayout<'tcx>;
|
||||||
|
|
||||||
fn layout_of(&self, ty: Ty<'tcx>) -> TyAndLayout<'tcx> {
|
#[inline]
|
||||||
RevealAllLayoutCx(self.tcx).layout_of(ty)
|
fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
|
||||||
|
RevealAllLayoutCx(self.tcx).handle_layout_err(err, span, ty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,15 +368,13 @@ pub(crate) struct RevealAllLayoutCx<'tcx>(pub(crate) TyCtxt<'tcx>);
|
||||||
impl<'tcx> LayoutOf<'tcx> for RevealAllLayoutCx<'tcx> {
|
impl<'tcx> LayoutOf<'tcx> for RevealAllLayoutCx<'tcx> {
|
||||||
type LayoutOfResult = TyAndLayout<'tcx>;
|
type LayoutOfResult = TyAndLayout<'tcx>;
|
||||||
|
|
||||||
fn layout_of(&self, ty: Ty<'tcx>) -> TyAndLayout<'tcx> {
|
#[inline]
|
||||||
assert!(!ty.still_further_specializable());
|
fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
|
||||||
self.0.layout_of(ParamEnv::reveal_all().and(&ty)).unwrap_or_else(|e| {
|
if let layout::LayoutError::SizeOverflow(_) = err {
|
||||||
if let layout::LayoutError::SizeOverflow(_) = e {
|
self.0.sess.span_fatal(span, &err.to_string())
|
||||||
self.0.sess.fatal(&e.to_string())
|
|
||||||
} else {
|
} else {
|
||||||
bug!("failed to get layout for `{}`: {}", ty, e)
|
span_bug!(span, "failed to get layout for `{}`: {}", ty, err)
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ use rustc_codegen_ssa::traits::*;
|
||||||
use rustc_codegen_ssa::MemFlags;
|
use rustc_codegen_ssa::MemFlags;
|
||||||
use rustc_data_structures::small_c_str::SmallCStr;
|
use rustc_data_structures::small_c_str::SmallCStr;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
|
use rustc_middle::ty::layout::{LayoutError, LayoutOf, TyAndLayout};
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_target::abi::{self, Align, Size};
|
use rustc_target::abi::{self, Align, Size};
|
||||||
|
@ -91,8 +91,9 @@ impl HasTargetSpec for Builder<'_, '_, 'tcx> {
|
||||||
impl LayoutOf<'tcx> for Builder<'_, '_, 'tcx> {
|
impl LayoutOf<'tcx> for Builder<'_, '_, 'tcx> {
|
||||||
type LayoutOfResult = TyAndLayout<'tcx>;
|
type LayoutOfResult = TyAndLayout<'tcx>;
|
||||||
|
|
||||||
fn layout_of(&self, ty: Ty<'tcx>) -> Self::LayoutOfResult {
|
#[inline]
|
||||||
self.cx.layout_of(ty)
|
fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
|
||||||
|
self.cx.handle_layout_err(err, span, ty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,13 +14,13 @@ use rustc_codegen_ssa::traits::*;
|
||||||
use rustc_data_structures::base_n;
|
use rustc_data_structures::base_n;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::small_c_str::SmallCStr;
|
use rustc_data_structures::small_c_str::SmallCStr;
|
||||||
use rustc_middle::bug;
|
|
||||||
use rustc_middle::mir::mono::CodegenUnit;
|
use rustc_middle::mir::mono::CodegenUnit;
|
||||||
use rustc_middle::ty::layout::{HasParamEnv, LayoutError, LayoutOf, TyAndLayout};
|
use rustc_middle::ty::layout::{HasParamEnv, LayoutError, LayoutOf, TyAndLayout};
|
||||||
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
|
||||||
|
use rustc_middle::{bug, span_bug};
|
||||||
use rustc_session::config::{CFGuard, CrateType, DebugInfo};
|
use rustc_session::config::{CFGuard, CrateType, DebugInfo};
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::source_map::{Span, DUMMY_SP};
|
use rustc_span::source_map::Span;
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
use rustc_target::abi::{HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
|
use rustc_target::abi::{HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
|
||||||
use rustc_target::spec::{HasTargetSpec, RelocModel, Target, TlsModel};
|
use rustc_target::spec::{HasTargetSpec, RelocModel, Target, TlsModel};
|
||||||
|
@ -838,18 +838,13 @@ impl ty::layout::HasTyCtxt<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||||
impl LayoutOf<'tcx> for CodegenCx<'ll, 'tcx> {
|
impl LayoutOf<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||||
type LayoutOfResult = TyAndLayout<'tcx>;
|
type LayoutOfResult = TyAndLayout<'tcx>;
|
||||||
|
|
||||||
fn layout_of(&self, ty: Ty<'tcx>) -> Self::LayoutOfResult {
|
#[inline]
|
||||||
self.spanned_layout_of(ty, DUMMY_SP)
|
fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
|
||||||
}
|
if let LayoutError::SizeOverflow(_) = err {
|
||||||
|
self.sess().span_fatal(span, &err.to_string())
|
||||||
fn spanned_layout_of(&self, ty: Ty<'tcx>, span: Span) -> Self::LayoutOfResult {
|
|
||||||
self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)).unwrap_or_else(|e| {
|
|
||||||
if let LayoutError::SizeOverflow(_) = e {
|
|
||||||
self.sess().span_fatal(span, &e.to_string())
|
|
||||||
} else {
|
} else {
|
||||||
bug!("failed to get layout for `{}`: {}", ty, e)
|
span_bug!(span, "failed to get layout for `{}`: {}", ty, err)
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1083,8 +1083,9 @@ impl<'tcx> ty::layout::HasParamEnv<'tcx> for LateContext<'tcx> {
|
||||||
impl<'tcx> LayoutOf<'tcx> for LateContext<'tcx> {
|
impl<'tcx> LayoutOf<'tcx> for LateContext<'tcx> {
|
||||||
type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
|
type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
|
||||||
|
|
||||||
fn layout_of(&self, ty: Ty<'tcx>) -> Self::LayoutOfResult {
|
#[inline]
|
||||||
self.tcx.layout_of(self.param_env.and(ty))
|
fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> {
|
||||||
|
err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2095,35 +2095,74 @@ pub type TyAndLayout<'tcx> = rustc_target::abi::TyAndLayout<'tcx, Ty<'tcx>>;
|
||||||
|
|
||||||
/// Trait for contexts that can compute layouts of types.
|
/// Trait for contexts that can compute layouts of types.
|
||||||
pub trait LayoutOf<'tcx>: HasDataLayout + HasTyCtxt<'tcx> + HasParamEnv<'tcx> {
|
pub trait LayoutOf<'tcx>: HasDataLayout + HasTyCtxt<'tcx> + HasParamEnv<'tcx> {
|
||||||
|
/// The `TyAndLayout`-wrapping type (or `TyAndLayout` itself), which will be
|
||||||
|
/// returned from `layout_of` (see also `handle_layout_err`).
|
||||||
type LayoutOfResult: MaybeResult<TyAndLayout<'tcx>>;
|
type LayoutOfResult: MaybeResult<TyAndLayout<'tcx>>;
|
||||||
|
|
||||||
fn layout_of(&self, ty: Ty<'tcx>) -> Self::LayoutOfResult;
|
/// `Span` to use for `tcx.at(span)`, from `layout_of`.
|
||||||
|
// FIXME(eddyb) perhaps make this mandatory to get contexts to track it better?
|
||||||
|
#[inline]
|
||||||
|
fn layout_tcx_at_span(&self) -> Span {
|
||||||
|
DUMMY_SP
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper used for `layout_of`, to adapt `tcx.layout_of(...)` into a
|
||||||
|
/// `Self::LayoutOfResult` (which does not need to be a `Result<...>`).
|
||||||
|
///
|
||||||
|
/// Most `impl`s, which propagate `LayoutError`s, should simply return `err`,
|
||||||
|
/// but this hook allows e.g. codegen to return only `TyAndLayout` from its
|
||||||
|
/// `cx.layout_of(...)`, without any `Result<...>` around it to deal with
|
||||||
|
/// (and any `LayoutError`s are turned into fatal errors or ICEs).
|
||||||
|
fn handle_layout_err(
|
||||||
|
&self,
|
||||||
|
err: LayoutError<'tcx>,
|
||||||
|
span: Span,
|
||||||
|
ty: Ty<'tcx>,
|
||||||
|
) -> <Self::LayoutOfResult as MaybeResult<TyAndLayout<'tcx>>>::Error;
|
||||||
|
|
||||||
|
/// Computes the layout of a type. Note that this implicitly
|
||||||
|
/// executes in "reveal all" mode, and will normalize the input type.
|
||||||
|
#[inline]
|
||||||
|
fn layout_of(&self, ty: Ty<'tcx>) -> Self::LayoutOfResult {
|
||||||
|
self.spanned_layout_of(ty, DUMMY_SP)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the layout of a type, at `span`. Note that this implicitly
|
||||||
|
/// executes in "reveal all" mode, and will normalize the input type.
|
||||||
// FIXME(eddyb) avoid passing information like this, and instead add more
|
// FIXME(eddyb) avoid passing information like this, and instead add more
|
||||||
// `TyCtxt::at`-like APIs to be able to do e.g. `cx.at(span).layout_of(ty)`.
|
// `TyCtxt::at`-like APIs to be able to do e.g. `cx.at(span).layout_of(ty)`.
|
||||||
fn spanned_layout_of(&self, ty: Ty<'tcx>, _span: Span) -> Self::LayoutOfResult {
|
#[inline]
|
||||||
self.layout_of(ty)
|
fn spanned_layout_of(&self, ty: Ty<'tcx>, span: Span) -> Self::LayoutOfResult {
|
||||||
|
let span = if !span.is_dummy() { span } else { self.layout_tcx_at_span() };
|
||||||
|
MaybeResult::from(
|
||||||
|
self.tcx()
|
||||||
|
.at(span)
|
||||||
|
.layout_of(self.param_env().and(ty))
|
||||||
|
.map_err(|err| self.handle_layout_err(err, span, ty)),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LayoutOf<'tcx> for LayoutCx<'tcx, TyCtxt<'tcx>> {
|
impl LayoutOf<'tcx> for LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||||
type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
|
type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
|
||||||
|
|
||||||
/// Computes the layout of a type. Note that this implicitly
|
|
||||||
/// executes in "reveal all" mode, and will normalize the input type.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn layout_of(&self, ty: Ty<'tcx>) -> Self::LayoutOfResult {
|
fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> {
|
||||||
self.tcx.layout_of(self.param_env.and(ty))
|
err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LayoutOf<'tcx> for LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> {
|
impl LayoutOf<'tcx> for LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> {
|
||||||
type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
|
type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
|
||||||
|
|
||||||
/// Computes the layout of a type. Note that this implicitly
|
|
||||||
/// executes in "reveal all" mode, and will normalize the input type.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn layout_of(&self, ty: Ty<'tcx>) -> Self::LayoutOfResult {
|
fn layout_tcx_at_span(&self) -> Span {
|
||||||
self.tcx.layout_of(self.param_env.and(ty))
|
self.tcx.span
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> {
|
||||||
|
err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ use rustc_index::vec::IndexVec;
|
||||||
use rustc_macros::HashStable;
|
use rustc_macros::HashStable;
|
||||||
use rustc_middle::ich::StableHashingContext;
|
use rustc_middle::ich::StableHashingContext;
|
||||||
use rustc_middle::mir;
|
use rustc_middle::mir;
|
||||||
use rustc_middle::ty::layout::{self, LayoutOf, TyAndLayout};
|
use rustc_middle::ty::layout::{self, LayoutError, LayoutOf, TyAndLayout};
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable,
|
self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable,
|
||||||
};
|
};
|
||||||
|
@ -17,9 +17,9 @@ use rustc_span::{Pos, Span};
|
||||||
use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout};
|
use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
AllocId, GlobalId, Immediate, InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory,
|
AllocId, GlobalId, Immediate, InterpErrorInfo, InterpResult, MPlaceTy, Machine, MemPlace,
|
||||||
MemoryKind, Operand, Place, PlaceTy, Pointer, Provenance, Scalar, ScalarMaybeUninit,
|
MemPlaceMeta, Memory, MemoryKind, Operand, Place, PlaceTy, Pointer, Provenance, Scalar,
|
||||||
StackPopJump,
|
ScalarMaybeUninit, StackPopJump,
|
||||||
};
|
};
|
||||||
use crate::transform::validate::equal_up_to_regions;
|
use crate::transform::validate::equal_up_to_regions;
|
||||||
use crate::util::storage::AlwaysLiveLocals;
|
use crate::util::storage::AlwaysLiveLocals;
|
||||||
|
@ -316,10 +316,18 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> LayoutOf<'tcx> for InterpCx<'mir,
|
||||||
type LayoutOfResult = InterpResult<'tcx, TyAndLayout<'tcx>>;
|
type LayoutOfResult = InterpResult<'tcx, TyAndLayout<'tcx>>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn layout_of(&self, ty: Ty<'tcx>) -> Self::LayoutOfResult {
|
fn layout_tcx_at_span(&self) -> Span {
|
||||||
self.tcx
|
self.tcx.span
|
||||||
.layout_of(self.param_env.and(ty))
|
}
|
||||||
.map_err(|layout| err_inval!(Layout(layout)).into())
|
|
||||||
|
#[inline]
|
||||||
|
fn handle_layout_err(
|
||||||
|
&self,
|
||||||
|
err: LayoutError<'tcx>,
|
||||||
|
_: Span,
|
||||||
|
_: Ty<'tcx>,
|
||||||
|
) -> InterpErrorInfo<'tcx> {
|
||||||
|
err_inval!(Layout(err)).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -333,8 +333,9 @@ struct ConstPropagator<'mir, 'tcx> {
|
||||||
impl<'mir, 'tcx> LayoutOf<'tcx> for ConstPropagator<'mir, 'tcx> {
|
impl<'mir, 'tcx> LayoutOf<'tcx> for ConstPropagator<'mir, 'tcx> {
|
||||||
type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
|
type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
|
||||||
|
|
||||||
fn layout_of(&self, ty: Ty<'tcx>) -> Self::LayoutOfResult {
|
#[inline]
|
||||||
self.tcx.layout_of(self.param_env.and(ty))
|
fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> {
|
||||||
|
err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,10 @@ use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_hir::itemlikevisit::ItemLikeVisitor;
|
use rustc_hir::itemlikevisit::ItemLikeVisitor;
|
||||||
use rustc_hir::ItemKind;
|
use rustc_hir::ItemKind;
|
||||||
use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutOf, TyAndLayout};
|
use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutError, LayoutOf, TyAndLayout};
|
||||||
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
|
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
|
use rustc_span::Span;
|
||||||
use rustc_target::abi::{HasDataLayout, TargetDataLayout};
|
use rustc_target::abi::{HasDataLayout, TargetDataLayout};
|
||||||
|
|
||||||
pub fn test_layout(tcx: TyCtxt<'_>) {
|
pub fn test_layout(tcx: TyCtxt<'_>) {
|
||||||
|
@ -116,8 +117,13 @@ struct UnwrapLayoutCx<'tcx> {
|
||||||
impl LayoutOf<'tcx> for UnwrapLayoutCx<'tcx> {
|
impl LayoutOf<'tcx> for UnwrapLayoutCx<'tcx> {
|
||||||
type LayoutOfResult = TyAndLayout<'tcx>;
|
type LayoutOfResult = TyAndLayout<'tcx>;
|
||||||
|
|
||||||
fn layout_of(&self, ty: Ty<'tcx>) -> Self::LayoutOfResult {
|
fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
|
||||||
self.tcx.layout_of(self.param_env.and(ty)).unwrap()
|
span_bug!(
|
||||||
|
span,
|
||||||
|
"`#[rustc_layout(..)]` test resulted in `layout_of({}) = Err({})`",
|
||||||
|
ty,
|
||||||
|
err
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue