@@ -86,10 +86,11 @@ use middle::traits;
86
86
use middle:: ty:: * ;
87
87
use middle:: ty;
88
88
use middle:: typeck:: astconv:: AstConv ;
89
- use middle:: typeck:: check:: { FnCtxt , PreferMutLvalue , impl_self_ty} ;
89
+ use middle:: typeck:: check:: { FnCtxt , NoPreference , PreferMutLvalue } ;
90
+ use middle:: typeck:: check:: { impl_self_ty} ;
90
91
use middle:: typeck:: check;
91
92
use middle:: typeck:: infer;
92
- use middle:: typeck:: MethodCallee ;
93
+ use middle:: typeck:: { MethodCall , MethodCallee } ;
93
94
use middle:: typeck:: { MethodOrigin , MethodParam , MethodTypeParam } ;
94
95
use middle:: typeck:: { MethodStatic , MethodStaticUnboxedClosure , MethodObject , MethodTraitObject } ;
95
96
use middle:: typeck:: check:: regionmanip:: replace_late_bound_regions_in_fn_sig;
@@ -353,11 +354,15 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> {
353
354
354
355
let ( _, _, result) =
355
356
check:: autoderef (
356
- self . fcx , span, self_ty, self_expr_id, PreferMutLvalue ,
357
+ self . fcx , span, self_ty, self_expr_id, NoPreference ,
357
358
|self_ty, autoderefs| self . search_step ( self_ty, autoderefs) ) ;
358
359
359
360
match result {
360
- Some ( Some ( result) ) => Some ( result) ,
361
+ Some ( Some ( result) ) => {
362
+ self . fixup_derefs_on_method_receiver_if_necessary ( & result,
363
+ self_ty) ;
364
+ Some ( result)
365
+ }
361
366
_ => None
362
367
}
363
368
}
@@ -430,7 +435,7 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> {
430
435
*/
431
436
432
437
let span = self . self_expr . map_or ( self . span , |e| e. span ) ;
433
- check:: autoderef ( self . fcx , span, self_ty, None , PreferMutLvalue , |self_ty, _| {
438
+ check:: autoderef ( self . fcx , span, self_ty, None , NoPreference , |self_ty, _| {
434
439
match get ( self_ty) . sty {
435
440
ty_trait( box TyTrait { def_id, ref substs, bounds, .. } ) => {
436
441
self . push_inherent_candidates_from_object (
@@ -458,7 +463,7 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> {
458
463
459
464
fn push_bound_candidates ( & mut self , self_ty : ty:: t , restrict_to : Option < DefId > ) {
460
465
let span = self . self_expr . map_or ( self . span , |e| e. span ) ;
461
- check:: autoderef ( self . fcx , span, self_ty, None , PreferMutLvalue , |self_ty, _| {
466
+ check:: autoderef ( self . fcx , span, self_ty, None , NoPreference , |self_ty, _| {
462
467
match get ( self_ty) . sty {
463
468
ty_param( p) => {
464
469
self . push_inherent_candidates_from_param ( self_ty, restrict_to, p) ;
@@ -1135,7 +1140,7 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> {
1135
1140
} ;
1136
1141
1137
1142
// This is hokey. We should have mutability inference as a
1138
- // variable. But for now, try &const, then & , then &mut:
1143
+ // variable. But for now, try &, then &mut:
1139
1144
let region =
1140
1145
self . infcx ( ) . next_region_var ( infer:: Autoref ( self . span ) ) ;
1141
1146
for mutbl in mutbls. iter ( ) {
@@ -1381,6 +1386,77 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> {
1381
1386
}
1382
1387
}
1383
1388
1389
+ fn fixup_derefs_on_method_receiver_if_necessary (
1390
+ & self ,
1391
+ method_callee : & MethodCallee ,
1392
+ self_ty : ty:: t ) {
1393
+ let sig = match ty:: get ( method_callee. ty ) . sty {
1394
+ ty:: ty_bare_fn( ref f) => f. sig . clone ( ) ,
1395
+ ty:: ty_closure( ref f) => f. sig . clone ( ) ,
1396
+ _ => return ,
1397
+ } ;
1398
+
1399
+ match ty:: get ( * sig. inputs . get ( 0 ) ) . sty {
1400
+ ty:: ty_rptr( _, ty:: mt {
1401
+ ty : _,
1402
+ mutbl : ast:: MutMutable ,
1403
+ } ) => { }
1404
+ _ => return ,
1405
+ }
1406
+
1407
+ // Fix up autoderefs and derefs.
1408
+ let mut self_expr = match self . self_expr {
1409
+ Some ( expr) => expr,
1410
+ None => return ,
1411
+ } ;
1412
+ loop {
1413
+ // Count autoderefs.
1414
+ let autoderef_count = match self . fcx
1415
+ . inh
1416
+ . adjustments
1417
+ . borrow ( )
1418
+ . find ( & self_expr. id ) {
1419
+ Some ( & ty:: AdjustDerefRef ( ty:: AutoDerefRef {
1420
+ autoderefs : autoderef_count,
1421
+ autoref : _
1422
+ } ) ) if autoderef_count > 0 => autoderef_count,
1423
+ Some ( _) | None => return ,
1424
+ } ;
1425
+
1426
+ check:: autoderef ( self . fcx ,
1427
+ self_expr. span ,
1428
+ self . fcx . expr_ty ( self_expr) ,
1429
+ Some ( self_expr. id ) ,
1430
+ PreferMutLvalue ,
1431
+ |_, autoderefs| {
1432
+ if autoderefs == autoderef_count + 1 {
1433
+ Some ( ( ) )
1434
+ } else {
1435
+ None
1436
+ }
1437
+ } ) ;
1438
+
1439
+ match self_expr. node {
1440
+ ast:: ExprParen ( ref expr) |
1441
+ ast:: ExprIndex ( ref expr, _) |
1442
+ ast:: ExprField ( ref expr, _, _) |
1443
+ ast:: ExprTupField ( ref expr, _, _) |
1444
+ ast:: ExprSlice ( ref expr, _, _, _) => self_expr = & * * expr,
1445
+ ast:: ExprUnary ( ast:: UnDeref , ref expr) => {
1446
+ drop ( check:: try_overloaded_deref (
1447
+ self . fcx ,
1448
+ self_expr. span ,
1449
+ Some ( MethodCall :: expr ( self_expr. id ) ) ,
1450
+ Some ( self_expr) ,
1451
+ self_ty,
1452
+ PreferMutLvalue ) ) ;
1453
+ self_expr = & * * expr
1454
+ }
1455
+ _ => break ,
1456
+ }
1457
+ }
1458
+ }
1459
+
1384
1460
fn enforce_object_limitations ( & self , candidate : & Candidate ) {
1385
1461
/*!
1386
1462
* There are some limitations to calling functions through an
0 commit comments