IsNullableType() public méthode

public IsNullableType ( ) : bool
Résultat bool
Exemple #1
0
        // It would be nice to make this a virtual method on typeSym.
        public AggregateType GetAggTypeSym(CType typeSym)
        {
            Debug.Assert(typeSym != null);
            Debug.Assert(typeSym.IsAggregateType() ||
                         typeSym.IsTypeParameterType() ||
                         typeSym.IsArrayType() ||
                         typeSym.IsNullableType());

            switch (typeSym.GetTypeKind())
            {
            case TypeKind.TK_AggregateType:
                return(typeSym.AsAggregateType());

            case TypeKind.TK_ArrayType:
                return(GetReqPredefType(PredefinedType.PT_ARRAY));

            case TypeKind.TK_TypeParameterType:
                return(typeSym.AsTypeParameterType().GetEffectiveBaseClass());

            case TypeKind.TK_NullableType:
                return(typeSym.AsNullableType().GetAts(ErrorContext));
            }
            Debug.Assert(false, "Bad typeSym!");
            return(null);
        }
Exemple #2
0
        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;
        }
Exemple #3
0
        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);
        }
Exemple #4
0
        public bool HasImplicitBoxingConversion(CType pSource, CType pDest)
        {
            Debug.Assert(pSource != null);
            Debug.Assert(pDest != null);

            // Certain type parameter conversions are classified as boxing conversions.

            if (pSource.IsTypeParameterType() &&
                HasImplicitBoxingTypeParameterConversion(pSource.AsTypeParameterType(), pDest))
            {
                return(true);
            }

            // The rest of the boxing conversions only operate when going from a value type
            // to a reference type.

            if (!pSource.IsValType() || !pDest.IsRefType())
            {
                return(false);
            }

            // A boxing conversion exists from a nullable type to a reference type
            // if and only if a boxing conversion exists from the underlying type.

            if (pSource.IsNullableType())
            {
                return(HasImplicitBoxingConversion(pSource.AsNullableType().GetUnderlyingType(), pDest));
            }

            // A boxing conversion exists from any non-nullable value type to object,
            // to System.ValueType, and to any interface type implemented by the
            // non-nullable value type.  Furthermore, an enum type can be converted
            // to the type System.Enum.

            // We set the base class of the structs to System.ValueType, System.Enum, etc,
            // so we can just check here.

            if (IsBaseClass(pSource, pDest))
            {
                return(true);
            }
            if (HasAnyBaseInterfaceConversion(pSource, pDest))
            {
                return(true);
            }
            return(false);
        }
Exemple #5
0
        private bool IsBaseClass(CType pDerived, CType pBase)
        {
            Debug.Assert(pDerived != null);
            Debug.Assert(pBase != null);
            // A base class has got to be a class. The derived type might be a struct.

            if (!pBase.isClassType())
            {
                return(false);
            }
            if (pDerived.IsNullableType())
            {
                pDerived = pDerived.AsNullableType().GetAts(ErrorContext);
                if (pDerived == null)
                {
                    return(false);
                }
            }

            if (!pDerived.IsAggregateType())
            {
                return(false);
            }

            AggregateType atsDer  = pDerived.AsAggregateType();
            AggregateType atsBase = pBase.AsAggregateType();
            AggregateType atsCur  = atsDer.GetBaseClass();

            while (atsCur != null)
            {
                if (atsCur == atsBase)
                {
                    return(true);
                }
                atsCur = atsCur.GetBaseClass();
            }
            return(false);
        }
Exemple #6
0
        private 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);
        }
Exemple #7
0
        //
        // SymbolLoader forwarders (end)
        /////////////////////////////////////////////////////////////////////////////////

        //
        // Utility methods
        //
        protected ACCESSERROR CheckAccessCore(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());

            switch (symCheck.GetAccess())
            {
                default:
                    throw Error.InternalCompilerError();
                //return ACCESSERROR.ACCESSERROR_NOACCESS;

                case ACCESS.ACC_UNKNOWN:
                    return ACCESSERROR.ACCESSERROR_NOACCESS;

                case ACCESS.ACC_PUBLIC:
                    return ACCESSERROR.ACCESSERROR_NOERROR;

                case ACCESS.ACC_PRIVATE:
                case ACCESS.ACC_PROTECTED:
                    if (symWhere == null)
                    {
                        return ACCESSERROR.ACCESSERROR_NOACCESS;
                    }
                    break;

                case ACCESS.ACC_INTERNAL:
                case ACCESS.ACC_INTERNALPROTECTED:   // Check internal, then protected.

                    if (symWhere == null)
                    {
                        return ACCESSERROR.ACCESSERROR_NOACCESS;
                    }
                    if (symWhere.SameAssemOrFriend(symCheck))
                    {
                        return ACCESSERROR.ACCESSERROR_NOERROR;
                    }
                    if (symCheck.GetAccess() == ACCESS.ACC_INTERNAL)
                    {
                        return ACCESSERROR.ACCESSERROR_NOACCESS;
                    }
                    break;
            }

            // Should always have atsCheck for private and protected access check.
            // We currently don't need it since access doesn't respect instantiation.
            // We just use symWhere.parent.AsAggregateSymbol() instead.
            AggregateSymbol aggCheck = symCheck.parent.AsAggregateSymbol();

            // Find the inner-most enclosing AggregateSymbol.
            AggregateSymbol aggWhere = null;

            for (Symbol symT = symWhere; symT != null; symT = symT.parent)
            {
                if (symT.IsAggregateSymbol())
                {
                    aggWhere = symT.AsAggregateSymbol();
                    break;
                }
                if (symT.IsAggregateDeclaration())
                {
                    aggWhere = symT.AsAggregateDeclaration().Agg();
                    break;
                }
            }

            if (aggWhere == null)
            {
                return ACCESSERROR.ACCESSERROR_NOACCESS;
            }

            // First check for private access.
            for (AggregateSymbol agg = aggWhere; agg != null; agg = agg.GetOuterAgg())
            {
                if (agg == aggCheck)
                {
                    return ACCESSERROR.ACCESSERROR_NOERROR;
                }
            }

            if (symCheck.GetAccess() == ACCESS.ACC_PRIVATE)
            {
                return ACCESSERROR.ACCESSERROR_NOACCESS;
            }

            // Handle the protected case - which is the only real complicated one.
            Debug.Assert(symCheck.GetAccess() == ACCESS.ACC_PROTECTED || symCheck.GetAccess() == ACCESS.ACC_INTERNALPROTECTED);

            // Check if symCheck is in aggWhere or a base of aggWhere,
            // or in an outer agg of aggWhere or a base of an outer agg of aggWhere.

            AggregateType atsThru = null;

            if (typeThru != null && !symCheck.isStatic)
            {
                atsThru = SymbolLoader.GetAggTypeSym(typeThru);
            }

            // Look for aggCheck among the base classes of aggWhere and outer aggs.
            bool found = false;
            for (AggregateSymbol agg = aggWhere; agg != null; agg = agg.GetOuterAgg())
            {
                Debug.Assert(agg != aggCheck); // We checked for this above.

                // Look for aggCheck among the base classes of agg.
                if (agg.FindBaseAgg(aggCheck))
                {
                    found = true;
                    // aggCheck is a base class of agg. Check atsThru.
                    // For non-static protected access to be legal, atsThru must be an instantiation of
                    // agg or a CType derived from an instantiation of agg. In this case
                    // all that matters is that agg is in the base AggregateSymbol chain of atsThru. The
                    // actual AGGTYPESYMs involved don't matter.
                    if (atsThru == null || atsThru.getAggregate().FindBaseAgg(agg))
                    {
                        return ACCESSERROR.ACCESSERROR_NOERROR;
                    }
                }
            }

            // the CType in which the method is being called has no relationship with the 
            // CType on which the method is defined surely this is NOACCESS and not NOACCESSTHRU
            if (found == false)
                return ACCESSERROR.ACCESSERROR_NOACCESS;

            return (atsThru == null) ? ACCESSERROR.ACCESSERROR_NOACCESS : ACCESSERROR.ACCESSERROR_NOACCESSTHRU;
        }
Exemple #8
0
            /*
             * BindImplicitConversion
             *
             * This is a complex routine with complex parameters. Generally, this should
             * be called through one of the helper methods that insulates you
             * from the complexity of the interface. This routine handles all the logic
             * associated with implicit conversions.
             *
             * exprSrc - the expression being converted. Can be null if only type conversion
             *           info is being supplied.
             * typeSrc - type of the source
             * typeDest - type of the destination
             * exprDest - returns an expression of the src converted to the dest. If null, we
             *            only care about whether the conversion can be attempted, not the
             *            expression tree.
             * flags    - flags possibly customizing the conversions allowed. E.g., can suppress
             *            user-defined conversions.
             *
             * returns true if the conversion can be made, false if not.
             */
            public bool Bind()
            {
                // 13.1 Implicit conversions
                //
                // The following conversions are classified as implicit conversions:
                //
                // *   Identity conversions
                // *   Implicit numeric conversions
                // *   Implicit enumeration conversions
                // *   Implicit reference conversions
                // *   Boxing conversions
                // *   Implicit type parameter conversions
                // *   Implicit constant expression conversions
                // *   User-defined implicit conversions
                // *   Implicit conversions from an anonymous method expression to a compatible delegate type
                // *   Implicit conversion from a method group to a compatible delegate type
                // *   Conversions from the null type (11.2.7) to any nullable type
                // *   Implicit nullable conversions
                // *   Lifted user-defined implicit conversions
                //
                // Implicit conversions can occur in a variety of situations, including function member invocations
                // (14.4.3), cast expressions (14.6.6), and assignments (14.14).

                // Can't convert to or from the error type.
                if (typeSrc == null || typeDest == null || typeDest.IsNeverSameType())
                {
                    return(false);
                }

                Debug.Assert(typeSrc != null && typeDest != null);         // types must be supplied.
                Debug.Assert(exprSrc == null || typeSrc == exprSrc.type);  // type of source should be correct if source supplied
                Debug.Assert(!needsExprDest || exprSrc != null);           // need source expr to create dest expr

                switch (typeDest.GetTypeKind())
                {
                case TypeKind.TK_ErrorType:
                    Debug.Assert(typeDest.AsErrorType().HasTypeParent() || typeDest.AsErrorType().HasNSParent());
                    if (typeSrc != typeDest)
                    {
                        return(false);
                    }
                    if (needsExprDest)
                    {
                        exprDest = exprSrc;
                    }
                    return(true);

                case TypeKind.TK_NullType:
                    // Can only convert to the null type if src is null.
                    if (!typeSrc.IsNullType())
                    {
                        return(false);
                    }
                    if (needsExprDest)
                    {
                        exprDest = exprSrc;
                    }
                    return(true);

                case TypeKind.TK_MethodGroupType:
                    VSFAIL("Something is wrong with Type.IsNeverSameType()");
                    return(false);

                case TypeKind.TK_NaturalIntegerType:
                case TypeKind.TK_ArgumentListType:
                    return(typeSrc == typeDest);

                case TypeKind.TK_VoidType:
                    return(false);

                default:
                    break;
                }

                if (typeSrc.IsErrorType())
                {
                    Debug.Assert(!typeDest.IsErrorType());
                    return(false);
                }

                // 13.1.1 Identity conversion
                //
                // An identity conversion converts from any type to the same type. This conversion exists only
                // such that an entity that already has a required type can be said to be convertible to that type.

                if (typeSrc == typeDest &&
                    ((flags & CONVERTTYPE.ISEXPLICIT) == 0 || (!typeSrc.isPredefType(PredefinedType.PT_FLOAT) && !typeSrc.isPredefType(PredefinedType.PT_DOUBLE))))
                {
                    if (needsExprDest)
                    {
                        exprDest = exprSrc;
                    }
                    return(true);
                }

                if (typeDest.IsNullableType())
                {
                    return(BindNubConversion(typeDest.AsNullableType()));
                }

                if (typeSrc.IsNullableType())
                {
                    return(bindImplicitConversionFromNullable(typeSrc.AsNullableType()));
                }

                if ((flags & CONVERTTYPE.ISEXPLICIT) != 0)
                {
                    flags |= CONVERTTYPE.NOUDC;
                }

                // Get the fundamental types of destination.
                FUNDTYPE ftDest = typeDest.fundType();

                Debug.Assert(ftDest != FUNDTYPE.FT_NONE || typeDest.IsParameterModifierType());

                switch (typeSrc.GetTypeKind())
                {
                default:
                    VSFAIL("Bad type symbol kind");
                    break;

                case TypeKind.TK_MethodGroupType:
                    if (exprSrc.isMEMGRP())
                    {
                        EXPRCALL outExpr;
                        bool     retVal = binder.BindGrpConversion(exprSrc.asMEMGRP(), typeDest, needsExprDest, out outExpr, false);
                        exprDest = outExpr;
                        return(retVal);
                    }
                    return(false);

                case TypeKind.TK_VoidType:
                case TypeKind.TK_ErrorType:
                case TypeKind.TK_ParameterModifierType:
                case TypeKind.TK_ArgumentListType:
                    return(false);

                case TypeKind.TK_NullType:
                    if (bindImplicitConversionFromNull())
                    {
                        return(true);
                    }
                    // If not, try user defined implicit conversions.
                    break;

                case TypeKind.TK_ArrayType:
                    if (bindImplicitConversionFromArray())
                    {
                        return(true);
                    }
                    // If not, try user defined implicit conversions.
                    break;

                case TypeKind.TK_PointerType:
                    if (bindImplicitConversionFromPointer())
                    {
                        return(true);
                    }
                    // If not, try user defined implicit conversions.
                    break;

                case TypeKind.TK_TypeParameterType:
                    if (bindImplicitConversionFromTypeVar(typeSrc.AsTypeParameterType()))
                    {
                        return(true);
                    }
                    // If not, try user defined implicit conversions.
                    break;

                case TypeKind.TK_AggregateType:
                    // TypeReference and ArgIterator can't be boxed (or converted to anything else)
                    if (typeSrc.isSpecialByRefType())
                    {
                        return(false);
                    }
                    if (bindImplicitConversionFromAgg(typeSrc.AsAggregateType()))
                    {
                        return(true);
                    }
                    // If not, try user defined implicit conversions.
                    break;
                }

                // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                // RUNTIME BINDER ONLY CHANGE
                // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                //
                // Every incoming dynamic operand should be implicitly convertible
                // to any type that it is an instance of.

                if (exprSrc != null &&
                    exprSrc.RuntimeObject != null &&
                    typeDest.AssociatedSystemType.IsInstanceOfType(exprSrc.RuntimeObject) &&
                    binder.GetSemanticChecker().CheckTypeAccess(typeDest, binder.Context.ContextForMemberLookup()))
                {
                    if (needsExprDest)
                    {
                        binder.bindSimpleCast(exprSrc, exprTypeDest, out exprDest, exprSrc.flags & EXPRFLAG.EXF_CANTBENULL);
                    }
                    return(true);
                }

                // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                // END RUNTIME BINDER ONLY CHANGE
                // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

                // 13.1.8 User-defined implicit conversions
                //
                // A user-defined implicit conversion consists of an optional standard implicit conversion,
                // followed by execution of a user-defined implicit conversion operator, followed by another
                // optional standard implicit conversion. The exact rules for evaluating user-defined
                // conversions are described in 13.4.3.

                if (0 == (flags & CONVERTTYPE.NOUDC))
                {
                    return(binder.bindUserDefinedConversion(exprSrc, typeSrc, typeDest, needsExprDest, out exprDest, true));
                }

                // No conversion was found.

                return(false);
            }
Exemple #9
0
 /***************************************************************************************************
     Determines whether there is a wrapping conversion from typeSrc to typeDst
     
 13.7 Conversions involving nullable types
 
 The following terms are used in the subsequent sections:
 *   The term wrapping denotes the process of packaging a value, of type T, in an instance of type T?. 
     A value x of type T is wrapped to type T? by evaluating the expression new T?(x).
 ***************************************************************************************************/
 public static bool FWrappingConv(CType typeSrc, CType typeDst)
 {
     return typeDst.IsNullableType() && typeSrc == typeDst.AsNullableType().GetUnderlyingType();
 }
Exemple #10
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;
        }
Exemple #11
0
        /*
            Same as CanConvertArg1 but with the indices interchanged!
        */
        private bool CanConvertArg2(BinOpArgInfo info, CType typeDst, out LiftFlags pgrflt,
                                      out CType ptypeSig1, out CType ptypeSig2)
        {
            Debug.Assert(!typeDst.IsNullableType());
            ptypeSig1 = null;
            ptypeSig2 = null;

            if (canConvert(info.arg2, typeDst))
                pgrflt = LiftFlags.None;
            else
            {
                pgrflt = LiftFlags.None;
                if (!GetSymbolLoader().FCanLift())
                    return false;
                typeDst = GetSymbolLoader().GetTypeManager().GetNullable(typeDst);
                if (!canConvert(info.arg2, typeDst))
                    return false;
                pgrflt = LiftFlags.Convert2;
            }
            ptypeSig2 = typeDst;

            if (info.type1.IsNullableType())
            {
                pgrflt = pgrflt | LiftFlags.Lift1;
                ptypeSig1 = GetSymbolLoader().GetTypeManager().GetNullable(info.typeRaw1);
            }
            else
                ptypeSig1 = info.typeRaw1;

            return true;
        }
Exemple #12
0
        /////////////////////////////////////////////////////////////////////////////////

        private void LiftArgument(EXPR pArgument, CType pParameterType, bool bConvertBeforeLift,
                                            out EXPR ppLiftedArgument, out EXPR ppNonLiftedArgument)
        {
            EXPR pLiftedArgument = mustConvert(pArgument, pParameterType);
            if (pLiftedArgument != pArgument)
            {
                MarkAsIntermediateConversion(pLiftedArgument);
            }

            EXPR pNonLiftedArgument = pArgument;
            if (pParameterType.IsNullableType())
            {
                if (pNonLiftedArgument.isNull())
                {
                    pNonLiftedArgument = mustCast(pNonLiftedArgument, pParameterType);
                }
                pNonLiftedArgument = mustCast(pNonLiftedArgument, pParameterType.AsNullableType().GetUnderlyingType());
                if (bConvertBeforeLift)
                {
                    MarkAsIntermediateConversion(pNonLiftedArgument);
                }
            }
            else
            {
                pNonLiftedArgument = pLiftedArgument;
            }
            ppLiftedArgument = pLiftedArgument;
            ppNonLiftedArgument = pNonLiftedArgument;
        }
Exemple #13
0
        public bool HasImplicitBoxingConversion(CType pSource, CType pDest)
        {
            Debug.Assert(pSource != null);
            Debug.Assert(pDest != null);

            // Certain type parameter conversions are classified as boxing conversions.

            if (pSource.IsTypeParameterType() &&
                HasImplicitBoxingTypeParameterConversion(pSource.AsTypeParameterType(), pDest))
            {
                return true;
            }

            // The rest of the boxing conversions only operate when going from a value type
            // to a reference type.

            if (!pSource.IsValType() || !pDest.IsRefType())
            {
                return false;
            }

            // A boxing conversion exists from a nullable type to a reference type
            // if and only if a boxing conversion exists from the underlying type.

            if (pSource.IsNullableType())
            {
                return HasImplicitBoxingConversion(pSource.AsNullableType().GetUnderlyingType(), pDest);
            }

            // A boxing conversion exists from any non-nullable value type to object,
            // to System.ValueType, and to any interface type implemented by the
            // non-nullable value type.  Furthermore, an enum type can be converted
            // to the type System.Enum.

            // We set the base class of the structs to System.ValueType, System.Enum, etc,
            // so we can just check here.

            if (IsBaseClass(pSource, pDest))
            {
                return true;
            }
            if (HasAnyBaseInterfaceConversion(pSource, pDest))
            {
                return true;
            }
            return false;
        }
Exemple #14
0
        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;
        }
Exemple #15
0
        public bool IsBaseClass(CType pDerived, CType pBase)
        {
            Debug.Assert(pDerived != null);
            Debug.Assert(pBase != null);
            // A base class has got to be a class. The derived type might be a struct.

            if (!pBase.isClassType())
            {
                return false;
            }
            if (pDerived.IsNullableType())
            {
                pDerived = pDerived.AsNullableType().GetAts(ErrorContext);
                if (pDerived == null)
                {
                    return false;
                }
            }

            if (!pDerived.IsAggregateType())
            {
                return false;
            }

            AggregateType atsDer = pDerived.AsAggregateType();
            AggregateType atsBase = pBase.AsAggregateType();
            AggregateType atsCur = atsDer.GetBaseClass();
            while (atsCur != null)
            {
                if (atsCur == atsBase)
                {
                    return true;
                }
                atsCur = atsCur.GetBaseClass();
            }
            return false;
        }
Exemple #16
0
        // It would be nice to make this a virtual method on typeSym.
        public AggregateType GetAggTypeSym(CType typeSym)
        {
            Debug.Assert(typeSym != null);
            Debug.Assert(typeSym.IsAggregateType() ||
                   typeSym.IsTypeParameterType() ||
                   typeSym.IsArrayType() ||
                   typeSym.IsNullableType());

            switch (typeSym.GetTypeKind())
            {
                case TypeKind.TK_AggregateType:
                    return typeSym.AsAggregateType();
                case TypeKind.TK_ArrayType:
                    return GetReqPredefType(PredefinedType.PT_ARRAY);
                case TypeKind.TK_TypeParameterType:
                    return typeSym.AsTypeParameterType().GetEffectiveBaseClass();
                case TypeKind.TK_NullableType:
                    return typeSym.AsNullableType().GetAts(ErrorContext);
            }
            Debug.Assert(false, "Bad typeSym!");
            return null;
        }
Exemple #17
0
 public bool IsNonNullableValueType()
 {
     return((_constraints & SpecCons.Val) > 0 || _bHasValBound && !_pDeducedBaseClass.IsNullableType());
 }
Exemple #18
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;
        }
Exemple #19
0
 /***************************************************************************************************
 *   Determines whether there is a wrapping conversion from typeSrc to typeDst
 *
 *  13.7 Conversions involving nullable types
 *
 *  The following terms are used in the subsequent sections:
 *   The term wrapping denotes the process of packaging a value, of type T, in an instance of type T?.
 *   A value x of type T is wrapped to type T? by evaluating the expression new T?(x).
 ***************************************************************************************************/
 public static bool FWrappingConv(CType typeSrc, CType typeDst)
 {
     return(typeDst.IsNullableType() && typeSrc == typeDst.AsNullableType().GetUnderlyingType());
 }
            /////////////////////////////////////////////////////////////////////////////////

            private static EXPR GenerateOptionalArgument(
                    SymbolLoader symbolLoader,
                    ExprFactory exprFactory,
                    MethodOrPropertySymbol methprop,
                    CType type,
                    int index)
            {
                CType pParamType = type;
                CType pRawParamType = type.IsNullableType() ? type.AsNullableType().GetUnderlyingType() : type;

                EXPR optionalArgument = null;
                if (methprop.HasDefaultParameterValue(index))
                {
                    CType pConstValType = methprop.GetDefaultParameterValueConstValType(index);
                    CONSTVAL cv = methprop.GetDefaultParameterValue(index);

                    if (pConstValType.isPredefType(PredefinedType.PT_DATETIME) &&
                        (pRawParamType.isPredefType(PredefinedType.PT_DATETIME) || pRawParamType.isPredefType(PredefinedType.PT_OBJECT) || pRawParamType.isPredefType(PredefinedType.PT_VALUE)))
                    {
                        // This is the specific case where we want to create a DateTime
                        // but the constval that stores it is a long.

                        AggregateType dateTimeType = symbolLoader.GetReqPredefType(PredefinedType.PT_DATETIME);
                        optionalArgument = exprFactory.CreateConstant(dateTimeType, new CONSTVAL(DateTime.FromBinary(cv.longVal)));
                    }
                    else if (pConstValType.isSimpleOrEnumOrString())
                    {
                        // In this case, the constval is a simple type (all the numerics, including
                        // decimal), or an enum or a string. This covers all the substantial values,
                        // and everything else that can be encoded is just null or default(something).

                        // For enum parameters, we create a constant of the enum type. For everything
                        // else, we create the appropriate constant.

                        if (pRawParamType.isEnumType() && pConstValType == pRawParamType.underlyingType())
                        {
                            optionalArgument = exprFactory.CreateConstant(pRawParamType, cv);
                        }
                        else
                        {
                            optionalArgument = exprFactory.CreateConstant(pConstValType, cv);
                        }
                    }
                    else if ((pParamType.IsRefType() || pParamType.IsNullableType()) && cv.IsNullRef())
                    {
                        // We have an "= null" default value with a reference type or a nullable type.

                        optionalArgument = exprFactory.CreateNull();
                    }
                    else
                    {
                        // We have a default value that is encoded as a nullref, and that nullref is
                        // interpreted as default(something). For instance, the pParamType could be
                        // a type parameter type or a non-simple value type.

                        optionalArgument = exprFactory.CreateZeroInit(pParamType);
                    }
                }
                else
                {
                    // There was no default parameter specified, so generally use default(T),
                    // except for some cases when the parameter type in metatdata is object.

                    if (pParamType.isPredefType(PredefinedType.PT_OBJECT))
                    {
                        if (methprop.MarshalAsObject(index))
                        {
                            // For [opt] parameters of type object, if we have marshal(iunknown),
                            // marshal(idispatch), or marshal(interface), then we emit a null.

                            optionalArgument = exprFactory.CreateNull();
                        }
                        else
                        {
                            // Otherwise, we generate Type.Missing

                            AggregateSymbol agg = symbolLoader.GetOptPredefAgg(PredefinedType.PT_MISSING);
                            Name name = symbolLoader.GetNameManager().GetPredefinedName(PredefinedName.PN_CAP_VALUE);
                            FieldSymbol field = symbolLoader.LookupAggMember(name, agg, symbmask_t.MASK_FieldSymbol).AsFieldSymbol();
                            FieldWithType fwt = new FieldWithType(field, agg.getThisType());
                            EXPRFIELD exprField = exprFactory.CreateField(0, agg.getThisType(), null, 0, fwt, null);

                            if (agg.getThisType() != type)
                            {
                                optionalArgument = exprFactory.CreateCast(0, type, exprField);
                            }
                            else
                            {
                                optionalArgument = exprField;
                            }
                        }
                    }
                    else
                    {
                        // Every type aside from object that doesn't have a default value gets
                        // its default value.

                        optionalArgument = exprFactory.CreateZeroInit(pParamType);
                    }
                }

                Debug.Assert(optionalArgument != null);
                optionalArgument.IsOptionalArgument = true;
                return optionalArgument;
            }
Exemple #21
0
        ////////////////////////////////////////////////////////////////////////////////
        // For a base call we need to remap from the virtual to the specific override 
        // to invoke.  This is also used to map a virtual on pObject (like ToString) to 
        // the specific override when the pObject is a simple type (int, bool, char, 
        // etc). In these cases it is safe to assume that any override won't later be 
        // removed.... We start searching from "typeObj" up the superclass hierarchy 
        // until we find a method with an exact signature match.

        public static void RemapToOverride(SymbolLoader symbolLoader, SymWithType pswt, CType typeObj)
        {
            // For a property/indexer we remap the accessors, not the property/indexer.
            // Since every event has both accessors we remap the event instead of the accessors.
            Debug.Assert(pswt && (pswt.Sym.IsMethodSymbol() || pswt.Sym.IsEventSymbol() || pswt.Sym.IsMethodOrPropertySymbol()));
            Debug.Assert(typeObj != null);

            // Don't remap static or interface methods.
            if (typeObj.IsNullableType())
            {
                typeObj = typeObj.AsNullableType().GetAts(symbolLoader.GetErrorContext());
                if (typeObj == null)
                {
                    VSFAIL("Why did GetAts return null?");
                    return;
                }
            }

            // Don't remap non-virtual members
            if (!typeObj.IsAggregateType() || typeObj.isInterfaceType() || !pswt.Sym.IsVirtual())
            {
                return;
            }

            symbmask_t mask = pswt.Sym.mask();

            AggregateType atsObj = typeObj.AsAggregateType();

            // Search for an override version of the method.
            while (atsObj != null && atsObj.getAggregate() != pswt.Sym.parent)
            {
                for (Symbol symT = symbolLoader.LookupAggMember(pswt.Sym.name, atsObj.getAggregate(), mask);
                     symT != null;
                     symT = symbolLoader.LookupNextSym(symT, atsObj.getAggregate(), mask))
                {
                    if (symT.IsOverride() && (symT.SymBaseVirtual() == pswt.Sym || symT.SymBaseVirtual() == pswt.Sym.SymBaseVirtual()))
                    {
                        pswt.Set(symT, atsObj);
                        return;
                    }
                }
                atsObj = atsObj.GetBaseClass();
            }
        }
Exemple #22
0
        // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        // 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.IsVoidType() && !typeSrc.IsErrorType() && !typeSrc.IsTypeParameterType());

            if (typeSrc.IsParameterModifierType() || typeSrc.IsPointerType())
            {
                // We cannot vary these.
                return false;
            }

            CType intermediateType;
            if ((typeSrc.isInterfaceType() || typeSrc.isDelegateType()) && TryVarianceAdjustmentToGetAccessibleType(semanticChecker, bindingContext, typeSrc.AsAggregateType(), 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.IsArrayType() && TryArrayVarianceAdjustmentToGetAccessibleType(semanticChecker, bindingContext, typeSrc.AsArrayType(), 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.IsNullableType())
            {
                // We have an inaccessible nullable type, which means that the best we can do is System.ValueType.
                typeDst = this.GetOptPredefAgg(PredefinedType.PT_VALUE).getThisType();

                Debug.Assert(semanticChecker.CheckTypeAccess(typeDst, bindingContext.ContextForMemberLookup()));
                return true;
            }

            if (typeSrc.IsArrayType())
            {
                // 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 = this.GetReqPredefAgg(PredefinedType.PT_ARRAY).getThisType();

                Debug.Assert(semanticChecker.CheckTypeAccess(typeDst, bindingContext.ContextForMemberLookup()));
                return true;
            }

            Debug.Assert(typeSrc.IsAggregateType());

            if (typeSrc.IsAggregateType())
            {
                // We have an AggregateType, so recurse on its base class.
                AggregateType aggType = typeSrc.AsAggregateType();
                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 = this.GetReqPredefAgg(PredefinedType.PT_OBJECT).getThisType();
                }

                return GetBestAccessibleType(semanticChecker, bindingContext, baseType, out typeDst);
            }

            return false;
        }
            /*
             * BindExplicitConversion
             *
             * This is a complex routine with complex parameter. Generally, this should
             * be called through one of the helper methods that insulates you
             * from the complexity of the interface. This routine handles all the logic
             * associated with explicit conversions.
             *
             * Note that this function calls BindImplicitConversion first, so the main
             * logic is only concerned with conversions that can be made explicitly, but
             * not implicitly.
             */
            public bool Bind()
            {
                // To test for a standard conversion, call canConvert(exprSrc, typeDest, STANDARDANDCONVERTTYPE.NOUDC) and
                // canConvert(typeDest, typeSrc, STANDARDANDCONVERTTYPE.NOUDC).
                Debug.Assert((_flags & CONVERTTYPE.STANDARD) == 0);

                // 13.2 Explicit conversions
                //
                // The following conversions are classified as explicit conversions:
                //
                // * All implicit conversions
                // * Explicit numeric conversions
                // * Explicit enumeration conversions
                // * Explicit reference conversions
                // * Explicit interface conversions
                // * Unboxing conversions
                // * Explicit type parameter conversions
                // * User-defined explicit conversions
                // * Explicit nullable conversions
                // * Lifted user-defined explicit conversions
                //
                // Explicit conversions can occur in cast expressions (14.6.6).
                //
                // The explicit conversions that are not implicit conversions are conversions that cannot be
                // proven always to succeed, conversions that are known possibly to lose information, and
                // conversions across domains of types sufficiently different to merit explicit notation.

                // The set of explicit conversions includes all implicit conversions.

                // Don't try user-defined conversions now because we'll try them again later.
                if (_binder.BindImplicitConversion(_exprSrc, _typeSrc, _exprTypeDest, _pDestinationTypeForLambdaErrorReporting, _needsExprDest, out _exprDest, _flags | CONVERTTYPE.ISEXPLICIT))
                {
                    return(true);
                }

                if (_typeSrc == null || _typeDest == null || _typeSrc.IsErrorType() ||
                    _typeDest.IsErrorType() || _typeDest.IsNeverSameType())
                {
                    return(false);
                }

                if (_typeDest.IsNullableType())
                {
                    // This is handled completely by BindImplicitConversion.
                    return(false);
                }

                if (_typeSrc.IsNullableType())
                {
                    return(bindExplicitConversionFromNub());
                }

                if (bindExplicitConversionFromArrayToIList())
                {
                    return(true);
                }

                // if we were casting an integral constant to another constant type,
                // then, if the constant were in range, then the above call would have succeeded.

                // But it failed, and so we know that the constant is not in range

                switch (_typeDest.GetTypeKind())
                {
                default:
                    VSFAIL("Bad type kind");
                    return(false);

                case TypeKind.TK_VoidType:
                    return(false);    // Can't convert to a method group or anon method.

                case TypeKind.TK_NullType:
                    return(false);     // Can never convert TO the null type.

                case TypeKind.TK_TypeParameterType:
                    if (bindExplicitConversionToTypeVar())
                    {
                        return(true);
                    }
                    break;

                case TypeKind.TK_ArrayType:
                    if (bindExplicitConversionToArray(_typeDest.AsArrayType()))
                    {
                        return(true);
                    }
                    break;

                case TypeKind.TK_PointerType:
                    if (bindExplicitConversionToPointer())
                    {
                        return(true);
                    }
                    break;

                case TypeKind.TK_AggregateType:
                {
                    AggCastResult result = bindExplicitConversionToAggregate(_typeDest.AsAggregateType());

                    if (result == AggCastResult.Success)
                    {
                        return(true);
                    }
                    if (result == AggCastResult.Abort)
                    {
                        return(false);
                    }
                    break;
                }
                }

                // No built-in conversion was found. Maybe a user-defined conversion?
                if (0 == (_flags & CONVERTTYPE.NOUDC))
                {
                    return(_binder.bindUserDefinedConversion(_exprSrc, _typeSrc, _typeDest, _needsExprDest, out _exprDest, false));
                }
                return(false);
            }
Exemple #24
0
        ////////////////////////////////////////////////////////////////////////////////

        private bool ExactNullableInference(CType pSource, CType pDest)
        {
            // SPEC:  Otherwise, if U is the CType U1? and V is the CType V1? 
            // SPEC:   then an exact inference is made from U to V.
            if (!pSource.IsNullableType() || !pDest.IsNullableType())
            {
                return false;
            }
            ExactInference(pSource.AsNullableType().GetUnderlyingType(),
                pDest.AsNullableType().GetUnderlyingType());
            return true;
        }
 protected bool IsNullableValueType(CType pType)
 {
     if (pType.IsNullableType())
     {
         CType pStrippedType = pType.StripNubs();
         return pStrippedType.IsAggregateType() && pStrippedType.AsAggregateType().getAggregate().IsValueType();
     }
     return false;
 }
Exemple #26
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().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);
        }
Exemple #27
0
        //
        // SymbolLoader forwarders (end)
        /////////////////////////////////////////////////////////////////////////////////

        //
        // Utility methods
        //
        protected ACCESSERROR CheckAccessCore(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());

            switch (symCheck.GetAccess())
            {
            default:
                throw Error.InternalCompilerError();
            //return ACCESSERROR.ACCESSERROR_NOACCESS;

            case ACCESS.ACC_UNKNOWN:
                return(ACCESSERROR.ACCESSERROR_NOACCESS);

            case ACCESS.ACC_PUBLIC:
                return(ACCESSERROR.ACCESSERROR_NOERROR);

            case ACCESS.ACC_PRIVATE:
            case ACCESS.ACC_PROTECTED:
                if (symWhere == null)
                {
                    return(ACCESSERROR.ACCESSERROR_NOACCESS);
                }
                break;

            case ACCESS.ACC_INTERNAL:
            case ACCESS.ACC_INTERNALPROTECTED:       // Check internal, then protected.

                if (symWhere == null)
                {
                    return(ACCESSERROR.ACCESSERROR_NOACCESS);
                }
                if (symWhere.SameAssemOrFriend(symCheck))
                {
                    return(ACCESSERROR.ACCESSERROR_NOERROR);
                }
                if (symCheck.GetAccess() == ACCESS.ACC_INTERNAL)
                {
                    return(ACCESSERROR.ACCESSERROR_NOACCESS);
                }
                break;
            }

            // Should always have atsCheck for private and protected access check.
            // We currently don't need it since access doesn't respect instantiation.
            // We just use symWhere.parent.AsAggregateSymbol() instead.
            AggregateSymbol aggCheck = symCheck.parent.AsAggregateSymbol();

            // Find the inner-most enclosing AggregateSymbol.
            AggregateSymbol aggWhere = null;

            for (Symbol symT = symWhere; symT != null; symT = symT.parent)
            {
                if (symT.IsAggregateSymbol())
                {
                    aggWhere = symT.AsAggregateSymbol();
                    break;
                }
                if (symT.IsAggregateDeclaration())
                {
                    aggWhere = symT.AsAggregateDeclaration().Agg();
                    break;
                }
            }

            if (aggWhere == null)
            {
                return(ACCESSERROR.ACCESSERROR_NOACCESS);
            }

            // First check for private access.
            for (AggregateSymbol agg = aggWhere; agg != null; agg = agg.GetOuterAgg())
            {
                if (agg == aggCheck)
                {
                    return(ACCESSERROR.ACCESSERROR_NOERROR);
                }
            }

            if (symCheck.GetAccess() == ACCESS.ACC_PRIVATE)
            {
                return(ACCESSERROR.ACCESSERROR_NOACCESS);
            }

            // Handle the protected case - which is the only real complicated one.
            Debug.Assert(symCheck.GetAccess() == ACCESS.ACC_PROTECTED || symCheck.GetAccess() == ACCESS.ACC_INTERNALPROTECTED);

            // Check if symCheck is in aggWhere or a base of aggWhere,
            // or in an outer agg of aggWhere or a base of an outer agg of aggWhere.

            AggregateType atsThru = null;

            if (typeThru != null && !symCheck.isStatic)
            {
                atsThru = SymbolLoader.GetAggTypeSym(typeThru);
            }

            // Look for aggCheck among the base classes of aggWhere and outer aggs.
            bool found = false;

            for (AggregateSymbol agg = aggWhere; agg != null; agg = agg.GetOuterAgg())
            {
                Debug.Assert(agg != aggCheck); // We checked for this above.

                // Look for aggCheck among the base classes of agg.
                if (agg.FindBaseAgg(aggCheck))
                {
                    found = true;
                    // aggCheck is a base class of agg. Check atsThru.
                    // For non-static protected access to be legal, atsThru must be an instantiation of
                    // agg or a CType derived from an instantiation of agg. In this case
                    // all that matters is that agg is in the base AggregateSymbol chain of atsThru. The
                    // actual AGGTYPESYMs involved don't matter.
                    if (atsThru == null || atsThru.getAggregate().FindBaseAgg(agg))
                    {
                        return(ACCESSERROR.ACCESSERROR_NOERROR);
                    }
                }
            }

            // the CType in whice the method is being called has no relationship with the
            // CType on which the method is defined surely this is NOACCESS and not NOACCESSTHRU
            if (found == false)
            {
                return(ACCESSERROR.ACCESSERROR_NOACCESS);
            }

            return((atsThru == null) ? ACCESSERROR.ACCESSERROR_NOACCESS : ACCESSERROR.ACCESSERROR_NOACCESSTHRU);
        }
 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);
 }
Exemple #29
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.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(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);
        }