File tree Expand file tree Collapse file tree 3 files changed +171
-0
lines changed Expand file tree Collapse file tree 3 files changed +171
-0
lines changed Original file line number Diff line number Diff line change 1+ // check-pass
2+ //
3+ // Taken from https://github.com/rust-lang/rust/blob/6cc0a764e082d9c0abcf37a768d5889247ba13e2/compiler/rustc_typeck/src/check/_match.rs#L445-L462
4+ //
5+ // We attempt to `let Bar::Present(_): &mut Bar = foo else { ... }` where foo is meant to
6+ // Deref/DerefMut to Bar. You can do this with an irrefutable binding, so it should work with
7+ // let-else too.
8+
9+ #![ feature( let_else) ]
10+ use std:: ops:: { Deref , DerefMut } ;
11+
12+ struct Foo ( Bar ) ;
13+
14+ enum Bar {
15+ Present ( u32 ) ,
16+ Absent ,
17+ }
18+ impl Deref for Foo {
19+ type Target = Bar ;
20+ fn deref ( & self ) -> & Bar {
21+ & self . 0
22+ }
23+ }
24+ impl DerefMut for Foo {
25+ fn deref_mut ( & mut self ) -> & mut Bar {
26+ & mut self . 0
27+ }
28+ }
29+ impl Bar {
30+ fn bar ( & self ) -> Option < u32 > {
31+ let Bar :: Present ( z) : & Bar = self else {
32+ return None ;
33+ } ;
34+ return Some ( * z) ;
35+ }
36+ }
37+ impl Foo {
38+ fn set_bar_annotated ( & mut self , value : u32 ) {
39+ let Bar :: Present ( z) : & mut Bar = self else { // OK
40+ return ;
41+ } ;
42+ * z = value;
43+ }
44+ }
45+
46+ fn main ( ) {
47+ let mut foo = Foo ( Bar :: Present ( 1 ) ) ;
48+ foo. set_bar_annotated ( 42 ) ;
49+ assert_eq ! ( foo. bar( ) , Some ( 42 ) ) ;
50+ irrefutable:: inner ( ) ;
51+ }
52+
53+ // The original, to show it works for irrefutable let decls
54+ mod irrefutable {
55+ use std:: ops:: { Deref , DerefMut } ;
56+ struct Foo ( Bar ) ;
57+ struct Bar ( u32 ) ;
58+ impl Deref for Foo {
59+ type Target = Bar ;
60+ fn deref ( & self ) -> & Bar {
61+ & self . 0
62+ }
63+ }
64+ impl DerefMut for Foo {
65+ fn deref_mut ( & mut self ) -> & mut Bar {
66+ & mut self . 0
67+ }
68+ }
69+ fn foo ( x : & mut Foo ) {
70+ let Bar ( z) : & mut Bar = x; // OK
71+ * z = 42 ;
72+ assert_eq ! ( ( x. 0 ) . 0 , 42 ) ;
73+ }
74+ pub fn inner ( ) {
75+ foo ( & mut Foo ( Bar ( 1 ) ) ) ;
76+ }
77+ }
Original file line number Diff line number Diff line change 1+ // Taken from https://github.com/rust-lang/rust/blob/6cc0a764e082d9c0abcf37a768d5889247ba13e2/compiler/rustc_typeck/src/check/_match.rs#L445-L462
2+ //
3+ // We attempt to `let Bar::Present(_) = foo else { ... }` where foo is meant to Deref/DerefMut to
4+ // Bar. This fails, you must add a type annotation like `let _: &mut Bar = _ else { ... }`
5+
6+ #![ feature( let_else) ]
7+ use std:: ops:: { Deref , DerefMut } ;
8+
9+ struct Foo ( Bar ) ;
10+
11+ enum Bar {
12+ Present ( u32 ) ,
13+ Absent ,
14+ }
15+ impl Deref for Foo {
16+ type Target = Bar ;
17+ fn deref ( & self ) -> & Bar {
18+ & self . 0
19+ }
20+ }
21+ impl DerefMut for Foo {
22+ fn deref_mut ( & mut self ) -> & mut Bar {
23+ & mut self . 0
24+ }
25+ }
26+ impl Bar {
27+ fn bar ( & self ) -> Option < u32 > {
28+ let Bar :: Present ( z) : & Bar = self else {
29+ return None ;
30+ } ;
31+ return Some ( * z) ;
32+ }
33+ }
34+ impl Foo {
35+ // Try without the type annotation
36+ fn set_bar_unannotated ( & mut self , value : u32 ) {
37+ let Bar :: Present ( z) = self else { //~ ERROR mismatched types
38+ return ;
39+ } ;
40+ * z = value;
41+ }
42+ }
43+
44+ fn main ( ) {
45+ let mut foo = Foo ( Bar :: Present ( 1 ) ) ;
46+ foo. set_bar_unannotated ( 54 ) ;
47+ assert_eq ! ( foo. bar( ) , Some ( 54 ) ) ;
48+ irrefutable:: inner ( ) ;
49+ }
50+
51+ // The original, to show it fails for irrefutable let decls
52+ mod irrefutable {
53+ use std:: ops:: { Deref , DerefMut } ;
54+ struct Foo ( Bar ) ;
55+ struct Bar ( u32 ) ;
56+ impl Deref for Foo {
57+ type Target = Bar ;
58+ fn deref ( & self ) -> & Bar {
59+ & self . 0
60+ }
61+ }
62+ impl DerefMut for Foo {
63+ fn deref_mut ( & mut self ) -> & mut Bar {
64+ & mut self . 0
65+ }
66+ }
67+ fn foo ( x : & mut Foo ) {
68+ let Bar ( z) = x; //~ ERROR mismatched types
69+ * z = 54 ;
70+ assert_eq ! ( ( x. 0 ) . 0 , 54 ) ;
71+ }
72+ pub fn inner ( ) {
73+ foo ( & mut Foo ( Bar ( 1 ) ) ) ;
74+ }
75+ }
Original file line number Diff line number Diff line change 1+ error[E0308]: mismatched types
2+ --> $DIR/let-else-deref-coercion.rs:37:13
3+ |
4+ LL | let Bar::Present(z) = self else {
5+ | ^^^^^^^^^^^^^^^ ---- this expression has type `&mut Foo`
6+ | |
7+ | expected struct `Foo`, found enum `Bar`
8+
9+ error[E0308]: mismatched types
10+ --> $DIR/let-else-deref-coercion.rs:68:13
11+ |
12+ LL | let Bar(z) = x;
13+ | ^^^^^^ - this expression has type `&mut irrefutable::Foo`
14+ | |
15+ | expected struct `irrefutable::Foo`, found struct `irrefutable::Bar`
16+
17+ error: aborting due to 2 previous errors
18+
19+ For more information about this error, try `rustc --explain E0308`.
You can’t perform that action at this time.
0 commit comments