Skip to content

Commit

Permalink
Statically bind invocations in presence of dynamic arguments only for…
Browse files Browse the repository at this point in the history
… local functions or language version past C# 12.

Related to dotnet#72750.
  • Loading branch information
AlekseyTs committed Apr 19, 2024
1 parent 123d88b commit af4a668
Show file tree
Hide file tree
Showing 4 changed files with 533 additions and 34 deletions.
3 changes: 2 additions & 1 deletion src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9719,7 +9719,8 @@ private BoundExpression BindIndexedPropertyAccess(SyntaxNode syntax, BoundExpres
argumentSyntax, singleCandidate);
}
}
else
// For C# 12 and earlier statically bind invocations in presence of dynamic arguments only for expanded non-array params cases.
else if (Compilation.LanguageVersion > LanguageVersion.CSharp12 || IsMemberWithExpandedNonArrayParamsCollection(finalApplicableCandidates[0]))
{
var resultWithSingleCandidate = OverloadResolutionResult<PropertySymbol>.GetInstance();
resultWithSingleCandidate.ResultsBuilder.Add(finalApplicableCandidates[0]);
Expand Down
50 changes: 35 additions & 15 deletions src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -638,10 +638,15 @@ private ImmutableArray<BoundExpression> BuildArgumentsForDynamicInvocation(Analy

result = BindDynamicInvocation(node, boundExpression, analyzedArguments, overloadResolutionResult.GetAllApplicableMembers(), diagnostics, queryClause);
}
else
// For C# 12 and earlier statically bind invocations in presence of dynamic arguments only for expanded non-array params cases.
else if (Compilation.LanguageVersion > LanguageVersion.CSharp12 || IsMemberWithExpandedNonArrayParamsCollection(applicable))
{
result = BindInvocationExpressionContinued(node, expression, methodName, overloadResolutionResult, analyzedArguments, methodGroup, delegateType, diagnostics, queryClause);
}
else
{
result = BindDynamicInvocation(node, boundExpression, analyzedArguments, overloadResolutionResult.GetAllApplicableMembers(), diagnostics, queryClause);
}
}
else
{
Expand Down Expand Up @@ -682,6 +687,13 @@ private bool HasApplicableMemberWithPossiblyExpandedNonArrayParamsCollection<TMe
return false;
}

private bool IsMemberWithExpandedNonArrayParamsCollection<TMember>(MemberResolutionResult<TMember> candidate)
where TMember : Symbol
{
return candidate.Result.Kind == MemberResolutionKind.ApplicableInExpandedForm &&
!candidate.Member.GetParameters().Last().Type.IsSZArray();
}

private BoundExpression BindMethodGroupInvocation(
SyntaxNode syntax,
SyntaxNode expression,
Expand Down Expand Up @@ -975,23 +987,31 @@ private bool IsAmbiguousDynamicParamsArgument<TMethodOrPropertySymbol>(ArrayBuil
return null;
}

var resultWithSingleCandidate = OverloadResolutionResult<MethodSymbol>.GetInstance();
resultWithSingleCandidate.ResultsBuilder.Add(methodResolutionResult);
// For C# 12 and earlier statically bind invocations in presence of dynamic arguments only for local functions or expanded non-array params cases.
if (Compilation.LanguageVersion > LanguageVersion.CSharp12 ||
singleCandidate.MethodKind == MethodKind.LocalFunction ||
IsMemberWithExpandedNonArrayParamsCollection(methodResolutionResult))
{
var resultWithSingleCandidate = OverloadResolutionResult<MethodSymbol>.GetInstance();
resultWithSingleCandidate.ResultsBuilder.Add(methodResolutionResult);

BoundExpression result = BindInvocationExpressionContinued(
node: syntax,
expression: expression,
methodName: methodName,
result: resultWithSingleCandidate,
analyzedArguments: resolution.AnalyzedArguments,
methodGroup: resolution.MethodGroup,
delegateTypeOpt: null,
diagnostics: diagnostics,
queryClause: queryClause);
BoundExpression result = BindInvocationExpressionContinued(
node: syntax,
expression: expression,
methodName: methodName,
result: resultWithSingleCandidate,
analyzedArguments: resolution.AnalyzedArguments,
methodGroup: resolution.MethodGroup,
delegateTypeOpt: null,
diagnostics: diagnostics,
queryClause: queryClause);

resultWithSingleCandidate.Free();
resultWithSingleCandidate.Free();

return result;
return result;
}

return null;
}

private ImmutableArray<MemberResolutionResult<TMethodOrPropertySymbol>> GetCandidatesPassingFinalValidation<TMethodOrPropertySymbol>(
Expand Down

0 comments on commit af4a668

Please sign in to comment.