Skip to content

Commit 8313bc5

Browse files
committed
Normalize param env and type argument of layout_of query before invoking the query
This allows us to have full control over whether `layout_of` may reveal hidden types
1 parent aad707d commit 8313bc5

File tree

12 files changed

+52
-37
lines changed

12 files changed

+52
-37
lines changed

compiler/rustc_middle/src/query/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1398,7 +1398,7 @@ rustc_queries! {
13981398

13991399
/// Computes the layout of a type. Note that this implicitly
14001400
/// executes in "reveal all" mode, and will normalize the input type.
1401-
query layout_of(
1401+
query layout_of_raw(
14021402
key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>
14031403
) -> Result<ty::layout::TyAndLayout<'tcx>, &'tcx ty::layout::LayoutError<'tcx>> {
14041404
depth_limit

compiler/rustc_middle/src/ty/layout.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,39 @@ pub trait LayoutOf<'tcx>: LayoutOfHelpers<'tcx> {
688688
}
689689
}
690690

691+
impl<'tcx> TyCtxt<'tcx> {
692+
pub fn layout_of(
693+
self,
694+
query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
695+
) -> Result<TyAndLayout<'tcx>, &'tcx LayoutError<'tcx>> {
696+
self.at(DUMMY_SP).layout_of(query)
697+
}
698+
}
699+
700+
impl<'tcx> TyCtxtAt<'tcx> {
701+
pub fn layout_of(
702+
self,
703+
query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
704+
) -> Result<TyAndLayout<'tcx>, &'tcx LayoutError<'tcx>> {
705+
let (param_env, ty) = query.into_parts();
706+
let param_env = param_env.with_reveal_all_normalized(self.tcx);
707+
708+
// FIXME: We might want to have two different versions of `layout_of`:
709+
// One that can be called after typecheck has completed and can use
710+
// `normalize_erasing_regions` here and another one that can be called
711+
// before typecheck has completed and uses `try_normalize_erasing_regions`.
712+
let ty = match self.try_normalize_erasing_regions(param_env, ty) {
713+
Ok(t) => t,
714+
Err(normalization_error) => {
715+
return Err(self
716+
.arena
717+
.alloc(LayoutError::NormalizationFailure(ty, normalization_error)));
718+
}
719+
};
720+
self.layout_of_raw(param_env.and(ty))
721+
}
722+
}
723+
691724
impl<'tcx, C: LayoutOfHelpers<'tcx>> LayoutOf<'tcx> for C {}
692725

693726
impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx, TyCtxt<'tcx>> {

compiler/rustc_query_system/src/query/job.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ impl QueryJobId {
174174
while let Some(id) = current_id {
175175
let info = query_map.get(&id).unwrap();
176176
// FIXME: This string comparison should probably not be done.
177-
if format!("{:?}", info.query.dep_kind) == "layout_of" {
177+
if format!("{:?}", info.query.dep_kind) == "layout_of_raw" {
178178
depth += 1;
179179
last_layout = Some((info.clone(), depth));
180180
}

compiler/rustc_ty_utils/src/layout.rs

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -24,38 +24,17 @@ use crate::errors::{
2424
use crate::layout_sanity_check::sanity_check_layout;
2525

2626
pub fn provide(providers: &mut Providers) {
27-
*providers = Providers { layout_of, ..*providers };
27+
*providers = Providers { layout_of_raw, ..*providers };
2828
}
2929

3030
#[instrument(skip(tcx, query), level = "debug")]
31-
fn layout_of<'tcx>(
31+
fn layout_of_raw<'tcx>(
3232
tcx: TyCtxt<'tcx>,
3333
query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
3434
) -> Result<TyAndLayout<'tcx>, &'tcx LayoutError<'tcx>> {
3535
let (param_env, ty) = query.into_parts();
3636
debug!(?ty);
3737

38-
let param_env = param_env.with_reveal_all_normalized(tcx);
39-
let unnormalized_ty = ty;
40-
41-
// FIXME: We might want to have two different versions of `layout_of`:
42-
// One that can be called after typecheck has completed and can use
43-
// `normalize_erasing_regions` here and another one that can be called
44-
// before typecheck has completed and uses `try_normalize_erasing_regions`.
45-
let ty = match tcx.try_normalize_erasing_regions(param_env, ty) {
46-
Ok(t) => t,
47-
Err(normalization_error) => {
48-
return Err(tcx
49-
.arena
50-
.alloc(LayoutError::NormalizationFailure(ty, normalization_error)));
51-
}
52-
};
53-
54-
if ty != unnormalized_ty {
55-
// Ensure this layout is also cached for the normalized type.
56-
return tcx.layout_of(param_env.and(ty));
57-
}
58-
5938
let cx = LayoutCx { tcx, param_env };
6039

6140
let layout = layout_of_uncached(&cx, ty)?;

tests/ui/consts/const-size_of-cycle.stderr

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ 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; std::mem::size_of::<Foo>()]`...
1918
= note: ...which requires normalizing `[u8; std::mem::size_of::<Foo>()]`...
2019
= note: ...which again requires evaluating type-level constant, completing the cycle
2120
note: cycle used when checking that `Foo` is well-formed

tests/ui/consts/issue-44415.stderr

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ 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; unsafe { intrinsics::size_of::<Foo>() }]`...
1918
= note: ...which requires normalizing `[u8; unsafe { intrinsics::size_of::<Foo>() }]`...
2019
= note: ...which again requires evaluating type-level constant, completing the cycle
2120
note: cycle used when checking that `Foo` is well-formed

tests/ui/layout/layout-cycle.stderr

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
error[E0391]: cycle detected when computing layout of `S<S<()>>`
22
|
3-
= note: ...which requires computing layout of `<S<()> as Tr>::I`...
4-
= note: ...which again requires computing layout of `S<S<()>>`, completing the cycle
3+
= note: ...which immediately requires computing layout of `S<S<()>>` again
54
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
65

76
error: failed to get layout for S<S<()>>: a cycle occurred during layout computation

tests/ui/layout/valid_range_oob.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
error: the compiler unexpectedly panicked. this is a bug.
33

44
query stack during panic:
5-
#0 [layout_of] computing layout of `Foo`
5+
#0 [layout_of_raw] computing layout of `Foo`
66
#1 [eval_to_allocation_raw] const-evaluating + checking `FOO`
77
end of query stack

tests/ui/recursion/issue-26548-recursion-via-normalize.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
//~ ERROR cycle detected when computing layout of `core::option::Option<S>`
22
//~| NOTE see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
33
//~| NOTE ...which requires computing layout of `S`...
4-
//~| NOTE ...which requires computing layout of `core::option::Option<<S as Mirror>::It>`...
54
//~| NOTE ...which again requires computing layout of `core::option::Option<S>`, completing the cycle
6-
//~| NOTE cycle used when computing layout of `core::option::Option<<S as Mirror>::It>`
75

86
trait Mirror {
7+
//~^ NOTE: cycle used when checking deathness of variables in top-level module
98
type It: ?Sized;
109
}
1110
impl<T: ?Sized> Mirror for T {

tests/ui/recursion/issue-26548-recursion-via-normalize.stderr

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
11
error[E0391]: cycle detected when computing layout of `core::option::Option<S>`
22
|
33
= note: ...which requires computing layout of `S`...
4-
= note: ...which requires computing layout of `core::option::Option<<S as Mirror>::It>`...
54
= note: ...which again requires computing layout of `core::option::Option<S>`, completing the cycle
6-
= note: cycle used when computing layout of `core::option::Option<<S as Mirror>::It>`
5+
note: cycle used when checking deathness of variables in top-level module
6+
--> $DIR/issue-26548-recursion-via-normalize.rs:6:1
7+
|
8+
LL | / trait Mirror {
9+
LL | |
10+
LL | | type It: ?Sized;
11+
LL | | }
12+
... |
13+
LL | | let _s = S(None);
14+
LL | | }
15+
| |_^
716
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
817

918
error: aborting due to previous error

tests/ui/sized/recursive-type-2.stderr

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
error[E0391]: cycle detected when computing layout of `Foo<()>`
22
|
3-
= note: ...which requires computing layout of `<() as A>::Assoc`...
4-
= note: ...which again requires computing layout of `Foo<()>`, completing the cycle
3+
= note: ...which immediately requires computing layout of `Foo<()>` again
54
note: cycle used when elaborating drops for `main`
65
--> $DIR/recursive-type-2.rs:11:1
76
|

tests/ui/type-alias-impl-trait/issue-53092-2.stderr

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ note: ...which requires type-checking `CONST_BUG`...
1414
|
1515
LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
1616
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
17-
= note: ...which requires computing layout of `Bug<u8, ()>`...
1817
= note: ...which requires normalizing `Bug<u8, ()>`...
1918
= note: ...which again requires computing type of `Bug::{opaque#0}`, completing the cycle
2019
note: cycle used when checking item types in top-level module

0 commit comments

Comments
 (0)