Item() public method

public Item ( int i ) : CType
i int
return CType
Example #1
0
        private static Type CalculateAssociatedSystemTypeForAggregate(AggregateType aggtype)
        {
            AggregateSymbol agg      = aggtype.GetOwningAggregate();
            TypeArray       typeArgs = aggtype.GetTypeArgsAll();

            List <Type> list = new List <Type>();

            // Get each type arg.
            for (int i = 0; i < typeArgs.size; i++)
            {
                // Unnamed type parameter types are just placeholders.
                if (typeArgs.Item(i).IsTypeParameterType() && typeArgs.Item(i).AsTypeParameterType().GetTypeParameterSymbol().name == null)
                {
                    return(null);
                }
                list.Add(typeArgs.Item(i).AssociatedSystemType);
            }

            Type[] systemTypeArgs     = list.ToArray();
            Type   uninstantiatedType = agg.AssociatedSystemType;

            if (uninstantiatedType.GetTypeInfo().IsGenericType)
            {
                try
                {
                    return(uninstantiatedType.MakeGenericType(systemTypeArgs));
                }
                catch (ArgumentException)
                {
                    // If the constraints don't work, just return the type without substituting it.
                    return(uninstantiatedType);
                }
            }
            return(uninstantiatedType);
        }
        ////////////////////////////////////////////////////////////////////////////////
        // We need to rearange the method parameters so that the type of any specified named argument
        // appears in the same place as the named argument. Consider the example below:
        //    Foo(int x = 4, string y = "", long l = 4)
        //    Foo(string y = "", string x="", long l = 5)
        // and the call site:
        //    Foo(y:"a")
        // After rearanging the parameter types we will have:
        //   (string, int, long) and (string, string, long)
        // By rearanging the arguments as such we make sure that any specified named arguments appear in the same position for both
        // methods and we also maintain the relative order of the other parameters (the type long appears after int in the above example)

        private TypeArray RearrangeNamedArguments(TypeArray pta, MethPropWithInst mpwi,
                                                  CType pTypeThrough, ArgInfos args)
        {
            if (!args.fHasExprs)
            {
                return(pta);
            }

        #if DEBUG
            // We never have a named argument that is in a position in the argument
            // list past the end of what would be the formal parameter list.
            for (int i = pta.size; i < args.carg; i++)
            {
                Debug.Assert(!args.prgexpr[i].isNamedArgumentSpecification());
            }
        #endif

            CType   type     = pTypeThrough != null ? pTypeThrough : mpwi.GetType();
            CType[] typeList = new CType[pta.size];
            MethodOrPropertySymbol methProp = GroupToArgsBinder.FindMostDerivedMethod(GetSymbolLoader(), mpwi.MethProp(), type);

            // We initialize the new type array with the parameters for the method.
            for (int iParam = 0; iParam < pta.size; iParam++)
            {
                typeList[iParam] = pta.Item(iParam);
            }

            // We then go over the specified arguments and put the type for any named argument in the right position in the array.
            for (int iParam = 0; iParam < args.carg; iParam++)
            {
                EXPR arg = args.prgexpr[iParam];
                if (arg.isNamedArgumentSpecification())
                {
                    // We find the index of the type of the argument in the method parameter list and store that in a temp
                    int   index    = FindName(methProp.ParameterNames, arg.asNamedArgumentSpecification().Name);
                    CType tempType = pta.Item(index);

                    // Starting from the current position in the type list up until the location of the type of the optional argument
                    //  We shift types by one:
                    //   before: (int, string, long)
                    //   after: (string, int, long)
                    // We only touch the types between the current position and the position of the type we need to move
                    for (int iShift = iParam; iShift < index; iShift++)
                    {
                        typeList[iShift + 1] = typeList[iShift];
                    }

                    typeList[iParam] = tempType;
                }
            }

            return(GetSymbolLoader().getBSymmgr().AllocParams(pta.size, typeList));
        }
Example #3
0
        public bool IsBaseInterface(CType pDerived, CType pBase)
        {
            Debug.Assert(pDerived != null);
            Debug.Assert(pBase != null);
            if (!pBase.isInterfaceType())
            {
                return(false);
            }
            if (!pDerived.IsAggregateType())
            {
                return(false);
            }
            AggregateType atsDer = pDerived.AsAggregateType();

            while (atsDer != null)
            {
                TypeArray ifacesAll = atsDer.GetIfacesAll();
                for (int i = 0; i < ifacesAll.Size; i++)
                {
                    if (AreTypesEqualForConversion(ifacesAll.Item(i), pBase))
                    {
                        return(true);
                    }
                }
                atsDer = atsDer.GetBaseClass();
            }
            return(false);
        }
Example #4
0
        public bool DependsOn(TypeParameterType pType)
        {
            Debug.Assert(pType != null);

            // * If a type parameter T is used as a constraint for type parameter S
            //   then S depends on T.
            // * If a type parameter S depends on a type parameter T and T depends on
            //   U then S depends on U.

            TypeArray pConstraints = GetBounds();

            for (int iConstraint = 0; iConstraint < pConstraints.size; ++iConstraint)
            {
                CType pConstraint = pConstraints.Item(iConstraint);
                if (pConstraint == pType)
                {
                    return(true);
                }
                if (pConstraint.IsTypeParameterType() &&
                    pConstraint.AsTypeParameterType().DependsOn(pType))
                {
                    return(true);
                }
            }
            return(false);
        }
Example #5
0
        public virtual bool CheckTypeAccess(CType type, Symbol symWhere)
        {
            Debug.Assert(type != null);

            // Array, Ptr, Nub, etc don't matter.
            type = type.GetNakedType(true);

            if (!type.IsAggregateType())
            {
                Debug.Assert(type.IsVoidType() || type.IsErrorType() || type.IsTypeParameterType());
                return(true);
            }

            for (AggregateType ats = type.AsAggregateType(); ats != null; ats = ats.outerType)
            {
                if (ACCESSERROR.ACCESSERROR_NOERROR != CheckAccessCore(ats.GetOwningAggregate(), ats.outerType, symWhere, null))
                {
                    return(false);
                }
            }

            TypeArray typeArgs = type.AsAggregateType().GetTypeArgsAll();

            for (int i = 0; i < typeArgs.size; i++)
            {
                if (!CheckTypeAccess(typeArgs.Item(i), symWhere))
                {
                    return(false);
                }
            }

            return(true);
        }
Example #6
0
        private bool HasAnyBaseInterfaceConversion(CType pDerived, CType pBase)
        {
            if (!pBase.isInterfaceType())
            {
                return(false);
            }
            if (!pDerived.IsAggregateType())
            {
                return(false);
            }
            AggregateType atsDer = pDerived.AsAggregateType();

            while (atsDer != null)
            {
                TypeArray ifacesAll = atsDer.GetIfacesAll();
                for (int i = 0; i < ifacesAll.size; i++)
                {
                    if (HasInterfaceConversion(ifacesAll.Item(i).AsAggregateType(), pBase.AsAggregateType()))
                    {
                        return(true);
                    }
                }
                atsDer = atsDer.GetBaseClass();
            }
            return(false);
        }
Example #7
0
        public bool AreAllTypeArgumentsUnitTypes(TypeArray typeArray)
        {
            if (typeArray.Size == 0)
            {
                return(true);
            }

            for (int i = 0; i < typeArray.size; i++)
            {
                Debug.Assert(typeArray.Item(i) != null);
                if (!typeArray.Item(i).IsOpenTypePlaceholderType())
                {
                    return(false);
                }
            }
            return(true);
        }
            /////////////////////////////////////////////////////////////////////////////////

            private static int NumberOfErrorTypes(TypeArray pTypeArgs)
            {
                int nCount = 0;
                for (int i = 0; i < pTypeArgs.Size; i++)
                {
                    if (pTypeArgs.Item(i).IsErrorType())
                    {
                        nCount++;
                    }
                }
                return nCount;
            }
Example #9
0
        //////////////////////////////////////////////////////////////////////////////

        private bool HasVariantConversion(AggregateType pSource, AggregateType pDest)
        {
            Debug.Assert(pSource != null);
            Debug.Assert(pDest != null);
            if (pSource == pDest)
            {
                return(true);
            }
            AggregateSymbol pAggSym = pSource.getAggregate();

            if (pAggSym != pDest.getAggregate())
            {
                return(false);
            }

            TypeArray pTypeParams = pAggSym.GetTypeVarsAll();
            TypeArray pSourceArgs = pSource.GetTypeArgsAll();
            TypeArray pDestArgs   = pDest.GetTypeArgsAll();

            Debug.Assert(pTypeParams.size == pSourceArgs.size);
            Debug.Assert(pTypeParams.size == pDestArgs.size);

            for (int iParam = 0; iParam < pTypeParams.size; ++iParam)
            {
                CType pSourceArg = pSourceArgs.Item(iParam);
                CType pDestArg   = pDestArgs.Item(iParam);
                // If they're identical then this one is automatically good, so skip it.
                if (pSourceArg == pDestArg)
                {
                    continue;
                }
                TypeParameterType pParam = pTypeParams.Item(iParam).AsTypeParameterType();
                if (pParam.Invariant)
                {
                    return(false);
                }
                if (pParam.Covariant)
                {
                    if (!HasImplicitReferenceConversion(pSourceArg, pDestArg))
                    {
                        return(false);
                    }
                }
                if (pParam.Contravariant)
                {
                    if (!HasImplicitReferenceConversion(pDestArg, pSourceArg))
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
            /////////////////////////////////////////////////////////////////////////////////

            private static int NumberOfErrorTypes(TypeArray pTypeArgs)
            {
                int nCount = 0;

                for (int i = 0; i < pTypeArgs.Size; i++)
                {
                    if (pTypeArgs.Item(i).IsErrorType())
                    {
                        nCount++;
                    }
                }
                return(nCount);
            }
Example #11
0
        /***************************************************************************************************
        *
        *  There exists an explicit conversion ...
        * From a generic delegate type S to generic delegate type T, provided all of the follow are true:
        *   o Both types are constructed generic types of the same generic delegate type, D<X1,... Xk>.That is,
        *     S is D<S1,... Sk> and T is D<T1,... Tk>.
        *   o S is not compatible with or identical to T.
        *   o If type parameter Xi is declared to be invariant then Si must be identical to Ti.
        *   o If type parameter Xi is declared to be covariant ("out") then Si must be convertible
        *     to Ti via an identify conversion,  implicit reference conversion, or explicit reference conversion.
        *   o If type parameter Xi is declared to be contravariant ("in") then either Si must be identical to Ti,
        *     or Si and Ti must both be reference types.
        ***************************************************************************************************/
        public static bool HasGenericDelegateExplicitReferenceConversion(SymbolLoader loader, CType pSource, CType pTarget)
        {
            if (!pSource.isDelegateType() ||
                !pTarget.isDelegateType() ||
                pSource.getAggregate() != pTarget.getAggregate() ||
                loader.HasIdentityOrImplicitReferenceConversion(pSource, pTarget))
            {
                return(false);
            }

            TypeArray pTypeParams = pSource.getAggregate().GetTypeVarsAll();
            TypeArray pSourceArgs = pSource.AsAggregateType().GetTypeArgsAll();
            TypeArray pTargetArgs = pTarget.AsAggregateType().GetTypeArgsAll();

            Debug.Assert(pTypeParams.size == pSourceArgs.size);
            Debug.Assert(pTypeParams.size == pTargetArgs.size);

            for (int iParam = 0; iParam < pTypeParams.size; ++iParam)
            {
                CType pSourceArg = pSourceArgs.Item(iParam);
                CType pTargetArg = pTargetArgs.Item(iParam);

                // If they're identical then this one is automatically good, so skip it.
                // If we have an error type, then we're in some fault tolerance. Let it through.
                if (pSourceArg == pTargetArg || pTargetArg.IsErrorType() || pSourceArg.IsErrorType())
                {
                    continue;
                }
                TypeParameterType pParam = pTypeParams.Item(iParam).AsTypeParameterType();
                if (pParam.Invariant)
                {
                    return(false);
                }

                if (pParam.Covariant)
                {
                    if (!FExpRefConv(loader, pSourceArg, pTargetArg))
                    {
                        return(false);
                    }
                }
                else if (pParam.Contravariant)
                {
                    if (!pSourceArg.IsRefType() || !pTargetArg.IsRefType())
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
Example #12
0
        private bool HasImplicitReferenceTypeParameterConversion(
            TypeParameterType pSource, CType pDest)
        {
            Debug.Assert(pSource != null);
            Debug.Assert(pDest != null);

            if (!pSource.IsRefType())
            {
                // Not a reference conversion.
                return(false);
            }

            // The following implicit conversions exist for a given type parameter T:
            //
            // * From T to its effective base class C.
            AggregateType pEBC = pSource.GetEffectiveBaseClass();

            if (pDest == pEBC)
            {
                return(true);
            }
            // * From T to any base class of C.
            if (IsBaseClass(pEBC, pDest))
            {
                return(true);
            }
            // * From T to any interface implemented by C.
            if (IsBaseInterface(pEBC, pDest))
            {
                return(true);
            }
            // * From T to any interface type I in T's effective interface set, and
            //   from T to any base interface of I.
            TypeArray pInterfaces = pSource.GetInterfaceBounds();

            for (int i = 0; i < pInterfaces.Size; ++i)
            {
                if (pInterfaces.Item(i) == pDest)
                {
                    return(true);
                }
            }
            // * From T to a type parameter U, provided T depends on U.
            if (pDest.IsTypeParameterType() && pSource.DependsOn(pDest.AsTypeParameterType()))
            {
                return(true);
            }
            return(false);
        }
            private static bool IsBetterThanCurrent(TypeArray pTypeArgs1, TypeArray pTypeArgs2)
            {
                int leftErrors = NumberOfErrorTypes(pTypeArgs1);
                int rightErrors = NumberOfErrorTypes(pTypeArgs2);

                if (leftErrors == rightErrors)
                {
                    int max = pTypeArgs1.Size > pTypeArgs2.Size ? pTypeArgs2.Size : pTypeArgs1.Size;

                    // If we dont have a winner yet, go through each element's type args.
                    for (int i = 0; i < max; i++)
                    {
                        if (pTypeArgs1.Item(i).IsAggregateType())
                        {
                            leftErrors += NumberOfErrorTypes(pTypeArgs1.Item(i).AsAggregateType().GetTypeArgsAll());
                        }
                        if (pTypeArgs2.Item(i).IsAggregateType())
                        {
                            rightErrors += NumberOfErrorTypes(pTypeArgs2.Item(i).AsAggregateType().GetTypeArgsAll());
                        }
                    }
                }
                return rightErrors < leftErrors;
            }
            private static bool IsBetterThanCurrent(TypeArray pTypeArgs1, TypeArray pTypeArgs2)
            {
                int leftErrors  = NumberOfErrorTypes(pTypeArgs1);
                int rightErrors = NumberOfErrorTypes(pTypeArgs2);

                if (leftErrors == rightErrors)
                {
                    int max = pTypeArgs1.Size > pTypeArgs2.Size ? pTypeArgs2.Size : pTypeArgs1.Size;

                    // If we dont have a winner yet, go through each element's type args.
                    for (int i = 0; i < max; i++)
                    {
                        if (pTypeArgs1.Item(i).IsAggregateType())
                        {
                            leftErrors += NumberOfErrorTypes(pTypeArgs1.Item(i).AsAggregateType().GetTypeArgsAll());
                        }
                        if (pTypeArgs2.Item(i).IsAggregateType())
                        {
                            rightErrors += NumberOfErrorTypes(pTypeArgs2.Item(i).AsAggregateType().GetTypeArgsAll());
                        }
                    }
                }
                return(rightErrors < leftErrors);
            }
Example #15
0
        private bool HasImplicitBoxingTypeParameterConversion(
            TypeParameterType pSource, CType pDest)
        {
            Debug.Assert(pSource != null);
            Debug.Assert(pDest != null);

            if (pSource.IsRefType())
            {
                // Not a boxing conversion; both source and destination are references.
                return(false);
            }

            // The following implicit conversions exist for a given type parameter T:
            //
            // * From T to its effective base class C.
            AggregateType pEBC = pSource.GetEffectiveBaseClass();

            if (pDest == pEBC)
            {
                return(true);
            }
            // * From T to any base class of C.
            if (IsBaseClass(pEBC, pDest))
            {
                return(true);
            }
            // * From T to any interface implemented by C.
            if (IsBaseInterface(pEBC, pDest))
            {
                return(true);
            }
            // * From T to any interface type I in T's effective interface set, and
            //   from T to any base interface of I.
            TypeArray pInterfaces = pSource.GetInterfaceBounds();

            for (int i = 0; i < pInterfaces.Size; ++i)
            {
                if (pInterfaces.Item(i) == pDest)
                {
                    return(true);
                }
            }
            // * The conversion from T to a type parameter U, provided T depends on U, is not
            //   classified as a boxing conversion because it is not guaranteed to box.
            //   (If both T and U are value types then it is an identity conversion.)

            return(false);
        }
Example #16
0
        ////////////////////////////////////////////////////////////////////////////////
        // Check whether typeArgs satisfies the constraints of typeVars. The
        // typeArgsCls and typeArgsMeth are used for substitution on the bounds. The
        // tree and symErr are used for error reporting.

        private static bool CheckConstraintsCore(CSemanticChecker checker, ErrorHandling errHandling, Symbol symErr, TypeArray typeVars, TypeArray typeArgs, TypeArray typeArgsCls, TypeArray typeArgsMeth, CheckConstraintsFlags flags)
        {
            Debug.Assert(typeVars.size == typeArgs.size);
            Debug.Assert(typeVars.size > 0);
            Debug.Assert(flags == CheckConstraintsFlags.None || flags == CheckConstraintsFlags.NoErrors);

            bool fError = false;

            for (int i = 0; i < typeVars.size; i++)
            {
                // Empty bounds should be set to object.
                TypeParameterType var = typeVars.ItemAsTypeParameterType(i);
                CType             arg = typeArgs.Item(i);

                bool fOK = CheckSingleConstraint(checker, errHandling, symErr, var, arg, typeArgsCls, typeArgsMeth, flags);
                fError |= !fOK;
            }

            return(!fError);
        }
Example #17
0
        public TypeArray GetWinRTCollectionIfacesAll(SymbolLoader pSymbolLoader)
        {
            if (_winrtifacesAll == null)
            {
                TypeArray ifaces = GetIfacesAll();
                System.Collections.Generic.List <CType> typeList = new System.Collections.Generic.List <CType>();

                for (int i = 0; i < ifaces.size; i++)
                {
                    AggregateType type = ifaces.Item(i).AsAggregateType();
                    Debug.Assert(type.isInterfaceType());

                    if (type.IsCollectionType())
                    {
                        typeList.Add(type);
                    }
                }
                _winrtifacesAll = pSymbolLoader.getBSymmgr().AllocParams(typeList.Count, typeList.ToArray());
            }
            return(_winrtifacesAll);
        }
Example #18
0
            private bool FindNextTypeForInstanceMethods()
            {
                // Otherwise, search through other types listed as well as our base class.
                if (m_pContainingTypes.size > 0)
                {
                    if (m_nCurrentTypeCount >= m_pContainingTypes.size)
                    {
                        // No more types to check.
                        m_pCurrentType = null;
                    }
                    else
                    {
                        m_pCurrentType = m_pContainingTypes.Item(m_nCurrentTypeCount++).AsAggregateType();
                    }
                }
                else
                {
                    // We have no more types to consider, so check out the base class.

                    m_pCurrentType = m_pCurrentType.GetBaseClass();
                }
                return(m_pCurrentType != null);
            }
Example #19
0
        public static bool TypeContainsTyVars(CType type, TypeArray typeVars)
        {
        LRecurse:  // Label used for "tail" recursion.
            switch (type.GetTypeKind())
            {
                default:
                    Debug.Assert(false, "Bad Symbol kind in TypeContainsTyVars");
                    return false;

                case TypeKind.TK_UnboundLambdaType:
                case TypeKind.TK_BoundLambdaType:
                case TypeKind.TK_NullType:
                case TypeKind.TK_VoidType:
                case TypeKind.TK_OpenTypePlaceholderType:
                case TypeKind.TK_MethodGroupType:
                    return false;

                case TypeKind.TK_ArrayType:
                case TypeKind.TK_NullableType:
                case TypeKind.TK_ParameterModifierType:
                case TypeKind.TK_PointerType:
                    type = type.GetBaseOrParameterOrElementType();
                    goto LRecurse;

                case TypeKind.TK_AggregateType:
                    { // BLOCK
                        AggregateType ats = type.AsAggregateType();

                        for (int i = 0; i < ats.GetTypeArgsAll().Size; i++)
                        {
                            if (TypeContainsTyVars(ats.GetTypeArgsAll().Item(i), typeVars))
                            {
                                return true;
                            }
                        }
                    }
                    return false;

                case TypeKind.TK_ErrorType:
                    if (type.AsErrorType().HasParent())
                    {
                        ErrorType err = type.AsErrorType();
                        Debug.Assert(err.nameText != null && err.typeArgs != null);

                        for (int i = 0; i < err.typeArgs.Size; i++)
                        {
                            if (TypeContainsTyVars(err.typeArgs.Item(i), typeVars))
                            {
                                return true;
                            }
                        }
                        if (err.HasTypeParent())
                        {
                            type = err.GetTypeParent();
                            goto LRecurse;
                        }
                    }
                    return false;

                case TypeKind.TK_TypeParameterType:
                    if (typeVars != null && typeVars.Size > 0)
                    {
                        int ivar = type.AsTypeParameterType().GetIndexInTotalParameters();
                        return ivar < typeVars.Size && type == typeVars.Item(ivar);
                    }
                    return true;
            }
        }
Example #20
0
        public bool SubstEqualTypeArrays(TypeArray taDst, TypeArray taSrc, TypeArray typeArgsCls, TypeArray typeArgsMeth, SubstTypeFlags grfst)
        {
            // Handle the simple common cases first.
            if (taDst == taSrc || (taDst != null && taDst.Equals(taSrc)))
            {
                // The following assertion is not always true and indicates a problem where
                // the signature of override method does not match the one inherited from
                // the base class. The method match we have found does not take the type 
                // arguments of the base class into account. So actually we are not overriding
                // the method that we "intend" to. 
                // Debug.Assert(taDst == SubstTypeArray(taSrc, typeArgsCls, typeArgsMeth, grfst));
                return true;
            }
            if (taDst.Size != taSrc.Size)
                return false;
            if (taDst.Size == 0)
                return true;

            var ctx = new SubstContext(typeArgsCls, typeArgsMeth, grfst);

            if (ctx.FNop())
                return false;

            for (int i = 0; i < taDst.size; i++)
            {
                if (!SubstEqualTypesCore(taDst.Item(i), taSrc.Item(i), ctx))
                    return false;
            }

            return true;
        }
Example #21
0
        public TypeArray SubstTypeArray(TypeArray taSrc, TypeArray typeArgsCls, TypeArray typeArgsMeth, SubstTypeFlags grfst)
        {
            if (taSrc == null || taSrc.Size == 0)
                return taSrc;

            var ctx = new SubstContext(typeArgsCls, typeArgsMeth, grfst);

            if (ctx.FNop())
                return taSrc;

            CType[] prgpts = new CType[taSrc.Size];
            for (int ipts = 0; ipts < taSrc.Size; ipts++)
            {
                prgpts[ipts] = SubstTypeCore(taSrc.Item(ipts), ctx);
            }
            return _BSymmgr.AllocParams(taSrc.Size, prgpts);
        }
Example #22
0
        public TypeArray SubstTypeArray(TypeArray taSrc, SubstContext pctx)
        {
            if (taSrc == null || taSrc.Size == 0 || pctx == null || pctx.FNop())
                return taSrc;

            CType[] prgpts = new CType[taSrc.Size];
            for (int ipts = 0; ipts < taSrc.Size; ipts++)
            {
                prgpts[ipts] = this.SubstTypeCore(taSrc.Item(ipts), pctx);
            }
            return _BSymmgr.AllocParams(taSrc.size, prgpts);
        }
Example #23
0
            private void UpdateArguments()
            {
                // Parameter types might have changed as a result of
                // method type inference. 

                _pCurrentParameters = _pExprBinder.GetTypes().SubstTypeArray(
                        _pCurrentParameters, _pCurrentType, _pCurrentTypeArgs);

                // It is also possible that an optional argument has changed its value
                // as a result of method type inference. For example, when inferring
                // from Foo(10) to Foo<T>(T t1, T t2 = default(T)), the fabricated
                // argument list starts off as being (10, default(T)). After type
                // inference has successfully inferred T as int, it needs to be 
                // transformed into (10, default(int)) before applicability checking
                // notices that default(T) is not assignable to int.

                if (_pArguments.prgexpr == null || _pArguments.prgexpr.Count == 0)
                {
                    return;
                }

                MethodOrPropertySymbol pMethod = null;
                for (int iParam = 0; iParam < _pCurrentParameters.size; ++iParam)
                {
                    EXPR pArgument = _pArguments.prgexpr[iParam];
                    if (!pArgument.IsOptionalArgument)
                    {
                        continue;
                    }
                    CType pType = _pCurrentParameters.Item(iParam);

                    if (pType == pArgument.type)
                    {
                        continue;
                    }

                    // Argument has changed its type because of method type inference. Recompute it.
                    if (pMethod == null)
                    {
                        pMethod = FindMostDerivedMethod(_pCurrentSym, _pGroup.GetOptionalObject());
                        Debug.Assert(pMethod != null);
                    }
                    Debug.Assert(pMethod.IsParameterOptional(iParam));
                    EXPR pArgumentNew = GenerateOptionalArgument(GetSymbolLoader(), _pExprBinder.GetExprFactory(), pMethod, _pCurrentParameters[iParam], iParam);
                    _pArguments.prgexpr[iParam] = pArgumentNew;
                }
            }
        ////////////////////////////////////////////////////////////////////////////////
        // Determine which method is better for the purposes of overload resolution.
        // Better means: as least as good in all params, and better in at least one param.
        // Better w/r to a param means is an ordering, from best down:
        // 1) same type as argument
        // 2) implicit conversion from argument to formal type
        // Because of user defined conversion opers this relation is not transitive.
        //
        // If there is a tie because of identical signatures, the tie may be broken by the
        // following rules:
        // 1) If one is generic and the other isn't, the non-generic wins.
        // 2) Otherwise if one is expanded (params) and the other isn't, the non-expanded wins.
        // 3) Otherwise if one has more specific parameter types (at the declaration) it wins:
        //    This occurs if at least on parameter type is more specific and no parameter type is
        //    less specific.
        //* A type parameter is less specific than a non-type parameter.
        //* A constructed type is more specific than another constructed type if at least
        //      one type argument is more specific and no type argument is less specific than
        //      the corresponding type args in the other.
        // 4) Otherwise if one has more modopts than the other does, the smaller number of modopts wins.
        //
        // Returns Left if m1 is better, Right if m2 is better, or Neither/Same

        // REFACTOR: Much of this logic is duplicated in WhichTypeIsBetter in conversions.cpp.
        // REFACTOR: Refactor this so that it uses the existing logic rather than replicating it.

        protected BetterType WhichMethodIsBetter(
            CandidateFunctionMember node1,
            CandidateFunctionMember node2,
            CType pTypeThrough,
            ArgInfos args)
        {
            MethPropWithInst mpwi1 = node1.mpwi;
            MethPropWithInst mpwi2 = node2.mpwi;

            // Substitutions should have already been done on these!
            TypeArray pta1 = RearrangeNamedArguments(node1.@params, mpwi1, pTypeThrough, args);
            TypeArray pta2 = RearrangeNamedArguments(node2.@params, mpwi2, pTypeThrough, args);

            // If the parameter types for both candidate methods are identical,
            // use the tie breaking rules.

            if (pta1 == pta2)
            {
                return(WhichMethodIsBetterTieBreaker(node1, node2, pTypeThrough, args));
            }

            //  Otherwise, do a parameter-by-parameter comparison:
            //
            // Given an argument list A with a set of argument expressions {E1, ... En} and
            // two applicable function members Mp and Mq with parameter types {P1,... Pn} and
            // {Q1, ... Qn}, Mp is defined to be a better function member than Mq if:
            //* for each argument the implicit conversion from Ex to Qx is not better than
            //   the implicit conversion from Ex to Px.
            //* for at least one argument, the conversion from Ex to Px is better than the
            //   conversion from Ex to Qx.

            BetterType             betterMethod = BetterType.Neither;
            CType                  type1        = pTypeThrough != null ? pTypeThrough : mpwi1.GetType();
            CType                  type2        = pTypeThrough != null ? pTypeThrough : mpwi2.GetType();
            MethodOrPropertySymbol methProp1    = ExpressionBinder.GroupToArgsBinder.FindMostDerivedMethod(GetSymbolLoader(), mpwi1.MethProp(), type1);
            MethodOrPropertySymbol methProp2    = ExpressionBinder.GroupToArgsBinder.FindMostDerivedMethod(GetSymbolLoader(), mpwi2.MethProp(), type2);
            List <Name>            names1       = methProp1.ParameterNames;
            List <Name>            names2       = methProp2.ParameterNames;

            for (int i = 0; i < args.carg; i++)
            {
                EXPR  arg     = args.fHasExprs ? args.prgexpr[i] : null;
                CType argType = args.types.Item(i);
                CType p1      = pta1.Item(i);
                CType p2      = pta2.Item(i);

                // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                // RUNTIME BINDER ONLY CHANGE
                // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                //
                // We need to consider conversions from the actual runtime type
                // since we could have private interfaces that we are converting

                if (arg.RuntimeObjectActualType != null)
                {
                    argType = arg.RuntimeObjectActualType;
                }

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

                BetterType betterConversion = WhichConversionIsBetter(arg, argType, p1, p2);

                if (betterMethod == BetterType.Right && betterConversion == BetterType.Left)
                {
                    betterMethod = BetterType.Neither;
                    break;
                }
                else if (betterMethod == BetterType.Left && betterConversion == BetterType.Right)
                {
                    betterMethod = BetterType.Neither;
                    break;
                }
                else if (betterMethod == BetterType.Neither)
                {
                    if (betterConversion == BetterType.Right || betterConversion == BetterType.Left)
                    {
                        betterMethod = betterConversion;
                    }
                }
            }

            // We may have different sizes if we had optional parameters. If thats the case,
            // the one with fewer parameters wins (ie less optional parameters) unless it is
            // expanded. If so, the one with more parameters wins (ie option beats expanded).
            if (pta1.size != pta2.size && betterMethod == BetterType.Neither)
            {
                if (node1.fExpanded && !node2.fExpanded)
                {
                    return(BetterType.Right);
                }
                else if (node2.fExpanded && !node1.fExpanded)
                {
                    return(BetterType.Left);
                }

                // Here, if both methods needed to use optionals to fill in the signatures,
                // then we are ambiguous. Otherwise, take the one that didn't need any
                // optionals.

                if (pta1.size == args.carg)
                {
                    return(BetterType.Left);
                }
                else if (pta2.size == args.carg)
                {
                    return(BetterType.Right);
                }
                return(BetterType.Neither);
            }

            return(betterMethod);
        }
Example #25
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))    // UNDONE: 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();

                // DevDivBugs : 133313
                // 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);
        }
Example #26
0
 protected void ErrAppendTypeParameters(TypeArray @params, SubstContext pctx, bool forClass)
 {
     if (@params != null && @params.size != 0)
     {
         ErrAppendChar('<');
         ErrAppendType(@params.Item(0), pctx);
         for (int i = 1; i < @params.size; i++)
         {
             ErrAppendString(",");
             ErrAppendType(@params.Item(i), pctx);
         }
         ErrAppendChar('>');
     }
 }
Example #27
0
        /*
         * Create a fill-in string describing a parameter list.
         * Does NOT include ()
         */
        protected void ErrAppendParamList(TypeArray @params, bool isVarargs, bool isParamArray)
        {
            if (null == @params)
                return;

            for (int i = 0; i < @params.size; i++)
            {
                if (i > 0)
                {
                    ErrAppendString(", ");
                }

                if (isParamArray && i == @params.size - 1)
                {
                    ErrAppendString("params ");
                }

                // parameter type name
                ErrAppendType(@params.Item(i), null);
            }

            if (isVarargs)
            {
                if (@params.size != 0)
                {
                    ErrAppendString(", ");
                }

                ErrAppendString("...");
            }
        }
Example #28
0
 private bool UserDefinedBinaryOperatorCanBeLifted(ExpressionKind ek, MethodSymbol method, AggregateType ats,
     TypeArray Params)
 {
     if (!Params.Item(0).IsNonNubValType())
     {
         return false;
     }
     if (!Params.Item(1).IsNonNubValType())
     {
         return false;
     }
     CType typeRet = GetTypes().SubstType(method.RetType, ats);
     if (!typeRet.IsNonNubValType())
     {
         return false;
     }
     switch (ek)
     {
         case ExpressionKind.EK_EQ:
         case ExpressionKind.EK_NE:
             if (!typeRet.isPredefType(PredefinedType.PT_BOOL))
             {
                 return false;
             }
             if (Params.Item(0) != Params.Item(1))
             {
                 return false;
             }
             return true;
         case ExpressionKind.EK_GT:
         case ExpressionKind.EK_GE:
         case ExpressionKind.EK_LT:
         case ExpressionKind.EK_LE:
             if (!typeRet.isPredefType(PredefinedType.PT_BOOL))
             {
                 return false;
             }
             return true;
         default:
             return true;
     }
 }
Example #29
0
        private EXPRCALL BindUDBinopCall(EXPR arg1, EXPR arg2, TypeArray Params, CType typeRet, MethPropWithInst mpwi)
        {
            arg1 = mustConvert(arg1, Params.Item(0));
            arg2 = mustConvert(arg2, Params.Item(1));
            EXPRLIST args = GetExprFactory().CreateList(arg1, arg2);

            checkUnsafe(arg1.type); // added to the binder so we don't bind to pointer ops
            checkUnsafe(arg2.type); // added to the binder so we don't bind to pointer ops
            checkUnsafe(typeRet); // added to the binder so we don't bind to pointer ops


            EXPRMEMGRP pMemGroup = GetExprFactory().CreateMemGroup(null, mpwi);
            EXPRCALL call = GetExprFactory().CreateCall(0, typeRet, args, pMemGroup, null);
            call.mwi = new MethWithInst(mpwi);
            verifyMethodArgs(call, mpwi.GetType());
            return call;
        }
Example #30
0
        private EXPRCALL BindLiftedUDBinop(ExpressionKind ek, EXPR arg1, EXPR arg2, TypeArray Params, MethPropWithInst mpwi)
        {
            EXPR exprVal1 = arg1;
            EXPR exprVal2 = arg2;
            TypeArray paramsRaw;
            CType typeRet;
            CType typeRetRaw = GetTypes().SubstType(mpwi.Meth().RetType, mpwi.GetType());

            // This is a lifted user defined operator.  We know that both arguments
            // go to the nullable formal parameter types, and that at least one
            // of the arguments does not go to the non-nullable formal parameter type.
            // (If both went to the non-nullable types then we would not be lifting.)
            // We also know that the non-nullable type of the argument goes to the
            // non-nullable type of formal parameter.  However, if it does so only via
            // a user-defined conversion then we should bind the conversion from the
            // argument to the nullable formal parameter type first, before we then
            // do the cast for the non-nullable call.

            paramsRaw = GetTypes().SubstTypeArray(mpwi.Meth().Params, mpwi.GetType());
            Debug.Assert(Params != paramsRaw);
            Debug.Assert(paramsRaw.Item(0) == Params.Item(0).GetBaseOrParameterOrElementType());
            Debug.Assert(paramsRaw.Item(1) == Params.Item(1).GetBaseOrParameterOrElementType());

            if (!canConvert(arg1.type.StripNubs(), paramsRaw.Item(0), CONVERTTYPE.NOUDC))
            {
                exprVal1 = mustConvert(arg1, Params.Item(0));
            }
            if (!canConvert(arg2.type.StripNubs(), paramsRaw.Item(1), CONVERTTYPE.NOUDC))
            {
                exprVal2 = mustConvert(arg2, Params.Item(1));
            }
            EXPR nonLiftedArg1 = mustCast(exprVal1, paramsRaw.Item(0));
            EXPR nonLiftedArg2 = mustCast(exprVal2, paramsRaw.Item(1));
            switch (ek)
            {
                default:
                    typeRet = GetTypes().GetNullable(typeRetRaw);
                    break;
                case ExpressionKind.EK_EQ:
                case ExpressionKind.EK_NE:
                    Debug.Assert(paramsRaw.Item(0) == paramsRaw.Item(1));
                    Debug.Assert(typeRetRaw.isPredefType(PredefinedType.PT_BOOL));
                    // These ones don't lift the return type. Instead, if either side is null, the result is false.
                    typeRet = typeRetRaw;
                    break;
                case ExpressionKind.EK_GT:
                case ExpressionKind.EK_GE:
                case ExpressionKind.EK_LT:
                case ExpressionKind.EK_LE:
                    Debug.Assert(typeRetRaw.isPredefType(PredefinedType.PT_BOOL));
                    // These ones don't lift the return type. Instead, if either side is null, the result is false.
                    typeRet = typeRetRaw;
                    break;
            }

            // Now get the result for the pre-lifted call.

            Debug.Assert(!(ek == ExpressionKind.EK_EQ || ek == ExpressionKind.EK_NE) || nonLiftedArg1.type == nonLiftedArg2.type);

            EXPRCALL nonLiftedResult = BindUDBinopCall(nonLiftedArg1, nonLiftedArg2, paramsRaw, typeRetRaw, mpwi);

            EXPRLIST args = GetExprFactory().CreateList(exprVal1, exprVal2);
            EXPRMEMGRP pMemGroup = GetExprFactory().CreateMemGroup(null, mpwi);
            EXPRCALL call = GetExprFactory().CreateCall(0, typeRet, args, pMemGroup, null);
            call.mwi = new MethWithInst(mpwi);

            switch (ek)
            {
                case ExpressionKind.EK_EQ:
                    call.nubLiftKind = NullableCallLiftKind.EqualityOperator;
                    break;

                case ExpressionKind.EK_NE:
                    call.nubLiftKind = NullableCallLiftKind.InequalityOperator;
                    break;

                default:
                    call.nubLiftKind = NullableCallLiftKind.Operator;
                    break;
            }

            call.castOfNonLiftedResultToLiftedType = mustCast(nonLiftedResult, typeRet, 0);
            return call;
        }
        private CType LoadTypeFromSignature(int[] signature, ref int indexIntoSignatures, TypeArray classTyVars)
        {
            Debug.Assert(signature != null && signature != null);

            MethodSignatureEnum current = (MethodSignatureEnum)signature[indexIntoSignatures];
            indexIntoSignatures++;

            switch (current)
            {
                case MethodSignatureEnum.SIG_REF:
                    {
                        CType refType = LoadTypeFromSignature(signature, ref indexIntoSignatures, classTyVars);
                        if (refType == null)
                        {
                            return null;
                        }
                        return GetTypeManager().GetParameterModifier(refType, false);
                    }
                case MethodSignatureEnum.SIG_OUT:
                    {
                        CType outType = LoadTypeFromSignature(signature, ref indexIntoSignatures, classTyVars);
                        if (outType == null)
                        {
                            return null;
                        }
                        return GetTypeManager().GetParameterModifier(outType, true);
                    }
                case MethodSignatureEnum.SIG_SZ_ARRAY:
                    {
                        CType elementType = LoadTypeFromSignature(signature, ref indexIntoSignatures, classTyVars);
                        if (elementType == null)
                        {
                            return null;
                        }
                        return GetTypeManager().GetArray(elementType, 1);
                    }
                case MethodSignatureEnum.SIG_METH_TYVAR:
                    {
                        int index = signature[indexIntoSignatures];
                        indexIntoSignatures++;
                        return GetTypeManager().GetStdMethTypeVar(index);
                    }
                case MethodSignatureEnum.SIG_CLASS_TYVAR:
                    {
                        int index = signature[indexIntoSignatures];
                        indexIntoSignatures++;
                        return classTyVars.Item(index);
                    }
                case (MethodSignatureEnum)PredefinedType.PT_VOID:
                    return GetTypeManager().GetVoid();
                default:
                    {
                        Debug.Assert(current >= 0 && (int)current < (int)PredefinedType.PT_COUNT);
                        AggregateSymbol agg = GetOptPredefAgg((PredefinedType)current);
                        if (agg != null)
                        {
                            CType[] typeArgs = new CType[agg.GetTypeVars().size];
                            for (int iTypeArg = 0; iTypeArg < agg.GetTypeVars().size; iTypeArg++)
                            {
                                typeArgs[iTypeArg] = LoadTypeFromSignature(signature, ref indexIntoSignatures, classTyVars);
                                if (typeArgs[iTypeArg] == null)
                                {
                                    return null;
                                }
                            }
                            AggregateType type = GetTypeManager().GetAggregate(agg, getBSymmgr().AllocParams(agg.GetTypeVars().size, typeArgs));
                            if (type.isPredefType(PredefinedType.PT_G_OPTIONAL))
                            {
                                return GetTypeManager().GetNubFromNullable(type);
                            }

                            return type;
                        }
                    }
                    break;
            }

            return null;
        }
Example #32
0
        public bool AreAllTypeArgumentsUnitTypes(TypeArray typeArray)
        {
            if (typeArray.Size == 0)
            {
                return true;
            }

            for (int i = 0; i < typeArray.size; i++)
            {
                Debug.Assert(typeArray.Item(i) != null);
                if (!typeArray.Item(i).IsOpenTypePlaceholderType())
                {
                    return false;
                }
            }
            return true;
        }
Example #33
0
        public BetterType CompareTypes(TypeArray ta1, TypeArray ta2)
        {
            if (ta1 == ta2)
            {
                return(BetterType.Same);
            }
            if (ta1.Size != ta2.Size)
            {
                // The one with more parameters is more specific.
                return(ta1.Size > ta2.Size ? BetterType.Left : BetterType.Right);
            }

            BetterType nTot = BetterType.Neither;

            for (int i = 0; i < ta1.Size; i++)
            {
                CType      type1  = ta1.Item(i);
                CType      type2  = ta2.Item(i);
                BetterType nParam = BetterType.Neither;

LAgain:
                if (type1.GetTypeKind() != type2.GetTypeKind())
                {
                    if (type1.IsTypeParameterType())
                    {
                        nParam = BetterType.Right;
                    }
                    else if (type2.IsTypeParameterType())
                    {
                        nParam = BetterType.Left;
                    }
                }
                else
                {
                    switch (type1.GetTypeKind())
                    {
                    default:
                        Debug.Assert(false, "Bad kind in CompareTypes");
                        break;

                    case TypeKind.TK_TypeParameterType:
                    case TypeKind.TK_ErrorType:
                        break;

                    case TypeKind.TK_PointerType:
                    case TypeKind.TK_ParameterModifierType:
                    case TypeKind.TK_ArrayType:
                    case TypeKind.TK_NullableType:
                        type1 = type1.GetBaseOrParameterOrElementType();
                        type2 = type2.GetBaseOrParameterOrElementType();
                        goto LAgain;

                    case TypeKind.TK_AggregateType:
                        nParam = CompareTypes(type1.AsAggregateType().GetTypeArgsAll(), type2.AsAggregateType().GetTypeArgsAll());
                        break;
                    }
                }

                if (nParam == BetterType.Right || nParam == BetterType.Left)
                {
                    if (nTot == BetterType.Same || nTot == BetterType.Neither)
                    {
                        nTot = nParam;
                    }
                    else if (nParam != nTot)
                    {
                        return(BetterType.Neither);
                    }
                }
            }

            return(nTot);
        }
Example #34
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);
        }
Example #35
0
        ////////////////////////////////////////////////////////////////////////////////
        // Check whether typeArgs satisfies the constraints of typeVars. The 
        // typeArgsCls and typeArgsMeth are used for substitution on the bounds. The
        // tree and symErr are used for error reporting.

        private static bool CheckConstraintsCore(CSemanticChecker checker, ErrorHandling errHandling, Symbol symErr, TypeArray typeVars, TypeArray typeArgs, TypeArray typeArgsCls, TypeArray typeArgsMeth, CheckConstraintsFlags flags)
        {
            Debug.Assert(typeVars.size == typeArgs.size);
            Debug.Assert(typeVars.size > 0);
            Debug.Assert(flags == CheckConstraintsFlags.None || flags == CheckConstraintsFlags.NoErrors);

            bool fError = false;

            for (int i = 0; i < typeVars.size; i++)
            {
                // Empty bounds should be set to object.
                TypeParameterType var = typeVars.ItemAsTypeParameterType(i);
                CType arg = typeArgs.Item(i);

                bool fOK = CheckSingleConstraint(checker, errHandling, symErr, var, arg, typeArgsCls, typeArgsMeth, flags);
                fError |= !fOK;
            }

            return !fError;
        }
Example #36
0
        ////////////////////////////////////////////////////////////////////////////////
        // We need to rearange the method parameters so that the type of any specified named argument
        // appears in the same place as the named argument. Consider the example below:
        //    Foo(int x = 4, string y = "", long l = 4)
        //    Foo(string y = "", string x="", long l = 5)
        // and the call site:
        //    Foo(y:"a")
        // After rearranging the parameter types we will have:
        //   (string, int, long) and (string, string, long)
        // By rearranging the arguments as such we make sure that any specified named arguments appear in the same position for both
        // methods and we also maintain the relative order of the other parameters (the type long appears after int in the above example)

        private TypeArray RearrangeNamedArguments(TypeArray pta, MethPropWithInst mpwi,
            CType pTypeThrough, ArgInfos args)
        {
            if (!args.fHasExprs)
            {
                return pta;
            }

#if DEBUG
            // We never have a named argument that is in a position in the argument
            // list past the end of what would be the formal parameter list.
            for (int i = pta.size; i < args.carg; i++)
            {
                Debug.Assert(!args.prgexpr[i].isNamedArgumentSpecification());
            }
#endif

            CType type = pTypeThrough != null ? pTypeThrough : mpwi.GetType();
            CType[] typeList = new CType[pta.size];
            MethodOrPropertySymbol methProp = GroupToArgsBinder.FindMostDerivedMethod(GetSymbolLoader(), mpwi.MethProp(), type);

            // We initialize the new type array with the parameters for the method. 
            for (int iParam = 0; iParam < pta.size; iParam++)
            {
                typeList[iParam] = pta.Item(iParam);
            }

            // We then go over the specified arguments and put the type for any named argument in the right position in the array.
            for (int iParam = 0; iParam < args.carg; iParam++)
            {
                EXPR arg = args.prgexpr[iParam];
                if (arg.isNamedArgumentSpecification())
                {
                    // We find the index of the type of the argument in the method parameter list and store that in a temp
                    int index = FindName(methProp.ParameterNames, arg.asNamedArgumentSpecification().Name);
                    CType tempType = pta.Item(index);

                    // Starting from the current position in the type list up until the location of the type of the optional argument
                    //  We shift types by one:
                    //   before: (int, string, long)
                    //   after: (string, int, long)
                    // We only touch the types between the current position and the position of the type we need to move
                    for (int iShift = iParam; iShift < index; iShift++)
                    {
                        typeList[iShift + 1] = typeList[iShift];
                    }

                    typeList[iParam] = tempType;
                }
            }

            return GetSymbolLoader().getBSymmgr().AllocParams(pta.size, typeList);
        }
Example #37
0
            private bool bindImplicitConversionFromTypeVar(TypeParameterType tyVarSrc)
            {
                // 13.1.4
                //
                // For a type-parameter T that is known to be a reference type (25.7), the following implicit
                // reference conversions exist:
                //
                // *   From T to its effective base class C, from T to any base class of C, and from T to any
                //     interface implemented by C.
                // *   From T to an interface-type I in T's effective interface set and from T to any base
                //     interface of I.
                // *   From T to a type parameter U provided that T depends on U (25.7). [Note: Since T is known
                //     to be a reference type, within the scope of T, the run-time type of U will always be a
                //     reference type, even if U is not known to be a reference type at compile-time.]
                // *   From the null type (11.2.7) to T.
                //
                // 13.1.5
                //
                // For a type-parameter T that is not known to be a reference type (25.7), the following conversions
                // involving T are considered to be boxing conversions at compile-time. At run-time, if T is a value
                // type, the conversion is executed as a boxing conversion. At run-time, if T is a reference type,
                // the conversion is executed as an implicit reference conversion or identity conversion.
                //
                // *   From T to its effective base class C, from T to any base class of C, and from T to any
                //     interface implemented by C. [Note: C will be one of the types System.Object, System.ValueType,
                //     or System.Enum (otherwise T would be known to be a reference type and 13.1.4 would apply
                //     instead of this clause).]
                // *   From T to an interface-type I in T's effective interface set and from T to any base
                //     interface of I.
                //
                // 13.1.6 Implicit type parameter conversions
                //
                // This clause details implicit conversions involving type parameters that are not classified as
                // implicit reference conversions or implicit boxing conversions.
                //
                // For a type-parameter T that is not known to be a reference type, there is an implicit conversion
                // from T to a type parameter U provided T depends on U. At run-time, if T is a value type and U is
                // a reference type, the conversion is executed as a boxing conversion. At run-time, if both T and U
                // are value types, then T and U are necessarily the same type and no conversion is performed. At
                // run-time, if T is a reference type, then U is necessarily also a reference type and the conversion
                // is executed as an implicit reference conversion or identity conversion (25.7).

                CType     typeTmp = tyVarSrc.GetEffectiveBaseClass();
                TypeArray bnds    = tyVarSrc.GetBounds();
                int       itype   = -1;

                for (; ;)
                {
                    if (binder.canConvert(typeTmp, typeDest, flags | CONVERTTYPE.NOUDC))
                    {
                        if (!needsExprDest)
                        {
                            return(true);
                        }
                        if (typeDest.IsTypeParameterType())
                        {
                            // For a type var destination we need to cast to object then to the other type var.
                            EXPR      exprT;
                            EXPRCLASS exprObj = GetExprFactory().MakeClass(binder.GetReqPDT(PredefinedType.PT_OBJECT));
                            binder.bindSimpleCast(exprSrc, exprObj, out exprT, EXPRFLAG.EXF_FORCE_BOX);
                            binder.bindSimpleCast(exprT, exprTypeDest, out exprDest, EXPRFLAG.EXF_FORCE_UNBOX);
                        }
                        else
                        {
                            binder.bindSimpleCast(exprSrc, exprTypeDest, out exprDest, EXPRFLAG.EXF_FORCE_BOX);
                        }
                        return(true);
                    }
                    do
                    {
                        if (++itype >= bnds.Size)
                        {
                            return(false);
                        }
                        typeTmp = bnds.Item(itype);
                    }while (!typeTmp.isInterfaceType() && !typeTmp.IsTypeParameterType());
                }
            }
Example #38
0
        protected bool TryGetExpandedParams(TypeArray @params, int count, out TypeArray ppExpandedParams)
        {
            CType[] prgtype;
            if (count < @params.size - 1)
            {
                // The user has specified less arguments than our parameters, but we still
                // need to return our set of types without the param array. This is in the 
                // case that all the parameters are optional.
                prgtype = new CType[@params.size - 1];
                @params.CopyItems(0, @params.size - 1, prgtype);
                ppExpandedParams = GetGlobalSymbols().AllocParams(@params.size - 1, prgtype);
                return true;
            }

            prgtype = new CType[count];
            @params.CopyItems(0, @params.size - 1, prgtype);

            CType type = @params.Item(@params.size - 1);
            CType elementType = null;

            if (!type.IsArrayType())
            {
                ppExpandedParams = null;
                // If we don't have an array sym, we don't have expanded parameters.
                return false;
            }

            // At this point, we have an array sym.
            elementType = type.AsArrayType().GetElementType();

            for (int itype = @params.size - 1; itype < count; itype++)
            {
                prgtype[itype] = elementType;
            }

            ppExpandedParams = GetGlobalSymbols().AllocParams(prgtype);

            return true;
        }
Example #39
0
        /******************************************************************************
        *   Returns true if searching should continue to object.
        ******************************************************************************/
        private bool LookupInInterfaces(AggregateType typeStart, TypeArray types)
        {
            Debug.Assert(!_swtFirst || _fMulti);
            Debug.Assert(typeStart == null || typeStart.isInterfaceType());
            Debug.Assert(typeStart != null || types.size != 0);

            // Clear all the hidden flags. Anything found in a class hides any other
            // kind of member in all the interfaces.
            if (typeStart != null)
            {
                typeStart.fAllHidden  = false;
                typeStart.fDiffHidden = (_swtFirst != null);
            }

            for (int i = 0; i < types.size; i++)
            {
                AggregateType type = types.Item(i).AsAggregateType();
                Debug.Assert(type.isInterfaceType());
                type.fAllHidden  = false;
                type.fDiffHidden = !!_swtFirst;
            }

            bool          fHideObject = false;
            AggregateType typeCur     = typeStart;
            int           itypeNext   = 0;

            if (typeCur == null)
            {
                typeCur = types.Item(itypeNext++).AsAggregateType();
            }
            Debug.Assert(typeCur != null);

            // Loop through the interfaces.
            for (; ;)
            {
                Debug.Assert(typeCur != null && typeCur.isInterfaceType());

                bool fHideByName = false;

                if (!typeCur.fAllHidden && SearchSingleType(typeCur, out fHideByName))
                {
                    fHideByName |= !_fMulti;

                    // Mark base interfaces appropriately.
                    TypeArray ifaces = typeCur.GetIfacesAll();
                    for (int i = 0; i < ifaces.size; i++)
                    {
                        AggregateType type = ifaces.Item(i).AsAggregateType();
                        Debug.Assert(type.isInterfaceType());
                        if (fHideByName)
                        {
                            type.fAllHidden = true;
                        }
                        type.fDiffHidden = true;
                    }

                    // If we hide all base types, that includes object!
                    if (fHideByName)
                    {
                        fHideObject = true;
                    }
                }
                _flags &= ~MemLookFlags.TypeVarsAllowed;

                if (itypeNext >= types.size)
                {
                    return(!fHideObject);
                }

                // Substitution has already been done.
                typeCur = types.Item(itypeNext++).AsAggregateType();
            }
        }
Example #40
0
        /******************************************************************************
            Returns true if searching should continue to object.
        ******************************************************************************/
        private bool LookupInInterfaces(AggregateType typeStart, TypeArray types)
        {
            Debug.Assert(!_swtFirst || _fMulti);
            Debug.Assert(typeStart == null || typeStart.isInterfaceType());
            Debug.Assert(typeStart != null || types.size != 0);

            // Clear all the hidden flags. Anything found in a class hides any other
            // kind of member in all the interfaces.
            if (typeStart != null)
            {
                typeStart.fAllHidden = false;
                typeStart.fDiffHidden = (_swtFirst != null);
            }

            for (int i = 0; i < types.size; i++)
            {
                AggregateType type = types.Item(i).AsAggregateType();
                Debug.Assert(type.isInterfaceType());
                type.fAllHidden = false;
                type.fDiffHidden = !!_swtFirst;
            }

            bool fHideObject = false;
            AggregateType typeCur = typeStart;
            int itypeNext = 0;

            if (typeCur == null)
            {
                typeCur = types.Item(itypeNext++).AsAggregateType();
            }
            Debug.Assert(typeCur != null);

            // Loop through the interfaces.
            for (; ;)
            {
                Debug.Assert(typeCur != null && typeCur.isInterfaceType());

                bool fHideByName = false;

                if (!typeCur.fAllHidden && SearchSingleType(typeCur, out fHideByName))
                {
                    fHideByName |= !_fMulti;

                    // Mark base interfaces appropriately.
                    TypeArray ifaces = typeCur.GetIfacesAll();
                    for (int i = 0; i < ifaces.size; i++)
                    {
                        AggregateType type = ifaces.Item(i).AsAggregateType();
                        Debug.Assert(type.isInterfaceType());
                        if (fHideByName)
                            type.fAllHidden = true;
                        type.fDiffHidden = true;
                    }

                    // If we hide all base types, that includes object!
                    if (fHideByName)
                        fHideObject = true;
                }
                _flags &= ~MemLookFlags.TypeVarsAllowed;

                if (itypeNext >= types.size)
                    return !fHideObject;

                // Substitution has already been done.
                typeCur = types.Item(itypeNext++).AsAggregateType();
            }
        }