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

Pattern-matching fixes for ITuple, short tuple patterns, and nulls #31056

Merged
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*.userprefs
*.sln.docstates
.vs/
.dotnet/

# Build results
[Bb]inaries/
Expand Down
20 changes: 9 additions & 11 deletions src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ private bool MakeDeconstructionConversion(

var inputPlaceholder = new BoundDeconstructValuePlaceholder(syntax, this.LocalScopeDepth, type);
BoundExpression deconstructInvocation = MakeDeconstructInvocationExpression(variables.Count,
inputPlaceholder, rightSyntax, diagnostics, outPlaceholders: out ImmutableArray<BoundDeconstructValuePlaceholder> outPlaceholders);
inputPlaceholder, rightSyntax, diagnostics, outPlaceholders: out ImmutableArray<BoundDeconstructValuePlaceholder> outPlaceholders, out _);

if (deconstructInvocation.HasAnyErrors)
{
Expand Down Expand Up @@ -600,8 +600,10 @@ private BoundExpression MakeDeconstructInvocationExpression(
BoundExpression receiver,
SyntaxNode rightSyntax,
DiagnosticBag diagnostics,
out ImmutableArray<BoundDeconstructValuePlaceholder> outPlaceholders)
out ImmutableArray<BoundDeconstructValuePlaceholder> outPlaceholders,
out bool anyApplicableCandidates)
{
anyApplicableCandidates = false;
var receiverSyntax = (CSharpSyntaxNode)receiver.Syntax;
if (receiver.Type.IsDynamic())
{
Expand Down Expand Up @@ -643,22 +645,18 @@ private BoundExpression MakeDeconstructInvocationExpression(
// So the generated invocation expression will contain placeholders instead of those outVar nodes.
// Those placeholders are also recorded in the outVar for easy access below, by the `SetInferredType` call on the outVar nodes.
BoundExpression result = BindMethodGroupInvocation(
rightSyntax, rightSyntax, methodName, (BoundMethodGroup)memberAccess, analyzedArguments, diagnostics, queryClause: null,
allowUnexpandedForm: true);
rightSyntax, rightSyntax, methodName, (BoundMethodGroup)memberAccess, analyzedArguments, diagnostics, queryClause: null,
allowUnexpandedForm: true, anyApplicableCandidates: out anyApplicableCandidates);

result.WasCompilerGenerated = true;

if (result.HasErrors && !receiver.HasAnyErrors)
{
return MissingDeconstruct(receiver, rightSyntax, numCheckedVariables, diagnostics, out outPlaceholders, result);
}

// Verify all the parameters (except "this" for extension methods) are out parameters
if (result.Kind != BoundKind.Call)
if (!anyApplicableCandidates)
{
return MissingDeconstruct(receiver, rightSyntax, numCheckedVariables, diagnostics, out outPlaceholders, result);
}

// Verify all the parameters (except "this" for extension methods) are out parameters.
// This prevents, for example, an unused params parameter after the out parameters.
var deconstructMethod = ((BoundCall)result).Method;
var parameters = deconstructMethod.Parameters;
for (int i = (deconstructMethod.IsExtensionMethod ? 1 : 0); i < parameters.Length; i++)
Expand Down
6 changes: 3 additions & 3 deletions src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1640,7 +1640,7 @@ protected virtual BoundExpression BindRangeVariable(SimpleNameSyntax node, Range
return Next.BindRangeVariable(node, qv, diagnostics);
}

private BoundExpression SynthesizeReceiver(CSharpSyntaxNode node, Symbol member, DiagnosticBag diagnostics)
private BoundExpression SynthesizeReceiver(SyntaxNode node, Symbol member, DiagnosticBag diagnostics)
{
// SPEC: Otherwise, if T is the instance type of the immediately enclosing class or
// struct type, if the lookup identifies an instance member, and if the reference occurs
Expand Down Expand Up @@ -1710,7 +1710,7 @@ internal Symbol ContainingMember()
return containingMember;
}

private BoundExpression TryBindInteractiveReceiver(CSharpSyntaxNode syntax, Symbol currentMember, NamedTypeSymbol currentType, NamedTypeSymbol memberDeclaringType)
private BoundExpression TryBindInteractiveReceiver(SyntaxNode syntax, Symbol currentMember, NamedTypeSymbol currentType, NamedTypeSymbol memberDeclaringType)
{
if (currentType.TypeKind == TypeKind.Submission && !currentMember.IsStatic)
{
Expand Down Expand Up @@ -1841,7 +1841,7 @@ private BoundThisReference BindThis(ThisExpressionSyntax node, DiagnosticBag dia
return ThisReference(node, this.ContainingType, hasErrors);
}

private BoundThisReference ThisReference(CSharpSyntaxNode node, NamedTypeSymbol thisTypeOpt, bool hasErrors = false, bool wasCompilerGenerated = false)
private BoundThisReference ThisReference(SyntaxNode node, NamedTypeSymbol thisTypeOpt, bool hasErrors = false, bool wasCompilerGenerated = false)
{
return new BoundThisReference(node, thisTypeOpt ?? CreateErrorType(), hasErrors) { WasCompilerGenerated = wasCompilerGenerated };
}
Expand Down
25 changes: 12 additions & 13 deletions src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,9 @@ private BoundExpression BindInvocationExpression(
}
else if (boundExpression.Kind == BoundKind.MethodGroup)
{
result = BindMethodGroupInvocation(node, expression, methodName, (BoundMethodGroup)boundExpression, analyzedArguments, diagnostics, queryClause, allowUnexpandedForm: allowUnexpandedForm);
result = BindMethodGroupInvocation(
node, expression, methodName, (BoundMethodGroup)boundExpression, analyzedArguments,
diagnostics, queryClause, allowUnexpandedForm: allowUnexpandedForm, anyApplicableCandidates: out _);
}
else if ((object)(delegateType = GetDelegateType(boundExpression)) != null)
{
Expand Down Expand Up @@ -555,14 +557,16 @@ private BoundExpression BindMethodGroupInvocation(
AnalyzedArguments analyzedArguments,
DiagnosticBag diagnostics,
CSharpSyntaxNode queryClause,
bool allowUnexpandedForm = true)
bool allowUnexpandedForm,
out bool anyApplicableCandidates)
{
BoundExpression result;
HashSet<DiagnosticInfo> useSiteDiagnostics = null;
var resolution = this.ResolveMethodGroup(
methodGroup, expression, methodName, analyzedArguments, isMethodGroupConversion: false,
useSiteDiagnostics: ref useSiteDiagnostics, allowUnexpandedForm: allowUnexpandedForm);
diagnostics.Add(expression, useSiteDiagnostics);
anyApplicableCandidates = resolution.ResultKind == LookupResultKind.Viable && resolution.OverloadResolutionResult.HasAnyApplicableMember;

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

Expand Down Expand Up @@ -1105,13 +1109,8 @@ private BoundCall BindInvocationExpressionContinued(
diagnostics);
}

if ((object)delegateTypeOpt != null)
{
return new BoundCall(node, receiver, method, args, argNames, argRefKinds, isDelegateCall: true,
expanded: expanded, invokedAsExtensionMethod: invokedAsExtensionMethod,
argsToParamsOpt: argsToParams, resultKind: LookupResultKind.Viable, binderOpt: this, type: returnType, hasErrors: gotError);
}
else
bool isDelegateCall = (object)delegateTypeOpt != null;
if (!isDelegateCall)
{
if ((object)receiver != null && receiver.Kind == BoundKind.BaseReference && method.IsAbstract)
{
Expand All @@ -1127,11 +1126,11 @@ private BoundCall BindInvocationExpressionContinued(
receiver,
diagnostics);
}

return new BoundCall(node, receiver, method, args, argNames, argRefKinds, isDelegateCall: false,
expanded: expanded, invokedAsExtensionMethod: invokedAsExtensionMethod,
argsToParamsOpt: argsToParams, resultKind: LookupResultKind.Viable, binderOpt: this, type: returnType, hasErrors: gotError);
}

return new BoundCall(node, receiver, method, args, argNames, argRefKinds, isDelegateCall: isDelegateCall,
expanded: expanded, invokedAsExtensionMethod: invokedAsExtensionMethod,
argsToParamsOpt: argsToParams, resultKind: LookupResultKind.Viable, binderOpt: this, type: returnType, hasErrors: gotError);
}

private bool IsBindingModuleLevelAttribute()
Expand Down
Loading