-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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 constants in patterns #32199
Restrict constants in patterns #32199
Conversation
cc @alexcrichton @huonw -- I'd like to get some eyes on the commit "do not overwrite spans as eagerly" in particular, because I am really unsure if what I am doing there makes sense. Not sure who is best to cc -- the logic there that I am modifying is indeed very old. |
Oh dear, anyone else's guess is as good as mine as to what's going on there... I basically have no idea :( Some other random thoughts though:
#[derive(Eq)]
struct A { a: i32 }
impl A {
fn eq(&self, other: &A) -> bool { true }
}
#[derive(Eq, PartialEq)]
struct B { a: A }
const CONST_B1: B = B { a: A { a: 1 } };
const CONST_B2: B = B { a: A { a: 2 } };
fn main() {
match CONST_B1 {
CONST_B2 => println!("b2"),
CONST_B1 => println!("b1"),
_ => {}
}
} By equality, in theory that should print (if this is covered in the RFC or discussions, please disregard me!) |
}; | ||
debug!("new_span({:?}) = {:?}", sp, sp1); | ||
if sp.expn_id.into_u32() == 0 && env::var_os("NDM").is_some() { | ||
panic!("NDM"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, oops -- that was a debugging remnant, obviously :) should have left a // TODO
, like I usually do
This is not so -- all of our "this will break in the future" code goes through lints now, precisely so that it plays nicely with
Heh, good point. I probably about to require that both PartialEq and Eq are derived. |
☔ The latest upstream changes (presumably #30587) made this pull request unmergeable. Please resolve the merge conflicts. |
@@ -24,6 +24,7 @@ | |||
#![feature(str_char)] | |||
|
|||
extern crate fmt_macros; | |||
#[macro_use] extern crate log; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this needs corresponding dependency edges in both Makefiles and rustbuild.
(I used to be able to leave comments on individual commits to mark them as "lgtm" while I did an incremental review of a PR... but it seems like github may have removed this capability ... so I will leave comments in the PR comment thread that reference the commit's via their hash instead...) Update: I realized after the fact that leaving comments in this thread wont accomplish the main goal, which was to use each commits marker of the little "i have comments" icon as a way of track progress. So maybe I'll try something else. |
commits lgtm:
|
if self == NEG_INFINITY { | ||
NEG_INFINITY | ||
} else { | ||
(self + ((self * self) + 1.0).sqrt()).ln() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(I personally would have left this as a match and just changed its first clause to x if x == NEG_INFINITY => x
)
@nikomatsakis okay PR looks good; r=me after you address notes above (including the bit about |
to careful use of the span from deriving, we can permit it in stable code if it derives from deriving (not-even-a-pun intended)
this was required to preserve the span from the #[structural_match] attribute -- but honestly I am not 100% sure if it makes sense.
This is a [breaking-change]: according to RFC rust-lang#1445, constants used as patterns must be of a type that *derives* `Eq`. 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.
afc4c70
to
93e4443
Compare
@bors r=pnkfelix |
📌 Commit 93e4443 has been approved by |
⌛ Testing commit 93e4443 with merge 4b59084... |
💔 Test failed - auto-linux-64-x-armhf |
@bors r=pnkfelix |
📌 Commit 944dc4a has been approved by |
@bors r=pnkfelix |
📌 Commit 2536ae5 has been approved by |
⌛ Testing commit 2536ae5 with merge 49e312b... |
⛄ The build was interrupted to prioritize another pull request. |
…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
This implements RFC 1445. The primary change is to limit the types of constants used in patterns to those that derive
Eq
(note that implementingEq
is not sufficient). This has two main effects:Eq
but onlyPartialEq
. This check replaces the existing special case code that aimed to detect the use ofNaN
.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:The easiest and most future compatible fix is to annotate the type in question with
#[derive(Eq)]
(note that merely implementingEq
is not enough, it must be derived):Another good option is to rewrite the match arm to use an
if
condition (this is also particularly good for floating point types, which implementPartialEq
but notEq
):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 #1445 for more details.cc #31434
r? @pnkfelix