diff options
| author | bors <bors@rust-lang.org> | 2020-09-26 06:44:28 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2020-09-26 06:44:28 +0000 |
| commit | fd15e6180d9c48b4f1157e44cdaff6e901e5f854 (patch) | |
| tree | 11801a40b3c4b0ccc7c10b589347b28348705871 /compiler/rustc_session/src | |
| parent | 9e1c4361780e69ed54444a3b03fef0cbbc26b547 (diff) | |
| parent | daf976f6129e5fb16effc48bf91853548774e235 (diff) | |
| download | rust-fd15e6180d9c48b4f1157e44cdaff6e901e5f854.tar.gz rust-fd15e6180d9c48b4f1157e44cdaff6e901e5f854.zip | |
Auto merge of #70743 - oli-obk:eager_const_to_pat_conversion, r=eddyb
Fully destructure constants into patterns r? `@varkor` as discussed in https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/constants.20in.20patterns/near/192789924 we should probably crater it once reviewed
Diffstat (limited to 'compiler/rustc_session/src')
| -rw-r--r-- | compiler/rustc_session/src/lint/builtin.rs | 108 |
1 files changed, 90 insertions, 18 deletions
diff --git a/compiler/rustc_session/src/lint/builtin.rs b/compiler/rustc_session/src/lint/builtin.rs index 562df176b14..13a4057a35b 100644 --- a/compiler/rustc_session/src/lint/builtin.rs +++ b/compiler/rustc_session/src/lint/builtin.rs @@ -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, @@ -2198,6 +2191,83 @@ declare_lint! { } 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, |
