Rollup merge of #52207 - RalfJung:unsafety-errors, r=estebank
improve error message shown for unsafe operations Add a short explanation saying why undefined behavior could arise. In particular, the error many people got for "creating a pointer to a packed field requires unsafe block" was not worded great -- it lead to people just adding the unsafe block without considering if what they are doing follows the rules. I am not sure if a "note" is the right thing, but that was the easiest thing to add... Inspired by @gnzlbg at https://github.com/rust-lang/rust/issues/46043#issuecomment-381544673
This commit is contained in:
commit
7897ee4d42
23 changed files with 114 additions and 50 deletions
|
|
@ -17,5 +17,5 @@ mod test {
|
|||
|
||||
fn main() {
|
||||
test::free();
|
||||
//~^ ERROR call to unsafe function requires unsafe function or block
|
||||
//~^ ERROR call to unsafe function is unsafe
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
use std::intrinsics::{init};
|
||||
|
||||
// Test that the `forget` and `init` intrinsics are really unsafe
|
||||
// Test that the `init` intrinsic is really unsafe
|
||||
pub fn main() {
|
||||
let stuff = init::<isize>(); //~ ERROR call to unsafe function requires unsafe
|
||||
let stuff = init::<isize>(); //~ ERROR call to unsafe function is unsafe
|
||||
}
|
||||
|
|
@ -27,12 +27,12 @@ fn __getit() -> std::option::Option<
|
|||
&'static std::cell::UnsafeCell<
|
||||
std::option::Option<Foo>>>
|
||||
{
|
||||
__KEY.get() //~ ERROR call to unsafe function requires unsafe
|
||||
__KEY.get() //~ ERROR call to unsafe function is unsafe
|
||||
}
|
||||
|
||||
static FOO: std::thread::LocalKey<Foo> =
|
||||
std::thread::LocalKey::new(__getit, Default::default);
|
||||
//~^ ERROR call to unsafe function requires unsafe
|
||||
//~^ ERROR call to unsafe function is unsafe
|
||||
|
||||
fn main() {
|
||||
FOO.with(|foo| println!("{}", foo.borrow()));
|
||||
|
|
|
|||
|
|
@ -11,5 +11,5 @@
|
|||
fn main() {
|
||||
return;
|
||||
*(1 as *mut u32) = 42;
|
||||
//~^ ERROR dereference of raw pointer requires unsafe
|
||||
//~^ ERROR dereference of raw pointer is unsafe
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
fn main() {
|
||||
let _ = || {
|
||||
*(1 as *mut u32) = 42;
|
||||
//~^ ERROR dereference of raw pointer requires unsafe
|
||||
//~^ ERROR dereference of raw pointer is unsafe
|
||||
yield;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,13 +19,13 @@ fn union_field() {
|
|||
union Union { unit: (), void: Void }
|
||||
let u = Union { unit: () };
|
||||
match u.void {}
|
||||
//~^ ERROR access to union field requires unsafe function or block
|
||||
//~^ ERROR access to union field is unsafe
|
||||
}
|
||||
|
||||
fn raw_ptr_deref() {
|
||||
let ptr = std::ptr::null::<Void>();
|
||||
match *ptr {}
|
||||
//~^ ERROR dereference of raw pointer requires unsafe function or block
|
||||
//~^ ERROR dereference of raw pointer is unsafe
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ extern {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
let b = B; //~ ERROR use of mutable static requires unsafe function or block
|
||||
let rb = &B; //~ ERROR use of mutable static requires unsafe function or block
|
||||
let xb = XB; //~ ERROR use of mutable static requires unsafe function or block
|
||||
let xrb = &XB; //~ ERROR use of mutable static requires unsafe function or block
|
||||
let b = B; //~ ERROR use of mutable static is unsafe
|
||||
let rb = &B; //~ ERROR use of mutable static is unsafe
|
||||
let xb = XB; //~ ERROR use of mutable static is unsafe
|
||||
let xrb = &XB; //~ ERROR use of mutable static is unsafe
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,12 +20,12 @@ extern {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
let a = A; //~ ERROR use of extern static requires unsafe function or block
|
||||
let a = A; //~ ERROR use of extern static is unsafe
|
||||
//~^ WARN this was previously accepted by the compiler
|
||||
let ra = &A; //~ ERROR use of extern static requires unsafe function or block
|
||||
let ra = &A; //~ ERROR use of extern static is unsafe
|
||||
//~^ WARN this was previously accepted by the compiler
|
||||
let xa = XA; //~ ERROR use of extern static requires unsafe function or block
|
||||
let xa = XA; //~ ERROR use of extern static is unsafe
|
||||
//~^ WARN this was previously accepted by the compiler
|
||||
let xra = &XA; //~ ERROR use of extern static requires unsafe function or block
|
||||
let xra = &XA; //~ ERROR use of extern static is unsafe
|
||||
//~^ WARN this was previously accepted by the compiler
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ union U4<T: Copy> {
|
|||
|
||||
fn generic_noncopy<T: Default>() {
|
||||
let mut u3 = U3 { a: T::default() };
|
||||
u3.a = T::default(); //~ ERROR assignment to non-`Copy` union field requires unsafe
|
||||
u3.a = T::default(); //~ ERROR assignment to non-`Copy` union field is unsafe
|
||||
}
|
||||
|
||||
fn generic_copy<T: Copy + Default>() {
|
||||
|
|
@ -40,16 +40,16 @@ fn generic_copy<T: Copy + Default>() {
|
|||
|
||||
fn main() {
|
||||
let mut u1 = U1 { a: 10 }; // OK
|
||||
let a = u1.a; //~ ERROR access to union field requires unsafe
|
||||
let a = u1.a; //~ ERROR access to union field is unsafe
|
||||
u1.a = 11; // OK
|
||||
let U1 { a } = u1; //~ ERROR access to union field requires unsafe
|
||||
if let U1 { a: 12 } = u1 {} //~ ERROR access to union field requires unsafe
|
||||
let U1 { a } = u1; //~ ERROR access to union field is unsafe
|
||||
if let U1 { a: 12 } = u1 {} //~ ERROR access to union field is unsafe
|
||||
// let U1 { .. } = u1; // OK
|
||||
|
||||
let mut u2 = U2 { a: String::from("old") }; // OK
|
||||
u2.a = String::from("new"); //~ ERROR assignment to non-`Copy` union field requires unsafe
|
||||
u2.a = String::from("new"); //~ ERROR assignment to non-`Copy` union field is unsafe
|
||||
let mut u3 = U3 { a: 0 }; // OK
|
||||
u3.a = 1; // OK
|
||||
let mut u3 = U3 { a: String::from("old") }; // OK
|
||||
u3.a = String::from("new"); //~ ERROR assignment to non-`Copy` union field requires unsafe
|
||||
u3.a = String::from("new"); //~ ERROR assignment to non-`Copy` union field is unsafe
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
|
||||
fn f(p: *mut u8) {
|
||||
*p = 0; //~ ERROR dereference of raw pointer requires unsafe function or block
|
||||
*p = 0; //~ ERROR dereference of raw pointer is unsafe
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,5 +12,5 @@
|
|||
unsafe fn f() { return; }
|
||||
|
||||
fn main() {
|
||||
f(); //~ ERROR call to unsafe function requires unsafe function or block
|
||||
f(); //~ ERROR call to unsafe function is unsafe
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
|
||||
fn f(p: *const u8) -> u8 {
|
||||
return *p; //~ ERROR dereference of raw pointer requires unsafe function or block
|
||||
return *p; //~ ERROR dereference of raw pointer is unsafe
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -13,5 +13,5 @@ unsafe fn f() { return; }
|
|||
|
||||
fn main() {
|
||||
let x = f;
|
||||
x(); //~ ERROR call to unsafe function requires unsafe function or block
|
||||
x(); //~ ERROR call to unsafe function is unsafe
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,5 +16,5 @@ use std::intrinsics;
|
|||
// as unsafe.
|
||||
fn main() {
|
||||
intrinsics::move_val_init(1 as *mut u32, 1);
|
||||
//~^ ERROR dereference of raw pointer requires unsafe function or block
|
||||
//~^ ERROR dereference of raw pointer is unsafe
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
error[E0133]: call to unsafe function requires unsafe function or block
|
||||
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
|
||||
--> $DIR/E0133.rs:14:5
|
||||
|
|
||||
LL | f();
|
||||
| ^^^ call to unsafe function
|
||||
|
|
||||
= note: consult the function's documentation for information on how to avoid undefined behavior
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ fn main() {
|
|||
let _ = &good.data2[0]; // ok
|
||||
}
|
||||
|
||||
let _ = &good.data; //~ ERROR borrow of packed field requires unsafe
|
||||
let _ = &good.data; //~ ERROR borrow of packed field is unsafe
|
||||
//~| hard error
|
||||
let _ = &good.data2[0]; //~ ERROR borrow of packed field requires unsafe
|
||||
let _ = &good.data2[0]; //~ ERROR borrow of packed field is unsafe
|
||||
//~| hard error
|
||||
let _ = &*good.data; // ok, behind a pointer
|
||||
let _ = &good.aligned; // ok, has align 1
|
||||
27
src/test/ui/issue-27060.stderr
Normal file
27
src/test/ui/issue-27060.stderr
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
error: borrow of packed field is unsafe and requires unsafe function or block (error E0133)
|
||||
--> $DIR/issue-27060.rs:36:13
|
||||
|
|
||||
LL | let _ = &good.data; //~ ERROR borrow of packed field is unsafe
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/issue-27060.rs:23:8
|
||||
|
|
||||
LL | #[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/issue-27060.rs:38:13
|
||||
|
|
||||
LL | let _ = &good.data2[0]; //~ ERROR borrow of packed field is unsafe
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= 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
|
||||
|
||||
|
|
@ -1,8 +1,10 @@
|
|||
error[E0133]: call to unsafe function requires unsafe function or block
|
||||
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
|
||||
--> $DIR/issue-28776.rs:14:5
|
||||
|
|
||||
LL | (&ptr::write)(1 as *mut _, 42);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
|
||||
|
|
||||
= note: consult the function's documentation for information on how to avoid undefined behavior
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
error[E0133]: dereference of raw pointer requires unsafe function or block
|
||||
error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
|
||||
--> $DIR/trait-safety-fn-body.rs:21:9
|
||||
|
|
||||
LL | *self += 1;
|
||||
| ^^^^^^^^^^ dereference of raw pointer
|
||||
|
|
||||
= note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
error[E0133]: call to unsafe function requires unsafe function or block
|
||||
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
|
||||
--> $DIR/unsafe-const-fn.rs:19:18
|
||||
|
|
||||
LL | const VAL: u32 = dummy(0xFFFF);
|
||||
| ^^^^^^^^^^^^^ call to unsafe function
|
||||
|
|
||||
= note: consult the function's documentation for information on how to avoid undefined behavior
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue