public bool Init(ErrorHandling errorContext, SymbolTable symtable) { _runtimeBinderSymbolTable = symtable; Debug.Assert(_pBSymmgr != null); #if !CSEE Debug.Assert(_predefSyms == null); #else // CSEE Debug.Assert(predefSyms == null || aidMsCorLib != KAID.kaidNil); #endif // CSEE if (_aidMsCorLib == KAID.kaidNil) { // If we haven't found mscorlib yet, first look for System.Object. Then use its assembly as // the location for all other pre-defined types. AggregateSymbol aggObj = FindPredefinedType(errorContext, PredefinedTypeFacts.GetName(PredefinedType.PT_OBJECT), KAID.kaidGlobal, AggKindEnum.Class, 0, true); if (aggObj == null) return false; _aidMsCorLib = aggObj.GetAssemblyID(); } _predefSyms = new AggregateSymbol[(int)PredefinedType.PT_COUNT]; Debug.Assert(_predefSyms != null); return true; }
//////////////////////////////////////////////////////////////////////////////// // Construct a compiler. All the real work is done in the Init() routine. This // primary initializes all the sub-components. public LangCompiler(CController pCtrl, NameManager pNameMgr) { Debug.Assert(pCtrl != null); _pController = pCtrl; GlobalSymbolContext globalSymbolContext = new GlobalSymbolContext(pNameMgr); _errorContext = new ErrorHandling(new UserStringBuilder(globalSymbolContext), this, pCtrl.GetErrorFactory()); _symbolLoader = new SymbolLoader(globalSymbolContext, null, _errorContext); }
public SymbolLoader( GlobalSymbolContext globalSymbols, UserStringBuilder userStringBuilder, ErrorHandling errorContext ) { _nameManager = globalSymbols.GetNameManager(); PredefinedMembers = new PredefinedMembers(this); ErrorContext = errorContext; GlobalSymbolContext = globalSymbols; Debug.Assert(GlobalSymbolContext != null); }
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 void ReportMissingPredefTypeError(ErrorHandling errorContext, PredefinedType pt) { Debug.Assert(_pBSymmgr != null); Debug.Assert(_predefSyms != null); Debug.Assert((PredefinedType)0 <= pt && pt < PredefinedType.PT_COUNT && _predefSyms[(int)pt] == null); // We do not assert that !predefTypeInfo[pt].isRequired because if the user is defining // their own MSCorLib and is defining a required PredefType, they'll run into this error // and we need to allow it to go through. errorContext.Error(ErrorCode.ERR_PredefinedTypeNotFound, PredefinedTypeFacts.GetName(pt)); }
private AggregateSymbol FindPredefinedType(ErrorHandling errorContext, string pszType, KAID aid, AggKindEnum aggKind, int arity, bool isRequired) { Debug.Assert(!string.IsNullOrEmpty(pszType)); // Shouldn't be the empty string! NamespaceOrAggregateSymbol bagCur = _pBSymmgr.GetRootNS(); Name name = null; string[] nameParts = pszType.Split(s_nameSeparators); for (int i = 0, n = nameParts.Length; i < n; i++) { name = _pBSymmgr.GetNameManager().Add(nameParts[i]); if (i == n - 1) { // This is the last component. Handle it special below. break; } // first search for an outer type which is also predefined // this must be first because we always create a namespace for // outer names, even for nested types AggregateSymbol aggNext = _pBSymmgr.LookupGlobalSymCore(name, bagCur, symbmask_t.MASK_AggregateSymbol).AsAggregateSymbol(); if (aggNext != null && aggNext.InAlias(aid) && aggNext.IsPredefined()) { bagCur = aggNext; } else { // ... if no outer type, then search for namespaces NamespaceSymbol nsNext = _pBSymmgr.LookupGlobalSymCore(name, bagCur, symbmask_t.MASK_NamespaceSymbol).AsNamespaceSymbol(); bool bIsInAlias = true; if (nsNext == null) { bIsInAlias = false; } else { bIsInAlias = nsNext.InAlias(aid); } if (!bIsInAlias) { // Didn't find the namespace in this aid. if (isRequired) { errorContext.Error(ErrorCode.ERR_PredefinedTypeNotFound, pszType); } return null; } bagCur = nsNext; } } AggregateSymbol aggAmbig; AggregateSymbol aggBad; AggregateSymbol aggFound = FindPredefinedTypeCore(name, bagCur, aid, aggKind, arity, out aggAmbig, out aggBad); if (aggFound == null) { // Didn't find the AggregateSymbol. if (aggBad != null && (isRequired || aid == KAID.kaidGlobal && aggBad.IsSource())) errorContext.ErrorRef(ErrorCode.ERR_PredefinedTypeBadType, aggBad); else if (isRequired) errorContext.Error(ErrorCode.ERR_PredefinedTypeNotFound, pszType); return null; } if (aggAmbig == null && aid != KAID.kaidGlobal) { // Look in kaidGlobal to make sure there isn't a conflicting one. AggregateSymbol tmp; AggregateSymbol agg2 = FindPredefinedTypeCore(name, bagCur, KAID.kaidGlobal, aggKind, arity, out aggAmbig, out tmp); Debug.Assert(agg2 != null); if (agg2 != aggFound) aggAmbig = agg2; } return aggFound; }
public void ReportMissingPredefTypeError(ErrorHandling errorContext, PredefinedType pt) { _predefTypes.ReportMissingPredefTypeError(errorContext, pt); }
// 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().size == 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.size == typeArgsThis.size); 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.size > 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.size; i++) { CType arg = typeArgsThis.Item(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 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() || arg.isSpecialByRefType()) { 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.size > 0) { bIsNullable = pArgBnds.Item(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.size != 0 && bnds.Item(0).isPredefType(PredefinedType.PT_VALUE)) { itypeMin = 1; } } for (int j = itypeMin; j < bnds.size; j++) { CType typeBnd = bnds.Item(j); if (!SatisfiesBound(checker, arg, typeBnd)) { if (fReportErrors) { // The bound isn't satisfied because of a constaint 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 varaiable // - 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(checker.GetNameManager().GetPredefName(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; }
//////////////////////////////////////////////////////////////////////////////// // Check whether typeArgs satisfies the constraints of typeVars. The // typeArgsCls and typeArgsMeth are used for substitution on the bounds. The // tree and symErr are used for error reporting. private static bool CheckConstraintsCore(CSemanticChecker checker, ErrorHandling errHandling, Symbol symErr, TypeArray typeVars, TypeArray typeArgs, TypeArray typeArgsCls, TypeArray typeArgsMeth, CheckConstraintsFlags flags) { Debug.Assert(typeVars.size == typeArgs.size); Debug.Assert(typeVars.size > 0); Debug.Assert(flags == CheckConstraintsFlags.None || flags == CheckConstraintsFlags.NoErrors); bool fError = false; for (int i = 0; i < typeVars.size; i++) { // Empty bounds should be set to object. TypeParameterType var = typeVars.ItemAsTypeParameterType(i); CType arg = typeArgs.Item(i); bool fOK = CheckSingleConstraint(checker, errHandling, symErr, var, arg, typeArgsCls, typeArgsMeth, flags); fError |= !fOK; } return !fError; }
//////////////////////////////////////////////////////////////////////////////// // Check the constraints on the method instantiation. public static void CheckMethConstraints(CSemanticChecker checker, ErrorHandling errCtx, MethWithInst mwi) { Debug.Assert(mwi.Meth() != null && mwi.GetType() != null && mwi.TypeArgs != null); Debug.Assert(mwi.Meth().typeVars.size == mwi.TypeArgs.size); Debug.Assert(mwi.GetType().getAggregate() == mwi.Meth().getClass()); if (mwi.TypeArgs.size > 0) { CheckConstraintsCore(checker, errCtx, mwi.Meth(), mwi.Meth().typeVars, mwi.TypeArgs, mwi.GetType().GetTypeArgsAll(), mwi.TypeArgs, CheckConstraintsFlags.None); } }
public CNullable(SymbolLoader symbolLoader, ErrorHandling errorContext, ExprFactory exprFactory) { _pSymbolLoader = symbolLoader; _pErrorContext = errorContext; _exprFactory = exprFactory; }