Rollup merge of #111665 - est31:offset_of_tests, r=WaffleLapkin

Add more tests for the offset_of macro

Implements what I [suggested in the tracking issue](https://github.com/rust-lang/rust/issues/106655#issuecomment-1535007205), plus some further improvements:

* ensuring that offset_of!(Self, ...) works iff inside an impl block
* ensuring that the output type is usize and doesn't coerce. this can be changed in the future, but if it is done, it should be a conscious decision
* improving the privacy checking test
* ensuring that generics don't let you escape the unsized check

r? `````@WaffleLapkin`````
This commit is contained in:
Dylan DPC 2023-05-20 12:21:00 +05:30 committed by GitHub
commit e892e32df4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 345 additions and 7 deletions

View File

@ -386,6 +386,21 @@ fn offset_of() {
// Layout of tuples is unstable
assert!(offset_of!((u8, u16), 0) <= size_of::<(u8, u16)>() - 1);
assert!(offset_of!((u8, u16), 1) <= size_of::<(u8, u16)>() - 2);
#[repr(C)]
struct Generic<T> {
x: u8,
y: u32,
z: T
}
// Ensure that this type of generics works
fn offs_of_z<T>() -> usize {
offset_of!(Generic<T>, z)
}
assert_eq!(offset_of!(Generic<u8>, z), 8);
assert_eq!(offs_of_z::<u8>(), 8);
}
#[test]

View File

@ -26,8 +26,23 @@ struct Gamma {
z: Extern,
}
struct Delta<T: ?Sized> {
x: u8,
y: u16,
z: T,
}
fn main() {
offset_of!(Alpha, z); //~ ERROR the size for values of type
offset_of!(Beta, z); //~ ERROR the size for values of type
offset_of!(Gamma, z); //~ ERROR the size for values of type
}
fn delta() {
offset_of!(Delta<Alpha>, z); //~ ERROR the size for values of type
offset_of!(Delta<Extern>, z); //~ ERROR the size for values of type
}
fn generic_with_maybe_sized<T: ?Sized>() -> usize {
offset_of!(Delta<T>, z) //~ ERROR the size for values of type
}

View File

@ -1,5 +1,5 @@
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> $DIR/offset-of-dst-field.rs:30:5
--> $DIR/offset-of-dst-field.rs:36:5
|
LL | offset_of!(Alpha, z);
| ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@ -8,7 +8,7 @@ LL | offset_of!(Alpha, z);
= note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
--> $DIR/offset-of-dst-field.rs:31:5
--> $DIR/offset-of-dst-field.rs:37:5
|
LL | offset_of!(Beta, z);
| ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@ -17,7 +17,7 @@ LL | offset_of!(Beta, z);
= note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: the size for values of type `Extern` cannot be known at compilation time
--> $DIR/offset-of-dst-field.rs:32:5
--> $DIR/offset-of-dst-field.rs:38:5
|
LL | offset_of!(Gamma, z);
| ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@ -25,6 +25,44 @@ LL | offset_of!(Gamma, z);
= help: the trait `Sized` is not implemented for `Extern`
= note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 3 previous errors
error[E0277]: the size for values of type `Extern` cannot be known at compilation time
--> $DIR/offset-of-dst-field.rs:43:5
|
LL | offset_of!(Delta<Extern>, z);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `Extern`
= note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> $DIR/offset-of-dst-field.rs:42:5
|
LL | offset_of!(Delta<Alpha>, z);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: within `Alpha`, the trait `Sized` is not implemented for `[u8]`
note: required because it appears within the type `Alpha`
--> $DIR/offset-of-dst-field.rs:5:8
|
LL | struct Alpha {
| ^^^^^
= note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: the size for values of type `T` cannot be known at compilation time
--> $DIR/offset-of-dst-field.rs:47:5
|
LL | fn generic_with_maybe_sized<T: ?Sized>() -> usize {
| - this type parameter needs to be `std::marker::Sized`
LL | offset_of!(Delta<T>, z)
| ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
LL - fn generic_with_maybe_sized<T: ?Sized>() -> usize {
LL + fn generic_with_maybe_sized<T>() -> usize {
|
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,20 @@
#![feature(offset_of)]
use std::mem::offset_of;
struct S {
v: u8,
w: u16,
}
fn main() {
let _: u8 = offset_of!(S, v); //~ ERROR mismatched types
let _: u16 = offset_of!(S, v); //~ ERROR mismatched types
let _: u32 = offset_of!(S, v); //~ ERROR mismatched types
let _: u64 = offset_of!(S, v); //~ ERROR mismatched types
let _: isize = offset_of!(S, v); //~ ERROR mismatched types
let _: usize = offset_of!(S, v);
offset_of!(S, v) //~ ERROR mismatched types
}

View File

@ -0,0 +1,64 @@
error[E0308]: mismatched types
--> $DIR/offset-of-output-type.rs:12:17
|
LL | let _: u8 = offset_of!(S, v);
| -- ^^^^^^^^^^^^^^^^ expected `u8`, found `usize`
| |
| expected due to this
|
= note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
--> $DIR/offset-of-output-type.rs:13:18
|
LL | let _: u16 = offset_of!(S, v);
| --- ^^^^^^^^^^^^^^^^ expected `u16`, found `usize`
| |
| expected due to this
|
= note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
--> $DIR/offset-of-output-type.rs:14:18
|
LL | let _: u32 = offset_of!(S, v);
| --- ^^^^^^^^^^^^^^^^ expected `u32`, found `usize`
| |
| expected due to this
|
= note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
--> $DIR/offset-of-output-type.rs:15:18
|
LL | let _: u64 = offset_of!(S, v);
| --- ^^^^^^^^^^^^^^^^ expected `u64`, found `usize`
| |
| expected due to this
|
= note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
--> $DIR/offset-of-output-type.rs:16:20
|
LL | let _: isize = offset_of!(S, v);
| ----- ^^^^^^^^^^^^^^^^ expected `isize`, found `usize`
| |
| expected due to this
|
= note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
--> $DIR/offset-of-output-type.rs:19:5
|
LL | fn main() {
| - expected `()` because of default return type
...
LL | offset_of!(S, v)
| ^^^^^^^^^^^^^^^^ expected `()`, found `usize`
|
= note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0308`.

View File

@ -8,9 +8,21 @@ mod m {
pub public: u8,
private: u8,
}
#[repr(C)]
pub struct FooTuple(pub u8, u8);
#[repr(C)]
struct Bar {
pub public: u8,
private: u8,
}
}
fn main() {
offset_of!(m::Foo, public);
offset_of!(m::Foo, private); //~ ERROR field `private` of struct `Foo` is private
offset_of!(m::FooTuple, 0);
offset_of!(m::FooTuple, 1); //~ ERROR field `1` of struct `FooTuple` is private
offset_of!(m::Bar, public); //~ ERROR struct `Bar` is private
offset_of!(m::Bar, private); //~ ERROR struct `Bar` is private
//~| ERROR field `private` of struct `Bar` is private
}

View File

@ -1,9 +1,46 @@
error[E0603]: struct `Bar` is private
--> $DIR/offset-of-private.rs:25:19
|
LL | offset_of!(m::Bar, public);
| ^^^ private struct
|
note: the struct `Bar` is defined here
--> $DIR/offset-of-private.rs:14:5
|
LL | struct Bar {
| ^^^^^^^^^^
error[E0603]: struct `Bar` is private
--> $DIR/offset-of-private.rs:26:19
|
LL | offset_of!(m::Bar, private);
| ^^^ private struct
|
note: the struct `Bar` is defined here
--> $DIR/offset-of-private.rs:14:5
|
LL | struct Bar {
| ^^^^^^^^^^
error[E0616]: field `private` of struct `Foo` is private
--> $DIR/offset-of-private.rs:15:24
--> $DIR/offset-of-private.rs:22:24
|
LL | offset_of!(m::Foo, private);
| ^^^^^^^ private field
error: aborting due to previous error
error[E0616]: field `1` of struct `FooTuple` is private
--> $DIR/offset-of-private.rs:24:29
|
LL | offset_of!(m::FooTuple, 1);
| ^ private field
For more information about this error, try `rustc --explain E0616`.
error[E0616]: field `private` of struct `Bar` is private
--> $DIR/offset-of-private.rs:26:24
|
LL | offset_of!(m::Bar, private);
| ^^^^^^^ private field
error: aborting due to 5 previous errors
Some errors have detailed explanations: E0603, E0616.
For more information about an error, try `rustc --explain E0603`.

View File

@ -0,0 +1,58 @@
#![feature(offset_of)]
use std::mem::offset_of;
struct C<T> {
v: T,
w: T,
}
struct S {
v: u8,
w: u16,
}
impl S {
fn v_offs() -> usize {
offset_of!(Self, v)
}
fn v_offs_wrong_syntax() {
offset_of!(Self, Self::v); //~ ERROR no rules expected the token `::`
offset_of!(S, Self); //~ ERROR expected identifier, found keyword `Self`
//~| no field `Self` on type `S`
}
fn offs_in_c() -> usize {
offset_of!(C<Self>, w)
}
fn offs_in_c_colon() -> usize {
offset_of!(C::<Self>, w)
}
}
mod m {
use std::mem::offset_of;
fn off() {
offset_of!(self::S, v); //~ ERROR cannot find type `S` in module
offset_of!(super::S, v);
offset_of!(crate::S, v);
}
impl super::n::T {
fn v_offs_self() -> usize {
offset_of!(Self, v) //~ ERROR field `v` of struct `T` is private
}
}
}
mod n {
pub struct T { v: u8, }
}
fn main() {
offset_of!(self::S, v);
offset_of!(Self, v); //~ ERROR cannot find type `Self` in this scope
offset_of!(S, self); //~ ERROR expected identifier, found keyword `self`
//~| no field `self` on type `S`
offset_of!(S, v.self); //~ ERROR expected identifier, found keyword `self`
//~| no field `self` on type `u8`
}

View File

@ -0,0 +1,79 @@
error: no rules expected the token `::`
--> $DIR/offset-of-self.rs:20:30
|
LL | offset_of!(Self, Self::v);
| ^^ no rules expected this token in macro call
|
= note: while trying to match sequence start
error: expected identifier, found keyword `Self`
--> $DIR/offset-of-self.rs:21:23
|
LL | offset_of!(S, Self);
| ^^^^ expected identifier, found keyword
error: expected identifier, found keyword `self`
--> $DIR/offset-of-self.rs:54:19
|
LL | offset_of!(S, self);
| ^^^^ expected identifier, found keyword
error: expected identifier, found keyword `self`
--> $DIR/offset-of-self.rs:56:21
|
LL | offset_of!(S, v.self);
| ^^^^ expected identifier, found keyword
error[E0412]: cannot find type `S` in module `self`
--> $DIR/offset-of-self.rs:35:26
|
LL | offset_of!(self::S, v);
| ^ not found in `self`
|
help: consider importing this struct
|
LL + use S;
|
help: if you import `S`, refer to it directly
|
LL - offset_of!(self::S, v);
LL + offset_of!(S, v);
|
error[E0411]: cannot find type `Self` in this scope
--> $DIR/offset-of-self.rs:52:16
|
LL | fn main() {
| ---- `Self` not allowed in a function
LL | offset_of!(self::S, v);
LL | offset_of!(Self, v);
| ^^^^ `Self` is only available in impls, traits, and type definitions
error[E0609]: no field `Self` on type `S`
--> $DIR/offset-of-self.rs:21:23
|
LL | offset_of!(S, Self);
| ^^^^
error[E0616]: field `v` of struct `T` is private
--> $DIR/offset-of-self.rs:41:30
|
LL | offset_of!(Self, v)
| ^ private field
error[E0609]: no field `self` on type `S`
--> $DIR/offset-of-self.rs:54:19
|
LL | offset_of!(S, self);
| ^^^^
error[E0609]: no field `self` on type `u8`
--> $DIR/offset-of-self.rs:56:21
|
LL | offset_of!(S, v.self);
| ^^^^
error: aborting due to 10 previous errors
Some errors have detailed explanations: E0411, E0412, E0609, E0616.
For more information about an error, try `rustc --explain E0411`.