@@ -34,6 +34,90 @@ use rustc::ty::subst::InternalSubsts;
34
34
use rustc:: traits:: { self , ObligationCauseCode } ;
35
35
36
36
impl < ' a , ' tcx > FnCtxt < ' a , ' tcx > {
37
+ fn check_expr_eq_type ( & self , expr : & ' tcx hir:: Expr , expected : Ty < ' tcx > ) {
38
+ let ty = self . check_expr_with_hint ( expr, expected) ;
39
+ self . demand_eqtype ( expr. span , expected, ty) ;
40
+ }
41
+
42
+ pub fn check_expr_has_type_or_error (
43
+ & self ,
44
+ expr : & ' tcx hir:: Expr ,
45
+ expected : Ty < ' tcx > ,
46
+ ) -> Ty < ' tcx > {
47
+ self . check_expr_meets_expectation_or_error ( expr, ExpectHasType ( expected) )
48
+ }
49
+
50
+ fn check_expr_meets_expectation_or_error (
51
+ & self ,
52
+ expr : & ' tcx hir:: Expr ,
53
+ expected : Expectation < ' tcx > ,
54
+ ) -> Ty < ' tcx > {
55
+ let expected_ty = expected. to_option ( & self ) . unwrap_or ( self . tcx . types . bool ) ;
56
+ let mut ty = self . check_expr_with_expectation ( expr, expected) ;
57
+
58
+ // While we don't allow *arbitrary* coercions here, we *do* allow
59
+ // coercions from ! to `expected`.
60
+ if ty. is_never ( ) {
61
+ assert ! ( !self . tables. borrow( ) . adjustments( ) . contains_key( expr. hir_id) ,
62
+ "expression with never type wound up being adjusted" ) ;
63
+ let adj_ty = self . next_diverging_ty_var (
64
+ TypeVariableOrigin {
65
+ kind : TypeVariableOriginKind :: AdjustmentType ,
66
+ span : expr. span ,
67
+ } ,
68
+ ) ;
69
+ self . apply_adjustments ( expr, vec ! [ Adjustment {
70
+ kind: Adjust :: NeverToAny ,
71
+ target: adj_ty
72
+ } ] ) ;
73
+ ty = adj_ty;
74
+ }
75
+
76
+ if let Some ( mut err) = self . demand_suptype_diag ( expr. span , expected_ty, ty) {
77
+ let expr = match & expr. node {
78
+ ExprKind :: DropTemps ( expr) => expr,
79
+ _ => expr,
80
+ } ;
81
+ // Error possibly reported in `check_assign` so avoid emitting error again.
82
+ err. emit_unless ( self . is_assign_to_bool ( expr, expected_ty) ) ;
83
+ }
84
+ ty
85
+ }
86
+
87
+ pub ( super ) fn check_expr_coercable_to_type (
88
+ & self ,
89
+ expr : & ' tcx hir:: Expr ,
90
+ expected : Ty < ' tcx >
91
+ ) -> Ty < ' tcx > {
92
+ let ty = self . check_expr_with_hint ( expr, expected) ;
93
+ // checks don't need two phase
94
+ self . demand_coerce ( expr, ty, expected, AllowTwoPhase :: No )
95
+ }
96
+
97
+ pub ( super ) fn check_expr_with_hint (
98
+ & self ,
99
+ expr : & ' tcx hir:: Expr ,
100
+ expected : Ty < ' tcx >
101
+ ) -> Ty < ' tcx > {
102
+ self . check_expr_with_expectation ( expr, ExpectHasType ( expected) )
103
+ }
104
+
105
+ pub ( super ) fn check_expr_with_expectation (
106
+ & self ,
107
+ expr : & ' tcx hir:: Expr ,
108
+ expected : Expectation < ' tcx > ,
109
+ ) -> Ty < ' tcx > {
110
+ self . check_expr_with_expectation_and_needs ( expr, expected, Needs :: None )
111
+ }
112
+
113
+ pub ( super ) fn check_expr ( & self , expr : & ' tcx hir:: Expr ) -> Ty < ' tcx > {
114
+ self . check_expr_with_expectation ( expr, NoExpectation )
115
+ }
116
+
117
+ pub ( super ) fn check_expr_with_needs ( & self , expr : & ' tcx hir:: Expr , needs : Needs ) -> Ty < ' tcx > {
118
+ self . check_expr_with_expectation_and_needs ( expr, NoExpectation , needs)
119
+ }
120
+
37
121
/// Invariant:
38
122
/// If an expression has any sub-expressions that result in a type error,
39
123
/// inspecting that expression's type with `ty.references_error()` will return
@@ -44,7 +128,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
44
128
/// Note that inspecting a type's structure *directly* may expose the fact
45
129
/// that there are actually multiple representations for `Error`, so avoid
46
130
/// that when err needs to be handled differently.
47
- pub ( super ) fn check_expr_with_expectation_and_needs (
131
+ fn check_expr_with_expectation_and_needs (
48
132
& self ,
49
133
expr : & ' tcx hir:: Expr ,
50
134
expected : Expectation < ' tcx > ,
0 commit comments