Skip to content

Commit 06d4748

Browse files
swalkinshawclaude
andcommitted
Cache mutually_exclusive? results and use Array#intersect?
Cache type-pair mutual exclusivity checks to avoid repeated possible_types lookups for the same pair. Use object identity (equal?) instead of == for type comparison, and Array#intersect? instead of (& other).empty? for the set overlap check. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent d246f7b commit 06d4748

1 file changed

Lines changed: 28 additions & 10 deletions

File tree

lib/graphql/static_validation/rules/fields_will_merge.rb

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ def initialize(*)
3939
@conflict_count = 0
4040
@max_errors = context.max_errors
4141
@fragments = context.fragments
42+
@mutually_exclusive_cache = {}.compare_by_identity
4243
end
4344

4445
def on_operation_definition(node, _parent)
@@ -483,24 +484,41 @@ def mutually_exclusive?(parents1, parents2)
483484
if parents1.empty? || parents2.empty?
484485
false
485486
elsif parents1.length == parents2.length
486-
parents1.length.times.any? do |i|
487+
i = 0
488+
len = parents1.length
489+
while i < len
487490
type1 = parents1[i - 1]
488491
type2 = parents2[i - 1]
489-
if type1 == type2
490-
# If the types we're comparing are the same type,
491-
# then they aren't mutually exclusive
492-
false
493-
else
494-
# Check if these two scopes have _any_ types in common.
495-
possible_right_types = @types.possible_types(type1)
496-
possible_left_types = @types.possible_types(type2)
497-
(possible_right_types & possible_left_types).empty?
492+
unless type1.equal?(type2)
493+
# Check cache for this type pair
494+
inner = @mutually_exclusive_cache[type1]
495+
if inner
496+
cached = inner[type2]
497+
if cached.nil?
498+
cached = types_mutually_exclusive?(type1, type2)
499+
inner[type2] = cached
500+
end
501+
else
502+
cached = types_mutually_exclusive?(type1, type2)
503+
inner = {}.compare_by_identity
504+
inner[type2] = cached
505+
@mutually_exclusive_cache[type1] = inner
506+
end
507+
return true if cached
498508
end
509+
i += 1
499510
end
511+
false
500512
else
501513
true
502514
end
503515
end
516+
517+
def types_mutually_exclusive?(type1, type2)
518+
possible_right_types = @types.possible_types(type1)
519+
possible_left_types = @types.possible_types(type2)
520+
!possible_right_types.intersect?(possible_left_types)
521+
end
504522
end
505523
end
506524
end

0 commit comments

Comments
 (0)