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
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[repr(packed)]
|
||||
pub struct Good {
|
||||
data: &'static u32,
|
||||
data2: [&'static u32; 2],
|
||||
aligned: [u8; 32],
|
||||
}
|
||||
|
||||
#[repr(packed)]
|
||||
pub struct JustArray {
|
||||
array: [u32]
|
||||
}
|
||||
|
||||
#[deny(safe_packed_borrows)]
|
||||
fn main() {
|
||||
let good = Good {
|
||||
data: &0,
|
||||
data2: [&0, &0],
|
||||
aligned: [0; 32]
|
||||
};
|
||||
|
||||
unsafe {
|
||||
let _ = &good.data; // ok
|
||||
let _ = &good.data2[0]; // ok
|
||||
}
|
||||
|
||||
let _ = &good.data; //~ ERROR borrow of packed field requires unsafe
|
||||
//~| hard error
|
||||
let _ = &good.data2[0]; //~ ERROR borrow of packed field requires unsafe
|
||||
//~| hard error
|
||||
let _ = &*good.data; // ok, behind a pointer
|
||||
let _ = &good.aligned; // ok, has align 1
|
||||
let _ = &good.aligned[2]; // ok, has align 1
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue