diff options
| -rw-r--r-- | compiler/rustc_middle/messages.ftl | 3 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/layout.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/values.rs | 6 | ||||
| -rw-r--r-- | src/librustdoc/html/templates/type_layout.html | 93 | ||||
| -rw-r--r-- | src/tools/miri/tests/fail/layout_cycle.rs | 28 | ||||
| -rw-r--r-- | src/tools/miri/tests/fail/layout_cycle.stderr | 28 |
6 files changed, 119 insertions, 44 deletions
diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl index bd9d89deee1..c6bbf2ef0cd 100644 --- a/compiler/rustc_middle/messages.ftl +++ b/compiler/rustc_middle/messages.ftl @@ -32,6 +32,9 @@ middle_values_too_big = middle_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 = to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled .label = due to this attribute diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 6e6b7c39ecb..f2a2e67cf82 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -210,6 +210,7 @@ pub enum LayoutError<'tcx> { Unknown(Ty<'tcx>), SizeOverflow(Ty<'tcx>), NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>), + Cycle, } impl IntoDiagnostic<'_, !> for LayoutError<'_> { @@ -230,6 +231,9 @@ impl IntoDiagnostic<'_, !> for LayoutError<'_> { diag.set_arg("failure_ty", e.get_type_for_failure()); diag.set_primary_message(fluent::middle_cannot_be_normalized); } + LayoutError::Cycle => { + diag.set_primary_message(fluent::middle_cycle); + } } diag } @@ -250,6 +254,7 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> { t, e.get_type_for_failure() ), + LayoutError::Cycle => write!(f, "a cycle occurred during layout computation"), } } } diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index 5c38c0acc7f..c62c33d4dfc 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -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 // type in the next element in the list pub fn recursive_type_error( diff --git a/src/librustdoc/html/templates/type_layout.html b/src/librustdoc/html/templates/type_layout.html index 58b220c7428..20e09a54805 100644 --- a/src/librustdoc/html/templates/type_layout.html +++ b/src/librustdoc/html/templates/type_layout.html @@ -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> {# #} </h2> {# #} <div class="docblock"> {# #} {% match type_layout_size %} - {% when Ok(type_layout_size) %} - <div class="warning"> {# #} - <p> {# #} - <strong>Note:</strong> Most layout information is <strong>completely {#+ #} - unstable</strong> and may even differ between compilations. {#+ #} - The only exception is types with certain <code>repr(...)</code> {#+ #} - attributes. Please see the Rust Reference’s {#+ #} - <a href="https://doc.rust-lang.org/reference/type-layout.html">“Type Layout”</a> {#+ #} - chapter for details on type layout guarantees. {# #} - </p> {# #} - </div> {# #} - <p><strong>Size:</strong> {{ type_layout_size|safe }}</p> {# #} - {% if !variants.is_empty() %} - <p> {# #} - <strong>Size for each variant:</strong> {# #} - </p> {# #} - <ul> {# #} - {% for (name, layout_size) in variants %} - <li> {# #} - <code>{{ name }}</code>: {#+ #} - {{ layout_size|safe }} - </li> {# #} - {% endfor %} - </ul> {# #} - {% endif %} - {# 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>`. #} + {% when Ok(type_layout_size) %} + <div class="warning"> {# #} + <p> {# #} + <strong>Note:</strong> Most layout information is <strong>completely {#+ #} + unstable</strong> and may even differ between compilations. {#+ #} + The only exception is types with certain <code>repr(...)</code> {#+ #} + attributes. Please see the Rust Reference’s {#+ #} + <a href="https://doc.rust-lang.org/reference/type-layout.html">“Type Layout”</a> {#+ #} + chapter for details on type layout guarantees. {# #} + </p> {# #} + </div> {# #} + <p><strong>Size:</strong> {{ type_layout_size|safe }}</p> {# #} + {% if !variants.is_empty() %} + <p> {# #} + <strong>Size for each variant:</strong> {# #} + </p> {# #} + <ul> {# #} + {% for (name, layout_size) in variants %} + <li> {# #} + <code>{{ name }}</code>: {#+ #} + {{ layout_size|safe }} + </li> {# #} + {% endfor %} + </ul> {# #} + {% endif %} + {# 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>`. #} {% when Err(LayoutError::Unknown(_)) %} - <p> {# #} - <strong>Note:</strong> Unable to compute type layout, {#+ #} - possibly due to this type having generic parameters. {#+ #} - Layout can only be computed for concrete, fully-instantiated types. {# #} - </p> {# #} + <p> {# #} + <strong>Note:</strong> Unable to compute type layout, {#+ #} + possibly due to this type having generic parameters. {#+ #} + Layout can only be computed for concrete, fully-instantiated types. {# #} + </p> {# #} {# 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 - user know that we couldn't compute the layout. #} + want to panic and prevent the docs from building, so we just let the + user know that we couldn't compute the layout. #} {% when Err(LayoutError::SizeOverflow(_)) %} - <p> {# #} - <strong>Note:</strong> Encountered an error during type layout; {#+ #} - the type was too big. {# #} - </p> {# #} + <p> {# #} + <strong>Note:</strong> Encountered an error during type layout; {#+ #} + the type was too big. {# #} + </p> {# #} {% when Err(LayoutError::NormalizationFailure(_, _)) %} - <p> {# #} - <strong>Note:</strong> Encountered an error during type layout; {#+ #} - the type failed to be normalized. {# #} - </p> {# #} - {% endmatch %} + <p> {# #} + <strong>Note:</strong> Encountered an error during type layout; {#+ #} + the type failed to be normalized. {# #} + </p> {# #} + {% 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> {# #} diff --git a/src/tools/miri/tests/fail/layout_cycle.rs b/src/tools/miri/tests/fail/layout_cycle.rs new file mode 100644 index 00000000000..d050310bd80 --- /dev/null +++ b/src/tools/miri/tests/fail/layout_cycle.rs @@ -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<()>>()); +} diff --git a/src/tools/miri/tests/fail/layout_cycle.stderr b/src/tools/miri/tests/fail/layout_cycle.stderr new file mode 100644 index 00000000000..62b7d5fb77d --- /dev/null +++ b/src/tools/miri/tests/fail/layout_cycle.stderr @@ -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`. |
