@@ -967,6 +967,51 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCall)
967
967
}
968
968
}
969
969
970
+ // .NET 10 made changes to overload resolution to prefer Span-based overloads when those exist ("first-class spans").
971
+ // Unfortunately, the LINQ interpreter does not support ref structs, so we rewrite e.g. MemoryExtensions.Contains to
972
+ // Enumerable.Contains here. See https://github.com/dotnet/runtime/issues/109757.
973
+ if ( method . DeclaringType == typeof ( MemoryExtensions ) )
974
+ {
975
+ switch ( method . Name )
976
+ {
977
+ case nameof ( MemoryExtensions . Contains )
978
+ when methodCall . Arguments is [ var arg0 , var arg1 ] && TryUnwrapSpanImplicitCast ( arg0 , out var unwrappedArg0 ) :
979
+ {
980
+ return Visit (
981
+ Call (
982
+ EnumerableMethods . Contains . MakeGenericMethod ( methodCall . Method . GetGenericArguments ( ) [ 0 ] ) ,
983
+ unwrappedArg0 , arg1 ) ) ;
984
+ }
985
+
986
+ case nameof ( MemoryExtensions . SequenceEqual )
987
+ when methodCall . Arguments is [ var arg0 , var arg1 ]
988
+ && TryUnwrapSpanImplicitCast ( arg0 , out var unwrappedArg0 )
989
+ && TryUnwrapSpanImplicitCast ( arg1 , out var unwrappedArg1 ) :
990
+ return Visit (
991
+ Call (
992
+ EnumerableMethods . SequenceEqual . MakeGenericMethod ( methodCall . Method . GetGenericArguments ( ) [ 0 ] ) ,
993
+ unwrappedArg0 , unwrappedArg1 ) ) ;
994
+ }
995
+
996
+ static bool TryUnwrapSpanImplicitCast ( Expression expression , [ NotNullWhen ( true ) ] out Expression ? result )
997
+ {
998
+ if ( expression is MethodCallExpression
999
+ {
1000
+ Method : { Name : "op_Implicit" , DeclaringType : { IsGenericType : true } implicitCastDeclaringType } ,
1001
+ Arguments : [ var unwrapped ]
1002
+ }
1003
+ && implicitCastDeclaringType . GetGenericTypeDefinition ( ) is var genericTypeDefinition
1004
+ && ( genericTypeDefinition == typeof ( Span < > ) || genericTypeDefinition == typeof ( ReadOnlySpan < > ) ) )
1005
+ {
1006
+ result = unwrapped ;
1007
+ return true ;
1008
+ }
1009
+
1010
+ result = null ;
1011
+ return false ;
1012
+ }
1013
+ }
1014
+
970
1015
// Regular/arbitrary method handling from here on
971
1016
972
1017
// First, visit the object and all arguments, saving states as well
0 commit comments