Skip to content

Commit edb4b2d

Browse files
committed
Morph layout_raw query into layout_of.
1 parent b5fe3bc commit edb4b2d

File tree

9 files changed

+54
-94
lines changed

9 files changed

+54
-94
lines changed

Diff for: compiler/rustc_middle/src/query/mod.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -1100,10 +1100,12 @@ rustc_queries! {
11001100
cache_on_disk_if { false }
11011101
}
11021102

1103-
query layout_raw(
1104-
env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>
1105-
) -> Result<&'tcx rustc_target::abi::Layout, ty::layout::LayoutError<'tcx>> {
1106-
desc { "computing layout of `{}`", env.value }
1103+
/// Computes the layout of a type. Note that this implicitly
1104+
/// executes in "reveal all" mode, and will normalize the input type.
1105+
query layout_of(
1106+
key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>
1107+
) -> Result<ty::layout::TyAndLayout<'tcx>, ty::layout::LayoutError<'tcx>> {
1108+
desc { "computing layout of `{}`", key.value }
11071109
}
11081110

11091111
query dylib_dependency_formats(_: CrateNum)

Diff for: compiler/rustc_middle/src/ty/layout.rs

+33-75
Original file line numberDiff line numberDiff line change
@@ -205,10 +205,10 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
205205
}
206206
}
207207

208-
fn layout_raw<'tcx>(
208+
fn layout_of<'tcx>(
209209
tcx: TyCtxt<'tcx>,
210210
query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
211-
) -> Result<&'tcx Layout, LayoutError<'tcx>> {
211+
) -> Result<TyAndLayout<'tcx>, LayoutError<'tcx>> {
212212
ty::tls::with_related_context(tcx, move |icx| {
213213
let (param_env, ty) = query.into_parts();
214214

@@ -220,21 +220,33 @@ fn layout_raw<'tcx>(
220220
let icx = ty::tls::ImplicitCtxt { layout_depth: icx.layout_depth + 1, ..icx.clone() };
221221

222222
ty::tls::enter_context(&icx, |_| {
223+
let param_env = param_env.with_reveal_all_normalized(tcx);
224+
let unnormalized_ty = ty;
225+
let ty = tcx.normalize_erasing_regions(param_env, ty);
226+
if ty != unnormalized_ty {
227+
// Ensure this layout is also cached for the normalized type.
228+
return tcx.layout_of(param_env.and(ty));
229+
}
230+
223231
let cx = LayoutCx { tcx, param_env };
224-
let layout = cx.layout_raw_uncached(ty);
232+
233+
let layout = cx.layout_of_uncached(ty)?;
234+
let layout = TyAndLayout { ty, layout };
235+
236+
cx.record_layout_for_printing(layout);
237+
225238
// Type-level uninhabitedness should always imply ABI uninhabitedness.
226-
if let Ok(layout) = layout {
227-
if tcx.conservative_is_privately_uninhabited(param_env.and(ty)) {
228-
assert!(layout.abi.is_uninhabited());
229-
}
239+
if tcx.conservative_is_privately_uninhabited(param_env.and(ty)) {
240+
assert!(layout.abi.is_uninhabited());
230241
}
231-
layout
242+
243+
Ok(layout)
232244
})
233245
})
234246
}
235247

236248
pub fn provide(providers: &mut ty::query::Providers) {
237-
*providers = ty::query::Providers { layout_raw, ..*providers };
249+
*providers = ty::query::Providers { layout_of, ..*providers };
238250
}
239251

240252
pub struct LayoutCx<'tcx, C> {
@@ -492,7 +504,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
492504
})
493505
}
494506

495-
fn layout_raw_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'tcx>> {
507+
fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'tcx>> {
496508
let tcx = self.tcx;
497509
let param_env = self.param_env;
498510
let dl = self.data_layout();
@@ -886,7 +898,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
886898
let present_first = match present_first {
887899
Some(present_first) => present_first,
888900
// Uninhabited because it has no variants, or only absent ones.
889-
None if def.is_enum() => return tcx.layout_raw(param_env.and(tcx.types.never)),
901+
None if def.is_enum() => {
902+
return Ok(tcx.layout_of(param_env.and(tcx.types.never))?.layout);
903+
}
890904
// If it's a struct, still compute a layout so that we can still compute the
891905
// field offsets.
892906
None => VariantIdx::new(0),
@@ -1362,11 +1376,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
13621376

13631377
// Types with no meaningful known layout.
13641378
ty::Projection(_) | ty::Opaque(..) => {
1365-
let normalized = tcx.normalize_erasing_regions(param_env, ty);
1366-
if ty == normalized {
1367-
return Err(LayoutError::Unknown(ty));
1368-
}
1369-
tcx.layout_raw(param_env.and(normalized))?
1379+
// NOTE(eddyb) `layout_of` query should've normalized these away,
1380+
// if that was possible, so there's no reason to try again here.
1381+
return Err(LayoutError::Unknown(ty));
13701382
}
13711383

13721384
ty::Placeholder(..) | ty::GeneratorWitness(..) | ty::Infer(_) => {
@@ -1703,7 +1715,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
17031715
Ok(layout)
17041716
}
17051717

1706-
/// This is invoked by the `layout_raw` query to record the final
1718+
/// This is invoked by the `layout_of` query to record the final
17071719
/// layout of each type.
17081720
#[inline(always)]
17091721
fn record_layout_for_printing(&self, layout: TyAndLayout<'tcx>) {
@@ -2031,22 +2043,9 @@ impl<'tcx> LayoutOf for LayoutCx<'tcx, TyCtxt<'tcx>> {
20312043
type TyAndLayout = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
20322044

20332045
/// Computes the layout of a type. Note that this implicitly
2034-
/// executes in "reveal all" mode.
2046+
/// executes in "reveal all" mode, and will normalize the input type.
20352047
fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
2036-
let param_env = self.param_env.with_reveal_all_normalized(self.tcx);
2037-
let ty = self.tcx.normalize_erasing_regions(param_env, ty);
2038-
let layout = self.tcx.layout_raw(param_env.and(ty))?;
2039-
let layout = TyAndLayout { ty, layout };
2040-
2041-
// N.B., this recording is normally disabled; when enabled, it
2042-
// can however trigger recursive invocations of `layout_of`.
2043-
// Therefore, we execute it *after* the main query has
2044-
// completed, to avoid problems around recursive structures
2045-
// and the like. (Admittedly, I wasn't able to reproduce a problem
2046-
// here, but it seems like the right thing to do. -nmatsakis)
2047-
self.record_layout_for_printing(layout);
2048-
2049-
Ok(layout)
2048+
self.tcx.layout_of(self.param_env.and(ty))
20502049
}
20512050
}
20522051

@@ -2055,50 +2054,9 @@ impl LayoutOf for LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> {
20552054
type TyAndLayout = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
20562055

20572056
/// Computes the layout of a type. Note that this implicitly
2058-
/// executes in "reveal all" mode.
2057+
/// executes in "reveal all" mode, and will normalize the input type.
20592058
fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
2060-
let param_env = self.param_env.with_reveal_all_normalized(*self.tcx);
2061-
let ty = self.tcx.normalize_erasing_regions(param_env, ty);
2062-
let layout = self.tcx.layout_raw(param_env.and(ty))?;
2063-
let layout = TyAndLayout { ty, layout };
2064-
2065-
// N.B., this recording is normally disabled; when enabled, it
2066-
// can however trigger recursive invocations of `layout_of`.
2067-
// Therefore, we execute it *after* the main query has
2068-
// completed, to avoid problems around recursive structures
2069-
// and the like. (Admittedly, I wasn't able to reproduce a problem
2070-
// here, but it seems like the right thing to do. -nmatsakis)
2071-
let cx = LayoutCx { tcx: *self.tcx, param_env: self.param_env };
2072-
cx.record_layout_for_printing(layout);
2073-
2074-
Ok(layout)
2075-
}
2076-
}
2077-
2078-
// Helper (inherent) `layout_of` methods to avoid pushing `LayoutCx` to users.
2079-
impl TyCtxt<'tcx> {
2080-
/// Computes the layout of a type. Note that this implicitly
2081-
/// executes in "reveal all" mode.
2082-
#[inline]
2083-
pub fn layout_of(
2084-
self,
2085-
param_env_and_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
2086-
) -> Result<TyAndLayout<'tcx>, LayoutError<'tcx>> {
2087-
let cx = LayoutCx { tcx: self, param_env: param_env_and_ty.param_env };
2088-
cx.layout_of(param_env_and_ty.value)
2089-
}
2090-
}
2091-
2092-
impl ty::query::TyCtxtAt<'tcx> {
2093-
/// Computes the layout of a type. Note that this implicitly
2094-
/// executes in "reveal all" mode.
2095-
#[inline]
2096-
pub fn layout_of(
2097-
self,
2098-
param_env_and_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
2099-
) -> Result<TyAndLayout<'tcx>, LayoutError<'tcx>> {
2100-
let cx = LayoutCx { tcx: self.at(self.span), param_env: param_env_and_ty.param_env };
2101-
cx.layout_of(param_env_and_ty.value)
2059+
self.tcx.layout_of(self.param_env.and(ty))
21022060
}
21032061
}
21042062

Diff for: compiler/rustc_mir/src/util/alignment.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ where
2424
};
2525

2626
let ty = place.ty(local_decls, tcx).ty;
27-
match tcx.layout_raw(param_env.and(ty)) {
27+
match tcx.layout_of(param_env.and(ty)) {
2828
Ok(layout) if layout.align.abi <= pack => {
2929
// If the packed alignment is greater or equal to the field alignment, the type won't be
3030
// further disaligned.

Diff for: compiler/rustc_target/src/abi/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1063,7 +1063,7 @@ impl Layout {
10631063
/// to that obtained from `layout_of(ty)`, as we need to produce
10641064
/// layouts for which Rust types do not exist, such as enum variants
10651065
/// or synthetic fields of enums (i.e., discriminants) and fat pointers.
1066-
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
1066+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable_Generic)]
10671067
pub struct TyAndLayout<'a, Ty> {
10681068
pub ty: Ty,
10691069
pub layout: &'a Layout,

Diff for: compiler/rustc_typeck/src/check/upvar.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1485,7 +1485,7 @@ fn restrict_repr_packed_field_ref_capture<'tcx>(
14851485
match p.kind {
14861486
ProjectionKind::Field(..) => match ty.kind() {
14871487
ty::Adt(def, _) if def.repr.packed() => {
1488-
match tcx.layout_raw(param_env.and(p.ty)) {
1488+
match tcx.layout_of(param_env.and(p.ty)) {
14891489
Ok(layout) if layout.align.abi.bytes() == 1 => {
14901490
// if the alignment is 1, the type can't be further
14911491
// disaligned.

Diff for: src/test/ui/consts/const-size_of-cycle.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`..
1515
LL | bytes: [u8; std::mem::size_of::<Foo>()]
1616
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
1717
= note: ...which requires computing layout of `Foo`...
18+
= note: ...which requires computing layout of `[u8; _]`...
1819
= note: ...which requires normalizing `[u8; _]`...
1920
= note: ...which again requires simplifying constant for the type system `Foo::bytes::{constant#0}`, completing the cycle
2021
note: cycle used when checking that `Foo` is well-formed

Diff for: src/test/ui/consts/issue-44415.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`..
1515
LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
1616
| ^^^^^^
1717
= note: ...which requires computing layout of `Foo`...
18+
= note: ...which requires computing layout of `[u8; _]`...
1819
= note: ...which requires normalizing `[u8; _]`...
1920
= note: ...which again requires simplifying constant for the type system `Foo::bytes::{constant#0}`, completing the cycle
2021
note: cycle used when checking that `Foo` is well-formed

Diff for: src/test/ui/recursion/issue-26548-recursion-via-normalize.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
//~ ERROR cycle detected when computing layout of
2-
//~| NOTE ...which requires computing layout of
3-
//~| NOTE ...which again requires computing layout of
1+
//~ ERROR cycle detected when computing layout of `S`
2+
//~| NOTE ...which requires computing layout of `std::option::Option<<S as Mirror>::It>`...
3+
//~| NOTE ...which requires computing layout of `std::option::Option<S>`...
4+
//~| NOTE ...which again requires computing layout of `S`, completing the cycle
5+
//~| NOTE cycle used when computing layout of `std::option::Option<S>`
46

57
// build-fail
68

@@ -13,6 +15,5 @@ impl<T: ?Sized> Mirror for T {
1315
struct S(Option<<S as Mirror>::It>);
1416

1517
fn main() {
16-
//~^ NOTE cycle used when optimizing MIR for `main`
1718
let _s = S(None);
1819
}

Diff for: src/test/ui/recursion/issue-26548-recursion-via-normalize.stderr

+5-8
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
1-
error[E0391]: cycle detected when computing layout of `std::option::Option<S>`
1+
error[E0391]: cycle detected when computing layout of `S`
22
|
3-
= note: ...which requires computing layout of `S`...
4-
= note: ...which again requires computing layout of `std::option::Option<S>`, completing the cycle
5-
note: cycle used when optimizing MIR for `main`
6-
--> $DIR/issue-26548-recursion-via-normalize.rs:15:1
7-
|
8-
LL | fn main() {
9-
| ^^^^^^^^^
3+
= note: ...which requires computing layout of `std::option::Option<<S as Mirror>::It>`...
4+
= note: ...which requires computing layout of `std::option::Option<S>`...
5+
= note: ...which again requires computing layout of `S`, completing the cycle
6+
= note: cycle used when computing layout of `std::option::Option<S>`
107

118
error: aborting due to previous error
129

0 commit comments

Comments
 (0)