@@ -95,7 +95,7 @@ use rustc::ty::{ParamTy, ParameterEnvironment};
95
95
use rustc:: ty:: { LvaluePreference , NoPreference , PreferMutLvalue } ;
96
96
use rustc:: ty:: { self , Ty , TyCtxt , Visibility } ;
97
97
use rustc:: ty:: { MethodCall , MethodCallee } ;
98
- use rustc:: ty:: adjustment;
98
+ use rustc:: ty:: adjustment:: { Adjust , Adjustment , AutoBorrow } ;
99
99
use rustc:: ty:: fold:: { BottomUpFolder , TypeFoldable } ;
100
100
use rustc:: ty:: maps:: Providers ;
101
101
use rustc:: ty:: util:: { Representability , IntTypeExt } ;
@@ -108,6 +108,7 @@ use util::common::{ErrorReported, indenter};
108
108
use util:: nodemap:: { DefIdMap , FxHashMap , FxHashSet , NodeMap } ;
109
109
110
110
use std:: cell:: { Cell , RefCell } ;
111
+ use std:: collections:: hash_map:: Entry ;
111
112
use std:: cmp;
112
113
use std:: mem:: replace;
113
114
use std:: ops:: { self , Deref } ;
@@ -1637,12 +1638,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
1637
1638
}
1638
1639
}
1639
1640
1640
- pub fn write_autoderef_adjustment ( & self ,
1641
+ pub fn apply_autoderef_adjustment ( & self ,
1641
1642
node_id : ast:: NodeId ,
1642
1643
derefs : usize ,
1643
1644
adjusted_ty : Ty < ' tcx > ) {
1644
- self . write_adjustment ( node_id, adjustment :: Adjustment {
1645
- kind : adjustment :: Adjust :: DerefRef {
1645
+ self . apply_adjustment ( node_id, Adjustment {
1646
+ kind : Adjust :: DerefRef {
1646
1647
autoderefs : derefs,
1647
1648
autoref : None ,
1648
1649
unsize : false
@@ -1651,16 +1652,42 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
1651
1652
} ) ;
1652
1653
}
1653
1654
1654
- pub fn write_adjustment ( & self ,
1655
- node_id : ast:: NodeId ,
1656
- adj : adjustment:: Adjustment < ' tcx > ) {
1657
- debug ! ( "write_adjustment(node_id={}, adj={:?})" , node_id, adj) ;
1655
+ pub fn apply_adjustment ( & self , node_id : ast:: NodeId , adj : Adjustment < ' tcx > ) {
1656
+ debug ! ( "apply_adjustment(node_id={}, adj={:?})" , node_id, adj) ;
1658
1657
1659
1658
if adj. is_identity ( ) {
1660
1659
return ;
1661
1660
}
1662
1661
1663
- self . tables . borrow_mut ( ) . adjustments . insert ( node_id, adj) ;
1662
+ match self . tables . borrow_mut ( ) . adjustments . entry ( node_id) {
1663
+ Entry :: Vacant ( entry) => { entry. insert ( adj) ; } ,
1664
+ Entry :: Occupied ( mut entry) => {
1665
+ debug ! ( " - composing on top of {:?}" , entry. get( ) ) ;
1666
+ let composed_kind = match ( entry. get ( ) . kind , adj. kind ) {
1667
+ // Applying any adjustment on top of a NeverToAny
1668
+ // is a valid NeverToAny adjustment, because it can't
1669
+ // be reached.
1670
+ ( Adjust :: NeverToAny , _) => Adjust :: NeverToAny ,
1671
+ ( Adjust :: DerefRef {
1672
+ autoderefs : 1 ,
1673
+ autoref : Some ( AutoBorrow :: Ref ( ..) ) ,
1674
+ unsize : false
1675
+ } , Adjust :: DerefRef { autoderefs, .. } ) if autoderefs > 0 => {
1676
+ // A reborrow has no effect before a dereference.
1677
+ adj. kind
1678
+ }
1679
+ // FIXME: currently we never try to compose autoderefs
1680
+ // and ReifyFnPointer/UnsafeFnPointer, but we could.
1681
+ _ =>
1682
+ bug ! ( "while adjusting {}, can't compose {:?} and {:?}" ,
1683
+ node_id, entry. get( ) , adj)
1684
+ } ;
1685
+ * entry. get_mut ( ) = Adjustment {
1686
+ kind : composed_kind,
1687
+ target : adj. target
1688
+ } ;
1689
+ }
1690
+ }
1664
1691
}
1665
1692
1666
1693
/// Basically whenever we are converting from a type scheme into
@@ -2302,7 +2329,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
2302
2329
debug ! ( "try_index_step: success, using built-in indexing" ) ;
2303
2330
// If we had `[T; N]`, we should've caught it before unsizing to `[T]`.
2304
2331
assert ! ( !unsize) ;
2305
- self . write_autoderef_adjustment ( base_expr. id , autoderefs, adjusted_ty) ;
2332
+ self . apply_autoderef_adjustment ( base_expr. id , autoderefs, adjusted_ty) ;
2306
2333
return Some ( ( tcx. types . usize , ty) ) ;
2307
2334
}
2308
2335
_ => { }
@@ -2685,8 +2712,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
2685
2712
"expression with never type wound up being adjusted" ) ;
2686
2713
let adj_ty = self . next_diverging_ty_var (
2687
2714
TypeVariableOrigin :: AdjustmentType ( expr. span ) ) ;
2688
- self . write_adjustment ( expr. id , adjustment :: Adjustment {
2689
- kind : adjustment :: Adjust :: NeverToAny ,
2715
+ self . apply_adjustment ( expr. id , Adjustment {
2716
+ kind : Adjust :: NeverToAny ,
2690
2717
target : adj_ty
2691
2718
} ) ;
2692
2719
ty = adj_ty;
@@ -2917,7 +2944,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
2917
2944
let field_ty = self . field_ty ( expr. span , field, substs) ;
2918
2945
if self . tcx . vis_is_accessible_from ( field. vis , self . body_id ) {
2919
2946
autoderef. finalize ( lvalue_pref, & [ base] ) ;
2920
- self . write_autoderef_adjustment ( base. id , autoderefs, base_t) ;
2947
+ self . apply_autoderef_adjustment ( base. id , autoderefs, base_t) ;
2921
2948
2922
2949
self . tcx . check_stability ( field. did , expr. id , expr. span ) ;
2923
2950
@@ -3041,7 +3068,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
3041
3068
3042
3069
if let Some ( field_ty) = field {
3043
3070
autoderef. finalize ( lvalue_pref, & [ base] ) ;
3044
- self . write_autoderef_adjustment ( base. id , autoderefs, base_t) ;
3071
+ self . apply_autoderef_adjustment ( base. id , autoderefs, base_t) ;
3045
3072
return field_ty;
3046
3073
}
3047
3074
}
0 commit comments