Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upIrrefutable while-let pattern in log4rs-rolling-file-0.2.0, Rust 1.16 #38972
Comments
This comment has been minimized.
This comment has been minimized.
|
Why was this made an error in the first place? |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
To save other people from digging through the crate, the situation is: #[derive(Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Config {
}The generated code (cleaned up) looks like: impl Deserialize for Config {
fn deserialize<D>(deserializer: &mut D) -> Result<Config, D::Error>
where D: Deserializer
{
enum Field {}
impl Deserialize for Field {
/* ... */
}
struct Visitor<D: Deserializer>(PhantomData<D>);
impl<D: Deserializer> Visitor for Visitor<D> {
type Value = Config;
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<Config, V::Error>
where V: SeqVisitor
{
try!(visitor.end());
Ok(Config{})
}
fn visit_map<V>(&mut self, mut visitor: V) -> Result<Config, V::Error>
where V: MapVisitor
{
// ERROR: irrefutable while-let pattern
while let Some(key) = try!(visitor.visit_key::<Field>()) {
match key {}
}
try!(visitor.end());
Ok(Config{})
}
}
const FIELDS: &'static [&'static str] = &[];
deserializer.deserialize_struct("Config", FIELDS, Visitor::<D>(PhantomData))
}
}This looks like the code for an ordinary braced struct except there are zero fields. So the error is because the line I filed serde-rs/serde#676 to fix this in Serde and I will leave it to you guys to debate whether this should be an error. |
This comment has been minimized.
This comment has been minimized.
|
Sounds like there's some debate to be had yet about the behavior here. Assigning to niko to make sure something happens. |
brson
added
the
P-high
label
Jan 12, 2017
brson
assigned
nikomatsakis
Jan 12, 2017
This comment has been minimized.
This comment has been minimized.
|
cc @canndrew -- @eddyb and I agree this should be a warning. It's not clear what definition of "irrefutable pattern" is being used here, presumably it is checking that the other variants are not reachable, probably so that this works: #![feature(never_type)]
fn foo(x: Result<u32, !>) {
let Ok(y) = x;
}
fn main() {
} |
This comment has been minimized.
This comment has been minimized.
|
I love the new behavior and plan to use it in Serde, for example here: // Before
try!(visitor.visit_key::<__Field>()).map(|impossible| match impossible {});
// After
let None::<__Field> = try!(visitor.visit_key());But it seems like this should be consistent with how unreachable patterns in enum Void {}
fn f() -> Option<Void> { None }
fn main() {
match f() {
None => println!("none"),
// WARNING: unreachable pattern, #[warn(unreachable_patterns)] on by default
Some(_) => println!("some"),
}
// ERROR: irrefutable if-let pattern
// (previously okay)
if let None = f() {
println!("definitely none");
}
// ERROR: irrefutable if-let pattern
// (previously okay)
if let Some(_) = f() {
println!("definitely some");
}
}Also "irrefutable pattern" makes sense for |
This comment has been minimized.
This comment has been minimized.
|
I think the definition is correct, it's just that this should not be an error. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
at least for now =) |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Yeah, this should be fixed properly. |
This comment has been minimized.
This comment has been minimized.
|
Looks like #39127 did not include a test for this particular case, so I'm going to add E-needs-test. |
nikomatsakis
added
the
E-needstest
label
Jan 27, 2017
nikomatsakis
removed their assignment
Jan 27, 2017
nikomatsakis
added
E-mentor
E-easy
labels
Jan 27, 2017
This comment has been minimized.
This comment has been minimized.
|
I am marking this issue as E-mentor and E-easy. The task is to add a test case for the The other problem is that there is no reduced form of the test. @dtolnay gave a relatively minimized example but it seems like it could be reduced further. The crux of the problem is that we have an enum #[deny(warnings)]
enum Foo { }
fn make_foo() -> Option<Foo> { None }
fn main() {
while let Some(_f) = make_foo() { }
}This should generate a warning about dead-code, ideally, but it should not generate an error. (At least, not on the current nightly: it should generate an error on the older nightly, if I did the reduction right.) So the steps to close are:
|
This comment has been minimized.
This comment has been minimized.
|
This seems to still be broken on latest master, actually. The exact test you provide fails with
|
This comment has been minimized.
This comment has been minimized.
|
@canndrew see @russellmcc's comment above; that's a bit surprising, no? |
arielb1
self-assigned this
Feb 2, 2017
This comment has been minimized.
This comment has been minimized.
|
Surprising and wrong |
This comment has been minimized.
This comment has been minimized.
|
Alright, sorry for saying this should be fixed when it was, in fact, not at all fixed. It's fixed now though! |
This comment has been minimized.
This comment has been minimized.
|
So with your patch, we end up in a situation where: enum Foo { }
fn make_foo() -> Option<Foo> { None }
fn main() {
match make_foo() {
None => {},
Some(_) => {}, //~ WARN unreachable pattern
}
}but if you remove the arm: enum Foo { }
fn make_foo() -> Option<Foo> { None }
fn main() {
match make_foo() { //~ ERROR non-exhaustive patterns
None => {}
}
}If you want to shut it up, you have to use: enum Foo { }
fn make_foo() -> Option<Foo> { None }
fn main() {
match make_foo() {
None => {},
_ => {}
}
} |
This comment has been minimized.
This comment has been minimized.
|
@arielb1 Heh. That's... kind of amusing. Though to be fair to @canndrew he would have preferred the second example to work, we kind of asked him not to allow it to work just yet. I'm not unhappy with the status quo, in some sense, as long as it's temporary; but it does seem likely to be awfully confusing. I could imagine a couple of things:
I think the TL;DR is that we should discuss and settle some kind of unreachable semantics. But I'm not 100% sure I'm ready to do that yet. I guess at minimum I gotta catch up on the RFC + old conversation. |
This comment has been minimized.
This comment has been minimized.
|
@arielb1 Arrgh. The problem is my Hide uninhabitedness checks behind feature gate PR didn't completely hide them. The changes I made for the uninhabited patterns stuff were:
When I tried to hide this stuff I hid (2) but didn't revert (0) and (1) (I guess because they seemed like more of a fix than a major change). I can hide them aswell with a follow-up PR though if you'd like? |
This comment has been minimized.
This comment has been minimized.
|
We had some discussion about that yesterday. You can read the notes at |
This comment has been minimized.
This comment has been minimized.
|
@canndrew I think the semantics we ultimately decided that we want kind of fall somewhere in between the older behavior and the newest behavior =) |
brson
added
regression-from-stable-to-beta
and removed
regression-from-stable-to-nightly
labels
Feb 9, 2017
arielb1
removed
E-easy
E-mentor
E-needstest
labels
Feb 16, 2017
This comment has been minimized.
This comment has been minimized.
|
I found another regression from 1.15 to 1.16 that involves empty enums. The following will compile on rust version 1.15: enum Void { }
fn use_void(v: &Void) -> u32 {
match v { }
}
fn main() { }But on
Does this seem like the same issue or should I ticket it separately? |
brson commentedJan 10, 2017
•
edited by nikomatsakis
UPDATE: The underlying problem has been solved (we believe), but there is not yet a regression test in the test base. Here are some instructions for how to add a regression test.
https://github.com/sfackler/log4rs-rolling-file 1ce36b4301c86fa750134d35cb815d146c5836ee
Not on stable/beta.
This case is interesting. The loop is generated by serde and from inspection seems be a degenerate case. I can't tell if it was previously right or wrong.
cc @sfackler @erickt