@@ -146,7 +146,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
146
146
hir:: ExprKind :: Block ( self . lower_block ( blk, opt_label. is_some ( ) ) , opt_label)
147
147
}
148
148
ExprKind :: Assign ( ref el, ref er, span) => {
149
- hir :: ExprKind :: Assign ( self . lower_expr ( el) , self . lower_expr ( er ) , span)
149
+ self . lower_expr_assign ( el, er , span , e . span )
150
150
}
151
151
ExprKind :: AssignOp ( op, ref el, ref er) => hir:: ExprKind :: AssignOp (
152
152
self . lower_binop ( op) ,
@@ -163,6 +163,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
163
163
ExprKind :: Range ( ref e1, ref e2, lims) => {
164
164
self . lower_expr_range ( e. span , e1. as_deref ( ) , e2. as_deref ( ) , lims)
165
165
}
166
+ ExprKind :: Underscore => {
167
+ self . sess
168
+ . struct_span_err (
169
+ e. span ,
170
+ "expected expression, found reserved identifier `_`" ,
171
+ )
172
+ . span_label ( e. span , "expected expression" )
173
+ . emit ( ) ;
174
+ hir:: ExprKind :: Err
175
+ }
166
176
ExprKind :: Path ( ref qself, ref path) => {
167
177
let qpath = self . lower_qpath (
168
178
e. id ,
@@ -186,8 +196,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
186
196
}
187
197
ExprKind :: InlineAsm ( ref asm) => self . lower_expr_asm ( e. span , asm) ,
188
198
ExprKind :: LlvmInlineAsm ( ref asm) => self . lower_expr_llvm_asm ( asm) ,
189
- ExprKind :: Struct ( ref path, ref fields, ref maybe_expr) => {
190
- let maybe_expr = maybe_expr. as_ref ( ) . map ( |x| self . lower_expr ( x) ) ;
199
+ ExprKind :: Struct ( ref path, ref fields, ref rest) => {
200
+ let rest = match rest {
201
+ StructRest :: Base ( e) => Some ( self . lower_expr ( e) ) ,
202
+ StructRest :: Rest ( sp) => {
203
+ self . sess
204
+ . struct_span_err ( * sp, "base expression required after `..`" )
205
+ . span_label ( * sp, "add a base expression here" )
206
+ . emit ( ) ;
207
+ Some ( & * self . arena . alloc ( self . expr_err ( * sp) ) )
208
+ }
209
+ StructRest :: None => None ,
210
+ } ;
191
211
hir:: ExprKind :: Struct (
192
212
self . arena . alloc ( self . lower_qpath (
193
213
e. id ,
@@ -197,7 +217,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
197
217
ImplTraitContext :: disallowed ( ) ,
198
218
) ) ,
199
219
self . arena . alloc_from_iter ( fields. iter ( ) . map ( |x| self . lower_field ( x) ) ) ,
200
- maybe_expr ,
220
+ rest ,
201
221
)
202
222
}
203
223
ExprKind :: Yield ( ref opt_expr) => self . lower_expr_yield ( e. span , opt_expr. as_deref ( ) ) ,
@@ -840,6 +860,66 @@ impl<'hir> LoweringContext<'_, 'hir> {
840
860
} )
841
861
}
842
862
863
+ /// Lower `(a,b) = t` to `{ let (lhs1,lhs2) = t; a = lhs1; b = lhs2; }`.
864
+ fn lower_expr_assign (
865
+ & mut self ,
866
+ lhs : & Expr ,
867
+ rhs : & Expr ,
868
+ eq_sign_span : Span ,
869
+ whole_span : Span ,
870
+ ) -> hir:: ExprKind < ' hir > {
871
+ let mut assignments = Vec :: new ( ) ;
872
+
873
+ // The LHS becomes a pattern: `(lhs1, lhs2)`
874
+ let pat = self . destructure_assign ( lhs, eq_sign_span, & mut assignments) ;
875
+ let rhs = self . lower_expr ( rhs) ;
876
+
877
+ // Introduce a let for destructuring: `let (lhs1,lhs2) = t`.
878
+ let destructure_let = self . stmt_let_pat (
879
+ ThinVec :: new ( ) ,
880
+ whole_span,
881
+ Some ( rhs) ,
882
+ pat,
883
+ hir:: LocalSource :: AssignDesugar ( eq_sign_span) ,
884
+ ) ;
885
+
886
+ // `a = lhs1; b = lhs2;`.
887
+ let stmts = self
888
+ . arena
889
+ . alloc_from_iter ( std:: iter:: once ( destructure_let) . chain ( assignments. into_iter ( ) ) ) ;
890
+
891
+ // Wrap everything in a block.
892
+ hir:: ExprKind :: Block ( & self . block_all ( whole_span, stmts, None ) , None )
893
+ }
894
+
895
+ /// Convert the LHS of a destructuring assignment to a pattern.
896
+ /// Along the way, introduce additional assignments in the parameter assignments.
897
+ fn destructure_assign (
898
+ & mut self ,
899
+ lhs : & Expr ,
900
+ eq_sign_span : Span ,
901
+ assignments : & mut Vec < hir:: Stmt < ' hir > > ,
902
+ ) -> & ' hir hir:: Pat < ' hir > {
903
+ match & lhs. kind {
904
+ ExprKind :: Tup ( elements) => {
905
+ let pats = self . arena . alloc_from_iter (
906
+ elements. iter ( ) . map ( |e| self . destructure_assign ( e, eq_sign_span, assignments) ) ,
907
+ ) ;
908
+ let tuple_pat = hir:: PatKind :: Tuple ( pats, None ) ;
909
+ self . pat ( lhs. span , tuple_pat)
910
+ }
911
+ _ => {
912
+ let ident = Ident :: new ( sym:: lhs, lhs. span ) ;
913
+ let ( pat, binding) = self . pat_ident ( lhs. span , ident) ;
914
+ let ident = self . expr_ident ( lhs. span , ident, binding) ;
915
+ let assign = hir:: ExprKind :: Assign ( self . lower_expr ( lhs) , ident, eq_sign_span) ;
916
+ let expr = self . expr ( lhs. span , assign, ThinVec :: new ( ) ) ;
917
+ assignments. push ( self . stmt_expr ( lhs. span , expr) ) ;
918
+ pat
919
+ }
920
+ }
921
+ }
922
+
843
923
/// Desugar `<start>..=<end>` into `std::ops::RangeInclusive::new(<start>, <end>)`.
844
924
fn lower_expr_range_closed ( & mut self , span : Span , e1 : & Expr , e2 : & Expr ) -> hir:: ExprKind < ' hir > {
845
925
let e1 = self . lower_expr_mut ( e1) ;
0 commit comments