Browse Source

#3466: avoid recursion in `CSharpConversions.SelectOperator`

pull/3481/head
Daniel Grunwald 2 months ago
parent
commit
d4de698465
  1. 33
      ICSharpCode.Decompiler/CSharp/Resolver/CSharpConversions.cs

33
ICSharpCode.Decompiler/CSharp/Resolver/CSharpConversions.cs

@ -307,6 +307,14 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
return UserDefinedExplicitConversion(null, fromType, toType); return UserDefinedExplicitConversion(null, fromType, toType);
} }
Conversion ExplicitConversionNotUserDefined(IType fromType, IType toType)
{
Conversion c = ImplicitConversion(fromType, toType, allowUserDefined: false, allowTuple: false);
if (c != Conversion.None)
return c;
return ExplicitConversionImpl(fromType, toType);
}
Conversion ExplicitConversionImpl(IType fromType, IType toType) Conversion ExplicitConversionImpl(IType fromType, IType toType)
{ {
// This method is called after we already checked for implicit conversions, // This method is called after we already checked for implicit conversions,
@ -971,16 +979,31 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
return Conversion.None; return Conversion.None;
if (selected.Count == 1) if (selected.Count == 1)
return Conversion.UserDefinedConversion(selected[0].Method, isLifted: selected[0].IsLifted, isImplicit: isImplicit, conversionBeforeUserDefinedOperator: ExplicitConversion(source, mostSpecificSource), conversionAfterUserDefinedOperator: ExplicitConversion(mostSpecificTarget, target)); {
return Conversion.UserDefinedConversion(selected[0].Method,
isLifted: selected[0].IsLifted,
isImplicit: isImplicit,
conversionBeforeUserDefinedOperator: ExplicitConversionNotUserDefined(source, mostSpecificSource),
conversionAfterUserDefinedOperator: ExplicitConversionNotUserDefined(mostSpecificTarget, target));
}
int nNonLifted = selected.Count(s => !s.IsLifted); int nNonLifted = selected.Count(s => !s.IsLifted);
if (nNonLifted == 1) if (nNonLifted == 1)
{ {
var op = selected.First(s => !s.IsLifted); var op = selected.First(s => !s.IsLifted);
return Conversion.UserDefinedConversion(op.Method, isLifted: op.IsLifted, isImplicit: isImplicit, conversionBeforeUserDefinedOperator: ExplicitConversion(source, mostSpecificSource), conversionAfterUserDefinedOperator: ExplicitConversion(mostSpecificTarget, target)); return Conversion.UserDefinedConversion(op.Method,
} isLifted: op.IsLifted,
isImplicit: isImplicit,
return Conversion.UserDefinedConversion(selected[0].Method, isLifted: selected[0].IsLifted, isImplicit: isImplicit, isAmbiguous: true, conversionBeforeUserDefinedOperator: ExplicitConversion(source, mostSpecificSource), conversionAfterUserDefinedOperator: ExplicitConversion(mostSpecificTarget, target)); conversionBeforeUserDefinedOperator: ExplicitConversionNotUserDefined(source, mostSpecificSource),
conversionAfterUserDefinedOperator: ExplicitConversionNotUserDefined(mostSpecificTarget, target));
}
return Conversion.UserDefinedConversion(selected[0].Method,
isLifted: selected[0].IsLifted,
isImplicit: isImplicit,
isAmbiguous: true,
conversionBeforeUserDefinedOperator: ExplicitConversionNotUserDefined(source, mostSpecificSource),
conversionAfterUserDefinedOperator: ExplicitConversionNotUserDefined(mostSpecificTarget, target));
} }
Conversion UserDefinedImplicitConversion(ResolveResult fromResult, IType fromType, IType toType) Conversion UserDefinedImplicitConversion(ResolveResult fromResult, IType fromType, IType toType)

Loading…
Cancel
Save