Skip to content

Commit 0f48e63

Browse files
Rollup merge of #85555 - LeSeulArtichaut:thir-unsafeck, r=nikomatsakis
Check for more things in THIR unsafeck Reunion of #85306, #85381 and #85419 with conflicts resolved. r? `@nikomatsakis`
2 parents 9ec88ce + 0e1afc4 commit 0f48e63

File tree

67 files changed

+645
-66
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+645
-66
lines changed

compiler/rustc_mir_build/src/check_unsafety.rs

+68-9
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@ use rustc_middle::ty::{self, TyCtxt};
77
use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE};
88
use rustc_session::lint::Level;
99
use rustc_span::def_id::{DefId, LocalDefId};
10+
use rustc_span::symbol::Symbol;
1011
use rustc_span::Span;
1112

13+
use std::ops::Bound;
14+
1215
struct UnsafetyVisitor<'a, 'tcx> {
1316
tcx: TyCtxt<'tcx>,
1417
thir: &'a Thir<'tcx>,
@@ -19,6 +22,10 @@ struct UnsafetyVisitor<'a, 'tcx> {
1922
/// `unsafe` block, and whether it has been used.
2023
safety_context: SafetyContext,
2124
body_unsafety: BodyUnsafety,
25+
/// The `#[target_feature]` attributes of the body. Used for checking
26+
/// calls to functions with `#[target_feature]` (RFC 2396).
27+
body_target_features: &'tcx Vec<Symbol>,
28+
is_const: bool,
2229
}
2330

2431
impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
@@ -148,11 +155,55 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
148155
ExprKind::Call { fun, ty: _, args: _, from_hir_call: _, fn_span: _ } => {
149156
if self.thir[fun].ty.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe {
150157
self.requires_unsafe(expr.span, CallToUnsafeFunction);
158+
} else if let &ty::FnDef(func_did, _) = self.thir[fun].ty.kind() {
159+
// If the called function has target features the calling function hasn't,
160+
// the call requires `unsafe`.
161+
if !self
162+
.tcx
163+
.codegen_fn_attrs(func_did)
164+
.target_features
165+
.iter()
166+
.all(|feature| self.body_target_features.contains(feature))
167+
{
168+
self.requires_unsafe(expr.span, CallToFunctionWith);
169+
}
170+
}
171+
}
172+
ExprKind::Deref { arg } => {
173+
if let ExprKind::StaticRef { def_id, .. } = self.thir[arg].kind {
174+
if self.tcx.is_mutable_static(def_id) {
175+
self.requires_unsafe(expr.span, UseOfMutableStatic);
176+
} else if self.tcx.is_foreign_item(def_id) {
177+
self.requires_unsafe(expr.span, UseOfExternStatic);
178+
}
179+
} else if self.thir[arg].ty.is_unsafe_ptr() {
180+
self.requires_unsafe(expr.span, DerefOfRawPointer);
151181
}
152182
}
153183
ExprKind::InlineAsm { .. } | ExprKind::LlvmInlineAsm { .. } => {
154184
self.requires_unsafe(expr.span, UseOfInlineAssembly);
155185
}
186+
ExprKind::Adt {
187+
adt_def,
188+
variant_index: _,
189+
substs: _,
190+
user_ty: _,
191+
fields: _,
192+
base: _,
193+
} => match self.tcx.layout_scalar_valid_range(adt_def.did) {
194+
(Bound::Unbounded, Bound::Unbounded) => {}
195+
_ => self.requires_unsafe(expr.span, InitializingTypeWith),
196+
},
197+
ExprKind::Cast { source } => {
198+
let source = &self.thir[source];
199+
if self.tcx.features().const_raw_ptr_to_usize_cast
200+
&& self.is_const
201+
&& (source.ty.is_unsafe_ptr() || source.ty.is_fn_ptr())
202+
&& expr.ty.is_integral()
203+
{
204+
self.requires_unsafe(expr.span, CastOfPointerToInt);
205+
}
206+
}
156207
_ => {}
157208
}
158209

@@ -195,15 +246,10 @@ impl BodyUnsafety {
195246
enum UnsafeOpKind {
196247
CallToUnsafeFunction,
197248
UseOfInlineAssembly,
198-
#[allow(dead_code)] // FIXME
199249
InitializingTypeWith,
200-
#[allow(dead_code)] // FIXME
201250
CastOfPointerToInt,
202-
#[allow(dead_code)] // FIXME
203251
UseOfMutableStatic,
204-
#[allow(dead_code)] // FIXME
205252
UseOfExternStatic,
206-
#[allow(dead_code)] // FIXME
207253
DerefOfRawPointer,
208254
#[allow(dead_code)] // FIXME
209255
AssignToDroppingUnionField,
@@ -213,7 +259,6 @@ enum UnsafeOpKind {
213259
MutationOfLayoutConstrainedField,
214260
#[allow(dead_code)] // FIXME
215261
BorrowOfLayoutConstrainedField,
216-
#[allow(dead_code)] // FIXME
217262
CallToFunctionWith,
218263
}
219264

@@ -287,6 +332,7 @@ pub fn check_unsafety<'tcx>(
287332
tcx: TyCtxt<'tcx>,
288333
thir: &Thir<'tcx>,
289334
expr: ExprId,
335+
def_id: LocalDefId,
290336
hir_id: hir::HirId,
291337
) {
292338
let body_unsafety = tcx.hir().fn_sig_by_hir_id(hir_id).map_or(BodyUnsafety::Safe, |fn_sig| {
@@ -296,10 +342,23 @@ pub fn check_unsafety<'tcx>(
296342
BodyUnsafety::Safe
297343
}
298344
});
345+
let body_target_features = &tcx.codegen_fn_attrs(def_id).target_features;
299346
let safety_context =
300347
if body_unsafety.is_unsafe() { SafetyContext::UnsafeFn } else { SafetyContext::Safe };
301-
let mut visitor =
302-
UnsafetyVisitor { tcx, thir, safety_context, hir_context: hir_id, body_unsafety };
348+
let is_const = match tcx.hir().body_owner_kind(hir_id) {
349+
hir::BodyOwnerKind::Closure => false,
350+
hir::BodyOwnerKind::Fn => tcx.is_const_fn_raw(def_id.to_def_id()),
351+
hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => true,
352+
};
353+
let mut visitor = UnsafetyVisitor {
354+
tcx,
355+
thir,
356+
safety_context,
357+
hir_context: hir_id,
358+
body_unsafety,
359+
body_target_features,
360+
is_const,
361+
};
303362
visitor.visit_expr(&thir[expr]);
304363
}
305364

@@ -311,7 +370,7 @@ crate fn thir_check_unsafety_inner<'tcx>(
311370
let body_id = tcx.hir().body_owned_by(hir_id);
312371
let body = tcx.hir().body(body_id);
313372
let (thir, expr) = cx::build_thir(tcx, def, &body.value);
314-
check_unsafety(tcx, &thir, expr, hir_id);
373+
check_unsafety(tcx, &thir, expr, def.did, hir_id);
315374
}
316375

317376
crate fn thir_check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0133]: cast of pointer to int is unsafe and requires unsafe function or block
2+
--> $DIR/cast-ptr-to-int-const.rs:10:9
3+
|
4+
LL | &Y as *const u32 as usize
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ cast of pointer to int
6+
|
7+
= note: casting pointers to integers in constants
8+
9+
error[E0133]: cast of pointer to int is unsafe and requires unsafe function or block
10+
--> $DIR/cast-ptr-to-int-const.rs:17:5
11+
|
12+
LL | &0 as *const i32 as usize
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ cast of pointer to int
14+
|
15+
= note: casting pointers to integers in constants
16+
17+
error: aborting due to 2 previous errors
18+
19+
For more information about this error, try `rustc --explain E0133`.
+7-13
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,19 @@
1-
// gate-test-const_raw_ptr_to_usize_cast
2-
// revisions: with_feature without_feature
1+
// revisions: mir thir
2+
// [thir]compile-flags: -Z thir-unsafeck
33

4-
#![cfg_attr(with_feature, feature(const_raw_ptr_to_usize_cast))]
4+
#![feature(const_raw_ptr_to_usize_cast)]
55

66
fn main() {
7-
const X: usize = unsafe {
8-
main as usize //[without_feature]~ ERROR casting pointers to integers in constants is unstable
9-
};
107
const Y: u32 = 0;
11-
const Z: usize = unsafe {
12-
&Y as *const u32 as usize //[without_feature]~ ERROR is unstable
13-
};
148
// Cast in `const` without `unsafe` block
159
const SAFE: usize = {
16-
&Y as *const u32 as usize //[without_feature]~ ERROR is unstable
17-
//[with_feature]~^ ERROR cast of pointer to int is unsafe and requires unsafe
10+
&Y as *const u32 as usize
11+
//~^ ERROR cast of pointer to int is unsafe and requires unsafe
1812
};
1913
}
2014

2115
// Cast in `const fn` without `unsafe` block
2216
const fn test() -> usize {
23-
&0 as *const i32 as usize //[without_feature]~ ERROR is unstable
24-
//[with_feature]~^ ERROR cast of pointer to int is unsafe and requires unsafe
17+
&0 as *const i32 as usize
18+
//~^ ERROR cast of pointer to int is unsafe and requires unsafe
2519
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0133]: cast of pointer to int is unsafe and requires unsafe function or block
2+
--> $DIR/cast-ptr-to-int-const.rs:10:9
3+
|
4+
LL | &Y as *const u32 as usize
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ cast of pointer to int
6+
|
7+
= note: casting pointers to integers in constants
8+
9+
error[E0133]: cast of pointer to int is unsafe and requires unsafe function or block
10+
--> $DIR/cast-ptr-to-int-const.rs:17:5
11+
|
12+
LL | &0 as *const i32 as usize
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ cast of pointer to int
14+
|
15+
= note: casting pointers to integers in constants
16+
17+
error: aborting due to 2 previous errors
18+
19+
For more information about this error, try `rustc --explain E0133`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
fn main() {
2+
const X: usize = unsafe {
3+
main as usize //~ ERROR casting pointers to integers in constants is unstable
4+
};
5+
const Y: u32 = 0;
6+
const Z: usize = unsafe {
7+
&Y as *const u32 as usize //~ ERROR is unstable
8+
};
9+
}
10+
11+
const fn test() -> usize {
12+
&0 as *const i32 as usize //~ ERROR is unstable
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
error[E0658]: casting pointers to integers in constants is unstable
2+
--> $DIR/feature-gate-const_raw_ptr_to_usize_cast.rs:3:9
3+
|
4+
LL | main as usize
5+
| ^^^^^^^^^^^^^
6+
|
7+
= note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
8+
= help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
9+
10+
error[E0658]: casting pointers to integers in constants is unstable
11+
--> $DIR/feature-gate-const_raw_ptr_to_usize_cast.rs:7:9
12+
|
13+
LL | &Y as *const u32 as usize
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
15+
|
16+
= note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
17+
= help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
18+
19+
error[E0658]: casting pointers to integers in constant functions is unstable
20+
--> $DIR/feature-gate-const_raw_ptr_to_usize_cast.rs:12:5
21+
|
22+
LL | &0 as *const i32 as usize
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
24+
|
25+
= note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
26+
= help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
27+
28+
error: aborting due to 3 previous errors
29+
30+
For more information about this error, try `rustc --explain E0658`.

src/test/ui/generator/issue-45729-unsafe-in-generator.stderr src/test/ui/generator/issue-45729-unsafe-in-generator.mir.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
2-
--> $DIR/issue-45729-unsafe-in-generator.rs:5:9
2+
--> $DIR/issue-45729-unsafe-in-generator.rs:8:9
33
|
44
LL | *(1 as *mut u32) = 42;
55
| ^^^^^^^^^^^^^^^^^^^^^ dereference of raw pointer

src/test/ui/generator/issue-45729-unsafe-in-generator.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// revisions: mir thir
2+
// [thir]compile-flags: -Z thir-unsafeck
3+
14
#![feature(generators)]
25

36
fn main() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
2+
--> $DIR/issue-45729-unsafe-in-generator.rs:8:9
3+
|
4+
LL | *(1 as *mut u32) = 42;
5+
| ^^^^^^^^^^^^^^^^ dereference of raw pointer
6+
|
7+
= note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0133`.

src/test/ui/intrinsics/issue-28575.stderr src/test/ui/intrinsics/issue-28575.mir.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0133]: use of extern static is unsafe and requires unsafe function or block
2-
--> $DIR/issue-28575.rs:8:5
2+
--> $DIR/issue-28575.rs:11:5
33
|
44
LL | FOO()
55
| ^^^ use of extern static

src/test/ui/intrinsics/issue-28575.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// revisions: mir thir
2+
// [thir]compile-flags: -Z thir-unsafeck
3+
14
#![feature(intrinsics)]
25

36
extern "C" {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0133]: use of extern static is unsafe and requires unsafe function or block
2+
--> $DIR/issue-28575.rs:11:5
3+
|
4+
LL | FOO()
5+
| ^^^ use of extern static
6+
|
7+
= note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0133`.

src/test/ui/issues/issue-14227.stderr src/test/ui/issues/issue-14227.mir.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0133]: use of extern static is unsafe and requires unsafe function or block
2-
--> $DIR/issue-14227.rs:4:21
2+
--> $DIR/issue-14227.rs:7:21
33
|
44
LL | static CRASH: u32 = symbol;
55
| ^^^^^^ use of extern static

src/test/ui/issues/issue-14227.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// revisions: mir thir
2+
// [thir]compile-flags: -Z thir-unsafeck
3+
14
extern "C" {
25
pub static symbol: u32;
36
}
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0133]: use of extern static is unsafe and requires unsafe function or block
2+
--> $DIR/issue-14227.rs:7:21
3+
|
4+
LL | static CRASH: u32 = symbol;
5+
| ^^^^^^ use of extern static
6+
|
7+
= note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0133`.

src/test/ui/issues/issue-16538.stderr src/test/ui/issues/issue-16538.mir.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
2-
--> $DIR/issue-16538.rs:11:27
2+
--> $DIR/issue-16538.rs:14:27
33
|
44
LL | static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
66

77
error[E0277]: `*const usize` cannot be shared between threads safely
8-
--> $DIR/issue-16538.rs:11:1
8+
--> $DIR/issue-16538.rs:14:1
99
|
1010
LL | static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const usize` cannot be shared between threads safely
@@ -14,7 +14,7 @@ LL | static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
1414
= note: shared static variables must have a type that implements `Sync`
1515

1616
error[E0133]: use of extern static is unsafe and requires unsafe function or block
17-
--> $DIR/issue-16538.rs:11:34
17+
--> $DIR/issue-16538.rs:14:34
1818
|
1919
LL | static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
2020
| ^^^^ use of extern static

src/test/ui/issues/issue-16538.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// revisions: mir thir
2+
// [thir]compile-flags: -Z thir-unsafeck
3+
14
mod Y {
25
pub type X = usize;
36
extern "C" {
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
2+
--> $DIR/issue-16538.rs:14:27
3+
|
4+
LL | static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
7+
error[E0277]: `*const usize` cannot be shared between threads safely
8+
--> $DIR/issue-16538.rs:14:1
9+
|
10+
LL | static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const usize` cannot be shared between threads safely
12+
|
13+
= help: the trait `Sync` is not implemented for `*const usize`
14+
= note: shared static variables must have a type that implements `Sync`
15+
16+
error[E0133]: use of extern static is unsafe and requires unsafe function or block
17+
--> $DIR/issue-16538.rs:14:34
18+
|
19+
LL | static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
20+
| ^^^^ use of extern static
21+
|
22+
= note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
23+
24+
error: aborting due to 3 previous errors
25+
26+
Some errors have detailed explanations: E0015, E0133, E0277.
27+
For more information about an error, try `rustc --explain E0015`.

0 commit comments

Comments
 (0)