11//! Type inference for expressions.
22
33use std:: iter:: { repeat, repeat_with} ;
4- use std:: sync:: Arc ;
4+ use std:: { mem , sync:: Arc } ;
55
66use hir_def:: {
77 builtin_type:: Signedness ,
@@ -21,11 +21,15 @@ use crate::{
2121 Ty , TypeCtor , Uncertain ,
2222} ;
2323
24- use super :: { BindingMode , Expectation , InferenceContext , InferenceDiagnostic , TypeMismatch } ;
24+ use super :: { BindingMode , Expectation , InferenceContext , InferenceDiagnostic , TypeMismatch , Diverges } ;
2525
2626impl < ' a > InferenceContext < ' a > {
2727 pub ( super ) fn infer_expr ( & mut self , tgt_expr : ExprId , expected : & Expectation ) -> Ty {
2828 let ty = self . infer_expr_inner ( tgt_expr, expected) ;
29+ if ty. is_never ( ) {
30+ // Any expression that produces a value of type `!` must have diverged
31+ self . diverges = Diverges :: Always ;
32+ }
2933 let could_unify = self . unify ( & ty, & expected. ty ) ;
3034 if !could_unify {
3135 self . result . type_mismatches . insert (
@@ -64,11 +68,18 @@ impl<'a> InferenceContext<'a> {
6468 // if let is desugared to match, so this is always simple if
6569 self . infer_expr ( * condition, & Expectation :: has_type ( Ty :: simple ( TypeCtor :: Bool ) ) ) ;
6670
71+ let condition_diverges = mem:: replace ( & mut self . diverges , Diverges :: Maybe ) ;
72+ let mut both_arms_diverge = Diverges :: Always ;
73+
6774 let then_ty = self . infer_expr_inner ( * then_branch, & expected) ;
75+ both_arms_diverge &= mem:: replace ( & mut self . diverges , Diverges :: Maybe ) ;
6876 let else_ty = match else_branch {
6977 Some ( else_branch) => self . infer_expr_inner ( * else_branch, & expected) ,
7078 None => Ty :: unit ( ) ,
7179 } ;
80+ both_arms_diverge &= self . diverges ;
81+
82+ self . diverges = condition_diverges | both_arms_diverge;
7283
7384 self . coerce_merge_branch ( & then_ty, & else_ty)
7485 }
@@ -132,10 +143,12 @@ impl<'a> InferenceContext<'a> {
132143 // infer the body.
133144 self . coerce ( & closure_ty, & expected. ty ) ;
134145
135- let prev_ret_ty = std:: mem:: replace ( & mut self . return_ty , ret_ty. clone ( ) ) ;
146+ let prev_diverges = mem:: replace ( & mut self . diverges , Diverges :: Maybe ) ;
147+ let prev_ret_ty = mem:: replace ( & mut self . return_ty , ret_ty. clone ( ) ) ;
136148
137149 self . infer_expr_coerce ( * body, & Expectation :: has_type ( ret_ty) ) ;
138150
151+ self . diverges = prev_diverges;
139152 self . return_ty = prev_ret_ty;
140153
141154 closure_ty
@@ -165,7 +178,11 @@ impl<'a> InferenceContext<'a> {
165178 self . table . new_type_var ( )
166179 } ;
167180
181+ let matchee_diverges = self . diverges ;
182+ let mut all_arms_diverge = Diverges :: Always ;
183+
168184 for arm in arms {
185+ self . diverges = Diverges :: Maybe ;
169186 let _pat_ty = self . infer_pat ( arm. pat , & input_ty, BindingMode :: default ( ) ) ;
170187 if let Some ( guard_expr) = arm. guard {
171188 self . infer_expr (
@@ -175,9 +192,12 @@ impl<'a> InferenceContext<'a> {
175192 }
176193
177194 let arm_ty = self . infer_expr_inner ( arm. expr , & expected) ;
195+ all_arms_diverge &= self . diverges ;
178196 result_ty = self . coerce_merge_branch ( & result_ty, & arm_ty) ;
179197 }
180198
199+ self . diverges = matchee_diverges | all_arms_diverge;
200+
181201 result_ty
182202 }
183203 Expr :: Path ( p) => {
@@ -522,7 +542,6 @@ impl<'a> InferenceContext<'a> {
522542 tail : Option < ExprId > ,
523543 expected : & Expectation ,
524544 ) -> Ty {
525- let mut diverges = false ;
526545 for stmt in statements {
527546 match stmt {
528547 Statement :: Let { pat, type_ref, initializer } => {
@@ -544,24 +563,30 @@ impl<'a> InferenceContext<'a> {
544563 self . infer_pat ( * pat, & ty, BindingMode :: default ( ) ) ;
545564 }
546565 Statement :: Expr ( expr) => {
547- if let ty_app ! ( TypeCtor :: Never ) = self . infer_expr ( * expr, & Expectation :: none ( ) ) {
548- diverges = true ;
549- }
566+ self . infer_expr ( * expr, & Expectation :: none ( ) ) ;
550567 }
551568 }
552569 }
553570
554571 let ty = if let Some ( expr) = tail {
555572 self . infer_expr_coerce ( expr, expected)
556573 } else {
557- self . coerce ( & Ty :: unit ( ) , expected. coercion_target ( ) ) ;
558- Ty :: unit ( )
574+ // Citing rustc: if there is no explicit tail expression,
575+ // that is typically equivalent to a tail expression
576+ // of `()` -- except if the block diverges. In that
577+ // case, there is no value supplied from the tail
578+ // expression (assuming there are no other breaks,
579+ // this implies that the type of the block will be
580+ // `!`).
581+ if self . diverges . is_always ( ) {
582+ // we don't even make an attempt at coercion
583+ self . table . new_maybe_never_type_var ( )
584+ } else {
585+ self . coerce ( & Ty :: unit ( ) , expected. coercion_target ( ) ) ;
586+ Ty :: unit ( )
587+ }
559588 } ;
560- if diverges {
561- Ty :: simple ( TypeCtor :: Never )
562- } else {
563- ty
564- }
589+ ty
565590 }
566591
567592 fn infer_method_call (
0 commit comments