public void CopyItems(int i, int c, CType[] dest) { for (int j = 0; j < c; ++j) { dest[j] = _items[i + j]; } }
public CMethodIterator(CSemanticChecker checker, SymbolLoader symLoader, Name name, TypeArray containingTypes, CType @object, CType qualifyingType, Declaration context, bool allowBogusAndInaccessible, bool allowExtensionMethods, int arity, EXPRFLAG flags, symbmask_t mask) { Debug.Assert(name != null); Debug.Assert(symLoader != null); Debug.Assert(checker != null); Debug.Assert(containingTypes != null); _pSemanticChecker = checker; _pSymbolLoader = symLoader; _pCurrentType = null; _pCurrentSym = null; _pName = name; _pContainingTypes = containingTypes; _pQualifyingType = qualifyingType; _pContext = context; _bAllowBogusAndInaccessible = allowBogusAndInaccessible; _bAllowExtensionMethods = allowExtensionMethods; _nArity = arity; _flags = flags; _mask = mask; _nCurrentTypeCount = 0; _bIsCheckingInstanceMethods = true; _bAtEnd = false; _bCurrentSymIsBogus = false; _bCurrentSymIsInaccessible = false; _bcanIncludeExtensionsInResults = _bAllowExtensionMethods; _bEndIterationAtCurrentExtensionList = false; }
public CMethodIterator GetMethodIterator( CSemanticChecker pChecker, SymbolLoader pSymLoader, CType pObject, CType pQualifyingType, Declaration pContext, bool allowBogusAndInaccessible, bool allowExtensionMethods, int arity, EXPRFLAG flags, symbmask_t mask) { Debug.Assert(pSymLoader != null); CMethodIterator iterator = new CMethodIterator(pChecker, pSymLoader, _pName, ContainingTypes, pObject, pQualifyingType, pContext, allowBogusAndInaccessible, allowExtensionMethods, arity, flags, mask); return iterator; }
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; }
// Generate an error if CType is static. public bool CheckForStaticClass(Symbol symCtx, CType CType, ErrorCode err) { if (!CType.isStaticClass()) return false; ReportStaticClassError(symCtx, CType, err); return true; }
public SubstContext(CType[] prgtypeCls, int ctypeCls, CType[] prgtypeMeth, int ctypeMeth, SubstTypeFlags grfst) { this.prgtypeCls = prgtypeCls; this.ctypeCls = ctypeCls; this.prgtypeMeth = prgtypeMeth; this.ctypeMeth = ctypeMeth; this.grfst = grfst; }
public TypeArray(CType[] types) { _items = types; if (_items == null) { _items = Array.Empty<CType>(); } }
public void SetBounds(TypeArray pBounds) { _pBounds = pBounds; _pInterfaceBounds = null; _pEffectiveBaseClass = null; _pDeducedBaseClass = null; _bHasRefBound = false; _bHasValBound = false; }
public UnaOpFullSig(CType type, PfnBindUnaOp pfn, LiftFlags grflt, UnaOpFuncKind fnkind) { this.pt = PredefinedType.PT_UNDEFINEDINDEX; this.grfuom = UnaOpMask.None; this.cuosSkip = 0; this.pfn = pfn; _type = type; _grflt = grflt; this.fnkind = fnkind; }
/*************************************************************************************************** Set the values of the UnaOpFullSig from the given UnaOpSig. The ExpressionBinder is needed to get the predefined type. Returns true iff the predef type is found. ***************************************************************************************************/ public UnaOpFullSig(ExpressionBinder fnc, UnaOpSig uos) { this.pt = uos.pt; this.grfuom = uos.grfuom; this.cuosSkip = uos.cuosSkip; this.pfn = uos.pfn; this.fnkind = uos.fnkind; _type = pt != PredefinedType.PT_UNDEFINEDINDEX ? fnc.GetOptPDT(pt) : null; _grflt = LiftFlags.None; }
public ImplicitConversion(ExpressionBinder binder, EXPR exprSrc, CType typeSrc, EXPRTYPEORNAMESPACE typeDest, bool needsExprDest, CONVERTTYPE flags) { _binder = binder; _exprSrc = exprSrc; _typeSrc = typeSrc; _typeDest = typeDest.TypeOrNamespace.AsType(); _exprTypeDest = typeDest; _needsExprDest = needsExprDest; _flags = flags; _exprDest = null; }
public EXPRFUNCPTR CreateFunctionPointer(EXPRFLAG nFlags, CType pType, EXPR pObject, MethWithInst MWI) { Debug.Assert(0 == (nFlags & ~(EXPRFLAG.EXF_BASECALL))); EXPRFUNCPTR rval = new EXPRFUNCPTR(); rval.kind = ExpressionKind.EK_FUNCPTR; rval.type = pType; rval.flags = nFlags; rval.OptionalObject = pObject; rval.mwi = new MethWithInst(MWI); Debug.Assert(rval != null); return (rval); }
// ---------------------------------------------------------------------------- // BindExplicitConversion // ---------------------------------------------------------------------------- public ExplicitConversion(ExpressionBinder binder, EXPR exprSrc, CType typeSrc, EXPRTYPEORNAMESPACE typeDest, CType pDestinationTypeForLambdaErrorReporting, bool needsExprDest, CONVERTTYPE flags) { _binder = binder; _exprSrc = exprSrc; _typeSrc = typeSrc; _typeDest = typeDest.TypeOrNamespace.AsType(); _pDestinationTypeForLambdaErrorReporting = pDestinationTypeForLambdaErrorReporting; _exprTypeDest = typeDest; _needsExprDest = needsExprDest; _flags = flags; _exprDest = null; }
public static bool TypeContainsAnonymousTypes(CType type) { CType ctype = (CType)type; LRecurse: // Label used for "tail" recursion. switch (ctype.GetTypeKind()) { default: Debug.Assert(false, "Bad Symbol kind in TypeContainsAnonymousTypes"); return false; case TypeKind.TK_NullType: case TypeKind.TK_VoidType: case TypeKind.TK_NullableType: case TypeKind.TK_TypeParameterType: case TypeKind.TK_UnboundLambdaType: case TypeKind.TK_MethodGroupType: return false; case TypeKind.TK_ArrayType: case TypeKind.TK_ParameterModifierType: case TypeKind.TK_PointerType: ctype = (CType)ctype.GetBaseOrParameterOrElementType(); goto LRecurse; case TypeKind.TK_AggregateType: if (ctype.AsAggregateType().getAggregate().IsAnonymousType()) { return true; } TypeArray typeArgsAll = ctype.AsAggregateType().GetTypeArgsAll(); for (int i = 0; i < typeArgsAll.size; i++) { CType typeArg = typeArgsAll.Item(i); if (TypeContainsAnonymousTypes(typeArg)) { return true; } } return false; case TypeKind.TK_ErrorType: if (ctype.AsErrorType().HasTypeParent()) { ctype = ctype.AsErrorType().GetTypeParent(); goto LRecurse; } return false; } }
public BinOpFullSig(CType type1, CType type2, PfnBindBinOp pfn, OpSigFlags grfos, LiftFlags grflt, BinOpFuncKind fnkind) { this.pt1 = PredefinedType.PT_UNDEFINEDINDEX; this.pt2 = PredefinedType.PT_UNDEFINEDINDEX; this.mask = BinOpMask.None; this.cbosSkip = 0; this.pfn = pfn; this.grfos = grfos; _type1 = type1; _type2 = type2; _grflt = grflt; this.fnkind = fnkind; }
public EXPRFIELD CreateField(EXPRFLAG nFlags, CType pType, EXPR pOptionalObject, uint nOffset, FieldWithType FWT, EXPR pOptionalLHS) { Debug.Assert(0 == (nFlags & ~(EXPRFLAG.EXF_MEMBERSET | EXPRFLAG.EXF_MASK_ANY))); EXPRFIELD rval = new EXPRFIELD(); rval.kind = ExpressionKind.EK_FIELD; rval.type = pType; rval.flags = nFlags; rval.SetOptionalObject(pOptionalObject); if (FWT != null) { rval.fwt = FWT; } Debug.Assert(rval != null); return (rval); }
public AggregateType GetAts(ErrorHandling errorContext) { AggregateSymbol aggNullable = typeManager.GetNullable(); if (aggNullable == null) { throw Error.InternalCompilerError(); } if (ats == null) { CType typePar = GetUnderlyingType(); CType[] typeParArray = new CType[] { typePar }; TypeArray ta = symmgr.AllocParams(1, typeParArray); ats = typeManager.GetAggregate(aggNullable, ta); } return ats; }
public AggregateType GetAts(ErrorHandling errorContext) { AggregateSymbol aggNullable = typeManager.GetNullable(); if (aggNullable == null) { throw Error.InternalCompilerError(); } if (ats == null) { if (aggNullable == null) { typeManager.ReportMissingPredefTypeError(errorContext, PredefinedType.PT_G_OPTIONAL); return null; } CType typePar = GetUnderlyingType(); CType[] typeParArray = new CType[] { typePar }; TypeArray ta = symmgr.AllocParams(1, typeParArray); ats = typeManager.GetAggregate(aggNullable, ta); } return ats; }
public EXPRCALL CreateCall(EXPRFLAG nFlags, CType pType, EXPR pOptionalArguments, EXPRMEMGRP pMemberGroup, MethWithInst MWI) { Debug.Assert(0 == (nFlags & ~( EXPRFLAG.EXF_NEWOBJCALL | EXPRFLAG.EXF_CONSTRAINED | EXPRFLAG.EXF_BASECALL | EXPRFLAG.EXF_NEWSTRUCTASSG | EXPRFLAG.EXF_IMPLICITSTRUCTASSG | EXPRFLAG.EXF_MASK_ANY ) )); EXPRCALL rval = new EXPRCALL(); rval.kind = ExpressionKind.EK_CALL; rval.type = pType; rval.flags = nFlags; rval.SetOptionalArguments(pOptionalArguments); rval.SetMemberGroup(pMemberGroup); rval.nubLiftKind = NullableCallLiftKind.NotLifted; rval.castOfNonLiftedResultToLiftedType = null; rval.mwi = MWI; Debug.Assert(rval != null); return (rval); }
public ExprProperty CreateProperty(CType type, Expr optionalObjectThrough, Expr arguments, ExprMemberGroup memberGroup, PropWithType property, MethWithType setMethod) => new ExprProperty(type, optionalObjectThrough, arguments, memberGroup, property, setMethod);
public ExprCast CreateCast(EXPRFLAG flags, CType type, Expr argument) => new ExprCast(flags, type, argument);
public ExprUserLogicalOp CreateUserLogOp(CType type, Expr trueFalseCall, ExprCall operatorCall) => new ExprUserLogicalOp(type, trueFalseCall, operatorCall);
public ExprMulti CreateMulti(EXPRFLAG flags, CType type, Expr left, Expr op) => new ExprMulti(type, flags, left, op);
// 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); }
public bool HasImplicitReferenceConversion(CType pSource, CType pDest) { Debug.Assert(pSource != null); Debug.Assert(pDest != null); // The implicit reference conversions are: // * From any reference type to Object. if (pSource.IsRefType() && pDest.isPredefType(PredefinedType.PT_OBJECT)) { return(true); } // * From any class type S to any class type T provided S is derived from T. if (pSource.isClassType() && pDest.isClassType() && IsBaseClass(pSource, pDest)) { return(true); } // ORIGINAL RULES: // // * From any class type S to any interface type T provided S implements T. // if (pSource.isClassType() && pDest.isInterfaceType() && IsBaseInterface(pSource, pDest)) // { // return true; // } // // * from any interface type S to any interface type T, provided S is derived from T. // if (pSource.isInterfaceType() && pDest.isInterfaceType() && IsBaseInterface(pSource, pDest)) // { // return true; // } // VARIANCE EXTENSIONS: // * From any class type S to any interface type T provided S implements an interface // convertible to T. // * From any interface type S to any interface type T provided S implements an interface // convertible to T. // * From any interface type S to any interface type T provided S is not T and S is // an interface convertible to T. if (pSource.isClassType() && pDest.isInterfaceType() && HasAnyBaseInterfaceConversion(pSource, pDest)) { return(true); } if (pSource.isInterfaceType() && pDest.isInterfaceType() && HasAnyBaseInterfaceConversion(pSource, pDest)) { return(true); } if (pSource.isInterfaceType() && pDest.isInterfaceType() && pSource != pDest && HasInterfaceConversion(pSource.AsAggregateType(), pDest.AsAggregateType())) { return(true); } // * From an array type S with an element type SE to an array type T with element type TE // provided that 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. // * Both SE and TE are reference types. // * An implicit reference conversion exists from SE to TE. if (pSource.IsArrayType() && pDest.IsArrayType() && HasCovariantArrayConversion(pSource.AsArrayType(), pDest.AsArrayType())) { return(true); } // * From any array type to System.Array or any interface implemented by System.Array. if (pSource.IsArrayType() && (pDest.isPredefType(PredefinedType.PT_ARRAY) || IsBaseInterface(GetReqPredefType(PredefinedType.PT_ARRAY, false), pDest))) { return(true); } // * From a single-dimensional array type S[] to IList<T> and its base // interfaces, provided that there is an implicit identity or reference // conversion from S to T. if (pSource.IsArrayType() && HasArrayConversionToInterface(pSource.AsArrayType(), pDest)) { return(true); } // * From any delegate type to System.Delegate // // SPEC OMISSION: // // The spec should actually say // // * From any delegate type to System.Delegate // * From any delegate type to System.MulticastDelegate // * From any delegate type to any interface implemented by System.MulticastDelegate if (pSource.isDelegateType() && (pDest.isPredefType(PredefinedType.PT_MULTIDEL) || pDest.isPredefType(PredefinedType.PT_DELEGATE) || IsBaseInterface(GetReqPredefType(PredefinedType.PT_MULTIDEL, false), pDest))) { return(true); } // VARIANCE EXTENSION: // * From any delegate type S to a delegate type T provided S is not T and // S is a delegate convertible to T if (pSource.isDelegateType() && pDest.isDelegateType() && HasDelegateConversion(pSource.AsAggregateType(), pDest.AsAggregateType())) { return(true); } // * From the null literal to any reference type // NOTE: We extend the specification here. The C# 3.0 spec does not describe // a "null type". Rather, it says that the null literal is typeless, and is // convertible to any reference or nullable type. However, the C# 2.0 and 3.0 // implementations have a "null type" which some expressions other than the // null literal may have. (For example, (null??null), which is also an // extension to the specification.) if (pSource.IsNullType() && pDest.IsRefType()) { return(true); } if (pSource.IsNullType() && pDest.IsNullableType()) { return(true); } // * Implicit conversions involving type parameters that are known to be reference types. if (pSource.IsTypeParameterType() && HasImplicitReferenceTypeParameterConversion(pSource.AsTypeParameterType(), pDest)) { return(true); } return(false); }
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // RUNTIME BINDER ONLY CHANGE // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! internal bool GetBestAccessibleType(CSemanticChecker semanticChecker, BindingContext bindingContext, CType typeSrc, out CType typeDst) { // This method implements the "best accessible type" algorithm for determining the type // of untyped arguments in the runtime binder. It is also used in method type inference // to fix type arguments to types that are accessible. // The new type is returned in an out parameter. The result will be true (and the out param // non-null) only when the algorithm could find a suitable accessible type. Debug.Assert(semanticChecker != null); Debug.Assert(bindingContext != null); Debug.Assert(typeSrc != null); typeDst = null; if (semanticChecker.CheckTypeAccess(typeSrc, bindingContext.ContextForMemberLookup)) { // If we already have an accessible type, then use it. This is the terminal point of the recursion. typeDst = typeSrc; return(true); } // These guys have no accessibility concerns. Debug.Assert(!(typeSrc is VoidType) && !(typeSrc is ErrorType) && !(typeSrc is TypeParameterType)); if (typeSrc is ParameterModifierType || typeSrc is PointerType) { // We cannot vary these. return(false); } CType intermediateType; if (typeSrc is AggregateType aggSrc && (aggSrc.isInterfaceType() || aggSrc.isDelegateType()) && TryVarianceAdjustmentToGetAccessibleType(semanticChecker, bindingContext, aggSrc, out intermediateType)) { // If we have an interface or delegate type, then it can potentially be varied by its type arguments // to produce an accessible type, and if that's the case, then return that. // Example: IEnumerable<PrivateConcreteFoo> --> IEnumerable<PublicAbstractFoo> typeDst = intermediateType; Debug.Assert(semanticChecker.CheckTypeAccess(typeDst, bindingContext.ContextForMemberLookup)); return(true); } if (typeSrc is ArrayType arrSrc && TryArrayVarianceAdjustmentToGetAccessibleType(semanticChecker, bindingContext, arrSrc, out intermediateType)) { // Similarly to the interface and delegate case, arrays are covariant in their element type and // so we can potentially produce an array type that is accessible. // Example: PrivateConcreteFoo[] --> PublicAbstractFoo[] typeDst = intermediateType; Debug.Assert(semanticChecker.CheckTypeAccess(typeDst, bindingContext.ContextForMemberLookup)); return(true); } if (typeSrc is NullableType) { // We have an inaccessible nullable type, which means that the best we can do is System.ValueType. typeDst = GetPredefAgg(PredefinedType.PT_VALUE).getThisType(); Debug.Assert(semanticChecker.CheckTypeAccess(typeDst, bindingContext.ContextForMemberLookup)); return(true); } if (typeSrc is ArrayType) { // We have an inaccessible array type for which we could not earlier find a better array type // with a covariant conversion, so the best we can do is System.Array. typeDst = GetPredefAgg(PredefinedType.PT_ARRAY).getThisType(); Debug.Assert(semanticChecker.CheckTypeAccess(typeDst, bindingContext.ContextForMemberLookup)); return(true); } Debug.Assert(typeSrc is AggregateType); if (typeSrc is AggregateType aggType) { // We have an AggregateType, so recurse on its base class. AggregateType baseType = aggType.GetBaseClass(); if (baseType == null) { // This happens with interfaces, for instance. But in that case, the // conversion to object does exist, is an implicit reference conversion, // and so we will use it. baseType = GetPredefAgg(PredefinedType.PT_OBJECT).getThisType(); } return(GetBestAccessibleType(semanticChecker, bindingContext, baseType, out typeDst)); } return(false); }
private bool TryVarianceAdjustmentToGetAccessibleType(CSemanticChecker semanticChecker, BindingContext bindingContext, AggregateType typeSrc, out CType typeDst) { Debug.Assert(typeSrc != null); Debug.Assert(typeSrc.isInterfaceType() || typeSrc.isDelegateType()); typeDst = null; AggregateSymbol aggSym = typeSrc.GetOwningAggregate(); AggregateType aggOpenType = aggSym.getThisType(); if (!semanticChecker.CheckTypeAccess(aggOpenType, bindingContext.ContextForMemberLookup)) { // if the aggregate symbol itself is not accessible, then forget it, there is no // variance that will help us arrive at an accessible type. return(false); } TypeArray typeArgs = typeSrc.GetTypeArgsThis(); TypeArray typeParams = aggOpenType.GetTypeArgsThis(); CType[] newTypeArgsTemp = new CType[typeArgs.Count]; for (int i = 0; i < typeArgs.Count; i++) { if (semanticChecker.CheckTypeAccess(typeArgs[i], bindingContext.ContextForMemberLookup)) { // we have an accessible argument, this position is not a problem. newTypeArgsTemp[i] = typeArgs[i]; continue; } if (!typeArgs[i].IsRefType() || !((TypeParameterType)typeParams[i]).Covariant) { // This guy is inaccessible, and we are not going to be able to vary him, so we need to fail. return(false); } CType intermediateTypeArg; if (GetBestAccessibleType(semanticChecker, bindingContext, typeArgs[i], out intermediateTypeArg)) { // now we either have a value type (which must be accessible due to the above // check, OR we have an inaccessible type (which must be a ref type). In either // case, the recursion worked out and we are OK to vary this argument. newTypeArgsTemp[i] = intermediateTypeArg; continue; } else { Debug.Assert(false, "GetBestAccessibleType unexpectedly failed on a type that was used as a type parameter"); return(false); } } TypeArray newTypeArgs = semanticChecker.getBSymmgr().AllocParams(typeArgs.Count, newTypeArgsTemp); CType intermediateType = this.GetAggregate(aggSym, typeSrc.outerType, newTypeArgs); // All type arguments were varied successfully, which means now we must be accessible. But we could // have violated constraints. Let's check that out. if (!TypeBind.CheckConstraints(semanticChecker, null /*ErrorHandling*/, intermediateType, CheckConstraintsFlags.NoErrors)) { return(false); } typeDst = intermediateType; Debug.Assert(semanticChecker.CheckTypeAccess(typeDst, bindingContext.ContextForMemberLookup)); return(true); }
public bool SubstEqualTypes(CType typeDst, CType typeSrc, CType typeCls) { return(SubstEqualTypes(typeDst, typeSrc, typeCls, (TypeArray)null)); }
private bool SubstEqualTypes(CType typeDst, CType typeSrc, CType typeCls, TypeArray typeArgsMeth) { return(SubstEqualTypes(typeDst, typeSrc, (typeCls as AggregateType)?.GetTypeArgsAll(), typeArgsMeth, SubstTypeFlags.NormNone)); }
public CType SubstType(CType typeSrc, CType typeCls, TypeArray typeArgsMeth) { return(SubstType(typeSrc, (typeCls as AggregateType)?.GetTypeArgsAll(), typeArgsMeth)); }
public CType SubstType(CType typeSrc, AggregateType atsCls, TypeArray typeArgsMeth) { return(SubstType(typeSrc, atsCls?.GetTypeArgsAll(), typeArgsMeth)); }
private static bool isEnumToDecimalConversion(CType argtype, CType desttype) { CType strippedArgType = argtype.IsNullableType() ? argtype.StripNubs() : argtype; CType strippedDestType = desttype.IsNullableType() ? desttype.StripNubs() : desttype; return strippedArgType.isEnumType() && strippedDestType.isPredefType(PredefinedType.PT_DECIMAL); }
public ExprMemberGroup(EXPRFLAG flags, Name name, TypeArray typeArgs, SYMKIND symKind, CType parentType, MethodOrPropertySymbol pMPS, Expr optionalObject, CMemberLookupResults memberLookupResults) : base(ExpressionKind.MemberGroup, MethodGroupType.Instance) { Debug.Assert( (flags & ~(EXPRFLAG.EXF_CTOR | EXPRFLAG.EXF_INDEXER | EXPRFLAG.EXF_OPERATOR | EXPRFLAG.EXF_NEWOBJCALL | EXPRFLAG.EXF_DELEGATE | EXPRFLAG.EXF_USERCALLABLE | EXPRFLAG.EXF_MASK_ANY)) == 0); Flags = flags; Name = name; TypeArgs = typeArgs ?? BSYMMGR.EmptyTypeArray(); SymKind = symKind; ParentType = parentType; OptionalObject = optionalObject; MemberLookupResults = memberLookupResults; }
protected virtual EXPR GenerateConversionWithSource(EXPR pTarget, CType pType, bool bChecked) { PREDEFMETH pdm = bChecked ? PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED : PREDEFMETH.PM_EXPRESSION_CONVERT; EXPR pTypeOf = CreateTypeOf(pType); return GenerateCall(pdm, pTarget, pTypeOf); }
/*************************************************************************************************** * Called by BindImplicitConversion when the destination type is Nullable<T>. The following * conversions are handled by this method: * * For S in { object, ValueType, interfaces implemented by underlying type} there is an explicit * unboxing conversion S => T? * System.Enum => T? there is an unboxing conversion if T is an enum type * null => T? implemented as default(T?) * * Implicit T?* => T?+ implemented by either wrapping or calling GetValueOrDefault the * appropriate number of times. * If imp/exp S => T then imp/exp S => T?+ implemented by converting to T then wrapping the * appropriate number of times. * If imp/exp S => T then imp/exp S?+ => T?+ implemented by calling GetValueOrDefault (m-1) times * then calling HasValue, producing a null if it returns false, otherwise calling Value, * converting to T then wrapping the appropriate number of times. * * The 3 rules above can be summarized with the following recursive rules: * * If imp/exp S => T? then imp/exp S? => T? implemented as * qs.HasValue ? (T?)(qs.Value) : default(T?) * If imp/exp S => T then imp/exp S => T? implemented as new T?((T)s) * * This method also handles calling bindUserDefinedConverion. This method does NOT handle * the following conversions: * * Implicit boxing conversion from S? to { object, ValueType, Enum, ifaces implemented by S }. (Handled by BindImplicitConversion.) * If imp/exp S => T then explicit S?+ => T implemented by calling Value the appropriate number * of times. (Handled by BindExplicitConversion.) * * The recursive equivalent is: * * If imp/exp S => T and T is not nullable then explicit S? => T implemented as qs.Value * * Some nullable conversion are NOT standard conversions. In particular, if S => T is implicit * then S? => T is not standard. Similarly if S => T is not implicit then S => T? is not standard. ***************************************************************************************************/ private bool BindNubConversion(NullableType nubDst) { // This code assumes that STANDARD and ISEXPLICIT are never both set. // bindUserDefinedConversion should ensure this! Debug.Assert(0 != (~_flags & (CONVERTTYPE.STANDARD | CONVERTTYPE.ISEXPLICIT))); Debug.Assert(_exprSrc == null || _exprSrc.Type == _typeSrc); Debug.Assert(!_needsExprDest || _exprSrc != null); Debug.Assert(_typeSrc != nubDst); // BindImplicitConversion should have taken care of this already. AggregateType atsDst = nubDst.GetAts(GetErrorContext()); if (atsDst == null) { return(false); } // Check for the unboxing conversion. This takes precedence over the wrapping conversions. if (GetSymbolLoader().HasBaseConversion(nubDst.GetUnderlyingType(), _typeSrc) && !CConversions.FWrappingConv(_typeSrc, nubDst)) { // These should be different! Fix the caller if typeSrc is an AggregateType of Nullable. Debug.Assert(atsDst != _typeSrc); // typeSrc is a base type of the destination nullable type so there is an explicit // unboxing conversion. if (0 == (_flags & CONVERTTYPE.ISEXPLICIT)) { return(false); } if (_needsExprDest) { _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest, EXPRFLAG.EXF_UNBOX); } return(true); } int cnubDst; int cnubSrc; CType typeDstBase = nubDst.StripNubs(out cnubDst); ExprClass exprTypeDstBase = GetExprFactory().MakeClass(typeDstBase); CType typeSrcBase = _typeSrc.StripNubs(out cnubSrc); ConversionFunc pfn = (_flags & CONVERTTYPE.ISEXPLICIT) != 0 ? (ConversionFunc)_binder.BindExplicitConversion : (ConversionFunc)_binder.BindImplicitConversion; if (cnubSrc == 0) { Debug.Assert(_typeSrc == typeSrcBase); // The null type can be implicitly converted to T? as the default value. if (_typeSrc.IsNullType()) { // If we have the constant null, generate it as a default value of T?. If we have // some crazy expression which has been determined to be always null, like (null??null) // keep it in its expression form and transform it in the nullable rewrite pass. if (_needsExprDest) { if (_exprSrc.isCONSTANT_OK()) { _exprDest = GetExprFactory().CreateZeroInit(nubDst); } else { _exprDest = GetExprFactory().CreateCast(0x00, _typeDest, _exprSrc); } } return(true); } Expr exprTmp = _exprSrc; // If there is an implicit/explicit S => T then there is an implicit/explicit S => T? if (_typeSrc == typeDstBase || pfn(_exprSrc, _typeSrc, exprTypeDstBase, nubDst, _needsExprDest, out exprTmp, _flags | CONVERTTYPE.NOUDC)) { if (_needsExprDest) { ExprUserDefinedConversion exprUDC = exprTmp as ExprUserDefinedConversion; if (exprUDC != null) { exprTmp = exprUDC.UserDefinedCall; } // This logic is left over from the days when T?? was legal. However there are error/LAF cases that necessitates the loop. // typeSrc is not nullable so just wrap the required number of times. For legal code (cnubDst <= 0). for (int i = 0; i < cnubDst; i++) { ExprCall call = _binder.BindNubNew(exprTmp); exprTmp = call; call.NullableCallLiftKind = NullableCallLiftKind.NullableConversionConstructor; } if (exprUDC != null) { exprUDC.UserDefinedCall = exprTmp; exprUDC.Type = (CType)exprTmp.Type; exprTmp = exprUDC; } Debug.Assert(exprTmp.Type == nubDst); _exprDest = exprTmp; } return(true); } // No builtin conversion. Maybe there is a user defined conversion.... return(0 == (_flags & CONVERTTYPE.NOUDC) && _binder.bindUserDefinedConversion(_exprSrc, _typeSrc, nubDst, _needsExprDest, out _exprDest, 0 == (_flags & CONVERTTYPE.ISEXPLICIT))); } // Both are Nullable so there is only a conversion if there is a conversion between the base types. // That is, if there is an implicit/explicit S => T then there is an implicit/explicit S?+ => T?+. if (typeSrcBase != typeDstBase && !pfn(null, typeSrcBase, exprTypeDstBase, nubDst, false, out _exprDest, _flags | CONVERTTYPE.NOUDC)) { // No builtin conversion. Maybe there is a user defined conversion.... return(0 == (_flags & CONVERTTYPE.NOUDC) && _binder.bindUserDefinedConversion(_exprSrc, _typeSrc, nubDst, _needsExprDest, out _exprDest, 0 == (_flags & CONVERTTYPE.ISEXPLICIT))); } if (_needsExprDest) { MethWithInst mwi = new MethWithInst(null, null); ExprMemberGroup pMemGroup = GetExprFactory().CreateMemGroup(null, mwi); ExprCall exprDst = GetExprFactory().CreateCall(0, nubDst, _exprSrc, pMemGroup, null); // Here we want to first check whether or not the conversions work on the base types. Expr arg1 = _binder.mustCast(_exprSrc, typeSrcBase); ExprClass arg2 = GetExprFactory().MakeClass(typeDstBase); bool convertible; if (0 != (_flags & CONVERTTYPE.ISEXPLICIT)) { convertible = _binder.BindExplicitConversion(arg1, arg1.Type, arg2, typeDstBase, out arg1, _flags | CONVERTTYPE.NOUDC); } else { convertible = _binder.BindImplicitConversion(arg1, arg1.Type, arg2, typeDstBase, out arg1, _flags | CONVERTTYPE.NOUDC); } if (!convertible) { VSFAIL("bind(Im|Ex)plicitConversion failed unexpectedly"); return(false); } exprDst.CastOfNonLiftedResultToLiftedType = _binder.mustCast(arg1, nubDst, 0); exprDst.NullableCallLiftKind = NullableCallLiftKind.NullableConversion; exprDst.PConversions = exprDst.CastOfNonLiftedResultToLiftedType; _exprDest = exprDst; } return(true); }
protected virtual EXPR GenerateUserDefinedConversion(EXPR arg, CType CType, EXPR target, MethWithInst method) { // The user-defined explicit conversion from enum? to decimal or decimal? requires // that we convert the enum? to its nullable underlying CType. if (isEnumToDecimalConversion(arg.type, CType)) { // Special case: If we have enum? to decimal? then we need to emit // a conversion from enum? to its nullable underlying CType first. // This is unfortunate; we ought to reorganize how conversions are // represented in the EXPR tree so that this is more transparent. // converting an enum to its underlying CType never fails, so no need to check it. CType underlyingType = arg.type.StripNubs().underlyingEnumType(); CType nullableType = GetSymbolLoader().GetTypeManager().GetNullable(underlyingType); EXPR typeofNubEnum = CreateTypeOf(nullableType); target = GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, target, typeofNubEnum); } // If the methodinfo does not return the target CType AND this is not a lifted conversion // from one value CType to another, then we need to wrap the whole thing in another conversion, // e.g. if we have a user-defined conversion from int to S? and we have (S)myint, then we need to generate // Convert(Convert(myint, typeof(S?), op_implicit), typeof(S)) CType pMethodReturnType = GetSymbolLoader().GetTypeManager().SubstType(method.Meth().RetType, method.GetType(), method.TypeArgs); bool fDontLiftReturnType = (pMethodReturnType == CType || (IsNullableValueType(arg.type) && IsNullableValueType(CType))); EXPR typeofInner = CreateTypeOf(fDontLiftReturnType ? CType : pMethodReturnType); EXPR methodInfo = GetExprFactory().CreateMethodInfo(method); PREDEFMETH pdmInner = arg.isChecked() ? PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED_USER_DEFINED : PREDEFMETH.PM_EXPRESSION_CONVERT_USER_DEFINED; EXPR callUserDefinedConversion = GenerateCall(pdmInner, target, typeofInner, methodInfo); if (fDontLiftReturnType) { return callUserDefinedConversion; } PREDEFMETH pdmOuter = arg.isChecked() ? PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED : PREDEFMETH.PM_EXPRESSION_CONVERT; EXPR typeofOuter = CreateTypeOf(CType); return GenerateCall(pdmOuter, callUserDefinedConversion, typeofOuter); }
private static bool CheckSingleConstraint(CSemanticChecker checker, ErrorHandling errHandling, Symbol symErr, TypeParameterType var, CType arg, TypeArray typeArgsCls, TypeArray typeArgsMeth, CheckConstraintsFlags flags) { bool fReportErrors = 0 == (flags & CheckConstraintsFlags.NoErrors); if (arg.IsOpenTypePlaceholderType()) { return(true); } if (arg.IsErrorType()) { // Error should have been reported previously. return(false); } if (checker.CheckBogus(arg)) { if (fReportErrors) { errHandling.ErrorRef(ErrorCode.ERR_BogusType, arg); } return(false); } if (arg.IsPointerType()) { if (fReportErrors) { errHandling.Error(ErrorCode.ERR_BadTypeArgument, arg); } return(false); } if (arg.isStaticClass()) { if (fReportErrors) { checker.ReportStaticClassError(null, arg, ErrorCode.ERR_GenericArgIsStaticClass); } return(false); } bool fError = false; if (var.HasRefConstraint() && !arg.IsRefType()) { if (fReportErrors) { errHandling.ErrorRef(ErrorCode.ERR_RefConstraintNotSatisfied, symErr, new ErrArgNoRef(var), arg); } fError = true; } TypeArray bnds = checker.GetSymbolLoader().GetTypeManager().SubstTypeArray(var.GetBounds(), typeArgsCls, typeArgsMeth); int itypeMin = 0; if (var.HasValConstraint()) { // If we have a type variable that is constrained to a value type, then we // want to check if its a nullable type, so that we can report the // constraint error below. In order to do this however, we need to check // that either the type arg is not a value type, or it is a nullable type. // // To check whether or not its a nullable type, we need to get the resolved // bound from the type argument and check against that. bool bIsValueType = arg.IsValType(); bool bIsNullable = arg.IsNullableType(); if (bIsValueType && arg.IsTypeParameterType()) { TypeArray pArgBnds = arg.AsTypeParameterType().GetBounds(); if (pArgBnds.Count > 0) { bIsNullable = pArgBnds[0].IsNullableType(); } } if (!bIsValueType || bIsNullable) { if (fReportErrors) { errHandling.ErrorRef(ErrorCode.ERR_ValConstraintNotSatisfied, symErr, new ErrArgNoRef(var), arg); } fError = true; } // Since FValCon() is set it is redundant to check System.ValueType as well. if (bnds.Count != 0 && bnds[0].isPredefType(PredefinedType.PT_VALUE)) { itypeMin = 1; } } for (int j = itypeMin; j < bnds.Count; j++) { CType typeBnd = bnds[j]; if (!SatisfiesBound(checker, arg, typeBnd)) { if (fReportErrors) { // The bound isn't satisfied because of a constraint type. Explain to the user why not. // There are 4 main cases, based on the type of the supplied type argument: // - reference type, or type parameter known to be a reference type // - nullable type, from which there is a boxing conversion to the constraint type(see below for details) // - type variable // - value type // These cases are broken out because: a) The sets of conversions which can be used // for constraint satisfaction is different based on the type argument supplied, // and b) Nullable is one funky type, and user's can use all the help they can get // when using it. ErrorCode error; if (arg.IsRefType()) { // A reference type can only satisfy bounds to types // to which they have an implicit reference conversion error = ErrorCode.ERR_GenericConstraintNotSatisfiedRefType; } else if (arg.IsNullableType() && checker.GetSymbolLoader().HasBaseConversion(arg.AsNullableType().GetUnderlyingType(), typeBnd)) // This is inlining FBoxingConv { // nullable types do not satisfy bounds to every type that they are boxable to // They only satisfy bounds of object and ValueType if (typeBnd.isPredefType(PredefinedType.PT_ENUM) || arg.AsNullableType().GetUnderlyingType() == typeBnd) { // Nullable types don't satisfy bounds of EnumType, or the underlying type of the enum // even though the conversion from Nullable to these types is a boxing conversion // This is a rare case, because these bounds can never be directly stated ... // These bounds can only occur when one type paramter is constrained to a second type parameter // and the second type parameter is instantiated with Enum or the underlying type of the first type // parameter error = ErrorCode.ERR_GenericConstraintNotSatisfiedNullableEnum; } else { // Nullable types don't satisfy the bounds of any interface type // even when there is a boxing conversion from the Nullable type to // the interface type. This will be a relatively common scenario // so we cal it out separately from the previous case. Debug.Assert(typeBnd.isInterfaceType()); error = ErrorCode.ERR_GenericConstraintNotSatisfiedNullableInterface; } } else if (arg.IsTypeParameterType()) { // Type variables can satisfy bounds through boxing and type variable conversions Debug.Assert(!arg.IsRefType()); error = ErrorCode.ERR_GenericConstraintNotSatisfiedTyVar; } else { // Value types can only satisfy bounds through boxing conversions. // Note that the exceptional case of Nullable types and boxing is handled above. error = ErrorCode.ERR_GenericConstraintNotSatisfiedValType; } errHandling.Error(error, new ErrArgRef(symErr), new ErrArg(typeBnd, ErrArgFlags.Unique), var, new ErrArgRef(arg, ErrArgFlags.Unique)); } fError = true; } } // Check the newable constraint. if (!var.HasNewConstraint() || arg.IsValType()) { return(!fError); } if (arg.isClassType()) { AggregateSymbol agg = arg.AsAggregateType().getAggregate(); // Due to late binding nature of IDE created symbols, the AggregateSymbol might not // have all the information necessary yet, if it is not fully bound. // by calling LookupAggMember, it will ensure that we will update all the // information necessary at least for the given method. checker.GetSymbolLoader().LookupAggMember(NameManager.GetPredefinedName(PredefinedName.PN_CTOR), agg, symbmask_t.MASK_ALL); if (agg.HasPubNoArgCtor() && !agg.IsAbstract()) { return(!fError); } } else if (arg.IsTypeParameterType() && arg.AsTypeParameterType().HasNewConstraint()) { return(!fError); } if (fReportErrors) { errHandling.ErrorRef(ErrorCode.ERR_NewConstraintNotSatisfied, symErr, new ErrArgNoRef(var), arg); } return(false); }
protected EXPRTYPEOF CreateTypeOf(CType CType) { return GetExprFactory().CreateTypeOf(CType); }
public ExprMultiGet CreateMultiGet(EXPRFLAG flags, CType type, ExprMulti multi) => new ExprMultiGet(type, flags, multi);
///////////////////////////////////////////////////////////////////////////////// private TypeArray GetMethodTypeParameters(MethodInfo method, MethodSymbol parent) { if (method.IsGenericMethod) { Type[] genericArguments = method.GetGenericArguments(); CType[] ctypes = new CType[genericArguments.Length]; for (int i = 0; i < genericArguments.Length; i++) { Type t = genericArguments[i]; ctypes[i] = LoadMethodTypeParameter(parent, t); } // After we load the type parameters, we need to resolve their bounds. for (int i = 0; i < genericArguments.Length; i++) { Type t = genericArguments[i]; ctypes[i].AsTypeParameterType().GetTypeParameterSymbol().SetBounds( _bsymmgr.AllocParams( GetCTypeArrayFromTypes(t.GetTypeInfo().GetGenericParameterConstraints()))); } return _bsymmgr.AllocParams(ctypes.Length, ctypes); } return BSYMMGR.EmptyTypeArray(); }
public ExprTypeOf CreateTypeOf(CType sourceType) => new ExprTypeOf(Types.GetPredefAgg(PredefinedType.PT_TYPE).getThisType(), sourceType);
public ExprArrayInit CreateArrayInit(CType type, Expr arguments, Expr argumentDimensions, int[] dimSizes, int dimSize) => new ExprArrayInit(type, arguments, argumentDimensions, dimSizes, dimSize);
public ExprCast CreateCast(CType type, Expr argument) => CreateCast(0, type, argument);
protected bool AreTypesEqualForConversion(CType pType1, CType pType2) { return(pType1.Equals(pType2)); }
public ExprMemberGroup CreateMemGroup(EXPRFLAG flags, Name name, TypeArray typeArgs, SYMKIND symKind, CType parentType, MethodOrPropertySymbol memberSymbol, Expr obj, CMemberLookupResults memberLookupResults) => new ExprMemberGroup(flags, name, typeArgs, symKind, parentType, memberSymbol, obj, memberLookupResults);
public bool isManagedType(CType type) { return(type.computeManagedType(this)); }
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); }
public NullableType(CType underlyingType) : base(TypeKind.TK_NullableType) { UnderlyingType = underlyingType; }
protected bool IsNullableValueType(CType pType) { if (pType.IsNullableType()) { CType pStrippedType = pType.StripNubs(); return pStrippedType.IsAggregateType() && pStrippedType.AsAggregateType().getAggregate().IsValueType(); } return false; }
public CType SubstType(CType typeSrc, TypeArray typeArgsCls) { return(SubstType(typeSrc, typeArgsCls, null, SubstTypeFlags.NormNone)); }
protected virtual EXPR GenerateConversion(EXPR arg, CType CType, bool bChecked) { return GenerateConversionWithSource(Visit(arg), CType, bChecked || arg.isChecked()); }
private CType SubstType(CType typeSrc, TypeArray typeArgsCls, TypeArray typeArgsMeth) { return(SubstType(typeSrc, typeArgsCls, typeArgsMeth, SubstTypeFlags.NormNone)); }
protected virtual EXPR GenerateUserDefinedConversion(EXPR arg, CType type, MethWithInst method) { EXPR target = Visit(arg); return GenerateUserDefinedConversion(arg, type, target, method); }
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_OpenTypePlaceholderType: 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); CType pParentType = null; if (err.HasTypeParent()) { pParentType = SubstTypeCore(err.GetTypeParent(), pctx); } TypeArray typeArgs = SubstTypeArray(err.typeArgs, pctx); if (typeArgs != err.typeArgs || (err.HasTypeParent() && pParentType != err.GetTypeParent())) { return(GetErrorType(pParentType, err.GetNSParent(), 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)); } } }
protected virtual EXPR GenerateParameter(string name, CType CType) { GetSymbolLoader().GetReqPredefType(PredefinedType.PT_STRING); // force an ensure state EXPRCONSTANT nameString = GetExprFactory().CreateStringConstant(name); EXPRTYPEOF pTypeOf = CreateTypeOf(CType); return GenerateCall(PREDEFMETH.PM_EXPRESSION_PARAMETER, pTypeOf, nameString); }
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: case TypeKind.TK_OpenTypePlaceholderType: // 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) { return(false); } if (errSrc.HasTypeParent() != errDst.HasTypeParent()) { return(false); } if (errSrc.HasTypeParent()) { if (errSrc.GetTypeParent() != errDst.GetTypeParent()) { return(false); } if (!SubstEqualTypesCore(errDst.GetTypeParent(), errSrc.GetTypeParent(), pctx)) { return(false); } } else { if (errSrc.GetNSParent() != errDst.GetNSParent()) { 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 void SetDefaultParameterValue(int index, CType type, CONSTVAL cv) { Debug.Assert(_defaultParameterIndex != null); ConstValFactory factory = new ConstValFactory(); _defaultParameterIndex[index] = true; _defaultParameters[index] = factory.Copy(type.constValKind(), cv); _defaultParameterConstValTypes[index] = type; }
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: case TypeKind.TK_OpenTypePlaceholderType: // 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); } } if (err.HasTypeParent()) { type = err.GetTypeParent(); goto LRecurse; } } return(false); case TypeKind.TK_TypeParameterType: return(false); } }
///////////////////////////////////////////////////////////////////////////////// internal CType[] GetCTypeArrayFromTypes(IList<Type> types) { if (types == null) { return null; } CType[] ctypes = new CType[types.Count]; int i = 0; foreach (Type t in types) { Debug.Assert(t != null); ctypes[i++] = GetCTypeFromType(t); } return ctypes; }
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_OpenTypePlaceholderType: 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); } } if (err.HasTypeParent()) { type = err.GetTypeParent(); goto LRecurse; } } 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); } }