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); }
// Is the method/property callable. Not if it's an override or not user-callable. public static bool IsMethPropCallable(MethodOrPropertySymbol sym, bool requireUC) { // The hide-by-pName option for binding other languages takes precedence over general // rules of not binding to overrides. return (!sym.isOverride || sym.isHideByName) && (!requireUC || sym.isUserCallable()); }