@@ -29,9 +29,7 @@ use rustc_hir::{ExprKind, QPath};
29
29
use rustc_infer:: infer;
30
30
use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
31
31
use rustc_middle:: ty;
32
- use rustc_middle:: ty:: adjustment:: {
33
- Adjust , Adjustment , AllowTwoPhase , AutoBorrow , AutoBorrowMutability ,
34
- } ;
32
+ use rustc_middle:: ty:: adjustment:: { Adjust , Adjustment , AllowTwoPhase } ;
35
33
use rustc_middle:: ty:: Ty ;
36
34
use rustc_middle:: ty:: TypeFoldable ;
37
35
use rustc_middle:: ty:: { AdtKind , Visibility } ;
@@ -113,12 +111,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
113
111
self . check_expr_with_expectation ( expr, ExpectHasType ( expected) )
114
112
}
115
113
116
- pub ( super ) fn check_expr_with_expectation (
114
+ fn check_expr_with_expectation_and_needs (
117
115
& self ,
118
116
expr : & ' tcx hir:: Expr < ' tcx > ,
119
117
expected : Expectation < ' tcx > ,
118
+ needs : Needs ,
120
119
) -> Ty < ' tcx > {
121
- self . check_expr_with_expectation_and_needs ( expr, expected, Needs :: None )
120
+ let ty = self . check_expr_with_expectation ( expr, expected) ;
121
+
122
+ // If the expression is used in a place whether mutable place is required
123
+ // e.g. LHS of assignment, perform the conversion.
124
+ if let Needs :: MutPlace = needs {
125
+ self . convert_place_derefs_to_mutable ( expr) ;
126
+ }
127
+
128
+ ty
122
129
}
123
130
124
131
pub ( super ) fn check_expr ( & self , expr : & ' tcx hir:: Expr < ' tcx > ) -> Ty < ' tcx > {
@@ -143,11 +150,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
143
150
/// Note that inspecting a type's structure *directly* may expose the fact
144
151
/// that there are actually multiple representations for `Error`, so avoid
145
152
/// that when err needs to be handled differently.
146
- fn check_expr_with_expectation_and_needs (
153
+ pub ( super ) fn check_expr_with_expectation (
147
154
& self ,
148
155
expr : & ' tcx hir:: Expr < ' tcx > ,
149
156
expected : Expectation < ' tcx > ,
150
- needs : Needs ,
151
157
) -> Ty < ' tcx > {
152
158
debug ! ( ">> type-checking: expr={:?} expected={:?}" , expr, expected) ;
153
159
@@ -171,7 +177,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
171
177
let old_diverges = self . diverges . replace ( Diverges :: Maybe ) ;
172
178
let old_has_errors = self . has_errors . replace ( false ) ;
173
179
174
- let ty = self . check_expr_kind ( expr, expected, needs ) ;
180
+ let ty = self . check_expr_kind ( expr, expected) ;
175
181
176
182
// Warn for non-block expressions with diverging children.
177
183
match expr. kind {
@@ -213,9 +219,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
213
219
& self ,
214
220
expr : & ' tcx hir:: Expr < ' tcx > ,
215
221
expected : Expectation < ' tcx > ,
216
- needs : Needs ,
217
222
) -> Ty < ' tcx > {
218
- debug ! ( "check_expr_kind(expr={:?}, expected={:?}, needs={:?} )" , expr, expected, needs , ) ;
223
+ debug ! ( "check_expr_kind(expr={:?}, expected={:?})" , expr, expected) ;
219
224
220
225
let tcx = self . tcx ;
221
226
match expr. kind {
@@ -226,9 +231,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
226
231
self . check_expr_assign ( expr, expected, lhs, rhs, span)
227
232
}
228
233
ExprKind :: AssignOp ( op, ref lhs, ref rhs) => self . check_binop_assign ( expr, op, lhs, rhs) ,
229
- ExprKind :: Unary ( unop, ref oprnd) => {
230
- self . check_expr_unary ( unop, oprnd, expected, needs, expr)
231
- }
234
+ ExprKind :: Unary ( unop, ref oprnd) => self . check_expr_unary ( unop, oprnd, expected, expr) ,
232
235
ExprKind :: AddrOf ( kind, mutbl, ref oprnd) => {
233
236
self . check_expr_addr_of ( kind, mutbl, oprnd, expected, expr)
234
237
}
@@ -264,7 +267,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
264
267
ExprKind :: Block ( ref body, _) => self . check_block_with_expected ( & body, expected) ,
265
268
ExprKind :: Call ( ref callee, ref args) => self . check_call ( expr, & callee, args, expected) ,
266
269
ExprKind :: MethodCall ( ref segment, span, ref args, _) => {
267
- self . check_method_call ( expr, segment, span, args, expected, needs )
270
+ self . check_method_call ( expr, segment, span, args, expected)
268
271
}
269
272
ExprKind :: Cast ( ref e, ref t) => self . check_expr_cast ( e, t, expr) ,
270
273
ExprKind :: Type ( ref e, ref t) => {
@@ -281,8 +284,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
281
284
ExprKind :: Struct ( ref qpath, fields, ref base_expr) => {
282
285
self . check_expr_struct ( expr, expected, qpath, fields, base_expr)
283
286
}
284
- ExprKind :: Field ( ref base, field) => self . check_field ( expr, needs , & base, field) ,
285
- ExprKind :: Index ( ref base, ref idx) => self . check_expr_index ( base, idx, needs , expr) ,
287
+ ExprKind :: Field ( ref base, field) => self . check_field ( expr, & base, field) ,
288
+ ExprKind :: Index ( ref base, ref idx) => self . check_expr_index ( base, idx, expr) ,
286
289
ExprKind :: Yield ( ref value, ref src) => self . check_expr_yield ( value, expr, src) ,
287
290
hir:: ExprKind :: Err => tcx. ty_error ( ) ,
288
291
}
@@ -302,48 +305,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
302
305
unop : hir:: UnOp ,
303
306
oprnd : & ' tcx hir:: Expr < ' tcx > ,
304
307
expected : Expectation < ' tcx > ,
305
- needs : Needs ,
306
308
expr : & ' tcx hir:: Expr < ' tcx > ,
307
309
) -> Ty < ' tcx > {
308
310
let tcx = self . tcx ;
309
311
let expected_inner = match unop {
310
312
hir:: UnOp :: UnNot | hir:: UnOp :: UnNeg => expected,
311
313
hir:: UnOp :: UnDeref => NoExpectation ,
312
314
} ;
313
- let needs = match unop {
314
- hir:: UnOp :: UnDeref => needs,
315
- _ => Needs :: None ,
316
- } ;
317
- let mut oprnd_t = self . check_expr_with_expectation_and_needs ( & oprnd, expected_inner, needs) ;
315
+ let mut oprnd_t = self . check_expr_with_expectation ( & oprnd, expected_inner) ;
318
316
319
317
if !oprnd_t. references_error ( ) {
320
318
oprnd_t = self . structurally_resolved_type ( expr. span , oprnd_t) ;
321
319
match unop {
322
320
hir:: UnOp :: UnDeref => {
323
- if let Some ( mt) = oprnd_t. builtin_deref ( true ) {
324
- oprnd_t = mt. ty ;
325
- } else if let Some ( ok) = self . try_overloaded_deref ( expr. span , oprnd_t, needs) {
326
- let method = self . register_infer_ok_obligations ( ok) ;
327
- if let ty:: Ref ( region, _, mutbl) = method. sig . inputs ( ) [ 0 ] . kind {
328
- let mutbl = match mutbl {
329
- hir:: Mutability :: Not => AutoBorrowMutability :: Not ,
330
- hir:: Mutability :: Mut => AutoBorrowMutability :: Mut {
331
- // (It shouldn't actually matter for unary ops whether
332
- // we enable two-phase borrows or not, since a unary
333
- // op has no additional operands.)
334
- allow_two_phase_borrow : AllowTwoPhase :: No ,
335
- } ,
336
- } ;
337
- self . apply_adjustments (
338
- oprnd,
339
- vec ! [ Adjustment {
340
- kind: Adjust :: Borrow ( AutoBorrow :: Ref ( region, mutbl) ) ,
341
- target: method. sig. inputs( ) [ 0 ] ,
342
- } ] ,
343
- ) ;
344
- }
345
- oprnd_t = self . make_overloaded_place_return_type ( method) . ty ;
346
- self . write_method_call ( expr. hir_id , method) ;
321
+ if let Some ( ty) = self . lookup_derefing ( expr, oprnd, oprnd_t) {
322
+ oprnd_t = ty;
347
323
} else {
348
324
let mut err = type_error_struct ! (
349
325
tcx. sess,
@@ -405,8 +381,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
405
381
_ => NoExpectation ,
406
382
}
407
383
} ) ;
408
- let needs = Needs :: maybe_mut_place ( mutbl ) ;
409
- let ty = self . check_expr_with_expectation_and_needs ( & oprnd, hint, needs ) ;
384
+ let ty =
385
+ self . check_expr_with_expectation_and_needs ( & oprnd, hint, Needs :: maybe_mut_place ( mutbl ) ) ;
410
386
411
387
let tm = ty:: TypeAndMut { ty, mutbl } ;
412
388
match kind {
@@ -861,10 +837,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
861
837
span : Span ,
862
838
args : & ' tcx [ hir:: Expr < ' tcx > ] ,
863
839
expected : Expectation < ' tcx > ,
864
- needs : Needs ,
865
840
) -> Ty < ' tcx > {
866
841
let rcvr = & args[ 0 ] ;
867
- let rcvr_t = self . check_expr_with_needs ( & rcvr, needs ) ;
842
+ let rcvr_t = self . check_expr ( & rcvr) ;
868
843
// no need to check for bot/err -- callee does that
869
844
let rcvr_t = self . structurally_resolved_type ( args[ 0 ] . span , rcvr_t) ;
870
845
@@ -1443,11 +1418,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1443
1418
fn check_field (
1444
1419
& self ,
1445
1420
expr : & ' tcx hir:: Expr < ' tcx > ,
1446
- needs : Needs ,
1447
1421
base : & ' tcx hir:: Expr < ' tcx > ,
1448
1422
field : Ident ,
1449
1423
) -> Ty < ' tcx > {
1450
- let expr_t = self . check_expr_with_needs ( base, needs ) ;
1424
+ let expr_t = self . check_expr ( base) ;
1451
1425
let expr_t = self . structurally_resolved_type ( base. span , expr_t) ;
1452
1426
let mut private_candidate = None ;
1453
1427
let mut autoderef = self . autoderef ( expr. span , expr_t) ;
@@ -1467,7 +1441,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1467
1441
// of error recovery.
1468
1442
self . write_field_index ( expr. hir_id , index) ;
1469
1443
if field. vis . is_accessible_from ( def_scope, self . tcx ) {
1470
- let adjustments = autoderef. adjust_steps ( self , needs ) ;
1444
+ let adjustments = autoderef. adjust_steps ( self ) ;
1471
1445
self . apply_adjustments ( base, adjustments) ;
1472
1446
autoderef. finalize ( self ) ;
1473
1447
@@ -1482,7 +1456,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1482
1456
if let Ok ( index) = fstr. parse :: < usize > ( ) {
1483
1457
if fstr == index. to_string ( ) {
1484
1458
if let Some ( field_ty) = tys. get ( index) {
1485
- let adjustments = autoderef. adjust_steps ( self , needs ) ;
1459
+ let adjustments = autoderef. adjust_steps ( self ) ;
1486
1460
self . apply_adjustments ( base, adjustments) ;
1487
1461
autoderef. finalize ( self ) ;
1488
1462
@@ -1721,10 +1695,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1721
1695
& self ,
1722
1696
base : & ' tcx hir:: Expr < ' tcx > ,
1723
1697
idx : & ' tcx hir:: Expr < ' tcx > ,
1724
- needs : Needs ,
1725
1698
expr : & ' tcx hir:: Expr < ' tcx > ,
1726
1699
) -> Ty < ' tcx > {
1727
- let base_t = self . check_expr_with_needs ( & base, needs ) ;
1700
+ let base_t = self . check_expr ( & base) ;
1728
1701
let idx_t = self . check_expr ( & idx) ;
1729
1702
1730
1703
if base_t. references_error ( ) {
@@ -1733,7 +1706,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1733
1706
idx_t
1734
1707
} else {
1735
1708
let base_t = self . structurally_resolved_type ( base. span , base_t) ;
1736
- match self . lookup_indexing ( expr, base, base_t, idx_t, needs ) {
1709
+ match self . lookup_indexing ( expr, base, base_t, idx_t) {
1737
1710
Some ( ( index_ty, element_ty) ) => {
1738
1711
// two-phase not needed because index_ty is never mutable
1739
1712
self . demand_coerce ( idx, idx_t, index_ty, None , AllowTwoPhase :: No ) ;
0 commit comments