@@ -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