Skip to content

Commit

Permalink
Unrolled build for rust-lang#135158
Browse files Browse the repository at this point in the history
Rollup merge of rust-lang#135158 - FedericoBruzzone:master, r=lukas-code

Add `TooGeneric` variant to `LayoutError` and emit `Unknown`

What's in this PR?

- Add `TooGeneric` variant to `LayoutError` and emit `Unknown` one

With this PR these issues and their respective ICEs are resolved:
- fixes rust-lang#135020
- fixes rust-lang#135138
  • Loading branch information
rust-timer authored Jan 27, 2025
2 parents 633a3fe + cef97bc commit 335743e
Show file tree
Hide file tree
Showing 29 changed files with 233 additions and 58 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
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/intrinsicck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
format!("generic size {size}")
}
}
Err(LayoutError::Unknown(bad)) => {
Err(LayoutError::TooGeneric(bad)) => {
if *bad == ty {
"this type does not have a fixed size".to_owned()
} else {
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
14 changes: 10 additions & 4 deletions 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 Expand Up @@ -413,10 +420,9 @@ impl<'tcx> SizeSkeleton<'tcx> {
// Alignment is unchanged by arrays.
return Ok(SizeSkeleton::Known(Size::from_bytes(size), a));
}
Err(tcx.arena.alloc(LayoutError::Unknown(ty)))
Err(err)
}
SizeSkeleton::Pointer { .. } => Err(err),
SizeSkeleton::Generic(_) => Err(tcx.arena.alloc(LayoutError::Unknown(ty))),
SizeSkeleton::Pointer { .. } | SizeSkeleton::Generic(_) => Err(err),
}
}

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
69 changes: 50 additions & 19 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 @@ -146,6 +144,35 @@ fn univariant_uninterned<'tcx>(
cx.calc.univariant(fields, repr, kind).map_err(|err| map_error(cx, ty, err))
}

fn validate_const_with_value<'tcx>(
const_: ty::Const<'tcx>,
ty: Ty<'tcx>,
cx: &LayoutCx<'tcx>,
) -> Result<ty::Const<'tcx>, &'tcx LayoutError<'tcx>> {
match const_.kind() {
ty::ConstKind::Value(..) => Ok(const_),
ty::ConstKind::Error(guar) => {
return Err(error(cx, LayoutError::ReferencesError(guar)));
}
ty::ConstKind::Param(_) | ty::ConstKind::Expr(_) => {
if !const_.has_param() {
bug!("no generic type found in the type: {ty:?}");
}
return Err(error(cx, LayoutError::TooGeneric(ty)));
}
ty::ConstKind::Unevaluated(_) => {
if !const_.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 type: {ty:?}");
}
}
}

fn layout_of_uncached<'tcx>(
cx: &LayoutCx<'tcx>,
ty: Ty<'tcx>,
Expand Down Expand Up @@ -182,12 +209,13 @@ fn layout_of_uncached<'tcx>(
&mut layout.backend_repr
{
if let Some(start) = start {
scalar.valid_range_mut().start = start
.try_to_bits(tcx, cx.typing_env)
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
scalar.valid_range_mut().start =
validate_const_with_value(start, ty, cx)?
.try_to_bits(tcx, cx.typing_env)
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
}
if let Some(end) = end {
let mut end = end
let mut end = validate_const_with_value(end, ty, cx)?
.try_to_bits(tcx, cx.typing_env)
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
if !include_end {
Expand Down Expand Up @@ -319,17 +347,13 @@ 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)));
}
}

let count = count
ty::Array(element, count) => {
let count = validate_const_with_value(count, ty, cx)?
.to_valtree()
.0
.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 +711,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 +723,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.

9 changes: 8 additions & 1 deletion tests/rustdoc/type-layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ 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 'Unable to compute type layout, possibly due to this type having generic parameters.'
//@ hasraw type_layout/struct.Generic.html 'Layout can only be computed for concrete, fully-instantiated types.'
//@ !hasraw - 'Size: '
pub struct Generic<T>(T);

Expand Down Expand Up @@ -91,3 +92,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;
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
1 change: 1 addition & 0 deletions tests/ui/layout/base-layout-is-sized-ice-123078.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ struct S {
}

const C: S = unsafe { std::mem::transmute(()) };
//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types
const _: [(); {
C;
0
Expand Down
14 changes: 12 additions & 2 deletions tests/ui/layout/base-layout-is-sized-ice-123078.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ help: the `Box` type always has a statically known size and allocates its conten
LL | a: Box<[u8]>,
| ++++ +

error: aborting due to 1 previous error
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/base-layout-is-sized-ice-123078.rs:10:23
|
LL | const C: S = unsafe { std::mem::transmute(()) };
| ^^^^^^^^^^^^^^^^^^^
|
= note: source type: `()` (0 bits)
= note: target type: `S` (the type `S` 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: E0277, E0512.
For more information about an error, try `rustc --explain E0277`.
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`.
Loading

0 comments on commit 335743e

Please sign in to comment.