Example #1
0
            public GroupToArgsBinder(ExpressionBinder exprBinder, BindingFlag bindFlags, EXPRMEMGRP grp, ArgInfos args, ArgInfos originalArgs, bool bHasNamedArguments, AggregateType atsDelegate)
            {
                Debug.Assert(grp != null);
                Debug.Assert(exprBinder != null);
                Debug.Assert(args != null);

                _pExprBinder = exprBinder;
                _fCandidatesUnsupported = false;
                _fBindFlags = bindFlags;
                _pGroup = grp;
                _pArguments = args;
                _pOriginalArguments = originalArgs;
                _bHasNamedArguments = bHasNamedArguments;
                _pDelegate = atsDelegate;
                _pCurrentType = null;
                _pCurrentSym = null;
                _pCurrentTypeArgs = null;
                _pCurrentParameters = null;
                _pBestParameters = null;
                _nArgBest = -1;
                _nWrongCount = 0;
                _bIterateToEndOfNsList = false;
                _bBindingCollectionAddArgs = false;
                _results = new GroupToArgsBinderResult();
                _methList = new List<CandidateFunctionMember>();
                _mpwiParamTypeConstraints = new MethPropWithInst();
                _mpwiBogus = new MethPropWithInst();
                _mpwiCantInferInstArg = new MethPropWithInst();
                _mwtBadArity = new MethWithType();
                _HiddenTypes = new List<CType>();
            }
Example #2
0
 public CMethodIterator(CSemanticChecker checker, SymbolLoader symLoader, Name name, TypeArray containingTypes, CType @object, CType qualifyingType, Declaration context, bool allowBogusAndInaccessible, bool allowExtensionMethods, int arity, EXPRFLAG flags, symbmask_t mask)
 {
     Debug.Assert(name != null);
     Debug.Assert(symLoader != null);
     Debug.Assert(checker != null);
     Debug.Assert(containingTypes != null);
     _pSemanticChecker = checker;
     _pSymbolLoader = symLoader;
     _pCurrentType = null;
     _pCurrentSym = null;
     _pName = name;
     _pContainingTypes = containingTypes;
     _pQualifyingType = qualifyingType;
     _pContext = context;
     _bAllowBogusAndInaccessible = allowBogusAndInaccessible;
     _bAllowExtensionMethods = allowExtensionMethods;
     _nArity = arity;
     _flags = flags;
     _mask = mask;
     _nCurrentTypeCount = 0;
     _bIsCheckingInstanceMethods = true;
     _bAtEnd = false;
     _bCurrentSymIsBogus = false;
     _bCurrentSymIsInaccessible = false;
     _bcanIncludeExtensionsInResults = _bAllowExtensionMethods;
     _bEndIterationAtCurrentExtensionList = false;
 }
Example #3
0
        public virtual ACCESSERROR CheckAccess2(Symbol symCheck, AggregateType atsCheck, Symbol symWhere, CType typeThru)
        {
            Debug.Assert(symCheck != null);
            Debug.Assert(atsCheck == null || symCheck.parent == atsCheck.getAggregate());
            Debug.Assert(typeThru == null ||
                   typeThru.IsAggregateType() ||
                   typeThru.IsTypeParameterType() ||
                   typeThru.IsArrayType() ||
                   typeThru.IsNullableType() ||
                   typeThru.IsErrorType());

#if DEBUG

            switch (symCheck.getKind())
            {
                default:
                    break;
                case SYMKIND.SK_MethodSymbol:
                case SYMKIND.SK_PropertySymbol:
                case SYMKIND.SK_FieldSymbol:
                case SYMKIND.SK_EventSymbol:
                    Debug.Assert(atsCheck != null);
                    break;
            }

#endif // DEBUG

            ACCESSERROR error = CheckAccessCore(symCheck, atsCheck, symWhere, typeThru);
            if (ACCESSERROR.ACCESSERROR_NOERROR != error)
            {
                return error;
            }

            // Check the accessibility of the return CType.
            CType CType = symCheck.getType();
            if (CType == null)
            {
                return ACCESSERROR.ACCESSERROR_NOERROR;
            }

            // For members of AGGSYMs, atsCheck should always be specified!
            Debug.Assert(atsCheck != null);

            if (atsCheck.getAggregate().IsSource())
            {
                // We already check the "at least as accessible as" rules.
                // Does this always work for generics?
                // Could we get a bad CType argument in typeThru?
                // Maybe call CheckTypeAccess on typeThru?
                return ACCESSERROR.ACCESSERROR_NOERROR;
            }

            // Substitute on the CType.
            if (atsCheck.GetTypeArgsAll().size > 0)
            {
                CType = SymbolLoader.GetTypeManager().SubstType(CType, atsCheck);
            }

            return CheckTypeAccess(CType, symWhere) ? ACCESSERROR.ACCESSERROR_NOERROR : ACCESSERROR.ACCESSERROR_NOACCESS;
        }
 public void SetBounds(TypeArray pBounds)
 {
     _pBounds = pBounds;
     _pInterfaceBounds = null;
     _pEffectiveBaseClass = null;
     _pDeducedBaseClass = null;
     _bHasRefBound = false;
     _bHasValBound = false;
 }
            /////////////////////////////////////////////////////////////////////////////////

            public void AddInconvertibleResult(
                MethodSymbol method,
                AggregateType currentType,
                TypeArray currentTypeArgs)
            {
                if (InconvertibleResult.Sym == null)
                {
                    // This is the first one, so set it for error reporting usage.
                    InconvertibleResult.Set(method, currentType, currentTypeArgs);
                }
                _inconvertibleResults.Add(new MethPropWithInst(method, currentType, currentTypeArgs));
            }
Example #6
0
        // Aggregate
        public AggregateType CreateAggregateType(
            Name name,
            AggregateSymbol parent,
            TypeArray typeArgsThis,
            AggregateType outerType)
        {
            AggregateType type = new AggregateType();

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

            type.SetTypeKind(TypeKind.TK_AggregateType);
            return type;
        }
Example #7
0
        public AggregateType GetAts(ErrorHandling errorContext)
        {
            AggregateSymbol aggNullable = typeManager.GetNullable();
            if (aggNullable == null)
            {
                throw Error.InternalCompilerError();
            }

            if (ats == null)
            {
                CType typePar = GetUnderlyingType();
                CType[] typeParArray = new CType[] { typePar };
                TypeArray ta = symmgr.AllocParams(1, typeParArray);
                ats = typeManager.GetAggregate(aggNullable, ta);
            }
            return ats;
        }
Example #8
0
        public AggregateType GetBaseClass()
        {
#if CSEE
            AggregateType atsBase = getAggregate().GetBaseClass();
            if (!atsBase || GetTypeArgsAll().size == 0 || atsBase.GetTypeArgsAll().size == 0)
                return atsBase;

            return getAggregate().GetTypeManager().SubstType(atsBase, GetTypeArgsAll()).AsAggregateType();
#else // !CSEE

            if (_baseType == null)
            {
                _baseType = getAggregate().GetTypeManager().SubstType(getAggregate().GetBaseClass(), GetTypeArgsAll()) as AggregateType;
            }

            return _baseType;
#endif // !CSEE
        }
Example #9
0
        public AggregateType GetAts(ErrorHandling errorContext)
        {
            AggregateSymbol aggNullable = typeManager.GetNullable();
            if (aggNullable == null)
            {
                throw Error.InternalCompilerError();
            }

            if (ats == null)
            {
                if (aggNullable == null)
                {
                    typeManager.ReportMissingPredefTypeError(errorContext, PredefinedType.PT_G_OPTIONAL);
                    return null;
                }

                CType typePar = GetUnderlyingType();
                CType[] typeParArray = new CType[] { typePar };
                TypeArray ta = symmgr.AllocParams(1, typeParArray);
                ats = typeManager.GetAggregate(aggNullable, ta);
            }
            return ats;
        }
Example #10
0
 public PropWithType(PropertySymbol prop, AggregateType ats)
 {
     Set(prop, ats);
 }
Example #11
0
 public virtual void Clear()
 {
     _sym = null;
     _ats = null;
 }
Example #12
0
 public MethPropWithInst(MethodOrPropertySymbol mps, AggregateType ats, TypeArray typeArgs)
 {
     Set(mps, ats, typeArgs);
 }
Example #13
0
 public FieldWithType(FieldSymbol field, AggregateType ats)
 {
     Set(field, ats);
 }
Example #14
0
 public MethWithInst(MethodSymbol meth, AggregateType ats)
     : this(meth, ats, null)
 {
 }
Example #15
0
 public MethWithType(MethodSymbol meth, AggregateType ats)
 {
     Set(meth, ats);
 }
Example #16
0
 public SubstContext(AggregateType type, TypeArray typeArgsMeth)
     : this(type, typeArgsMeth, SubstTypeFlags.NormNone)
 {
 }
Example #17
0
 public FieldWithType(FieldSymbol field, AggregateType ats)
 {
     Set(field, ats);
 }
Example #18
0
 private static bool IsDelegateType(CType pSrcType, AggregateType pAggType) =>
 TypeManager.SubstType(pSrcType, pAggType, pAggType.TypeArgsAll).IsDelegateType;
Example #19
0
 public SubstContext(AggregateType type)
     : this(type, null, SubstTypeFlags.NormNone)
 {
 }
Example #20
0
            private bool bindImplicitConversionBetweenSimpleTypes(AggregateType aggTypeSrc)
            {
                AggregateSymbol aggSrc = aggTypeSrc.getAggregate();

                Debug.Assert(aggSrc.getThisType().isSimpleType());
                Debug.Assert(_typeDest.isSimpleType());

                Debug.Assert(aggSrc.IsPredefined() && _typeDest.isPredefined());
                PredefinedType ptSrc  = aggSrc.GetPredefType();
                PredefinedType ptDest = _typeDest.getPredefType();
                ConvKind       convertKind;
                bool           fConstShrinkCast = false;

                Debug.Assert((int)ptSrc < NUM_SIMPLE_TYPES && (int)ptDest < NUM_SIMPLE_TYPES);

                // 13.1.7 Implicit constant expression conversions
                //
                // An implicit constant expression conversion permits the following conversions:
                // *   A constant-expression (14.16) of type int can be converted to type sbyte,  byte,  short,
                //     ushort,  uint, or ulong, provided the value of the constant-expression is within the range
                //     of the destination type.
                // *   A constant-expression of type long can be converted to type ulong, provided the value of
                //     the constant-expression is not negative.
                // Note: Don't use GetConst here since the conversion only applies to bona-fide compile time constants.
                if (_exprSrc != null && _exprSrc.isCONSTANT_OK() &&
                    ((ptSrc == PredefinedType.PT_INT && ptDest != PredefinedType.PT_BOOL && ptDest != PredefinedType.PT_CHAR) ||
                     (ptSrc == PredefinedType.PT_LONG && ptDest == PredefinedType.PT_ULONG)) &&
                    isConstantInRange(_exprSrc.asCONSTANT(), _typeDest))
                {
                    // Special case (CLR 6.1.6): if integral constant is in range, the conversion is a legal implicit conversion.
                    convertKind      = ConvKind.Implicit;
                    fConstShrinkCast = _needsExprDest && (GetConvKind(ptSrc, ptDest) != ConvKind.Implicit);
                }
                else if (ptSrc == ptDest)
                {
                    // Special case: precision limiting casts to float or double
                    Debug.Assert(ptSrc == PredefinedType.PT_FLOAT || ptSrc == PredefinedType.PT_DOUBLE);
                    Debug.Assert(0 != (_flags & CONVERTTYPE.ISEXPLICIT));
                    convertKind = ConvKind.Implicit;
                }
                else
                {
                    convertKind = GetConvKind(ptSrc, ptDest);
                    Debug.Assert(convertKind != ConvKind.Identity);
                    // identity conversion should have been handled at first.
                }

                if (convertKind != ConvKind.Implicit)
                {
                    return(false);
                }

                // An implicit conversion exists. Do the conversion.
                if (_exprSrc.GetConst() != null)
                {
                    // Fold the constant cast if possible.
                    ConstCastResult result = _binder.bindConstantCast(_exprSrc, _exprTypeDest, _needsExprDest, out _exprDest, false);
                    if (result == ConstCastResult.Success)
                    {
                        return(true);  // else, don't fold and use a regular cast, below.
                    }
                }

                if (isUserDefinedConversion(ptSrc, ptDest))
                {
                    if (!_needsExprDest)
                    {
                        return(true);
                    }
                    // According the language, this is a standard conversion, but it is implemented
                    // through a user-defined conversion. Because it's a standard conversion, we don't
                    // test the NOUDC flag here.
                    return(_binder.bindUserDefinedConversion(_exprSrc, aggTypeSrc, _typeDest, _needsExprDest, out _exprDest, true));
                }
                if (_needsExprDest)
                {
                    _binder.bindSimpleCast(_exprSrc, _exprTypeDest, out _exprDest);
                }
                return(true);
            }
Example #21
0
 public void InsertAggregate(
     AggregateSymbol aggregate, AggregateType outer, TypeArray args, AggregateType pAggregate)
 {
     Debug.Assert(LookupAggregate(aggregate, outer, args) == null);
     _aggregateTable.Add(MakeKey(aggregate, MakeKey(outer, args)), pAggregate);
 }
Example #22
0
 public AggregateType LookupAggregate(AggregateSymbol aggregate, AggregateType outer, TypeArray args)
 {
     _aggregateTable.TryGetValue(MakeKey(aggregate, MakeKey(outer, args)), out AggregateType result);
     return(result);
 }
Example #23
0
 public MethPropWithType(MethodOrPropertySymbol mps, AggregateType ats)
 {
     Set(mps, ats);
 }
Example #24
0
 private SubstContext(AggregateType type, TypeArray typeArgsMeth, SubstTypeFlags grfst)
 {
     Init(type != null ? type.GetTypeArgsAll() : null, typeArgsMeth, grfst);
 }
Example #25
0
 public PropWithType(PropertySymbol prop, AggregateType ats)
 {
     Set(prop, ats);
 }
            /***************************************************************************************************
                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(GetErrorContext());
                if (atsDst == null)
                    return false;

                // Check for the unboxing conversion. This takes precedence over the wrapping conversions.
                if (GetSymbolLoader().HasBaseConversion(nubDst.GetUnderlyingType(), _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, _exprTypeDest, out _exprDest, EXPRFLAG.EXF_UNBOX);
                    }
                    return true;
                }

                int cnubDst;
                int cnubSrc;
                CType typeDstBase = nubDst.StripNubs(out cnubDst);
                ExprClass exprTypeDstBase = GetExprFactory().MakeClass(typeDstBase);
                CType typeSrcBase = _typeSrc.StripNubs(out cnubSrc);

                ConversionFunc pfn = (_flags & CONVERTTYPE.ISEXPLICIT) != 0 ?
                    (ConversionFunc)_binder.BindExplicitConversion :
                    (ConversionFunc)_binder.BindImplicitConversion;

                if (cnubSrc == 0)
                {
                    Debug.Assert(_typeSrc == typeSrcBase);

                    // The null type can be implicitly converted to T? as the default value.
                    if (_typeSrc.IsNullType())
                    {
                        // If we have the constant null, generate it as a default value of T?.  If we have 
                        // some crazy 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)
                        {
                            if (_exprSrc.isCONSTANT_OK())
                            {
                                _exprDest = GetExprFactory().CreateZeroInit(nubDst);
                            }
                            else
                            {
                                _exprDest = GetExprFactory().CreateCast(0x00, _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, exprTypeDstBase, nubDst, _needsExprDest, out exprTmp, _flags | CONVERTTYPE.NOUDC))
                    {
                        if (_needsExprDest)
                        {
                            ExprUserDefinedConversion exprUDC = exprTmp as ExprUserDefinedConversion;
                            if (exprUDC != null)
                            {
                                exprTmp = exprUDC.UserDefinedCall;
                            }

                            // This logic is left over from the days when T?? was legal. However there are error/LAF cases that necessitates the loop.
                            // typeSrc is not nullable so just wrap the required number of times. For legal code (cnubDst <= 0).

                            for (int i = 0; i < cnubDst; i++)
                            {
                                ExprCall call = _binder.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, exprTypeDstBase, nubDst, 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 = GetExprFactory().CreateMemGroup(null, mwi);
                    ExprCall exprDst = GetExprFactory().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);
                    ExprClass arg2 = GetExprFactory().MakeClass(typeDstBase);

                    bool convertible;
                    if (0 != (_flags & CONVERTTYPE.ISEXPLICIT))
                    {
                        convertible = _binder.BindExplicitConversion(arg1, arg1.Type, arg2, typeDstBase, out arg1, _flags | CONVERTTYPE.NOUDC);
                    }
                    else
                    {
                        convertible = _binder.BindImplicitConversion(arg1, arg1.Type, arg2, typeDstBase, out arg1, _flags | CONVERTTYPE.NOUDC);
                    }
                    if (!convertible)
                    {
                        VSFAIL("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;
            }
Example #27
0
 public MethPropWithInst(MethodOrPropertySymbol mps, AggregateType ats, TypeArray typeArgs)
 {
     Set(mps, ats, typeArgs);
 }
Example #28
0
        ////////////////////////////////////////////////////////////////////////////////

        private bool LowerBoundInterfaceInference(CType pSource, AggregateType pDest)
        {
            if (!pDest.isInterfaceType())
            {
                return false;
            }

            // SPEC:  Otherwise, if V is an interface CType C<V1...Vk> and U is a class CType
            // SPEC:   or struct CType and there is a unique set U1...Uk such that U directly 
            // SPEC:   or indirectly implements C<U1...Uk> then an
            // SPEC:   exact, upper-bound, or lower-bound inference ...
            // SPEC:  ... and U is an interface CType ...
            // SPEC:  ... and U is a CType parameter ...

            //TypeArray pInterfaces = null;

            if (!pSource.isStructType() && !pSource.isClassType() &&
                !pSource.isInterfaceType() && !pSource.IsTypeParameterType())
            {
                return false;
            }

            var interfaces = pSource.AllPossibleInterfaces();
            AggregateType pInterface = null;
            foreach (AggregateType pCurrent in interfaces)
            {
                if (pCurrent.GetOwningAggregate() == pDest.GetOwningAggregate())
                {
                    if (pInterface == null)
                    {
                        pInterface = pCurrent;
                    }
                    else if (pInterface != pCurrent)
                    {
                        // Not unique. Bail out.
                        return false;
                    }
                }
            }
            if (pInterface == null)
            {
                return false;
            }
            LowerBoundTypeArgumentInference(pInterface, pDest);
            return true;
        }
Example #29
0
 public SymWithType(Symbol sym, AggregateType ats)
 {
     Set(sym, ats);
 }
Example #30
0
        ////////////////////////////////////////////////////////////////////////////////

        private bool UpperBoundInterfaceInference(AggregateType pSource, CType pDest)
        {
            if (!pSource.isInterfaceType())
            {
                return false;
            }

            // SPEC:  Otherwise, if U is an interface CType C<U1...Uk> and V is a class CType
            // SPEC:   or struct CType and there is a unique set V1...Vk such that V directly 
            // SPEC:   or indirectly implements C<V1...Vk> then an exact ...
            // SPEC:  ... and U is an interface CType ...

            if (!pDest.isStructType() && !pDest.isClassType() &&
                !pDest.isInterfaceType())
            {
                return false;
            }

            var interfaces = pDest.AllPossibleInterfaces();
            AggregateType pInterface = null;
            foreach (AggregateType pCurrent in interfaces)
            {
                if (pCurrent.GetOwningAggregate() == pSource.GetOwningAggregate())
                {
                    if (pInterface == null)
                    {
                        pInterface = pCurrent;
                    }
                    else if (pInterface != pCurrent)
                    {
                        // Not unique. Bail out.
                        return false;
                    }
                }
            }
            if (pInterface == null)
            {
                return false;
            }
            UpperBoundTypeArgumentInference(pInterface, pDest.AsAggregateType());
            return true;
        }
Example #31
0
 public MethWithInst(MethodSymbol meth, AggregateType ats)
     : this(meth, ats, null)
 {
 }
Example #32
0
        ////////////////////////////////////////////////////////////////////////////////

        private TypeArray GetFixedDelegateParameters(AggregateType pDelegateType)
        {
            Debug.Assert(pDelegateType.isDelegateType());

            // We have a delegate where the input types use no unfixed parameters.  Create
            // a substitution context; we can substitute unfixed parameters for themselves
            // since they don't actually occur in the inputs.  (They may occur in the outputs,
            // or there may be input parameters fixed to _unfixed_ method CType variables.
            // Both of those scenarios are legal.)

            CType[] ppMethodParameters = new CType[_pMethodTypeParameters.size];
            for (int iParam = 0; iParam < _pMethodTypeParameters.size; iParam++)
            {
                TypeParameterType pParam = _pMethodTypeParameters.ItemAsTypeParameterType(iParam);
                ppMethodParameters[iParam] = IsUnfixed(iParam) ? pParam : _pFixedResults[iParam];
            }
            SubstContext subsctx = new SubstContext(_pClassTypeArguments.ToArray(), _pClassTypeArguments.size,
                ppMethodParameters, _pMethodTypeParameters.size);
            AggregateType pFixedDelegateType =
                GetTypeManager().SubstType(pDelegateType, subsctx).AsAggregateType();
            TypeArray pFixedDelegateParams =
                pFixedDelegateType.GetDelegateParameters(GetSymbolLoader());
            return pFixedDelegateParams;
        }
Example #33
0
 public MethPropWithInst(MethodOrPropertySymbol mps, AggregateType ats)
     : this(mps, ats, null)
 {
 }
Example #34
0
 public MethWithInst(MethodSymbol meth, AggregateType ats, TypeArray typeArgs)
 {
     Set(meth, ats, typeArgs);
 }
Example #35
0
 public EventWithType(EventSymbol @event, AggregateType ats)
 {
     Set(@event, ats);
 }
Example #36
0
        protected virtual EXPRARRINIT GenerateMembersArray(AggregateType anonymousType, PredefinedType pt)
        {
            EXPR newArgs = null;
            EXPR newArgsTail = newArgs;
            int methodCount = 0;
            AggregateSymbol aggSym = anonymousType.getAggregate();

            for (Symbol member = aggSym.firstChild; member != null; member = member.nextChild)
            {
                if (member.IsMethodSymbol())
                {
                    MethodSymbol method = member.AsMethodSymbol();
                    if (method.MethKind() == MethodKindEnum.PropAccessor)
                    {
                        EXPRMETHODINFO methodInfo = GetExprFactory().CreateMethodInfo(method, anonymousType, method.Params);
                        GetExprFactory().AppendItemToList(methodInfo, ref newArgs, ref newArgsTail);
                        methodCount++;
                    }
                }
            }

            AggregateType paramsArrayElementType = GetSymbolLoader().GetOptPredefTypeErr(pt, true);
            ArrayType paramsArrayType = GetSymbolLoader().GetTypeManager().GetArray(paramsArrayElementType, 1);
            EXPRCONSTANT paramsArrayArg = GetExprFactory().CreateIntegerConstant(methodCount);
            EXPRARRINIT arrayInit = GetExprFactory().CreateArrayInit(EXPRFLAG.EXF_CANTBENULL, paramsArrayType, newArgs, paramsArrayArg, null);
            arrayInit.dimSize = methodCount;
            arrayInit.dimSizes = new int[] { arrayInit.dimSize }; // CLEANUP: Why isn't this done by the factory?
            return arrayInit;
        }
Example #37
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.IsAggregateType() ||
                         typeThru.IsTypeParameterType() ||
                         typeThru.IsArrayType() ||
                         typeThru.IsNullableType() ||
                         typeThru.IsErrorType());

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            AggregateType atsThru = null;

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

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

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

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

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

            return((atsThru == null) ? ACCESSERROR.ACCESSERROR_NOACCESS : ACCESSERROR.ACCESSERROR_NOACCESSTHRU);
        }
Example #38
0
 public SymWithType(Symbol sym, AggregateType ats)
 {
     Set(sym, ats);
 }
Example #39
0
        ////////////////////////////////////////////////////////////////////////////////

        private bool UpperBoundClassInference(AggregateType pSource, CType pDest)
        {
            if (!pSource.isClassType() || !pDest.isClassType())
            {
                return false;
            }

            // SPEC:  Otherwise, if U is a class CType C<U1...Uk> and V is a class CType which
            // SPEC:   inherits directly or indirectly from C<V1...Vk> then an exact 
            // SPEC:   inference is made from each Ui to the corresponding Vi.

            AggregateType pDestBase = pDest.AsAggregateType().GetBaseClass();

            while (pDestBase != null)
            {
                if (pDestBase.GetOwningAggregate() == pSource.GetOwningAggregate())
                {
                    ExactTypeArgumentInference(pSource, pDestBase);
                    return true;
                }
                pDestBase = pDestBase.GetBaseClass();
            }
            return false;
        }
Example #40
0
 public bool CheckAccess(Symbol symCheck, AggregateType atsCheck, Symbol symWhere, CType typeThru)
 {
     return(CheckAccess2(symCheck, atsCheck, symWhere, typeThru) == ACCESSERROR.ACCESSERROR_NOERROR);
 }
Example #41
0
        ////////////////////////////////////////////////////////////////////////////////

        private void UpperBoundTypeArgumentInference(
            AggregateType pSource, AggregateType pDest)
        {
            // SPEC: The choice of inference for the i-th CType argument is made
            // SPEC: based on the declaration of the i-th CType parameter of C, as
            // SPEC: follows:
            // SPEC:  if Ui is known to be of reference CType and the i-th CType parameter
            // SPEC:   was declared as covariant then an upper-bound inference is made.
            // SPEC:  if Ui is known to be of reference CType and the i-th CType parameter
            // SPEC:   was declared as contravariant then a lower-bound inference is made.
            // SPEC:  otherwise, an exact inference is made.

            Debug.Assert(pSource != null);
            Debug.Assert(pDest != null);
            Debug.Assert(pSource.GetOwningAggregate() == pDest.GetOwningAggregate());

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

            Debug.Assert(pTypeParams != null);
            Debug.Assert(pSourceArgs != null);
            Debug.Assert(pDestArgs != null);

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

            for (int arg = 0; arg < pSourceArgs.size; ++arg)
            {
                TypeParameterType pTypeParam = pTypeParams.ItemAsTypeParameterType(arg);
                CType pSourceArg = pSourceArgs.Item(arg);
                CType pDestArg = pDestArgs.Item(arg);

                if (pSourceArg.IsRefType() && pTypeParam.Covariant)
                {
                    UpperBoundInference(pSourceArg, pDestArg);
                }
                else if (pSourceArg.IsRefType() && pTypeParam.Contravariant)
                {
                    LowerBoundInference(pSourceArgs.Item(arg), pDestArgs.Item(arg));
                }
                else
                {
                    ExactInference(pSourceArgs.Item(arg), pDestArgs.Item(arg));
                }
            }
        }
Example #42
0
        //////////////////////////////////////////////////////////////////////////////

        private bool HasDelegateConversion(AggregateType pSource, AggregateType pDest)
        {
            Debug.Assert(pSource != null && pSource.isDelegateType());
            Debug.Assert(pDest != null && pDest.isDelegateType());
            return(HasVariantConversion(pSource, pDest));
        }
Example #43
0
        //
        // SymbolLoader forwarders (end)
        /////////////////////////////////////////////////////////////////////////////////

        //
        // Utility methods
        //
        protected ACCESSERROR CheckAccessCore(Symbol symCheck, AggregateType atsCheck, Symbol symWhere, CType typeThru)
        {
            Debug.Assert(symCheck != null);
            Debug.Assert(atsCheck == null || symCheck.parent == atsCheck.getAggregate());
            Debug.Assert(typeThru == null ||
                   typeThru.IsAggregateType() ||
                   typeThru.IsTypeParameterType() ||
                   typeThru.IsArrayType() ||
                   typeThru.IsNullableType() ||
                   typeThru.IsErrorType());

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

                case ACCESS.ACC_UNKNOWN:
                    return ACCESSERROR.ACCESSERROR_NOACCESS;

                case ACCESS.ACC_PUBLIC:
                    return ACCESSERROR.ACCESSERROR_NOERROR;

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

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

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

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

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

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

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

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

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

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

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

            AggregateType atsThru = null;

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

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

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

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

            return (atsThru == null) ? ACCESSERROR.ACCESSERROR_NOACCESS : ACCESSERROR.ACCESSERROR_NOACCESSTHRU;
        }
Example #44
0
        // Check the constraints of any type arguments in the given Type.
        public static bool CheckConstraints(CSemanticChecker checker, ErrorHandling errHandling, CType type, CheckConstraintsFlags flags)
        {
            type = type.GetNakedType(false);

            if (type.IsNullableType())
            {
                CType typeT = type.AsNullableType().GetAts(checker.GetErrorContext());
                if (typeT != null)
                {
                    type = typeT;
                }
                else
                {
                    type = type.GetNakedType(true);
                }
            }

            if (!type.IsAggregateType())
            {
                return(true);
            }

            AggregateType ats = type.AsAggregateType();

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

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

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

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

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

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

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

            // Now check type args themselves.
            for (int i = 0; i < typeArgsThis.size; i++)
            {
                CType arg = typeArgsThis.Item(i).GetNakedType(true);
                if (arg.IsAggregateType() && !arg.AsAggregateType().fConstraintsChecked)
                {
                    CheckConstraints(checker, errHandling, arg.AsAggregateType(), flags | CheckConstraintsFlags.Outer);
                    if (arg.AsAggregateType().fConstraintError)
                    {
                        ats.fConstraintError = true;
                    }
                }
            }
            return(!ats.fConstraintError);
        }
Example #45
0
 public bool CheckAccess(Symbol symCheck, AggregateType atsCheck, Symbol symWhere, CType typeThru)
 {
     return CheckAccess2(symCheck, atsCheck, symWhere, typeThru) == ACCESSERROR.ACCESSERROR_NOERROR;
 }
Example #46
0
        /***************************************************************************************************
        *   Determine whether there is an explicit or implicit reference conversion (or identity conversion)
        *   from typeSrc to typeDst. This is when:
        *
        *  13.2.3 Explicit reference conversions
        *
        *  The explicit reference conversions are:
        *   From object to any reference-type.
        *   From any class-type S to any class-type T, provided S is a base class of T.
        *   From any class-type S to any interface-type T, provided S is not sealed and provided S does not implement T.
        *   From any interface-type S to any class-type T, provided T is not sealed or provided T implements S.
        *   From any interface-type S to any interface-type T, provided S is not derived from T.
        *   From an array-type S with an element type SE to an array-type T with an element type TE, provided all of the following are true:
        *   o   S and T differ only in element type. (In other words, S and T have the same number of dimensions.)
        *   o   An explicit reference conversion exists from SE to TE.
        *   From System.Array and the interfaces it implements, to any array-type.
        *   From System.Delegate and the interfaces it implements, to any delegate-type.
        *   From a one-dimensional array-type S[] to System.Collections.Generic.IList<T>, System.Collections.Generic.IReadOnlyList<T> and their base interfaces, provided there is an explicit reference conversion from S to T.
        *   From a generic delegate type S to generic delegate type  T, provided all of the follow are true:
        *   o Both types are constructed generic types of the same generic delegate type, D<X1,... Xk>.That is,
        *     S is D<S1,... Sk> and T is D<T1,... Tk>.
        *   o S is not compatible with or identical to T.
        *   o If type parameter Xi is declared to be invariant then Si must be identical to Ti.
        *   o If type parameter Xi is declared to be covariant ("out") then Si must be convertible
        *     to Ti via an identify conversion,  implicit reference conversion, or explicit reference conversion.
        *   o If type parameter Xi is declared to be contravariant ("in") then either Si must be identical to Ti,
        *      or Si and Ti must both be reference types.
        *   From System.Collections.Generic.IList<T>, System.Collections.Generic.IReadOnlyList<T> and their base interfaces to a one-dimensional array-type S[], provided there is an implicit or explicit reference conversion from S[] to System.Collections.Generic.IList<T> or System.Collections.Generic.IReadOnlyList<T>. This is precisely when either S and T are the same type or there is an implicit or explicit reference conversion from S to T.
        *
        *  For a type-parameter T that is known to be a reference type (§25.7), the following explicit reference conversions exist:
        *   From the effective base class C of T to T and from any base class of C to T.
        *   From any interface-type to T.
        *   From T to any interface-type I provided there isn’t already an implicit reference conversion from T to I.
        *   From a type-parameter U to T provided that T depends on U (§25.7). [Note: Since T is known to be a reference type, within the scope of T, the run-time type of U will always be a reference type, even if U is not known to be a reference type at compile-time. end note]
        *
        * Both src and dst are reference types and there is a builtin explicit conversion from
        *     src to dst.
        * Or src is a reference type and dst is a base type of src (in which case the conversion is
        *     implicit as well).
        * Or dst is a reference type and src is a base type of dst.
        *
        *   The latter two cases can happen with type variables even though the other type variable is not
        *   a reference type.
        ***************************************************************************************************/
        public static bool FExpRefConv(SymbolLoader loader, CType typeSrc, CType typeDst)
        {
            Debug.Assert(typeSrc != null);
            Debug.Assert(typeDst != null);
            if (typeSrc.IsRefType() && typeDst.IsRefType())
            {
                // is there an implicit reference conversion in either direction?
                // this handles the bulk of the cases ...
                if (loader.HasIdentityOrImplicitReferenceConversion(typeSrc, typeDst) ||
                    loader.HasIdentityOrImplicitReferenceConversion(typeDst, typeSrc))
                {
                    return(true);
                }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                    CType typeArr = arrayDest.GetElementType();
                    CType typeLst = aggtypeSrc.GetTypeArgsAll()[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);
        }
Example #47
0
 public void Set(Symbol sym, AggregateType ats)
 {
     if (sym == null)
         ats = null;
     Debug.Assert(ats == null || sym.parent == ats.getAggregate());
     _sym = sym;
     _ats = ats;
 }
Example #48
0
        /******************************************************************************
        *   Search just the given type (not any bases). Returns true iff it finds
        *   something (which will have been recorded by RecordType).
        *
        *   pfHideByName is set to true iff something was found that hides all
        *   members of base types (eg, a hidebyname method).
        ******************************************************************************/
        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 = !GetSemanticChecker().CheckTypeAccess(typeCur, _symWhere);

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

            // Loop through symbols.
            Symbol symCur = null;

            for (symCur = GetSymbolLoader().LookupAggMember(_name, typeCur.getAggregate(), symbmask_t.MASK_ALL);
                 symCur != null;
                 symCur = GetSymbolLoader().LookupNextSym(symCur, typeCur.getAggregate(), symbmask_t.MASK_ALL))
            {
                // Check for arity.
                switch (symCur.getKind())
                {
                case SYMKIND.SK_MethodSymbol:
                    // 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.
                    if (_arity > 0 && ((MethodSymbol)symCur).typeVars.Count != _arity)
                    {
                        if (!_swtBadArity)
                        {
                            _swtBadArity.Set(symCur, typeCur);
                        }
                        continue;
                    }
                    break;

                case SYMKIND.SK_AggregateSymbol:
                    // For types, always filter on arity.
                    if (((AggregateSymbol)symCur).GetTypeVars().Count != _arity)
                    {
                        if (!_swtBadArity)
                        {
                            _swtBadArity.Set(symCur, typeCur);
                        }
                        continue;
                    }
                    break;

                case SYMKIND.SK_TypeParameterSymbol:
                    if ((_flags & MemLookFlags.TypeVarsAllowed) == 0)
                    {
                        continue;
                    }
                    if (_arity > 0)
                    {
                        if (!_swtBadArity)
                        {
                            _swtBadArity.Set(symCur, typeCur);
                        }
                        continue;
                    }
                    break;

                default:
                    // All others are only considered when arity is zero.
                    if (_arity > 0)
                    {
                        if (!_swtBadArity)
                        {
                            _swtBadArity.Set(symCur, typeCur);
                        }
                        continue;
                    }
                    break;
                }

                // Check for user callability.
                if (symCur.IsOverride() && !symCur.IsHideByName())
                {
                    if (!_swtOverride)
                    {
                        _swtOverride.Set(symCur, typeCur);
                    }
                    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.
                    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 || !GetSemanticChecker().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;
                        }
                        _swtAmbigWarn = _swtFirst;
                        // 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.fDiffHidden)
                        {
                            // Give method groups priority.
                            if (!(_swtFirst.Sym is MethodSymbol))
                            {
                                goto LAmbig;
                            }
                            if (!_swtAmbigWarn)
                            {
                                _swtAmbigWarn.Set(symCur, typeCur);
                            }
                        }
                        // 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);
        }
Example #49
0
 public MethWithType(MethodSymbol meth, AggregateType ats)
 {
     Set(meth, ats);
 }
Example #50
0
        /******************************************************************************
        *   Returns true if searching should continue to object.
        ******************************************************************************/
        private bool LookupInInterfaces(AggregateType typeStart, TypeArray types)
        {
            Debug.Assert(!_swtFirst || _fMulti);
            Debug.Assert(typeStart == null || typeStart.isInterfaceType());
            Debug.Assert(typeStart != null || types.Count != 0);

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

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

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

            if (typeCur == null)
            {
                typeCur = (AggregateType)types[itypeNext++];
            }
            Debug.Assert(typeCur != null);

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

                bool fHideByName = false;

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

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

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

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

                // Substitution has already been done.
                typeCur = types[itypeNext++] as AggregateType;
            }
        }
Example #51
0
 public EventWithType(EventSymbol @event, AggregateType ats)
 {
     Set(@event, ats);
 }
Example #52
0
        private bool IsDelegateType(CType pSrcType, AggregateType pAggType)
        {
            CType pInstantiatedType = GetSymbolLoader().GetTypeManager().SubstType(pSrcType, pAggType, pAggType.GetTypeArgsAll());

            return(pInstantiatedType.isDelegateType());
        }
Example #53
0
 public MethPropWithInst(MethodOrPropertySymbol mps, AggregateType ats)
     : this(mps, ats, null)
 {
 }
Example #54
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 || typeSrc is TypeParameterType);
            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 is TypeParameterType typeParamSrc)
            {
                Debug.Assert((_flags & (MemLookFlags.Ctor | MemLookFlags.NewObj | MemLookFlags.Operator | MemLookFlags.BaseCall | MemLookFlags.TypeVarsAllowed)) == 0);
                _flags  &= ~MemLookFlags.TypeVarsAllowed;
                ifaces   = typeParamSrc.GetInterfaceBounds();
                typeCls1 = typeParamSrc.GetEffectiveBaseClass();
                if (ifaces.Count > 0 && typeCls1.isPredefType(PredefinedType.PT_OBJECT))
                {
                    typeCls1 = null;
                }
            }
            else if (!typeSrc.isInterfaceType())
            {
                typeCls1 = (AggregateType)typeSrc;

                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 = (AggregateType)typeSrc;
                ifaces    = typeIface.GetIfacesAll();
            }

            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);
                }
            }

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

            return(!FError());
        }
Example #55
0
 public void Set(MethodOrPropertySymbol mps, AggregateType ats, TypeArray typeArgs)
 {
     if (mps == null)
     {
         ats = null;
         typeArgs = null;
     }
     Debug.Assert(ats == null || mps != null && mps.getClass() == ats.getAggregate());
     base.Set(mps, ats);
     this.TypeArgs = typeArgs;
 }
Example #56
0
 public void SetBaseClass(AggregateType baseClass)
 {
     _pBaseClass = baseClass;
 }
Example #57
0
 public MethWithInst(MethodSymbol meth, AggregateType ats, TypeArray typeArgs)
 {
     Set(meth, ats, typeArgs);
 }
Example #58
0
 public void SetUnderlyingType(AggregateType underlyingType)
 {
     _pUnderlyingType = underlyingType;
 }
Example #59
0
 public virtual void Clear()
 {
     _sym = null;
     _ats = null;
 }
            private AggCastResult bindExplicitConversionBetweenSimpleTypes(AggregateType aggTypeDest)
            {
                // 13.2.1
                //
                // Because the explicit conversions include all implicit and explicit numeric conversions,
                // it is always possible to convert from any numeric-type to any other numeric-type using
                // a cast expression (14.6.6).

                Debug.Assert(_typeSrc != null);
                Debug.Assert(aggTypeDest != null);

                if (!_typeSrc.IsSimpleType || !aggTypeDest.IsSimpleType)
                {
                    return(AggCastResult.Failure);
                }

                AggregateSymbol aggDest = aggTypeDest.OwningAggregate;

                Debug.Assert(_typeSrc.IsPredefined && aggDest.IsPredefined());

                PredefinedType ptSrc  = _typeSrc.PredefinedType;
                PredefinedType ptDest = aggDest.GetPredefType();

                Debug.Assert((int)ptSrc < NUM_SIMPLE_TYPES && (int)ptDest < NUM_SIMPLE_TYPES);

                ConvKind convertKind = GetConvKind(ptSrc, ptDest);

                // Identity and implicit conversions should already have been handled.
                Debug.Assert(convertKind != ConvKind.Implicit);
                Debug.Assert(convertKind != ConvKind.Identity);

                if (convertKind != ConvKind.Explicit)
                {
                    return(AggCastResult.Failure);
                }

                if (_exprSrc.GetConst() != null)
                {
                    // Fold the constant cast if possible.
                    ConstCastResult result = _binder.bindConstantCast(_exprSrc, _typeDest, _needsExprDest, out _exprDest, true);
                    if (result == ConstCastResult.Success)
                    {
                        return(AggCastResult.Success);  // else, don't fold and use a regular cast, below.
                    }
                    if (result == ConstCastResult.CheckFailure && 0 == (_flags & CONVERTTYPE.CHECKOVERFLOW))
                    {
                        return(AggCastResult.Abort);
                    }
                }

                bool bConversionOk = true;

                if (_needsExprDest)
                {
                    // Explicit conversions involving decimals are bound as user-defined conversions.
                    if (isUserDefinedConversion(ptSrc, ptDest))
                    {
                        // According the language, this is a standard conversion, but it is implemented
                        // through a user-defined conversion. Because it's a standard conversion, we don't
                        // test the CONVERTTYPE.NOUDC flag here.
                        bConversionOk = _binder.bindUserDefinedConversion(_exprSrc, _typeSrc, aggTypeDest, _needsExprDest, out _exprDest, false);
                    }
                    else
                    {
                        _binder.bindSimpleCast(_exprSrc, _typeDest, out _exprDest, (_flags & CONVERTTYPE.CHECKOVERFLOW) != 0 ? EXPRFLAG.EXF_CHECKOVERFLOW : 0);
                    }
                }
                return(bConversionOk ? AggCastResult.Success : AggCastResult.Failure);
            }