Lint on function pointers used in patterns
This commit is contained in:
parent
3795886f7e
commit
aba5ea1430
6 changed files with 97 additions and 3 deletions
|
@ -351,10 +351,27 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||||
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::FnDef(..) => {
|
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::FnDef(..) => {
|
||||||
PatKind::Constant { value: cv }
|
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
|
// FIXME: these can have very suprising behaviour where optimization levels or other
|
||||||
// compilation choices change the runtime behaviour of the match.
|
// compilation choices change the runtime behaviour of the match.
|
||||||
// See https://github.com/rust-lang/rust/issues/70861 for examples.
|
// 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));
|
tcx.sess.delay_span_bug(span, &format!("cannot make a pattern out of {}", cv.ty));
|
||||||
PatKind::Wild
|
PatKind::Wild
|
||||||
|
|
|
@ -2197,6 +2197,32 @@ declare_lint! {
|
||||||
report_in_external_macro
|
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! {
|
declare_lint! {
|
||||||
/// The `ambiguous_associated_items` lint detects ambiguity between
|
/// The `ambiguous_associated_items` lint detects ambiguity between
|
||||||
/// [associated items] and [enum variants].
|
/// [associated items] and [enum variants].
|
||||||
|
@ -2630,6 +2656,7 @@ declare_lint_pass! {
|
||||||
AMBIGUOUS_ASSOCIATED_ITEMS,
|
AMBIGUOUS_ASSOCIATED_ITEMS,
|
||||||
MUTABLE_BORROW_RESERVATION_CONFLICT,
|
MUTABLE_BORROW_RESERVATION_CONFLICT,
|
||||||
INDIRECT_STRUCTURAL_MATCH,
|
INDIRECT_STRUCTURAL_MATCH,
|
||||||
|
POINTER_STRUCTURAL_MATCH,
|
||||||
SOFT_UNSTABLE,
|
SOFT_UNSTABLE,
|
||||||
INLINE_NO_SANITIZE,
|
INLINE_NO_SANITIZE,
|
||||||
ASM_SUB_REGISTER,
|
ASM_SUB_REGISTER,
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
// run-pass
|
// run-pass
|
||||||
|
|
||||||
|
#![warn(pointer_structural_match)]
|
||||||
|
|
||||||
type Func = fn(usize, usize) -> usize;
|
type Func = fn(usize, usize) -> usize;
|
||||||
|
|
||||||
fn foo(a: usize, b: usize) -> usize { a + b }
|
fn foo(a: usize, b: usize) -> usize { a + b }
|
||||||
|
@ -13,8 +16,10 @@ const BAR: Func = bar;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
match test(std::env::consts::ARCH.len()) {
|
match test(std::env::consts::ARCH.len()) {
|
||||||
FOO => println!("foo"),
|
FOO => println!("foo"), //~ WARN pointers in patterns do not behave deterministically
|
||||||
BAR => println!("bar"),
|
//~^ WARN will become a hard error
|
||||||
|
BAR => println!("bar"), //~ WARN pointers in patterns do not behave deterministically
|
||||||
|
//~^ WARN will become a hard error
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
25
src/test/ui/issues/issue-44333.stderr
Normal file
25
src/test/ui/issues/issue-44333.stderr
Normal file
|
@ -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
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
// cover the case this hit; I've since expanded it accordingly, but the
|
// cover the case this hit; I've since expanded it accordingly, but the
|
||||||
// experience left me wary of leaving this regression test out.)
|
// experience left me wary of leaving this regression test out.)
|
||||||
|
|
||||||
|
#![warn(pointer_structural_match)]
|
||||||
|
|
||||||
#[derive(Eq)]
|
#[derive(Eq)]
|
||||||
struct A {
|
struct A {
|
||||||
a: i64
|
a: i64
|
||||||
|
@ -31,6 +33,8 @@ fn main() {
|
||||||
let s = B(my_fn);
|
let s = B(my_fn);
|
||||||
match s {
|
match s {
|
||||||
B(TEST) => println!("matched"),
|
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")
|
_ => panic!("didn't match")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
16
src/test/ui/rfc1445/issue-63479-match-fnptr.stderr
Normal file
16
src/test/ui/rfc1445/issue-63479-match-fnptr.stderr
Normal file
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue