Skip to content

Regression in dotnet SDK 6.0.300: optimizing match with type checks #13175

@Jand42

Description

@Jand42

Add following code in a new F# console application project and run it:

type A() = class end
type B() = inherit A()
type C() = inherit A()

let toName (x: obj) =
    match x with
    | :? A when false -> "not possible"
    | :? B -> "B"
    | :? C -> "C"
    | _ -> "unknown"

printfn "%A" (toName (C()))

Expected behavior

This should print "C", as first case should never be matched, and we are passing in a value of type C. This works as expected with dotnet SDK up to 6.0.203.

Actual behavior

In Visual Studio 17.2.1, a warning appears on the line | :? C -> "C" : FS0026 This rule will never be matched.
This seems incorrect, and indeed it's another sign of the match expression analysis on type checks failing to recognize that B and C are two different subclasses of A.

Running the program in either VS2022 Version 17.2.1, or via dotnet SDK 6.0.300 or 7.0.100 preview 4 prints "B" .

In the example, all the classes are empty, but the issue persists if they have members, so this problem can lead to unexpected runtime null or type cast exceptions.

The issue also persists if the first case does not have when false but some other when guard that can be false. The only relevant thing to produce error is to have a type check for the base class of B.

In ILSpy, it's visible that the case returning "C" are optimized away - incorrectly:

public static string toName(object x)
{
	if (x is A)
	{
		return "B";
	}
	return "unknown";
}

Known workarounds

Both Visual Studio 2022 17.1.x and dotnet SDK 6.0.203 work as expected.

On affected SDK, you can separate the match expression into multiple ones, making sure that a check for a base type with a when guard then multiple checks for subtypes does not happen in a single match.

Related information

I have tested in Windows x64 only, project targeting .NET 6.0.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Area-Compiler-PatternMatchingpattern compilation, active patterns, performance, codegenBugImpact-High(Internal MS Team use only) Describes an issue with extreme impact on existing code.Regression

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions