Juniper: impl ToInputValue for Uuid

Created on 4 Feb 2020  路  5Comments  路  Source: graphql-rust/juniper

13 | #[derive(juniper::GraphQLInputObject)]
   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `juniper::ast::FromInputValue<__S>` is not implemented for `uuid::Uuid`
   |
   = note: required because of the requirements on the impl of `juniper::ast::FromInputValue<__S>` for `std::option::Option<uuid::Uuid>`
   = note: required by `juniper::ast::FromInputValue::from_input_value`

Sample codes

#[derive(juniper::GraphQLInputObject)]
struct Sample {
    id: Option<Uuid>,
}
bug needs-triage

Most helpful comment

What you've run into is called the "orphan rule". Basically it says that you can implement traits if either the trait or the type you're implementing the trait for is defined in your crate. What you're doing violates that rules because ToInputValue is defined in juniper and Uuid is defined in uuid.

If you were able to implement traits you don't own for types you don't own what should the compiler do if it finds two competing impls of the same trait for the same type but in different dependencies of the same crate? There is no good answer there so it is not allowed.

In juniper however we are able to implement ToInputValue for Uuid because ToInputValue is defined in juniper, which would then be the current crate.

Hopefully that all makes sense 馃槉 Otherwise there are plenty of blog posts out there including ways to get around the orphan rule.

All 5 comments

error[E0277]: the trait bound `uuid::Uuid: juniper::types::base::GraphQLType<__S>` is not satisfied
 --> src/filter_type.rs:3:10
  |
3 | #[derive(juniper::GraphQLInputObject)]
  |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `juniper::types::base::GraphQLType<__S>` is not implemented for `uuid::Uuid`
  |
  = note: required because of the requirements on the impl of `juniper::types::base::GraphQLType<__S>` for `std::option::Option<uuid::Uuid>`

error[E0277]: the trait bound `uuid::Uuid: juniper::ast::FromInputValue<__S>` is not satisfied
 --> src/filter_type.rs:3:10
  |
3 | #[derive(juniper::GraphQLInputObject)]
  |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `juniper::ast::FromInputValue<__S>` is not implemented for `uuid::Uuid`
  |
  = note: required because of the requirements on the impl of `juniper::ast::FromInputValue<__S>` for `std::option::Option<uuid::Uuid>`

error[E0277]: the trait bound `uuid::Uuid: juniper::ast::FromInputValue<__S>` is not satisfied
 --> src/filter_type.rs:3:10
  |
3 | #[derive(juniper::GraphQLInputObject)]
  |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `juniper::ast::FromInputValue<__S>` is not implemented for `uuid::Uuid`
  |
  = note: required because of the requirements on the impl of `juniper::ast::FromInputValue<__S>` for `std::option::Option<uuid::Uuid>`
  = note: required by `juniper::ast::FromInputValue::from_input_value`

error[E0599]: no method named `to_input_value` found for type `std::option::Option<uuid::Uuid>` in the current scope
 --> src/filter_type.rs:3:10
  |
3 | #[derive(juniper::GraphQLInputObject)]
  |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `std::option::Option<uuid::Uuid>`
  |
  = note: the method `to_input_value` exists but the following trait bounds were not satisfied:
          `std::option::Option<uuid::Uuid> : juniper::ast::ToInputValue<_>`

error: aborting due to 4 previous errors

Which version are you using of UUID and Juniper? It works for me with

juniper = { version = "0.14.2", features = ["uuid"] }
uuid = { version = "0.7", features = ["serde", "v4"] }

We recently bumped the uuid version to 0.8 but that isn't shipped yet, and probably wont be until async is done. So if you're using uuid 0.8 are you able to use 0.7 for now?

Confirming that I can use 0.7. Thanks.

Noob here and I'll appreciate it if you can explain how you made a workaround on creating a ToInputValue and FromInputValue implementation for Uuid. I tried it on my own and the following errors occur:

18 | impl ToInputValue for Uuid {
   | ^^^^^------------^^^^^----
   | |    |                |
   | |    |                `uuid::Uuid` is not defined in the current crate
   | |    `juniper::value::scalar::DefaultScalarValue` is not defined in the current crate
   | impl doesn't use only types from inside the current crate
   |
   = note: define and implement a trait or new type instead

error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
  --> src/filter_type.rs:24:1
   |
24 | impl FromInputValue for Uuid {
   | ^^^^^--------------^^^^^----
   | |    |                  |
   | |    |                  `uuid::Uuid` is not defined in the current crate
   | |    `juniper::value::scalar::DefaultScalarValue` is not defined in the current crate
   | impl doesn't use only types from inside the current crate
   |
   = note: define and implement a trait or new type instead

What you've run into is called the "orphan rule". Basically it says that you can implement traits if either the trait or the type you're implementing the trait for is defined in your crate. What you're doing violates that rules because ToInputValue is defined in juniper and Uuid is defined in uuid.

If you were able to implement traits you don't own for types you don't own what should the compiler do if it finds two competing impls of the same trait for the same type but in different dependencies of the same crate? There is no good answer there so it is not allowed.

In juniper however we are able to implement ToInputValue for Uuid because ToInputValue is defined in juniper, which would then be the current crate.

Hopefully that all makes sense 馃槉 Otherwise there are plenty of blog posts out there including ways to get around the orphan rule.

That makes sense. I thought it was allowed only for the crate that owns the type (uuid) and not for the crate that owns the trait (juniper). Thanks

Was this page helpful?
0 / 5 - 0 ratings

Related issues

librelois picture librelois  路  3Comments

skerkour picture skerkour  路  5Comments

norcalli picture norcalli  路  6Comments

hrbigelow picture hrbigelow  路  5Comments

theduke picture theduke  路  4Comments