diff options
| author | Oliver Scherer <github35764891676564198441@oli-obk.de> | 2020-09-20 17:11:00 +0200 |
|---|---|---|
| committer | Oliver Scherer <github35764891676564198441@oli-obk.de> | 2020-09-20 18:42:15 +0200 |
| commit | aba5ea1430df393eddc90068e838de6b1707c0d8 (patch) | |
| tree | 928e31eed00839be4f11e561811f1a48b45062a5 | |
| parent | 3795886f7e1f3dc5f5dd207ba4a7c092fe929486 (diff) | |
| download | rust-aba5ea1430df393eddc90068e838de6b1707c0d8.tar.gz rust-aba5ea1430df393eddc90068e838de6b1707c0d8.zip | |
Lint on function pointers used in patterns
| -rw-r--r-- | compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs | 19 | ||||
| -rw-r--r-- | compiler/rustc_session/src/lint/builtin.rs | 27 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-44333.rs | 9 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-44333.stderr | 25 | ||||
| -rw-r--r-- | src/test/ui/rfc1445/issue-63479-match-fnptr.rs | 4 | ||||
| -rw-r--r-- | src/test/ui/rfc1445/issue-63479-match-fnptr.stderr | 16 |
6 files changed, 97 insertions, 3 deletions
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index ebb71ea24ec..6ca1ff2c5f2 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -351,10 +351,27 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::FnDef(..) => { PatKind::Constant { value: cv } } + ty::RawPtr(pointee) if pointee.ty.is_sized(tcx.at(span), param_env) => { + PatKind::Constant { value: cv } + } // FIXME: these can have very suprising behaviour where optimization levels or other // compilation choices change the runtime behaviour of the match. // See https://github.com/rust-lang/rust/issues/70861 for examples. - ty::FnPtr(..) | ty::RawPtr(..) => PatKind::Constant { value: cv }, + ty::FnPtr(..) | ty::RawPtr(..) => { + if self.include_lint_checks && !self.saw_const_match_error.get() { + self.saw_const_match_error.set(true); + let msg = "function pointers and unsized pointers in patterns do not behave \ + deterministically. \ + See https://github.com/rust-lang/rust/issues/70861 for details."; + tcx.struct_span_lint_hir( + lint::builtin::POINTER_STRUCTURAL_MATCH, + id, + span, + |lint| lint.build(&msg).emit(), + ); + } + PatKind::Constant { value: cv } + } _ => { tcx.sess.delay_span_bug(span, &format!("cannot make a pattern out of {}", cv.ty)); PatKind::Wild diff --git a/compiler/rustc_session/src/lint/builtin.rs b/compiler/rustc_session/src/lint/builtin.rs index 562df176b14..c72b97fa1ca 100644 --- a/compiler/rustc_session/src/lint/builtin.rs +++ b/compiler/rustc_session/src/lint/builtin.rs @@ -2198,6 +2198,32 @@ declare_lint! { } declare_lint! { + /// The `pointer_structural_match` lint detects pointers used in patterns that do not + /// behave deterministically across optimizations. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(pointer_structural_match)] + /// fn foo(a: usize, b: usize) -> usize { a + b } + /// const FOO: fn(usize, usize) -> usize = foo; + /// fn main() { + /// match FOO { + /// FOO => {}, + /// _ => {}, + /// } + /// } + /// ``` + pub POINTER_STRUCTURAL_MATCH, + Allow, + "pointers are not structural-match", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #62411 <https://github.com/rust-lang/rust/issues/70861>", + edition: None, + }; +} + +declare_lint! { /// The `ambiguous_associated_items` lint detects ambiguity between /// [associated items] and [enum variants]. /// @@ -2630,6 +2656,7 @@ declare_lint_pass! { AMBIGUOUS_ASSOCIATED_ITEMS, MUTABLE_BORROW_RESERVATION_CONFLICT, INDIRECT_STRUCTURAL_MATCH, + POINTER_STRUCTURAL_MATCH, SOFT_UNSTABLE, INLINE_NO_SANITIZE, ASM_SUB_REGISTER, diff --git a/src/test/ui/issues/issue-44333.rs b/src/test/ui/issues/issue-44333.rs index fffef975043..85f5ccbdb65 100644 --- a/src/test/ui/issues/issue-44333.rs +++ b/src/test/ui/issues/issue-44333.rs @@ -1,4 +1,7 @@ // run-pass + +#![warn(pointer_structural_match)] + type Func = fn(usize, usize) -> usize; fn foo(a: usize, b: usize) -> usize { a + b } @@ -13,8 +16,10 @@ const BAR: Func = bar; fn main() { match test(std::env::consts::ARCH.len()) { - FOO => println!("foo"), - BAR => println!("bar"), + FOO => println!("foo"), //~ WARN pointers in patterns do not behave deterministically + //~^ WARN will become a hard error + BAR => println!("bar"), //~ WARN pointers in patterns do not behave deterministically + //~^ WARN will become a hard error _ => unreachable!(), } } diff --git a/src/test/ui/issues/issue-44333.stderr b/src/test/ui/issues/issue-44333.stderr new file mode 100644 index 00000000000..a9ee5fc4dd7 --- /dev/null +++ b/src/test/ui/issues/issue-44333.stderr @@ -0,0 +1,25 @@ +warning: function pointers and unsized pointers in patterns do not behave deterministically. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-44333.rs:19:9 + | +LL | FOO => println!("foo"), + | ^^^ + | +note: the lint level is defined here + --> $DIR/issue-44333.rs:3:9 + | +LL | #![warn(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + = 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 #62411 <https://github.com/rust-lang/rust/issues/70861> + +warning: function pointers and unsized pointers in patterns do not behave deterministically. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-44333.rs:21:9 + | +LL | BAR => println!("bar"), + | ^^^ + | + = 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 #62411 <https://github.com/rust-lang/rust/issues/70861> + +warning: 2 warnings emitted + diff --git a/src/test/ui/rfc1445/issue-63479-match-fnptr.rs b/src/test/ui/rfc1445/issue-63479-match-fnptr.rs index b3c91cec580..0984b1d480e 100644 --- a/src/test/ui/rfc1445/issue-63479-match-fnptr.rs +++ b/src/test/ui/rfc1445/issue-63479-match-fnptr.rs @@ -5,6 +5,8 @@ // cover the case this hit; I've since expanded it accordingly, but the // experience left me wary of leaving this regression test out.) +#![warn(pointer_structural_match)] + #[derive(Eq)] struct A { a: i64 @@ -31,6 +33,8 @@ fn main() { let s = B(my_fn); match s { B(TEST) => println!("matched"), + //~^ WARN pointers in patterns do not behave deterministically + //~| WARN this was previously accepted by the compiler but is being phased out _ => panic!("didn't match") }; } diff --git a/src/test/ui/rfc1445/issue-63479-match-fnptr.stderr b/src/test/ui/rfc1445/issue-63479-match-fnptr.stderr new file mode 100644 index 00000000000..34b9c359ca8 --- /dev/null +++ b/src/test/ui/rfc1445/issue-63479-match-fnptr.stderr @@ -0,0 +1,16 @@ +warning: function pointers and unsized pointers in patterns do not behave deterministically. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-63479-match-fnptr.rs:35:7 + | +LL | B(TEST) => println!("matched"), + | ^^^^ + | +note: the lint level is defined here + --> $DIR/issue-63479-match-fnptr.rs:8:9 + | +LL | #![warn(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + = 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 #62411 <https://github.com/rust-lang/rust/issues/70861> + +warning: 1 warning emitted + |
