mirror of https://github.com/rust-lang/rust.git
Avoid ICEing miri on layout query cycles
This commit is contained in:
parent
7b99493492
commit
7bc6d598f9
|
@ -32,6 +32,9 @@ middle_values_too_big =
|
||||||
middle_cannot_be_normalized =
|
middle_cannot_be_normalized =
|
||||||
unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized
|
unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized
|
||||||
|
|
||||||
|
middle_cycle =
|
||||||
|
a cycle occurred during layout computation
|
||||||
|
|
||||||
middle_strict_coherence_needs_negative_coherence =
|
middle_strict_coherence_needs_negative_coherence =
|
||||||
to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled
|
to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled
|
||||||
.label = due to this attribute
|
.label = due to this attribute
|
||||||
|
|
|
@ -210,6 +210,7 @@ pub enum LayoutError<'tcx> {
|
||||||
Unknown(Ty<'tcx>),
|
Unknown(Ty<'tcx>),
|
||||||
SizeOverflow(Ty<'tcx>),
|
SizeOverflow(Ty<'tcx>),
|
||||||
NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>),
|
NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>),
|
||||||
|
Cycle,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoDiagnostic<'_, !> for LayoutError<'_> {
|
impl IntoDiagnostic<'_, !> for LayoutError<'_> {
|
||||||
|
@ -230,6 +231,9 @@ impl IntoDiagnostic<'_, !> for LayoutError<'_> {
|
||||||
diag.set_arg("failure_ty", e.get_type_for_failure());
|
diag.set_arg("failure_ty", e.get_type_for_failure());
|
||||||
diag.set_primary_message(fluent::middle_cannot_be_normalized);
|
diag.set_primary_message(fluent::middle_cannot_be_normalized);
|
||||||
}
|
}
|
||||||
|
LayoutError::Cycle => {
|
||||||
|
diag.set_primary_message(fluent::middle_cycle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
diag
|
diag
|
||||||
}
|
}
|
||||||
|
@ -250,6 +254,7 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
|
||||||
t,
|
t,
|
||||||
e.get_type_for_failure()
|
e.get_type_for_failure()
|
||||||
),
|
),
|
||||||
|
LayoutError::Cycle => write!(f, "a cycle occurred during layout computation"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,6 +106,12 @@ impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::EarlyBinder<ty::Binder<'_, ty::F
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx, T> Value<TyCtxt<'tcx>, DepKind> for Result<T, ty::layout::LayoutError<'_>> {
|
||||||
|
fn from_cycle_error(_tcx: TyCtxt<'tcx>, _cycle: &[QueryInfo<DepKind>]) -> Self {
|
||||||
|
Err(ty::layout::LayoutError::Cycle)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// item_and_field_ids should form a cycle where each field contains the
|
// item_and_field_ids should form a cycle where each field contains the
|
||||||
// type in the next element in the list
|
// type in the next element in the list
|
||||||
pub fn recursive_type_error(
|
pub fn recursive_type_error(
|
||||||
|
|
|
@ -1,53 +1,58 @@
|
||||||
<h2 id="layout" class="small-section-header"> {# #}
|
<h2 id="layout" class="small-section-header"> {# #}
|
||||||
Layout<a href="#layout" class="anchor">§</a> {# #}
|
Layout<a href="#layout" class="anchor">§</a> {# #}
|
||||||
</h2> {# #}
|
</h2> {# #}
|
||||||
<div class="docblock"> {# #}
|
<div class="docblock"> {# #}
|
||||||
{% match type_layout_size %}
|
{% match type_layout_size %}
|
||||||
{% when Ok(type_layout_size) %}
|
{% when Ok(type_layout_size) %}
|
||||||
<div class="warning"> {# #}
|
<div class="warning"> {# #}
|
||||||
<p> {# #}
|
<p> {# #}
|
||||||
<strong>Note:</strong> Most layout information is <strong>completely {#+ #}
|
<strong>Note:</strong> Most layout information is <strong>completely {#+ #}
|
||||||
unstable</strong> and may even differ between compilations. {#+ #}
|
unstable</strong> and may even differ between compilations. {#+ #}
|
||||||
The only exception is types with certain <code>repr(...)</code> {#+ #}
|
The only exception is types with certain <code>repr(...)</code> {#+ #}
|
||||||
attributes. Please see the Rust Reference’s {#+ #}
|
attributes. Please see the Rust Reference’s {#+ #}
|
||||||
<a href="https://doc.rust-lang.org/reference/type-layout.html">“Type Layout”</a> {#+ #}
|
<a href="https://doc.rust-lang.org/reference/type-layout.html">“Type Layout”</a> {#+ #}
|
||||||
chapter for details on type layout guarantees. {# #}
|
chapter for details on type layout guarantees. {# #}
|
||||||
</p> {# #}
|
</p> {# #}
|
||||||
</div> {# #}
|
</div> {# #}
|
||||||
<p><strong>Size:</strong> {{ type_layout_size|safe }}</p> {# #}
|
<p><strong>Size:</strong> {{ type_layout_size|safe }}</p> {# #}
|
||||||
{% if !variants.is_empty() %}
|
{% if !variants.is_empty() %}
|
||||||
<p> {# #}
|
<p> {# #}
|
||||||
<strong>Size for each variant:</strong> {# #}
|
<strong>Size for each variant:</strong> {# #}
|
||||||
</p> {# #}
|
</p> {# #}
|
||||||
<ul> {# #}
|
<ul> {# #}
|
||||||
{% for (name, layout_size) in variants %}
|
{% for (name, layout_size) in variants %}
|
||||||
<li> {# #}
|
<li> {# #}
|
||||||
<code>{{ name }}</code>: {#+ #}
|
<code>{{ name }}</code>: {#+ #}
|
||||||
{{ layout_size|safe }}
|
{{ layout_size|safe }}
|
||||||
</li> {# #}
|
</li> {# #}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul> {# #}
|
</ul> {# #}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{# This kind of layout error can occur with valid code, e.g. if you try to
|
{# This kind of layout error can occur with valid code, e.g. if you try to
|
||||||
get the layout of a generic type such as `Vec<T>`. #}
|
get the layout of a generic type such as `Vec<T>`. #}
|
||||||
{% when Err(LayoutError::Unknown(_)) %}
|
{% when Err(LayoutError::Unknown(_)) %}
|
||||||
<p> {# #}
|
<p> {# #}
|
||||||
<strong>Note:</strong> Unable to compute type layout, {#+ #}
|
<strong>Note:</strong> Unable to compute type layout, {#+ #}
|
||||||
possibly due to this type having generic parameters. {#+ #}
|
possibly due to this type having generic parameters. {#+ #}
|
||||||
Layout can only be computed for concrete, fully-instantiated types. {# #}
|
Layout can only be computed for concrete, fully-instantiated types. {# #}
|
||||||
</p> {# #}
|
</p> {# #}
|
||||||
{# This kind of error probably can't happen with valid code, but we don't
|
{# This kind of error probably can't happen with valid code, but we don't
|
||||||
want to panic and prevent the docs from building, so we just let the
|
want to panic and prevent the docs from building, so we just let the
|
||||||
user know that we couldn't compute the layout. #}
|
user know that we couldn't compute the layout. #}
|
||||||
{% when Err(LayoutError::SizeOverflow(_)) %}
|
{% when Err(LayoutError::SizeOverflow(_)) %}
|
||||||
<p> {# #}
|
<p> {# #}
|
||||||
<strong>Note:</strong> Encountered an error during type layout; {#+ #}
|
<strong>Note:</strong> Encountered an error during type layout; {#+ #}
|
||||||
the type was too big. {# #}
|
the type was too big. {# #}
|
||||||
</p> {# #}
|
</p> {# #}
|
||||||
{% when Err(LayoutError::NormalizationFailure(_, _)) %}
|
{% when Err(LayoutError::NormalizationFailure(_, _)) %}
|
||||||
<p> {# #}
|
<p> {# #}
|
||||||
<strong>Note:</strong> Encountered an error during type layout; {#+ #}
|
<strong>Note:</strong> Encountered an error during type layout; {#+ #}
|
||||||
the type failed to be normalized. {# #}
|
the type failed to be normalized. {# #}
|
||||||
</p> {# #}
|
</p> {# #}
|
||||||
{% endmatch %}
|
{% when Err(LayoutError::Cycle) %}
|
||||||
|
<p> {# #}
|
||||||
|
<strong>Note:</strong> Encountered an error during type layout; {#+ #}
|
||||||
|
the type's layout depended on the type's layout itself. {# #}
|
||||||
|
</p> {# #}
|
||||||
|
{% endmatch %}
|
||||||
</div> {# #}
|
</div> {# #}
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
//@error-pattern: a cycle occurred during layout computation
|
||||||
|
//~^ ERROR: cycle detected when computing layout of
|
||||||
|
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
|
pub struct S<T: Tr> {
|
||||||
|
pub f: <T as Tr>::I,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Tr {
|
||||||
|
type I: Tr;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Tr> Tr for S<T> {
|
||||||
|
type I = S<S<T>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Tr for () {
|
||||||
|
type I = ();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo<T: Tr>() -> usize {
|
||||||
|
mem::size_of::<S<T>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("{}", foo::<S<()>>());
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
error[E0391]: cycle detected when computing layout of `S<S<()>>`
|
||||||
|
|
|
||||||
|
= note: ...which requires computing layout of `<S<()> as Tr>::I`...
|
||||||
|
= note: ...which again requires computing layout of `S<S<()>>`, completing the cycle
|
||||||
|
|
||||||
|
error: post-monomorphization error: a cycle occurred during layout computation
|
||||||
|
--> RUSTLIB/core/src/mem/mod.rs:LL:CC
|
||||||
|
|
|
||||||
|
LL | intrinsics::size_of::<T>()
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ a cycle occurred during layout computation
|
||||||
|
|
|
||||||
|
= note: inside `std::mem::size_of::<S<S<()>>>` at RUSTLIB/core/src/mem/mod.rs:LL:CC
|
||||||
|
note: inside `foo::<S<()>>`
|
||||||
|
--> $DIR/layout_cycle.rs:LL:CC
|
||||||
|
|
|
||||||
|
LL | mem::size_of::<S<T>>()
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
note: inside `main`
|
||||||
|
--> $DIR/layout_cycle.rs:LL:CC
|
||||||
|
|
|
||||||
|
LL | println!("{}", foo::<S<()>>());
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0391`.
|
Loading…
Reference in New Issue