Skip to content

Commit

Permalink
Static analysis: revert tail recursion unrolling (#26970)
Browse files Browse the repository at this point in the history
  • Loading branch information
ajcvickers authored Dec 14, 2021
1 parent 08e5ebd commit 0aeab4d
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 77 deletions.
38 changes: 16 additions & 22 deletions src/EFCore/Design/Internal/CSharpRuntimeAnnotationCodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -262,34 +262,28 @@ protected virtual void GenerateSimpleAnnotation(
/// <param name="namespaces">The set of namespaces to add to.</param>
protected virtual void AddNamespace(Type type, ISet<string> namespaces)
{
while (true)
if (type.IsNested)
{
if (type.IsNested)
{
AddNamespace(type.DeclaringType!, namespaces);
}

if (type.Namespace != null)
{
namespaces.Add(type.Namespace);
}
AddNamespace(type.DeclaringType!, namespaces);
}

if (type.IsGenericType)
{
foreach (var argument in type.GenericTypeArguments)
{
AddNamespace(argument, namespaces);
}
}
if (type.Namespace != null)
{
namespaces.Add(type.Namespace);
}

var sequenceType = type.TryGetSequenceType();
if (sequenceType != null)
if (type.IsGenericType)
{
foreach (var argument in type.GenericTypeArguments)
{
type = sequenceType;
continue;
AddNamespace(argument, namespaces);
}
}

break;
var sequenceType = type.TryGetSequenceType();
if (sequenceType != null)
{
AddNamespace(sequenceType, namespaces);
}
}
}
16 changes: 6 additions & 10 deletions src/EFCore/Extensions/Internal/ExpressionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -182,18 +182,14 @@ public static bool IsLogicalNot(this UnaryExpression sqlUnaryExpression)
[return: NotNullIfNotNull("expression")]
private static Expression? RemoveConvert(Expression? expression)
{
while (true)
if (expression is UnaryExpression unaryExpression
&& (expression.NodeType == ExpressionType.Convert
|| expression.NodeType == ExpressionType.ConvertChecked))
{
if (expression is UnaryExpression unaryExpression
&& (expression.NodeType == ExpressionType.Convert
|| expression.NodeType == ExpressionType.ConvertChecked))
{
expression = unaryExpression.Operand;
continue;
}

return expression;
return RemoveConvert(unaryExpression.Operand);
}

return expression;
}

private static readonly MethodInfo ObjectEqualsMethodInfo
Expand Down
62 changes: 27 additions & 35 deletions src/EFCore/Query/Internal/ParameterExtractingExpressionVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,38 +111,34 @@ private Expression ExtractParameters(Expression expression, bool clearEvaluatedV
private static bool PreserveInitializationConstant(Expression expression, bool generateParameter)
=> !generateParameter && (expression is NewExpression || expression is MemberInitExpression);

private static bool PreserveConvertNode(Expression expression)
private bool PreserveConvertNode(Expression expression)
{
while (true)
if (expression is UnaryExpression unaryExpression
&& (unaryExpression.NodeType == ExpressionType.Convert
|| unaryExpression.NodeType == ExpressionType.ConvertChecked))
{
if (expression is UnaryExpression unaryExpression
&& (unaryExpression.NodeType == ExpressionType.Convert
|| unaryExpression.NodeType == ExpressionType.ConvertChecked))
if (unaryExpression.Type == typeof(object)
|| unaryExpression.Type == typeof(Enum)
|| unaryExpression.Operand.Type.UnwrapNullableType().IsEnum)
{
if (unaryExpression.Type == typeof(object)
|| unaryExpression.Type == typeof(Enum)
|| unaryExpression.Operand.Type.UnwrapNullableType().IsEnum)
{
return true;
}

var innerType = unaryExpression.Operand.Type.UnwrapNullableType();
if (unaryExpression.Type.UnwrapNullableType() == typeof(int)
&& (innerType == typeof(byte)
|| innerType == typeof(sbyte)
|| innerType == typeof(char)
|| innerType == typeof(short)
|| innerType == typeof(ushort)))
{
return true;
}
return true;
}

expression = unaryExpression.Operand;
continue;
var innerType = unaryExpression.Operand.Type.UnwrapNullableType();
if (unaryExpression.Type.UnwrapNullableType() == typeof(int)
&& (innerType == typeof(byte)
|| innerType == typeof(sbyte)
|| innerType == typeof(char)
|| innerType == typeof(short)
|| innerType == typeof(ushort)))
{
return true;
}

return false;
return PreserveConvertNode(unaryExpression.Operand);
}

return false;
}

/// <summary>
Expand Down Expand Up @@ -368,18 +364,14 @@ public ContextParameterReplacingExpressionVisitor(Type contextType)

private static Expression RemoveConvert(Expression expression)
{
while (true)
if (expression is UnaryExpression unaryExpression
&& (expression.NodeType == ExpressionType.Convert
|| expression.NodeType == ExpressionType.ConvertChecked))
{
if (expression is UnaryExpression unaryExpression
&& (expression.NodeType == ExpressionType.Convert
|| expression.NodeType == ExpressionType.ConvertChecked))
{
expression = unaryExpression.Operand;
continue;
}

return expression;
return RemoveConvert(unaryExpression.Operand);
}

return expression;
}

private object? GetValue(Expression? expression, out string? parameterName)
Expand Down
16 changes: 6 additions & 10 deletions src/Shared/ExpressionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,14 @@ public static LambdaExpression UnwrapLambdaFromQuote(this Expression expression)

private static Expression RemoveConvert(Expression expression)
{
while (true)
if (expression is UnaryExpression unaryExpression
&& (expression.NodeType == ExpressionType.Convert
|| expression.NodeType == ExpressionType.ConvertChecked))
{
if (expression is UnaryExpression unaryExpression
&& (expression.NodeType == ExpressionType.Convert
|| expression.NodeType == ExpressionType.ConvertChecked))
{
expression = unaryExpression.Operand;
continue;
}

return expression;
return RemoveConvert(unaryExpression.Operand);
}

return expression;
}

public static T GetConstantValue<T>(this Expression expression)
Expand Down

0 comments on commit 0aeab4d

Please sign in to comment.