1
1
use crate :: { ImplTraitContext , ImplTraitPosition , LoweringContext } ;
2
- use rustc_ast:: { Block , BlockCheckMode , Local , Stmt , StmtKind } ;
2
+ use rustc_ast:: { AttrVec , Block , BlockCheckMode , Expr , Local , LocalKind , Stmt , StmtKind } ;
3
3
use rustc_hir as hir;
4
+ use rustc_span:: symbol:: Ident ;
5
+ use rustc_span:: { sym, DesugaringKind } ;
4
6
5
7
use smallvec:: SmallVec ;
6
8
@@ -32,13 +34,24 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
32
34
let mut expr = None ;
33
35
while let [ s, tail @ ..] = ast_stmts {
34
36
match s. kind {
35
- StmtKind :: Local ( ref l) => {
36
- let l = self . lower_local ( l) ;
37
+ StmtKind :: Local ( ref local) => {
37
38
let hir_id = self . lower_node_id ( s. id ) ;
38
- self . alias_attrs ( hir_id, l. hir_id ) ;
39
- let kind = hir:: StmtKind :: Local ( self . arena . alloc ( l) ) ;
40
- let span = self . lower_span ( s. span ) ;
41
- stmts. push ( hir:: Stmt { hir_id, kind, span } ) ;
39
+ match & local. kind {
40
+ LocalKind :: InitElse ( init, els) => {
41
+ let ( s, e) = self . lower_let_else ( hir_id, local, init, els, tail) ;
42
+ stmts. push ( s) ;
43
+ expr = Some ( e) ;
44
+ // remaining statements are in let-else expression
45
+ break ;
46
+ }
47
+ _ => {
48
+ let local = self . lower_local ( local) ;
49
+ self . alias_attrs ( hir_id, local. hir_id ) ;
50
+ let kind = hir:: StmtKind :: Local ( local) ;
51
+ let span = self . lower_span ( s. span ) ;
52
+ stmts. push ( hir:: Stmt { hir_id, kind, span } ) ;
53
+ }
54
+ }
42
55
}
43
56
StmtKind :: Item ( ref it) => {
44
57
stmts. extend ( self . lower_item_id ( it) . into_iter ( ) . enumerate ( ) . map (
@@ -81,22 +94,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
81
94
( self . arena . alloc_from_iter ( stmts) , expr)
82
95
}
83
96
84
- fn lower_local ( & mut self , l : & Local ) -> hir:: Local < ' hir > {
97
+ fn lower_local ( & mut self , l : & Local ) -> & ' hir hir:: Local < ' hir > {
85
98
let ty = l
86
99
. ty
87
100
. as_ref ( )
88
101
. map ( |t| self . lower_ty ( t, ImplTraitContext :: Disallowed ( ImplTraitPosition :: Binding ) ) ) ;
89
102
let init = l. kind . init ( ) . map ( |init| self . lower_expr ( init) ) ;
90
103
let hir_id = self . lower_node_id ( l. id ) ;
104
+ let pat = self . lower_pat ( & l. pat ) ;
105
+ let span = self . lower_span ( l. span ) ;
106
+ let source = hir:: LocalSource :: Normal ;
91
107
self . lower_attrs ( hir_id, & l. attrs ) ;
92
- hir:: Local {
93
- hir_id,
94
- ty,
95
- pat : self . lower_pat ( & l. pat ) ,
96
- init,
97
- span : self . lower_span ( l. span ) ,
98
- source : hir:: LocalSource :: Normal ,
99
- }
108
+ self . arena . alloc ( hir:: Local { hir_id, ty, pat, init, span, source } )
100
109
}
101
110
102
111
fn lower_block_check_mode ( & mut self , b : & BlockCheckMode ) -> hir:: BlockCheckMode {
@@ -107,4 +116,60 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
107
116
}
108
117
}
109
118
}
119
+
120
+ fn lower_let_else (
121
+ & mut self ,
122
+ stmt_hir_id : hir:: HirId ,
123
+ local : & Local ,
124
+ init : & Expr ,
125
+ els : & Block ,
126
+ tail : & [ Stmt ] ,
127
+ ) -> ( hir:: Stmt < ' hir > , & ' hir hir:: Expr < ' hir > ) {
128
+ let ty = local
129
+ . ty
130
+ . as_ref ( )
131
+ . map ( |t| self . lower_ty ( t, ImplTraitContext :: Disallowed ( ImplTraitPosition :: Binding ) ) ) ;
132
+ let span = self . lower_span ( local. span ) ;
133
+ let span = self . mark_span_with_reason ( DesugaringKind :: LetElse , span, None ) ;
134
+ let init = Some ( self . lower_expr ( init) ) ;
135
+ let val = Ident :: with_dummy_span ( sym:: val) ;
136
+ let ( pat, val_id) =
137
+ self . pat_ident_binding_mode ( span, val, hir:: BindingAnnotation :: Unannotated ) ;
138
+ let local_hir_id = self . lower_node_id ( local. id ) ;
139
+ self . lower_attrs ( local_hir_id, & local. attrs ) ;
140
+ // first statement which basically exists for the type annotation
141
+ let stmt = {
142
+ let local = self . arena . alloc ( hir:: Local {
143
+ hir_id : local_hir_id,
144
+ ty,
145
+ pat,
146
+ init,
147
+ span,
148
+ source : hir:: LocalSource :: Normal ,
149
+ } ) ;
150
+ let kind = hir:: StmtKind :: Local ( local) ;
151
+ hir:: Stmt { hir_id : stmt_hir_id, kind, span }
152
+ } ;
153
+ let let_expr = {
154
+ let scrutinee = self . expr_ident ( span, val, val_id) ;
155
+ let let_kind = hir:: ExprKind :: Let ( self . lower_pat ( & local. pat ) , scrutinee, span) ;
156
+ self . arena . alloc ( self . expr ( span, let_kind, AttrVec :: new ( ) ) )
157
+ } ;
158
+ let then_expr = {
159
+ let ( stmts, expr) = self . lower_stmts ( tail) ;
160
+ let block = self . block_all ( span, stmts, expr) ;
161
+ self . arena . alloc ( self . expr_block ( block, AttrVec :: new ( ) ) )
162
+ } ;
163
+ let else_expr = {
164
+ let block = self . lower_block ( els, false ) ;
165
+ self . arena . alloc ( self . expr_block ( block, AttrVec :: new ( ) ) )
166
+ } ;
167
+ self . alias_attrs ( else_expr. hir_id , local_hir_id) ;
168
+ let if_expr = self . arena . alloc ( hir:: Expr {
169
+ hir_id : self . next_id ( ) ,
170
+ span,
171
+ kind : hir:: ExprKind :: If ( let_expr, then_expr, Some ( else_expr) ) ,
172
+ } ) ;
173
+ ( stmt, if_expr)
174
+ }
110
175
}
0 commit comments