Skip to content

Commit a2a65a8

Browse files
committed
Consider methods on fundamental impl when method is not found on numeric type
Fix #47759.
1 parent 6387b09 commit a2a65a8

File tree

3 files changed

+42
-4
lines changed

3 files changed

+42
-4
lines changed

src/librustc_typeck/check/method/suggest.rs

+26-2
Original file line numberDiff line numberDiff line change
@@ -271,11 +271,35 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
271271
let mut candidates = all_traits(self.tcx).into_iter().filter_map(|info| {
272272
self.associated_item(info.def_id, item_name, Namespace::ValueNS)
273273
});
274-
if let (true, false, SelfSource::MethodCall(expr), Some(_)) = (
274+
// There are methods that are defined on the primitive types and won't be
275+
// found when exploring `all_traits`, but we also need them to be acurate on
276+
// our suggestions (#47759).
277+
let fund_assoc = |opt_def_id: Option<DefId>| {
278+
opt_def_id
279+
.and_then(|id| self.associated_item(id, item_name, Namespace::ValueNS))
280+
.is_some()
281+
};
282+
let lang_items = tcx.lang_items();
283+
let found_candidate = candidates.next().is_some()
284+
|| fund_assoc(lang_items.i8_impl())
285+
|| fund_assoc(lang_items.i16_impl())
286+
|| fund_assoc(lang_items.i32_impl())
287+
|| fund_assoc(lang_items.i64_impl())
288+
|| fund_assoc(lang_items.i128_impl())
289+
|| fund_assoc(lang_items.u8_impl())
290+
|| fund_assoc(lang_items.u16_impl())
291+
|| fund_assoc(lang_items.u32_impl())
292+
|| fund_assoc(lang_items.u64_impl())
293+
|| fund_assoc(lang_items.u128_impl())
294+
|| fund_assoc(lang_items.f32_impl())
295+
|| fund_assoc(lang_items.f32_runtime_impl())
296+
|| fund_assoc(lang_items.f64_impl())
297+
|| fund_assoc(lang_items.f64_runtime_impl());
298+
if let (true, false, SelfSource::MethodCall(expr), true) = (
275299
actual.is_numeric(),
276300
actual.has_concrete_skeleton(),
277301
source,
278-
candidates.next(),
302+
found_candidate,
279303
) {
280304
let mut err = struct_span_err!(
281305
tcx.sess,

src/test/ui/issues/issue-29181.rs

+2
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ extern crate issue_29181 as foo;
44

55
fn main() {
66
0.homura(); //~ ERROR no method named `homura` found
7+
// Issue #47759, detect existing method on the fundamental impl:
8+
let _ = |x: f64| x * 2.0.exp(); //~ ERROR can't call method `exp` on ambiguous numeric type
79
}

src/test/ui/issues/issue-29181.stderr

+14-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,18 @@ error[E0599]: no method named `homura` found for type `{integer}` in the current
44
LL | 0.homura();
55
| ^^^^^^ method not found in `{integer}`
66

7-
error: aborting due to previous error
7+
error[E0689]: can't call method `exp` on ambiguous numeric type `{float}`
8+
--> $DIR/issue-29181.rs:8:30
9+
|
10+
LL | let _ = |x: f64| x * 2.0.exp();
11+
| ^^^
12+
|
13+
help: you must specify a concrete type for this numeric value, like `f32`
14+
|
15+
LL | let _ = |x: f64| x * 2.0_f32.exp();
16+
| ^^^^^^^
17+
18+
error: aborting due to 2 previous errors
819

9-
For more information about this error, try `rustc --explain E0599`.
20+
Some errors have detailed explanations: E0599, E0689.
21+
For more information about an error, try `rustc --explain E0599`.

0 commit comments

Comments
 (0)