Skip to content

Commit

Permalink
Add TooGeneric variant to LayoutError and emit Unknown one
Browse files Browse the repository at this point in the history
- `check-pass` test for a MRE of rust-lang#135020
- fail test for rust-lang#135138
- switch to `TooGeneric` for checking CMSE fn signatures
- switch to `TooGeneric` for compute `SizeSkeleton` (for transmute)
- fix broken tests
  • Loading branch information
FedericoBruzzone committed Jan 13, 2025
1 parent 7a202a9 commit 4cdbbdf
Show file tree
Hide file tree
Showing 32 changed files with 216 additions and 63 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/const_eval/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ where
// Don't emit a new diagnostic for these errors, they are already reported elsewhere or
// should remain silent.
err_inval!(AlreadyReported(info)) => ErrorHandled::Reported(info, span),
err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => {
err_inval!(Layout(LayoutError::TooGeneric(_))) | err_inval!(TooGeneric) => {
ErrorHandled::TooGeneric(span)
}
err_inval!(Layout(LayoutError::ReferencesError(guar))) => {
Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ fn should_emit_generic_error<'tcx>(abi: ExternAbi, layout_err: &'tcx LayoutError
use LayoutError::*;

match layout_err {
Unknown(ty) => {
TooGeneric(ty) => {
match abi {
ExternAbi::CCmseNonSecureCall => {
// prevent double reporting of this error
Expand All @@ -211,7 +211,11 @@ fn should_emit_generic_error<'tcx>(abi: ExternAbi, layout_err: &'tcx LayoutError
_ => bug!("invalid ABI: {abi}"),
}
}
SizeOverflow(..) | NormalizationFailure(..) | ReferencesError(..) | Cycle(..) => {
Unknown(..)
| SizeOverflow(..)
| NormalizationFailure(..)
| ReferencesError(..)
| Cycle(..) => {
false // not our job to report these
}
}
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_middle/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,14 @@ 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
middle_too_generic = `{$ty}` is too generic to determine the layout
middle_type_length_limit = reached the type-length limit while instantiating `{$shrunk}`
middle_unknown_layout =
the type `{$ty}` has an unknown layout
middle_values_too_big =
values of the type `{$ty}` are too big for the target architecture
middle_written_to_path = the full type name has been written to '{$path}'
3 changes: 3 additions & 0 deletions compiler/rustc_middle/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ pub enum LayoutError<'tcx> {
#[diag(middle_unknown_layout)]
Unknown { ty: Ty<'tcx> },

#[diag(middle_too_generic)]
TooGeneric { ty: Ty<'tcx> },

#[diag(middle_values_too_big)]
Overflow { ty: Ty<'tcx> },

Expand Down
9 changes: 8 additions & 1 deletion compiler/rustc_middle/src/ty/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ impl fmt::Display for ValidityRequirement {
pub enum LayoutError<'tcx> {
Unknown(Ty<'tcx>),
SizeOverflow(Ty<'tcx>),
TooGeneric(Ty<'tcx>),
NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>),
ReferencesError(ErrorGuaranteed),
Cycle(ErrorGuaranteed),
Expand All @@ -244,6 +245,7 @@ impl<'tcx> LayoutError<'tcx> {
match self {
Unknown(_) => middle_unknown_layout,
SizeOverflow(_) => middle_values_too_big,
TooGeneric(_) => middle_too_generic,
NormalizationFailure(_, _) => middle_cannot_be_normalized,
Cycle(_) => middle_cycle,
ReferencesError(_) => middle_layout_references_error,
Expand All @@ -257,6 +259,7 @@ impl<'tcx> LayoutError<'tcx> {
match self {
Unknown(ty) => E::Unknown { ty },
SizeOverflow(ty) => E::Overflow { ty },
TooGeneric(ty) => E::TooGeneric { ty },
NormalizationFailure(ty, e) => {
E::NormalizationFailure { ty, failure_ty: e.get_type_for_failure() }
}
Expand All @@ -272,6 +275,9 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
LayoutError::Unknown(ty) => write!(f, "the type `{ty}` has an unknown layout"),
LayoutError::TooGeneric(ty) => {
write!(f, "`{ty}` is too generic to determine the layout")
}
LayoutError::SizeOverflow(ty) => {
write!(f, "values of the type `{ty}` are too big for the target architecture")
}
Expand Down Expand Up @@ -350,10 +356,11 @@ impl<'tcx> SizeSkeleton<'tcx> {
return Err(tcx.arena.alloc(LayoutError::Unknown(ty)));
}
}
Err(err @ LayoutError::Unknown(_)) => err,
Err(err @ LayoutError::TooGeneric(_)) => err,
// We can't extract SizeSkeleton info from other layout errors
Err(
e @ LayoutError::Cycle(_)
| e @ LayoutError::Unknown(_)
| e @ LayoutError::SizeOverflow(_)
| e @ LayoutError::NormalizationFailure(..)
| e @ LayoutError::ReferencesError(_),
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_transmute/src/layout/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ pub(crate) mod rustc {
match err {
LayoutError::Unknown(..)
| LayoutError::ReferencesError(..)
| LayoutError::TooGeneric(..)
| LayoutError::NormalizationFailure(..) => Self::UnknownLayout,
LayoutError::SizeOverflow(..) => Self::SizeOverflow,
LayoutError::Cycle(err) => Self::TypeError(*err),
Expand Down
15 changes: 11 additions & 4 deletions compiler/rustc_ty_utils/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ fn map_error<'tcx>(
// This is sometimes not a compile error if there are trivially false where clauses.
// See `tests/ui/layout/trivial-bounds-sized.rs` for an example.
assert!(field.layout.is_unsized(), "invalid layout error {err:#?}");
if !field.ty.is_sized(cx.tcx(), cx.typing_env) {
if cx.typing_env.param_env.caller_bounds().is_empty() {
cx.tcx().dcx().delayed_bug(format!(
"encountered unexpected unsized field in layout of {ty:?}: {field:#?}"
));
Expand Down Expand Up @@ -317,13 +317,13 @@ fn layout_of_uncached<'tcx>(
if count.has_aliases() {
count = tcx.normalize_erasing_regions(cx.typing_env, count);
if count.has_aliases() {
return Err(error(cx, LayoutError::Unknown(ty)));
return Err(error(cx, LayoutError::TooGeneric(ty)));
}
}

let count = count
.try_to_target_usize(tcx)
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
.ok_or_else(|| error(cx, LayoutError::TooGeneric(ty)))?;
let element = cx.layout_of(element)?;
let size = element
.size
Expand Down Expand Up @@ -679,6 +679,9 @@ fn layout_of_uncached<'tcx>(

// Types with no meaningful known layout.
ty::Alias(..) => {
if ty.has_param() {
return Err(error(cx, LayoutError::TooGeneric(ty)));
}
// NOTE(eddyb) `layout_of` query should've normalized these away,
// if that was possible, so there's no reason to try again here.
return Err(error(cx, LayoutError::Unknown(ty)));
Expand All @@ -688,7 +691,11 @@ fn layout_of_uncached<'tcx>(
bug!("Layout::compute: unexpected type `{}`", ty)
}

ty::Placeholder(..) | ty::Param(_) => {
ty::Param(_) => {
return Err(error(cx, LayoutError::TooGeneric(ty)));
}

ty::Placeholder(..) => {
return Err(error(cx, LayoutError::Unknown(ty)));
}
})
Expand Down
8 changes: 8 additions & 0 deletions src/librustdoc/html/templates/type_layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ <h2 id="layout" class="section-header"> {# #}
<strong>Note:</strong> Encountered an error during type layout; {#+ #}
the type was too big. {# #}
</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. #}
{% when Err(LayoutError::TooGeneric(_)) %}
<p> {# #}
<strong>Note:</strong> Encountered an error during type layout; {#+ #}
the type was too generic. {# #}
</p>
{% when Err(LayoutError::ReferencesError(_)) %}
<p> {# #}
<strong>Note:</strong> Encountered an error during type layout; {#+ #}
Expand Down
11 changes: 0 additions & 11 deletions tests/crashes/135020.rs

This file was deleted.

36 changes: 18 additions & 18 deletions tests/ui/const-generics/transmute_no_gate.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,80 +4,80 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^
|
= note: source type: `[[u32; H]; W]` (this type does not have a fixed size)
= note: target type: `[[u32; W]; H]` (this type does not have a fixed size)
= note: source type: `[[u32; H]; W]` (`[[u32; H]; W]` is too generic to determine the layout)
= note: target type: `[[u32; W]; H]` (`[[u32; W]; H]` is too generic to determine the layout)

error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute_no_gate.rs:20:5
|
LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^
|
= note: source type: `[[u32; H]; W]` (this type does not have a fixed size)
= note: target type: `[u32; W * H]` (this type does not have a fixed size)
= note: source type: `[[u32; H]; W]` (`[[u32; H]; W]` is too generic to determine the layout)
= note: target type: `[u32; W * H]` (`[u32; W * H]` is too generic to determine the layout)

error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute_no_gate.rs:27:5
|
LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^
|
= note: source type: `[u32; H*W]` (this type does not have a fixed size)
= note: target type: `[[u32; W]; H]` (this type does not have a fixed size)
= note: source type: `[u32; H*W]` (`[u32; H*W]` is too generic to determine the layout)
= note: target type: `[[u32; W]; H]` (`[[u32; W]; H]` is too generic to determine the layout)

error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute_no_gate.rs:36:5
|
LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^
|
= note: source type: `[[[u32; D]; H]; W]` (this type does not have a fixed size)
= note: target type: `[u32; D * W * H]` (this type does not have a fixed size)
= note: source type: `[[[u32; D]; H]; W]` (`[[[u32; D]; H]; W]` is too generic to determine the layout)
= note: target type: `[u32; D * W * H]` (`[u32; D * W * H]` is too generic to determine the layout)

error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute_no_gate.rs:45:5
|
LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^
|
= note: source type: `[[[u32; D]; H]; W]` (this type does not have a fixed size)
= note: target type: `[[u32; D * W]; H]` (this type does not have a fixed size)
= note: source type: `[[[u32; D]; H]; W]` (`[[[u32; D]; H]; W]` is too generic to determine the layout)
= note: target type: `[[u32; D * W]; H]` (`[[u32; D * W]; H]` is too generic to determine the layout)

error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute_no_gate.rs:52:5
|
LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^
|
= note: source type: `[u16; L]` (this type does not have a fixed size)
= note: target type: `[u8; L * 2]` (this type does not have a fixed size)
= note: source type: `[u16; L]` (`[u16; L]` is too generic to determine the layout)
= note: target type: `[u8; L * 2]` (`[u8; L * 2]` is too generic to determine the layout)

error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute_no_gate.rs:59:5
|
LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^
|
= note: source type: `[u8; L * 2]` (this type does not have a fixed size)
= note: target type: `[u16; L]` (this type does not have a fixed size)
= note: source type: `[u8; L * 2]` (`[u8; L * 2]` is too generic to determine the layout)
= note: target type: `[u16; L]` (`[u16; L]` is too generic to determine the layout)

error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute_no_gate.rs:66:5
|
LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^
|
= note: source type: `[u8; L]` (this type does not have a fixed size)
= note: target type: `[[u8; 1]; L]` (this type does not have a fixed size)
= note: source type: `[u8; L]` (`[u8; L]` is too generic to determine the layout)
= note: target type: `[[u8; 1]; L]` (`[[u8; 1]; L]` is too generic to determine the layout)

error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute_no_gate.rs:75:5
|
LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^
|
= note: source type: `[[u32; 2 * H]; W + W]` (this type does not have a fixed size)
= note: target type: `[[u32; W + W]; 2 * H]` (this type does not have a fixed size)
= note: source type: `[[u32; 2 * H]; W + W]` (`[[u32; 2 * H]; W + W]` is too generic to determine the layout)
= note: target type: `[[u32; W + W]; 2 * H]` (`[[u32; W + W]; 2 * H]` is too generic to determine the layout)

error: aborting due to 9 previous errors

Expand Down
4 changes: 2 additions & 2 deletions tests/ui/issues/issue-21174.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
LL | let new: T::B = unsafe { std::mem::transmute(value) };
| ^^^^^^^^^^^^^^^^^^^
|
= note: source type: `<T as Trait<'_>>::A` (this type does not have a fixed size)
= note: target type: `<T as Trait<'_>>::B` (this type does not have a fixed size)
= note: source type: `<T as Trait<'_>>::A` (`<T as Trait<'_>>::A` is too generic to determine the layout)
= note: target type: `<T as Trait<'_>>::B` (`<T as Trait<'_>>::B` is too generic to determine the layout)

error: aborting due to 1 previous error

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/layout/base-layout-is-sized-ice-123078.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ LL | const C: S = unsafe { std::mem::transmute(()) };
| ^^^^^^^^^^^^^^^^^^^
|
= note: source type: `()` (0 bits)
= note: target type: `S` (size can vary because of [u8])
= note: target type: `S` (this type does not have a fixed size)

error: aborting due to 2 previous errors

Expand Down
1 change: 1 addition & 0 deletions tests/ui/layout/invalid-unsized-const-eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ struct LazyLock {
}

static EMPTY_SET: LazyLock = todo!();
//~^ ERROR could not evaluate static initializer

fn main() {}
11 changes: 9 additions & 2 deletions tests/ui/layout/invalid-unsized-const-eval.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ LL | data: (dyn Sync, ()),
= help: the trait `Sized` is not implemented for `(dyn Sync + 'static)`
= note: only the last element of a tuple may have a dynamically sized type

error: aborting due to 1 previous error
error[E0080]: could not evaluate static initializer
--> $DIR/invalid-unsized-const-eval.rs:12:1
|
LL | static EMPTY_SET: LazyLock = todo!();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `(dyn Sync, ())` has an unknown layout

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0277`.
Some errors have detailed explanations: E0080, E0277.
For more information about an error, try `rustc --explain E0080`.
18 changes: 16 additions & 2 deletions tests/ui/layout/invalid-unsized-in-always-sized-tail.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,20 @@ LL | struct MySlice<T>(T);
| |
| this could be changed to `T: ?Sized`...

error: aborting due to 1 previous error
error[E0080]: could not evaluate static initializer
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
= note: the type `MySlice<[bool]>` has an unknown layout
|
note: inside `align_of::<P2>`
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
note: inside `CHECK`
--> $DIR/invalid-unsized-in-always-sized-tail.rs:15:28
|
LL | static CHECK: () = assert!(align_of::<P2>() == 1);
| ^^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0277`.
Some errors have detailed explanations: E0080, E0277.
For more information about an error, try `rustc --explain E0080`.
1 change: 1 addition & 0 deletions tests/ui/layout/issue-unsized-tail-restatic-ice-122488.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ struct ArenaSet<U: Deref, V: ?Sized = <U as Deref>::Target>(V, U);
//~^ ERROR the size for values of type `V` cannot be known at compilation time

const DATA: *const ArenaSet<Vec<u8>> = std::ptr::null_mut();
//~^ ERROR evaluation of constant value failed

pub fn main() {}
11 changes: 9 additions & 2 deletions tests/ui/layout/issue-unsized-tail-restatic-ice-122488.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ help: the `Box` type always has a statically known size and allocates its conten
LL | struct ArenaSet<U: Deref, V: ?Sized = <U as Deref>::Target>(Box<V>, U);
| ++++ +

error: aborting due to 1 previous error
error[E0080]: evaluation of constant value failed
--> $DIR/issue-unsized-tail-restatic-ice-122488.rs:8:1
|
LL | const DATA: *const ArenaSet<Vec<u8>> = std::ptr::null_mut();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `ArenaSet<Vec<u8>, [u8]>` has an unknown layout

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0277`.
Some errors have detailed explanations: E0080, E0277.
For more information about an error, try `rustc --explain E0080`.
11 changes: 11 additions & 0 deletions tests/ui/layout/uncomputable-due-to-trivial-bounds-ice-135138.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#![feature(trivial_bounds)]

fn return_str()
where
str: Sized,
{
[(); { let _a: Option<str> = None; 0 }];
//~^ ERROR evaluation of constant value failed
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0080]: evaluation of constant value failed
--> $DIR/uncomputable-due-to-trivial-bounds-ice-135138.rs:7:16
|
LL | [(); { let _a: Option<str> = None; 0 }];
| ^^ the type `Option<str>` has an unknown layout

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0080`.
Loading

0 comments on commit 4cdbbdf

Please sign in to comment.