Skip to content

Hint the generic type and possible bounds on the unimplemented trait error #28660

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

Closed
lifthrasiir opened this issue Sep 25, 2015 · 6 comments
Closed
Labels
A-diagnostics Area: Messages for errors, warnings, and lints

Comments

@lifthrasiir
Copy link
Contributor

fn f<T>(x: T) { x + 4; }
fn g<T>(x: T) { println!("{}", x); }
fn h<T>(x: T) { trait X {} fn hh<T:X>(x: T) {} hh(x); }

Codes like these currently do not point to the original declaration of T for missing trait bounds. In some cases rustc even does not indicate which trait is unimplemented (f). Hinting T: Trait bounds would be helpful for those cases.
#19950 (Provide better error reporting for unimplemented traits) is related and in principle would be a superset, but the issue currently only discusses about nominal types and not generic types.

@jdm jdm added the A-diagnostics Area: Messages for errors, warnings, and lints label Sep 25, 2015
@arielb1
Copy link
Contributor

arielb1 commented Sep 25, 2015

The errors mention T pretty explicitly.

<anon>:1:17: 1:18 error: binary operation `+` cannot be applied to type `T` [E0369]
<anon>:1 fn f<T>(x: T) { x + 4; }
                         ^
<anon>:1:17: 1:18 help: see the detailed explanation for E0369
<anon>:2:32: 2:33 error: the trait `core::fmt::Display` is not implemented for the type `T` [E0277]
<anon>:2 fn g<T>(x: T) { println!("{}", x); }
                                        ^
<std macros>:2:25: 2:56 note: in this expansion of format_args!
<std macros>:3:1: 3:54 note: in this expansion of print! (defined in <std macros>)
<anon>:2:17: 2:35 note: in this expansion of println! (defined in <std macros>)
<anon>:2:32: 2:33 help: see the detailed explanation for E0277
<anon>:2:32: 2:33 note: `T` cannot be formatted with the default formatter; try using `:?` instead if you are using a format string
<anon>:2:32: 2:33 note: required by `core::fmt::Display::fmt`
<anon>:3:48: 3:50 error: the trait `h::X` is not implemented for the type `T` [E0277]
<anon>:3 fn h<T>(x: T) { trait X {} fn hh<T:X>(x: T) {} hh(x); }
                                                        ^~
<anon>:3:48: 3:50 help: see the detailed explanation for E0277
<anon>:3:48: 3:50 note: required by `h::hh`

@lifthrasiir
Copy link
Contributor Author

@arielb1 The original declaration of T is still missing (I've updated the original issue). To be exact, the second example involving println! was a motivation: a custom rustc_on_unimplemented attribute masks the actual problem (of missing bounds). While not as problematic as this, other examples will be benefited from the explicit note as well.

@arielb1
Copy link
Contributor

arielb1 commented Sep 25, 2015

@lifthrasiir

The errors look clear enough to me (but ops may want a "+ can be overloaded using the trait core::ops::Add" help).

Spanning the type parameter seems so weird (even the current error messages are a bit on the heavy side, and adding a bound isn't always the correct solution - e.g. in the println case you may actually have wanted to use Debug).

@masklinn
Copy link
Contributor

@arielb1 it doesn't if you don't already know what it's talking about, it does confuse people and these days it even gives the wrong advice:

if it is defined in your crate, add `#[derive(Debug)]` or manually implement it

The problem here is that Rust newcomers may not yet understand generic trait bounds[0] and thus how to fix it (see link above for an example), at best the error message is unhelpful and at worst it sends them on a wild goose chase.

It would make perfect sense for the compiler to, when it's working on a generic type (rather than a concrete one), suggest adding trait bounds to the trait declaration e.g.

src/x/mod.rs:22:33: 22:34 error: the trait `core::fmt::Debug` is not implemented for the type `T` [E0277]
src/x/mod.rs:22         println!("trait: {:?}", i);
                                                ^
requires that "i" implements core::fmt::Debug, but

src/x/mod.rs:15 impl<T> Info for Buffer<T> {
does not specify that T implements it

hint: you can bound T to core::fmt::Debug:

    impl <T> Info for Buffer<T> where T: core::fmt::Debug {

this means the code will only work with types which implements core::fmt::Debug, 
but lets you use core::fmt::Debug operations in your methods

Spanning the type parameter seems so weird (even the current error messages are a bit on the heavy side, and adding a bound isn't always the correct solution - e.g. in the println case you may actually have wanted to use Debug).

That wouldn't work either (for the same reason) and would yield essentially the same unhelpful error message. Although in specific context it's true that pointing to a related trait could help e.g. a Display println on a type which does implement or is bounded on Debug could suggest replacing Display by Debug, that would be neat.

[0] or worse may come from C++ as the link's author does and think they need template instantiation

@arielb1
Copy link
Contributor

arielb1 commented Apr 22, 2016

I feel like this is fixed in 1.9+:

<anon>:1:32: 1:33 error: the trait bound `T: std::fmt::Display` is not satisfied [E0277]
<anon>:1 fn g<T>(x: T) { println!("{}", x); }
                                        ^
<std macros>:2:25: 2:56 note: in this expansion of format_args!
<std macros>:3:1: 3:54 note: in this expansion of print! (defined in <std macros>)
<anon>:1:17: 1:35 note: in this expansion of println! (defined in <std macros>)
<anon>:1:32: 1:33 help: see the detailed explanation for E0277
<anon>:1:32: 1:33 help: consider adding a `where T: std::fmt::Display` bound
<anon>:1:32: 1:33 note: required by `std::fmt::Display::fmt`
error: aborting due to previous error

@birkenfeld
Copy link
Contributor

The message for the Add case is also nicer:

<anon>:2:17: 2:18 note: an implementation of `std::ops::Add` might be missing for `T`

so this seems fixed indeed.

@arielb1 arielb1 closed this as completed May 2, 2016
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
Projects
None yet
Development

No branches or pull requests

5 participants