diff --git a/src/registry/mod.rs b/src/registry/mod.rs index 5f0c6d58..5793388e 100644 --- a/src/registry/mod.rs +++ b/src/registry/mod.rs @@ -293,8 +293,22 @@ impl Registry { let mut dummy_registry = Registry::default(); T::create_type_info(&mut dummy_registry); if let Some(ty) = dummy_registry.types.remove(&*T::type_name()) { - self.types.extend(dummy_registry.types); - self.implements.extend(dummy_registry.implements); + // Do not overwrite existing types. + for (name, ty) in dummy_registry.types { + if !self.types.contains_key(&name) { + self.types.insert(name, ty); + } + } + + // Do not overwrite existing implements. + for (name, interfaces) in dummy_registry.implements { + if let Some(current_interfaces) = self.implements.get_mut(&name) { + current_interfaces.extend(interfaces); + } else { + self.implements.insert(name, interfaces); + } + } + ty } else { unreachable!() diff --git a/tests/merged_object.rs b/tests/merged_object.rs index 47f01ee5..7ead6c4f 100644 --- a/tests/merged_object.rs +++ b/tests/merged_object.rs @@ -290,3 +290,49 @@ pub async fn test_merged_entity() { }) ); } + +#[async_std::test] +pub async fn test_issue_316() { + #[derive(SimpleObject)] + struct Fruit { + id: ID, + name: String, + } + + struct Query; + + #[Object] + impl Query { + #[graphql(entity)] + async fn get_fruit(&self, id: ID) -> Fruit { + Fruit { + id, + name: "Apple".into(), + } + } + } + + #[derive(Default)] + struct Mutation1; + + #[Object] + impl Mutation1 { + async fn action1(&self) -> Fruit { + Fruit { + id: ID("hello".into()), + name: "Apple".into(), + } + } + } + + #[derive(MergedObject, Default)] + struct Mutation(Mutation1); + + // This works + let schema = Schema::new(Query, Mutation1, EmptySubscription); + assert!(schema.execute("{ _service { sdl }}").await.is_ok()); + + // This fails + let schema = Schema::new(Query, Mutation::default(), EmptySubscription); + assert!(schema.execute("{ _service { sdl }}").await.is_ok()); +}