Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Correct outdated object size limit #127546

Merged
merged 8 commits into from
Sep 21, 2024
Merged
Show file tree
Hide file tree
Changes from 7 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
10 changes: 4 additions & 6 deletions compiler/rustc_abi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,23 +337,21 @@ impl TargetDataLayout {
Ok(dl)
}

/// Returns exclusive upper bound on object size.
/// Returns **exclusive** upper bound on object size.
workingjubilee marked this conversation as resolved.
Show resolved Hide resolved
///
/// The theoretical maximum object size is defined as the maximum positive `isize` value.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not entirely sure what is even meant by "object". In general we are saying that "allocated objects" are limited by isize::MAX, and we do not publicly document anything else even for 64bit targets. So we do currently allow people to create heap allocations larger than obj_size_bound, and we rely on LLVM supporting that. It is only Rust types that can't be any bigger, and therefore static and let-bound variables and Box.

So either we should clarify the comment to say that this does not apply to all heap allocations, or we need to fix our docs.

@nikic will LLVM miscompile things if a heap allocation gets bigger than 2^61 bytes because that overflows u64 when counting in bits? Or does the 2^64 bits limit only apply to LLVM "typed objects"? Or is this too theoretical because nothing can be that big anyway? ;)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would only be a problem if it's a typed allocation/access, but I'm not particularly confident in that :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

anyone got a 64-bit address space computer lying around to find out?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not entirely sure what is even meant by "object".

Honestly I'm also not completely confident... I think allocation is what is meant?

I was pretty much just rolling with it because "we have a slightly wibbly definition of 'object' deep in the codegen backend" feels kinda low on our list of concerns. Relatively speaking.

/// This ensures that the `offset` semantics remain well-defined by allowing it to correctly
/// index every address within an object along with one byte past the end, along with allowing
/// `isize` to store the difference between any two pointers into an object.
///
/// The upper bound on 64-bit currently needs to be lower because LLVM uses a 64-bit integer
/// to represent object size in bits. It would need to be 1 << 61 to account for this, but is
/// currently conservatively bounded to 1 << 47 as that is enough to cover the current usable
/// address space on 64-bit ARMv8 and x86_64.
/// LLVM uses a 64-bit integer to represent object size in bits, but we care only for bytes,
workingjubilee marked this conversation as resolved.
Show resolved Hide resolved
/// so we adopt such a more-constrained address space due to its technical limitations.
workingjubilee marked this conversation as resolved.
Show resolved Hide resolved
#[inline]
pub fn obj_size_bound(&self) -> u64 {
match self.pointer_size.bits() {
16 => 1 << 15,
32 => 1 << 31,
64 => 1 << 47,
64 => 1 << 61,
bits => panic!("obj_size_bound: unknown pointer bit size {bits}"),
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ hir_analysis_tait_forward_compat2 = item does not constrain `{$opaque_type}`, bu

hir_analysis_target_feature_on_main = `main` function is not allowed to have `#[target_feature]`

hir_analysis_too_large_static = extern static is too large for the current architecture
hir_analysis_too_large_static = extern static is too large for the target architecture

hir_analysis_track_caller_on_main = `main` function is not allowed to be `#[track_caller]`
.suggestion = remove this annotation
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 @@ -95,7 +95,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
format!("{v} bits")
} else {
// `u128` should definitely be able to hold the size of different architectures
// larger sizes should be reported as error `are too big for the current architecture`
// larger sizes should be reported as error `are too big for the target architecture`
// otherwise we have a bug somewhere
bug!("{:?} overflow for u128", size)
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -103,5 +103,5 @@ middle_unknown_layout =
the type `{$ty}` has an unknown layout

middle_values_too_big =
values of the type `{$ty}` are too big for the current architecture
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}'
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
match *self {
LayoutError::Unknown(ty) => write!(f, "the type `{ty}` has an unknown layout"),
LayoutError::SizeOverflow(ty) => {
write!(f, "values of the type `{ty}` are too big for the current architecture")
write!(f, "values of the type `{ty}` are too big for the target architecture")
}
LayoutError::NormalizationFailure(t, e) => write!(
f,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2269,12 +2269,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
rustc_transmute::Reason::SrcSizeOverflow => {
format!(
"values of the type `{src}` are too big for the current architecture"
"values of the type `{src}` are too big for the target architecture"
)
}
rustc_transmute::Reason::DstSizeOverflow => {
format!(
"values of the type `{dst}` are too big for the current architecture"
"values of the type `{dst}` are too big for the target architecture"
)
}
rustc_transmute::Reason::DstHasStricterAlignment {
Expand Down
4 changes: 2 additions & 2 deletions src/tools/miri/tests/fail/type-too-large.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: post-monomorphization error: values of the type `[u8; 2305843011361177600]` are too big for the current architecture
error: post-monomorphization error: values of the type `[u8; 2305843011361177600]` are too big for the target architecture
--> tests/fail/type-too-large.rs:LL:CC
|
LL | _fat = [0; (1u64 << 61) as usize + (1u64 << 31) as usize];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ values of the type `[u8; 2305843011361177600]` are too big for the current architecture
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ values of the type `[u8; 2305843011361177600]` are too big for the target architecture
|
= note: BACKTRACE:
= note: inside `main` at tests/fail/type-too-large.rs:LL:CC
Expand Down
2 changes: 0 additions & 2 deletions src/tools/tidy/src/issues.txt
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,6 @@ ui/const-generics/infer/issue-77092.rs
ui/const-generics/issue-102124.rs
ui/const-generics/issue-105689.rs
ui/const-generics/issue-106419-struct-with-multiple-const-params.rs
ui/const-generics/issue-112505-overflow.rs
ui/const-generics/issue-46511.rs
ui/const-generics/issue-66451.rs
ui/const-generics/issue-70408.rs
Expand Down Expand Up @@ -2718,7 +2717,6 @@ ui/limits/issue-15919-32.rs
ui/limits/issue-15919-64.rs
ui/limits/issue-17913.rs
ui/limits/issue-55878.rs
ui/limits/issue-56762.rs
ui/limits/issue-69485-var-size-diffs-too-large.rs
ui/limits/issue-75158-64.rs
ui/linkage-attr/auxiliary/issue-12133-dylib.rs
Expand Down
2 changes: 1 addition & 1 deletion tests/crashes/125476.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//@ known-bug: rust-lang/rust#125476
//@ only-x86_64
pub struct Data([u8; usize::MAX >> 16]);
pub struct Data([u8; usize::MAX >> 2]);
const _: &'static [Data] = &[];
7 changes: 0 additions & 7 deletions tests/ui/const-generics/issue-112505-overflow.rs

This file was deleted.

12 changes: 0 additions & 12 deletions tests/ui/const-generics/issue-112505-overflow.stderr

This file was deleted.

10 changes: 10 additions & 0 deletions tests/ui/const-generics/transmute-fail.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
// ignore-tidy-linelength
//@ normalize-stderr-32bit: "values of the type `[^`]+` are too big" -> "values of the type $$REALLY_TOO_BIG are too big"
//@ normalize-stderr-64bit: "values of the type `[^`]+` are too big" -> "values of the type $$REALLY_TOO_BIG are too big"


#![feature(transmute_generic_consts)]
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]
Expand Down Expand Up @@ -31,6 +36,11 @@ fn overflow(v: [[[u32; 8888888]; 9999999]; 777777777]) -> [[[u32; 9999999]; 7777
}
}

fn overflow_more(v: [[[u32; 8888888]; 9999999]; 777777777]) -> [[[u32; 9999999]; 777777777]; 239] {
unsafe { std::mem::transmute(v) } //~ ERROR cannot transmute between types of different sizes
}


fn transpose<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] {
unsafe {
std::mem::transmute(v)
Expand Down
43 changes: 26 additions & 17 deletions tests/ui/const-generics/transmute-fail.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error: the constant `W` is not of type `usize`
--> $DIR/transmute-fail.rs:12:42
--> $DIR/transmute-fail.rs:17:42
|
LL | fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] {
| ^^^^^^^^^^^^^ expected `usize`, found `bool`

error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute-fail.rs:7:9
--> $DIR/transmute-fail.rs:12:9
|
LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^
Expand All @@ -14,13 +14,13 @@ LL | std::mem::transmute(v)
= note: target type: `[[u32; W + 1]; H]` (size can vary because of [u32; W + 1])

error: the constant `W` is not of type `usize`
--> $DIR/transmute-fail.rs:15:9
--> $DIR/transmute-fail.rs:20:9
|
LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool`

error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute-fail.rs:22:9
--> $DIR/transmute-fail.rs:27:9
|
LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^
Expand All @@ -29,16 +29,25 @@ LL | std::mem::transmute(v)
= note: target type: `[u32; W * H * H]` (this type does not have a fixed size)

error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute-fail.rs:29:9
--> $DIR/transmute-fail.rs:34:9
|
LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^
|
= note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[u32; 8888888]; 9999999]` are too big for the current architecture)
= note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture)
= note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type $REALLY_TOO_BIG are too big for the target architecture)
= note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type $REALLY_TOO_BIG are too big for the target architecture)

error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute-fail.rs:36:9
--> $DIR/transmute-fail.rs:40:14
|
LL | unsafe { std::mem::transmute(v) }
| ^^^^^^^^^^^^^^^^^^^
|
= note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type $REALLY_TOO_BIG are too big for the target architecture)
= note: target type: `[[[u32; 9999999]; 777777777]; 239]` (values of the type $REALLY_TOO_BIG are too big for the target architecture)

error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute-fail.rs:46:9
|
LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^
Expand All @@ -47,7 +56,7 @@ LL | std::mem::transmute(v)
= note: target type: `[[u32; W]; H]` (size can vary because of [u32; W])

error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute-fail.rs:47:9
--> $DIR/transmute-fail.rs:57:9
|
LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^
Expand All @@ -56,7 +65,7 @@ LL | std::mem::transmute(v)
= note: target type: `[u32; W * H]` (this type does not have a fixed size)

error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute-fail.rs:54:9
--> $DIR/transmute-fail.rs:64:9
|
LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^
Expand All @@ -65,7 +74,7 @@ LL | std::mem::transmute(v)
= note: target type: `[[u32; W]; H]` (size can vary because of [u32; W])

error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute-fail.rs:63:9
--> $DIR/transmute-fail.rs:73:9
|
LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^
Expand All @@ -74,7 +83,7 @@ LL | std::mem::transmute(v)
= note: target type: `[u32; D * W * H]` (this type does not have a fixed size)

error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute-fail.rs:72:9
--> $DIR/transmute-fail.rs:82:9
|
LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^
Expand All @@ -83,7 +92,7 @@ LL | std::mem::transmute(v)
= note: target type: `[[u32; D * W]; H]` (size can vary because of [u32; D * W])

error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute-fail.rs:79:9
--> $DIR/transmute-fail.rs:89:9
|
LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^
Expand All @@ -92,7 +101,7 @@ LL | std::mem::transmute(v)
= note: target type: `[u8; L * 2]` (this type does not have a fixed size)

error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute-fail.rs:86:9
--> $DIR/transmute-fail.rs:96:9
|
LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^
Expand All @@ -101,7 +110,7 @@ LL | std::mem::transmute(v)
= note: target type: `[u16; L]` (this type does not have a fixed size)

error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute-fail.rs:93:9
--> $DIR/transmute-fail.rs:103:9
|
LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^
Expand All @@ -110,14 +119,14 @@ LL | std::mem::transmute(v)
= note: target type: `[[u8; 1]; L]` (this type does not have a fixed size)

error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute-fail.rs:102:9
--> $DIR/transmute-fail.rs:112:9
|
LL | std::mem::transmute(v)
| ^^^^^^^^^^^^^^^^^^^
|
= note: source type: `[[u32; 2 * H]; W + W]` (size can vary because of [u32; 2 * H])
= note: target type: `[[u32; W + W]; 2 * H]` (size can vary because of [u32; W + W])

error: aborting due to 14 previous errors
error: aborting due to 15 previous errors

For more information about this error, try `rustc --explain E0512`.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

//@ compile-flags:-C debuginfo=2
//@ build-fail
//@ error-pattern: too big for the current architecture
//@ error-pattern: too big for the target architecture
//@ normalize-stderr-64bit: "18446744073709551615" -> "SIZE"
//@ normalize-stderr-32bit: "4294967295" -> "SIZE"

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: values of the type `[u8; usize::MAX]` are too big for the current architecture
error: values of the type `[u8; usize::MAX]` are too big for the target architecture

error: aborting due to 1 previous error

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

//@ compile-flags:-C debuginfo=2
//@ build-fail
//@ error-pattern: too big for the current architecture
//@ error-pattern: too big for the target architecture
//@ normalize-stderr-64bit: "18446744073709551615" -> "SIZE"
//@ normalize-stderr-32bit: "4294967295" -> "SIZE"

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: values of the type `[u8; usize::MAX]` are too big for the current architecture
error: values of the type `[u8; usize::MAX]` are too big for the target architecture

error: aborting due to 1 previous error

30 changes: 6 additions & 24 deletions tests/ui/extern/extern-static-size-overflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,13 @@ struct ReallyBig {
}

// The limit for "too big for the current architecture" is dependent on the target pointer size
// however it's artificially limited on 64 bits
// logic copied from rustc_target::abi::TargetDataLayout::obj_size_bound()
// but is artificially limited due to LLVM's internal architecture
// logic based on rustc_target::abi::TargetDataLayout::obj_size_bound()
const fn max_size() -> usize {
#[cfg(target_pointer_width = "16")]
{
1 << 15
}

#[cfg(target_pointer_width = "32")]
{
1 << 31
}

#[cfg(target_pointer_width = "64")]
{
1 << 47
}

#[cfg(not(any(
target_pointer_width = "16",
target_pointer_width = "32",
target_pointer_width = "64"
)))]
{
isize::MAX as usize
if usize::BITS < 61 {
1 << (usize::BITS - 1)
} else {
1 << 61
}
}

Expand Down
12 changes: 6 additions & 6 deletions tests/ui/extern/extern-static-size-overflow.stderr
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
error: extern static is too large for the current architecture
--> $DIR/extern-static-size-overflow.rs:38:5
error: extern static is too large for the target architecture
--> $DIR/extern-static-size-overflow.rs:20:5
|
LL | static BAZ: [u8; max_size()];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: extern static is too large for the current architecture
--> $DIR/extern-static-size-overflow.rs:39:5
error: extern static is too large for the target architecture
--> $DIR/extern-static-size-overflow.rs:21:5
|
LL | static UWU: [usize; usize::MAX];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: extern static is too large for the current architecture
--> $DIR/extern-static-size-overflow.rs:40:5
error: extern static is too large for the target architecture
--> $DIR/extern-static-size-overflow.rs:22:5
|
LL | static A: ReallyBig;
| ^^^^^^^^^^^^^^^^^^^
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/layout/size-of-val-raw-too-big.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//@ build-fail
//@ compile-flags: --crate-type lib
//@ only-32bit Layout computation rejects this layout for different reasons on 64-bit.
//@ error-pattern: too big for the current architecture
//@ error-pattern: too big for the target architecture
#![feature(core_intrinsics)]
#![allow(internal_features)]

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/layout/size-of-val-raw-too-big.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: values of the type `Example` are too big for the current architecture
error: values of the type `Example` are too big for the target architecture

error: aborting due to 1 previous error

Loading
Loading