Skip to content
Open
Changes from 1 commit
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
4 changes: 4 additions & 0 deletions src/Type/Schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ public function __construct($config)
$this->extensionASTNodes = $config->extensionASTNodes;

$this->config = $config;

foreach ($this->config->types as $type) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Users may specify types in a multitude of ways, its type is iterable<Type&NamedType>|(callable(): iterable<Type&NamedType>)|iterable<(callable(): Type&NamedType)>|(callable(): iterable<(callable(): Type&NamedType)>). The code you wrote does not work with some of those options.

$this->resolvedTypes[$type->name()] = $type;

Copilot AI Feb 16, 2026

Copy link

Choose a reason for hiding this comment

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

The constructor does not validate for duplicate type names, but getTypeMap() does (line 145-148). This means duplicate types in the 'types' config will silently overwrite each other in the constructor, potentially causing unexpected behavior. The validation check from getTypeMap() should be added to the constructor loop as well.

Suggested change
$this->resolvedTypes[$type->name()] = $type;
$typeName = $type->name();
if (isset($this->resolvedTypes[$typeName]) && $this->resolvedTypes[$typeName] !== $type) {
throw new InvariantViolation(
'Schema must contain unique named types but contains multiple types named ' . $typeName
);
}
$this->resolvedTypes[$typeName] = $type;

Copilot uses AI. Check for mistakes.
}
Comment on lines +111 to +119

Copilot AI Feb 16, 2026

Copy link

Choose a reason for hiding this comment

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

Eagerly resolving all types in the constructor defeats the purpose of lazy loading and can negatively impact performance for large schemas. If the types array contains many types or lazy callables, all of them will be resolved immediately during schema construction, even if they're never used. This is particularly problematic when combined with typeLoader, as it changes the expected behavior where types are only loaded on-demand. Consider documenting this behavior change and its performance implications.

Suggested change
if (is_callable($types)) {
$types = $types();
}
foreach ($types as $typeOrLazyType) {
/** @var Type|callable(): Type $typeOrLazyType */
$type = self::resolveType($typeOrLazyType);
assert($type instanceof NamedType);
$this->resolvedTypes[$type->name()] = $type;
}
// If $types is a callable, defer its execution to preserve lazy loading.
if (! is_callable($types)) {
foreach ($types as $typeOrLazyType) {
/** @var Type|callable(): Type $typeOrLazyType */
$type = self::resolveType($typeOrLazyType);
assert($type instanceof NamedType);
$this->resolvedTypes[$type->name()] = $type;
}
}

Copilot uses AI. Check for mistakes.
}

/**
Expand Down