|
|
|
@ -421,14 +421,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver |
|
|
|
&& ImplicitReferenceConversion(fromArray.ElementType, toArray.ElementType, subtypeCheckNestingDepth); |
|
|
|
&& ImplicitReferenceConversion(fromArray.ElementType, toArray.ElementType, subtypeCheckNestingDepth); |
|
|
|
} |
|
|
|
} |
|
|
|
// conversion from single-dimensional array S[] to IList<T>:
|
|
|
|
// conversion from single-dimensional array S[] to IList<T>:
|
|
|
|
ParameterizedType toPT = toType as ParameterizedType; |
|
|
|
IType toTypeArgument = UnpackGenericArrayInterface(toType); |
|
|
|
if (fromArray.Dimensions == 1 && toPT != null) { |
|
|
|
if (fromArray.Dimensions == 1 && toTypeArgument != null) { |
|
|
|
KnownTypeCode tc = toPT.GetDefinition().KnownTypeCode; |
|
|
|
// array covariance plays a part here as well (string[] is IList<object>)
|
|
|
|
if (tc == KnownTypeCode.IListOfT || tc == KnownTypeCode.ICollectionOfT || tc == KnownTypeCode.IEnumerableOfT || tc == KnownTypeCode.IReadOnlyListOfT) { |
|
|
|
return IdentityConversion(fromArray.ElementType, toTypeArgument) |
|
|
|
// array covariance plays a part here as well (string[] is IList<object>)
|
|
|
|
|| ImplicitReferenceConversion(fromArray.ElementType, toTypeArgument, subtypeCheckNestingDepth); |
|
|
|
return IdentityConversion(fromArray.ElementType, toPT.GetTypeArgument(0)) |
|
|
|
|
|
|
|
|| ImplicitReferenceConversion(fromArray.ElementType, toPT.GetTypeArgument(0), subtypeCheckNestingDepth); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
// conversion from any array to System.Array and the interfaces it implements:
|
|
|
|
// conversion from any array to System.Array and the interfaces it implements:
|
|
|
|
IType systemArray = compilation.FindType(KnownTypeCode.Array); |
|
|
|
IType systemArray = compilation.FindType(KnownTypeCode.Array); |
|
|
|
@ -439,6 +436,22 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver |
|
|
|
return IsSubtypeOf(fromType, toType, subtypeCheckNestingDepth); |
|
|
|
return IsSubtypeOf(fromType, toType, subtypeCheckNestingDepth); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
|
|
/// For IList{T}, ICollection{T}, IEnumerable{T} and IReadOnlyList{T}, returns T.
|
|
|
|
|
|
|
|
/// Otherwise, returns null.
|
|
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
IType UnpackGenericArrayInterface(IType interfaceType) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
ParameterizedType pt = interfaceType as ParameterizedType; |
|
|
|
|
|
|
|
if (pt != null) { |
|
|
|
|
|
|
|
KnownTypeCode tc = pt.GetDefinition().KnownTypeCode; |
|
|
|
|
|
|
|
if (tc == KnownTypeCode.IListOfT || tc == KnownTypeCode.ICollectionOfT || tc == KnownTypeCode.IEnumerableOfT || tc == KnownTypeCode.IReadOnlyListOfT) { |
|
|
|
|
|
|
|
return pt.GetTypeArgument(0); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Determines whether s is a subtype of t.
|
|
|
|
// Determines whether s is a subtype of t.
|
|
|
|
// Helper method used for ImplicitReferenceConversion, BoxingConversion and ImplicitTypeParameterConversion
|
|
|
|
// Helper method used for ImplicitReferenceConversion, BoxingConversion and ImplicitTypeParameterConversion
|
|
|
|
|
|
|
|
|
|
|
|
@ -530,16 +543,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
return ExplicitReferenceConversion(fromArray.ElementType, toArray.ElementType); |
|
|
|
return ExplicitReferenceConversion(fromArray.ElementType, toArray.ElementType); |
|
|
|
} |
|
|
|
} |
|
|
|
ParameterizedType pt = fromType as ParameterizedType; |
|
|
|
IType fromTypeArgument = UnpackGenericArrayInterface(fromType); |
|
|
|
if (pt != null && toArray.Dimensions == 1) { |
|
|
|
if (fromTypeArgument != null && toArray.Dimensions == 1) { |
|
|
|
KnownTypeCode tc = pt.GetDefinition().KnownTypeCode; |
|
|
|
return ExplicitReferenceConversion(fromTypeArgument, toArray.ElementType) |
|
|
|
if (tc == KnownTypeCode.IListOfT || tc == KnownTypeCode.ICollectionOfT || tc == KnownTypeCode.IEnumerableOfT || tc == KnownTypeCode.IReadOnlyListOfT) { |
|
|
|
|| IdentityConversion(fromTypeArgument, toArray.ElementType); |
|
|
|
return ExplicitReferenceConversion(pt.GetTypeArgument(0), toArray.ElementType) |
|
|
|
|
|
|
|
|| IdentityConversion(pt.GetTypeArgument(0), toArray.ElementType); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
// Otherwise treat the array like a sealed class - require implicit conversion in the opposite direction
|
|
|
|
// Otherwise treat the array like a sealed class - require implicit conversion in the opposite direction
|
|
|
|
return IsImplicitReferenceConversion(toType, fromType); |
|
|
|
return IsImplicitReferenceConversion(toType, fromType); |
|
|
|
|
|
|
|
} else if (fromType.Kind == TypeKind.Array) { |
|
|
|
|
|
|
|
ArrayType fromArray = (ArrayType)fromType; |
|
|
|
|
|
|
|
IType toTypeArgument = UnpackGenericArrayInterface(toType); |
|
|
|
|
|
|
|
if (toTypeArgument != null && fromArray.Dimensions == 1) { |
|
|
|
|
|
|
|
return ExplicitReferenceConversion(fromArray.ElementType, toTypeArgument); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// Otherwise treat the array like a sealed class
|
|
|
|
|
|
|
|
return IsImplicitReferenceConversion(fromType, toType); |
|
|
|
} else if (fromType.Kind == TypeKind.Delegate && toType.Kind == TypeKind.Delegate) { |
|
|
|
} else if (fromType.Kind == TypeKind.Delegate && toType.Kind == TypeKind.Delegate) { |
|
|
|
ITypeDefinition def = fromType.GetDefinition(); |
|
|
|
ITypeDefinition def = fromType.GetDefinition(); |
|
|
|
if (def == null || !def.Equals(toType.GetDefinition())) |
|
|
|
if (def == null || !def.Equals(toType.GetDefinition())) |
|
|
|
@ -570,7 +588,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} else if (IsSealedReferenceType(fromType) || fromType.Kind == TypeKind.Array) { |
|
|
|
} else if (IsSealedReferenceType(fromType)) { |
|
|
|
// If the source type is sealed, explicit conversions can't do anything more than implicit ones
|
|
|
|
// If the source type is sealed, explicit conversions can't do anything more than implicit ones
|
|
|
|
return IsImplicitReferenceConversion(fromType, toType); |
|
|
|
return IsImplicitReferenceConversion(fromType, toType); |
|
|
|
} else if (IsSealedReferenceType(toType)) { |
|
|
|
} else if (IsSealedReferenceType(toType)) { |
|
|
|
|