Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Diagnostics for ambiguous number types could be better #40985

Closed
Rufflewind opened this issue Apr 1, 2017 · 2 comments
Closed

Diagnostics for ambiguous number types could be better #40985

Rufflewind opened this issue Apr 1, 2017 · 2 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-enhancement Category: An issue proposing an enhancement or a PR with one. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. WG-diagnostics Working group: Diagnostics

Comments

@Rufflewind
Copy link
Contributor

Rufflewind commented Apr 1, 2017

Ambiguous integer or float type variable can lead to some rather confusing error messages. Consider:

fn main() {
    println!("{:?}", 2.0.powi(2));
    println!("{:?}", 2.0 as u32);
}

Method calls on an ambiguous number type

The first error says that {float} doesn't have a method called powi, but taken naively that's not true: both f32 and f64 have methods powi. The actual problem is that the type inference doesn't know which floating point type the user wants.

The help is even more confusing, because it suggests the user to use a deprecated trait that's not even documented anymore.

rustc 1.18.0-nightly (5c94997b6 2017-03-30)
error: no method named `powi` found for type `{float}` in the current scope
 --> <anon>:2:26
  |
2 |     println!("{:?}", 2.0.powi(2));
  |                          ^^^^
  |
  = help: items from traits can only be used if the trait is in scope; the following trait is implemented but not in scope, perhaps add a `use` for it:
  = help: candidate #1: `use core::num::Float;`

Casting an ambiguous number type

Likewise, when casting one could again run into the same problem. Here, it complains that the cast is "non-scalar" but naively {float} sounds like a perfectly scalar type! In reality the problem is that casting requires the source type to be non-ambiguous.

error: non-scalar cast: `{float}` as `u32`
 --> <anon>:3:22
  |
3 |     println!("{:?}", 2.0 as u32);
  |                      ^^^^^^^^^^

error: aborting due to 2 previous errors

Suggestion

Tentative PR: master...Rufflewind:ambiguous-number-type

Tweak the error messages a bit when the type is {float} or {integer}. Also, perhaps suggestions for deprecated traits could be suppressed?

rustc 1.18.0-nightly (5c94997b6 2017-03-30)
error: no method named `powi` found for the ambiguous type `{float}` in the current scope
 --> <anon>:2:26
  |
2 |     println!("{:?}", 2.0.powi(2));
  |                          ^^^^
  |
  = help: if you meant to call the `powi` method of, say, `f64`, consider adding some type annotations to clarify that `{float}` should be `f64`

error: casting from an ambiguous type: `{float}` as `u32`
 --> <anon>:3:22
  |
3 |     println!("{:?}", 2.0 as u32);
  |                      ^^^^^^^^^^

error: aborting due to 2 previous errors
@Mark-Simulacrum Mark-Simulacrum added the A-diagnostics Area: Messages for errors, warnings, and lints label Jun 20, 2017
@Mark-Simulacrum Mark-Simulacrum added the C-enhancement Category: An issue proposing an enhancement or a PR with one. label Jul 26, 2017
@estebank
Copy link
Contributor

estebank commented Dec 13, 2017

Method calls on an ambiguous number type

In the following code add a check to see if actual.is_numeric() && actual.is_fresh() and modify the error text accordingly:

let actual = self.resolve_type_vars_if_possible(&rcvr_ty);
let ty_string = self.ty_to_string(actual);
let is_method = mode == Mode::MethodCall;
let type_str = if is_method {
"method"
} else if actual.is_enum() {
"variant"
} else {
match (item_name.as_str().chars().next(), actual.is_fresh_ty()) {
(Some(name), false) if name.is_lowercase() => {
"function or associated item"
}
(Some(_), false) => "associated item",
(Some(_), true) | (None, false) => {
"variant or associated item"
}
(None, true) => "variant",
}
};
let mut err = if !actual.references_error() {
struct_span_err!(
tcx.sess,
span,
E0599,
"no {} named `{}` found for type `{}` in the current scope",
type_str,
item_name,
ty_string
)
} else {
tcx.sess.diagnostic().struct_dummy()
};
if let Some(def) = actual.ty_adt_def() {
if let Some(full_sp) = tcx.hir.span_if_local(def.did) {
let def_sp = tcx.sess.codemap().def_span(full_sp);
err.span_label(def_sp, format!("{} `{}` not found {}",
type_str,
item_name,
if def.is_enum() && !is_method {
"here"
} else {
"for this"
}));
}
}

Casting an ambiguous number type

On its own, println!("{:?}", 2.0 as u32); doesn't generate the error, but when it does, the output talks about "non-primitive cast":

error[E0605]: non-primitive cast: `{float}` as `u32`
 --> src/main.rs:3:22
  |
3 |     println!("{:?}", 2.0 as u32);
  |                      ^^^^^^^^^^
  |
  = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait

If the help where to be expanded, it could be done in the following code in the same way as above:

CastError::NonScalar => {
type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0605,
"non-primitive cast: `{}` as `{}`",
self.expr_ty,
fcx.ty_to_string(self.cast_ty))
.note("an `as` expression can only be used to convert between \
primitive types. Consider using the `From` trait")
.emit();
}


Update: output in nightly no longer shows the second error:

error[E0599]: no method named `powi` found for type `{float}` in the current scope
 --> src/main.rs:2:26
  |
2 |     println!("{:?}", 2.0.powi(2));
  |                          ^^^^
  |
  = help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope, perhaps add a `use` for it:
  |
1 | use core::num::Float;
  |

@estebank estebank added E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. WG-diagnostics Working group: Diagnostics labels Dec 13, 2017
@mikedilger
Copy link
Contributor

Glad I found this issue, I was quite confused by the reference to the core Float trait, and the rust manual saying f32 powi() was stable since 1.0.0

bors added a commit that referenced this issue Jan 7, 2018
…sakis

Provide suggestion when trying to use method on numeric literal

New output:

```
error[E0688]: can't call method `powi` on ambiguous numeric type `{float}`
  --> $DIR/method-on-ambiguous-numeric-type.rs:12:17
   |
12 |     let x = 2.0.powi(2);
   |                 ^^^^
help: you must specify a concrete type for this numeric value, like `f32`
   |
12 |     let x = 2.0_f32.powi(2);
   |             ^^^^^^^
```

Previous output:

```
error[E0599]: no method named `powi` found for type `{float}` in the current scope
  --> src/main.rs:12:17
   |
12 |     let x = 2.0.powi(2);
   |                 ^^^^
   |
   = help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope, perhaps add a `use` for it:
   |
11 | use core::num::Float;
   |
```

Fix #40985.
bors added a commit that referenced this issue Jan 7, 2018
…sakis

Provide suggestion when trying to use method on numeric literal

New output:

```
error[E0688]: can't call method `powi` on ambiguous numeric type `{float}`
  --> $DIR/method-on-ambiguous-numeric-type.rs:12:17
   |
12 |     let x = 2.0.powi(2);
   |                 ^^^^
help: you must specify a concrete type for this numeric value, like `f32`
   |
12 |     let x = 2.0_f32.powi(2);
   |             ^^^^^^^
```

Previous output:

```
error[E0599]: no method named `powi` found for type `{float}` in the current scope
  --> src/main.rs:12:17
   |
12 |     let x = 2.0.powi(2);
   |                 ^^^^
   |
   = help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope, perhaps add a `use` for it:
   |
11 | use core::num::Float;
   |
```

Fix #40985.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-enhancement Category: An issue proposing an enhancement or a PR with one. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. WG-diagnostics Working group: Diagnostics
Projects
None yet
Development

No branches or pull requests

4 participants