예제 #1
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;
 }
예제 #2
0
 public CMethodIterator GetMethodIterator(
     CSemanticChecker pChecker, SymbolLoader pSymLoader, CType pObject, CType pQualifyingType, Declaration pContext, bool allowBogusAndInaccessible, bool allowExtensionMethods, int arity, EXPRFLAG flags, symbmask_t mask)
 {
     Debug.Assert(pSymLoader != null);
     CMethodIterator iterator = new CMethodIterator(pChecker, pSymLoader, _pName, ContainingTypes, pObject, pQualifyingType, pContext, allowBogusAndInaccessible, allowExtensionMethods, arity, flags, mask);
     return iterator;
 }
예제 #3
0
        public EventSymbol getEvent(SymbolLoader symbolLoader)
        {
            Debug.Assert(this.isEvent == true);
            EventSymbol evt = symbolLoader.LookupAggMember(this.name,
                                                           this.getClass(),
                                                           symbmask_t.MASK_EventSymbol).AsEventSymbol();

            return evt;
        }
예제 #4
0
        ////////////////////////////////////////////////////////////////////////////////
        // Construct a compiler. All the real work is done in the Init() routine. This 
        // primary initializes all the sub-components.

        public LangCompiler(CController pCtrl, NameManager pNameMgr)
        {
            Debug.Assert(pCtrl != null);

            _pController = pCtrl;
            GlobalSymbolContext globalSymbolContext = new GlobalSymbolContext(pNameMgr);
            _errorContext = new ErrorHandling(new UserStringBuilder(globalSymbolContext), this, pCtrl.GetErrorFactory());
            _symbolLoader = new SymbolLoader(globalSymbolContext, null, _errorContext);
        }
예제 #5
0
        private Expr GenerateIndexList(Expr oldIndices)
        {
            CType intType = SymbolLoader.GetPredefindType(PredefinedType.PT_INT);

            Expr newIndices     = null;
            Expr newIndicesTail = newIndices;

            for (ExpressionIterator it = new ExpressionIterator(oldIndices); !it.AtEnd(); it.MoveNext())
            {
                Expr newIndex = it.Current();
                if (newIndex.Type != intType)
                {
                    newIndex        = ExprFactory.CreateCast(EXPRFLAG.EXF_INDEXEXPR, intType, newIndex);
                    newIndex.Flags |= EXPRFLAG.EXF_CHECKOVERFLOW;
                }
                Expr rewrittenIndex = Visit(newIndex);
                ExprFactory.AppendItemToList(rewrittenIndex, ref newIndices, ref newIndicesTail);
            }
            return(newIndices);
        }
        public PredefinedMembers(SymbolLoader loader)
        {
            _loader = loader;
            Debug.Assert(_loader != null);

            _methods    = new MethodSymbol[(int)PREDEFMETH.PM_COUNT];
            _properties = new PropertySymbol[(int)PREDEFPROP.PP_COUNT];

#if DEBUG
            // validate the tables
            for (int i = 0; i < (int)PREDEFMETH.PM_COUNT; i++)
            {
                Debug.Assert((int)GetMethInfo((PREDEFMETH)i).method == i);
            }
            for (int i = 0; i < (int)PREDEFPROP.PP_COUNT; i++)
            {
                Debug.Assert((int)GetPropInfo((PREDEFPROP)i).property == i);
            }
#endif
        }
예제 #7
0
        protected override Expr VisitCONCAT(ExprConcat expr)
        {
            Debug.Assert(expr != null);
            PREDEFMETH pdm;

            if (expr.FirstArgument.Type.IsPredefType(PredefinedType.PT_STRING) && expr.SecondArgument.Type.IsPredefType(PredefinedType.PT_STRING))
            {
                pdm = PREDEFMETH.PM_STRING_CONCAT_STRING_2;
            }
            else
            {
                pdm = PREDEFMETH.PM_STRING_CONCAT_OBJECT_2;
            }
            Expr         p1         = Visit(expr.FirstArgument);
            Expr         p2         = Visit(expr.SecondArgument);
            MethodSymbol method     = GetPreDefMethod(pdm);
            Expr         methodInfo = ExprFactory.CreateMethodInfo(method, SymbolLoader.GetPredefindType(PredefinedType.PT_STRING), null);

            return(GenerateCall(PREDEFMETH.PM_EXPRESSION_ADD_USER_DEFINED, p1, p2, methodInfo));
        }
예제 #8
0
            private bool bindExplicitConversionFromIListToArray(ArrayType arrayDest)
            {
                // 13.2.2
                //
                // The explicit reference conversions are:
                //
                // * 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 is AggregateType aggSrc) || !aggSrc.IsInterfaceType || aggSrc.TypeArgsAll.Count != 1)
                {
                    return(false);
                }

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

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

                CType typeArr = arrayDest.ElementType;
                CType typeLst = aggSrc.TypeArgsAll[0];

                Debug.Assert(!(typeArr is MethodGroupType));
                if (typeArr != typeLst && !CConversions.FExpRefConv(typeArr, typeLst))
                {
                    return(false);
                }
                if (_needsExprDest)
                {
                    _binder.bindSimpleCast(_exprSrc, _typeDest, out _exprDest, EXPRFLAG.EXF_REFCHECK);
                }
                return(true);
            }
예제 #9
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.Count; i++)
                {
                    AggregateType type = ifaces[i].AsAggregateType();
                    Debug.Assert(type.isInterfaceType());

                    if (type.IsCollectionType())
                    {
                        typeList.Add(type);
                    }
                }
                _winrtifacesAll = pSymbolLoader.getBSymmgr().AllocParams(typeList.Count, typeList.ToArray());
            }
            return(_winrtifacesAll);
        }
예제 #10
0
 private static MethodSymbol LookupMethodWhileLoading(AggregateSymbol type, int cMethodTyVars, Name methodName, ACCESS methodAccess, bool isStatic, bool isVirtual, CType returnType, TypeArray argumentTypes)
 {
     for (Symbol sym = SymbolLoader.LookupAggMember(methodName, type, symbmask_t.MASK_ALL);
          sym != null;
          sym = sym.LookupNext(symbmask_t.MASK_ALL))
     {
         if (sym is MethodSymbol methsym)
         {
             if ((methsym.GetAccess() == methodAccess || methodAccess == ACCESS.ACC_UNKNOWN) &&
                 methsym.isStatic == isStatic &&
                 methsym.isVirtual == isVirtual &&
                 methsym.typeVars.Count == cMethodTyVars &&
                 TypeManager.SubstEqualTypes(methsym.RetType, returnType, null, methsym.typeVars, true) &&
                 TypeManager.SubstEqualTypeArrays(methsym.Params, argumentTypes, null, methsym.typeVars))
             {
                 return(methsym);
             }
         }
     }
     return(null);
 }
예제 #11
0
            private bool bindImplicitConversionFromEnum(AggregateType aggTypeSrc)
            {
                // 13.1.5 Boxing conversions
                //
                // A boxing conversion permits any non-nullable-value-type to be implicitly converted to the type
                // object or System.ValueType or to any interface-type implemented by the value-type, and any enum
                // type to be implicitly converted to System.Enum as well. Boxing a value of a
                // non-nullable-value-type consists of allocating an object instance and copying the value-type
                // value into that instance. An enum can be boxed to the type System.Enum, since that is the direct
                // base class for all enums (21.4). A struct or enum can be boxed to the type System.ValueType,
                // since that is the direct base class for all structs (18.3.2) and a base class for all enums.

                if (_typeDest is AggregateType aggDest && SymbolLoader.HasBaseConversion(aggTypeSrc, aggDest))
                {
                    if (_needsExprDest)
                    {
                        _binder.bindSimpleCast(_exprSrc, _typeDest, out _exprDest, EXPRFLAG.EXF_BOX | EXPRFLAG.EXF_CANTBENULL);
                    }
                    return(true);
                }
                return(false);
            }
예제 #12
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;
        }
예제 #13
0
        private static Expr GenerateConstant(Expr expr)
        {
            EXPRFLAG flags = 0;

            AggregateType pObject = SymbolLoader.GetPredefindType(PredefinedType.PT_OBJECT);

            if (expr.Type is NullType)
            {
                ExprTypeOf pTypeOf = CreateTypeOf(pObject);
                return(GenerateCall(PREDEFMETH.PM_EXPRESSION_CONSTANT_OBJECT_TYPE, expr, pTypeOf));
            }

            AggregateType stringType = SymbolLoader.GetPredefindType(PredefinedType.PT_STRING);

            if (expr.Type != stringType)
            {
                flags = EXPRFLAG.EXF_BOX;
            }

            ExprCast   cast     = ExprFactory.CreateCast(flags, pObject, expr);
            ExprTypeOf pTypeOf2 = CreateTypeOf(expr.Type);

            return(GenerateCall(PREDEFMETH.PM_EXPRESSION_CONSTANT_OBJECT_TYPE, cast, pTypeOf2));
        }
예제 #14
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;
        }
예제 #15
0
 public BSYMMGR getBSymmgr()
 {
     return(SymbolLoader.getBSymmgr());
 }
예제 #16
0
 //protected CompilerPhase GetCompPhase() { return SymbolLoader.CompPhase(); }
 //protected void SetCompPhase(CompilerPhase compPhase) { SymbolLoader.compPhase = compPhase; }
 public PredefinedTypes getPredefTypes()
 {
     return(SymbolLoader.GetPredefindTypes());
 }
예제 #17
0
 private static AggregateSymbol GetPredefAgg(PredefinedType pt) => SymbolLoader.GetPredefAgg(pt);
예제 #18
0
 public NameManager GetNameManager()
 {
     return(SymbolLoader.GetNameManager());
 }
예제 #19
0
파일: Type.cs 프로젝트: dotnet/corefx
        public bool computeManagedType(SymbolLoader symbolLoader)
        {
            if (IsVoidType())
                return false;

            switch (fundType())
            {
                case FUNDTYPE.FT_NONE:
                case FUNDTYPE.FT_REF:
                case FUNDTYPE.FT_VAR:
                    return true;

                case FUNDTYPE.FT_STRUCT:
                    if (IsNullableType())
                    {
                        return true;
                    }
                    else
                    {
                        AggregateSymbol aggT = getAggregate();

                        // See if we already know.
                        if (aggT.IsKnownManagedStructStatus())
                        {
                            return aggT.IsManagedStruct();
                        }

                        // Generics are always managed.
                        if (aggT.GetTypeVarsAll().size > 0)
                        {
                            aggT.SetManagedStruct(true);
                            return true;
                        }

                        // If the struct layout has an error, don't recurse its children.
                        if (aggT.IsLayoutError())
                        {
                            aggT.SetUnmanagedStruct(true);
                            return false;
                        }

                        // at this point we can only determine the managed status
                        // if we have members defined, otherwise we don't know the result
                        if (symbolLoader != null)
                        {
                            for (Symbol ps = aggT.firstChild; ps != null; ps = ps.nextChild)
                            {
                                if (ps.IsFieldSymbol() && !ps.AsFieldSymbol().isStatic)
                                {
                                    CType type = ps.AsFieldSymbol().GetType();
                                    if (type.computeManagedType(symbolLoader))
                                    {
                                        aggT.SetManagedStruct(true);
                                        return true;
                                    }
                                }
                            }

                            aggT.SetUnmanagedStruct(true);
                        }

                        return false;
                    }
                default:
                    return false;
            }
        }
예제 #20
0
            /***************************************************************************************************
            *   Called by BindImplicitConversion when the destination type is Nullable<T>. The following
            *   conversions are handled by this method:
            *
            * For S in { object, ValueType, interfaces implemented by underlying type} there is an explicit
            *     unboxing conversion S => T?
            * System.Enum => T? there is an unboxing conversion if T is an enum type
            * null => T? implemented as default(T?)
            *
            * Implicit T?* => T?+ implemented by either wrapping or calling GetValueOrDefault the
            *     appropriate number of times.
            * If imp/exp S => T then imp/exp S => T?+ implemented by converting to T then wrapping the
            *     appropriate number of times.
            * If imp/exp S => T then imp/exp S?+ => T?+ implemented by calling GetValueOrDefault (m-1) times
            *     then calling HasValue, producing a null if it returns false, otherwise calling Value,
            *     converting to T then wrapping the appropriate number of times.
            *
            *   The 3 rules above can be summarized with the following recursive rules:
            *
            * If imp/exp S => T? then imp/exp S? => T? implemented as
            *     qs.HasValue ? (T?)(qs.Value) : default(T?)
            * If imp/exp S => T then imp/exp S => T? implemented as new T?((T)s)
            *
            *   This method also handles calling bindUserDefinedConverion. This method does NOT handle
            *   the following conversions:
            *
            * Implicit boxing conversion from S? to { object, ValueType, Enum, ifaces implemented by S }. (Handled by BindImplicitConversion.)
            * If imp/exp S => T then explicit S?+ => T implemented by calling Value the appropriate number
            *     of times. (Handled by BindExplicitConversion.)
            *
            *   The recursive equivalent is:
            *
            * If imp/exp S => T and T is not nullable then explicit S? => T implemented as qs.Value
            *
            *   Some nullable conversion are NOT standard conversions. In particular, if S => T is implicit
            *   then S? => T is not standard. Similarly if S => T is not implicit then S => T? is not standard.
            ***************************************************************************************************/
            private bool BindNubConversion(NullableType nubDst)
            {
                // This code assumes that STANDARD and ISEXPLICIT are never both set.
                // bindUserDefinedConversion should ensure this!
                Debug.Assert(0 != (~_flags & (CONVERTTYPE.STANDARD | CONVERTTYPE.ISEXPLICIT)));
                Debug.Assert(_exprSrc == null || _exprSrc.Type == _typeSrc);
                Debug.Assert(!_needsExprDest || _exprSrc != null);
                Debug.Assert(_typeSrc != nubDst); // BindImplicitConversion should have taken care of this already.
                AggregateType atsDst = nubDst.GetAts();

                // Check for the unboxing conversion. This takes precedence over the wrapping conversions.
                if (SymbolLoader.HasBaseConversion(nubDst.UnderlyingType, _typeSrc) && !CConversions.FWrappingConv(_typeSrc, nubDst))
                {
                    // These should be different! Fix the caller if typeSrc is an AggregateType of Nullable.
                    Debug.Assert(atsDst != _typeSrc);

                    // typeSrc is a base type of the destination nullable type so there is an explicit
                    // unboxing conversion.
                    if (0 == (_flags & CONVERTTYPE.ISEXPLICIT))
                    {
                        return(false);
                    }

                    if (_needsExprDest)
                    {
                        _binder.bindSimpleCast(_exprSrc, _typeDest, out _exprDest, EXPRFLAG.EXF_UNBOX);
                    }
                    return(true);
                }

                bool           dstWasNullable;
                bool           srcWasNullable;
                CType          typeDstBase = nubDst.StripNubs(out dstWasNullable);
                CType          typeSrcBase = _typeSrc.StripNubs(out srcWasNullable);
                ConversionFunc pfn         = (_flags & CONVERTTYPE.ISEXPLICIT) != 0 ?
                                             (ConversionFunc)_binder.BindExplicitConversion :
                                             (ConversionFunc)_binder.BindImplicitConversion;

                if (!srcWasNullable)
                {
                    Debug.Assert(_typeSrc == typeSrcBase);

                    // The null type can be implicitly converted to T? as the default value.
                    if (_typeSrc is NullType)
                    {
                        // If we have the constant null, generate it as a default value of T?.  If we have
                        // some wacky expression which has been determined to be always null, like (null??null)
                        // keep it in its expression form and transform it in the nullable rewrite pass.
                        if (_needsExprDest)
                        {
                            _exprDest = _exprSrc is ExprConstant
                                ? ExprFactory.CreateZeroInit(nubDst)
                                : ExprFactory.CreateCast(_typeDest, _exprSrc);
                        }
                        return(true);
                    }

                    Expr exprTmp = _exprSrc;

                    // If there is an implicit/explicit S => T then there is an implicit/explicit S => T?
                    if (_typeSrc == typeDstBase || pfn(_exprSrc, _typeSrc, typeDstBase, _needsExprDest, out exprTmp, _flags | CONVERTTYPE.NOUDC))
                    {
                        if (_needsExprDest)
                        {
                            ExprUserDefinedConversion exprUDC = exprTmp as ExprUserDefinedConversion;
                            if (exprUDC != null)
                            {
                                exprTmp = exprUDC.UserDefinedCall;
                            }

                            if (dstWasNullable)
                            {
                                ExprCall call = BindNubNew(exprTmp);
                                exprTmp = call;
                                call.NullableCallLiftKind = NullableCallLiftKind.NullableConversionConstructor;
                            }

                            if (exprUDC != null)
                            {
                                exprUDC.UserDefinedCall = exprTmp;
                                exprTmp = exprUDC;
                            }

                            Debug.Assert(exprTmp.Type == nubDst);
                            _exprDest = exprTmp;
                        }
                        return(true);
                    }

                    // No builtin conversion. Maybe there is a user defined conversion....
                    return(0 == (_flags & CONVERTTYPE.NOUDC) && _binder.bindUserDefinedConversion(_exprSrc, _typeSrc, nubDst, _needsExprDest, out _exprDest, 0 == (_flags & CONVERTTYPE.ISEXPLICIT)));
                }

                // Both are Nullable so there is only a conversion if there is a conversion between the base types.
                // That is, if there is an implicit/explicit S => T then there is an implicit/explicit S?+ => T?+.
                if (typeSrcBase != typeDstBase && !pfn(null, typeSrcBase, typeDstBase, false, out _exprDest, _flags | CONVERTTYPE.NOUDC))
                {
                    // No builtin conversion. Maybe there is a user defined conversion....
                    return(0 == (_flags & CONVERTTYPE.NOUDC) && _binder.bindUserDefinedConversion(_exprSrc, _typeSrc, nubDst, _needsExprDest, out _exprDest, 0 == (_flags & CONVERTTYPE.ISEXPLICIT)));
                }

                if (_needsExprDest)
                {
                    MethWithInst    mwi       = new MethWithInst(null, null);
                    ExprMemberGroup pMemGroup = ExprFactory.CreateMemGroup(null, mwi);
                    ExprCall        exprDst   = ExprFactory.CreateCall(0, nubDst, _exprSrc, pMemGroup, null);

                    // Here we want to first check whether or not the conversions work on the base types.

                    Expr arg1        = _binder.mustCast(_exprSrc, typeSrcBase);
                    bool convertible = (_flags & CONVERTTYPE.ISEXPLICIT) != 0
                        ? _binder.BindExplicitConversion(
                        arg1, arg1.Type, typeDstBase, out arg1, _flags | CONVERTTYPE.NOUDC)
                        : _binder.BindImplicitConversion(
                        arg1, arg1.Type, typeDstBase, out arg1, _flags | CONVERTTYPE.NOUDC);

                    if (!convertible)
                    {
                        Debug.Fail("bind(Im|Ex)plicitConversion failed unexpectedly");
                        return(false);
                    }

                    exprDst.CastOfNonLiftedResultToLiftedType = _binder.mustCast(arg1, nubDst, 0);
                    exprDst.NullableCallLiftKind = NullableCallLiftKind.NullableConversion;
                    exprDst.PConversions         = exprDst.CastOfNonLiftedResultToLiftedType;
                    _exprDest = exprDst;
                }

                return(true);
            }
예제 #21
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(CType typeSrc, CType typeDst)
        {
            Debug.Assert(typeSrc != null);
            Debug.Assert(typeDst != null);
            if (typeSrc.IsReferenceType && typeDst.IsReferenceType)
            {
                // is there an implicit reference conversion in either direction?
                // this handles the bulk of the cases ...
                if (SymbolLoader.HasIdentityOrImplicitReferenceConversion(typeSrc, typeDst) ||
                    SymbolLoader.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 || 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.OwningAggregate;
                    AggregateSymbol aggDest = atDst.OwningAggregate;

                    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(arrSrc.ElementType, arrDst.ElementType));
                    }

                    // *    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.TypeArgsAll;

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

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

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

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

                if (typeDst is ArrayType arrayDest && typeSrc is AggregateType aggtypeSrc)
                {
                    // * From System.Array and the interfaces it implements, to any array-type.
                    if (SymbolLoader.HasIdentityOrImplicitReferenceConversion(SymbolLoader.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.TypeArgsAll.Count != 1)
                    {
                        return(false);
                    }

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

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

                    CType typeArr = arrayDest.ElementType;
                    CType typeLst = aggtypeSrc.TypeArgsAll[0];

                    Debug.Assert(!(typeArr is MethodGroupType));
                    return(typeArr == typeLst || FExpRefConv(typeArr, typeLst));
                }
                if (HasGenericDelegateExplicitReferenceConversion(typeSrc, typeDst))
                {
                    return(true);
                }
            }
            else if (typeSrc.IsReferenceType)
            {
                // conversion of T . U, where T : class, U
                // .. these constraints implies where U : class
                return(SymbolLoader.HasIdentityOrImplicitReferenceConversion(typeSrc, typeDst));
            }
            else if (typeDst.IsReferenceType)
            {
                // conversion of T . U, where U : class, T
                // .. these constraints implies where T : class
                return(SymbolLoader.HasIdentityOrImplicitReferenceConversion(typeDst, typeSrc));
            }
            return(false);
        }
예제 #22
0
 public TypeArray GetDelegateParameters(SymbolLoader pSymbolLoader)
 {
     Debug.Assert(isDelegateType());
     MethodSymbol invoke = pSymbolLoader.LookupInvokeMeth(getAggregate());
     if (invoke == null || !invoke.isInvoke())
     {
         // This can happen if the delegate is internal to another assembly. 
         return null;
     }
     return getAggregate().GetTypeManager().SubstTypeArray(invoke.Params, this);
 }
예제 #23
0
 public CNullable(SymbolLoader symbolLoader, ErrorHandling errorContext, ExprFactory exprFactory)
 {
     _pSymbolLoader = symbolLoader;
     _pErrorContext = errorContext;
     _exprFactory   = exprFactory;
 }
예제 #24
0
        private bool SearchSingleType(AggregateType typeCur, out bool pfHideByName)
        {
            bool fFoundSome = false;

            pfHideByName = false;

            // Make sure this type is accessible. It may not be due to private inheritance
            // or friend assemblies.
            bool fInaccess = !CSemanticChecker.CheckTypeAccess(typeCur, _symWhere);

            if (fInaccess && (_csym != 0 || _swtInaccess != null))
            {
                return(false);
            }

            // Loop through symbols.
            Symbol symCur;

            for (symCur = SymbolLoader.LookupAggMember(_name, typeCur.OwningAggregate, symbmask_t.MASK_Member);
                 symCur != null;
                 symCur = symCur.LookupNext(symbmask_t.MASK_Member))
            {
                Debug.Assert(!(symCur is AggregateSymbol));
                // Check for arity.
                // For non-zero arity, only methods of the correct arity are considered.
                // For zero arity, don't filter out any methods since we do type argument
                // inferencing.
                // All others are only considered when arity is zero.
                if (_arity > 0 && (!(symCur is MethodSymbol curMeth) || curMeth.typeVars.Count != _arity))
                {
                    if (!_swtBadArity)
                    {
                        _swtBadArity.Set(symCur, typeCur);
                    }

                    continue;
                }

                // Check for user callability.
                if (symCur.IsOverride() && !symCur.IsHideByName())
                {
                    continue;
                }

                MethodOrPropertySymbol methProp = symCur as MethodOrPropertySymbol;
                MethodSymbol           meth     = symCur as MethodSymbol;
                if (methProp != null && (_flags & MemLookFlags.UserCallable) != 0 && !methProp.isUserCallable())
                {
                    // If its an indexed property method symbol, let it through.
                    // This is too liberal, but maintained for compatibility.
                    if (meth == null ||
                        !meth.isPropertyAccessor() ||
                        (!symCur.name.Text.StartsWith("set_", StringComparison.Ordinal) || meth.Params.Count <= 1) &&
                        (!symCur.name.Text.StartsWith("get_", StringComparison.Ordinal) || meth.Params.Count <= 0))
                    {
                        if (!_swtInaccess)
                        {
                            _swtInaccess.Set(symCur, typeCur);
                        }

                        continue;
                    }
                }

                if (fInaccess || !CSemanticChecker.CheckAccess(symCur, typeCur, _symWhere, _typeQual))
                {
                    // Not accessible so get the next sym.
                    if (!_swtInaccess)
                    {
                        _swtInaccess.Set(symCur, typeCur);
                    }
                    if (fInaccess)
                    {
                        return(false);
                    }
                    continue;
                }

                PropertySymbol prop = symCur as PropertySymbol;

                // Make sure that whether we're seeing a ctor, operator, or indexer is consistent with the flags.
                if (((_flags & MemLookFlags.Ctor) == 0) != (meth == null || !meth.IsConstructor()) ||
                    ((_flags & MemLookFlags.Operator) == 0) != (meth == null || !meth.isOperator) ||
                    ((_flags & MemLookFlags.Indexer) == 0) != !(prop is IndexerSymbol))
                {
                    if (!_swtBad)
                    {
                        _swtBad.Set(symCur, typeCur);
                    }
                    continue;
                }

                // We can't call CheckBogus on methods or indexers because if the method has the wrong
                // number of parameters people don't think they should have to /r the assemblies containing
                // the parameter types and they complain about the resulting CS0012 errors.
                if (!(symCur is MethodSymbol) && (_flags & MemLookFlags.Indexer) == 0 && CSemanticChecker.CheckBogus(symCur))
                {
                    // A bogus member - we can't use these, so only record them for error reporting.
                    if (!_swtBogus)
                    {
                        _swtBogus.Set(symCur, typeCur);
                    }
                    continue;
                }

                // if we are in a calling context then we should only find a property if it is delegate valued
                if ((_flags & MemLookFlags.MustBeInvocable) != 0)
                {
                    if ((symCur is FieldSymbol field && !IsDelegateType(field.GetType(), typeCur) && !IsDynamicMember(symCur)) ||
                        (prop != null && !IsDelegateType(prop.RetType, typeCur) && !IsDynamicMember(symCur)))
                    {
                        if (!_swtBad)
                        {
                            _swtBad.Set(symCur, typeCur);
                        }
                        continue;
                    }
                }

                if (methProp != null)
                {
                    MethPropWithType mwpInsert = new MethPropWithType(methProp, typeCur);
                    _methPropWithTypeList.Add(mwpInsert);
                }

                // We have a visible symbol.
                fFoundSome = true;

                if (_swtFirst)
                {
                    if (!typeCur.IsInterfaceType)
                    {
                        // Non-interface case.
                        Debug.Assert(_fMulti || typeCur == _prgtype[0]);
                        if (!_fMulti)
                        {
                            if (_swtFirst.Sym is FieldSymbol && symCur is EventSymbol
                                // The isEvent bit is only set on symbols which come from source...
                                // This is not a problem for the compiler because the field is only
                                // accessible in the scope in which it is declared,
                                // but in the EE we ignore accessibility...
                                && _swtFirst.Field().isEvent
                                )
                            {
                                // m_swtFirst is just the field behind the event symCur so ignore symCur.
                                continue;
                            }
                            else if (_swtFirst.Sym is FieldSymbol && symCur is EventSymbol)
                            {
                                // symCur is the matching event.
                                continue;
                            }
                            goto LAmbig;
                        }
                        if (_swtFirst.Sym.getKind() != symCur.getKind())
                        {
                            if (typeCur == _prgtype[0])
                            {
                                goto LAmbig;
                            }
                            // This one is hidden by the first one. This one also hides any more in base types.
                            pfHideByName = true;
                            continue;
                        }
                    }
                    // Interface case.
                    // m_fMulti   : n n n y y y y y
                    // same-kind  : * * * y n n n n
                    // fDiffHidden: * * * * y n n n
                    // meth       : * * * * * y n *  can n happen? just in case, we better handle it....
                    // hack       : n * y * * y * n
                    // meth-2     : * n y * * * * *
                    // res        : A A S R H H A A
                    else if (!_fMulti)
                    {
                        // Give method groups priority.
                        if (!(symCur is MethodSymbol))
                        {
                            goto LAmbig;
                        }
                        // Erase previous results so we'll record this method as the first.
                        _prgtype = new List <AggregateType>();
                        _csym    = 0;
                        _swtFirst.Clear();
                        _swtAmbig.Clear();
                    }
                    else if (_swtFirst.Sym.getKind() != symCur.getKind())
                    {
                        if (!typeCur.DiffHidden)
                        {
                            // Give method groups priority.
                            if (!(_swtFirst.Sym is MethodSymbol))
                            {
                                goto LAmbig;
                            }
                        }
                        // This one is hidden by another. This one also hides any more in base types.
                        pfHideByName = true;
                        continue;
                    }
                }

                RecordType(typeCur, symCur);

                if (methProp != null && methProp.isHideByName)
                {
                    pfHideByName = true;
                }
                // We've found a symbol in this type but need to make sure there aren't any conflicting
                // syms here, so keep searching the type.
            }

            Debug.Assert(!fInaccess || !fFoundSome);

            return(fFoundSome);

LAmbig:
            // Ambiguous!
            if (!_swtAmbig)
            {
                _swtAmbig.Set(symCur, typeCur);
            }
            pfHideByName = true;
            return(true);
        }
예제 #25
0
        // WARNING: These methods do not precisely match the spec.
        // WARNING: For example most also return true for identity conversions,
        // WARNING: FExpRefConv includes all Implicit and Explicit reference conversions.

        /***************************************************************************************************
        *   Determine whether there is an implicit reference conversion from typeSrc to typeDst. This is
        *   when the source is a reference type and the destination is a base type of the source. Note
        *   that typeDst.IsRefType() may still return false (when both are type parameters).
        ***************************************************************************************************/
        public static bool FImpRefConv(SymbolLoader loader, CType typeSrc, CType typeDst)
        {
            return(typeSrc.IsRefType() && loader.HasIdentityOrImplicitReferenceConversion(typeSrc, typeDst));
        }
예제 #26
0
 protected static AggregateType GetReqPDT(PredefinedType pt, SymbolLoader symbolLoader)
 {
     Debug.Assert(pt != PredefinedType.PT_VOID);  // use getVoidType()
     return symbolLoader.GetReqPredefType(pt, true);
 }
예제 #27
0
        ////////////////////////////////////////////////////////////////////////////////
        // For a base call we need to remap from the virtual to the specific override 
        // to invoke.  This is also used to map a virtual on pObject (like ToString) to 
        // the specific override when the pObject is a simple type (int, bool, char, 
        // etc). In these cases it is safe to assume that any override won't later be 
        // removed.... We start searching from "typeObj" up the superclass hierarchy 
        // until we find a method with an exact signature match.

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

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

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

            symbmask_t mask = pswt.Sym.mask();

            AggregateType atsObj = typeObj.AsAggregateType();

            // Search for an override version of the method.
            while (atsObj != null && atsObj.getAggregate() != pswt.Sym.parent)
            {
                for (Symbol symT = symbolLoader.LookupAggMember(pswt.Sym.name, atsObj.getAggregate(), mask);
                     symT != null;
                     symT = symbolLoader.LookupNextSym(symT, atsObj.getAggregate(), mask))
                {
                    if (symT.IsOverride() && (symT.SymBaseVirtual() == pswt.Sym || symT.SymBaseVirtual() == pswt.Sym.SymBaseVirtual()))
                    {
                        pswt.Set(symT, atsObj);
                        return;
                    }
                }
                atsObj = atsObj.GetBaseClass();
            }
        }
예제 #28
0
 public static void ReportTypeArgsNotAllowedError(SymbolLoader symbolLoader, int arity, ErrArgRef argName, ErrArgRef argKind)
 {
     symbolLoader.ErrorContext.ErrorRef(ErrorCode.ERR_TypeArgsNotAllowed, argName, argKind);
 }
예제 #29
0
 public CNullable(SymbolLoader symbolLoader, ErrorHandling errorContext, ExprFactory exprFactory)
 {
     _pSymbolLoader = symbolLoader;
     _pErrorContext = errorContext;
     _exprFactory = exprFactory;
 }
예제 #30
0
        /***************************************************************************************************
            Lookup must be called before anything else can be called.
         
            typeSrc - Must be an AggregateType or TypeParameterType.
            obj - the expression through which the member is being accessed. This is used for accessibility
                of protected members and for constructing a MEMGRP from the results of the lookup.
                It is legal for obj to be an EK_CLASS, in which case it may be used for accessibility, but
                will not be used for MEMGRP construction.
            symWhere - the symbol from with the name is being accessed (for checking accessibility).
            name - the name to look for.
            arity - the number of type args specified. Only members that support this arity are found.
                Note that when arity is zero, all methods are considered since we do type argument
                inferencing.
         
            flags - See MemLookFlags.
                TypeVarsAllowed only applies to the most derived type (not base types).
        ***************************************************************************************************/
        public bool Lookup(CSemanticChecker checker, CType typeSrc, EXPR obj, ParentSymbol symWhere, Name name, int arity, MemLookFlags flags)
        {
            Debug.Assert((flags & ~MemLookFlags.All) == 0);
            Debug.Assert(obj == null || obj.type != null);
            Debug.Assert(typeSrc.IsAggregateType() || typeSrc.IsTypeParameterType());
            Debug.Assert(checker != null);

            _prgtype = _rgtypeStart;

            // Save the inputs for error handling, etc.
            _pSemanticChecker = checker;
            _pSymbolLoader = checker.GetSymbolLoader();
            _typeSrc = typeSrc;
            _obj = (obj != null && !obj.isCLASS()) ? obj : null;
            _symWhere = symWhere;
            _name = name;
            _arity = arity;
            _flags = flags;

            if ((_flags & MemLookFlags.BaseCall) != 0)
                _typeQual = null;
            else if ((_flags & MemLookFlags.Ctor) != 0)
                _typeQual = _typeSrc;
            else if (obj != null)
                _typeQual = (CType)obj.type;
            else
                _typeQual = null;

            // Determine what to search.
            AggregateType typeCls1 = null;
            AggregateType typeIface = null;
            TypeArray ifaces = BSYMMGR.EmptyTypeArray();
            AggregateType typeCls2 = null;

            if (typeSrc.IsTypeParameterType())
            {
                Debug.Assert((_flags & (MemLookFlags.Ctor | MemLookFlags.NewObj | MemLookFlags.Operator | MemLookFlags.BaseCall | MemLookFlags.TypeVarsAllowed)) == 0);
                _flags &= ~MemLookFlags.TypeVarsAllowed;
                ifaces = typeSrc.AsTypeParameterType().GetInterfaceBounds();
                typeCls1 = typeSrc.AsTypeParameterType().GetEffectiveBaseClass();
                if (ifaces.size > 0 && typeCls1.isPredefType(PredefinedType.PT_OBJECT))
                    typeCls1 = null;
            }
            else if (!typeSrc.isInterfaceType())
            {
                typeCls1 = typeSrc.AsAggregateType();

                if (typeCls1.IsWindowsRuntimeType())
                {
                    ifaces = typeCls1.GetWinRTCollectionIfacesAll(GetSymbolLoader());
                }
            }
            else
            {
                Debug.Assert(typeSrc.isInterfaceType());
                Debug.Assert((_flags & (MemLookFlags.Ctor | MemLookFlags.NewObj | MemLookFlags.Operator | MemLookFlags.BaseCall)) == 0);
                typeIface = typeSrc.AsAggregateType();
                ifaces = typeIface.GetIfacesAll();
            }

            if (typeIface != null || ifaces.size > 0)
                typeCls2 = GetSymbolLoader().GetReqPredefType(PredefinedType.PT_OBJECT);

            // Search the class first (except possibly object).
            if (typeCls1 == null || LookupInClass(typeCls1, ref typeCls2))
            {
                // Search the interfaces.
                if ((typeIface != null || ifaces.size > 0) && LookupInInterfaces(typeIface, ifaces) && typeCls2 != null)
                {
                    // Search object last.
                    Debug.Assert(typeCls2 != null && typeCls2.isPredefType(PredefinedType.PT_OBJECT));

                    AggregateType result = null;
                    LookupInClass(typeCls2, ref result);
                }
            }

            // if we are requested with extension methods
            _results = new CMemberLookupResults(GetAllTypes(), _name);

            return !FError();
        }
예제 #31
0
 public EventSymbol getEvent()
 {
     Debug.Assert(isEvent);
     return(SymbolLoader.LookupAggMember(name, getClass(), symbmask_t.MASK_EventSymbol) as EventSymbol);
 }
 public static void ReportTypeArgsNotAllowedError(SymbolLoader symbolLoader, int arity, ErrArgRef argName, ErrArgRef argKind)
 {
     symbolLoader.ErrorContext.ErrorRef(ErrorCode.ERR_TypeArgsNotAllowed, argName, argKind);
 }
예제 #33
0
 private ExpressionTreeRewriter(ExprFactory expressionFactory, SymbolLoader symbolLoader)
 {
     this.expressionFactory = expressionFactory;
     this.symbolLoader      = symbolLoader;
 }
예제 #34
0
        public bool computeManagedType(SymbolLoader symbolLoader)
        {
            if (this.IsVoidType())
            {
                return(false);
            }

            switch (this.fundType())
            {
            case FUNDTYPE.FT_NONE:
            case FUNDTYPE.FT_REF:
            case FUNDTYPE.FT_VAR:
                return(true);

            case FUNDTYPE.FT_STRUCT:
                if (this.IsNullableType())
                {
                    return(true);
                }
                else
                {
                    AggregateSymbol aggT = this.getAggregate();

                    // See if we already know.
                    if (aggT.IsKnownManagedStructStatus())
                    {
                        return(aggT.IsManagedStruct());
                    }

                    // Generics are always managed.
                    if (aggT.GetTypeVarsAll().size > 0)
                    {
                        aggT.SetManagedStruct(true);
                        return(true);
                    }

                    // If the struct layout has an error, dont recurse its children.
                    if (aggT.IsLayoutError())
                    {
                        aggT.SetUnmanagedStruct(true);
                        return(false);
                    }

                    // at this point we can only determine the managed status
                    // if we have members defined, otherwise we don't know the result
                    if (symbolLoader != null)
                    {
                        for (Symbol ps = aggT.firstChild; ps != null; ps = ps.nextChild)
                        {
                            if (ps.IsFieldSymbol() && !ps.AsFieldSymbol().isStatic)
                            {
                                CType type = ps.AsFieldSymbol().GetType();
                                if (type.computeManagedType(symbolLoader))
                                {
                                    aggT.SetManagedStruct(true);
                                    return(true);
                                }
                            }
                        }

                        aggT.SetUnmanagedStruct(true);
                    }

                    return(false);
                }

            default:
                return(false);
            }
        }
예제 #35
0
 protected ExpressionTreeRewriter(ExprFactory expressionFactory, SymbolLoader symbolLoader)
 {
     this.expressionFactory = expressionFactory;
     this.symbolLoader = symbolLoader;
     this.alwaysRewrite = false;
 }
예제 #36
0
            internal static bool ReOrderArgsForNamedArguments(
                    MethodOrPropertySymbol methprop,
                    TypeArray pCurrentParameters,
                    AggregateType pCurrentType,
                    EXPRMEMGRP pGroup,
                    ArgInfos pArguments,
                    TypeManager typeManager,
                    ExprFactory exprFactory,
                    SymbolLoader symbolLoader)
            {
                // We use the param count from pCurrentParameters because they may have been resized 
                // for param arrays.
                int numParameters = pCurrentParameters.size;

                EXPR[] pExprArguments = new EXPR[numParameters];

                // Now go through the parameters. First set all positional arguments in the new argument
                // set, then for the remainder, look for a named argument with a matching name.
                int index = 0;
                EXPR paramArrayArgument = null;
                TypeArray @params = typeManager.SubstTypeArray(
                    pCurrentParameters,
                    pCurrentType,
                    pGroup.typeArgs);
                foreach (Name name in methprop.ParameterNames)
                {
                    // This can happen if we had expanded our param array to size 0.
                    if (index >= pCurrentParameters.size)
                    {
                        break;
                    }

                    // If:
                    // (1) we have a param array method
                    // (2) we're on the last arg
                    // (3) the thing we have is an array init thats generated for param array
                    // then let us through.
                    if (methprop.isParamArray &&
                        index < pArguments.carg &&
                        pArguments.prgexpr[index].isARRINIT() && pArguments.prgexpr[index].asARRINIT().GeneratedForParamArray)
                    {
                        paramArrayArgument = pArguments.prgexpr[index];
                    }

                    // Positional.
                    if (index < pArguments.carg &&
                        !pArguments.prgexpr[index].isNamedArgumentSpecification() &&
                        !(pArguments.prgexpr[index].isARRINIT() && pArguments.prgexpr[index].asARRINIT().GeneratedForParamArray))
                    {
                        pExprArguments[index] = pArguments.prgexpr[index++];
                        continue;
                    }

                    // Look for names.
                    EXPR pNewArg = FindArgumentWithName(pArguments, name);
                    if (pNewArg == null)
                    {
                        if (methprop.IsParameterOptional(index))
                        {
                            pNewArg = GenerateOptionalArgument(symbolLoader, exprFactory, methprop, @params.Item(index), index);
                        }
                        else if (paramArrayArgument != null && index == methprop.Params.Count - 1)
                        {
                            // If we have a param array argument and we're on the last one, then use it.
                            pNewArg = paramArrayArgument;
                        }
                        else
                        {
                            // No name and no default value.
                            return false;
                        }
                    }
                    pExprArguments[index++] = pNewArg;
                }

                // Here we've found all the arguments, or have default values for them.
                CType[] prgTypes = new CType[pCurrentParameters.size];
                for (int i = 0; i < numParameters; i++)
                {
                    if (i < pArguments.prgexpr.Count)
                    {
                        pArguments.prgexpr[i] = pExprArguments[i];
                    }
                    else
                    {
                        pArguments.prgexpr.Add(pExprArguments[i]);
                    }
                    prgTypes[i] = pArguments.prgexpr[i].type;
                }
                pArguments.carg = pCurrentParameters.size;
                pArguments.types = symbolLoader.getBSymmgr().AllocParams(pCurrentParameters.size, prgTypes);
                return true;
            }
예제 #37
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.IsTypeParameterType())
                {
                    return(true);
                }
                if (typeSrc.IsTypeParameterType() && 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.IsAggregateType() && typeDst.IsAggregateType())
                {
                    AggregateSymbol aggSrc  = typeSrc.AsAggregateType().getAggregate();
                    AggregateSymbol aggDest = typeDst.AsAggregateType().getAggregate();

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

                // *    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 (typeSrc.IsArrayType() && typeDst.IsArrayType())
                {
                    return(typeSrc.AsArrayType().rank == typeDst.AsArrayType().rank&& FExpRefConv(loader, typeSrc.AsArrayType().GetElementType(), typeDst.AsArrayType().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 (typeSrc.IsArrayType())
                {
                    if (typeSrc.AsArrayType().rank != 1 ||
                        !typeDst.isInterfaceType() || typeDst.AsAggregateType().GetTypeArgsAll().Size != 1)
                    {
                        return(false);
                    }

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

                    if ((aggIList == null ||
                         !loader.IsBaseAggregate(aggIList, typeDst.AsAggregateType().getAggregate())) &&
                        (aggIReadOnlyList == null ||
                         !loader.IsBaseAggregate(aggIReadOnlyList, typeDst.AsAggregateType().getAggregate())))
                    {
                        return(false);
                    }

                    return(FExpRefConv(loader, typeSrc.AsArrayType().GetElementType(), typeDst.AsAggregateType().GetTypeArgsAll().Item(0)));
                }

                if (typeDst.IsArrayType() && typeSrc.IsAggregateType())
                {
                    // * From System.Array and the interfaces it implements, to any array-type.
                    if (loader.HasIdentityOrImplicitReferenceConversion(loader.GetReqPredefType(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.
                    ArrayType     arrayDest  = typeDst.AsArrayType();
                    AggregateType aggtypeSrc = typeSrc.AsAggregateType();
                    if (arrayDest.rank != 1 || !typeSrc.isInterfaceType() ||
                        aggtypeSrc.GetTypeArgsAll().Size != 1)
                    {
                        return(false);
                    }

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

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

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

                    Debug.Assert(!typeArr.IsNeverSameType());
                    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);
        }
예제 #38
0
        /***************************************************************************************************
        *   Lookup must be called before anything else can be called.
        *
        *   typeSrc - Must be an AggregateType or TypeParameterType.
        *   obj - the expression through which the member is being accessed. This is used for accessibility
        *       of protected members and for constructing a MEMGRP from the results of the lookup.
        *       It is legal for obj to be an EK_CLASS, in which case it may be used for accessibility, but
        *       will not be used for MEMGRP construction.
        *   symWhere - the symbol from with the name is being accessed (for checking accessibility).
        *   name - the name to look for.
        *   arity - the number of type args specified. Only members that support this arity are found.
        *       Note that when arity is zero, all methods are considered since we do type argument
        *       inferencing.
        *
        *   flags - See MemLookFlags.
        *       TypeVarsAllowed only applies to the most derived type (not base types).
        ***************************************************************************************************/
        public bool Lookup(CSemanticChecker checker, CType typeSrc, Expr obj, ParentSymbol symWhere, Name name, int arity, MemLookFlags flags)
        {
            Debug.Assert((flags & ~MemLookFlags.All) == 0);
            Debug.Assert(obj == null || obj.Type != null);
            Debug.Assert(typeSrc is AggregateType);
            Debug.Assert(checker != null);

            _prgtype = _rgtypeStart;

            // Save the inputs for error handling, etc.
            _pSemanticChecker = checker;
            _pSymbolLoader    = checker.SymbolLoader;
            _typeSrc          = typeSrc;
            _obj      = obj is ExprClass ? null : obj;
            _symWhere = symWhere;
            _name     = name;
            _arity    = arity;
            _flags    = flags;

            _typeQual = (_flags & MemLookFlags.Ctor) != 0 ? _typeSrc : obj?.Type;

            // Determine what to search.
            AggregateType typeCls1  = null;
            AggregateType typeIface = null;
            TypeArray     ifaces    = BSYMMGR.EmptyTypeArray();
            AggregateType typeCls2  = null;

            if (!typeSrc.IsInterfaceType)
            {
                typeCls1 = (AggregateType)typeSrc;

                if (typeCls1.IsWindowsRuntimeType)
                {
                    ifaces = typeCls1.GetWinRTCollectionIfacesAll(GetSymbolLoader());
                }
            }
            else
            {
                Debug.Assert((_flags & (MemLookFlags.Ctor | MemLookFlags.NewObj | MemLookFlags.Operator | MemLookFlags.BaseCall)) == 0);
                typeIface = (AggregateType)typeSrc;
                ifaces    = typeIface.IfacesAll;
            }

            if (typeIface != null || ifaces.Count > 0)
            {
                typeCls2 = GetSymbolLoader().GetPredefindType(PredefinedType.PT_OBJECT);
            }

            // Search the class first (except possibly object).
            if (typeCls1 == null || LookupInClass(typeCls1, ref typeCls2))
            {
                // Search the interfaces.
                if ((typeIface != null || ifaces.Count > 0) && LookupInInterfaces(typeIface, ifaces) && typeCls2 != null)
                {
                    // Search object last.
                    Debug.Assert(typeCls2 != null && typeCls2.IsPredefType(PredefinedType.PT_OBJECT));

                    AggregateType result = null;
                    LookupInClass(typeCls2, ref result);
                }
            }

            return(!FError());
        }
예제 #39
0
            /////////////////////////////////////////////////////////////////////////////////

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

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

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

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

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

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

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

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

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

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

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

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

                        optionalArgument = exprFactory.CreateZeroInit(pParamType);
                    }
                }

                Debug.Assert(optionalArgument != null);
                optionalArgument.IsOptionalArgument = true;
                return optionalArgument;
            }
        private static bool CheckSingleConstraint(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 ErrorHandling.Error(ErrorCode.ERR_RefConstraintNotSatisfied, symErr, new ErrArgNoRef(var), arg);
                }

                return(false);
            }

            TypeArray bnds     = TypeManager.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 ErrorHandling.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(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 && 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 ErrorHandling.Error(error, new ErrArg(symErr), new ErrArg(typeBnd, ErrArgFlags.Unique), var, new ErrArg(arg, ErrArgFlags.Unique));
                    }

                    return(false);
                }
            }
예제 #41
0
            /////////////////////////////////////////////////////////////////////////////////

            public static MethodOrPropertySymbol FindMostDerivedMethod(
                    SymbolLoader symbolLoader,
                    MethodOrPropertySymbol pMethProp,
                    CType pType)
            {
                MethodSymbol method;
                bool bIsIndexer = false;

                if (pMethProp.IsMethodSymbol())
                {
                    method = pMethProp.AsMethodSymbol();
                }
                else
                {
                    PropertySymbol prop = pMethProp.AsPropertySymbol();
                    method = prop.methGet != null ? prop.methGet : prop.methSet;
                    if (method == null)
                    {
                        return null;
                    }
                    bIsIndexer = prop.isIndexer();
                }

                if (!method.isVirtual)
                {
                    return method;
                }

                if (pType == null)
                {
                    // This must be a static call.
                    return method;
                }

                // Now get the slot method.
                if (method.swtSlot != null && method.swtSlot.Meth() != null)
                {
                    method = method.swtSlot.Meth();
                }

                if (!pType.IsAggregateType())
                {
                    // Not something that can have overrides anyway.
                    return method;
                }

                for (AggregateSymbol pAggregate = pType.AsAggregateType().GetOwningAggregate();
                        pAggregate != null && pAggregate.GetBaseAgg() != null;
                        pAggregate = pAggregate.GetBaseAgg())
                {
                    for (MethodOrPropertySymbol meth = symbolLoader.LookupAggMember(method.name, pAggregate, symbmask_t.MASK_MethodSymbol | symbmask_t.MASK_PropertySymbol).AsMethodOrPropertySymbol();
                            meth != null;
                            meth = symbolLoader.LookupNextSym(meth, pAggregate, symbmask_t.MASK_MethodSymbol | symbmask_t.MASK_PropertySymbol).AsMethodOrPropertySymbol())
                    {
                        if (!meth.isOverride)
                        {
                            continue;
                        }
                        if (meth.swtSlot.Sym != null && meth.swtSlot.Sym == method)
                        {
                            if (bIsIndexer)
                            {
                                Debug.Assert(meth.IsMethodSymbol());
                                return meth.AsMethodSymbol().getProperty();
                            }
                            else
                            {
                                return meth;
                            }
                        }
                    }
                }

                // If we get here, it means we can have two cases: one is that we have 
                // a delegate. This is because the delegate invoke method is virtual and is 
                // an override, but we wont have the slots set up correctly, and will 
                // not find the base type in the inheritance hierarchy. The second is that
                // we're calling off of the base itself.
                Debug.Assert(method.parent.IsAggregateSymbol());
                return method;
            }
예제 #42
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();
        }
예제 #43
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;
        }
예제 #44
0
        public PredefinedMembers(SymbolLoader loader)
        {
            _loader = loader;
            Debug.Assert(_loader != null);

            _methods = new MethodSymbol[(int)PREDEFMETH.PM_COUNT];
            _properties = new PropertySymbol[(int)PREDEFPROP.PP_COUNT];

#if DEBUG
            // validate the tables
            for (int i = (int)PREDEFMETH.PM_FIRST + 1; i < (int)PREDEFMETH.PM_COUNT; i++)
            {
                Debug.Assert((int)GetMethInfo((PREDEFMETH)i).method == i);
            }
            for (int i = (int)PREDEFPROP.PP_FIRST + 1; i < (int)PREDEFPROP.PP_COUNT; i++)
            {
                Debug.Assert((int)GetPropInfo((PREDEFPROP)i).property == i);
            }
#endif
        }
예제 #45
0
        // WARNING: These methods do not precisely match the spec.
        // WARNING: For example most also return true for identiy conversions,
        // WARNING: FExpRefConv includes all Implict and Explicit reference conversions.

        /***************************************************************************************************
            Determine whether there is an implicit reference conversion from typeSrc to typeDst. This is
            when the source is a reference type and the destination is a base type of the source. Note
            that typeDst.IsRefType() may still return false (when both are type parameters).
        ***************************************************************************************************/
        public static bool FImpRefConv(SymbolLoader loader, CType typeSrc, CType typeDst)
        {
            return typeSrc.IsRefType() && loader.HasIdentityOrImplicitReferenceConversion(typeSrc, typeDst);
        }
예제 #46
0
 public static ExprBinOp Rewrite(ExprBoundLambda expr, ExprFactory expressionFactory, SymbolLoader symbolLoader) =>
 new ExpressionTreeRewriter(expressionFactory, symbolLoader).VisitBoundLambda(expr);
예제 #47
0
        /***************************************************************************************************
            Determines whether there is a boxing conversion from typeSrc to typeDst
        
        13.1.5 Boxing conversions
        
        A boxing conversion permits any non-nullable-value-type to be implicitly converted to the type 
        object or System.ValueType or to any interface-type implemented by the non-nullable-value-type, 
        and any enum type to be implicitly converted to System.Enum as well. ... An enum can be boxed to 
        the type System.Enum, since that is the direct base class for all enums (21.4). A struct or enum 
        can be boxed to the type System.ValueType, since that is the direct base class for all 
        structs (18.3.2) and a base class for all enums.
        
        A nullable-type has a boxing conversion to the same set of types to which the nullable-type’s 
        underlying type has boxing conversions. 
        
        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). end note]
        *   From T to an interface-type I in T’s effective interface set and from T to any base 
            interface of I.
        ***************************************************************************************************/

        public static bool FBoxingConv(SymbolLoader loader, CType typeSrc, CType typeDst)
        {
            return loader.HasImplicitBoxingConversion(typeSrc, typeDst);
        }
예제 #48
0
 public static EXPR Rewrite(EXPR expr, ExprFactory expressionFactory, SymbolLoader symbolLoader)
 {
     ExpressionTreeRewriter rewriter = new ExpressionTreeRewriter(expressionFactory, symbolLoader);
     rewriter.alwaysRewrite = true;
     return rewriter.Visit(expr);
 }
예제 #49
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.IsTypeParameterType())
                {
                    return true;
                }
                if (typeSrc.IsTypeParameterType() && 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.IsAggregateType() && typeDst.IsAggregateType())
                {
                    AggregateSymbol aggSrc = typeSrc.AsAggregateType().getAggregate();
                    AggregateSymbol aggDest = typeDst.AsAggregateType().getAggregate();

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

                // *    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 (typeSrc.IsArrayType() && typeDst.IsArrayType())
                {
                    return typeSrc.AsArrayType().rank == typeDst.AsArrayType().rank && FExpRefConv(loader, typeSrc.AsArrayType().GetElementType(), typeDst.AsArrayType().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 (typeSrc.IsArrayType())
                {
                    if (typeSrc.AsArrayType().rank != 1 ||
                        !typeDst.isInterfaceType() || typeDst.AsAggregateType().GetTypeArgsAll().Size != 1)
                    {
                        return false;
                    }

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

                    if ((aggIList == null ||
                        !loader.IsBaseAggregate(aggIList, typeDst.AsAggregateType().getAggregate())) &&
                        (aggIReadOnlyList == null ||
                        !loader.IsBaseAggregate(aggIReadOnlyList, typeDst.AsAggregateType().getAggregate())))
                    {
                        return false;
                    }

                    return FExpRefConv(loader, typeSrc.AsArrayType().GetElementType(), typeDst.AsAggregateType().GetTypeArgsAll().Item(0));
                }

                if (typeDst.IsArrayType() && typeSrc.IsAggregateType())
                {
                    // * From System.Array and the interfaces it implements, to any array-type.
                    if (loader.HasIdentityOrImplicitReferenceConversion(loader.GetReqPredefType(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.
                    ArrayType arrayDest = typeDst.AsArrayType();
                    AggregateType aggtypeSrc = typeSrc.AsAggregateType();
                    if (arrayDest.rank != 1 || !typeSrc.isInterfaceType() ||
                        aggtypeSrc.GetTypeArgsAll().Size != 1)
                    {
                        return false;
                    }

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

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

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

                    Debug.Assert(!typeArr.IsNeverSameType());
                    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;
        }
예제 #50
0
        /***************************************************************************************************
        *   Lookup must be called before anything else can be called.
        *
        *   typeSrc - Must be an AggregateType or TypeParameterType.
        *   obj - the expression through which the member is being accessed. This is used for accessibility
        *       of protected members and for constructing a MEMGRP from the results of the lookup.
        *       It is legal for obj to be an EK_CLASS, in which case it may be used for accessibility, but
        *       will not be used for MEMGRP construction.
        *   symWhere - the symbol from with the name is being accessed (for checking accessibility).
        *   name - the name to look for.
        *   arity - the number of type args specified. Only members that support this arity are found.
        *       Note that when arity is zero, all methods are considered since we do type argument
        *       inferencing.
        *
        *   flags - See MemLookFlags.
        *       TypeVarsAllowed only applies to the most derived type (not base types).
        ***************************************************************************************************/
        public bool Lookup(CSemanticChecker checker, CType typeSrc, EXPR obj, ParentSymbol symWhere, Name name, int arity, MemLookFlags flags)
        {
            Debug.Assert((flags & ~MemLookFlags.All) == 0);
            Debug.Assert(obj == null || obj.type != null);
            Debug.Assert(typeSrc.IsAggregateType() || typeSrc.IsTypeParameterType());
            Debug.Assert(checker != null);

            _prgtype = _rgtypeStart;

            // Save the inputs for error handling, etc.
            _pSemanticChecker = checker;
            _pSymbolLoader    = checker.GetSymbolLoader();
            _typeSrc          = typeSrc;
            _obj      = (obj != null && !obj.isCLASS()) ? obj : null;
            _symWhere = symWhere;
            _name     = name;
            _arity    = arity;
            _flags    = flags;

            if ((_flags & MemLookFlags.BaseCall) != 0)
            {
                _typeQual = null;
            }
            else if ((_flags & MemLookFlags.Ctor) != 0)
            {
                _typeQual = _typeSrc;
            }
            else if (obj != null)
            {
                _typeQual = (CType)obj.type;
            }
            else
            {
                _typeQual = null;
            }

            // Determine what to search.
            AggregateType typeCls1  = null;
            AggregateType typeIface = null;
            TypeArray     ifaces    = BSYMMGR.EmptyTypeArray();
            AggregateType typeCls2  = null;

            if (typeSrc.IsTypeParameterType())
            {
                Debug.Assert((_flags & (MemLookFlags.Ctor | MemLookFlags.NewObj | MemLookFlags.Operator | MemLookFlags.BaseCall | MemLookFlags.TypeVarsAllowed)) == 0);
                _flags  &= ~MemLookFlags.TypeVarsAllowed;
                ifaces   = typeSrc.AsTypeParameterType().GetInterfaceBounds();
                typeCls1 = typeSrc.AsTypeParameterType().GetEffectiveBaseClass();
                if (ifaces.size > 0 && typeCls1.isPredefType(PredefinedType.PT_OBJECT))
                {
                    typeCls1 = null;
                }
            }
            else if (!typeSrc.isInterfaceType())
            {
                typeCls1 = typeSrc.AsAggregateType();

                if (typeCls1.IsWindowsRuntimeType())
                {
                    ifaces = typeCls1.GetWinRTCollectionIfacesAll(GetSymbolLoader());
                }
            }
            else
            {
                Debug.Assert(typeSrc.isInterfaceType());
                Debug.Assert((_flags & (MemLookFlags.Ctor | MemLookFlags.NewObj | MemLookFlags.Operator | MemLookFlags.BaseCall)) == 0);
                typeIface = typeSrc.AsAggregateType();
                ifaces    = typeIface.GetIfacesAll();
            }

            if (typeIface != null || ifaces.size > 0)
            {
                typeCls2 = GetSymbolLoader().GetReqPredefType(PredefinedType.PT_OBJECT);
            }

            // Search the class first (except possibly object).
            if (typeCls1 == null || LookupInClass(typeCls1, ref typeCls2))
            {
                // Search the interfaces.
                if ((typeIface != null || ifaces.size > 0) && LookupInInterfaces(typeIface, ifaces) && typeCls2 != null)
                {
                    // Search object last.
                    Debug.Assert(typeCls2 != null && typeCls2.isPredefType(PredefinedType.PT_OBJECT));

                    AggregateType result = null;
                    LookupInClass(typeCls2, ref result);
                }
            }

            // if we are requested with extension methods
            _results = new CMemberLookupResults(GetAllTypes(), _name);

            return(!FError());
        }
예제 #51
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;
        }
예제 #52
0
 public TypeManager GetTypeManager()
 {
     return(SymbolLoader.GetTypeManager());
 }
예제 #53
0
 public CType GetDelegateReturnType(SymbolLoader pSymbolLoader)
 {
     Debug.Assert(isDelegateType());
     MethodSymbol invoke = pSymbolLoader.LookupInvokeMeth(this.getAggregate());
     if (invoke == null || !invoke.isInvoke())
     {
         // This can happen if the delegate is internal to another assembly. 
         return null;
     }
     return this.getAggregate().GetTypeManager().SubstType(invoke.RetType, this);
 }
예제 #54
0
 public MiscSymFactory GetGlobalMiscSymFactory()
 {
     return(SymbolLoader.GetGlobalMiscSymFactory());
 }
예제 #55
0
        ////////////////////////////////////////////////////////////////////////////////

        public bool HasConversion(SymbolLoader pLoader)
        {
            pLoader.RuntimeBinderSymbolTable.AddConversionsForType(AssociatedSystemType);

            if (!_hasConversion.HasValue)
            {
                // ok, we tried defining all the conversions, and we didn't get anything
                // for this type.  However, we will still think this type has conversions
                // if it's base type has conversions.
                _hasConversion = GetBaseAgg() != null && GetBaseAgg().HasConversion(pLoader);
            }

            return _hasConversion.Value;
        }
예제 #56
0
        //
        // SymbolLoader forwarders (end)
        /////////////////////////////////////////////////////////////////////////////////

        //
        // Utility methods
        //
        private ACCESSERROR CheckAccessCore(Symbol symCheck, AggregateType atsCheck, Symbol symWhere, CType typeThru)
        {
            Debug.Assert(symCheck != null);
            Debug.Assert(atsCheck == null || symCheck.parent == atsCheck.getAggregate());
            Debug.Assert(typeThru == null ||
                         typeThru is AggregateType ||
                         typeThru is TypeParameterType ||
                         typeThru is ArrayType ||
                         typeThru is NullableType ||
                         typeThru is ErrorType);

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

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

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

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

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

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

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

            for (Symbol symT = symWhere; symT != null; symT = symT.parent)
            {
                if (symT is AggregateSymbol aggSym)
                {
                    aggWhere = aggSym;
                    break;
                }
                if (symT is AggregateDeclaration aggDec)
                {
                    aggWhere = aggDec.Agg();
                    break;
                }
            }

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

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

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

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

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

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

            AggregateType atsThru = null;

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

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

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

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

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

            return((atsThru == null) ? ACCESSERROR.ACCESSERROR_NOACCESS : ACCESSERROR.ACCESSERROR_NOACCESSTHRU);
        }
예제 #57
0
        // WARNING: These methods do not precisely match the spec.
        // WARNING: For example most also return true for identity conversions,
        // WARNING: FExpRefConv includes all Implicit and Explicit reference conversions.

        /***************************************************************************************************
        *   Determine whether there is an implicit reference conversion from typeSrc to typeDst. This is
        *   when the source is a reference type and the destination is a base type of the source. Note
        *   that typeDst.IsRefType() may still return false (when both are type parameters).
        ***************************************************************************************************/
        public static bool FImpRefConv(CType typeSrc, CType typeDst) =>
        typeSrc.IsReferenceType && SymbolLoader.HasIdentityOrImplicitReferenceConversion(typeSrc, typeDst);