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:
Mark Rousskov 2018-07-11 12:38:36 -06:00 committed by GitHub
commit 7897ee4d42
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 114 additions and 50 deletions

View file

@ -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
}

View file

@ -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
}

View file

@ -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()));

View file

@ -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
}

View file

@ -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;
};
}

View file

@ -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() {}

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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;
}

View file

@ -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
}

View file

@ -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() {

View file

@ -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
}

View file

@ -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
}

View file

@ -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

View file

@ -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

View 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

View file

@ -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

View file

@ -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

View file

@ -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