Пример #1
0
        // Initializes a substitution context. Returns false iff no substitutions will ever be performed.
        public void Init(TypeArray typeArgsCls, TypeArray typeArgsMeth, SubstTypeFlags grfst)
        {
            if (typeArgsCls != null)
            {
#if DEBUG
                typeArgsCls.AssertValid();
#endif
                ctypeCls = typeArgsCls.size;
                prgtypeCls = typeArgsCls.ToArray();
            }
            else
            {
                ctypeCls = 0;
                prgtypeCls = null;
            }

            if (typeArgsMeth != null)
            {
#if DEBUG
                typeArgsMeth.AssertValid();
#endif

                ctypeMeth = typeArgsMeth.size;
                prgtypeMeth = typeArgsMeth.ToArray();
            }
            else
            {
                ctypeMeth = 0;
                prgtypeMeth = null;
            }

            this.grfst = grfst;
        }
Пример #2
0
 public CMethodIterator(CSemanticChecker checker, SymbolLoader symLoader, Name name, TypeArray containingTypes, CType @object, CType qualifyingType, Declaration context, bool allowBogusAndInaccessible, bool allowExtensionMethods, int arity, EXPRFLAG flags, symbmask_t mask)
 {
     Debug.Assert(name != null);
     Debug.Assert(symLoader != null);
     Debug.Assert(checker != null);
     Debug.Assert(containingTypes != null);
     _pSemanticChecker = checker;
     _pSymbolLoader = symLoader;
     _pCurrentType = null;
     _pCurrentSym = null;
     _pName = name;
     _pContainingTypes = containingTypes;
     _pQualifyingType = qualifyingType;
     _pContext = context;
     _bAllowBogusAndInaccessible = allowBogusAndInaccessible;
     _bAllowExtensionMethods = allowExtensionMethods;
     _nArity = arity;
     _flags = flags;
     _mask = mask;
     _nCurrentTypeCount = 0;
     _bIsCheckingInstanceMethods = true;
     _bAtEnd = false;
     _bCurrentSymIsBogus = false;
     _bCurrentSymIsInaccessible = false;
     _bcanIncludeExtensionsInResults = _bAllowExtensionMethods;
     _bEndIterationAtCurrentExtensionList = false;
 }
Пример #3
0
            public GroupToArgsBinder(ExpressionBinder exprBinder, BindingFlag bindFlags, EXPRMEMGRP grp, ArgInfos args, ArgInfos originalArgs, bool bHasNamedArguments, AggregateType atsDelegate)
            {
                Debug.Assert(grp != null);
                Debug.Assert(exprBinder != null);
                Debug.Assert(args != null);

                _pExprBinder = exprBinder;
                _fCandidatesUnsupported = false;
                _fBindFlags = bindFlags;
                _pGroup = grp;
                _pArguments = args;
                _pOriginalArguments = originalArgs;
                _bHasNamedArguments = bHasNamedArguments;
                _pDelegate = atsDelegate;
                _pCurrentType = null;
                _pCurrentSym = null;
                _pCurrentTypeArgs = null;
                _pCurrentParameters = null;
                _pBestParameters = null;
                _nArgBest = -1;
                _nWrongCount = 0;
                _bIterateToEndOfNsList = false;
                _bBindingCollectionAddArgs = false;
                _results = new GroupToArgsBinderResult();
                _methList = new List<CandidateFunctionMember>();
                _mpwiParamTypeConstraints = new MethPropWithInst();
                _mpwiBogus = new MethPropWithInst();
                _mpwiCantInferInstArg = new MethPropWithInst();
                _mwtBadArity = new MethWithType();
                _HiddenTypes = new List<CType>();
            }
Пример #4
0
 public void SetBounds(TypeArray pBounds)
 {
     _pBounds = pBounds;
     _pInterfaceBounds = null;
     _pEffectiveBaseClass = null;
     _pDeducedBaseClass = null;
     _bHasRefBound = false;
     _bHasValBound = false;
 }
Пример #5
0
 public CMemberLookupResults(
         TypeArray containingTypes,
         Name name)
 {
     _pName = name;
     ContainingTypes = containingTypes;
     if (ContainingTypes == null)
     {
         ContainingTypes = BSYMMGR.EmptyTypeArray();
     }
 }
Пример #6
0
            /////////////////////////////////////////////////////////////////////////////////

            public void AddInconvertibleResult(
                MethodSymbol method,
                AggregateType currentType,
                TypeArray currentTypeArgs)
            {
                if (InconvertibleResult.Sym == null)
                {
                    // This is the first one, so set it for error reporting usage.
                    InconvertibleResult.Set(method, currentType, currentTypeArgs);
                }
                _inconvertibleResults.Add(new MethPropWithInst(method, currentType, currentTypeArgs));
            }
Пример #7
0
            /////////////////////////////////////////////////////////////////////////////////

            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;
            }
Пример #8
0
        // Aggregate
        public AggregateType CreateAggregateType(
            Name name,
            AggregateSymbol parent,
            TypeArray typeArgsThis,
            AggregateType outerType)
        {
            AggregateType type = new AggregateType();

            type.outerType = outerType;
            type.SetOwningAggregate(parent);
            type.SetTypeArgsThis(typeArgsThis);
            type.SetName(name);

            type.SetTypeKind(TypeKind.TK_AggregateType);
            return type;
        }
Пример #9
0
        public void SetTypeArgsThis(TypeArray pTypeArgsThis)
        {
            TypeArray pOuterTypeArgs;
            if (outerType != null)
            {
                Debug.Assert(outerType.GetTypeArgsThis() != null);
                Debug.Assert(outerType.GetTypeArgsAll() != null);

                pOuterTypeArgs = outerType.GetTypeArgsAll();
            }
            else
            {
                pOuterTypeArgs = BSYMMGR.EmptyTypeArray();
            }

            Debug.Assert(pTypeArgsThis != null);
            _pTypeArgsThis = pTypeArgsThis;
            SetTypeArgsAll(pOuterTypeArgs);
        }
Пример #10
0
        /*
        SPEC:

        CType inference occurs as part of the compile-time processing of a method invocation
        and takes place before the overload resolution step of the invocation. When a
        particular method group is specified in a method invocation, and no CType arguments
        are specified as part of the method invocation, CType inference is applied to each
        generic method in the method group. If CType inference succeeds, then the inferred
        CType arguments are used to determine the types of formal parameters for subsequent 
        overload resolution. If overload resolution chooses a generic method as the one to
        invoke then the inferred CType arguments are used as the actual CType arguments for the
        invocation. If CType inference for a particular method fails, that method does not
        participate in overload resolution. The failure of CType inference, in and of itself,
        does not cause a compile-time error. However, it often leads to a compile-time error
        when overload resolution then fails to find any applicable methods.

        If the supplied number of arguments is different than the number of parameters in
        the method, then inference immediately fails. Otherwise, assume that the generic
        method has the following signature:

        Tr M<X1...Xn>(T1 x1 ... Tm xm)

        With a method call of the form M(E1...Em) the task of CType inference is to find
        unique CType arguments S1...Sn for each of the CType parameters X1...Xn so that the
        call M<S1...Sn>(E1...Em)becomes valid.

        During the process of inference each CType parameter Xi is either fixed to a particular
        CType Si or unfixed with an associated set of bounds. Each of the bounds is some CType T.
        Each bound is classified as an upper bound, lower bound or exact bound.
        Initially each CType variable Xi is unfixed with an empty set of bounds.


        */

        // This file contains the implementation for method CType inference on calls (with
        // arguments, and method CType inference on conversion of method groups to delegate
        // types (which will not have arguments.)

        ////////////////////////////////////////////////////////////////////////////////

        public static bool Infer(
            ExpressionBinder binder,
            SymbolLoader symbolLoader,
            MethodSymbol pMethod,
            TypeArray pClassTypeArguments,
            TypeArray pMethodFormalParameterTypes,
            ArgInfos pMethodArguments,
            out TypeArray ppInferredTypeArguments)
        {
            Debug.Assert(pMethod != null);
            Debug.Assert(pMethod.typeVars.size > 0);
            Debug.Assert(pMethod.isParamArray || pMethod.Params == pMethodFormalParameterTypes);
            ppInferredTypeArguments = null;
            if (pMethodFormalParameterTypes.size == 0 || pMethod.InferenceMustFail())
            {
                return false;
            }
            Debug.Assert(pMethodArguments != null);
            Debug.Assert(pMethodFormalParameterTypes != null);
            Debug.Assert(pMethodArguments.carg <= pMethodFormalParameterTypes.size);

            var inferrer = new MethodTypeInferrer(binder, symbolLoader,
                pMethodFormalParameterTypes, pMethodArguments,
                pMethod.typeVars, pClassTypeArguments);
            bool success;
            if (pMethodArguments.fHasExprs)
            {
                success = inferrer.InferTypeArgs();
            }
            else
            {
                success = inferrer.InferForMethodGroupConversion();
            }

            ppInferredTypeArguments = inferrer.GetResults();
            return success;
        }
Пример #11
0
            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;
            }
Пример #12
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;
        }
Пример #13
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;
        }
Пример #14
0
 private CType SubstType(CType typeSrc, TypeArray typeArgsCls, TypeArray typeArgsMeth)
 {
     return(SubstType(typeSrc, typeArgsCls, typeArgsMeth, SubstTypeFlags.NormNone));
 }
Пример #15
0
 public TypeArray SubstTypeArray(TypeArray taSrc, TypeArray typeArgsCls) => SubstTypeArray(taSrc, typeArgsCls, null);
Пример #16
0
        private TypeArray LoadTypeArrayFromSignature(int[] signature, ref int indexIntoSignatures, TypeArray classTyVars)
        {
            Debug.Assert(signature != null);

            int count = signature[indexIntoSignatures];
            indexIntoSignatures++;

            Debug.Assert(count >= 0);

            CType[] ptypes = new CType[count];
            for (int i = 0; i < count; i++)
            {
                ptypes[i] = LoadTypeFromSignature(signature, ref indexIntoSignatures, classTyVars);
                if (ptypes[i] == null)
                {
                    return null;
                }
            }
            return getBSymmgr().AllocParams(count, ptypes);
        }
Пример #17
0
        public AggregateType GetAggregate(AggregateSymbol agg, AggregateType atsOuter, TypeArray typeArgs)
        {
            Debug.Assert(agg.GetTypeManager() == this);
            Debug.Assert(atsOuter == null || atsOuter.getAggregate() == agg.Parent, "");

            if (typeArgs == null)
            {
                typeArgs = BSYMMGR.EmptyTypeArray();
            }

            Debug.Assert(agg.GetTypeVars().Count == typeArgs.Count);
            AggregateType pAggregate = _typeTable.LookupAggregate(agg, atsOuter, typeArgs);

            if (pAggregate == null)
            {
                pAggregate = _typeFactory.CreateAggregateType(
                    agg,
                    typeArgs,
                    atsOuter
                    );

                Debug.Assert(!pAggregate.fConstraintsChecked && !pAggregate.fConstraintError);

                pAggregate.SetErrors(false);
                _typeTable.InsertAggregate(agg, atsOuter, typeArgs, pAggregate);

                // If we have a generic type definition, then we need to set the
                // base class to be our current base type, and use that to calculate
                // our agg type and its base, then set it to be the generic version of the
                // base type. This is because:
                //
                // Suppose we have Foo<T> : IFoo<T>
                //
                // Initially, the BaseType will be IFoo<Foo.T>, which gives us the substitution
                // that we want to use for our agg type's base type. However, in the Symbol chain,
                // we want the base type to be IFoo<IFoo.T>. Thats why we need to do this little trick.
                //
                // If we don't have a generic type definition, then we just need to set our base
                // class. This is so that if we have a base type that's generic, we'll be
                // getting the correctly instantiated base type.

                var baseType = pAggregate.AssociatedSystemType?.BaseType;
                if (baseType != null)
                {
                    // Store the old base class.

                    AggregateType oldBaseType = agg.GetBaseClass();
                    agg.SetBaseClass(_symbolTable.GetCTypeFromType(baseType) as AggregateType);
                    pAggregate.GetBaseClass(); // Get the base type for the new agg type we're making.

                    agg.SetBaseClass(oldBaseType);
                }
            }
            else
            {
                Debug.Assert(!pAggregate.HasErrors());
            }

            Debug.Assert(pAggregate.getAggregate() == agg);
            Debug.Assert(pAggregate.GetTypeArgsThis() != null && pAggregate.GetTypeArgsAll() != null);
            Debug.Assert(pAggregate.GetTypeArgsThis() == typeArgs);

            return(pAggregate);
        }
Пример #18
0
 public TypeArray SubstTypeArray(TypeArray taSrc, AggregateType atsCls, TypeArray typeArgsMeth)
 {
     return(SubstTypeArray(taSrc, atsCls?.GetTypeArgsAll(), typeArgsMeth));
 }
Пример #19
0
        ////////////////////////////////////////////////////////////////////////////////
        //
        // Fixed, unfixed and bounded CType parameters
        //
        // SPEC: During the process of inference each CType parameter is either fixed to
        // SPEC: a particular CType or unfixed with an associated set of bounds. Each of
        // SPEC: the bounds is of some CType T. Initially each CType parameter is unfixed
        // SPEC: with an empty set of bounds.

        private MethodTypeInferrer(
            ExpressionBinder exprBinder, SymbolLoader symLoader,
            TypeArray pMethodFormalParameterTypes, ArgInfos pMethodArguments,
            TypeArray pMethodTypeParameters, TypeArray pClassTypeArguments)
        {
            _binder = exprBinder;
            _symbolLoader = symLoader;
            _pMethodFormalParameterTypes = pMethodFormalParameterTypes;
            _pMethodArguments = pMethodArguments;
            _pMethodTypeParameters = pMethodTypeParameters;
            _pClassTypeArguments = pClassTypeArguments;
            _pFixedResults = new CType[pMethodTypeParameters.size];
            _pLowerBounds = new List<CType>[pMethodTypeParameters.size];
            _pUpperBounds = new List<CType>[pMethodTypeParameters.size];
            _pExactBounds = new List<CType>[pMethodTypeParameters.size];
            for (int iBound = 0; iBound < pMethodTypeParameters.size; ++iBound)
            {
                _pLowerBounds[iBound] = new List<CType>();
                _pUpperBounds[iBound] = new List<CType>();
                _pExactBounds[iBound] = new List<CType>();
            }
            _ppDependencies = null;
        }
Пример #20
0
 public CType SubstType(CType typeSrc, AggregateType atsCls, TypeArray typeArgsMeth)
 {
     return(SubstType(typeSrc, atsCls?.GetTypeArgsAll(), typeArgsMeth));
 }
Пример #21
0
 public CType SubstType(CType typeSrc, CType typeCls, TypeArray typeArgsMeth)
 {
     return(SubstType(typeSrc, (typeCls as AggregateType)?.GetTypeArgsAll(), typeArgsMeth));
 }
Пример #22
0
 public TypeArray ConcatenateTypeArrays(TypeArray pTypeArray1, TypeArray pTypeArray2)
 {
     return(_BSymmgr.ConcatParams(pTypeArray1, pTypeArray2));
 }
Пример #23
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_NullType:
            case TypeKind.TK_VoidType:
            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 = (AggregateType)type;

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

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

                    for (int i = 0; i < err.typeArgs.Count; i++)
                    {
                        if (TypeContainsTyVars(err.typeArgs[i], typeVars))
                        {
                            return(true);
                        }
                    }
                }

                return(false);

            case TypeKind.TK_TypeParameterType:
                if (typeVars != null && typeVars.Count > 0)
                {
                    int ivar = ((TypeParameterType)type).GetIndexInTotalParameters();
                    return(ivar < typeVars.Count && type == typeVars[ivar]);
                }
                return(true);
            }
        }
Пример #24
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.Count != taSrc.Count)
            {
                return(false);
            }
            if (taDst.Count == 0)
            {
                return(true);
            }

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

            if (ctx.FNop())
            {
                return(false);
            }

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

            return(true);
        }
Пример #25
0
        public bool SubstEqualTypes(CType typeDst, CType typeSrc, TypeArray typeArgsCls, TypeArray typeArgsMeth, SubstTypeFlags grfst)
        {
            if (typeDst.Equals(typeSrc))
            {
                Debug.Assert(typeDst.Equals(SubstType(typeSrc, typeArgsCls, typeArgsMeth, grfst)));
                return(true);
            }

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

            return(!ctx.FNop() && SubstEqualTypesCore(typeDst, typeSrc, ctx));
        }
Пример #26
0
 public TypeArray SubstTypeArray(TypeArray taSrc, AggregateType atsCls)
 {
     return(this.SubstTypeArray(taSrc, atsCls, (TypeArray)null));
 }
Пример #27
0
        private readonly Name _pName; // The name that we're looking for.

        public CMemberLookupResults()
        {
            _pName = null;
            ContainingTypes = null;
        }
Пример #28
0
 private bool SubstEqualTypes(CType typeDst, CType typeSrc, CType typeCls, TypeArray typeArgsMeth)
 {
     return(SubstEqualTypes(typeDst, typeSrc, (typeCls as AggregateType)?.GetTypeArgsAll(), typeArgsMeth, SubstTypeFlags.NormNone));
 }
Пример #29
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);
        }
Пример #30
0
        /***************************************************************************************************
        *   Determine whether there is an explicit or implicit reference conversion (or identity conversion)
        *   from typeSrc to typeDst. This is when:
        *
        *  13.2.3 Explicit reference conversions
        *
        *  The explicit reference conversions are:
        *   From object to any reference-type.
        *   From any class-type S to any class-type T, provided S is a base class of T.
        *   From any class-type S to any interface-type T, provided S is not sealed and provided S does not implement T.
        *   From any interface-type S to any class-type T, provided T is not sealed or provided T implements S.
        *   From any interface-type S to any interface-type T, provided S is not derived from T.
        *   From an array-type S with an element type SE to an array-type T with an element type TE, provided all of the following are true:
        *   o   S and T differ only in element type. (In other words, S and T have the same number of dimensions.)
        *   o   An explicit reference conversion exists from SE to TE.
        *   From System.Array and the interfaces it implements, to any array-type.
        *   From System.Delegate and the interfaces it implements, to any delegate-type.
        *   From a one-dimensional array-type S[] to System.Collections.Generic.IList<T>, System.Collections.Generic.IReadOnlyList<T> and their base interfaces, provided there is an explicit reference conversion from S to T.
        *   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.
        *   From System.Collections.Generic.IList<T>, System.Collections.Generic.IReadOnlyList<T> and their base interfaces to a one-dimensional array-type S[], provided there is an implicit or explicit reference conversion from S[] to System.Collections.Generic.IList<T> or System.Collections.Generic.IReadOnlyList<T>. This is precisely when either S and T are the same type or there is an implicit or explicit reference conversion from S to T.
        *
        *  For a type-parameter T that is known to be a reference type (§25.7), the following explicit reference conversions exist:
        *   From the effective base class C of T to T and from any base class of C to T.
        *   From any interface-type to T.
        *   From T to any interface-type I provided there isn’t already an implicit reference conversion from T to I.
        *   From a type-parameter U to T 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. end note]
        *
        * Both src and dst are reference types and there is a builtin explicit conversion from
        *     src to dst.
        * Or src is a reference type and dst is a base type of src (in which case the conversion is
        *     implicit as well).
        * Or dst is a reference type and src is a base type of dst.
        *
        *   The latter two cases can happen with type variables even though the other type variable is not
        *   a reference type.
        ***************************************************************************************************/
        public static bool FExpRefConv(SymbolLoader loader, CType typeSrc, CType typeDst)
        {
            Debug.Assert(typeSrc != null);
            Debug.Assert(typeDst != null);
            if (typeSrc.IsRefType() && typeDst.IsRefType())
            {
                // is there an implicit reference conversion in either direction?
                // this handles the bulk of the cases ...
                if (loader.HasIdentityOrImplicitReferenceConversion(typeSrc, typeDst) ||
                    loader.HasIdentityOrImplicitReferenceConversion(typeDst, typeSrc))
                {
                    return(true);
                }

                // For a type-parameter T that is known to be a reference type (§25.7), the following explicit reference conversions exist:
                // •    From any interface-type to T.
                // •    From T to any interface-type I provided there isn’t already an implicit reference conversion from T to I.
                if (typeSrc.isInterfaceType() && typeDst is TypeParameterType)
                {
                    return(true);
                }
                if (typeSrc is TypeParameterType && typeDst.isInterfaceType())
                {
                    return(true);
                }

                // * From any class-type S to any interface-type T, provided S is not sealed
                // * From any interface-type S to any class-type T, provided T is not sealed
                // * From any interface-type S to any interface-type T, provided S is not derived from T.
                if (typeSrc is AggregateType atSrc && typeDst is AggregateType atDst)
                {
                    AggregateSymbol aggSrc  = atSrc.getAggregate();
                    AggregateSymbol aggDest = atDst.getAggregate();

                    if ((aggSrc.IsClass() && !aggSrc.IsSealed() && aggDest.IsInterface()) ||
                        (aggSrc.IsInterface() && aggDest.IsClass() && !aggDest.IsSealed()) ||
                        (aggSrc.IsInterface() && aggDest.IsInterface()))
                    {
                        return(true);
                    }
                }

                if (typeSrc is ArrayType arrSrc)
                {
                    // *    From an array-type S with an element type SE to an array-type T with an element type TE, provided all of the following are true:
                    //     o    S and T differ only in element type. (In other words, S and T have the same number of dimensions.)
                    //     o    An explicit reference conversion exists from SE to TE.
                    if (typeDst is ArrayType arrDst)
                    {
                        return(arrSrc.rank == arrDst.rank &&
                               arrSrc.IsSZArray == arrDst.IsSZArray &&
                               FExpRefConv(loader, arrSrc.GetElementType(), arrDst.GetElementType()));
                    }

                    // *    From a one-dimensional array-type S[] to System.Collections.Generic.IList<T>, System.Collections.Generic.IReadOnlyList<T>
                    //      and their base interfaces, provided there is an explicit reference conversion from S to T.
                    if (!arrSrc.IsSZArray ||
                        !typeDst.isInterfaceType())
                    {
                        return(false);
                    }

                    AggregateType aggDst      = (AggregateType)typeDst;
                    TypeArray     typeArgsAll = aggDst.GetTypeArgsAll();

                    if (typeArgsAll.Count != 1)
                    {
                        return(false);
                    }

                    AggregateSymbol aggIList         = loader.GetPredefAgg(PredefinedType.PT_G_ILIST);
                    AggregateSymbol aggIReadOnlyList = loader.GetPredefAgg(PredefinedType.PT_G_IREADONLYLIST);

                    if ((aggIList == null ||
                         !SymbolLoader.IsBaseAggregate(aggIList, aggDst.getAggregate())) &&
                        (aggIReadOnlyList == null ||
                         !SymbolLoader.IsBaseAggregate(aggIReadOnlyList, aggDst.getAggregate())))
                    {
                        return(false);
                    }

                    return(FExpRefConv(loader, arrSrc.GetElementType(), typeArgsAll[0]));
                }

                if (typeDst is ArrayType arrayDest && typeSrc is AggregateType aggtypeSrc)
                {
                    // * From System.Array and the interfaces it implements, to any array-type.
                    if (loader.HasIdentityOrImplicitReferenceConversion(loader.GetPredefindType(PredefinedType.PT_ARRAY), typeSrc))
                    {
                        return(true);
                    }

                    // *    From System.Collections.Generic.IList<T>, System.Collections.Generic.IReadOnlyList<T> and their base interfaces to a
                    //      one-dimensional array-type S[], provided there is an implicit or explicit reference conversion from S[] to
                    //      System.Collections.Generic.IList<T> or System.Collections.Generic.IReadOnlyList<T>. This is precisely when either S and T
                    //      are the same type or there is an implicit or explicit reference conversion from S to T.
                    if (!arrayDest.IsSZArray || !typeSrc.isInterfaceType() ||
                        aggtypeSrc.GetTypeArgsAll().Count != 1)
                    {
                        return(false);
                    }

                    AggregateSymbol aggIList         = loader.GetPredefAgg(PredefinedType.PT_G_ILIST);
                    AggregateSymbol aggIReadOnlyList = loader.GetPredefAgg(PredefinedType.PT_G_IREADONLYLIST);

                    if ((aggIList == null ||
                         !SymbolLoader.IsBaseAggregate(aggIList, aggtypeSrc.getAggregate())) &&
                        (aggIReadOnlyList == null ||
                         !SymbolLoader.IsBaseAggregate(aggIReadOnlyList, aggtypeSrc.getAggregate())))
                    {
                        return(false);
                    }

                    CType typeArr = arrayDest.GetElementType();
                    CType typeLst = aggtypeSrc.GetTypeArgsAll()[0];

                    Debug.Assert(!(typeArr is MethodGroupType));
                    return(typeArr == typeLst || FExpRefConv(loader, typeArr, typeLst));
                }
                if (HasGenericDelegateExplicitReferenceConversion(loader, typeSrc, typeDst))
                {
                    return(true);
                }
            }
            else if (typeSrc.IsRefType())
            {
                // conversion of T . U, where T : class, U
                // .. these constraints implies where U : class
                return(loader.HasIdentityOrImplicitReferenceConversion(typeSrc, typeDst));
            }
            else if (typeDst.IsRefType())
            {
                // conversion of T . U, where U : class, T
                // .. these constraints implies where T : class
                return(loader.HasIdentityOrImplicitReferenceConversion(typeDst, typeSrc));
            }
            return(false);
        }
 public static ExprMethodInfo CreateMethodInfo(MethodSymbol method, AggregateType methodType, TypeArray methodParameters) =>
 new ExprMethodInfo(
     TypeManager.GetPredefAgg(method.IsConstructor() ? PredefinedType.PT_CONSTRUCTORINFO : PredefinedType.PT_METHODINFO).getThisType(),
     method, methodType, methodParameters);
Пример #32
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 is NullableType nub)
            {
                CType typeT = nub.GetAts(checker.GetErrorContext());
                if (typeT != null)
                {
                    type = typeT;
                }
                else
                {
                    type = type.GetNakedType(true);
                }
            }

            if (!(type is AggregateType ats))
            {
                return(true);
            }

            if (ats.GetTypeArgsAll().Count == 0)
            {
                // Common case: there are no type vars, so there are no constraints.
                ats.fConstraintsChecked = true;
                ats.fConstraintError    = false;
                return(true);
            }

            if (ats.fConstraintsChecked)
            {
                // Already checked.
                if (!ats.fConstraintError || (flags & CheckConstraintsFlags.NoDupErrors) != 0)
                {
                    // No errors or no need to report errors again.
                    return(!ats.fConstraintError);
                }
            }

            TypeArray typeVars     = ats.getAggregate().GetTypeVars();
            TypeArray typeArgsThis = ats.GetTypeArgsThis();
            TypeArray typeArgsAll  = ats.GetTypeArgsAll();

            Debug.Assert(typeVars.Count == typeArgsThis.Count);

            if (!ats.fConstraintsChecked)
            {
                ats.fConstraintsChecked = true;
                ats.fConstraintError    = false;
            }

            // Check the outer type first. If CheckConstraintsFlags.Outer is not specified and the
            // outer type has already been checked then don't bother checking it.
            if (ats.outerType != null && ((flags & CheckConstraintsFlags.Outer) != 0 || !ats.outerType.fConstraintsChecked))
            {
                CheckConstraints(checker, errHandling, ats.outerType, flags);
                ats.fConstraintError |= ats.outerType.fConstraintError;
            }

            if (typeVars.Count > 0)
            {
                ats.fConstraintError |= !CheckConstraintsCore(checker, errHandling, ats.getAggregate(), typeVars, typeArgsThis, typeArgsAll, null, (flags & CheckConstraintsFlags.NoErrors));
            }

            // Now check type args themselves.
            for (int i = 0; i < typeArgsThis.Count; i++)
            {
                CType arg = typeArgsThis[i].GetNakedType(true);
                if (arg is AggregateType atArg && !atArg.fConstraintsChecked)
                {
                    CheckConstraints(checker, errHandling, atArg, flags | CheckConstraintsFlags.Outer);
                    if (atArg.fConstraintError)
                    {
                        ats.fConstraintError = true;
                    }
                }
            }
            return(!ats.fConstraintError);
        }
Пример #33
0
 public CType SubstType(CType typeSrc, TypeArray typeArgsCls)
 {
     return(SubstType(typeSrc, typeArgsCls, null, SubstTypeFlags.NormNone));
 }
Пример #34
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.Count == typeArgs.Count);
            Debug.Assert(typeVars.Count > 0);
            Debug.Assert(flags == CheckConstraintsFlags.None || flags == CheckConstraintsFlags.NoErrors);

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

                if (!CheckSingleConstraint(checker, errHandling, symErr, var, arg, typeArgsCls, typeArgsMeth, flags))
                {
                    return(false);
                }
            }

            return(true);
        }
Пример #35
0
 public TypeArray SubstTypeArray(TypeArray taSrc, TypeArray typeArgsCls, TypeArray typeArgsMeth)
 => taSrc == null || taSrc.Count == 0
     ? taSrc
     : SubstTypeArray(taSrc, new SubstContext(typeArgsCls, typeArgsMeth, SubstTypeFlags.NormNone));
Пример #36
0
        public void SetTypeArgsAll(TypeArray outerTypeArgs)
        {
            Debug.Assert(_pTypeArgsThis != null);

            // Here we need to check our current type args. If we have an open placeholder,
            // then we need to have all open placeholders, and we want to flush
            // our outer type args so that they're open placeholders. 
            //
            // This is because of the following scenario:
            //
            // class B<T>
            // {
            //     class C<U>
            //     {
            //     }
            //     class D
            //     {
            //         void Foo()
            //         {
            //             Type T = typeof(C<>);
            //         }
            //     }
            // }
            //
            // The outer type will be B<T>, but the inner type will be C<>. However,
            // this will eventually be represented in IL as B<>.C<>. As such, we should
            // keep our data structures clear - if we have one open type argument, then
            // all of them must be open type arguments.
            //
            // Ensure that invariant here.

            TypeArray pCheckedOuterTypeArgs = outerTypeArgs;
            TypeManager pTypeManager = getAggregate().GetTypeManager();

            if (_pTypeArgsThis.Size > 0 && AreAllTypeArgumentsUnitTypes(_pTypeArgsThis))
            {
                if (outerTypeArgs.Size > 0 && !AreAllTypeArgumentsUnitTypes(outerTypeArgs))
                {
                    // We have open placeholder types in our type, but not the parent.
                    pCheckedOuterTypeArgs = pTypeManager.CreateArrayOfUnitTypes(outerTypeArgs.Size);
                }
            }
            _pTypeArgsAll = pTypeManager.ConcatenateTypeArrays(pCheckedOuterTypeArgs, _pTypeArgsThis);
        }
Пример #37
0
        private CType SubstTypeCore(CType type, SubstContext pctx)
        {
            CType typeSrc;
            CType typeDst;

            switch (type.GetTypeKind())
            {
            default:
                Debug.Assert(false);
                return(type);

            case TypeKind.TK_NullType:
            case TypeKind.TK_VoidType:
            case TypeKind.TK_MethodGroupType:
            case TypeKind.TK_ArgumentListType:
            case TypeKind.TK_ErrorType:
                return(type);

            case TypeKind.TK_ParameterModifierType:
                ParameterModifierType mod = (ParameterModifierType)type;
                typeDst = SubstTypeCore(typeSrc = mod.GetParameterType(), pctx);
                return((typeDst == typeSrc) ? type : GetParameterModifier(typeDst, mod.isOut));

            case TypeKind.TK_ArrayType:
                var arr = (ArrayType)type;
                typeDst = SubstTypeCore(typeSrc = arr.GetElementType(), pctx);
                return((typeDst == typeSrc) ? type : GetArray(typeDst, arr.rank, arr.IsSZArray));

            case TypeKind.TK_PointerType:
                typeDst = SubstTypeCore(typeSrc = ((PointerType)type).GetReferentType(), pctx);
                return((typeDst == typeSrc) ? type : GetPointer(typeDst));

            case TypeKind.TK_NullableType:
                typeDst = SubstTypeCore(typeSrc = ((NullableType)type).GetUnderlyingType(), pctx);
                return((typeDst == typeSrc) ? type : GetNullable(typeDst));

            case TypeKind.TK_AggregateType:
                AggregateType ats = (AggregateType)type;
                if (ats.GetTypeArgsAll().Count > 0)
                {
                    TypeArray typeArgs = SubstTypeArray(ats.GetTypeArgsAll(), pctx);
                    if (ats.GetTypeArgsAll() != typeArgs)
                    {
                        return(GetAggregate(ats.getAggregate(), typeArgs));
                    }
                }
                return(type);

            case TypeKind.TK_TypeParameterType:
            {
                TypeParameterSymbol tvs = ((TypeParameterType)type).GetTypeParameterSymbol();
                int index = tvs.GetIndexInTotalParameters();
                if (tvs.IsMethodTypeParameter())
                {
                    if ((pctx.grfst & SubstTypeFlags.DenormMeth) != 0 && tvs.parent != null)
                    {
                        return(type);
                    }
                    Debug.Assert(tvs.GetIndexInOwnParameters() == tvs.GetIndexInTotalParameters());
                    if (index < pctx.ctypeMeth)
                    {
                        Debug.Assert(pctx.prgtypeMeth != null);
                        return(pctx.prgtypeMeth[index]);
                    }
                    else
                    {
                        return((pctx.grfst & SubstTypeFlags.NormMeth) != 0 ? GetStdMethTypeVar(index) : type);
                    }
                }
                if ((pctx.grfst & SubstTypeFlags.DenormClass) != 0 && tvs.parent != null)
                {
                    return(type);
                }
                return(index < pctx.ctypeCls ? pctx.prgtypeCls[index] :
                       ((pctx.grfst & SubstTypeFlags.NormClass) != 0 ? GetStdClsTypeVar(index) : type));
            }
            }
        }
Пример #38
0
 public TypeArray ConcatParams(TypeArray pta1, TypeArray pta2)
 {
     return(ConcatParams(pta1.ToArray(), pta2.ToArray()));
 }
Пример #39
0
 public TypeArray GetIfacesAll()
 {
     if (_ifacesAll == null)
     {
         _ifacesAll = getAggregate().GetTypeManager().SubstTypeArray(getAggregate().GetIfacesAll(), GetTypeArgsAll());
     }
     return _ifacesAll;
 }
Пример #40
0
 public void SetIfaces(TypeArray ifaces)
 {
     _ifaces = ifaces;
 }
Пример #41
0
        private static bool CheckSingleConstraint(CSemanticChecker checker, ErrorHandling errHandling, Symbol symErr, TypeParameterType var, CType arg, TypeArray typeArgsCls, TypeArray typeArgsMeth, CheckConstraintsFlags flags)
        {
            Debug.Assert(!(arg is PointerType));
            Debug.Assert(!arg.IsStaticClass);

            bool fReportErrors = 0 == (flags & CheckConstraintsFlags.NoErrors);

            if (var.HasRefConstraint && !arg.IsReferenceType)
            {
                if (fReportErrors)
                {
                    throw errHandling.Error(ErrorCode.ERR_RefConstraintNotSatisfied, symErr, new ErrArgNoRef(var), arg);
                }

                return(false);
            }

            TypeArray bnds     = checker.SymbolLoader.GetTypeManager().SubstTypeArray(var.Bounds, 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.

                if (!arg.IsNonNullableValueType)
                {
                    if (fReportErrors)
                    {
                        throw errHandling.Error(ErrorCode.ERR_ValConstraintNotSatisfied, symErr, new ErrArgNoRef(var), arg);
                    }

                    return(false);
                }

                // 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.IsReferenceType)
                        {
                            // 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.SymbolLoader.HasBaseConversion(nubArg.UnderlyingType, 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.UnderlyingType == 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
                        {
                            // 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;
                        }

                        throw errHandling.Error(error, new ErrArg(symErr), new ErrArg(typeBnd, ErrArgFlags.Unique), var, new ErrArg(arg, ErrArgFlags.Unique));
                    }

                    return(false);
                }
            }
Пример #42
0
        private bool TryVarianceAdjustmentToGetAccessibleType(CSemanticChecker semanticChecker, BindingContext bindingContext, AggregateType typeSrc, out CType typeDst)
        {
            Debug.Assert(typeSrc != null);
            Debug.Assert(typeSrc.isInterfaceType() || typeSrc.isDelegateType());

            typeDst = null;

            AggregateSymbol aggSym      = typeSrc.GetOwningAggregate();
            AggregateType   aggOpenType = aggSym.getThisType();

            if (!semanticChecker.CheckTypeAccess(aggOpenType, bindingContext.ContextForMemberLookup))
            {
                // if the aggregate symbol itself is not accessible, then forget it, there is no
                // variance that will help us arrive at an accessible type.
                return(false);
            }

            TypeArray typeArgs   = typeSrc.GetTypeArgsThis();
            TypeArray typeParams = aggOpenType.GetTypeArgsThis();

            CType[] newTypeArgsTemp = new CType[typeArgs.Count];

            for (int i = 0; i < typeArgs.Count; i++)
            {
                if (semanticChecker.CheckTypeAccess(typeArgs[i], bindingContext.ContextForMemberLookup))
                {
                    // we have an accessible argument, this position is not a problem.
                    newTypeArgsTemp[i] = typeArgs[i];
                    continue;
                }

                if (!typeArgs[i].IsRefType() || !((TypeParameterType)typeParams[i]).Covariant)
                {
                    // This guy is inaccessible, and we are not going to be able to vary him, so we need to fail.
                    return(false);
                }

                CType intermediateTypeArg;
                if (GetBestAccessibleType(semanticChecker, bindingContext, typeArgs[i], out intermediateTypeArg))
                {
                    // now we either have a value type (which must be accessible due to the above
                    // check, OR we have an inaccessible type (which must be a ref type). In either
                    // case, the recursion worked out and we are OK to vary this argument.
                    newTypeArgsTemp[i] = intermediateTypeArg;
                    continue;
                }
                else
                {
                    Debug.Assert(false, "GetBestAccessibleType unexpectedly failed on a type that was used as a type parameter");
                    return(false);
                }
            }

            TypeArray newTypeArgs      = semanticChecker.getBSymmgr().AllocParams(typeArgs.Count, newTypeArgsTemp);
            CType     intermediateType = this.GetAggregate(aggSym, typeSrc.outerType, newTypeArgs);

            // All type arguments were varied successfully, which means now we must be accessible. But we could
            // have violated constraints. Let's check that out.

            if (!TypeBind.CheckConstraints(semanticChecker, null /*ErrorHandling*/, intermediateType, CheckConstraintsFlags.NoErrors))
            {
                return(false);
            }

            typeDst = intermediateType;
            Debug.Assert(semanticChecker.CheckTypeAccess(typeDst, bindingContext.ContextForMemberLookup));
            return(true);
        }
Пример #43
0
        public ErrorType CreateError(
            Name name,
            CType parent,
            AssemblyQualifiedNamespaceSymbol pParentNS,
            Name nameText,
            TypeArray typeArgs)
        {
            ErrorType e = new ErrorType();
            e.SetName(name);
            e.nameText = nameText;
            e.typeArgs = typeArgs;
            e.SetTypeParent(parent);
            e.SetNSParent(pParentNS);

            e.SetTypeKind(TypeKind.TK_ErrorType);
            return e;
        }
Пример #44
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 is AggregateType ats))
            {
                if (type is NullableType nub)
                {
                    ats = nub.GetAts();
                }
                else
                {
                    return(true);
                }
            }

            if (ats.TypeArgsAll.Count == 0)
            {
                // Common case: there are no type vars, so there are no constraints.
                ats.ConstraintError = false;
                return(true);
            }

            // Already checked.
            if (ats.ConstraintError.HasValue)
            {
                // No errors
                if (!ats.ConstraintError.GetValueOrDefault())
                {
                    return(true);
                }

                // We want the result, not an exception.
                if ((flags & CheckConstraintsFlags.NoErrors) != 0)
                {
                    return(false);
                }
            }

            TypeArray typeVars     = ats.OwningAggregate.GetTypeVars();
            TypeArray typeArgsThis = ats.TypeArgsThis;
            TypeArray typeArgsAll  = ats.TypeArgsAll;

            Debug.Assert(typeVars.Count == typeArgsThis.Count);

            // 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.ConstraintError.HasValue))
            {
                if (!CheckConstraints(checker, errHandling, ats.OuterType, flags))
                {
                    ats.ConstraintError = true;
                    return(false);
                }
            }

            if (typeVars.Count > 0)
            {
                if (!CheckConstraintsCore(checker, errHandling, ats.OwningAggregate, typeVars, typeArgsThis, typeArgsAll, null, flags & CheckConstraintsFlags.NoErrors))
                {
                    ats.ConstraintError = true;
                    return(false);
                }
            }

            // Now check type args themselves.
            for (int i = 0; i < typeArgsThis.Count; i++)
            {
                CType arg = typeArgsThis[i].GetNakedType(true);
                if (arg is AggregateType atArg && !atArg.ConstraintError.HasValue)
                {
                    CheckConstraints(checker, errHandling, atArg, flags | CheckConstraintsFlags.Outer);
                    if (atArg.ConstraintError.GetValueOrDefault())
                    {
                        ats.ConstraintError = true;
                        return(false);
                    }
                }
            }

            ats.ConstraintError = false;
            return(true);
        }
Пример #45
0
        public void SetTypeVars(TypeArray typeVars)
        {
            if (typeVars == null)
            {
                _typeVarsThis = null;
                _typeVarsAll = null;
            }
            else
            {
                TypeArray outerTypeVars;
                if (this.GetOuterAgg() != null)
                {
                    Debug.Assert(this.GetOuterAgg().GetTypeVars() != null);
                    Debug.Assert(this.GetOuterAgg().GetTypeVarsAll() != null);

                    outerTypeVars = this.GetOuterAgg().GetTypeVarsAll();
                }
                else
                {
                    outerTypeVars = BSYMMGR.EmptyTypeArray();
                }

                _typeVarsThis = typeVars;
                _typeVarsAll = _pTypeManager.ConcatenateTypeArrays(outerTypeVars, typeVars);
            }
        }
 public SubstContext(TypeArray typeArgsCls, TypeArray typeArgsMeth, SubstTypeFlags grfst)
 {
     Init(typeArgsCls, typeArgsMeth, grfst);
 }
Пример #47
0
 public void SetIfacesAll(TypeArray ifacesAll)
 {
     _ifacesAll = ifacesAll;
 }
 public SubstContext(AggregateType type, TypeArray typeArgsMeth)
     : this(type, typeArgsMeth, SubstTypeFlags.NormNone)
 {
 }
Пример #49
0
        public AggregateType GetAggregate(AggregateSymbol agg, AggregateType atsOuter, TypeArray typeArgs)
        {
            Debug.Assert(agg.GetTypeManager() == this);
            Debug.Assert(atsOuter == null || atsOuter.getAggregate() == agg.Parent, "");

            if (typeArgs == null)
            {
                typeArgs = BSYMMGR.EmptyTypeArray();
            }

            Debug.Assert(agg.GetTypeVars().Count == typeArgs.Count);
            AggregateType pAggregate = _typeTable.LookupAggregate(agg, atsOuter, typeArgs);

            if (pAggregate == null)
            {
                pAggregate = _typeFactory.CreateAggregateType(
                    agg,
                    typeArgs,
                    atsOuter
                    );

                Debug.Assert(!pAggregate.fConstraintsChecked && !pAggregate.fConstraintError);

                _typeTable.InsertAggregate(agg, atsOuter, typeArgs, pAggregate);
            }

            Debug.Assert(pAggregate.getAggregate() == agg);
            Debug.Assert(pAggregate.GetTypeArgsThis() != null && pAggregate.GetTypeArgsAll() != null);
            Debug.Assert(pAggregate.GetTypeArgsThis() == typeArgs);

            return(pAggregate);
        }
 public SubstContext(AggregateType type, TypeArray typeArgsMeth, SubstTypeFlags grfst)
 {
     Init(type != null ? type.GetTypeArgsAll() : null, typeArgsMeth, grfst);
 }
Пример #51
0
        ////////////////////////////////////////////////////////////////////////////////
        //
        // In error recovery and reporting scenarios we sometimes end up in a situation
        // like this:
        //
        // x.Foo( y=>
        //
        // and the question is, "is Foo a valid extension method of x?"  If Foo is
        // generic, then Foo will be something like:
        //
        // static Blah Foo<T>(this Bar<T> bar, Func<T, T> f){ ... }
        //
        // What we would like to know is: given _only_ the expression x, can we infer
        // what T is in Bar<T> ?  If we can, then for error recovery and reporting
        // we can provisionally consider Foo to be an extension method of x. If we 
        // cannot deduce this just from x then we should consider Foo to not be an
        // extension method of x, at least until we have more information.
        //
        // Clearly it is pointless to run multiple phases

        public static bool CanObjectOfExtensionBeInferred(
            ExpressionBinder binder,
            SymbolLoader symbolLoader,
            MethodSymbol pMethod,
            TypeArray pClassTypeArguments,
            TypeArray pMethodFormalParameterTypes,
            ArgInfos pMethodArguments)
        {
            Debug.Assert(pMethod != null);
            Debug.Assert(pMethod.typeVars.size > 0);
            Debug.Assert(pMethodFormalParameterTypes != null);
            Debug.Assert(pMethod.isParamArray || pMethod.Params == pMethodFormalParameterTypes);
            // We need at least one formal parameter type and at least one argument.
            if (pMethodFormalParameterTypes.size < 1 || pMethod.InferenceMustFail())
            {
                return false;
            }
            Debug.Assert(pMethodArguments != null);
            Debug.Assert(pMethodArguments.carg <= pMethodFormalParameterTypes.size);
            if (pMethodArguments.carg < 1)
            {
                return false;
            }
            var inferrer = new MethodTypeInferrer(binder, symbolLoader,
            pMethodFormalParameterTypes, pMethodArguments, pMethod.typeVars, pClassTypeArguments);
            return inferrer.CanInferExtensionObject();
        }
Пример #52
0
 public void Set(MethodOrPropertySymbol mps, AggregateType ats, TypeArray typeArgs)
 {
     if (mps == null)
     {
         ats = null;
         typeArgs = null;
     }
     Debug.Assert(ats == null || mps != null && mps.getClass() == ats.getAggregate());
     base.Set(mps, ats);
     this.TypeArgs = typeArgs;
 }
Пример #53
0
        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;
        }
Пример #54
0
 public MethPropWithInst(MethodOrPropertySymbol mps, AggregateType ats, TypeArray typeArgs)
 {
     Set(mps, ats, typeArgs);
 }
Пример #55
0
 private MethodSymbol LookupMethodWhileLoading(AggregateSymbol type, int cMethodTyVars, Name methodName, ACCESS methodAccess, bool isStatic, bool isVirtual, CType returnType, TypeArray argumentTypes)
 {
     for (Symbol sym = GetSymbolLoader().LookupAggMember(methodName, type, symbmask_t.MASK_ALL);
          sym != null;
          sym = GetSymbolLoader().LookupNextSym(sym, type, symbmask_t.MASK_ALL))
     {
         if (sym.IsMethodSymbol())
         {
             MethodSymbol methsym = sym.AsMethodSymbol();
             if ((methsym.GetAccess() == methodAccess || methodAccess == ACCESS.ACC_UNKNOWN) &&
                 methsym.isStatic == isStatic &&
                 methsym.isVirtual == isVirtual &&
                 methsym.typeVars.size == cMethodTyVars &&
                 GetTypeManager().SubstEqualTypes(methsym.RetType, returnType, null, methsym.typeVars, SubstTypeFlags.DenormMeth) &&
                 GetTypeManager().SubstEqualTypeArrays(methsym.Params, argumentTypes, (TypeArray)null,
                     methsym.typeVars, SubstTypeFlags.DenormMeth) &&
                 !methsym.getBogus())
             {
                 return methsym;
             }
         }
     }
     return null;
 }
 public static ExprMemberGroup CreateMemGroup(EXPRFLAG flags, Name name, TypeArray typeArgs, SYMKIND symKind, CType parentType, Expr obj, CMemberLookupResults memberLookupResults) =>
 new ExprMemberGroup(flags, name, typeArgs, symKind, parentType, obj, memberLookupResults);
Пример #57
0
 public override void Clear()
 {
     base.Clear();
     TypeArgs = null;
 }
Пример #58
0
 public static bool ParametersContainTyVar(TypeArray @params, TypeParameterType typeFind)
 {
     Debug.Assert(@params != null);
     Debug.Assert(typeFind != null);
     for (int p = 0; p < @params.size; p++)
     {
         CType sym = @params[p];
         if (TypeContainsType(sym, typeFind))
         {
             return true;
         }
     }
     return false;
 }
Пример #59
0
 public MethWithInst(MethodSymbol meth, AggregateType ats, TypeArray typeArgs)
 {
     Set(meth, ats, typeArgs);
 }
Пример #60
0
        ////////////////////////////////////////////////////////////////////////////////
        // 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

        private 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;
            int        carg         = args.carg;

            for (int i = 0; i < carg; i++)
            {
                Expr  arg = args.fHasExprs ? args.prgexpr[i] : null;
                CType p1  = pta1[i];
                CType p2  = pta2[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

                CType argType = arg?.RuntimeObjectActualType ?? args.types[i];

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

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

                if (betterMethod == BetterType.Right)
                {
                    if (betterConversion == BetterType.Left)
                    {
                        betterMethod = BetterType.Neither;
                        break;
                    }
                }
                else if (betterMethod == BetterType.Left)
                {
                    if (betterConversion == BetterType.Right)
                    {
                        betterMethod = BetterType.Neither;
                        break;
                    }
                }
                else
                {
                    Debug.Assert(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.Count != pta2.Count && betterMethod == BetterType.Neither)
            {
                if (node1.fExpanded)
                {
                    if (!node2.fExpanded)
                    {
                        return(BetterType.Right);
                    }
                }
                else if (node2.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.Count == carg)
                {
                    return(BetterType.Left);
                }

                if (pta2.Count == carg)
                {
                    return(BetterType.Right);
                }

                return(BetterType.Neither);
            }

            return(betterMethod);
        }