Пример #1
0
        /******************************************************************************
        *   Lookup in a class and its bases (until *ptypeEnd is hit).
        *
        *   ptypeEnd [in/out] - *ptypeEnd should be either null or object. If we find
        *       something here that would hide members of object, this sets *ptypeEnd
        *       to null.
        *
        *   Returns true when searching should continue to the interfaces.
        ******************************************************************************/
        private bool LookupInClass(AggregateType typeStart, ref AggregateType ptypeEnd)
        {
            Debug.Assert(!_swtFirst || _fMulti);
            Debug.Assert(typeStart != null && !typeStart.isInterfaceType() && (ptypeEnd == null || typeStart != ptypeEnd));

            AggregateType typeEnd = ptypeEnd;
            AggregateType typeCur;

            // Loop through types. Loop until we hit typeEnd (object or null).
            for (typeCur = typeStart; typeCur != typeEnd && typeCur != null; typeCur = typeCur.GetBaseClass())
            {
                Debug.Assert(!typeCur.isInterfaceType());

                bool fHideByName = false;

                SearchSingleType(typeCur, out fHideByName);
                _flags &= ~MemLookFlags.TypeVarsAllowed;

                if (_swtFirst && !_fMulti)
                {
                    // Everything below this type and in interfaces is hidden.
                    return(false);
                }

                if (fHideByName)
                {
                    // This hides everything below it and in object, but not in the interfaces!
                    ptypeEnd = null;

                    // Return true to indicate that it's ok to search additional types.
                    return(true);
                }

                if ((_flags & MemLookFlags.Ctor) != 0)
                {
                    // If we're looking for a constructor, don't check base classes or interfaces.
                    return(false);
                }
            }

            Debug.Assert(typeCur == typeEnd);
            return(true);
        }
Пример #2
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);
        }
Пример #3
0
        private bool IsBaseInterface(AggregateType atsDer, AggregateType pBase)
        {
            Debug.Assert(atsDer != null);
            Debug.Assert(pBase != null);
            if (pBase.isInterfaceType())
            {
                while (atsDer != null)
                {
                    TypeArray ifacesAll = atsDer.GetIfacesAll();
                    for (int i = 0; i < ifacesAll.Count; i++)
                    {
                        if (AreTypesEqualForConversion(ifacesAll[i], pBase))
                        {
                            return(true);
                        }
                    }

                    atsDer = atsDer.GetBaseClass();
                }
            }

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

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

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

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

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

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

                bool fHideByName = false;

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

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

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

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

                // Substitution has already been done.
                typeCur = types.Item(itypeNext++).AsAggregateType();
            }
        }
Пример #5
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;
            MethPropWithType mwpInsert;

            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 && symCur.AsMethodSymbol().typeVars.size != _arity)
                    {
                        if (!_swtBadArity)
                        {
                            _swtBadArity.Set(symCur, typeCur);
                        }
                        continue;
                    }
                    break;

                case SYMKIND.SK_AggregateSymbol:
                    // For types, always filter on arity.
                    if (symCur.AsAggregateSymbol().GetTypeVars().size != _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;
                }
                if ((_flags & MemLookFlags.UserCallable) != 0 && symCur.IsMethodOrPropertySymbol() && !symCur.AsMethodOrPropertySymbol().isUserCallable())
                {
                    bool bIsIndexedProperty = false;
                    // If its an indexed property method symbol, let it through.
                    if (symCur.IsMethodSymbol() &&
                        symCur.AsMethodSymbol().isPropertyAccessor() &&
                        ((symCur.name.Text.StartsWith("set_", StringComparison.Ordinal) && symCur.AsMethodSymbol().Params.size > 1) ||
                         (symCur.name.Text.StartsWith("get_", StringComparison.Ordinal) && symCur.AsMethodSymbol().Params.size > 0)))
                    {
                        bIsIndexedProperty = true;
                    }

                    if (!bIsIndexedProperty)
                    {
                        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;
                }

                // Make sure that whether we're seeing a ctor, operator, or indexer is consistent with the flags.
                if (((_flags & MemLookFlags.Ctor) == 0) != (!symCur.IsMethodSymbol() || !symCur.AsMethodSymbol().IsConstructor()) ||
                    ((_flags & MemLookFlags.Operator) == 0) != (!symCur.IsMethodSymbol() || !symCur.AsMethodSymbol().isOperator) ||
                    ((_flags & MemLookFlags.Indexer) == 0) != (!symCur.IsPropertySymbol() || !symCur.AsPropertySymbol().isIndexer()))
                {
                    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.IsMethodSymbol() && (_flags & MemLookFlags.Indexer) == 0 && GetSemanticChecker().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.IsFieldSymbol() && !IsDelegateType(symCur.AsFieldSymbol().GetType(), typeCur) && !IsDynamicMember(symCur)) ||
                        (symCur.IsPropertySymbol() && !IsDelegateType(symCur.AsPropertySymbol().RetType, typeCur) && !IsDynamicMember(symCur)))
                    {
                        if (!_swtBad)
                        {
                            _swtBad.Set(symCur, typeCur);
                        }
                        continue;
                    }
                }

                if (symCur.IsMethodOrPropertySymbol())
                {
                    mwpInsert = new MethPropWithType(symCur.AsMethodOrPropertySymbol(), 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.IsFieldSymbol() && symCur.IsEventSymbol()
#if !CSEE                       // 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
#endif
                                )
                            {
                                // m_swtFirst is just the field behind the event symCur so ignore symCur.
                                continue;
                            }
                            else if (_swtFirst.Sym.IsFieldSymbol() && symCur.IsEventSymbol())
                            {
                                // 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 (/* !GetSymbolLoader().options.fLookupHack ||*/ !symCur.IsMethodSymbol())
                        {
                            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 (/*!GetSymbolLoader().options.fLookupHack ||*/ !_swtFirst.Sym.IsMethodSymbol())
                            {
                                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 (symCur.IsMethodOrPropertySymbol() && symCur.AsMethodOrPropertySymbol().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);
        }
Пример #6
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;
        }
Пример #7
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;
        }
Пример #8
0
        private bool TryVarianceAdjustmentToGetAccessibleType(CSemanticChecker semanticChecker, BindingContext bindingContext, AggregateType typeSrc, out CType typeDst)
        {
            Debug.Assert(typeSrc != null);
            Debug.Assert(typeSrc.isInterfaceType() || typeSrc.isDelegateType());

            typeDst = null;

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

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

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

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

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

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

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

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

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

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

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

            typeDst = null;

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

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

            TypeArray typeArgs = typeSrc.GetTypeArgsThis();
            TypeArray typeParams = aggOpenType.GetTypeArgsThis();
            CType[] newTypeArgsTemp = new CType[typeArgs.size];

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

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

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

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

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

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

            typeDst = intermediateType;
            Debug.Assert(semanticChecker.CheckTypeAccess(typeDst, bindingContext.ContextForMemberLookup()));
            return true;
        }
Пример #10
0
        ////////////////////////////////////////////////////////////////////////////////
        // The rules for variant interface and delegate conversions are the same:
        //
        // An interface/delegate type S is convertible to an interface/delegate type T
        // if and only if T is U<S1, ... Sn> and T is U<T1, ... Tn> such that for all
        // parameters of U:
        //
        // * if the ith parameter of U is invariant then Si is exactly equal to Ti.
        // * if the ith parameter of U is covariant then either Si is exactly equal
        //   to Ti, or there is an implicit reference conversion from Si to Ti.
        // * if the ith parameter of U is contravariant then either Si is exactly
        //   equal to Ti, or there is an implicit reference conversion from Ti to Si.

        private bool HasInterfaceConversion(AggregateType pSource, AggregateType pDest)
        {
            Debug.Assert(pSource != null && pSource.isInterfaceType());
            Debug.Assert(pDest != null && pDest.isInterfaceType());
            return(HasVariantConversion(pSource, pDest));
        }
Пример #11
0
        ////////////////////////////////////////////////////////////////////////////////
        // The rules for variant interface and delegate conversions are the same:
        //
        // An interface/delegate type S is convertible to an interface/delegate type T 
        // if and only if T is U<S1, ... Sn> and T is U<T1, ... Tn> such that for all
        // parameters of U:
        //
        // * if the ith parameter of U is invariant then Si is exactly equal to Ti.
        // * if the ith parameter of U is covariant then either Si is exactly equal
        //   to Ti, or there is an implicit reference conversion from Si to Ti.
        // * if the ith parameter of U is contravariant then either Si is exactly
        //   equal to Ti, or there is an implicit reference conversion from Ti to Si.

        private bool HasInterfaceConversion(AggregateType pSource, AggregateType pDest)
        {
            Debug.Assert(pSource != null && pSource.isInterfaceType());
            Debug.Assert(pDest != null && pDest.isInterfaceType());
            return HasVariantConversion(pSource, pDest);
        }
Пример #12
0
        /******************************************************************************
            Returns true if searching should continue to object.
        ******************************************************************************/
        private bool LookupInInterfaces(AggregateType typeStart, TypeArray types)
        {
            Debug.Assert(!_swtFirst || _fMulti);
            Debug.Assert(typeStart == null || typeStart.isInterfaceType());
            Debug.Assert(typeStart != null || types.size != 0);

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

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

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

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

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

                bool fHideByName = false;

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

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

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

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

                // Substitution has already been done.
                typeCur = types.Item(itypeNext++).AsAggregateType();
            }
        }
Пример #13
0
        /******************************************************************************
            Lookup in a class and its bases (until *ptypeEnd is hit).
            
            ptypeEnd [in/out] - *ptypeEnd should be either null or object. If we find
                something here that would hide members of object, this sets *ptypeEnd
                to null.
         
            Returns true when searching should continue to the interfaces.
        ******************************************************************************/
        private bool LookupInClass(AggregateType typeStart, ref AggregateType ptypeEnd)
        {
            Debug.Assert(!_swtFirst || _fMulti);
            Debug.Assert(typeStart != null && !typeStart.isInterfaceType() && (ptypeEnd == null || typeStart != ptypeEnd));

            AggregateType typeEnd = ptypeEnd;
            AggregateType typeCur;

            // Loop through types. Loop until we hit typeEnd (object or null).
            for (typeCur = typeStart; typeCur != typeEnd && typeCur != null; typeCur = typeCur.GetBaseClass())
            {
                Debug.Assert(!typeCur.isInterfaceType());

                bool fHideByName = false;

                SearchSingleType(typeCur, out fHideByName);
                _flags &= ~MemLookFlags.TypeVarsAllowed;

                if (_swtFirst && !_fMulti)
                {
                    // Everything below this type and in interfaces is hidden.
                    return false;
                }

                if (fHideByName)
                {
                    // This hides everything below it and in object, but not in the interfaces!
                    ptypeEnd = null;

                    // Return true to indicate that it's ok to search additional types.
                    return true;
                }

                if ((_flags & MemLookFlags.Ctor) != 0)
                {
                    // If we're looking for a constructor, don't check base classes or interfaces.
                    return false;
                }
            }

            Debug.Assert(typeCur == typeEnd);
            return true;
        }
Пример #14
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 && symCur.AsMethodSymbol().typeVars.size != _arity)
                        {
                            if (!_swtBadArity)
                                _swtBadArity.Set(symCur, typeCur);
                            continue;
                        }
                        break;

                    case SYMKIND.SK_AggregateSymbol:
                        // For types, always filter on arity.
                        if (symCur.AsAggregateSymbol().GetTypeVars().size != _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;
                }
                if ((_flags & MemLookFlags.UserCallable) != 0 && symCur.IsMethodOrPropertySymbol() && !symCur.AsMethodOrPropertySymbol().isUserCallable())
                {
                    bool bIsIndexedProperty = false;
                    // If its an indexed property method symbol, let it through.
                    if (symCur.IsMethodSymbol() &&
                        symCur.AsMethodSymbol().isPropertyAccessor() &&
                        ((symCur.name.Text.StartsWith("set_", StringComparison.Ordinal) && symCur.AsMethodSymbol().Params.size > 1) ||
                        (symCur.name.Text.StartsWith("get_", StringComparison.Ordinal) && symCur.AsMethodSymbol().Params.size > 0)))
                    {
                        bIsIndexedProperty = true;
                    }

                    if (!bIsIndexedProperty)
                    {
                        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;
                }

                // Make sure that whether we're seeing a ctor, operator, or indexer is consistent with the flags.
                if (((_flags & MemLookFlags.Ctor) == 0) != (!symCur.IsMethodSymbol() || !symCur.AsMethodSymbol().IsConstructor()) ||
                    ((_flags & MemLookFlags.Operator) == 0) != (!symCur.IsMethodSymbol() || !symCur.AsMethodSymbol().isOperator) ||
                    ((_flags & MemLookFlags.Indexer) == 0) != (!symCur.IsPropertySymbol() || !symCur.AsPropertySymbol().isIndexer()))
                {
                    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.IsMethodSymbol() && (_flags & MemLookFlags.Indexer) == 0 && GetSemanticChecker().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.IsFieldSymbol() && !IsDelegateType(symCur.AsFieldSymbol().GetType(), typeCur) && !IsDynamicMember(symCur)) ||
                        (symCur.IsPropertySymbol() && !IsDelegateType(symCur.AsPropertySymbol().RetType, typeCur) && !IsDynamicMember(symCur)))
                    {
                        if (!_swtBad)
                        {
                            _swtBad.Set(symCur, typeCur);
                        }
                        continue;
                    }
                }

                if (symCur.IsMethodOrPropertySymbol())
                {
                    MethPropWithType mwpInsert = new MethPropWithType(symCur.AsMethodOrPropertySymbol(), 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.IsFieldSymbol() && symCur.IsEventSymbol()
#if !CSEE                       // 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
#endif
)
                            {
                                // m_swtFirst is just the field behind the event symCur so ignore symCur.
                                continue;
                            }
                            else if (_swtFirst.Sym.IsFieldSymbol() && symCur.IsEventSymbol())
                            {
                                // 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 ( /* !GetSymbolLoader().options.fLookupHack ||*/ !symCur.IsMethodSymbol())
                            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 ( /*!GetSymbolLoader().options.fLookupHack ||*/ !_swtFirst.Sym.IsMethodSymbol())
                                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 (symCur.IsMethodOrPropertySymbol() && symCur.AsMethodOrPropertySymbol().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;
        }