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 17, 2025
1 parent 341f603 commit 997c3f4
Show file tree
Hide file tree
Showing 32 changed files with 243 additions and 79 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}` does not have a fixed size
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}` does not have a fixed size")
}
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
50 changes: 35 additions & 15 deletions compiler/rustc_ty_utils/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,12 @@ 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) {
let guar = cx.tcx().dcx().delayed_bug(format!(
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:#?}"
));
LayoutError::ReferencesError(guar)
} else {
LayoutError::Unknown(ty)
}
LayoutError::Unknown(ty)
}
LayoutCalculatorError::EmptyUnion => {
// This is always a compile error.
Expand Down Expand Up @@ -319,17 +317,32 @@ fn layout_of_uncached<'tcx>(
}

// Arrays and slices.
ty::Array(element, mut count) => {
if count.has_aliases() {
count = tcx.normalize_erasing_regions(cx.typing_env, count);
if count.has_aliases() {
return Err(error(cx, LayoutError::Unknown(ty)));
ty::Array(element, count) => {
let count = match count.kind() {
ty::ConstKind::Value(_, valtree) => valtree
.try_to_target_usize(tcx)
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?,
ty::ConstKind::Error(guar) => {
return Err(error(cx, LayoutError::ReferencesError(guar)));
}
}
ty::ConstKind::Param(_) | ty::ConstKind::Expr(_) => {
if !count.has_param() {
bug!("no generic type found in count of array type: {ty:?}");
}
return Err(error(cx, LayoutError::TooGeneric(ty)));
}
ty::ConstKind::Unevaluated(_) => {
if !count.has_param() {
return Err(error(cx, LayoutError::Unknown(ty)));
} else {
return Err(error(cx, LayoutError::TooGeneric(ty)));
}
}
ty::ConstKind::Infer(_)
| ty::ConstKind::Bound(..)
| ty::ConstKind::Placeholder(_) => bug!("unexpected count in array type: {ty:?}"),
};

let count = count
.try_to_target_usize(tcx)
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
let element = cx.layout_of(element)?;
let size = element
.size
Expand Down Expand Up @@ -687,6 +700,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 @@ -696,7 +712,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
16 changes: 11 additions & 5 deletions src/librustdoc/html/templates/type_layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,11 @@ <h2 id="layout" class="section-header"> {# #}
{% 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>`. #}
{# This kind of layout error can occur with valid code, for example
if there are trivial bounds: `struct Foo(str, str) where str: Sized;`. #}
{% 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. {# #}
<strong>Note:</strong> Unable to compute type layout. {# #}
</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
Expand All @@ -44,6 +42,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 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::TooGeneric(_)) %}
<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>
{% 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.

8 changes: 7 additions & 1 deletion tests/rustdoc/type-layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub struct Y(u8);
pub struct Z;

// We can't compute layout for generic types.
//@ hasraw type_layout/struct.Generic.html 'Unable to compute type layout, possibly due to this type having generic parameters'
//@ hasraw type_layout/struct.Generic.html 'Encountered an error during type layout; the type was too generic.'
//@ !hasraw - 'Size: '
pub struct Generic<T>(T);

Expand Down Expand Up @@ -91,3 +91,9 @@ pub enum Uninhabited {}
//@ hasraw type_layout/struct.Uninhabited2.html 'Size: '
//@ hasraw - '8 bytes (<a href="https://doc.rust-lang.org/stable/reference/glossary.html#uninhabited">uninhabited</a>)'
pub struct Uninhabited2(std::convert::Infallible, u64);

pub trait Project { type Assoc; }
// We can't compute layout. A `LayoutError::Unknown` is returned.
//@ hasraw type_layout/struct.Unknown.html 'Unable to compute type layout.'
//@ !hasraw - 'Size: '
pub struct Unknown(<() as Project>::Assoc) where for<'a> (): Project;
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]` does not have a fixed size)
= note: target type: `[[u32; W]; H]` (`[[u32; W]; H]` does not have a fixed size)

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]` does not have a fixed size)
= note: target type: `[u32; W * H]` (`[u32; W * H]` does not have a fixed size)

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]` does not have a fixed size)
= note: target type: `[[u32; W]; H]` (`[[u32; W]; H]` does not have a fixed size)

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]` does not have a fixed size)
= note: target type: `[u32; D * W * H]` (`[u32; D * W * H]` does not have a fixed size)

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]` does not have a fixed size)
= note: target type: `[[u32; D * W]; H]` (`[[u32; D * W]; H]` does not have a fixed size)

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]` does not have a fixed size)
= note: target type: `[u8; L * 2]` (`[u8; L * 2]` does not have a fixed size)

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]` does not have a fixed size)
= note: target type: `[u16; L]` (`[u16; L]` does not have a fixed size)

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]` does not have a fixed size)
= note: target type: `[[u8; 1]; L]` (`[[u8; 1]; L]` does not have a fixed size)

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]` does not have a fixed size)
= note: target type: `[[u32; W + W]; 2 * H]` (`[[u32; W + W]; 2 * H]` does not have a fixed size)

error: aborting due to 9 previous errors

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/enum-discriminant/eval-error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ union Foo {

enum Bar {
Boo = {
let _: Option<Foo> = None;
let _: Option<Foo> = None; //~ ERROR evaluation of constant value failed
0
},
}
Expand Down
12 changes: 9 additions & 3 deletions tests/ui/enum-discriminant/eval-error.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,13 @@ help: wrap the field type in `ManuallyDrop<...>`
LL | a: std::mem::ManuallyDrop<str>,
| +++++++++++++++++++++++ +

error: aborting due to 4 previous errors
error[E0080]: evaluation of constant value failed
--> $DIR/eval-error.rs:9:30
|
LL | let _: Option<Foo> = None;
| ^^^^ the type `Foo` has an unknown layout

error: aborting due to 5 previous errors

Some errors have detailed explanations: E0277, E0517, E0740.
For more information about an error, try `rustc --explain E0277`.
Some errors have detailed explanations: E0080, E0277, E0517, E0740.
For more information about an error, try `rustc --explain E0080`.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ impl<T, const L: u8> VirtualWrapper<T, L> {
impl<T: MyTrait + 'static, const L: u8> MyTrait for VirtualWrapper<T, L> {
fn virtualize(&self) -> &dyn MyTrait {
unsafe { virtualize_my_trait(L, self) }
// unsafe { virtualize_my_trait(L, &self.0) } // <-- this code fixes the problem
// unsafe { virtualize_my_trait(L, &self.0) } // <-- this code fixes the problem
}
}

Expand Down
Loading

0 comments on commit 997c3f4

Please sign in to comment.