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
|
||||
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]
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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`.
|
||||
|
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,
|
||||
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
|
||||
}
|
||||
|
@ -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`.
|
||||
|
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