提交 4f19a0ae 编写于 作者: C Charles Stoner

Return after first non-convertible argument in `OverloadResolution.IsApplicable`

上级 8bdbcfb4
......@@ -1496,7 +1496,7 @@ private BoundExpression BindNonMethod(SimpleNameSyntax node, Symbol symbol, Diag
case SymbolKind.Alias:
{
var alias = symbol as AliasSymbol;
var alias = (AliasSymbol)symbol;
symbol = alias.Target;
switch (symbol.Kind)
{
......@@ -1511,7 +1511,7 @@ private BoundExpression BindNonMethod(SimpleNameSyntax node, Symbol symbol, Diag
}
case SymbolKind.RangeVariable:
return BindRangeVariable(node, symbol as RangeVariableSymbol, diagnostics);
return BindRangeVariable(node, (RangeVariableSymbol)symbol, diagnostics);
default:
throw ExceptionUtilities.UnexpectedValue(symbol.Kind);
......
......@@ -1127,12 +1127,24 @@ private static bool IsUnboundGeneric(MethodSymbol method)
return method.IsGenericMethod && method.ConstructedFrom() == method;
}
// Arbitrary limit on the number of parameter lists from overload
// resolution candidates considered when binding argument types.
// Any additional parameter lists are ignored.
internal const int MaxParameterListsForErrorRecovery = 10;
private ImmutableArray<BoundExpression> BuildArgumentsForErrorRecovery(AnalyzedArguments analyzedArguments, ImmutableArray<MethodSymbol> methods)
{
var parameterListList = ArrayBuilder<ImmutableArray<ParameterSymbol>>.GetInstance();
foreach (var m in methods)
{
if (!IsUnboundGeneric(m) && m.ParameterCount > 0) parameterListList.Add(m.Parameters);
if (!IsUnboundGeneric(m) && m.ParameterCount > 0)
{
parameterListList.Add(m.Parameters);
if (parameterListList.Count == MaxParameterListsForErrorRecovery)
{
break;
}
}
}
var result = BuildArgumentsForErrorRecovery(analyzedArguments, parameterListList);
......@@ -1143,9 +1155,16 @@ private ImmutableArray<BoundExpression> BuildArgumentsForErrorRecovery(AnalyzedA
private ImmutableArray<BoundExpression> BuildArgumentsForErrorRecovery(AnalyzedArguments analyzedArguments, ImmutableArray<PropertySymbol> properties)
{
var parameterListList = ArrayBuilder<ImmutableArray<ParameterSymbol>>.GetInstance();
foreach (var m in properties)
foreach (var p in properties)
{
if (m.ParameterCount > 0) parameterListList.Add(m.Parameters);
if (p.ParameterCount > 0)
{
parameterListList.Add(p.Parameters);
if (parameterListList.Count == MaxParameterListsForErrorRecovery)
{
break;
}
}
}
var result = BuildArgumentsForErrorRecovery(analyzedArguments, parameterListList);
......
......@@ -312,13 +312,13 @@ private static bool OverloadResolutionResultIsValid<TMember>(ArrayBuilder<Member
return;
}
var normalResult = IsConstructorApplicableInNormalForm(constructor, arguments, ref useSiteDiagnostics);
var normalResult = IsConstructorApplicableInNormalForm(constructor, arguments, completeResults, ref useSiteDiagnostics);
var result = normalResult;
if (!normalResult.IsValid)
{
if (IsValidParams(constructor))
{
var expandedResult = IsConstructorApplicableInExpandedForm(constructor, arguments, ref useSiteDiagnostics);
var expandedResult = IsConstructorApplicableInExpandedForm(constructor, arguments, completeResults, ref useSiteDiagnostics);
if (expandedResult.IsValid || completeResults)
{
result = expandedResult;
......@@ -333,7 +333,11 @@ private static bool OverloadResolutionResultIsValid<TMember>(ArrayBuilder<Member
}
}
private MemberAnalysisResult IsConstructorApplicableInNormalForm(MethodSymbol constructor, AnalyzedArguments arguments, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
private MemberAnalysisResult IsConstructorApplicableInNormalForm(
MethodSymbol constructor,
AnalyzedArguments arguments,
bool completeResults,
ref HashSet<DiagnosticInfo> useSiteDiagnostics)
{
var argumentAnalysis = AnalyzeArguments(constructor, arguments, isMethodGroupConversion: false, expanded: false); // Constructors are never involved in method group conversion.
if (!argumentAnalysis.IsValid)
......@@ -349,10 +353,23 @@ private MemberAnalysisResult IsConstructorApplicableInNormalForm(MethodSymbol co
var effectiveParameters = GetEffectiveParametersInNormalForm(constructor, arguments.Arguments.Count, argumentAnalysis.ArgsToParamsOpt, arguments.RefKinds, allowRefOmittedArguments: false);
return IsApplicable(constructor, effectiveParameters, arguments, argumentAnalysis.ArgsToParamsOpt, isVararg: constructor.IsVararg, hasAnyRefOmittedArgument: false, ignoreOpenTypes: false, useSiteDiagnostics: ref useSiteDiagnostics);
return IsApplicable(
constructor,
effectiveParameters,
arguments,
argumentAnalysis.ArgsToParamsOpt,
isVararg: constructor.IsVararg,
hasAnyRefOmittedArgument: false,
ignoreOpenTypes: false,
completeResults: completeResults,
useSiteDiagnostics: ref useSiteDiagnostics);
}
private MemberAnalysisResult IsConstructorApplicableInExpandedForm(MethodSymbol constructor, AnalyzedArguments arguments, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
private MemberAnalysisResult IsConstructorApplicableInExpandedForm(
MethodSymbol constructor,
AnalyzedArguments arguments,
bool completeResults,
ref HashSet<DiagnosticInfo> useSiteDiagnostics)
{
var argumentAnalysis = AnalyzeArguments(constructor, arguments, isMethodGroupConversion: false, expanded: true);
if (!argumentAnalysis.IsValid)
......@@ -371,7 +388,16 @@ private MemberAnalysisResult IsConstructorApplicableInExpandedForm(MethodSymbol
// A vararg ctor is never applicable in its expanded form because
// it is never a params method.
Debug.Assert(!constructor.IsVararg);
var result = IsApplicable(constructor, effectiveParameters, arguments, argumentAnalysis.ArgsToParamsOpt, isVararg: false, hasAnyRefOmittedArgument: false, ignoreOpenTypes: false, useSiteDiagnostics: ref useSiteDiagnostics);
var result = IsApplicable(
constructor,
effectiveParameters,
arguments,
argumentAnalysis.ArgsToParamsOpt,
isVararg: false,
hasAnyRefOmittedArgument: false,
ignoreOpenTypes: false,
completeResults: completeResults,
useSiteDiagnostics: ref useSiteDiagnostics);
return result.IsValid ? MemberAnalysisResult.ExpandedForm(result.ArgsToParamsOpt, result.ConversionsOpt, hasAnyRefOmittedArgument: false) : result;
}
......@@ -492,7 +518,16 @@ private MemberAnalysisResult IsConstructorApplicableInExpandedForm(MethodSymbol
// Second, we need to determine if the method is applicable in its normal form or its expanded form.
var normalResult = (allowUnexpandedForm || !IsValidParams(leastOverriddenMember))
? IsMemberApplicableInNormalForm(member, leastOverriddenMember, typeArguments, arguments, isMethodGroupConversion, allowRefOmittedArguments, inferWithDynamic, ref useSiteDiagnostics, completeResults: completeResults)
? IsMemberApplicableInNormalForm(
member,
leastOverriddenMember,
typeArguments,
arguments,
isMethodGroupConversion: isMethodGroupConversion,
allowRefOmittedArguments: allowRefOmittedArguments,
inferWithDynamic: inferWithDynamic,
completeResults: completeResults,
useSiteDiagnostics: ref useSiteDiagnostics)
: default(MemberResolutionResult<TMember>);
var result = normalResult;
......@@ -505,7 +540,14 @@ private MemberAnalysisResult IsConstructorApplicableInExpandedForm(MethodSymbol
if (!isMethodGroupConversion && IsValidParams(leastOverriddenMember))
{
var expandedResult = IsMemberApplicableInExpandedForm(member, leastOverriddenMember, typeArguments, arguments, allowRefOmittedArguments, ref useSiteDiagnostics);
var expandedResult = IsMemberApplicableInExpandedForm(
member,
leastOverriddenMember,
typeArguments,
arguments,
allowRefOmittedArguments: allowRefOmittedArguments,
completeResults: completeResults,
useSiteDiagnostics: ref useSiteDiagnostics);
if (PreferExpandedFormOverNormalForm(normalResult.Result, expandedResult.Result))
{
result = expandedResult;
......@@ -2537,7 +2579,7 @@ private RefKind GetEffectiveParameterRefKind(ParameterSymbol parameter, RefKind
return new EffectiveParameters(types.ToImmutableAndFree(), refKinds);
}
internal MemberResolutionResult<TMember> IsMemberApplicableInNormalForm<TMember>(
private MemberResolutionResult<TMember> IsMemberApplicableInNormalForm<TMember>(
TMember member, // method or property
TMember leastOverriddenMember, // method or property
ArrayBuilder<TypeSymbol> typeArguments,
......@@ -2545,8 +2587,8 @@ private RefKind GetEffectiveParameterRefKind(ParameterSymbol parameter, RefKind
bool isMethodGroupConversion,
bool allowRefOmittedArguments,
bool inferWithDynamic,
ref HashSet<DiagnosticInfo> useSiteDiagnostics,
bool completeResults = false)
bool completeResults,
ref HashSet<DiagnosticInfo> useSiteDiagnostics)
where TMember : Symbol
{
// AnalyzeArguments matches arguments to parameter names and positions.
......@@ -2601,9 +2643,11 @@ private RefKind GetEffectiveParameterRefKind(ParameterSymbol parameter, RefKind
var applicableResult = IsApplicable(
member, leastOverriddenMember,
typeArguments, arguments, originalEffectiveParameters, constructedEffectiveParameters,
argumentAnalysis.ArgsToParamsOpt, hasAnyRefOmittedArgument,
ref useSiteDiagnostics,
inferWithDynamic);
argumentAnalysis.ArgsToParamsOpt,
hasAnyRefOmittedArgument: hasAnyRefOmittedArgument,
inferWithDynamic: inferWithDynamic,
completeResults: completeResults,
useSiteDiagnostics: ref useSiteDiagnostics);
// If we were producing complete results and had missing arguments, we pushed on in order to call IsApplicable for
// type inference and lambda binding. In that case we still need to return the argument mismatch failure here.
......@@ -2621,6 +2665,7 @@ private RefKind GetEffectiveParameterRefKind(ParameterSymbol parameter, RefKind
ArrayBuilder<TypeSymbol> typeArguments,
AnalyzedArguments arguments,
bool allowRefOmittedArguments,
bool completeResults,
ref HashSet<DiagnosticInfo> useSiteDiagnostics)
where TMember : Symbol
{
......@@ -2665,7 +2710,11 @@ private RefKind GetEffectiveParameterRefKind(ParameterSymbol parameter, RefKind
var result = IsApplicable(
member, leastOverriddenMember,
typeArguments, arguments, originalEffectiveParameters, constructedEffectiveParameters,
argumentAnalysis.ArgsToParamsOpt, hasAnyRefOmittedArgument, ref useSiteDiagnostics);
argumentAnalysis.ArgsToParamsOpt,
hasAnyRefOmittedArgument: hasAnyRefOmittedArgument,
inferWithDynamic: false,
completeResults: completeResults,
useSiteDiagnostics: ref useSiteDiagnostics);
return result.Result.IsValid ?
new MemberResolutionResult<TMember>(
......@@ -2684,8 +2733,9 @@ private RefKind GetEffectiveParameterRefKind(ParameterSymbol parameter, RefKind
EffectiveParameters constructedEffectiveParameters,
ImmutableArray<int> argsToParamsMap,
bool hasAnyRefOmittedArgument,
ref HashSet<DiagnosticInfo> useSiteDiagnostics,
bool inferWithDynamic = false)
bool inferWithDynamic,
bool completeResults,
ref HashSet<DiagnosticInfo> useSiteDiagnostics)
where TMember : Symbol
{
bool ignoreOpenTypes;
......@@ -2791,10 +2841,17 @@ private RefKind GetEffectiveParameterRefKind(ParameterSymbol parameter, RefKind
ignoreOpenTypes = false;
}
return new MemberResolutionResult<TMember>(
var applicableResult = IsApplicable(
member,
leastOverriddenMember,
IsApplicable(member, effectiveParameters, arguments, argsToParamsMap, member.GetIsVararg(), hasAnyRefOmittedArgument, ignoreOpenTypes, ref useSiteDiagnostics));
effectiveParameters,
arguments,
argsToParamsMap,
isVararg: member.GetIsVararg(),
hasAnyRefOmittedArgument: hasAnyRefOmittedArgument,
ignoreOpenTypes: ignoreOpenTypes,
completeResults: completeResults,
useSiteDiagnostics: ref useSiteDiagnostics);
return new MemberResolutionResult<TMember>(member, leastOverriddenMember, applicableResult);
}
private ImmutableArray<TypeSymbol> InferMethodTypeArguments(
......@@ -2849,6 +2906,7 @@ private RefKind GetEffectiveParameterRefKind(ParameterSymbol parameter, RefKind
bool isVararg,
bool hasAnyRefOmittedArgument,
bool ignoreOpenTypes,
bool completeResults,
ref HashSet<DiagnosticInfo> useSiteDiagnostics)
{
// The effective parameters are in the right order with respect to the arguments.
......@@ -2903,8 +2961,20 @@ private RefKind GetEffectiveParameterRefKind(ParameterSymbol parameter, RefKind
RefKind parameterRefKind = parameters.ParameterRefKinds.IsDefault ? RefKind.None : parameters.ParameterRefKinds[argumentPosition];
conversion = CheckArgumentForApplicability(candidate, argument, argumentRefKind, parameters.ParameterTypes[argumentPosition], parameterRefKind, ignoreOpenTypes, ref useSiteDiagnostics);
if (!conversion.Exists ||
(arguments.IsExtensionMethodThisArgument(argumentPosition) && !Conversions.IsValidExtensionMethodThisArgConversion(conversion)))
if (arguments.IsExtensionMethodThisArgument(argumentPosition) && !Conversions.IsValidExtensionMethodThisArgConversion(conversion))
{
// Return early, without checking conversions of subsequent arguments,
// if the instance argument is not convertible to the 'this' parameter,
// even when 'completeResults' is requested. This avoids unnecessary
// lambda binding in particular, for instance, with LINQ expressions.
// Note that BuildArgumentsForErrorRecovery will still bind some number
// of overloads for the semantic model.
Debug.Assert(badArguments == null);
Debug.Assert(conversions == null);
return MemberAnalysisResult.BadArgumentConversions(argsToParameters, ImmutableArray.Create(argumentPosition), ImmutableArray.Create(conversion));
}
if (!conversion.Exists)
{
badArguments = badArguments ?? ArrayBuilder<int>.GetInstance();
badArguments.Add(argumentPosition);
......@@ -2921,6 +2991,11 @@ private RefKind GetEffectiveParameterRefKind(ParameterSymbol parameter, RefKind
conversions.AddMany(Conversion.Identity, argumentPosition);
conversions.Add(conversion);
}
if (badArguments != null && !completeResults)
{
break;
}
}
MemberAnalysisResult result;
......
......@@ -74,6 +74,7 @@
<Compile Include="FlowAnalysis\StructTests.cs" />
<Compile Include="FlowAnalysis\TryLockUsingStatementTests.cs" />
<Compile Include="Semantics\FuzzTests.cs" />
<Compile Include="Semantics\OverloadResolutionPerfTests.cs" />
<Compile Include="Semantics\PatternMatchingTests_Global.cs" />
<Compile Include="Semantics\BindingAsyncTasklikeMoreTests.cs" />
<Compile Include="Semantics\BindingAsyncTasklikeTests.cs" />
......
......@@ -3,6 +3,7 @@
using System;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
......@@ -2272,6 +2273,81 @@ static void Main(string[] args)
}
}
// See MaxParameterListsForErrorRecovery.
[Fact]
public void BuildArgumentsForErrorRecovery_ManyOverloads()
{
BuildArgumentsForErrorRecovery_ManyOverloads_Internal(Binder.MaxParameterListsForErrorRecovery - 1, tooMany: false);
BuildArgumentsForErrorRecovery_ManyOverloads_Internal(Binder.MaxParameterListsForErrorRecovery, tooMany: true);
}
private void BuildArgumentsForErrorRecovery_ManyOverloads_Internal(int n, bool tooMany)
{
var builder = new StringBuilder();
builder.AppendLine("using System;");
for (int i = 0; i < n; i++)
{
builder.AppendLine($"class C{i} {{ }}");
}
builder.Append(
@"class A { }
class B { }
class C
{
void M()
{
F(1, (t, a, b, c) => { });
var o = this[(a, b, c) => { }];
}
");
// Too few parameters.
AppendLines(builder, n, i => $" void F<T>(T t, Action<T, A, C{i}> a) {{ }}");
AppendLines(builder, n, i => $" object this[Action<A, C{i}> a] => {i}");
// Type inference failure.
AppendLines(builder, n, i => $" void F<T, U>(T t, Action<T, U, C{i}> a) where U : T {{ }}");
// Too many parameters.
AppendLines(builder, n, i => $" void F<T>(T t, Action<T, A, B, C, C{i}> a) {{ }}");
AppendLines(builder, n, i => $" object this[Action<A, B, C, C{i}> a] => {i}");
builder.AppendLine("}");
var source = builder.ToString();
var compilation = CreateCompilationWithMscorlibAndSystemCore(source);
var tree = compilation.SyntaxTrees[0];
var sm = compilation.GetSemanticModel(tree);
var lambdas = tree.GetRoot().DescendantNodes().OfType<ParenthesizedLambdaExpressionSyntax>().ToArray();
// F(1, (t, a, b, c) => { });
var lambda = lambdas[0];
var parameters = lambda.ParameterList.Parameters;
var parameter = (ParameterSymbol)sm.GetDeclaredSymbol(parameters[0]);
Assert.False(parameter.Type.IsErrorType());
Assert.Equal("System.Int32 t", parameter.ToTestDisplayString());
parameter = (ParameterSymbol)sm.GetDeclaredSymbol(parameters[1]);
Assert.False(parameter.Type.IsErrorType());
Assert.Equal("A a", parameter.ToTestDisplayString());
parameter = (ParameterSymbol)sm.GetDeclaredSymbol(parameters[3]);
Assert.Equal(tooMany, parameter.Type.IsErrorType());
Assert.Equal(tooMany ? "? c" : "C c", parameter.ToTestDisplayString());
// var o = this[(a, b, c) => { }];
lambda = lambdas[1];
parameters = lambda.ParameterList.Parameters;
parameter = (ParameterSymbol)sm.GetDeclaredSymbol(parameters[0]);
Assert.False(parameter.Type.IsErrorType());
Assert.Equal("A a", parameter.ToTestDisplayString());
parameter = (ParameterSymbol)sm.GetDeclaredSymbol(parameters[2]);
Assert.Equal(tooMany, parameter.Type.IsErrorType());
Assert.Equal(tooMany ? "? c" : "C c", parameter.ToTestDisplayString());
}
private static void AppendLines(StringBuilder builder, int n, Func<int, string> getLine)
{
for (int i = 0; i < n; i++)
{
builder.AppendLine(getLine(i));
}
}
[Fact]
[WorkItem(13797, "https://github.com/dotnet/roslyn/issues/13797")]
public void DelegateAsAction()
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using System.Linq;
using System.Text;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
// Tests that should take a long time, perhaps even exceeding
// test timeout, without shortcuts in overload resolution.
public class OverloadResolutionPerfTests : CSharpTestBase
{
[Fact]
public void StaticMethodsWithLambda()
{
const int n = 100;
var builder = new StringBuilder();
builder.AppendLine("using System;");
for (int i = 0; i < n; i++)
{
builder.AppendLine($"class C{i} {{ }}");
}
builder.AppendLine("static class S");
builder.AppendLine("{");
for (int i = 0; i < n; i++)
{
builder.AppendLine($" internal static void F(C{i} x, Action<C{i}> a) {{ F(x, y => F(y, z => F(z, w => {{ }}))); }}");
}
builder.AppendLine("}");
var source = builder.ToString();
var comp = CreateCompilationWithMscorlibAndSystemCore(source);
comp.VerifyDiagnostics();
}
[Fact]
public void ConstructorsWithLambdaAndParams()
{
const int n = 100;
var builder = new StringBuilder();
builder.AppendLine("using System;");
for (int i = 0; i < n; i++)
{
builder.AppendLine($"class C{i} {{ }}");
}
builder.AppendLine("class C");
builder.AppendLine("{");
for (int i = 0; i < n; i++)
{
builder.AppendLine($" internal static C F(C{i} x, params object[] args) => new C(x, y => F(y, args[1]), args[0]);");
builder.AppendLine($" internal C(C{i} x, Func<C{i}, C> f, params object[] args) {{ }}");
}
builder.AppendLine("}");
var source = builder.ToString();
var comp = CreateCompilationWithMscorlibAndSystemCore(source);
comp.VerifyDiagnostics();
}
[Fact]
public void ExtensionMethodsWithLambda()
{
const int n = 100;
var builder = new StringBuilder();
builder.AppendLine("using System;");
for (int i = 0; i < n; i++)
{
builder.AppendLine($"class C{i} {{ }}");
}
builder.AppendLine("static class S");
builder.AppendLine("{");
for (int i = 0; i < n; i++)
{
builder.AppendLine($" internal static void F(this C{i} x, Action<C{i}> a) {{ x.F(y => y.F(z => z.F(w => {{ }}))); }}");
}
builder.AppendLine("}");
var source = builder.ToString();
var comp = CreateCompilationWithMscorlibAndSystemCore(source);
comp.VerifyDiagnostics();
}
[Fact]
public void ExtensionMethodsWithLambdaAndParams()
{
const int n = 100;
var builder = new StringBuilder();
builder.AppendLine("using System;");
for (int i = 0; i < n; i++)
{
builder.AppendLine($"class C{i} {{ }}");
}
builder.AppendLine("static class S");
builder.AppendLine("{");
for (int i = 0; i < n; i++)
{
builder.AppendLine($" internal static void F(this C{i} x, Action<C{i}> a, params object[] args) {{ x.F(y => y.F(z => z.F(w => {{ }}), args[1]), args[0]); }}");
}
builder.AppendLine("}");
var source = builder.ToString();
var comp = CreateCompilationWithMscorlibAndSystemCore(source);
comp.VerifyDiagnostics();
}
[Fact]
public void ExtensionMethodsWithLambdaAndErrors()
{
const int n = 200;
var builder = new StringBuilder();
builder.AppendLine("using System;");
for (int i = 0; i < n; i++)
{
builder.AppendLine($"class C{i} {{ }}");
}
builder.AppendLine("static class S");
builder.AppendLine("{");
for (int i = 0; i < n; i++)
{
if (i % 2 == 0)
{
builder.AppendLine($" internal static void F(this C{i} x) {{ x.G(y => y.G(z => z.F())); }}"); // No match for x.G(...).
}
else
{
builder.AppendLine($" internal static void G(this C{i} x, Action<C{i}> a) {{ }}");
}
}
builder.AppendLine("}");
var source = builder.ToString();
var comp = CreateCompilationWithMscorlibAndSystemCore(source);
// error CS1929: 'Ci' does not contain a definition for 'G' and the best extension method overload 'S.G(C1, Action<C1>)' requires a receiver of type 'C1'
var diagnostics = Enumerable.Range(0, n / 2).
Select(i => Diagnostic(ErrorCode.ERR_BadInstanceArgType, "x").WithArguments($"C{i * 2}", "G", "S.G(C1, System.Action<C1>)", "C1")).
ToArray();
comp.VerifyDiagnostics(diagnostics);
}
}
}
......@@ -1229,10 +1229,10 @@ public void TestRefOutAnonymousDelegate()
using System.Linq.Expressions;
class p
{
static void Foo<T>(ref Func<T,T> a) { }
static void Foo<T>(ref Func<T, T> a) { }
static void Bar<T>(out Func<T, T> a) { a = null; }
static void Foo2<T>(ref Expression<Func<T,T>> a) { }
static void Foo2<T>(ref Expression<Func<T, T>> a) { }
static void Bar2<T>(out Expression<Func<T, T>> a) { a = null; }
static void Main()
......@@ -1259,7 +1259,6 @@ static void Main()
Diagnostic(ErrorCode.ERR_BadArgType, "x => x").WithArguments("1", "lambda expression", "out System.Linq.Expressions.Expression<System.Func<string, string>>").WithLocation(17, 22));
}
[Fact, WorkItem(1157097, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1157097"), WorkItem(2298, "https://github.com/dotnet/roslyn/issues/2298")]
public void TestOverloadResolutionTiebreaker()
{
......@@ -1391,8 +1390,8 @@ public static void M()
// Test6<L<string>>(null);
Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "Test6<L<string>>").WithArguments("C.L<S>", "S", "string").WithLocation(58, 9));
}
[Fact]
[Fact]
public void TestBug9583()
{
var source =
......@@ -1432,8 +1431,8 @@ static void M()
// System.Console.WriteLine(VoidReturning());
Diagnostic(ErrorCode.ERR_BadArgType, "VoidReturning()").WithArguments("1", "void", "bool").WithLocation(8, 34));
}
[Fact]
[Fact]
public void TestBug6156()
{
TestOverloadResolutionWithDiff(
......@@ -1478,10 +1477,8 @@ class Out2 : Ref2
// C# says this overrides SLOT2
}");
}
[Fact]
[Fact]
public void TestGenericMethods()
{
TestOverloadResolutionWithDiff(
......@@ -1503,9 +1500,8 @@ void M()
}
}");
}
[Fact]
[Fact]
public void TestDelegateBetterness()
{
TestOverloadResolutionWithDiff(
......@@ -1566,8 +1562,8 @@ void M()
}
");
}
[Fact]
[Fact]
public void TestTieBreakers()
{
TestOverloadResolutionWithDiff(
......@@ -1837,9 +1833,9 @@ public static void Main2()
Diagnostic(ErrorCode.ERR_BadArgCount, "Method2").WithArguments("Method2", "5"),
Diagnostic(ErrorCode.ERR_BadArgCount, "Method2").WithArguments("Method2", "5"));
}
[WorkItem(6353, "DevDiv_Projects/Roslyn")]
[Fact()]
public void TestBaseAccessForAbstractMembers()
{
// Tests:
......@@ -1892,9 +1888,9 @@ public override U Property
Diagnostic(ErrorCode.ERR_AbstractBaseCall, "base.Method(x, y)").WithArguments("Base3<U, V>.Method(U, V)"),
Diagnostic(ErrorCode.ERR_AbstractBaseCall, "base.Property").WithArguments("Base3<U, V>.Property"));
}
[WorkItem(6353, "DevDiv_Projects/Roslyn")]
[Fact()]
public void TestBaseAccessForAbstractMembers1()
{
// Tests:
......@@ -1919,9 +1915,9 @@ public override void Method(A a, B b)
CreateCompilationWithMscorlib(source).VerifyDiagnostics(
Diagnostic(ErrorCode.ERR_AbstractBaseCall, "base.Method").WithArguments("Base<A, B>.Method(A, B)"));
}
[WorkItem(6353, "DevDiv_Projects/Roslyn")]
[Fact()]
public void TestBaseAccessForAbstractMembers2()
{
var source = @"
......@@ -7480,7 +7476,6 @@ static void Main(string[] args)
);
}
[Fact]
[WorkItem(655409, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/655409")]
public void TestBug655409()
......@@ -9163,5 +9158,75 @@ private class StringValues : List<string>
Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "Assert").WithArguments("Test.Assert<T>(T, T)").WithLocation(18, 9)
);
}
/// <summary>
/// Inapplicable extension methods with bad arguments, with overloads where
/// the instance argument can be converted to 'this' before overloads where the
/// instance argument cannot be converted. Overload resolution should choose
/// a method with convertible 'this', as with the native compiler.
/// </summary>
[Fact]
public void InapplicableExtensionMethods_1()
{
string source =
@"using System;
class A { }
class B { }
class C
{
static void Main()
{
var a = new A();
a.F(o => {}, a);
}
}
static class E
{
internal static void F(this A x, Action<object> y) { }
internal static void F(this A x, Action<object> y, B z) { }
internal static void F(this B x, Action<object> y) { }
internal static void F(this B x, Action<object> y, A z) { }
}";
var comp = CreateCompilationWithMscorlibAndSystemCore(source);
comp.VerifyDiagnostics(
// (9,22): error CS1503: Argument 3: cannot convert from 'A' to 'B'
// a.F(o => {}, a);
Diagnostic(ErrorCode.ERR_BadArgType, "a").WithArguments("3", "A", "B").WithLocation(9, 22));
}
/// <summary>
/// Inapplicable extension methods with bad arguments, with overloads where
/// the instance argument can be converted to 'this' after overloads where the
/// instance argument cannot be converted. Overload resolution should choose
/// a method where non-convertible 'this', as with the native compiler.
/// </summary>
[Fact]
public void InapplicableExtensionMethods_2()
{
string source =
@"using System;
class A { }
class B { }
class C
{
static void Main()
{
var a = new A();
a.F(o => {}, a);
}
}
static class E
{
internal static void F(this B x, Action<object> y) { }
internal static void F(this B x, Action<object> y, A z) { }
internal static void F(this A x, Action<object> y) { }
internal static void F(this A x, Action<object> y, B z) { }
}";
var comp = CreateCompilationWithMscorlibAndSystemCore(source);
comp.VerifyDiagnostics(
// (9,9): error CS1929: 'A' does not contain a definition for 'F' and the best extension method overload 'E.F(B, Action<object>, A)' requires a receiver of type 'B'
// a.F(o => {}, a);
Diagnostic(ErrorCode.ERR_BadInstanceArgType, "a").WithArguments("A", "F", "E.F(B, System.Action<object>, A)", "B").WithLocation(9, 9));
}
}
}
......@@ -180,89 +180,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return constructedType
End Function
''' <summary>
''' Resolves overloaded methods or constructors or properties for SemanticModel.
''' </summary>
Friend Function ResolveOverloadedMembers(Of TMember As Symbol)(
members As ImmutableArray(Of TMember),
typeArguments As ImmutableArray(Of TypeSymbol),
arguments As ImmutableArray(Of ArgumentSyntax)) As OverloadResolutionResult(Of TMember)
If members.IsDefault Then
members = ImmutableArray(Of TMember).Empty
End If
Dim isProperties As Boolean = (GetType(TMember) Is GetType(PropertySymbol))
Dim isMethods As Boolean = (GetType(TMember) Is GetType(MethodSymbol))
If Not (isProperties OrElse isMethods) Then
Throw New ArgumentException("Must resolve overloads on PropertySymbol or MethodSymbol", NameOf(TMember))
End If
If isProperties And Not typeArguments.IsEmpty Then
Throw New ArgumentException(VBResources.PropertiesCanNotHaveTypeArguments, NameOf(typeArguments))
End If
Dim boundArguments As ImmutableArray(Of BoundExpression) = Nothing
Dim argumentNames As ImmutableArray(Of String) = Nothing
Dim argumentNamesLocations As ImmutableArray(Of Location) = Nothing
Dim diagnostics = DiagnosticBag.GetInstance()
Try
BindArgumentsAndNames(arguments, boundArguments, argumentNames, argumentNamesLocations, diagnostics)
Dim boundMemberGroup As BoundMethodOrPropertyGroup
If isMethods Then
boundMemberGroup = New BoundMethodGroup(VisualBasicSyntaxTree.Dummy.GetRoot(Nothing),
If(typeArguments.IsEmpty,
Nothing,
New BoundTypeArguments(VisualBasicSyntaxTree.Dummy.GetRoot(Nothing), typeArguments)),
ImmutableArray.Create(Of MethodSymbol)(DirectCast(DirectCast(members.ToArray(), Symbol()), MethodSymbol())),
LookupResultKind.Good, Nothing, QualificationKind.Unqualified)
Else
boundMemberGroup = New BoundPropertyGroup(VisualBasicSyntaxTree.Dummy.GetRoot(Nothing),
ImmutableArray.Create(Of PropertySymbol)(DirectCast(DirectCast(members.ToArray(), Symbol()), PropertySymbol())),
LookupResultKind.Good, Nothing, QualificationKind.Unqualified)
End If
' do resolve overloads
Dim internalResult As OverloadResolution.OverloadResolutionResult =
OverloadResolution.MethodOrPropertyInvocationOverloadResolution(
boundMemberGroup, boundArguments, argumentNames, Me, includeEliminatedCandidates:=True, callerInfoOpt:=Nothing,
useSiteDiagnostics:=Nothing)
' process the result
Dim succeeded As Boolean = internalResult.BestResult.HasValue
Dim results(internalResult.Candidates.Length - 1) As MemberResolutionResult(Of TMember)
Dim validResult As MemberResolutionResult(Of TMember) ? = Nothing
Dim bestResult As MemberResolutionResult(Of TMember) ? = Nothing
For i As Integer = 0 To internalResult.Candidates.Length - 1 Step 1
If succeeded AndAlso internalResult.Candidates(i).State = VisualBasic.OverloadResolution.CandidateAnalysisResultState.Applicable Then
validResult = New MemberResolutionResult(Of TMember)(internalResult.Candidates(i), True)
bestResult = validResult
results(i) = validResult.Value
Else
results(i) = New MemberResolutionResult(Of TMember)(internalResult.Candidates(i), False)
End If
Next
If Not bestResult.HasValue Then
Dim bestCandidates = ArrayBuilder(Of OverloadResolution.CandidateAnalysisResult).GetInstance()
GetSetOfTheBestCandidates(internalResult, bestCandidates, ImmutableArray(Of Symbol).Empty)
If bestCandidates.Count = 1 Then
bestResult = New MemberResolutionResult(Of TMember)(bestCandidates(0), False)
End If
bestCandidates.Free()
End If
Return New OverloadResolutionResult(Of TMember)(results.AsImmutableOrNull(), validResult, bestResult)
Finally
diagnostics.Free()
End Try
End Function
Friend Shared Function ReportUseSiteError(diagBag As DiagnosticBag, syntax As SyntaxNodeOrToken, symbol As Symbol) As Boolean
Dim useSiteErrorInfo As DiagnosticInfo = symbol.GetUseSiteErrorInfo()
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册