private static IEnumerable <AggregateType> AllPossibleInterfaces(TypeParameterType type) { foreach (AggregateType t in type.GetEffectiveBaseClass().TypeAndBaseClassInterfaces()) { yield return(t); } foreach (AggregateType t in type.GetInterfaceBounds().AllConstraintInterfaces()) { yield return(t); } }
private bool HasImplicitReferenceTypeParameterConversion( TypeParameterType pSource, CType pDest) { Debug.Assert(pSource != null); Debug.Assert(pDest != null); if (!pSource.IsRefType()) { // Not a reference conversion. return(false); } // The following implicit conversions exist for a given type parameter T: // // * From T to its effective base class C. AggregateType pEBC = pSource.GetEffectiveBaseClass(); if (pDest == pEBC) { return(true); } // * From T to any base class of C. if (IsBaseClass(pEBC, pDest)) { return(true); } // * From T to any interface implemented by C. if (IsBaseInterface(pEBC, pDest)) { return(true); } // * From T to any interface type I in T's effective interface set, and // from T to any base interface of I. TypeArray pInterfaces = pSource.GetInterfaceBounds(); for (int i = 0; i < pInterfaces.Count; ++i) { if (pInterfaces[i] == pDest) { return(true); } } // * From T to a type parameter U, provided T depends on U. if (pDest.IsTypeParameterType() && pSource.DependsOn(pDest.AsTypeParameterType())) { return(true); } return(false); }
private bool HasImplicitBoxingTypeParameterConversion( TypeParameterType pSource, CType pDest) { Debug.Assert(pSource != null); Debug.Assert(pDest != null); if (pSource.IsRefType()) { // Not a boxing conversion; both source and destination are references. return(false); } // The following implicit conversions exist for a given type parameter T: // // * From T to its effective base class C. AggregateType pEBC = pSource.GetEffectiveBaseClass(); if (pDest == pEBC) { return(true); } // * From T to any base class of C. if (IsBaseClass(pEBC, pDest)) { return(true); } // * From T to any interface implemented by C. if (IsBaseInterface(pEBC, pDest)) { return(true); } // * From T to any interface type I in T's effective interface set, and // from T to any base interface of I. TypeArray pInterfaces = pSource.GetInterfaceBounds(); for (int i = 0; i < pInterfaces.Count; ++i) { if (pInterfaces[i] == pDest) { return(true); } } // * The conversion from T to a type parameter U, provided T depends on U, is not // classified as a boxing conversion because it is not guaranteed to box. // (If both T and U are value types then it is an identity conversion.) return(false); }
private bool bindImplicitConversionFromTypeVar(TypeParameterType tyVarSrc) { // 13.1.4 // // For a type-parameter T that is known to be a reference type (25.7), the following implicit // reference conversions exist: // // * From T to its effective base class C, from T to any base class of C, and from T to any // interface implemented by C. // * From T to an interface-type I in T's effective interface set and from T to any base // interface of I. // * From T to a type parameter U 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.] // * From the null type (11.2.7) to T. // // 13.1.5 // // For a type-parameter T that is not known to be a reference type (25.7), the following conversions // involving T are considered to be boxing conversions at compile-time. At run-time, if T is a value // type, the conversion is executed as a boxing conversion. At run-time, if T is a reference type, // the conversion is executed as an implicit reference conversion or identity conversion. // // * From T to its effective base class C, from T to any base class of C, and from T to any // interface implemented by C. [Note: C will be one of the types System.Object, System.ValueType, // or System.Enum (otherwise T would be known to be a reference type and 13.1.4 would apply // instead of this clause).] // * From T to an interface-type I in T's effective interface set and from T to any base // interface of I. // // 13.1.6 Implicit type parameter conversions // // This clause details implicit conversions involving type parameters that are not classified as // implicit reference conversions or implicit boxing conversions. // // For a type-parameter T that is not known to be a reference type, there is an implicit conversion // from T to a type parameter U provided T depends on U. At run-time, if T is a value type and U is // a reference type, the conversion is executed as a boxing conversion. At run-time, if both T and U // are value types, then T and U are necessarily the same type and no conversion is performed. At // run-time, if T is a reference type, then U is necessarily also a reference type and the conversion // is executed as an implicit reference conversion or identity conversion (25.7). CType typeTmp = tyVarSrc.GetEffectiveBaseClass(); TypeArray bnds = tyVarSrc.GetBounds(); int itype = -1; for (; ;) { if (binder.canConvert(typeTmp, typeDest, flags | CONVERTTYPE.NOUDC)) { if (!needsExprDest) { return(true); } if (typeDest.IsTypeParameterType()) { // For a type var destination we need to cast to object then to the other type var. EXPR exprT; EXPRCLASS exprObj = GetExprFactory().MakeClass(binder.GetReqPDT(PredefinedType.PT_OBJECT)); binder.bindSimpleCast(exprSrc, exprObj, out exprT, EXPRFLAG.EXF_FORCE_BOX); binder.bindSimpleCast(exprT, exprTypeDest, out exprDest, EXPRFLAG.EXF_FORCE_UNBOX); } else { binder.bindSimpleCast(exprSrc, exprTypeDest, out exprDest, EXPRFLAG.EXF_FORCE_BOX); } return(true); } do { if (++itype >= bnds.Size) { return(false); } typeTmp = bnds.Item(itype); }while (!typeTmp.isInterfaceType() && !typeTmp.IsTypeParameterType()); } }
private bool HasImplicitBoxingTypeParameterConversion( TypeParameterType pSource, CType pDest) { Debug.Assert(pSource != null); Debug.Assert(pDest != null); if (pSource.IsRefType()) { // Not a boxing conversion; both source and destination are references. return false; } // The following implicit conversions exist for a given type parameter T: // // * From T to its effective base class C. AggregateType pEBC = pSource.GetEffectiveBaseClass(); if (pDest == pEBC) { return true; } // * From T to any base class of C. if (IsBaseClass(pEBC, pDest)) { return true; } // * From T to any interface implemented by C. if (IsBaseInterface(pEBC, pDest)) { return true; } // * From T to any interface type I in T's effective interface set, and // from T to any base interface of I. TypeArray pInterfaces = pSource.GetInterfaceBounds(); for (int i = 0; i < pInterfaces.Size; ++i) { if (pInterfaces.Item(i) == pDest) { return true; } } // * The conversion from T to a type parameter U, provided T depends on U, is not // classified as a boxing conversion because it is not guaranteed to box. // (If both T and U are value types then it is an identity conversion.) return false; }
private bool HasImplicitReferenceTypeParameterConversion( TypeParameterType pSource, CType pDest) { Debug.Assert(pSource != null); Debug.Assert(pDest != null); if (!pSource.IsRefType()) { // Not a reference conversion. return false; } // The following implicit conversions exist for a given type parameter T: // // * From T to its effective base class C. AggregateType pEBC = pSource.GetEffectiveBaseClass(); if (pDest == pEBC) { return true; } // * From T to any base class of C. if (IsBaseClass(pEBC, pDest)) { return true; } // * From T to any interface implemented by C. if (IsBaseInterface(pEBC, pDest)) { return true; } // * From T to any interface type I in T's effective interface set, and // from T to any base interface of I. TypeArray pInterfaces = pSource.GetInterfaceBounds(); for (int i = 0; i < pInterfaces.Size; ++i) { if (pInterfaces.Item(i) == pDest) { return true; } } // * From T to a type parameter U, provided T depends on U. if (pDest.IsTypeParameterType() && pSource.DependsOn(pDest.AsTypeParameterType())) { return true; } return false; }
private bool bindImplicitConversionFromTypeVar(TypeParameterType tyVarSrc) { // 13.1.4 // // For a type-parameter T that is known to be a reference type (25.7), the following implicit // reference conversions exist: // // * From T to its effective base class C, from T to any base class of C, and from T to any // interface implemented by C. // * From T to an interface-type I in T's effective interface set and from T to any base // interface of I. // * From T to a type parameter U 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.] // * From the null type (11.2.7) to T. // // 13.1.5 // // For a type-parameter T that is not known to be a reference type (25.7), the following conversions // involving T are considered to be boxing conversions at compile-time. At run-time, if T is a value // type, the conversion is executed as a boxing conversion. At run-time, if T is a reference type, // the conversion is executed as an implicit reference conversion or identity conversion. // // * From T to its effective base class C, from T to any base class of C, and from T to any // interface implemented by C. [Note: C will be one of the types System.Object, System.ValueType, // or System.Enum (otherwise T would be known to be a reference type and 13.1.4 would apply // instead of this clause).] // * From T to an interface-type I in T's effective interface set and from T to any base // interface of I. // // 13.1.6 Implicit type parameter conversions // // This clause details implicit conversions involving type parameters that are not classified as // implicit reference conversions or implicit boxing conversions. // // For a type-parameter T that is not known to be a reference type, there is an implicit conversion // from T to a type parameter U provided T depends on U. At run-time, if T is a value type and U is // a reference type, the conversion is executed as a boxing conversion. At run-time, if both T and U // are value types, then T and U are necessarily the same type and no conversion is performed. At // run-time, if T is a reference type, then U is necessarily also a reference type and the conversion // is executed as an implicit reference conversion or identity conversion (25.7). CType typeTmp = tyVarSrc.GetEffectiveBaseClass(); TypeArray bnds = tyVarSrc.GetBounds(); int itype = -1; for (; ;) { if (_binder.canConvert(typeTmp, _typeDest, _flags | CONVERTTYPE.NOUDC)) { if (!_needsExprDest) { return true; } if (_typeDest.IsTypeParameterType()) { // For a type var destination we need to cast to object then to the other type var. EXPR exprT; EXPRCLASS exprObj = GetExprFactory().MakeClass(_binder.GetReqPDT(PredefinedType.PT_OBJECT)); _binder.bindSimpleCast(_exprSrc, exprObj, out exprT, EXPRFLAG.EXF_FORCE_BOX); _binder.bindSimpleCast(exprT, _exprTypeDest, out _exprDest, EXPRFLAG.EXF_FORCE_UNBOX); } else { _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, EXPRFLAG.EXF_FORCE_BOX); } return true; } do { if (++itype >= bnds.Size) { return false; } typeTmp = bnds.Item(itype); } while (!typeTmp.isInterfaceType() && !typeTmp.IsTypeParameterType()); } }