Skip to content

Commit

Permalink
Rollup merge of #111665 - est31:offset_of_tests, r=WaffleLapkin
Browse files Browse the repository at this point in the history
Add more tests for the offset_of macro

Implements what I [suggested in the tracking issue](#106655 (comment)), 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`
  • Loading branch information
Dylan-DPC authored May 18, 2023
2 parents 7bc736c + 30c0e4e commit 660ed0e
Show file tree
Hide file tree
Showing 9 changed files with 345 additions and 7 deletions.
15 changes: 15 additions & 0 deletions library/core/tests/mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
15 changes: 15 additions & 0 deletions tests/ui/offset-of/offset-of-dst-field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
46 changes: 42 additions & 4 deletions tests/ui/offset-of/offset-of-dst-field.stderr
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand All @@ -17,14 +17,52 @@ 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
|
= 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 changes: 20 additions & 0 deletions tests/ui/offset-of/offset-of-output-type.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 64 additions & 0 deletions tests/ui/offset-of/offset-of-output-type.stderr
Original file line number Diff line number Diff line change
@@ -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`.
12 changes: 12 additions & 0 deletions tests/ui/offset-of/offset-of-private.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
43 changes: 40 additions & 3 deletions tests/ui/offset-of/offset-of-private.stderr
Original file line number Diff line number Diff line change
@@ -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

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

For more information about this error, try `rustc --explain E0616`.
Some errors have detailed explanations: E0603, E0616.
For more information about an error, try `rustc --explain E0603`.
58 changes: 58 additions & 0 deletions tests/ui/offset-of/offset-of-self.rs
Original file line number Diff line number Diff line change
@@ -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`
}
Loading

0 comments on commit 660ed0e

Please sign in to comment.