Skip to content

Fix IDE0048 to trigger consistently for is null and is not null in coalesce expressions#81489

Merged
CyrusNajmabadi merged 5 commits intomainfrom
copilot/refactor-null-coalescing-expressions
Dec 1, 2025
Merged

Fix IDE0048 to trigger consistently for is null and is not null in coalesce expressions#81489
CyrusNajmabadi merged 5 commits intomainfrom
copilot/refactor-null-coalescing-expressions

Conversation

Copy link
Contributor

Copilot AI commented Nov 30, 2025

IDE0048 triggers for left?.Equals(right) ?? right is null but not for left?.Equals(right) ?? right is not null.

// Triggers IDE0048
public static bool operator ==(Test? left, Test? right) => left?.Equals(right) ?? right is null;

// Does NOT trigger IDE0048 (should)
public static bool operator !=(Test? left, Test? right) => !left?.Equals(right) ?? right is not null;

Changes

  • IsBinaryLike: Added pattern match for IsPatternExpressionSyntax { Pattern: UnaryPatternSyntax { Pattern: ConstantPatternSyntax } } to recognize is not null
  • GetPartsOfBinaryLike: Added corresponding case to extract parts from the is not null pattern
  • TryGetAppropriateParent: Updated to navigate through UnaryPatternSyntax when the constant pattern is wrapped by not

The root cause was that is null produces ConstantPatternSyntax directly, while is not null wraps it in a UnaryPatternSyntax.

Fixes #81488

Original prompt

This section details on the original issue you should resolve

<issue_title>IDE0048 triggers for is null but not for is not null in null-coalescing expressions</issue_title>
<issue_description>Version Used:
Visual Studio 2026 v18.0.0
.NET 10

Steps to Reproduce:

  1. Create a class like the following:
internal sealed class Test
{
    public override bool Equals(object? obj)
    {
        return Equals(obj as Test);
    }

    public override int GetHashCode()
    {
        return 0;
    }

    public static bool operator ==(Test? left, Test? right) => left?.Equals(right) ?? right is null; // <- Triggers IDE0048

    public static bool operator !=(Test? left, Test? right) => !left?.Equals(right) ?? right is not null; // <- Does not trigger IDE0048
}
  1. Observe that left?.Equals(right) ?? right is null; triggers IDE0048, while !left?.Equals(right) ?? right is not null; does not.

Diagnostic Id:
IDE0048 Parentheses should be added for clarity

Expected Behavior:
IDE0048 should behave consistently, it should either trigger for both cases or for neither. For reference, Rider considers parentheses redundant in both cases.

Actual Behavior:
IDE0048 is triggered for the is null check but not for the is not null check.</issue_description>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

…ce expressions

Co-authored-by: CyrusNajmabadi <4564579+CyrusNajmabadi@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix IDE0048 issue for is not null in expressions Fix IDE0048 to trigger consistently for is null and is not null in coalesce expressions Nov 30, 2025
Copilot AI requested a review from CyrusNajmabadi November 30, 2025 14:05
@CyrusNajmabadi CyrusNajmabadi marked this pull request as ready for review November 30, 2025 18:28
@CyrusNajmabadi CyrusNajmabadi requested a review from a team as a code owner November 30, 2025 18:28
@CyrusNajmabadi CyrusNajmabadi merged commit 354c1a4 into main Dec 1, 2025
26 checks passed
@CyrusNajmabadi CyrusNajmabadi deleted the copilot/refactor-null-coalescing-expressions branch December 1, 2025 17:29
@dotnet-policy-service dotnet-policy-service bot added this to the Next milestone Dec 1, 2025
@davidwengier davidwengier modified the milestones: Next, 18.3 Jan 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

IDE0048 triggers for is null but not for is not null in null-coalescing expressions

4 participants