Skip to content

Conversation

@thomhurst
Copy link
Owner

Summary

  • Fix IgnoringType being bypassed when the ignored type is nested inside a ValueTuple or other value type implementing IEquatable<T>
  • Add ContainsIgnoredGenericArgument() helper method that recursively checks if a generic type contains ignored types
  • Add comprehensive tests for tuple scenarios

Problem

When a type is stored inside a ValueTuple (like (IgnoreMe, IgnoreMe)), the tuple is treated as a "primitive" type by TypeHelper.IsPrimitiveOrWellKnownType() because it implements IEquatable<T>. This causes the comparison to use Equals() directly instead of recursively comparing members, bypassing the ShouldIgnoreType check entirely.

Solution

Before treating a value type as primitive, check if it's a generic type containing any ignored types as generic arguments. If so, fall through to structural comparison which properly handles the ignored types.

Test plan

  • Added test: IgnoringType_In_Tuple_Properties_Are_Ignored - Basic tuple case
  • Added test: IgnoringType_In_Nested_Tuple_Properties_Are_Ignored - Nested tuples
  • Added test: IgnoringType_In_Mixed_Tuple_Still_Compares_Non_Ignored_Parts - Verifies non-ignored parts are still compared
  • Added test: IgnoringType_In_Mixed_Tuple_Passes_When_NonIgnored_Parts_Match - Mixed tuple with matching non-ignored values
  • All existing IgnoringTypeEquivalentTests pass (12 tests)
  • All CollectionStructuralEquivalenceTests pass (20 tests)
  • All EquivalentAssertionTests pass (29 tests)

Fixes #4320

🤖 Generated with Claude Code

When a type is stored inside a ValueTuple (or any value type implementing
IEquatable<T>), the tuple was treated as a "primitive" type and compared
directly with Equals() instead of recursively comparing members. This caused
IgnoringType to be bypassed for types nested within tuples.

The fix adds a ContainsIgnoredGenericArgument() check that recursively
inspects generic type arguments. When a generic value type contains an
ignored type, the comparison falls through to structural comparison which
properly handles the ignored type.

Fixes #4320

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@thomhurst
Copy link
Owner Author

Summary

Fixes a bug where IgnoringType was bypassed when ignored types were nested inside ValueTuples, by checking if generic types contain ignored type arguments before treating them as primitives.

Critical Issues

None found ✅

Suggestions

Performance: Hot path optimization

The new ContainsIgnoredGenericArgument() call at line 123 is in a hot path (called for every object comparison). Consider optimizing:

// Current: Always calls the method
if (TypeHelper.IsPrimitiveOrWellKnownType(actualType) && !ContainsIgnoredGenericArgument(actualType))

// Suggested: Only check generic types
if (TypeHelper.IsPrimitiveOrWellKnownType(actualType) && 
    !(actualType.IsGenericType && _ignoredTypes.Count > 0 && ContainsIgnoredGenericArgument(actualType)))

This avoids the method call overhead for non-generic types and when no types are being ignored (the common case). The early exits are already in ContainsIgnoredGenericArgument(), but pulling them inline removes the call overhead.

Alternatively, consider caching results or only checking value types that implement IEquatable (since that's the only category from TypeHelper that would include tuples).

Consider edge case: What about generic classes implementing IEquatable?

The fix specifically targets value types (which include ValueTuple), but could a similar issue occur with a generic class that implements IEquatable<T> and contains ignored types? Based on TypeHelper.cs:95-98, classes aren't treated as primitive even if they implement IEquatable, so this should be fine - but worth confirming this edge case is handled correctly.

Verdict

APPROVE - No critical issues. The fix correctly solves the reported bug with comprehensive tests. The performance suggestion is optional optimization.

@thomhurst thomhurst merged commit 11664dc into main Jan 12, 2026
13 checks passed
@thomhurst thomhurst deleted the fix/ignoring-type-in-valuetypes branch January 12, 2026 18:24
This was referenced Jan 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: IgnoringType is ignored if type is in a ValueType

2 participants