Skip to content

Fix relational operators failing for nullable IComparable types (e.g., Instant?)#975

Merged
StefH merged 5 commits intomasterfrom
copilot/fix-incompatible-operator-comparison
Mar 28, 2026
Merged

Fix relational operators failing for nullable IComparable types (e.g., Instant?)#975
StefH merged 5 commits intomasterfrom
copilot/fix-incompatible-operator-comparison

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 28, 2026

Relational operators (>, >=, <, <=) threw Operator '>' incompatible with operand types 'Instant?' and 'Instant?' for any nullable struct type implementing IComparable<T> that isn't explicitly listed in IRelationalSignatures.

Root cause

Nullable<T> does not itself implement IComparable<T> — only the underlying T does. In ParseComparisonOperator, the interface check was called directly on the nullable type, so typesAreSameAndImplementCorrectInterface was false for Instant?, falling through to CheckAndPromoteOperands which had no matching signature.

Fix

Use TypeHelper.GetNonNullableType() before the interface check so that T? is treated the same as T for IComparable<> and IEquatable<> resolution:

// Before
var interfaces = left.Type.GetInterfaces().Where(x => x.GetTypeInfo().IsGenericType);

// After
var typeToCheck = TypeHelper.GetNonNullableType(left.Type);
var interfaces = typeToCheck.GetInterfaces().Where(x => x.GetTypeInfo().IsGenericType);

This applies to both the IComparable<> check (relational operators) and the IEquatable<> check (equality operators) for consistency.

Tests

Added parameterized tests in NodaTimeConverterTests covering all relational operators (>, >=, <, <=) as well as equality operators (==, !=) against both Instant and Instant? properties, with count assertions verifying correct filtering semantics (including that null entries satisfy null != value in C# nullable semantics for the nullable case).


📱 Kick off Copilot coding agent tasks wherever you are with GitHub Mobile, available on iOS and Android.

Copilot AI and others added 2 commits March 28, 2026 10:36
…(>, >=, <, <=)

When comparing two values of the same nullable type (e.g., Instant?) using relational
operators, the check for IComparable<> interface was done on the nullable type itself
(Nullable<T>), which doesn't directly implement IComparable<>. The fix uses
TypeHelper.GetNonNullableType() to get the underlying type first, so that if T
implements IComparable<T>, nullable T? also works correctly with relational operators.

Fixes: Operator '>' incompatible with operand types 'Instant?' and 'Instant?'

Agent-Logs-Url: https://github.com/zzzprojects/System.Linq.Dynamic.Core/sessions/b497145d-ba3d-430a-b608-eda596efffdd

Co-authored-by: StefH <249938+StefH@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix operator '>' incompatible with nullable Instant comparison Fix relational operators failing for nullable IComparable types (e.g., Instant?) Mar 28, 2026
Copilot AI requested a review from StefH March 28, 2026 10:42
Copilot AI requested a review from StefH March 28, 2026 10:47
@StefH StefH marked this pull request as ready for review March 28, 2026 10:49
@StefH StefH merged commit 4ff9105 into master Mar 28, 2026
4 checks passed
@StefH StefH deleted the copilot/fix-incompatible-operator-comparison branch March 28, 2026 11:01
@StefH StefH added the bug label Mar 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Development

Successfully merging this pull request may close these issues.

Operator '>' incompatible with operand types 'Instant?' and 'Instant?'

2 participants