]> git.lizzy.rs Git - rust.git/commitdiff
Consider methods on fundamental `impl` when method is not found on numeric type
authorEsteban Küber <esteban@kuber.com.ar>
Sat, 4 Apr 2020 18:38:22 +0000 (11:38 -0700)
committerEsteban Küber <esteban@kuber.com.ar>
Fri, 10 Apr 2020 00:46:26 +0000 (17:46 -0700)
Fix #47759.

src/librustc_typeck/check/method/suggest.rs
src/test/ui/issues/issue-29181.rs
src/test/ui/issues/issue-29181.stderr

index add706b5fcc9a7fa335c73df71e11d4addc7b359..f075d1e74d455df26ab62f9eb7fd81e379a0eef3 100644 (file)
@@ -271,11 +271,35 @@ pub fn report_method_error<'b>(
                     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,
index 45752ad4f62b6dba9634fd9b4e1e4aca77716172..70e5bc0192086e3ffb8890a47cab7e1e6ff77b00 100644 (file)
@@ -4,4 +4,6 @@
 
 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
 }
index 250b158ab8e33e8bd8c0bc463660e0fee500828b..b66dcb88d00625adcb17534f04743d7a578fb3c5 100644 (file)
@@ -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();
+   |                          ^^^^^^^
+
+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`.