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<DefId>| {
+ 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,
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();
+ | ^^^^^^^
+
+error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0599`.
+Some errors have detailed explanations: E0599, E0689.
+For more information about an error, try `rustc --explain E0599`.