1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System; 6 using System.Collections.Generic; 7 using System.Diagnostics; 8 using System.Linq; 9 using Microsoft.CSharp.RuntimeBinder.Errors; 10 using Microsoft.CSharp.RuntimeBinder.Syntax; 11 12 namespace Microsoft.CSharp.RuntimeBinder.Semantics 13 { 14 [Flags] 15 internal enum MemLookFlags : uint 16 { 17 None = 0, 18 19 Ctor = EXPRFLAG.EXF_CTOR, 20 NewObj = EXPRFLAG.EXF_NEWOBJCALL, 21 Operator = EXPRFLAG.EXF_OPERATOR, 22 Indexer = EXPRFLAG.EXF_INDEXER, 23 UserCallable = EXPRFLAG.EXF_USERCALLABLE, 24 BaseCall = EXPRFLAG.EXF_BASECALL, 25 26 // All EXF flags are < 0x01000000 27 MustBeInvocable = 0x20000000, 28 29 All = Ctor | NewObj | Operator | Indexer | UserCallable | BaseCall | MustBeInvocable 30 } 31 32 ///////////////////////////////////////////////////////////////////////////////// 33 // MemberLookup class handles looking for a member within a type and its 34 // base types. This only handles AGGTYPESYMs and TYVARSYMs. 35 // 36 // Lookup must be called before any other methods. 37 38 internal sealed class MemberLookup 39 { 40 // The inputs to Lookup. 41 private CSemanticChecker _pSemanticChecker; 42 private SymbolLoader _pSymbolLoader; 43 private CType _typeSrc; 44 private Expr _obj; 45 private CType _typeQual; 46 private ParentSymbol _symWhere; 47 private Name _name; 48 private int _arity; 49 private MemLookFlags _flags; 50 51 // For maintaining the type array. We throw the first 8 or so here. 52 private readonly List<AggregateType> _rgtypeStart; 53 54 // Results of the lookup. 55 private List<AggregateType> _prgtype; 56 private int _csym; // Number of syms found. 57 private readonly SymWithType _swtFirst; // The first symbol found. 58 private readonly List<MethPropWithType> _methPropWithTypeList; // When we look up methods, we want to keep the list of all candidate methods given a particular name. 59 60 // These are for error reporting. 61 private readonly SymWithType _swtAmbig; // An ambiguous symbol. 62 private readonly SymWithType _swtInaccess; // An inaccessible symbol. 63 private readonly SymWithType _swtBad; // If we're looking for a constructor or indexer, this matched on name, but isn't the right thing. 64 private readonly SymWithType _swtBogus; // A bogus member - such as an indexed property. 65 private readonly SymWithType _swtBadArity; // An symbol with the wrong arity. 66 private bool _fMulti; // Whether symFirst is of a kind for which we collect multiples (methods and indexers). 67 68 /*************************************************************************************************** 69 Another match was found. Increment the count of syms and add the type to our list if it's not 70 already there. 71 ***************************************************************************************************/ RecordType(AggregateType type, Symbol sym)72 private void RecordType(AggregateType type, Symbol sym) 73 { 74 Debug.Assert(type != null && sym != null); 75 76 if (!_prgtype.Contains(type)) 77 { 78 _prgtype.Add(type); 79 } 80 81 // Now record the sym.... 82 83 _csym++; 84 85 // If it is first, record it. 86 if (_swtFirst == null) 87 { 88 _swtFirst.Set(sym, type); 89 Debug.Assert(_csym == 1); 90 Debug.Assert(_prgtype[0] == type); 91 _fMulti = sym is MethodSymbol || sym is IndexerSymbol; 92 } 93 } 94 95 /****************************************************************************** 96 Search just the given type (not any bases). Returns true iff it finds 97 something (which will have been recorded by RecordType). 98 99 pfHideByName is set to true iff something was found that hides all 100 members of base types (eg, a hidebyname method). 101 ******************************************************************************/ SearchSingleType(AggregateType typeCur, out bool pfHideByName)102 private bool SearchSingleType(AggregateType typeCur, out bool pfHideByName) 103 { 104 bool fFoundSome = false; 105 106 pfHideByName = false; 107 108 // Make sure this type is accessible. It may not be due to private inheritance 109 // or friend assemblies. 110 bool fInaccess = !GetSemanticChecker().CheckTypeAccess(typeCur, _symWhere); 111 if (fInaccess && (_csym != 0 || _swtInaccess != null)) 112 return false; 113 114 // Loop through symbols. 115 Symbol symCur; 116 for (symCur = GetSymbolLoader().LookupAggMember(_name, typeCur.getAggregate(), symbmask_t.MASK_ALL); 117 symCur != null; 118 symCur = SymbolLoader.LookupNextSym(symCur, typeCur.getAggregate(), symbmask_t.MASK_ALL)) 119 { 120 // Check for arity. 121 switch (symCur.getKind()) 122 { 123 case SYMKIND.SK_MethodSymbol: 124 // For non-zero arity, only methods of the correct arity are considered. 125 // For zero arity, don't filter out any methods since we do type argument 126 // inferencing. 127 if (_arity > 0 && ((MethodSymbol)symCur).typeVars.Count != _arity) 128 { 129 if (!_swtBadArity) 130 _swtBadArity.Set(symCur, typeCur); 131 continue; 132 } 133 break; 134 135 case SYMKIND.SK_AggregateSymbol: 136 // For types, always filter on arity. 137 if (((AggregateSymbol)symCur).GetTypeVars().Count != _arity) 138 { 139 if (!_swtBadArity) 140 _swtBadArity.Set(symCur, typeCur); 141 continue; 142 } 143 break; 144 145 default: 146 // All others are only considered when arity is zero. 147 if (_arity > 0) 148 { 149 if (!_swtBadArity) 150 _swtBadArity.Set(symCur, typeCur); 151 continue; 152 } 153 break; 154 } 155 156 // Check for user callability. 157 if (symCur.IsOverride() && !symCur.IsHideByName()) 158 { 159 continue; 160 } 161 162 MethodOrPropertySymbol methProp = symCur as MethodOrPropertySymbol; 163 MethodSymbol meth = symCur as MethodSymbol; 164 if (methProp != null && (_flags & MemLookFlags.UserCallable) != 0 && !methProp.isUserCallable()) 165 { 166 // If its an indexed property method symbol, let it through. 167 if (meth != null && 168 meth.isPropertyAccessor() && 169 ((symCur.name.Text.StartsWith("set_", StringComparison.Ordinal) && meth.Params.Count > 1) || 170 (symCur.name.Text.StartsWith("get_", StringComparison.Ordinal) && meth.Params.Count > 0))) 171 { 172 if (!_swtInaccess) 173 { 174 _swtInaccess.Set(symCur, typeCur); 175 } 176 continue; 177 } 178 } 179 180 if (fInaccess || !GetSemanticChecker().CheckAccess(symCur, typeCur, _symWhere, _typeQual)) 181 { 182 // Not accessible so get the next sym. 183 if (!_swtInaccess) 184 { 185 _swtInaccess.Set(symCur, typeCur); 186 } 187 if (fInaccess) 188 { 189 return false; 190 } 191 continue; 192 } 193 194 PropertySymbol prop = symCur as PropertySymbol; 195 196 // Make sure that whether we're seeing a ctor, operator, or indexer is consistent with the flags. 197 if (((_flags & MemLookFlags.Ctor) == 0) != (meth == null || !meth.IsConstructor()) || 198 ((_flags & MemLookFlags.Operator) == 0) != (meth == null || !meth.isOperator) || 199 ((_flags & MemLookFlags.Indexer) == 0) != !(prop is IndexerSymbol)) 200 { 201 if (!_swtBad) 202 { 203 _swtBad.Set(symCur, typeCur); 204 } 205 continue; 206 } 207 208 // We can't call CheckBogus on methods or indexers because if the method has the wrong 209 // number of parameters people don't think they should have to /r the assemblies containing 210 // the parameter types and they complain about the resulting CS0012 errors. 211 if (!(symCur is MethodSymbol) && (_flags & MemLookFlags.Indexer) == 0 && CSemanticChecker.CheckBogus(symCur)) 212 { 213 // A bogus member - we can't use these, so only record them for error reporting. 214 if (!_swtBogus) 215 { 216 _swtBogus.Set(symCur, typeCur); 217 } 218 continue; 219 } 220 221 // if we are in a calling context then we should only find a property if it is delegate valued 222 if ((_flags & MemLookFlags.MustBeInvocable) != 0) 223 { 224 if ((symCur is FieldSymbol field && !IsDelegateType(field.GetType(), typeCur) && !IsDynamicMember(symCur)) || 225 (prop != null && !IsDelegateType(prop.RetType, typeCur) && !IsDynamicMember(symCur))) 226 { 227 if (!_swtBad) 228 { 229 _swtBad.Set(symCur, typeCur); 230 } 231 continue; 232 } 233 } 234 235 if (methProp != null) 236 { 237 MethPropWithType mwpInsert = new MethPropWithType(methProp, typeCur); 238 _methPropWithTypeList.Add(mwpInsert); 239 } 240 241 // We have a visible symbol. 242 fFoundSome = true; 243 244 if (_swtFirst) 245 { 246 if (!typeCur.isInterfaceType()) 247 { 248 // Non-interface case. 249 Debug.Assert(_fMulti || typeCur == _prgtype[0]); 250 if (!_fMulti) 251 { 252 if (_swtFirst.Sym is FieldSymbol && symCur is EventSymbol 253 // The isEvent bit is only set on symbols which come from source... 254 // This is not a problem for the compiler because the field is only 255 // accessible in the scope in which it is declared, 256 // but in the EE we ignore accessibility... 257 && _swtFirst.Field().isEvent 258 ) 259 { 260 // m_swtFirst is just the field behind the event symCur so ignore symCur. 261 continue; 262 } 263 else if (_swtFirst.Sym is FieldSymbol && symCur is EventSymbol) 264 { 265 // symCur is the matching event. 266 continue; 267 } 268 goto LAmbig; 269 } 270 if (_swtFirst.Sym.getKind() != symCur.getKind()) 271 { 272 if (typeCur == _prgtype[0]) 273 goto LAmbig; 274 // This one is hidden by the first one. This one also hides any more in base types. 275 pfHideByName = true; 276 continue; 277 } 278 } 279 // Interface case. 280 // m_fMulti : n n n y y y y y 281 // same-kind : * * * y n n n n 282 // fDiffHidden: * * * * y n n n 283 // meth : * * * * * y n * can n happen? just in case, we better handle it.... 284 // hack : n * y * * y * n 285 // meth-2 : * n y * * * * * 286 // res : A A S R H H A A 287 else if (!_fMulti) 288 { 289 // Give method groups priority. 290 if (!(symCur is MethodSymbol)) 291 goto LAmbig; 292 // Erase previous results so we'll record this method as the first. 293 _prgtype = new List<AggregateType>(); 294 _csym = 0; 295 _swtFirst.Clear(); 296 _swtAmbig.Clear(); 297 } 298 else if (_swtFirst.Sym.getKind() != symCur.getKind()) 299 { 300 if (!typeCur.fDiffHidden) 301 { 302 // Give method groups priority. 303 if (!(_swtFirst.Sym is MethodSymbol)) 304 goto LAmbig; 305 } 306 // This one is hidden by another. This one also hides any more in base types. 307 pfHideByName = true; 308 continue; 309 } 310 } 311 312 RecordType(typeCur, symCur); 313 314 if (methProp != null && methProp.isHideByName) 315 pfHideByName = true; 316 // We've found a symbol in this type but need to make sure there aren't any conflicting 317 // syms here, so keep searching the type. 318 } 319 320 Debug.Assert(!fInaccess || !fFoundSome); 321 322 return fFoundSome; 323 324 LAmbig: 325 // Ambiguous! 326 if (!_swtAmbig) 327 _swtAmbig.Set(symCur, typeCur); 328 pfHideByName = true; 329 return true; 330 } 331 IsDynamicMember(Symbol sym)332 private bool IsDynamicMember(Symbol sym) 333 { 334 System.Runtime.CompilerServices.DynamicAttribute da = null; 335 if (sym is FieldSymbol field) 336 { 337 if (!field.getType().isPredefType(PredefinedType.PT_OBJECT)) 338 { 339 return false; 340 } 341 var o = field.AssociatedFieldInfo.GetCustomAttributes(typeof(System.Runtime.CompilerServices.DynamicAttribute), false).ToArray(); 342 if (o.Length == 1) 343 { 344 da = o[0] as System.Runtime.CompilerServices.DynamicAttribute; 345 } 346 } 347 else 348 { 349 Debug.Assert(sym is PropertySymbol); 350 PropertySymbol prop = (PropertySymbol)sym; 351 if (!prop.getType().isPredefType(PredefinedType.PT_OBJECT)) 352 { 353 return false; 354 } 355 var o = prop.AssociatedPropertyInfo.GetCustomAttributes(typeof(System.Runtime.CompilerServices.DynamicAttribute), false).ToArray(); 356 if (o.Length == 1) 357 { 358 da = o[0] as System.Runtime.CompilerServices.DynamicAttribute; 359 } 360 } 361 362 if (da == null) 363 { 364 return false; 365 } 366 return (da.TransformFlags.Count == 0 || (da.TransformFlags.Count == 1 && da.TransformFlags[0])); 367 } 368 369 /****************************************************************************** 370 Lookup in a class and its bases (until *ptypeEnd is hit). 371 372 ptypeEnd [in/out] - *ptypeEnd should be either null or object. If we find 373 something here that would hide members of object, this sets *ptypeEnd 374 to null. 375 376 Returns true when searching should continue to the interfaces. 377 ******************************************************************************/ LookupInClass(AggregateType typeStart, ref AggregateType ptypeEnd)378 private bool LookupInClass(AggregateType typeStart, ref AggregateType ptypeEnd) 379 { 380 Debug.Assert(!_swtFirst || _fMulti); 381 Debug.Assert(typeStart != null && !typeStart.isInterfaceType() && (ptypeEnd == null || typeStart != ptypeEnd)); 382 383 AggregateType typeEnd = ptypeEnd; 384 AggregateType typeCur; 385 386 // Loop through types. Loop until we hit typeEnd (object or null). 387 for (typeCur = typeStart; typeCur != typeEnd && typeCur != null; typeCur = typeCur.GetBaseClass()) 388 { 389 Debug.Assert(!typeCur.isInterfaceType()); 390 391 SearchSingleType(typeCur, out bool fHideByName); 392 393 if (_swtFirst && !_fMulti) 394 { 395 // Everything below this type and in interfaces is hidden. 396 return false; 397 } 398 399 if (fHideByName) 400 { 401 // This hides everything below it and in object, but not in the interfaces! 402 ptypeEnd = null; 403 404 // Return true to indicate that it's ok to search additional types. 405 return true; 406 } 407 408 if ((_flags & MemLookFlags.Ctor) != 0) 409 { 410 // If we're looking for a constructor, don't check base classes or interfaces. 411 return false; 412 } 413 } 414 415 Debug.Assert(typeCur == typeEnd); 416 return true; 417 } 418 419 /****************************************************************************** 420 Returns true if searching should continue to object. 421 ******************************************************************************/ LookupInInterfaces(AggregateType typeStart, TypeArray types)422 private bool LookupInInterfaces(AggregateType typeStart, TypeArray types) 423 { 424 Debug.Assert(!_swtFirst || _fMulti); 425 Debug.Assert(typeStart == null || typeStart.isInterfaceType()); 426 Debug.Assert(typeStart != null || types.Count != 0); 427 428 // Clear all the hidden flags. Anything found in a class hides any other 429 // kind of member in all the interfaces. 430 if (typeStart != null) 431 { 432 typeStart.fAllHidden = false; 433 typeStart.fDiffHidden = (_swtFirst != null); 434 } 435 436 for (int i = 0; i < types.Count; i++) 437 { 438 AggregateType type = (AggregateType)types[i]; 439 Debug.Assert(type.isInterfaceType()); 440 type.fAllHidden = false; 441 type.fDiffHidden = !!_swtFirst; 442 } 443 444 bool fHideObject = false; 445 AggregateType typeCur = typeStart; 446 int itypeNext = 0; 447 448 if (typeCur == null) 449 { 450 typeCur = (AggregateType)types[itypeNext++]; 451 } 452 Debug.Assert(typeCur != null); 453 454 // Loop through the interfaces. 455 for (; ;) 456 { 457 Debug.Assert(typeCur != null && typeCur.isInterfaceType()); 458 459 if (!typeCur.fAllHidden && SearchSingleType(typeCur, out bool fHideByName)) 460 { 461 fHideByName |= !_fMulti; 462 463 // Mark base interfaces appropriately. 464 TypeArray ifaces = typeCur.GetIfacesAll(); 465 for (int i = 0; i < ifaces.Count; i++) 466 { 467 AggregateType type = (AggregateType)ifaces[i]; 468 Debug.Assert(type.isInterfaceType()); 469 if (fHideByName) 470 type.fAllHidden = true; 471 type.fDiffHidden = true; 472 } 473 474 // If we hide all base types, that includes object! 475 if (fHideByName) 476 fHideObject = true; 477 } 478 479 if (itypeNext >= types.Count) 480 return !fHideObject; 481 482 // Substitution has already been done. 483 typeCur = types[itypeNext++] as AggregateType; 484 } 485 } 486 GetSymbolLoader()487 private SymbolLoader GetSymbolLoader() { return _pSymbolLoader; } GetSemanticChecker()488 private CSemanticChecker GetSemanticChecker() { return _pSemanticChecker; } GetErrorContext()489 private ErrorHandling GetErrorContext() { return GetSymbolLoader().GetErrorContext(); } 490 ReportBogus(SymWithType swt)491 private RuntimeBinderException ReportBogus(SymWithType swt) 492 { 493 Debug.Assert(CSemanticChecker.CheckBogus(swt.Sym)); 494 MethodSymbol meth1 = swt.Prop().GetterMethod; 495 MethodSymbol meth2 = swt.Prop().SetterMethod; 496 Debug.Assert((meth1 ?? meth2) != null); 497 return meth1 == null | meth2 == null 498 ? GetErrorContext().Error( 499 ErrorCode.ERR_BindToBogusProp1, swt.Sym.name, new SymWithType(meth1 ?? meth2, swt.GetType()), 500 new ErrArgRefOnly(swt.Sym)) 501 : GetErrorContext().Error( 502 ErrorCode.ERR_BindToBogusProp2, swt.Sym.name, new SymWithType(meth1, swt.GetType()), 503 new SymWithType(meth2, swt.GetType()), new ErrArgRefOnly(swt.Sym)); 504 } 505 IsDelegateType(CType pSrcType, AggregateType pAggType)506 private bool IsDelegateType(CType pSrcType, AggregateType pAggType) 507 { 508 CType pInstantiatedType = GetSymbolLoader().GetTypeManager().SubstType(pSrcType, pAggType, pAggType.GetTypeArgsAll()); 509 return pInstantiatedType.isDelegateType(); 510 } 511 512 ///////////////////////////////////////////////////////////////////////////////// 513 // Public methods. 514 MemberLookup()515 public MemberLookup() 516 { 517 _methPropWithTypeList = new List<MethPropWithType>(); 518 _rgtypeStart = new List<AggregateType>(); 519 _swtFirst = new SymWithType(); 520 _swtAmbig = new SymWithType(); 521 _swtInaccess = new SymWithType(); 522 _swtBad = new SymWithType(); 523 _swtBogus = new SymWithType(); 524 _swtBadArity = new SymWithType(); 525 } 526 527 /*************************************************************************************************** 528 Lookup must be called before anything else can be called. 529 530 typeSrc - Must be an AggregateType or TypeParameterType. 531 obj - the expression through which the member is being accessed. This is used for accessibility 532 of protected members and for constructing a MEMGRP from the results of the lookup. 533 It is legal for obj to be an EK_CLASS, in which case it may be used for accessibility, but 534 will not be used for MEMGRP construction. 535 symWhere - the symbol from with the name is being accessed (for checking accessibility). 536 name - the name to look for. 537 arity - the number of type args specified. Only members that support this arity are found. 538 Note that when arity is zero, all methods are considered since we do type argument 539 inferencing. 540 541 flags - See MemLookFlags. 542 TypeVarsAllowed only applies to the most derived type (not base types). 543 ***************************************************************************************************/ Lookup(CSemanticChecker checker, CType typeSrc, Expr obj, ParentSymbol symWhere, Name name, int arity, MemLookFlags flags)544 public bool Lookup(CSemanticChecker checker, CType typeSrc, Expr obj, ParentSymbol symWhere, Name name, int arity, MemLookFlags flags) 545 { 546 Debug.Assert((flags & ~MemLookFlags.All) == 0); 547 Debug.Assert(obj == null || obj.Type != null); 548 Debug.Assert(typeSrc is AggregateType); 549 Debug.Assert(checker != null); 550 551 _prgtype = _rgtypeStart; 552 553 // Save the inputs for error handling, etc. 554 _pSemanticChecker = checker; 555 _pSymbolLoader = checker.SymbolLoader; 556 _typeSrc = typeSrc; 557 _obj = obj is ExprClass ? null : obj; 558 _symWhere = symWhere; 559 _name = name; 560 _arity = arity; 561 _flags = flags; 562 563 _typeQual = (_flags & MemLookFlags.Ctor) != 0 ? _typeSrc : obj?.Type; 564 565 // Determine what to search. 566 AggregateType typeCls1 = null; 567 AggregateType typeIface = null; 568 TypeArray ifaces = BSYMMGR.EmptyTypeArray(); 569 AggregateType typeCls2 = null; 570 571 if (!typeSrc.isInterfaceType()) 572 { 573 typeCls1 = (AggregateType)typeSrc; 574 575 if (typeCls1.IsWindowsRuntimeType()) 576 { 577 ifaces = typeCls1.GetWinRTCollectionIfacesAll(GetSymbolLoader()); 578 } 579 } 580 else 581 { 582 Debug.Assert(typeSrc.isInterfaceType()); 583 Debug.Assert((_flags & (MemLookFlags.Ctor | MemLookFlags.NewObj | MemLookFlags.Operator | MemLookFlags.BaseCall)) == 0); 584 typeIface = (AggregateType)typeSrc; 585 ifaces = typeIface.GetIfacesAll(); 586 } 587 588 if (typeIface != null || ifaces.Count > 0) 589 typeCls2 = GetSymbolLoader().GetPredefindType(PredefinedType.PT_OBJECT); 590 591 // Search the class first (except possibly object). 592 if (typeCls1 == null || LookupInClass(typeCls1, ref typeCls2)) 593 { 594 // Search the interfaces. 595 if ((typeIface != null || ifaces.Count > 0) && LookupInInterfaces(typeIface, ifaces) && typeCls2 != null) 596 { 597 // Search object last. 598 Debug.Assert(typeCls2 != null && typeCls2.isPredefType(PredefinedType.PT_OBJECT)); 599 600 AggregateType result = null; 601 LookupInClass(typeCls2, ref result); 602 } 603 } 604 605 return !FError(); 606 } 607 608 // Whether there were errors. FError()609 private bool FError() 610 { 611 return !_swtFirst || _swtAmbig; 612 } 613 614 // The first symbol found. SymFirst()615 public Symbol SymFirst() 616 { 617 return _swtFirst.Sym; 618 } SwtFirst()619 public SymWithType SwtFirst() 620 { 621 return _swtFirst; 622 } 623 GetObject()624 public Expr GetObject() 625 { 626 return _obj; 627 } 628 GetSourceType()629 public CType GetSourceType() 630 { 631 return _typeSrc; 632 } 633 GetFlags()634 public MemLookFlags GetFlags() 635 { 636 return _flags; 637 } 638 639 // Put all the types in a type array. GetAllTypes()640 private TypeArray GetAllTypes() 641 { 642 return GetSymbolLoader().getBSymmgr().AllocParams(_prgtype.Count, _prgtype.ToArray()); 643 } 644 645 /****************************************************************************** 646 Reports errors. Only call this if FError() is true. 647 ******************************************************************************/ ReportErrors()648 public Exception ReportErrors() 649 { 650 Debug.Assert(FError()); 651 652 // Report error. 653 // NOTE: If the definition of FError changes, this code will need to change. 654 Debug.Assert(!_swtFirst || _swtAmbig); 655 656 if (_swtFirst) 657 { 658 // Ambiguous lookup. 659 return GetErrorContext().Error(ErrorCode.ERR_AmbigMember, _swtFirst, _swtAmbig); 660 } 661 662 if (_swtInaccess) 663 { 664 return !_swtInaccess.Sym.isUserCallable() && ((_flags & MemLookFlags.UserCallable) != 0) 665 ? GetErrorContext().Error(ErrorCode.ERR_CantCallSpecialMethod, _swtInaccess) 666 : GetSemanticChecker().ReportAccessError(_swtInaccess, _symWhere, _typeQual); 667 } 668 669 if ((_flags & MemLookFlags.Ctor) != 0) 670 { 671 return _arity > 0 672 ? GetErrorContext().Error(ErrorCode.ERR_BadCtorArgCount, _typeSrc.getAggregate(), _arity) 673 : GetErrorContext().Error(ErrorCode.ERR_NoConstructors, _typeSrc.getAggregate()); 674 } 675 676 if ((_flags & MemLookFlags.Operator) != 0) 677 { 678 return GetErrorContext().Error(ErrorCode.ERR_NoSuchMember, _typeSrc, _name); 679 } 680 681 if ((_flags & MemLookFlags.Indexer) != 0) 682 { 683 return GetErrorContext().Error(ErrorCode.ERR_BadIndexLHS, _typeSrc); 684 } 685 686 if (_swtBad) 687 { 688 return GetErrorContext().Error((_flags & MemLookFlags.MustBeInvocable) != 0 ? ErrorCode.ERR_NonInvocableMemberCalled : ErrorCode.ERR_CantCallSpecialMethod, _swtBad); 689 } 690 691 if (_swtBogus) 692 { 693 return ReportBogus(_swtBogus); 694 } 695 696 if (_swtBadArity) 697 { 698 int cvar; 699 700 switch (_swtBadArity.Sym.getKind()) 701 { 702 case SYMKIND.SK_MethodSymbol: 703 Debug.Assert(_arity != 0); 704 cvar = ((MethodSymbol)_swtBadArity.Sym).typeVars.Count; 705 return GetErrorContext().Error(cvar > 0 ? ErrorCode.ERR_BadArity : ErrorCode.ERR_HasNoTypeVars, _swtBadArity, new ErrArgSymKind(_swtBadArity.Sym), cvar); 706 707 case SYMKIND.SK_AggregateSymbol: 708 cvar = ((AggregateSymbol)_swtBadArity.Sym).GetTypeVars().Count; 709 return GetErrorContext().Error(cvar > 0 ? ErrorCode.ERR_BadArity : ErrorCode.ERR_HasNoTypeVars, _swtBadArity, new ErrArgSymKind(_swtBadArity.Sym), cvar); 710 711 default: 712 Debug.Assert(_arity != 0); 713 return GetErrorContext().Error(ErrorCode.ERR_TypeArgsNotAllowed, _swtBadArity, new ErrArgSymKind(_swtBadArity.Sym)); 714 } 715 } 716 717 return GetErrorContext().Error(ErrorCode.ERR_NoSuchMember, _typeSrc, _name); 718 } 719 } 720 } 721