Skip to content

Commit

Permalink
Merge #83
Browse files Browse the repository at this point in the history
83: Improve error message for #[repr(packed(N))] r=taiki-e a=taiki-e

#34 can [already detect this](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=7331036de27faeb8354e367ef514c6c6), but this will generate better error messages.

This also adds some tests related to `#[repr(packed)]`.

Co-authored-by: Taiki Endo <[email protected]>
  • Loading branch information
bors[bot] and taiki-e authored Sep 10, 2019
2 parents 6eac367 + b9feff4 commit edc9cd4
Show file tree
Hide file tree
Showing 18 changed files with 254 additions and 32 deletions.
16 changes: 12 additions & 4 deletions pin-project-internal/src/pin_project/attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -338,14 +338,21 @@ fn ensure_not_packed(item: &ItemStruct) -> Result<TokenStream> {
for meta in item.attrs.iter().filter_map(|attr| attr.parse_meta().ok()) {
if let Meta::List(l) = meta {
if l.path.is_ident("repr") {
for repr in &l.nested {
if let NestedMeta::Meta(Meta::Path(p)) = repr {
if p.is_ident("packed") {
for repr in l.nested.iter() {
match repr {
NestedMeta::Meta(Meta::Path(p)) if p.is_ident("packed") => {
return Err(error!(
p,
"#[pin_project] attribute may not be used on #[repr(packed)] types"
));
}
NestedMeta::Meta(Meta::List(l)) if l.path.is_ident("packed") => {
return Err(error!(
l,
"#[pin_project] attribute may not be used on #[repr(packed(N))] types"
));
}
_ => {}
}
}
}
Expand Down Expand Up @@ -394,7 +401,8 @@ fn ensure_not_packed(item: &ItemStruct) -> Result<TokenStream> {
for Field { attrs, ident, .. } in named {
let cfg = collect_cfg(attrs);
field_refs.push(quote! {
#(#cfg)* { &val.#ident; }
#(#cfg)*
{ &val.#ident; }
});
}
}
Expand Down
1 change: 1 addition & 0 deletions tests/repr_packed.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#![warn(unsafe_code)]
#![warn(rust_2018_idioms, single_use_lifetimes)]
#![allow(dead_code)]
#![deny(safe_packed_borrows)]

use std::cell::Cell;

Expand Down
10 changes: 10 additions & 0 deletions tests/ui/cfg/auxiliary/sneaky_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,13 @@ pub fn add_pinned_field(_: TokenStream, input: TokenStream) -> TokenStream {
pub fn hidden_repr(attr: TokenStream, item: TokenStream) -> TokenStream {
format!("#[repr({})] {}", attr, item).parse().unwrap()
}

#[proc_macro_attribute]
pub fn hidden_repr_cfg_any(attr: TokenStream, item: TokenStream) -> TokenStream {
format!("#[cfg_attr(any(), repr({}))] {}", attr, item).parse().unwrap()
}

#[proc_macro_attribute]
pub fn hidden_repr_cfg_not_any(attr: TokenStream, item: TokenStream) -> TokenStream {
format!("#[cfg_attr(not(any()), repr({}))] {}", attr, item).parse().unwrap()
}
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error: borrow of packed field is unsafe and requires unsafe function or block (error E0133)
--> $DIR/packed_sneaky.rs:20:1
--> $DIR/packed_sneaky-1.rs:20:1
|
20 | #[pin_project] //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
| ^^^^^^^^^^^^^^
|
note: lint level defined here
--> $DIR/packed_sneaky.rs:20:1
--> $DIR/packed_sneaky-1.rs:20:1
|
20 | #[pin_project] //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
| ^^^^^^^^^^^^^^
Expand Down
17 changes: 17 additions & 0 deletions tests/ui/cfg/packed_sneaky-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// run-pass
// aux-build:sneaky_macro.rs

#[macro_use]
extern crate sneaky_macro;

use pin_project::pin_project;

// #[cfg_attr(any(), repr(packed))]
#[pin_project]
#[hidden_repr_cfg_any(packed)]
struct Foo {
#[pin]
field: u32,
}

fn main() {}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ extern crate sneaky_macro;

use pin_project::pin_project;

// #[cfg_attr(not(any()), repr(packed))]
#[pin_project] //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
#[hidden_repr(packed)]
#[hidden_repr_cfg_not_any(packed)]
struct Foo {
#[pin]
field: u32,
Expand Down
17 changes: 17 additions & 0 deletions tests/ui/cfg/packed_sneaky-3.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
error: borrow of packed field is unsafe and requires unsafe function or block (error E0133)
--> $DIR/packed_sneaky-3.rs:10:1
|
10 | #[pin_project] //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
| ^^^^^^^^^^^^^^
|
note: lint level defined here
--> $DIR/packed_sneaky-3.rs:10:1
|
10 | #[pin_project] //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
| ^^^^^^^^^^^^^^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
= note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior

error: aborting due to previous error

6 changes: 5 additions & 1 deletion tests/ui/pin_project/auxiliary/sneaky_macro.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// force-host
// force-host
// no-prefer-dynamic

#![crate_type = "proc-macro"]
Expand All @@ -12,3 +12,7 @@ pub fn hidden_repr(attr: TokenStream, item: TokenStream) -> TokenStream {
format!("#[repr({})] {}", attr, item).parse().unwrap()
}

#[proc_macro]
pub fn hidden_repr_macro(item: TokenStream) -> TokenStream {
format!("#[repr(packed)] {}", item).parse().unwrap()
}
15 changes: 11 additions & 4 deletions tests/ui/pin_project/packed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,25 @@
use pin_project::pin_project;

#[pin_project]
#[repr(packed, C)] //~ ERROR may not be used on #[repr(packed)] type
struct Foo {
#[repr(packed, C)] //~ ERROR may not be used on #[repr(packed)] types
struct A {
#[pin]
field: u8,
}

// Test putting 'repr' before the 'pin_project' attribute
#[repr(packed, C)] //~ ERROR may not be used on #[repr(packed)] type
#[repr(packed, C)] //~ ERROR may not be used on #[repr(packed)] types
#[pin_project]
struct Foo2 {
struct B {
#[pin]
field: u8,
}

#[pin_project]
#[repr(packed(2))] //~ ERROR may not be used on #[repr(packed(N))] types
struct C {
#[pin]
field: u32,
}

fn main() {}
12 changes: 9 additions & 3 deletions tests/ui/pin_project/packed.stderr
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
error: #[pin_project] attribute may not be used on #[repr(packed)] types
--> $DIR/packed.rs:6:8
|
6 | #[repr(packed, C)] //~ ERROR may not be used on #[repr(packed)] type
6 | #[repr(packed, C)] //~ ERROR may not be used on #[repr(packed)] types
| ^^^^^^

error: #[pin_project] attribute may not be used on #[repr(packed)] types
--> $DIR/packed.rs:13:8
|
13 | #[repr(packed, C)] //~ ERROR may not be used on #[repr(packed)] type
13 | #[repr(packed, C)] //~ ERROR may not be used on #[repr(packed)] types
| ^^^^^^

error: aborting due to 2 previous errors
error: #[pin_project] attribute may not be used on #[repr(packed(N))] types
--> $DIR/packed.rs:21:8
|
21 | #[repr(packed(2))] //~ ERROR may not be used on #[repr(packed(N))] types
| ^^^^^^^^^

error: aborting due to 3 previous errors

36 changes: 36 additions & 0 deletions tests/ui/pin_project/packed_sneaky-1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// compile-fail
// aux-build:sneaky_macro.rs

#[macro_use]
extern crate sneaky_macro;

use pin_project::{pin_project, pinned_drop, UnsafeUnpin};
use std::pin::Pin;

#[pin_project] //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
#[hidden_repr(packed)]
struct A {
#[pin]
field: u32,
}

#[pin_project(UnsafeUnpin)] //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
#[hidden_repr(packed)]
struct C {
#[pin]
field: u32,
}

unsafe impl UnsafeUnpin for C {}

#[pin_project(PinnedDrop)] //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
#[hidden_repr(packed)]
struct D {
#[pin]
field: u32,
}

#[pinned_drop]
fn drop_d(_: Pin<&mut D>) {}

fn main() {}
47 changes: 47 additions & 0 deletions tests/ui/pin_project/packed_sneaky-1.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
error: borrow of packed field is unsafe and requires unsafe function or block (error E0133)
--> $DIR/packed_sneaky-1.rs:10:1
|
10 | #[pin_project] //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
| ^^^^^^^^^^^^^^
|
note: lint level defined here
--> $DIR/packed_sneaky-1.rs:10:1
|
10 | #[pin_project] //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
| ^^^^^^^^^^^^^^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
= note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior

error: borrow of packed field is unsafe and requires unsafe function or block (error E0133)
--> $DIR/packed_sneaky-1.rs:17:1
|
17 | #[pin_project(UnsafeUnpin)] //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: lint level defined here
--> $DIR/packed_sneaky-1.rs:17:1
|
17 | #[pin_project(UnsafeUnpin)] //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
= note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior

error: borrow of packed field is unsafe and requires unsafe function or block (error E0133)
--> $DIR/packed_sneaky-1.rs:26:1
|
26 | #[pin_project(PinnedDrop)] //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: lint level defined here
--> $DIR/packed_sneaky-1.rs:26:1
|
26 | #[pin_project(PinnedDrop)] //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
= note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior

error: aborting due to 3 previous errors

17 changes: 17 additions & 0 deletions tests/ui/pin_project/packed_sneaky-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// compile-fail
// aux-build:sneaky_macro.rs

#[macro_use]
extern crate sneaky_macro;

use pin_project::pin_project;

hidden_repr_macro! { //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
#[pin_project]
struct B {
#[pin]
field: u32,
}
}

fn main() {}
16 changes: 16 additions & 0 deletions tests/ui/pin_project/packed_sneaky-2.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
error: #[pin_project] attribute may not be used on #[repr(packed)] types
--> $DIR/packed_sneaky-2.rs:9:1
|
9 | / hidden_repr_macro! { //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
10 | | #[pin_project]
11 | | struct B {
12 | | #[pin]
13 | | field: u32,
14 | | }
15 | | }
| | ^ in this macro invocation
| |_|
|

error: aborting due to previous error

17 changes: 0 additions & 17 deletions tests/ui/pin_project/packed_sneaky.stderr

This file was deleted.

25 changes: 25 additions & 0 deletions tests/ui/pin_project/safe_packed_borrows.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// compile-fail

#![deny(safe_packed_borrows)]

// Refs: https://github.com/rust-lang/rust/issues/46043

#[repr(packed)]
struct A {
field: u32,
}

#[repr(packed(2))]
struct B {
field: u32,
}

fn foo() {
let a = A { field: 1 };
&a.field; //~ ERROR borrow of packed field is unsafe and requires unsafe function or block

let b = B { field: 1 };
&b.field; //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
}

fn main() {}
27 changes: 27 additions & 0 deletions tests/ui/pin_project/safe_packed_borrows.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
error: borrow of packed field is unsafe and requires unsafe function or block (error E0133)
--> $DIR/safe_packed_borrows.rs:17:5
|
17 | &a.field; //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
| ^^^^^^^^
|
note: lint level defined here
--> $DIR/safe_packed_borrows.rs:1:9
|
1 | #![deny(safe_packed_borrows)]
| ^^^^^^^^^^^^^^^^^^^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
= note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior

error: borrow of packed field is unsafe and requires unsafe function or block (error E0133)
--> $DIR/safe_packed_borrows.rs:20:5
|
20 | &b.field; //~ ERROR borrow of packed field is unsafe and requires unsafe function or block
| ^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
= note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior

error: aborting due to 2 previous errors

0 comments on commit edc9cd4

Please sign in to comment.