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

Improve error message for #[repr(packed(N))] #83

Merged
merged 1 commit into from
Sep 10, 2019
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
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