Skip to content

Commit

Permalink
fix: fixed detection IsByRefLike types in reflection related to mono
Browse files Browse the repository at this point in the history
  • Loading branch information
deniszykov committed Mar 2, 2024
1 parent dc59386 commit f3251f3
Show file tree
Hide file tree
Showing 7 changed files with 27 additions and 15 deletions.
4 changes: 2 additions & 2 deletions src/GameDevWare.Dynamic.Expressions/Aot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -216,10 +216,10 @@ static partial void StaticConstructor()
GameDevWare.Dynamic.Expressions.ExpressionUtils.TryPromoteUnaryOperation(ref param_33554448_100663424_0, default(System.Linq.Expressions.ExpressionType), out param_33554448_100663424_2);
GameDevWare.Dynamic.Expressions.ExpressionUtils.IsNull(default(System.Linq.Expressions.Expression), default(System.Boolean));
var param_33554448_100663426_0 = default(System.Linq.Expressions.Expression);
GameDevWare.Dynamic.Expressions.ExpressionUtils.MorphType(ref param_33554448_100663426_0, default(System.Type));
GameDevWare.Dynamic.Expressions.ExpressionUtils.CoerceType(ref param_33554448_100663426_0, default(System.Type));
var param_33554448_100663427_0 = default(System.Linq.Expressions.Expression);
var param_33554448_100663427_2 = default(System.Single);
GameDevWare.Dynamic.Expressions.ExpressionUtils.TryMorphType(ref param_33554448_100663427_0, default(System.Type), out param_33554448_100663427_2);
GameDevWare.Dynamic.Expressions.ExpressionUtils.TryCoerceType(ref param_33554448_100663427_0, default(System.Type), out param_33554448_100663427_2);
GameDevWare.Dynamic.Expressions.ExpressionUtils.MakeNullPropagationExpression(default(System.Collections.Generic.List<System.Linq.Expressions.Expression>), default(System.Linq.Expressions.Expression));
var param_33554448_100663432_1 = default(System.Collections.Generic.List<System.Linq.Expressions.Expression>);
var param_33554448_100663432_2 = default(System.Linq.Expressions.Expression);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public static bool TryBind(SyntaxTreeNode node, BindingContext bindingContext, T
if (ifTrueBranch.Type != ifFalseBranch.Type)
{
float quality;
ExpressionUtils.TryMorphType(ref ifTrueBranch, ifFalseBranch.Type, out quality);
ExpressionUtils.TryCoerceType(ref ifTrueBranch, ifFalseBranch.Type, out quality);
}

boundExpression = Expression.Condition(testExpression, ifTrueBranch, ifFalseBranch);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ public MemberDescription(TypeDescription declaringType, MethodInfo method, Membe
}
}

this.HasByRefLikeParameters = this.parameters.Any(parameter => TypeDescription.HasByRefLikeAttribute(parameter.ParameterType));
this.HasByRefLikeParameters = this.parameters.Any(parameter => TypeDescription.HasByRefLikeAttribute(parameter) || TypeDescription.HasByRefLikeAttribute(parameter.ParameterType)) ||
TypeDescription.HasByRefLikeAttribute(this.returnParameter);
this.IsMethod = true;
this.IsStatic = method.IsStatic;
this.IsImplicitOperator = method.IsSpecialName && this.Name == "op_Implicit";
Expand Down Expand Up @@ -306,7 +307,7 @@ public bool TryMakeCall(Expression target, ArgumentsTree argumentsTree, BindingC
Debug.Assert(argValue != null, "argValue != null");

var quality = 0.0f;
if (ExpressionUtils.TryMorphType(ref argValue, expectedType, out quality) == false || quality <= 0)
if (ExpressionUtils.TryCoerceType(ref argValue, expectedType, out quality) == false || quality <= 0)
return false;// failed to bind parameter

parametersQuality += quality; // casted
Expand Down
4 changes: 2 additions & 2 deletions src/GameDevWare.Dynamic.Expressions/Binding/TypeConversion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ static TypeConversion()
Conversions = new Dictionary<TypeTuple2, TypeConversion>(EqualityComparer<TypeTuple2>.Default);

// typeof(char), typeof(string), typeof(float), typeof(double), typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong)
SetNaturalConversion(QUALITY_IMPLICIT_CONVERSION, typeof(char), typeof(ushort), typeof(uint), typeof(int), typeof(long), typeof(ulong), typeof(float), typeof(double));
SetNaturalConversion(QUALITY_IMPLICIT_CONVERSION, typeof(float), typeof(double));
SetNaturalConversion(QUALITY_IMPLICIT_CONVERSION, typeof(byte), typeof(ushort), typeof(short), typeof(uint), typeof(int), typeof(long), typeof(ulong), typeof(float), typeof(double));
SetNaturalConversion(QUALITY_IMPLICIT_CONVERSION, typeof(char), typeof(ushort), typeof(uint), typeof(int), typeof(long), typeof(ulong), typeof(float), typeof(double));
SetNaturalConversion(QUALITY_IMPLICIT_CONVERSION, typeof(ushort), typeof(uint), typeof(int), typeof(long), typeof(ulong), typeof(float), typeof(double));
SetNaturalConversion(QUALITY_IMPLICIT_CONVERSION, typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double));
SetNaturalConversion(QUALITY_IMPLICIT_CONVERSION, typeof(ulong), typeof(float), typeof(double));
Expand All @@ -53,10 +53,10 @@ static TypeConversion()
SetNaturalConversion(QUALITY_IMPLICIT_CONVERSION, typeof(int), typeof(long), typeof(float), typeof(double));
SetNaturalConversion(QUALITY_IMPLICIT_CONVERSION, typeof(long), typeof(float), typeof(double));

SetNaturalConversion(QUALITY_EXPLICIT_CONVERSION, typeof(char), typeof(sbyte), typeof(byte));
SetNaturalConversion(QUALITY_EXPLICIT_CONVERSION, typeof(double), typeof(float), typeof(long), typeof(ulong), typeof(int), typeof(uint), typeof(short), typeof(char), typeof(ushort), typeof(sbyte), typeof(byte));
SetNaturalConversion(QUALITY_EXPLICIT_CONVERSION, typeof(float), typeof(long), typeof(ulong), typeof(int), typeof(uint), typeof(short), typeof(char), typeof(ushort), typeof(sbyte), typeof(byte));
SetNaturalConversion(QUALITY_EXPLICIT_CONVERSION, typeof(byte), typeof(sbyte));
SetNaturalConversion(QUALITY_EXPLICIT_CONVERSION, typeof(char), typeof(sbyte), typeof(byte));
SetNaturalConversion(QUALITY_IMPLICIT_CONVERSION, typeof(ushort), typeof(char), typeof(short), typeof(byte), typeof(sbyte));
SetNaturalConversion(QUALITY_IMPLICIT_CONVERSION, typeof(uint), typeof(int), typeof(char), typeof(ushort), typeof(short), typeof(byte), typeof(sbyte));
SetNaturalConversion(QUALITY_IMPLICIT_CONVERSION, typeof(ulong), typeof(long), typeof(uint), typeof(int), typeof(char), typeof(ushort), typeof(short), typeof(byte), typeof(sbyte));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -352,10 +352,19 @@ private static T[] Combine<T>(params T[][] arrays)
return newArray;
}

public static bool HasByRefLikeAttribute(ParameterInfo parameterInfo)
{
if (parameterInfo.Member.Name == "ToString" && parameterInfo.Position == -1 /* return value */)
{
return false; // fix for https://github.com/mono/mono/issues/17192
}
return parameterInfo.GetCustomAttributes(inherit: true).Any(attribute => IsByRefLikeAttributeType(attribute.GetType()));
}
public static bool HasByRefLikeAttribute(Type type)
{
return type.GetTypeInfo().GetCustomAttributes(inherit: true).Any(attribute => IsByRefLikeAttributeType(attribute.GetType()));
}

private static bool IsByRefLikeAttributeType(Type attributeType)
{
return attributeType.Namespace == "System.Runtime.CompilerServices" && attributeType.Name == "IsByRefLikeAttribute";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ public static ExecutionNode Compile(Expression expression, ConstantExpression[]
if (constExpressions == null) throw new ArgumentNullException("constExpressions");
if (parameterExpressions == null) throw new ArgumentNullException("parameterExpressions");

// ReSharper disable once SwitchStatementHandlesSomeKnownEnumValuesWithDefault
switch (expression.NodeType)
{
case ExpressionType.ArrayIndex:
Expand Down
17 changes: 9 additions & 8 deletions src/GameDevWare.Dynamic.Expressions/ExpressionUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ private static bool TryPromoteNumberBinaryOperation(ref Expression leftOperand,
var quality = 0.0f;
var rightOperandTmp = rightOperand;
var expectedRightType = promoteRightToNullable ? typeof(ulong?) : typeof(ulong);
if (NumberUtils.IsSignedInteger(rightTypeCode) && TryMorphType(ref rightOperandTmp, expectedRightType, out quality) == false)
if (NumberUtils.IsSignedInteger(rightTypeCode) && TryCoerceType(ref rightOperandTmp, expectedRightType, out quality) == false)
return false; // will throw exception

rightOperand = rightOperandTmp;
Expand All @@ -140,7 +140,7 @@ private static bool TryPromoteNumberBinaryOperation(ref Expression leftOperand,
var quality = 0.0f;
var leftOperandTmp = leftOperand;
var expectedLeftType = promoteLeftToNullable ? typeof(ulong?) : typeof(ulong);
if (NumberUtils.IsSignedInteger(leftTypeCode) && TryMorphType(ref leftOperandTmp, expectedLeftType, out quality) == false)
if (NumberUtils.IsSignedInteger(leftTypeCode) && TryCoerceType(ref leftOperandTmp, expectedLeftType, out quality) == false)
return false; // will throw exception

leftOperand = leftOperandTmp;
Expand Down Expand Up @@ -198,6 +198,7 @@ private static bool TryPromoteEnumBinaryOperation(ref Expression leftOperand, Ty
if (promoteToNullable)
rightOperand = ConvertToNullable(rightOperand, leftType);

// ReSharper disable once SwitchStatementHandlesSomeKnownEnumValuesWithDefault
switch (type)
{
case ExpressionType.Add: operation = Expression.Add(leftOperand, rightOperand); break;
Expand Down Expand Up @@ -266,11 +267,11 @@ public static bool TryPromoteUnaryOperation(ref Expression operand, ExpressionTy
var promoteToNullable = operandType.IsNullable;

if (operandTypeUnwrap.IsEnum)
MorphType(ref operand, promoteToNullable ? operandTypeUnwrap.UnderlyingType.GetNullableType() : operandTypeUnwrap.UnderlyingType);
CoerceType(ref operand, promoteToNullable ? operandTypeUnwrap.UnderlyingType.GetNullableType() : operandTypeUnwrap.UnderlyingType);
else if (operandTypeUnwrap.TypeCode >= TypeCode.SByte && operandTypeUnwrap.TypeCode <= TypeCode.UInt16)
MorphType(ref operand, promoteToNullable ? typeof(int?) : typeof(int));
CoerceType(ref operand, promoteToNullable ? typeof(int?) : typeof(int));
else if (operandTypeUnwrap.TypeCode == TypeCode.UInt32 && type == ExpressionType.Not)
MorphType(ref operand, promoteToNullable ? typeof(long?) : typeof(long));
CoerceType(ref operand, promoteToNullable ? typeof(long?) : typeof(long));

return false;
}
Expand All @@ -291,16 +292,16 @@ public static bool IsNull(Expression expression, bool unwrapConversions = true)

return constantExpression.Value == null && constantExpression.Type == typeof(object);
}
public static void MorphType(ref Expression expression, Type toType)
public static void CoerceType(ref Expression expression, Type toType)
{
if (expression == null) throw new ArgumentNullException("expression");
if (toType == null) throw new ArgumentNullException("toType");

var quality = 0.0f;
if (TryMorphType(ref expression, toType, out quality) == false || quality <= TypeConversion.QUALITY_NO_CONVERSION)
if (TryCoerceType(ref expression, toType, out quality) == false || quality <= TypeConversion.QUALITY_NO_CONVERSION)
throw new InvalidOperationException(string.Format("Failed to change type of expression '{0}' to '{1}'.", expression, toType));
}
public static bool TryMorphType(ref Expression expression, Type toType, out float quality)
public static bool TryCoerceType(ref Expression expression, Type toType, out float quality)
{
if (expression == null) throw new ArgumentNullException("expression");
if (toType == null) throw new ArgumentNullException("toType");
Expand Down

0 comments on commit f3251f3

Please sign in to comment.