Skip to content

Commit 30c0e4e

Browse files
committed
Add more tests for the offset_of!() macro
* 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 descision * improving the privacy checking test * ensuring that generics don't let you escape the unsized check
1 parent c2ccc85 commit 30c0e4e

9 files changed

+345
-7
lines changed

Diff for: library/core/tests/mem.rs

+15
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,21 @@ fn offset_of() {
386386
// Layout of tuples is unstable
387387
assert!(offset_of!((u8, u16), 0) <= size_of::<(u8, u16)>() - 1);
388388
assert!(offset_of!((u8, u16), 1) <= size_of::<(u8, u16)>() - 2);
389+
390+
#[repr(C)]
391+
struct Generic<T> {
392+
x: u8,
393+
y: u32,
394+
z: T
395+
}
396+
397+
// Ensure that this type of generics works
398+
fn offs_of_z<T>() -> usize {
399+
offset_of!(Generic<T>, z)
400+
}
401+
402+
assert_eq!(offset_of!(Generic<u8>, z), 8);
403+
assert_eq!(offs_of_z::<u8>(), 8);
389404
}
390405

391406
#[test]

Diff for: tests/ui/offset-of/offset-of-dst-field.rs

+15
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,23 @@ struct Gamma {
2626
z: Extern,
2727
}
2828

29+
struct Delta<T: ?Sized> {
30+
x: u8,
31+
y: u16,
32+
z: T,
33+
}
34+
2935
fn main() {
3036
offset_of!(Alpha, z); //~ ERROR the size for values of type
3137
offset_of!(Beta, z); //~ ERROR the size for values of type
3238
offset_of!(Gamma, z); //~ ERROR the size for values of type
3339
}
40+
41+
fn delta() {
42+
offset_of!(Delta<Alpha>, z); //~ ERROR the size for values of type
43+
offset_of!(Delta<Extern>, z); //~ ERROR the size for values of type
44+
}
45+
46+
fn generic_with_maybe_sized<T: ?Sized>() -> usize {
47+
offset_of!(Delta<T>, z) //~ ERROR the size for values of type
48+
}

Diff for: tests/ui/offset-of/offset-of-dst-field.stderr

+42-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
2-
--> $DIR/offset-of-dst-field.rs:30:5
2+
--> $DIR/offset-of-dst-field.rs:36:5
33
|
44
LL | offset_of!(Alpha, z);
55
| ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -8,7 +8,7 @@ LL | offset_of!(Alpha, z);
88
= note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
99

1010
error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
11-
--> $DIR/offset-of-dst-field.rs:31:5
11+
--> $DIR/offset-of-dst-field.rs:37:5
1212
|
1313
LL | offset_of!(Beta, z);
1414
| ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -17,14 +17,52 @@ LL | offset_of!(Beta, z);
1717
= note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
1818

1919
error[E0277]: the size for values of type `Extern` cannot be known at compilation time
20-
--> $DIR/offset-of-dst-field.rs:32:5
20+
--> $DIR/offset-of-dst-field.rs:38:5
2121
|
2222
LL | offset_of!(Gamma, z);
2323
| ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
2424
|
2525
= help: the trait `Sized` is not implemented for `Extern`
2626
= note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
2727

28-
error: aborting due to 3 previous errors
28+
error[E0277]: the size for values of type `Extern` cannot be known at compilation time
29+
--> $DIR/offset-of-dst-field.rs:43:5
30+
|
31+
LL | offset_of!(Delta<Extern>, z);
32+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
33+
|
34+
= help: the trait `Sized` is not implemented for `Extern`
35+
= note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
36+
37+
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
38+
--> $DIR/offset-of-dst-field.rs:42:5
39+
|
40+
LL | offset_of!(Delta<Alpha>, z);
41+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
42+
|
43+
= help: within `Alpha`, the trait `Sized` is not implemented for `[u8]`
44+
note: required because it appears within the type `Alpha`
45+
--> $DIR/offset-of-dst-field.rs:5:8
46+
|
47+
LL | struct Alpha {
48+
| ^^^^^
49+
= note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
50+
51+
error[E0277]: the size for values of type `T` cannot be known at compilation time
52+
--> $DIR/offset-of-dst-field.rs:47:5
53+
|
54+
LL | fn generic_with_maybe_sized<T: ?Sized>() -> usize {
55+
| - this type parameter needs to be `std::marker::Sized`
56+
LL | offset_of!(Delta<T>, z)
57+
| ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
58+
|
59+
= note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
60+
help: consider removing the `?Sized` bound to make the type parameter `Sized`
61+
|
62+
LL - fn generic_with_maybe_sized<T: ?Sized>() -> usize {
63+
LL + fn generic_with_maybe_sized<T>() -> usize {
64+
|
65+
66+
error: aborting due to 6 previous errors
2967

3068
For more information about this error, try `rustc --explain E0277`.

Diff for: tests/ui/offset-of/offset-of-output-type.rs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#![feature(offset_of)]
2+
3+
use std::mem::offset_of;
4+
5+
struct S {
6+
v: u8,
7+
w: u16,
8+
}
9+
10+
11+
fn main() {
12+
let _: u8 = offset_of!(S, v); //~ ERROR mismatched types
13+
let _: u16 = offset_of!(S, v); //~ ERROR mismatched types
14+
let _: u32 = offset_of!(S, v); //~ ERROR mismatched types
15+
let _: u64 = offset_of!(S, v); //~ ERROR mismatched types
16+
let _: isize = offset_of!(S, v); //~ ERROR mismatched types
17+
let _: usize = offset_of!(S, v);
18+
19+
offset_of!(S, v) //~ ERROR mismatched types
20+
}

Diff for: tests/ui/offset-of/offset-of-output-type.stderr

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/offset-of-output-type.rs:12:17
3+
|
4+
LL | let _: u8 = offset_of!(S, v);
5+
| -- ^^^^^^^^^^^^^^^^ expected `u8`, found `usize`
6+
| |
7+
| expected due to this
8+
|
9+
= note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
10+
11+
error[E0308]: mismatched types
12+
--> $DIR/offset-of-output-type.rs:13:18
13+
|
14+
LL | let _: u16 = offset_of!(S, v);
15+
| --- ^^^^^^^^^^^^^^^^ expected `u16`, found `usize`
16+
| |
17+
| expected due to this
18+
|
19+
= note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
20+
21+
error[E0308]: mismatched types
22+
--> $DIR/offset-of-output-type.rs:14:18
23+
|
24+
LL | let _: u32 = offset_of!(S, v);
25+
| --- ^^^^^^^^^^^^^^^^ expected `u32`, found `usize`
26+
| |
27+
| expected due to this
28+
|
29+
= note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
30+
31+
error[E0308]: mismatched types
32+
--> $DIR/offset-of-output-type.rs:15:18
33+
|
34+
LL | let _: u64 = offset_of!(S, v);
35+
| --- ^^^^^^^^^^^^^^^^ expected `u64`, found `usize`
36+
| |
37+
| expected due to this
38+
|
39+
= note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
40+
41+
error[E0308]: mismatched types
42+
--> $DIR/offset-of-output-type.rs:16:20
43+
|
44+
LL | let _: isize = offset_of!(S, v);
45+
| ----- ^^^^^^^^^^^^^^^^ expected `isize`, found `usize`
46+
| |
47+
| expected due to this
48+
|
49+
= note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
50+
51+
error[E0308]: mismatched types
52+
--> $DIR/offset-of-output-type.rs:19:5
53+
|
54+
LL | fn main() {
55+
| - expected `()` because of default return type
56+
...
57+
LL | offset_of!(S, v)
58+
| ^^^^^^^^^^^^^^^^ expected `()`, found `usize`
59+
|
60+
= note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
61+
62+
error: aborting due to 6 previous errors
63+
64+
For more information about this error, try `rustc --explain E0308`.

Diff for: tests/ui/offset-of/offset-of-private.rs

+12
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,21 @@ mod m {
88
pub public: u8,
99
private: u8,
1010
}
11+
#[repr(C)]
12+
pub struct FooTuple(pub u8, u8);
13+
#[repr(C)]
14+
struct Bar {
15+
pub public: u8,
16+
private: u8,
17+
}
1118
}
1219

1320
fn main() {
1421
offset_of!(m::Foo, public);
1522
offset_of!(m::Foo, private); //~ ERROR field `private` of struct `Foo` is private
23+
offset_of!(m::FooTuple, 0);
24+
offset_of!(m::FooTuple, 1); //~ ERROR field `1` of struct `FooTuple` is private
25+
offset_of!(m::Bar, public); //~ ERROR struct `Bar` is private
26+
offset_of!(m::Bar, private); //~ ERROR struct `Bar` is private
27+
//~| ERROR field `private` of struct `Bar` is private
1628
}

Diff for: tests/ui/offset-of/offset-of-private.stderr

+40-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,46 @@
1+
error[E0603]: struct `Bar` is private
2+
--> $DIR/offset-of-private.rs:25:19
3+
|
4+
LL | offset_of!(m::Bar, public);
5+
| ^^^ private struct
6+
|
7+
note: the struct `Bar` is defined here
8+
--> $DIR/offset-of-private.rs:14:5
9+
|
10+
LL | struct Bar {
11+
| ^^^^^^^^^^
12+
13+
error[E0603]: struct `Bar` is private
14+
--> $DIR/offset-of-private.rs:26:19
15+
|
16+
LL | offset_of!(m::Bar, private);
17+
| ^^^ private struct
18+
|
19+
note: the struct `Bar` is defined here
20+
--> $DIR/offset-of-private.rs:14:5
21+
|
22+
LL | struct Bar {
23+
| ^^^^^^^^^^
24+
125
error[E0616]: field `private` of struct `Foo` is private
2-
--> $DIR/offset-of-private.rs:15:24
26+
--> $DIR/offset-of-private.rs:22:24
327
|
428
LL | offset_of!(m::Foo, private);
529
| ^^^^^^^ private field
630

7-
error: aborting due to previous error
31+
error[E0616]: field `1` of struct `FooTuple` is private
32+
--> $DIR/offset-of-private.rs:24:29
33+
|
34+
LL | offset_of!(m::FooTuple, 1);
35+
| ^ private field
36+
37+
error[E0616]: field `private` of struct `Bar` is private
38+
--> $DIR/offset-of-private.rs:26:24
39+
|
40+
LL | offset_of!(m::Bar, private);
41+
| ^^^^^^^ private field
42+
43+
error: aborting due to 5 previous errors
844

9-
For more information about this error, try `rustc --explain E0616`.
45+
Some errors have detailed explanations: E0603, E0616.
46+
For more information about an error, try `rustc --explain E0603`.

Diff for: tests/ui/offset-of/offset-of-self.rs

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#![feature(offset_of)]
2+
3+
use std::mem::offset_of;
4+
5+
struct C<T> {
6+
v: T,
7+
w: T,
8+
}
9+
10+
struct S {
11+
v: u8,
12+
w: u16,
13+
}
14+
15+
impl S {
16+
fn v_offs() -> usize {
17+
offset_of!(Self, v)
18+
}
19+
fn v_offs_wrong_syntax() {
20+
offset_of!(Self, Self::v); //~ ERROR no rules expected the token `::`
21+
offset_of!(S, Self); //~ ERROR expected identifier, found keyword `Self`
22+
//~| no field `Self` on type `S`
23+
}
24+
fn offs_in_c() -> usize {
25+
offset_of!(C<Self>, w)
26+
}
27+
fn offs_in_c_colon() -> usize {
28+
offset_of!(C::<Self>, w)
29+
}
30+
}
31+
32+
mod m {
33+
use std::mem::offset_of;
34+
fn off() {
35+
offset_of!(self::S, v); //~ ERROR cannot find type `S` in module
36+
offset_of!(super::S, v);
37+
offset_of!(crate::S, v);
38+
}
39+
impl super::n::T {
40+
fn v_offs_self() -> usize {
41+
offset_of!(Self, v) //~ ERROR field `v` of struct `T` is private
42+
}
43+
}
44+
}
45+
46+
mod n {
47+
pub struct T { v: u8, }
48+
}
49+
50+
fn main() {
51+
offset_of!(self::S, v);
52+
offset_of!(Self, v); //~ ERROR cannot find type `Self` in this scope
53+
54+
offset_of!(S, self); //~ ERROR expected identifier, found keyword `self`
55+
//~| no field `self` on type `S`
56+
offset_of!(S, v.self); //~ ERROR expected identifier, found keyword `self`
57+
//~| no field `self` on type `u8`
58+
}

0 commit comments

Comments
 (0)