num-derive icon indicating copy to clipboard operation
num-derive copied to clipboard

Poor error suggestion from failure to `use` trait

Open jnqnfe opened this issue 5 years ago • 2 comments

This is probably an issue best suited for rustc itself rather than this crate, but I wanted to start here in case there's anything to be done for your crate to improve things...

I'm just now implementing use of this crate in one of mine (thanks btw!), and I forgot initially to add a use num_traits::FromPrimitive; line in the file, since the instructions for this crate failed to remind me of the need :p

The error message that resulted (using rustc v1.47) was:

error[E0599]: no variant or associated item named `from_i32` found for enum `capi::pa_port_available_t` in the current scope
   --> pulse-binding/src/context/introspect.rs:351:48
    |
351 |                 available: def::PortAvailable::from_i32(src.available).unwrap(),
    |                                                ^^^^^^^^ variant or associated item not found in `capi::pa_port_available_t`
    |
    = help: items from traits can only be used if the trait is in scope
    = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
            `use crate::channelmap::_IMPL_NUM_ToPrimitive_FOR_Position::_num_traits::FromPrimitive;`

That use suggestion is obviously not the most helpful.

It is similar to what was noticed in issue #27, though it that case it was referencing an external crate. Here it's referencing... well, I guess something generated by the macros via the derive... within my own crate... though for a completely different module than the one containing the type I'm calling the method on (crate::def::PortAvailable). I have derived the trait on multiple enums throughout the crate, including within the channelmap module, and interestingly I think that module comes first alphabetically...

It's also not ideal that it's referencing capi::pa_port_available_t as the type the method is not found for, which is the original type from the 'sys' crate (aliased as capi) which this binding crate is re-exporting as def::PortAvailable. Which brings up the point that for this type, the derive is actually applied to it within the 'sys' crate, if that detail is at all important.

jnqnfe avatar Nov 25 '20 07:11 jnqnfe

    = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
            `use crate::channelmap::_IMPL_NUM_ToPrimitive_FOR_Position::_num_traits::FromPrimitive;`

This should be filed as a compiler bug -- _IMPL_NUM_ToPrimitive_FOR_Position is a private const generated by the derivation. Constants are not a valid path prefix regardless of publicity, so that suggestion makes no sense at all. I don't know how easy it would be for the compiler to find a path that is accessible to you though.

One way you can get around this is explicitly naming the crate (#35), #[num_traits = "num_traits"], which basically assumes that crate is in the extern prelude (no extern crate needed) and that the name is not shadowed locally. This is almost always true, but not assumed by the derivation.

It's also not ideal that it's referencing capi::pa_port_available_t as the type the method is not found for, which is the original type from the 'sys' crate (aliased as capi) which this binding crate is re-exporting as def::PortAvailable.

This may also be a compiler issue, but I'm less sure that anything can be changed here. Whether that's a type alias or a renamed use, they're all the exact same type to the compiler, and the original name would be canonical. If you really want to hide that from end users, you'd need a newtype wrapper like struct PortAvailable(capi::pa_port_available_t);.

cuviper avatar Nov 30 '20 19:11 cuviper

Ok, thanks, I'll try to remember to pass it along as a compiler bug shortly, very busy just at the moment though. :)

jnqnfe avatar Nov 30 '20 20:11 jnqnfe