@@ -967,6 +967,51 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCall)
967967 }
968968 }
969969
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+
9701015 // Regular/arbitrary method handling from here on
9711016
9721017 // First, visit the object and all arguments, saving states as well
0 commit comments