3717 lines
137 KiB
C#
3717 lines
137 KiB
C#
using System;
|
|
using System.Collections.Immutable;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using Microsoft.CodeAnalysis.CSharp.Symbols;
|
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
|
using Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax;
|
|
using Microsoft.CodeAnalysis.PooledObjects;
|
|
using Roslyn.Utilities;
|
|
|
|
namespace Microsoft.CodeAnalysis.CSharp;
|
|
|
|
internal abstract class ConversionsBase
|
|
{
|
|
private static class ConversionEasyOut
|
|
{
|
|
private static readonly byte[,] s_convkind;
|
|
|
|
static ConversionEasyOut()
|
|
{
|
|
s_convkind = new byte[32, 32]
|
|
{
|
|
{
|
|
2, 27, 28, 28, 28, 28, 28, 28, 28, 28,
|
|
28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
|
28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
|
28, 28
|
|
},
|
|
{
|
|
12, 2, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1
|
|
},
|
|
{
|
|
13, 1, 2, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 10, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1
|
|
},
|
|
{
|
|
13, 1, 1, 2, 24, 24, 3, 3, 24, 3,
|
|
3, 3, 3, 3, 3, 3, 3, 1, 10, 26,
|
|
26, 10, 10, 26, 10, 10, 10, 10, 10, 10,
|
|
10, 10
|
|
},
|
|
{
|
|
13, 1, 1, 24, 2, 3, 3, 3, 24, 24,
|
|
24, 24, 3, 24, 3, 3, 3, 1, 26, 10,
|
|
10, 10, 10, 26, 26, 26, 26, 10, 26, 10,
|
|
10, 10
|
|
},
|
|
{
|
|
13, 1, 1, 24, 24, 2, 3, 3, 24, 24,
|
|
24, 24, 3, 24, 3, 3, 3, 1, 26, 26,
|
|
10, 10, 10, 26, 26, 26, 26, 10, 26, 10,
|
|
10, 10
|
|
},
|
|
{
|
|
13, 1, 1, 24, 24, 24, 2, 3, 24, 24,
|
|
24, 24, 3, 24, 3, 3, 3, 1, 26, 26,
|
|
26, 10, 10, 26, 26, 26, 26, 10, 26, 10,
|
|
10, 10
|
|
},
|
|
{
|
|
13, 1, 1, 24, 24, 24, 24, 2, 24, 24,
|
|
24, 24, 24, 24, 3, 3, 3, 1, 26, 26,
|
|
26, 26, 10, 26, 26, 26, 26, 26, 26, 10,
|
|
10, 10
|
|
},
|
|
{
|
|
13, 1, 1, 24, 24, 3, 3, 3, 2, 3,
|
|
3, 3, 3, 3, 3, 3, 3, 1, 26, 26,
|
|
10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
|
|
10, 10
|
|
},
|
|
{
|
|
13, 1, 1, 24, 24, 24, 3, 3, 24, 2,
|
|
3, 3, 3, 3, 3, 3, 3, 1, 26, 26,
|
|
26, 10, 10, 26, 10, 10, 10, 10, 10, 10,
|
|
10, 10
|
|
},
|
|
{
|
|
13, 1, 1, 24, 24, 24, 24, 3, 24, 24,
|
|
2, 3, 24, 3, 3, 3, 3, 1, 26, 26,
|
|
26, 26, 10, 26, 26, 10, 10, 26, 10, 10,
|
|
10, 10
|
|
},
|
|
{
|
|
13, 1, 1, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 2, 24, 24, 3, 3, 3, 1, 26, 26,
|
|
26, 26, 26, 26, 26, 26, 10, 26, 26, 10,
|
|
10, 10
|
|
},
|
|
{
|
|
13, 1, 1, 24, 24, 24, 24, 3, 24, 24,
|
|
24, 24, 2, 24, 3, 3, 3, 1, 26, 26,
|
|
26, 26, 10, 26, 26, 26, 26, 10, 26, 10,
|
|
10, 10
|
|
},
|
|
{
|
|
13, 1, 1, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 3, 24, 2, 3, 3, 3, 1, 26, 26,
|
|
26, 26, 26, 26, 26, 26, 10, 26, 10, 10,
|
|
10, 10
|
|
},
|
|
{
|
|
13, 1, 1, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 2, 3, 24, 1, 26, 26,
|
|
26, 26, 26, 26, 26, 26, 26, 26, 26, 10,
|
|
10, 26
|
|
},
|
|
{
|
|
13, 1, 1, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 24, 2, 24, 1, 26, 26,
|
|
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
|
10, 26
|
|
},
|
|
{
|
|
13, 1, 1, 24, 24, 24, 24, 24, 24, 24,
|
|
24, 24, 24, 24, 24, 24, 2, 1, 26, 26,
|
|
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
|
26, 10
|
|
},
|
|
{
|
|
13, 1, 26, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 2, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1
|
|
},
|
|
{
|
|
13, 1, 1, 26, 26, 26, 26, 26, 26, 26,
|
|
26, 26, 26, 26, 26, 26, 26, 1, 2, 26,
|
|
26, 10, 10, 26, 10, 10, 10, 10, 10, 10,
|
|
10, 10
|
|
},
|
|
{
|
|
13, 1, 1, 26, 26, 26, 26, 26, 26, 26,
|
|
26, 26, 26, 26, 26, 26, 26, 1, 26, 2,
|
|
10, 10, 10, 26, 26, 26, 26, 10, 26, 10,
|
|
10, 10
|
|
},
|
|
{
|
|
13, 1, 1, 26, 26, 26, 26, 26, 26, 26,
|
|
26, 26, 26, 26, 26, 26, 26, 1, 26, 26,
|
|
2, 10, 10, 26, 26, 26, 26, 10, 26, 10,
|
|
10, 10
|
|
},
|
|
{
|
|
13, 1, 1, 26, 26, 26, 26, 26, 26, 26,
|
|
26, 26, 26, 26, 26, 26, 26, 1, 26, 26,
|
|
26, 2, 10, 26, 26, 26, 26, 10, 26, 10,
|
|
10, 10
|
|
},
|
|
{
|
|
13, 1, 1, 26, 26, 26, 26, 26, 26, 26,
|
|
26, 26, 26, 26, 26, 26, 26, 1, 26, 26,
|
|
26, 26, 2, 26, 26, 26, 26, 26, 26, 10,
|
|
10, 10
|
|
},
|
|
{
|
|
13, 1, 1, 26, 26, 26, 26, 26, 26, 26,
|
|
26, 26, 26, 26, 26, 26, 26, 1, 26, 26,
|
|
10, 10, 10, 2, 10, 10, 10, 10, 10, 10,
|
|
10, 10
|
|
},
|
|
{
|
|
13, 1, 1, 26, 26, 26, 26, 26, 26, 26,
|
|
26, 26, 26, 26, 26, 26, 26, 1, 26, 26,
|
|
26, 10, 10, 26, 2, 10, 10, 10, 10, 10,
|
|
10, 10
|
|
},
|
|
{
|
|
13, 1, 1, 26, 26, 26, 26, 26, 26, 26,
|
|
26, 26, 26, 26, 26, 26, 26, 1, 26, 26,
|
|
26, 26, 10, 26, 26, 2, 10, 26, 10, 10,
|
|
10, 10
|
|
},
|
|
{
|
|
13, 1, 1, 26, 26, 26, 26, 26, 26, 26,
|
|
26, 26, 26, 26, 26, 26, 26, 1, 26, 26,
|
|
26, 26, 26, 26, 26, 26, 2, 26, 26, 10,
|
|
10, 10
|
|
},
|
|
{
|
|
13, 1, 1, 26, 26, 26, 26, 26, 26, 26,
|
|
26, 26, 26, 26, 26, 26, 26, 1, 26, 26,
|
|
26, 26, 10, 26, 26, 26, 26, 2, 26, 10,
|
|
10, 10
|
|
},
|
|
{
|
|
13, 1, 1, 26, 26, 26, 26, 26, 26, 26,
|
|
26, 26, 26, 26, 26, 26, 26, 1, 26, 26,
|
|
26, 26, 26, 26, 26, 26, 10, 26, 2, 10,
|
|
10, 10
|
|
},
|
|
{
|
|
13, 1, 1, 26, 26, 26, 26, 26, 26, 26,
|
|
26, 26, 26, 26, 26, 26, 26, 1, 26, 26,
|
|
26, 26, 26, 26, 26, 26, 26, 26, 26, 2,
|
|
10, 26
|
|
},
|
|
{
|
|
13, 1, 1, 26, 26, 26, 26, 26, 26, 26,
|
|
26, 26, 26, 26, 26, 26, 26, 1, 26, 26,
|
|
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
|
2, 26
|
|
},
|
|
{
|
|
13, 1, 1, 26, 26, 26, 26, 26, 26, 26,
|
|
26, 26, 26, 26, 26, 26, 26, 1, 26, 26,
|
|
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
|
26, 2
|
|
}
|
|
};
|
|
}
|
|
|
|
public static ConversionKind ClassifyConversion(TypeSymbol source, TypeSymbol target)
|
|
{
|
|
int num = source.TypeToIndex();
|
|
if (num < 0)
|
|
{
|
|
return ConversionKind.NoConversion;
|
|
}
|
|
int num2 = target.TypeToIndex();
|
|
if (num2 < 0)
|
|
{
|
|
return ConversionKind.NoConversion;
|
|
}
|
|
return (ConversionKind)s_convkind[num, num2];
|
|
}
|
|
}
|
|
|
|
private delegate Conversion ClassifyConversionFromExpressionDelegate(ConversionsBase conversions, BoundExpression sourceExpression, TypeWithAnnotations destination, bool isChecked, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo, bool forCast);
|
|
|
|
private delegate Conversion ClassifyConversionFromTypeDelegate(ConversionsBase conversions, TypeWithAnnotations source, TypeWithAnnotations destination, bool isChecked, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo, bool forCast);
|
|
|
|
private const int MaximumRecursionDepth = 50;
|
|
|
|
protected readonly AssemblySymbol corLibrary;
|
|
|
|
protected readonly int currentRecursionDepth;
|
|
|
|
internal readonly bool IncludeNullability;
|
|
|
|
private ConversionsBase _lazyOtherNullability;
|
|
|
|
protected abstract bool IsAttributeArgumentBinding { get; }
|
|
|
|
protected abstract bool IsParameterDefaultValueBinding { get; }
|
|
|
|
internal AssemblySymbol CorLibrary => corLibrary;
|
|
|
|
protected abstract CSharpCompilation? Compilation { get; }
|
|
|
|
protected ConversionsBase(AssemblySymbol corLibrary, int currentRecursionDepth, bool includeNullability, ConversionsBase otherNullabilityOpt)
|
|
{
|
|
this.corLibrary = corLibrary;
|
|
this.currentRecursionDepth = currentRecursionDepth;
|
|
IncludeNullability = includeNullability;
|
|
_lazyOtherNullability = otherNullabilityOpt;
|
|
}
|
|
|
|
internal ConversionsBase WithNullability(bool includeNullability)
|
|
{
|
|
if (IncludeNullability == includeNullability)
|
|
{
|
|
return this;
|
|
}
|
|
if (_lazyOtherNullability == null)
|
|
{
|
|
Interlocked.CompareExchange(ref _lazyOtherNullability, WithNullabilityCore(includeNullability), null);
|
|
}
|
|
return _lazyOtherNullability;
|
|
}
|
|
|
|
protected abstract ConversionsBase WithNullabilityCore(bool includeNullability);
|
|
|
|
public abstract Conversion GetMethodGroupDelegateConversion(BoundMethodGroup source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo);
|
|
|
|
public abstract Conversion GetMethodGroupFunctionPointerConversion(BoundMethodGroup source, FunctionPointerTypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo);
|
|
|
|
public abstract Conversion GetStackAllocConversion(BoundStackAllocArrayCreation sourceExpression, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo);
|
|
|
|
protected abstract ConversionsBase CreateInstance(int currentRecursionDepth);
|
|
|
|
protected abstract Conversion GetInterpolatedStringConversion(BoundExpression source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo);
|
|
|
|
protected abstract Conversion GetCollectionExpressionConversion(BoundUnconvertedCollectionExpression source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo);
|
|
|
|
public Conversion ClassifyImplicitConversionFromExpression(BoundExpression sourceExpression, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
TypeSymbol type = sourceExpression.Type;
|
|
if ((object)type != null && HasIdentityConversionInternal(type, destination))
|
|
{
|
|
return Conversion.Identity;
|
|
}
|
|
Conversion result = ClassifyImplicitBuiltInConversionFromExpression(sourceExpression, type, destination, ref useSiteInfo);
|
|
if (result.Exists)
|
|
{
|
|
return result;
|
|
}
|
|
if ((object)type != null)
|
|
{
|
|
Conversion result2 = FastClassifyConversion(type, destination);
|
|
if (result2.Exists)
|
|
{
|
|
if (result2.IsImplicit)
|
|
{
|
|
return result2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
result = ClassifyImplicitBuiltInConversionSlow(type, destination, ref useSiteInfo);
|
|
if (result.Exists)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FunctionTypeSymbol functionType = sourceExpression.GetFunctionType();
|
|
if ((object)functionType != null && HasImplicitFunctionTypeConversion(functionType, destination, ref useSiteInfo))
|
|
{
|
|
return Conversion.FunctionType;
|
|
}
|
|
}
|
|
result = GetImplicitUserDefinedConversion(sourceExpression, type, destination, ref useSiteInfo);
|
|
if (result.Exists)
|
|
{
|
|
return result;
|
|
}
|
|
result = GetSwitchExpressionConversion(sourceExpression, destination, ref useSiteInfo);
|
|
if (result.Exists)
|
|
{
|
|
return result;
|
|
}
|
|
return GetConditionalExpressionConversion(sourceExpression, destination, ref useSiteInfo);
|
|
}
|
|
|
|
public Conversion ClassifyImplicitConversionFromType(TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
if (HasIdentityConversionInternal(source, destination))
|
|
{
|
|
return Conversion.Identity;
|
|
}
|
|
Conversion result = FastClassifyConversion(source, destination);
|
|
if (result.Exists)
|
|
{
|
|
if (!result.IsImplicit)
|
|
{
|
|
return Conversion.NoConversion;
|
|
}
|
|
return result;
|
|
}
|
|
Conversion result2 = ClassifyImplicitBuiltInConversionSlow(source, destination, ref useSiteInfo);
|
|
if (result2.Exists)
|
|
{
|
|
return result2;
|
|
}
|
|
return GetImplicitUserDefinedConversion(source, destination, ref useSiteInfo);
|
|
}
|
|
|
|
public Conversion ClassifyImplicitConversionFromTypeWhenNeitherOrBothFunctionTypes(TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
FunctionTypeSymbol functionTypeSymbol = source as FunctionTypeSymbol;
|
|
FunctionTypeSymbol functionTypeSymbol2 = destination as FunctionTypeSymbol;
|
|
if ((object)functionTypeSymbol == null && (object)functionTypeSymbol2 == null)
|
|
{
|
|
return ClassifyImplicitConversionFromType(source, destination, ref useSiteInfo);
|
|
}
|
|
if ((object)functionTypeSymbol != null && (object)functionTypeSymbol2 != null)
|
|
{
|
|
if (!HasImplicitFunctionTypeToFunctionTypeConversion(functionTypeSymbol, functionTypeSymbol2, ref useSiteInfo))
|
|
{
|
|
return Conversion.NoConversion;
|
|
}
|
|
return Conversion.FunctionType;
|
|
}
|
|
return Conversion.NoConversion;
|
|
}
|
|
|
|
public Conversion ClassifyConversionFromExpressionType(TypeSymbol source, TypeSymbol destination, bool isChecked, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
if (HasImplicitDynamicConversionFromExpression(source, destination))
|
|
{
|
|
return Conversion.ImplicitDynamic;
|
|
}
|
|
return ClassifyConversionFromType(source, destination, isChecked, ref useSiteInfo);
|
|
}
|
|
|
|
private static bool TryGetVoidConversion(TypeSymbol source, TypeSymbol destination, out Conversion conversion)
|
|
{
|
|
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_000d: Invalid comparison between Unknown and I4
|
|
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0017: Invalid comparison between Unknown and I4
|
|
bool flag = (object)source != null && (int)source.SpecialType == 6;
|
|
bool flag2 = (int)destination.SpecialType == 6;
|
|
if (flag && flag2)
|
|
{
|
|
conversion = Conversion.Identity;
|
|
return true;
|
|
}
|
|
if (flag || flag2)
|
|
{
|
|
conversion = Conversion.NoConversion;
|
|
return true;
|
|
}
|
|
conversion = default(Conversion);
|
|
return false;
|
|
}
|
|
|
|
public Conversion ClassifyConversionFromExpression(BoundExpression sourceExpression, TypeSymbol destination, bool isChecked, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo, bool forCast = false)
|
|
{
|
|
if (TryGetVoidConversion(sourceExpression.Type, destination, out var conversion))
|
|
{
|
|
return conversion;
|
|
}
|
|
if (forCast)
|
|
{
|
|
return ClassifyConversionFromExpressionForCast(sourceExpression, destination, isChecked, ref useSiteInfo);
|
|
}
|
|
Conversion result = ClassifyImplicitConversionFromExpression(sourceExpression, destination, ref useSiteInfo);
|
|
if (result.Exists)
|
|
{
|
|
return result;
|
|
}
|
|
return ClassifyExplicitOnlyConversionFromExpression(sourceExpression, destination, isChecked, ref useSiteInfo, forCast: false);
|
|
}
|
|
|
|
public Conversion ClassifyConversionFromType(TypeSymbol source, TypeSymbol destination, bool isChecked, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo, bool forCast = false)
|
|
{
|
|
if (TryGetVoidConversion(source, destination, out var conversion))
|
|
{
|
|
return conversion;
|
|
}
|
|
if (forCast)
|
|
{
|
|
return ClassifyConversionFromTypeForCast(source, destination, isChecked, ref useSiteInfo);
|
|
}
|
|
Conversion result = FastClassifyConversion(source, destination);
|
|
if (result.Exists)
|
|
{
|
|
return result;
|
|
}
|
|
Conversion result2 = ClassifyImplicitBuiltInConversionSlow(source, destination, ref useSiteInfo);
|
|
if (result2.Exists)
|
|
{
|
|
return result2;
|
|
}
|
|
Conversion implicitUserDefinedConversion = GetImplicitUserDefinedConversion(source, destination, ref useSiteInfo);
|
|
if (implicitUserDefinedConversion.Exists)
|
|
{
|
|
return implicitUserDefinedConversion;
|
|
}
|
|
implicitUserDefinedConversion = ClassifyExplicitBuiltInOnlyConversion(source, destination, isChecked, ref useSiteInfo, forCast: false);
|
|
if (implicitUserDefinedConversion.Exists)
|
|
{
|
|
return implicitUserDefinedConversion;
|
|
}
|
|
return GetExplicitUserDefinedConversion(source, destination, isChecked, ref useSiteInfo);
|
|
}
|
|
|
|
private Conversion ClassifyConversionFromExpressionForCast(BoundExpression source, TypeSymbol destination, bool isChecked, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
Conversion conversion = ClassifyImplicitConversionFromExpression(source, destination, ref useSiteInfo);
|
|
if (conversion.Exists && !ExplicitConversionMayDifferFromImplicit(conversion))
|
|
{
|
|
return conversion;
|
|
}
|
|
Conversion result = ClassifyExplicitOnlyConversionFromExpression(source, destination, isChecked, ref useSiteInfo, forCast: true);
|
|
if (result.Exists)
|
|
{
|
|
return result;
|
|
}
|
|
return conversion;
|
|
}
|
|
|
|
private Conversion ClassifyConversionFromTypeForCast(TypeSymbol source, TypeSymbol destination, bool isChecked, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
Conversion result = FastClassifyConversion(source, destination);
|
|
if (result.Exists)
|
|
{
|
|
return result;
|
|
}
|
|
Conversion conversion = ClassifyImplicitBuiltInConversionSlow(source, destination, ref useSiteInfo);
|
|
if (conversion.Exists && !ExplicitConversionMayDifferFromImplicit(conversion))
|
|
{
|
|
return conversion;
|
|
}
|
|
Conversion result2 = ClassifyExplicitBuiltInOnlyConversion(source, destination, isChecked, ref useSiteInfo, forCast: true);
|
|
if (result2.Exists)
|
|
{
|
|
return result2;
|
|
}
|
|
if (conversion.Exists)
|
|
{
|
|
return conversion;
|
|
}
|
|
Conversion explicitUserDefinedConversion = GetExplicitUserDefinedConversion(source, destination, isChecked, ref useSiteInfo);
|
|
if (explicitUserDefinedConversion.Exists)
|
|
{
|
|
return explicitUserDefinedConversion;
|
|
}
|
|
return GetImplicitUserDefinedConversion(source, destination, ref useSiteInfo);
|
|
}
|
|
|
|
public static Conversion FastClassifyConversion(TypeSymbol source, TypeSymbol target)
|
|
{
|
|
ConversionKind conversionKind = ConversionEasyOut.ClassifyConversion(source, target);
|
|
if (conversionKind != ConversionKind.ImplicitNullable && conversionKind != ConversionKind.ExplicitNullable)
|
|
{
|
|
return Conversion.GetTrivialConversion(conversionKind);
|
|
}
|
|
return Conversion.MakeNullableConversion(conversionKind, FastClassifyConversion(source.StrippedType(), target.StrippedType()));
|
|
}
|
|
|
|
public Conversion ClassifyBuiltInConversion(TypeSymbol source, TypeSymbol destination, bool isChecked, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
Conversion result = FastClassifyConversion(source, destination);
|
|
if (result.Exists)
|
|
{
|
|
return result;
|
|
}
|
|
Conversion result2 = ClassifyImplicitBuiltInConversionSlow(source, destination, ref useSiteInfo);
|
|
if (result2.Exists)
|
|
{
|
|
return result2;
|
|
}
|
|
return ClassifyExplicitBuiltInOnlyConversion(source, destination, isChecked, ref useSiteInfo, forCast: false);
|
|
}
|
|
|
|
public Conversion ClassifyStandardConversion(TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
return ClassifyStandardConversion(null, source, destination, ref useSiteInfo);
|
|
}
|
|
|
|
public Conversion ClassifyStandardConversion(BoundExpression sourceExpression, TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
Conversion result = ClassifyStandardImplicitConversion(sourceExpression, source, destination, ref useSiteInfo);
|
|
if (result.Exists)
|
|
{
|
|
return result;
|
|
}
|
|
if ((object)source != null)
|
|
{
|
|
return DeriveStandardExplicitFromOppositeStandardImplicitConversion(source, destination, ref useSiteInfo);
|
|
}
|
|
return Conversion.NoConversion;
|
|
}
|
|
|
|
private static bool IsStandardImplicitConversionFromExpression(ConversionKind kind)
|
|
{
|
|
if (IsStandardImplicitConversionFromType(kind))
|
|
{
|
|
return true;
|
|
}
|
|
switch (kind)
|
|
{
|
|
case ConversionKind.ImplicitEnumeration:
|
|
case ConversionKind.ImplicitTupleLiteral:
|
|
case ConversionKind.ImplicitNullToPointer:
|
|
case ConversionKind.ImplicitDynamic:
|
|
case ConversionKind.AnonymousFunction:
|
|
case ConversionKind.MethodGroup:
|
|
case ConversionKind.StackAllocToPointerType:
|
|
case ConversionKind.StackAllocToSpanType:
|
|
case ConversionKind.InlineArray:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private static bool IsStandardImplicitConversionFromType(ConversionKind kind)
|
|
{
|
|
switch (kind)
|
|
{
|
|
case ConversionKind.Identity:
|
|
case ConversionKind.ImplicitNumeric:
|
|
case ConversionKind.ImplicitTuple:
|
|
case ConversionKind.ImplicitNullable:
|
|
case ConversionKind.ImplicitReference:
|
|
case ConversionKind.Boxing:
|
|
case ConversionKind.ImplicitPointerToVoid:
|
|
case ConversionKind.ImplicitPointer:
|
|
case ConversionKind.ImplicitConstant:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private Conversion ClassifyStandardImplicitConversion(BoundExpression sourceExpression, TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
Conversion result = ClassifyImplicitBuiltInConversionFromExpression(sourceExpression, source, destination, ref useSiteInfo);
|
|
if (result.Exists && !result.IsInterpolatedStringHandler && !result.IsCollectionExpression)
|
|
{
|
|
return result;
|
|
}
|
|
if ((object)source != null)
|
|
{
|
|
return ClassifyStandardImplicitConversion(source, destination, ref useSiteInfo);
|
|
}
|
|
return Conversion.NoConversion;
|
|
}
|
|
|
|
private Conversion ClassifyStandardImplicitConversion(TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
return classifyConversion(source, destination, ref useSiteInfo);
|
|
Conversion classifyConversion(TypeSymbol typeSymbol, TypeSymbol typeSymbol2, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo2)
|
|
{
|
|
if (HasIdentityConversionInternal(typeSymbol, typeSymbol2))
|
|
{
|
|
return Conversion.Identity;
|
|
}
|
|
if (HasImplicitNumericConversion(typeSymbol, typeSymbol2))
|
|
{
|
|
return Conversion.ImplicitNumeric;
|
|
}
|
|
Conversion result = ClassifyImplicitNullableConversion(typeSymbol, typeSymbol2, ref useSiteInfo2);
|
|
if (result.Exists)
|
|
{
|
|
return result;
|
|
}
|
|
if (typeSymbol is FunctionTypeSymbol)
|
|
{
|
|
return Conversion.NoConversion;
|
|
}
|
|
if (HasImplicitReferenceConversion(typeSymbol, typeSymbol2, ref useSiteInfo2))
|
|
{
|
|
return Conversion.ImplicitReference;
|
|
}
|
|
if (HasBoxingConversion(typeSymbol, typeSymbol2, ref useSiteInfo2))
|
|
{
|
|
return Conversion.Boxing;
|
|
}
|
|
if (HasImplicitPointerToVoidConversion(typeSymbol, typeSymbol2))
|
|
{
|
|
return Conversion.PointerToVoid;
|
|
}
|
|
if (HasImplicitPointerConversion(typeSymbol, typeSymbol2, ref useSiteInfo2))
|
|
{
|
|
return Conversion.ImplicitPointer;
|
|
}
|
|
Conversion result2 = ClassifyImplicitTupleConversion(typeSymbol, typeSymbol2, ref useSiteInfo2);
|
|
if (result2.Exists)
|
|
{
|
|
return result2;
|
|
}
|
|
return Conversion.NoConversion;
|
|
}
|
|
}
|
|
|
|
private Conversion ClassifyImplicitBuiltInConversionSlow(TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
if (source.IsVoidType() || destination.IsVoidType())
|
|
{
|
|
return Conversion.NoConversion;
|
|
}
|
|
Conversion result = ClassifyStandardImplicitConversion(source, destination, ref useSiteInfo);
|
|
if (result.Exists)
|
|
{
|
|
return result;
|
|
}
|
|
return Conversion.NoConversion;
|
|
}
|
|
|
|
private Conversion GetImplicitUserDefinedConversion(BoundExpression sourceExpression, TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
return new Conversion(AnalyzeImplicitUserDefinedConversions(sourceExpression, source, destination, ref useSiteInfo), isImplicit: true);
|
|
}
|
|
|
|
private Conversion GetImplicitUserDefinedConversion(TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
return GetImplicitUserDefinedConversion(null, source, destination, ref useSiteInfo);
|
|
}
|
|
|
|
private Conversion ClassifyExplicitBuiltInOnlyConversion(TypeSymbol source, TypeSymbol destination, bool isChecked, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo, bool forCast)
|
|
{
|
|
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0060: Invalid comparison between Unknown and I4
|
|
if (source.IsVoidType() || destination.IsVoidType())
|
|
{
|
|
return Conversion.NoConversion;
|
|
}
|
|
if (HasSpecialIntPtrConversion(source, destination))
|
|
{
|
|
return Conversion.IntPtr;
|
|
}
|
|
if (HasExplicitEnumerationConversion(source, destination))
|
|
{
|
|
return Conversion.ExplicitEnumeration;
|
|
}
|
|
Conversion result = ClassifyExplicitNullableConversion(source, destination, isChecked, ref useSiteInfo, forCast);
|
|
if (result.Exists)
|
|
{
|
|
return result;
|
|
}
|
|
if (HasExplicitReferenceConversion(source, destination, ref useSiteInfo))
|
|
{
|
|
if ((int)source.Kind != 3)
|
|
{
|
|
return Conversion.ExplicitReference;
|
|
}
|
|
return Conversion.ExplicitDynamic;
|
|
}
|
|
if (HasUnboxingConversion(source, destination, ref useSiteInfo))
|
|
{
|
|
return Conversion.Unboxing;
|
|
}
|
|
Conversion result2 = ClassifyExplicitTupleConversion(source, destination, isChecked, ref useSiteInfo, forCast);
|
|
if (result2.Exists)
|
|
{
|
|
return result2;
|
|
}
|
|
if (HasPointerToPointerConversion(source, destination))
|
|
{
|
|
return Conversion.PointerToPointer;
|
|
}
|
|
if (HasPointerToIntegerConversion(source, destination))
|
|
{
|
|
return Conversion.PointerToInteger;
|
|
}
|
|
if (HasIntegerToPointerConversion(source, destination))
|
|
{
|
|
return Conversion.IntegerToPointer;
|
|
}
|
|
if (HasExplicitDynamicConversion(source, destination))
|
|
{
|
|
return Conversion.ExplicitDynamic;
|
|
}
|
|
return Conversion.NoConversion;
|
|
}
|
|
|
|
private Conversion GetExplicitUserDefinedConversion(BoundExpression sourceExpression, TypeSymbol source, TypeSymbol destination, bool isChecked, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
return new Conversion(AnalyzeExplicitUserDefinedConversions(sourceExpression, source, destination, isChecked, ref useSiteInfo), isImplicit: false);
|
|
}
|
|
|
|
private Conversion GetExplicitUserDefinedConversion(TypeSymbol source, TypeSymbol destination, bool isChecked, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
return GetExplicitUserDefinedConversion(null, source, destination, isChecked, ref useSiteInfo);
|
|
}
|
|
|
|
private Conversion DeriveStandardExplicitFromOppositeStandardImplicitConversion(TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
Conversion conversion = ClassifyStandardImplicitConversion(destination, source, ref useSiteInfo);
|
|
switch (conversion.Kind)
|
|
{
|
|
case ConversionKind.Identity:
|
|
return Conversion.Identity;
|
|
case ConversionKind.ImplicitNumeric:
|
|
return Conversion.ExplicitNumeric;
|
|
case ConversionKind.ImplicitReference:
|
|
return Conversion.ExplicitReference;
|
|
case ConversionKind.Boxing:
|
|
return Conversion.Unboxing;
|
|
case ConversionKind.NoConversion:
|
|
return Conversion.NoConversion;
|
|
case ConversionKind.ImplicitPointerToVoid:
|
|
return Conversion.PointerToPointer;
|
|
case ConversionKind.ImplicitTuple:
|
|
return Conversion.NoConversion;
|
|
case ConversionKind.ImplicitNullable:
|
|
{
|
|
TypeSymbol source2 = source.StrippedType();
|
|
TypeSymbol destination2 = destination.StrippedType();
|
|
Conversion nestedConversion = DeriveStandardExplicitFromOppositeStandardImplicitConversion(source2, destination2, ref useSiteInfo);
|
|
return nestedConversion.Exists ? Conversion.MakeNullableConversion(ConversionKind.ExplicitNullable, nestedConversion) : Conversion.NoConversion;
|
|
}
|
|
default:
|
|
throw ExceptionUtilities.UnexpectedValue((object)conversion.Kind);
|
|
}
|
|
}
|
|
|
|
public bool IsBaseInterface(TypeSymbol baseType, TypeSymbol derivedType, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
if (!baseType.IsInterfaceType())
|
|
{
|
|
return false;
|
|
}
|
|
if (!(derivedType is NamedTypeSymbol namedTypeSymbol))
|
|
{
|
|
return false;
|
|
}
|
|
ImmutableArray<NamedTypeSymbol>.Enumerator enumerator = namedTypeSymbol.AllInterfacesWithDefinitionUseSiteDiagnostics(ref useSiteInfo).GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
NamedTypeSymbol current = enumerator.Current;
|
|
if (HasIdentityConversionInternal(current, baseType))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public bool IsBaseClass(TypeSymbol derivedType, TypeSymbol baseType, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
if (!baseType.IsClassType())
|
|
{
|
|
return false;
|
|
}
|
|
TypeSymbol typeSymbol = derivedType.BaseTypeWithDefinitionUseSiteDiagnostics(ref useSiteInfo);
|
|
while ((object)typeSymbol != null)
|
|
{
|
|
if (HasIdentityConversionInternal(typeSymbol, baseType))
|
|
{
|
|
return true;
|
|
}
|
|
typeSymbol = typeSymbol.BaseTypeWithDefinitionUseSiteDiagnostics(ref useSiteInfo);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private static bool ExplicitConversionMayDifferFromImplicit(Conversion implicitConversion)
|
|
{
|
|
switch (implicitConversion.Kind)
|
|
{
|
|
case ConversionKind.ImplicitTupleLiteral:
|
|
case ConversionKind.ImplicitTuple:
|
|
case ConversionKind.ImplicitNullable:
|
|
case ConversionKind.ImplicitDynamic:
|
|
case ConversionKind.ImplicitUserDefined:
|
|
case ConversionKind.ConditionalExpression:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private Conversion ClassifyImplicitBuiltInConversionFromExpression(BoundExpression sourceExpression, TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
if (HasImplicitDynamicConversionFromExpression(source, destination))
|
|
{
|
|
return Conversion.ImplicitDynamic;
|
|
}
|
|
if (sourceExpression == null)
|
|
{
|
|
return Conversion.NoConversion;
|
|
}
|
|
if (HasImplicitEnumerationConversion(sourceExpression, destination))
|
|
{
|
|
return Conversion.ImplicitEnumeration;
|
|
}
|
|
Conversion result = ClassifyImplicitConstantExpressionConversion(sourceExpression, destination);
|
|
if (result.Exists)
|
|
{
|
|
return result;
|
|
}
|
|
BoundKind kind = sourceExpression.Kind;
|
|
if (kind <= BoundKind.UnconvertedObjectCreationExpression)
|
|
{
|
|
if (kind <= BoundKind.DefaultLiteral)
|
|
{
|
|
if (kind != BoundKind.UnconvertedAddressOfOperator)
|
|
{
|
|
if (kind != BoundKind.BinaryOperator)
|
|
{
|
|
if (kind == BoundKind.DefaultLiteral)
|
|
{
|
|
return Conversion.DefaultLiteral;
|
|
}
|
|
}
|
|
else if (((BoundBinaryOperator)sourceExpression).IsUnconvertedInterpolatedStringAddition)
|
|
{
|
|
goto IL_01bb;
|
|
}
|
|
}
|
|
else if (destination is FunctionPointerTypeSymbol destination2)
|
|
{
|
|
Conversion methodGroupFunctionPointerConversion = GetMethodGroupFunctionPointerConversion(((BoundUnconvertedAddressOfOperator)sourceExpression).Operand, destination2, ref useSiteInfo);
|
|
if (methodGroupFunctionPointerConversion.Exists)
|
|
{
|
|
return methodGroupFunctionPointerConversion;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (kind)
|
|
{
|
|
case BoundKind.Literal:
|
|
{
|
|
Conversion result2 = ClassifyNullLiteralConversion(sourceExpression, destination);
|
|
if (result2.Exists)
|
|
{
|
|
return result2;
|
|
}
|
|
break;
|
|
}
|
|
case BoundKind.MethodGroup:
|
|
{
|
|
Conversion methodGroupDelegateConversion = GetMethodGroupDelegateConversion((BoundMethodGroup)sourceExpression, destination, ref useSiteInfo);
|
|
if (methodGroupDelegateConversion.Exists)
|
|
{
|
|
return methodGroupDelegateConversion;
|
|
}
|
|
break;
|
|
}
|
|
case BoundKind.UnconvertedObjectCreationExpression:
|
|
return Conversion.ObjectCreation;
|
|
}
|
|
}
|
|
}
|
|
else if (kind <= BoundKind.StackAllocArrayCreation)
|
|
{
|
|
switch (kind)
|
|
{
|
|
case BoundKind.TupleLiteral:
|
|
{
|
|
Conversion result3 = ClassifyImplicitTupleLiteralConversion((BoundTupleLiteral)sourceExpression, destination, ref useSiteInfo);
|
|
if (result3.Exists)
|
|
{
|
|
return result3;
|
|
}
|
|
break;
|
|
}
|
|
case BoundKind.StackAllocArrayCreation:
|
|
{
|
|
Conversion stackAllocConversion = GetStackAllocConversion((BoundStackAllocArrayCreation)sourceExpression, destination, ref useSiteInfo);
|
|
if (stackAllocConversion.Exists)
|
|
{
|
|
return stackAllocConversion;
|
|
}
|
|
break;
|
|
}
|
|
case BoundKind.UnconvertedCollectionExpression:
|
|
{
|
|
Conversion implicitCollectionExpressionConversion = GetImplicitCollectionExpressionConversion((BoundUnconvertedCollectionExpression)sourceExpression, destination, ref useSiteInfo);
|
|
if (implicitCollectionExpressionConversion.Exists)
|
|
{
|
|
return implicitCollectionExpressionConversion;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if (kind <= BoundKind.UnconvertedInterpolatedString)
|
|
{
|
|
if (kind != BoundKind.UnboundLambda)
|
|
{
|
|
if (kind == BoundKind.UnconvertedInterpolatedString)
|
|
{
|
|
goto IL_01bb;
|
|
}
|
|
}
|
|
else if (HasAnonymousFunctionConversion(sourceExpression, destination, Compilation))
|
|
{
|
|
return Conversion.AnonymousFunction;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (kind)
|
|
{
|
|
case BoundKind.ExpressionWithNullability:
|
|
{
|
|
BoundExpression expression = ((BoundExpressionWithNullability)sourceExpression).Expression;
|
|
Conversion result4 = ClassifyImplicitBuiltInConversionFromExpression(expression, expression.Type, destination, ref useSiteInfo);
|
|
if (result4.Exists)
|
|
{
|
|
return result4;
|
|
}
|
|
break;
|
|
}
|
|
case BoundKind.ThrowExpression:
|
|
return Conversion.ImplicitThrow;
|
|
}
|
|
}
|
|
goto IL_0248;
|
|
IL_0248:
|
|
if (!IsAttributeArgumentBinding && !IsParameterDefaultValueBinding && (object)source != null && source.HasInlineArrayAttribute(out var _))
|
|
{
|
|
FieldSymbol fieldSymbol = source.TryGetInlineArrayElementField();
|
|
if ((object)fieldSymbol != null)
|
|
{
|
|
TypeWithAnnotations typeWithAnnotations = fieldSymbol.TypeWithAnnotations;
|
|
if ((destination.OriginalDefinition.Equals(Compilation.GetWellKnownType((WellKnownType)275), (TypeCompareKind)63) || destination.OriginalDefinition.Equals(Compilation.GetWellKnownType((WellKnownType)276), (TypeCompareKind)63)) && HasIdentityConversionInternal(((NamedTypeSymbol)destination.OriginalDefinition).Construct(ImmutableArray.Create(typeWithAnnotations)), destination))
|
|
{
|
|
return Conversion.InlineArray;
|
|
}
|
|
}
|
|
}
|
|
return Conversion.NoConversion;
|
|
IL_01bb:
|
|
Conversion interpolatedStringConversion = GetInterpolatedStringConversion(sourceExpression, destination, ref useSiteInfo);
|
|
if (interpolatedStringConversion.Exists)
|
|
{
|
|
return interpolatedStringConversion;
|
|
}
|
|
goto IL_0248;
|
|
}
|
|
|
|
private Conversion GetImplicitCollectionExpressionConversion(BoundUnconvertedCollectionExpression collectionExpression, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
Conversion collectionExpressionConversion = GetCollectionExpressionConversion(collectionExpression, destination, ref useSiteInfo);
|
|
if (collectionExpressionConversion.Exists)
|
|
{
|
|
return collectionExpressionConversion;
|
|
}
|
|
if (destination.IsNullableType(out TypeSymbol underlyingType))
|
|
{
|
|
Conversion collectionExpressionConversion2 = GetCollectionExpressionConversion(collectionExpression, underlyingType, ref useSiteInfo);
|
|
if (collectionExpressionConversion2.Exists)
|
|
{
|
|
return new Conversion(ConversionKind.ImplicitNullable, ImmutableArray.Create(collectionExpressionConversion2));
|
|
}
|
|
}
|
|
return Conversion.NoConversion;
|
|
}
|
|
|
|
private Conversion GetSwitchExpressionConversion(BoundExpression source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
if (!(source is BoundConvertedSwitchExpression))
|
|
{
|
|
if (source is BoundUnconvertedSwitchExpression boundUnconvertedSwitchExpression)
|
|
{
|
|
ArrayBuilder<Conversion> instance = ArrayBuilder<Conversion>.GetInstance(boundUnconvertedSwitchExpression.SwitchArms.Length);
|
|
ImmutableArray<BoundSwitchExpressionArm>.Enumerator enumerator = boundUnconvertedSwitchExpression.SwitchArms.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
BoundSwitchExpressionArm current = enumerator.Current;
|
|
Conversion conversion = ClassifyImplicitConversionFromExpression(current.Value, destination, ref useSiteInfo);
|
|
if (!conversion.Exists)
|
|
{
|
|
instance.Free();
|
|
return Conversion.NoConversion;
|
|
}
|
|
instance.Add(conversion);
|
|
}
|
|
return Conversion.MakeSwitchExpression(instance.ToImmutableAndFree());
|
|
}
|
|
return Conversion.NoConversion;
|
|
}
|
|
return Conversion.NoConversion;
|
|
}
|
|
|
|
private Conversion GetConditionalExpressionConversion(BoundExpression source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
if (!(source is BoundUnconvertedConditionalOperator boundUnconvertedConditionalOperator))
|
|
{
|
|
return Conversion.NoConversion;
|
|
}
|
|
Conversion item = ClassifyImplicitConversionFromExpression(boundUnconvertedConditionalOperator.Consequence, destination, ref useSiteInfo);
|
|
if (!item.Exists)
|
|
{
|
|
return Conversion.NoConversion;
|
|
}
|
|
Conversion item2 = ClassifyImplicitConversionFromExpression(boundUnconvertedConditionalOperator.Alternative, destination, ref useSiteInfo);
|
|
if (!item2.Exists)
|
|
{
|
|
return Conversion.NoConversion;
|
|
}
|
|
return Conversion.MakeConditionalExpression(ImmutableArray.Create(item, item2));
|
|
}
|
|
|
|
private static Conversion ClassifyNullLiteralConversion(BoundExpression source, TypeSymbol destination)
|
|
{
|
|
if (!source.IsLiteralNull())
|
|
{
|
|
return Conversion.NoConversion;
|
|
}
|
|
if (destination.IsNullableType())
|
|
{
|
|
return Conversion.NullLiteral;
|
|
}
|
|
if (destination.IsReferenceType)
|
|
{
|
|
return Conversion.ImplicitReference;
|
|
}
|
|
if (destination.IsPointerOrFunctionPointer())
|
|
{
|
|
return Conversion.NullToPointer;
|
|
}
|
|
return Conversion.NoConversion;
|
|
}
|
|
|
|
private static Conversion ClassifyImplicitConstantExpressionConversion(BoundExpression source, TypeSymbol destination)
|
|
{
|
|
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0017: Invalid comparison between Unknown and I4
|
|
if (HasImplicitConstantExpressionConversion(source, destination))
|
|
{
|
|
return Conversion.ImplicitConstant;
|
|
}
|
|
if ((int)destination.Kind == 11 && destination.IsNullableType(out TypeSymbol underlyingType) && HasImplicitConstantExpressionConversion(source, underlyingType))
|
|
{
|
|
return Conversion.ImplicitNullableWithImplicitConstantUnderlying;
|
|
}
|
|
return Conversion.NoConversion;
|
|
}
|
|
|
|
private Conversion ClassifyImplicitTupleLiteralConversion(BoundTupleLiteral source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
Conversion implicitTupleLiteralConversion = GetImplicitTupleLiteralConversion(source, destination, ref useSiteInfo);
|
|
if (implicitTupleLiteralConversion.Exists)
|
|
{
|
|
return implicitTupleLiteralConversion;
|
|
}
|
|
if (destination.IsNullableType(out TypeSymbol underlyingType))
|
|
{
|
|
Conversion implicitTupleLiteralConversion2 = GetImplicitTupleLiteralConversion(source, underlyingType, ref useSiteInfo);
|
|
if (implicitTupleLiteralConversion2.Exists)
|
|
{
|
|
return new Conversion(ConversionKind.ImplicitNullable, ImmutableArray.Create(implicitTupleLiteralConversion2));
|
|
}
|
|
}
|
|
return Conversion.NoConversion;
|
|
}
|
|
|
|
private Conversion ClassifyExplicitTupleLiteralConversion(BoundTupleLiteral source, TypeSymbol destination, bool isChecked, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo, bool forCast)
|
|
{
|
|
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0021: Invalid comparison between Unknown and I4
|
|
Conversion explicitTupleLiteralConversion = GetExplicitTupleLiteralConversion(source, destination, isChecked, ref useSiteInfo, forCast);
|
|
if (explicitTupleLiteralConversion.Exists)
|
|
{
|
|
return explicitTupleLiteralConversion;
|
|
}
|
|
if ((int)destination.Kind == 11 && destination.IsNullableType(out TypeSymbol underlyingType))
|
|
{
|
|
Conversion explicitTupleLiteralConversion2 = GetExplicitTupleLiteralConversion(source, underlyingType, isChecked, ref useSiteInfo, forCast);
|
|
if (explicitTupleLiteralConversion2.Exists)
|
|
{
|
|
return new Conversion(ConversionKind.ExplicitNullable, ImmutableArray.Create(explicitTupleLiteralConversion2));
|
|
}
|
|
}
|
|
return Conversion.NoConversion;
|
|
}
|
|
|
|
internal static bool HasImplicitConstantExpressionConversion(BoundExpression source, TypeSymbol destination)
|
|
{
|
|
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0029: Invalid comparison between Unknown and I4
|
|
//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00fd: Invalid comparison between Unknown and I4
|
|
//IL_0100: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0107: Invalid comparison between Unknown and I4
|
|
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0088: Expected I4, but got Unknown
|
|
ConstantValue constantValueOpt = source.ConstantValueOpt;
|
|
if (constantValueOpt == (ConstantValue)null || (object)source.Type == null)
|
|
{
|
|
return false;
|
|
}
|
|
SpecialType specialTypeSafe = source.Type.GetSpecialTypeSafe();
|
|
if ((int)specialTypeSafe == 13)
|
|
{
|
|
int num = ((!constantValueOpt.IsBad) ? constantValueOpt.Int32Value : 0);
|
|
SpecialType specialTypeSafe2 = destination.GetSpecialTypeSafe();
|
|
switch (specialTypeSafe2 - 9)
|
|
{
|
|
case 1:
|
|
if (0 <= num)
|
|
{
|
|
return num <= 255;
|
|
}
|
|
return false;
|
|
case 0:
|
|
if (-128 <= num)
|
|
{
|
|
return num <= 127;
|
|
}
|
|
return false;
|
|
case 2:
|
|
if (-32768 <= num)
|
|
{
|
|
return num <= 32767;
|
|
}
|
|
return false;
|
|
case 12:
|
|
if (destination.IsNativeIntegerType)
|
|
{
|
|
return true;
|
|
}
|
|
break;
|
|
case 13:
|
|
if (!destination.IsNativeIntegerType)
|
|
{
|
|
break;
|
|
}
|
|
goto case 5;
|
|
case 5:
|
|
return 0L <= (long)num;
|
|
case 7:
|
|
return 0 <= num;
|
|
case 3:
|
|
if (0 <= num)
|
|
{
|
|
return num <= 65535;
|
|
}
|
|
return false;
|
|
}
|
|
return false;
|
|
}
|
|
if ((int)specialTypeSafe == 15 && (int)destination.GetSpecialTypeSafe() == 16 && (constantValueOpt.IsBad || 0 <= constantValueOpt.Int64Value))
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private Conversion ClassifyExplicitOnlyConversionFromExpression(BoundExpression sourceExpression, TypeSymbol destination, bool isChecked, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo, bool forCast)
|
|
{
|
|
if (sourceExpression.Kind == BoundKind.TupleLiteral)
|
|
{
|
|
Conversion result = ClassifyExplicitTupleLiteralConversion((BoundTupleLiteral)sourceExpression, destination, isChecked, ref useSiteInfo, forCast);
|
|
if (result.Exists)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
TypeSymbol type = sourceExpression.Type;
|
|
if ((object)type != null)
|
|
{
|
|
Conversion result2 = FastClassifyConversion(type, destination);
|
|
if (result2.Exists)
|
|
{
|
|
return result2;
|
|
}
|
|
Conversion result3 = ClassifyExplicitBuiltInOnlyConversion(type, destination, isChecked, ref useSiteInfo, forCast);
|
|
if (result3.Exists)
|
|
{
|
|
return result3;
|
|
}
|
|
}
|
|
return GetExplicitUserDefinedConversion(sourceExpression, type, destination, isChecked, ref useSiteInfo);
|
|
}
|
|
|
|
private static bool HasImplicitEnumerationConversion(BoundExpression source, TypeSymbol destination)
|
|
{
|
|
if (!destination.IsEnumType() && (!destination.IsNullableType() || !destination.GetNullableUnderlyingType().IsEnumType()))
|
|
{
|
|
return false;
|
|
}
|
|
ConstantValue constantValueOpt = source.ConstantValueOpt;
|
|
if (constantValueOpt != (ConstantValue)null && (object)source.Type != null && IsNumericType(source.Type))
|
|
{
|
|
return IsConstantNumericZero(constantValueOpt);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private static LambdaConversionResult IsAnonymousFunctionCompatibleWithDelegate(UnboundLambda anonymousFunction, TypeSymbol type, CSharpCompilation compilation, bool isTargetExpressionTree)
|
|
{
|
|
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0136: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_013c: Invalid comparison between Unknown and I4
|
|
//IL_0159: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_015e: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00db: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
|
|
NamedTypeSymbol namedTypeSymbol = (NamedTypeSymbol)type;
|
|
MethodSymbol delegateInvokeMethod = namedTypeSymbol.DelegateInvokeMethod;
|
|
if ((object)delegateInvokeMethod == null || delegateInvokeMethod.HasUseSiteError)
|
|
{
|
|
return LambdaConversionResult.BadTargetType;
|
|
}
|
|
if (anonymousFunction.HasExplicitReturnType(out var refKind, out var returnType) && (delegateInvokeMethod.RefKind != refKind || !delegateInvokeMethod.ReturnType.Equals(returnType.Type, (TypeCompareKind)63)))
|
|
{
|
|
return LambdaConversionResult.MismatchedReturnType;
|
|
}
|
|
ImmutableArray<ParameterSymbol> parameters = delegateInvokeMethod.Parameters;
|
|
if (anonymousFunction.HasSignature)
|
|
{
|
|
if (anonymousFunction.ParameterCount != delegateInvokeMethod.ParameterCount)
|
|
{
|
|
return LambdaConversionResult.BadParameterCount;
|
|
}
|
|
if (anonymousFunction.HasExplicitlyTypedParameterList)
|
|
{
|
|
for (int i = 0; i < parameters.Length; i++)
|
|
{
|
|
if (!OverloadResolution.AreRefsCompatibleForMethodConversion(parameters[i].RefKind, anonymousFunction.RefKind(i), compilation) || !parameters[i].Type.Equals(anonymousFunction.ParameterType(i), (TypeCompareKind)63))
|
|
{
|
|
return LambdaConversionResult.MismatchedParameterType;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int j = 0; j < parameters.Length; j++)
|
|
{
|
|
if ((int)parameters[j].RefKind != 0)
|
|
{
|
|
return LambdaConversionResult.RefInImplicitlyTypedLambda;
|
|
}
|
|
}
|
|
for (int k = 0; k < parameters.Length; k++)
|
|
{
|
|
if (parameters[k].TypeWithAnnotations.IsStatic)
|
|
{
|
|
return LambdaConversionResult.StaticTypeInImplicitlyTypedLambda;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int l = 0; l < parameters.Length; l++)
|
|
{
|
|
if ((int)parameters[l].RefKind == 2)
|
|
{
|
|
return LambdaConversionResult.MissingSignatureWithOutParameter;
|
|
}
|
|
}
|
|
}
|
|
if (ErrorFacts.PreventsSuccessfulDelegateConversion(anonymousFunction.Bind(namedTypeSymbol, isTargetExpressionTree).Diagnostics.Diagnostics))
|
|
{
|
|
return LambdaConversionResult.BindingFailed;
|
|
}
|
|
return LambdaConversionResult.Success;
|
|
}
|
|
|
|
private static LambdaConversionResult IsAnonymousFunctionCompatibleWithExpressionTree(UnboundLambda anonymousFunction, NamedTypeSymbol type, CSharpCompilation compilation)
|
|
{
|
|
TypeSymbol type2 = type.TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0].Type;
|
|
if (!type2.IsDelegateType())
|
|
{
|
|
return LambdaConversionResult.ExpressionTreeMustHaveDelegateTypeArgument;
|
|
}
|
|
if (anonymousFunction.Syntax.Kind() == SyntaxKind.AnonymousMethodExpression)
|
|
{
|
|
return LambdaConversionResult.ExpressionTreeFromAnonymousMethod;
|
|
}
|
|
return IsAnonymousFunctionCompatibleWithDelegate(anonymousFunction, type2, compilation, isTargetExpressionTree: true);
|
|
}
|
|
|
|
internal bool IsAssignableFromMulticastDelegate(TypeSymbol type, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
NamedTypeSymbol specialType = corLibrary.GetSpecialType((SpecialType)3);
|
|
specialType.AddUseSiteInfo(ref useSiteInfo);
|
|
return ClassifyImplicitConversionFromType(specialType, type, ref useSiteInfo).Exists;
|
|
}
|
|
|
|
public static LambdaConversionResult IsAnonymousFunctionCompatibleWithType(UnboundLambda anonymousFunction, TypeSymbol type, CSharpCompilation compilation)
|
|
{
|
|
if (type.IsDelegateType())
|
|
{
|
|
return IsAnonymousFunctionCompatibleWithDelegate(anonymousFunction, type, compilation, isTargetExpressionTree: false);
|
|
}
|
|
if (type.IsExpressionTree())
|
|
{
|
|
return IsAnonymousFunctionCompatibleWithExpressionTree(anonymousFunction, (NamedTypeSymbol)type, compilation);
|
|
}
|
|
return LambdaConversionResult.BadTargetType;
|
|
}
|
|
|
|
private static bool HasAnonymousFunctionConversion(BoundExpression source, TypeSymbol destination, CSharpCompilation compilation)
|
|
{
|
|
if (source.Kind != BoundKind.UnboundLambda)
|
|
{
|
|
return false;
|
|
}
|
|
return IsAnonymousFunctionCompatibleWithType((UnboundLambda)source, destination, compilation) == LambdaConversionResult.Success;
|
|
}
|
|
|
|
internal static CollectionExpressionTypeKind GetCollectionExpressionTypeKind(CSharpCompilation compilation, TypeSymbol destination, out TypeWithAnnotations elementType)
|
|
{
|
|
if (destination is ArrayTypeSymbol arrayTypeSymbol)
|
|
{
|
|
if (arrayTypeSymbol.IsSZArray)
|
|
{
|
|
elementType = arrayTypeSymbol.ElementTypeWithAnnotations;
|
|
return CollectionExpressionTypeKind.Array;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (isSpanOrListType(compilation, destination, (WellKnownType)204, out elementType) && (object)compilation.GetWellKnownTypeMember((WellKnownMember)505) != null)
|
|
{
|
|
return CollectionExpressionTypeKind.ImmutableArray;
|
|
}
|
|
if (isSpanOrListType(compilation, destination, (WellKnownType)275, out elementType))
|
|
{
|
|
return CollectionExpressionTypeKind.Span;
|
|
}
|
|
if (isSpanOrListType(compilation, destination, (WellKnownType)276, out elementType))
|
|
{
|
|
return CollectionExpressionTypeKind.ReadOnlySpan;
|
|
}
|
|
if (isSpanOrListType(compilation, destination, (WellKnownType)206, out elementType))
|
|
{
|
|
return CollectionExpressionTypeKind.List;
|
|
}
|
|
NamedTypeSymbol obj = destination as NamedTypeSymbol;
|
|
if ((object)obj != null && obj.HasCollectionBuilderAttribute(out TypeSymbol _, out string _))
|
|
{
|
|
return CollectionExpressionTypeKind.CollectionBuilder;
|
|
}
|
|
if (implementsSpecialInterface(compilation, destination, (SpecialType)25))
|
|
{
|
|
elementType = default(TypeWithAnnotations);
|
|
return CollectionExpressionTypeKind.ImplementsIEnumerableT;
|
|
}
|
|
if (implementsSpecialInterface(compilation, destination, (SpecialType)24))
|
|
{
|
|
elementType = default(TypeWithAnnotations);
|
|
return CollectionExpressionTypeKind.ImplementsIEnumerable;
|
|
}
|
|
if (destination.IsArrayInterface(out elementType))
|
|
{
|
|
return CollectionExpressionTypeKind.ArrayInterface;
|
|
}
|
|
}
|
|
elementType = default(TypeWithAnnotations);
|
|
return CollectionExpressionTypeKind.None;
|
|
static bool implementsSpecialInterface(CSharpCompilation cSharpCompilation, TypeSymbol targetType, SpecialType specialInterface)
|
|
{
|
|
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
|
|
ImmutableArray<NamedTypeSymbol> allInterfacesOrEffectiveInterfaces = targetType.GetAllInterfacesOrEffectiveInterfaces();
|
|
NamedTypeSymbol specialType = cSharpCompilation.GetSpecialType(specialInterface);
|
|
return ImmutableArrayExtensions.Any<NamedTypeSymbol, NamedTypeSymbol>(allInterfacesOrEffectiveInterfaces, (Func<NamedTypeSymbol, NamedTypeSymbol, bool>)((NamedTypeSymbol a, NamedTypeSymbol b) => (object)a.OriginalDefinition == b), specialType);
|
|
}
|
|
static bool isSpanOrListType(CSharpCompilation cSharpCompilation, TypeSymbol targetType, WellKnownType spanType, [NotNullWhen(true)] out TypeWithAnnotations reference)
|
|
{
|
|
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
|
|
if (targetType is NamedTypeSymbol { Arity: 1 } namedTypeSymbol && (object)namedTypeSymbol.OriginalDefinition == cSharpCompilation.GetWellKnownType(spanType))
|
|
{
|
|
reference = namedTypeSymbol.TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0];
|
|
return true;
|
|
}
|
|
reference = default(TypeWithAnnotations);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
internal Conversion ClassifyImplicitUserDefinedConversionForV6SwitchGoverningType(TypeSymbol sourceType, out TypeSymbol switchGoverningType, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
UserDefinedConversionResult conversionResult = AnalyzeImplicitUserDefinedConversionForV6SwitchGoverningType(sourceType, ref useSiteInfo);
|
|
if (conversionResult.Kind == UserDefinedConversionResultKind.Valid)
|
|
{
|
|
UserDefinedConversionAnalysis userDefinedConversionAnalysis = conversionResult.Results[conversionResult.Best];
|
|
switchGoverningType = userDefinedConversionAnalysis.ToType;
|
|
}
|
|
else
|
|
{
|
|
switchGoverningType = null;
|
|
}
|
|
return new Conversion(conversionResult, isImplicit: true);
|
|
}
|
|
|
|
internal Conversion GetCallerLineNumberConversion(TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
Microsoft.CodeAnalysis.CSharp.Syntax.LiteralExpressionSyntax syntax = new Microsoft.CodeAnalysis.CSharp.Syntax.LiteralExpressionSyntax(new Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.LiteralExpressionSyntax(SyntaxKind.NumericLiteralExpression, new SyntaxToken(SyntaxKind.NumericLiteralToken)), null, 0);
|
|
TypeSymbol specialType = corLibrary.GetSpecialType((SpecialType)13);
|
|
BoundLiteral source = new BoundLiteral((SyntaxNode)(object)syntax, ConstantValue.Create(int.MaxValue), specialType);
|
|
if (HasImplicitEnumerationConversion(source, destination))
|
|
{
|
|
return Conversion.ImplicitEnumeration;
|
|
}
|
|
Conversion result = ClassifyImplicitConstantExpressionConversion(source, destination);
|
|
if (result.Exists)
|
|
{
|
|
return result;
|
|
}
|
|
return ClassifyStandardImplicitConversion(specialType, destination, ref useSiteInfo);
|
|
}
|
|
|
|
internal bool HasCallerLineNumberConversion(TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
return GetCallerLineNumberConversion(destination, ref useSiteInfo).Exists;
|
|
}
|
|
|
|
internal bool HasCallerInfoStringConversion(TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
TypeSymbol specialType = corLibrary.GetSpecialType((SpecialType)20);
|
|
return ClassifyStandardImplicitConversion(specialType, destination, ref useSiteInfo).Exists;
|
|
}
|
|
|
|
public static bool HasIdentityConversion(TypeSymbol type1, TypeSymbol type2)
|
|
{
|
|
return HasIdentityConversionInternal(type1, type2, includeNullability: false);
|
|
}
|
|
|
|
private static bool HasIdentityConversionInternal(TypeSymbol type1, TypeSymbol type2, bool includeNullability)
|
|
{
|
|
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
|
|
TypeCompareKind compareKind = (TypeCompareKind)(includeNullability ? 55 : 63);
|
|
return type1.Equals(type2, compareKind);
|
|
}
|
|
|
|
private bool HasIdentityConversionInternal(TypeSymbol type1, TypeSymbol type2)
|
|
{
|
|
return HasIdentityConversionInternal(type1, type2, IncludeNullability);
|
|
}
|
|
|
|
internal bool HasTopLevelNullabilityIdentityConversion(TypeWithAnnotations source, TypeWithAnnotations destination)
|
|
{
|
|
if (!IncludeNullability)
|
|
{
|
|
return true;
|
|
}
|
|
if (source.NullableAnnotation.IsOblivious() || destination.NullableAnnotation.IsOblivious())
|
|
{
|
|
return true;
|
|
}
|
|
bool flag = IsPossiblyNullableTypeTypeParameter(in source);
|
|
bool flag2 = IsPossiblyNullableTypeTypeParameter(in destination);
|
|
if (flag && !flag2)
|
|
{
|
|
return destination.NullableAnnotation.IsAnnotated();
|
|
}
|
|
if (flag2 && !flag)
|
|
{
|
|
return source.NullableAnnotation.IsAnnotated();
|
|
}
|
|
return source.NullableAnnotation.IsAnnotated() == destination.NullableAnnotation.IsAnnotated();
|
|
}
|
|
|
|
internal bool HasTopLevelNullabilityImplicitConversion(TypeWithAnnotations source, TypeWithAnnotations destination)
|
|
{
|
|
if (!IncludeNullability)
|
|
{
|
|
return true;
|
|
}
|
|
if (source.NullableAnnotation.IsOblivious() || destination.NullableAnnotation.IsOblivious() || destination.NullableAnnotation.IsAnnotated())
|
|
{
|
|
return true;
|
|
}
|
|
if (IsPossiblyNullableTypeTypeParameter(in source) && !IsPossiblyNullableTypeTypeParameter(in destination))
|
|
{
|
|
return false;
|
|
}
|
|
return !source.NullableAnnotation.IsAnnotated();
|
|
}
|
|
|
|
private static bool IsPossiblyNullableTypeTypeParameter(in TypeWithAnnotations typeWithAnnotations)
|
|
{
|
|
TypeSymbol type = typeWithAnnotations.Type;
|
|
if ((object)type != null)
|
|
{
|
|
if (!type.IsPossiblyNullableReferenceTypeTypeParameter())
|
|
{
|
|
return type.IsNullableTypeOrTypeParameter();
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public bool HasAnyNullabilityImplicitConversion(TypeWithAnnotations source, TypeWithAnnotations destination)
|
|
{
|
|
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
|
|
CompoundUseSiteInfo<AssemblySymbol> useSiteInfo = CompoundUseSiteInfo<AssemblySymbol>.Discarded;
|
|
if (HasTopLevelNullabilityImplicitConversion(source, destination))
|
|
{
|
|
return ClassifyImplicitConversionFromType(source.Type, destination.Type, ref useSiteInfo).Kind != ConversionKind.NoConversion;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private static bool HasIdentityConversionToAny(NamedTypeSymbol type, ArrayBuilder<(NamedTypeSymbol ParticipatingType, TypeParameterSymbol ConstrainedToTypeOpt)> targetTypes)
|
|
{
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
|
Enumerator<(NamedTypeSymbol, TypeParameterSymbol)> enumerator = targetTypes.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
if (HasIdentityConversionInternal(type, enumerator.Current.Item1, includeNullability: false))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public Conversion ConvertExtensionMethodThisArg(TypeSymbol parameterType, TypeSymbol thisType, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
Conversion conversion = ClassifyImplicitExtensionMethodThisArgConversion(null, thisType, parameterType, ref useSiteInfo);
|
|
if (!IsValidExtensionMethodThisArgConversion(conversion))
|
|
{
|
|
return Conversion.NoConversion;
|
|
}
|
|
return conversion;
|
|
}
|
|
|
|
public Conversion ClassifyImplicitExtensionMethodThisArgConversion(BoundExpression sourceExpressionOpt, TypeSymbol sourceType, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
if ((object)sourceType != null)
|
|
{
|
|
if (HasIdentityConversionInternal(sourceType, destination))
|
|
{
|
|
return Conversion.Identity;
|
|
}
|
|
if (HasBoxingConversion(sourceType, destination, ref useSiteInfo))
|
|
{
|
|
return Conversion.Boxing;
|
|
}
|
|
if (HasImplicitReferenceConversion(sourceType, destination, ref useSiteInfo))
|
|
{
|
|
return Conversion.ImplicitReference;
|
|
}
|
|
}
|
|
if (sourceExpressionOpt != null && sourceExpressionOpt.Kind == BoundKind.TupleLiteral)
|
|
{
|
|
Conversion tupleLiteralConversion = GetTupleLiteralConversion((BoundTupleLiteral)sourceExpressionOpt, destination, ref useSiteInfo, ConversionKind.ImplicitTupleLiteral, delegate(ConversionsBase conversions, BoundExpression s, TypeWithAnnotations d, bool isChecked, ref CompoundUseSiteInfo<AssemblySymbol> u, bool forCast)
|
|
{
|
|
return conversions.ClassifyImplicitExtensionMethodThisArgConversion(s, s.Type, d.Type, ref u);
|
|
}, isChecked: false, forCast: false);
|
|
if (tupleLiteralConversion.Exists)
|
|
{
|
|
return tupleLiteralConversion;
|
|
}
|
|
}
|
|
if ((object)sourceType != null)
|
|
{
|
|
Conversion result = ClassifyTupleConversion(sourceType, destination, ref useSiteInfo, ConversionKind.ImplicitTuple, delegate(ConversionsBase conversions, TypeWithAnnotations s, TypeWithAnnotations d, bool _, ref CompoundUseSiteInfo<AssemblySymbol> u, bool _)
|
|
{
|
|
return (!conversions.HasTopLevelNullabilityImplicitConversion(s, d)) ? Conversion.NoConversion : conversions.ClassifyImplicitExtensionMethodThisArgConversion(null, s.Type, d.Type, ref u);
|
|
}, isChecked: false, forCast: false);
|
|
if (result.Exists)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
return Conversion.NoConversion;
|
|
}
|
|
|
|
public static bool IsValidExtensionMethodThisArgConversion(Conversion conversion)
|
|
{
|
|
switch (conversion.Kind)
|
|
{
|
|
case ConversionKind.Identity:
|
|
case ConversionKind.ImplicitReference:
|
|
case ConversionKind.Boxing:
|
|
return true;
|
|
case ConversionKind.ImplicitTupleLiteral:
|
|
case ConversionKind.ImplicitTuple:
|
|
{
|
|
ImmutableArray<Conversion>.Enumerator enumerator = conversion.UnderlyingConversions.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
if (!IsValidExtensionMethodThisArgConversion(enumerator.Current))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private static ConversionKind GetNumericConversion(TypeSymbol source, TypeSymbol destination)
|
|
{
|
|
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
|
|
if (!IsNumericType(source) || !IsNumericType(destination))
|
|
{
|
|
return ConversionKind.UnsetConversionKind;
|
|
}
|
|
if (source.SpecialType == destination.SpecialType)
|
|
{
|
|
return ConversionKind.UnsetConversionKind;
|
|
}
|
|
return ConversionEasyOut.ClassifyConversion(source, destination);
|
|
}
|
|
|
|
private static bool HasImplicitNumericConversion(TypeSymbol source, TypeSymbol destination)
|
|
{
|
|
return GetNumericConversion(source, destination) == ConversionKind.ImplicitNumeric;
|
|
}
|
|
|
|
private static bool HasExplicitNumericConversion(TypeSymbol source, TypeSymbol destination)
|
|
{
|
|
return GetNumericConversion(source, destination) == ConversionKind.ExplicitNumeric;
|
|
}
|
|
|
|
private static bool IsConstantNumericZero(ConstantValue value)
|
|
{
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_004f: Expected I4, but got Unknown
|
|
ConstantValueTypeDiscriminator discriminator = value.Discriminator;
|
|
switch (discriminator - 2)
|
|
{
|
|
case 0:
|
|
return value.SByteValue == 0;
|
|
case 1:
|
|
return value.ByteValue == 0;
|
|
case 2:
|
|
return value.Int16Value == 0;
|
|
case 4:
|
|
case 8:
|
|
return value.Int32Value == 0;
|
|
case 6:
|
|
return value.Int64Value == 0;
|
|
case 3:
|
|
return value.UInt16Value == 0;
|
|
case 5:
|
|
case 9:
|
|
return value.UInt32Value == 0;
|
|
case 7:
|
|
return value.UInt64Value == 0;
|
|
case 12:
|
|
case 13:
|
|
return value.DoubleValue == 0.0;
|
|
case 15:
|
|
return value.DecimalValue == 0m;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private static bool IsNumericType(TypeSymbol type)
|
|
{
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_004b: Expected I4, but got Unknown
|
|
SpecialType specialType = type.SpecialType;
|
|
switch (specialType - 8)
|
|
{
|
|
case 13:
|
|
if (!type.IsNativeIntegerType)
|
|
{
|
|
break;
|
|
}
|
|
goto case 0;
|
|
case 14:
|
|
if (!type.IsNativeIntegerType)
|
|
{
|
|
break;
|
|
}
|
|
goto case 0;
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
case 8:
|
|
case 9:
|
|
case 10:
|
|
case 11:
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private static bool HasSpecialIntPtrConversion(TypeSymbol source, TypeSymbol target)
|
|
{
|
|
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0039: Invalid comparison between Unknown and I4
|
|
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0049: Invalid comparison between Unknown and I4
|
|
TypeSymbol typeSymbol = source.StrippedType();
|
|
TypeSymbol typeSymbol2 = target.StrippedType();
|
|
TypeSymbol typeSymbol3;
|
|
if (isIntPtrOrUIntPtr(typeSymbol))
|
|
{
|
|
typeSymbol3 = typeSymbol2;
|
|
}
|
|
else
|
|
{
|
|
if (!isIntPtrOrUIntPtr(typeSymbol2))
|
|
{
|
|
return false;
|
|
}
|
|
typeSymbol3 = typeSymbol;
|
|
}
|
|
if (typeSymbol3.IsPointerOrFunctionPointer())
|
|
{
|
|
return true;
|
|
}
|
|
if ((int)typeSymbol3.TypeKind == 5)
|
|
{
|
|
return true;
|
|
}
|
|
SpecialType specialType = typeSymbol3.SpecialType;
|
|
if (specialType - 8 <= 11)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
static bool isIntPtrOrUIntPtr(TypeSymbol type)
|
|
{
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0008: Invalid comparison between Unknown and I4
|
|
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0012: Invalid comparison between Unknown and I4
|
|
if ((int)type.SpecialType == 21 || (int)type.SpecialType == 22)
|
|
{
|
|
return !type.IsNativeIntegerType;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private static bool HasExplicitEnumerationConversion(TypeSymbol source, TypeSymbol destination)
|
|
{
|
|
if (IsNumericType(source) && destination.IsEnumType())
|
|
{
|
|
return true;
|
|
}
|
|
if (IsNumericType(destination) && source.IsEnumType())
|
|
{
|
|
return true;
|
|
}
|
|
if (source.IsEnumType() && destination.IsEnumType())
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private Conversion ClassifyImplicitNullableConversion(TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
if (!destination.IsNullableType())
|
|
{
|
|
return Conversion.NoConversion;
|
|
}
|
|
TypeSymbol nullableUnderlyingType = destination.GetNullableUnderlyingType();
|
|
TypeSymbol typeSymbol = source.StrippedType();
|
|
if (!typeSymbol.IsValueType)
|
|
{
|
|
return Conversion.NoConversion;
|
|
}
|
|
if (HasIdentityConversionInternal(typeSymbol, nullableUnderlyingType))
|
|
{
|
|
return Conversion.ImplicitNullableWithIdentityUnderlying;
|
|
}
|
|
if (HasImplicitNumericConversion(typeSymbol, nullableUnderlyingType))
|
|
{
|
|
return Conversion.ImplicitNullableWithImplicitNumericUnderlying;
|
|
}
|
|
Conversion item = ClassifyImplicitTupleConversion(typeSymbol, nullableUnderlyingType, ref useSiteInfo);
|
|
if (item.Exists)
|
|
{
|
|
return new Conversion(ConversionKind.ImplicitNullable, ImmutableArray.Create(item));
|
|
}
|
|
return Conversion.NoConversion;
|
|
}
|
|
|
|
private Conversion GetImplicitTupleLiteralConversion(BoundTupleLiteral source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
return GetTupleLiteralConversion(source, destination, ref useSiteInfo, ConversionKind.ImplicitTupleLiteral, delegate(ConversionsBase conversions, BoundExpression s, TypeWithAnnotations d, bool isChecked, ref CompoundUseSiteInfo<AssemblySymbol> u, bool forCast)
|
|
{
|
|
return conversions.ClassifyImplicitConversionFromExpression(s, d.Type, ref u);
|
|
}, isChecked: false, forCast: false);
|
|
}
|
|
|
|
private Conversion GetExplicitTupleLiteralConversion(BoundTupleLiteral source, TypeSymbol destination, bool isChecked, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo, bool forCast)
|
|
{
|
|
return GetTupleLiteralConversion(source, destination, ref useSiteInfo, ConversionKind.ExplicitTupleLiteral, delegate(ConversionsBase conversions, BoundExpression s, TypeWithAnnotations d, bool isChecked2, ref CompoundUseSiteInfo<AssemblySymbol> u, bool forCast2)
|
|
{
|
|
return conversions.ClassifyConversionFromExpression(s, d.Type, isChecked2, ref u, forCast2);
|
|
}, isChecked, forCast);
|
|
}
|
|
|
|
private Conversion GetTupleLiteralConversion(BoundTupleLiteral source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo, ConversionKind kind, ClassifyConversionFromExpressionDelegate classifyConversion, bool isChecked, bool forCast)
|
|
{
|
|
ImmutableArray<BoundExpression> arguments = source.Arguments;
|
|
if (!destination.IsTupleTypeOfCardinality(arguments.Length))
|
|
{
|
|
return Conversion.NoConversion;
|
|
}
|
|
ImmutableArray<TypeWithAnnotations> tupleElementTypesWithAnnotations = destination.TupleElementTypesWithAnnotations;
|
|
ArrayBuilder<Conversion> instance = ArrayBuilder<Conversion>.GetInstance(arguments.Length);
|
|
for (int i = 0; i < arguments.Length; i++)
|
|
{
|
|
BoundExpression sourceExpression = arguments[i];
|
|
Conversion conversion = classifyConversion(this, sourceExpression, tupleElementTypesWithAnnotations[i], isChecked, ref useSiteInfo, forCast);
|
|
if (!conversion.Exists)
|
|
{
|
|
instance.Free();
|
|
return Conversion.NoConversion;
|
|
}
|
|
instance.Add(conversion);
|
|
}
|
|
return new Conversion(kind, instance.ToImmutableAndFree());
|
|
}
|
|
|
|
private Conversion ClassifyImplicitTupleConversion(TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
return ClassifyTupleConversion(source, destination, ref useSiteInfo, ConversionKind.ImplicitTuple, delegate(ConversionsBase conversions, TypeWithAnnotations s, TypeWithAnnotations d, bool _, ref CompoundUseSiteInfo<AssemblySymbol> u, bool _)
|
|
{
|
|
return (!conversions.HasTopLevelNullabilityImplicitConversion(s, d)) ? Conversion.NoConversion : conversions.ClassifyImplicitConversionFromType(s.Type, d.Type, ref u);
|
|
}, isChecked: false, forCast: false);
|
|
}
|
|
|
|
private Conversion ClassifyExplicitTupleConversion(TypeSymbol source, TypeSymbol destination, bool isChecked, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo, bool forCast)
|
|
{
|
|
return ClassifyTupleConversion(source, destination, ref useSiteInfo, ConversionKind.ExplicitTuple, delegate(ConversionsBase conversions, TypeWithAnnotations s, TypeWithAnnotations d, bool isChecked2, ref CompoundUseSiteInfo<AssemblySymbol> u, bool forCast2)
|
|
{
|
|
return (!conversions.HasTopLevelNullabilityImplicitConversion(s, d)) ? Conversion.NoConversion : conversions.ClassifyConversionFromType(s.Type, d.Type, isChecked2, ref u, forCast2);
|
|
}, isChecked, forCast);
|
|
}
|
|
|
|
private Conversion ClassifyTupleConversion(TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo, ConversionKind kind, ClassifyConversionFromTypeDelegate classifyConversion, bool isChecked, bool forCast)
|
|
{
|
|
if (!source.TryGetElementTypesWithAnnotationsIfTupleType(out var elementTypes) || !destination.TryGetElementTypesWithAnnotationsIfTupleType(out var elementTypes2) || elementTypes.Length != elementTypes2.Length)
|
|
{
|
|
return Conversion.NoConversion;
|
|
}
|
|
ArrayBuilder<Conversion> instance = ArrayBuilder<Conversion>.GetInstance(elementTypes.Length);
|
|
for (int i = 0; i < elementTypes.Length; i++)
|
|
{
|
|
Conversion conversion = classifyConversion(this, elementTypes[i], elementTypes2[i], isChecked, ref useSiteInfo, forCast);
|
|
if (!conversion.Exists)
|
|
{
|
|
instance.Free();
|
|
return Conversion.NoConversion;
|
|
}
|
|
instance.Add(conversion);
|
|
}
|
|
return new Conversion(kind, instance.ToImmutableAndFree());
|
|
}
|
|
|
|
private Conversion ClassifyExplicitNullableConversion(TypeSymbol source, TypeSymbol destination, bool isChecked, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo, bool forCast)
|
|
{
|
|
if (!source.IsNullableType() && !destination.IsNullableType())
|
|
{
|
|
return Conversion.NoConversion;
|
|
}
|
|
TypeSymbol typeSymbol = source.StrippedType();
|
|
TypeSymbol typeSymbol2 = destination.StrippedType();
|
|
if (HasIdentityConversionInternal(typeSymbol, typeSymbol2))
|
|
{
|
|
return Conversion.ExplicitNullableWithIdentityUnderlying;
|
|
}
|
|
if (HasImplicitNumericConversion(typeSymbol, typeSymbol2))
|
|
{
|
|
return Conversion.ExplicitNullableWithImplicitNumericUnderlying;
|
|
}
|
|
if (HasExplicitNumericConversion(typeSymbol, typeSymbol2))
|
|
{
|
|
return Conversion.ExplicitNullableWithExplicitNumericUnderlying;
|
|
}
|
|
Conversion item = ClassifyExplicitTupleConversion(typeSymbol, typeSymbol2, isChecked, ref useSiteInfo, forCast);
|
|
if (item.Exists)
|
|
{
|
|
return new Conversion(ConversionKind.ExplicitNullable, ImmutableArray.Create(item));
|
|
}
|
|
if (HasExplicitEnumerationConversion(typeSymbol, typeSymbol2))
|
|
{
|
|
return Conversion.ExplicitNullableWithExplicitEnumerationUnderlying;
|
|
}
|
|
if (HasPointerToIntegerConversion(typeSymbol, typeSymbol2))
|
|
{
|
|
return Conversion.ExplicitNullableWithPointerToIntegerUnderlying;
|
|
}
|
|
return Conversion.NoConversion;
|
|
}
|
|
|
|
private bool HasCovariantArrayConversion(TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
ArrayTypeSymbol arrayTypeSymbol = source as ArrayTypeSymbol;
|
|
ArrayTypeSymbol arrayTypeSymbol2 = destination as ArrayTypeSymbol;
|
|
if ((object)arrayTypeSymbol == null || (object)arrayTypeSymbol2 == null)
|
|
{
|
|
return false;
|
|
}
|
|
if (!arrayTypeSymbol.HasSameShapeAs(arrayTypeSymbol2))
|
|
{
|
|
return false;
|
|
}
|
|
return HasImplicitReferenceConversion(arrayTypeSymbol.ElementTypeWithAnnotations, arrayTypeSymbol2.ElementTypeWithAnnotations, ref useSiteInfo);
|
|
}
|
|
|
|
public bool HasIdentityOrImplicitReferenceConversion(TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
if (HasIdentityConversionInternal(source, destination))
|
|
{
|
|
return true;
|
|
}
|
|
return HasImplicitReferenceConversion(source, destination, ref useSiteInfo);
|
|
}
|
|
|
|
private static bool HasImplicitDynamicConversionFromExpression(TypeSymbol expressionType, TypeSymbol destination)
|
|
{
|
|
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_000a: Invalid comparison between Unknown and I4
|
|
if ((object)expressionType != null && (int)expressionType.Kind == 3)
|
|
{
|
|
return !destination.IsPointerOrFunctionPointer();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private static bool HasExplicitDynamicConversion(TypeSymbol source, TypeSymbol destination)
|
|
{
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0007: Invalid comparison between Unknown and I4
|
|
if ((int)source.Kind == 3)
|
|
{
|
|
return !destination.IsPointerOrFunctionPointer();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private bool HasArrayConversionToInterface(ArrayTypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_001c: Invalid comparison between Unknown and I4
|
|
if (!source.IsSZArray)
|
|
{
|
|
return false;
|
|
}
|
|
if (!destination.IsInterfaceType())
|
|
{
|
|
return false;
|
|
}
|
|
if ((int)destination.SpecialType == 24)
|
|
{
|
|
return true;
|
|
}
|
|
NamedTypeSymbol namedTypeSymbol = (NamedTypeSymbol)destination;
|
|
if (namedTypeSymbol.AllTypeArgumentCount() != 1)
|
|
{
|
|
return false;
|
|
}
|
|
if (!namedTypeSymbol.IsPossibleArrayGenericInterface())
|
|
{
|
|
return false;
|
|
}
|
|
TypeWithAnnotations elementTypeWithAnnotations = source.ElementTypeWithAnnotations;
|
|
TypeWithAnnotations destination2 = namedTypeSymbol.TypeArgumentWithDefinitionUseSiteDiagnostics(0, ref useSiteInfo);
|
|
if (IncludeNullability && !HasTopLevelNullabilityImplicitConversion(elementTypeWithAnnotations, destination2))
|
|
{
|
|
return false;
|
|
}
|
|
return HasIdentityOrImplicitReferenceConversion(elementTypeWithAnnotations.Type, destination2.Type, ref useSiteInfo);
|
|
}
|
|
|
|
private bool HasImplicitReferenceConversion(TypeWithAnnotations source, TypeWithAnnotations destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
if (IncludeNullability)
|
|
{
|
|
if (!HasTopLevelNullabilityImplicitConversion(source, destination))
|
|
{
|
|
return false;
|
|
}
|
|
if (source.NullableAnnotation != destination.NullableAnnotation && HasIdentityConversionInternal(source.Type, destination.Type, includeNullability: true))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return HasImplicitReferenceConversion(source.Type, destination.Type, ref useSiteInfo);
|
|
}
|
|
|
|
internal bool HasImplicitReferenceConversion(TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_001b: Invalid comparison between Unknown and I4
|
|
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0024: Invalid comparison between Unknown and I4
|
|
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0053: Expected I4, but got Unknown
|
|
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0056: Invalid comparison between Unknown and I4
|
|
if (source.IsErrorType())
|
|
{
|
|
return false;
|
|
}
|
|
if (!source.IsReferenceType)
|
|
{
|
|
return false;
|
|
}
|
|
if ((int)destination.SpecialType == 1 || (int)destination.Kind == 3)
|
|
{
|
|
return true;
|
|
}
|
|
TypeKind typeKind = source.TypeKind;
|
|
switch (typeKind - 1)
|
|
{
|
|
default:
|
|
if ((int)typeKind != 11)
|
|
{
|
|
break;
|
|
}
|
|
return HasImplicitReferenceTypeParameterConversion((TypeParameterSymbol)source, destination, ref useSiteInfo);
|
|
case 1:
|
|
if (destination.IsClassType() && IsBaseClass(source, destination, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
return HasImplicitConversionToInterface(source, destination, ref useSiteInfo);
|
|
case 6:
|
|
return HasImplicitConversionToInterface(source, destination, ref useSiteInfo);
|
|
case 2:
|
|
return HasImplicitConversionFromDelegate(source, destination, ref useSiteInfo);
|
|
case 0:
|
|
return HasImplicitConversionFromArray(source, destination, ref useSiteInfo);
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private bool HasImplicitConversionToInterface(TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
if (!destination.IsInterfaceType())
|
|
{
|
|
return false;
|
|
}
|
|
if (source.IsClassType())
|
|
{
|
|
return HasAnyBaseInterfaceConversion(source, destination, ref useSiteInfo);
|
|
}
|
|
if (source.IsInterfaceType())
|
|
{
|
|
if (HasAnyBaseInterfaceConversion(source, destination, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
if (!HasIdentityConversionInternal(source, destination) && HasInterfaceVarianceConversion(source, destination, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private bool HasImplicitConversionFromArray(TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0021: Invalid comparison between Unknown and I4
|
|
if (!(source is ArrayTypeSymbol source2))
|
|
{
|
|
return false;
|
|
}
|
|
if (HasCovariantArrayConversion(source, destination, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
if ((int)destination.GetSpecialTypeSafe() == 23)
|
|
{
|
|
return true;
|
|
}
|
|
if (IsBaseInterface(destination, corLibrary.GetDeclaredSpecialType((SpecialType)23), ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
if (HasArrayConversionToInterface(source2, destination, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private bool HasImplicitConversionFromDelegate(TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0013: Invalid comparison between Unknown and I4
|
|
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0017: Invalid comparison between Unknown and I4
|
|
if (!source.IsDelegateType())
|
|
{
|
|
return false;
|
|
}
|
|
SpecialType specialTypeSafe = destination.GetSpecialTypeSafe();
|
|
if ((int)specialTypeSafe == 3 || (int)specialTypeSafe == 4 || IsBaseInterface(destination, corLibrary.GetDeclaredSpecialType((SpecialType)3), ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
if (HasDelegateVarianceConversion(source, destination, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private bool HasImplicitFunctionTypeConversion(FunctionTypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
if (destination is FunctionTypeSymbol destinationType)
|
|
{
|
|
return HasImplicitFunctionTypeToFunctionTypeConversion(source, destinationType, ref useSiteInfo);
|
|
}
|
|
if (IsValidFunctionTypeConversionTarget(destination, ref useSiteInfo))
|
|
{
|
|
return (object)source.GetInternalDelegateType() != null;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
internal bool IsValidFunctionTypeConversionTarget(TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0007: Invalid comparison between Unknown and I4
|
|
if ((int)destination.SpecialType == 3)
|
|
{
|
|
return true;
|
|
}
|
|
if (destination.IsNonGenericExpressionType())
|
|
{
|
|
return true;
|
|
}
|
|
NamedTypeSymbol declaredSpecialType = corLibrary.GetDeclaredSpecialType((SpecialType)3);
|
|
if (IsBaseClass(declaredSpecialType, destination, ref useSiteInfo) || IsBaseInterface(destination, declaredSpecialType, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private bool HasImplicitFunctionTypeToFunctionTypeConversion(FunctionTypeSymbol sourceType, FunctionTypeSymbol destinationType, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
NamedTypeSymbol internalDelegateType = sourceType.GetInternalDelegateType();
|
|
if ((object)internalDelegateType == null)
|
|
{
|
|
return false;
|
|
}
|
|
NamedTypeSymbol internalDelegateType2 = destinationType.GetInternalDelegateType();
|
|
if ((object)internalDelegateType2 == null)
|
|
{
|
|
return false;
|
|
}
|
|
return HasDelegateVarianceConversion(internalDelegateType, internalDelegateType2, ref useSiteInfo);
|
|
}
|
|
|
|
public bool HasImplicitTypeParameterConversion(TypeParameterSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0022: Invalid comparison between Unknown and I4
|
|
if (HasImplicitReferenceTypeParameterConversion(source, destination, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
if (HasImplicitBoxingTypeParameterConversion(source, destination, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
if ((int)destination.TypeKind == 11 && source.DependsOn((TypeParameterSymbol)destination))
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private bool HasImplicitReferenceTypeParameterConversion(TypeParameterSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_002c: Invalid comparison between Unknown and I4
|
|
if (source.IsValueType)
|
|
{
|
|
return false;
|
|
}
|
|
if (HasImplicitEffectiveBaseConversion(source, destination, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
if (HasImplicitEffectiveInterfaceSetConversion(source, destination, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
if ((int)destination.TypeKind == 11 && source.DependsOn((TypeParameterSymbol)destination))
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private bool HasImplicitEffectiveBaseConversion(TypeParameterSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
NamedTypeSymbol namedTypeSymbol = source.EffectiveBaseClass(ref useSiteInfo);
|
|
if (HasIdentityConversionInternal(namedTypeSymbol, destination))
|
|
{
|
|
return true;
|
|
}
|
|
if (IsBaseClass(namedTypeSymbol, destination, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
if (HasAnyBaseInterfaceConversion(namedTypeSymbol, destination, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private bool HasImplicitEffectiveInterfaceSetConversion(TypeParameterSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
if (!destination.IsInterfaceType())
|
|
{
|
|
return false;
|
|
}
|
|
ImmutableArray<NamedTypeSymbol>.Enumerator enumerator = source.AllEffectiveInterfacesWithDefinitionUseSiteDiagnostics(ref useSiteInfo).GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
NamedTypeSymbol current = enumerator.Current;
|
|
if (HasInterfaceVarianceConversion(current, destination, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private bool HasAnyBaseInterfaceConversion(TypeSymbol derivedType, TypeSymbol baseType, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
if (!baseType.IsInterfaceType())
|
|
{
|
|
return false;
|
|
}
|
|
if (!(derivedType is NamedTypeSymbol namedTypeSymbol))
|
|
{
|
|
return false;
|
|
}
|
|
ImmutableArray<NamedTypeSymbol>.Enumerator enumerator = namedTypeSymbol.AllInterfacesWithDefinitionUseSiteDiagnostics(ref useSiteInfo).GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
NamedTypeSymbol current = enumerator.Current;
|
|
if (HasInterfaceVarianceConversion(current, baseType, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private bool HasInterfaceVarianceConversion(TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
NamedTypeSymbol namedTypeSymbol = source as NamedTypeSymbol;
|
|
NamedTypeSymbol namedTypeSymbol2 = destination as NamedTypeSymbol;
|
|
if ((object)namedTypeSymbol == null || (object)namedTypeSymbol2 == null)
|
|
{
|
|
return false;
|
|
}
|
|
if (!namedTypeSymbol.IsInterfaceType() || !namedTypeSymbol2.IsInterfaceType())
|
|
{
|
|
return false;
|
|
}
|
|
return HasVariantConversion(namedTypeSymbol, namedTypeSymbol2, ref useSiteInfo);
|
|
}
|
|
|
|
private bool HasDelegateVarianceConversion(TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
NamedTypeSymbol namedTypeSymbol = source as NamedTypeSymbol;
|
|
NamedTypeSymbol namedTypeSymbol2 = destination as NamedTypeSymbol;
|
|
if ((object)namedTypeSymbol == null || (object)namedTypeSymbol2 == null)
|
|
{
|
|
return false;
|
|
}
|
|
if (!namedTypeSymbol.IsDelegateType() || !namedTypeSymbol2.IsDelegateType())
|
|
{
|
|
return false;
|
|
}
|
|
return HasVariantConversion(namedTypeSymbol, namedTypeSymbol2, ref useSiteInfo);
|
|
}
|
|
|
|
private bool HasVariantConversion(NamedTypeSymbol source, NamedTypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
|
|
if (currentRecursionDepth >= 50)
|
|
{
|
|
return false;
|
|
}
|
|
ThreeState val = HasVariantConversionQuick(source, destination);
|
|
if (ThreeStateHelpers.HasValue(val))
|
|
{
|
|
return ThreeStateHelpers.Value(val);
|
|
}
|
|
return CreateInstance(currentRecursionDepth + 1).HasVariantConversionNoCycleCheck(source, destination, ref useSiteInfo);
|
|
}
|
|
|
|
private ThreeState HasVariantConversionQuick(NamedTypeSymbol source, NamedTypeSymbol destination)
|
|
{
|
|
if (!HasIdentityConversionInternal(source, destination))
|
|
{
|
|
if (TypeSymbol.Equals(source.OriginalDefinition, destination.OriginalDefinition, (TypeCompareKind)0))
|
|
{
|
|
return (ThreeState)0;
|
|
}
|
|
return (ThreeState)1;
|
|
}
|
|
return (ThreeState)2;
|
|
}
|
|
|
|
private bool HasVariantConversionNoCycleCheck(NamedTypeSymbol source, NamedTypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00a0: Expected I4, but got Unknown
|
|
//IL_0102: Unknown result type (might be due to invalid IL or missing references)
|
|
ArrayBuilder<TypeWithAnnotations> instance = ArrayBuilder<TypeWithAnnotations>.GetInstance();
|
|
ArrayBuilder<TypeWithAnnotations> instance2 = ArrayBuilder<TypeWithAnnotations>.GetInstance();
|
|
ArrayBuilder<TypeWithAnnotations> instance3 = ArrayBuilder<TypeWithAnnotations>.GetInstance();
|
|
try
|
|
{
|
|
source.OriginalDefinition.GetAllTypeArguments(instance, ref useSiteInfo);
|
|
source.GetAllTypeArguments(instance2, ref useSiteInfo);
|
|
destination.GetAllTypeArguments(instance3, ref useSiteInfo);
|
|
for (int i = 0; i < instance.Count; i++)
|
|
{
|
|
TypeWithAnnotations typeWithAnnotations = instance2[i];
|
|
TypeWithAnnotations typeWithAnnotations2 = instance3[i];
|
|
if (HasIdentityConversionInternal(typeWithAnnotations.Type, typeWithAnnotations2.Type) && HasTopLevelNullabilityIdentityConversion(typeWithAnnotations, typeWithAnnotations2))
|
|
{
|
|
continue;
|
|
}
|
|
TypeParameterSymbol typeParameterSymbol = (TypeParameterSymbol)instance[i].Type;
|
|
VarianceKind variance = typeParameterSymbol.Variance;
|
|
switch ((int)variance)
|
|
{
|
|
case 0:
|
|
if (isTypeIEquatable(destination.OriginalDefinition) && TypeSymbol.Equals(typeWithAnnotations2.Type, typeWithAnnotations.Type, (TypeCompareKind)24) && HasAnyNullabilityImplicitConversion(typeWithAnnotations2, typeWithAnnotations))
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
case 1:
|
|
if (!HasImplicitReferenceConversion(typeWithAnnotations, typeWithAnnotations2, ref useSiteInfo))
|
|
{
|
|
return false;
|
|
}
|
|
break;
|
|
case 2:
|
|
if (!HasImplicitReferenceConversion(typeWithAnnotations2, typeWithAnnotations, ref useSiteInfo))
|
|
{
|
|
return false;
|
|
}
|
|
break;
|
|
default:
|
|
throw ExceptionUtilities.UnexpectedValue((object)typeParameterSymbol.Variance);
|
|
}
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
instance.Free();
|
|
instance2.Free();
|
|
instance3.Free();
|
|
}
|
|
return true;
|
|
static bool isTypeIEquatable(NamedTypeSymbol type)
|
|
{
|
|
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_005d: Invalid comparison between Unknown and I4
|
|
if ((object)type != null && type.IsInterface && type.Name == "IEquatable")
|
|
{
|
|
NamespaceSymbol containingNamespace = type.ContainingNamespace;
|
|
if ((object)containingNamespace != null && containingNamespace.Name == "System")
|
|
{
|
|
NamespaceSymbol containingNamespace2 = containingNamespace.ContainingNamespace;
|
|
if ((object)containingNamespace2 != null && containingNamespace2.IsGlobalNamespace)
|
|
{
|
|
Symbol containingSymbol = type.ContainingSymbol;
|
|
if ((object)containingSymbol != null && (int)containingSymbol.Kind == 12)
|
|
{
|
|
return type.TypeParameters.Length == 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private bool HasImplicitBoxingTypeParameterConversion(TypeParameterSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_002c: Invalid comparison between Unknown and I4
|
|
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0045: Invalid comparison between Unknown and I4
|
|
if (source.IsReferenceType)
|
|
{
|
|
return false;
|
|
}
|
|
if (HasImplicitEffectiveBaseConversion(source, destination, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
if (HasImplicitEffectiveInterfaceSetConversion(source, destination, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
if ((int)destination.TypeKind == 11 && source.DependsOn((TypeParameterSymbol)destination))
|
|
{
|
|
return true;
|
|
}
|
|
if ((int)destination.Kind == 3)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public bool HasBoxingConversion(TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0008: Invalid comparison between Unknown and I4
|
|
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0057: Invalid comparison between Unknown and I4
|
|
if ((int)source.TypeKind == 11 && HasImplicitBoxingTypeParameterConversion((TypeParameterSymbol)source, destination, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
if (!source.IsValueType || !destination.IsReferenceType)
|
|
{
|
|
return false;
|
|
}
|
|
if (source.IsNullableType())
|
|
{
|
|
return HasBoxingConversion(source.GetNullableUnderlyingType(), destination, ref useSiteInfo);
|
|
}
|
|
if (source.IsRestrictedType())
|
|
{
|
|
return false;
|
|
}
|
|
if ((int)destination.Kind == 3)
|
|
{
|
|
return !source.IsPointerOrFunctionPointer();
|
|
}
|
|
if (IsBaseClass(source, destination, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
if (HasAnyBaseInterfaceConversion(source, destination, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
internal static bool HasImplicitPointerToVoidConversion(TypeSymbol source, TypeSymbol destination)
|
|
{
|
|
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0023: Invalid comparison between Unknown and I4
|
|
if (source.IsPointerOrFunctionPointer())
|
|
{
|
|
if (destination is PointerTypeSymbol pointerTypeSymbol)
|
|
{
|
|
TypeSymbol pointedAtType = pointerTypeSymbol.PointedAtType;
|
|
if ((object)pointedAtType != null)
|
|
{
|
|
return (int)pointedAtType.SpecialType == 6;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
internal bool HasImplicitPointerConversion(TypeSymbol? source, TypeSymbol? destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0050: Invalid comparison between Unknown and I4
|
|
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
|
|
if (source is FunctionPointerTypeSymbol functionPointerTypeSymbol)
|
|
{
|
|
FunctionPointerMethodSymbol signature = functionPointerTypeSymbol.Signature;
|
|
if ((object)signature != null && destination is FunctionPointerTypeSymbol functionPointerTypeSymbol2)
|
|
{
|
|
FunctionPointerMethodSymbol signature2 = functionPointerTypeSymbol2.Signature;
|
|
if ((object)signature2 != null)
|
|
{
|
|
if (signature.ParameterCount != signature2.ParameterCount || signature.CallingConvention != signature2.CallingConvention)
|
|
{
|
|
return false;
|
|
}
|
|
if ((int)signature.CallingConvention == 9 && !ImmutableHashSetExtensions.SetEqualsWithoutIntermediateHashSet<CustomModifier>(signature.GetCallingConventionModifiers(), signature2.GetCallingConventionModifiers()))
|
|
{
|
|
return false;
|
|
}
|
|
for (int i = 0; i < signature.ParameterCount; i++)
|
|
{
|
|
ParameterSymbol parameterSymbol = signature.Parameters[i];
|
|
ParameterSymbol parameterSymbol2 = signature2.Parameters[i];
|
|
if (parameterSymbol.RefKind != parameterSymbol2.RefKind)
|
|
{
|
|
return false;
|
|
}
|
|
if (!hasConversion(parameterSymbol.RefKind, signature2.Parameters[i].TypeWithAnnotations, signature.Parameters[i].TypeWithAnnotations, ref useSiteInfo))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
if (signature.RefKind == signature2.RefKind)
|
|
{
|
|
return hasConversion(signature.RefKind, signature.ReturnTypeWithAnnotations, signature2.ReturnTypeWithAnnotations, ref useSiteInfo);
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
bool hasConversion(RefKind refKind, TypeWithAnnotations sourceType, TypeWithAnnotations destinationType, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo2)
|
|
{
|
|
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0002: Invalid comparison between Unknown and I4
|
|
if ((int)refKind == 0)
|
|
{
|
|
if (!IncludeNullability || HasTopLevelNullabilityImplicitConversion(sourceType, destinationType))
|
|
{
|
|
if (!HasIdentityOrImplicitReferenceConversion(sourceType.Type, destinationType.Type, ref useSiteInfo2) && !HasImplicitPointerToVoidConversion(sourceType.Type, destinationType.Type))
|
|
{
|
|
return HasImplicitPointerConversion(sourceType.Type, destinationType.Type, ref useSiteInfo2);
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
if (!IncludeNullability || HasTopLevelNullabilityIdentityConversion(sourceType, destinationType))
|
|
{
|
|
return HasIdentityConversion(sourceType.Type, destinationType.Type);
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private bool HasIdentityOrReferenceConversion(TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
if (HasIdentityConversionInternal(source, destination))
|
|
{
|
|
return true;
|
|
}
|
|
if (HasImplicitReferenceConversion(source, destination, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
if (HasExplicitReferenceConversion(source, destination, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private bool HasExplicitReferenceConversion(TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0007: Invalid comparison between Unknown and I4
|
|
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_001a: Invalid comparison between Unknown and I4
|
|
if ((int)source.SpecialType == 1)
|
|
{
|
|
if (destination.IsReferenceType)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
else if ((int)source.Kind == 3 && destination.IsReferenceType)
|
|
{
|
|
return true;
|
|
}
|
|
if (destination.IsClassType() && IsBaseClass(destination, source, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
if (source.IsClassType() && destination.IsInterfaceType() && !source.IsSealed && !HasAnyBaseInterfaceConversion(source, destination, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
if (source.IsInterfaceType() && destination.IsClassType() && (!destination.IsSealed || HasAnyBaseInterfaceConversion(destination, source, ref useSiteInfo)))
|
|
{
|
|
return true;
|
|
}
|
|
if (source.IsInterfaceType() && destination.IsInterfaceType() && !HasImplicitConversionToInterface(source, destination, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
if (HasExplicitArrayConversion(source, destination, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
if (HasExplicitDelegateConversion(source, destination, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
if (HasExplicitReferenceTypeParameterConversion(source, destination, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private bool HasExplicitReferenceTypeParameterConversion(TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
TypeParameterSymbol typeParameterSymbol = source as TypeParameterSymbol;
|
|
TypeParameterSymbol typeParameterSymbol2 = destination as TypeParameterSymbol;
|
|
if ((object)typeParameterSymbol2 != null && typeParameterSymbol2.IsReferenceType)
|
|
{
|
|
NamedTypeSymbol namedTypeSymbol = typeParameterSymbol2.EffectiveBaseClass(ref useSiteInfo);
|
|
while ((object)namedTypeSymbol != null)
|
|
{
|
|
if (HasIdentityConversionInternal(namedTypeSymbol, source))
|
|
{
|
|
return true;
|
|
}
|
|
namedTypeSymbol = namedTypeSymbol.BaseTypeWithDefinitionUseSiteDiagnostics(ref useSiteInfo);
|
|
}
|
|
}
|
|
if ((object)typeParameterSymbol2 != null && source.IsInterfaceType() && typeParameterSymbol2.IsReferenceType)
|
|
{
|
|
return true;
|
|
}
|
|
if ((object)typeParameterSymbol != null && typeParameterSymbol.IsReferenceType && destination.IsInterfaceType() && !HasImplicitReferenceTypeParameterConversion(typeParameterSymbol, destination, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
if ((object)typeParameterSymbol != null && (object)typeParameterSymbol2 != null && typeParameterSymbol2.IsReferenceType && typeParameterSymbol2.DependsOn(typeParameterSymbol))
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private bool HasUnboxingTypeParameterConversion(TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
TypeParameterSymbol typeParameterSymbol = source as TypeParameterSymbol;
|
|
TypeParameterSymbol typeParameterSymbol2 = destination as TypeParameterSymbol;
|
|
if ((object)typeParameterSymbol2 != null && !typeParameterSymbol2.IsReferenceType)
|
|
{
|
|
NamedTypeSymbol namedTypeSymbol = typeParameterSymbol2.EffectiveBaseClass(ref useSiteInfo);
|
|
while ((object)namedTypeSymbol != null)
|
|
{
|
|
if (TypeSymbol.Equals(namedTypeSymbol, source, (TypeCompareKind)0))
|
|
{
|
|
return true;
|
|
}
|
|
namedTypeSymbol = namedTypeSymbol.BaseTypeWithDefinitionUseSiteDiagnostics(ref useSiteInfo);
|
|
}
|
|
}
|
|
if (source.IsInterfaceType() && (object)typeParameterSymbol2 != null && !typeParameterSymbol2.IsReferenceType)
|
|
{
|
|
return true;
|
|
}
|
|
if ((object)typeParameterSymbol != null && !typeParameterSymbol.IsReferenceType && destination.IsInterfaceType() && !HasImplicitReferenceTypeParameterConversion(typeParameterSymbol, destination, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
if ((object)typeParameterSymbol != null && (object)typeParameterSymbol2 != null && !typeParameterSymbol2.IsReferenceType && typeParameterSymbol2.DependsOn(typeParameterSymbol))
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private bool HasExplicitDelegateConversion(TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_000f: Invalid comparison between Unknown and I4
|
|
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0018: Invalid comparison between Unknown and I4
|
|
//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00f6: Expected I4, but got Unknown
|
|
if (destination.IsDelegateType())
|
|
{
|
|
if ((int)source.SpecialType == 4 || (int)source.SpecialType == 3)
|
|
{
|
|
return true;
|
|
}
|
|
if (HasImplicitConversionToInterface(corLibrary.GetDeclaredSpecialType((SpecialType)4), source, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
if (!source.IsDelegateType() || !destination.IsDelegateType())
|
|
{
|
|
return false;
|
|
}
|
|
if (!TypeSymbol.Equals(source.OriginalDefinition, destination.OriginalDefinition, (TypeCompareKind)0))
|
|
{
|
|
return false;
|
|
}
|
|
NamedTypeSymbol namedTypeSymbol = (NamedTypeSymbol)source;
|
|
NamedTypeSymbol namedTypeSymbol2 = (NamedTypeSymbol)destination;
|
|
NamedTypeSymbol originalDefinition = namedTypeSymbol.OriginalDefinition;
|
|
if (HasIdentityConversionInternal(source, destination))
|
|
{
|
|
return false;
|
|
}
|
|
if (HasDelegateVarianceConversion(source, destination, ref useSiteInfo))
|
|
{
|
|
return false;
|
|
}
|
|
ImmutableArray<TypeWithAnnotations> immutableArray = namedTypeSymbol.TypeArgumentsWithDefinitionUseSiteDiagnostics(ref useSiteInfo);
|
|
ImmutableArray<TypeWithAnnotations> immutableArray2 = namedTypeSymbol2.TypeArgumentsWithDefinitionUseSiteDiagnostics(ref useSiteInfo);
|
|
for (int i = 0; i < immutableArray.Length; i++)
|
|
{
|
|
TypeSymbol type = immutableArray[i].Type;
|
|
TypeSymbol type2 = immutableArray2[i].Type;
|
|
VarianceKind variance = originalDefinition.TypeParameters[i].Variance;
|
|
switch ((int)variance)
|
|
{
|
|
case 0:
|
|
if (!HasIdentityConversionInternal(type, type2))
|
|
{
|
|
return false;
|
|
}
|
|
break;
|
|
case 1:
|
|
if (!HasIdentityOrReferenceConversion(type, type2, ref useSiteInfo))
|
|
{
|
|
return false;
|
|
}
|
|
break;
|
|
case 2:
|
|
{
|
|
bool num = HasIdentityConversionInternal(type, type2);
|
|
bool flag = type.IsReferenceType && type2.IsReferenceType;
|
|
if (!(num || flag))
|
|
{
|
|
return false;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private bool HasExplicitArrayConversion(TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_003e: Invalid comparison between Unknown and I4
|
|
//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00d5: Invalid comparison between Unknown and I4
|
|
//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00db: Invalid comparison between Unknown and I4
|
|
//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00e1: Invalid comparison between Unknown and I4
|
|
//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00e7: Invalid comparison between Unknown and I4
|
|
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00ed: Invalid comparison between Unknown and I4
|
|
ArrayTypeSymbol arrayTypeSymbol = source as ArrayTypeSymbol;
|
|
ArrayTypeSymbol arrayTypeSymbol2 = destination as ArrayTypeSymbol;
|
|
if ((object)arrayTypeSymbol != null && (object)arrayTypeSymbol2 != null)
|
|
{
|
|
if (arrayTypeSymbol.HasSameShapeAs(arrayTypeSymbol2))
|
|
{
|
|
return HasExplicitReferenceConversion(arrayTypeSymbol.ElementType, arrayTypeSymbol2.ElementType, ref useSiteInfo);
|
|
}
|
|
return false;
|
|
}
|
|
if ((object)arrayTypeSymbol2 != null)
|
|
{
|
|
if ((int)source.SpecialType == 23)
|
|
{
|
|
return true;
|
|
}
|
|
ImmutableArray<NamedTypeSymbol>.Enumerator enumerator = corLibrary.GetDeclaredSpecialType((SpecialType)23).AllInterfacesWithDefinitionUseSiteDiagnostics(ref useSiteInfo).GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
NamedTypeSymbol current = enumerator.Current;
|
|
if (HasIdentityConversionInternal(current, source))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
if ((object)arrayTypeSymbol != null && arrayTypeSymbol.IsSZArray && destination.IsPossibleArrayGenericInterface() && HasExplicitReferenceConversion(arrayTypeSymbol.ElementType, ((NamedTypeSymbol)destination).TypeArgumentWithDefinitionUseSiteDiagnostics(0, ref useSiteInfo).Type, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
if ((object)arrayTypeSymbol2 != null && arrayTypeSymbol2.IsSZArray)
|
|
{
|
|
SpecialType specialType = source.OriginalDefinition.SpecialType;
|
|
if ((int)specialType == 26 || (int)specialType == 27 || (int)specialType == 25 || (int)specialType == 30 || (int)specialType == 31)
|
|
{
|
|
TypeSymbol type = ((NamedTypeSymbol)source).TypeArgumentWithDefinitionUseSiteDiagnostics(0, ref useSiteInfo).Type;
|
|
TypeSymbol elementType = arrayTypeSymbol2.ElementType;
|
|
if (HasIdentityConversionInternal(type, elementType))
|
|
{
|
|
return true;
|
|
}
|
|
if (HasImplicitReferenceConversion(type, elementType, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
if (HasExplicitReferenceConversion(type, elementType, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private bool HasUnboxingConversion(TypeSymbol source, TypeSymbol destination, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_001e: Invalid comparison between Unknown and I4
|
|
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0022: Invalid comparison between Unknown and I4
|
|
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0062: Invalid comparison between Unknown and I4
|
|
if (destination.IsPointerOrFunctionPointer())
|
|
{
|
|
return false;
|
|
}
|
|
if (destination.IsRestrictedType())
|
|
{
|
|
return false;
|
|
}
|
|
SpecialType specialType = source.SpecialType;
|
|
if (((int)specialType == 1 || (int)specialType == 5) && destination.IsValueType && !destination.IsNullableType())
|
|
{
|
|
return true;
|
|
}
|
|
if (source.IsInterfaceType() && destination.IsValueType && !destination.IsNullableType() && HasBoxingConversion(destination, source, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
if ((int)source.SpecialType == 2 && destination.IsEnumType())
|
|
{
|
|
return true;
|
|
}
|
|
if (source.IsReferenceType && destination.IsNullableType() && HasUnboxingConversion(source, destination.GetNullableUnderlyingType(), ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
if (HasUnboxingTypeParameterConversion(source, destination, ref useSiteInfo))
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private static bool HasPointerToPointerConversion(TypeSymbol source, TypeSymbol destination)
|
|
{
|
|
if (source.IsPointerOrFunctionPointer())
|
|
{
|
|
return destination.IsPointerOrFunctionPointer();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private static bool HasPointerToIntegerConversion(TypeSymbol source, TypeSymbol destination)
|
|
{
|
|
if (!source.IsPointerOrFunctionPointer())
|
|
{
|
|
return false;
|
|
}
|
|
return IsIntegerTypeSupportingPointerConversions(destination.StrippedType());
|
|
}
|
|
|
|
private static bool HasIntegerToPointerConversion(TypeSymbol source, TypeSymbol destination)
|
|
{
|
|
if (!destination.IsPointerOrFunctionPointer())
|
|
{
|
|
return false;
|
|
}
|
|
return IsIntegerTypeSupportingPointerConversions(source);
|
|
}
|
|
|
|
private static bool IsIntegerTypeSupportingPointerConversions(TypeSymbol type)
|
|
{
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_000c: Invalid comparison between Unknown and I4
|
|
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0013: Invalid comparison between Unknown and I4
|
|
SpecialType specialType = type.SpecialType;
|
|
if (specialType - 9 > 7)
|
|
{
|
|
if (specialType - 21 <= 1)
|
|
{
|
|
return type.IsNativeIntegerType;
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public static void AddTypesParticipatingInUserDefinedConversion(ArrayBuilder<(NamedTypeSymbol ParticipatingType, TypeParameterSymbol? ConstrainedToTypeOpt)> result, TypeSymbol type, bool includeBaseTypes, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
if ((object)type == null)
|
|
{
|
|
return;
|
|
}
|
|
type = type.StrippedType();
|
|
bool flag = result.Count > 0;
|
|
if (type is TypeParameterSymbol typeParameterSymbol)
|
|
{
|
|
NamedTypeSymbol type2 = typeParameterSymbol.EffectiveBaseClass(ref useSiteInfo);
|
|
addFromClassOrStruct(result, flag, type2, includeBaseTypes, ref useSiteInfo);
|
|
ImmutableArray<NamedTypeSymbol>.Enumerator enumerator = (includeBaseTypes ? typeParameterSymbol.AllEffectiveInterfacesWithDefinitionUseSiteDiagnostics(ref useSiteInfo) : typeParameterSymbol.EffectiveInterfacesWithDefinitionUseSiteDiagnostics(ref useSiteInfo)).GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
NamedTypeSymbol current = enumerator.Current;
|
|
if (!flag || !HasIdentityConversionToAny(current, result))
|
|
{
|
|
result.Add((current, typeParameterSymbol));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
addFromClassOrStruct(result, flag, type, includeBaseTypes, ref useSiteInfo);
|
|
}
|
|
static void addFromClassOrStruct(ArrayBuilder<(NamedTypeSymbol ParticipatingType, TypeParameterSymbol? ConstrainedToTypeOpt)> val, bool excludeExisting, TypeSymbol typeSymbol, bool flag2, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo2)
|
|
{
|
|
if (typeSymbol.IsClassType() || typeSymbol.IsStructType())
|
|
{
|
|
NamedTypeSymbol namedTypeSymbol = (NamedTypeSymbol)typeSymbol;
|
|
if (!excludeExisting || !HasIdentityConversionToAny(namedTypeSymbol, val))
|
|
{
|
|
val.Add((namedTypeSymbol, (TypeParameterSymbol)null));
|
|
}
|
|
}
|
|
if (flag2)
|
|
{
|
|
NamedTypeSymbol namedTypeSymbol2 = typeSymbol.BaseTypeWithDefinitionUseSiteDiagnostics(ref useSiteInfo2);
|
|
while ((object)namedTypeSymbol2 != null)
|
|
{
|
|
if (!excludeExisting || !HasIdentityConversionToAny(namedTypeSymbol2, val))
|
|
{
|
|
val.Add((namedTypeSymbol2, (TypeParameterSymbol)null));
|
|
}
|
|
namedTypeSymbol2 = namedTypeSymbol2.BaseTypeWithDefinitionUseSiteDiagnostics(ref useSiteInfo2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private UserDefinedConversionResult AnalyzeExplicitUserDefinedConversions(BoundExpression sourceExpression, TypeSymbol source, TypeSymbol target, bool isChecked, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
ArrayBuilder<(NamedTypeSymbol, TypeParameterSymbol)> instance = ArrayBuilder<(NamedTypeSymbol, TypeParameterSymbol)>.GetInstance();
|
|
ComputeUserDefinedExplicitConversionTypeSet(source, target, instance, ref useSiteInfo);
|
|
ArrayBuilder<UserDefinedConversionAnalysis> instance2 = ArrayBuilder<UserDefinedConversionAnalysis>.GetInstance();
|
|
ComputeApplicableUserDefinedExplicitConversionSet(sourceExpression, source, target, isChecked, instance, instance2, ref useSiteInfo);
|
|
instance.Free();
|
|
ImmutableArray<UserDefinedConversionAnalysis> immutableArray = instance2.ToImmutableAndFree();
|
|
if (immutableArray.Length == 0)
|
|
{
|
|
return UserDefinedConversionResult.NoApplicableOperators(immutableArray);
|
|
}
|
|
TypeSymbol typeSymbol = MostSpecificSourceTypeForExplicitUserDefinedConversion(immutableArray, sourceExpression, source, ref useSiteInfo);
|
|
if ((object)typeSymbol == null)
|
|
{
|
|
return UserDefinedConversionResult.NoBestSourceType(immutableArray);
|
|
}
|
|
TypeSymbol typeSymbol2 = MostSpecificTargetTypeForExplicitUserDefinedConversion(immutableArray, target, ref useSiteInfo);
|
|
if ((object)typeSymbol2 == null)
|
|
{
|
|
return UserDefinedConversionResult.NoBestTargetType(immutableArray);
|
|
}
|
|
int? num = MostSpecificConversionOperator(typeSymbol, typeSymbol2, immutableArray);
|
|
if (!num.HasValue)
|
|
{
|
|
return UserDefinedConversionResult.Ambiguous(immutableArray);
|
|
}
|
|
return UserDefinedConversionResult.Valid(immutableArray, num.Value);
|
|
}
|
|
|
|
private static void ComputeUserDefinedExplicitConversionTypeSet(TypeSymbol source, TypeSymbol target, ArrayBuilder<(NamedTypeSymbol ParticipatingType, TypeParameterSymbol ConstrainedToTypeOpt)> d, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
AddTypesParticipatingInUserDefinedConversion(d, source, includeBaseTypes: true, ref useSiteInfo);
|
|
AddTypesParticipatingInUserDefinedConversion(d, target, includeBaseTypes: true, ref useSiteInfo);
|
|
}
|
|
|
|
private void ComputeApplicableUserDefinedExplicitConversionSet(BoundExpression sourceExpression, TypeSymbol source, TypeSymbol target, bool isChecked, ArrayBuilder<(NamedTypeSymbol ParticipatingType, TypeParameterSymbol ConstrainedToTypeOpt)> d, ArrayBuilder<UserDefinedConversionAnalysis> u, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
|
|
bool flag = false;
|
|
Enumerator<(NamedTypeSymbol, TypeParameterSymbol)> enumerator = d.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
NamedTypeSymbol item = enumerator.Current.Item1;
|
|
if (item.IsInterface)
|
|
{
|
|
flag = true;
|
|
}
|
|
else
|
|
{
|
|
addCandidatesFromType(null, item, sourceExpression, source, target, isChecked, u, ref useSiteInfo);
|
|
}
|
|
}
|
|
if (!(u.Count == 0 && flag))
|
|
{
|
|
return;
|
|
}
|
|
enumerator = d.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
var (namedTypeSymbol, constrainedToTypeOpt) = enumerator.Current;
|
|
if (namedTypeSymbol.IsInterface)
|
|
{
|
|
addCandidatesFromType(constrainedToTypeOpt, namedTypeSymbol, sourceExpression, source, target, isChecked, u, ref useSiteInfo);
|
|
}
|
|
}
|
|
void addCandidatesFromType(TypeParameterSymbol constrainedToTypeOpt2, NamedTypeSymbol declaringType, BoundExpression sourceExpression2, TypeSymbol source2, TypeSymbol target2, bool isChecked2, ArrayBuilder<UserDefinedConversionAnalysis> u2, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo2)
|
|
{
|
|
AddUserDefinedConversionsToExplicitCandidateSet(sourceExpression2, source2, target2, u2, constrainedToTypeOpt2, declaringType, isExplicit: true, isChecked2, ref useSiteInfo2);
|
|
AddUserDefinedConversionsToExplicitCandidateSet(sourceExpression2, source2, target2, u2, constrainedToTypeOpt2, declaringType, isExplicit: false, isChecked2, ref useSiteInfo2);
|
|
}
|
|
}
|
|
|
|
private void AddUserDefinedConversionsToExplicitCandidateSet(BoundExpression sourceExpression, TypeSymbol source, TypeSymbol target, ArrayBuilder<UserDefinedConversionAnalysis> u, TypeParameterSymbol constrainedToTypeOpt, NamedTypeSymbol declaringType, bool isExplicit, bool isChecked, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0101: Invalid comparison between Unknown and I4
|
|
if (((object)source != null && source.IsInterfaceType()) || target.IsInterfaceType())
|
|
{
|
|
return;
|
|
}
|
|
ImmutableArray<MethodSymbol> operators = declaringType.GetOperators((!isExplicit) ? "op_Implicit" : (isChecked ? "op_CheckedExplicit" : "op_Explicit"));
|
|
ArrayBuilder<MethodSymbol> instance = ArrayBuilder<MethodSymbol>.GetInstance(operators.Length);
|
|
instance.AddRange(operators);
|
|
if (isExplicit && isChecked)
|
|
{
|
|
ImmutableArray<MethodSymbol> operators2 = declaringType.GetOperators("op_Explicit");
|
|
if (operators.IsEmpty)
|
|
{
|
|
instance.AddRange(operators2);
|
|
}
|
|
else
|
|
{
|
|
ImmutableArray<MethodSymbol>.Enumerator enumerator = operators2.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
MethodSymbol current = enumerator.Current;
|
|
bool flag = true;
|
|
ImmutableArray<MethodSymbol>.Enumerator enumerator2 = operators.GetEnumerator();
|
|
while (enumerator2.MoveNext())
|
|
{
|
|
if (SourceMemberContainerTypeSymbol.DoOperatorsPair(enumerator2.Current, current))
|
|
{
|
|
flag = false;
|
|
break;
|
|
}
|
|
}
|
|
if (flag)
|
|
{
|
|
instance.Add(current);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Enumerator<MethodSymbol> enumerator3 = instance.GetEnumerator();
|
|
while (enumerator3.MoveNext())
|
|
{
|
|
MethodSymbol current2 = enumerator3.Current;
|
|
if (current2.ReturnsVoid || current2.ParameterCount != 1 || (int)current2.ReturnType.TypeKind == 6)
|
|
{
|
|
continue;
|
|
}
|
|
TypeSymbol typeSymbol = current2.GetParameterType(0);
|
|
TypeSymbol typeSymbol2 = current2.ReturnType;
|
|
Conversion sourceConversion = EncompassingExplicitConversion(sourceExpression, source, typeSymbol, ref useSiteInfo);
|
|
Conversion targetConversion = EncompassingExplicitConversion(typeSymbol2, target, ref useSiteInfo);
|
|
if (!sourceConversion.Exists && (object)source != null && source.IsNullableType() && EncompassingExplicitConversion(source.GetNullableUnderlyingType(), typeSymbol, ref useSiteInfo).Exists)
|
|
{
|
|
sourceConversion = ClassifyBuiltInConversion(source, typeSymbol, isChecked, ref useSiteInfo);
|
|
}
|
|
if (!targetConversion.Exists && (object)target != null && target.IsNullableType() && EncompassingExplicitConversion(typeSymbol2, target.GetNullableUnderlyingType(), ref useSiteInfo).Exists)
|
|
{
|
|
targetConversion = ClassifyBuiltInConversion(typeSymbol2, target, isChecked, ref useSiteInfo);
|
|
}
|
|
if (!sourceConversion.Exists || !targetConversion.Exists)
|
|
{
|
|
continue;
|
|
}
|
|
if ((object)source != null && source.IsNullableType() && typeSymbol.IsValidNullableTypeArgument() && target.CanBeAssignedNull())
|
|
{
|
|
TypeSymbol typeSymbol3 = MakeNullableType(typeSymbol);
|
|
TypeSymbol typeSymbol4 = (typeSymbol2.IsValidNullableTypeArgument() ? MakeNullableType(typeSymbol2) : typeSymbol2);
|
|
Conversion sourceConversion2 = EncompassingExplicitConversion(sourceExpression, source, typeSymbol3, ref useSiteInfo);
|
|
Conversion targetConversion2 = EncompassingExplicitConversion(typeSymbol4, target, ref useSiteInfo);
|
|
u.Add(UserDefinedConversionAnalysis.Lifted(constrainedToTypeOpt, current2, sourceConversion2, targetConversion2, typeSymbol3, typeSymbol4));
|
|
continue;
|
|
}
|
|
if (target.IsNullableType() && typeSymbol2.IsValidNullableTypeArgument())
|
|
{
|
|
typeSymbol2 = MakeNullableType(typeSymbol2);
|
|
targetConversion = EncompassingExplicitConversion(typeSymbol2, target, ref useSiteInfo);
|
|
}
|
|
if ((object)source != null && source.IsNullableType() && typeSymbol.IsValidNullableTypeArgument())
|
|
{
|
|
typeSymbol = MakeNullableType(typeSymbol);
|
|
sourceConversion = EncompassingExplicitConversion(typeSymbol, source, ref useSiteInfo);
|
|
}
|
|
u.Add(UserDefinedConversionAnalysis.Normal(constrainedToTypeOpt, current2, sourceConversion, targetConversion, typeSymbol, typeSymbol2));
|
|
}
|
|
instance.Free();
|
|
}
|
|
|
|
private TypeSymbol MostSpecificSourceTypeForExplicitUserDefinedConversion(ImmutableArray<UserDefinedConversionAnalysis> u, BoundExpression sourceExpression, TypeSymbol source, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
|
|
if ((object)source != null)
|
|
{
|
|
if (ImmutableArrayExtensions.Any<UserDefinedConversionAnalysis, TypeSymbol>(u, (Func<UserDefinedConversionAnalysis, TypeSymbol, bool>)((UserDefinedConversionAnalysis conv, TypeSymbol right) => TypeSymbol.Equals(conv.FromType, right, (TypeCompareKind)0)), source))
|
|
{
|
|
return source;
|
|
}
|
|
CompoundUseSiteInfo<AssemblySymbol> inLambdaUseSiteInfo = useSiteInfo;
|
|
Func<UserDefinedConversionAnalysis, bool> func = (UserDefinedConversionAnalysis conv) => IsEncompassedBy(sourceExpression, source, conv.FromType, ref inLambdaUseSiteInfo);
|
|
if (u.Any(func))
|
|
{
|
|
TypeSymbol result = MostEncompassedType(u, func, (UserDefinedConversionAnalysis conv) => conv.FromType, ref inLambdaUseSiteInfo);
|
|
useSiteInfo = inLambdaUseSiteInfo;
|
|
return result;
|
|
}
|
|
useSiteInfo = inLambdaUseSiteInfo;
|
|
}
|
|
return MostEncompassingType(u, (UserDefinedConversionAnalysis conv) => conv.FromType, ref useSiteInfo);
|
|
}
|
|
|
|
private TypeSymbol MostSpecificTargetTypeForExplicitUserDefinedConversion(ImmutableArray<UserDefinedConversionAnalysis> u, TypeSymbol target, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
|
|
if (ImmutableArrayExtensions.Any<UserDefinedConversionAnalysis, TypeSymbol>(u, (Func<UserDefinedConversionAnalysis, TypeSymbol, bool>)((UserDefinedConversionAnalysis conv, TypeSymbol right) => TypeSymbol.Equals(conv.ToType, right, (TypeCompareKind)0)), target))
|
|
{
|
|
return target;
|
|
}
|
|
CompoundUseSiteInfo<AssemblySymbol> inLambdaUseSiteInfo = useSiteInfo;
|
|
Func<UserDefinedConversionAnalysis, bool> func = (UserDefinedConversionAnalysis conv) => IsEncompassedBy(conv.ToType, target, ref inLambdaUseSiteInfo);
|
|
if (u.Any(func))
|
|
{
|
|
TypeSymbol result = MostEncompassingType(u, func, (UserDefinedConversionAnalysis conv) => conv.ToType, ref inLambdaUseSiteInfo);
|
|
useSiteInfo = inLambdaUseSiteInfo;
|
|
return result;
|
|
}
|
|
useSiteInfo = inLambdaUseSiteInfo;
|
|
return MostEncompassedType(u, (UserDefinedConversionAnalysis conv) => conv.ToType, ref useSiteInfo);
|
|
}
|
|
|
|
private Conversion EncompassingExplicitConversion(BoundExpression expr, TypeSymbol a, TypeSymbol b, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
Conversion result = ClassifyStandardConversion(expr, a, b, ref useSiteInfo);
|
|
if (!result.IsEnumeration)
|
|
{
|
|
return result;
|
|
}
|
|
return Conversion.NoConversion;
|
|
}
|
|
|
|
private Conversion EncompassingExplicitConversion(TypeSymbol a, TypeSymbol b, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
return EncompassingExplicitConversion(null, a, b, ref useSiteInfo);
|
|
}
|
|
|
|
private UserDefinedConversionResult AnalyzeImplicitUserDefinedConversions(BoundExpression sourceExpression, TypeSymbol source, TypeSymbol target, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
ArrayBuilder<(NamedTypeSymbol, TypeParameterSymbol)> instance = ArrayBuilder<(NamedTypeSymbol, TypeParameterSymbol)>.GetInstance();
|
|
ComputeUserDefinedImplicitConversionTypeSet(source, target, instance, ref useSiteInfo);
|
|
ArrayBuilder<UserDefinedConversionAnalysis> instance2 = ArrayBuilder<UserDefinedConversionAnalysis>.GetInstance();
|
|
ComputeApplicableUserDefinedImplicitConversionSet(sourceExpression, source, target, instance, instance2, ref useSiteInfo);
|
|
instance.Free();
|
|
ImmutableArray<UserDefinedConversionAnalysis> immutableArray = instance2.ToImmutableAndFree();
|
|
if (immutableArray.Length == 0)
|
|
{
|
|
return UserDefinedConversionResult.NoApplicableOperators(immutableArray);
|
|
}
|
|
TypeSymbol typeSymbol = MostSpecificSourceTypeForImplicitUserDefinedConversion(immutableArray, source, ref useSiteInfo);
|
|
if ((object)typeSymbol == null)
|
|
{
|
|
return UserDefinedConversionResult.NoBestSourceType(immutableArray);
|
|
}
|
|
TypeSymbol typeSymbol2 = MostSpecificTargetTypeForImplicitUserDefinedConversion(immutableArray, target, ref useSiteInfo);
|
|
if ((object)typeSymbol2 == null)
|
|
{
|
|
return UserDefinedConversionResult.NoBestTargetType(immutableArray);
|
|
}
|
|
int? num = MostSpecificConversionOperator(typeSymbol, typeSymbol2, immutableArray);
|
|
if (!num.HasValue)
|
|
{
|
|
return UserDefinedConversionResult.Ambiguous(immutableArray);
|
|
}
|
|
return UserDefinedConversionResult.Valid(immutableArray, num.Value);
|
|
}
|
|
|
|
private static void ComputeUserDefinedImplicitConversionTypeSet(TypeSymbol s, TypeSymbol t, ArrayBuilder<(NamedTypeSymbol ParticipatingType, TypeParameterSymbol ConstrainedToTypeOpt)> d, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
AddTypesParticipatingInUserDefinedConversion(d, s, includeBaseTypes: true, ref useSiteInfo);
|
|
AddTypesParticipatingInUserDefinedConversion(d, t, includeBaseTypes: false, ref useSiteInfo);
|
|
}
|
|
|
|
private void ComputeApplicableUserDefinedImplicitConversionSet(BoundExpression sourceExpression, TypeSymbol source, TypeSymbol target, ArrayBuilder<(NamedTypeSymbol ParticipatingType, TypeParameterSymbol ConstrainedToTypeOpt)> d, ArrayBuilder<UserDefinedConversionAnalysis> u, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo, bool allowAnyTarget = false)
|
|
{
|
|
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
|
|
if (((object)source != null && source.IsInterfaceType()) || ((object)target != null && target.IsInterfaceType()))
|
|
{
|
|
return;
|
|
}
|
|
bool flag = false;
|
|
Enumerator<(NamedTypeSymbol, TypeParameterSymbol)> enumerator = d.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
NamedTypeSymbol item = enumerator.Current.Item1;
|
|
if (item.IsInterface)
|
|
{
|
|
flag = true;
|
|
}
|
|
else
|
|
{
|
|
addCandidatesFromType(null, item, sourceExpression, source, target, u, ref useSiteInfo, allowAnyTarget);
|
|
}
|
|
}
|
|
if (!(u.Count == 0 && flag))
|
|
{
|
|
return;
|
|
}
|
|
enumerator = d.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
var (namedTypeSymbol, constrainedToTypeOpt) = enumerator.Current;
|
|
if (namedTypeSymbol.IsInterface)
|
|
{
|
|
addCandidatesFromType(constrainedToTypeOpt, namedTypeSymbol, sourceExpression, source, target, u, ref useSiteInfo, allowAnyTarget);
|
|
}
|
|
}
|
|
void addCandidatesFromType(TypeParameterSymbol constrainedToTypeOpt2, NamedTypeSymbol declaringType, BoundExpression aExpr, TypeSymbol typeSymbol2, TypeSymbol typeSymbol3, ArrayBuilder<UserDefinedConversionAnalysis> val, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo2, bool flag2)
|
|
{
|
|
ImmutableArray<MethodSymbol>.Enumerator enumerator2 = declaringType.GetOperators("op_Implicit").GetEnumerator();
|
|
while (enumerator2.MoveNext())
|
|
{
|
|
MethodSymbol current = enumerator2.Current;
|
|
if (!current.ReturnsVoid && current.ParameterCount == 1)
|
|
{
|
|
TypeSymbol parameterType = current.GetParameterType(0);
|
|
TypeSymbol typeSymbol = current.ReturnType;
|
|
Conversion sourceConversion = EncompassingImplicitConversion(aExpr, typeSymbol2, parameterType, ref useSiteInfo2);
|
|
Conversion targetConversion = (flag2 ? Conversion.Identity : EncompassingImplicitConversion(typeSymbol, typeSymbol3, ref useSiteInfo2));
|
|
if (sourceConversion.Exists && targetConversion.Exists)
|
|
{
|
|
if ((object)typeSymbol3 != null && typeSymbol3.IsNullableType() && typeSymbol.IsValidNullableTypeArgument())
|
|
{
|
|
typeSymbol = MakeNullableType(typeSymbol);
|
|
targetConversion = (flag2 ? Conversion.Identity : EncompassingImplicitConversion(typeSymbol, typeSymbol3, ref useSiteInfo2));
|
|
}
|
|
val.Add(UserDefinedConversionAnalysis.Normal(constrainedToTypeOpt2, current, sourceConversion, targetConversion, parameterType, typeSymbol));
|
|
}
|
|
else if ((object)typeSymbol2 != null && typeSymbol2.IsNullableType() && parameterType.IsValidNullableTypeArgument() && (flag2 || typeSymbol3.CanBeAssignedNull()))
|
|
{
|
|
TypeSymbol typeSymbol4 = MakeNullableType(parameterType);
|
|
TypeSymbol typeSymbol5 = (typeSymbol.IsValidNullableTypeArgument() ? MakeNullableType(typeSymbol) : typeSymbol);
|
|
Conversion sourceConversion2 = EncompassingImplicitConversion(aExpr, typeSymbol2, typeSymbol4, ref useSiteInfo2);
|
|
Conversion targetConversion2 = ((!flag2) ? EncompassingImplicitConversion(typeSymbol5, typeSymbol3, ref useSiteInfo2) : Conversion.Identity);
|
|
if (sourceConversion2.Exists && targetConversion2.Exists)
|
|
{
|
|
val.Add(UserDefinedConversionAnalysis.Lifted(constrainedToTypeOpt2, current, sourceConversion2, targetConversion2, typeSymbol4, typeSymbol5));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private TypeSymbol MostSpecificSourceTypeForImplicitUserDefinedConversion(ImmutableArray<UserDefinedConversionAnalysis> u, TypeSymbol source, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
if ((object)source != null && ImmutableArrayExtensions.Any<UserDefinedConversionAnalysis, TypeSymbol>(u, (Func<UserDefinedConversionAnalysis, TypeSymbol, bool>)((UserDefinedConversionAnalysis conv, TypeSymbol right) => TypeSymbol.Equals(conv.FromType, right, (TypeCompareKind)0)), source))
|
|
{
|
|
return source;
|
|
}
|
|
return MostEncompassedType(u, (UserDefinedConversionAnalysis conv) => conv.FromType, ref useSiteInfo);
|
|
}
|
|
|
|
private TypeSymbol MostSpecificTargetTypeForImplicitUserDefinedConversion(ImmutableArray<UserDefinedConversionAnalysis> u, TypeSymbol target, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
if (ImmutableArrayExtensions.Any<UserDefinedConversionAnalysis, TypeSymbol>(u, (Func<UserDefinedConversionAnalysis, TypeSymbol, bool>)((UserDefinedConversionAnalysis conv, TypeSymbol right) => TypeSymbol.Equals(conv.ToType, right, (TypeCompareKind)0)), target))
|
|
{
|
|
return target;
|
|
}
|
|
return MostEncompassingType(u, (UserDefinedConversionAnalysis conv) => conv.ToType, ref useSiteInfo);
|
|
}
|
|
|
|
private static int LiftingCount(UserDefinedConversionAnalysis conv)
|
|
{
|
|
int num = 0;
|
|
if (!TypeSymbol.Equals(conv.FromType, conv.Operator.GetParameterType(0), (TypeCompareKind)0))
|
|
{
|
|
num++;
|
|
}
|
|
if (!TypeSymbol.Equals(conv.ToType, conv.Operator.ReturnType, (TypeCompareKind)0))
|
|
{
|
|
num++;
|
|
}
|
|
return num;
|
|
}
|
|
|
|
private static int? MostSpecificConversionOperator(TypeSymbol sx, TypeSymbol tx, ImmutableArray<UserDefinedConversionAnalysis> u)
|
|
{
|
|
return MostSpecificConversionOperator((UserDefinedConversionAnalysis conv) => TypeSymbol.Equals(conv.FromType, sx, (TypeCompareKind)0) && TypeSymbol.Equals(conv.ToType, tx, (TypeCompareKind)0), u);
|
|
}
|
|
|
|
private static int? MostSpecificConversionOperator(Func<UserDefinedConversionAnalysis, bool> constraint, ImmutableArray<UserDefinedConversionAnalysis> u)
|
|
{
|
|
BestIndex bestIndex = UniqueIndex(u, (UserDefinedConversionAnalysis conv) => constraint(conv) && LiftingCount(conv) == 0);
|
|
if (bestIndex.Kind == BestIndexKind.Best)
|
|
{
|
|
return bestIndex.Best;
|
|
}
|
|
if (bestIndex.Kind == BestIndexKind.Ambiguous)
|
|
{
|
|
return null;
|
|
}
|
|
BestIndex bestIndex2 = UniqueIndex(u, (UserDefinedConversionAnalysis conv) => constraint(conv) && LiftingCount(conv) == 1);
|
|
if (bestIndex2.Kind == BestIndexKind.Best)
|
|
{
|
|
return bestIndex2.Best;
|
|
}
|
|
if (bestIndex2.Kind == BestIndexKind.Ambiguous)
|
|
{
|
|
return null;
|
|
}
|
|
BestIndex bestIndex3 = UniqueIndex(u, (UserDefinedConversionAnalysis conv) => constraint(conv) && LiftingCount(conv) == 2);
|
|
if (bestIndex3.Kind == BestIndexKind.Best)
|
|
{
|
|
return bestIndex3.Best;
|
|
}
|
|
_ = bestIndex3.Kind;
|
|
_ = 2;
|
|
return null;
|
|
}
|
|
|
|
private static BestIndex UniqueIndex<T>(ImmutableArray<T> items, Func<T, bool> predicate)
|
|
{
|
|
if (items.IsEmpty)
|
|
{
|
|
return BestIndex.None();
|
|
}
|
|
int? num = null;
|
|
for (int i = 0; i < items.Length; i++)
|
|
{
|
|
if (predicate(items[i]))
|
|
{
|
|
if (num.HasValue)
|
|
{
|
|
return BestIndex.IsAmbiguous(num.Value, i);
|
|
}
|
|
num = i;
|
|
}
|
|
}
|
|
if (num.HasValue)
|
|
{
|
|
return BestIndex.HasBest(num.Value);
|
|
}
|
|
return BestIndex.None();
|
|
}
|
|
|
|
private bool IsEncompassedBy(BoundExpression aExpr, TypeSymbol a, TypeSymbol b, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
return EncompassingImplicitConversion(aExpr, a, b, ref useSiteInfo).Exists;
|
|
}
|
|
|
|
private bool IsEncompassedBy(TypeSymbol a, TypeSymbol b, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
return IsEncompassedBy(null, a, b, ref useSiteInfo);
|
|
}
|
|
|
|
private Conversion EncompassingImplicitConversion(BoundExpression aExpr, TypeSymbol a, TypeSymbol b, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
Conversion result = ClassifyStandardImplicitConversion(aExpr, a, b, ref useSiteInfo);
|
|
if (!IsEncompassingImplicitConversionKind(result.Kind))
|
|
{
|
|
return Conversion.NoConversion;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private Conversion EncompassingImplicitConversion(TypeSymbol a, TypeSymbol b, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
return EncompassingImplicitConversion(null, a, b, ref useSiteInfo);
|
|
}
|
|
|
|
private static bool IsEncompassingImplicitConversionKind(ConversionKind kind)
|
|
{
|
|
switch (kind)
|
|
{
|
|
case ConversionKind.NoConversion:
|
|
case ConversionKind.ImplicitEnumeration:
|
|
case ConversionKind.ExplicitTupleLiteral:
|
|
case ConversionKind.ExplicitTuple:
|
|
case ConversionKind.ImplicitDynamic:
|
|
case ConversionKind.ExplicitDynamic:
|
|
case ConversionKind.ImplicitUserDefined:
|
|
case ConversionKind.AnonymousFunction:
|
|
case ConversionKind.MethodGroup:
|
|
case ConversionKind.FunctionType:
|
|
case ConversionKind.ExplicitNumeric:
|
|
case ConversionKind.ExplicitEnumeration:
|
|
case ConversionKind.ExplicitNullable:
|
|
case ConversionKind.ExplicitReference:
|
|
case ConversionKind.Unboxing:
|
|
case ConversionKind.ExplicitUserDefined:
|
|
case ConversionKind.ExplicitPointerToPointer:
|
|
case ConversionKind.ExplicitIntegerToPointer:
|
|
case ConversionKind.ExplicitPointerToInteger:
|
|
case ConversionKind.IntPtr:
|
|
case ConversionKind.InterpolatedString:
|
|
case ConversionKind.SwitchExpression:
|
|
case ConversionKind.ConditionalExpression:
|
|
case ConversionKind.StackAllocToPointerType:
|
|
case ConversionKind.StackAllocToSpanType:
|
|
case ConversionKind.InterpolatedStringHandler:
|
|
return false;
|
|
case ConversionKind.Identity:
|
|
case ConversionKind.ImplicitNumeric:
|
|
case ConversionKind.ImplicitThrow:
|
|
case ConversionKind.ImplicitTupleLiteral:
|
|
case ConversionKind.ImplicitTuple:
|
|
case ConversionKind.ImplicitNullable:
|
|
case ConversionKind.NullLiteral:
|
|
case ConversionKind.ImplicitReference:
|
|
case ConversionKind.Boxing:
|
|
case ConversionKind.ImplicitPointerToVoid:
|
|
case ConversionKind.ImplicitNullToPointer:
|
|
case ConversionKind.ImplicitPointer:
|
|
case ConversionKind.ImplicitConstant:
|
|
case ConversionKind.DefaultLiteral:
|
|
case ConversionKind.InlineArray:
|
|
return true;
|
|
default:
|
|
throw ExceptionUtilities.UnexpectedValue((object)kind);
|
|
}
|
|
}
|
|
|
|
private TypeSymbol MostEncompassedType<T>(ImmutableArray<T> items, Func<T, TypeSymbol> extract, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
return MostEncompassedType(items, (T x) => true, extract, ref useSiteInfo);
|
|
}
|
|
|
|
private TypeSymbol MostEncompassedType<T>(ImmutableArray<T> items, Func<T, bool> valid, Func<T, TypeSymbol> extract, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
|
|
CompoundUseSiteInfo<AssemblySymbol> inLambdaUseSiteInfo = useSiteInfo;
|
|
int? num = UniqueBestValidIndex(items, valid, delegate(T left, T right)
|
|
{
|
|
TypeSymbol typeSymbol = extract(left);
|
|
TypeSymbol typeSymbol2 = extract(right);
|
|
if (TypeSymbol.Equals(typeSymbol, typeSymbol2, (TypeCompareKind)0))
|
|
{
|
|
return BetterResult.Equal;
|
|
}
|
|
bool flag = IsEncompassedBy(typeSymbol, typeSymbol2, ref inLambdaUseSiteInfo);
|
|
bool flag2 = IsEncompassedBy(typeSymbol2, typeSymbol, ref inLambdaUseSiteInfo);
|
|
if (flag == flag2)
|
|
{
|
|
return BetterResult.Neither;
|
|
}
|
|
return (!flag) ? BetterResult.Right : BetterResult.Left;
|
|
});
|
|
useSiteInfo = inLambdaUseSiteInfo;
|
|
if (num.HasValue)
|
|
{
|
|
return extract(items[num.Value]);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private TypeSymbol MostEncompassingType<T>(ImmutableArray<T> items, Func<T, TypeSymbol> extract, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
return MostEncompassingType(items, (T x) => true, extract, ref useSiteInfo);
|
|
}
|
|
|
|
private TypeSymbol MostEncompassingType<T>(ImmutableArray<T> items, Func<T, bool> valid, Func<T, TypeSymbol> extract, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
|
|
CompoundUseSiteInfo<AssemblySymbol> inLambdaUseSiteInfo = useSiteInfo;
|
|
int? num = UniqueBestValidIndex(items, valid, delegate(T left, T right)
|
|
{
|
|
TypeSymbol typeSymbol = extract(left);
|
|
TypeSymbol typeSymbol2 = extract(right);
|
|
if (TypeSymbol.Equals(typeSymbol, typeSymbol2, (TypeCompareKind)0))
|
|
{
|
|
return BetterResult.Equal;
|
|
}
|
|
bool flag = IsEncompassedBy(typeSymbol2, typeSymbol, ref inLambdaUseSiteInfo);
|
|
bool flag2 = IsEncompassedBy(typeSymbol, typeSymbol2, ref inLambdaUseSiteInfo);
|
|
if (flag == flag2)
|
|
{
|
|
return BetterResult.Neither;
|
|
}
|
|
return (!flag) ? BetterResult.Right : BetterResult.Left;
|
|
});
|
|
useSiteInfo = inLambdaUseSiteInfo;
|
|
if (num.HasValue)
|
|
{
|
|
return extract(items[num.Value]);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private static int? UniqueBestValidIndex<T>(ImmutableArray<T> items, Func<T, bool> valid, Func<T, T, BetterResult> better)
|
|
{
|
|
if (items.IsEmpty)
|
|
{
|
|
return null;
|
|
}
|
|
int? result = null;
|
|
T arg = default(T);
|
|
for (int i = 0; i < items.Length; i++)
|
|
{
|
|
T val = items[i];
|
|
if (!valid(val))
|
|
{
|
|
continue;
|
|
}
|
|
if (!result.HasValue)
|
|
{
|
|
result = i;
|
|
arg = val;
|
|
continue;
|
|
}
|
|
switch (better(arg, val))
|
|
{
|
|
case BetterResult.Neither:
|
|
result = null;
|
|
arg = default(T);
|
|
break;
|
|
case BetterResult.Right:
|
|
result = i;
|
|
arg = val;
|
|
break;
|
|
}
|
|
}
|
|
if (!result.HasValue)
|
|
{
|
|
return null;
|
|
}
|
|
for (int j = 0; j < result.Value; j++)
|
|
{
|
|
T val2 = items[j];
|
|
if (valid(val2))
|
|
{
|
|
BetterResult betterResult = better(arg, val2);
|
|
if (betterResult != BetterResult.Left && betterResult != BetterResult.Equal)
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private NamedTypeSymbol MakeNullableType(TypeSymbol type)
|
|
{
|
|
return corLibrary.GetDeclaredSpecialType((SpecialType)32).Construct(type);
|
|
}
|
|
|
|
protected UserDefinedConversionResult AnalyzeImplicitUserDefinedConversionForV6SwitchGoverningType(TypeSymbol source, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo)
|
|
{
|
|
ArrayBuilder<(NamedTypeSymbol, TypeParameterSymbol)> instance = ArrayBuilder<(NamedTypeSymbol, TypeParameterSymbol)>.GetInstance();
|
|
ComputeUserDefinedImplicitConversionTypeSet(source, null, instance, ref useSiteInfo);
|
|
ArrayBuilder<UserDefinedConversionAnalysis> instance2 = ArrayBuilder<UserDefinedConversionAnalysis>.GetInstance();
|
|
ComputeApplicableUserDefinedImplicitConversionSet(null, source, null, instance, instance2, ref useSiteInfo, allowAnyTarget: true);
|
|
instance.Free();
|
|
ImmutableArray<UserDefinedConversionAnalysis> immutableArray = instance2.ToImmutableAndFree();
|
|
int? num = MostSpecificConversionOperator((UserDefinedConversionAnalysis conv) => conv.ToType.IsValidV6SwitchGoverningType(isTargetTypeOfUserDefinedOp: true), immutableArray);
|
|
if (num.HasValue)
|
|
{
|
|
return UserDefinedConversionResult.Valid(immutableArray, num.Value);
|
|
}
|
|
return UserDefinedConversionResult.NoApplicableOperators(immutableArray);
|
|
}
|
|
}
|