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

Add more tests for the offset_of macro #111665

Merged
merged 1 commit into from
May 20, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
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
Copy link
Member

Choose a reason for hiding this comment

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

Could you also add a test for privacy with Self? There recently were some issues with it, so a test that Self doesn't allow to refer to private fields would be nice.

Something like

mod module {
    pub struct Named { v: u8 }
}

trait Trait {
    fn f() -> usize {}
}

impl Trait for module::Named {
    fn f() -> usize {
        offset_of!(Self, v) //~ error: field is private or whatever
    }
}

(and similarly for a tuple struct)

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