11use 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 } ;
33use rustc_hir as hir;
4+ use rustc_span:: symbol:: Ident ;
5+ use rustc_span:: { sym, DesugaringKind } ;
46
57use smallvec:: SmallVec ;
68
@@ -32,13 +34,24 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
3234 let mut expr = None ;
3335 while let [ s, tail @ ..] = ast_stmts {
3436 match s. kind {
35- StmtKind :: Local ( ref l) => {
36- let l = self . lower_local ( l) ;
37+ StmtKind :: Local ( ref local) => {
3738 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+ }
4255 }
4356 StmtKind :: Item ( ref it) => {
4457 stmts. extend ( self . lower_item_id ( it) . into_iter ( ) . enumerate ( ) . map (
@@ -81,22 +94,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
8194 ( self . arena . alloc_from_iter ( stmts) , expr)
8295 }
8396
84- fn lower_local ( & mut self , l : & Local ) -> hir:: Local < ' hir > {
97+ fn lower_local ( & mut self , l : & Local ) -> & ' hir hir:: Local < ' hir > {
8598 let ty = l
8699 . ty
87100 . as_ref ( )
88101 . map ( |t| self . lower_ty ( t, ImplTraitContext :: Disallowed ( ImplTraitPosition :: Binding ) ) ) ;
89102 let init = l. kind . init ( ) . map ( |init| self . lower_expr ( init) ) ;
90103 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 ;
91107 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 } )
100109 }
101110
102111 fn lower_block_check_mode ( & mut self , b : & BlockCheckMode ) -> hir:: BlockCheckMode {
@@ -107,4 +116,60 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
107116 }
108117 }
109118 }
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+ }
110175}
0 commit comments