Skip to content

Commit 97be510

Browse files
committed
Overload resolution was ignoring HasTypeArgumentInferredFromFunctionType for calls in expanded form
1 parent 78a8a4a commit 97be510

File tree

3 files changed

+80
-28
lines changed

3 files changed

+80
-28
lines changed

src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MemberResolutionResult.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,19 @@ namespace Microsoft.CodeAnalysis.CSharp
2222
/// </summary>
2323
internal readonly bool HasTypeArgumentInferredFromFunctionType;
2424

25-
internal MemberResolutionResult(TMember member, TMember leastOverriddenMember, MemberAnalysisResult result, bool hasTypeArgumentInferredFromFunctionType = false)
25+
internal MemberResolutionResult(TMember member, TMember leastOverriddenMember, MemberAnalysisResult result, bool hasTypeArgumentInferredFromFunctionType)
2626
{
2727
_member = member;
2828
_leastOverriddenMember = leastOverriddenMember;
2929
_result = result;
3030
HasTypeArgumentInferredFromFunctionType = hasTypeArgumentInferredFromFunctionType;
3131
}
3232

33+
internal MemberResolutionResult<TMember> WithResult(MemberAnalysisResult result)
34+
{
35+
return new MemberResolutionResult<TMember>(Member, LeastOverriddenMember, result, HasTypeArgumentInferredFromFunctionType);
36+
}
37+
3338
internal bool IsNull
3439
{
3540
get { return (object)_member == null; }
@@ -92,12 +97,12 @@ public bool IsApplicable
9297

9398
internal MemberResolutionResult<TMember> Worse()
9499
{
95-
return new MemberResolutionResult<TMember>(Member, LeastOverriddenMember, MemberAnalysisResult.Worse());
100+
return WithResult(MemberAnalysisResult.Worse());
96101
}
97102

98103
internal MemberResolutionResult<TMember> Worst()
99104
{
100-
return new MemberResolutionResult<TMember>(Member, LeastOverriddenMember, MemberAnalysisResult.Worst());
105+
return WithResult(MemberAnalysisResult.Worst());
101106
}
102107

103108
internal bool HasUseSiteDiagnosticToReport

src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ private static void RemoveStaticInstanceMismatches<TMember>(ArrayBuilder<MemberR
385385
TMember member = result.Member;
386386
if (result.Result.IsValid && member.RequiresInstanceReceiver() == requireStatic)
387387
{
388-
results[f] = new MemberResolutionResult<TMember>(member, result.LeastOverriddenMember, MemberAnalysisResult.StaticInstanceMismatch());
388+
results[f] = result.WithResult(MemberAnalysisResult.StaticInstanceMismatch());
389389
}
390390
}
391391
}
@@ -401,7 +401,7 @@ private static void RemoveMethodsNotDeclaredStatic<TMember>(ArrayBuilder<MemberR
401401
TMember member = result.Member;
402402
if (result.Result.IsValid && !member.IsStatic)
403403
{
404-
results[f] = new MemberResolutionResult<TMember>(member, result.LeastOverriddenMember, MemberAnalysisResult.StaticInstanceMismatch());
404+
results[f] = result.WithResult(MemberAnalysisResult.StaticInstanceMismatch());
405405
}
406406
}
407407
}
@@ -426,8 +426,7 @@ private void RemoveConstraintViolations<TMember>(ArrayBuilder<MemberResolutionRe
426426
if ((result.Result.IsValid || result.Result.Kind == MemberResolutionKind.ConstructedParameterFailedConstraintCheck) &&
427427
FailsConstraintChecks(member, out ArrayBuilder<TypeParameterDiagnosticInfo> constraintFailureDiagnosticsOpt, template))
428428
{
429-
results[f] = new MemberResolutionResult<TMember>(
430-
result.Member, result.LeastOverriddenMember,
429+
results[f] = result.WithResult(
431430
MemberAnalysisResult.ConstraintFailure(constraintFailureDiagnosticsOpt.ToImmutableAndFree()));
432431
}
433432
}
@@ -559,7 +558,7 @@ private void RemoveCallingConventionMismatches<TMember>(ArrayBuilder<MemberResol
559558
}
560559

561560
static MemberResolutionResult<TMember> makeWrongCallingConvention(MemberResolutionResult<TMember> result)
562-
=> new MemberResolutionResult<TMember>(result.Member, result.LeastOverriddenMember, MemberAnalysisResult.WrongCallingConvention());
561+
=> result.WithResult(MemberAnalysisResult.WrongCallingConvention());
563562
}
564563
#nullable disable
565564

@@ -649,13 +648,11 @@ private void RemoveDelegateConversionsWithWrongReturnType<TMember>(
649648

650649
if (!returnsMatch)
651650
{
652-
results[f] = new MemberResolutionResult<TMember>(
653-
result.Member, result.LeastOverriddenMember, MemberAnalysisResult.WrongReturnType());
651+
results[f] = result.WithResult(MemberAnalysisResult.WrongReturnType());
654652
}
655653
else if (method.RefKind != returnRefKind)
656654
{
657-
results[f] = new MemberResolutionResult<TMember>(
658-
result.Member, result.LeastOverriddenMember, MemberAnalysisResult.WrongRefKind());
655+
results[f] = result.WithResult(MemberAnalysisResult.WrongRefKind());
659656
}
660657
}
661658
}
@@ -699,7 +696,7 @@ private void AddConstructorToCandidateSet(MethodSymbol constructor, ArrayBuilder
699696
Debug.Assert(!MemberAnalysisResult.UnsupportedMetadata().HasUseSiteDiagnosticToReportFor(constructor));
700697
if (completeResults)
701698
{
702-
results.Add(new MemberResolutionResult<MethodSymbol>(constructor, constructor, MemberAnalysisResult.UnsupportedMetadata()));
699+
results.Add(new MemberResolutionResult<MethodSymbol>(constructor, constructor, MemberAnalysisResult.UnsupportedMetadata(), hasTypeArgumentInferredFromFunctionType: false));
703700
}
704701
return;
705702
}
@@ -721,7 +718,7 @@ private void AddConstructorToCandidateSet(MethodSymbol constructor, ArrayBuilder
721718
// If the constructor has a use site diagnostic, we don't want to discard it because we'll have to report the diagnostic later.
722719
if (result.IsValid || completeResults || result.HasUseSiteDiagnosticToReportFor(constructor))
723720
{
724-
results.Add(new MemberResolutionResult<MethodSymbol>(constructor, constructor, result));
721+
results.Add(new MemberResolutionResult<MethodSymbol>(constructor, constructor, result, hasTypeArgumentInferredFromFunctionType: false));
725722
}
726723
}
727724

@@ -905,7 +902,7 @@ private void AddMemberToCandidateSet<TMember>(
905902
Debug.Assert(!MemberAnalysisResult.UnsupportedMetadata().HasUseSiteDiagnosticToReportFor(member));
906903
if (completeResults)
907904
{
908-
results.Add(new MemberResolutionResult<TMember>(member, leastOverriddenMember, MemberAnalysisResult.UnsupportedMetadata()));
905+
results.Add(new MemberResolutionResult<TMember>(member, leastOverriddenMember, MemberAnalysisResult.UnsupportedMetadata(), hasTypeArgumentInferredFromFunctionType: false));
909906
}
910907
return;
911908
}
@@ -1141,7 +1138,7 @@ private void RemoveInaccessibleTypeArguments<TMember>(ArrayBuilder<MemberResolut
11411138
var result = results[f];
11421139
if (result.Result.IsValid && !TypeArgumentsAccessible(result.Member.GetMemberTypeArgumentsNoUseSiteDiagnostics(), ref useSiteInfo))
11431140
{
1144-
results[f] = new MemberResolutionResult<TMember>(result.Member, result.LeastOverriddenMember, MemberAnalysisResult.InaccessibleTypeArgument());
1141+
results[f] = result.WithResult(MemberAnalysisResult.InaccessibleTypeArgument());
11451142
}
11461143
}
11471144
}
@@ -1272,7 +1269,7 @@ private static void RemoveLessDerivedMembers<TMember>(ArrayBuilder<MemberResolut
12721269

12731270
if (IsLessDerivedThanAny(result.LeastOverriddenMember.ContainingType, results, ref useSiteInfo))
12741271
{
1275-
results[f] = new MemberResolutionResult<TMember>(result.Member, result.LeastOverriddenMember, MemberAnalysisResult.LessDerived());
1272+
results[f] = result.WithResult(MemberAnalysisResult.LessDerived());
12761273
}
12771274
}
12781275
}
@@ -1383,7 +1380,7 @@ private static void RemoveAllInterfaceMembers<TMember>(ArrayBuilder<MemberResolu
13831380
var member = result.Member;
13841381
if (member.ContainingType.IsInterfaceType())
13851382
{
1386-
results[f] = new MemberResolutionResult<TMember>(member, result.LeastOverriddenMember, MemberAnalysisResult.LessDerived());
1383+
results[f] = result.WithResult(MemberAnalysisResult.LessDerived());
13871384
}
13881385
}
13891386
}
@@ -3284,15 +3281,15 @@ private MemberResolutionResult<TMember> IsMemberApplicableInNormalForm<TMember>(
32843281
// thus improving the API and intellisense experience.
32853282
break;
32863283
default:
3287-
return new MemberResolutionResult<TMember>(member, leastOverriddenMember, MemberAnalysisResult.ArgumentParameterMismatch(argumentAnalysis));
3284+
return new MemberResolutionResult<TMember>(member, leastOverriddenMember, MemberAnalysisResult.ArgumentParameterMismatch(argumentAnalysis), hasTypeArgumentInferredFromFunctionType: false);
32883285
}
32893286
}
32903287

32913288
// Check after argument analysis, but before more complicated type inference and argument type validation.
32923289
// NOTE: The diagnostic may not be reported (e.g. if the member is later removed as less-derived).
32933290
if (member.HasUseSiteError)
32943291
{
3295-
return new MemberResolutionResult<TMember>(member, leastOverriddenMember, MemberAnalysisResult.UseSiteError());
3292+
return new MemberResolutionResult<TMember>(member, leastOverriddenMember, MemberAnalysisResult.UseSiteError(), hasTypeArgumentInferredFromFunctionType: false);
32963293
}
32973294

32983295
bool hasAnyRefOmittedArgument;
@@ -3334,7 +3331,7 @@ private MemberResolutionResult<TMember> IsMemberApplicableInNormalForm<TMember>(
33343331
// type inference and lambda binding. In that case we still need to return the argument mismatch failure here.
33353332
if (completeResults && !argumentAnalysis.IsValid)
33363333
{
3337-
return new MemberResolutionResult<TMember>(member, leastOverriddenMember, MemberAnalysisResult.ArgumentParameterMismatch(argumentAnalysis));
3334+
return new MemberResolutionResult<TMember>(member, leastOverriddenMember, MemberAnalysisResult.ArgumentParameterMismatch(argumentAnalysis), hasTypeArgumentInferredFromFunctionType: false);
33383335
}
33393336

33403337
return applicableResult;
@@ -3355,14 +3352,14 @@ private MemberResolutionResult<TMember> IsMemberApplicableInExpandedForm<TMember
33553352
var argumentAnalysis = AnalyzeArguments(member, arguments, isMethodGroupConversion: false, expanded: true);
33563353
if (!argumentAnalysis.IsValid)
33573354
{
3358-
return new MemberResolutionResult<TMember>(member, leastOverriddenMember, MemberAnalysisResult.ArgumentParameterMismatch(argumentAnalysis));
3355+
return new MemberResolutionResult<TMember>(member, leastOverriddenMember, MemberAnalysisResult.ArgumentParameterMismatch(argumentAnalysis), hasTypeArgumentInferredFromFunctionType: false);
33593356
}
33603357

33613358
// Check after argument analysis, but before more complicated type inference and argument type validation.
33623359
// NOTE: The diagnostic may not be reported (e.g. if the member is later removed as less-derived).
33633360
if (member.HasUseSiteError)
33643361
{
3365-
return new MemberResolutionResult<TMember>(member, leastOverriddenMember, MemberAnalysisResult.UseSiteError());
3362+
return new MemberResolutionResult<TMember>(member, leastOverriddenMember, MemberAnalysisResult.UseSiteError(), hasTypeArgumentInferredFromFunctionType: false);
33663363
}
33673364

33683365
bool hasAnyRefOmittedArgument;
@@ -3401,9 +3398,7 @@ private MemberResolutionResult<TMember> IsMemberApplicableInExpandedForm<TMember
34013398
useSiteInfo: ref useSiteInfo);
34023399

34033400
return result.Result.IsValid ?
3404-
new MemberResolutionResult<TMember>(
3405-
result.Member,
3406-
result.LeastOverriddenMember,
3401+
result.WithResult(
34073402
MemberAnalysisResult.ExpandedForm(result.Result.ArgsToParamsOpt, result.Result.ConversionsOpt, hasAnyRefOmittedArgument)) :
34083403
result;
34093404
}
@@ -3465,7 +3460,7 @@ private MemberResolutionResult<TMember> IsApplicable<TMember>(
34653460
ref useSiteInfo);
34663461
if (typeArguments.IsDefault)
34673462
{
3468-
return new MemberResolutionResult<TMember>(member, leastOverriddenMember, inferenceError);
3463+
return new MemberResolutionResult<TMember>(member, leastOverriddenMember, inferenceError, hasTypeArgumentInferredFromFunctionType: false);
34693464
}
34703465
}
34713466

@@ -3505,7 +3500,7 @@ private MemberResolutionResult<TMember> IsApplicable<TMember>(
35053500
{
35063501
if (!parameterTypes[i].Type.CheckAllConstraints(Compilation, Conversions))
35073502
{
3508-
return new MemberResolutionResult<TMember>(member, leastOverriddenMember, MemberAnalysisResult.ConstructedParameterFailedConstraintsCheck(i));
3503+
return new MemberResolutionResult<TMember>(member, leastOverriddenMember, MemberAnalysisResult.ConstructedParameterFailedConstraintsCheck(i), hasTypeArgumentsInferredFromFunctionType);
35093504
}
35103505
}
35113506

src/Compilers/CSharp/Test/Semantic/Semantics/DelegateTypeTests.cs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4371,6 +4371,58 @@ static void Main()
43714371
CompileAndVerify(source, expectedOutput: expectedOutput);
43724372
}
43734373

4374+
[WorkItem(57627, "https://github.com/dotnet/roslyn/issues/57627")]
4375+
[Fact]
4376+
public void OverloadResolution_48()
4377+
{
4378+
var source =
4379+
@"using System;
4380+
using System.Threading.Tasks;
4381+
4382+
delegate void MyAction();
4383+
delegate T MyFunc<T>();
4384+
4385+
class A
4386+
{
4387+
public static void F(object o) { Console.WriteLine(""F(object o)""); }
4388+
public static void F(object o, string format, params object[] args) { Console.WriteLine(""F(object o, string format, params object[] args)""); }
4389+
4390+
public static void F<T>(T t) { Console.WriteLine(""F<T>(T t)""); }
4391+
public static void F<T>(T t, string format, params object[] args) { Console.WriteLine(""F<T>(T t, string format, params object[] args)""); }
4392+
4393+
public static void F(MyAction a) { Console.WriteLine(""F(MyAction a)""); }
4394+
public static void F(MyAction a, string format, params object[] args) { Console.WriteLine(""F(MyAction a, string format, params object[] args)""); }
4395+
4396+
public static void F<T>(MyFunc<T> f) { Console.WriteLine(""F<T>(MyFunc<T> f)""); }
4397+
public static void F<T>(MyFunc<T> f, string format, params object[] args) { Console.WriteLine(""F<T>(MyFunc<T> f, string format, params object[] args)""); }
4398+
}
4399+
4400+
class B
4401+
{
4402+
static async Task Main()
4403+
{
4404+
A.F(() => { });
4405+
A.F(() => { }, """");
4406+
A.F(() => { }, ""{0}"", 1);
4407+
A.F(async () => await Task.FromResult<object>(null));
4408+
A.F(async () => await Task.FromResult<object>(null), """");
4409+
A.F(async () => await Task.FromResult<object>(null), ""{0}"", 1);
4410+
}
4411+
}";
4412+
4413+
string expectedOutput =
4414+
@"F(MyAction a)
4415+
F(MyAction a, string format, params object[] args)
4416+
F(MyAction a, string format, params object[] args)
4417+
F<T>(MyFunc<T> f)
4418+
F<T>(MyFunc<T> f, string format, params object[] args)
4419+
F<T>(MyFunc<T> f, string format, params object[] args)
4420+
";
4421+
CompileAndVerify(source, parseOptions: TestOptions.Regular9, expectedOutput: expectedOutput);
4422+
CompileAndVerify(source, parseOptions: TestOptions.Regular10, expectedOutput: expectedOutput);
4423+
CompileAndVerify(source, expectedOutput: expectedOutput);
4424+
}
4425+
43744426
[Fact]
43754427
public void BestCommonType_01()
43764428
{

0 commit comments

Comments
 (0)