コード例 #1
0
        private static RuntimeBinderException ReportBogus(SymWithType swt)
        {
            Debug.Assert(CSemanticChecker.CheckBogus(swt.Sym));
            MethodSymbol meth1 = swt.Prop().GetterMethod;
            MethodSymbol meth2 = swt.Prop().SetterMethod;

            Debug.Assert((meth1 ?? meth2) != null);
            return(meth1 == null | meth2 == null
                ? ErrorHandling.Error(
                       ErrorCode.ERR_BindToBogusProp1, swt.Sym.name, new SymWithType(meth1 ?? meth2, swt.GetType()),
                       new ErrArgRefOnly(swt.Sym))
                : ErrorHandling.Error(
                       ErrorCode.ERR_BindToBogusProp2, swt.Sym.name, new SymWithType(meth1, swt.GetType()),
                       new SymWithType(meth2, swt.GetType()), new ErrArgRefOnly(swt.Sym)));
        }
コード例 #2
0
        private void ReportBogus(SymWithType swt)
        {
            Debug.Assert(CSemanticChecker.CheckBogus(swt.Sym));
            MethodSymbol meth1 = swt.Prop().GetterMethod;
            MethodSymbol meth2 = swt.Prop().SetterMethod;

            Debug.Assert((meth1 ?? meth2) != null);
            if (meth1 == null | meth2 == null)
            {
                GetErrorContext().Error(
                    ErrorCode.ERR_BindToBogusProp1, swt.Sym.name, new SymWithType(meth1 ?? meth2, swt.GetType()),
                    new ErrArgRefOnly(swt.Sym));
            }
            else
            {
                GetErrorContext().Error(
                    ErrorCode.ERR_BindToBogusProp2, swt.Sym.name, new SymWithType(meth1, swt.GetType()),
                    new SymWithType(meth2, swt.GetType()), new ErrArgRefOnly(swt.Sym));
            }
        }
コード例 #3
0
        private bool SearchSingleType(AggregateType typeCur, out bool pfHideByName)
        {
            bool fFoundSome = false;

            pfHideByName = false;

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

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

            // Loop through symbols.
            Symbol symCur;

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

                    continue;
                }

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

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

                        continue;
                    }
                }

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

                PropertySymbol prop = symCur as PropertySymbol;

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

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

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

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

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

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

                RecordType(typeCur, symCur);

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

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

            return(fFoundSome);

LAmbig:
            // Ambiguous!
            if (!_swtAmbig)
            {
                _swtAmbig.Set(symCur, typeCur);
            }
            pfHideByName = true;
            return(true);
        }
コード例 #4
0
ファイル: MethodIterator.cs プロジェクト: stantoxt/corefx
            public bool CanUseCurrentSymbol()
            {
                _bCurrentSymIsInaccessible = false;
                _bCurrentSymIsBogus        = false;

                // Make sure that whether we're seeing a ctor is consistent with the flag.
                // The only properties we handle are indexers.
                if (_mask == symbmask_t.MASK_MethodSymbol && (
                        0 == (_flags & EXPRFLAG.EXF_CTOR) != !((MethodSymbol)_pCurrentSym).IsConstructor() ||
                        0 == (_flags & EXPRFLAG.EXF_OPERATOR) != !((MethodSymbol)_pCurrentSym).isOperator) ||
                    _mask == symbmask_t.MASK_PropertySymbol && !(_pCurrentSym is IndexerSymbol))
                {
                    // Get the next symbol.
                    return(false);
                }

                // If our arity is non-0, we must match arity with this symbol.
                if (_nArity > 0)
                {
                    if (_mask == symbmask_t.MASK_MethodSymbol && ((MethodSymbol)_pCurrentSym).typeVars.Count != _nArity)
                    {
                        return(false);
                    }
                }

                // If this guy's not callable, no good.
                if (!ExpressionBinder.IsMethPropCallable(_pCurrentSym, (_flags & EXPRFLAG.EXF_USERCALLABLE) != 0))
                {
                    return(false);
                }

                // Check access.
                if (!GetSemanticChecker().CheckAccess(_pCurrentSym, _pCurrentType, _pContext, _pQualifyingType))
                {
                    // Sym is not accessible. However, if we're allowing inaccessible, then let it through and mark it.
                    if (_bAllowBogusAndInaccessible)
                    {
                        _bCurrentSymIsInaccessible = true;
                    }
                    else
                    {
                        return(false);
                    }
                }

                // Check bogus.
                if (CSemanticChecker.CheckBogus(_pCurrentSym))
                {
                    // Sym is bogus, but if we're allow it, then let it through and mark it.
                    if (_bAllowBogusAndInaccessible)
                    {
                        _bCurrentSymIsBogus = true;
                    }
                    else
                    {
                        return(false);
                    }
                }

                // if we are done checking all the instance types ensure that currentsym is an
                // extension method and not a simple static method
                if (!_bIsCheckingInstanceMethods && !((MethodSymbol)_pCurrentSym).IsExtension())
                {
                    return(false);
                }

                return(true);
            }
コード例 #5
0
        private static bool CheckSingleConstraint(CSemanticChecker checker, ErrorHandling errHandling, Symbol symErr, TypeParameterType var, CType arg, TypeArray typeArgsCls, TypeArray typeArgsMeth, CheckConstraintsFlags flags)
        {
            bool fReportErrors = 0 == (flags & CheckConstraintsFlags.NoErrors);

            if (arg is OpenTypePlaceholderType)
            {
                return(true);
            }

            if (arg is ErrorType)
            {
                // Error should have been reported previously.
                return(false);
            }

            if (checker.CheckBogus(arg))
            {
                if (fReportErrors)
                {
                    errHandling.ErrorRef(ErrorCode.ERR_BogusType, arg);
                }

                return(false);
            }

            if (arg is PointerType)
            {
                if (fReportErrors)
                {
                    errHandling.Error(ErrorCode.ERR_BadTypeArgument, arg);
                }

                return(false);
            }

            if (arg.isStaticClass())
            {
                if (fReportErrors)
                {
                    checker.ReportStaticClassError(null, arg, ErrorCode.ERR_GenericArgIsStaticClass);
                }

                return(false);
            }

            bool fError = false;

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

                fError = true;
            }

            TypeArray bnds     = checker.GetSymbolLoader().GetTypeManager().SubstTypeArray(var.GetBounds(), typeArgsCls, typeArgsMeth);
            int       itypeMin = 0;

            if (var.HasValConstraint())
            {
                // If we have a type variable that is constrained to a value type, then we
                // want to check if its a nullable type, so that we can report the
                // constraint error below. In order to do this however, we need to check
                // that either the type arg is not a value type, or it is a nullable type.
                //
                // To check whether or not its a nullable type, we need to get the resolved
                // bound from the type argument and check against that.

                bool bIsValueType = arg.IsValType();
                bool bIsNullable  = arg is NullableType;
                if (bIsValueType && arg is TypeParameterType typeArg)
                {
                    TypeArray pArgBnds = typeArg.GetBounds();
                    if (pArgBnds.Count > 0)
                    {
                        bIsNullable = pArgBnds[0] is NullableType;
                    }
                }

                if (!bIsValueType || bIsNullable)
                {
                    if (fReportErrors)
                    {
                        errHandling.ErrorRef(ErrorCode.ERR_ValConstraintNotSatisfied, symErr, new ErrArgNoRef(var), arg);
                    }

                    fError = true;
                }

                // Since FValCon() is set it is redundant to check System.ValueType as well.
                if (bnds.Count != 0 && bnds[0].isPredefType(PredefinedType.PT_VALUE))
                {
                    itypeMin = 1;
                }
            }

            for (int j = itypeMin; j < bnds.Count; j++)
            {
                CType typeBnd = bnds[j];
                if (!SatisfiesBound(checker, arg, typeBnd))
                {
                    if (fReportErrors)
                    {
                        // The bound isn't satisfied because of a constraint type. Explain to the user why not.
                        // There are 4 main cases, based on the type of the supplied type argument:
                        //  - reference type, or type parameter known to be a reference type
                        //  - nullable type, from which there is a boxing conversion to the constraint type(see below for details)
                        //  - type variable
                        //  - value type
                        // These cases are broken out because: a) The sets of conversions which can be used
                        // for constraint satisfaction is different based on the type argument supplied,
                        // and b) Nullable is one funky type, and user's can use all the help they can get
                        // when using it.
                        ErrorCode error;
                        if (arg.IsRefType())
                        {
                            // A reference type can only satisfy bounds to types
                            // to which they have an implicit reference conversion
                            error = ErrorCode.ERR_GenericConstraintNotSatisfiedRefType;
                        }
                        else if (arg is NullableType nubArg && checker.GetSymbolLoader().HasBaseConversion(nubArg.GetUnderlyingType(), typeBnd))    // This is inlining FBoxingConv
                        {
                            // nullable types do not satisfy bounds to every type that they are boxable to
                            // They only satisfy bounds of object and ValueType
                            if (typeBnd.isPredefType(PredefinedType.PT_ENUM) || nubArg.GetUnderlyingType() == typeBnd)
                            {
                                // Nullable types don't satisfy bounds of EnumType, or the underlying type of the enum
                                // even though the conversion from Nullable to these types is a boxing conversion
                                // This is a rare case, because these bounds can never be directly stated ...
                                // These bounds can only occur when one type paramter is constrained to a second type parameter
                                // and the second type parameter is instantiated with Enum or the underlying type of the first type
                                // parameter
                                error = ErrorCode.ERR_GenericConstraintNotSatisfiedNullableEnum;
                            }
                            else
                            {
                                // Nullable types don't satisfy the bounds of any interface type
                                // even when there is a boxing conversion from the Nullable type to
                                // the interface type. This will be a relatively common scenario
                                // so we cal it out separately from the previous case.
                                Debug.Assert(typeBnd.isInterfaceType());
                                error = ErrorCode.ERR_GenericConstraintNotSatisfiedNullableInterface;
                            }
                        }
                        else if (arg is TypeParameterType)
                        {
                            // Type variables can satisfy bounds through boxing and type variable conversions
                            Debug.Assert(!arg.IsRefType());
                            error = ErrorCode.ERR_GenericConstraintNotSatisfiedTyVar;
                        }
                        else
                        {
                            // Value types can only satisfy bounds through boxing conversions.
                            // Note that the exceptional case of Nullable types and boxing is handled above.
                            error = ErrorCode.ERR_GenericConstraintNotSatisfiedValType;
                        }
                        errHandling.Error(error, new ErrArgRef(symErr), new ErrArg(typeBnd, ErrArgFlags.Unique), var, new ErrArgRef(arg, ErrArgFlags.Unique));
                    }
                    fError = true;
                }
            }
コード例 #6
0
ファイル: TypeBind.cs プロジェクト: er0dr1guez/corefx
        private static bool CheckSingleConstraint(CSemanticChecker checker, ErrorHandling errHandling, Symbol symErr, TypeParameterType var, CType arg, TypeArray typeArgsCls, TypeArray typeArgsMeth, CheckConstraintsFlags flags)
        {
            bool fReportErrors = 0 == (flags & CheckConstraintsFlags.NoErrors);

            if (arg.IsOpenTypePlaceholderType())
            {
                return true;
            }

            if (arg.IsErrorType())
            {
                // Error should have been reported previously.
                return false;
            }

            if (checker.CheckBogus(arg))
            {
                if (fReportErrors)
                {
                    errHandling.ErrorRef(ErrorCode.ERR_BogusType, arg);
                }

                return false;
            }

            if (arg.IsPointerType() || arg.isSpecialByRefType())
            {
                if (fReportErrors)
                {
                    errHandling.Error(ErrorCode.ERR_BadTypeArgument, arg);
                }

                return false;
            }

            if (arg.isStaticClass())
            {
                if (fReportErrors)
                {
                    checker.ReportStaticClassError(null, arg, ErrorCode.ERR_GenericArgIsStaticClass);
                }

                return false;
            }

            bool fError = false;
            if (var.HasRefConstraint() && !arg.IsRefType())
            {
                if (fReportErrors)
                {
                    errHandling.ErrorRef(ErrorCode.ERR_RefConstraintNotSatisfied, symErr, new ErrArgNoRef(var), arg);
                }

                fError = true;
            }

            TypeArray bnds = checker.GetSymbolLoader().GetTypeManager().SubstTypeArray(var.GetBounds(), typeArgsCls, typeArgsMeth);
            int itypeMin = 0;

            if (var.HasValConstraint())
            {
                // If we have a type variable that is constrained to a value type, then we
                // want to check if its a nullable type, so that we can report the 
                // constraint error below. In order to do this however, we need to check 
                // that either the type arg is not a value type, or it is a nullable type.
                //
                // To check whether or not its a nullable type, we need to get the resolved
                // bound from the type argument and check against that.

                bool bIsValueType = arg.IsValType();
                bool bIsNullable = arg.IsNullableType();
                if (bIsValueType && arg.IsTypeParameterType())
                {
                    TypeArray pArgBnds = arg.AsTypeParameterType().GetBounds();
                    if (pArgBnds.size > 0)
                    {
                        bIsNullable = pArgBnds.Item(0).IsNullableType();
                    }
                }

                if (!bIsValueType || bIsNullable)
                {
                    if (fReportErrors)
                    {
                        errHandling.ErrorRef(ErrorCode.ERR_ValConstraintNotSatisfied, symErr, new ErrArgNoRef(var), arg);
                    }

                    fError = true;
                }

                // Since FValCon() is set it is redundant to check System.ValueType as well.
                if (bnds.size != 0 && bnds.Item(0).isPredefType(PredefinedType.PT_VALUE))
                {
                    itypeMin = 1;
                }
            }

            for (int j = itypeMin; j < bnds.size; j++)
            {
                CType typeBnd = bnds.Item(j);
                if (!SatisfiesBound(checker, arg, typeBnd))
                {
                    if (fReportErrors)
                    {
                        // The bound isn't satisfied because of a constaint type. Explain to the user why not.
                        // There are 4 main cases, based on the type of the supplied type argument:
                        //  - reference type, or type parameter known to be a reference type
                        //  - nullable type, from which there is a boxing conversion to the constraint type(see below for details)
                        //  - type varaiable
                        //  - value type
                        // These cases are broken out because: a) The sets of conversions which can be used 
                        // for constraint satisfaction is different based on the type argument supplied, 
                        // and b) Nullable is one funky type, and user's can use all the help they can get
                        // when using it.
                        ErrorCode error;
                        if (arg.IsRefType())
                        {
                            // A reference type can only satisfy bounds to types 
                            // to which they have an implicit reference conversion
                            error = ErrorCode.ERR_GenericConstraintNotSatisfiedRefType;
                        }
                        else if (arg.IsNullableType() && checker.GetSymbolLoader().HasBaseConversion(arg.AsNullableType().GetUnderlyingType(), typeBnd))    // This is inlining FBoxingConv
                        {
                            // nullable types do not satisfy bounds to every type that they are boxable to
                            // They only satisfy bounds of object and ValueType
                            if (typeBnd.isPredefType(PredefinedType.PT_ENUM) || arg.AsNullableType().GetUnderlyingType() == typeBnd)
                            {
                                // Nullable types don't satisfy bounds of EnumType, or the underlying type of the enum
                                // even though the conversion from Nullable to these types is a boxing conversion
                                // This is a rare case, because these bounds can never be directly stated ...
                                // These bounds can only occur when one type paramter is constrained to a second type parameter
                                // and the second type parameter is instantiated with Enum or the underlying type of the first type
                                // parameter
                                error = ErrorCode.ERR_GenericConstraintNotSatisfiedNullableEnum;
                            }
                            else
                            {
                                // Nullable types don't satisfy the bounds of any interface type
                                // even when there is a boxing conversion from the Nullable type to 
                                // the interface type. This will be a relatively common scenario
                                // so we cal it out separately from the previous case.
                                Debug.Assert(typeBnd.isInterfaceType());
                                error = ErrorCode.ERR_GenericConstraintNotSatisfiedNullableInterface;
                            }
                        }
                        else if (arg.IsTypeParameterType())
                        {
                            // Type variables can satisfy bounds through boxing and type variable conversions
                            Debug.Assert(!arg.IsRefType());
                            error = ErrorCode.ERR_GenericConstraintNotSatisfiedTyVar;
                        }
                        else
                        {
                            // Value types can only satisfy bounds through boxing conversions.
                            // Note that the exceptional case of Nullable types and boxing is handled above.
                            error = ErrorCode.ERR_GenericConstraintNotSatisfiedValType;
                        }
                        errHandling.Error(error, new ErrArgRef(symErr), new ErrArg(typeBnd, ErrArgFlags.Unique), var, new ErrArgRef(arg, ErrArgFlags.Unique));
                    }
                    fError = true;
                }
            }

            // Check the newable constraint.
            if (!var.HasNewConstraint() || arg.IsValType())
            {
                return !fError;
            }

            if (arg.isClassType())
            {
                AggregateSymbol agg = arg.AsAggregateType().getAggregate();

                // Due to late binding nature of IDE created symbols, the AggregateSymbol might not
                // have all the information necessary yet, if it is not fully bound.
                // by calling LookupAggMember, it will ensure that we will update all the
                // information necessary at least for the given method.
                checker.GetSymbolLoader().LookupAggMember(checker.GetNameManager().GetPredefName(PredefinedName.PN_CTOR), agg, symbmask_t.MASK_ALL);

                if (agg.HasPubNoArgCtor() && !agg.IsAbstract())
                {
                    return !fError;
                }
            }
            else if (arg.IsTypeParameterType() && arg.AsTypeParameterType().HasNewConstraint())
            {
                return !fError;
            }

            if (fReportErrors)
            {
                errHandling.ErrorRef(ErrorCode.ERR_NewConstraintNotSatisfied, symErr, new ErrArgNoRef(var), arg);
            }

            return false;
        }