-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2715c5f
commit fec8a50
Showing
3 changed files
with
171 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
// check-pass | ||
// | ||
// Taken from https://github.com/rust-lang/rust/blob/6cc0a764e082d9c0abcf37a768d5889247ba13e2/compiler/rustc_typeck/src/check/_match.rs#L445-L462 | ||
// | ||
// We attempt to `let Bar::Present(_): &mut Bar = foo else { ... }` where foo is meant to | ||
// Deref/DerefMut to Bar. You can do this with an irrefutable binding, so it should work with | ||
// let-else too. | ||
|
||
#![feature(let_else)] | ||
use std::ops::{Deref, DerefMut}; | ||
|
||
struct Foo(Bar); | ||
|
||
enum Bar { | ||
Present(u32), | ||
Absent, | ||
} | ||
impl Deref for Foo { | ||
type Target = Bar; | ||
fn deref(&self) -> &Bar { | ||
&self.0 | ||
} | ||
} | ||
impl DerefMut for Foo { | ||
fn deref_mut(&mut self) -> &mut Bar { | ||
&mut self.0 | ||
} | ||
} | ||
impl Bar { | ||
fn bar(&self) -> Option<u32> { | ||
let Bar::Present(z): &Bar = self else { | ||
return None; | ||
}; | ||
return Some(*z); | ||
} | ||
} | ||
impl Foo { | ||
fn set_bar_annotated(&mut self, value: u32) { | ||
let Bar::Present(z): &mut Bar = self else { // OK | ||
return; | ||
}; | ||
*z = value; | ||
} | ||
} | ||
|
||
fn main() { | ||
let mut foo = Foo(Bar::Present(1)); | ||
foo.set_bar_annotated(42); | ||
assert_eq!(foo.bar(), Some(42)); | ||
irrefutable::inner(); | ||
} | ||
|
||
// The original, to show it works for irrefutable let decls | ||
mod irrefutable { | ||
use std::ops::{Deref, DerefMut}; | ||
struct Foo(Bar); | ||
struct Bar(u32); | ||
impl Deref for Foo { | ||
type Target = Bar; | ||
fn deref(&self) -> &Bar { | ||
&self.0 | ||
} | ||
} | ||
impl DerefMut for Foo { | ||
fn deref_mut(&mut self) -> &mut Bar { | ||
&mut self.0 | ||
} | ||
} | ||
fn foo(x: &mut Foo) { | ||
let Bar(z): &mut Bar = x; // OK | ||
*z = 42; | ||
assert_eq!((x.0).0, 42); | ||
} | ||
pub fn inner() { | ||
foo(&mut Foo(Bar(1))); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
// Taken from https://github.com/rust-lang/rust/blob/6cc0a764e082d9c0abcf37a768d5889247ba13e2/compiler/rustc_typeck/src/check/_match.rs#L445-L462 | ||
// | ||
// We attempt to `let Bar::Present(_) = foo else { ... }` where foo is meant to Deref/DerefMut to | ||
// Bar. This fails, you must add a type annotation like `let _: &mut Bar = _ else { ... }` | ||
|
||
#![feature(let_else)] | ||
use std::ops::{Deref, DerefMut}; | ||
|
||
struct Foo(Bar); | ||
|
||
enum Bar { | ||
Present(u32), | ||
Absent, | ||
} | ||
impl Deref for Foo { | ||
type Target = Bar; | ||
fn deref(&self) -> &Bar { | ||
&self.0 | ||
} | ||
} | ||
impl DerefMut for Foo { | ||
fn deref_mut(&mut self) -> &mut Bar { | ||
&mut self.0 | ||
} | ||
} | ||
impl Bar { | ||
fn bar(&self) -> Option<u32> { | ||
let Bar::Present(z): &Bar = self else { | ||
return None; | ||
}; | ||
return Some(*z); | ||
} | ||
} | ||
impl Foo { | ||
// Try without the type annotation | ||
fn set_bar_unannotated(&mut self, value: u32) { | ||
let Bar::Present(z) = self else { //~ ERROR mismatched types | ||
return; | ||
}; | ||
*z = value; | ||
} | ||
} | ||
|
||
fn main() { | ||
let mut foo = Foo(Bar::Present(1)); | ||
foo.set_bar_unannotated(54); | ||
assert_eq!(foo.bar(), Some(54)); | ||
irrefutable::inner(); | ||
} | ||
|
||
// The original, to show it fails for irrefutable let decls | ||
mod irrefutable { | ||
use std::ops::{Deref, DerefMut}; | ||
struct Foo(Bar); | ||
struct Bar(u32); | ||
impl Deref for Foo { | ||
type Target = Bar; | ||
fn deref(&self) -> &Bar { | ||
&self.0 | ||
} | ||
} | ||
impl DerefMut for Foo { | ||
fn deref_mut(&mut self) -> &mut Bar { | ||
&mut self.0 | ||
} | ||
} | ||
fn foo(x: &mut Foo) { | ||
let Bar(z) = x; //~ ERROR mismatched types | ||
*z = 54; | ||
assert_eq!((x.0).0, 54); | ||
} | ||
pub fn inner() { | ||
foo(&mut Foo(Bar(1))); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
error[E0308]: mismatched types | ||
--> $DIR/let-else-deref-coercion.rs:37:13 | ||
| | ||
LL | let Bar::Present(z) = self else { | ||
| ^^^^^^^^^^^^^^^ ---- this expression has type `&mut Foo` | ||
| | | ||
| expected struct `Foo`, found enum `Bar` | ||
|
||
error[E0308]: mismatched types | ||
--> $DIR/let-else-deref-coercion.rs:68:13 | ||
| | ||
LL | let Bar(z) = x; | ||
| ^^^^^^ - this expression has type `&mut irrefutable::Foo` | ||
| | | ||
| expected struct `irrefutable::Foo`, found struct `irrefutable::Bar` | ||
|
||
error: aborting due to 2 previous errors | ||
|
||
For more information about this error, try `rustc --explain E0308`. |