Skip to content

Commit d7787bb

Browse files
Check for calls to functions with #[target_feature] in THIR unsafeck
1 parent 27fe959 commit d7787bb

File tree

9 files changed

+147
-15
lines changed

9 files changed

+147
-15
lines changed

compiler/rustc_mir_build/src/check_unsafety.rs

+27-4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ 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

1213
struct UnsafetyVisitor<'a, 'tcx> {
@@ -19,6 +20,9 @@ struct UnsafetyVisitor<'a, 'tcx> {
1920
/// `unsafe` block, and whether it has been used.
2021
safety_context: SafetyContext,
2122
body_unsafety: BodyUnsafety,
23+
/// The `#[target_feature]` attributes of the body. Used for checking
24+
/// calls to functions with `#[target_feature]` (RFC 2396).
25+
body_target_features: &'tcx Vec<Symbol>,
2226
}
2327

2428
impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
@@ -148,6 +152,18 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
148152
ExprKind::Call { fun, ty: _, args: _, from_hir_call: _, fn_span: _ } => {
149153
if self.thir[fun].ty.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe {
150154
self.requires_unsafe(expr.span, CallToUnsafeFunction);
155+
} else if let &ty::FnDef(func_did, _) = self.thir[fun].ty.kind() {
156+
// If the called function has target features the calling function hasn't,
157+
// the call requires `unsafe`.
158+
if !self
159+
.tcx
160+
.codegen_fn_attrs(func_did)
161+
.target_features
162+
.iter()
163+
.all(|feature| self.body_target_features.contains(feature))
164+
{
165+
self.requires_unsafe(expr.span, CallToFunctionWith);
166+
}
151167
}
152168
}
153169
ExprKind::InlineAsm { .. } | ExprKind::LlvmInlineAsm { .. } => {
@@ -217,7 +233,6 @@ enum UnsafeOpKind {
217233
MutationOfLayoutConstrainedField,
218234
#[allow(dead_code)] // FIXME
219235
BorrowOfLayoutConstrainedField,
220-
#[allow(dead_code)] // FIXME
221236
CallToFunctionWith,
222237
}
223238

@@ -291,6 +306,7 @@ pub fn check_unsafety<'tcx>(
291306
tcx: TyCtxt<'tcx>,
292307
thir: &Thir<'tcx>,
293308
expr: ExprId,
309+
def_id: LocalDefId,
294310
hir_id: hir::HirId,
295311
) {
296312
let body_unsafety = tcx.hir().fn_sig_by_hir_id(hir_id).map_or(BodyUnsafety::Safe, |fn_sig| {
@@ -300,10 +316,17 @@ pub fn check_unsafety<'tcx>(
300316
BodyUnsafety::Safe
301317
}
302318
});
319+
let body_target_features = &tcx.codegen_fn_attrs(def_id).target_features;
303320
let safety_context =
304321
if body_unsafety.is_unsafe() { SafetyContext::UnsafeFn } else { SafetyContext::Safe };
305-
let mut visitor =
306-
UnsafetyVisitor { tcx, thir, safety_context, hir_context: hir_id, body_unsafety };
322+
let mut visitor = UnsafetyVisitor {
323+
tcx,
324+
thir,
325+
safety_context,
326+
hir_context: hir_id,
327+
body_unsafety,
328+
body_target_features,
329+
};
307330
visitor.visit_expr(&thir[expr]);
308331
}
309332

@@ -315,7 +338,7 @@ crate fn thir_check_unsafety_inner<'tcx>(
315338
let body_id = tcx.hir().body_owned_by(hir_id);
316339
let body = tcx.hir().body(body_id);
317340
let (thir, expr) = cx::build_thir(tcx, def, &body.value);
318-
check_unsafety(tcx, &thir, expr, hir_id);
341+
check_unsafety(tcx, &thir, expr, def.did, hir_id);
319342
}
320343

321344
crate fn thir_check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {

src/test/ui/rfcs/rfc-2396-target_feature-11/check-pass.rs

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
// check-pass
1010
// only-x86_64
11+
// revisions: mir thir
12+
// [thir]compile-flags: -Z thir-unsafeck
1113

1214
#![feature(target_feature_11)]
1315

src/test/ui/rfcs/rfc-2396-target_feature-11/closures-inherit-target_feature.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Tests #73631: closures inherit `#[target_feature]` annotations
22

33
// check-pass
4+
// revisions: mir thir
5+
// [thir]compile-flags: -Z thir-unsafeck
46
// only-x86_64
57

68
#![feature(target_feature_11)]

src/test/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.stderr renamed to src/test/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0308]: mismatched types
2-
--> $DIR/fn-ptr.rs:9:21
2+
--> $DIR/fn-ptr.rs:11:21
33
|
44
LL | #[target_feature(enable = "sse2")]
55
| ---------------------------------- `#[target_feature]` added here

src/test/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// revisions: mir thir
2+
// [thir]compile-flags: -Z thir-unsafeck
13
// only-x86_64
24

35
#![feature(target_feature_11)]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/fn-ptr.rs:11:21
3+
|
4+
LL | #[target_feature(enable = "sse2")]
5+
| ---------------------------------- `#[target_feature]` added here
6+
...
7+
LL | let foo: fn() = foo;
8+
| ---- ^^^ cannot coerce functions with `#[target_feature]` to safe function pointers
9+
| |
10+
| expected due to this
11+
|
12+
= note: expected fn pointer `fn()`
13+
found fn item `fn() {foo}`
14+
= note: functions with `#[target_feature]` can only be coerced to `unsafe` function pointers
15+
16+
error: aborting due to previous error
17+
18+
For more information about this error, try `rustc --explain E0308`.

src/test/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr renamed to src/test/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,77 @@
11
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
2-
--> $DIR/safe-calls.rs:21:5
2+
--> $DIR/safe-calls.rs:23:5
33
|
44
LL | sse2();
55
| ^^^^^^ call to function with `#[target_feature]`
66
|
77
= note: can only be called if the required target features are available
88

99
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
10-
--> $DIR/safe-calls.rs:22:5
10+
--> $DIR/safe-calls.rs:24:5
1111
|
1212
LL | avx_bmi2();
1313
| ^^^^^^^^^^ call to function with `#[target_feature]`
1414
|
1515
= note: can only be called if the required target features are available
1616

1717
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
18-
--> $DIR/safe-calls.rs:23:5
18+
--> $DIR/safe-calls.rs:25:5
1919
|
2020
LL | Quux.avx_bmi2();
2121
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
2222
|
2323
= note: can only be called if the required target features are available
2424

2525
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
26-
--> $DIR/safe-calls.rs:28:5
26+
--> $DIR/safe-calls.rs:30:5
2727
|
2828
LL | avx_bmi2();
2929
| ^^^^^^^^^^ call to function with `#[target_feature]`
3030
|
3131
= note: can only be called if the required target features are available
3232

3333
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
34-
--> $DIR/safe-calls.rs:29:5
34+
--> $DIR/safe-calls.rs:31:5
3535
|
3636
LL | Quux.avx_bmi2();
3737
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
3838
|
3939
= note: can only be called if the required target features are available
4040

4141
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
42-
--> $DIR/safe-calls.rs:34:5
42+
--> $DIR/safe-calls.rs:36:5
4343
|
4444
LL | sse2();
4545
| ^^^^^^ call to function with `#[target_feature]`
4646
|
4747
= note: can only be called if the required target features are available
4848

4949
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
50-
--> $DIR/safe-calls.rs:35:5
50+
--> $DIR/safe-calls.rs:37:5
5151
|
5252
LL | avx_bmi2();
5353
| ^^^^^^^^^^ call to function with `#[target_feature]`
5454
|
5555
= note: can only be called if the required target features are available
5656

5757
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
58-
--> $DIR/safe-calls.rs:36:5
58+
--> $DIR/safe-calls.rs:38:5
5959
|
6060
LL | Quux.avx_bmi2();
6161
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
6262
|
6363
= note: can only be called if the required target features are available
6464

6565
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
66-
--> $DIR/safe-calls.rs:42:5
66+
--> $DIR/safe-calls.rs:44:5
6767
|
6868
LL | sse2();
6969
| ^^^^^^ call to function with `#[target_feature]`
7070
|
7171
= note: can only be called if the required target features are available
7272

7373
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
74-
--> $DIR/safe-calls.rs:45:18
74+
--> $DIR/safe-calls.rs:47:18
7575
|
7676
LL | const name: () = sse2();
7777
| ^^^^^^ call to function with `#[target_feature]`

src/test/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// revisions: mir thir
2+
// [thir]compile-flags: -Z thir-unsafeck
13
// only-x86_64
24

35
#![feature(target_feature_11)]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
2+
--> $DIR/safe-calls.rs:23:5
3+
|
4+
LL | sse2();
5+
| ^^^^^^ call to function with `#[target_feature]`
6+
|
7+
= note: can only be called if the required target features are available
8+
9+
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
10+
--> $DIR/safe-calls.rs:24:5
11+
|
12+
LL | avx_bmi2();
13+
| ^^^^^^^^^^ call to function with `#[target_feature]`
14+
|
15+
= note: can only be called if the required target features are available
16+
17+
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
18+
--> $DIR/safe-calls.rs:25:5
19+
|
20+
LL | Quux.avx_bmi2();
21+
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
22+
|
23+
= note: can only be called if the required target features are available
24+
25+
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
26+
--> $DIR/safe-calls.rs:30:5
27+
|
28+
LL | avx_bmi2();
29+
| ^^^^^^^^^^ call to function with `#[target_feature]`
30+
|
31+
= note: can only be called if the required target features are available
32+
33+
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
34+
--> $DIR/safe-calls.rs:31:5
35+
|
36+
LL | Quux.avx_bmi2();
37+
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
38+
|
39+
= note: can only be called if the required target features are available
40+
41+
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
42+
--> $DIR/safe-calls.rs:36:5
43+
|
44+
LL | sse2();
45+
| ^^^^^^ call to function with `#[target_feature]`
46+
|
47+
= note: can only be called if the required target features are available
48+
49+
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
50+
--> $DIR/safe-calls.rs:37:5
51+
|
52+
LL | avx_bmi2();
53+
| ^^^^^^^^^^ call to function with `#[target_feature]`
54+
|
55+
= note: can only be called if the required target features are available
56+
57+
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
58+
--> $DIR/safe-calls.rs:38:5
59+
|
60+
LL | Quux.avx_bmi2();
61+
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
62+
|
63+
= note: can only be called if the required target features are available
64+
65+
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
66+
--> $DIR/safe-calls.rs:44:5
67+
|
68+
LL | sse2();
69+
| ^^^^^^ call to function with `#[target_feature]`
70+
|
71+
= note: can only be called if the required target features are available
72+
73+
error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block
74+
--> $DIR/safe-calls.rs:47:18
75+
|
76+
LL | const name: () = sse2();
77+
| ^^^^^^ call to function with `#[target_feature]`
78+
|
79+
= note: can only be called if the required target features are available
80+
81+
error: aborting due to 10 previous errors
82+
83+
For more information about this error, try `rustc --explain E0133`.

0 commit comments

Comments
 (0)