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:
commit
e892e32df4
@ -386,6 +386,21 @@ fn offset_of() {
|
|||||||
// Layout of tuples is unstable
|
// Layout of tuples is unstable
|
||||||
assert!(offset_of!((u8, u16), 0) <= size_of::<(u8, u16)>() - 1);
|
assert!(offset_of!((u8, u16), 0) <= size_of::<(u8, u16)>() - 1);
|
||||||
assert!(offset_of!((u8, u16), 1) <= size_of::<(u8, u16)>() - 2);
|
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]
|
#[test]
|
||||||
|
@ -26,8 +26,23 @@ struct Gamma {
|
|||||||
z: Extern,
|
z: Extern,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Delta<T: ?Sized> {
|
||||||
|
x: u8,
|
||||||
|
y: u16,
|
||||||
|
z: T,
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
offset_of!(Alpha, z); //~ ERROR the size for values of type
|
offset_of!(Alpha, z); //~ ERROR the size for values of type
|
||||||
offset_of!(Beta, 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
|
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
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
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);
|
LL | offset_of!(Alpha, z);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
| ^^^^^^^^^^^^^^^^^^^^ 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)
|
= 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
|
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);
|
LL | offset_of!(Beta, z);
|
||||||
| ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
| ^^^^^^^^^^^^^^^^^^^ 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)
|
= 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
|
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);
|
LL | offset_of!(Gamma, z);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
| ^^^^^^^^^^^^^^^^^^^^ 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`
|
= 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)
|
= 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`.
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
|
20
tests/ui/offset-of/offset-of-output-type.rs
Normal file
20
tests/ui/offset-of/offset-of-output-type.rs
Normal 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
|
||||||
|
}
|
64
tests/ui/offset-of/offset-of-output-type.stderr
Normal file
64
tests/ui/offset-of/offset-of-output-type.stderr
Normal 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`.
|
@ -8,9 +8,21 @@ mod m {
|
|||||||
pub public: u8,
|
pub public: u8,
|
||||||
private: u8,
|
private: u8,
|
||||||
}
|
}
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct FooTuple(pub u8, u8);
|
||||||
|
#[repr(C)]
|
||||||
|
struct Bar {
|
||||||
|
pub public: u8,
|
||||||
|
private: u8,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
offset_of!(m::Foo, public);
|
offset_of!(m::Foo, public);
|
||||||
offset_of!(m::Foo, private); //~ ERROR field `private` of struct `Foo` is private
|
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
|
||||||
}
|
}
|
||||||
|
@ -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
|
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);
|
LL | offset_of!(m::Foo, private);
|
||||||
| ^^^^^^^ private field
|
| ^^^^^^^ 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`.
|
||||||
|
58
tests/ui/offset-of/offset-of-self.rs
Normal file
58
tests/ui/offset-of/offset-of-self.rs
Normal 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`
|
||||||
|
}
|
79
tests/ui/offset-of/offset-of-self.stderr
Normal file
79
tests/ui/offset-of/offset-of-self.stderr
Normal 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`.
|
Loading…
x
Reference in New Issue
Block a user