Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion compiler/rustc_ty_utils/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,18 @@ fn layout_of_uncached<'tcx>(
}

if pointee.is_sized(tcx, cx.typing_env) {
return Ok(tcx.mk_layout(LayoutData::scalar(cx, data_ptr)));
// Guard against bogus `impl Sized` declarations (e.g.,
// `impl<T: ?Sized> Sized for T {}`), which are rejected with E0322
// but can still be processed by the trait solver in erroneous code.
// Such impls can make DSTs like `[T]`, `str`, and `dyn Trait` appear
// sized, causing pointer layout to be incorrectly computed as a thin
// pointer (Scalar) instead of a fat pointer (ScalarPair). We guard
// against this by checking the type kind directly (O(1), no recursion).
if !matches!(pointee.kind(), ty::Slice(_) | ty::Str | ty::Dynamic(..)) {
return Ok(tcx.mk_layout(LayoutData::scalar(cx, data_ptr)));
}
// The pointee is structurally a DST — `is_sized` is unreliable here.
// Fall through to compute the correct fat-pointer layout below.
}

let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//@ compile-flags: -Znext-solver=globally

// A bogus `impl Sized for T` (rejected with E0322) used to cause an ICE when
// the new trait solver processed it and made DSTs like `[T]` appear sized. This
// caused pointer layout to be computed as a thin-pointer (Scalar) instead of a
// fat-pointer (ScalarPair), and const evaluation of unsafe pointer arithmetic
// inside a `const {}` block would then ICE with:
// "invalid immediate for given destination place: value ScalarPair(...) does
// not match ABI Scalar(...)"

impl<'a, T: ?Sized> Sized for T {}
//~^ ERROR explicit impls for the `Sized` trait are not permitted
//~| ERROR type parameter `T` must be used as the type parameter for some local type

fn main() {
const {
unsafe {
let value = [1, 2];
let _ptr = value.as_ptr().add(2);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
error[E0322]: explicit impls for the `Sized` trait are not permitted
--> $DIR/dont-ice-on-bogus-sized-impl-in-const-block.rs:11:1
|
LL | impl<'a, T: ?Sized> Sized for T {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `Sized` not allowed

error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
--> $DIR/dont-ice-on-bogus-sized-impl-in-const-block.rs:11:10
|
LL | impl<'a, T: ?Sized> Sized for T {}
| ^ type parameter `T` must be used as the type parameter for some local type
|
= note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0210, E0322.
For more information about an error, try `rustc --explain E0210`.
Loading