Skip to content

System.Text.Json emits uncompilable code #103515

Closed
@SteveDunn

Description

@SteveDunn

Description

I had a bug report for my open source source generator project:
SteveDunn/Vogen#622

I looked at the emitted code and can see that it emits value == null rather than value is null. This caused a compilation error because the type in question has overloaded == operators, so the C# compiler reports:
CS0034: Operator '==' is ambiguous on operands of type 'Foo' and '<null>'

The line in question in STJ is here: https://github.com/dotnet/runtime/blob/main/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs#L977

Reproduction Steps

[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Foo))]
internal partial class JsonSourceGenerationContext : JsonSerializerContext;

internal class Foo
{
    public Foo(string value) => Value = value;
    
    public string Value { get; }

    public bool Equals(string primitive) => Value.Equals(primitive);

    public override bool Equals(Object obj) => Equals(obj as Foo);
    public bool Equals(Foo foo) => Value == foo.Value;

    public static bool operator ==(Foo left, Foo right) => Equals(left, right);
    public static bool operator !=(Foo left, Foo right) => !Equals(left, right);

    public static bool operator ==(Foo left, string right) => Equals(left.Value, right);
    public static bool operator !=(Foo left, string right) => !Equals(left.Value, right);


    public override int GetHashCode()
    {
        unchecked // Overflow is fine, just wrap
        {
            int hash = (int)2166136261;
            hash = (hash * 16777619) ^ GetType().GetHashCode();
            hash = (hash * 16777619) ^ EqualityComparer<string>.Default.GetHashCode(Value);
            return hash;
        }
    }
}

This should compile, but doesn't. Instead, the compiler reports:

CS0034: Operator '==' is ambiguous on operands of type 'Foo' and '<null>'

Expected behavior

For it to compile

Actual behavior

Emits error CS0034: Operator '==' is ambiguous on operands of type 'Foo' and '<null>'

Regression?

No, I think the source generator stuff in STJ is fairly new

Known Workarounds

If I change my type from a class to a struct, then the null check isn't emitted.

Configuration

.NET 8, Windows 11, X64, not specific to any particular configuration.

Other information

I plan on doing a fix and a PR

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions