Example #1
0
            private bool bindExplicitConversionFromArrayToArray(ArrayType arraySrc, ArrayType arrayDest)
            {
                // 13.2.2
                //
                // The explicit reference conversions are:
                //
                // * From an array-type S with an element type SE to an array-type T with an element type
                //   TE, provided all of the following are true:
                //
                //   * S and T differ only in element type. (In other words, S and T have the same number
                //     of dimensions.)
                //
                //   * An explicit reference conversion exists from SE to TE.

                if (arraySrc.rank != arrayDest.rank || arraySrc.IsSZArray != arrayDest.IsSZArray)
                {
                    return(false);  // Ranks do not match.
                }

                if (CConversions.FExpRefConv(GetSymbolLoader(), arraySrc.GetElementType(), arrayDest.GetElementType()))
                {
                    if (_needsExprDest)
                    {
                        _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, EXPRFLAG.EXF_REFCHECK);
                    }
                    return(true);
                }

                return(false);
            }
Example #2
0
        private bool TryArrayVarianceAdjustmentToGetAccessibleType(CSemanticChecker semanticChecker, BindingContext bindingContext, ArrayType typeSrc, out CType typeDst)
        {
            Debug.Assert(typeSrc != null);

            typeDst = null;

            // We are here because we have an array type with an inaccessible element type. If possible,
            // we should create a new array type that has an accessible element type for which a
            // conversion exists.

            CType elementType = typeSrc.GetElementType();

            if (!elementType.IsRefType())
            {
                // Covariant array conversions exist for reference types only.
                return(false);
            }

            CType intermediateType;

            if (GetBestAccessibleType(semanticChecker, bindingContext, elementType, out intermediateType))
            {
                typeDst = this.GetArray(intermediateType, typeSrc.rank, typeSrc.IsSZArray);

                Debug.Assert(semanticChecker.CheckTypeAccess(typeDst, bindingContext.ContextForMemberLookup));
                return(true);
            }

            return(false);
        }
Example #3
0
 private bool HasCovariantArrayConversion(ArrayType pSource, ArrayType pDest)
 {
     Debug.Assert(pSource != null);
     Debug.Assert(pDest != null);
     // * S and T differ only in element type. In other words, S and T have the same number of dimensions.
     // * Both SE and TE are reference types.
     // * An implicit reference conversion exists from SE to TE.
     return((pSource.rank == pDest.rank) && pSource.IsSZArray == pDest.IsSZArray &&
            HasImplicitReferenceConversion(pSource.GetElementType(), pDest.GetElementType()));
 }
Example #4
0
        private static Type CalculateAssociatedSystemType(CType src)
        {
            Type result = null;

            switch (src.GetTypeKind())
            {
            case TypeKind.TK_ArrayType:
                ArrayType a           = (ArrayType)src;
                Type      elementType = a.GetElementType().AssociatedSystemType;
                result = a.IsSZArray ? elementType.MakeArrayType() : elementType.MakeArrayType(a.rank);
                break;

            case TypeKind.TK_NullableType:
                NullableType n = (NullableType)src;
                Type         underlyingType = n.GetUnderlyingType().AssociatedSystemType;
                result = typeof(Nullable <>).MakeGenericType(underlyingType);
                break;

            case TypeKind.TK_PointerType:
                PointerType p            = (PointerType)src;
                Type        referentType = p.GetReferentType().AssociatedSystemType;
                result = referentType.MakePointerType();
                break;

            case TypeKind.TK_ParameterModifierType:
                ParameterModifierType r = (ParameterModifierType)src;
                Type parameterType      = r.GetParameterType().AssociatedSystemType;
                result = parameterType.MakeByRefType();
                break;

            case TypeKind.TK_AggregateType:
                result = CalculateAssociatedSystemTypeForAggregate((AggregateType)src);
                break;

            case TypeKind.TK_TypeParameterType:
                TypeParameterType t = (TypeParameterType)src;
                if (t.IsMethodTypeParameter())
                {
                    MethodInfo meth = ((MethodSymbol)t.GetOwningSymbol()).AssociatedMemberInfo as MethodInfo;
                    result = meth.GetGenericArguments()[t.GetIndexInOwnParameters()];
                }
                else
                {
                    Type parentType = ((AggregateSymbol)t.GetOwningSymbol()).AssociatedSystemType;
                    result = parentType.GetGenericArguments()[t.GetIndexInOwnParameters()];
                }
                break;
            }

            Debug.Assert(result != null || src.GetTypeKind() == TypeKind.TK_AggregateType);
            return(result);
        }
Example #5
0
        public ArrayType GetArray(CType elementType, int args, bool isSZArray)
        {
            Name name;

            Debug.Assert(args > 0 && args < 32767);
            Debug.Assert(args == 1 || !isSZArray);

            switch (args)
            {
            case 1:
                if (isSZArray)
                {
                    goto case 2;
                }
                else
                {
                    goto default;
                }

            case 2:
                name = NameManager.GetPredefinedName(PredefinedName.PN_ARRAY0 + args);
                break;

            default:
                name = _BSymmgr.GetNameManager().Add("[X" + args + 1);
                break;
            }

            // See if we already have an array type of this element type and rank.
            ArrayType pArray = _typeTable.LookupArray(name, elementType);

            if (pArray == null)
            {
                // No existing array symbol. Create a new one.
                pArray = _typeFactory.CreateArray(name, elementType, args, isSZArray);
                pArray.InitFromParent();

                _typeTable.InsertArray(name, elementType, pArray);
            }
            else
            {
                Debug.Assert(pArray.HasErrors() == elementType.HasErrors());
            }

            Debug.Assert(pArray.rank == args);
            Debug.Assert(pArray.GetElementType() == elementType);

            return(pArray);
        }
Example #6
0
        private bool HasArrayConversionToInterface(ArrayType pSource, CType pDest)
        {
            Debug.Assert(pSource != null);
            Debug.Assert(pDest != null);
            if (!pSource.IsSZArray)
            {
                return(false);
            }
            if (!pDest.isInterfaceType())
            {
                return(false);
            }

            // * From a single-dimensional array type S[] to IList<T> or IReadOnlyList<T> and their base
            //   interfaces, provided that there is an implicit identity or reference
            //   conversion from S to T.

            // We only have six interfaces to check. IList<T>, IReadOnlyList<T> and their bases:
            // * The base interface of IList<T> is ICollection<T>.
            // * The base interface of ICollection<T> is IEnumerable<T>.
            // * The base interface of IEnumerable<T> is IEnumerable.
            // * The base interface of IReadOnlyList<T> is IReadOnlyCollection<T>.
            // * The base interface of IReadOnlyCollection<T> is IEnumerable<T>.

            if (pDest.isPredefType(PredefinedType.PT_IENUMERABLE))
            {
                return(true);
            }

            AggregateType   atsDest = (AggregateType)pDest;
            AggregateSymbol aggDest = atsDest.getAggregate();

            if (!aggDest.isPredefAgg(PredefinedType.PT_G_ILIST) &&
                !aggDest.isPredefAgg(PredefinedType.PT_G_ICOLLECTION) &&
                !aggDest.isPredefAgg(PredefinedType.PT_G_IENUMERABLE) &&
                !aggDest.isPredefAgg(PredefinedType.PT_G_IREADONLYCOLLECTION) &&
                !aggDest.isPredefAgg(PredefinedType.PT_G_IREADONLYLIST))
            {
                return(false);
            }

            Debug.Assert(atsDest.GetTypeArgsAll().Count == 1);

            CType pSourceElement    = pSource.GetElementType();
            CType pDestTypeArgument = atsDest.GetTypeArgsAll()[0];

            return(HasIdentityOrImplicitReferenceConversion(pSourceElement, pDestTypeArgument));
        }
Example #7
0
            private bool bindExplicitConversionFromIListToArray(ArrayType arrayDest)
            {
                // 13.2.2
                //
                // The explicit reference conversions are:
                //
                // * From System.Collections.Generic.IList<T>, System.Collections.Generic.IReadOnlyList<T> and their base interfaces
                //   to a one-dimensional array-type S[], provided there is an implicit or explicit reference conversion from
                //   S[] to System.Collections.Generic.IList<T> or System.Collections.Generic.IReadOnlyList<T>. This is precisely when either S and T
                //   are the same type or there is an implicit or explicit reference conversion from S to T.

                if (!arrayDest.IsSZArray || !(_typeSrc is AggregateType aggSrc) || !aggSrc.isInterfaceType() ||
                    aggSrc.GetTypeArgsAll().Count != 1)
                {
                    return(false);
                }

                AggregateSymbol aggIList         = GetSymbolLoader().GetPredefAgg(PredefinedType.PT_G_ILIST);
                AggregateSymbol aggIReadOnlyList = GetSymbolLoader().GetPredefAgg(PredefinedType.PT_G_IREADONLYLIST);

                if ((aggIList == null ||
                     !GetSymbolLoader().IsBaseAggregate(aggIList, aggSrc.getAggregate())) &&
                    (aggIReadOnlyList == null ||
                     !GetSymbolLoader().IsBaseAggregate(aggIReadOnlyList, aggSrc.getAggregate())))
                {
                    return(false);
                }

                CType typeArr = arrayDest.GetElementType();
                CType typeLst = aggSrc.GetTypeArgsAll()[0];

                Debug.Assert(!typeArr.IsNeverSameType());
                if (typeArr != typeLst && !CConversions.FExpRefConv(GetSymbolLoader(), typeArr, typeLst))
                {
                    return(false);
                }
                if (_needsExprDest)
                {
                    _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, EXPRFLAG.EXF_REFCHECK);
                }
                return(true);
            }
Example #8
0
        private static Type CalculateAssociatedSystemType(CType src)
        {
            Type result = null;

            switch (src.GetTypeKind())
            {
            case TypeKind.TK_ArrayType:
                ArrayType a           = src.AsArrayType();
                Type      elementType = a.GetElementType().AssociatedSystemType;
                if (a.rank == 1)
                {
                    result = elementType.MakeArrayType();
                }
                else
                {
                    result = elementType.MakeArrayType(a.rank);
                }
                break;

            case TypeKind.TK_NullableType:
                NullableType n = src.AsNullableType();
                Type         underlyingType = n.GetUnderlyingType().AssociatedSystemType;
                result = typeof(Nullable <>).MakeGenericType(underlyingType);
                break;

            case TypeKind.TK_PointerType:
                PointerType p            = src.AsPointerType();
                Type        referentType = p.GetReferentType().AssociatedSystemType;
                result = referentType.MakePointerType();
                break;

            case TypeKind.TK_ParameterModifierType:
                ParameterModifierType r = src.AsParameterModifierType();
                Type parameterType      = r.GetParameterType().AssociatedSystemType;
                result = parameterType.MakeByRefType();
                break;

            case TypeKind.TK_AggregateType:
                result = CalculateAssociatedSystemTypeForAggregate(src.AsAggregateType());
                break;

            case TypeKind.TK_TypeParameterType:
                TypeParameterType t = src.AsTypeParameterType();
                Type parentType     = null;
                if (t.IsMethodTypeParameter())
                {
                    MethodInfo meth = t.GetOwningSymbol().AsMethodSymbol().AssociatedMemberInfo as MethodInfo;
                    result = meth.GetGenericArguments()[t.GetIndexInOwnParameters()];
                }
                else
                {
                    parentType = t.GetOwningSymbol().AsAggregateSymbol().AssociatedSystemType;
                    result     = parentType.GetTypeInfo().GenericTypeParameters[t.GetIndexInOwnParameters()];
                }
                break;

            case TypeKind.TK_ArgumentListType:
            case TypeKind.TK_BoundLambdaType:
            case TypeKind.TK_ErrorType:
            case TypeKind.TK_MethodGroupType:
            case TypeKind.TK_NaturalIntegerType:
            case TypeKind.TK_NullType:
            case TypeKind.TK_OpenTypePlaceholderType:
            case TypeKind.TK_UnboundLambdaType:
            case TypeKind.TK_VoidType:

            default:
                break;
            }

            Debug.Assert(result != null || src.GetTypeKind() == TypeKind.TK_AggregateType);
            return(result);
        }
Example #9
0
            private bool bindExplicitConversionFromArrayToArray(ArrayType arraySrc, ArrayType arrayDest)
            {
                // 13.2.2
                //
                // The explicit reference conversions are:
                //
                // * From an array-type S with an element type SE to an array-type T with an element type
                //   TE, provided all of the following are true:
                //
                //   * S and T differ only in element type. (In other words, S and T have the same number
                //     of dimensions.)
                //
                //   * An explicit reference conversion exists from SE to TE.

                if (arraySrc.rank != arrayDest.rank)
                {
                    return false;  // Ranks do not match.
                }

                if (CConversions.FExpRefConv(GetSymbolLoader(), arraySrc.GetElementType(), arrayDest.GetElementType()))
                {
                    if (_needsExprDest)
                        _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, EXPRFLAG.EXF_REFCHECK);
                    return true;
                }

                return false;
            }
Example #10
0
            private bool bindExplicitConversionFromIListToArray(ArrayType arrayDest)
            {
                // 13.2.2
                //
                // The explicit reference conversions are:
                //
                // * From System.Collections.Generic.IList<T>, System.Collections.Generic.IReadOnlyList<T> and their base interfaces 
                //   to a one-dimensional array-type S[], provided there is an implicit or explicit reference conversion from
                //   S[] to System.Collections.Generic.IList<T> or System.Collections.Generic.IReadOnlyList<T>. This is precisely when either S and T
                //   are the same type or there is an implicit or explicit reference conversion from S to T.

                if (arrayDest.rank != 1 || !_typeSrc.isInterfaceType() ||
                    _typeSrc.AsAggregateType().GetTypeArgsAll().Size != 1)
                {
                    return false;
                }

                AggregateSymbol aggIList = GetSymbolLoader().GetOptPredefAgg(PredefinedType.PT_G_ILIST);
                AggregateSymbol aggIReadOnlyList = GetSymbolLoader().GetOptPredefAgg(PredefinedType.PT_G_IREADONLYLIST);

                if ((aggIList == null ||
                    !GetSymbolLoader().IsBaseAggregate(aggIList, _typeSrc.AsAggregateType().getAggregate())) &&
                    (aggIReadOnlyList == null ||
                    !GetSymbolLoader().IsBaseAggregate(aggIReadOnlyList, _typeSrc.AsAggregateType().getAggregate())))
                {
                    return false;
                }

                CType typeArr = arrayDest.GetElementType();
                CType typeLst = _typeSrc.AsAggregateType().GetTypeArgsAll().Item(0);

                Debug.Assert(!typeArr.IsNeverSameType());
                if (typeArr != typeLst && !CConversions.FExpRefConv(GetSymbolLoader(), typeArr, typeLst))
                {
                    return false;
                }
                if (_needsExprDest)
                    _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, EXPRFLAG.EXF_REFCHECK);
                return true;
            }
Example #11
0
        private bool TryArrayVarianceAdjustmentToGetAccessibleType(CSemanticChecker semanticChecker, BindingContext bindingContext, ArrayType typeSrc, out CType typeDst)
        {
            Debug.Assert(typeSrc != null);

            typeDst = null;

            // We are here because we have an array type with an inaccessible element type. If possible,
            // we should create a new array type that has an accessible element type for which a
            // conversion exists.

            CType elementType = typeSrc.GetElementType();
            if (!elementType.IsRefType())
            {
                // Covariant array conversions exist for reference types only.
                return false;
            }

            CType intermediateType;
            if (GetBestAccessibleType(semanticChecker, bindingContext, elementType, out intermediateType))
            {
                typeDst = this.GetArray(intermediateType, typeSrc.rank);

                Debug.Assert(semanticChecker.CheckTypeAccess(typeDst, bindingContext.ContextForMemberLookup()));
                return true;
            }

            return false;
        }
Example #12
0
        /***************************************************************************************************
        *   Determine whether there is an explicit or implicit reference conversion (or identity conversion)
        *   from typeSrc to typeDst. This is when:
        *
        *  13.2.3 Explicit reference conversions
        *
        *  The explicit reference conversions are:
        *   From object to any reference-type.
        *   From any class-type S to any class-type T, provided S is a base class of T.
        *   From any class-type S to any interface-type T, provided S is not sealed and provided S does not implement T.
        *   From any interface-type S to any class-type T, provided T is not sealed or provided T implements S.
        *   From any interface-type S to any interface-type T, provided S is not derived from T.
        *   From an array-type S with an element type SE to an array-type T with an element type TE, provided all of the following are true:
        *   o   S and T differ only in element type. (In other words, S and T have the same number of dimensions.)
        *   o   An explicit reference conversion exists from SE to TE.
        *   From System.Array and the interfaces it implements, to any array-type.
        *   From System.Delegate and the interfaces it implements, to any delegate-type.
        *   From a one-dimensional array-type S[] to System.Collections.Generic.IList<T>, System.Collections.Generic.IReadOnlyList<T> and their base interfaces, provided there is an explicit reference conversion from S to T.
        *   From a generic delegate type S to generic delegate type  T, provided all of the follow are true:
        *   o Both types are constructed generic types of the same generic delegate type, D<X1,... Xk>.That is,
        *     S is D<S1,... Sk> and T is D<T1,... Tk>.
        *   o S is not compatible with or identical to T.
        *   o If type parameter Xi is declared to be invariant then Si must be identical to Ti.
        *   o If type parameter Xi is declared to be covariant ("out") then Si must be convertible
        *     to Ti via an identify conversion,  implicit reference conversion, or explicit reference conversion.
        *   o If type parameter Xi is declared to be contravariant ("in") then either Si must be identical to Ti,
        *      or Si and Ti must both be reference types.
        *   From System.Collections.Generic.IList<T>, System.Collections.Generic.IReadOnlyList<T> and their base interfaces to a one-dimensional array-type S[], provided there is an implicit or explicit reference conversion from S[] to System.Collections.Generic.IList<T> or System.Collections.Generic.IReadOnlyList<T>. This is precisely when either S and T are the same type or there is an implicit or explicit reference conversion from S to T.
        *
        *  For a type-parameter T that is known to be a reference type (§25.7), the following explicit reference conversions exist:
        *   From the effective base class C of T to T and from any base class of C to T.
        *   From any interface-type to T.
        *   From T to any interface-type I provided there isn’t already an implicit reference conversion from T to I.
        *   From a type-parameter U to T provided that T depends on U (§25.7). [Note: Since T is known to be a reference type, within the scope of T, the run-time type of U will always be a reference type, even if U is not known to be a reference type at compile-time. end note]
        *
        * Both src and dst are reference types and there is a builtin explicit conversion from
        *     src to dst.
        * Or src is a reference type and dst is a base type of src (in which case the conversion is
        *     implicit as well).
        * Or dst is a reference type and src is a base type of dst.
        *
        *   The latter two cases can happen with type variables even though the other type variable is not
        *   a reference type.
        ***************************************************************************************************/
        public static bool FExpRefConv(SymbolLoader loader, CType typeSrc, CType typeDst)
        {
            Debug.Assert(typeSrc != null);
            Debug.Assert(typeDst != null);
            if (typeSrc.IsRefType() && typeDst.IsRefType())
            {
                // is there an implicit reference conversion in either direction?
                // this handles the bulk of the cases ...
                if (loader.HasIdentityOrImplicitReferenceConversion(typeSrc, typeDst) ||
                    loader.HasIdentityOrImplicitReferenceConversion(typeDst, typeSrc))
                {
                    return(true);
                }

                // For a type-parameter T that is known to be a reference type (§25.7), the following explicit reference conversions exist:
                // •    From any interface-type to T.
                // •    From T to any interface-type I provided there isn’t already an implicit reference conversion from T to I.
                if (typeSrc.isInterfaceType() && typeDst.IsTypeParameterType())
                {
                    return(true);
                }
                if (typeSrc.IsTypeParameterType() && typeDst.isInterfaceType())
                {
                    return(true);
                }

                // * From any class-type S to any interface-type T, provided S is not sealed
                // * From any interface-type S to any class-type T, provided T is not sealed
                // * From any interface-type S to any interface-type T, provided S is not derived from T.
                if (typeSrc.IsAggregateType() && typeDst.IsAggregateType())
                {
                    AggregateSymbol aggSrc  = typeSrc.AsAggregateType().getAggregate();
                    AggregateSymbol aggDest = typeDst.AsAggregateType().getAggregate();

                    if ((aggSrc.IsClass() && !aggSrc.IsSealed() && aggDest.IsInterface()) ||
                        (aggSrc.IsInterface() && aggDest.IsClass() && !aggDest.IsSealed()) ||
                        (aggSrc.IsInterface() && aggDest.IsInterface()))
                    {
                        return(true);
                    }
                }

                // *    From an array-type S with an element type SE to an array-type T with an element type TE, provided all of the following are true:
                //     o    S and T differ only in element type. (In other words, S and T have the same number of dimensions.)
                //     o    An explicit reference conversion exists from SE to TE.
                if (typeSrc.IsArrayType() && typeDst.IsArrayType())
                {
                    return(typeSrc.AsArrayType().rank == typeDst.AsArrayType().rank&& FExpRefConv(loader, typeSrc.AsArrayType().GetElementType(), typeDst.AsArrayType().GetElementType()));
                }

                // *    From a one-dimensional array-type S[] to System.Collections.Generic.IList<T>, System.Collections.Generic.IReadOnlyList<T>
                //      and their base interfaces, provided there is an explicit reference conversion from S to T.
                if (typeSrc.IsArrayType())
                {
                    if (typeSrc.AsArrayType().rank != 1 ||
                        !typeDst.isInterfaceType() || typeDst.AsAggregateType().GetTypeArgsAll().Size != 1)
                    {
                        return(false);
                    }

                    AggregateSymbol aggIList         = loader.GetOptPredefAgg(PredefinedType.PT_G_ILIST);
                    AggregateSymbol aggIReadOnlyList = loader.GetOptPredefAgg(PredefinedType.PT_G_IREADONLYLIST);

                    if ((aggIList == null ||
                         !loader.IsBaseAggregate(aggIList, typeDst.AsAggregateType().getAggregate())) &&
                        (aggIReadOnlyList == null ||
                         !loader.IsBaseAggregate(aggIReadOnlyList, typeDst.AsAggregateType().getAggregate())))
                    {
                        return(false);
                    }

                    return(FExpRefConv(loader, typeSrc.AsArrayType().GetElementType(), typeDst.AsAggregateType().GetTypeArgsAll().Item(0)));
                }

                if (typeDst.IsArrayType() && typeSrc.IsAggregateType())
                {
                    // * From System.Array and the interfaces it implements, to any array-type.
                    if (loader.HasIdentityOrImplicitReferenceConversion(loader.GetReqPredefType(PredefinedType.PT_ARRAY), typeSrc))
                    {
                        return(true);
                    }

                    // *    From System.Collections.Generic.IList<T>, System.Collections.Generic.IReadOnlyList<T> and their base interfaces to a
                    //      one-dimensional array-type S[], provided there is an implicit or explicit reference conversion from S[] to
                    //      System.Collections.Generic.IList<T> or System.Collections.Generic.IReadOnlyList<T>. This is precisely when either S and T
                    //      are the same type or there is an implicit or explicit reference conversion from S to T.
                    ArrayType     arrayDest  = typeDst.AsArrayType();
                    AggregateType aggtypeSrc = typeSrc.AsAggregateType();
                    if (arrayDest.rank != 1 || !typeSrc.isInterfaceType() ||
                        aggtypeSrc.GetTypeArgsAll().Size != 1)
                    {
                        return(false);
                    }

                    AggregateSymbol aggIList         = loader.GetOptPredefAgg(PredefinedType.PT_G_ILIST);
                    AggregateSymbol aggIReadOnlyList = loader.GetOptPredefAgg(PredefinedType.PT_G_IREADONLYLIST);

                    if ((aggIList == null ||
                         !loader.IsBaseAggregate(aggIList, aggtypeSrc.getAggregate())) &&
                        (aggIReadOnlyList == null ||
                         !loader.IsBaseAggregate(aggIReadOnlyList, aggtypeSrc.getAggregate())))
                    {
                        return(false);
                    }

                    CType typeArr = arrayDest.GetElementType();
                    CType typeLst = aggtypeSrc.GetTypeArgsAll().Item(0);

                    Debug.Assert(!typeArr.IsNeverSameType());
                    return(typeArr == typeLst || FExpRefConv(loader, typeArr, typeLst));
                }
                if (HasGenericDelegateExplicitReferenceConversion(loader, typeSrc, typeDst))
                {
                    return(true);
                }
            }
            else if (typeSrc.IsRefType())
            {
                // conversion of T . U, where T : class, U
                // .. these constraints implies where U : class
                return(loader.HasIdentityOrImplicitReferenceConversion(typeSrc, typeDst));
            }
            else if (typeDst.IsRefType())
            {
                // conversion of T . U, where U : class, T
                // .. these constraints implies where T : class
                return(loader.HasIdentityOrImplicitReferenceConversion(typeDst, typeSrc));
            }
            return(false);
        }
Example #13
0
        private bool HasArrayConversionToInterface(ArrayType pSource, CType pDest)
        {
            Debug.Assert(pSource != null);
            Debug.Assert(pDest != null);
            if (pSource.rank != 1)
            {
                return false;
            }
            if (!pDest.isInterfaceType())
            {
                return false;
            }

            // * From a single-dimensional array type S[] to IList<T> or IReadOnlyList<T> and their base
            //   interfaces, provided that there is an implicit identity or reference
            //   conversion from S to T.

            // We only have six interfaces to check. IList<T>, IReadOnlyList<T> and their bases:
            // * The base interface of IList<T> is ICollection<T>.
            // * The base interface of ICollection<T> is IEnumerable<T>.
            // * The base interface of IEnumerable<T> is IEnumerable.
            // * The base interface of IReadOnlyList<T> is IReadOnlyCollection<T>.
            // * The base interface of IReadOnlyCollection<T> is IEnumerable<T>.

            if (pDest.isPredefType(PredefinedType.PT_IENUMERABLE))
            {
                return true;
            }

            AggregateType atsDest = pDest.AsAggregateType();
            AggregateSymbol aggDest = pDest.getAggregate();
            if (!aggDest.isPredefAgg(PredefinedType.PT_G_ILIST) &&
                !aggDest.isPredefAgg(PredefinedType.PT_G_ICOLLECTION) &&
                !aggDest.isPredefAgg(PredefinedType.PT_G_IENUMERABLE) &&
                !aggDest.isPredefAgg(PredefinedType.PT_G_IREADONLYCOLLECTION) &&
                !aggDest.isPredefAgg(PredefinedType.PT_G_IREADONLYLIST))
            {
                return false;
            }

            Debug.Assert(atsDest.GetTypeArgsAll().Size == 1);

            CType pSourceElement = pSource.GetElementType();
            CType pDestTypeArgument = atsDest.GetTypeArgsAll().Item(0);
            return HasIdentityOrImplicitReferenceConversion(pSourceElement, pDestTypeArgument);
        }
Example #14
0
 private bool HasCovariantArrayConversion(ArrayType pSource, ArrayType pDest)
 {
     Debug.Assert(pSource != null);
     Debug.Assert(pDest != null);
     // * S and T differ only in element type. In other words, S and T have the same number of dimensions.
     // * Both SE and TE are reference types.
     // * An implicit reference conversion exists from SE to TE.
     return (pSource.rank == pDest.rank) &&
         HasImplicitReferenceConversion(pSource.GetElementType(), pDest.GetElementType());
 }