Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolve extension members in all non-invocation contexts #73239

Merged
merged 13 commits into from
May 2, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ private bool CheckIdentifier(Binder enclosingBinder, IdentifierNameSyntax id)
}

/// <summary>
/// Follows the logic of <see cref="Binder.BindInstanceMemberAccess"/> and <see cref="Binder.BindMemberOfType"/>
/// Follows the logic of <see cref="Binder.BindMemberAccessWithBoundLeftCore"/> and <see cref="Binder.BindMemberOfType"/>
/// </summary>
protected static bool TreatAsInstanceMemberAccess(
Binder enclosingBinder,
Expand Down
8 changes: 2 additions & 6 deletions src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -406,11 +406,6 @@ private BoundIndexerAccess BindIndexerDefaultArgumentsAndParamsCollection(BoundI
/// </summary>
private BoundExpression CheckValue(BoundExpression expr, BindValueKind valueKind, BindingDiagnosticBag diagnostics)
{
if (RequiresAssignableVariable(valueKind))
{
expr = ResolveToExtensionMemberIfPossible(expr, diagnostics);
}

switch (expr.Kind)
{
case BoundKind.PropertyGroup:
Expand Down Expand Up @@ -480,9 +475,10 @@ private BoundExpression CheckValue(BoundExpression expr, BindValueKind valueKind
var methodGroup = (BoundMethodGroup)expr;
CompoundUseSiteInfo<AssemblySymbol> useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics);
var resolution = this.ResolveMethodGroup(methodGroup, analyzedArguments: null, useSiteInfo: ref useSiteInfo, options: OverloadResolution.Options.None);
Debug.Assert(!resolution.IsNonMethodExtensionMember(out _));
diagnostics.Add(expr.Syntax, useSiteInfo);
Symbol otherSymbol = null;
bool resolvedToUnusableSymbol = resolution.MethodGroup == null && !resolution.IsExtensionMember(out _);
bool resolvedToUnusableSymbol = resolution.MethodGroup == null;
if (!expr.HasAnyErrors) diagnostics.AddRange(resolution.Diagnostics); // Suppress cascading.
hasResolutionErrors = resolution.HasAnyErrors;
if (hasResolutionErrors)
Expand Down
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Portable/Binder/Binder_Await.cs
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ private bool GetIsCompletedProperty(TypeSymbol awaiterType, SyntaxNode node, Typ
{
var receiver = new BoundLiteral(node, ConstantValue.Null, awaiterType);
var name = WellKnownMemberNames.IsCompleted;
var qualified = BindInstanceMemberAccess(node, node, receiver, name, 0, default(SeparatedSyntaxList<TypeSyntax>), default(ImmutableArray<TypeWithAnnotations>), invoked: false, indexed: false, diagnostics);
var qualified = BindMemberAccessWithBoundLeftCore(node, node, receiver, name, 0, default(SeparatedSyntaxList<TypeSyntax>), default(ImmutableArray<TypeWithAnnotations>), invoked: false, indexed: false, diagnostics);
if (qualified.HasAnyErrors)
{
isCompletedProperty = null;
Expand Down
24 changes: 10 additions & 14 deletions src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ internal partial class Binder

Debug.Assert(result is BoundConversion
|| (conversion.IsIdentity && ((object)result == source)
|| (conversion.IsExtensionMemberConversion(out _, out var nestedConversion) && nestedConversion.IsIdentity)
|| source.NeedsToBeConverted())
|| hasErrors);

Expand Down Expand Up @@ -135,15 +134,6 @@ static bool filterConversion(Conversion conversion)
return CreateMethodGroupConversion(syntax, source, conversion, isCast: isCast, conversionGroupOpt, destination, diagnostics);
}

if (conversion.IsExtensionMemberConversion(out Symbol? extensionMember, out Conversion nestedConversion))
{
var methodGroup = (BoundMethodGroup)source;
source = GetExtensionMemberAccess(syntax, methodGroup.ReceiverOpt, extensionMember,
methodGroup.TypeArgumentsSyntax, methodGroup.TypeArgumentsOpt, diagnostics);

return CreateConversion(syntax, source, nestedConversion, isCast, conversionGroupOpt, destination, diagnostics);
}

// Obsolete diagnostics for method group are reported as part of creating the method group conversion.
reportUseSiteDiagnostics(syntax, conversion, source, destination, diagnostics);

Expand Down Expand Up @@ -529,7 +519,7 @@ void checkConstraintLanguageVersionAndRuntimeSupportForConversion(SyntaxNode syn
return BindFieldAccess(syntax, receiver, fieldSymbol, diagnostics, LookupResultKind.Viable, indexed: false, hasErrors: false);

case NamedTypeSymbol namedTypeSymbol:
bool wasError = false;
bool wasError = namedTypeSymbol.IsErrorType();

if (!typeArgumentsOpt.IsDefault)
{
Expand Down Expand Up @@ -1054,11 +1044,11 @@ internal bool HasCollectionExpressionApplicableAddMethod(SyntaxNode syntax, Type
BindingDiagnosticBag diagnostics,
out ImmutableArray<MethodSymbol> addMethods)
{
var boundExpression = addMethodBinder.BindInstanceMemberAccess(
var boundExpression = addMethodBinder.BindMemberAccessWithBoundLeftCore(
node, node, receiver, WellKnownMemberNames.CollectionInitializerAddMethodName, rightArity: 0,
typeArgumentsSyntax: default(SeparatedSyntaxList<TypeSyntax>),
typeArgumentsWithAnnotations: default(ImmutableArray<TypeWithAnnotations>),
invoked: true, indexed: false, diagnostics, searchExtensionMethodsIfNecessary: true);
invoked: true, indexed: false, diagnostics, searchExtensionsIfNecessary: true);

// require the target member to be a method.
if (boundExpression.Kind == BoundKind.FieldAccess || boundExpression.Kind == BoundKind.PropertyAccess)
Expand Down Expand Up @@ -1134,7 +1124,13 @@ internal bool HasCollectionExpressionApplicableAddMethod(SyntaxNode syntax, Type

if (!methodGroup.HasAnyErrors) diagnostics.AddRange(resolution.Diagnostics); // Suppress cascading.

if (resolution.HasAnyErrors)
if (resolution.IsNonMethodExtensionMember(out Symbol? extensionMember))
{
ReportMakeInvocationExpressionBadMemberKind(syntax, WellKnownMemberNames.CollectionInitializerAddMethodName, methodGroup, diagnostics);
addMethods = [];
result = false;
}
else if (resolution.HasAnyErrors)
{
addMethods = [];
result = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,7 @@ private string GetDebuggerDisplay()
}

const string methodName = WellKnownMemberNames.DeconstructMethodName;
var memberAccess = BindInstanceMemberAccess(
var memberAccess = BindMemberAccessWithBoundLeftCore(
rightSyntax, receiverSyntax, receiver, methodName, rightArity: 0,
typeArgumentsSyntax: default(SeparatedSyntaxList<TypeSyntax>),
typeArgumentsWithAnnotations: default(ImmutableArray<TypeWithAnnotations>),
Expand Down