Skip to content

Using construct "if (pointer is null)" produces invalid IL on latest Roslyn #48563

@GrabYourPitchforks

Description

@GrabYourPitchforks

The construct if (pointer is null) produces invalid IL, per https://sharplab.io/ running on latest Roslyn master.

public unsafe class C {
    public static bool Foo(void* ptr) {
        return (ptr == null);
    }
    
    public static bool Bar(void* ptr) {
        return (ptr is null);
    }
}
.class public auto ansi beforefieldinit C
    extends [System.Private.CoreLib]System.Object
{
    // Methods
    .method public hidebysig static 
        bool Foo (
            void* ptr
        ) cil managed 
    {
        // Method begins at RVA 0x2050
        // Code size 6 (0x6)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: ldc.i4.0
        IL_0002: conv.u
        IL_0003: ceq
        IL_0005: ret
    } // end of method C::Foo

    .method public hidebysig static 
        bool Bar (
            void* ptr
        ) cil managed 
    {
        // Method begins at RVA 0x2057
        // Code size 5 (0x5)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: ldnull
        IL_0002: ceq
        IL_0004: ret
    } // end of method C::Bar
} // end of class C

In the Foo method, the compiler emits a ceq instruction comparing a native int against a native int. However, in the Bar method, the compiler emits a ceq instruction comparing a native int against an O (see ECMA-335, Sec. III.3.45).

Per ECMA-335, Sec. III.1.5 (Table III.4), it is illegal for the IL stream to use ceq to compare a native int against an O. We even had to work around this in the runtime in our implementation of Unsafe.IsNullRef (see source).

The expected behavior is that the if (pointer is null) construct should continue to emit the same IL that the if (pointer == null) construct did.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions