@@ -55,6 +55,9 @@ use crate::{
55
55
} ;
56
56
57
57
impl < ' a , ' tcx > FnCtxt < ' a , ' tcx > {
58
+ /// Check an expr with an expectation type, and also demand that the expr's
59
+ /// evaluated type is a subtype of the expectation at the end. This is a
60
+ /// *hard* requirement.
58
61
pub ( crate ) fn check_expr_has_type_or_error (
59
62
& self ,
60
63
expr : & ' tcx hir:: Expr < ' tcx > ,
@@ -97,6 +100,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
97
100
ty
98
101
}
99
102
103
+ /// Check an expr with an expectation type, and also demand that the expr's
104
+ /// evaluated type is a coercible to the expectation at the end. This is a
105
+ /// *hard* requirement.
100
106
pub ( super ) fn check_expr_coercible_to_type (
101
107
& self ,
102
108
expr : & ' tcx hir:: Expr < ' tcx > ,
@@ -128,6 +134,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
128
134
}
129
135
}
130
136
137
+ /// Check an expr with an expectation type. Don't actually enforce that expectation
138
+ /// is related to the expr's evaluated type via subtyping or coercion. This is
139
+ /// usually called because we want to do that subtype/coerce call manually for better
140
+ /// diagnostics.
131
141
pub ( super ) fn check_expr_with_hint (
132
142
& self ,
133
143
expr : & ' tcx hir:: Expr < ' tcx > ,
@@ -136,6 +146,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
136
146
self . check_expr_with_expectation ( expr, ExpectHasType ( expected) )
137
147
}
138
148
149
+ /// Check an expr with an expectation type, and also [`Needs`] which will
150
+ /// prompt typeck to convert any implicit immutable derefs to mutable derefs.
139
151
fn check_expr_with_expectation_and_needs (
140
152
& self ,
141
153
expr : & ' tcx hir:: Expr < ' tcx > ,
@@ -153,10 +165,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
153
165
ty
154
166
}
155
167
168
+ /// Check an expr with no expectations.
156
169
pub ( super ) fn check_expr ( & self , expr : & ' tcx hir:: Expr < ' tcx > ) -> Ty < ' tcx > {
157
170
self . check_expr_with_expectation ( expr, NoExpectation )
158
171
}
159
172
173
+ /// Check an expr with no expectations, but with [`Needs`] which will
174
+ /// prompt typeck to convert any implicit immutable derefs to mutable derefs.
160
175
pub ( super ) fn check_expr_with_needs (
161
176
& self ,
162
177
expr : & ' tcx hir:: Expr < ' tcx > ,
@@ -165,33 +180,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
165
180
self . check_expr_with_expectation_and_needs ( expr, NoExpectation , needs)
166
181
}
167
182
168
- /// Invariant:
169
- /// If an expression has any sub-expressions that result in a type error,
170
- /// inspecting that expression's type with `ty.references_error()` will return
171
- /// true. Likewise, if an expression is known to diverge, inspecting its
172
- /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
173
- /// strict, _|_ can appear in the type of an expression that does not,
174
- /// itself, diverge: for example, fn() -> _|_.)
175
- /// Note that inspecting a type's structure *directly* may expose the fact
176
- /// that there are actually multiple representations for `Error`, so avoid
177
- /// that when err needs to be handled differently.
183
+ /// Check an expr with an expectation type which may be used to eagerly
184
+ /// guide inference when evaluating that expr.
178
185
#[ instrument( skip( self , expr) , level = "debug" ) ]
179
186
pub ( super ) fn check_expr_with_expectation (
180
187
& self ,
181
188
expr : & ' tcx hir:: Expr < ' tcx > ,
182
189
expected : Expectation < ' tcx > ,
183
190
) -> Ty < ' tcx > {
184
- self . check_expr_with_expectation_and_args ( expr, expected, & [ ] , None )
191
+ self . check_expr_with_expectation_and_args ( expr, expected, None )
185
192
}
186
193
187
- /// Same as `check_expr_with_expectation`, but allows us to pass in the arguments of a
188
- /// `ExprKind::Call` when evaluating its callee when it is an `ExprKind::Path`.
194
+ /// Same as [`Self::check_expr_with_expectation`], but allows us to pass in
195
+ /// the arguments of a [`ExprKind::Call`] when evaluating its callee that
196
+ /// is an [`ExprKind::Path`]. We use this to refine the spans for certain
197
+ /// well-formedness guarantees for the path expr.
189
198
pub ( super ) fn check_expr_with_expectation_and_args (
190
199
& self ,
191
200
expr : & ' tcx hir:: Expr < ' tcx > ,
192
201
expected : Expectation < ' tcx > ,
193
- args : & ' tcx [ hir:: Expr < ' tcx > ] ,
194
- call : Option < & ' tcx hir:: Expr < ' tcx > > ,
202
+ call_expr_and_args : Option < ( & ' tcx hir:: Expr < ' tcx > , & ' tcx [ hir:: Expr < ' tcx > ] ) > ,
195
203
) -> Ty < ' tcx > {
196
204
if self . tcx ( ) . sess . verbose_internals ( ) {
197
205
// make this code only run with -Zverbose-internals because it is probably slow
@@ -236,9 +244,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
236
244
} ;
237
245
238
246
let ty = ensure_sufficient_stack ( || match & expr. kind {
247
+ // Intercept the callee path expr and give it better spans.
239
248
hir:: ExprKind :: Path (
240
249
qpath @ ( hir:: QPath :: Resolved ( ..) | hir:: QPath :: TypeRelative ( ..) ) ,
241
- ) => self . check_expr_path ( qpath, expr, Some ( args ) , call ) ,
250
+ ) => self . check_expr_path ( qpath, expr, call_expr_and_args ) ,
242
251
_ => self . check_expr_kind ( expr, expected) ,
243
252
} ) ;
244
253
let ty = self . resolve_vars_if_possible ( ty) ;
@@ -472,28 +481,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
472
481
473
482
let tcx = self . tcx ;
474
483
match expr. kind {
475
- ExprKind :: Lit ( ref lit) => self . check_lit ( lit, expected) ,
476
- ExprKind :: Binary ( op, lhs, rhs) => self . check_binop ( expr, op, lhs, rhs, expected) ,
484
+ ExprKind :: Lit ( ref lit) => self . check_expr_lit ( lit, expected) ,
485
+ ExprKind :: Binary ( op, lhs, rhs) => self . check_expr_binop ( expr, op, lhs, rhs, expected) ,
477
486
ExprKind :: Assign ( lhs, rhs, span) => {
478
487
self . check_expr_assign ( expr, expected, lhs, rhs, span)
479
488
}
480
489
ExprKind :: AssignOp ( op, lhs, rhs) => {
481
- self . check_binop_assign ( expr, op, lhs, rhs, expected)
490
+ self . check_expr_binop_assign ( expr, op, lhs, rhs, expected)
482
491
}
483
- ExprKind :: Unary ( unop, oprnd) => self . check_expr_unary ( unop, oprnd, expected, expr) ,
492
+ ExprKind :: Unary ( unop, oprnd) => self . check_expr_unop ( unop, oprnd, expected, expr) ,
484
493
ExprKind :: AddrOf ( kind, mutbl, oprnd) => {
485
494
self . check_expr_addr_of ( kind, mutbl, oprnd, expected, expr)
486
495
}
487
496
ExprKind :: Path ( QPath :: LangItem ( lang_item, _) ) => {
488
497
self . check_lang_item_path ( lang_item, expr)
489
498
}
490
- ExprKind :: Path ( ref qpath) => self . check_expr_path ( qpath, expr, None , None ) ,
499
+ ExprKind :: Path ( ref qpath) => self . check_expr_path ( qpath, expr, None ) ,
491
500
ExprKind :: InlineAsm ( asm) => {
492
501
// We defer some asm checks as we may not have resolved the input and output types yet (they may still be infer vars).
493
502
self . deferred_asm_checks . borrow_mut ( ) . push ( ( asm, expr. hir_id ) ) ;
494
503
self . check_expr_asm ( asm)
495
504
}
496
- ExprKind :: OffsetOf ( container, fields) => self . check_offset_of ( container, fields, expr) ,
505
+ ExprKind :: OffsetOf ( container, fields) => {
506
+ self . check_expr_offset_of ( container, fields, expr)
507
+ }
497
508
ExprKind :: Break ( destination, ref expr_opt) => {
498
509
self . check_expr_break ( destination, expr_opt. as_deref ( ) , expr)
499
510
}
@@ -512,13 +523,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
512
523
self . check_expr_loop ( body, source, expected, expr)
513
524
}
514
525
ExprKind :: Match ( discrim, arms, match_src) => {
515
- self . check_match ( expr, discrim, arms, expected, match_src)
526
+ self . check_expr_match ( expr, discrim, arms, expected, match_src)
516
527
}
517
528
ExprKind :: Closure ( closure) => self . check_expr_closure ( closure, expr. span , expected) ,
518
- ExprKind :: Block ( body, _) => self . check_block_with_expected ( body, expected) ,
519
- ExprKind :: Call ( callee, args) => self . check_call ( expr, callee, args, expected) ,
529
+ ExprKind :: Block ( body, _) => self . check_expr_block ( body, expected) ,
530
+ ExprKind :: Call ( callee, args) => self . check_expr_call ( expr, callee, args, expected) ,
520
531
ExprKind :: MethodCall ( segment, receiver, args, _) => {
521
- self . check_method_call ( expr, segment, receiver, args, expected)
532
+ self . check_expr_method_call ( expr, segment, receiver, args, expected)
522
533
}
523
534
ExprKind :: Cast ( e, t) => self . check_expr_cast ( e, t, expr) ,
524
535
ExprKind :: Type ( e, t) => {
@@ -528,7 +539,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
528
539
ascribed_ty
529
540
}
530
541
ExprKind :: If ( cond, then_expr, opt_else_expr) => {
531
- self . check_then_else ( cond, then_expr, opt_else_expr, expr. span , expected)
542
+ self . check_expr_if ( cond, then_expr, opt_else_expr, expr. span , expected)
532
543
}
533
544
ExprKind :: DropTemps ( e) => self . check_expr_with_expectation ( e, expected) ,
534
545
ExprKind :: Array ( args) => self . check_expr_array ( args, expected, expr) ,
@@ -540,7 +551,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
540
551
ExprKind :: Struct ( qpath, fields, ref base_expr) => {
541
552
self . check_expr_struct ( expr, expected, qpath, fields, base_expr)
542
553
}
543
- ExprKind :: Field ( base, field) => self . check_field ( expr, base, field, expected) ,
554
+ ExprKind :: Field ( base, field) => self . check_expr_field ( expr, base, field, expected) ,
544
555
ExprKind :: Index ( base, idx, brackets_span) => {
545
556
self . check_expr_index ( base, idx, expr, brackets_span)
546
557
}
@@ -549,7 +560,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
549
560
}
550
561
}
551
562
552
- fn check_expr_unary (
563
+ fn check_expr_unop (
553
564
& self ,
554
565
unop : hir:: UnOp ,
555
566
oprnd : & ' tcx hir:: Expr < ' tcx > ,
@@ -699,8 +710,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
699
710
& self ,
700
711
qpath : & ' tcx hir:: QPath < ' tcx > ,
701
712
expr : & ' tcx hir:: Expr < ' tcx > ,
702
- args : Option < & ' tcx [ hir:: Expr < ' tcx > ] > ,
703
- call : Option < & ' tcx hir:: Expr < ' tcx > > ,
713
+ call_expr_and_args : Option < ( & ' tcx hir:: Expr < ' tcx > , & ' tcx [ hir:: Expr < ' tcx > ] ) > ,
704
714
) -> Ty < ' tcx > {
705
715
let tcx = self . tcx ;
706
716
let ( res, opt_ty, segs) =
@@ -730,7 +740,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
730
740
segs,
731
741
opt_ty,
732
742
res,
733
- call . map_or ( expr. span , |e | e. span ) ,
743
+ call_expr_and_args . map_or ( expr. span , |( e , _ ) | e. span ) ,
734
744
expr. span ,
735
745
expr. hir_id ,
736
746
)
@@ -769,7 +779,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
769
779
// We just want to check sizedness, so instead of introducing
770
780
// placeholder lifetimes with probing, we just replace higher lifetimes
771
781
// with fresh vars.
772
- let span = args. and_then ( |args| args. get ( i) ) . map_or ( expr. span , |arg| arg. span ) ;
782
+ let span = call_expr_and_args
783
+ . and_then ( |( _, args) | args. get ( i) )
784
+ . map_or ( expr. span , |arg| arg. span ) ;
773
785
let input = self . instantiate_binder_with_fresh_vars (
774
786
span,
775
787
infer:: BoundRegionConversionTime :: FnCall ,
@@ -795,7 +807,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
795
807
) ;
796
808
self . require_type_is_sized_deferred (
797
809
output,
798
- call . map_or ( expr. span , |e | e. span ) ,
810
+ call_expr_and_args . map_or ( expr. span , |( e , _ ) | e. span ) ,
799
811
ObligationCauseCode :: SizedCallReturnType ,
800
812
) ;
801
813
}
@@ -972,7 +984,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
972
984
if self . ret_coercion_span . get ( ) . is_none ( ) {
973
985
self . ret_coercion_span . set ( Some ( e. span ) ) ;
974
986
}
975
- self . check_return_expr ( e, true ) ;
987
+ self . check_return_or_body_tail ( e, true ) ;
976
988
} else {
977
989
let mut coercion = self . ret_coercion . as_ref ( ) . unwrap ( ) . borrow_mut ( ) ;
978
990
if self . ret_coercion_span . get ( ) . is_none ( ) {
@@ -1035,7 +1047,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1035
1047
///
1036
1048
/// `explicit_return` is `true` if we're checking an explicit `return expr`,
1037
1049
/// and `false` if we're checking a trailing expression.
1038
- pub ( super ) fn check_return_expr (
1050
+ pub ( super ) fn check_return_or_body_tail (
1039
1051
& self ,
1040
1052
return_expr : & ' tcx hir:: Expr < ' tcx > ,
1041
1053
explicit_return : bool ,
@@ -1259,7 +1271,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1259
1271
1260
1272
// A generic function for checking the 'then' and 'else' clauses in an 'if'
1261
1273
// or 'if-else' expression.
1262
- fn check_then_else (
1274
+ fn check_expr_if (
1263
1275
& self ,
1264
1276
cond_expr : & ' tcx hir:: Expr < ' tcx > ,
1265
1277
then_expr : & ' tcx hir:: Expr < ' tcx > ,
@@ -1542,7 +1554,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1542
1554
}
1543
1555
1544
1556
/// Checks a method call.
1545
- fn check_method_call (
1557
+ fn check_expr_method_call (
1546
1558
& self ,
1547
1559
expr : & ' tcx hir:: Expr < ' tcx > ,
1548
1560
segment : & ' tcx hir:: PathSegment < ' tcx > ,
@@ -2594,7 +2606,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2594
2606
}
2595
2607
2596
2608
// Check field access expressions
2597
- fn check_field (
2609
+ fn check_expr_field (
2598
2610
& self ,
2599
2611
expr : & ' tcx hir:: Expr < ' tcx > ,
2600
2612
base : & ' tcx hir:: Expr < ' tcx > ,
@@ -3535,8 +3547,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3535
3547
let previous_diverges = self . diverges . get ( ) ;
3536
3548
3537
3549
// The label blocks should have unit return value or diverge.
3538
- let ty =
3539
- self . check_block_with_expected ( block, ExpectHasType ( self . tcx . types . unit ) ) ;
3550
+ let ty = self . check_expr_block ( block, ExpectHasType ( self . tcx . types . unit ) ) ;
3540
3551
if !ty. is_never ( ) {
3541
3552
self . demand_suptype ( block. span , self . tcx . types . unit , ty) ;
3542
3553
diverge = false ;
@@ -3551,7 +3562,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3551
3562
if diverge { self . tcx . types . never } else { self . tcx . types . unit }
3552
3563
}
3553
3564
3554
- fn check_offset_of (
3565
+ fn check_expr_offset_of (
3555
3566
& self ,
3556
3567
container : & ' tcx hir:: Ty < ' tcx > ,
3557
3568
fields : & [ Ident ] ,
0 commit comments