-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
implement pattern-binding-modes RFC #44614
Conversation
(rust_highfive has picked a reviewer for you, use r? to override) |
d8571a8
to
ded93d3
Compare
@nikomatsakis I updated the mem categorization code. Maybe I missed something, but your example borrowcks now (see |
30edb33
to
5c972f4
Compare
☔ The latest upstream changes (presumably #44678) made this pull request unmergeable. Please resolve the merge conflicts. |
@tschottdorf sorry for being slow. Start of the impl period has gotten me pretty slammed! |
No worries, if you're getting anything in before Friday that'll be enough
:-)
|
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 left a few nits and suggestions. It seems like the major unknown is how to deal with the "patterns contain binding" test. I know that @arielb1 and I had some discussion about this at some point that I'd like to re-read. =)
@@ -1144,8 +1144,53 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { | |||
|
|||
debug!("cat_pattern: {:?} cmt={:?}", pat, cmt); | |||
|
|||
// FIXME(tschottdorf): I'm not clear on whether this should also see the adjusted `cmt`. | |||
// I would assume so, but @nikomatsakis pointed me at just after this line to make the | |||
// adjustments. |
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 did point you to do the adjustment after, but I think I was wrong. I think we should move this callback to occur after. At first I thought we would do the callback both before and after each adjustment, but since we supply both the pattern and the cmt, I think it's better to just do a callback after the adjustments. We are therefore giving (a) the pattern that is being used and (b) the cmt that is being matched by this pattern. Looking at the use-sites of this function, all of them expect this and will work properly.
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.
Ok, will give that a try. Do you have an example or another way of testing that would break the current code and works with the callback invoked at the right place?
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.
mm let me think about it. There may be such a thing.
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 cannot find a way that it makes any difference -- all the consumers of this except for an obscure one in clippy only care about binding patterns, and those are never adjusted. However, it still seems more correct. Right now, we are passing in the bare pattern paired with the cmt that corresponds to (logically) the adjusted pattern. This is also coherent but it seems a bit .. less expected. i.e., if I match on the pattern and get (e.g.) PatTuple
, I would expect the cmt to have tuple type (but in this code, it may have reference type).
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 just want to double check your comment above because the code that you commented on gives the cmt
for the bare pattern and the bare pattern, whereas moving the callback gives the adjusted cmt
and (still) the bare pattern. Your wording makes it sound like you'd actually prefer option 1, which is the current code (right?).
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.
So, what I meant is this:
- Consider first
match &Some(3) { &Some(ref x) =>
.- When
cat_pattern
is first invoked, we have the cmt C for the discriminant (&Some(3)
) and the pattern&Some(ref x)
, and we invoke the callback with that - We then process the pattern, yielding the CMT for
*&Some(3)
and the patternSome(ref x)
, and we invoke the callback with that. - Finally, we process the CMT one step further to
Downcast<Some>(*&Some(3)).0
and invoke callback with with the patternref x
.
- When
- Under the code as it is there now:
- When
cat_pattern
is first invoked, we still have the same cmt C for the discriminant (&Some(3)
), but the pattern is forSome(x)
. We invoke the callback with that. - Then we adjust the CMT to
*&Some(3)
. No callback occurs after this. - Then we process the pattern, downcasting to
Downcast<Some>(*&Some(3)).0
, and invoke callback with patternx
, where the ref is implied.
- When
These don't quite match -- there aren't the same number of callbacks, to start, but also the cmt and patterns don't match up. If we move the callback to after the adjustment, we will get:
- Under the code as proposed:
- When
cat_pattern
is first invoked, we still have the same cmt C for the discriminant (&Some(3)
), but the pattern is forSome(x)
. - Then we adjust the CMT to
*&Some(3)
. - Now we callback with CMT
*&Some(3)
and patternSome(x)
, just as before. - Then we process the pattern, downcasting to
Downcast<Some>(*&Some(3)).0
, and invoke callback with patternx
, where the ref is implied.
- When
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.
Done.
src/librustc_const_eval/pattern.rs
Outdated
) | ||
} | ||
|
||
pub fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> { |
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.
Make this private.
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.
Done.
src/librustc_typeck/check/_match.rs
Outdated
} | ||
|
||
/// The `is_arg` argument indicates whether this pattern is the | ||
/// *outermost* pattern in an argument (e.g., in `fn foo(&x: | ||
/// &u32)`, it is true for the `&x` pattern but not `x`). This is | ||
/// used to tailor error reporting. | ||
pub fn check_pat_arg(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>, is_arg: bool) { | ||
pub fn check_pat_arg(&self, pat: &'gcx hir::Pat, mut expected: Ty<'tcx>, | ||
mut def_bm: ty::BindingMode, is_arg: bool) { |
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.
Nit: I'd prefer the arguments to each be on their own line.
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.
Done.
src/librustc_typeck/check/_match.rs
Outdated
PatKind::TupleStruct(..) | | ||
PatKind::Tuple(..) | | ||
PatKind::Box(_) | | ||
// PatKind::Lit(_) | // FIXME(tschottdorf): causes lots of errors |
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.
OK, we gotta figure this out.
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 forget, did you have examples?
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.
Among possibly other things, we treat string literals incorrectly.
match s {
"inf" => T::INFINITY,
"NaN" => T::NAN,
_ => { return Err(pfe_invalid()); }
}
Compiling core v0.0.0 (file:///Users/tschottdorf/rust/binding-modes/src/libcore)
error[E0308]: mismatched types
--> src/libcore/num/dec2flt/mod.rs:219:13
|
219 | "inf" => T::INFINITY,
| ^^^^^ expected str, found reference
|
= note: expected type `str`
found type `&'static str`
error[E0308]: mismatched types
--> src/libcore/num/dec2flt/mod.rs:220:13
|
220 | "NaN" => T::NAN,
| ^^^^^ expected str, found reference
|
= note: expected type `str`
found type `&'static str`
error[E0308]: mismatched types
--> src/libcore/str/mod.rs:130:13
|
130 | "true" => Ok(true),
| ^^^^^^ expected str, found reference
|
= note: expected type `str`
found type `&'static str`
error[E0308]: mismatched types
--> src/libcore/str/mod.rs:131:13
|
131 | "false" => Ok(false),
| ^^^^^^^ expected str, found reference
|
= note: expected type `str`
found type `&'static str`
error: aborting due to 4 previous errors
error: Could not compile `core`.
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.
Yeah it seems like string and byte literals (and maybe slices?) are the other places this would go wrong. But I guess more generally one can have a constant with references in it (e.g., const X: &'static u32 = &22
-- I forget if you can use such a constant in a match though.
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 added a computation of the type and make the true/false
depend on whether there's a TyRef
. May not be the right thing to do, but at least it works somewhat.
src/librustc_typeck/check/_match.rs
Outdated
PatKind::Slice(..) => true, | ||
PatKind::Path(ref qpath) => { | ||
// FIXME(tschottdorf): is it OK to call this here? | ||
let (def, _, _) = self.resolve_ty_and_def_ufcs(qpath, pat.id, pat.span); |
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.
Hmm. It's not great to call this here, in that it can report an error, which might then get reported again later on (by check_pat_path
). Not sure how best to fix this though!
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.
Hmm, we might be able to just modify resolve_ty_and_def_ufcs
to cache the result. It already writes the final result into a table:
// Write back the new resolution.
let hir_id = self.tcx.hir.node_to_hir_id(node_id);
self.tables.borrow_mut().type_dependent_defs_mut().insert(hir_id, def);
seems like we can check that cache in the case that we get TypeRelative
.
(cc @eddyb -- this seem ok to you?)
@@ -0,0 +1,38 @@ | |||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT |
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.
So I've been advocating for us to organize the tests for new language features like this by putting them into a directory. So can we move this to ths directory:
src/test/compile-fail/rfc-XXX-default-binding-mode/
The idea is that we should be able to browse this directory (as well as corresponding directories in src/test/run-pass
and src/test/ui
) to get a good idea of how the feature behaves.
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.
Done.
@@ -0,0 +1,49 @@ | |||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT | |||
// file at the top-level directory of this distribution and at | |||
// http://rust-lang.org/COPYRIGHT. |
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.
move this file to a directory, as described before
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.
Done.
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your |
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.
directory
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.
Done.
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed |
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.
directory
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.
Done.
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed |
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.
directory
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.
Done.
Was there some particular test that caught your eye? Most of them actually looked like improvements to me. |
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.
Thanks for the review @nikomatsakis! Haven't changed anything (will do tomorrow), just posted a few responses to comments to get you unstuck.
@@ -1144,8 +1144,53 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { | |||
|
|||
debug!("cat_pattern: {:?} cmt={:?}", pat, cmt); | |||
|
|||
// FIXME(tschottdorf): I'm not clear on whether this should also see the adjusted `cmt`. | |||
// I would assume so, but @nikomatsakis pointed me at just after this line to make the | |||
// adjustments. |
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.
Ok, will give that a try. Do you have an example or another way of testing that would break the current code and works with the callback invoked at the right place?
// FIXME(tschottdorf): don't call contains_explicit_ref_binding, which | ||
// is problematic as the HIR is being scraped, but ref bindings may be | ||
// implicit after #42640. We need to make sure that pat_adjustments | ||
// (once introduced) is populated by the time we get here. |
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.
src/librustc_typeck/check/_match.rs
Outdated
PatKind::TupleStruct(..) | | ||
PatKind::Tuple(..) | | ||
PatKind::Box(_) | | ||
// PatKind::Lit(_) | // FIXME(tschottdorf): causes lots of errors |
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.
Among possibly other things, we treat string literals incorrectly.
match s {
"inf" => T::INFINITY,
"NaN" => T::NAN,
_ => { return Err(pfe_invalid()); }
}
Compiling core v0.0.0 (file:///Users/tschottdorf/rust/binding-modes/src/libcore)
error[E0308]: mismatched types
--> src/libcore/num/dec2flt/mod.rs:219:13
|
219 | "inf" => T::INFINITY,
| ^^^^^ expected str, found reference
|
= note: expected type `str`
found type `&'static str`
error[E0308]: mismatched types
--> src/libcore/num/dec2flt/mod.rs:220:13
|
220 | "NaN" => T::NAN,
| ^^^^^ expected str, found reference
|
= note: expected type `str`
found type `&'static str`
error[E0308]: mismatched types
--> src/libcore/str/mod.rs:130:13
|
130 | "true" => Ok(true),
| ^^^^^^ expected str, found reference
|
= note: expected type `str`
found type `&'static str`
error[E0308]: mismatched types
--> src/libcore/str/mod.rs:131:13
|
131 | "false" => Ok(false),
| ^^^^^^^ expected str, found reference
|
= note: expected type `str`
found type `&'static str`
error: aborting due to 4 previous errors
error: Could not compile `core`.
5c972f4
to
7ad162e
Compare
OK, so, I was thinking some more about the problem of how to replace the code that scans (syntactically) for Let's focus on the case of a
What makes this complicated is that we sometimes need to coerce the result of evaluating
this is generally equivalent to So what we do TODAY is to say this, effectively:
However, in the new system, we now have to account for the possibility that there will be "type-based" ref-bindings in the pattern P that are not syntactically evident. However, we know that if such ref-bindings exist, they occur "beneath" a I think this means we don't have to worry about the big danger that we were afraid of. In particular, no coercion ever modifies the referent of a reference -- we don't know where that memory lives, and we don't know that we have the freedom to change it. In other words, if we coerce the result of E, it will only affect the owned content of that result, not its borrowed content -- and for their to be borrows of the owned content, they must be done with a (There is one exception of sorts: we do permit The other cases where we use this check, I think, can never perform coercion, and so are not as problematic. They only have to worry about subtyping, and in that case the same logic above applies -- we will only ever take a
|
Now that I'm reading this again: If we just wanted to be consistent with that, then the #23116 example: #![allow(dead_code)]
use std::fmt::Debug;
struct S(Box<Debug + 'static>);
impl S {
fn bar<'a>(&'a mut self)->&'a mut Box<Debug + 'a> {
match self.0 { ref mut x => x } // should not compile, but does
}
}
fn main() {} Would perform a lexpr->vexpr->lexpr conversion, and therefore a temporary, creating MIR as follows:
Which would of course cause a "borrow does not live long enough" when it catches you trying to return a borrow of the local Obviously, creating such coercion temporaries by default will annoy anyone who tries to use However, if all the An asideThe above description is not actually implementation-coherent with typeck - to satisfy closure inference, match bindings can't use subtyping, so rustc actually sometimes performs subtyping on immutable lexprs - see this comment: rust/src/librustc_typeck/check/_match.rs Lines 331 to 379 in dcb4378
Note that typeck's strategy is imperfect and leads to spurious errors in some situations fn foo<'x>(mut x: (&'x isize, ())) {
let a = 1;
let (mut _z, ref _y) = x;
_z = &a; //~ ERROR no subtyping for you!
}
fn main() {} We'll also have to solve the closure inference wonkyness when we get to MIR-based regionck, but hopefully the MIR-based regionck won't have wonky anyway. |
While this argument works today, it will put us in a somewhat sticky situation when we get struct Newtype<T>(T);
impl<T> Deref for Newtype<T> {
type Target = T;
fn deref(&self) -> &T { &self.0 }
}
impl<T> DerefMut for Newtype<T> {
fn deref_mut(&mut self) -> &mut T { &mut self.0 }
}
unsafe impl<T> DerefPure for Newtype<T> { /* ... */ }
fn main() {
let n = Newtype(("hello",));
{
let s = "hi there".to_string();
let (mut d,) = n;
*d = &s; // create a temporary? fail? both options are unsatisfying
}
} |
My take is that we can land this without fully resolving the "coercion chicken" question. I've filed #44848 to track that. |
☔ The latest upstream changes (presumably #44735) made this pull request unmergeable. Please resolve the merge conflicts. |
match &&&&i { | ||
1 ... 3 => panic!(), | ||
3 ... 8 => {}, | ||
_ => {}, |
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.
Shouldn't default variant panic too, considering it's unexpected result value?
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.
Done.
@tschottdorf I wrote up a list of test cases here. Can you just check that you have tests covering those cases? |
346bd34
to
85cf6ed
Compare
@nikomatsakis confirmed, though one of your test cases doesn't compile (out of scope of this PR, see #42640 (comment)). I added a compile-fail test that documents this but you probably want to file an issue unless there's already one. Could you review the FIXMEs (just search for |
src/librustc/hir/pat_util.rs
Outdated
/// FIXME(tschottdorf): this is problematic as the HIR is being scraped, | ||
/// but ref bindings may be implicit after #42640. | ||
/// FIXME(tschottdorf): this is problematic as the HIR is being scraped, but | ||
/// ref bindings may be implicit after #42640 (default match binding modes). |
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.
Leave as is, link to #44848.
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.
Done.
@@ -188,7 +188,7 @@ impl hir::Arm { | |||
/// bindings, and if yes whether its containing mutable ones or just immutables ones. | |||
pub fn contains_explicit_ref_binding(&self) -> Option<hir::Mutability> { | |||
// FIXME(tschottdorf): contains_explicit_ref_binding() must be removed | |||
// for #42640. | |||
// for #42640 (default match binding modes). |
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.
Leave as is, link to #44848.
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.
Done.
@@ -1144,8 +1144,53 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { | |||
|
|||
debug!("cat_pattern: {:?} cmt={:?}", pat, cmt); | |||
|
|||
// FIXME(tschottdorf): I'm not clear on whether this should also see the adjusted `cmt`. |
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.
Change as discussed below (move callback later).
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.
Done.
.get(pat.hir_id) | ||
.map(|v| v.len()) | ||
.unwrap_or(0) { | ||
// FIXME(tschottdorf): is implicit==true correct? |
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.
It is correct. If you make it false, I think it would affect how the error in this example is printed.
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.
Ack, done.
// Ditto with byte strings. | ||
fn with_bytes() { | ||
let s: &'static [u8] = b"abc"; | ||
let result = match s { |
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 we should test match &s {
too.
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.
(Though I think this would maybe give an error?)
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.
Yeah, this gives an error. What would you like me to do? Move to ui tests & file an issue? Try to fix?
let s: &'static str = "abc";
match &s {
"abc" => true,
_ => panic!(),
};
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
// FIXME(tschottdorf): what other noteworthy literals are there? |
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.
Booleans? Not much else really.
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.
Do we have a test with named constants of struct type etc?
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.
Like this?
#[derive(PartialEq, Eq)]
struct Foo {
bar: i32,
}
const FOO: Foo = Foo{bar: 5};
fn main() {
let f = Foo{bar:6};
match &f {
FOO => {},
_ => panic!(),
}
}
Doesn't compile (but should), added to ui tests for now.
Done |
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.
Thanks! Mostly done except for avoiding double type errors. Plus there may be some non-compiling tests that you'll want to advise me on/open follow-up issues for (all have comments in this review).
src/librustc/hir/pat_util.rs
Outdated
/// FIXME(tschottdorf): this is problematic as the HIR is being scraped, | ||
/// but ref bindings may be implicit after #42640. | ||
/// FIXME(tschottdorf): this is problematic as the HIR is being scraped, but | ||
/// ref bindings may be implicit after #42640 (default match binding modes). |
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.
Done.
@@ -188,7 +188,7 @@ impl hir::Arm { | |||
/// bindings, and if yes whether its containing mutable ones or just immutables ones. | |||
pub fn contains_explicit_ref_binding(&self) -> Option<hir::Mutability> { | |||
// FIXME(tschottdorf): contains_explicit_ref_binding() must be removed | |||
// for #42640. | |||
// for #42640 (default match binding modes). |
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.
Done.
@@ -1144,8 +1144,53 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { | |||
|
|||
debug!("cat_pattern: {:?} cmt={:?}", pat, cmt); | |||
|
|||
// FIXME(tschottdorf): I'm not clear on whether this should also see the adjusted `cmt`. |
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.
Done.
@@ -1144,8 +1144,53 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { | |||
|
|||
debug!("cat_pattern: {:?} cmt={:?}", pat, cmt); | |||
|
|||
// FIXME(tschottdorf): I'm not clear on whether this should also see the adjusted `cmt`. | |||
// I would assume so, but @nikomatsakis pointed me at just after this line to make the | |||
// adjustments. |
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.
Done.
.get(pat.hir_id) | ||
.map(|v| v.len()) | ||
.unwrap_or(0) { | ||
// FIXME(tschottdorf): is implicit==true correct? |
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.
Ack, done.
let _: &i32 = match x { | ||
// Here, each of the patterns are treated independently | ||
// | ||
// FIXME(tschottdorf): make this compile without the actual `|`. |
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.
Filed #44912.
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
// FIXME(tschottdorf): what other noteworthy literals are there? |
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.
Like this?
#[derive(PartialEq, Eq)]
struct Foo {
bar: i32,
}
const FOO: Foo = Foo{bar: 5};
fn main() {
let f = Foo{bar:6};
match &f {
FOO => {},
_ => panic!(),
}
}
Doesn't compile (but should), added to ui tests for now.
// Ditto with byte strings. | ||
fn with_bytes() { | ||
let s: &'static [u8] = b"abc"; | ||
let result = match s { |
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.
Yeah, this gives an error. What would you like me to do? Move to ui tests & file an issue? Try to fix?
let s: &'static str = "abc";
match &s {
"abc" => true,
_ => panic!(),
};
src/librustc_typeck/check/_match.rs
Outdated
} | ||
} | ||
PatKind::Path(ref qpath) => { | ||
// FIXME(tschottdorf): is it OK to call this here? |
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.
Yep. I'll try to do that tomorrow.
src/librustc_typeck/check/_match.rs
Outdated
PatKind::Range(..) | | ||
PatKind::Slice(..) => true, | ||
PatKind::Lit(ref lt) => { | ||
// FIXME(tschottdorf): is it OK to call this here? |
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'll take a look at this tomorrow.
6e5d235
to
185a738
Compare
Added a feature gate and docs in the unstable book. Mod bikeshedding on the feature gate name and avoiding doubly reporting errors I think I'm done here. Anything else missing? |
af06651
to
bc651af
Compare
@nikomatsakis, re #44614 (comment): what's an example that would return an error twice? I'll need that to test that I fixed something, and wasn't able to put one together myself. I did add caching in |
Re: #44614 (comment) (same problem for |
Regarding the double errors: This is an example of a test-case that gives double errors without your fix, but no longer does. fn main() {
let foo = 22;
match foo {
u32::XXX => { }
_ => { }
}
} |
I imagine something like this, yes. Basically a pre-pass over all the patterns that finds literals and type-checks them -- this would probably happen when let ty = self.check_expr(<); but rather let ty = self.node_ty(lt.hir_id); which will read out the (previously computed) type . In other words, you don't need to add a new map, we already have the tables. In terms of a test that would go awry... hmm... that may be a bit harder. =) I am trying to think if it's possible to get an error while type-checking a literal! Maybe it's not. |
Squashed and ready for more review and merge. @nikomatsakis double-error worked fine. As for the literals, I realized I didn't have to add an extra walk -- we were always calling |
See the [RFC] and [tracking issue]. [tracking issue]: rust-lang#42640 [RFC]: https://github.com/rust-lang/rfcs/blob/491e0af/text/2005-match-ergonomics.md
@bors r+ |
📌 Commit de55b4f has been approved by |
implement pattern-binding-modes RFC See the [RFC] and [tracking issue]. [tracking issue]: #42640 [RFC]: https://github.com/rust-lang/rfcs/blob/491e0af/text/2005-match-ergonomics.md
☀️ Test successful - status-appveyor, status-travis |
--> $DIR/explicit-mut.rs:19:13 | ||
| | ||
18 | Some(n) => { | ||
| - consider changing this to `n` |
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.
this kind of lint seems a bit weird since n
is already n
.
See the RFC and tracking issue #42640