Repository navigation
First class span's break EFC #109757
Copy link
Copy link
Closed as not planned
Labels
area-System.Linq.Expressionsbreaking-changeIssue or PR that represents a breaking API or functional change over a previous release.Issue or PR that represents a breaking API or functional change over a previous release.
Description
Description
When enabling LangVersion preview, that enables first class span's which then prefers MemoryExtensions.Contains over Enumerable.Contains which then breaks EFC. It seems that EFC internally calls Expression.Compile with preferInterpretation set to true which then eventually crashes.
Reproduction Steps
public class MyDbContext : DbContext
{
public DbSet<MyTable> MyTable { get; set; }
}
public class MyTable
{
public int Id { get; set; }
public string Name { get; set; }
}
string[] filters = ["Test"];
var dbContext = new MyDbContext();
dbContext.MyTable.Where(x => filters.Contains(x.Name)).ToList();Expected behavior
First class span's should not negatively affect EFC queries
Actual behavior
TypeLoadException: GenericArguments[1], 'System.Span`1[System.String]', on 'System.Linq.Expressions.Interpreter.FuncCallInstruction`2[T0,TRet]' violates the constraint of type parameter 'TRet'.
at System.RuntimeType.ValidateGenericArguments(MemberInfo definition, RuntimeType[] genericArguments, Exception e)
at System.RuntimeType.MakeGenericType(Type[] instantiation)
at System.Linq.Expressions.Interpreter.CallInstruction.GetHelperType(MethodInfo info, Type[] arrTypes)
at System.Linq.Expressions.Interpreter.CallInstruction.SlowCreate(MethodInfo info, ParameterInfo[] pis)
at System.Linq.Expressions.Interpreter.CallInstruction.Create(MethodInfo info, ParameterInfo[] parameters)
at System.Linq.Expressions.Interpreter.LightCompiler.CompileMethodCallExpression(Expression object, MethodInfo method, IArgumentProvider arguments)
at System.Linq.Expressions.Interpreter.LightCompiler.Compile(Expression expr)
at System.Linq.Expressions.Interpreter.LightCompiler.CompileConvertUnaryExpression(Expression expr)
at System.Linq.Expressions.Interpreter.LightCompiler.Compile(Expression expr)
at System.Linq.Expressions.Interpreter.LightCompiler.CompileTop(LambdaExpression node)
at System.Linq.Expressions.Expression`1.Compile(Boolean preferInterpretation)
at Microsoft.EntityFrameworkCore.Query.Internal.ExpressionTreeFuncletizer.<Evaluate>g__EvaluateCore|70_0(Expression expression, String& parameterName, Boolean& isContextAccessor) in Microsoft.EntityFrameworkCore.Query.Internal\ExpressionTreeFuncletizer.cs:line 1755
Regression?
Yes, only when enabling <LangVersion>preview</LangVersion>
Known Workarounds
set <LangVersion>preview</LangVersion> to anything but preview
Configuration
.NET 9.0.0
EFC 9.0.0
Other information
No response
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
area-System.Linq.Expressionsbreaking-changeIssue or PR that represents a breaking API or functional change over a previous release.Issue or PR that represents a breaking API or functional change over a previous release.
Activity
dotnet-policy-service commentedon Nov 12, 2024
Tagging subscribers to this area: @cston
See info in area-owners.md if you want to be subscribed.
jkotas commentedon Nov 13, 2024
cc @jjonescz
ChrisJollyAU commentedon Nov 14, 2024
@Suchiman Which version of VS are you on? 17.13 Preview 1?
I've just come across this when building the tests on efcore (same problem with MemoryExtesions.* vs IEnumerable.*) To me it only happened on 17.13 preview 1 AND
LangVersionispreview. Using 17.12 even with LangVersion onpreviewit was fine to buildSuchiman commentedon Nov 14, 2024
yes
ilGianfri commentedon Nov 16, 2024
I've attached a simple repro application ConsoleApp2.zip
On Visual Studio 17.12 it works, in 17.13p1 I get this issue with both .NET 8 and .NET 9 if LangVersion is set to preview
ChrisJollyAU commentedon Nov 17, 2024
Any relation to #96160 ?
jjonescz commentedon Dec 9, 2024
This was discussed at LDM with no change in the C# language planned. LINQ-to-DB should be probably updated to recognize
MemoryExtensions.Contains(and perhaps other similar methods) or users will need to update the calls (e.g., callingEnumerable.Containsexplicitly, or casting the array toIEnumerable<T>).GerardSmit commentedon Dec 9, 2024
Does this mean libraries need to fix this issue?
In that case it would mean .NET 9 (or lower) can never use the new C# LangVersion together with EF Core when First class span's get released?
You will either need to lower the C# LangVersion or upgrade .NET.
I know using newer C# LangVersions in older .NET versions isn't official supported, but I do this together with PolySharp a lot.
When I upgraded my .NET SDK locally, I got hit by this issue; since I had
<LangVersion>preview</LangVersion>in my project during the .NET 7 to .NET 8 transition, I forgot I had the preview version still configured 😄.jjonescz commentedon Dec 9, 2024
You can use .NET 9, just make sure you call
Enumerablemethods (e.g., by calling them in their non-extension static forms) instead ofMemoryExtensionsones. As you said, older .NETs are not supported with newer LangVersions, so workarounds like that are expected.jkotas commentedon Dec 9, 2024
This problem is not specific to EF Core. You can hit it with plain vanilla System.Linq.Expressions. It can be fixed in System.Linq.Expressions by adding support for byref-like types to the Interpreter, but that is in conflict with the effectively archived status of System.Linq.Expressions.
@jjonescz This needs a breaking change notice to be filled.
cc @jaredpar
dotnet-policy-service commentedon Dec 9, 2024
Added
needs-breaking-change-doc-createdlabel because this issue has thebreaking-changelabel.needs-breaking-change-doc-createdlabel.Tagging @dotnet/compat for awareness of the breaking change.
26 remaining items
ChrisJollyAU commentedon Nov 13, 2025
Its about the best at the moment. It works because first class spans were introduced in c# 14. So setting it to 13 is before that. The only downside is you can't use any new c# 14 (and future version) features
jjonescz commentedon Nov 13, 2025
If the error is caused by using a ReadOnlySpan during evaluation of the expression (which seems to be the case from the exception trace), a workaround can be defining your own
Containsextension method which C# will bind to instead ofMemoryExtensions.Contains, for example, (assuming your receiver is anT[]):And you can continue using C# 14 with this.
CypherPotato commentedon Nov 13, 2025
Tried this, but doens't work on EF. It claims that cannot translate the user-defined Contains method.
jjonescz commentedon Nov 13, 2025
But EF Core was updated to be able to handle
MemoryExtensions.Containsafaik. You've mentioned that you are using another library, so likely that one is the culprit.We would need a minimal reproducible example to investigate further I think.
CypherPotato commentedon Nov 13, 2025
There you go.
jjonescz commentedon Nov 14, 2025
Thanks. You are using EFCore v9, that does not seem to have the fix; if you update to v10, there is no crash.
ChrisJollyAU commentedon Nov 14, 2025
@jjonescz Actually it was ported back to v9 and v8 dotnet/efcore#35719 and dotnet/efcore#35720
I was having a look and whats happened is there is a specific case that gets overlooked.
Normally efcore only can manage a
Containswhen there is no EqualityComparer. But for some reason.Contains(bp.State)in your code gets to using theMemoryExtensions.Containsoverload that does take an EqualityComparer even though you didnt specify one. The value in this case isnullThat is why it is jumping over that and doesnt switch it back to theEnumerable.Containsjjonescz commentedon Nov 14, 2025
^ @roji
(still, using EFCore v10 works, so I guess just the backports are incomplete?)
ChrisJollyAU commentedon Nov 14, 2025
@jjonescz @roji
See dotnet/efcore#35547 and its resulting PR dotnet/efcore#36057
The changes of that weren't backported
CypherPotato commentedon Nov 14, 2025
I'm using Pomelo MySQL, which doens't runs on EFCore v10, so I will just sit down here and wait for Pomelo update their lib to v10.
gurustron commentedon Nov 15, 2025
@CypherPotato
Please see https://stackoverflow.com/a/79820634/2501279
Have you tried downgrading language version as suggested before? I.e.:
Also you can try explicitly using
Enumerable.Contains:Finally you can try using another type for the variable:
roji commentedon Nov 16, 2025
@ChrisJollyAU thanks for looking into this, and @CypherPotato thanks for reporting. I've opened dotnet/efcore#37176 to backport the fix to EF 8 and 9, and will try to do this ASAP for the upcoming patch releases. In the meantime, you can either upgrade to EF 10 (which already has the fix) or stay on C# 13 as suggested above.
As I don't think there's anything actionable remaining with this issue, I'll go ahead and close it. But feel free to continue posting and we can reopen if needed.