-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Restrict use of constants in patterns (RFC 1445) #31434
Comments
Why |
See the PR #32199 |
The primary reason is that types which only implement If we wind up adopting a "semantic" interpretation, then we could consider loosening to |
…patterns-2, r=pnkfelix Restrict constants in patterns This implements [RFC 1445](https://github.com/rust-lang/rfcs/blob/master/text/1445-restrict-constants-in-patterns.md). The primary change is to limit the types of constants used in patterns to those that *derive* `Eq` (note that implementing `Eq` is not sufficient). This has two main effects: 1. Floating point constants are linted, and will eventually be disallowed. This is because floating point constants do not implement `Eq` but only `PartialEq`. This check replaces the existing special case code that aimed to detect the use of `NaN`. 2. Structs and enums must derive `Eq` to be usable within a match. This is a [breaking-change]: if you encounter a problem, you are most likely using a constant in an expression where the type of the constant is some struct that does not currently implement `Eq`. Something like the following: ```rust struct SomeType { ... } const SOME_CONST: SomeType = ...; match foo { SOME_CONST => ... } ``` The easiest and most future compatible fix is to annotate the type in question with `#[derive(Eq)]` (note that merely *implementing* `Eq` is not enough, it must be *derived*): ```rust struct SomeType { ... } const SOME_CONST: SomeType = ...; match foo { SOME_CONST => ... } ``` Another good option is to rewrite the match arm to use an `if` condition (this is also particularly good for floating point types, which implement `PartialEq` but not `Eq`): ```rust match foo { c if c == SOME_CONST => ... } ``` Finally, a third alternative is to tag the type with `#[structural_match]`; but this is not recommended, as the attribute is never expected to be stabilized. Please see RFC rust-lang#1445 for more details. cc rust-lang#31434 r? @pnkfelix
…patterns-2, r=pnkfelix Restrict constants in patterns This implements [RFC 1445](https://github.com/rust-lang/rfcs/blob/master/text/1445-restrict-constants-in-patterns.md). The primary change is to limit the types of constants used in patterns to those that *derive* `Eq` (note that implementing `Eq` is not sufficient). This has two main effects: 1. Floating point constants are linted, and will eventually be disallowed. This is because floating point constants do not implement `Eq` but only `PartialEq`. This check replaces the existing special case code that aimed to detect the use of `NaN`. 2. Structs and enums must derive `Eq` to be usable within a match. This is a [breaking-change]: if you encounter a problem, you are most likely using a constant in an expression where the type of the constant is some struct that does not currently implement `Eq`. Something like the following: ```rust struct SomeType { ... } const SOME_CONST: SomeType = ...; match foo { SOME_CONST => ... } ``` The easiest and most future compatible fix is to annotate the type in question with `#[derive(Eq)]` (note that merely *implementing* `Eq` is not enough, it must be *derived*): ```rust struct SomeType { ... } const SOME_CONST: SomeType = ...; match foo { SOME_CONST => ... } ``` Another good option is to rewrite the match arm to use an `if` condition (this is also particularly good for floating point types, which implement `PartialEq` but not `Eq`): ```rust match foo { c if c == SOME_CONST => ... } ``` Finally, a third alternative is to tag the type with `#[structural_match]`; but this is not recommended, as the attribute is never expected to be stabilized. Please see RFC rust-lang#1445 for more details. cc rust-lang#31434 r? @pnkfelix
Nominating for status update. |
@nikomatsakis status update? |
@brson this is basically implemented, except that I don't think I did anything clever for the exhaustiveness check. I updated the check marks. The semantics are still (in my mind) basically a kind of temporary hack. |
Triage: @nikomatsakis any movement here? |
Came here via #62339/#62411/#62614 use std::rc::Rc;
use std::error::Error;
const OK: Result<(), Rc<dyn Error>> = Ok(());
fn main() {
let is_ok = match OK {
OK => true,
_ => false,
};
} On the current nightly this complains about not being able to structurally match |
What is still left to be done for this issue? |
|
#63438 is closed. However on rustdoc page it seems the primitive types are missing...: https://doc.rust-lang.org/nightly/std/marker/trait.StructuralEq.html |
One original goal of RFC 1445 is to address the weakened abstraction boundary. But looks like it doesn't consider the leak through error messages. mod state {
use std::borrow::Cow;
#[derive(PartialEq, Eq)]
pub struct State(Cow<'static, str>);
impl State {
pub fn new(s: &'static str) -> Self {
State(Cow::Borrowed(s))
}
}
pub const COLD: State = State(Cow::Borrowed("cold"));
}
fn main() {
let s = state::State::new("hot");
match s {
state::COLD => (),
_ => (),
}
} The error message:
exposes the fact that |
CTFE forbids comparing pointers for equality, since two pointers being unequal may arbitrarily change to the two pointers being equal depending on various factors (e.g. different constants sharing the same memory or not depending on whether they were instantiated in the same crate). Should we thus also exclude raw pointers from |
I apologize if I missed something, but why isn't this trait implemented for |
Which trait? |
For this issue, is there anything left to do here? I think it is entirely superseded by #120362. |
Closing in favor of #120362. |
Tracking issue for rust-lang/rfcs#1445.
Implementation steps:
#[structural_match]
#[derive(Eq)]
add#[structural_match]
attributeindirect_structural_match
compatibility lint #62411 .#[structural_match]
attribute to something with impl items (e.g. aStructural
trait)The text was updated successfully, but these errors were encountered: