IsValType() public method

public IsValType ( ) : bool
return bool
Ejemplo n.º 1
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);
        }
Ejemplo n.º 2
0
            private bool bindExplicitConversionFromNub()
            {
                Debug.Assert(_typeSrc != null);
                Debug.Assert(_typeDest != null);

                // If S and T are value types and there is a builtin conversion from S => T then there is an
                // explicit conversion from S? => T that throws on null.
                if (_typeDest.IsValType() && _binder.BindExplicitConversion(null, _typeSrc.StripNubs(), _exprTypeDest, _pDestinationTypeForLambdaErrorReporting, _flags | CONVERTTYPE.NOUDC))
                {
                    if (_needsExprDest)
                    {
                        Expr valueSrc = _exprSrc;
                        // This is a holdover from the days when you could have nullable of nullable.
                        // Can we remove this loop?
                        while (valueSrc.Type is NullableType)
                        {
                            valueSrc = _binder.BindNubValue(valueSrc);
                        }
                        Debug.Assert(valueSrc.Type == _typeSrc.StripNubs());
                        if (!_binder.BindExplicitConversion(valueSrc, valueSrc.Type, _exprTypeDest, _pDestinationTypeForLambdaErrorReporting, _needsExprDest, out _exprDest, _flags | CONVERTTYPE.NOUDC))
                        {
                            VSFAIL("BindExplicitConversion failed unexpectedly");
                            return(false);
                        }
                        if (_exprDest is ExprUserDefinedConversion udc)
                        {
                            udc.Argument = _exprSrc;
                        }
                    }
                    return(true);
                }

                if ((_flags & CONVERTTYPE.NOUDC) == 0)
                {
                    return(_binder.bindUserDefinedConversion(_exprSrc, _typeSrc, _typeDest, _needsExprDest, out _exprDest, false));
                }
                return(false);
            }
            private bool bindExplicitConversionFromNub()
            {
                Debug.Assert(typeSrc != null);
                Debug.Assert(typeDest != null);

                // If S and T are value types and there is a builtin conversion from S => T then there is an
                // explicit conversion from S? => T that throws on null.
                if (typeDest.IsValType() && binder.BindExplicitConversion(null, typeSrc.StripNubs(), exprTypeDest, m_pDestinationTypeForLambdaErrorReporting, flags | CONVERTTYPE.NOUDC))
                {
                    if (needsExprDest)
                    {
                        EXPR valueSrc = exprSrc;
                        // UNDONE: This is a holdover from the days when you could have nullable of nullable.
                        // UNDONE: Can we remove this loop?
                        while (valueSrc.type.IsNullableType())
                        {
                            valueSrc = binder.BindNubValue(valueSrc);
                        }
                        Debug.Assert(valueSrc.type == typeSrc.StripNubs());
                        if (!binder.BindExplicitConversion(valueSrc, valueSrc.type, exprTypeDest, m_pDestinationTypeForLambdaErrorReporting, needsExprDest, out exprDest, flags | CONVERTTYPE.NOUDC))
                        {
                            VSFAIL("BindExplicitConversion failed unexpectedly");
                            return(false);
                        }
                        if (exprDest.kind == ExpressionKind.EK_USERDEFINEDCONVERSION)
                        {
                            exprDest.asUSERDEFINEDCONVERSION().Argument = exprSrc;
                        }
                    }
                    return(true);
                }

                if ((flags & CONVERTTYPE.NOUDC) == 0)
                {
                    return(binder.bindUserDefinedConversion(exprSrc, typeSrc, typeDest, needsExprDest, out exprDest, false));
                }
                return(false);
            }
Ejemplo n.º 4
0
            private bool bindExplicitConversionFromNub()
            {
                Debug.Assert(_typeSrc != null);
                Debug.Assert(_typeDest != null);

                // If S and T are value types and there is a builtin conversion from S => T then there is an
                // explicit conversion from S? => T that throws on null.
                if (_typeDest.IsValType() && _binder.BindExplicitConversion(null, _typeSrc.StripNubs(), _typeDest, _flags | CONVERTTYPE.NOUDC))
                {
                    if (_needsExprDest)
                    {
                        Expr valueSrc = _exprSrc;
                        if (valueSrc.Type is NullableType)
                        {
                            valueSrc = _binder.BindNubValue(valueSrc);
                        }

                        Debug.Assert(valueSrc.Type == _typeSrc.StripNubs());
                        if (!_binder.BindExplicitConversion(valueSrc, valueSrc.Type, _typeDest, _needsExprDest, out _exprDest, _flags | CONVERTTYPE.NOUDC))
                        {
                            Debug.Fail("BindExplicitConversion failed unexpectedly");
                            return(false);
                        }
                        if (_exprDest is ExprUserDefinedConversion udc)
                        {
                            udc.Argument = _exprSrc;
                        }
                    }
                    return(true);
                }

                if ((_flags & CONVERTTYPE.NOUDC) == 0)
                {
                    return(_binder.bindUserDefinedConversion(_exprSrc, _typeSrc, _typeDest, _needsExprDest, out _exprDest, false));
                }
                return(false);
            }
Ejemplo n.º 5
0
        private bool HasImplicitBoxingConversion(CType pSource, CType pDest)
        {
            Debug.Assert(pSource != null);
            Debug.Assert(pDest != null);
            Debug.Assert(!(pSource is TypeParameterType));

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

            if (!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 is NullableType nubSource)
            {
                pSource = nubSource.UnderlyingType; // pSource.IsValType() known to be true.
            }
            else if (!pSource.IsValType())
            {
                return(false);
            }


            // 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.

            return(IsBaseClass(pSource, pDest) || HasAnyBaseInterfaceConversion(pSource, pDest));
        }
Ejemplo n.º 6
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 is OpenTypePlaceholderType)
            {
                return(true);
            }

            if (arg is ErrorType)
            {
                // Error should have been reported previously.
                return(false);
            }

            if (checker.CheckBogus(arg))
            {
                if (fReportErrors)
                {
                    errHandling.ErrorRef(ErrorCode.ERR_BogusType, arg);
                }

                return(false);
            }

            if (arg is PointerType)
            {
                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 is NullableType;
                if (bIsValueType && arg is TypeParameterType typeArg)
                {
                    TypeArray pArgBnds = typeArg.GetBounds();
                    if (pArgBnds.Count > 0)
                    {
                        bIsNullable = pArgBnds[0] is NullableType;
                    }
                }

                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 is NullableType nubArg && checker.GetSymbolLoader().HasBaseConversion(nubArg.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) || nubArg.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 is TypeParameterType)
                        {
                            // 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;
                }
            }
Ejemplo n.º 7
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;
        }
Ejemplo n.º 8
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;
        }