File tree 3 files changed +171
-0
lines changed
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