@@ -130,7 +130,7 @@ impl<'a> InferenceContext<'a> {
130
130
) ;
131
131
let ty = match label {
132
132
Some ( _) => {
133
- let break_ty = self . table . new_type_var ( ) ;
133
+ let break_ty = expected . coercion_target_type ( & mut self . table ) ;
134
134
let ( breaks, ty) = self . with_breakable_ctx (
135
135
BreakableKind :: Block ,
136
136
Some ( break_ty. clone ( ) ) ,
@@ -403,37 +403,47 @@ impl<'a> InferenceContext<'a> {
403
403
Expr :: Match { expr, arms } => {
404
404
let input_ty = self . infer_expr ( * expr, & Expectation :: none ( ) ) ;
405
405
406
- let expected = expected. adjust_for_branches ( & mut self . table ) ;
407
-
408
- let result_ty = if arms. is_empty ( ) {
406
+ if arms. is_empty ( ) {
407
+ self . diverges = Diverges :: Always ;
409
408
self . result . standard_types . never . clone ( )
410
409
} else {
411
- expected. coercion_target_type ( & mut self . table )
412
- } ;
413
- let mut coerce = CoerceMany :: new ( result_ty) ;
414
-
415
- let matchee_diverges = self . diverges ;
416
- let mut all_arms_diverge = Diverges :: Always ;
417
-
418
- for arm in arms. iter ( ) {
419
- self . diverges = Diverges :: Maybe ;
420
- let input_ty = self . resolve_ty_shallow ( & input_ty) ;
421
- self . infer_top_pat ( arm. pat , & input_ty) ;
422
- if let Some ( guard_expr) = arm. guard {
423
- self . infer_expr (
424
- guard_expr,
425
- & Expectation :: HasType ( self . result . standard_types . bool_ . clone ( ) ) ,
426
- ) ;
410
+ let matchee_diverges = mem:: replace ( & mut self . diverges , Diverges :: Maybe ) ;
411
+ let mut all_arms_diverge = Diverges :: Always ;
412
+ for arm in arms. iter ( ) {
413
+ let input_ty = self . resolve_ty_shallow ( & input_ty) ;
414
+ self . infer_top_pat ( arm. pat , & input_ty) ;
427
415
}
428
416
429
- let arm_ty = self . infer_expr_inner ( arm. expr , & expected) ;
430
- all_arms_diverge &= self . diverges ;
431
- coerce. coerce ( self , Some ( arm. expr ) , & arm_ty) ;
432
- }
417
+ let expected = expected. adjust_for_branches ( & mut self . table ) ;
418
+ let result_ty = match & expected {
419
+ // We don't coerce to `()` so that if the match expression is a
420
+ // statement it's branches can have any consistent type.
421
+ Expectation :: HasType ( ty) if * ty != self . result . standard_types . unit => {
422
+ ty. clone ( )
423
+ }
424
+ _ => self . table . new_type_var ( ) ,
425
+ } ;
426
+ let mut coerce = CoerceMany :: new ( result_ty) ;
427
+
428
+ for arm in arms. iter ( ) {
429
+ if let Some ( guard_expr) = arm. guard {
430
+ self . diverges = Diverges :: Maybe ;
431
+ self . infer_expr (
432
+ guard_expr,
433
+ & Expectation :: HasType ( self . result . standard_types . bool_ . clone ( ) ) ,
434
+ ) ;
435
+ }
436
+ self . diverges = Diverges :: Maybe ;
433
437
434
- self . diverges = matchee_diverges | all_arms_diverge;
438
+ let arm_ty = self . infer_expr_inner ( arm. expr , & expected) ;
439
+ all_arms_diverge &= self . diverges ;
440
+ coerce. coerce ( self , Some ( arm. expr ) , & arm_ty) ;
441
+ }
435
442
436
- coerce. complete ( self )
443
+ self . diverges = matchee_diverges | all_arms_diverge;
444
+
445
+ coerce. complete ( self )
446
+ }
437
447
}
438
448
Expr :: Path ( p) => {
439
449
// FIXME this could be more efficient...
@@ -1179,8 +1189,15 @@ impl<'a> InferenceContext<'a> {
1179
1189
self . diverges = previous_diverges;
1180
1190
}
1181
1191
}
1182
- Statement :: Expr { expr, .. } => {
1183
- self . infer_expr ( * expr, & Expectation :: none ( ) ) ;
1192
+ & Statement :: Expr { expr, has_semi } => {
1193
+ self . infer_expr (
1194
+ expr,
1195
+ & if has_semi {
1196
+ Expectation :: none ( )
1197
+ } else {
1198
+ Expectation :: HasType ( self . result . standard_types . unit . clone ( ) )
1199
+ } ,
1200
+ ) ;
1184
1201
}
1185
1202
}
1186
1203
}
0 commit comments