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

Improve error messages on failure to derive #329

Merged
merged 1 commit into from
Sep 9, 2020

Conversation

JayKickliter
Copy link
Contributor

This PR uses spans to add source-of-error messages when a rustler derive macro fails.

Example invalid input

use rustler::{NifMap, NifRecord, NifStruct, NifTuple, NifUnitEnum, NifUntaggedEnum};

/// This struct does not implement Encoder/Decoder
pub struct C(i32);

#[derive(NifStruct)]
#[module = "AddStruct"]
struct AddStruct {
    lhs: i32,
    rhs: C,
}

#[derive(NifMap)]
struct AddMap {
    lhs: i32,
    rhs: C,
}

#[derive(NifRecord)]
#[tag = "record"]
struct AddRecord {
    lhs: i32,
    rhs: C,
}

#[derive(NifTuple)]
struct AddTuple {
    lhs: i32,
    rhs: C,
}

#[derive(NifUnitEnum)]
enum UnitEnum {
    FooBar,
    Baz(u8),
}

#[derive(NifUntaggedEnum)]
enum UntaggedEnum {
    Foo(u32),
    Bar(String),
    Baz(i32,i32),
}

Improved messages

error: NifUnitEnum can only be used with enums containing unit variants.
  --> src/nifmap.rs:34:5
   |
34 |     Baz(u8),
   |     ^^^

error: NifUntaggedEnum can only be used with enums that contain all NewType variants.
  --> src/nifmap.rs:41:5
   |
41 |     Baz(i32,i32),
   |     ^^^

error[E0277]: the trait bound `nifmap::C: rustler::Decoder<'_>` is not satisfied
 --> src/nifmap.rs:9:5
  |
5 | #[derive(NifStruct)]
  |          --------- required by this bound in `<nifmap::AddStruct as rustler::Decoder<'a>>::decode::try_decode_field`
...
9 |     rhs: C,
  |     ^^^ the trait `rustler::Decoder<'_>` is not implemented for `nifmap::C`

error[E0599]: no method named `encode` found for struct `nifmap::C` in the current scope
 --> src/nifmap.rs:9:5
  |
3 | pub struct C(i32);
  | ------------------ method `encode` not found for this
...
9 |     rhs: C,
  |     ^^^ method not found in `nifmap::C`
  |
  = help: items from traits can only be used if the trait is implemented and in scope
  = note: the following trait defines an item `encode`, perhaps you need to implement it:
          candidate #1: `rustler::Encoder`

error[E0277]: the trait bound `nifmap::C: rustler::Decoder<'_>` is not satisfied
  --> src/nifmap.rs:15:5
   |
12 | #[derive(NifMap)]
   |          ------ required by this bound in `<nifmap::AddMap as rustler::Decoder<'a>>::decode::try_decode_field`
...
15 |     rhs: C,
   |     ^^^ the trait `rustler::Decoder<'_>` is not implemented for `nifmap::C`

error[E0599]: no method named `encode` found for struct `nifmap::C` in the current scope
  --> src/nifmap.rs:15:5
   |
3  | pub struct C(i32);
   | ------------------ method `encode` not found for this
...
15 |     rhs: C,
   |     ^^^ method not found in `nifmap::C`
   |
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `encode`, perhaps you need to implement it:
           candidate #1: `rustler::Encoder`

error[E0277]: the trait bound `nifmap::C: rustler::Decoder<'_>` is not satisfied
  --> src/nifmap.rs:22:5
   |
18 | #[derive(NifRecord)]
   |          --------- required by this bound in `<nifmap::AddRecord as rustler::Decoder<'a>>::decode::try_decode_index`
...
22 |     rhs: C,
   |     ^^^ the trait `rustler::Decoder<'_>` is not implemented for `nifmap::C`

error[E0599]: no method named `encode` found for struct `nifmap::C` in the current scope
  --> src/nifmap.rs:22:5
   |
3  | pub struct C(i32);
   | ------------------ method `encode` not found for this
...
22 |     rhs: C,
   |     ^^^ method not found in `nifmap::C`
   |
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `encode`, perhaps you need to implement it:
           candidate #1: `rustler::Encoder`

error[E0277]: the trait bound `nifmap::C: rustler::Decoder<'_>` is not satisfied
  --> src/nifmap.rs:28:5
   |
25 | #[derive(NifTuple)]
   |          -------- required by this bound in `<nifmap::AddTuple as rustler::Decoder<'a>>::decode::try_decode_index`
...
28 |     rhs: C,
   |     ^^^ the trait `rustler::Decoder<'_>` is not implemented for `nifmap::C`

error[E0599]: no method named `encode` found for struct `nifmap::C` in the current scope
  --> src/nifmap.rs:28:5
   |
3  | pub struct C(i32);
   | ------------------ method `encode` not found for this
...
28 |     rhs: C,
   |     ^^^ method not found in `nifmap::C`
   |
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `encode`, perhaps you need to implement it:
           candidate #1: `rustler::Encoder`

error: aborting due to 10 previous errors

Some errors have detailed explanations: E0277, E0599.
For more information about an error, try `rustc --explain E0277`.
error: could not compile `nifmap`.

Current error messages

error: proc-macro derive panicked
  --> src/nifmap.rs:31:10
   |
31 | #[derive(NifUnitEnum)]
   |          ^^^^^^^^^^^
   |
   = help: message: NifUnitEnum can only be used with enums that contain all unit variants.

error: proc-macro derive panicked
  --> src/nifmap.rs:37:10
   |
37 | #[derive(NifUntaggedEnum)]
   |          ^^^^^^^^^^^^^^^
   |
   = help: message: NifUntaggedEnum can only be used with enums that contain all NewType variants.

error[E0277]: the trait bound `nifmap::C: rustler::Decoder<'_>` is not satisfied
 --> src/nifmap.rs:5:10
  |
5 | #[derive(NifStruct)]
  |          ^^^^^^^^^
  |          |
  |          the trait `rustler::Decoder<'_>` is not implemented for `nifmap::C`
  |          required by this bound in `<nifmap::AddStruct as rustler::Decoder<'a>>::decode::try_decode_field`
  |
  = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0599]: no method named `encode` found for struct `nifmap::C` in the current scope
 --> src/nifmap.rs:5:10
  |
3 | pub struct C(i32);
  | ------------------ method `encode` not found for this
4 |
5 | #[derive(NifStruct)]
  |          ^^^^^^^^^ method not found in `nifmap::C`
  |
  = help: items from traits can only be used if the trait is implemented and in scope
  = note: the following trait defines an item `encode`, perhaps you need to implement it:
          candidate #1: `rustler::Encoder`
  = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `nifmap::C: rustler::Decoder<'_>` is not satisfied
  --> src/nifmap.rs:12:10
   |
12 | #[derive(NifMap)]
   |          ^^^^^^
   |          |
   |          the trait `rustler::Decoder<'_>` is not implemented for `nifmap::C`
   |          required by this bound in `<nifmap::AddMap as rustler::Decoder<'a>>::decode::try_decode_field`
   |
   = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0599]: no method named `encode` found for struct `nifmap::C` in the current scope
  --> src/nifmap.rs:12:10
   |
3  | pub struct C(i32);
   | ------------------ method `encode` not found for this
...
12 | #[derive(NifMap)]
   |          ^^^^^^ method not found in `nifmap::C`
   |
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `encode`, perhaps you need to implement it:
           candidate #1: `rustler::Encoder`
   = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `nifmap::C: rustler::Decoder<'_>` is not satisfied
  --> src/nifmap.rs:18:10
   |
18 | #[derive(NifRecord)]
   |          ^^^^^^^^^
   |          |
   |          the trait `rustler::Decoder<'_>` is not implemented for `nifmap::C`
   |          required by this bound in `<nifmap::AddRecord as rustler::Decoder<'a>>::decode::try_decode_index`
   |
   = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0599]: no method named `encode` found for struct `nifmap::C` in the current scope
  --> src/nifmap.rs:18:10
   |
3  | pub struct C(i32);
   | ------------------ method `encode` not found for this
...
18 | #[derive(NifRecord)]
   |          ^^^^^^^^^ method not found in `nifmap::C`
   |
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `encode`, perhaps you need to implement it:
           candidate #1: `rustler::Encoder`
   = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `nifmap::C: rustler::Decoder<'_>` is not satisfied
  --> src/nifmap.rs:25:10
   |
25 | #[derive(NifTuple)]
   |          ^^^^^^^^
   |          |
   |          the trait `rustler::Decoder<'_>` is not implemented for `nifmap::C`
   |          required by this bound in `<nifmap::AddTuple as rustler::Decoder<'a>>::decode::try_decode_index`
   |
   = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0599]: no method named `encode` found for struct `nifmap::C` in the current scope
  --> src/nifmap.rs:25:10
   |
3  | pub struct C(i32);
   | ------------------ method `encode` not found for this
...
25 | #[derive(NifTuple)]
   |          ^^^^^^^^ method not found in `nifmap::C`
   |
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `encode`, perhaps you need to implement it:
           candidate #1: `rustler::Encoder`
   = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 10 previous errors

Some errors have detailed explanations: E0277, E0599.
For more information about an error, try `rustc --explain E0277`.
error: could not compile `nifmap`.

To learn more, run the command again with --verbose

@evnu evnu merged commit 5d07755 into rusterlium:master Sep 9, 2020
@evnu
Copy link
Member

evnu commented Sep 9, 2020

@JayKickliter thank you!

@JayKickliter
Copy link
Contributor Author

You're welcome! I've been looking for an excuse to learn a little bit about proc macros.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants