Repository: graphql-rust/juniper (language: rust)

Issue:
#[juniper::graphql_object] != #[derive(juniper::GraphQLObject)]
Code like this in master branch:
```rust
pub struct Data {
   pub value: String,
}

#[juniper::graphql_object]
impl Data {
    pub fn value(&self) -> String {
        self.value
    }
}

#[derive(juniper::GraphQLObject)]
pub struct User {
   pub username: String,
   pub values: Vec<Data>,
}
```
Produce an error: 
```sh
the trait bound `Data: juniper::types::async_await::GraphQLTypeAsync<__S>` is not satisfied
required because of the requirements on the impl of `juniper::types::async_await::GraphQLTypeAsync<__S>` for `std::vec::Vec<Data>`
required because of the requirements on the impl of `juniper::types::async_await::GraphQLTypeAsync<__S>` for `&std::vec::Vec<Data>`

`match` arms have incompatible types
expected enum `std::result::Result<juniper::value::Value<__S>, juniper::executor::FieldError<__S>>`
   found enum `std::result::Result<_, juniper::executor::FieldError<juniper::value::scalar::DefaultScalarValue>>`
type parameters must be constrained to match other types
for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
```

But code like this works:
```rust
#[derive(juniper::GraphQLObject)]
pub struct Data {
   pub value: String,
}

#[derive(juniper::GraphQLObject)]
pub struct User {
   pub username: String,
   pub values: Vec<Data>,
}
```



Discussion / hints:
You need to add "value" as an async function in the proc macro case.

This will be fixed when I rip out the sync resolvers.
We are not going to be removing the sync code.
I'm having the same problem where I want to nest a type defined with `#[juniper::graphql_object]` with only `async` functions inside one defined with `
#[derive(juniper::GraphQLObject)]` and I get these same kinds of errors.
Is this something we want to fix or not?
If you add `noasync` to the first case (a la https://github.com/graphql-rust/juniper/blob/4d77a1a9b9b0e60cbeb200527289bd45afec4141/juniper/src/schema/schema.rs#L134) then does it work?
@LegNeato it's not about asyncness, but rather because one of the macros derives code for `DefaultScalarValue` and another oned for `__S: ScalarValue`. Then the first is used as the field of the second one, so we have the situation when we need funtion being abstracted over `__S: ScalarValue`, but in fact we can call inside only something with `DefaultScalarValue`.

I'm going to fix this once I finish with interfaces.

@loafofpiecrust at the moment, you should specialize the generic implementation by providing attributes argument `scalar = DefaultScalarValue`. This way both implementations will be derived for `DefaultScalarValue`, so no conflict will happen.
Ah yeah, that's what I figured but wanted to confirm there wasn't any wonkiness going on with our async handling

Fix patch:
diff --git a/docs/book/content/advanced/introspection.md b/docs/book/content/advanced/introspection.md
index 9bf7e8956..3fabcb73a 100644
--- a/docs/book/content/advanced/introspection.md
+++ b/docs/book/content/advanced/introspection.md
@@ -33,11 +33,14 @@ result can then be converted to JSON for use with tools and libraries such as
 # #![allow(unused_variables)]
 # extern crate juniper;
 # extern crate serde_json;
-use juniper::{EmptyMutation, EmptySubscription, FieldResult, IntrospectionFormat};
+use juniper::{
+    graphql_object, EmptyMutation, EmptySubscription, FieldResult, 
+    GraphQLObject, IntrospectionFormat,
+};
 
 // Define our schema.
 
-#[derive(juniper::GraphQLObject)]
+#[derive(GraphQLObject)]
 struct Example {
   id: String,
 }
@@ -47,9 +50,7 @@ impl juniper::Context for Context {}
 
 struct Query;
 
-#[juniper::graphql_object(
-  Context = Context,
-)]
+#[graphql_object(context = Context)]
 impl Query {
    fn example(id: String) -> FieldResult<Example> {
        unimplemented!()
diff --git a/docs/book/content/advanced/non_struct_objects.md b/docs/book/content/advanced/non_struct_objects.md
index 19b2626bd..75169350d 100644
--- a/docs/book/content/advanced/non_struct_objects.md
+++ b/docs/book/content/advanced/non_struct_objects.md
@@ -10,9 +10,10 @@ errors from a mutation:
 
 ```rust
 # extern crate juniper;
+# use juniper::{graphql_object, GraphQLObject};
 # #[derive(juniper::GraphQLObject)] struct User { name: String }
-
-#[derive(juniper::GraphQLObject)]
+#
+#[derive(GraphQLObject)]
 struct ValidationError {
     field: String,
     message: String,
@@ -24,7 +25,7 @@ enum SignUpResult {
     Error(Vec<ValidationError>),
 }
 
-#[juniper::graphql_object]
+#[graphql_object]
 impl SignUpResult {
     fn user(&self) -> Option<&User> {
         match *self {
@@ -40,7 +41,7 @@ impl SignUpResult {
         }
     }
 }
-
+#
 # fn main() {}
 ```
 
diff --git a/docs/book/content/advanced/subscriptions.md b/docs/book/content/advanced/subscriptions.md
index 59f145161..c1052b37c 100644
--- a/docs/book/content/advanced/subscriptions.md
+++ b/docs/book/content/advanced/subscriptions.md
@@ -29,7 +29,7 @@ sequentially:
 # extern crate juniper;
 # extern crate juniper_subscriptions;
 # extern crate tokio;
-# use juniper::FieldError;
+# use juniper::{graphql_object, graphql_subscription, FieldError};
 # use futures::Stream;
 # use std::pin::Pin;
 #
@@ -38,7 +38,7 @@ sequentially:
 # impl juniper::Context for Database {}
 
 # pub struct Query;
-# #[juniper::graphql_object(Context = Database)]
+# #[graphql_object(context = Database)]
 # impl Query {
 #    fn hello_world() -> &str {
 #        "Hello World!"
@@ -48,7 +48,7 @@ pub struct Subscription;
 
 type StringStream = Pin<Box<dyn Stream<Item = Result<String, FieldError>> + Send>>;
 
-#[juniper::graphql_subscription(Context = Database)]
+#[graphql_subscription(context = Database)]
 impl Subscription {
     async fn hello_world() -> StringStream {
         let stream = tokio::stream::iter(vec![
@@ -58,8 +58,9 @@ impl Subscription {
         Box::pin(stream)
     }
 }
+#
 # fn main () {}
-```         
+```
 
 
 
@@ -84,8 +85,12 @@ where [`Connection`][Connection] is a `Stream` of values returned by the operati
 # extern crate juniper_subscriptions;
 # extern crate serde_json;
 # extern crate tokio;
-# use juniper::http::GraphQLRequest;
-# use juniper::{DefaultScalarValue, EmptyMutation, FieldError, RootNode, SubscriptionCoordinator};
+# use juniper::{
+#     http::GraphQLRequest,
+#     graphql_object, graphql_subscription, 
+#     DefaultScalarValue, EmptyMutation, FieldError, 
+#     RootNode, SubscriptionCoordinator,
+# };
 # use juniper_subscriptions::Coordinator;
 # use futures::{Stream, StreamExt};
 # use std::pin::Pin;
@@ -103,7 +108,7 @@ where [`Connection`][Connection] is a `Stream` of values returned by the operati
 # 
 # pub struct Query;
 # 
-# #[juniper::graphql_object(Context = Database)]
+# #[graphql_object(context = Database)]
 # impl Query {
 #     fn hello_world() -> &str {
 #         "Hello World!"
@@ -114,7 +119,7 @@ where [`Connection`][Connection] is a `Stream` of values returned by the operati
 # 
 # type StringStream = Pin<Box<dyn Stream<Item = Result<String, FieldError>> + Send>>;
 # 
-# #[juniper::graphql_subscription(Context = Database)]
+# #[graphql_subscription(context = Database)]
 # impl Subscription {
 #     async fn hello_world() -> StringStream {
 #         let stream =
@@ -132,11 +137,9 @@ async fn run_subscription() {
     let schema = schema();
     let coordinator = Coordinator::new(schema);
     let req: GraphQLRequest<DefaultScalarValue> = serde_json::from_str(
-        r#"
-        {
+        r#"{
             "query": "subscription { helloWorld }"
-        }
-    "#,
+        }"#,
     )
         .unwrap();
     let ctx = Database::new();
@@ -145,7 +148,7 @@ async fn run_subscription() {
         println!("{}", serde_json::to_string(&result).unwrap());
     }
 }
-
+#
 # fn main() { }
 ```     
 
diff --git a/docs/book/content/quickstart.md b/docs/book/content/quickstart.md
index b3b580152..aa9661ae1 100644
--- a/docs/book/content/quickstart.md
+++ b/docs/book/content/quickstart.md
@@ -28,8 +28,12 @@ resolvers, which you will use for the `Query` and `Mutation` roots.
 ```rust
 # #![allow(unused_variables)]
 # extern crate juniper;
-use juniper::{FieldResult, EmptySubscription};
-
+# use std::fmt::Display;
+use juniper::{
+    graphql_object, EmptySubscription, FieldResult, GraphQLEnum, 
+    GraphQLInputObject, GraphQLObject, ScalarValue,
+};
+#
 # struct DatabasePool;
 # impl DatabasePool {
 #     fn get_connection(&self) -> FieldResult<DatabasePool> { Ok(DatabasePool) }
@@ -37,15 +41,15 @@ use juniper::{FieldResult, EmptySubscription};
 #     fn insert_human(&self, _human: &NewHuman) -> FieldResult<Human> { Err("")? }
 # }
 
-#[derive(juniper::GraphQLEnum)]
+#[derive(GraphQLEnum)]
 enum Episode {
     NewHope,
     Empire,
     Jedi,
 }
 
-#[derive(juniper::GraphQLObject)]
-#[graphql(description="A humanoid creature in the Star Wars universe")]
+#[derive(GraphQLObject)]
+#[graphql(description = "A humanoid creature in the Star Wars universe")]
 struct Human {
     id: String,
     name: String,
@@ -55,8 +59,8 @@ struct Human {
 
 // There is also a custom derive for mapping GraphQL input objects.
 
-#[derive(juniper::GraphQLInputObject)]
-#[graphql(description="A humanoid creature in the Star Wars universe")]
+#[derive(GraphQLInputObject)]
+#[graphql(description = "A humanoid creature in the Star Wars universe")]
 struct NewHuman {
     name: String,
     appears_in: Vec<Episode>,
@@ -78,14 +82,13 @@ impl juniper::Context for Context {}
 
 struct Query;
 
-#[juniper::graphql_object(
+#[graphql_object(
     // Here we specify the context type for the object.
     // We need to do this in every type that
     // needs access to the context.
-    Context = Context,
+    context = Context,
 )]
 impl Query {
-
     fn apiVersion() -> &str {
         "1.0"
     }
@@ -109,14 +112,18 @@ impl Query {
 
 struct Mutation;
 
-#[juniper::graphql_object(
-    Context = Context,
-)]
-impl Mutation {
+#[graphql_object(
+    context = Context,
 
-    fn createHuman(context: &Context, new_human: NewHuman) -> FieldResult<Human> {
-        let db = context.pool.get_connection()?;
-        let human: Human = db.insert_human(&new_human)?;
+    // If we need to use `ScalarValue` parametrization explicitly somewhere
+    // in the object definition (like here in `FieldResult`), we should
+    // declare an explicit type parameter for that, and specify it.
+    scalar = S,
+)]
+impl<S: ScalarValue + Display> Mutation {
+    fn createHuman(context: &Context, new_human: NewHuman) -> FieldResult<Human, S> {
+        let db = context.pool.get_connection().map_err(|e| e.map_scalar_value())?;
+        let human: Human = db.insert_human(&new_human).map_err(|e| e.map_scalar_value())?;
         Ok(human)
     }
 }
@@ -124,7 +131,7 @@ impl Mutation {
 // A root schema consists of a query, a mutation, and a subscription.
 // Request queries can be executed against a RootNode.
 type Schema = juniper::RootNode<'static, Query, Mutation, EmptySubscription<Context>>;
-
+#
 # fn main() {
 #   let _ = Schema::new(Query, Mutation{}, EmptySubscription::new());
 # }
@@ -143,10 +150,12 @@ You can invoke `juniper::execute` directly to run a GraphQL query:
 ```rust
 # // Only needed due to 2018 edition because the macro is not accessible.
 # #[macro_use] extern crate juniper;
-use juniper::{FieldResult, Variables, EmptyMutation, EmptySubscription};
-
+use juniper::{
+    graphql_object, EmptyMutation, EmptySubscription, FieldResult, 
+    GraphQLEnum, Variables,
+};
 
-#[derive(juniper::GraphQLEnum, Clone, Copy)]
+#[derive(GraphQLEnum, Clone, Copy)]
 enum Episode {
     NewHope,
     Empire,
@@ -160,16 +169,13 @@ impl juniper::Context for Ctx {}
 
 struct Query;
 
-#[juniper::graphql_object(
-    Context = Ctx,
-)]
+#[graphql_object(context = Ctx)]
 impl Query {
     fn favoriteEpisode(context: &Ctx) -> FieldResult<Episode> {
         Ok(context.0)
     }
 }
 
-
 // A root schema consists of a query, a mutation, and a subscription.
 // Request queries can be executed against a RootNode.
 type Schema = juniper::RootNode<'static, Query, EmptyMutation<Ctx>, EmptySubscription<Ctx>>;
diff --git a/docs/book/content/schema/schemas_and_mutations.md b/docs/book/content/schema/schemas_and_mutations.md
index 77cb45571..c7ecc7d38 100644
--- a/docs/book/content/schema/schemas_and_mutations.md
+++ b/docs/book/content/schema/schemas_and_mutations.md
@@ -24,18 +24,18 @@ object in Juniper, most commonly using the `graphql_object` proc macro:
 ```rust
 # #![allow(unused_variables)]
 # extern crate juniper;
-# use juniper::FieldResult;
-# #[derive(juniper::GraphQLObject)] struct User { name: String }
+# use juniper::{graphql_object, FieldResult, GraphQLObject};
+# #[derive(GraphQLObject)] struct User { name: String }
 struct Root;
 
-#[juniper::graphql_object]
+#[graphql_object]
 impl Root {
     fn userWithUsername(username: String) -> FieldResult<Option<User>> {
         // Look up user in database...
-# unimplemented!()
+#       unimplemented!()
     }
 }
-
+#
 # fn main() { }
 ```
 
@@ -47,18 +47,18 @@ that performs some mutating side-effect such as updating a database.
 ```rust
 # #![allow(unused_variables)]
 # extern crate juniper;
-# use juniper::FieldResult;
-# #[derive(juniper::GraphQLObject)] struct User { name: String }
+# use juniper::{graphql_object, FieldResult, GraphQLObject};
+# #[derive(GraphQLObject)] struct User { name: String }
 struct Mutations;
 
-#[juniper::graphql_object]
+#[graphql_object]
 impl Mutations {
     fn signUpUser(name: String, email: String) -> FieldResult<User> {
         // Validate inputs and save user in database...
-# unimplemented!()
+#       unimplemented!()
     }
 }
-
+#
 # fn main() { }
 ```
 
@@ -68,11 +68,13 @@ Many tools in the GraphQL ecosystem require the schema to be defined in the [Gra
 
 ```rust
 # extern crate juniper;
-use juniper::{FieldResult, EmptyMutation, EmptySubscription, RootNode};
+use juniper::{
+    graphql_object, EmptyMutation, EmptySubscription, FieldResult, RootNode,
+};
 
 struct Query;
 
-#[juniper::graphql_object]
+#[graphql_object]
 impl Query {
     fn hello(&self) -> FieldResult<&str> {
         Ok("hello world")
diff --git a/docs/book/content/types/objects/complex_fields.md b/docs/book/content/types/objects/complex_fields.md
index 6abc6a047..75867184c 100644
--- a/docs/book/content/types/objects/complex_fields.md
+++ b/docs/book/content/types/objects/complex_fields.md
@@ -2,7 +2,7 @@
 
 If you've got a struct that can't be mapped directly to GraphQL, that contains
 computed fields or circular structures, you have to use a more powerful tool:
-the `object` procedural macro. This macro lets you define GraphQL object
+the `#[graphql_object]` procedural macro. This macro lets you define GraphQL object
 fields in a Rust `impl` block for a type. Note that only GraphQL fields
 can be specified in this `impl` block. If you want to define normal methods on the struct,
 you have to do so in a separate, normal `impl` block. Continuing with the
@@ -12,13 +12,14 @@ macro:
 ```rust
 # #![allow(dead_code)]
 # extern crate juniper;
+# use juniper::graphql_object;
 #
 struct Person {
     name: String,
     age: i32,
 }
 
-#[juniper::graphql_object]
+#[graphql_object]
 impl Person {
     fn name(&self) -> &str {
         self.name.as_str()
@@ -36,7 +37,7 @@ impl Person {
         // [...]
     }
 }
-
+#
 # fn main() { }
 ```
 
@@ -46,7 +47,9 @@ field resolver. With this syntax, fields can also take arguments:
 
 ```rust
 # extern crate juniper;
-#[derive(juniper::GraphQLObject)]
+# use juniper::{graphql_object, GraphQLObject};
+#
+#[derive(GraphQLObject)]
 struct Person {
     name: String,
     age: i32,
@@ -56,14 +59,14 @@ struct House {
     inhabitants: Vec<Person>,
 }
 
-#[juniper::graphql_object]
+#[graphql_object]
 impl House {
     // Creates the field inhabitantWithName(name), returning a nullable person
     fn inhabitant_with_name(&self, name: String) -> Option<&Person> {
         self.inhabitants.iter().find(|p| p.name == name)
     }
 }
-
+#
 # fn main() {}
 ```
 
@@ -79,20 +82,20 @@ the field. Also, the type name can be changed with an alias:
 
 ```rust
 # extern crate juniper;
-
-struct Person {
-}
+# use juniper::graphql_object;
+#
+struct Person;
 
 /// Doc comments are used as descriptions for GraphQL.
-#[juniper::graphql_object(
+#[graphql_object(
     // With this attribute you can change the public GraphQL name of the type.
     name = "PersonObject",
+
     // You can also specify a description here, which will overwrite 
     // a doc comment description.
     description = "...",
 )]
 impl Person {
-
     /// A doc comment on the field will also be used for GraphQL.
     #[graphql(
         // Or provide a description here.
@@ -103,9 +106,7 @@ impl Person {
     }
 
     // Fields can also be renamed if required.
-    #[graphql(
-        name = "myCustomFieldName",
-    )]
+    #[graphql(name = "myCustomFieldName")]
     fn renamed_field() -> bool {
         true
     }
@@ -122,7 +123,7 @@ impl Person {
         true
     }
 }
-
+#
 # fn main() { }
 ```
 
@@ -137,10 +138,11 @@ This will become better once the [Rust RFC 2565](https://github.com/rust-lang/ru
 
 ```rust
 # extern crate juniper;
-
+# use juniper::graphql_object;
+#
 struct Person {}
 
-#[juniper::graphql_object]
+#[graphql_object]
 impl Person {
     #[graphql(
         arguments(
@@ -160,7 +162,7 @@ impl Person {
         format!("{} {}", arg1, arg2)
     }
 }
-
+#
 # fn main() { }
 ```
 
@@ -172,5 +174,5 @@ GraphQL fields expose more features than Rust's standard method syntax gives us:
 * Per-argument default values
 * Per-argument descriptions
 
-These, and more features, are described more thorougly in [the reference
+These, and more features, are described more thoroughly in [the reference
 documentation](https://docs.rs/juniper/latest/juniper/macro.object.html).
diff --git a/docs/book/content/types/objects/defining_objects.md b/docs/book/content/types/objects/defining_objects.md
index b0c95dd29..1a4dcb7da 100644
--- a/docs/book/content/types/objects/defining_objects.md
+++ b/docs/book/content/types/objects/defining_objects.md
@@ -10,12 +10,13 @@ chapter.
 
 ```rust
 # extern crate juniper;
-#[derive(juniper::GraphQLObject)]
+# use juniper::GraphQLObject;
+#[derive(GraphQLObject)]
 struct Person {
     name: String,
     age: i32,
 }
-
+#
 # fn main() {}
 ```
 
@@ -33,7 +34,8 @@ descriptions:
 
 ```rust
 # extern crate juniper;
-#[derive(juniper::GraphQLObject)]
+# use juniper::GraphQLObject;
+#[derive(GraphQLObject)]
 /// Information about a person
 struct Person {
     /// The person's full name, including both first and last names
@@ -41,7 +43,7 @@ struct Person {
     /// The person's age in years, rounded down
     age: i32,
 }
-
+#
 # fn main() {}
 ```
 
@@ -52,15 +54,16 @@ via the `graphql` attribute. The following example is equivalent to the above:
 
 ```rust
 # extern crate juniper;
-#[derive(juniper::GraphQLObject)]
-#[graphql(description="Information about a person")]
+# use juniper::GraphQLObject;
+#[derive(GraphQLObject)]
+#[graphql(description = "Information about a person")]
 struct Person {
-    #[graphql(description="The person's full name, including both first and last names")]
+    #[graphql(description = "The person's full name, including both first and last names")]
     name: String,
-    #[graphql(description="The person's age in years, rounded down")]
+    #[graphql(description = "The person's age in years, rounded down")]
     age: i32,
 }
-
+#
 # fn main() {}
 ```
 
@@ -70,17 +73,18 @@ documentation to differ:
 
 ```rust
 # extern crate juniper;
-#[derive(juniper::GraphQLObject)]
-#[graphql(description="This description shows up in GraphQL")]
+# use juniper::GraphQLObject;
+#[derive(GraphQLObject)]
+#[graphql(description = "This description shows up in GraphQL")]
 /// This description shows up in RustDoc
 struct Person {
-    #[graphql(description="This description shows up in GraphQL")]
+    #[graphql(description = "This description shows up in GraphQL")]
     /// This description shows up in RustDoc
     name: String,
     /// This description shows up in both RustDoc and GraphQL
     age: i32,
 }
-
+#
 # fn main() {}
 ```
 
@@ -100,18 +104,19 @@ Let's see what that means for building relationships between objects:
 
 ```rust
 # extern crate juniper;
-#[derive(juniper::GraphQLObject)]
+# use juniper::GraphQLObject;
+#[derive(GraphQLObject)]
 struct Person {
     name: String,
     age: i32,
 }
 
-#[derive(juniper::GraphQLObject)]
+#[derive(GraphQLObject)]
 struct House {
     address: Option<String>, // Converted into String (nullable)
     inhabitants: Vec<Person>, // Converted into [Person!]!
 }
-
+#
 # fn main() {}
 ```
 
@@ -126,12 +131,13 @@ convention into GraphQL's `camelCase` convention:
 
 ```rust
 # extern crate juniper;
-#[derive(juniper::GraphQLObject)]
+# use juniper::GraphQLObject;
+#[derive(GraphQLObject)]
 struct Person {
     first_name: String, // Would be exposed as firstName in the GraphQL schema
     last_name: String, // Exposed as lastName
 }
-
+#
 # fn main() {}
 ```
 
@@ -140,14 +146,15 @@ fields:
 
 ```rust
 # extern crate juniper;
-#[derive(juniper::GraphQLObject)]
+# use juniper::GraphQLObject;
+#[derive(GraphQLObject)]
 struct Person {
     name: String,
     age: i32,
-    #[graphql(name="websiteURL")]
+    #[graphql(name = "websiteURL")]
     website_url: Option<String>, // Now exposed as websiteURL in the schema
 }
-
+#
 # fn main() {}
 ```
 
@@ -158,14 +165,15 @@ attribute:
 
 ```rust
 # extern crate juniper;
-#[derive(juniper::GraphQLObject)]
+# use juniper::GraphQLObject;
+#[derive(GraphQLObject)]
 struct Person {
     name: String,
     age: i32,
     #[graphql(deprecated = "Please use the name field instead")]
     first_name: String,
 }
-
+#
 # fn main() {}
 ```
 
@@ -179,7 +187,8 @@ By default all fields in a `GraphQLObject` are included in the generated GraphQL
 
 ```rust
 # extern crate juniper;
-#[derive(juniper::GraphQLObject)]
+# use juniper::GraphQLObject;
+#[derive(GraphQLObject)]
 struct Person {
     name: String,
     age: i32,
@@ -187,6 +196,6 @@ struct Person {
     # #[allow(dead_code)]
     password_hash: String, // This cannot be queried or modified from GraphQL
 }
-
+#
 # fn main() {}
 ```
diff --git a/docs/book/content/types/objects/error_handling.md b/docs/book/content/types/objects/error_handling.md
index 247b07e3a..ea64e7642 100644
--- a/docs/book/content/types/objects/error_handling.md
+++ b/docs/book/content/types/objects/error_handling.md
@@ -28,13 +28,13 @@ use std::{
     fs::{File},
     io::{Read},
 };
-use juniper::FieldResult;
+use juniper::{graphql_object, FieldResult};
 
 struct Example {
     filename: PathBuf,
 }
 
-#[juniper::graphql_object]
+#[graphql_object]
 impl Example {
     fn contents() -> FieldResult<String> {
         let mut file = File::open(&self.filename)?;
@@ -53,7 +53,7 @@ impl Example {
       }
     }
 }
-
+#
 # fn main() {}
 ```
 
@@ -137,14 +137,16 @@ to clients. This can be accomplished by implementing [`IntoFieldError`](https://
 
 ```rust
 # #[macro_use] extern crate juniper;
+# use juniper::{graphql_object, FieldError, IntoFieldError, ScalarValue};
+#
 enum CustomError {
     WhateverNotSet,
 }
 
-impl juniper::IntoFieldError for CustomError {
-    fn into_field_error(self) -> juniper::FieldError {
+impl<S: ScalarValue> IntoFieldError<S> for CustomError {
+    fn into_field_error(self) -> FieldError<S> {
         match self {
-            CustomError::WhateverNotSet => juniper::FieldError::new(
+            CustomError::WhateverNotSet => FieldError::new(
                 "Whatever does not exist",
                 graphql_value!({
                     "type": "NO_WHATEVER"
@@ -158,7 +160,7 @@ struct Example {
     whatever: Option<bool>,
 }
 
-#[juniper::graphql_object]
+#[graphql_object]
 impl Example {
     fn whatever() -> Result<bool, CustomError> {
       if let Some(value) = self.whatever {
@@ -167,21 +169,21 @@ impl Example {
       Err(CustomError::WhateverNotSet)
     }
 }
-
+#
 # fn main() {}
 ```
 
 The specified structured error information is included in the [`extensions`](https://facebook.github.io/graphql/June2018/#sec-Errors) key:
 
-```js
+```json
 {
-  "errors": [
+  "errors": [{
     "message": "Whatever does not exist",
-    "locations": [{ "line": 2, "column": 4 }]),
+    "locations": [{"line": 2, "column": 4}],
     "extensions": {
       "type": "NO_WHATEVER"
     }
-  ]
+  }]
 }
 ```
 
@@ -211,24 +213,26 @@ possible to return a unique string identifier and have the client present a loca
 
 ```rust
 # extern crate juniper;
-#[derive(juniper::GraphQLObject)]
+# use juniper::{graphql_object, GraphQLObject, GraphQLUnion};
+#
+#[derive(GraphQLObject)]
 pub struct Item {
     name: String,
     quantity: i32,
 }
 
-#[derive(juniper::GraphQLObject)]
+#[derive(GraphQLObject)]
 pub struct ValidationError {
     field: String,
     message: String,
 }
 
-#[derive(juniper::GraphQLObject)]
+#[derive(GraphQLObject)]
 pub struct ValidationErrors {
     errors: Vec<ValidationError>,
 }
 
-#[derive(juniper::GraphQLUnion)]
+#[derive(GraphQLUnion)]
 pub enum GraphQLResult {
     Ok(Item),
     Err(ValidationErrors),
@@ -236,7 +240,7 @@ pub enum GraphQLResult {
 
 pub struct Mutation;
 
-#[juniper::graphql_object]
+#[graphql_object]
 impl Mutation {
     fn addItem(&self, name: String, quantity: i32) -> GraphQLResult {
         let mut errors = Vec::new();
@@ -262,7 +266,7 @@ impl Mutation {
         }
     }
 }
-
+#
 # fn main() {}
 ```
 
@@ -308,19 +312,21 @@ contains only fields provided by the function.
 
 ```rust
 # extern crate juniper;
-#[derive(juniper::GraphQLObject)]
+# use juniper::{graphql_object, GraphQLObject, GraphQLUnion};
+#
+#[derive(GraphQLObject)]
 pub struct Item {
     name: String,
     quantity: i32,
 }
 
-#[derive(juniper::GraphQLObject)]
+#[derive(GraphQLObject)]
 pub struct ValidationError {
     name: Option<String>,
     quantity: Option<String>,
 }
 
-#[derive(juniper::GraphQLUnion)]
+#[derive(GraphQLUnion)]
 pub enum GraphQLResult {
     Ok(Item),
     Err(ValidationError),
@@ -328,7 +334,7 @@ pub enum GraphQLResult {
 
 pub struct Mutation;
 
-#[juniper::graphql_object]
+#[graphql_object]
 impl Mutation {
     fn addItem(&self, name: String, quantity: i32) -> GraphQLResult {
         let mut error = ValidationError {
@@ -351,7 +357,7 @@ impl Mutation {
         }
     }
 }
-
+#
 # fn main() {}
 ```
 
@@ -385,22 +391,23 @@ and would generate errors. Since it is not common for the database to
 fail, the corresponding error is returned as a critical error:
 
 ```rust
-# // Only needed due to 2018 edition because the macro is not accessible.
-# #[macro_use] extern crate juniper;
+# extern crate juniper;
+#
+use juniper::{graphql_object, graphql_value, FieldError, GraphQLObject, GraphQLUnion, ScalarValue};
 
-#[derive(juniper::GraphQLObject)]
+#[derive(GraphQLObject)]
 pub struct Item {
     name: String,
     quantity: i32,
 }
 
-#[derive(juniper::GraphQLObject)]
+#[derive(GraphQLObject)]
 pub struct ValidationErrorItem {
     name: Option<String>,
     quantity: Option<String>,
 }
 
-#[derive(juniper::GraphQLUnion)]
+#[derive(GraphQLUnion)]
 pub enum GraphQLResult {
     Ok(Item),
     Err(ValidationErrorItem),
@@ -410,10 +417,10 @@ pub enum ApiError {
     Database,
 }
 
-impl juniper::IntoFieldError for ApiError {
-    fn into_field_error(self) -> juniper::FieldError {
+impl<S: ScalarValue> juniper::IntoFieldError<S> for ApiError {
+    fn into_field_error(self) -> FieldError<S> {
         match self {
-            ApiError::Database => juniper::FieldError::new(
+            ApiError::Database => FieldError::new(
                 "Internal database error",
                 graphql_value!({
                     "type": "DATABASE"
@@ -425,7 +432,7 @@ impl juniper::IntoFieldError for ApiError {
 
 pub struct Mutation;
 
-#[juniper::graphql_object]
+#[graphql_object]
 impl Mutation {
     fn addItem(&self, name: String, quantity: i32) -> Result<GraphQLResult, ApiError> {
         let mut error = ValidationErrorItem {
@@ -448,7 +455,7 @@ impl Mutation {
         }
     }
 }
-
+#
 # fn main() {}
 ```
 
diff --git a/docs/book/content/types/objects/using_contexts.md b/docs/book/content/types/objects/using_contexts.md
index 1233ec5bf..0576a6644 100644
--- a/docs/book/content/types/objects/using_contexts.md
+++ b/docs/book/content/types/objects/using_contexts.md
@@ -13,7 +13,7 @@ resolvers. Let's say that we have a simple user database in a `HashMap`:
 ```rust
 # #![allow(dead_code)]
 # use std::collections::HashMap;
-
+#
 struct Database {
     users: HashMap<i32, User>,
 }
@@ -23,7 +23,7 @@ struct User {
     name: String,
     friend_ids: Vec<i32>,
 }
-
+#
 # fn main() { }
 ```
 
@@ -38,9 +38,10 @@ type as the specified `Context` for the type:
 
 
 ```rust
+# extern crate juniper;
 # use std::collections::HashMap;
-extern crate juniper;
-
+# use juniper::graphql_object;
+#
 // This struct represents our context.
 struct Database {
     users: HashMap<i32, User>,
@@ -55,11 +56,8 @@ struct User {
     friend_ids: Vec<i32>,
 }
 
-
 // Assign Database as the context type for User
-#[juniper::graphql_object(
-    Context = Database,
-)]
+#[graphql_object(context = Database)]
 impl User {
     // 3. Inject the context by specifying an argument
     //    with the context type.
@@ -82,7 +80,7 @@ impl User {
         self.id 
     }
 }
-
+#
 # fn main() { }
 ```
 
diff --git a/examples/actix_subscriptions/src/main.rs b/examples/actix_subscriptions/src/main.rs
index 08a78651d..0061c023c 100644
--- a/examples/actix_subscriptions/src/main.rs
+++ b/examples/actix_subscriptions/src/main.rs
@@ -4,6 +4,7 @@ use actix_cors::Cors;
 use actix_web::{middleware, web, App, Error, HttpRequest, HttpResponse, HttpServer};
 
 use juniper::{
+    graphql_object, graphql_subscription,
     tests::fixtures::starwars::schema::{Character as _, Database, Query},
     DefaultScalarValue, EmptyMutation, FieldError, RootNode,
 };
@@ -37,7 +38,7 @@ struct RandomHuman {
 }
 
 // TODO: remove this when async interfaces are merged
-#[juniper::graphql_object(Context = Database)]
+#[graphql_object(context = Database)]
 impl RandomHuman {
     fn id(&self) -> &str {
         &self.id
@@ -51,7 +52,7 @@ impl RandomHuman {
 type RandomHumanStream =
     Pin<Box<dyn futures::Stream<Item = Result<RandomHuman, FieldError>> + Send>>;
 
-#[juniper::graphql_subscription(Context = Database)]
+#[graphql_subscription(context = Database)]
 impl Subscription {
     #[graphql(
         description = "A random humanoid creature in the Star Wars universe every 3 seconds. Second result will be an error."
diff --git a/examples/basic_subscriptions/src/main.rs b/examples/basic_subscriptions/src/main.rs
index a5d463e19..819fe5354 100644
--- a/examples/basic_subscriptions/src/main.rs
+++ b/examples/basic_subscriptions/src/main.rs
@@ -4,8 +4,8 @@ use std::pin::Pin;
 
 use futures::{Stream, StreamExt};
 use juniper::{
-    http::GraphQLRequest, DefaultScalarValue, EmptyMutation, FieldError, RootNode,
-    SubscriptionCoordinator,
+    graphql_object, graphql_subscription, http::GraphQLRequest, DefaultScalarValue, EmptyMutation,
+    FieldError, RootNode, SubscriptionCoordinator,
 };
 use juniper_subscriptions::Coordinator;
 
@@ -22,7 +22,7 @@ impl Database {
 
 pub struct Query;
 
-#[juniper::graphql_object(Context = Database)]
+#[graphql_object(context = Database)]
 impl Query {
     fn hello_world() -> &str {
         "Hello World!"
@@ -33,7 +33,7 @@ pub struct Subscription;
 
 type StringStream = Pin<Box<dyn Stream<Item = Result<String, FieldError>> + Send>>;
 
-#[juniper::graphql_subscription(Context = Database)]
+#[graphql_subscription(context = Database)]
 impl Subscription {
     async fn hello_world() -> StringStream {
         let stream =
diff --git a/examples/warp_async/src/main.rs b/examples/warp_async/src/main.rs
index 95a1671a6..7f1b902f8 100644
--- a/examples/warp_async/src/main.rs
+++ b/examples/warp_async/src/main.rs
@@ -23,7 +23,7 @@ struct User {
     name: String,
 }
 
-#[graphql_object(Context = Context)]
+#[graphql_object(context = Context)]
 impl User {
     fn id(&self) -> i32 {
         self.id
@@ -45,7 +45,7 @@ impl User {
 #[derive(Clone, Copy, Debug)]
 struct Query;
 
-#[graphql_object(Context = Context)]
+#[graphql_object(context = Context)]
 impl Query {
     async fn users() -> Vec<User> {
         vec![User {
diff --git a/examples/warp_subscriptions/src/main.rs b/examples/warp_subscriptions/src/main.rs
index 0d4f31a67..369a14b91 100644
--- a/examples/warp_subscriptions/src/main.rs
+++ b/examples/warp_subscriptions/src/main.rs
@@ -3,7 +3,10 @@
 use std::{env, pin::Pin, sync::Arc, time::Duration};
 
 use futures::{FutureExt as _, Stream};
-use juniper::{DefaultScalarValue, EmptyMutation, FieldError, RootNode};
+use juniper::{
+    graphql_object, graphql_subscription, DefaultScalarValue, EmptyMutation, FieldError,
+    GraphQLEnum, RootNode,
+};
 use juniper_graphql_ws::ConnectionConfig;
 use juniper_warp::{playground_filter, subscriptions::serve_graphql_ws};
 use warp::{http::Response, Filter};
@@ -13,7 +16,7 @@ struct Context {}
 
 impl juniper::Context for Context {}
 
-#[derive(Clone, Copy, juniper::GraphQLEnum)]
+#[derive(Clone, Copy, GraphQLEnum)]
 enum UserKind {
     Admin,
     User,
@@ -27,7 +30,7 @@ struct User {
 }
 
 // Field resolvers implementation
-#[juniper::graphql_object(Context = Context)]
+#[graphql_object(context = Context)]
 impl User {
     fn id(&self) -> i32 {
         self.id
@@ -87,7 +90,7 @@ impl User {
 
 struct Query;
 
-#[juniper::graphql_object(Context = Context)]
+#[graphql_object(context = Context)]
 impl Query {
     async fn users(id: i32) -> Vec<User> {
         vec![User {
@@ -102,7 +105,7 @@ type UsersStream = Pin<Box<dyn Stream<Item = Result<User, FieldError>> + Send>>;
 
 struct Subscription;
 
-#[juniper::graphql_subscription(Context = Context)]
+#[graphql_subscription(context = Context)]
 impl Subscription {
     async fn users() -> UsersStream {
         let mut counter = 0;
diff --git a/juniper/CHANGELOG.md b/juniper/CHANGELOG.md
index 25cf215b9..df66705ee 100644
--- a/juniper/CHANGELOG.md
+++ b/juniper/CHANGELOG.md
@@ -32,11 +32,10 @@
   - `LexerError`
   - `ParseError`
   - `RuleError`
-  
+
 - Support `chrono-tz::Tz` scalar behind a `chrono-tz` feature flag. ([#519](https://github.com/graphql-rust/juniper/pull/519))
 
 - Added support for distinguishing between between implicit and explicit null. ([#795](https://github.com/graphql-rust/juniper/pull/795))
-  
 
 - Implement `IntoFieldError` for `std::convert::Infallible`. ([#796](https://github.com/graphql-rust/juniper/pull/796))
 
@@ -76,7 +75,7 @@
   ```rust
     #[graphql(arguments(argA(name = "test")))]
   ```
-  
+
 - `SchemaType` is now public.
   - This is helpful when using `context.getSchema()` inside of your field resolvers.
 
@@ -94,9 +93,10 @@
 
 - `juniper::graphiql` has moved to `juniper::http::graphiql`.
   - `juniper::http::graphiql::graphiql_source()` now requires a second parameter for subscriptions.
-  
+
 - Renamed the `object` proc macro to `graphql_object`.
 - Removed the `graphql_object!` macro. Use the `#[graphql_object]` proc macro instead.
+- Made `#[graphql_object]` macro to generate code generic over `ScalarValue` by default. ([#779](https://github.com/graphql-rust/juniper/pull/779))
 
 - Renamed the `scalar` proc macro to `graphql_scalar`.
 - Removed the `graphql_scalar!` macro. Use the `#[graphql_scalar]` proc macro instead.
@@ -117,7 +117,7 @@
 - The return type of `GraphQLType::resolve()` has been changed to `ExecutionResult`.
   - This was done to unify the return type of all resolver methods. The previous `Value` return type was just an internal artifact of 
   error handling.
-  
+
 - Subscription-related: 
   - Add subscription type to `RootNode`.
   - Add subscription endpoint to `playground_source()`.
@@ -130,6 +130,8 @@
   - Renamed `http::tests::HTTPIntegration` as `http::tests::HttpIntegration`.
   - Added support for `application/graphql` POST request.
 
+- `RootNode::new()` now returns `RootNode` parametrized with `DefaultScalarValue`. For custom `ScalarValue` use `RootNode::new_with_scalar_value()` instead. ([#779](https://github.com/graphql-rust/juniper/pull/779))
+
 - When using `LookAheadMethods` to access child selections, children are always found using their alias if it exists rather than their name. ([#662](https://github.com/graphql-rust/juniper/pull/662))
   - These methods are also deprecated in favor of the new `LookAheadMethods::children()` method.
 
diff --git a/juniper/src/executor/mod.rs b/juniper/src/executor/mod.rs
index 9a4588fa3..527e5540f 100644
--- a/juniper/src/executor/mod.rs
+++ b/juniper/src/executor/mod.rs
@@ -216,6 +216,18 @@ impl<S> FieldError<S> {
     pub fn extensions(&self) -> &Value<S> {
         &self.extensions
     }
+
+    /// Maps the [`ScalarValue`] type of this [`FieldError`] into the specified one.
+    pub fn map_scalar_value<Into>(self) -> FieldError<Into>
+    where
+        S: ScalarValue,
+        Into: ScalarValue,
+    {
+        FieldError {
+            message: self.message,
+            extensions: self.extensions.map_scalar_value(),
+        }
+    }
 }
 
 /// The result of resolving the value of a field of type `T`
@@ -240,9 +252,10 @@ pub trait IntoFieldError<S = DefaultScalarValue> {
     fn into_field_error(self) -> FieldError<S>;
 }
 
-impl<S> IntoFieldError<S> for FieldError<S> {
-    fn into_field_error(self) -> FieldError<S> {
-        self
+impl<S1: ScalarValue, S2: ScalarValue> IntoFieldError<S2> for FieldError<S1> {
+    #[inline]
+    fn into_field_error(self) -> FieldError<S2> {
+        self.map_scalar_value()
     }
 }
 
@@ -315,28 +328,31 @@ where
     }
 }
 
-impl<'a, S, T, C> IntoResolvable<'a, S, T, C> for FieldResult<(&'a T::Context, T), S>
+impl<'a, S1, S2, T, C> IntoResolvable<'a, S2, T, C> for FieldResult<(&'a T::Context, T), S1>
 where
-    S: ScalarValue,
-    T: GraphQLValue<S>,
+    S1: ScalarValue,
+    S2: ScalarValue,
+    T: GraphQLValue<S2>,
 {
     type Type = T;
 
-    fn into(self, _: &'a C) -> FieldResult<Option<(&'a T::Context, T)>, S> {
-        self.map(Some)
+    fn into(self, _: &'a C) -> FieldResult<Option<(&'a T::Context, T)>, S2> {
+        self.map(Some).map_err(FieldError::map_scalar_value)
     }
 }
 
-impl<'a, S, T, C> IntoResolvable<'a, S, Option<T>, C>
-    for FieldResult<Option<(&'a T::Context, T)>, S>
+impl<'a, S1, S2, T, C> IntoResolvable<'a, S2, Option<T>, C>
+    for FieldResult<Option<(&'a T::Context, T)>, S1>
 where
-    S: ScalarValue,
-    T: GraphQLValue<S>,
+    S1: ScalarValue,
+    S2: ScalarValue,
+    T: GraphQLValue<S2>,
 {
     type Type = T;
 
-    fn into(self, _: &'a C) -> FieldResult<Option<(&'a T::Context, Option<T>)>, S> {
+    fn into(self, _: &'a C) -> FieldResult<Option<(&'a T::Context, Option<T>)>, S2> {
         self.map(|o| o.map(|(ctx, v)| (ctx, Some(v))))
+            .map_err(FieldError::map_scalar_value)
     }
 }
 
diff --git a/juniper/src/macros/helper/subscription.rs b/juniper/src/macros/helper/subscription.rs
index 9d533185a..88d1cb40f 100644
--- a/juniper/src/macros/helper/subscription.rs
+++ b/juniper/src/macros/helper/subscription.rs
@@ -5,7 +5,7 @@
 
 use futures::Stream;
 
-use crate::{FieldError, GraphQLValue, ScalarValue};
+use crate::{FieldError, GraphQLValue, IntoFieldError, ScalarValue};
 
 /// Trait for wrapping [`Stream`] into [`Ok`] if it's not [`Result`].
 ///
@@ -22,12 +22,12 @@ pub trait IntoFieldResult<T, S> {
 impl<T, E, S> IntoFieldResult<T, S> for Result<T, E>
 where
     T: IntoFieldResult<T, S>,
-    E: Into<FieldError<S>>,
+    E: IntoFieldError<S>,
 {
     type Item = T::Item;
 
     fn into_result(self) -> Result<T, FieldError<S>> {
-        self.map_err(|e| e.into())
+        self.map_err(E::into_field_error)
     }
 }
 
diff --git a/juniper/src/schema/model.rs b/juniper/src/schema/model.rs
index 2d6bf691f..7be0c6161 100644
--- a/juniper/src/schema/model.rs
+++ b/juniper/src/schema/model.rs
@@ -88,6 +88,20 @@ pub enum DirectiveLocation {
     InlineFragment,
 }
 
+impl<'a, QueryT, MutationT, SubscriptionT>
+    RootNode<'a, QueryT, MutationT, SubscriptionT, DefaultScalarValue>
+where
+    QueryT: GraphQLType<DefaultScalarValue, TypeInfo = ()>,
+    MutationT: GraphQLType<DefaultScalarValue, TypeInfo = ()>,
+    SubscriptionT: GraphQLType<DefaultScalarValue, TypeInfo = ()>,
+{
+    /// Constructs a new [`RootNode`] from `query`, `mutation` and `subscription` nodes,
+    /// parametrizing it with a [`DefaultScalarValue`].
+    pub fn new(query: QueryT, mutation: MutationT, subscription: SubscriptionT) -> Self {
+        Self::new_with_info(query, mutation, subscription, (), (), ())
+    }
+}
+
 impl<'a, QueryT, MutationT, SubscriptionT, S> RootNode<'a, QueryT, MutationT, SubscriptionT, S>
 where
     S: ScalarValue + 'a,
@@ -95,16 +109,14 @@ where
     MutationT: GraphQLType<S, TypeInfo = ()>,
     SubscriptionT: GraphQLType<S, TypeInfo = ()>,
 {
-    /// Construct a new root node from query, mutation, and subscription nodes
-    ///
-    /// If the schema should not support mutations, use the
-    /// `new` constructor instead.
-    pub fn new(
-        query_obj: QueryT,
-        mutation_obj: MutationT,
-        subscription_obj: SubscriptionT,
+    /// Constructs a new [`RootNode`] from `query`, `mutation` and `subscription` nodes,
+    /// parametrizing it with the provided [`ScalarValue`].
+    pub fn new_with_scalar_value(
+        query: QueryT,
+        mutation: MutationT,
+        subscription: SubscriptionT,
     ) -> Self {
-        RootNode::new_with_info(query_obj, mutation_obj, subscription_obj, (), (), ())
+        RootNode::new_with_info(query, mutation, subscription, (), (), ())
     }
 
     #[cfg(feature = "schema-language")]
@@ -560,19 +572,18 @@ mod test {
 
     #[cfg(feature = "graphql-parser-integration")]
     mod graphql_parser_integration {
-        use crate as juniper;
-        use crate::{EmptyMutation, EmptySubscription};
+        use crate::{graphql_object, EmptyMutation, EmptySubscription, RootNode};
 
         #[test]
         fn graphql_parser_doc() {
             struct Query;
-            #[juniper::graphql_object]
+            #[graphql_object]
             impl Query {
                 fn blah() -> bool {
                     true
                 }
             };
-            let schema = crate::RootNode::new(
+            let schema = RootNode::new(
                 Query,
                 EmptyMutation::<()>::new(),
                 EmptySubscription::<()>::new(),
@@ -598,10 +609,9 @@ mod test {
 
     #[cfg(feature = "schema-language")]
     mod schema_language {
-        use crate as juniper;
         use crate::{
-            EmptyMutation, EmptySubscription, GraphQLEnum, GraphQLInputObject, GraphQLObject,
-            GraphQLUnion,
+            graphql_object, EmptyMutation, EmptySubscription, GraphQLEnum, GraphQLInputObject,
+            GraphQLObject, GraphQLUnion, RootNode,
         };
 
         #[test]
@@ -630,7 +640,7 @@ mod test {
                 longitude: f64,
             }
             struct Query;
-            #[juniper::graphql_object]
+            #[graphql_object]
             impl Query {
                 fn blah() -> bool {
                     true
@@ -666,7 +676,7 @@ mod test {
                 }
             };
 
-            let schema = crate::RootNode::new(
+            let schema = RootNode::new(
                 Query,
                 EmptyMutation::<()>::new(),
                 EmptySubscription::<()>::new(),
diff --git a/juniper/src/value/mod.rs b/juniper/src/value/mod.rs
index 7f729a833..eb6b62597 100644
--- a/juniper/src/value/mod.rs
+++ b/juniper/src/value/mod.rs
@@ -1,14 +1,21 @@
+mod object;
+mod scalar;
+
+use std::{
+    any::TypeId,
+    fmt::{self, Display, Formatter},
+    mem,
+};
+
 use crate::{
     ast::{InputValue, ToInputValue},
     parser::Spanning,
 };
-use std::fmt::{self, Display, Formatter};
-mod object;
-mod scalar;
-
-pub use self::object::Object;
 
-pub use self::scalar::{DefaultScalarValue, ParseScalarResult, ParseScalarValue, ScalarValue};
+pub use self::{
+    object::Object,
+    scalar::{DefaultScalarValue, ParseScalarResult, ParseScalarValue, ScalarValue},
+};
 
 /// Serializable value returned from query and field execution.
 ///
@@ -28,15 +35,12 @@ pub enum Value<S = DefaultScalarValue> {
     Object(Object<S>),
 }
 
-impl<S> Value<S>
-where
-    S: ScalarValue,
-{
+impl<S: ScalarValue> Value<S> {
     // CONSTRUCTORS
 
     /// Construct a null value.
     pub fn null() -> Self {
-        Value::Null
+        Self::Null
     }
 
     /// Construct an integer value.
@@ -65,12 +69,12 @@ where
 
     /// Construct a list value.
     pub fn list(l: Vec<Self>) -> Self {
-        Value::List(l)
+        Self::List(l)
     }
 
     /// Construct an object value.
     pub fn object(o: Object<S>) -> Self {
-        Value::Object(o)
+        Self::Object(o)
     }
 
     /// Construct a scalar value
@@ -78,7 +82,7 @@ where
     where
         T: Into<S>,
     {
-        Value::Scalar(s.into())
+        Self::Scalar(s.into())
     }
 
     // DISCRIMINATORS
@@ -86,7 +90,7 @@ where
     /// Does this value represent null?
     pub fn is_null(&self) -> bool {
         match *self {
-            Value::Null => true,
+            Self::Null => true,
             _ => false,
         }
     }
@@ -97,16 +101,15 @@ where
         &'a S: Into<Option<&'a T>>,
     {
         match *self {
-            Value::Scalar(ref s) => s.into(),
+            Self::Scalar(ref s) => s.into(),
             _ => None,
         }
     }
 
     /// View the underlying float value, if present.
-    pub fn as_float_value(&self) -> Option<f64>
-where {
+    pub fn as_float_value(&self) -> Option<f64> {
         match self {
-            Value::Scalar(ref s) => s.as_float(),
+            Self::Scalar(ref s) => s.as_float(),
             _ => None,
         }
     }
@@ -114,7 +117,7 @@ where {
     /// View the underlying object value, if present.
     pub fn as_object_value(&self) -> Option<&Object<S>> {
         match *self {
-            Value::Object(ref o) => Some(o),
+            Self::Object(ref o) => Some(o),
             _ => None,
         }
     }
@@ -124,7 +127,7 @@ where {
     /// Returns None if value is not an Object.
     pub fn into_object(self) -> Option<Object<S>> {
         match self {
-            Value::Object(o) => Some(o),
+            Self::Object(o) => Some(o),
             _ => None,
         }
     }
@@ -132,7 +135,7 @@ where {
     /// Mutable view into the underlying object value, if present.
     pub fn as_mut_object_value(&mut self) -> Option<&mut Object<S>> {
         match *self {
-            Value::Object(ref mut o) => Some(o),
+            Self::Object(ref mut o) => Some(o),
             _ => None,
         }
     }
@@ -140,7 +143,7 @@ where {
     /// View the underlying list value, if present.
     pub fn as_list_value(&self) -> Option<&Vec<Self>> {
         match *self {
-            Value::List(ref l) => Some(l),
+            Self::List(ref l) => Some(l),
             _ => None,
         }
     }
@@ -148,7 +151,7 @@ where {
     /// View the underlying scalar value, if present
     pub fn as_scalar(&self) -> Option<&S> {
         match *self {
-            Value::Scalar(ref s) => Some(s),
+            Self::Scalar(ref s) => Some(s),
             _ => None,
         }
     }
@@ -160,6 +163,27 @@ where {
     {
         self.as_scalar_value::<String>().map(|s| s as &str)
     }
+
+    /// Maps the [`ScalarValue`] type of this [`Value`] into the specified one.
+    pub fn map_scalar_value<Into: ScalarValue>(self) -> Value<Into> {
+        if TypeId::of::<Into>() == TypeId::of::<S>() {
+            // This is totally safe, because we're transmuting the value into itself,
+            // so no invariants may change and we're just satisfying the type checker.
+            let val = mem::ManuallyDrop::new(self);
+            unsafe { mem::transmute_copy(&*val) }
+        } else {
+            match self {
+                Self::Null => Value::Null,
+                Self::Scalar(s) => Value::Scalar(s.into_another()),
+                Self::List(l) => Value::List(l.into_iter().map(Value::map_scalar_value).collect()),
+                Self::Object(o) => Value::Object(
+                    o.into_iter()
+                        .map(|(k, v)| (k, v.map_scalar_value()))
+                        .collect(),
+                ),
+            }
+        }
+    }
 }
 
 impl<S: ScalarValue> ToInputValue<S> for Value<S> {
diff --git a/juniper/src/value/scalar.rs b/juniper/src/value/scalar.rs
index 84643e078..397860e18 100644
--- a/juniper/src/value/scalar.rs
+++ b/juniper/src/value/scalar.rs
@@ -53,36 +53,43 @@ pub trait ParseScalarValue<S = DefaultScalarValue> {
 ///
 ///      fn as_int(&self) -> Option<i32> {
 ///        match *self {
-///            MyScalarValue::Int(ref i) => Some(*i),
+///            Self::Int(ref i) => Some(*i),
 ///            _ => None,
 ///        }
 ///    }
 ///
 ///    fn as_string(&self) -> Option<String> {
 ///        match *self {
-///            MyScalarValue::String(ref s) => Some(s.clone()),
+///            Self::String(ref s) => Some(s.clone()),
+///            _ => None,
+///        }
+///    }
+///
+///    fn into_string(self) -> Option<String> {
+///        match self {
+///            Self::String(s) => Some(s),
 ///            _ => None,
 ///        }
 ///    }
 ///
 ///    fn as_str(&self) -> Option<&str> {
 ///        match *self {
-///            MyScalarValue::String(ref s) => Some(s.as_str()),
+///            Self::String(ref s) => Some(s.as_str()),
 ///            _ => None,
 ///        }
 ///    }
 ///
 ///    fn as_float(&self) -> Option<f64> {
 ///        match *self {
-///            MyScalarValue::Int(ref i) => Some(*i as f64),
-///            MyScalarValue::Float(ref f) => Some(*f),
+///            Self::Int(ref i) => Some(*i as f64),
+///            Self::Float(ref f) => Some(*f),
 ///            _ => None,
 ///        }
 ///    }
 ///
 ///    fn as_boolean(&self) -> Option<bool> {
 ///        match *self {
-///            MyScalarValue::Boolean(ref b) => Some(*b),
+///            Self::Boolean(ref b) => Some(*b),
 ///            _ => None,
 ///        }
 ///    }
@@ -175,6 +182,7 @@ pub trait ScalarValue:
     + From<bool>
     + From<i32>
     + From<f64>
+    + 'static
 {
     /// Serde visitor used to deserialize this scalar value
     type Visitor: for<'de> de::Visitor<'de, Value = Self> + Default;
@@ -205,12 +213,18 @@ pub trait ScalarValue:
     /// types with 32 bit or less to an integer if requested.
     fn as_int(&self) -> Option<i32>;
 
-    /// Convert the given scalar value into a string value
+    /// Represents this [`ScalarValue`] a [`String`] value.
     ///
     /// This function is used for implementing `GraphQLValue` for `String` for all
     /// scalar values
     fn as_string(&self) -> Option<String>;
 
+    /// Converts this [`ScalarValue`] into a [`String`] value.
+    ///
+    /// Same as [`ScalarValue::as_string`], but takes ownership, so allows to omit redundant
+    /// cloning.
+    fn into_string(self) -> Option<String>;
+
     /// Convert the given scalar value into a string value
     ///
     /// This function is used for implementing `GraphQLValue` for `String` for all
@@ -230,6 +244,21 @@ pub trait ScalarValue:
     /// This function is used for implementing `GraphQLValue` for `bool` for all
     /// scalar values.
     fn as_boolean(&self) -> Option<bool>;
+
+    /// Converts this [`ScalarValue`] into another one.
+    fn into_another<S: ScalarValue>(self) -> S {
+        if let Some(i) = self.as_int() {
+            S::from(i)
+        } else if let Some(f) = self.as_float() {
+            S::from(f)
+        } else if let Some(b) = self.as_boolean() {
+            S::from(b)
+        } else if let Some(s) = self.into_string() {
+            S::from(s)
+        } else {
+            unreachable!("`ScalarValue` must represent at least one of the GraphQL spec types")
+        }
+    }
 }
 
 /// The default scalar value representation in juniper
@@ -249,44 +278,60 @@ impl ScalarValue for DefaultScalarValue {
 
     fn as_int(&self) -> Option<i32> {
         match *self {
-            DefaultScalarValue::Int(ref i) => Some(*i),
+            Self::Int(ref i) => Some(*i),
             _ => None,
         }
     }
 
     fn as_float(&self) -> Option<f64> {
         match *self {
-            DefaultScalarValue::Int(ref i) => Some(*i as f64),
-            DefaultScalarValue::Float(ref f) => Some(*f),
+            Self::Int(ref i) => Some(*i as f64),
+            Self::Float(ref f) => Some(*f),
             _ => None,
         }
     }
 
     fn as_str(&self) -> Option<&str> {
         match *self {
-            DefaultScalarValue::String(ref s) => Some(s.as_str()),
+            Self::String(ref s) => Some(s.as_str()),
             _ => None,
         }
     }
 
     fn as_string(&self) -> Option<String> {
         match *self {
-            DefaultScalarValue::String(ref s) => Some(s.clone()),
+            Self::String(ref s) => Some(s.clone()),
+            _ => None,
+        }
+    }
+
+    fn into_string(self) -> Option<String> {
+        match self {
+            Self::String(s) => Some(s),
             _ => None,
         }
     }
 
     fn as_boolean(&self) -> Option<bool> {
         match *self {
-            DefaultScalarValue::Boolean(ref b) => Some(*b),
+            Self::Boolean(ref b) => Some(*b),
             _ => None,
         }
     }
+
+    fn into_another<S: ScalarValue>(self) -> S {
+        match self {
+            Self::Int(i) => S::from(i),
+            Self::Float(f) => S::from(f),
+            Self::String(s) => S::from(s),
+            Self::Boolean(b) => S::from(b),
+        }
+    }
 }
 
 impl<'a> From<&'a str> for DefaultScalarValue {
     fn from(s: &'a str) -> Self {
-        DefaultScalarValue::String(s.into())
+        Self::String(s.into())
     }
 }
 
diff --git a/juniper_actix/src/lib.rs b/juniper_actix/src/lib.rs
index 1821f2e22..e62ded6df 100644
--- a/juniper_actix/src/lib.rs
+++ b/juniper_actix/src/lib.rs
@@ -481,7 +481,6 @@ pub mod subscriptions {
 
 #[cfg(test)]
 mod tests {
-    use super::*;
     use actix_web::{dev::ServiceResponse, http, http::header::CONTENT_TYPE, test, App};
     use juniper::{
         futures::stream::StreamExt,
@@ -490,6 +489,8 @@ mod tests {
         EmptyMutation, EmptySubscription, RootNode,
     };
 
+    use super::*;
+
     type Schema =
         juniper::RootNode<'static, Query, EmptyMutation<Database>, EmptySubscription<Database>>;
 
@@ -713,7 +714,7 @@ mod tests {
     impl TestActixWebIntegration {
         fn make_request(&self, req: test::TestRequest) -> TestResponse {
             actix_web::rt::System::new("request").block_on(async move {
-                let schema = RootNode::new(
+                let schema = Schema::new(
                     Query,
                     EmptyMutation::<Database>::new(),
                     EmptySubscription::<Database>::new(),
diff --git a/juniper_benchmarks/src/lib.rs b/juniper_benchmarks/src/lib.rs
index f06bbf688..526d0043c 100644
--- a/juniper_benchmarks/src/lib.rs
+++ b/juniper_benchmarks/src/lib.rs
@@ -1,6 +1,6 @@
 use juniper::{
     graphql_object, DefaultScalarValue, EmptyMutation, EmptySubscription, ExecutionError,
-    FieldError, GraphQLEnum, Value, Variables,
+    FieldError, GraphQLEnum, GraphQLObject, RootNode, Value, Variables,
 };
 
 pub type QueryResult = Result<
@@ -37,7 +37,7 @@ pub enum UserKind {
     Guest,
 }
 
-#[derive(juniper::GraphQLObject)]
+#[derive(GraphQLObject)]
 pub struct User {
     pub id: i32,
     pub kind: UserKind,
@@ -60,7 +60,7 @@ impl User {
 
 pub struct Query;
 
-#[graphql_object(Context = Context)]
+#[graphql_object(context = Context)]
 impl Query {
     fn user_sync_instant(id: i32) -> Result<User, FieldError> {
         Ok(User::new(id))
@@ -89,9 +89,9 @@ impl Query {
     }
 }
 
-pub fn new_schema(
-) -> juniper::RootNode<'static, Query, EmptyMutation<Context>, EmptySubscription<Context>> {
-    juniper::RootNode::new(Query, EmptyMutation::new(), EmptySubscription::new())
+pub fn new_schema() -> RootNode<'static, Query, EmptyMutation<Context>, EmptySubscription<Context>>
+{
+    RootNode::new(Query, EmptyMutation::new(), EmptySubscription::new())
 }
 
 pub fn execute_sync(query: &str, vars: Variables) -> QueryResult {
diff --git a/juniper_codegen/src/impl_object.rs b/juniper_codegen/src/impl_object.rs
index ed90f932c..9de0a7551 100644
--- a/juniper_codegen/src/impl_object.rs
+++ b/juniper_codegen/src/impl_object.rs
@@ -223,7 +223,7 @@ fn create(
             .map(SpanContainer::into_inner)
             .collect(),
         include_type_generics: false,
-        generic_scalar: false,
+        generic_scalar: true,
         no_async: _impl.attrs.no_async.is_some(),
     };
 
diff --git a/juniper_codegen/src/util/mod.rs b/juniper_codegen/src/util/mod.rs
index f54592800..062b52b1f 100644
--- a/juniper_codegen/src/util/mod.rs
+++ b/juniper_codegen/src/util/mod.rs
@@ -1232,11 +1232,10 @@ impl GraphQLTypeDefiniton {
             // No custom scalar specified, but always generic specified.
             // Therefore we inject the generic scalar.
 
-            generics.params.push(parse_quote!(__S));
-
-            let where_clause = generics.where_clause.get_or_insert(parse_quote!(where));
             // Insert ScalarValue constraint.
-            where_clause
+            generics.params.push(parse_quote!(__S));
+            generics
+                .make_where_clause()
                 .predicates
                 .push(parse_quote!(__S: ::juniper::ScalarValue));
         }
@@ -1248,6 +1247,15 @@ impl GraphQLTypeDefiniton {
         };
         let (impl_generics, _, where_clause) = generics.split_for_impl();
 
+        let mut generics_with_send_sync = generics.clone();
+        if self.scalar.is_none() && self.generic_scalar {
+            generics_with_send_sync
+                .make_where_clause()
+                .predicates
+                .push(parse_quote!(__S: Send + Sync));
+        }
+        let (_, _, where_clause_with_send_sync) = generics_with_send_sync.split_for_impl();
+
         let resolve_matches_async = self.fields.iter().filter(|field| field.is_async).map(
             |field| {
                 let name = &field.name;
@@ -1378,7 +1386,7 @@ impl GraphQLTypeDefiniton {
 
         let subscription_implementation = quote!(
             impl#impl_generics ::juniper::GraphQLSubscriptionValue<#scalar> for #ty #type_generics_tokens
-            #where_clause
+            #where_clause_with_send_sync
             {
                 #[allow(unused_variables)]
                 fn resolve_field_into_stream<
diff --git a/juniper_iron/examples/iron_server.rs b/juniper_iron/examples/iron_server.rs
index 6df296683..d243b2210 100644
--- a/juniper_iron/examples/iron_server.rs
+++ b/juniper_iron/examples/iron_server.rs
@@ -3,7 +3,7 @@ use std::env;
 use iron::prelude::*;
 use juniper::{
     tests::fixtures::starwars::schema::{Database, Query},
-    EmptyMutation, EmptySubscription,
+    DefaultScalarValue, EmptyMutation, EmptySubscription,
 };
 use juniper_iron::{GraphQLHandler, GraphiQLHandler};
 use logger::Logger;
@@ -16,7 +16,7 @@ fn context_factory(_: &mut Request) -> IronResult<Database> {
 fn main() {
     let mut mount = Mount::new();
 
-    let graphql_endpoint = GraphQLHandler::new(
+    let graphql_endpoint = <GraphQLHandler<_, _, _, _, _, DefaultScalarValue>>::new(
         context_factory,
         Query,
         EmptyMutation::<Database>::new(),
diff --git a/juniper_iron/src/lib.rs b/juniper_iron/src/lib.rs
index 1f40bae54..91c60041a 100644
--- a/juniper_iron/src/lib.rs
+++ b/juniper_iron/src/lib.rs
@@ -34,7 +34,7 @@ use juniper::{Context, EmptyMutation, EmptySubscription};
 # struct QueryRoot;
 # struct Database { users: HashMap<String, User> }
 #
-# #[juniper::graphql_object( Context = Database )]
+# #[juniper::graphql_object(context = Database)]
 # impl User {
 #     fn id(&self) -> FieldResult<&String> {
 #         Ok(&self.id)
@@ -51,7 +51,7 @@ use juniper::{Context, EmptyMutation, EmptySubscription};
 #     }
 # }
 #
-# #[juniper::graphql_object( Context = Database )]
+# #[juniper::graphql_object(context = Database, scalar = juniper::DefaultScalarValue)]
 # impl QueryRoot {
 #     fn user(context: &Database, id: String) -> FieldResult<Option<&User>> {
 #         Ok(executor.context().users.get(&id))
@@ -220,7 +220,7 @@ where
     ) -> Self {
         GraphQLHandler {
             context_factory,
-            root_node: RootNode::new(query, mutation, subscription),
+            root_node: RootNode::new_with_scalar_value(query, mutation, subscription),
         }
     }
 
@@ -412,7 +412,7 @@ mod tests {
     use juniper::{
         http::tests as http_tests,
         tests::fixtures::starwars::schema::{Database, Query},
-        EmptyMutation, EmptySubscription,
+        DefaultScalarValue, EmptyMutation, EmptySubscription,
     };
 
     use super::GraphQLHandler;
@@ -511,7 +511,7 @@ mod tests {
     }
 
     fn make_handler() -> Box<dyn Handler> {
-        Box::new(GraphQLHandler::new(
+        Box::new(<GraphQLHandler<_, _, _, _, _, DefaultScalarValue>>::new(
             context_factory,
             Query,
             EmptyMutation::<Database>::new(),
diff --git a/juniper_warp/src/lib.rs b/juniper_warp/src/lib.rs
index a8bbf0d52..7bb88cb51 100644
--- a/juniper_warp/src/lib.rs
+++ b/juniper_warp/src/lib.rs
@@ -64,7 +64,7 @@ use warp::{body, filters::BoxedFilter, http, query, Filter};
 /// ```
 /// # use std::sync::Arc;
 /// # use warp::Filter;
-/// # use juniper::{EmptyMutation, EmptySubscription, RootNode};
+/// # use juniper::{graphql_object, EmptyMutation, EmptySubscription, RootNode};
 /// # use juniper_warp::make_graphql_filter;
 /// #
 /// type UserId = String;
@@ -74,9 +74,7 @@ use warp::{body, filters::BoxedFilter, http, query, Filter};
 ///
 /// struct QueryRoot;
 ///
-/// #[juniper::graphql_object(
-///    Context = ExampleContext
-/// )]
+/// #[graphql_object(context = ExampleContext)]
 /// impl QueryRoot {
 ///     fn say_hello(context: &ExampleContext) -> String {
 ///         format!(
@@ -683,18 +681,18 @@ mod tests {
 
 #[cfg(test)]
 mod tests_http_harness {
-    use super::*;
     use juniper::{
         http::tests::{run_http_test_suite, HttpIntegration, TestResponse},
         tests::fixtures::starwars::schema::{Database, Query},
         EmptyMutation, EmptySubscription, RootNode,
     };
     use warp::{
-        self,
         filters::{path, BoxedFilter},
         Filter,
     };
 
+    use super::*;
+
     struct TestWarpIntegration {
         filter: BoxedFilter<(http::Response<Vec<u8>>,)>,
     }


Test patch:
diff --git a/integration_tests/async_await/src/main.rs b/integration_tests/async_await/src/main.rs
index d4004aa32..6d9d3d415 100644
--- a/integration_tests/async_await/src/main.rs
+++ b/integration_tests/async_await/src/main.rs
@@ -1,7 +1,9 @@
-#[cfg(test)]
-use juniper::{graphql_value, EmptyMutation, EmptySubscription, GraphQLError, RootNode, Value};
+use juniper::{
+    graphql_object, graphql_value, EmptyMutation, EmptySubscription, GraphQLEnum, GraphQLError,
+    RootNode, Value,
+};
 
-#[derive(juniper::GraphQLEnum)]
+#[derive(GraphQLEnum)]
 enum UserKind {
     Admin,
     User,
@@ -15,7 +17,7 @@ struct User {
     kind: UserKind,
 }
 
-#[juniper::graphql_object]
+#[graphql_object]
 impl User {
     async fn id(&self) -> i32 {
         self.id
@@ -47,7 +49,7 @@ impl User {
 
 struct Query;
 
-#[juniper::graphql_object]
+#[graphql_object]
 impl Query {
     fn field_sync(&self) -> &'static str {
         "field_sync"
diff --git a/integration_tests/codegen_fail/fail/object/impl_argument_no_object.stderr b/integration_tests/codegen_fail/fail/object/impl_argument_no_object.stderr
index c10177873..87040d369 100644
--- a/integration_tests/codegen_fail/fail/object/impl_argument_no_object.stderr
+++ b/integration_tests/codegen_fail/fail/object/impl_argument_no_object.stderr
@@ -1,16 +1,29 @@
-error[E0277]: the trait bound `Obj: IsInputType<DefaultScalarValue>` is not satisfied
+error[E0277]: the trait bound `Obj: IsInputType<__S>` is not satisfied
  --> $DIR/impl_argument_no_object.rs:8:1
   |
 8 | #[juniper::graphql_object]
-  | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `IsInputType<DefaultScalarValue>` is not implemented for `Obj`
+  | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `IsInputType<__S>` is not implemented for `Obj`
   |
   = note: required by `juniper::marker::IsInputType::mark`
   = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0277]: the trait bound `Obj: FromInputValue` is not satisfied
+error[E0277]: the trait bound `Obj: FromInputValue<__S>` is not satisfied
  --> $DIR/impl_argument_no_object.rs:8:1
   |
 8 | #[juniper::graphql_object]
-  | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromInputValue` is not implemented for `Obj`
+  | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromInputValue<__S>` is not implemented for `Obj`
   |
   = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `Obj: FromInputValue` is not satisfied
+   --> $DIR/impl_argument_no_object.rs:8:1
+    |
+8   | #[juniper::graphql_object]
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromInputValue` is not implemented for `Obj`
+    |
+   ::: $WORKSPACE/juniper/src/ast.rs
+    |
+    | pub trait FromInputValue<S = DefaultScalarValue>: Sized {
+    | ------------------------------------------------------- required by this bound in `FromInputValue`
+    |
+    = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/integration_tests/juniper_tests/src/codegen/derive_enum.rs b/integration_tests/juniper_tests/src/codegen/derive_enum.rs
index f4adbc691..47329b9b0 100644
--- a/integration_tests/juniper_tests/src/codegen/derive_enum.rs
+++ b/integration_tests/juniper_tests/src/codegen/derive_enum.rs
@@ -1,14 +1,14 @@
-#[cfg(test)]
 use fnv::FnvHashMap;
-
-#[cfg(test)]
-use juniper::{self, DefaultScalarValue, FromInputValue, GraphQLType, InputValue, ToInputValue};
+use juniper::{
+    DefaultScalarValue, FromInputValue, GraphQLEnum, GraphQLType, InputValue, Registry,
+    ToInputValue,
+};
 
 pub struct CustomContext {}
 
 impl juniper::Context for CustomContext {}
 
-#[derive(juniper::GraphQLEnum, Debug, PartialEq)]
+#[derive(GraphQLEnum, Debug, PartialEq)]
 #[graphql(name = "Some", description = "enum descr")]
 enum SomeEnum {
     Regular,
@@ -24,7 +24,7 @@ enum NoRenameEnum {
 }
 
 /// Enum doc.
-#[derive(juniper::GraphQLEnum)]
+#[derive(GraphQLEnum)]
 enum DocEnum {
     /// Variant doc.
     Foo,
@@ -34,7 +34,7 @@ enum DocEnum {
 /// Doc 2.
 ///
 /// Doc 4.
-#[derive(juniper::GraphQLEnum, Debug, PartialEq)]
+#[derive(GraphQLEnum, Debug, PartialEq)]
 enum MultiDocEnum {
     /// Variant 1.
     /// Variant 2.
@@ -42,7 +42,7 @@ enum MultiDocEnum {
 }
 
 /// This is not used as the description.
-#[derive(juniper::GraphQLEnum, Debug, PartialEq)]
+#[derive(GraphQLEnum, Debug, PartialEq)]
 #[graphql(description = "enum override")]
 enum OverrideDocEnum {
     /// This is not used as the description.
@@ -50,7 +50,7 @@ enum OverrideDocEnum {
     Foo,
 }
 
-#[derive(juniper::GraphQLEnum)]
+#[derive(GraphQLEnum)]
 #[graphql(context = CustomContext, noasync)]
 enum ContextEnum {
     A,
@@ -65,7 +65,7 @@ fn test_derived_enum() {
     );
 
     // Ensure validity of meta info.
-    let mut registry: juniper::Registry = juniper::Registry::new(FnvHashMap::default());
+    let mut registry: Registry = Registry::new(FnvHashMap::default());
     let meta = SomeEnum::meta(&(), &mut registry);
 
     assert_eq!(meta.name(), Some("Some"));
@@ -100,14 +100,14 @@ fn test_derived_enum() {
 
 #[test]
 fn test_doc_comment() {
-    let mut registry: juniper::Registry = juniper::Registry::new(FnvHashMap::default());
+    let mut registry: Registry = Registry::new(FnvHashMap::default());
     let meta = DocEnum::meta(&(), &mut registry);
     assert_eq!(meta.description(), Some(&"Enum doc.".to_string()));
 }
 
 #[test]
 fn test_multi_doc_comment() {
-    let mut registry: juniper::Registry = juniper::Registry::new(FnvHashMap::default());
+    let mut registry: Registry = Registry::new(FnvHashMap::default());
     let meta = MultiDocEnum::meta(&(), &mut registry);
     assert_eq!(
         meta.description(),
@@ -117,7 +117,7 @@ fn test_multi_doc_comment() {
 
 #[test]
 fn test_doc_comment_override() {
-    let mut registry: juniper::Registry = juniper::Registry::new(FnvHashMap::default());
+    let mut registry: Registry = Registry::new(FnvHashMap::default());
     let meta = OverrideDocEnum::meta(&(), &mut registry);
     assert_eq!(meta.description(), Some(&"enum override".to_string()));
 }
diff --git a/integration_tests/juniper_tests/src/codegen/derive_input_object.rs b/integration_tests/juniper_tests/src/codegen/derive_input_object.rs
index d6fa4ca58..cc1595f5e 100644
--- a/integration_tests/juniper_tests/src/codegen/derive_input_object.rs
+++ b/integration_tests/juniper_tests/src/codegen/derive_input_object.rs
@@ -1,8 +1,7 @@
 use fnv::FnvHashMap;
-
 use juniper::{
     marker, DefaultScalarValue, FromInputValue, GraphQLInputObject, GraphQLType, GraphQLValue,
-    InputValue, ToInputValue,
+    InputValue, Registry, ToInputValue,
 };
 
 #[derive(GraphQLInputObject, Debug, PartialEq)]
@@ -74,7 +73,7 @@ impl<'a> GraphQLType<DefaultScalarValue> for &'a Fake {
     fn name(_: &()) -> Option<&'static str> {
         None
     }
-    fn meta<'r>(_: &(), registry: &mut juniper::Registry<'r>) -> juniper::meta::MetaType<'r>
+    fn meta<'r>(_: &(), registry: &mut Registry<'r>) -> juniper::meta::MetaType<'r>
     where
         DefaultScalarValue: 'r,
     {
@@ -113,7 +112,7 @@ fn test_derived_input_object() {
     );
 
     // Validate meta info.
-    let mut registry: juniper::Registry = juniper::Registry::new(FnvHashMap::default());
+    let mut registry: Registry = Registry::new(FnvHashMap::default());
     let meta = Input::meta(&(), &mut registry);
     assert_eq!(meta.name(), Some("MyInput"));
     assert_eq!(meta.description(), Some(&"input descr".to_string()));
@@ -172,14 +171,14 @@ fn test_derived_input_object() {
 
 #[test]
 fn test_doc_comment() {
-    let mut registry: juniper::Registry = juniper::Registry::new(FnvHashMap::default());
+    let mut registry: Registry = Registry::new(FnvHashMap::default());
     let meta = DocComment::meta(&(), &mut registry);
     assert_eq!(meta.description(), Some(&"Object comment.".to_string()));
 }
 
 #[test]
 fn test_multi_doc_comment() {
-    let mut registry: juniper::Registry = juniper::Registry::new(FnvHashMap::default());
+    let mut registry: Registry = Registry::new(FnvHashMap::default());
     let meta = MultiDocComment::meta(&(), &mut registry);
     assert_eq!(
         meta.description(),
@@ -189,7 +188,7 @@ fn test_multi_doc_comment() {
 
 #[test]
 fn test_doc_comment_override() {
-    let mut registry: juniper::Registry = juniper::Registry::new(FnvHashMap::default());
+    let mut registry: Registry = Registry::new(FnvHashMap::default());
     let meta = OverrideDocComment::meta(&(), &mut registry);
     assert_eq!(meta.description(), Some(&"obj override".to_string()));
 }
diff --git a/integration_tests/juniper_tests/src/codegen/derive_object.rs b/integration_tests/juniper_tests/src/codegen/derive_object.rs
index 8a387b804..2a5336aba 100644
--- a/integration_tests/juniper_tests/src/codegen/derive_object.rs
+++ b/integration_tests/juniper_tests/src/codegen/derive_object.rs
@@ -1,20 +1,11 @@
-#[cfg(test)]
 use fnv::FnvHashMap;
-#[cfg(test)]
-use juniper::Object;
-use juniper::{DefaultScalarValue, GraphQLObject};
-
-#[cfg(test)]
 use juniper::{
-    self, execute, EmptyMutation, EmptySubscription, GraphQLType, RootNode, Value, Variables,
+    execute, graphql_object, DefaultScalarValue, EmptyMutation, EmptySubscription, GraphQLObject,
+    GraphQLType, Object, Registry, RootNode, Value, Variables,
 };
 
 #[derive(GraphQLObject, Debug, PartialEq)]
-#[graphql(
-    name = "MyObj",
-    description = "obj descr",
-    scalar = DefaultScalarValue
-)]
+#[graphql(name = "MyObj", description = "obj descr")]
 struct Obj {
     regular_field: bool,
     #[graphql(
@@ -26,14 +17,10 @@ struct Obj {
 }
 
 #[derive(GraphQLObject, Debug, PartialEq)]
-#[graphql(scalar = DefaultScalarValue)]
 struct Nested {
     obj: Obj,
 }
 
-struct Query;
-struct NoRenameQuery;
-
 /// Object comment.
 #[derive(GraphQLObject, Debug, PartialEq)]
 struct DocComment {
@@ -79,16 +66,19 @@ struct NoRenameObj {
     one_field: bool,
     another_field: i32,
 }
+
 struct Context;
 impl juniper::Context for Context {}
 
 #[derive(GraphQLObject, Debug)]
-#[graphql(Context = Context)]
+#[graphql(context = Context)]
 struct WithCustomContext {
     a: bool,
 }
 
-#[juniper::graphql_object]
+struct Query;
+
+#[graphql_object]
 impl Query {
     fn obj() -> Obj {
         Obj {
@@ -139,7 +129,9 @@ impl Query {
     }
 }
 
-#[juniper::graphql_object(rename = "none")]
+struct NoRenameQuery;
+
+#[graphql_object(rename = "none")]
 impl NoRenameQuery {
     fn obj() -> Obj {
         Obj {
@@ -158,7 +150,7 @@ impl NoRenameQuery {
 
 #[tokio::test]
 async fn test_doc_comment_simple() {
-    let mut registry: juniper::Registry = juniper::Registry::new(FnvHashMap::default());
+    let mut registry: Registry = Registry::new(FnvHashMap::default());
     let meta = DocComment::meta(&(), &mut registry);
     assert_eq!(meta.description(), Some(&"Object comment.".to_string()));
 
@@ -173,7 +165,7 @@ async fn test_doc_comment_simple() {
 
 #[tokio::test]
 async fn test_multi_doc_comment() {
-    let mut registry: juniper::Registry = juniper::Registry::new(FnvHashMap::default());
+    let mut registry: Registry = Registry::new(FnvHashMap::default());
     let meta = MultiDocComment::meta(&(), &mut registry);
     assert_eq!(
         meta.description(),
@@ -191,7 +183,7 @@ async fn test_multi_doc_comment() {
 
 #[tokio::test]
 async fn test_doc_comment_override() {
-    let mut registry: juniper::Registry = juniper::Registry::new(FnvHashMap::default());
+    let mut registry: Registry = Registry::new(FnvHashMap::default());
     let meta = OverrideDocComment::meta(&(), &mut registry);
     assert_eq!(meta.description(), Some(&"obj override".to_string()));
 
@@ -204,98 +196,6 @@ async fn test_doc_comment_override() {
     .await;
 }
 
-#[tokio::test]
-async fn test_no_rename_root() {
-    let doc = r#"
-        {
-            no_rename_obj {
-                one_field
-                another_field
-            }
-
-            obj {
-                regularField
-            }
-        }"#;
-
-    let schema = RootNode::new(
-        NoRenameQuery,
-        EmptyMutation::<()>::new(),
-        EmptySubscription::<()>::new(),
-    );
-
-    assert_eq!(
-        execute(doc, None, &schema, &Variables::new(), &()).await,
-        Ok((
-            Value::object(
-                vec![
-                    (
-                        "no_rename_obj",
-                        Value::object(
-                            vec![
-                                ("one_field", Value::scalar(true)),
-                                ("another_field", Value::scalar(146)),
-                            ]
-                            .into_iter()
-                            .collect(),
-                        ),
-                    ),
-                    (
-                        "obj",
-                        Value::object(
-                            vec![("regularField", Value::scalar(false)),]
-                                .into_iter()
-                                .collect(),
-                        ),
-                    )
-                ]
-                .into_iter()
-                .collect()
-            ),
-            vec![]
-        ))
-    );
-}
-
-#[tokio::test]
-async fn test_no_rename_obj() {
-    let doc = r#"
-        {
-            noRenameObj {
-                one_field
-                another_field
-            }
-        }"#;
-
-    let schema = RootNode::new(
-        Query,
-        EmptyMutation::<()>::new(),
-        EmptySubscription::<()>::new(),
-    );
-
-    assert_eq!(
-        execute(doc, None, &schema, &Variables::new(), &()).await,
-        Ok((
-            Value::object(
-                vec![(
-                    "noRenameObj",
-                    Value::object(
-                        vec![
-                            ("one_field", Value::scalar(true)),
-                            ("another_field", Value::scalar(146)),
-                        ]
-                        .into_iter()
-                        .collect(),
-                    ),
-                )]
-                .into_iter()
-                .collect()
-            ),
-            vec![]
-        ))
-    );
-}
-
 #[tokio::test]
 async fn test_derived_object() {
     assert_eq!(
@@ -304,7 +204,7 @@ async fn test_derived_object() {
     );
 
     // Verify meta info.
-    let mut registry: juniper::Registry = juniper::Registry::new(FnvHashMap::default());
+    let mut registry: Registry = Registry::new(FnvHashMap::default());
     let meta = Obj::meta(&(), &mut registry);
 
     assert_eq!(meta.name(), Some("MyObj"));
@@ -432,7 +332,98 @@ async fn test_derived_object_nested() {
     );
 }
 
-#[cfg(test)]
+#[tokio::test]
+async fn test_no_rename_root() {
+    let doc = r#"
+        {
+            no_rename_obj {
+                one_field
+                another_field
+            }
+
+            obj {
+                regularField
+            }
+        }"#;
+
+    let schema = RootNode::new(
+        NoRenameQuery,
+        EmptyMutation::<()>::new(),
+        EmptySubscription::<()>::new(),
+    );
+
+    assert_eq!(
+        execute(doc, None, &schema, &Variables::new(), &()).await,
+        Ok((
+            Value::object(
+                vec![
+                    (
+                        "no_rename_obj",
+                        Value::object(
+                            vec![
+                                ("one_field", Value::scalar(true)),
+                                ("another_field", Value::scalar(146)),
+                            ]
+                            .into_iter()
+                            .collect(),
+                        ),
+                    ),
+                    (
+                        "obj",
+                        Value::object(
+                            vec![("regularField", Value::scalar(false)),]
+                                .into_iter()
+                                .collect(),
+                        ),
+                    )
+                ]
+                .into_iter()
+                .collect()
+            ),
+            vec![]
+        ))
+    );
+}
+
+#[tokio::test]
+async fn test_no_rename_obj() {
+    let doc = r#"
+        {
+            noRenameObj {
+                one_field
+                another_field
+            }
+        }"#;
+
+    let schema = RootNode::new(
+        Query,
+        EmptyMutation::<()>::new(),
+        EmptySubscription::<()>::new(),
+    );
+
+    assert_eq!(
+        execute(doc, None, &schema, &Variables::new(), &()).await,
+        Ok((
+            Value::object(
+                vec![(
+                    "noRenameObj",
+                    Value::object(
+                        vec![
+                            ("one_field", Value::scalar(true)),
+                            ("another_field", Value::scalar(146)),
+                        ]
+                        .into_iter()
+                        .collect(),
+                    ),
+                )]
+                .into_iter()
+                .collect()
+            ),
+            vec![]
+        ))
+    );
+}
+
 async fn check_descriptions(
     object_name: &str,
     object_description: &Value,
@@ -475,7 +466,6 @@ async fn check_descriptions(
     .await;
 }
 
-#[cfg(test)]
 async fn run_type_info_query<F>(doc: &str, f: F)
 where
     F: Fn((&Object<DefaultScalarValue>, &Vec<Value>)) -> (),
diff --git a/integration_tests/juniper_tests/src/codegen/derive_object_with_raw_idents.rs b/integration_tests/juniper_tests/src/codegen/derive_object_with_raw_idents.rs
index b043425a2..241a2ab83 100644
--- a/integration_tests/juniper_tests/src/codegen/derive_object_with_raw_idents.rs
+++ b/integration_tests/juniper_tests/src/codegen/derive_object_with_raw_idents.rs
@@ -1,12 +1,11 @@
-#[cfg(test)]
 use juniper::{
-    self, execute, graphql_value, EmptyMutation, EmptySubscription, GraphQLInputObject, RootNode,
-    Value, Variables,
+    execute, graphql_object, graphql_value, EmptyMutation, EmptySubscription, GraphQLInputObject,
+    RootNode, Value, Variables,
 };
 
 pub struct Query;
 
-#[juniper::graphql_object]
+#[graphql_object]
 impl Query {
     fn r#type(r#fn: MyInputType) -> Vec<String> {
         let _ = r#fn;
@@ -87,7 +86,6 @@ async fn supports_raw_idents_in_fields_of_input_types() {
     );
 }
 
-#[cfg(test)]
 async fn run_type_info_query(doc: &str) -> Value {
     let schema = RootNode::new(
         Query,
diff --git a/integration_tests/juniper_tests/src/codegen/impl_object.rs b/integration_tests/juniper_tests/src/codegen/impl_object.rs
index 463be9b75..6349f7aae 100644
--- a/integration_tests/juniper_tests/src/codegen/impl_object.rs
+++ b/integration_tests/juniper_tests/src/codegen/impl_object.rs
@@ -1,13 +1,11 @@
-use juniper::DefaultScalarValue;
-#[cfg(test)]
-use juniper::Object;
-
-#[cfg(test)]
-use juniper::{execute, EmptyMutation, EmptySubscription, FieldError, RootNode, Value, Variables};
+use juniper::{
+    execute, graphql_object, DefaultScalarValue, EmptyMutation, EmptySubscription, Object,
+    RootNode, Value, Variables,
+};
 
 pub struct MyObject;
 
-#[juniper::graphql_object]
+#[graphql_object]
 impl MyObject {
     #[graphql(arguments(arg(name = "test")))]
     fn test(&self, arg: String) -> String {
@@ -49,7 +47,6 @@ async fn check_argument_rename() {
     .await;
 }
 
-#[cfg(test)]
 async fn run_type_info_query<F>(doc: &str, f: F)
 where
     F: Fn((&Object<DefaultScalarValue>, &Vec<Value>)) -> (),
@@ -86,11 +83,11 @@ where
 }
 
 mod fallible {
-    use super::*;
+    use juniper::{graphql_object, FieldError};
 
     struct Obj;
 
-    #[juniper::graphql_object]
+    #[graphql_object]
     impl Obj {
         fn test(&self, arg: String) -> Result<String, FieldError> {
             Ok(arg)
diff --git a/integration_tests/juniper_tests/src/codegen/impl_scalar.rs b/integration_tests/juniper_tests/src/codegen/impl_scalar.rs
index 640937fa7..721aba8f5 100644
--- a/integration_tests/juniper_tests/src/codegen/impl_scalar.rs
+++ b/integration_tests/juniper_tests/src/codegen/impl_scalar.rs
@@ -86,7 +86,7 @@ impl GraphQLScalar for ScalarDescription {
     }
 }
 
-#[graphql_object]
+#[graphql_object(scalar = DefaultScalarValue)]
 impl Root {
     fn default_name() -> DefaultName {
         DefaultName(0)
@@ -278,7 +278,7 @@ async fn scalar_description_introspection() {
 async fn resolves_with_custom_scalar_value() {
     const DOC: &str = r#"{ withCustomScalarValue }"#;
 
-    let schema = RootNode::<_, _, _, MyScalarValue>::new(
+    let schema = RootNode::<_, _, _, MyScalarValue>::new_with_scalar_value(
         RootWithCustomScalarValue,
         EmptyMutation::<()>::new(),
         EmptySubscription::<()>::new(),
diff --git a/integration_tests/juniper_tests/src/codegen/interface_attr.rs b/integration_tests/juniper_tests/src/codegen/interface_attr.rs
index 3cf4f198d..3cffc9a44 100644
--- a/integration_tests/juniper_tests/src/codegen/interface_attr.rs
+++ b/integration_tests/juniper_tests/src/codegen/interface_attr.rs
@@ -6,12 +6,25 @@ use juniper::{
     IntoFieldError, RootNode, ScalarValue, Variables,
 };
 
-fn schema<'q, C, S, Q>(query_root: Q) -> RootNode<'q, Q, EmptyMutation<C>, EmptySubscription<C>, S>
+fn schema<'q, C, Q>(query_root: Q) -> RootNode<'q, Q, EmptyMutation<C>, EmptySubscription<C>>
+where
+    Q: GraphQLType<DefaultScalarValue, Context = C, TypeInfo = ()> + 'q,
+{
+    RootNode::new(
+        query_root,
+        EmptyMutation::<C>::new(),
+        EmptySubscription::<C>::new(),
+    )
+}
+
+fn schema_with_scalar<'q, S, C, Q>(
+    query_root: Q,
+) -> RootNode<'q, Q, EmptyMutation<C>, EmptySubscription<C>, S>
 where
     Q: GraphQLType<S, Context = C, TypeInfo = ()> + 'q,
     S: ScalarValue + 'q,
 {
-    RootNode::new(
+    RootNode::new_with_scalar_value(
         query_root,
         EmptyMutation::<C>::new(),
         EmptySubscription::<C>::new(),
@@ -39,7 +52,7 @@ mod no_implers {
             unimplemented!()
         }
 
-        fn hero(&self) -> Box<DynHero<'_>> {
+        fn hero(&self) -> Box<DynHero<'_, __S>> {
             unimplemented!()
         }
     }
@@ -170,8 +183,8 @@ mod trivial {
         Droid,
     }
 
-    #[graphql_object]
-    impl QueryRoot {
+    #[graphql_object(scalar = S)]
+    impl<S: ScalarValue + Send + Sync> QueryRoot {
         fn character(&self) -> CharacterValue {
             match self {
                 Self::Human => Human {
@@ -187,8 +200,8 @@ mod trivial {
             }
         }
 
-        fn hero(&self) -> Box<DynHero<'_>> {
-            let ch: Box<DynHero<'_>> = match self {
+        fn hero(&self) -> Box<DynHero<'_, S>> {
+            let ch: Box<DynHero<'_, _>> = match self {
                 Self::Human => Box::new(Human {
                     id: "human-32".to_string(),
                     home_planet: "earth".to_string(),
@@ -692,8 +705,8 @@ mod trivial_async {
         Droid,
     }
 
-    #[graphql_object]
-    impl QueryRoot {
+    #[graphql_object(scalar = S)]
+    impl<S: ScalarValue + Send + Sync> QueryRoot {
         fn character(&self) -> CharacterValue {
             match self {
                 Self::Human => Human {
@@ -709,8 +722,8 @@ mod trivial_async {
             }
         }
 
-        fn hero(&self) -> Box<DynHero<'_>> {
-            let ch: Box<DynHero<'_>> = match self {
+        fn hero(&self) -> Box<DynHero<'_, S>> {
+            let ch: Box<DynHero<'_, _>> = match self {
                 Self::Human => Box::new(Human {
                     id: "human-32".to_string(),
                     home_planet: "earth".to_string(),
@@ -1055,8 +1068,8 @@ mod explicit_async {
         Droid,
     }
 
-    #[graphql_object]
-    impl QueryRoot {
+    #[graphql_object(scalar = S)]
+    impl<S: ScalarValue + Send + Sync> QueryRoot {
         fn character(&self) -> CharacterValue {
             match self {
                 Self::Human => Human {
@@ -1072,8 +1085,8 @@ mod explicit_async {
             }
         }
 
-        fn hero(&self) -> Box<DynHero<'_>> {
-            let ch: Box<DynHero<'_>> = match self {
+        fn hero(&self) -> Box<DynHero<'_, S>> {
+            let ch: Box<DynHero<'_, _>> = match self {
                 Self::Human => Box::new(Human {
                     id: "human-32".to_string(),
                     home_planet: "earth".to_string(),
@@ -1305,8 +1318,8 @@ mod fallible_field {
         Droid,
     }
 
-    #[graphql_object]
-    impl QueryRoot {
+    #[graphql_object(scalar = S)]
+    impl<S: ScalarValue + Send + Sync> QueryRoot {
         fn character(&self) -> CharacterValue {
             match self {
                 Self::Human => Human {
@@ -1322,8 +1335,8 @@ mod fallible_field {
             }
         }
 
-        fn hero(&self) -> Box<DynHero<'_>> {
-            let ch: Box<DynHero<'_>> = match self {
+        fn hero(&self) -> Box<DynHero<'_, S>> {
+            let ch: Box<DynHero<'_, _>> = match self {
                 Self::Human => Box::new(Human {
                     id: "human-32".to_string(),
                     home_planet: "earth".to_string(),
@@ -1571,8 +1584,8 @@ mod generic {
         Droid,
     }
 
-    #[graphql_object]
-    impl QueryRoot {
+    #[graphql_object(scalar = S)]
+    impl<S: ScalarValue + Send + Sync> QueryRoot {
         fn character(&self) -> CharacterValue {
             match self {
                 Self::Human => Human {
@@ -1588,8 +1601,8 @@ mod generic {
             }
         }
 
-        fn hero(&self) -> Box<DynHero<'_, u8, ()>> {
-            let ch: Box<DynHero<'_, u8, ()>> = match self {
+        fn hero(&self) -> Box<DynHero<'_, u8, (), S>> {
+            let ch: Box<DynHero<'_, u8, (), _>> = match self {
                 Self::Human => Box::new(Human {
                     id: "human-32".to_string(),
                     home_planet: "earth".to_string(),
@@ -1815,8 +1828,8 @@ mod generic_async {
         Droid,
     }
 
-    #[graphql_object]
-    impl QueryRoot {
+    #[graphql_object(scalar = S)]
+    impl<S: ScalarValue + Send + Sync> QueryRoot {
         fn character(&self) -> CharacterValue {
             match self {
                 Self::Human => Human {
@@ -1832,8 +1845,8 @@ mod generic_async {
             }
         }
 
-        fn hero(&self) -> Box<DynHero<'_, u8, ()>> {
-            let ch: Box<DynHero<'_, u8, ()>> = match self {
+        fn hero(&self) -> Box<DynHero<'_, u8, (), S>> {
+            let ch: Box<DynHero<'_, u8, (), _>> = match self {
                 Self::Human => Box::new(Human {
                     id: "human-32".to_string(),
                     home_planet: "earth".to_string(),
@@ -2059,8 +2072,8 @@ mod generic_lifetime_async {
         Droid,
     }
 
-    #[graphql_object]
-    impl QueryRoot {
+    #[graphql_object(scalar = S)]
+    impl<S: ScalarValue + Send + Sync> QueryRoot {
         fn character(&self) -> CharacterValue<'_, ()> {
             match self {
                 Self::Human => Human {
@@ -2076,8 +2089,8 @@ mod generic_lifetime_async {
             }
         }
 
-        fn hero(&self) -> Box<DynHero<'_, '_, ()>> {
-            let ch: Box<DynHero<'_, '_, ()>> = match self {
+        fn hero(&self) -> Box<DynHero<'_, '_, (), S>> {
+            let ch: Box<DynHero<'_, '_, (), _>> = match self {
                 Self::Human => Box::new(Human {
                     id: "human-32".to_string(),
                     home_planet: "earth".to_string(),
@@ -2286,8 +2299,8 @@ mod argument {
 
     struct QueryRoot;
 
-    #[graphql_object]
-    impl QueryRoot {
+    #[graphql_object(scalar = S)]
+    impl<S: ScalarValue + Send + Sync> QueryRoot {
         fn character(&self) -> CharacterValue {
             Human {
                 id: "human-32".to_string(),
@@ -2296,7 +2309,7 @@ mod argument {
             .into()
         }
 
-        fn hero(&self) -> Box<DynHero<'_>> {
+        fn hero(&self) -> Box<DynHero<'_, S>> {
             Box::new(Human {
                 id: "human-32".to_string(),
                 home_planet: "earth".to_string(),
@@ -3011,7 +3024,7 @@ mod explicit_scalar {
             }
         }"#;
 
-        let schema = schema::<_, DefaultScalarValue, _>(QueryRoot::Human);
+        let schema = schema(QueryRoot::Human);
 
         assert_eq!(
             execute(DOC, None, &schema, &Variables::new(), &()).await,
@@ -3033,7 +3046,7 @@ mod explicit_scalar {
             }
         }"#;
 
-        let schema = schema::<_, DefaultScalarValue, _>(QueryRoot::Droid);
+        let schema = schema(QueryRoot::Droid);
 
         assert_eq!(
             execute(DOC, None, &schema, &Variables::new(), &()).await,
@@ -3055,7 +3068,7 @@ mod explicit_scalar {
             }
         }"#;
 
-        let schema = schema::<_, DefaultScalarValue, _>(QueryRoot::Human);
+        let schema = schema(QueryRoot::Human);
 
         assert_eq!(
             execute(DOC, None, &schema, &Variables::new(), &()).await,
@@ -3077,7 +3090,7 @@ mod explicit_scalar {
             }
         }"#;
 
-        let schema = schema::<_, DefaultScalarValue, _>(QueryRoot::Droid);
+        let schema = schema(QueryRoot::Droid);
 
         assert_eq!(
             execute(DOC, None, &schema, &Variables::new(), &()).await,
@@ -3100,7 +3113,7 @@ mod explicit_scalar {
             (QueryRoot::Human, "human-32"),
             (QueryRoot::Droid, "droid-99"),
         ] {
-            let schema = schema::<_, DefaultScalarValue, _>(*root);
+            let schema = schema(*root);
 
             let expected_id: &str = *expected_id;
             assert_eq!(
@@ -3119,7 +3132,7 @@ mod explicit_scalar {
         }"#;
 
         for (root, expected_info) in &[(QueryRoot::Human, "earth"), (QueryRoot::Droid, "run")] {
-            let schema = schema::<_, DefaultScalarValue, _>(*root);
+            let schema = schema(*root);
 
             let expected_info: &str = *expected_info;
             assert_eq!(
@@ -3237,7 +3250,7 @@ mod custom_scalar {
             }
         }"#;
 
-        let schema = schema::<_, MyScalarValue, _>(QueryRoot::Human);
+        let schema = schema_with_scalar::<MyScalarValue, _, _>(QueryRoot::Human);
 
         assert_eq!(
             execute(DOC, None, &schema, &Variables::new(), &()).await,
@@ -3259,7 +3272,7 @@ mod custom_scalar {
             }
         }"#;
 
-        let schema = schema::<_, MyScalarValue, _>(QueryRoot::Droid);
+        let schema = schema_with_scalar::<MyScalarValue, _, _>(QueryRoot::Droid);
 
         assert_eq!(
             execute(DOC, None, &schema, &Variables::new(), &()).await,
@@ -3281,7 +3294,7 @@ mod custom_scalar {
             }
         }"#;
 
-        let schema = schema::<_, MyScalarValue, _>(QueryRoot::Human);
+        let schema = schema_with_scalar::<MyScalarValue, _, _>(QueryRoot::Human);
 
         assert_eq!(
             execute(DOC, None, &schema, &Variables::new(), &()).await,
@@ -3303,7 +3316,7 @@ mod custom_scalar {
             }
         }"#;
 
-        let schema = schema::<_, MyScalarValue, _>(QueryRoot::Droid);
+        let schema = schema_with_scalar::<MyScalarValue, _, _>(QueryRoot::Droid);
 
         assert_eq!(
             execute(DOC, None, &schema, &Variables::new(), &()).await,
@@ -3326,7 +3339,7 @@ mod custom_scalar {
             (QueryRoot::Human, "human-32"),
             (QueryRoot::Droid, "droid-99"),
         ] {
-            let schema = schema::<_, MyScalarValue, _>(*root);
+            let schema = schema_with_scalar::<MyScalarValue, _, _>(*root);
 
             let expected_id: &str = *expected_id;
             assert_eq!(
@@ -3345,7 +3358,7 @@ mod custom_scalar {
         }"#;
 
         for (root, expected_info) in &[(QueryRoot::Human, "earth"), (QueryRoot::Droid, "run")] {
-            let schema = schema::<_, MyScalarValue, _>(*root);
+            let schema = schema_with_scalar::<MyScalarValue, _, _>(*root);
 
             let expected_info: &str = *expected_info;
             assert_eq!(
@@ -3417,9 +3430,9 @@ mod explicit_generic_scalar {
         Droid,
     }
 
-    #[graphql_object(scalar = DefaultScalarValue)]
-    impl QueryRoot {
-        fn character(&self) -> CharacterValue {
+    #[graphql_object(scalar = S)]
+    impl<S: ScalarValue + Send + Sync> QueryRoot {
+        fn character(&self) -> CharacterValue<S> {
             match self {
                 Self::Human => Human {
                     id: "human-32".to_string(),
@@ -3434,8 +3447,8 @@ mod explicit_generic_scalar {
             }
         }
 
-        fn hero(&self) -> Box<DynHero<'_>> {
-            let ch: Box<DynHero<'_>> = match self {
+        fn hero(&self) -> Box<DynHero<'_, S>> {
+            let ch: Box<DynHero<'_, _>> = match self {
                 Self::Human => Box::new(Human {
                     id: "human-32".to_string(),
                     home_planet: "earth".to_string(),
@@ -3685,8 +3698,8 @@ mod explicit_custom_context {
         Droid,
     }
 
-    #[graphql_object(context = CustomContext)]
-    impl QueryRoot {
+    #[graphql_object(context = CustomContext, scalar = S)]
+    impl<S: ScalarValue + Send + Sync> QueryRoot {
         fn character(&self) -> CharacterValue {
             match self {
                 Self::Human => Human {
@@ -3702,8 +3715,8 @@ mod explicit_custom_context {
             }
         }
 
-        fn hero(&self) -> Box<DynHero<'_>> {
-            let ch: Box<DynHero<'_>> = match self {
+        fn hero(&self) -> Box<DynHero<'_, S>> {
+            let ch: Box<DynHero<'_, _>> = match self {
                 Self::Human => Box::new(Human {
                     id: "human-32".to_string(),
                     home_planet: "earth".to_string(),
@@ -3931,8 +3944,8 @@ mod inferred_custom_context_from_field {
         Droid,
     }
 
-    #[graphql_object(context = CustomContext)]
-    impl QueryRoot {
+    #[graphql_object(context = CustomContext, scalar = S)]
+    impl<S: ScalarValue + Send + Sync> QueryRoot {
         fn character(&self) -> CharacterValue {
             match self {
                 Self::Human => Human {
@@ -3948,8 +3961,8 @@ mod inferred_custom_context_from_field {
             }
         }
 
-        fn hero(&self) -> Box<DynHero<'_>> {
-            let ch: Box<DynHero<'_>> = match self {
+        fn hero(&self) -> Box<DynHero<'_, S>> {
+            let ch: Box<DynHero<'_, _>> = match self {
                 Self::Human => Box::new(Human {
                     id: "human-32".to_string(),
                     home_planet: "earth".to_string(),
@@ -4183,8 +4196,8 @@ mod inferred_custom_context_from_downcast {
         Droid,
     }
 
-    #[graphql_object(context = Database)]
-    impl QueryRoot {
+    #[graphql_object(context = Database, scalar = S)]
+    impl<S: ScalarValue + Send + Sync> QueryRoot {
         fn character(&self) -> CharacterValue {
             match self {
                 Self::Human => Human {
@@ -4200,8 +4213,8 @@ mod inferred_custom_context_from_downcast {
             }
         }
 
-        fn hero(&self) -> Box<DynHero<'_>> {
-            let ch: Box<DynHero<'_>> = match self {
+        fn hero(&self) -> Box<DynHero<'_, S>> {
+            let ch: Box<DynHero<'_, _>> = match self {
                 Self::Human => Box::new(Human {
                     id: "human-32".to_string(),
                     home_planet: "earth".to_string(),
@@ -4793,8 +4806,8 @@ mod downcast_method {
         Droid,
     }
 
-    #[graphql_object]
-    impl QueryRoot {
+    #[graphql_object(scalar = S)]
+    impl<S: ScalarValue + Send + Sync> QueryRoot {
         fn character(&self) -> CharacterValue {
             match self {
                 Self::Human => Human {
@@ -4810,8 +4823,8 @@ mod downcast_method {
             }
         }
 
-        fn hero(&self) -> Box<DynHero<'_>> {
-            let ch: Box<DynHero<'_>> = match self {
+        fn hero(&self) -> Box<DynHero<'_, S>> {
+            let ch: Box<DynHero<'_, _>> = match self {
                 Self::Human => Box::new(Human {
                     id: "human-32".to_string(),
                     home_planet: "earth".to_string(),
@@ -5058,8 +5071,8 @@ mod external_downcast {
         Droid,
     }
 
-    #[graphql_object(context = Database)]
-    impl QueryRoot {
+    #[graphql_object(context = Database, scalar = S)]
+    impl<S: ScalarValue + Send + Sync> QueryRoot {
         fn character(&self) -> CharacterValue {
             match self {
                 Self::Human => Human {
@@ -5075,8 +5088,8 @@ mod external_downcast {
             }
         }
 
-        fn hero(&self) -> Box<DynHero<'_>> {
-            let ch: Box<DynHero<'_>> = match self {
+        fn hero(&self) -> Box<DynHero<'_, S>> {
+            let ch: Box<DynHero<'_, _>> = match self {
                 Self::Human => Box::new(Human {
                     id: "human-32".to_string(),
                     home_planet: "earth".to_string(),
diff --git a/integration_tests/juniper_tests/src/codegen/scalar_value_transparent.rs b/integration_tests/juniper_tests/src/codegen/scalar_value_transparent.rs
index 6f52e5b64..087bc91c2 100644
--- a/integration_tests/juniper_tests/src/codegen/scalar_value_transparent.rs
+++ b/integration_tests/juniper_tests/src/codegen/scalar_value_transparent.rs
@@ -1,20 +1,23 @@
 use fnv::FnvHashMap;
-use juniper::{DefaultScalarValue, FromInputValue, GraphQLType, InputValue, ToInputValue};
+use juniper::{
+    graphql_object, DefaultScalarValue, FromInputValue, GraphQLObject, GraphQLScalarValue,
+    GraphQLType, InputValue, Registry, ToInputValue,
+};
 
-#[derive(juniper::GraphQLScalarValue, PartialEq, Eq, Debug)]
+#[derive(GraphQLScalarValue, Debug, Eq, PartialEq)]
 #[graphql(transparent)]
 struct UserId(String);
 
-#[derive(juniper::GraphQLScalarValue, PartialEq, Eq, Debug)]
+#[derive(GraphQLScalarValue, Debug, Eq, PartialEq)]
 #[graphql(transparent, name = "MyUserId", description = "custom description...")]
 struct CustomUserId(String);
 
 /// The doc comment...
-#[derive(juniper::GraphQLScalarValue, PartialEq, Eq, Debug)]
+#[derive(GraphQLScalarValue, Debug, Eq, PartialEq)]
 #[graphql(transparent)]
 struct IdWithDocComment(i32);
 
-#[derive(juniper::GraphQLObject)]
+#[derive(GraphQLObject)]
 struct User {
     id: UserId,
     id_custom: CustomUserId,
@@ -22,7 +25,7 @@ struct User {
 
 struct User2;
 
-#[juniper::graphql_object]
+#[graphql_object]
 impl User2 {
     fn id(&self) -> UserId {
         UserId("id".to_string())
@@ -36,7 +39,7 @@ fn test_scalar_value_simple() {
         Some("UserId")
     );
 
-    let mut registry: juniper::Registry = juniper::Registry::new(FnvHashMap::default());
+    let mut registry: Registry = Registry::new(FnvHashMap::default());
     let meta = UserId::meta(&(), &mut registry);
     assert_eq!(meta.name(), Some("UserId"));
     assert_eq!(meta.description(), None);
@@ -57,7 +60,7 @@ fn test_scalar_value_custom() {
         Some("MyUserId")
     );
 
-    let mut registry: juniper::Registry = juniper::Registry::new(FnvHashMap::default());
+    let mut registry: Registry = Registry::new(FnvHashMap::default());
     let meta = CustomUserId::meta(&(), &mut registry);
     assert_eq!(meta.name(), Some("MyUserId"));
     assert_eq!(
@@ -76,7 +79,7 @@ fn test_scalar_value_custom() {
 
 #[test]
 fn test_scalar_value_doc_comment() {
-    let mut registry: juniper::Registry = juniper::Registry::new(FnvHashMap::default());
+    let mut registry: Registry = Registry::new(FnvHashMap::default());
     let meta = IdWithDocComment::meta(&(), &mut registry);
     assert_eq!(meta.description(), Some(&"The doc comment...".to_string()));
 }
diff --git a/integration_tests/juniper_tests/src/codegen/union_attr.rs b/integration_tests/juniper_tests/src/codegen/union_attr.rs
index ebad82217..8d414630e 100644
--- a/integration_tests/juniper_tests/src/codegen/union_attr.rs
+++ b/integration_tests/juniper_tests/src/codegen/union_attr.rs
@@ -51,12 +51,25 @@ struct EwokCustomContext {
     funny: bool,
 }
 
-fn schema<'q, C, S, Q>(query_root: Q) -> RootNode<'q, Q, EmptyMutation<C>, EmptySubscription<C>, S>
+fn schema<'q, C, Q>(query_root: Q) -> RootNode<'q, Q, EmptyMutation<C>, EmptySubscription<C>>
+where
+    Q: GraphQLType<DefaultScalarValue, Context = C, TypeInfo = ()> + 'q,
+{
+    RootNode::new(
+        query_root,
+        EmptyMutation::<C>::new(),
+        EmptySubscription::<C>::new(),
+    )
+}
+
+fn schema_with_scalar<'q, S, C, Q>(
+    query_root: Q,
+) -> RootNode<'q, Q, EmptyMutation<C>, EmptySubscription<C>, S>
 where
     Q: GraphQLType<S, Context = C, TypeInfo = ()> + 'q,
     S: ScalarValue + 'q,
 {
-    RootNode::new(
+    RootNode::new_with_scalar_value(
         query_root,
         EmptyMutation::<C>::new(),
         EmptySubscription::<C>::new(),
@@ -531,7 +544,7 @@ mod explicit_scalar {
 
     #[tokio::test]
     async fn resolves_human() {
-        let schema = schema::<_, DefaultScalarValue, _>(QueryRoot::Human);
+        let schema = schema(QueryRoot::Human);
 
         assert_eq!(
             execute(DOC, None, &schema, &Variables::new(), &()).await,
@@ -544,7 +557,7 @@ mod explicit_scalar {
 
     #[tokio::test]
     async fn resolves_droid() {
-        let schema = schema::<_, DefaultScalarValue, _>(QueryRoot::Droid);
+        let schema = schema(QueryRoot::Droid);
 
         assert_eq!(
             execute(DOC, None, &schema, &Variables::new(), &()).await,
@@ -622,7 +635,7 @@ mod custom_scalar {
 
     #[tokio::test]
     async fn resolves_human() {
-        let schema = schema::<_, MyScalarValue, _>(QueryRoot::Human);
+        let schema = schema_with_scalar::<MyScalarValue, _, _>(QueryRoot::Human);
 
         assert_eq!(
             execute(DOC, None, &schema, &Variables::new(), &()).await,
@@ -635,7 +648,7 @@ mod custom_scalar {
 
     #[tokio::test]
     async fn resolves_droid() {
-        let schema = schema::<_, MyScalarValue, _>(QueryRoot::Droid);
+        let schema = schema_with_scalar::<MyScalarValue, _, _>(QueryRoot::Droid);
 
         assert_eq!(
             execute(DOC, None, &schema, &Variables::new(), &()).await,
@@ -1054,7 +1067,7 @@ mod full_featured {
 
     struct QueryRoot;
 
-    #[graphql_object(context = CustomContext)]
+    #[graphql_object(context = CustomContext, scalar = DefaultScalarValue)]
     impl QueryRoot {
         fn character(&self, ctx: &CustomContext) -> Box<DynCharacter<'_, ()>> {
             let ch: Box<DynCharacter<'_, ()>> = match ctx {
diff --git a/integration_tests/juniper_tests/src/codegen/union_derive.rs b/integration_tests/juniper_tests/src/codegen/union_derive.rs
index 655ca9954..8db96512e 100644
--- a/integration_tests/juniper_tests/src/codegen/union_derive.rs
+++ b/integration_tests/juniper_tests/src/codegen/union_derive.rs
@@ -53,12 +53,25 @@ struct EwokCustomContext {
     funny: bool,
 }
 
-fn schema<'q, C, S, Q>(query_root: Q) -> RootNode<'q, Q, EmptyMutation<C>, EmptySubscription<C>, S>
+fn schema<'q, C, Q>(query_root: Q) -> RootNode<'q, Q, EmptyMutation<C>, EmptySubscription<C>>
+where
+    Q: GraphQLType<DefaultScalarValue, Context = C, TypeInfo = ()> + 'q,
+{
+    RootNode::new(
+        query_root,
+        EmptyMutation::<C>::new(),
+        EmptySubscription::<C>::new(),
+    )
+}
+
+fn schema_with_scalar<'q, S, C, Q>(
+    query_root: Q,
+) -> RootNode<'q, Q, EmptyMutation<C>, EmptySubscription<C>, S>
 where
     Q: GraphQLType<S, Context = C, TypeInfo = ()> + 'q,
     S: ScalarValue + 'q,
 {
-    RootNode::new(
+    RootNode::new_with_scalar_value(
         query_root,
         EmptyMutation::<C>::new(),
         EmptySubscription::<C>::new(),
@@ -429,7 +442,7 @@ mod explicit_scalar {
         Droid,
     }
 
-    #[graphql_object]
+    #[graphql_object(scalar = DefaultScalarValue)]
     impl QueryRoot {
         fn character(&self) -> Character {
             match self {
@@ -460,7 +473,7 @@ mod explicit_scalar {
 
     #[tokio::test]
     async fn resolves_human() {
-        let schema = schema::<_, DefaultScalarValue, _>(QueryRoot::Human);
+        let schema = schema(QueryRoot::Human);
 
         assert_eq!(
             execute(DOC, None, &schema, &Variables::new(), &()).await,
@@ -473,7 +486,7 @@ mod explicit_scalar {
 
     #[tokio::test]
     async fn resolves_droid() {
-        let schema = schema::<_, DefaultScalarValue, _>(QueryRoot::Droid);
+        let schema = schema(QueryRoot::Droid);
 
         assert_eq!(
             execute(DOC, None, &schema, &Variables::new(), &()).await,
@@ -533,7 +546,7 @@ mod custom_scalar {
 
     #[tokio::test]
     async fn resolves_human() {
-        let schema = schema::<_, MyScalarValue, _>(QueryRoot::Human);
+        let schema = schema_with_scalar::<MyScalarValue, _, _>(QueryRoot::Human);
 
         assert_eq!(
             execute(DOC, None, &schema, &Variables::new(), &()).await,
@@ -546,7 +559,7 @@ mod custom_scalar {
 
     #[tokio::test]
     async fn resolves_droid() {
-        let schema = schema::<_, MyScalarValue, _>(QueryRoot::Droid);
+        let schema = schema_with_scalar::<MyScalarValue, _, _>(QueryRoot::Droid);
 
         assert_eq!(
             execute(DOC, None, &schema, &Variables::new(), &()).await,
@@ -993,7 +1006,7 @@ mod full_featured_enum {
 
     struct QueryRoot;
 
-    #[graphql_object(context = CustomContext)]
+    #[graphql_object(context = CustomContext, scalar = DefaultScalarValue)]
     impl QueryRoot {
         fn character(&self, ctx: &CustomContext) -> Character<()> {
             match ctx {
@@ -1349,7 +1362,7 @@ mod full_featured_struct {
         Droid,
     }
 
-    #[graphql_object(context = Database)]
+    #[graphql_object(context = Database, scalar = DefaultScalarValue)]
     impl QueryRoot {
         fn character(&self) -> Character<()> {
             Character {
diff --git a/integration_tests/juniper_tests/src/custom_scalar.rs b/integration_tests/juniper_tests/src/custom_scalar.rs
index f76df3e1b..fcd9b5bd7 100644
--- a/integration_tests/juniper_tests/src/custom_scalar.rs
+++ b/integration_tests/juniper_tests/src/custom_scalar.rs
@@ -1,14 +1,15 @@
-use std::fmt;
+use std::{fmt, pin::Pin};
 
+use futures::{stream, Stream};
 use juniper::{
-    execute,
+    execute, graphql_object, graphql_scalar, graphql_subscription,
     parser::{ParseError, ScalarToken, Spanning, Token},
     serde::de,
-    EmptyMutation, FieldResult, InputValue, Object, ParseScalarResult, RootNode, ScalarValue,
-    Value, Variables,
+    EmptyMutation, FieldResult, GraphQLScalarValue, InputValue, Object, ParseScalarResult,
+    RootNode, ScalarValue, Value, Variables,
 };
 
-#[derive(Debug, Clone, PartialEq, juniper::GraphQLScalarValue)]
+#[derive(GraphQLScalarValue, Clone, Debug, PartialEq)]
 pub(crate) enum MyScalarValue {
     Int(i32),
     Long(i64),
@@ -22,42 +23,49 @@ impl ScalarValue for MyScalarValue {
 
     fn as_int(&self) -> Option<i32> {
         match *self {
-            MyScalarValue::Int(ref i) => Some(*i),
+            Self::Int(ref i) => Some(*i),
             _ => None,
         }
     }
 
     fn as_string(&self) -> Option<String> {
         match *self {
-            MyScalarValue::String(ref s) => Some(s.clone()),
+            Self::String(ref s) => Some(s.clone()),
+            _ => None,
+        }
+    }
+
+    fn into_string(self) -> Option<String> {
+        match self {
+            Self::String(s) => Some(s),
             _ => None,
         }
     }
 
     fn as_str(&self) -> Option<&str> {
         match *self {
-            MyScalarValue::String(ref s) => Some(s.as_str()),
+            Self::String(ref s) => Some(s.as_str()),
             _ => None,
         }
     }
 
     fn as_float(&self) -> Option<f64> {
         match *self {
-            MyScalarValue::Int(ref i) => Some(*i as f64),
-            MyScalarValue::Float(ref f) => Some(*f),
+            Self::Int(ref i) => Some(f64::from(*i)),
+            Self::Float(ref f) => Some(*f),
             _ => None,
         }
     }
 
     fn as_boolean(&self) -> Option<bool> {
         match *self {
-            MyScalarValue::Boolean(ref b) => Some(*b),
+            Self::Boolean(ref b) => Some(*b),
             _ => None,
         }
     }
 }
 
-#[derive(Default, Debug)]
+#[derive(Debug, Default)]
 pub(crate) struct MyScalarValueVisitor;
 
 impl<'de> de::Visitor<'de> for MyScalarValueVisitor {
@@ -82,7 +90,7 @@ impl<'de> de::Visitor<'de> for MyScalarValueVisitor {
     where
         E: de::Error,
     {
-        if value <= i32::max_value() as i64 {
+        if value <= i64::from(i32::max_value()) {
             self.visit_i32(value as i32)
         } else {
             Ok(MyScalarValue::Long(value))
@@ -132,7 +140,7 @@ impl<'de> de::Visitor<'de> for MyScalarValueVisitor {
     }
 }
 
-#[juniper::graphql_scalar(name = "Long")]
+#[graphql_scalar(name = "Long")]
 impl GraphQLScalar for i64 {
     fn resolve(&self) -> Value {
         Value::scalar(*self)
@@ -158,12 +166,10 @@ impl GraphQLScalar for i64 {
 
 struct TestType;
 
-#[juniper::graphql_object(
-    Scalar = MyScalarValue
-)]
+#[graphql_object(scalar = MyScalarValue)]
 impl TestType {
     fn long_field() -> i64 {
-        (::std::i32::MAX as i64) + 1
+        i64::from(i32::max_value()) + 1
     }
 
     fn long_with_arg(long_arg: i64) -> i64 {
@@ -173,14 +179,10 @@ impl TestType {
 
 struct TestSubscriptionType;
 
-#[juniper::graphql_subscription(
-    Scalar = MyScalarValue
-)]
+#[graphql_subscription(scalar = MyScalarValue)]
 impl TestSubscriptionType {
-    async fn foo(
-    ) -> std::pin::Pin<Box<dyn futures::Stream<Item = FieldResult<i32, MyScalarValue>> + Send>>
-    {
-        Box::pin(futures::stream::empty())
+    async fn foo() -> Pin<Box<dyn Stream<Item = FieldResult<i32, MyScalarValue>> + Send>> {
+        Box::pin(stream::empty())
     }
 }
 
@@ -188,7 +190,8 @@ async fn run_variable_query<F>(query: &str, vars: Variables<MyScalarValue>, f: F
 where
     F: Fn(&Object<MyScalarValue>) -> (),
 {
-    let schema = RootNode::new(TestType, EmptyMutation::<()>::new(), TestSubscriptionType);
+    let schema =
+        RootNode::new_with_scalar_value(TestType, EmptyMutation::<()>::new(), TestSubscriptionType);
 
     let (result, errs) = execute(query, None, &schema, &vars, &())
         .await
@@ -215,7 +218,7 @@ async fn querying_long() {
     run_query("{ longField }", |result| {
         assert_eq!(
             result.get_field_value("longField"),
-            Some(&Value::scalar((::std::i32::MAX as i64) + 1))
+            Some(&Value::scalar(i64::from(i32::max_value()) + 1))
         );
     })
     .await;
@@ -226,12 +229,12 @@ async fn querying_long_arg() {
     run_query(
         &format!(
             "{{ longWithArg(longArg: {}) }}",
-            (::std::i32::MAX as i64) + 3
+            i64::from(i32::max_value()) + 3
         ),
         |result| {
             assert_eq!(
                 result.get_field_value("longWithArg"),
-                Some(&Value::scalar((::std::i32::MAX as i64) + 3))
+                Some(&Value::scalar(i64::from(i32::max_value()) + 3))
             );
         },
     )
@@ -244,14 +247,14 @@ async fn querying_long_variable() {
         "query q($test: Long!){ longWithArg(longArg: $test) }",
         vec![(
             "test".to_owned(),
-            InputValue::Scalar(MyScalarValue::Long((::std::i32::MAX as i64) + 42)),
+            InputValue::Scalar(MyScalarValue::Long(i64::from(i32::max_value()) + 42)),
         )]
         .into_iter()
         .collect(),
         |result| {
             assert_eq!(
                 result.get_field_value("longWithArg"),
-                Some(&Value::scalar((::std::i32::MAX as i64) + 42))
+                Some(&Value::scalar(i64::from(i32::max_value()) + 42))
             );
         },
     )
@@ -260,7 +263,7 @@ async fn querying_long_variable() {
 
 #[test]
 fn deserialize_variable() {
-    let json = format!("{{\"field\": {}}}", (::std::i32::MAX as i64) + 42);
+    let json = format!("{{\"field\": {}}}", i64::from(i32::max_value()) + 42);
 
     let input_value: InputValue<MyScalarValue> = serde_json::from_str(&json).unwrap();
     assert_eq!(
@@ -268,7 +271,7 @@ fn deserialize_variable() {
         InputValue::Object(vec![(
             Spanning::unlocated("field".into()),
             Spanning::unlocated(InputValue::Scalar(MyScalarValue::Long(
-                (::std::i32::MAX as i64) + 42
+                i64::from(i32::max_value()) + 42
             )))
         )])
     );
diff --git a/integration_tests/juniper_tests/src/issue_371.rs b/integration_tests/juniper_tests/src/issue_371.rs
index 771843808..d4085e60d 100644
--- a/integration_tests/juniper_tests/src/issue_371.rs
+++ b/integration_tests/juniper_tests/src/issue_371.rs
@@ -1,5 +1,8 @@
 // Original author of this test is <https://github.com/davidpdrsn>.
-use juniper::*;
+
+use juniper::{
+    graphql_object, EmptyMutation, EmptySubscription, LookAheadMethods as _, RootNode, Variables,
+};
 
 pub struct Context;
 
@@ -7,9 +10,7 @@ impl juniper::Context for Context {}
 
 pub struct Query;
 
-#[graphql_object(
-    Context = Context
-)]
+#[graphql_object(context = Context)]
 impl Query {
     fn users(exec: &Executor) -> Vec<User> {
         let lh = exec.look_ahead();
@@ -27,9 +28,7 @@ impl Query {
 #[derive(Clone)]
 pub struct User;
 
-#[graphql_object(
-    Context = Context
-)]
+#[graphql_object(context = Context)]
 impl User {
     fn id() -> i32 {
         1
@@ -46,7 +45,7 @@ impl Country {
     }
 }
 
-type Schema = juniper::RootNode<'static, Query, EmptyMutation<Context>, EmptySubscription<Context>>;
+type Schema = RootNode<'static, Query, EmptyMutation<Context>, EmptySubscription<Context>>;
 
 #[tokio::test]
 async fn users() {
@@ -109,7 +108,7 @@ async fn both() {
             EmptyMutation::<Context>::new(),
             EmptySubscription::<Context>::new(),
         ),
-        &juniper::Variables::new(),
+        &Variables::new(),
         &ctx,
     )
     .await
@@ -137,7 +136,7 @@ async fn both_in_different_order() {
             EmptyMutation::<Context>::new(),
             EmptySubscription::<Context>::new(),
         ),
-        &juniper::Variables::new(),
+        &Variables::new(),
         &ctx,
     )
     .await
diff --git a/integration_tests/juniper_tests/src/issue_398.rs b/integration_tests/juniper_tests/src/issue_398.rs
index 124e1befa..5a42ac238 100644
--- a/integration_tests/juniper_tests/src/issue_398.rs
+++ b/integration_tests/juniper_tests/src/issue_398.rs
@@ -1,9 +1,10 @@
 // Original author of this test is <https://github.com/davidpdrsn>.
-use juniper::*;
+
+use juniper::{graphql_object, EmptyMutation, EmptySubscription, RootNode, Variables};
 
 struct Query;
 
-#[juniper::graphql_object]
+#[graphql_object]
 impl Query {
     fn users(executor: &Executor) -> Vec<User> {
         // This doesn't cause a panic
@@ -19,7 +20,7 @@ struct User {
     country: Country,
 }
 
-#[juniper::graphql_object]
+#[graphql_object]
 impl User {
     fn country(&self, executor: &Executor) -> &Country {
         // This panics!
@@ -33,14 +34,14 @@ struct Country {
     id: i32,
 }
 
-#[juniper::graphql_object]
+#[graphql_object]
 impl Country {
     fn id(&self) -> i32 {
         self.id
     }
 }
 
-type Schema = juniper::RootNode<'static, Query, EmptyMutation<()>, EmptySubscription<()>>;
+type Schema = RootNode<'static, Query, EmptyMutation<()>, EmptySubscription<()>>;
 
 #[tokio::test]
 async fn test_lookahead_from_fragment_with_nested_type() {
diff --git a/juniper/src/executor_tests/async_await/mod.rs b/juniper/src/executor_tests/async_await/mod.rs
index f1717c76a..064b4067b 100644
--- a/juniper/src/executor_tests/async_await/mod.rs
+++ b/juniper/src/executor_tests/async_await/mod.rs
@@ -1,6 +1,6 @@
-use crate::{EmptyMutation, RootNode, Value};
+use crate::{graphql_object, EmptyMutation, EmptySubscription, GraphQLEnum, RootNode, Value};
 
-#[derive(crate::GraphQLEnum)]
+#[derive(GraphQLEnum)]
 enum UserKind {
     Admin,
     User,
@@ -14,7 +14,7 @@ struct User {
     kind: UserKind,
 }
 
-#[crate::graphql_object]
+#[graphql_object]
 impl User {
     async fn id(&self) -> i32 {
         self.id
@@ -46,7 +46,7 @@ impl User {
 
 struct Query;
 
-#[crate::graphql_object]
+#[graphql_object]
 impl Query {
     fn field_sync(&self) -> &'static str {
         "field_sync"
@@ -72,7 +72,7 @@ impl Query {
 
 #[tokio::test]
 async fn async_simple() {
-    let schema = RootNode::new(Query, EmptyMutation::new(), crate::EmptySubscription::new());
+    let schema = RootNode::new(Query, EmptyMutation::new(), EmptySubscription::new());
     let doc = r#"
         query { 
             fieldSync
diff --git a/juniper/src/executor_tests/executor.rs b/juniper/src/executor_tests/executor.rs
index 1b1f25371..fb45ba175 100644
--- a/juniper/src/executor_tests/executor.rs
+++ b/juniper/src/executor_tests/executor.rs
@@ -58,7 +58,7 @@ mod field_execution {
 
     #[tokio::test]
     async fn test() {
-        let schema = RootNode::<_, _, _, crate::DefaultScalarValue>::new(
+        let schema = RootNode::new(
             DataType,
             EmptyMutation::<()>::new(),
             EmptySubscription::<()>::new(),
@@ -470,6 +470,7 @@ mod dynamic_context_switching {
 
     use crate::{
         executor::{Context, ExecutionError, FieldError, FieldResult},
+        graphql_object,
         parser::SourcePosition,
         schema::model::RootNode,
         types::scalars::{EmptyMutation, EmptySubscription},
@@ -491,7 +492,7 @@ mod dynamic_context_switching {
 
     struct ItemRef;
 
-    #[crate::graphql_object(Context = OuterContext)]
+    #[graphql_object(context = OuterContext)]
     impl Schema {
         fn item_opt(_context: &OuterContext, key: i32) -> Option<(&InnerContext, ItemRef)> {
             executor.context().items.get(&key).map(|c| (c, ItemRef))
@@ -521,7 +522,7 @@ mod dynamic_context_switching {
         }
     }
 
-    #[crate::graphql_object(Context = InnerContext)]
+    #[graphql_object(context = InnerContext)]
     impl ItemRef {
         fn value(context: &InnerContext) -> String {
             context.value.clone()
@@ -828,6 +829,7 @@ mod dynamic_context_switching {
 mod propagates_errors_to_nullable_fields {
     use crate::{
         executor::{ExecutionError, FieldError, FieldResult, IntoFieldError},
+        graphql_object,
         parser::SourcePosition,
         schema::model::RootNode,
         types::scalars::{EmptyMutation, EmptySubscription},
@@ -857,7 +859,7 @@ mod propagates_errors_to_nullable_fields {
         }
     }
 
-    #[crate::graphql_object]
+    #[graphql_object]
     impl Schema {
         fn inner() -> Inner {
             Inner
@@ -870,7 +872,7 @@ mod propagates_errors_to_nullable_fields {
         }
     }
 
-    #[crate::graphql_object]
+    #[graphql_object]
     impl Inner {
         fn nullable_field() -> Option<Inner> {
             Some(Inner)
@@ -1176,7 +1178,7 @@ mod named_operations {
 
     #[tokio::test]
     async fn uses_inline_operation_if_no_name_provided() {
-        let schema = RootNode::<_, _, _, crate::DefaultScalarValue>::new(
+        let schema = RootNode::new(
             Schema,
             EmptyMutation::<()>::new(),
             EmptySubscription::<()>::new(),
diff --git a/juniper/src/executor_tests/introspection/mod.rs b/juniper/src/executor_tests/introspection/mod.rs
index eeb4e144d..74403ff85 100644
--- a/juniper/src/executor_tests/introspection/mod.rs
+++ b/juniper/src/executor_tests/introspection/mod.rs
@@ -7,10 +7,10 @@ use self::input_object::{NamedPublic, NamedPublicWithDescription};
 
 use crate::{
     executor::Variables,
-    graphql_interface, graphql_object,
+    graphql_interface, graphql_object, graphql_scalar,
     schema::model::RootNode,
     types::scalars::{EmptyMutation, EmptySubscription},
-    value::{DefaultScalarValue, ParseScalarResult, ParseScalarValue, Value},
+    value::{ParseScalarResult, ParseScalarValue, ScalarValue, Value},
     GraphQLEnum,
 };
 
@@ -23,23 +23,23 @@ enum Sample {
 
 struct Scalar(i32);
 
-#[crate::graphql_scalar(name = "SampleScalar")]
-impl GraphQLScalar for Scalar {
+#[graphql_scalar(name = "SampleScalar")]
+impl<S: ScalarValue> GraphQLScalar for Scalar {
     fn resolve(&self) -> Value {
         Value::scalar(self.0)
     }
 
     fn from_input_value(v: &InputValue) -> Option<Scalar> {
-        v.as_scalar_value().map(|i: &i32| Scalar(*i))
+        v.as_scalar().and_then(ScalarValue::as_int).map(Scalar)
     }
 
-    fn from_str<'a>(value: ScalarToken<'a>) -> ParseScalarResult<'a, DefaultScalarValue> {
-        <i32 as ParseScalarValue>::from_str(value)
+    fn from_str<'a>(value: ScalarToken<'a>) -> ParseScalarResult<'a, S> {
+        <i32 as ParseScalarValue<S>>::from_str(value)
     }
 }
 
 /// A sample interface
-#[graphql_interface(name = "SampleInterface", for = Root, scalar = DefaultScalarValue)]
+#[graphql_interface(name = "SampleInterface", for = Root)]
 trait Interface {
     /// A sample field in the interface
     fn sample_enum(&self) -> Sample {
@@ -50,7 +50,7 @@ trait Interface {
 struct Root;
 
 /// The root query object in the schema
-#[graphql_object(interfaces = InterfaceValue)]
+#[graphql_object(impl = InterfaceValue)]
 impl Root {
     fn sample_enum() -> Sample {
         Sample::One
diff --git a/juniper/src/executor_tests/variables.rs b/juniper/src/executor_tests/variables.rs
index 4875c134b..76f73e014 100644
--- a/juniper/src/executor_tests/variables.rs
+++ b/juniper/src/executor_tests/variables.rs
@@ -1,11 +1,12 @@
 use crate::{
     ast::InputValue,
     executor::Variables,
+    graphql_object, graphql_scalar,
     parser::SourcePosition,
     schema::model::RootNode,
     types::scalars::{EmptyMutation, EmptySubscription},
     validation::RuleError,
-    value::{DefaultScalarValue, Object, ParseScalarResult, ParseScalarValue, Value},
+    value::{DefaultScalarValue, Object, ParseScalarResult, ParseScalarValue, ScalarValue, Value},
     GraphQLError::ValidationError,
     GraphQLInputObject,
 };
@@ -13,17 +14,15 @@ use crate::{
 #[derive(Debug)]
 struct TestComplexScalar;
 
-struct TestType;
-
-#[crate::graphql_scalar]
-impl GraphQLScalar for TestComplexScalar {
+#[graphql_scalar]
+impl<S: ScalarValue> GraphQLScalar for TestComplexScalar {
     fn resolve(&self) -> Value {
         Value::scalar(String::from("SerializedValue"))
     }
 
     fn from_input_value(v: &InputValue) -> Option<TestComplexScalar> {
-        if let Some(s) = v.as_scalar_value::<String>() {
-            if *s == "SerializedValue" {
+        if let Some(s) = v.as_scalar().and_then(ScalarValue::as_str) {
+            if s == "SerializedValue" {
                 return Some(TestComplexScalar);
             }
         }
@@ -31,13 +30,12 @@ impl GraphQLScalar for TestComplexScalar {
         None
     }
 
-    fn from_str<'a>(value: ScalarToken<'a>) -> ParseScalarResult<'a, DefaultScalarValue> {
-        <String as ParseScalarValue>::from_str(value)
+    fn from_str<'a>(value: ScalarToken<'a>) -> ParseScalarResult<'a, S> {
+        <String as ParseScalarValue<S>>::from_str(value)
     }
 }
 
 #[derive(GraphQLInputObject, Debug)]
-#[graphql(scalar = DefaultScalarValue)]
 struct TestInputObject {
     a: Option<String>,
     b: Option<Vec<Option<String>>>,
@@ -46,7 +44,6 @@ struct TestInputObject {
 }
 
 #[derive(GraphQLInputObject, Debug)]
-#[graphql(scalar = DefaultScalarValue)]
 struct TestNestedInputObject {
     na: TestInputObject,
     nb: String,
@@ -64,7 +61,9 @@ struct InputWithDefaults {
     a: i32,
 }
 
-#[crate::graphql_object]
+struct TestType;
+
+#[graphql_object]
 impl TestType {
     fn field_with_object_input(input: Option<TestInputObject>) -> String {
         format!("{:?}", input)
diff --git a/juniper/src/macros/tests/field.rs b/juniper/src/macros/tests/field.rs
index 1104454fa..3e884493e 100644
--- a/juniper/src/macros/tests/field.rs
+++ b/juniper/src/macros/tests/field.rs
@@ -24,7 +24,7 @@ use crate::{
 #[derive(Debug)]
 struct Root;
 
-#[graphql_object(interfaces = [InterfaceValue])]
+#[graphql_object(impl = InterfaceValue)]
 impl Root {
     fn simple() -> i32 {
         0
@@ -104,7 +104,7 @@ impl Root {
     }
 }
 
-#[graphql_interface(scalar = DefaultScalarValue)]
+#[graphql_interface]
 impl Interface for Root {
     fn simple(&self) -> i32 {
         0
@@ -147,7 +147,7 @@ impl Interface for Root {
     }
 }
 
-#[graphql_interface(for = Root, scalar = DefaultScalarValue)]
+#[graphql_interface(for = Root)]
 trait Interface {
     fn simple(&self) -> i32;
 
diff --git a/juniper/src/macros/tests/interface.rs b/juniper/src/macros/tests/interface.rs
index fffeded65..0f2eb3a57 100644
--- a/juniper/src/macros/tests/interface.rs
+++ b/juniper/src/macros/tests/interface.rs
@@ -29,44 +29,44 @@ impl Concrete {
     }
 }
 
-#[graphql_interface(for = Concrete, name = "ACustomNamedInterface", scalar = DefaultScalarValue)]
+#[graphql_interface(for = Concrete, name = "ACustomNamedInterface")]
 trait CustomName {
     fn simple(&self) -> i32;
 }
-#[graphql_interface(scalar = DefaultScalarValue)]
+#[graphql_interface]
 impl CustomName for Concrete {
     fn simple(&self) -> i32 {
         0
     }
 }
 
-#[graphql_interface(for = Concrete, scalar = DefaultScalarValue)]
+#[graphql_interface(for = Concrete)]
 trait WithLifetime<'a> {
     fn simple(&self) -> i32;
 }
-#[graphql_interface(scalar = DefaultScalarValue)]
+#[graphql_interface]
 impl<'a> WithLifetime<'a> for Concrete {
     fn simple(&self) -> i32 {
         0
     }
 }
 
-#[graphql_interface(for = Concrete, scalar = DefaultScalarValue)]
+#[graphql_interface(for = Concrete)]
 trait WithGenerics<T> {
     fn simple(&self) -> i32;
 }
-#[graphql_interface(scalar = DefaultScalarValue)]
+#[graphql_interface]
 impl<T> WithGenerics<T> for Concrete {
     fn simple(&self) -> i32 {
         0
     }
 }
 
-#[graphql_interface(for = Concrete, desc = "A description", scalar = DefaultScalarValue)]
+#[graphql_interface(for = Concrete, desc = "A description")]
 trait Description {
     fn simple(&self) -> i32;
 }
-#[graphql_interface(scalar = DefaultScalarValue)]
+#[graphql_interface]
 impl Description for Concrete {
     fn simple(&self) -> i32 {
         0
@@ -75,7 +75,7 @@ impl Description for Concrete {
 
 struct Root;
 
-#[crate::graphql_object]
+#[graphql_object]
 impl Root {
     fn custom_name() -> CustomNameValue {
         Concrete.into()
diff --git a/juniper/src/macros/tests/union.rs b/juniper/src/macros/tests/union.rs
index 01e3ff7d6..f36010b65 100644
--- a/juniper/src/macros/tests/union.rs
+++ b/juniper/src/macros/tests/union.rs
@@ -31,13 +31,13 @@ impl Concrete {
 }
 
 #[derive(GraphQLUnion)]
-#[graphql(name = "ACustomNamedUnion", scalar = DefaultScalarValue)]
+#[graphql(name = "ACustomNamedUnion")]
 enum CustomName {
     Concrete(Concrete),
 }
 
 #[derive(GraphQLUnion)]
-#[graphql(on Concrete = WithLifetime::resolve, scalar = DefaultScalarValue)]
+#[graphql(on Concrete = WithLifetime::resolve)]
 enum WithLifetime<'a> {
     #[graphql(ignore)]
     Int(PhantomData<&'a i32>),
@@ -54,7 +54,7 @@ impl<'a> WithLifetime<'a> {
 }
 
 #[derive(GraphQLUnion)]
-#[graphql(on Concrete = WithGenerics::resolve, scalar = DefaultScalarValue)]
+#[graphql(on Concrete = WithGenerics::resolve)]
 enum WithGenerics<T> {
     #[graphql(ignore)]
     Generic(T),
@@ -71,20 +71,19 @@ impl<T> WithGenerics<T> {
 }
 
 #[derive(GraphQLUnion)]
-#[graphql(description = "A description", scalar = DefaultScalarValue)]
+#[graphql(description = "A description")]
 enum DescriptionFirst {
     Concrete(Concrete),
 }
 
 struct Root;
 
-// FIXME: make async work
-#[crate::graphql_object(noasync)]
-impl<'a> Root {
+#[graphql_object]
+impl Root {
     fn custom_name() -> CustomName {
         CustomName::Concrete(Concrete)
     }
-    fn with_lifetime() -> WithLifetime<'a> {
+    fn with_lifetime() -> WithLifetime<'_> {
         WithLifetime::Int(PhantomData)
     }
     fn with_generics() -> WithGenerics<i32> {
diff --git a/juniper/src/parser/tests/document.rs b/juniper/src/parser/tests/document.rs
index 993a4edf4..5958ec7d9 100644
--- a/juniper/src/parser/tests/document.rs
+++ b/juniper/src/parser/tests/document.rs
@@ -162,11 +162,11 @@ fn issue_427_panic_is_not_expected() {
         }
     }
 
-    let schema = SchemaType::new::<QueryWithoutFloat, EmptyMutation<()>, EmptySubscription<()>>(
-        &(),
-        &(),
-        &(),
-    );
+    let schema = <SchemaType<DefaultScalarValue>>::new::<
+        QueryWithoutFloat,
+        EmptyMutation<()>,
+        EmptySubscription<()>,
+    >(&(), &(), &());
     let parse_result = parse_document_source(r##"{ echo(value: 123.0) }"##, &schema);
 
     assert_eq!(
diff --git a/juniper/src/tests/fixtures/starwars/schema.rs b/juniper/src/tests/fixtures/starwars/schema.rs
index 8693f4b2c..95e5be1da 100644
--- a/juniper/src/tests/fixtures/starwars/schema.rs
+++ b/juniper/src/tests/fixtures/starwars/schema.rs
@@ -2,14 +2,11 @@
 
 use std::{collections::HashMap, pin::Pin};
 
-use crate::{
-    graphql_interface, graphql_object, graphql_subscription, Context, DefaultScalarValue,
-    GraphQLEnum,
-};
+use crate::{graphql_interface, graphql_object, graphql_subscription, Context, GraphQLEnum};
 
 pub struct Query;
 
-#[graphql_object(context = Database, scalar = DefaultScalarValue)]
+#[graphql_object(context = Database)]
 /// The root query object of the schema
 impl Query {
     #[graphql(arguments(id(description = "id of the human")))]
@@ -51,7 +48,7 @@ pub enum Episode {
     Jedi,
 }
 
-#[graphql_interface(for = [Human, Droid], context = Database, scalar = DefaultScalarValue)]
+#[graphql_interface(for = [Human, Droid], context = Database)]
 /// A character in the Star Wars Trilogy
 pub trait Character {
     /// The id of the character
@@ -105,11 +102,7 @@ impl Human {
 }
 
 /// A humanoid creature in the Star Wars universe.
-#[graphql_object(
-    context = Database,
-    scalar = DefaultScalarValue,
-    interfaces = CharacterValue,
-)]
+#[graphql_object(context = Database, impl = CharacterValue)]
 impl Human {
     /// The id of the human
     fn id(&self) -> &str {
@@ -137,7 +130,7 @@ impl Human {
     }
 }
 
-#[graphql_interface(scalar = DefaultScalarValue)]
+#[graphql_interface]
 impl Character for Human {
     fn id(&self) -> &str {
         &self.id
@@ -195,11 +188,7 @@ impl Droid {
 }
 
 /// A mechanical creature in the Star Wars universe.
-#[graphql_object(
-    context = Database,
-    scalar = DefaultScalarValue,
-    interfaces = CharacterValue,
-)]
+#[graphql_object(context = Database, impl = CharacterValue)]
 impl Droid {
     /// The id of the droid
     fn id(&self) -> &str {
@@ -227,7 +216,7 @@ impl Droid {
     }
 }
 
-#[graphql_interface(scalar = DefaultScalarValue)]
+#[graphql_interface]
 impl Character for Droid {
     fn id(&self) -> &str {
         &self.id
diff --git a/juniper/src/tests/fixtures/starwars/schema_language.rs b/juniper/src/tests/fixtures/starwars/schema_language.rs
index 7a71c8d7a..044362f66 100644
--- a/juniper/src/tests/fixtures/starwars/schema_language.rs
+++ b/juniper/src/tests/fixtures/starwars/schema_language.rs
@@ -5,6 +5,8 @@ pub const STATIC_GRAPHQL_SCHEMA_DEFINITION: &str = include_str!("starwars.graphq
 
 #[cfg(test)]
 mod tests {
+    use pretty_assertions::assert_eq;
+
     use crate::{
         schema::model::RootNode,
         tests::fixtures::starwars::{
@@ -13,7 +15,6 @@ mod tests {
         },
         types::scalars::{EmptyMutation, EmptySubscription},
     };
-    use pretty_assertions::assert_eq;
 
     #[test]
     fn dynamic_schema_language_matches_static() {
diff --git a/juniper/src/validation/test_harness.rs b/juniper/src/validation/test_harness.rs
index ce1c7fce7..8d3acd195 100644
--- a/juniper/src/validation/test_harness.rs
+++ b/juniper/src/validation/test_harness.rs
@@ -827,7 +827,7 @@ where
     V: Visitor<'a, S> + 'a,
     F: Fn() -> V,
 {
-    let mut root = RootNode::new(r, m, s);
+    let mut root = RootNode::new_with_scalar_value(r, m, s);
 
     root.schema.add_directive(DirectiveType::new(
         "onQuery",