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
report_in_external_macro
}
+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].
AMBIGUOUS_ASSOCIATED_ITEMS,
MUTABLE_BORROW_RESERVATION_CONFLICT,
INDIRECT_STRUCTURAL_MATCH,
+ POINTER_STRUCTURAL_MATCH,
SOFT_UNSTABLE,
INLINE_NO_SANITIZE,
ASM_SUB_REGISTER,
// run-pass
+
+#![warn(pointer_structural_match)]
+
type Func = fn(usize, usize) -> usize;
fn foo(a: usize, b: usize) -> usize { a + b }
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!(),
}
}
--- /dev/null
+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
+
// 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
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")
};
}
--- /dev/null
+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
+