@@ -2877,7 +2877,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2877
2877
// two-phase not needed because index_ty is never mutable
2878
2878
self . demand_coerce ( idx, idx_t, index_ty, None , AllowTwoPhase :: No ) ;
2879
2879
self . select_obligations_where_possible ( |errors| {
2880
- self . point_at_index ( errors, idx. span ) ;
2880
+ self . point_at_index ( errors, idx, expr , base , base_t ) ;
2881
2881
} ) ;
2882
2882
element_ty
2883
2883
}
@@ -3036,7 +3036,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3036
3036
. ok ( )
3037
3037
}
3038
3038
3039
- fn point_at_index ( & self , errors : & mut Vec < traits:: FulfillmentError < ' tcx > > , span : Span ) {
3039
+ fn point_at_index (
3040
+ & self ,
3041
+ errors : & mut Vec < traits:: FulfillmentError < ' tcx > > ,
3042
+ idx : & ' tcx hir:: Expr < ' tcx > ,
3043
+ expr : & ' tcx hir:: Expr < ' tcx > ,
3044
+ base : & ' tcx hir:: Expr < ' tcx > ,
3045
+ base_t : Ty < ' tcx > ,
3046
+ ) {
3047
+ let idx_span = idx. span ;
3040
3048
let mut seen_preds = FxHashSet :: default ( ) ;
3041
3049
// We re-sort here so that the outer most root obligations comes first, as we have the
3042
3050
// subsequent weird logic to identify *every* relevant obligation for proper deduplication
@@ -3060,7 +3068,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3060
3068
( root, pred) if seen_preds. contains ( & pred) || seen_preds. contains ( & root) => { }
3061
3069
_ => continue ,
3062
3070
}
3063
- error. obligation . cause . span = span;
3071
+ error. obligation . cause . span = idx_span;
3072
+
3073
+ // If the index value is a double borrow, that can cause typeck errors
3074
+ // that can be easily resolved by removing the borrow from the expression.
3075
+ // We check for that here and provide a suggestion in a custom obligation
3076
+ // cause code.
3077
+ if let hir:: ExprKind :: AddrOf ( _, _, idx) = idx. kind {
3078
+ let idx_t = self . typeck_results . borrow ( ) . expr_ty ( idx) ;
3079
+ if let Some ( ( index_ty, _element_ty) ) =
3080
+ self . lookup_indexing ( expr, base, base_t, idx, idx_t)
3081
+ {
3082
+ let ( _ty, err) =
3083
+ self . demand_coerce_diag ( idx, idx_t, index_ty, None , AllowTwoPhase :: No ) ;
3084
+ if let Some ( err) = err {
3085
+ err. cancel ( ) ;
3086
+ } else if self
3087
+ . fulfillment_cx
3088
+ . borrow_mut ( )
3089
+ . select_where_possible ( self )
3090
+ . is_empty ( )
3091
+ {
3092
+ if let Some ( pred) = error. obligation . predicate . to_opt_poly_trait_pred ( ) {
3093
+ error. obligation . cause =
3094
+ error. obligation . cause . clone ( ) . derived_cause ( pred, |cause| {
3095
+ ObligationCauseCode :: IndexExprDerivedObligation ( Box :: new ( (
3096
+ cause,
3097
+ idx_span. with_hi ( idx. span . lo ( ) ) ,
3098
+ ) ) )
3099
+ } ) ;
3100
+ }
3101
+ }
3102
+ }
3103
+ }
3064
3104
}
3065
3105
}
3066
3106
0 commit comments