Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit c141b82

Browse files
committedOct 4, 2022
find the correct lang item for ranges
1 parent 5dd44d4 commit c141b82

File tree

3 files changed

+72
-33
lines changed

3 files changed

+72
-33
lines changed
 

‎compiler/rustc_hir_analysis/src/check/method/suggest.rs

+42-31
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc_hir as hir;
1313
use rustc_hir::def::DefKind;
1414
use rustc_hir::def_id::DefId;
1515
use rustc_hir::lang_items::LangItem;
16-
use rustc_hir::{is_range_literal, ExprKind, Node, QPath};
16+
use rustc_hir::{ExprKind, Node, QPath};
1717
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
1818
use rustc_middle::traits::util::supertraits;
1919
use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
@@ -1214,50 +1214,61 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12141214
ty_str: &str,
12151215
) -> bool {
12161216
if let SelfSource::MethodCall(expr) = source {
1217-
let mut search_limit = 5;
1218-
for (_, parent) in tcx.hir().parent_iter(expr.hir_id) {
1219-
search_limit -= 1;
1220-
if search_limit == 0 {
1221-
break;
1222-
}
1217+
for (_, parent) in tcx.hir().parent_iter(expr.hir_id).take(5) {
1218+
if let Node::Expr(parent_expr) = parent {
1219+
let lang_item = match parent_expr.kind {
1220+
ExprKind::Struct(ref qpath, _, _) => match **qpath {
1221+
QPath::LangItem(LangItem::Range, ..) => Some(LangItem::Range),
1222+
QPath::LangItem(LangItem::RangeTo, ..) => Some(LangItem::RangeTo),
1223+
QPath::LangItem(LangItem::RangeToInclusive, ..) => {
1224+
Some(LangItem::RangeToInclusive)
1225+
}
1226+
_ => None,
1227+
},
1228+
ExprKind::Call(ref func, _) => match func.kind {
1229+
// `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1230+
ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)) => {
1231+
Some(LangItem::RangeInclusiveStruct)
1232+
}
1233+
_ => None,
1234+
},
1235+
_ => None,
1236+
};
1237+
1238+
if lang_item.is_none() {
1239+
continue;
1240+
}
12231241

1224-
if let Node::Expr(parent_expr) = parent && is_range_literal(parent_expr) {
12251242
let span_included = match parent_expr.kind {
1226-
hir::ExprKind::Struct(_, eps, _) =>
1227-
eps.len() > 0 && eps.last().map_or(false, |ep| ep.span.contains(span)),
1228-
// `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1229-
hir::ExprKind::Call(ref func, ..) => func.span.contains(span),
1230-
_ => false,
1243+
hir::ExprKind::Struct(_, eps, _) => {
1244+
eps.len() > 0 && eps.last().map_or(false, |ep| ep.span.contains(span))
1245+
}
1246+
// `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1247+
hir::ExprKind::Call(ref func, ..) => func.span.contains(span),
1248+
_ => false,
12311249
};
12321250

12331251
if !span_included {
12341252
continue;
12351253
}
12361254

1237-
let range_def_id = self.tcx.lang_items().range_struct().unwrap();
1238-
let range_ty = self.tcx.bound_type_of(range_def_id).subst(self.tcx, &[actual.into()]);
1239-
1240-
// avoid suggesting when the method name is not implemented for a `range`
1241-
let pick = self.lookup_probe(
1242-
span,
1243-
item_name,
1244-
range_ty,
1245-
expr,
1246-
ProbeScope::AllTraits
1247-
);
1255+
debug!("lang_item: {:?}", lang_item);
1256+
let range_def_id = self.tcx.require_lang_item(lang_item.unwrap(), None);
1257+
let range_ty =
1258+
self.tcx.bound_type_of(range_def_id).subst(self.tcx, &[actual.into()]);
12481259

1260+
let pick =
1261+
self.lookup_probe(span, item_name, range_ty, expr, ProbeScope::AllTraits);
12491262
if pick.is_ok() {
12501263
let range_span = parent_expr.span.with_hi(expr.span.hi());
12511264
tcx.sess.emit_err(errors::MissingParentheseInRange {
12521265
span: span,
12531266
ty_str: ty_str.to_string(),
1254-
add_missing_parentheses: Some(
1255-
errors::AddMissingParenthesesInRange {
1256-
func_name: item_name.name.as_str().to_string(),
1257-
left: range_span.shrink_to_lo(),
1258-
right: range_span.shrink_to_hi(),
1259-
}
1260-
)
1267+
add_missing_parentheses: Some(errors::AddMissingParenthesesInRange {
1268+
func_name: item_name.name.as_str().to_string(),
1269+
left: range_span.shrink_to_lo(),
1270+
right: range_span.shrink_to_hi(),
1271+
}),
12611272
});
12621273
return true;
12631274
}

‎src/test/ui/methods/issues/issue-90315.rs

+6
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,10 @@ fn main() {
6767

6868
let _res = b.take(1)..a;
6969
//~^ ERROR not an iterator
70+
71+
let _res: i32 = ..6.take(2).sum();
72+
//~^ can't call method `take` on ambiguous numeric type
73+
//~| ERROR mismatched types [E0308]
74+
//~| HELP you must specify a concrete type for this numeric value
75+
// Won't suggest because `RangeTo` dest not implemented `take`
7076
}

‎src/test/ui/methods/issues/issue-90315.stderr

+24-2
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,29 @@ LL | let _res = b.take(1)..a;
173173
`usize: Iterator`
174174
which is required by `&mut usize: Iterator`
175175

176-
error: aborting due to 17 previous errors
176+
error[E0689]: can't call method `take` on ambiguous numeric type `{integer}`
177+
--> $DIR/issue-90315.rs:71:25
178+
|
179+
LL | let _res: i32 = ..6.take(2).sum();
180+
| ^^^^
181+
|
182+
help: you must specify a concrete type for this numeric value, like `i32`
183+
|
184+
LL | let _res: i32 = ..6_i32.take(2).sum();
185+
| ~~~~~
186+
187+
error[E0308]: mismatched types
188+
--> $DIR/issue-90315.rs:71:21
189+
|
190+
LL | let _res: i32 = ..6.take(2).sum();
191+
| --- ^^^^^^^^^^^^^^^^^ expected `i32`, found struct `RangeTo`
192+
| |
193+
| expected due to this
194+
|
195+
= note: expected type `i32`
196+
found struct `RangeTo<_>`
197+
198+
error: aborting due to 19 previous errors
177199

178-
Some errors have detailed explanations: E0308, E0599.
200+
Some errors have detailed explanations: E0308, E0599, E0689.
179201
For more information about an error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)