Skip to content

.NET 10 RC 2: If statement evaluates incorrectly even everything is in order #120792

@r-oelsner

Description

@r-oelsner

Description

I am very sorry if this report is not up to expected standards but this is my first time reporting.
I observed a strange behaviour that i cannot even describe clearly with words alone.

I am using:
Windows 10
VisualStudio 2026 (Insiders [11111.16])
.net 10.0.100-rc.2

The issue i got is related in evaluating Expressions for a custom implemented IQueryProvider. The code that causes the issue worked perfectly fine in .net8 as well as .net9.

Also this issue only occurs in Release-Builds and does not happen for Debug-Builds, for me that is so far.

`

private static void QueryableTakeHandler(ref AggregateStatementContext state, Expression source, MethodCallExpression take)
{
	if ( state.IsClosed )
		throw new InvalidOperationException("Context is already closed.");

	Expression value = take.Arguments[1].Resolve();

	if ( value is not ConstantExpression constant || !constant.Type.Equals(typeof(int)) || constant.Value == null )
		throw new InvalidOperationException("Linq.Take: Argument expression could not be resolved to a constant expression.");

	state.Add(new AggregateSegment { Type = DefinitionType.Limit, Expression = constant });
}

`

Since .net10 the if-statement evaluates that the Expression is not valid and so the InvalidOperationException in thrown. To figure out what is going on i changed the code to:

`

private static void QueryableTakeHandler(ref AggregateStatementContext state, Expression source, MethodCallExpression take)
{
	if ( state.IsClosed )
		throw new InvalidOperationException("Context is already closed.");

	Expression value = take.Arguments[1].Resolve();
	ConstantExpression? constant = value as ConstantExpression;

	if ( constant == null || !constant.Type.Equals(typeof(int)) || constant.Value == null )
		throw new InvalidOperationException($"Linq.Take: Argument expression could not be resolved to a constant expression. ({value.GetType().FormatName()} | {((constant != null) ? constant.Type.FormatName() : "")} | {((constant != null) ? constant.Value ?? "" : "")})");

	state.Add(new AggregateSegment { Type = DefinitionType.Limit, Expression = constant });
}

`

With this change the Exception is still thrown and looks like this:
Linq.Take: Argument expression could not be resolved to a constant expression. (ConstantExpression | Int32 | 25)

The weird part comes now. When i switch places of !constant.Type.Equals(typeof(int)) and constant.Value == null, so that the Null-Check is done first and the Type-Check second then everything works just fine.

`

private static void QueryableTakeHandler(ref AggregateStatementContext state, Expression source, MethodCallExpression take)
{
	if ( state.IsClosed )
		throw new InvalidOperationException("Context is already closed.");

	Expression value = take.Arguments[1].Resolve();
	ConstantExpression? constant = value as ConstantExpression;

	if ( constant == null || constant.Value == null || !constant.Type.Equals(typeof(int)) )
		throw new InvalidOperationException($"Linq.Take: Argument expression could not be resolved to a constant expression. ({value.GetType().FormatName()} | {((constant != null) ? constant.Type.FormatName() : "")} | {((constant != null) ? constant.Value ?? "" : "")})");

	state.Add(new AggregateSegment { Type = DefinitionType.Limit, Expression = constant });
}

`

I am not sure if this is the right place to post this issue and i do not even know if it is related to .net10 or may be an Compiler issue (code-optimization?).

If there is anything i can provide additionally i will happily do so because i think this is wild one.

Best regards
R.Oelsner

Reproduction Steps

I do not know if this can be reproduced. On my setup it is enough to change the order of checks in the if-statement mentioned in the description

Expected behavior

I expect that the behaviour of the if-statement should not change in any way.

Actual behavior

The if-statement evaluates that the Expression is invalid even if the Expression is perfectly fine

Regression?

This code was in place at least since 16.04.2024 (.net 8.0.203). Because of a bigger refactoring its hard to get the full history but i think this should be enough i hope.

Known Workarounds

The workaround is explained in the description but i do not know if this is only an issue for me or if this is a general issue.

Configuration

Windows 10 Pro x64 (22H2 Build: 19045.6332)
VisualStudio 2026 (Insiders [11111.16])
.net 10.0.100-rc.2

Other information

No response

Metadata

Metadata

Assignees

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Type

Projects

Status

Done

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions