diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index add706b5fcc..f075d1e74d4 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -271,11 +271,35 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut candidates = all_traits(self.tcx).into_iter().filter_map(|info| { self.associated_item(info.def_id, item_name, Namespace::ValueNS) }); - if let (true, false, SelfSource::MethodCall(expr), Some(_)) = ( + // There are methods that are defined on the primitive types and won't be + // found when exploring `all_traits`, but we also need them to be acurate on + // our suggestions (#47759). + let fund_assoc = |opt_def_id: Option| { + opt_def_id + .and_then(|id| self.associated_item(id, item_name, Namespace::ValueNS)) + .is_some() + }; + let lang_items = tcx.lang_items(); + let found_candidate = candidates.next().is_some() + || fund_assoc(lang_items.i8_impl()) + || fund_assoc(lang_items.i16_impl()) + || fund_assoc(lang_items.i32_impl()) + || fund_assoc(lang_items.i64_impl()) + || fund_assoc(lang_items.i128_impl()) + || fund_assoc(lang_items.u8_impl()) + || fund_assoc(lang_items.u16_impl()) + || fund_assoc(lang_items.u32_impl()) + || fund_assoc(lang_items.u64_impl()) + || fund_assoc(lang_items.u128_impl()) + || fund_assoc(lang_items.f32_impl()) + || fund_assoc(lang_items.f32_runtime_impl()) + || fund_assoc(lang_items.f64_impl()) + || fund_assoc(lang_items.f64_runtime_impl()); + if let (true, false, SelfSource::MethodCall(expr), true) = ( actual.is_numeric(), actual.has_concrete_skeleton(), source, - candidates.next(), + found_candidate, ) { let mut err = struct_span_err!( tcx.sess, diff --git a/src/test/ui/issues/issue-29181.rs b/src/test/ui/issues/issue-29181.rs index 45752ad4f62..70e5bc01920 100644 --- a/src/test/ui/issues/issue-29181.rs +++ b/src/test/ui/issues/issue-29181.rs @@ -4,4 +4,6 @@ extern crate issue_29181 as foo; fn main() { 0.homura(); //~ ERROR no method named `homura` found + // Issue #47759, detect existing method on the fundamental impl: + let _ = |x: f64| x * 2.0.exp(); //~ ERROR can't call method `exp` on ambiguous numeric type } diff --git a/src/test/ui/issues/issue-29181.stderr b/src/test/ui/issues/issue-29181.stderr index 250b158ab8e..b66dcb88d00 100644 --- a/src/test/ui/issues/issue-29181.stderr +++ b/src/test/ui/issues/issue-29181.stderr @@ -4,6 +4,18 @@ error[E0599]: no method named `homura` found for type `{integer}` in the current LL | 0.homura(); | ^^^^^^ method not found in `{integer}` -error: aborting due to previous error +error[E0689]: can't call method `exp` on ambiguous numeric type `{float}` + --> $DIR/issue-29181.rs:8:30 + | +LL | let _ = |x: f64| x * 2.0.exp(); + | ^^^ + | +help: you must specify a concrete type for this numeric value, like `f32` + | +LL | let _ = |x: f64| x * 2.0_f32.exp(); + | ^^^^^^^ -For more information about this error, try `rustc --explain E0599`. +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0599, E0689. +For more information about an error, try `rustc --explain E0599`.