Skip to content

Commit

Permalink
Resolve extension members in all non-invocation contexts (#73239)
Browse files Browse the repository at this point in the history
  • Loading branch information
jcouv committed May 2, 2024
1 parent a33cedf commit 6b9b076
Show file tree
Hide file tree
Showing 18 changed files with 3,145 additions and 413 deletions.
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
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs
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

0 comments on commit 6b9b076

Please sign in to comment.