@@ -49,7 +49,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
49
49
expr : & hir:: Expr < ' _ > ,
50
50
base_expr : & ' tcx hir:: Expr < ' tcx > ,
51
51
base_ty : Ty < ' tcx > ,
52
- idx_expr : & ' tcx hir:: Expr < ' tcx > ,
52
+ index_expr : & ' tcx hir:: Expr < ' tcx > ,
53
53
idx_ty : Ty < ' tcx > ,
54
54
) -> Option < ( /*index type*/ Ty < ' tcx > , /*element type*/ Ty < ' tcx > ) > {
55
55
// FIXME(#18741) -- this is almost but not quite the same as the
@@ -59,12 +59,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
59
59
let mut autoderef = self . autoderef ( base_expr. span , base_ty) ;
60
60
let mut result = None ;
61
61
while result. is_none ( ) && autoderef. next ( ) . is_some ( ) {
62
- result = self . try_index_step ( expr, base_expr, & autoderef, idx_ty, idx_expr ) ;
62
+ result = self . try_index_step ( expr, base_expr, & autoderef, idx_ty, index_expr ) ;
63
63
}
64
64
self . register_predicates ( autoderef. into_obligations ( ) ) ;
65
65
result
66
66
}
67
67
68
+ fn negative_index (
69
+ & self ,
70
+ ty : Ty < ' tcx > ,
71
+ span : Span ,
72
+ base_expr : & hir:: Expr < ' _ > ,
73
+ ) -> Option < ( Ty < ' tcx > , Ty < ' tcx > ) > {
74
+ let ty = self . resolve_vars_if_possible ( ty) ;
75
+ let mut err = self . tcx . sess . struct_span_err (
76
+ span,
77
+ & format ! ( "negative integers cannot be used to index on a `{}`" , ty) ,
78
+ ) ;
79
+ err. span_label ( span, & format ! ( "cannot use a negative integer for indexing on `{}`" , ty) ) ;
80
+ if let ( hir:: ExprKind :: Path ( ..) , Ok ( snippet) ) =
81
+ ( & base_expr. kind , self . tcx . sess . source_map ( ) . span_to_snippet ( base_expr. span ) )
82
+ {
83
+ // `foo[-1]` to `foo[foo.len() - 1]`
84
+ err. span_suggestion_verbose (
85
+ span. shrink_to_lo ( ) ,
86
+ & format ! (
87
+ "to access an element starting from the end of the `{}`, compute the index" ,
88
+ ty,
89
+ ) ,
90
+ format ! ( "{}.len() " , snippet) ,
91
+ Applicability :: MachineApplicable ,
92
+ ) ;
93
+ }
94
+ err. emit ( ) ;
95
+ Some ( ( self . tcx . ty_error ( ) , self . tcx . ty_error ( ) ) )
96
+ }
97
+
68
98
/// To type-check `base_expr[index_expr]`, we progressively autoderef
69
99
/// (and otherwise adjust) `base_expr`, looking for a type which either
70
100
/// supports builtin indexing or overloaded indexing.
@@ -76,7 +106,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
76
106
base_expr : & hir:: Expr < ' _ > ,
77
107
autoderef : & Autoderef < ' a , ' tcx > ,
78
108
index_ty : Ty < ' tcx > ,
79
- idx_expr : & hir:: Expr < ' _ > ,
109
+ index_expr : & hir:: Expr < ' _ > ,
80
110
) -> Option < ( /*index type*/ Ty < ' tcx > , /*element type*/ Ty < ' tcx > ) > {
81
111
let adjusted_ty =
82
112
self . structurally_resolved_type ( autoderef. span ( ) , autoderef. final_ty ( false ) ) ;
@@ -86,49 +116,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
86
116
expr, base_expr, adjusted_ty, index_ty
87
117
) ;
88
118
89
- let negative_index = || {
90
- let ty = self . resolve_vars_if_possible ( adjusted_ty) ;
91
- let mut err = self . tcx . sess . struct_span_err (
92
- idx_expr. span ,
93
- & format ! ( "negative integers cannot be used to index on a `{}`" , ty) ,
94
- ) ;
95
- err. span_label (
96
- idx_expr. span ,
97
- & format ! ( "cannot use a negative integer for indexing on `{}`" , ty) ,
98
- ) ;
99
- if let ( hir:: ExprKind :: Path ( ..) , Ok ( snippet) ) =
100
- ( & base_expr. kind , self . tcx . sess . source_map ( ) . span_to_snippet ( base_expr. span ) )
101
- {
102
- // `foo[-1]` to `foo[foo.len() - 1]`
103
- err. span_suggestion_verbose (
104
- idx_expr. span . shrink_to_lo ( ) ,
105
- & format ! (
106
- "if you wanted to access an element starting from the end of the `{}`, you \
107
- must compute it",
108
- ty,
109
- ) ,
110
- format ! ( "{}.len() " , snippet) ,
111
- Applicability :: MachineApplicable ,
112
- ) ;
113
- }
114
- err. emit ( ) ;
115
- Some ( ( self . tcx . ty_error ( ) , self . tcx . ty_error ( ) ) )
116
- } ;
117
119
if let hir:: ExprKind :: Unary (
118
120
hir:: UnOp :: Neg ,
119
121
hir:: Expr {
120
122
kind : hir:: ExprKind :: Lit ( hir:: Lit { node : ast:: LitKind :: Int ( ..) , .. } ) ,
121
123
..
122
124
} ,
123
- ) = idx_expr . kind
125
+ ) = index_expr . kind
124
126
{
125
127
match adjusted_ty. kind ( ) {
126
128
ty:: Adt ( ty:: AdtDef { did, .. } , _)
127
129
if self . tcx . is_diagnostic_item ( sym:: vec_type, * did) =>
128
130
{
129
- return negative_index ( ) ;
131
+ return self . negative_index ( adjusted_ty, index_expr. span , base_expr) ;
132
+ }
133
+ ty:: Slice ( _) | ty:: Array ( _, _) => {
134
+ return self . negative_index ( adjusted_ty, index_expr. span , base_expr) ;
130
135
}
131
- ty:: Slice ( _) | ty:: Array ( _, _) => return negative_index ( ) ,
132
136
_ => { }
133
137
}
134
138
}
0 commit comments