Auto merge of #70743 - oli-obk:eager_const_to_pat_conversion, r=eddyb

Fully destructure constants into patterns

r? `@varkor`

as discussed in 192789924

we should probably crater it once reviewed
This commit is contained in:
bors 2020-09-26 06:44:28 +00:00
commit fd15e6180d
66 changed files with 796 additions and 435 deletions

View file

@ -2138,22 +2138,16 @@ declare_lint! {
/// ```rust,compile_fail
/// #![deny(indirect_structural_match)]
///
/// struct Plus(i32, i32);
/// const ONE_PLUS_TWO: &&Plus = &&Plus(1, 2);
///
/// impl PartialEq for Plus {
/// fn eq(&self, other: &Self) -> bool {
/// self.0 + self.1 == other.0 + other.1
/// }
/// }
///
/// impl Eq for Plus {}
///
/// struct NoDerive(i32);
/// impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
/// impl Eq for NoDerive { }
/// #[derive(PartialEq, Eq)]
/// struct WrapParam<T>(T);
/// const WRAP_INDIRECT_PARAM: & &WrapParam<NoDerive> = & &WrapParam(NoDerive(0));
/// fn main() {
/// if let ONE_PLUS_TWO = &&Plus(3, 0) {
/// println!("semantic!");
/// } else {
/// println!("structural!");
/// match WRAP_INDIRECT_PARAM {
/// WRAP_INDIRECT_PARAM => { }
/// _ => { }
/// }
/// }
/// ```
@ -2170,9 +2164,8 @@ declare_lint! {
/// [issue #62411]: https://github.com/rust-lang/rust/issues/62411
/// [future-incompatible]: ../index.md#future-incompatible-lints
pub INDIRECT_STRUCTURAL_MATCH,
// defaulting to allow until rust-lang/rust#62614 is fixed.
Allow,
"pattern with const indirectly referencing non-structural-match type",
Warn,
"constant used in pattern contains value of non-structural-match type in a field or a variant",
@future_incompatible = FutureIncompatibleInfo {
reference: "issue #62411 <https://github.com/rust-lang/rust/issues/62411>",
edition: None,
@ -2197,6 +2190,83 @@ declare_lint! {
report_in_external_macro
}
declare_lint! {
/// The `pointer_structural_match` lint detects pointers used in patterns whose behaviour
/// cannot be relied upon across compiler versions and optimization levels.
///
/// ### 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 => {},
/// _ => {},
/// }
/// }
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// Previous versions of Rust allowed function pointers and wide raw pointers in patterns.
/// While these work in many cases as expected by users, it is possible that due to
/// optimizations pointers are "not equal to themselves" or pointers to different functions
/// compare as equal during runtime. This is because LLVM optimizations can deduplicate
/// functions if their bodies are the same, thus also making pointers to these functions point
/// to the same location. Additionally functions may get duplicated if they are instantiated
/// in different crates and not deduplicated again via LTO.
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 `nontrivial_structural_match` lint detects constants that are used in patterns,
/// whose type is not structural-match and whose initializer body actually uses values
/// that are not structural-match. So `Option<NotStruturalMatch>` is ok if the constant
/// is just `None`.
///
/// ### Example
///
/// ```rust,compile_fail
/// #![deny(nontrivial_structural_match)]
///
/// #[derive(Copy, Clone, Debug)]
/// struct NoDerive(u32);
/// impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
/// impl Eq for NoDerive { }
/// fn main() {
/// const INDEX: Option<NoDerive> = [None, Some(NoDerive(10))][0];
/// match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), };
/// }
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// Previous versions of Rust accepted constants in patterns, even if those constants's types
/// did not have `PartialEq` derived. Thus the compiler falls back to runtime execution of
/// `PartialEq`, which can report that two constants are not equal even if they are
/// bit-equivalent.
pub NONTRIVIAL_STRUCTURAL_MATCH,
Warn,
"constant used in pattern of non-structural-match type and the constant's initializer \
expression contains values of non-structural-match types",
@future_incompatible = FutureIncompatibleInfo {
reference: "issue #73448 <https://github.com/rust-lang/rust/issues/73448>",
edition: None,
};
}
declare_lint! {
/// The `ambiguous_associated_items` lint detects ambiguity between
/// [associated items] and [enum variants].
@ -2630,6 +2700,8 @@ declare_lint_pass! {
AMBIGUOUS_ASSOCIATED_ITEMS,
MUTABLE_BORROW_RESERVATION_CONFLICT,
INDIRECT_STRUCTURAL_MATCH,
POINTER_STRUCTURAL_MATCH,
NONTRIVIAL_STRUCTURAL_MATCH,
SOFT_UNSTABLE,
INLINE_NO_SANITIZE,
ASM_SUB_REGISTER,