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); } }
private CType SubstTypeCore(CType type, SubstContext pctx) { CType typeSrc; CType typeDst; switch (type.TypeKind) { 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.ParameterType, pctx); return((typeDst == typeSrc) ? type : GetParameterModifier(typeDst, mod.IsOut)); case TypeKind.TK_ArrayType: var arr = (ArrayType)type; typeDst = SubstTypeCore(typeSrc = arr.ElementType, pctx); return((typeDst == typeSrc) ? type : GetArray(typeDst, arr.Rank, arr.IsSZArray)); case TypeKind.TK_PointerType: typeDst = SubstTypeCore(typeSrc = ((PointerType)type).ReferentType, pctx); return((typeDst == typeSrc) ? type : GetPointer(typeDst)); case TypeKind.TK_NullableType: typeDst = SubstTypeCore(typeSrc = ((NullableType)type).UnderlyingType, pctx); return((typeDst == typeSrc) ? type : GetNullable(typeDst)); case TypeKind.TK_AggregateType: return(SubstTypeCore((AggregateType)type, pctx)); case TypeKind.TK_TypeParameterType: { TypeParameterSymbol tvs = ((TypeParameterType)type).Symbol; 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 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 bool SubstEqualTypesCore(CType typeDst, CType typeSrc, SubstContext pctx) { LRecurse: // Label used for "tail" recursion. if (typeDst == typeSrc || typeDst.Equals(typeSrc)) { return(true); } switch (typeSrc.TypeKind) { 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.TypeKind != typeSrc.TypeKind); 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) || modDest.IsOut != ((ParameterModifierType)typeSrc).IsOut) { return(false); } goto LCheckBases; case TypeKind.TK_PointerType: case TypeKind.TK_NullableType: if (typeDst.TypeKind != typeSrc.TypeKind) { return(false); } LCheckBases: typeSrc = typeSrc.BaseOrParameterOrElementType; typeDst = typeDst.BaseOrParameterOrElementType; goto LRecurse; case TypeKind.TK_AggregateType: if (!(typeDst is AggregateType atsDst)) { return(false); } { // BLOCK AggregateType atsSrc = (AggregateType)typeSrc; if (atsSrc.OwningAggregate != atsDst.OwningAggregate) { return(false); } Debug.Assert(atsSrc.TypeArgsAll.Count == atsDst.TypeArgsAll.Count); // All the args must unify. for (int i = 0; i < atsSrc.TypeArgsAll.Count; i++) { if (!SubstEqualTypesCore(atsDst.TypeArgsAll[i], atsSrc.TypeArgsAll[i], pctx)) { return(false); } } } return(true); case TypeKind.TK_TypeParameterType: { // BLOCK TypeParameterSymbol tvs = ((TypeParameterType)typeSrc).Symbol; int index = tvs.GetIndexInTotalParameters(); if (tvs.IsMethodTypeParameter()) { if (pctx.DenormMeth && tvs.parent != null) { // typeDst == typeSrc was handled above. Debug.Assert(typeDst != typeSrc); return(false); } Debug.Assert(tvs.GetIndexInOwnParameters() == index); Debug.Assert(tvs.GetIndexInTotalParameters() < pctx.MethodTypes.Length); if (index < pctx.MethodTypes.Length) { return(typeDst == pctx.MethodTypes[index]); } } else { Debug.Assert(index < pctx.ClassTypes.Length); if (index < pctx.ClassTypes.Length) { return(typeDst == pctx.ClassTypes[index]); } } } return(false); } }