@@ -130,7 +130,7 @@ impl<'a> InferenceContext<'a> {
130130 ) ;
131131 let ty = match label {
132132 Some ( _) => {
133- let break_ty = self . table . new_type_var ( ) ;
133+ let break_ty = expected . coercion_target_type ( & mut self . table ) ;
134134 let ( breaks, ty) = self . with_breakable_ctx (
135135 BreakableKind :: Block ,
136136 Some ( break_ty. clone ( ) ) ,
@@ -403,37 +403,47 @@ impl<'a> InferenceContext<'a> {
403403 Expr :: Match { expr, arms } => {
404404 let input_ty = self . infer_expr ( * expr, & Expectation :: none ( ) ) ;
405405
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 ;
409408 self . result . standard_types . never . clone ( )
410409 } 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) ;
427415 }
428416
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 ;
433437
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+ }
435442
436- coerce. complete ( self )
443+ self . diverges = matchee_diverges | all_arms_diverge;
444+
445+ coerce. complete ( self )
446+ }
437447 }
438448 Expr :: Path ( p) => {
439449 // FIXME this could be more efficient...
@@ -1179,8 +1189,15 @@ impl<'a> InferenceContext<'a> {
11791189 self . diverges = previous_diverges;
11801190 }
11811191 }
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+ ) ;
11841201 }
11851202 }
11861203 }
0 commit comments