]> git.lizzy.rs Git - rust.git/commitdiff
Lint on function pointers used in patterns
authorOliver Scherer <github35764891676564198441@oli-obk.de>
Sun, 20 Sep 2020 15:11:00 +0000 (17:11 +0200)
committerOliver Scherer <github35764891676564198441@oli-obk.de>
Sun, 20 Sep 2020 16:42:15 +0000 (18:42 +0200)
compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
compiler/rustc_session/src/lint/builtin.rs
src/test/ui/issues/issue-44333.rs
src/test/ui/issues/issue-44333.stderr [new file with mode: 0644]
src/test/ui/rfc1445/issue-63479-match-fnptr.rs
src/test/ui/rfc1445/issue-63479-match-fnptr.stderr [new file with mode: 0644]

index ebb71ea24ecc0ec9a71de3a78d5332e48d8a0e21..6ca1ff2c5f2e75fbb3d27e264a7fb21a26f0243b 100644 (file)
@@ -351,10 +351,27 @@ fn recur(&self, cv: &'tcx ty::Const<'tcx>) -> Pat<'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
index 562df176b14a7aea895fd6bb98affff3acb780b4..c72b97fa1cabca2a7d7bcee7d39a263d2d4bbefa 100644 (file)
     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,
index fffef975043da8ddb6b4cc0529c8705147e960cc..85f5ccbdb65612f569e4b5064390008a5eb11f1c 100644 (file)
@@ -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 @@ fn test(x: usize) -> Func {
 
 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 (file)
index 0000000..a9ee5fc
--- /dev/null
@@ -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
+
index b3c91cec580bfc777b7b41c5827a5699c549a903..0984b1d480ecbc4ebea5eae5c4ad06313008ad40 100644 (file)
@@ -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 (file)
index 0000000..34b9c35
--- /dev/null
@@ -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
+