Skip to content

Commit

Permalink
No longer promote generic types if their arguments aren't compatible (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
metoule authored Feb 22, 2023
1 parent cd73460 commit a7899b8
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 2 deletions.
19 changes: 17 additions & 2 deletions src/DynamicExpresso.Core/Parsing/Parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2452,7 +2452,7 @@ private static Expression PromoteExpression(Expression expr, Type type, bool exa

if (type.IsGenericType && !IsNumericType(type))
{
var genericType = FindAssignableGenericType(expr.Type, type.GetGenericTypeDefinition());
var genericType = FindAssignableGenericType(expr.Type, type);
if (genericType != null)
return Expression.Convert(expr, genericType);
}
Expand All @@ -2476,6 +2476,11 @@ private static bool IsCompatibleWith(Type source, Type target)
return true;
}

if (target.IsGenericParameter)
{
return true;
}

if (!target.IsValueType)
{
return target.IsAssignableFrom(source);
Expand Down Expand Up @@ -2626,8 +2631,9 @@ private static bool IsWritable(Expression expression)
}

// from http://stackoverflow.com/a/1075059/209727
private static Type FindAssignableGenericType(Type givenType, Type genericTypeDefinition)
private static Type FindAssignableGenericType(Type givenType, Type constructedGenericType)
{
var genericTypeDefinition = constructedGenericType.GetGenericTypeDefinition();
var interfaceTypes = givenType.GetInterfaces();

foreach (var it in interfaceTypes)
Expand All @@ -2639,7 +2645,16 @@ private static Type FindAssignableGenericType(Type givenType, Type genericTypeDe
}

if (givenType.IsGenericType && givenType.GetGenericTypeDefinition() == genericTypeDefinition)
{
// the given type has the same generic type of the fully constructed generic type
// => check if the generic arguments are compatible (e.g. Nullable<int> and Nullable<DateTime>: int is not compatible with DateTime)
var givenTypeGenericsArgs = givenType.GenericTypeArguments;
var constructedGenericsArgs = constructedGenericType.GenericTypeArguments;
if (givenTypeGenericsArgs.Zip(constructedGenericsArgs, (g, c) => IsCompatibleWith(g, c)).Any(compatible => !compatible))
return null;

return givenType;
}

var baseType = givenType.BaseType;
if (baseType == null)
Expand Down
9 changes: 9 additions & 0 deletions test/DynamicExpresso.UnitTest/GithubIssues.cs
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,15 @@ public void GitHub_Issue_263(string paramsArguments)
var result = interpreter.Eval<int>($"Utils.ParamArrayObjects({paramsArguments})");
Assert.AreEqual(4, result);
}

[Test]
public void GitHub_Issue_276()
{
var interpreter = new Interpreter();

var result = interpreter.Eval<bool>("((int?)5)>((double?)4)");
Assert.IsTrue(result);
}
}

internal static class GithubIssuesTestExtensionsMethods
Expand Down

0 comments on commit a7899b8

Please sign in to comment.