Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit aba5ea1

Browse files
committed
Lint on function pointers used in patterns
1 parent 3795886 commit aba5ea1

File tree

6 files changed

+97
-3
lines changed

6 files changed

+97
-3
lines changed

compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,10 +351,27 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
351351
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::FnDef(..) => {
352352
PatKind::Constant { value: cv }
353353
}
354+
ty::RawPtr(pointee) if pointee.ty.is_sized(tcx.at(span), param_env) => {
355+
PatKind::Constant { value: cv }
356+
}
354357
// FIXME: these can have very suprising behaviour where optimization levels or other
355358
// compilation choices change the runtime behaviour of the match.
356359
// See https://github.com/rust-lang/rust/issues/70861 for examples.
357-
ty::FnPtr(..) | ty::RawPtr(..) => PatKind::Constant { value: cv },
360+
ty::FnPtr(..) | ty::RawPtr(..) => {
361+
if self.include_lint_checks && !self.saw_const_match_error.get() {
362+
self.saw_const_match_error.set(true);
363+
let msg = "function pointers and unsized pointers in patterns do not behave \
364+
deterministically. \
365+
See https://github.com/rust-lang/rust/issues/70861 for details.";
366+
tcx.struct_span_lint_hir(
367+
lint::builtin::POINTER_STRUCTURAL_MATCH,
368+
id,
369+
span,
370+
|lint| lint.build(&msg).emit(),
371+
);
372+
}
373+
PatKind::Constant { value: cv }
374+
}
358375
_ => {
359376
tcx.sess.delay_span_bug(span, &format!("cannot make a pattern out of {}", cv.ty));
360377
PatKind::Wild

compiler/rustc_session/src/lint/builtin.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2197,6 +2197,32 @@ declare_lint! {
21972197
report_in_external_macro
21982198
}
21992199

2200+
declare_lint! {
2201+
/// The `pointer_structural_match` lint detects pointers used in patterns that do not
2202+
/// behave deterministically across optimizations.
2203+
///
2204+
/// ### Example
2205+
///
2206+
/// ```rust,compile_fail
2207+
/// #![deny(pointer_structural_match)]
2208+
/// fn foo(a: usize, b: usize) -> usize { a + b }
2209+
/// const FOO: fn(usize, usize) -> usize = foo;
2210+
/// fn main() {
2211+
/// match FOO {
2212+
/// FOO => {},
2213+
/// _ => {},
2214+
/// }
2215+
/// }
2216+
/// ```
2217+
pub POINTER_STRUCTURAL_MATCH,
2218+
Allow,
2219+
"pointers are not structural-match",
2220+
@future_incompatible = FutureIncompatibleInfo {
2221+
reference: "issue #62411 <https://github.com/rust-lang/rust/issues/70861>",
2222+
edition: None,
2223+
};
2224+
}
2225+
22002226
declare_lint! {
22012227
/// The `ambiguous_associated_items` lint detects ambiguity between
22022228
/// [associated items] and [enum variants].
@@ -2630,6 +2656,7 @@ declare_lint_pass! {
26302656
AMBIGUOUS_ASSOCIATED_ITEMS,
26312657
MUTABLE_BORROW_RESERVATION_CONFLICT,
26322658
INDIRECT_STRUCTURAL_MATCH,
2659+
POINTER_STRUCTURAL_MATCH,
26332660
SOFT_UNSTABLE,
26342661
INLINE_NO_SANITIZE,
26352662
ASM_SUB_REGISTER,

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
// run-pass
2+
3+
#![warn(pointer_structural_match)]
4+
25
type Func = fn(usize, usize) -> usize;
36

47
fn foo(a: usize, b: usize) -> usize { a + b }
@@ -13,8 +16,10 @@ const BAR: Func = bar;
1316

1417
fn main() {
1518
match test(std::env::consts::ARCH.len()) {
16-
FOO => println!("foo"),
17-
BAR => println!("bar"),
19+
FOO => println!("foo"), //~ WARN pointers in patterns do not behave deterministically
20+
//~^ WARN will become a hard error
21+
BAR => println!("bar"), //~ WARN pointers in patterns do not behave deterministically
22+
//~^ WARN will become a hard error
1823
_ => unreachable!(),
1924
}
2025
}

src/test/ui/issues/issue-44333.stderr

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
warning: function pointers and unsized pointers in patterns do not behave deterministically. See https://github.com/rust-lang/rust/issues/70861 for details.
2+
--> $DIR/issue-44333.rs:19:9
3+
|
4+
LL | FOO => println!("foo"),
5+
| ^^^
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/issue-44333.rs:3:9
9+
|
10+
LL | #![warn(pointer_structural_match)]
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^
12+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
13+
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
14+
15+
warning: function pointers and unsized pointers in patterns do not behave deterministically. See https://github.com/rust-lang/rust/issues/70861 for details.
16+
--> $DIR/issue-44333.rs:21:9
17+
|
18+
LL | BAR => println!("bar"),
19+
| ^^^
20+
|
21+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
22+
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
23+
24+
warning: 2 warnings emitted
25+

src/test/ui/rfc1445/issue-63479-match-fnptr.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
// cover the case this hit; I've since expanded it accordingly, but the
66
// experience left me wary of leaving this regression test out.)
77

8+
#![warn(pointer_structural_match)]
9+
810
#[derive(Eq)]
911
struct A {
1012
a: i64
@@ -31,6 +33,8 @@ fn main() {
3133
let s = B(my_fn);
3234
match s {
3335
B(TEST) => println!("matched"),
36+
//~^ WARN pointers in patterns do not behave deterministically
37+
//~| WARN this was previously accepted by the compiler but is being phased out
3438
_ => panic!("didn't match")
3539
};
3640
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
warning: function pointers and unsized pointers in patterns do not behave deterministically. See https://github.com/rust-lang/rust/issues/70861 for details.
2+
--> $DIR/issue-63479-match-fnptr.rs:35:7
3+
|
4+
LL | B(TEST) => println!("matched"),
5+
| ^^^^
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/issue-63479-match-fnptr.rs:8:9
9+
|
10+
LL | #![warn(pointer_structural_match)]
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^
12+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
13+
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
14+
15+
warning: 1 warning emitted
16+

0 commit comments

Comments
 (0)