Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 9bf574e

Browse files
JonHannaVSadov
authored andcommitted
Only search for member types in Microsoft.CSharp member lookup. (#26633)
As opposed to nested classes, or type parameters. Fixes #26632
1 parent 033851f commit 9bf574e

File tree

3 files changed

+108
-48
lines changed

3 files changed

+108
-48
lines changed

src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MemberLookup.cs

Lines changed: 20 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -112,44 +112,24 @@ private bool SearchSingleType(AggregateType typeCur, out bool pfHideByName)
112112

113113
// Loop through symbols.
114114
Symbol symCur;
115-
for (symCur = GetSymbolLoader().LookupAggMember(_name, typeCur.OwningAggregate, symbmask_t.MASK_ALL);
115+
for (symCur = GetSymbolLoader().LookupAggMember(_name, typeCur.OwningAggregate, symbmask_t.MASK_Member);
116116
symCur != null;
117-
symCur = SymbolLoader.LookupNextSym(symCur, typeCur.OwningAggregate, symbmask_t.MASK_ALL))
117+
symCur = SymbolLoader.LookupNextSym(symCur, typeCur.OwningAggregate, symbmask_t.MASK_Member))
118118
{
119+
Debug.Assert(!(symCur is AggregateSymbol));
119120
// Check for arity.
120-
switch (symCur.getKind())
121+
// For non-zero arity, only methods of the correct arity are considered.
122+
// For zero arity, don't filter out any methods since we do type argument
123+
// inferencing.
124+
// All others are only considered when arity is zero.
125+
if (_arity > 0 && (!(symCur is MethodSymbol curMeth) || curMeth.typeVars.Count != _arity))
121126
{
122-
case SYMKIND.SK_MethodSymbol:
123-
// For non-zero arity, only methods of the correct arity are considered.
124-
// For zero arity, don't filter out any methods since we do type argument
125-
// inferencing.
126-
if (_arity > 0 && ((MethodSymbol)symCur).typeVars.Count != _arity)
127-
{
128-
if (!_swtBadArity)
129-
_swtBadArity.Set(symCur, typeCur);
130-
continue;
131-
}
132-
break;
133-
134-
case SYMKIND.SK_AggregateSymbol:
135-
// For types, always filter on arity.
136-
if (((AggregateSymbol)symCur).GetTypeVars().Count != _arity)
137-
{
138-
if (!_swtBadArity)
139-
_swtBadArity.Set(symCur, typeCur);
140-
continue;
141-
}
142-
break;
127+
if (!_swtBadArity)
128+
{
129+
_swtBadArity.Set(symCur, typeCur);
130+
}
143131

144-
default:
145-
// All others are only considered when arity is zero.
146-
if (_arity > 0)
147-
{
148-
if (!_swtBadArity)
149-
_swtBadArity.Set(symCur, typeCur);
150-
continue;
151-
}
152-
break;
132+
continue;
153133
}
154134

155135
// Check for user callability.
@@ -672,23 +652,15 @@ public Exception ReportErrors()
672652

673653
if (_swtBadArity)
674654
{
675-
int cvar;
676-
677-
switch (_swtBadArity.Sym.getKind())
655+
Debug.Assert(_arity != 0);
656+
Debug.Assert(!(_swtBadArity.Sym is AggregateSymbol));
657+
if (_swtBadArity.Sym is MethodSymbol badMeth)
678658
{
679-
case SYMKIND.SK_MethodSymbol:
680-
Debug.Assert(_arity != 0);
681-
cvar = ((MethodSymbol)_swtBadArity.Sym).typeVars.Count;
682-
return GetErrorContext().Error(cvar > 0 ? ErrorCode.ERR_BadArity : ErrorCode.ERR_HasNoTypeVars, _swtBadArity, new ErrArgSymKind(_swtBadArity.Sym), cvar);
683-
684-
case SYMKIND.SK_AggregateSymbol:
685-
cvar = ((AggregateSymbol)_swtBadArity.Sym).GetTypeVars().Count;
686-
return GetErrorContext().Error(cvar > 0 ? ErrorCode.ERR_BadArity : ErrorCode.ERR_HasNoTypeVars, _swtBadArity, new ErrArgSymKind(_swtBadArity.Sym), cvar);
687-
688-
default:
689-
Debug.Assert(_arity != 0);
690-
return GetErrorContext().Error(ErrorCode.ERR_TypeArgsNotAllowed, _swtBadArity, new ErrArgSymKind(_swtBadArity.Sym));
659+
int cvar = badMeth.typeVars.Count;
660+
return GetErrorContext().Error(cvar > 0 ? ErrorCode.ERR_BadArity : ErrorCode.ERR_HasNoTypeVars, _swtBadArity, new ErrArgSymKind(_swtBadArity.Sym), cvar);
691661
}
662+
663+
return GetErrorContext().Error(ErrorCode.ERR_TypeArgsNotAllowed, _swtBadArity, new ErrArgSymKind(_swtBadArity.Sym));
692664
}
693665

694666
return GetErrorContext().Error(ErrorCode.ERR_NoSuchMember, _typeSrc, _name);

src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/SymbolMask.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@ internal enum symbmask_t : long
1717
MASK_PropertySymbol = 1 << SYMKIND.SK_PropertySymbol,
1818
MASK_EventSymbol = 1 << SYMKIND.SK_EventSymbol,
1919
MASK_ALL = ~0,
20+
MASK_Member = MASK_FieldSymbol | MASK_MethodSymbol | MASK_PropertySymbol | MASK_EventSymbol
2021
}
2122
}

src/Microsoft.CSharp/tests/BindingErrors.cs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,93 @@ public void CannotInferTypeArgument()
428428
Assert.Throws<RuntimeBinderException>(() => DoStuff(d));
429429
}
430430

431+
public class Outer
432+
{
433+
public class Inner
434+
{
435+
public void DoNothing()
436+
{
437+
}
438+
}
439+
}
440+
441+
[Fact]
442+
public void TryInvokeOrAccessNestedClassAsMember()
443+
{
444+
dynamic dFirst = new Outer.Inner();
445+
dFirst.DoNothing();
446+
dynamic d = new Outer();
447+
Assert.Throws<RuntimeBinderException>(() => d.Inner<int>());
448+
Assert.Throws<RuntimeBinderException>(() => d.Inner());
449+
Assert.Throws<RuntimeBinderException>(() => d.Inner = 2);
450+
Assert.Throws<RuntimeBinderException>(
451+
() =>
452+
{
453+
int i = d.Inner<int>();
454+
});
455+
}
456+
457+
[Fact]
458+
public void TryInvokeTypeParameterAsMember()
459+
{
460+
dynamic d = new List<int>();
461+
Assert.Throws<RuntimeBinderException>(() => d.T);
462+
Assert.Throws<RuntimeBinderException>(() => d.T());
463+
Assert.Throws<RuntimeBinderException>(() => d.T<int>());
464+
Assert.Throws<RuntimeBinderException>(() =>
465+
{
466+
int i = d.T;
467+
});
468+
}
469+
470+
public class BaseForOuterWithMethod
471+
{
472+
public int Inner() => 42;
473+
}
474+
475+
public class DerivedOuterHidingMethod : BaseForOuterWithMethod
476+
{
477+
public new class Inner
478+
{
479+
public void DoNothing()
480+
{
481+
}
482+
}
483+
}
484+
485+
[Fact]
486+
public void AccessMethodHiddenByNested()
487+
{
488+
dynamic dFirst = new DerivedOuterHidingMethod.Inner();
489+
dFirst.DoNothing();
490+
dynamic d = new DerivedOuterHidingMethod();
491+
Assert.Equal(42, d.Inner());
492+
}
493+
494+
public class BaseForOuterWithNested
495+
{
496+
public class Inner
497+
{
498+
public void DoNothing()
499+
{
500+
}
501+
}
502+
}
503+
504+
public class DerivedOuterHidingNested : BaseForOuterWithNested
505+
{
506+
public new int Inner() => 42;
507+
}
508+
509+
[Fact]
510+
public void AccessMethodHidingNested()
511+
{
512+
dynamic dFirst = new BaseForOuterWithNested.Inner();
513+
dFirst.DoNothing();
514+
dynamic d = new DerivedOuterHidingNested();
515+
Assert.Equal(42, d.Inner());
516+
}
517+
431518
[Fact]
432519
public void CannotCallOperatorDirectly()
433520
{

0 commit comments

Comments
 (0)