public virtual ACCESSERROR CheckAccess2(Symbol symCheck, AggregateType atsCheck, Symbol symWhere, CType typeThru) { Debug.Assert(symCheck != null); Debug.Assert(atsCheck == null || symCheck.parent == atsCheck.getAggregate()); Debug.Assert(typeThru == null || typeThru.IsAggregateType() || typeThru.IsTypeParameterType() || typeThru.IsArrayType() || typeThru.IsNullableType() || typeThru.IsErrorType()); #if DEBUG switch (symCheck.getKind()) { default: break; case SYMKIND.SK_MethodSymbol: case SYMKIND.SK_PropertySymbol: case SYMKIND.SK_FieldSymbol: case SYMKIND.SK_EventSymbol: Debug.Assert(atsCheck != null); break; } #endif // DEBUG ACCESSERROR error = CheckAccessCore(symCheck, atsCheck, symWhere, typeThru); if (ACCESSERROR.ACCESSERROR_NOERROR != error) { return error; } // Check the accessibility of the return CType. CType CType = symCheck.getType(); if (CType == null) { return ACCESSERROR.ACCESSERROR_NOERROR; } // For members of AGGSYMs, atsCheck should always be specified! Debug.Assert(atsCheck != null); if (atsCheck.getAggregate().IsSource()) { // We already check the "at least as accessible as" rules. // Does this always work for generics? // Could we get a bad CType argument in typeThru? // Maybe call CheckTypeAccess on typeThru? return ACCESSERROR.ACCESSERROR_NOERROR; } // Substitute on the CType. if (atsCheck.GetTypeArgsAll().size > 0) { CType = SymbolLoader.GetTypeManager().SubstType(CType, atsCheck); } return CheckTypeAccess(CType, symWhere) ? ACCESSERROR.ACCESSERROR_NOERROR : ACCESSERROR.ACCESSERROR_NOACCESS; }
////////////////////////////////////////////////////////////////////////////// private bool HasVariantConversion(AggregateType pSource, AggregateType pDest) { Debug.Assert(pSource != null); Debug.Assert(pDest != null); if (pSource == pDest) { return(true); } AggregateSymbol pAggSym = pSource.getAggregate(); if (pAggSym != pDest.getAggregate()) { return(false); } TypeArray pTypeParams = pAggSym.GetTypeVarsAll(); TypeArray pSourceArgs = pSource.GetTypeArgsAll(); TypeArray pDestArgs = pDest.GetTypeArgsAll(); Debug.Assert(pTypeParams.Count == pSourceArgs.Count); Debug.Assert(pTypeParams.Count == pDestArgs.Count); for (int iParam = 0; iParam < pTypeParams.Count; ++iParam) { CType pSourceArg = pSourceArgs[iParam]; CType pDestArg = pDestArgs[iParam]; // If they're identical then this one is automatically good, so skip it. if (pSourceArg == pDestArg) { continue; } TypeParameterType pParam = (TypeParameterType)pTypeParams[iParam]; if (pParam.Invariant) { return(false); } if (pParam.Covariant) { if (!HasImplicitReferenceConversion(pSourceArg, pDestArg)) { return(false); } } if (pParam.Contravariant) { if (!HasImplicitReferenceConversion(pDestArg, pSourceArg)) { return(false); } } } return(true); }
public virtual ACCESSERROR CheckAccess2(Symbol symCheck, AggregateType atsCheck, Symbol symWhere, CType typeThru) { Debug.Assert(symCheck != null); Debug.Assert(atsCheck == null || symCheck.parent == atsCheck.getAggregate()); Debug.Assert(typeThru == null || typeThru.IsAggregateType() || typeThru.IsTypeParameterType() || typeThru.IsArrayType() || typeThru.IsNullableType() || typeThru.IsErrorType()); #if DEBUG switch (symCheck.getKind()) { default: break; case SYMKIND.SK_MethodSymbol: case SYMKIND.SK_PropertySymbol: case SYMKIND.SK_FieldSymbol: case SYMKIND.SK_EventSymbol: Debug.Assert(atsCheck != null); break; } #endif // DEBUG ACCESSERROR error = CheckAccessCore(symCheck, atsCheck, symWhere, typeThru); if (ACCESSERROR.ACCESSERROR_NOERROR != error) { return(error); } // Check the accessibility of the return CType. CType CType = symCheck.getType(); if (CType == null) { return(ACCESSERROR.ACCESSERROR_NOERROR); } // For members of AGGSYMs, atsCheck should always be specified! Debug.Assert(atsCheck != null); // Substitute on the CType. if (atsCheck.GetTypeArgsAll().Count > 0) { CType = SymbolLoader.GetTypeManager().SubstType(CType, atsCheck); } return(CheckTypeAccess(CType, symWhere) ? ACCESSERROR.ACCESSERROR_NOERROR : ACCESSERROR.ACCESSERROR_NOACCESS); }
private AggregateType SubstTypeCore(AggregateType type, SubstContext ctx) { TypeArray args = type.GetTypeArgsAll(); if (args.Count > 0) { TypeArray typeArgs = SubstTypeArray(args, ctx); if (args != typeArgs) { return(GetAggregate(type.getAggregate(), typeArgs)); } } return(type); }
public AggregateType GetBaseClass() { #if CSEE AggregateType atsBase = getAggregate().GetBaseClass(); if (!atsBase || GetTypeArgsAll().size == 0 || atsBase.GetTypeArgsAll().size == 0) return atsBase; return getAggregate().GetTypeManager().SubstType(atsBase, GetTypeArgsAll()).AsAggregateType(); #else // !CSEE if (_baseType == null) { _baseType = getAggregate().GetTypeManager().SubstType(getAggregate().GetBaseClass(), GetTypeArgsAll()) as AggregateType; } return _baseType; #endif // !CSEE }
public AggregateType GetAggregate(AggregateSymbol agg, AggregateType atsOuter, TypeArray typeArgs) { Debug.Assert(agg.GetTypeManager() == this); Debug.Assert(atsOuter == null || atsOuter.getAggregate() == agg.Parent, ""); if (typeArgs == null) { typeArgs = BSYMMGR.EmptyTypeArray(); } Debug.Assert(agg.GetTypeVars().Count == typeArgs.Count); AggregateType pAggregate = _typeTable.LookupAggregate(agg, atsOuter, typeArgs); if (pAggregate == null) { pAggregate = _typeFactory.CreateAggregateType( agg, typeArgs, atsOuter ); Debug.Assert(!pAggregate.fConstraintsChecked && !pAggregate.fConstraintError); pAggregate.SetErrors(false); _typeTable.InsertAggregate(agg, atsOuter, typeArgs, pAggregate); } else { Debug.Assert(!pAggregate.HasErrors()); } Debug.Assert(pAggregate.getAggregate() == agg); Debug.Assert(pAggregate.GetTypeArgsThis() != null && pAggregate.GetTypeArgsAll() != null); Debug.Assert(pAggregate.GetTypeArgsThis() == typeArgs); return(pAggregate); }
private CType SubstTypeCore(CType type, SubstContext pctx) { CType typeSrc; CType typeDst; switch (type.GetTypeKind()) { default: Debug.Assert(false); return(type); case TypeKind.TK_NullType: case TypeKind.TK_VoidType: case TypeKind.TK_MethodGroupType: case TypeKind.TK_ArgumentListType: return(type); case TypeKind.TK_ParameterModifierType: ParameterModifierType mod = (ParameterModifierType)type; typeDst = SubstTypeCore(typeSrc = mod.GetParameterType(), pctx); return((typeDst == typeSrc) ? type : GetParameterModifier(typeDst, mod.isOut)); case TypeKind.TK_ArrayType: var arr = (ArrayType)type; typeDst = SubstTypeCore(typeSrc = arr.GetElementType(), pctx); return((typeDst == typeSrc) ? type : GetArray(typeDst, arr.rank, arr.IsSZArray)); case TypeKind.TK_PointerType: typeDst = SubstTypeCore(typeSrc = ((PointerType)type).GetReferentType(), pctx); return((typeDst == typeSrc) ? type : GetPointer(typeDst)); case TypeKind.TK_NullableType: typeDst = SubstTypeCore(typeSrc = ((NullableType)type).GetUnderlyingType(), pctx); return((typeDst == typeSrc) ? type : GetNullable(typeDst)); case TypeKind.TK_AggregateType: AggregateType ats = (AggregateType)type; if (ats.GetTypeArgsAll().Count > 0) { TypeArray typeArgs = SubstTypeArray(ats.GetTypeArgsAll(), pctx); if (ats.GetTypeArgsAll() != typeArgs) { return(GetAggregate(ats.getAggregate(), typeArgs)); } } return(type); case TypeKind.TK_ErrorType: ErrorType err = (ErrorType)type; if (err.HasParent) { Debug.Assert(err.nameText != null && err.typeArgs != null); TypeArray typeArgs = SubstTypeArray(err.typeArgs, pctx); if (typeArgs != err.typeArgs) { return(GetErrorType(err.nameText, typeArgs)); } } return(type); case TypeKind.TK_TypeParameterType: { TypeParameterSymbol tvs = ((TypeParameterType)type).GetTypeParameterSymbol(); int index = tvs.GetIndexInTotalParameters(); if (tvs.IsMethodTypeParameter()) { if ((pctx.grfst & SubstTypeFlags.DenormMeth) != 0 && tvs.parent != null) { return(type); } Debug.Assert(tvs.GetIndexInOwnParameters() == tvs.GetIndexInTotalParameters()); if (index < pctx.ctypeMeth) { Debug.Assert(pctx.prgtypeMeth != null); return(pctx.prgtypeMeth[index]); } else { return((pctx.grfst & SubstTypeFlags.NormMeth) != 0 ? GetStdMethTypeVar(index) : type); } } if ((pctx.grfst & SubstTypeFlags.DenormClass) != 0 && tvs.parent != null) { return(type); } return(index < pctx.ctypeCls ? pctx.prgtypeCls[index] : ((pctx.grfst & SubstTypeFlags.NormClass) != 0 ? GetStdClsTypeVar(index) : type)); } } }
//////////////////////////////////////////////////////////////////////////////// private void ExactTypeArgumentInference( AggregateType pSource, AggregateType pDest) { Debug.Assert(pSource != null); Debug.Assert(pDest != null); Debug.Assert(pSource.GetOwningAggregate() == pDest.GetOwningAggregate()); TypeArray pSourceArgs = pSource.GetTypeArgsAll(); TypeArray pDestArgs = pDest.GetTypeArgsAll(); Debug.Assert(pSourceArgs != null); Debug.Assert(pDestArgs != null); Debug.Assert(pSourceArgs.size == pDestArgs.size); for (int arg = 0; arg < pSourceArgs.size; ++arg) { ExactInference(pSourceArgs.Item(arg), pDestArgs.Item(arg)); } }
private static Type CalculateAssociatedSystemTypeForAggregate(AggregateType aggtype) { AggregateSymbol agg = aggtype.GetOwningAggregate(); TypeArray typeArgs = aggtype.GetTypeArgsAll(); List<Type> list = new List<Type>(); // Get each type arg. for (int i = 0; i < typeArgs.size; i++) { // Unnamed type parameter types are just placeholders. if (typeArgs.Item(i).IsTypeParameterType() && typeArgs.Item(i).AsTypeParameterType().GetTypeParameterSymbol().name == null) { return null; } list.Add(typeArgs.Item(i).AssociatedSystemType); } Type[] systemTypeArgs = list.ToArray(); Type uninstantiatedType = agg.AssociatedSystemType; if (uninstantiatedType.GetTypeInfo().IsGenericType) { try { return uninstantiatedType.MakeGenericType(systemTypeArgs); } catch (ArgumentException) { // If the constraints don't work, just return the type without substituting it. return uninstantiatedType; } } return uninstantiatedType; }
public TypeArray SubstTypeArray(TypeArray taSrc, AggregateType atsCls, TypeArray typeArgsMeth) { return(SubstTypeArray(taSrc, atsCls?.GetTypeArgsAll(), typeArgsMeth)); }
public static bool TypeContainsTyVars(CType type, TypeArray typeVars) { LRecurse: // Label used for "tail" recursion. switch (type.GetTypeKind()) { default: Debug.Assert(false, "Bad Symbol kind in TypeContainsTyVars"); return(false); case TypeKind.TK_NullType: case TypeKind.TK_VoidType: case TypeKind.TK_MethodGroupType: return(false); case TypeKind.TK_ArrayType: case TypeKind.TK_NullableType: case TypeKind.TK_ParameterModifierType: case TypeKind.TK_PointerType: type = type.GetBaseOrParameterOrElementType(); goto LRecurse; case TypeKind.TK_AggregateType: { // BLOCK AggregateType ats = (AggregateType)type; for (int i = 0; i < ats.GetTypeArgsAll().Count; i++) { if (TypeContainsTyVars(ats.GetTypeArgsAll()[i], typeVars)) { return(true); } } } return(false); case TypeKind.TK_ErrorType: ErrorType err = (ErrorType)type; if (err.HasParent) { Debug.Assert(err.nameText != null && err.typeArgs != null); for (int i = 0; i < err.typeArgs.Count; i++) { if (TypeContainsTyVars(err.typeArgs[i], typeVars)) { return(true); } } } return(false); case TypeKind.TK_TypeParameterType: if (typeVars != null && typeVars.Count > 0) { int ivar = ((TypeParameterType)type).GetIndexInTotalParameters(); return(ivar < typeVars.Count && type == typeVars[ivar]); } return(true); } }
////////////////////////////////////////////////////////////////////////////// private bool HasVariantConversion(AggregateType pSource, AggregateType pDest) { Debug.Assert(pSource != null); Debug.Assert(pDest != null); if (pSource == pDest) { return true; } AggregateSymbol pAggSym = pSource.getAggregate(); if (pAggSym != pDest.getAggregate()) { return false; } TypeArray pTypeParams = pAggSym.GetTypeVarsAll(); TypeArray pSourceArgs = pSource.GetTypeArgsAll(); TypeArray pDestArgs = pDest.GetTypeArgsAll(); Debug.Assert(pTypeParams.size == pSourceArgs.size); Debug.Assert(pTypeParams.size == pDestArgs.size); for (int iParam = 0; iParam < pTypeParams.size; ++iParam) { CType pSourceArg = pSourceArgs.Item(iParam); CType pDestArg = pDestArgs.Item(iParam); // If they're identical then this one is automatically good, so skip it. if (pSourceArg == pDestArg) { continue; } TypeParameterType pParam = pTypeParams.Item(iParam).AsTypeParameterType(); if (pParam.Invariant) { return false; } if (pParam.Covariant) { if (!HasImplicitReferenceConversion(pSourceArg, pDestArg)) { return false; } } if (pParam.Contravariant) { if (!HasImplicitReferenceConversion(pDestArg, pSourceArg)) { return false; } } } return true; }
// Check the constraints of any type arguments in the given Type. public static bool CheckConstraints(CSemanticChecker checker, ErrorHandling errHandling, CType type, CheckConstraintsFlags flags) { type = type.GetNakedType(false); if (type.IsNullableType()) { CType typeT = type.AsNullableType().GetAts(checker.GetErrorContext()); if (typeT != null) { type = typeT; } else { type = type.GetNakedType(true); } } if (!type.IsAggregateType()) { return(true); } AggregateType ats = type.AsAggregateType(); if (ats.GetTypeArgsAll().Count == 0) { // Common case: there are no type vars, so there are no constraints. ats.fConstraintsChecked = true; ats.fConstraintError = false; return(true); } if (ats.fConstraintsChecked) { // Already checked. if (!ats.fConstraintError || (flags & CheckConstraintsFlags.NoDupErrors) != 0) { // No errors or no need to report errors again. return(!ats.fConstraintError); } } TypeArray typeVars = ats.getAggregate().GetTypeVars(); TypeArray typeArgsThis = ats.GetTypeArgsThis(); TypeArray typeArgsAll = ats.GetTypeArgsAll(); Debug.Assert(typeVars.Count == typeArgsThis.Count); if (!ats.fConstraintsChecked) { ats.fConstraintsChecked = true; ats.fConstraintError = false; } // Check the outer type first. If CheckConstraintsFlags.Outer is not specified and the // outer type has already been checked then don't bother checking it. if (ats.outerType != null && ((flags & CheckConstraintsFlags.Outer) != 0 || !ats.outerType.fConstraintsChecked)) { CheckConstraints(checker, errHandling, ats.outerType, flags); ats.fConstraintError |= ats.outerType.fConstraintError; } if (typeVars.Count > 0) { ats.fConstraintError |= !CheckConstraintsCore(checker, errHandling, ats.getAggregate(), typeVars, typeArgsThis, typeArgsAll, null, (flags & CheckConstraintsFlags.NoErrors)); } // Now check type args themselves. for (int i = 0; i < typeArgsThis.Count; i++) { CType arg = typeArgsThis[i].GetNakedType(true); if (arg.IsAggregateType() && !arg.AsAggregateType().fConstraintsChecked) { CheckConstraints(checker, errHandling, arg.AsAggregateType(), flags | CheckConstraintsFlags.Outer); if (arg.AsAggregateType().fConstraintError) { ats.fConstraintError = true; } } } return(!ats.fConstraintError); }
private bool IsDelegateType(CType pSrcType, AggregateType pAggType) { CType pInstantiatedType = GetSymbolLoader().GetTypeManager().SubstType(pSrcType, pAggType, pAggType.GetTypeArgsAll()); return pInstantiatedType.isDelegateType(); }
public SubstContext(AggregateType type, TypeArray typeArgsMeth, SubstTypeFlags grfst) { Init(type != null ? type.GetTypeArgsAll() : null, typeArgsMeth, grfst); }
private bool SubstEqualTypesCore(CType typeDst, CType typeSrc, SubstContext pctx) { LRecurse: // Label used for "tail" recursion. if (typeDst == typeSrc || typeDst.Equals(typeSrc)) { return(true); } switch (typeSrc.GetTypeKind()) { default: Debug.Assert(false, "Bad Symbol kind in SubstEqualTypesCore"); return(false); case TypeKind.TK_NullType: case TypeKind.TK_VoidType: // There should only be a single instance of these. Debug.Assert(typeDst.GetTypeKind() != typeSrc.GetTypeKind()); return(false); case TypeKind.TK_ArrayType: ArrayType arrSrc = (ArrayType)typeSrc; if (!(typeDst is ArrayType arrDst) || arrDst.rank != arrSrc.rank || arrDst.IsSZArray != arrSrc.IsSZArray) { return(false); } goto LCheckBases; case TypeKind.TK_ParameterModifierType: if (!(typeDst is ParameterModifierType modDest) || ((pctx.grfst & SubstTypeFlags.NoRefOutDifference) == 0 && modDest.isOut != ((ParameterModifierType)typeSrc).isOut)) { return(false); } goto LCheckBases; case TypeKind.TK_PointerType: case TypeKind.TK_NullableType: if (typeDst.GetTypeKind() != typeSrc.GetTypeKind()) { return(false); } LCheckBases: typeSrc = typeSrc.GetBaseOrParameterOrElementType(); typeDst = typeDst.GetBaseOrParameterOrElementType(); goto LRecurse; case TypeKind.TK_AggregateType: if (!(typeDst is AggregateType atsDst)) { return(false); } { // BLOCK AggregateType atsSrc = (AggregateType)typeSrc; if (atsSrc.getAggregate() != atsDst.getAggregate()) { return(false); } Debug.Assert(atsSrc.GetTypeArgsAll().Count == atsDst.GetTypeArgsAll().Count); // All the args must unify. for (int i = 0; i < atsSrc.GetTypeArgsAll().Count; i++) { if (!SubstEqualTypesCore(atsDst.GetTypeArgsAll()[i], atsSrc.GetTypeArgsAll()[i], pctx)) { return(false); } } } return(true); case TypeKind.TK_ErrorType: ErrorType errSrc = (ErrorType)typeSrc; if (!(typeDst is ErrorType errDst) || !errSrc.HasParent || !errDst.HasParent) { return(false); } { Debug.Assert(errSrc.nameText != null && errSrc.typeArgs != null); Debug.Assert(errDst.nameText != null && errDst.typeArgs != null); if (errSrc.nameText != errDst.nameText || errSrc.typeArgs.Count != errDst.typeArgs.Count || errSrc.HasParent != errDst.HasParent) { return(false); } // All the args must unify. for (int i = 0; i < errSrc.typeArgs.Count; i++) { if (!SubstEqualTypesCore(errDst.typeArgs[i], errSrc.typeArgs[i], pctx)) { return(false); } } } return(true); case TypeKind.TK_TypeParameterType: { // BLOCK TypeParameterSymbol tvs = ((TypeParameterType)typeSrc).GetTypeParameterSymbol(); int index = tvs.GetIndexInTotalParameters(); if (tvs.IsMethodTypeParameter()) { if ((pctx.grfst & SubstTypeFlags.DenormMeth) != 0 && tvs.parent != null) { // typeDst == typeSrc was handled above. Debug.Assert(typeDst != typeSrc); return(false); } Debug.Assert(tvs.GetIndexInOwnParameters() == tvs.GetIndexInTotalParameters()); Debug.Assert(pctx.prgtypeMeth == null || tvs.GetIndexInTotalParameters() < pctx.ctypeMeth); if (index < pctx.ctypeMeth && pctx.prgtypeMeth != null) { return(typeDst == pctx.prgtypeMeth[index]); } if ((pctx.grfst & SubstTypeFlags.NormMeth) != 0) { return(typeDst == GetStdMethTypeVar(index)); } } else { if ((pctx.grfst & SubstTypeFlags.DenormClass) != 0 && tvs.parent != null) { // typeDst == typeSrc was handled above. Debug.Assert(typeDst != typeSrc); return(false); } Debug.Assert(pctx.prgtypeCls == null || tvs.GetIndexInTotalParameters() < pctx.ctypeCls); if (index < pctx.ctypeCls) { return(typeDst == pctx.prgtypeCls[index]); } if ((pctx.grfst & SubstTypeFlags.NormClass) != 0) { return(typeDst == GetStdClsTypeVar(index)); } } } return(false); } }
public static bool TypeContainsType(CType type, CType typeFind) { LRecurse: // Label used for "tail" recursion. if (type == typeFind || type.Equals(typeFind)) { return(true); } switch (type.GetTypeKind()) { default: Debug.Assert(false, "Bad Symbol kind in TypeContainsType"); return(false); case TypeKind.TK_NullType: case TypeKind.TK_VoidType: // There should only be a single instance of these. Debug.Assert(typeFind.GetTypeKind() != type.GetTypeKind()); return(false); case TypeKind.TK_ArrayType: case TypeKind.TK_NullableType: case TypeKind.TK_ParameterModifierType: case TypeKind.TK_PointerType: type = type.GetBaseOrParameterOrElementType(); goto LRecurse; case TypeKind.TK_AggregateType: { // BLOCK AggregateType ats = (AggregateType)type; for (int i = 0; i < ats.GetTypeArgsAll().Count; i++) { if (TypeContainsType(ats.GetTypeArgsAll()[i], typeFind)) { return(true); } } } return(false); case TypeKind.TK_ErrorType: ErrorType err = (ErrorType)type; if (err.HasParent) { Debug.Assert(err.nameText != null && err.typeArgs != null); for (int i = 0; i < err.typeArgs.Count; i++) { if (TypeContainsType(err.typeArgs[i], typeFind)) { return(true); } } } return(false); case TypeKind.TK_TypeParameterType: return(false); } }
/*************************************************************************************************** * 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 is TypeParameterType) { return(true); } if (typeSrc is TypeParameterType && 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 is AggregateType atSrc && typeDst is AggregateType atDst) { AggregateSymbol aggSrc = atSrc.getAggregate(); AggregateSymbol aggDest = atDst.getAggregate(); if ((aggSrc.IsClass() && !aggSrc.IsSealed() && aggDest.IsInterface()) || (aggSrc.IsInterface() && aggDest.IsClass() && !aggDest.IsSealed()) || (aggSrc.IsInterface() && aggDest.IsInterface())) { return(true); } } if (typeSrc is ArrayType arrSrc) { // * 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 (typeDst is ArrayType arrDst) { return(arrSrc.rank == arrDst.rank && arrSrc.IsSZArray == arrDst.IsSZArray && FExpRefConv(loader, arrSrc.GetElementType(), arrDst.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 (!arrSrc.IsSZArray || !typeDst.isInterfaceType()) { return(false); } AggregateType aggDst = (AggregateType)typeDst; TypeArray typeArgsAll = aggDst.GetTypeArgsAll(); if (typeArgsAll.Count != 1) { return(false); } AggregateSymbol aggIList = loader.GetPredefAgg(PredefinedType.PT_G_ILIST); AggregateSymbol aggIReadOnlyList = loader.GetPredefAgg(PredefinedType.PT_G_IREADONLYLIST); if ((aggIList == null || !SymbolLoader.IsBaseAggregate(aggIList, aggDst.getAggregate())) && (aggIReadOnlyList == null || !SymbolLoader.IsBaseAggregate(aggIReadOnlyList, aggDst.getAggregate()))) { return(false); } return(FExpRefConv(loader, arrSrc.GetElementType(), typeArgsAll[0])); } if (typeDst is ArrayType arrayDest && typeSrc is AggregateType aggtypeSrc) { // * From System.Array and the interfaces it implements, to any array-type. if (loader.HasIdentityOrImplicitReferenceConversion(loader.GetPredefindType(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. if (!arrayDest.IsSZArray || !typeSrc.isInterfaceType() || aggtypeSrc.GetTypeArgsAll().Count != 1) { return(false); } AggregateSymbol aggIList = loader.GetPredefAgg(PredefinedType.PT_G_ILIST); AggregateSymbol aggIReadOnlyList = loader.GetPredefAgg(PredefinedType.PT_G_IREADONLYLIST); if ((aggIList == null || !SymbolLoader.IsBaseAggregate(aggIList, aggtypeSrc.getAggregate())) && (aggIReadOnlyList == null || !SymbolLoader.IsBaseAggregate(aggIReadOnlyList, aggtypeSrc.getAggregate()))) { return(false); } CType typeArr = arrayDest.GetElementType(); CType typeLst = aggtypeSrc.GetTypeArgsAll()[0]; Debug.Assert(!(typeArr is MethodGroupType)); 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); }
public CType SubstType(CType typeSrc, AggregateType atsCls, TypeArray typeArgsMeth) { return(SubstType(typeSrc, atsCls?.GetTypeArgsAll(), typeArgsMeth)); }
public CType SubstType(CType typeSrc, AggregateType atsCls, TypeArray typeArgsMeth) { return SubstType(typeSrc, atsCls != null ? atsCls.GetTypeArgsAll() : null, typeArgsMeth); }
public TypeArray SubstTypeArray(TypeArray taSrc, AggregateType atsCls, TypeArray typeArgsMeth) { return SubstTypeArray(taSrc, atsCls != null ? atsCls.GetTypeArgsAll() : null, typeArgsMeth); }
private SubstContext(AggregateType type, TypeArray typeArgsMeth, SubstTypeFlags grfst) { Init(type?.GetTypeArgsAll(), typeArgsMeth, grfst); }
public NullableType GetNubFromNullable(AggregateType ats) { Debug.Assert(ats.isPredefType(PredefinedType.PT_G_OPTIONAL)); return GetNullable(ats.GetTypeArgsAll().Item(0)); }
//////////////////////////////////////////////////////////////////////////////// private void UpperBoundTypeArgumentInference( AggregateType pSource, AggregateType pDest) { // SPEC: The choice of inference for the i-th CType argument is made // SPEC: based on the declaration of the i-th CType parameter of C, as // SPEC: follows: // SPEC: if Ui is known to be of reference CType and the i-th CType parameter // SPEC: was declared as covariant then an upper-bound inference is made. // SPEC: if Ui is known to be of reference CType and the i-th CType parameter // SPEC: was declared as contravariant then a lower-bound inference is made. // SPEC: otherwise, an exact inference is made. Debug.Assert(pSource != null); Debug.Assert(pDest != null); Debug.Assert(pSource.GetOwningAggregate() == pDest.GetOwningAggregate()); TypeArray pTypeParams = pSource.GetOwningAggregate().GetTypeVarsAll(); TypeArray pSourceArgs = pSource.GetTypeArgsAll(); TypeArray pDestArgs = pDest.GetTypeArgsAll(); Debug.Assert(pTypeParams != null); Debug.Assert(pSourceArgs != null); Debug.Assert(pDestArgs != null); Debug.Assert(pTypeParams.size == pSourceArgs.size); Debug.Assert(pTypeParams.size == pDestArgs.size); for (int arg = 0; arg < pSourceArgs.size; ++arg) { TypeParameterType pTypeParam = pTypeParams.ItemAsTypeParameterType(arg); CType pSourceArg = pSourceArgs.Item(arg); CType pDestArg = pDestArgs.Item(arg); if (pSourceArg.IsRefType() && pTypeParam.Covariant) { UpperBoundInference(pSourceArg, pDestArg); } else if (pSourceArg.IsRefType() && pTypeParam.Contravariant) { LowerBoundInference(pSourceArgs.Item(arg), pDestArgs.Item(arg)); } else { ExactInference(pSourceArgs.Item(arg), pDestArgs.Item(arg)); } } }
public AggregateType GetAggregate(AggregateSymbol agg, AggregateType atsOuter, TypeArray typeArgs) { Debug.Assert(agg.GetTypeManager() == this); Debug.Assert(atsOuter == null || atsOuter.getAggregate() == agg.Parent, ""); if (typeArgs == null) { typeArgs = BSYMMGR.EmptyTypeArray(); } Debug.Assert(agg.GetTypeVars().Count == typeArgs.Count); Name name = _BSymmgr.GetNameFromPtrs(typeArgs, atsOuter); Debug.Assert(name != null); AggregateType pAggregate = _typeTable.LookupAggregate(name, agg); if (pAggregate == null) { pAggregate = _typeFactory.CreateAggregateType( name, agg, typeArgs, atsOuter ); Debug.Assert(!pAggregate.fConstraintsChecked && !pAggregate.fConstraintError); pAggregate.SetErrors(false); _typeTable.InsertAggregate(name, agg, pAggregate); // If we have a generic type definition, then we need to set the // base class to be our current base type, and use that to calculate // our agg type and its base, then set it to be the generic version of the // base type. This is because: // // Suppose we have Foo<T> : IFoo<T> // // Initially, the BaseType will be IFoo<Foo.T>, which gives us the substitution // that we want to use for our agg type's base type. However, in the Symbol chain, // we want the base type to be IFoo<IFoo.T>. Thats why we need to do this little trick. // // If we don't have a generic type definition, then we just need to set our base // class. This is so that if we have a base type that's generic, we'll be // getting the correctly instantiated base type. var baseType = pAggregate.AssociatedSystemType?.BaseType; if (baseType != null) { // Store the old base class. AggregateType oldBaseType = agg.GetBaseClass(); agg.SetBaseClass(_symbolTable.GetCTypeFromType(baseType) as AggregateType); pAggregate.GetBaseClass(); // Get the base type for the new agg type we're making. agg.SetBaseClass(oldBaseType); } } else { Debug.Assert(!pAggregate.HasErrors()); } Debug.Assert(pAggregate.getAggregate() == agg); Debug.Assert(pAggregate.GetTypeArgsThis() != null && pAggregate.GetTypeArgsAll() != null); Debug.Assert(pAggregate.GetTypeArgsThis() == typeArgs); return(pAggregate); }
private bool IsDelegateType(CType pSrcType, AggregateType pAggType) { CType pInstantiatedType = GetSymbolLoader().GetTypeManager().SubstType(pSrcType, pAggType, pAggType.GetTypeArgsAll()); return(pInstantiatedType.isDelegateType()); }
public NullableType GetNubFromNullable(AggregateType ats) { Debug.Assert(ats.isPredefType(PredefinedType.PT_G_OPTIONAL)); return(GetNullable(ats.GetTypeArgsAll()[0])); }