src/Executor/ReferenceExecutor.php
private function completeValue(
        Type $returnType,
        $fieldNodes,
        ResolveInfo $info,
        $path,
        &$result
    ) {
        $promise = $this->getPromise($result);
        // If result is a Promise, apply-lift over completeValue.
        if ($promise) {
            return $promise->then(function (&$resolved) use ($returnType, $fieldNodes, $info, $path) {
                return $this->completeValue($returnType, $fieldNodes, $info, $path, $resolved);
            });
        }
        if ($result instanceof Exception || $result instanceof Throwable) {
            throw $result;
        }
        // If field type is NonNull, complete for inner type, and throw field error
        // if result is null.
        if ($returnType instanceof NonNull) {
            $completed = $this->completeValue(
                $returnType->getWrappedType(),
                $fieldNodes,
                $info,
                $path,
                $result
            );
            if ($completed === null) {
                throw new InvariantViolation(
                    'Cannot return null for non-nullable field ' . $info->parentType . '.' . $info->fieldName . '.'
                );
            }

            return $completed;
        }
        // If result is null-like, return null.
        if ($result === null) {
            return null;
        }
        // If field type is List, complete each item in the list with the inner type
        if ($returnType instanceof ListOfType) {
            return $this->completeListValue($returnType, $fieldNodes, $info, $path, $result);
        }
        // Account for invalid schema definition when typeLoader returns different
        // instance than `resolveType` or $field->getType() or $arg->getType()
        if ($returnType !== $this->exeContext->schema->getType($returnType->name)) {
            $hint = '';
            if ($this->exeContext->schema->getConfig()->typeLoader) {
                $hint = sprintf(
                    'Make sure that type loader returns the same instance as defined in %s.%s',
                    $info->parentType,
                    $info->fieldName
                );
            }
            throw new InvariantViolation(
                sprintf(
                    'Schema must contain unique named types but contains multiple types named "%s". %s ' .
                    '(see http://webonyx.github.io/graphql-php/type-system/#type-registry).',
                    $returnType,
                    $hint
                )
            );
        }
        // If field type is Scalar or Enum, serialize to a valid value, returning
        // null if serialization is not possible.
        if ($returnType instanceof LeafType) {
            return $this->completeLeafValue($returnType, $result);
        }
        if ($returnType instanceof AbstractType) {
            return $this->completeAbstractValue($returnType, $fieldNodes, $info, $path, $result);
        }
        // Field type must be Object, Interface or Union and expect sub-selections.
        if ($returnType instanceof ObjectType) {
            return $this->completeObjectValue($returnType, $fieldNodes, $info, $path, $result);
        }
        throw new RuntimeException(sprintf('Cannot complete value of unexpected type "%s".', $returnType));
    }
private function completeValue(
        Type $returnType,
        $fieldNodes,
        ResolveInfo $info,
        $path,
        &$result
    ) {
        $promise = $this->getPromise($result);
        // If result is a Promise, apply-lift over completeValue.
        if ($promise) {
            return $promise->then(function (&$resolved) use ($returnType, $fieldNodes, $info, $path) {
                return $this->completeValue($returnType, $fieldNodes, $info, $path, $resolved);
            });
        }
        if ($result instanceof Exception || $result instanceof Throwable) {
            throw $result;
        }
        // If field type is NonNull, complete for inner type, and throw field error
        // if result is null.
        if ($returnType instanceof NonNull) {
            $completed = $this->completeValue(
                $returnType->getWrappedType(),
                $fieldNodes,
                $info,
                $path,
                $result
            );
            if ($completed === null) {
                throw new InvariantViolation(
                    'Cannot return null for non-nullable field ' . $info->parentType . '.' . $info->fieldName . '.'
                );
            }

            return $completed;
        }
        // If result is null-like, return null.
        if ($result === null) {
            return null;
        }
        // If field type is List, complete each item in the list with the inner type
        if ($returnType instanceof ListOfType) {
            return $this->completeListValue($returnType, $fieldNodes, $info, $path, $result);
        }
        // Account for invalid schema definition when typeLoader returns different
        // instance than `resolveType` or $field->getType() or $arg->getType()
        if ($returnType !== $this->exeContext->schema->getType($returnType->name)) {
            $hint = '';
            if ($this->exeContext->schema->getConfig()->typeLoader) {
                $hint = sprintf(
                    'Make sure that type loader returns the same instance as defined in %s.%s',
                    $info->parentType,
                    $info->fieldName
                );
            }
            throw new InvariantViolation(
                sprintf(
                    'Schema must contain unique named types but contains multiple types named "%s". %s ' .
                    '(see http://webonyx.github.io/graphql-php/type-system/#type-registry).',
                    $returnType,
                    $hint
                )
            );
        }
        // If field type is Scalar or Enum, serialize to a valid value, returning
        // null if serialization is not possible.
        if ($returnType instanceof LeafType) {
            return $this->completeLeafValue($returnType, $result);
        }
        if ($returnType instanceof AbstractType) {
            return $this->completeAbstractValue($returnType, $fieldNodes, $info, $path, $result);
        }
        // Field type must be Object, Interface or Union and expect sub-selections.
        if ($returnType instanceof ObjectType) {
            return $this->completeObjectValue($returnType, $fieldNodes, $info, $path, $result);
        }
        throw new RuntimeException(sprintf('Cannot complete value of unexpected type "%s".', $returnType));
    }
Implements the instructions for completeValue as defined in the
"Field entries" section of the spec.

If the field type is Non-Null, then this recursively completes the value
for the inner type. It throws a field error if that completion returns null,
as per the "Nullability" section of the spec.

If the field type is a List, then this recursively completes the value
for the inner type on each item in the list.

If the field type is a Scalar or Enum, ensures the completed value is a legal
value of the type by calling the `serialize` method of GraphQL type
definition.

If the field is an abstract type, determine the runtime type of the value
and then complete based on that type

Otherwise, the field type expects a sub-selection set, and will complete the
value by evaluating all sub-selections.

@param FieldNode[] $fieldNodes
@param string[]    $path
@param mixed       $result

@return mixed[]|mixed|Promise|null

@throws Error
@throws Throwable