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,18 @@ use crate::{
2121 Ty , TypeCtor , Uncertain ,
2222} ;
2323
24- use super :: { BindingMode , Expectation , InferenceContext , InferenceDiagnostic , TypeMismatch } ;
24+ use super :: {
25+ BindingMode , BreakableContext , Diverges , Expectation , InferenceContext , InferenceDiagnostic ,
26+ TypeMismatch ,
27+ } ;
2528
2629impl < ' a > InferenceContext < ' a > {
2730 pub ( super ) fn infer_expr ( & mut self , tgt_expr : ExprId , expected : & Expectation ) -> Ty {
2831 let ty = self . infer_expr_inner ( tgt_expr, expected) ;
32+ if ty. is_never ( ) {
33+ // Any expression that produces a value of type `!` must have diverged
34+ self . diverges = Diverges :: Always ;
35+ }
2936 let could_unify = self . unify ( & ty, & expected. ty ) ;
3037 if !could_unify {
3138 self . result . type_mismatches . insert (
@@ -64,11 +71,18 @@ impl<'a> InferenceContext<'a> {
6471 // if let is desugared to match, so this is always simple if
6572 self . infer_expr ( * condition, & Expectation :: has_type ( Ty :: simple ( TypeCtor :: Bool ) ) ) ;
6673
74+ let condition_diverges = mem:: replace ( & mut self . diverges , Diverges :: Maybe ) ;
75+ let mut both_arms_diverge = Diverges :: Always ;
76+
6777 let then_ty = self . infer_expr_inner ( * then_branch, & expected) ;
78+ both_arms_diverge &= mem:: replace ( & mut self . diverges , Diverges :: Maybe ) ;
6879 let else_ty = match else_branch {
6980 Some ( else_branch) => self . infer_expr_inner ( * else_branch, & expected) ,
7081 None => Ty :: unit ( ) ,
7182 } ;
83+ both_arms_diverge &= self . diverges ;
84+
85+ self . diverges = condition_diverges | both_arms_diverge;
7286
7387 self . coerce_merge_branch ( & then_ty, & else_ty)
7488 }
@@ -79,24 +93,43 @@ impl<'a> InferenceContext<'a> {
7993 Ty :: Unknown
8094 }
8195 Expr :: Loop { body } => {
96+ self . breakables . push ( BreakableContext { may_break : false } ) ;
8297 self . infer_expr ( * body, & Expectation :: has_type ( Ty :: unit ( ) ) ) ;
98+
99+ let ctxt = self . breakables . pop ( ) . expect ( "breakable stack broken" ) ;
100+ if ctxt. may_break {
101+ self . diverges = Diverges :: Maybe ;
102+ }
83103 // FIXME handle break with value
84- Ty :: simple ( TypeCtor :: Never )
104+ if ctxt. may_break {
105+ Ty :: unit ( )
106+ } else {
107+ Ty :: simple ( TypeCtor :: Never )
108+ }
85109 }
86110 Expr :: While { condition, body } => {
111+ self . breakables . push ( BreakableContext { may_break : false } ) ;
87112 // while let is desugared to a match loop, so this is always simple while
88113 self . infer_expr ( * condition, & Expectation :: has_type ( Ty :: simple ( TypeCtor :: Bool ) ) ) ;
89114 self . infer_expr ( * body, & Expectation :: has_type ( Ty :: unit ( ) ) ) ;
115+ let _ctxt = self . breakables . pop ( ) . expect ( "breakable stack broken" ) ;
116+ // the body may not run, so it diverging doesn't mean we diverge
117+ self . diverges = Diverges :: Maybe ;
90118 Ty :: unit ( )
91119 }
92120 Expr :: For { iterable, body, pat } => {
93121 let iterable_ty = self . infer_expr ( * iterable, & Expectation :: none ( ) ) ;
94122
123+ self . breakables . push ( BreakableContext { may_break : false } ) ;
95124 let pat_ty =
96125 self . resolve_associated_type ( iterable_ty, self . resolve_into_iter_item ( ) ) ;
97126
98127 self . infer_pat ( * pat, & pat_ty, BindingMode :: default ( ) ) ;
128+
99129 self . infer_expr ( * body, & Expectation :: has_type ( Ty :: unit ( ) ) ) ;
130+ let _ctxt = self . breakables . pop ( ) . expect ( "breakable stack broken" ) ;
131+ // the body may not run, so it diverging doesn't mean we diverge
132+ self . diverges = Diverges :: Maybe ;
100133 Ty :: unit ( )
101134 }
102135 Expr :: Lambda { body, args, ret_type, arg_types } => {
@@ -132,10 +165,12 @@ impl<'a> InferenceContext<'a> {
132165 // infer the body.
133166 self . coerce ( & closure_ty, & expected. ty ) ;
134167
135- let prev_ret_ty = std:: mem:: replace ( & mut self . return_ty , ret_ty. clone ( ) ) ;
168+ let prev_diverges = mem:: replace ( & mut self . diverges , Diverges :: Maybe ) ;
169+ let prev_ret_ty = mem:: replace ( & mut self . return_ty , ret_ty. clone ( ) ) ;
136170
137171 self . infer_expr_coerce ( * body, & Expectation :: has_type ( ret_ty) ) ;
138172
173+ self . diverges = prev_diverges;
139174 self . return_ty = prev_ret_ty;
140175
141176 closure_ty
@@ -165,7 +200,11 @@ impl<'a> InferenceContext<'a> {
165200 self . table . new_type_var ( )
166201 } ;
167202
203+ let matchee_diverges = self . diverges ;
204+ let mut all_arms_diverge = Diverges :: Always ;
205+
168206 for arm in arms {
207+ self . diverges = Diverges :: Maybe ;
169208 let _pat_ty = self . infer_pat ( arm. pat , & input_ty, BindingMode :: default ( ) ) ;
170209 if let Some ( guard_expr) = arm. guard {
171210 self . infer_expr (
@@ -175,9 +214,12 @@ impl<'a> InferenceContext<'a> {
175214 }
176215
177216 let arm_ty = self . infer_expr_inner ( arm. expr , & expected) ;
217+ all_arms_diverge &= self . diverges ;
178218 result_ty = self . coerce_merge_branch ( & result_ty, & arm_ty) ;
179219 }
180220
221+ self . diverges = matchee_diverges | all_arms_diverge;
222+
181223 result_ty
182224 }
183225 Expr :: Path ( p) => {
@@ -191,6 +233,13 @@ impl<'a> InferenceContext<'a> {
191233 // FIXME handle break with value
192234 self . infer_expr ( * expr, & Expectation :: none ( ) ) ;
193235 }
236+ if let Some ( ctxt) = self . breakables . last_mut ( ) {
237+ ctxt. may_break = true ;
238+ } else {
239+ self . push_diagnostic ( InferenceDiagnostic :: BreakOutsideOfLoop {
240+ expr : tgt_expr,
241+ } ) ;
242+ }
194243 Ty :: simple ( TypeCtor :: Never )
195244 }
196245 Expr :: Return { expr } => {
@@ -522,7 +571,6 @@ impl<'a> InferenceContext<'a> {
522571 tail : Option < ExprId > ,
523572 expected : & Expectation ,
524573 ) -> Ty {
525- let mut diverges = false ;
526574 for stmt in statements {
527575 match stmt {
528576 Statement :: Let { pat, type_ref, initializer } => {
@@ -544,24 +592,30 @@ impl<'a> InferenceContext<'a> {
544592 self . infer_pat ( * pat, & ty, BindingMode :: default ( ) ) ;
545593 }
546594 Statement :: Expr ( expr) => {
547- if let ty_app ! ( TypeCtor :: Never ) = self . infer_expr ( * expr, & Expectation :: none ( ) ) {
548- diverges = true ;
549- }
595+ self . infer_expr ( * expr, & Expectation :: none ( ) ) ;
550596 }
551597 }
552598 }
553599
554600 let ty = if let Some ( expr) = tail {
555601 self . infer_expr_coerce ( expr, expected)
556602 } else {
557- self . coerce ( & Ty :: unit ( ) , expected. coercion_target ( ) ) ;
558- Ty :: unit ( )
603+ // Citing rustc: if there is no explicit tail expression,
604+ // that is typically equivalent to a tail expression
605+ // of `()` -- except if the block diverges. In that
606+ // case, there is no value supplied from the tail
607+ // expression (assuming there are no other breaks,
608+ // this implies that the type of the block will be
609+ // `!`).
610+ if self . diverges . is_always ( ) {
611+ // we don't even make an attempt at coercion
612+ self . table . new_maybe_never_type_var ( )
613+ } else {
614+ self . coerce ( & Ty :: unit ( ) , expected. coercion_target ( ) ) ;
615+ Ty :: unit ( )
616+ }
559617 } ;
560- if diverges {
561- Ty :: simple ( TypeCtor :: Never )
562- } else {
563- ty
564- }
618+ ty
565619 }
566620
567621 fn infer_method_call (
0 commit comments