@@ -49,7 +49,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
4949 expr : & hir:: Expr < ' _ > ,
5050 base_expr : & ' tcx hir:: Expr < ' tcx > ,
5151 base_ty : Ty < ' tcx > ,
52- idx_expr : & ' tcx hir:: Expr < ' tcx > ,
52+ index_expr : & ' tcx hir:: Expr < ' tcx > ,
5353 idx_ty : Ty < ' tcx > ,
5454 ) -> Option < ( /*index type*/ Ty < ' tcx > , /*element type*/ Ty < ' tcx > ) > {
5555 // FIXME(#18741) -- this is almost but not quite the same as the
@@ -59,12 +59,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
5959 let mut autoderef = self . autoderef ( base_expr. span , base_ty) ;
6060 let mut result = None ;
6161 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 ) ;
6363 }
6464 self . register_predicates ( autoderef. into_obligations ( ) ) ;
6565 result
6666 }
6767
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+
6898 /// To type-check `base_expr[index_expr]`, we progressively autoderef
6999 /// (and otherwise adjust) `base_expr`, looking for a type which either
70100 /// supports builtin indexing or overloaded indexing.
@@ -76,7 +106,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
76106 base_expr : & hir:: Expr < ' _ > ,
77107 autoderef : & Autoderef < ' a , ' tcx > ,
78108 index_ty : Ty < ' tcx > ,
79- idx_expr : & hir:: Expr < ' _ > ,
109+ index_expr : & hir:: Expr < ' _ > ,
80110 ) -> Option < ( /*index type*/ Ty < ' tcx > , /*element type*/ Ty < ' tcx > ) > {
81111 let adjusted_ty =
82112 self . structurally_resolved_type ( autoderef. span ( ) , autoderef. final_ty ( false ) ) ;
@@ -86,49 +116,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
86116 expr, base_expr, adjusted_ty, index_ty
87117 ) ;
88118
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- } ;
117119 if let hir:: ExprKind :: Unary (
118120 hir:: UnOp :: Neg ,
119121 hir:: Expr {
120122 kind : hir:: ExprKind :: Lit ( hir:: Lit { node : ast:: LitKind :: Int ( ..) , .. } ) ,
121123 ..
122124 } ,
123- ) = idx_expr . kind
125+ ) = index_expr . kind
124126 {
125127 match adjusted_ty. kind ( ) {
126128 ty:: Adt ( ty:: AdtDef { did, .. } , _)
127129 if self . tcx . is_diagnostic_item ( sym:: vec_type, * did) =>
128130 {
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) ;
130135 }
131- ty:: Slice ( _) | ty:: Array ( _, _) => return negative_index ( ) ,
132136 _ => { }
133137 }
134138 }
0 commit comments