Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 54 additions & 6 deletions spec/Section 3 -- Type System.md
Original file line number Diff line number Diff line change
Expand Up @@ -1594,9 +1594,9 @@ Input Objects are allowed to reference other Input Objects as field types. A
circular reference occurs when an Input Object references itself either directly
or through referenced Input Objects.

Circular references are generally allowed, however they may not be defined as an
unbroken chain of Non-Null singular fields. Such Input Objects are invalid
because there is no way to provide a legal value for them.
Circular references are generally allowed, however they may not form cycles such
that no finite value can be provided. Such Input Objects are invalid because
there is no way to provide a legal value for them.

This example of a circularly-referenced input type is valid as the field `self`
may be omitted or the value {null}.
Expand Down Expand Up @@ -1642,6 +1642,22 @@ input Second {
}
```

Because _OneOf Input Objects_ require exactly one field to be set and non-null,
nullable fields do not allow a finite value to be provided as they do in other
Input Objects. This example is invalid because providing a value for `First`
requires a non-null `Second`, and constructing a `Second` requires a non-null
`First`:

```graphql counter-example
input First @oneOf {
second: Second
}

input Second {
first: First!
}
```

**Result Coercion**

An input object is never a valid result. Input Object types cannot be the return
Expand Down Expand Up @@ -1726,9 +1742,7 @@ input ExampleInputObject {
5. If the Input Object is a _OneOf Input Object_ then:
1. The type of the input field must be nullable.
2. The input field must not have a default value.
3. If an Input Object references itself either directly or through referenced
Input Objects, at least one of the fields in the chain of references must be
either a nullable or a List type.
3. {InputObjectCanBeProvidedAFiniteValue(inputObject)} must be {true}.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit... Maybe:

Suggested change
3. {InputObjectCanBeProvidedAFiniteValue(inputObject)} must be {true}.
3. {InputObjectHasUnbreakableCycle(inputObject)} must be {false}.

4. {InputObjectDefaultValueHasCycle(inputObject)} must be {false}.

InputObjectDefaultValueHasCycle(inputObject, defaultValue, visitedFields):
Expand Down Expand Up @@ -1768,6 +1782,40 @@ InputFieldDefaultValueHasCycle(field, defaultValue, visitedFields):
- Return {InputObjectDefaultValueHasCycle(namedFieldType, fieldDefaultValue,
nextVisitedFields)}.

InputObjectCanBeProvidedAFiniteValue(inputObject, visited):

- If {visited} is not provided, initialize it to the empty set.
- If {inputObject} is in {visited}:
- Return {false}.
- Let {nextVisited} be a new set containing {inputObject} and everything
from {visited}.
- If {inputObject} is a _OneOf Input Object_:
- For each field {field} of {inputObject}:
- Let {fieldType} be the type of {field}.
- If {FieldTypeCanBeProvidedAFiniteValue(fieldType, nextVisited)}:
- Return {true}.
- Return {false}.
- Otherwise:
- For each field {field} of {inputObject}:
- Let {fieldType} be the type of {field}.
- If {fieldType} is Non-Null:
- Let {innerType} be the type wrapped by {fieldType}.
- If not {FieldTypeCanBeProvidedAFiniteValue(innerType, nextVisited)}:
Comment on lines +1802 to +1803
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Let {innerType} be the type wrapped by {fieldType}.
- If not {FieldTypeCanBeProvidedAFiniteValue(innerType, nextVisited)}:
- Let {nullableType} be the unwrapped nullable type of {fieldType}.
- If not {FieldTypeCanBeProvidedAFiniteValue(nullableType, nextVisited)}:

- Return {false}.
- Return {true}.

FieldTypeCanBeProvidedAFiniteValue(fieldType, visited):

- If {fieldType} is a List type:
- Return {true}.
- If {fieldType} is a Non-Null type:
- Let {innerType} be the type wrapped by {fieldType}.
- Return {FieldTypeCanBeProvidedAFiniteValue(innerType, visited)}.
Comment on lines +1812 to +1813
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Let {innerType} be the type wrapped by {fieldType}.
- Return {FieldTypeCanBeProvidedAFiniteValue(innerType, visited)}.
- Let {nullableType} be the unwrapped nullable type of {fieldType}.
- Return {FieldTypeCanBeProvidedAFiniteValue(nullableType, visited)}.

- Assert: {fieldType} is a named type.
- If {fieldType} is not an Input Object type:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if we need this added for clarity... To make it clear that OneOf Input Objects are included?

Suggested change
- If {fieldType} is not an Input Object type:
- If {fieldType} is not an Input Object type (including variants):

- Return {true}.
- Return {InputObjectCanBeProvidedAFiniteValue(fieldType, visited)}.

### OneOf Input Objects

:: A _OneOf Input Object_ is a special variant of _Input Object_ where exactly
Expand Down
Loading