Skip to content

Commit 7bc6d59

Browse files
committed
Avoid ICEing miri on layout query cycles
1 parent 7b99493 commit 7bc6d59

File tree

6 files changed

+119
-44
lines changed

6 files changed

+119
-44
lines changed

compiler/rustc_middle/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ middle_values_too_big =
3232
middle_cannot_be_normalized =
3333
unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized
3434
35+
middle_cycle =
36+
a cycle occurred during layout computation
37+
3538
middle_strict_coherence_needs_negative_coherence =
3639
to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled
3740
.label = due to this attribute

compiler/rustc_middle/src/ty/layout.rs

+5
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ pub enum LayoutError<'tcx> {
210210
Unknown(Ty<'tcx>),
211211
SizeOverflow(Ty<'tcx>),
212212
NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>),
213+
Cycle,
213214
}
214215

215216
impl IntoDiagnostic<'_, !> for LayoutError<'_> {
@@ -230,6 +231,9 @@ impl IntoDiagnostic<'_, !> for LayoutError<'_> {
230231
diag.set_arg("failure_ty", e.get_type_for_failure());
231232
diag.set_primary_message(fluent::middle_cannot_be_normalized);
232233
}
234+
LayoutError::Cycle => {
235+
diag.set_primary_message(fluent::middle_cycle);
236+
}
233237
}
234238
diag
235239
}
@@ -250,6 +254,7 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
250254
t,
251255
e.get_type_for_failure()
252256
),
257+
LayoutError::Cycle => write!(f, "a cycle occurred during layout computation"),
253258
}
254259
}
255260
}

compiler/rustc_middle/src/values.rs

+6
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,12 @@ impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::EarlyBinder<ty::Binder<'_, ty::F
106106
}
107107
}
108108

109+
impl<'tcx, T> Value<TyCtxt<'tcx>, DepKind> for Result<T, ty::layout::LayoutError<'_>> {
110+
fn from_cycle_error(_tcx: TyCtxt<'tcx>, _cycle: &[QueryInfo<DepKind>]) -> Self {
111+
Err(ty::layout::LayoutError::Cycle)
112+
}
113+
}
114+
109115
// item_and_field_ids should form a cycle where each field contains the
110116
// type in the next element in the list
111117
pub fn recursive_type_error(
+49-44
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,58 @@
1-
<h2 id="layout" class="small-section-header"> {# #}
1+
<h2 id="layout" class="small-section-header"> {# #}
22
Layout<a href="#layout" class="anchor">§</a> {# #}
33
</h2> {# #}
44
<div class="docblock"> {# #}
55
{% match type_layout_size %}
6-
{% when Ok(type_layout_size) %}
7-
<div class="warning"> {# #}
8-
<p> {# #}
9-
<strong>Note:</strong> Most layout information is <strong>completely {#+ #}
10-
unstable</strong> and may even differ between compilations. {#+ #}
11-
The only exception is types with certain <code>repr(...)</code> {#+ #}
12-
attributes. Please see the Rust Reference’s {#+ #}
13-
<a href="https://doc.rust-lang.org/reference/type-layout.html">“Type Layout”</a> {#+ #}
14-
chapter for details on type layout guarantees. {# #}
15-
</p> {# #}
16-
</div> {# #}
17-
<p><strong>Size:</strong> {{ type_layout_size|safe }}</p> {# #}
18-
{% if !variants.is_empty() %}
19-
<p> {# #}
20-
<strong>Size for each variant:</strong> {# #}
21-
</p> {# #}
22-
<ul> {# #}
23-
{% for (name, layout_size) in variants %}
24-
<li> {# #}
25-
<code>{{ name }}</code>: {#+ #}
26-
{{ layout_size|safe }}
27-
</li> {# #}
28-
{% endfor %}
29-
</ul> {# #}
30-
{% endif %}
31-
{# This kind of layout error can occur with valid code, e.g. if you try to
32-
get the layout of a generic type such as `Vec<T>`. #}
6+
{% when Ok(type_layout_size) %}
7+
<div class="warning"> {# #}
8+
<p> {# #}
9+
<strong>Note:</strong> Most layout information is <strong>completely {#+ #}
10+
unstable</strong> and may even differ between compilations. {#+ #}
11+
The only exception is types with certain <code>repr(...)</code> {#+ #}
12+
attributes. Please see the Rust Reference’s {#+ #}
13+
<a href="https://doc.rust-lang.org/reference/type-layout.html">“Type Layout”</a> {#+ #}
14+
chapter for details on type layout guarantees. {# #}
15+
</p> {# #}
16+
</div> {# #}
17+
<p><strong>Size:</strong> {{ type_layout_size|safe }}</p> {# #}
18+
{% if !variants.is_empty() %}
19+
<p> {# #}
20+
<strong>Size for each variant:</strong> {# #}
21+
</p> {# #}
22+
<ul> {# #}
23+
{% for (name, layout_size) in variants %}
24+
<li> {# #}
25+
<code>{{ name }}</code>: {#+ #}
26+
{{ layout_size|safe }}
27+
</li> {# #}
28+
{% endfor %}
29+
</ul> {# #}
30+
{% endif %}
31+
{# This kind of layout error can occur with valid code, e.g. if you try to
32+
get the layout of a generic type such as `Vec<T>`. #}
3333
{% when Err(LayoutError::Unknown(_)) %}
34-
<p> {# #}
35-
<strong>Note:</strong> Unable to compute type layout, {#+ #}
36-
possibly due to this type having generic parameters. {#+ #}
37-
Layout can only be computed for concrete, fully-instantiated types. {# #}
38-
</p> {# #}
34+
<p> {# #}
35+
<strong>Note:</strong> Unable to compute type layout, {#+ #}
36+
possibly due to this type having generic parameters. {#+ #}
37+
Layout can only be computed for concrete, fully-instantiated types. {# #}
38+
</p> {# #}
3939
{# This kind of error probably can't happen with valid code, but we don't
40-
want to panic and prevent the docs from building, so we just let the
41-
user know that we couldn't compute the layout. #}
40+
want to panic and prevent the docs from building, so we just let the
41+
user know that we couldn't compute the layout. #}
4242
{% when Err(LayoutError::SizeOverflow(_)) %}
43-
<p> {# #}
44-
<strong>Note:</strong> Encountered an error during type layout; {#+ #}
45-
the type was too big. {# #}
46-
</p> {# #}
43+
<p> {# #}
44+
<strong>Note:</strong> Encountered an error during type layout; {#+ #}
45+
the type was too big. {# #}
46+
</p> {# #}
4747
{% when Err(LayoutError::NormalizationFailure(_, _)) %}
48-
<p> {# #}
49-
<strong>Note:</strong> Encountered an error during type layout; {#+ #}
50-
the type failed to be normalized. {# #}
51-
</p> {# #}
52-
{% endmatch %}
48+
<p> {# #}
49+
<strong>Note:</strong> Encountered an error during type layout; {#+ #}
50+
the type failed to be normalized. {# #}
51+
</p> {# #}
52+
{% when Err(LayoutError::Cycle) %}
53+
<p> {# #}
54+
<strong>Note:</strong> Encountered an error during type layout; {#+ #}
55+
the type's layout depended on the type's layout itself. {# #}
56+
</p> {# #}
57+
{% endmatch %}
5358
</div> {# #}
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//@error-pattern: a cycle occurred during layout computation
2+
//~^ ERROR: cycle detected when computing layout of
3+
4+
use std::mem;
5+
6+
pub struct S<T: Tr> {
7+
pub f: <T as Tr>::I,
8+
}
9+
10+
pub trait Tr {
11+
type I: Tr;
12+
}
13+
14+
impl<T: Tr> Tr for S<T> {
15+
type I = S<S<T>>;
16+
}
17+
18+
impl Tr for () {
19+
type I = ();
20+
}
21+
22+
fn foo<T: Tr>() -> usize {
23+
mem::size_of::<S<T>>()
24+
}
25+
26+
fn main() {
27+
println!("{}", foo::<S<()>>());
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
error[E0391]: cycle detected when computing layout of `S<S<()>>`
2+
|
3+
= note: ...which requires computing layout of `<S<()> as Tr>::I`...
4+
= note: ...which again requires computing layout of `S<S<()>>`, completing the cycle
5+
6+
error: post-monomorphization error: a cycle occurred during layout computation
7+
--> RUSTLIB/core/src/mem/mod.rs:LL:CC
8+
|
9+
LL | intrinsics::size_of::<T>()
10+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ a cycle occurred during layout computation
11+
|
12+
= note: inside `std::mem::size_of::<S<S<()>>>` at RUSTLIB/core/src/mem/mod.rs:LL:CC
13+
note: inside `foo::<S<()>>`
14+
--> $DIR/layout_cycle.rs:LL:CC
15+
|
16+
LL | mem::size_of::<S<T>>()
17+
| ^^^^^^^^^^^^^^^^^^^^^^
18+
note: inside `main`
19+
--> $DIR/layout_cycle.rs:LL:CC
20+
|
21+
LL | println!("{}", foo::<S<()>>());
22+
| ^^^^^^^^^^^^^^
23+
24+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
25+
26+
error: aborting due to 2 previous errors
27+
28+
For more information about this error, try `rustc --explain E0391`.

0 commit comments

Comments
 (0)