Skip to content

Commit 4ac3767

Browse files
authored
Fix C# 14 Contains translation for MEVD providers (#13407)
This fixes the failing Contains-related MEVD filter tests. I'm not quite sure what happened since I merged #13263 (at which point these were passing) - possibly #13395 - but these pass again. Note that I still plan to go back and design the translators in a way which doesn't require the code to be duplicated, but we shouldn't block on that.
1 parent 0195778 commit 4ac3767

File tree

9 files changed

+288
-45
lines changed

9 files changed

+288
-45
lines changed

dotnet/src/VectorData/AzureAISearch/AzureAISearchFilterTranslator.cs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -207,14 +207,41 @@ private void TranslateMethodCall(MethodCallExpression methodCall)
207207

208208
static bool TryUnwrapSpanImplicitCast(Expression expression, [NotNullWhen(true)] out Expression? result)
209209
{
210-
if (expression is UnaryExpression
210+
// Different versions of the compiler seem to generate slightly different expression tree representations for this
211+
// implicit cast:
212+
var (unwrapped, castDeclaringType) = expression switch
213+
{
214+
UnaryExpression
211215
{
212216
NodeType: ExpressionType.Convert,
213217
Method: { Name: "op_Implicit", DeclaringType: { IsGenericType: true } implicitCastDeclaringType },
214-
Operand: var unwrapped
215-
}
216-
&& implicitCastDeclaringType.GetGenericTypeDefinition() is var genericTypeDefinition
217-
&& (genericTypeDefinition == typeof(Span<>) || genericTypeDefinition == typeof(ReadOnlySpan<>)))
218+
Operand: var operand
219+
} => (operand, implicitCastDeclaringType),
220+
221+
MethodCallExpression
222+
{
223+
Method: { Name: "op_Implicit", DeclaringType: { IsGenericType: true } implicitCastDeclaringType },
224+
Arguments: [var firstArgument]
225+
} => (firstArgument, implicitCastDeclaringType),
226+
227+
_ => (null, null)
228+
};
229+
230+
// For the dynamic case, there's a Convert node representing an up-cast to object[]; unwrap that too.
231+
if (unwrapped is UnaryExpression
232+
{
233+
NodeType: ExpressionType.Convert,
234+
Method: null
235+
} convert
236+
&& convert.Type == typeof(object[]))
237+
{
238+
result = convert.Operand;
239+
return true;
240+
}
241+
242+
if (unwrapped is not null
243+
&& castDeclaringType?.GetGenericTypeDefinition() is var genericTypeDefinition
244+
&& (genericTypeDefinition == typeof(Span<>) || genericTypeDefinition == typeof(ReadOnlySpan<>)))
218245
{
219246
result = unwrapped;
220247
return true;

dotnet/src/VectorData/Common/SqlFilterTranslator.cs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -259,14 +259,41 @@ private void TranslateMethodCall(MethodCallExpression methodCall, bool isSearchC
259259

260260
static bool TryUnwrapSpanImplicitCast(Expression expression, [NotNullWhen(true)] out Expression? result)
261261
{
262-
if (expression is UnaryExpression
262+
// Different versions of the compiler seem to generate slightly different expression tree representations for this
263+
// implicit cast:
264+
var (unwrapped, castDeclaringType) = expression switch
265+
{
266+
UnaryExpression
263267
{
264268
NodeType: ExpressionType.Convert,
265269
Method: { Name: "op_Implicit", DeclaringType: { IsGenericType: true } implicitCastDeclaringType },
266-
Operand: var unwrapped
267-
}
268-
&& implicitCastDeclaringType.GetGenericTypeDefinition() is var genericTypeDefinition
269-
&& (genericTypeDefinition == typeof(Span<>) || genericTypeDefinition == typeof(ReadOnlySpan<>)))
270+
Operand: var operand
271+
} => (operand, implicitCastDeclaringType),
272+
273+
MethodCallExpression
274+
{
275+
Method: { Name: "op_Implicit", DeclaringType: { IsGenericType: true } implicitCastDeclaringType },
276+
Arguments: [var firstArgument]
277+
} => (firstArgument, implicitCastDeclaringType),
278+
279+
_ => (null, null)
280+
};
281+
282+
// For the dynamic case, there's a Convert node representing an up-cast to object[]; unwrap that too.
283+
if (unwrapped is UnaryExpression
284+
{
285+
NodeType: ExpressionType.Convert,
286+
Method: null
287+
} convert
288+
&& convert.Type == typeof(object[]))
289+
{
290+
result = convert.Operand;
291+
return true;
292+
}
293+
294+
if (unwrapped is not null
295+
&& castDeclaringType?.GetGenericTypeDefinition() is var genericTypeDefinition
296+
&& (genericTypeDefinition == typeof(Span<>) || genericTypeDefinition == typeof(ReadOnlySpan<>)))
270297
{
271298
result = unwrapped;
272299
return true;

dotnet/src/VectorData/CosmosMongoDB/CosmosMongoFilterTranslator.cs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -196,14 +196,41 @@ private BsonDocument TranslateMethodCall(MethodCallExpression methodCall)
196196

197197
static bool TryUnwrapSpanImplicitCast(Expression expression, [NotNullWhen(true)] out Expression? result)
198198
{
199-
if (expression is UnaryExpression
199+
// Different versions of the compiler seem to generate slightly different expression tree representations for this
200+
// implicit cast:
201+
var (unwrapped, castDeclaringType) = expression switch
202+
{
203+
UnaryExpression
200204
{
201205
NodeType: ExpressionType.Convert,
202206
Method: { Name: "op_Implicit", DeclaringType: { IsGenericType: true } implicitCastDeclaringType },
203-
Operand: var unwrapped
204-
}
205-
&& implicitCastDeclaringType.GetGenericTypeDefinition() is var genericTypeDefinition
206-
&& (genericTypeDefinition == typeof(Span<>) || genericTypeDefinition == typeof(ReadOnlySpan<>)))
207+
Operand: var operand
208+
} => (operand, implicitCastDeclaringType),
209+
210+
MethodCallExpression
211+
{
212+
Method: { Name: "op_Implicit", DeclaringType: { IsGenericType: true } implicitCastDeclaringType },
213+
Arguments: [var firstArgument]
214+
} => (firstArgument, implicitCastDeclaringType),
215+
216+
_ => (null, null)
217+
};
218+
219+
// For the dynamic case, there's a Convert node representing an up-cast to object[]; unwrap that too.
220+
if (unwrapped is UnaryExpression
221+
{
222+
NodeType: ExpressionType.Convert,
223+
Method: null
224+
} convert
225+
&& convert.Type == typeof(object[]))
226+
{
227+
result = convert.Operand;
228+
return true;
229+
}
230+
231+
if (unwrapped is not null
232+
&& castDeclaringType?.GetGenericTypeDefinition() is var genericTypeDefinition
233+
&& (genericTypeDefinition == typeof(Span<>) || genericTypeDefinition == typeof(ReadOnlySpan<>)))
207234
{
208235
result = unwrapped;
209236
return true;

dotnet/src/VectorData/CosmosNoSql/CosmosNoSqlFilterTranslator.cs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -250,14 +250,41 @@ private void TranslateMethodCall(MethodCallExpression methodCall)
250250

251251
static bool TryUnwrapSpanImplicitCast(Expression expression, [NotNullWhen(true)] out Expression? result)
252252
{
253-
if (expression is UnaryExpression
253+
// Different versions of the compiler seem to generate slightly different expression tree representations for this
254+
// implicit cast:
255+
var (unwrapped, castDeclaringType) = expression switch
256+
{
257+
UnaryExpression
254258
{
255259
NodeType: ExpressionType.Convert,
256260
Method: { Name: "op_Implicit", DeclaringType: { IsGenericType: true } implicitCastDeclaringType },
257-
Operand: var unwrapped
258-
}
259-
&& implicitCastDeclaringType.GetGenericTypeDefinition() is var genericTypeDefinition
260-
&& (genericTypeDefinition == typeof(Span<>) || genericTypeDefinition == typeof(ReadOnlySpan<>)))
261+
Operand: var operand
262+
} => (operand, implicitCastDeclaringType),
263+
264+
MethodCallExpression
265+
{
266+
Method: { Name: "op_Implicit", DeclaringType: { IsGenericType: true } implicitCastDeclaringType },
267+
Arguments: [var firstArgument]
268+
} => (firstArgument, implicitCastDeclaringType),
269+
270+
_ => (null, null)
271+
};
272+
273+
// For the dynamic case, there's a Convert node representing an up-cast to object[]; unwrap that too.
274+
if (unwrapped is UnaryExpression
275+
{
276+
NodeType: ExpressionType.Convert,
277+
Method: null
278+
} convert
279+
&& convert.Type == typeof(object[]))
280+
{
281+
result = convert.Operand;
282+
return true;
283+
}
284+
285+
if (unwrapped is not null
286+
&& castDeclaringType?.GetGenericTypeDefinition() is var genericTypeDefinition
287+
&& (genericTypeDefinition == typeof(Span<>) || genericTypeDefinition == typeof(ReadOnlySpan<>)))
261288
{
262289
result = unwrapped;
263290
return true;

dotnet/src/VectorData/MongoDB/MongoFilterTranslator.cs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -201,14 +201,41 @@ private BsonDocument TranslateMethodCall(MethodCallExpression methodCall)
201201

202202
static bool TryUnwrapSpanImplicitCast(Expression expression, [NotNullWhen(true)] out Expression? result)
203203
{
204-
if (expression is UnaryExpression
204+
// Different versions of the compiler seem to generate slightly different expression tree representations for this
205+
// implicit cast:
206+
var (unwrapped, castDeclaringType) = expression switch
207+
{
208+
UnaryExpression
205209
{
206210
NodeType: ExpressionType.Convert,
207211
Method: { Name: "op_Implicit", DeclaringType: { IsGenericType: true } implicitCastDeclaringType },
208-
Operand: var unwrapped
209-
}
210-
&& implicitCastDeclaringType.GetGenericTypeDefinition() is var genericTypeDefinition
211-
&& (genericTypeDefinition == typeof(Span<>) || genericTypeDefinition == typeof(ReadOnlySpan<>)))
212+
Operand: var operand
213+
} => (operand, implicitCastDeclaringType),
214+
215+
MethodCallExpression
216+
{
217+
Method: { Name: "op_Implicit", DeclaringType: { IsGenericType: true } implicitCastDeclaringType },
218+
Arguments: [var firstArgument]
219+
} => (firstArgument, implicitCastDeclaringType),
220+
221+
_ => (null, null)
222+
};
223+
224+
// For the dynamic case, there's a Convert node representing an up-cast to object[]; unwrap that too.
225+
if (unwrapped is UnaryExpression
226+
{
227+
NodeType: ExpressionType.Convert,
228+
Method: null
229+
} convert
230+
&& convert.Type == typeof(object[]))
231+
{
232+
result = convert.Operand;
233+
return true;
234+
}
235+
236+
if (unwrapped is not null
237+
&& castDeclaringType?.GetGenericTypeDefinition() is var genericTypeDefinition
238+
&& (genericTypeDefinition == typeof(Span<>) || genericTypeDefinition == typeof(ReadOnlySpan<>)))
212239
{
213240
result = unwrapped;
214241
return true;

dotnet/src/VectorData/Pinecone/PineconeFilterTranslator.cs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -203,14 +203,41 @@ private Metadata TranslateMethodCall(MethodCallExpression methodCall)
203203

204204
static bool TryUnwrapSpanImplicitCast(Expression expression, [NotNullWhen(true)] out Expression? result)
205205
{
206-
if (expression is UnaryExpression
206+
// Different versions of the compiler seem to generate slightly different expression tree representations for this
207+
// implicit cast:
208+
var (unwrapped, castDeclaringType) = expression switch
209+
{
210+
UnaryExpression
207211
{
208212
NodeType: ExpressionType.Convert,
209213
Method: { Name: "op_Implicit", DeclaringType: { IsGenericType: true } implicitCastDeclaringType },
210-
Operand: var unwrapped
211-
}
212-
&& implicitCastDeclaringType.GetGenericTypeDefinition() is var genericTypeDefinition
213-
&& (genericTypeDefinition == typeof(Span<>) || genericTypeDefinition == typeof(ReadOnlySpan<>)))
214+
Operand: var operand
215+
} => (operand, implicitCastDeclaringType),
216+
217+
MethodCallExpression
218+
{
219+
Method: { Name: "op_Implicit", DeclaringType: { IsGenericType: true } implicitCastDeclaringType },
220+
Arguments: [var firstArgument]
221+
} => (firstArgument, implicitCastDeclaringType),
222+
223+
_ => (null, null)
224+
};
225+
226+
// For the dynamic case, there's a Convert node representing an up-cast to object[]; unwrap that too.
227+
if (unwrapped is UnaryExpression
228+
{
229+
NodeType: ExpressionType.Convert,
230+
Method: null
231+
} convert
232+
&& convert.Type == typeof(object[]))
233+
{
234+
result = convert.Operand;
235+
return true;
236+
}
237+
238+
if (unwrapped is not null
239+
&& castDeclaringType?.GetGenericTypeDefinition() is var genericTypeDefinition
240+
&& (genericTypeDefinition == typeof(Span<>) || genericTypeDefinition == typeof(ReadOnlySpan<>)))
214241
{
215242
result = unwrapped;
216243
return true;

dotnet/src/VectorData/Qdrant/QdrantFilterTranslator.cs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -308,14 +308,41 @@ private Filter TranslateMethodCall(MethodCallExpression methodCall)
308308

309309
static bool TryUnwrapSpanImplicitCast(Expression expression, [NotNullWhen(true)] out Expression? result)
310310
{
311-
if (expression is UnaryExpression
311+
// Different versions of the compiler seem to generate slightly different expression tree representations for this
312+
// implicit cast:
313+
var (unwrapped, castDeclaringType) = expression switch
314+
{
315+
UnaryExpression
312316
{
313317
NodeType: ExpressionType.Convert,
314318
Method: { Name: "op_Implicit", DeclaringType: { IsGenericType: true } implicitCastDeclaringType },
315-
Operand: var unwrapped
316-
}
317-
&& implicitCastDeclaringType.GetGenericTypeDefinition() is var genericTypeDefinition
318-
&& (genericTypeDefinition == typeof(Span<>) || genericTypeDefinition == typeof(ReadOnlySpan<>)))
319+
Operand: var operand
320+
} => (operand, implicitCastDeclaringType),
321+
322+
MethodCallExpression
323+
{
324+
Method: { Name: "op_Implicit", DeclaringType: { IsGenericType: true } implicitCastDeclaringType },
325+
Arguments: [var firstArgument]
326+
} => (firstArgument, implicitCastDeclaringType),
327+
328+
_ => (null, null)
329+
};
330+
331+
// For the dynamic case, there's a Convert node representing an up-cast to object[]; unwrap that too.
332+
if (unwrapped is UnaryExpression
333+
{
334+
NodeType: ExpressionType.Convert,
335+
Method: null
336+
} convert
337+
&& convert.Type == typeof(object[]))
338+
{
339+
result = convert.Operand;
340+
return true;
341+
}
342+
343+
if (unwrapped is not null
344+
&& castDeclaringType?.GetGenericTypeDefinition() is var genericTypeDefinition
345+
&& (genericTypeDefinition == typeof(Span<>) || genericTypeDefinition == typeof(ReadOnlySpan<>)))
319346
{
320347
result = unwrapped;
321348
return true;

dotnet/src/VectorData/Redis/RedisFilterTranslator.cs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -201,14 +201,41 @@ private void TranslateMethodCall(MethodCallExpression methodCall)
201201

202202
static bool TryUnwrapSpanImplicitCast(Expression expression, [NotNullWhen(true)] out Expression? result)
203203
{
204-
if (expression is UnaryExpression
204+
// Different versions of the compiler seem to generate slightly different expression tree representations for this
205+
// implicit cast:
206+
var (unwrapped, castDeclaringType) = expression switch
207+
{
208+
UnaryExpression
205209
{
206210
NodeType: ExpressionType.Convert,
207211
Method: { Name: "op_Implicit", DeclaringType: { IsGenericType: true } implicitCastDeclaringType },
208-
Operand: var unwrapped
209-
}
210-
&& implicitCastDeclaringType.GetGenericTypeDefinition() is var genericTypeDefinition
211-
&& (genericTypeDefinition == typeof(Span<>) || genericTypeDefinition == typeof(ReadOnlySpan<>)))
212+
Operand: var operand
213+
} => (operand, implicitCastDeclaringType),
214+
215+
MethodCallExpression
216+
{
217+
Method: { Name: "op_Implicit", DeclaringType: { IsGenericType: true } implicitCastDeclaringType },
218+
Arguments: [var firstArgument]
219+
} => (firstArgument, implicitCastDeclaringType),
220+
221+
_ => (null, null)
222+
};
223+
224+
// For the dynamic case, there's a Convert node representing an up-cast to object[]; unwrap that too.
225+
if (unwrapped is UnaryExpression
226+
{
227+
NodeType: ExpressionType.Convert,
228+
Method: null
229+
} convert
230+
&& convert.Type == typeof(object[]))
231+
{
232+
result = convert.Operand;
233+
return true;
234+
}
235+
236+
if (unwrapped is not null
237+
&& castDeclaringType?.GetGenericTypeDefinition() is var genericTypeDefinition
238+
&& (genericTypeDefinition == typeof(Span<>) || genericTypeDefinition == typeof(ReadOnlySpan<>)))
212239
{
213240
result = unwrapped;
214241
return true;

0 commit comments

Comments
 (0)