Пример #1
0
        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;
        }
Пример #2
0
        ////////////////////////////////////////////////////////////////////////////////
        // 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);
        }
Пример #3
0
 public SymbolLoader(
     GlobalSymbolContext globalSymbols,
     UserStringBuilder userStringBuilder,
     ErrorHandling errorContext
 )
 {
     _nameManager = globalSymbols.GetNameManager();
     PredefinedMembers = new PredefinedMembers(this);
     ErrorContext = errorContext;
     GlobalSymbolContext = globalSymbols;
     Debug.Assert(GlobalSymbolContext != null);
 }
Пример #4
0
        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;
        }
Пример #5
0
        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;
        }
Пример #6
0
        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));
        }
Пример #7
0
        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;
        }
Пример #8
0
 public void ReportMissingPredefTypeError(ErrorHandling errorContext, PredefinedType pt)
 {
     _predefTypes.ReportMissingPredefTypeError(errorContext, pt);
 }
Пример #9
0
        // 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;
        }
Пример #10
0
        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;
        }
Пример #11
0
        ////////////////////////////////////////////////////////////////////////////////
        // 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;
        }
Пример #12
0
        ////////////////////////////////////////////////////////////////////////////////
        // 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);
            }
        }
Пример #13
0
 public CNullable(SymbolLoader symbolLoader, ErrorHandling errorContext, ExprFactory exprFactory)
 {
     _pSymbolLoader = symbolLoader;
     _pErrorContext = errorContext;
     _exprFactory = exprFactory;
 }