|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable disable
using System;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
public class OverloadResolutionTests : OverloadResolutionTestBase
{
[Fact]
public void TestBug12439()
{
// The spec has an omission; I believe we intended it to say that there is no
// conversion from any old-style anonymous method expression to any expression tree
// type. This is the rule the native compiler enforces; Roslyn should as well, and
// we should clarify the specification.
string source =
@"
using System;
using System.Linq.Expressions;
class Program
{
static void Main()
{
Goo(delegate { }); // No error; chooses the non-expression version.
}
static void Goo(Action a) { }
static void Goo(Expression<Action> a) { }
}";
var comp = CreateCompilationWithMscorlib40AndSystemCore(source);
comp.VerifyDiagnostics();
}
[Fact]
public void TestBug11961()
{
// This test verifies a deliberate spec violation that we have implemented
// to ensure backwards compatibility.
//
// When doing overload resolution, we must find the best applicable method.
//
// When tiebreaking between two applicable candidate methods, we examine each conversion from the
// argument to the corresponding parameter type to determine which method is better *in that parameter*.
// If a method is *not worse* in every parameter and better in at least one, then that method
// wins. Under what circumstances is one conversion better than another?
//
// * A conversion from the argument to a more specific parameter type is better than a conversion to a less
// specific parameter type. If we have M(null) and candidates M(string) and M(object) then the conversion to
// string is better because string is more specific.
//
// * If the argument is a lambda and the parameter types are delegate types, then the conversion to the
// delegate type with the more specific return type wins. If we have M(()=>null) and we are choosing between
// M(ObjectReturningDelegate) and M(StringReturningDelegate), the latter wins.
//
// In C# 3, these rules were never in conflict because no delegate type was ever more or less specific
// than another. But in C# 4 we added delegate covariance and contravariance, and now there are delegate
// types that are more specific than others. We did not correctly update the C# 4 compiler to handle this
// situation.
//
// Unfortunately, real-world code exists that depends on this bad behavior, so we are going to preserve it.
//
// The essence of the bug is: the correct behavior is to do the first tiebreaker first, and the second tiebreaker
// if necessary. The native compiler, and now Roslyn, does this wrong. It says "is the argument a lambda?" If so,
// then it applies the second tiebreaker and ignores the first. Otherwise, it applies the first tiebreaker and
// ignores the second.
//
// Let's take a look at some examples of where it does and does not make a difference:
//
// On the first call, the native compiler and Roslyn agree that overload 2 is better. (Remember, Action<T> is
// contravariant, so Action<object> is more specific than Action<string>. Every action that takes an object
// is also an action that takes a string, so an action that takes an object is more specific.) This is the correct
// behavior. The compiler uses the first tiebreaker.
// On the second call, the native compiler incorrectly believes that overload 3 is better, because it
// does not correctly determine that Action<object> is more specific than Action<string> when the argument is
// a lambda. The correct behavior according to the spec would be to produce an ambiguity error. (Why?
// because overload 3 is more specific in its first parameter type, and less specific in its second parameter type.
// And vice-versa for overload 4. No overload is not-worse in all parameters.)
string source1 = @"
using System;
class P
{
static void M(Action<string> a) { Console.Write(1); }
static void M(Action<object> a) { Console.Write(2); }
static void M(string x, Action<string> a) { Console.Write(3); }
static void M(object x, Action<object> a) { Console.Write(4); }
static void M1(string x, Func<object> a) { Console.Write(5); }
static void M1(object x, Func<ValueType> a) { Console.Write(6); }
static void M2(Func<object> a, string x) { Console.Write(7); }
static void M2(Func<ValueType> a, object x) { Console.Write(8); }
static void M3(Func<object> a, Action<object> b, string x) { Console.Write(9); }
static void M3(Func<ValueType> a, Action<string> b, object x) { Console.Write('A'); }
static void M5(Action<object> b, string x, Func<object> a) { Console.Write('D'); }
static void M5(Action<string> b, object x, Func<ValueType> a) { Console.Write('E'); }
static void Main()
{
M(null);
M((string)null, q=>{});
M(q=>{});
M1((string)null, ()=>{ throw new NotImplementedException();});
M2(()=>{ throw new NotImplementedException();}, (string)null);
M3(()=>{ throw new NotImplementedException();}, q=> {}, (string)null);
M5(q=> {}, (string)null, ()=>{ throw new NotImplementedException();});
}
}";
CompileAndVerify(source1, expectedOutput: @"232579D");
// Now let's look at some ambiguity errors:
//
// On the first call, the native compiler incorrectly produces an ambiguity error. The correct behavior according
// to the specification is to choose overload 2, because it is more specific. Because the argument is a lambda
// we incorrectly skip the first tiebreaker entirely and go straight to the second tiebreaker. We are now in a situation
// where we have two delegate types that are both void returning, and so by the second tiebreaker, neither is better.
// On the second call, the native compiler correctly produces an ambiguity error. Overload 3 is better that the
// overload 4 in its first parameter and worse in its second parameter, and similarly for overload 4. Since
// neither overload is not-worse in all parameters, neither is the best choice.
string source2 = @"
using System;
class P
{
static void M(Action<string> a) { }
static void M(Action<object> a) { }
static void M(string x, Action<string> a) { }
static void M(object x, Action<object> a) { }
static void M1(string x, Func<object> a) { Console.Write(5); }
static void M1(object x, Func<ValueType> a) { Console.Write(6); }
static void M4(Func<object> a, Action<object> b, Action<string> x) { Console.Write('B'); }
static void M4(Func<ValueType> a, Action<string> b, Action<object> x) { Console.Write('C'); }
static void M6(Action<object> b, string x, object a) { Console.Write('F'); }
static void M6(Action<string> b, object x, string a) { Console.Write('G'); }
static void Main()
{
M((string)null, null);
M1((string)null, ()=>{ return 5;});
M4(()=>{ throw new NotImplementedException();}, q=> {}, q=> {});
M6(q=> {},(string)null, (string)null);
}
}";
CreateCompilation(source2).VerifyDiagnostics(
// (18,5): error CS0121: The call is ambiguous between the following methods or properties: 'P.M(string, System.Action<string>)' and 'P.M(object, System.Action<object>)'
// M((string)null, null);
Diagnostic(ErrorCode.ERR_AmbigCall, "M").WithArguments("P.M(string, System.Action<string>)", "P.M(object, System.Action<object>)"),
// (19,5): error CS0121: The call is ambiguous between the following methods or properties: 'P.M1(string, System.Func<object>)' and 'P.M1(object, System.Func<System.ValueType>)'
// M1((string)null, ()=>{ return 5;});
Diagnostic(ErrorCode.ERR_AmbigCall, "M1").WithArguments("P.M1(string, System.Func<object>)", "P.M1(object, System.Func<System.ValueType>)"),
// (20,5): error CS0121: The call is ambiguous between the following methods or properties: 'P.M4(System.Func<object>, System.Action<object>, System.Action<string>)' and 'P.M4(System.Func<System.ValueType>, System.Action<string>, System.Action<object>)'
// M4(()=>{ throw new NotImplementedException();}, q=> {}, q=> {});
Diagnostic(ErrorCode.ERR_AmbigCall, "M4").WithArguments("P.M4(System.Func<object>, System.Action<object>, System.Action<string>)", "P.M4(System.Func<System.ValueType>, System.Action<string>, System.Action<object>)"),
// (21,5): error CS0121: The call is ambiguous between the following methods or properties: 'P.M6(System.Action<object>, string, object)' and 'P.M6(System.Action<string>, object, string)'
// M6(q=> {},(string)null, (string)null);
Diagnostic(ErrorCode.ERR_AmbigCall, "M6").WithArguments("P.M6(System.Action<object>, string, object)", "P.M6(System.Action<string>, object, string)")
);
// By comparing these two programs, it becomes clear how unfortunate this is. M(q=>null) is ambiguous,
// M(null) is unambiguous. But M((string)null, q=>{}) is unambiguous, M((string)null, null) is ambiguous!
string source3 = @"
using System;
using System.Collections.Generic;
class SyntaxNode {}
class ExpressionSyntax : SyntaxNode {}
class IdentifierNameSyntax : ExpressionSyntax {}
class SyntaxAnnotation {}
static class P
{
public static TRoot ReplaceNodes1<TRoot>(this TRoot root, IEnumerable<SyntaxNode> nodes, Func<SyntaxNode, SyntaxNode, SyntaxNode> computeReplacementNode)
where TRoot : SyntaxNode
{
Console.Write('A');
return null;
}
public static TRoot ReplaceNodes1<TRoot, TNode>(this TRoot root, IEnumerable<TNode> nodes, Func<TNode, TNode, SyntaxNode> computeReplacementNode)
where TRoot : SyntaxNode
where TNode : SyntaxNode
{
Console.Write('B');
return null;
}
public static TNode WithAdditionalAnnotations<TNode>(this TNode node, params SyntaxAnnotation[] annotations)
where TNode : SyntaxNode
{
return null;
}
public static TRoot ReplaceNodes2<TRoot, TNode>(this TRoot root, IEnumerable<TNode> nodes, Func<TNode, TNode, SyntaxNode> computeReplacementNode)
where TRoot : SyntaxNode
where TNode : SyntaxNode
{
Console.Write('B');
return null;
}
public static TRoot ReplaceNodes2<TRoot>(this TRoot root, IEnumerable<SyntaxNode> nodes, Func<SyntaxNode, SyntaxNode, SyntaxNode> computeReplacementNode)
where TRoot : SyntaxNode
{
Console.Write('A');
return null;
}
static void Main()
{
ExpressionSyntax expr = null;
var identifierNodes = new List<IdentifierNameSyntax>();
var myAnnotation = new SyntaxAnnotation();
expr.ReplaceNodes1(identifierNodes, (e, e2) => e2.WithAdditionalAnnotations(myAnnotation));
expr.ReplaceNodes2(identifierNodes, (e, e2) => e2.WithAdditionalAnnotations(myAnnotation));
}
}";
CompileAndVerify(source3, expectedOutput: @"BB");
}
[Fact]
public void DeviationFromSpec()
{
string source1 = @"
using System;
class P
{
static void M1(int a) { Console.Write(1); }
static void M1(uint? a) { Console.Write(2); }
static void M2(int? a) { Console.Write(3); }
static void M2(uint a) { Console.Write(4); }
static void Main()
{
int i = 0;
int? ni = 0;
uint u = 0;
uint? nu = 0;
short s = 0;
short? ns = 0;
ushort us = 0;
ushort? nus = 0;
M1(null);
M1(i);
Console.Write("" "");//M1(ni);
M1(u);
M1(nu);
M1(s);
Console.Write("" "");//M1(ns);
M1(us);
M1(nus);
M2(null);
M2(i);
M2(ni);
M2(u);
Console.Write("" "");//M2(nu);
M2(s);
M2(ns);
M2(us);
M2(nus);
}
}";
CompileAndVerify(source1, expectedOutput: @"21 221 123334 3333");
string source2 = @"
using System;
class P
{
static void M1(int a) { Console.Write(1); }
static void M1(uint? a) { Console.Write(2); }
static void M2(int? a) { Console.Write(3); }
static void M2(uint a) { Console.Write(4); }
static void Main()
{
int? ni = 0;
uint? nu = 0;
short? ns = 0;
//ushort us = 0;
M1(ni);
M1(ns);
M2(nu);
}
}";
CreateCompilation(source2).VerifyDiagnostics(
// (16,8): error CS1503: Argument 1: cannot convert from 'int?' to 'int'
// M1(ni);
Diagnostic(ErrorCode.ERR_BadArgType, "ni").WithArguments("1", "int?", "int"),
// (17,8): error CS1503: Argument 1: cannot convert from 'short?' to 'int'
// M1(ns);
Diagnostic(ErrorCode.ERR_BadArgType, "ns").WithArguments("1", "short?", "int"),
// (19,8): error CS1503: Argument 1: cannot convert from 'uint?' to 'int?'
// M2(nu);
Diagnostic(ErrorCode.ERR_BadArgType, "nu").WithArguments("1", "uint?", "int?")
);
}
[Fact]
public void ParametersExactlyMatchExpression()
{
string source2 = @"
using System;
class P
{
delegate int DA();
delegate int DB();
static void M1(DA a) { Console.Write(1); }
static void M1(DB a) { Console.Write(2); }
static void Main()
{
int x = 1;
M1(() => x);
}
}";
CreateCompilation(source2).VerifyDiagnostics(
// (14,5): error CS0121: The call is ambiguous between the following methods or properties: 'P.M1(P.DA)' and 'P.M1(P.DB)'
// M1(() => x);
Diagnostic(ErrorCode.ERR_AmbigCall, "M1").WithArguments("P.M1(P.DA)", "P.M1(P.DB)")
);
}
[Fact]
public void ExactlyMatchingNestedLambda()
{
string source1 = @"
using System;
class P
{
delegate Func<int> DA();
delegate Func<object> DB();
static void M1(DA a) { Console.Write(1); }
static void M1(DB a) { Console.Write(2); }
static void Main()
{
int i = 0;
M1(() => () => i);
}
}";
CompileAndVerify(source1, expectedOutput: @"1");
string source2 = @"
using System;
class P
{
delegate Func<int> DA();
delegate Func<object> DB();
static void M1(DA a, object b) { Console.Write(1); }
static void M1(DB a, int b) { Console.Write(2); }
static void Main()
{
int i = 0;
M1(() => () => i, i);
}
}";
CompileAndVerify(source2, parseOptions: TestOptions.Regular9, expectedOutput: @"2");
var comp = CreateCompilation(source2);
comp.VerifyDiagnostics(
// (15,5): error CS0121: The call is ambiguous between the following methods or properties: 'P.M1(P.DA, object)' and 'P.M1(P.DB, int)'
// M1(() => () => i, i);
Diagnostic(ErrorCode.ERR_AmbigCall, "M1").WithArguments("P.M1(P.DA, object)", "P.M1(P.DB, int)").WithLocation(15, 5));
}
[Fact]
public void ParametersImplicitlyConvertibleToEachOther()
{
string source1 = @"
using System;
class CA
{
public static implicit operator CA(int x)
{
return null;
}
public static implicit operator CA(CB x)
{
return null;
}
}
class CB
{
public static implicit operator CB(int x)
{
return null;
}
public static implicit operator CB(CA x)
{
return null;
}
}
class P
{
static void M1(CA a) { Console.Write(1); }
static void M1(CB a) { Console.Write(2); }
static void Main()
{
int i = 0;
M1(i);
}
}";
CreateCompilation(source1).VerifyDiagnostics(
// (36,5): error CS0121: The call is ambiguous between the following methods or properties: 'P.M1(CA)' and 'P.M1(CB)'
// M1(i);
Diagnostic(ErrorCode.ERR_AmbigCall, "M1").WithArguments("P.M1(CA)", "P.M1(CB)")
);
}
[Fact]
public void BetterTaskType()
{
string source1 = @"
using System;
using System.Threading.Tasks;
class P
{
static void M1(Task<int> a) { Console.Write(1); }
static void M1(Task<uint> a) { Console.Write(2); }
static void Main()
{
M1(null);
}
}";
CompileAndVerify(source1, expectedOutput: @"1");
string source2 = @"
using System;
using System.Threading.Tasks;
class P
{
static void M1(Task<int> a, uint b) { Console.Write(1); }
static void M1(Task<uint> a, int b) { Console.Write(2); }
static void Main()
{
M1(null,0);
}
}";
CreateCompilation(source2).VerifyDiagnostics(
// (11,5): error CS0121: The call is ambiguous between the following methods or properties: 'P.M1(System.Threading.Tasks.Task<int>, uint)' and 'P.M1(System.Threading.Tasks.Task<uint>, int)'
// M1(null,0);
Diagnostic(ErrorCode.ERR_AmbigCall, "M1").WithArguments("P.M1(System.Threading.Tasks.Task<int>, uint)", "P.M1(System.Threading.Tasks.Task<uint>, int)")
);
}
[Fact]
public void BetterTasklikeType()
{
string source1 = @"
using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
class C
{
static void Main()
{
h(async () => { await (Task)null; return 1; });
}
static void h<T>(Func<Task<T>> lambda) { }
static void h<T>(Func<MyTask<T>> lambda) { }
}
[AsyncMethodBuilder(typeof(MyTaskBuilder<>))]
public class MyTask<T> { }
public class MyTaskBuilder<T>
{
public static MyTaskBuilder<T> Create() => null;
public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { }
public void SetStateMachine(IAsyncStateMachine stateMachine) { }
public void SetResult(T result) { }
public void SetException(Exception exception) { }
public MyTask<T> Task => default(MyTask<T>);
public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine { }
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine { }
}
namespace System.Runtime.CompilerServices { class AsyncMethodBuilderAttribute : System.Attribute { public AsyncMethodBuilderAttribute(System.Type t) { } } }
";
CreateCompilationWithMscorlib45(source1).VerifyDiagnostics(
// (9,9): error CS0121: The call is ambiguous between the following methods or properties: 'C.h<T>(Func<Task<T>>)' and 'C.h<T>(Func<MyTask<T>>)'
// h(async () => { await (Task)null; return 1; });
Diagnostic(ErrorCode.ERR_AmbigCall, "h").WithArguments("C.h<T>(System.Func<System.Threading.Tasks.Task<T>>)", "C.h<T>(System.Func<MyTask<T>>)").WithLocation(9, 9)
);
string source2 = @"
using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
class C
{
static void Main()
{
k(async () => { await (Task)null; return 1; });
}
static void k<T>(Func<YourTask<T>> lambda) { }
static void k<T>(Func<MyTask<T>> lambda) { }
}
[AsyncMethodBuilder(typeof(MyTaskBuilder<>))]
public class MyTask<T> { }
public class MyTaskBuilder<T>
{
public static MyTaskBuilder<T> Create() => null;
public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { }
public void SetStateMachine(IAsyncStateMachine stateMachine) { }
public void SetResult(T result) { }
public void SetException(Exception exception) { }
public MyTask<T> Task => default(MyTask<T>);
public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine { }
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine { }
}
[AsyncMethodBuilder(typeof(YourTask<>))]
public class YourTask<T> { }
public class YourTaskBuilder<T>
{
public static YourTaskBuilder<T> Create() => null;
public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { }
public void SetStateMachine(IAsyncStateMachine stateMachine) { }
public void SetResult(T result) { }
public void SetException(Exception exception) { }
public YourTask<T> Task => default(YourTask<T>);
public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine { }
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine { }
}
namespace System.Runtime.CompilerServices { class AsyncMethodBuilderAttribute : System.Attribute { public AsyncMethodBuilderAttribute(System.Type t) { } } }
";
CreateCompilationWithMscorlib45(source2).VerifyDiagnostics(
// (9,9): error CS0121: The call is ambiguous between the following methods or properties: 'C.k<T>(Func<YourTask<T>>)' and 'C.k<T>(Func<MyTask<T>>)'
// k(async () => { await (Task)null; return 1; });
Diagnostic(ErrorCode.ERR_AmbigCall, "k").WithArguments("C.k<T>(System.Func<YourTask<T>>)", "C.k<T>(System.Func<MyTask<T>>)").WithLocation(9, 9)
);
}
[Fact]
public void NormalizeTaskTypes()
{
string source =
@"
using System.Runtime.CompilerServices;
class A<T>
{
internal struct B<U> { }
}
unsafe class C<T, U>
{
#pragma warning disable CS0169
static MyTask F0;
static MyTask<T> F1;
static C<MyTask, MyTask[]>[,] F2;
static A<MyTask<MyTask>>.B<C<int, MyTask>> F3;
static int* F4;
#pragma warning restore CS0169
}
[AsyncMethodBuilder(typeof(MyTaskMethodBuilder))]
struct MyTask { }
[AsyncMethodBuilder(typeof(MyTaskMethodBuilder<>))]
struct MyTask<T> { }
struct MyTaskMethodBuilder
{
public static MyTaskMethodBuilder Create() => new MyTaskMethodBuilder();
}
struct MyTaskMethodBuilder<T>
{
public static MyTaskMethodBuilder<T> Create() => new MyTaskMethodBuilder<T>();
}
namespace System.Runtime.CompilerServices { class AsyncMethodBuilderAttribute : System.Attribute { public AsyncMethodBuilderAttribute(System.Type t) { } } }
";
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.UnsafeDebugDll);
compilation.VerifyDiagnostics();
var type = compilation.GetMember<FieldSymbol>("C.F0").Type;
var normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("MyTask", type.ToTestDisplayString());
Assert.Equal("System.Threading.Tasks.Task", normalized.ToTestDisplayString());
type = compilation.GetMember<FieldSymbol>("C.F1").Type;
normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("MyTask<T>", type.ToTestDisplayString());
Assert.Equal("System.Threading.Tasks.Task<T>", normalized.ToTestDisplayString());
type = compilation.GetMember<FieldSymbol>("C.F2").Type;
normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("C<MyTask, MyTask[]>[,]", type.ToTestDisplayString());
Assert.Equal("C<System.Threading.Tasks.Task, System.Threading.Tasks.Task[]>[,]", normalized.ToTestDisplayString());
type = compilation.GetMember<FieldSymbol>("C.F3").Type;
normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("A<MyTask<MyTask>>.B<C<System.Int32, MyTask>>", type.ToTestDisplayString());
Assert.Equal("A<System.Threading.Tasks.Task<System.Threading.Tasks.Task>>.B<C<System.Int32, System.Threading.Tasks.Task>>", normalized.ToTestDisplayString());
type = compilation.GetMember<FieldSymbol>("C.F4").Type;
normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("System.Int32*", type.ToTestDisplayString());
Assert.Equal("System.Int32*", normalized.ToTestDisplayString());
}
[Fact]
public void NormalizeTaskTypes_Tuples()
{
string source =
@"using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
class C<T, U>
{
#pragma warning disable CS0169
static MyTask<ValueTuple<MyTask, T>> F0;
static ((MyTask a, T b) c, MyTask<(U, MyTask<T>)[]> d) F1;
static Task<(Task, object)[]> F2;
static (MyTask, char, byte, short, ushort, int, uint, long, ulong, char, byte, short, ushort, int, uint, long, MyTask<T>) F3;
#pragma warning restore CS0169
}
[AsyncMethodBuilder(typeof(MyTaskMethodBuilder))]
struct MyTask { }
[AsyncMethodBuilder(typeof(MyTaskMethodBuilder<>))]
struct MyTask<T> { }
struct MyTaskMethodBuilder
{
public static MyTaskMethodBuilder Create() => new MyTaskMethodBuilder();
}
struct MyTaskMethodBuilder<T>
{
public static MyTaskMethodBuilder<T> Create() => new MyTaskMethodBuilder<T>();
}
namespace System
{
struct ValueTuple<T1, T2>
{
}
struct ValueTuple<T1, T2, T3>
{
}
struct ValueTuple<T1, T2, T3, T4, T5, T6, T7, T8>
{
}
}
namespace System.Runtime.CompilerServices
{
class TupleElementNamesAttribute : Attribute
{
public TupleElementNamesAttribute(string[] names) { }
}
}
namespace System.Runtime.CompilerServices { class AsyncMethodBuilderAttribute : System.Attribute { public AsyncMethodBuilderAttribute(System.Type t) { } } }
";
var compilation = CreateCompilationWithMscorlib45(source, assemblyName: "comp");
compilation.VerifyDiagnostics(
// (10,12): error CS8128: Member 'Rest' was not found on type 'ValueTuple<T1, T2, T3, T4, T5, T6, T7, T8>' from assembly comp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
// static (MyTask, char, byte, short, ushort, int, uint, long, ulong, char, byte, short, ushort, int, uint, long, MyTask<T>) F3;
Diagnostic(ErrorCode.ERR_PredefinedTypeMemberNotFoundInAssembly, "(MyTask, char, byte, short, ushort, int, uint, long, ulong, char, byte, short, ushort, int, uint, long, MyTask<T>)").WithArguments("Rest", "System.ValueTuple<T1, T2, T3, T4, T5, T6, T7, T8>", "comp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(10, 12));
var type = compilation.GetMember<FieldSymbol>("C.F0").Type;
var normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("MyTask<(MyTask, T)>", type.ToTestDisplayString());
Assert.Equal("System.Threading.Tasks.Task<(System.Threading.Tasks.Task, T)>", normalized.ToTestDisplayString());
type = compilation.GetMember<FieldSymbol>("C.F1").Type;
normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("((MyTask a, T b) c, MyTask<(U, MyTask<T>)[]> d)", type.ToTestDisplayString());
Assert.Equal("((System.Threading.Tasks.Task a, T b) c, System.Threading.Tasks.Task<(U, System.Threading.Tasks.Task<T>)[]> d)", normalized.ToTestDisplayString());
// No changes.
type = compilation.GetMember<FieldSymbol>("C.F2").Type;
normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("System.Threading.Tasks.Task<(System.Threading.Tasks.Task, System.Object)[]>", type.ToTestDisplayString());
Assert.Same(type, normalized);
// Nested System.ValueTuple<>.
type = compilation.GetMember<FieldSymbol>("C.F3").Type;
normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("(MyTask, System.Char, System.Byte, System.Int16, System.UInt16, System.Int32, System.UInt32, System.Int64, System.UInt64, System.Char, System.Byte, System.Int16, System.UInt16, System.Int32, System.UInt32, System.Int64, MyTask<T>)", type.ToTestDisplayString());
Assert.Equal("(System.Threading.Tasks.Task, System.Char, System.Byte, System.Int16, System.UInt16, System.Int32, System.UInt32, System.Int64, System.UInt64, System.Char, System.Byte, System.Int16, System.UInt16, System.Int32, System.UInt32, System.Int64, System.Threading.Tasks.Task<T>)", normalized.ToTestDisplayString());
Assert.Equal("(System.UInt32, System.Int64, MyTask<T>)", GetUnderlyingTupleTypeRest(type).ToTestDisplayString());
Assert.Equal("(System.UInt32, System.Int64, System.Threading.Tasks.Task<T>)", GetUnderlyingTupleTypeRest(normalized).ToTestDisplayString());
}
// Return the underlying type of the most-nested part of the TupleTypeSymbol.
private static NamedTypeSymbol GetUnderlyingTupleTypeRest(TypeSymbol type)
{
while (type.IsTupleType)
{
var typeArgs = ((NamedTypeSymbol)type).TypeArguments();
if (typeArgs.Length < 8)
{
return (NamedTypeSymbol)type;
}
type = typeArgs[7];
}
return null;
}
// Preserve type argument custom modifiers.
[WorkItem(592, "https://github.com/dotnet/roslyn/issues/12615")]
[Fact]
public void NormalizeTaskTypes_TypeArgumentCustomModifiers()
{
var ilSource =
@".class public C
{
.field public static class MyTask`1<class MyTask modopt(class MyTask`1<object>)> F0
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public MyTask
{
.custom instance void System.Runtime.CompilerServices.AsyncMethodBuilderAttribute::.ctor(class [mscorlib]System.Type) = { type(MyTaskMethodBuilder) }
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public MyTask`1<T>
{
.custom instance void System.Runtime.CompilerServices.AsyncMethodBuilderAttribute::.ctor(class [mscorlib]System.Type) = { type(MyTaskMethodBuilder`1) }
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public MyTaskMethodBuilder
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public MyTaskMethodBuilder`1<T>
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.namespace System.Runtime.CompilerServices
{
.class public AsyncMethodBuilderAttribute extends [mscorlib]System.Attribute
{
.method public hidebysig specialname rtspecialname instance void .ctor(class [mscorlib]System.Type t) cil managed { ret }
}
}
";
var source =
@"";
var reference = CompileIL(ilSource);
var compilation = CreateCompilationWithMscorlib45(source, references: new[] { reference });
compilation.VerifyDiagnostics();
var type = compilation.GetMember<FieldSymbol>("C.F0").Type;
var normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("MyTask<MyTask modopt(MyTask<System.Object>)>", type.ToTestDisplayString());
Assert.Equal("System.Threading.Tasks.Task<System.Threading.Tasks.Task modopt(MyTask<System.Object>)>", normalized.ToTestDisplayString());
}
[Fact]
public void NormalizeTaskTypes_Pointers()
{
string source =
@"
using System.Runtime.CompilerServices;
unsafe class C<T>
{
#pragma warning disable CS0169
static C<MyTask<int>>* F0;
#pragma warning restore CS0169
}
[AsyncMethodBuilder(typeof(MyTaskMethodBuilder<>))]
struct MyTask<T> { }
struct MyTaskMethodBuilder<T>
{
public static MyTaskMethodBuilder<T> Create() => new MyTaskMethodBuilder<T>();
}
namespace System.Runtime.CompilerServices { class AsyncMethodBuilderAttribute : System.Attribute { public AsyncMethodBuilderAttribute(System.Type t) { } } }
";
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.UnsafeDebugDll);
compilation.VerifyDiagnostics(
// (6,28): warning CS8500: This takes the address of, gets the size of, or declares a pointer to a managed type ('C<MyTask<int>>')
// static C<MyTask<int>>* F0;
Diagnostic(ErrorCode.WRN_ManagedAddr, "F0").WithArguments("C<MyTask<int>>").WithLocation(6, 28));
var type = compilation.GetMember<FieldSymbol>("C.F0").Type;
var normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("C<MyTask<System.Int32>>*", type.ToTestDisplayString());
Assert.Equal("C<System.Threading.Tasks.Task<System.Int32>>*", normalized.ToTestDisplayString());
}
[Fact]
public void NormalizeTaskTypes_PointersCustomModifiers()
{
var ilSource =
@".class public C
{
.field public static class MyTask modopt(class MyTask) *[] F0
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public MyTask
{
.custom instance void System.Runtime.CompilerServices.AsyncMethodBuilderAttribute::.ctor(class [mscorlib]System.Type) = { type(MyTaskMethodBuilder) }
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public MyTaskMethodBuilder
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.namespace System.Runtime.CompilerServices
{
.class public AsyncMethodBuilderAttribute extends [mscorlib]System.Attribute
{
.method public hidebysig specialname rtspecialname instance void .ctor(class [mscorlib]System.Type t) cil managed { ret }
}
}
";
var source =
@"";
var reference = CompileIL(ilSource);
var compilation = CreateCompilationWithMscorlib45(source, references: new[] { reference });
compilation.VerifyDiagnostics();
var type = compilation.GetMember<FieldSymbol>("C.F0").Type;
var normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("MyTask modopt(MyTask) *[]", type.ToTestDisplayString());
Assert.Equal("System.Threading.Tasks.Task modopt(MyTask) *[]", normalized.ToTestDisplayString());
}
[Fact]
public void NormalizeTaskTypes_FunctionPointers()
{
string source =
@"
using System.Runtime.CompilerServices;
unsafe class C<T>
{
#pragma warning disable CS0169
static delegate*<int, int, C<MyTask<int>>> F0;
static delegate*<C<MyTask<int>>, int, int> F1;
static delegate*<int, C<MyTask<int>>, int> F2;
static delegate*<int, int, int> F3;
#pragma warning restore CS0169
}
[AsyncMethodBuilder(typeof(MyTaskMethodBuilder<>))]
struct MyTask<T> { }
struct MyTaskMethodBuilder<T>
{
public static MyTaskMethodBuilder<T> Create() => new MyTaskMethodBuilder<T>();
}
namespace System.Runtime.CompilerServices { class AsyncMethodBuilderAttribute : System.Attribute { public AsyncMethodBuilderAttribute(System.Type t) { } } }
";
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.UnsafeDebugDll, parseOptions: TestOptions.Regular9);
compilation.VerifyDiagnostics();
assert("F0", "delegate*<System.Int32, System.Int32, C<MyTask<System.Int32>>>", "delegate*<System.Int32, System.Int32, C<System.Threading.Tasks.Task<System.Int32>>>");
assert("F1", "delegate*<C<MyTask<System.Int32>>, System.Int32, System.Int32>", "delegate*<C<System.Threading.Tasks.Task<System.Int32>>, System.Int32, System.Int32>");
assert("F2", "delegate*<System.Int32, C<MyTask<System.Int32>>, System.Int32>", "delegate*<System.Int32, C<System.Threading.Tasks.Task<System.Int32>>, System.Int32>");
assert("F3", "delegate*<System.Int32, System.Int32, System.Int32>", normalized: null);
void assert(string fieldName, string original, string normalized)
{
var type = compilation.GetMember<FieldSymbol>($"C.{fieldName}").Type;
FunctionPointerUtilities.CommonVerifyFunctionPointer((FunctionPointerTypeSymbol)type);
var normalizedType = type.NormalizeTaskTypes(compilation);
Assert.Equal(original, type.ToTestDisplayString());
if (normalized is object)
{
Assert.Equal(normalized, normalizedType.ToTestDisplayString());
}
else
{
Assert.Same(type, normalizedType);
}
}
}
[Fact]
public void NormalizeTaskTypes_FunctionPointersCustomModifiers()
{
var ilSource =
@".class public C
{
.field public static method class MyTask modopt(class MyTask) *(class MyTask modopt(class MyTask)) F0
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public MyTask
{
.custom instance void System.Runtime.CompilerServices.AsyncMethodBuilderAttribute::.ctor(class [mscorlib]System.Type) = { type(MyTaskMethodBuilder) }
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public MyTaskMethodBuilder
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.namespace System.Runtime.CompilerServices
{
.class public AsyncMethodBuilderAttribute extends [mscorlib]System.Attribute
{
.method public hidebysig specialname rtspecialname instance void .ctor(class [mscorlib]System.Type t) cil managed { ret }
}
}
";
var source =
@"";
var reference = CompileIL(ilSource);
var compilation = CreateCompilationWithMscorlib45(source, references: new[] { reference });
compilation.VerifyDiagnostics();
var type = compilation.GetMember<FieldSymbol>("C.F0").Type;
var normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("delegate*<MyTask modopt(MyTask), MyTask modopt(MyTask)>", type.ToTestDisplayString());
Assert.Equal("delegate*<System.Threading.Tasks.Task modopt(MyTask), System.Threading.Tasks.Task modopt(MyTask)>", normalized.ToTestDisplayString());
}
[Fact]
public void NormalizeTaskTypes_Errors()
{
string source =
@"
using System.Runtime.CompilerServices;
class C
{
#pragma warning disable CS0169
static A<int, MyTask> F0;
static MyTask<B> F1;
#pragma warning restore CS0169
}
[AsyncMethodBuilder(typeof(MyTaskMethodBuilder))]
struct MyTask { }
[AsyncMethodBuilder(typeof(MyTaskMethodBuilder<>))]
struct MyTask<T> { }
struct MyTaskMethodBuilder
{
public static MyTaskMethodBuilder Create() => new MyTaskMethodBuilder();
}
struct MyTaskMethodBuilder<T>
{
public static MyTaskMethodBuilder<T> Create() => new MyTaskMethodBuilder<T>();
}
namespace System.Runtime.CompilerServices { class AsyncMethodBuilderAttribute : System.Attribute { public AsyncMethodBuilderAttribute(System.Type t) { } } }
";
var compilation = CreateCompilationWithMscorlib45(source);
compilation.VerifyDiagnostics(
// (5,19): error CS0246: The type or namespace name 'B' could not be found (are you missing a using directive or an assembly reference?)
// static MyTask<B> F1;
Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "B").WithArguments("B").WithLocation(7, 19),
// (4,12): error CS0246: The type or namespace name 'A<,>' could not be found (are you missing a using directive or an assembly reference?)
// static A<int, MyTask> F0;
Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "A<int, MyTask>").WithArguments("A<,>").WithLocation(6, 12));
var type = compilation.GetMember<FieldSymbol>("C.F0").Type;
Assert.Equal(TypeKind.Error, type.TypeKind);
var normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("A<System.Int32, MyTask>", type.ToTestDisplayString());
Assert.Equal("A<System.Int32, System.Threading.Tasks.Task>", normalized.ToTestDisplayString());
type = compilation.GetMember<FieldSymbol>("C.F1").Type;
Assert.Equal(TypeKind.Error, ((NamedTypeSymbol)type).TypeArguments()[0].TypeKind);
normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("MyTask<B>", type.ToTestDisplayString());
Assert.Equal("System.Threading.Tasks.Task<B>", normalized.ToTestDisplayString());
}
[Fact]
public void NormalizeTaskTypes_Inner()
{
string source =
@"
using System.Runtime.CompilerServices;
class C<T, U>
{
#pragma warning disable CS0169
static MyTask<U> F0;
static C<U, MyTask>.MyTask F1;
static C<T, MyTask<U>>.Inner F2;
#pragma warning restore CS0169
class Inner
{
}
[AsyncMethodBuilder(typeof(C<,>.MyTaskMethodBuilder))]
class MyTask { }
[AsyncMethodBuilder(typeof(C<,>.MyTaskMethodBuilder<>))]
class MyTask<V> { }
class MyTaskMethodBuilder
{
public static MyTaskMethodBuilder Create() => null;
}
class MyTaskMethodBuilder<V>
{
public static MyTaskMethodBuilder<V> Create() => null;
}
}
namespace System.Runtime.CompilerServices { class AsyncMethodBuilderAttribute : System.Attribute { public AsyncMethodBuilderAttribute(System.Type t) { } } }
";
var compilation = CreateCompilationWithMscorlib45(source);
compilation.VerifyDiagnostics();
var type = compilation.GetMember<FieldSymbol>("C.F0").Type;
var normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("C<T, U>.MyTask<U>", type.ToTestDisplayString());
Assert.Equal("System.Threading.Tasks.Task<U>", normalized.ToTestDisplayString());
type = compilation.GetMember<FieldSymbol>("C.F1").Type;
normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("C<U, C<T, U>.MyTask>.MyTask", type.ToTestDisplayString());
Assert.Equal("System.Threading.Tasks.Task", normalized.ToTestDisplayString());
type = compilation.GetMember<FieldSymbol>("C.F2").Type;
normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("C<T, C<T, U>.MyTask<U>>.Inner", type.ToTestDisplayString());
Assert.Equal("C<T, System.Threading.Tasks.Task<U>>.Inner", normalized.ToTestDisplayString());
}
[Fact]
public void NormalizeTaskTypes_Outer()
{
string source =
@"
using System.Runtime.CompilerServices;
class C
{
#pragma warning disable CS0169
static MyTask<MyTask.A> F0;
static MyTask<MyTask<object>>.B F1;
#pragma warning restore CS0169
}
[AsyncMethodBuilder(typeof(MyTaskMethodBuilder))]
class MyTask
{
internal class A { }
}
[AsyncMethodBuilder(typeof(MyTaskMethodBuilder<>))]
class MyTask<V>
{
internal class B { }
}
class MyTaskMethodBuilder
{
public static MyTaskMethodBuilder Create() => null;
}
class MyTaskMethodBuilder<V>
{
public static MyTaskMethodBuilder<V> Create() => null;
}
namespace System.Runtime.CompilerServices { class AsyncMethodBuilderAttribute : System.Attribute { public AsyncMethodBuilderAttribute(System.Type t) { } } }
";
var compilation = CreateCompilationWithMscorlib45(source);
compilation.VerifyDiagnostics();
var type = compilation.GetMember<FieldSymbol>("C.F0").Type;
var normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("MyTask<MyTask.A>", type.ToTestDisplayString());
Assert.Equal("System.Threading.Tasks.Task<MyTask.A>", normalized.ToTestDisplayString());
type = compilation.GetMember<FieldSymbol>("C.F1").Type;
normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("MyTask<MyTask<System.Object>>.B", type.ToTestDisplayString());
Assert.Equal("MyTask<System.Threading.Tasks.Task<System.Object>>.B", normalized.ToTestDisplayString());
}
/// <summary>
/// Normalize should have no effect if System.Threading.Tasks.Task
/// and System.Threading.Tasks.Task<T> are not available.
/// </summary>
[Fact]
public void NormalizeTaskTypes_MissingWellKnownTypes()
{
string source =
@"
using System.Runtime.CompilerServices;
class C
{
#pragma warning disable CS0169
static MyTask<MyTask> F;
#pragma warning restore CS0169
}
[AsyncMethodBuilder(typeof(MyTaskMethodBuilder))]
struct MyTask { }
[AsyncMethodBuilder(typeof(MyTaskMethodBuilder<>))]
struct MyTask<T> { }
struct MyTaskMethodBuilder
{
public static MyTaskMethodBuilder Create() => new MyTaskMethodBuilder();
}
struct MyTaskMethodBuilder<T>
{
public MyTaskMethodBuilder<T> Create() => new MyTaskMethodBuilder<T>();
}
namespace System.Runtime.CompilerServices { class AsyncMethodBuilderAttribute : System.Attribute { public AsyncMethodBuilderAttribute(System.Type t) { } } }
";
var compilation = CreateEmptyCompilation(source, references: new[] { MscorlibRef_v20 });
compilation.VerifyDiagnostics();
var type = compilation.GetMember<FieldSymbol>("C.F").Type;
var normalized = type.NormalizeTaskTypes(compilation);
Assert.Equal("MyTask<MyTask>", type.ToTestDisplayString());
Assert.Equal("MyTask<MyTask>", normalized.ToTestDisplayString());
}
[Fact]
public void BetterDelegateType_01()
{
string source1 = @"
using System;
class P
{
static void M1(Func<int> a) { Console.Write(1); }
static void M1(Func<uint> a) { Console.Write(2); }
static void M2(Func<int> a) { Console.Write(3); }
static void M2(Action a) { Console.Write(4); }
static void Main()
{
M1(null);
M2(null);
}
}";
CompileAndVerify(source1, expectedOutput: @"13");
string source2 = @"
using System;
class P
{
static void M1(Func<int> a, uint b) { Console.Write(1); }
static void M1(Func<uint> a, int b) { Console.Write(2); }
static void M2(Func<int> a, uint b) { Console.Write(3); }
static void M2(Action a, int b) { Console.Write(4); }
static void Main()
{
M1(null,0);
M2(null,0);
}
}";
CreateCompilation(source2).VerifyDiagnostics(
// (13,5): error CS0121: The call is ambiguous between the following methods or properties: 'P.M1(System.Func<int>, uint)' and 'P.M1(System.Func<uint>, int)'
// M1(null,0);
Diagnostic(ErrorCode.ERR_AmbigCall, "M1").WithArguments("P.M1(System.Func<int>, uint)", "P.M1(System.Func<uint>, int)"),
// (14,5): error CS0121: The call is ambiguous between the following methods or properties: 'P.M2(System.Func<int>, uint)' and 'P.M2(System.Action, int)'
// M2(null,0);
Diagnostic(ErrorCode.ERR_AmbigCall, "M2").WithArguments("P.M2(System.Func<int>, uint)", "P.M2(System.Action, int)")
);
}
[Fact, WorkItem(6560, "https://github.com/dotnet/roslyn/issues/6560")]
public void BetterDelegateType_02()
{
string source1 = @"
using System;
class C
{
public static void Main()
{
Run1(() => MethodReturnsVoid());
Run1(MethodReturnsVoid);
Run2(() => MethodReturnsVoid());
Run2(MethodReturnsVoid);
}
public static object Run1(Action action)
{
Console.WriteLine(""Run1(Action action)"");
action();
return null;
}
public static object Run1(Func<object> action, bool optional = false)
{
Console.WriteLine(""Run1(Func<object> action, bool optional = false)"");
return action();
}
public static object Run2(Func<object> action, bool optional = false)
{
Console.WriteLine(""Run2(Func<object> action, bool optional = false)"");
return action();
}
public static object Run2(Action action)
{
Console.WriteLine(""Run2(Action action)"");
action();
return null;
}
private static void MethodReturnsVoid()
{
}
}
";
CompileAndVerify(source1, expectedOutput:
@"Run1(Action action)
Run1(Action action)
Run2(Action action)
Run2(Action action)");
}
[Fact]
public void TestBug9851()
{
// We should ensure that we do not report "no method M takes n parameters" if in fact
// there is any method M that could take n parameters.
var source =
@"
class C
{
static void J<T>(T t1, T t2) {}
static void J(int x) {}
public static void M()
{
J(123.0, 456.0m);
}
}";
CreateCompilation(source).VerifyDiagnostics(
// (8,9): error CS0411: The type arguments for method 'C.J<T>(T, T)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
// J(123.0, 456.0m);
Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "J").WithArguments("C.J<T>(T, T)").WithLocation(8, 9));
}
[Fact]
public void TestLambdaErrorReporting()
{
var source =
@"
using System;
class C
{
static void J(Action<int> action) {}
static void J(Action<string> action) {}
static void K(Action<decimal> action) {}
static void K(Action<double> action) {}
static void K(Action<string> action) {}
public static void M()
{
// If there are multiple possible bindings for a lambda and both of them produce
// 'the same' errors then we should report those errors to the exclusion of any
// errors produced on only some of the bindings.
//
// For instance, here the binding of x as int produces two errors:
// * int does not have ToStrign
// * int does not have Length
// the binding of x as string produces two errors:
// * string does not have ToStrign
// * cannot multiply strings
// We should only report the common error.
J(x=>{ Console.WriteLine(x.ToStrign(), x.Length, x * 2); });
// If there is no common error then we should report both errors:
J(y=>{ Console.WriteLine(y == string.Empty, y / 4.5); });
// If there is an error that is in common to two of three bindings,
// then we should report it but only report it once.
// For instance, here the binding of x as decimal produces:
// * no decimal == string
// * no decimal - double
// The binding as double produces:
// * no double == string
// The binding as string produces:
// * no string - double
//
// There is no error common to all three bindings. However, of the
// four errors we should only report two of them.
K(z=>{ Console.WriteLine(z == string.Empty, z - 4.5); });
}
}";
CreateCompilation(source).VerifyDiagnostics(
// (26,36): error CS1061: 'string' does not contain a definition for 'ToStrign' and no extension method 'ToStrign' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
// J(x=>{ Console.WriteLine(x.ToStrign(), x.Length, x * 2); });
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "ToStrign").WithArguments("string", "ToStrign").WithLocation(26, 36),
// (30,34): error CS0019: Operator '==' cannot be applied to operands of type 'int' and 'string'
// J(y=>{ Console.WriteLine(y == string.Empty, y / 4.5); });
Diagnostic(ErrorCode.ERR_BadBinaryOps, "y == string.Empty").WithArguments("==", "int", "string").WithLocation(30, 34),
// (30,53): error CS0019: Operator '/' cannot be applied to operands of type 'string' and 'double'
// J(y=>{ Console.WriteLine(y == string.Empty, y / 4.5); });
Diagnostic(ErrorCode.ERR_BadBinaryOps, "y / 4.5").WithArguments("/", "string", "double").WithLocation(30, 53),
// (45,53): error CS0019: Operator '-' cannot be applied to operands of type 'string' and 'double'
// K(z=>{ Console.WriteLine(z == string.Empty, z - 4.5); });
Diagnostic(ErrorCode.ERR_BadBinaryOps, "z - 4.5").WithArguments("-", "string", "double").WithLocation(45, 53),
// (45,34): error CS0019: Operator '==' cannot be applied to operands of type 'double' and 'string'
// K(z=>{ Console.WriteLine(z == string.Empty, z - 4.5); });
Diagnostic(ErrorCode.ERR_BadBinaryOps, "z == string.Empty").WithArguments("==", "double", "string").WithLocation(45, 34));
}
[Fact]
public void TestRefOutAnonymousDelegate()
{
string source = @"
using System;
using System.Linq.Expressions;
class @p
{
static void Goo<T>(ref Func<T, T> a) { }
static void Bar<T>(out Func<T, T> a) { a = null; }
static void Goo2<T>(ref Expression<Func<T, T>> a) { }
static void Bar2<T>(out Expression<Func<T, T>> a) { a = null; }
static void Main()
{
Goo<string>(x => x);
Bar<string>(x => x);
Goo2<string>(x => x);
Bar2<string>(x => x);
}
}";
CreateCompilationWithMscorlib40AndSystemCore(source).VerifyDiagnostics(
// (14,21): error CS1503: Argument 1: cannot convert from 'lambda expression' to 'ref Func<string, string>'
// Goo<string>(x => x);
Diagnostic(ErrorCode.ERR_BadArgType, "x => x").WithArguments("1", "lambda expression", "ref System.Func<string, string>").WithLocation(14, 21),
// (15,21): error CS1503: Argument 1: cannot convert from 'lambda expression' to 'out Func<string, string>'
// Bar<string>(x => x);
Diagnostic(ErrorCode.ERR_BadArgType, "x => x").WithArguments("1", "lambda expression", "out System.Func<string, string>").WithLocation(15, 21),
// (16,22): error CS1503: Argument 1: cannot convert from 'lambda expression' to 'ref Expression<Func<string, string>>'
// Goo2<string>(x => x);
Diagnostic(ErrorCode.ERR_BadArgType, "x => x").WithArguments("1", "lambda expression", "ref System.Linq.Expressions.Expression<System.Func<string, string>>").WithLocation(16, 22),
// (17,22): error CS1503: Argument 1: cannot convert from 'lambda expression' to 'out Expression<Func<string, string>>'
// Bar2<string>(x => x);
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()
{
// Testing that we get the same ambiguity error as the one reported by the native compiler.
string source = @"
class C
{
static void X(params string[] s) {}
static void X<T>(T t){}
static void X(string s, object o = null) {}
public void M()
{
X((string)null); //-C.X(string, object)
}
}";
var compilation = CreateCompilation(source, options: TestOptions.DebugDll);
compilation.VerifyDiagnostics(
// (9,9): error CS0121: The call is ambiguous between the following methods or properties: 'C.X(params string[])' and 'C.X<T>(T)'
// X((string)null); //-C.X(string, object)
Diagnostic(ErrorCode.ERR_AmbigCall, "X").WithArguments("C.X(params string[])", "C.X<T>(T)").WithLocation(9, 9)
);
}
[Fact]
public void TestConstraintViolationApplicabilityErrors()
{
// The rules for constraint satisfaction during overload resolution are a bit odd. If a constraint
// *on a parameter type* is not met then the candidate is not applicable. But if a constraint
// is violated *on the method type parameter itself* then the method can be chosen as the best
// applicable candidate, and then rejected during "final validation".
//
// Furthermore: most of the time a constraint violation on a formal type parameter will also
// be a constraint violation on the method type parameter. The latter seems like the better
// error to report. We only report the violation on the parameter if the constraint
// is not violated on the method type parameter.
var source =
@"
class C
{
static string MakeString() { return null; }
struct L<S> where S : struct {}
class N<T> where T : struct {}
public static void M()
{
string s = MakeString();
// We violate the constraint on both T and U.
// The method is not applicable.
// Overload resolution fails and reports the violation on U,
// even though technically it was the violation on U that caused
// the method to be inapplicable.
Test1<string>(s, null);
// Type inference successfully infers that V is string;
// we now should do exactly the same as the previous case.
Test2(s, null);
// In the previous two tests it is not clear whether the compiler is
// allowing overload resolution to succeed and then final validation
// fails, or if the candidate set really is empty. We must verify
// that the generic version is actually an inapplicable candidate.
//
// Even though its arguments under construction are better,
// the generic version is inapplicable because the constraint
// on T is violated. Therefore there is no error; the object
// version wins:
Test3(s, null);
// By contrast, here overload resolution infers that X<string> is the
// best possible match, and then final validation fails:
Test4(s);
// When a method is inapplicable because of a constraint violation we
// prefer to state the violation on the method type parameter constraint.
// In an error recovery scenario we might not be able to do that.
// Here there are two errors: first, the declaration of Test5 is bad because
// Y does not meet the constraint on T. Second, the method call is bad
// because string does not meet the constraint on T. We cannot say that
// string does not meet the constraint on Y because, erroneously, there is
// no such constraint.
Test5(s, null);
// Here we have another error recovery scenario. L<string> is clearly
// illegal, but what if we try to do overload resolution anyway?
// The constraint is not violated on Z because L<string> is a struct.
// Overload resolution fails because the constraint on L is violated in
// N<L<string>>. Thus that is the overload resolution error we report.
// We therefore end up reporting this error twice, unfortunately; we
// should consider putting some gear in place to suppress the cascading
// error.
Test6<L<string>>(null);
}
static void Test1<U>(U u, N<U> nu) where U : struct { }
static void Test2<V>(V v, N<V> nv) where V : struct { }
static void Test3<W>(W w, N<W> nw) where W : struct { }
static void Test3(object o1, object o2) {}
static void Test4<X>(X x) where X : struct { }
static void Test4(object x) {}
static void Test5<Y>(Y y, N<Y> ny) { }
static void Test6<Z>(N<Z> nz) where Z : struct {}
}";
CreateCompilation(source, parseOptions: TestOptions.WithoutImprovedOverloadCandidates).VerifyDiagnostics(
// (67,36): error CS0453: The type 'Y' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'C.N<T>'
// static void Test5<Y>(Y y, N<Y> ny) { }
Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "ny").WithArguments("C.N<T>", "T", "Y").WithLocation(67, 36),
// (17,9): error CS0453: The type 'string' must be a non-nullable value type in order to use it as parameter 'U' in the generic type or method 'C.Test1<U>(U, C.N<U>)'
// Test1<string>(s, null);
Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "Test1<string>").WithArguments("C.Test1<U>(U, C.N<U>)", "U", "string").WithLocation(17, 9),
// (21,9): error CS0453: The type 'string' must be a non-nullable value type in order to use it as parameter 'V' in the generic type or method 'C.Test2<V>(V, C.N<V>)'
// Test2(s, null);
Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "Test2").WithArguments("C.Test2<V>(V, C.N<V>)", "V", "string").WithLocation(21, 9),
// (36,9): error CS0453: The type 'string' must be a non-nullable value type in order to use it as parameter 'X' in the generic type or method 'C.Test4<X>(X)'
// Test4(s);
Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "Test4").WithArguments("C.Test4<X>(X)", "X", "string").WithLocation(36, 9),
// (47,9): error CS0453: The type 'string' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'C.N<T>'
// Test5(s, null);
Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "Test5").WithArguments("C.N<T>", "T", "string").WithLocation(47, 9),
// (58,17): error CS0453: The type 'string' must be a non-nullable value type in order to use it as parameter 'S' in the generic type or method 'C.L<S>'
// Test6<L<string>>(null);
Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "string").WithArguments("C.L<S>", "S", "string").WithLocation(58, 17),
// (58,9): error CS0453: The type 'string' must be a non-nullable value type in order to use it as parameter 'S' in the generic type or method 'C.L<S>'
// Test6<L<string>>(null);
Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "Test6<L<string>>").WithArguments("C.L<S>", "S", "string").WithLocation(58, 9));
CreateCompilation(source).VerifyDiagnostics(
// (67,36): error CS0453: The type 'Y' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'C.N<T>'
// static void Test5<Y>(Y y, N<Y> ny) { }
Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "ny").WithArguments("C.N<T>", "T", "Y").WithLocation(67, 36),
// (17,9): error CS0453: The type 'string' must be a non-nullable value type in order to use it as parameter 'U' in the generic type or method 'C.Test1<U>(U, C.N<U>)'
// Test1<string>(s, null);
Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "Test1<string>").WithArguments("C.Test1<U>(U, C.N<U>)", "U", "string").WithLocation(17, 9),
// (21,9): error CS0453: The type 'string' must be a non-nullable value type in order to use it as parameter 'V' in the generic type or method 'C.Test2<V>(V, C.N<V>)'
// Test2(s, null);
Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "Test2").WithArguments("C.Test2<V>(V, C.N<V>)", "V", "string").WithLocation(21, 9),
// (47,9): error CS0453: The type 'string' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'C.N<T>'
// Test5(s, null);
Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "Test5").WithArguments("C.N<T>", "T", "string").WithLocation(47, 9),
// (58,17): error CS0453: The type 'string' must be a non-nullable value type in order to use it as parameter 'S' in the generic type or method 'C.L<S>'
// Test6<L<string>>(null);
Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "string").WithArguments("C.L<S>", "S", "string").WithLocation(58, 17),
// (58,9): error CS0453: The type 'string' must be a non-nullable value type in order to use it as parameter 'S' in the generic type or method 'C.L<S>'
// Test6<L<string>>(null);
Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "Test6<L<string>>").WithArguments("C.L<S>", "S", "string").WithLocation(58, 9));
}
[Fact]
public void TestBug9583()
{
var source =
@"
class C
{
public static void M()
{
Goo();
}
static void Goo<T>(params T[] x) { }
}";
CreateCompilation(source).VerifyDiagnostics(
// (6,9): error CS0411: The type arguments for method 'C.Goo<T>(params T[])' cannot be inferred from the usage. Try specifying the type arguments explicitly.
// Goo();
Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "Goo").WithArguments("C.Goo<T>(params T[])").WithLocation(6, 9));
}
[Fact]
public void TestMoreOverloadResolutionErrors()
{
var source = @"
class C
{
static void VoidReturning() {}
static void M()
{
byte b = new byte(1);
System.Console.WriteLine(VoidReturning());
}
}";
CreateCompilation(source).VerifyDiagnostics(
// (7,22): error CS1729: 'byte' does not contain a constructor that takes 1 arguments
// byte b = new byte(1);
Diagnostic(ErrorCode.ERR_BadCtorArgCount, "byte").WithArguments("byte", "1").WithLocation(7, 22),
// (8,34): error CS1503: Argument 1: cannot convert from 'void' to 'bool'
// System.Console.WriteLine(VoidReturning());
Diagnostic(ErrorCode.ERR_BadArgType, "VoidReturning()").WithArguments("1", "void", "bool").WithLocation(8, 34));
}
[Fact]
public void TestBug6156()
{
TestOverloadResolutionWithDiff(
@"
class C
{
public static void M()
{
int y = 123;
Out2 o2 = new Out2();
Ref2 r2 = o2;
Out1 o1 = o2;
Ref1 r1 = o2;
r1.M(ref y); //-Ref1.M(ref int)
o1.M(ref y); //-Ref1.M(ref int)
o1.M(out y); //-Out1.M(out int)
r2.M(ref y); //-Ref2.M(ref int)
r2.M(out y); //-Out1.M(out int)
o2.M(ref y); //-Ref2.M(ref int)
o2.M(out y); //-Out2.M(out int)
}
}
class Ref1
{
public virtual void M(ref int x) { x = 1; } // SLOT1
}
class Out1 : Ref1
{
public virtual void M(out int x) { x = 2; } // SLOT2
}
class Ref2 : Out1
{
public override void M(ref int x) { x = 3; }
// CLR says this overrides SLOT2, even though there is a ref/out mismatch with Out1.
// C# says this overrides SLOT1
}
class Out2 : Ref2
{
public override void M(out int x) { x = 4; }
// CLR says this overrides SLOT2, even though there is a ref/out mismatch with Ref2.M.
// C# says this overrides SLOT2
}");
}
[Fact]
public void TestGenericMethods()
{
TestOverloadResolutionWithDiff(
@"
class C
{
class D<T>
{
public static void N<U>(U u){}
public class E<V>
{
public static void O<W>(W w){}
}
}
void M()
{
D<int>.N<byte>(1); //-C.D<int>.N<byte>(byte)
D<int>.E<double>.O<short>(1); //-C.D<int>.E<double>.O<short>(short)
}
}");
}
[Fact]
public void TestDelegateBetterness()
{
TestOverloadResolutionWithDiff(
@"
delegate void Action();
delegate void Action<in A>(A a);
delegate R Func<out R>();
delegate R Func<in A, out R>(A a);
delegate R Func2<in A, out R>(A a);
class Animal {}
class Mammal : Animal {}
class Tiger : Mammal {}
class C
{
static void N1(Func<object> f){}
static void N1(Func<string> f){}
static void N2(Func<int, object> f){}
static void N2(Action<int> f){}
static void N3(Func<int, Tiger> f){}
static void N3(Func2<int, Mammal> f){}
static void N4(Func<int, Animal> f){}
static void N4(Func2<int, Mammal> f){}
void M()
{
// If we have a lambda argument and two delegates, the rules are:
// First, if one delegate is convertible to the other but not vice-versa
// then the more specific delegate wins. A Func<string> is convertible to Func<object>
// but not vice-versa, so Func<string> must be more specific:
// This test is disabled; see the comments to TestBug11961 above.
// N1(()=>null);
// Second, if the delegates have identical parameters, then the non-void one wins.
// This lambda could be both an action and a func; we don't know if the construction
// is being done for its value or for its side effects.
N2(x=>new System.Object()); //-C.N2(Func<int, object>)
// Third, if the delegates have identical parameters and both have a return type
// and the lambda has an inferred return type, then the better delegate is the
// one where the delegate return type exactly matches the lambda return type.
N3(x=>new Tiger()); //-C.N3(Func<int, Tiger>)
// Fourth, if the delegate return type does not exactly match the lambda return
// type then the most specific delegate return type wins.
N4(x=>new Tiger()); //-C.N4(Func2<int, Mammal>)
}
}
");
}
[Fact]
public void TestTieBreakers()
{
TestOverloadResolutionWithDiff(
@"
class C
{
class D<TD>{}
void N1<T1>(T1 p1) {}
void N1(int p1) {}
void N2(int p1) {}
void N2(params int[] p1) {}
void N3(int p1, int p2, params int[] p3) {}
void N3(int p1, params int[] p3) {}
void N4(int p1, int p2 = 0) {}
void N4(int p1) {}
void N51<T51>(T51 p1, double p2 = 0) {}
void N51<T51>(int p1, string p2 = null ) {}
void N52<T52>(D<T52> p1, double p2 = 0) {}
void N52<T52>(D<int> p1, string p2 = null ) {}
void N53<T53>(T53[] p1, double p2 = 0) {}
void N53<T53>(int[] p1, string p2 = null ) {}
void M()
{
// If due to construction or dynamicness all the effective parameters of two methods are identical
// then we do a series of tiebreaking rules.
// 1: A generic method is worse than a non-generic method.
N1(123); //-C.N1(int)
// 2: A method applicable in normal form is better than one applicable only in expanded form.
N2(123); //-C.N2(int)
// 3: If both methods are applicable in expanded form then the one with more 'real' parameters wins.
N3(1, 2, 3, 4, 5, 6); //-C.N3(int, int, params int[])
// 4: If one method has no default arguments substituted and the other has one or more, the one
// with no defaults wins.
N4(1); //-C.N4(int)
// 5: The more specific method wins. One method's declared parameter types list is more specific than
// anothers if, for each position in the list, the type of one is not less specific than that
// of the other, and, for at least one position, the type is more specific than that of the other.
// 5.1: A type parameter is less specific than any other type.
// 5.2: A constructed type C<X, Y> is less specific than C<A, B> if the type list <X, Y> is less specific than <A, B>
// 5.3: An array type X[] is less specific than Y[] if X is less specific than Y.
// 5.4: NOT TESTED: A pointer type X* is less specific than Y* if X is less specific than Y*.
//EDMAURER removed the next three tests that fail due to the fact that omitted optional parameters are not supported.
// N51<int>(123); //C.N51<int>(int, string)
// N52<int>(null); //C.N52<int>(C.D<int>, string)
// N53<int>(null); //C.N53<int>(int[], string)
// 6: NOT TESTED: A non-lifted operator is better than a lifted operator.
}
}
");
}
[WorkItem(540153, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540153")]
[Fact]
public void TestOverridingMismatchedParamsErrorCase_Source()
{
// Tests:
// Replace params with non-params in signature of overridden member (and vice-versa)
var source = @"
abstract class Base
{
public abstract void Method1(Derived c1, Derived c2, params Derived[] c3);
public abstract void Method2(Derived c1, Derived c2, Derived[] c3);
}
class Derived : Base
{
public override void Method1(Derived C1, Derived C2, Derived[] C3) { } //removes 'params'
public override void Method2(Derived C1, Derived C2, params Derived[] C3) { } //adds 'params'
}
class Test2
{
public static void Main2()
{
Derived d = new Derived();
Base b = d;
b.Method1(d, d, d, d, d); // Fine
d.Method1(d, d, d, d, d); // Fine
b.Method2(d, d, d, d, d); // Should report error - No overload for Method2 takes 5 arguments
d.Method2(d, d, d, d, d); // Should report error - No overload for Method2 takes 5 arguments
}
}";
CreateCompilation(source).VerifyDiagnostics(
Diagnostic(ErrorCode.ERR_BadArgCount, "Method2").WithArguments("Method2", "5"),
Diagnostic(ErrorCode.ERR_BadArgCount, "Method2").WithArguments("Method2", "5"));
}
[Fact]
public void TestImplicitImplMismatchedParamsErrorCase_Source()
{
// Tests:
// Replace params with non-params in signature of implemented member (and vice-versa)
var source = @"
interface Base
{
void Method1(Derived c1, Derived c2, params Derived[] c3);
void Method2(Derived c1, Derived c2, Derived[] c3);
}
class Derived : Base
{
public void Method1(Derived C1, Derived C2, Derived[] C3) { } //removes 'params'
public void Method2(Derived C1, Derived C2, params Derived[] C3) { } //adds 'params'
}
class Test2
{
public static void Main2()
{
Derived d = new Derived();
Base b = d;
b.Method1(d, d, d, d, d); // Fine
d.Method1(d, d, d, d, d); // Should report error - No overload for Method1 takes 5 arguments
b.Method2(d, d, d, d, d); // Should report error - No overload for Method2 takes 5 arguments
d.Method2(d, d, d, d, d); // Fine
}
}";
CreateCompilation(source).VerifyDiagnostics(
Diagnostic(ErrorCode.ERR_BadArgCount, "Method1").WithArguments("Method1", "5"),
Diagnostic(ErrorCode.ERR_BadArgCount, "Method2").WithArguments("Method2", "5"));
}
[Fact]
public void TestExplicitImplMismatchedParamsErrorCase_Source()
{
// Tests:
// Replace params with non-params in signature of implemented member (and vice-versa)
var source = @"
interface Base
{
void Method1(Derived c1, Derived c2, params Derived[] c3);
void Method2(Derived c1, Derived c2, Derived[] c3);
}
class Derived : Base
{
void Base.Method1(Derived C1, Derived C2, Derived[] C3) { } //removes 'params'
void Base.Method2(Derived C1, Derived C2, params Derived[] C3) { } //adds 'params' - CS0466
}
class Test2
{
public static void Main2()
{
Derived d = new Derived();
Base b = d;
b.Method1(d, d, d, d, d); // Fine
b.Method2(d, d, d, d, d); // Should report error - No overload for Method2 takes 5 arguments
}
}";
CreateCompilation(source).VerifyDiagnostics(
// (10,15): error CS0466: 'Derived.Base.Method2(Derived, Derived, params Derived[])' should not have a params parameter since 'Base.Method2(Derived, Derived, Derived[])' does not
Diagnostic(ErrorCode.ERR_ExplicitImplParams, "Method2").WithArguments("Derived.Base.Method2(Derived, Derived, params Derived[])", "Base.Method2(Derived, Derived, Derived[])"),
// (19,9): error CS1501: No overload for method 'Method2' takes 5 arguments
Diagnostic(ErrorCode.ERR_BadArgCount, "Method2").WithArguments("Method2", "5"));
}
[WorkItem(540153, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540153")]
[WorkItem(540406, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540406")]
[ClrOnlyFact(ClrOnlyReason.Ilasm)]
public void TestOverridingMismatchedParamsErrorCase_Metadata()
{
// Tests:
// Replace params with non-params in signature of overridden member (and vice-versa)
var ilSource = @"
.class public abstract auto ansi beforefieldinit Base
extends [mscorlib]System.Object
{
.method public hidebysig newslot abstract virtual
instance void Method1(class Derived c1,
class Derived c2,
class Derived[] c3) cil managed
{
.param [3]
.custom instance void [mscorlib]System.ParamArrayAttribute::.ctor() = {}
} // end of method Base::Method1
.method public hidebysig newslot abstract virtual
instance void Method2(class Derived c1,
class Derived c2,
class Derived[] c3) cil managed
{
} // end of method Base::Method2
.method family hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method Base::.ctor
} // end of class Base
.class public auto ansi beforefieldinit Derived
extends Base
{
.method public hidebysig virtual instance void
Method1(class Derived C1,
class Derived C2,
class Derived[] C3) cil managed
{
ret
} // end of method Derived::Method1
//// Adds 'params' ////
.method public hidebysig virtual instance void
Method2(class Derived C1,
class Derived C2,
class Derived[] C3) cil managed
{
.param [3]
.custom instance void [mscorlib]System.ParamArrayAttribute::.ctor() = {}
ret
} // end of method Derived::Method2
//// Removes 'params' ////
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void Base::.ctor()
IL_0006: ret
} // end of method Derived::.ctor
} // end of class Derived
";
var csharpSource = @"
class Test2
{
public static void Main2()
{
Derived d = new Derived();
Base b = d;
b.Method1(d, d, d, d, d); // Fine
d.Method1(d, d, d, d, d); // Fine
b.Method2(d, d, d, d, d); // Should report error - No overload for Method2 takes 5 arguments
d.Method2(d, d, d, d, d); // Should report error - No overload for Method2 takes 5 arguments
}
}";
// Same errors as in source case
var comp = CreateCompilationWithILAndMscorlib40(csharpSource, ilSource);
comp.VerifyDiagnostics(
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:
// Override virtual member with abstract member – override this abstract member in further derived class
// Test that call to abstract member fails when calling through "base."
var source = @"
abstract class Base<T, U>
{
T f = default(T);
public abstract void Method(T i, U j);
public virtual T Property
{
get { return f; }
set { }
}
}
class Base2<A, B> : Base<A, B>
{
public override void Method(A a, B b)
{
base.Method(a, b); // Error - Cannot call abstract base member
}
public override A Property { set { } }
}
abstract class Base3<T, U> : Base2<T, U>
{
public override abstract void Method(T x, U y);
public override abstract T Property { set; }
}
class Base4<U, V> : Base3<U, V>
{
U f;
public override void Method(U x, V y)
{
base.Method(x, y); // Error - Cannot call abstract base member
}
public override U Property
{
set
{
f = base.Property; // No error - Only setter is abstract in base class
base.Property = f; // Error - Cannot call abstract base member
}
}
}";
CreateCompilation(source).VerifyDiagnostics(
Diagnostic(ErrorCode.ERR_AbstractBaseCall, "base.Method").WithArguments("Base<A, B>.Method(A, B)"),
Diagnostic(ErrorCode.ERR_AbstractBaseCall, "base.Method").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:
// Override virtual member with abstract member – override this abstract member in further derived class
// Test that assigning an abstract member referenced through "base." to a delegate fails
var source = @"
using System;
abstract class Base<T, U>
{
public abstract void Method(T i, U j);
}
class Base2<A, B> : Base<A, B>
{
public override void Method(A a, B b)
{
Action<A, B> m = base.Method; // Error - Cannot call abstract base member
}
}";
CreateCompilation(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 = @"
namespace A
{
abstract class Base<T>
{
public abstract T Method(int x);
}
abstract class Base2<A> : Base<A>
{
A f = default(A);
public override A Method(int x) { return f; }
public abstract A Method(A x);
}
class Derived : Base2<long>
{
// Surprisingly in Dev10 base.Method seems to bind to the second overload above and reports error (can't call abstract method)
public override long Method(int x) { base.Method(x); return 1; }
public override long Method(long x) { return 2; }
}
}
namespace B
{
abstract class Base2<A>
{
A f = default(A);
public virtual A Method(int x) { return f; }
public abstract A Method(A x);
}
class Derived : Base2<long>
{
// But the same call seems to work in this case in Dev10 i.e. base.Method correctly binds to the first overload
public override long Method(int x) { base.Method(x); return 1; }
public override long Method(long x) { return 2; }
}
}
";
CreateCompilation(source).VerifyDiagnostics(
Diagnostic(ErrorCode.ERR_AbstractBaseCall, "base.Method").WithArguments("A.Base2<long>.Method(long)"));
}
[Fact]
public void Bug8766_ConstructorOverloadResolution_PrivateCtor()
{
var source =
@"using System;
public class A
{
const int C = 1;
private A(int x) { Console.WriteLine(""int""); }
public A(long x) { Console.WriteLine(""long""); }
public void Goo() { A a = new A(C); }
static void Main()
{
A a = new A(C);
a.Goo();
B.Goo();
}
}
public class B
{
const int C = 1;
public static void Goo() { A a = new A(C);}
}
";
CompileAndVerify(source, expectedOutput: @"int
int
long
");
}
[Fact]
public void Bug8766_ConstructorOverloadResolution_ProtectedCtor()
{
var source =
@"using System;
public class A
{
const int C = 1;
protected A(int x) { Console.WriteLine(""int""); }
public A(long x) { Console.WriteLine(""long""); }
public void Goo() { A a = new A(C); }
static void Main()
{
A a = new A(C);
a.Goo();
B.Goo();
}
}
public class B
{
const int C = 1;
public static void Goo() { A a = new A(C);}
}
";
CompileAndVerify(source, expectedOutput: @"int
int
long
");
}
[Fact, WorkItem(546694, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546694")]
public void Bug16581_ConstructorOverloadResolution_BaseClass()
{
var source = @"
using System;
class A
{
private A(int x) { }
public A(long x)
{
Console.WriteLine(""PASS"");
}
private void M(int x) { }
public void M(long x)
{
Console.WriteLine(""PASS"");
}
}
class B: A
{
public B(): base(123)
{
base.M(123);
}
public static void Main()
{
var unused = new B();
}
}
";
CompileAndVerify(source, expectedOutput: @"PASS
PASS");
}
[Fact, WorkItem(529847, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529847")]
public void Bug14585_ConstructorOverloadResolution_BaseClass()
{
var source = @"
public class Base
{
protected Base()
{
}
public Base(int i)
{
}
}
class Test
{
static void Main(string[] args)
{
var a = new Base();
}
}
";
CreateCompilation(source).VerifyDiagnostics(
// (17,21): error CS0122: 'Base.Base()' is inaccessible due to its protection level
// var a = new Base();
Diagnostic(ErrorCode.ERR_BadAccess, "Base").WithArguments("Base.Base()"));
}
[Fact]
public void Bug8766_MethodOverloadResolution()
{
var source =
@"using System;
public class A
{
const int C = 1;
void AA(int x) { Console.WriteLine(""int""); }
public void AA(long x) { Console.Write(""long""); }
public void Goo() { A a = new A(); a.AA(C); }
static void Main()
{
A a = new A();
a.Goo();
B.Goo();
}
}
public class B
{
const int C = 1;
public static void Goo() { A a = new A(); a.AA(C);}
}
";
CompileAndVerify(source, expectedOutput: @"int
long
");
}
[Fact]
public void RegressionTestForIEnumerableOfDynamic()
{
TestOverloadResolutionWithDiff(
@"using System;
using System.Collections.Generic;
class C
{
class DynamicWrapper
{
public IEnumerable<dynamic> Value { get; set; }
}
static void M()
{
DynamicWrapper[] array = null;
Goo(array, x => x.Value, (x, y) => string.Empty); //-C.Goo(System.Collections.Generic.IEnumerable<C.DynamicWrapper>, System.Func<C.DynamicWrapper, System.Collections.Generic.IEnumerable<dynamic>>, System.Func<C.DynamicWrapper, dynamic, string>)
}
static IEnumerable<dynamic> Goo(
object source,
Func<dynamic, IEnumerable<dynamic>> collectionSelector,
Func<dynamic, dynamic, dynamic> resultSelector)
{
return null;
}
static IEnumerable<string> Goo(
IEnumerable<DynamicWrapper> source,
Func<DynamicWrapper, IEnumerable<dynamic>> collectionSelector,
Func<DynamicWrapper, dynamic, string> resultSelector)
{
return null;
}
}");
}
[Fact]
public void MissingBaseTypeAndParamsCtor()
{
var cCommon = CreateCompilation(@"
public class TCommon {}
", assemblyName: "cCommon");
Assert.Empty(cCommon.GetDiagnostics());
var cCS = CreateCompilation(@"
public class MProvider : TCommon {}
", new MetadataReference[] { new CSharpCompilationReference(cCommon) }, assemblyName: "cCS");
Assert.Empty(cCS.GetDiagnostics());
var cFinal = CreateCompilation(@"
public class T : MProvider {}
class PArray
{
public PArray(TCommon t, params object[] p)
{
}
}
class Goo
{
void M()
{
T t = new T();
var x = new PArray(t, 1, 2);
}
}
",
//note that the reference to the 'cCS' compilation is missing.
new MetadataReference[] { new CSharpCompilationReference(cCommon) });
cFinal.GetDiagnostics();
}
[Fact]
public void RefOmittedComCall_Basic()
{
var source =
@"using System;
using System.Runtime.InteropServices;
[ComImport]
[Guid(""A88A175D-2448-447A-B786-64682CBEF156"")]
public interface IRef1
{
int M(ref int x, int y);
}
public class Ref1Impl : IRef1
{
public int M(ref int x, int y) { return x + y; }
}
class Test
{
public static int Main()
{
IRef1 ref1 = new Ref1Impl();
int ret = ref1.M(10, 10);
Console.WriteLine(ret);
return ret;
}
}
";
CompileAndVerify(source, expectedOutput: @"20");
}
[WorkItem(546733, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546733")]
[Fact]
public void RefOmittedComCall_Iterator()
{
var source =
@"using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
[ComImport]
[Guid(""A88A175D-2448-447A-B786-64682CBEF156"")]
public interface IRef1
{
int M(ref int x, int y);
}
public class Ref1Impl : IRef1
{
public int M(ref int x, int y) { return x + y; }
}
class Test
{
static IEnumerable<int> M()
{
IRef1 ref1 = new Ref1Impl();
int ret = ref1.M(10, 2);
yield return ret;
}
public static void Main()
{
Console.WriteLine(M().First());
}
}";
CompileAndVerify(source, expectedOutput: @"12");
}
[Fact]
public void RefOmittedComCall_ArgumentNotAddressTaken_01()
{
var source =
@"using System;
using System.Runtime.InteropServices;
[ComImport]
[Guid(""A88A175D-2448-447A-B786-64682CBEF156"")]
public interface IRef1
{
int M(ref int x, ref int y);
}
public class Ref1Impl : IRef1
{
public int M(ref int x, ref int y)
{
int ret = x + y;
x = -1;
y = 0;
return ret;
}
}
class Test
{
public static int Main()
{
IRef1 ref1 = new Ref1Impl();
int x = 10, y = 10;
int ret = ref1.M(x, ref y);
Console.WriteLine(x);
Console.WriteLine(y);
Console.WriteLine(ret);
return ret;
}
}
";
CompileAndVerify(source, expectedOutput: @"10
0
20");
}
[Fact]
public void RefOmittedComCall_ArgumentNotAddressTaken_02()
{
var source =
@"using System;
using System.Runtime.InteropServices;
[ComImport]
[Guid(""A88A175D-2448-447A-B786-64682CBEF156"")]
public interface IRef1
{
int M(ref int x, int y);
}
public class Ref1Impl : IRef1
{
public int M(ref int x, int y)
{
int ret = x + y;
x = 0;
return ret;
}
}
class Test
{
public static int Main()
{
IRef1 ref1 = new Ref1Impl();
int x = 10, y = 10;
int ret = ref1.M(x, y);
Console.WriteLine(x);
Console.WriteLine(y);
Console.WriteLine(ret);
return ret;
}
}
";
CompileAndVerify(source, expectedOutput: @"10
10
20");
}
[Fact]
public void RefOmittedComCall_NamedArguments()
{
var source =
@"using System;
using System.Runtime.InteropServices;
[ComImport]
[Guid(""A88A175D-2448-447A-B786-64682CBEF156"")]
public interface IRef1
{
int M(ref int x, ref int y);
}
public class Ref1Impl : IRef1
{
public int M(ref int x, ref int y)
{
int ret = x + y;
x = -1;
y = 0;
return ret;
}
}
class Test
{
public static int Main()
{
IRef1 ref1 = new Ref1Impl();
int y = 10;
int ret = ref1.M(y: ref y, x: y);
Console.WriteLine(y);
Console.WriteLine(ret);
return ret;
}
}
";
CompileAndVerify(source, expectedOutput: @"0
20");
}
[Fact]
public void RefOmittedComCall_MethodCallArgument()
{
var source =
@"using System;
using System.Runtime.InteropServices;
[ComImport]
[Guid(""A88A175D-2448-447A-B786-64682CBEF156"")]
public interface IRef1
{
int M(ref int x, ref int y, ref int z);
}
public class Ref1Impl : IRef1
{
public int M(ref int x, ref int y, ref int z)
{
int ret = x + y + z;
x = -1;
y = -2;
z = -3;
return ret;
}
}
class Test
{
public static int Goo(ref int x)
{
Console.WriteLine(x);
x++;
return x;
}
public static int Main()
{
IRef1 ref1 = new Ref1Impl();
int a = 10;
int ret = ref1.M(
z: Goo(ref a), // Print 10
y: ref1.M(z: ref a, y: a, x: ref a),
x: Goo(ref a)); // Print -3
Console.WriteLine(a); // Print -2
Console.WriteLine(ret); // Print 42
int b = 1, c = 2;
ret = ref1.M(
z: Goo(ref c), // Print 2
y: ref1.M(z: ref b, y: b + c, x: b),
x: Goo(ref b)); // Print -3
Console.WriteLine(b); // Print -2
Console.WriteLine(c); // Print 3
Console.WriteLine(ret); // Print 7
return ret;
}
}
";
CompileAndVerify(source, expectedOutput: @"10
-3
-2
42
2
-3
-2
3
7");
}
[Fact]
public void RefOmittedComCall_AssignToRefParam()
{
var source =
@"using System;
using System.Runtime.InteropServices;
[ComImport]
[Guid(""A88A175D-2448-447A-B786-64682CBEF156"")]
public interface IRef1
{
int M(ref int x, ref int y);
}
public class Ref1Impl : IRef1
{
public int M(ref int x, ref int y)
{
x = 1;
y = 2;
return x + y;
}
}
class Test
{
public static int Goo(ref int x)
{
Console.WriteLine(x);
x++;
return x;
}
public static int Main()
{
IRef1 ref1 = new Ref1Impl();
int a = 10;
int ret = ref1.M(a, a) + ref1.M(10, 10);
Console.WriteLine(ret);
return ret;
}
}
";
CompileAndVerify(source, expectedOutput: @"6");
}
[Fact]
public void RefOmittedComCall_ExternMethod()
{
var source =
@"using System;
using System.Runtime.InteropServices;
[ComImport]
[Guid(""A88A175D-2448-447A-B786-64682CBEF156"")]
public class Ref1Impl
{
public extern int M(ref int x, int y);
}
class Test
{
public static int Main()
{
var ref1 = new Ref1Impl();
int ret = ref1.M(10, 10);
Console.WriteLine(ret);
return ret;
}
}
";
CreateCompilation(source).VerifyDiagnostics();
}
[Fact, WorkItem(530747, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530747")]
public void RefOmittedComCall_Unsafe()
{
// Native compiler generates invalid IL for ref omitted argument of pointer type, while Roslyn generates correct IL.
// See Won't Fixed Devdiv bug #16837 for details.
var source =
@"using System;
using System.Runtime.InteropServices;
[ComImport]
[Guid(""A88A175D-2448-447A-B786-64682CBEF156"")]
unsafe public interface IRef1
{
void M(ref int* x);
void M2(ref int* x, ref int* y);
void M3(ref int* x, ref int* y);
}
unsafe public class Ref1Impl : IRef1
{
public void M(ref int* x)
{
*x = *x + 1;
x = null;
}
public void M2(ref int* x, ref int* y)
{
*y = *y + 1;
}
public void M3(ref int* x, ref int* y)
{
x = null;
*y = *y + 1;
}
}
unsafe class Test
{
public static int Main()
{
IRef1 ref1 = new Ref1Impl();
int a = 1;
int *p = &a;
ref1.M(ref p);
Console.WriteLine(a);
Console.WriteLine(p == null);
p = &a;
ref1.M2(&a, ref p);
Console.WriteLine(a);
Console.WriteLine(*p);
ref1.M3(p, ref p);
Console.WriteLine(a);
Console.WriteLine(*p);
return 0;
}
}
";
CompileAndVerify(source, options: TestOptions.UnsafeReleaseExe, verify: Verification.Fails, expectedOutput: @"2
True
3
3
4
4");
}
[Fact()]
public void RefOmittedComCall_ERR_ComImportWithImpl()
{
var source =
@"using System;
using System.Runtime.InteropServices;
public interface IRef1
{
int M(ref int x, int y);
}
[ComImport]
[Guid(""A88A175D-2448-447A-B786-64682CBEF156"")]
public class Ref1Impl : IRef1
{
public int M(ref int x, int y) { return x + y; }
}
class Test
{
public static int Main()
{
var ref1 = new Ref1Impl();
int ret = ref1.M(10, 10);
Console.WriteLine(ret);
return ret;
}
}
";
CreateCompilation(source).VerifyDiagnostics(
// (13,16): error CS0423: Since 'Ref1Impl' has the ComImport attribute, 'Ref1Impl.M(ref int, int)' must be extern or abstract
// public int M(ref int x, int y) { return x + y; }
Diagnostic(ErrorCode.ERR_ComImportWithImpl, "M").WithArguments("Ref1Impl.M(ref int, int)", "Ref1Impl").WithLocation(13, 16));
}
[Fact]
public void RefOmittedComCall_Error_NonComImportType()
{
var source =
@"using System;
using System.Runtime.InteropServices;
public interface IRef1
{
int M(ref int x, int y);
}
[ComImport]
[Guid(""A88A175D-2448-447A-B786-64682CBEF156"")]
public class Ref1Impl: IRef1
{
public extern int M(ref int x, int y);
}
class Test
{
public static int Main()
{
IRef1 ref1 = new Ref1Impl();
int ret = ref1.M(10, 10);
Console.WriteLine(ret);
return ret;
}
}
";
CreateCompilation(source).VerifyDiagnostics(
// (21,25): error CS1620: Argument 1 must be passed with the 'ref' keyword
// int ret = ref1.M(10, 10);
Diagnostic(ErrorCode.ERR_BadArgRef, "10").WithArguments("1", "ref").WithLocation(21, 25));
}
[Fact]
public void RefOmittedComCall_Error_OutParam()
{
var source =
@"using System;
using System.Runtime.InteropServices;
[ComImport]
[Guid(""A88A175D-2448-447A-B786-64682CBEF156"")]
public interface IRef1
{
int M(out int x, int y);
}
public class Ref1Impl : IRef1
{
public int M(out int x, int y) { x = 1; return y; }
}
class Test
{
public static int Main()
{
IRef1 ref1 = new Ref1Impl();
int x;
int ret = ref1.M(x, 10);
Console.WriteLine(ret);
return ret;
}
}";
CreateCompilation(source).VerifyDiagnostics(
// (22,25): error CS1620: Argument 1 must be passed with the 'out' keyword
// int ret = ref1.M(x, 10);
Diagnostic(ErrorCode.ERR_BadArgRef, "x").WithArguments("1", "out").WithLocation(22, 25),
// (22,25): error CS0165: Use of unassigned local variable 'x'
// int ret = ref1.M(x, 10);
Diagnostic(ErrorCode.ERR_UseDefViolation, "x").WithArguments("x").WithLocation(22, 25));
}
[Fact]
public void RefOmittedComCall_Error_WithinAttributeContext()
{
var source =
@"
using System;
using System.Runtime.InteropServices;
[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
class Attr: Attribute
{
public Attr(int x) {}
}
[ComImport]
[Guid(""A88A175D-2448-447A-B786-64682CBEF156"")]
class Attr2: Attribute
{
public Attr2(ref int x) {}
}
[ComImport]
[Guid(""A88A175D-2448-447A-B786-64682CBEF156"")]
[Attr(new Goo().M1(1, 1))]
[Attr(Goo.M2(1, 1))]
[Attr2(1)]
public class Goo
{
public extern int M1(ref int x, int y);
public static extern int M2(ref int x, int y);
}";
CreateCompilation(source).VerifyDiagnostics(
// (13,7): error CS0424: 'Attr2': a class with the ComImport attribute cannot specify a base class
// class Attr2: Attribute
Diagnostic(ErrorCode.ERR_ComImportWithBase, "Attr2").WithArguments("Attr2").WithLocation(13, 7),
// (15,12): error CS0669: A class with the ComImport attribute cannot have a user-defined constructor
// public Attr2(ref int x) {}
Diagnostic(ErrorCode.ERR_ComImportWithUserCtor, "Attr2").WithLocation(15, 12),
// (20,20): error CS1620: Argument 1 must be passed with the 'ref' keyword
// [Attr(new Goo().M1(1, 1))]
Diagnostic(ErrorCode.ERR_BadArgRef, "1").WithArguments("1", "ref").WithLocation(20, 20),
// (21,14): error CS1620: Argument 1 must be passed with the 'ref' keyword
// [Attr(Goo.M2(1, 1))]
Diagnostic(ErrorCode.ERR_BadArgRef, "1").WithArguments("1", "ref").WithLocation(21, 14),
// (22,8): error CS1620: Argument 1 must be passed with the 'ref' keyword
// [Attr2(1)]
Diagnostic(ErrorCode.ERR_BadArgRef, "1").WithArguments("1", "ref").WithLocation(22, 8));
}
[Fact]
public void RefOmittedComCall_CtorWithRefArgument()
{
var ilSource = @"
.class public auto ansi import beforefieldinit Ref1
extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = ( 01 00 24 41 38 38 41 31 37 35 44 2D 32 34 34 38 // ..$A88A175D-2448
2D 34 34 37 41 2D 42 37 38 36 2D 36 34 36 38 32 // -447A-B786-64682
43 42 45 46 31 35 36 00 00 ) // CBEF156..
.method public hidebysig specialname rtspecialname
instance void .ctor(int32& x) runtime managed internalcall
{
} // end of method Ref1::.ctor
} // end of class Ref1
";
var source = @"
public class MainClass
{
public static int Main ()
{
int x = 0;
var r = new Ref1(x);
return 0;
}
}";
var compilation = CreateCompilationWithILAndMscorlib40(source, ilSource);
compilation.VerifyDiagnostics(
// (7,26): error CS1620: Argument 1 must be passed with the 'ref' keyword
// var r = new Ref1(x);
Diagnostic(ErrorCode.ERR_BadArgRef, "x").WithArguments("1", "ref").WithLocation(7, 26));
}
[Fact, WorkItem(546122, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546122")]
public void TestComImportOverloadResolutionCantOmitRef()
{
string source = @"
using System;
using System.Runtime.InteropServices;
[ComImport, Guid(""1234C65D-1234-447A-B786-64682CBEF136"")]
abstract class C
{
extern public void M(ref short p);
extern public void M(sbyte p);
}
class D : C
{
public static void Goo()
{
short x = 123;
sbyte s = 123;
new D().M(x);
C c = new D();
c.M(x);
new D().M(s);
}
}
";
CreateCompilation(source).VerifyDiagnostics(
// (18,19): error CS1620: Argument 1 must be passed with the 'ref' keyword
// new D().M(x);
Diagnostic(ErrorCode.ERR_BadArgRef, "x").WithArguments("1", "ref"));
}
[Fact, WorkItem(546122, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546122")]
public void RefOmittedComCall_BaseTypeComImport()
{
string source = @"
using System;
using System.Runtime.InteropServices;
[ComImport, Guid(""1234C65D-1234-447A-B786-64682CBEF136"")]
abstract class E
{
extern public void M(ref short p);
}
class F : E
{
[DllImport(""goo"")]
extern public void M(sbyte p);
public static void Goo()
{
short x = 123;
sbyte s = 123;
new F().M(x);
E e = new F();
e.M(x);
new F().M(s);
}
}
[ComImport, Guid(""1234C65D-1234-447A-B786-64682CBEF136"")]
abstract class G
{
extern public void M(sbyte p);
}
class H : G
{
extern public void M(ref short p);
public static void Goo()
{
short x = 123;
sbyte s = 123;
new H().M(x);
G g = new H();
g.M(x);
new H().M(s);
}
}
[ComImport, Guid(""1234C65D-1234-447A-B786-64682CBEF136"")]
abstract class I
{
}
class J : I
{
extern public void M(sbyte p);
extern public void M(ref short p);
public static void Goo()
{
short x = 123;
sbyte s = 123;
new J().M(x);
I i = new J();
i.M(x);
new J().M(s);
}
}
";
CreateCompilation(source).VerifyDiagnostics(
// (12,6): error CS0601: The DllImport attribute must be specified on a method marked 'static' and 'extern'
// [DllImport("goo")]
Diagnostic(ErrorCode.ERR_DllImportOnInvalidMethod, "DllImport"),
// (20,19): error CS1503: Argument 1: cannot convert from 'short' to 'sbyte'
// new F().M(x);
Diagnostic(ErrorCode.ERR_BadArgType, "x").WithArguments("1", "short", "sbyte"),
// (36,24): warning CS0626: Method, operator, or accessor 'H.M(ref short)' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation.
// extern public void M(ref short p);
Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M").WithArguments("H.M(ref short)"),
// (43,19): error CS1620: Argument 1 must be passed with the 'ref' keyword
// new H().M(x);
Diagnostic(ErrorCode.ERR_BadArgRef, "x").WithArguments("1", "ref"),
// (46,13): error CS1503: Argument 1: cannot convert from 'short' to 'sbyte'
// g.M(x);
Diagnostic(ErrorCode.ERR_BadArgType, "x").WithArguments("1", "short", "sbyte"),
// (58,24): warning CS0626: Method, operator, or accessor 'J.M(sbyte)' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation.
// extern public void M(sbyte p);
Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M").WithArguments("J.M(sbyte)"),
// (59,24): warning CS0626: Method, operator, or accessor 'J.M(ref short)' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation.
// extern public void M(ref short p);
Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M").WithArguments("J.M(ref short)"),
// (66,19): error CS1503: Argument 1: cannot convert from 'short' to 'sbyte'
// new J().M(x);
Diagnostic(ErrorCode.ERR_BadArgType, "x").WithArguments("1", "short", "sbyte"),
// (69,11): error CS1061: 'I' does not contain a definition for 'M' and no extension method 'M' accepting a first argument of type 'I' could be found (are you missing a using directive or an assembly reference?)
// i.M(x);
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "M").WithArguments("I", "M"));
}
[Fact, WorkItem(546122, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546122")]
public void RefOmittedComCall_DerivedComImport()
{
string source = @"
using System;
using System.Runtime.InteropServices;
interface A
{
void M(ref short p);
void M(sbyte p);
}
[ComImport, Guid(""1234C65D-1234-447A-B786-64682CBEF136"")]
interface B: A
{
}
class C: B
{
public void M(ref short p) {}
public void M(sbyte p) {}
public static void Goo()
{
short x = 123;
sbyte s = 123;
A a = new C();
B b = new C();
C c = new C();
a.M(x);
b.M(x);
c.M(x);
a.M(s);
b.M(s);
c.M(s);
}
}
";
CreateCompilation(source).VerifyDiagnostics(
// (30,13): error CS1620: Argument 1 must be passed with the 'ref' keyword
// a.M(x);
Diagnostic(ErrorCode.ERR_BadArgRef, "x").WithArguments("1", "ref"),
// (32,13): error CS1620: Argument 1 must be passed with the 'ref' keyword
// c.M(x);
Diagnostic(ErrorCode.ERR_BadArgRef, "x").WithArguments("1", "ref"));
}
[Fact, WorkItem(546122, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546122")]
public void RefOmittedComCall_TypeParameterConstrainedToComImportType()
{
string source = @"
using System;
using System.Runtime.InteropServices;
[ComImport, Guid(""1234C65D-1234-447A-B786-64682CBEF136"")]
class K
{
public extern void M(ref short p);
public extern void M(sbyte p);
}
class H<T> where T: K, new()
{
public static void Goo()
{
short x = 123;
T t = new T();
t.M(x);
}
}
";
CreateCompilation(source).VerifyDiagnostics(
// (18,13): error CS1620: Argument 1 must be passed with the 'ref' keyword
// t.M(x);
Diagnostic(ErrorCode.ERR_BadArgRef, "x").WithArguments("1", "ref"));
}
[Fact, WorkItem(546122, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546122")]
public void RefOmittedComCall_StaticMethod1()
{
string source = @"
using System;
using System.Runtime.InteropServices;
[ComImport, Guid(""1234C65D-1234-447A-B786-64682CBEF136"")]
static class E
{
public extern static void M(ref short p);
public extern static void M(sbyte p);
}
class Y
{
public static void Goo()
{
short x = 123;
E.M(x); // Dev11 reports CS1620 (missing 'ref')
}
}
";
// BREAK: Dev11 does not allow this, but it's probably an accident.
// That is, it inspects the receiver type of the invocation and it
// finds no receiver for a static method invocation.
// MITIGATION: Candidates with 'ref' omitted lose tie-breakers, so
// it should not be possible for this to cause overload resolution
// to succeed in a different way.
CreateCompilation(source).VerifyDiagnostics();
}
[Fact, WorkItem(546122, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546122")]
public void RefOmittedComCall_StaticMethod2()
{
string source = @"
using System;
using System.Runtime.InteropServices;
[ComImport, Guid(""1234C65D-1234-447A-B786-64682CBEF136"")]
class E
{
public extern static void M(ref short p);
}
[ComImport, Guid(""1234C65D-1234-447A-B786-64682CBEF137"")]
class F
{
public extern static void M(ref short p);
}
class Y
{
public static void Main()
{
short x = 123;
E E = null;
E.M(x); // Allowed in dev11.
F.M(x); // CS1620 (missing 'ref') in dev11.
}
}
";
// BREAK: Dev11 produces an error. It doesn't make sense that the introduction
// of a color-color local would eliminate an error, since it does not affect the
// outcome of overload resolution.
CreateCompilation(source).VerifyDiagnostics(
// (22,11): warning CS0219: The variable 'E' is assigned but its value is never used
// E E = null;
Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "E").WithArguments("E").WithLocation(22, 11));
}
[Fact, WorkItem(546122, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546122"), WorkItem(842476, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/842476")]
public void RefOmittedComCall_ExtensionMethod()
{
string source = @"
using System;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
[ComImport, Guid(""1234C65D-1234-447A-B786-64682CBEF136"")]
class C
{
}
static class CExtensions
{
public static void M(this C c, ref short p) {}
public static void M(this C c, sbyte p) {}
public static void I(this C c, ref int p) {}
}
class X
{
public static void Goo()
{
short x = 123;
C c = new C();
c.M(x);
c.I(123);
}
}
";
CompileAndVerify(source);
}
[Fact]
public void RefOmittedComCall_OverloadResolution_SingleArgument()
{
var source =
@"
using System;
using System.Runtime.InteropServices;
[ComImport]
[Guid(""A88A175D-2448-447A-B786-64682CBEF156"")]
public interface IRef1
{
void M1(int x);
void M1(ref int x);
void M2(long x);
void M2(ref int x);
void M3(char x);
void M3(ref int x);
void M4(out uint x);
void M4(ref int x);
void M5(ref int x);
void M5(ref long x);
void M6(ref char x);
void M6(ref long x);
void M7(ref long x);
void M7(int x);
void M8(ref long x);
void M8(char x);
void M9(ref char x);
void M9(long x);
}
public class Ref1Impl : IRef1
{
public void M1(int x) { Console.WriteLine(1); }
public void M1(ref int x) { Console.WriteLine(2); }
public void M2(long x) { Console.WriteLine(3); }
public void M2(ref int x) { Console.WriteLine(4); }
public void M3(char x) { Console.WriteLine(5); }
public void M3(ref int x) { Console.WriteLine(6); }
public void M4(out uint x) { x = 0; Console.WriteLine(7); }
public void M4(ref int x) { Console.WriteLine(8); }
public void M5(ref int x) { Console.WriteLine(9); }
public void M5(ref long x) { Console.WriteLine(10); }
public void M6(ref char x) { Console.WriteLine(11); }
public void M6(ref long x) { Console.WriteLine(12); }
public void M7(ref long x) { Console.WriteLine(13); }
public void M7(int x) { Console.WriteLine(14); }
public void M8(ref long x) { Console.WriteLine(15); }
public void M8(char x) { Console.WriteLine(16); }
public void M9(ref char x) { Console.WriteLine(17); }
public void M9(long x) { Console.WriteLine(18); }
}
class Test
{
public static void Main()
{
IRef1 ref1 = new Ref1Impl();
int i = 1;
long l = 1;
char c = 'c';
// void M1(int x);
// void M1(ref int x);
ref1.M1(10);
//ref1.M1(10L); CS1503
ref1.M1('c');
ref1.M1(i);
//ref1.M1(l); CS1503
ref1.M1(c);
ref1.M1(ref i);
//ref1.M1(ref l); CS1615
//ref1.M1(ref c); CS1615
// void M2(long x);
// void M2(ref int x);
Console.WriteLine();
ref1.M2(10);
ref1.M2(10L);
ref1.M2('c');
ref1.M2(i);
ref1.M2(l);
ref1.M2(c);
ref1.M2(ref i);
//ref1.M2(ref l); CS1615
//ref1.M2(ref c); CS1615
// void M3(char x);
// void M3(ref int x);
Console.WriteLine();
ref1.M3(10);
//ref1.M3(10L); CS1503
ref1.M3('c');
ref1.M3(i);
//ref1.M3(l); CS1503
ref1.M3(c);
ref1.M3(ref i);
//ref1.M3(ref l); CS1615
//ref1.M3(ref c); CS1615
// void M4(out uint x);
// void M4(ref int x);
Console.WriteLine();
ref1.M4(10);
//ref1.M4(10L); CS1620
ref1.M4('c');
ref1.M4(i);
//ref1.M4(l); CS1620
ref1.M4(c);
ref1.M4(ref i);
//ref1.M4(ref l); CS1620
//ref1.M4(ref c); CS1620
// void M5(ref int x);
// void M5(ref long x);
Console.WriteLine();
//ref1.M5(10); CS0121
ref1.M5(10L);
//ref1.M5('c'); CS0121
//ref1.M5(i); CS0121
ref1.M5(l);
//ref1.M5(c); CS0121
ref1.M5(ref i);
ref1.M5(ref l);
//ref1.M5(ref c); CS1503
// void M6(ref char x);
// void M6(ref long x);
Console.WriteLine();
ref1.M6(10);
ref1.M6(10L);
//ref1.M6('c'); CS0121
ref1.M6(i);
ref1.M6(l);
//ref1.M6(c); CS0121
//ref1.M6(ref i); CS1503
ref1.M6(ref l);
ref1.M6(ref c);
// void M7(ref long x);
// void M7(int x);
Console.WriteLine();
ref1.M7(10);
ref1.M7(10L);
ref1.M7('c');
ref1.M7(i);
ref1.M7(l);
ref1.M7(c);
//ref1.M7(ref i); CS1503
ref1.M7(ref l);
//ref1.M7(ref c); CS1503
// void M8(ref long x);
// void M8(char x);
Console.WriteLine();
ref1.M8(10);
ref1.M8(10L);
ref1.M8('c');
ref1.M8(i);
ref1.M8(l);
ref1.M8(c);
//ref1.M8(ref i); CS1503
ref1.M8(ref l);
//ref1.M8(ref c); CS1503
// void M9(ref char x);
// void M9(long x);
Console.WriteLine();
ref1.M9(10);
ref1.M9(10L);
ref1.M9('c');
ref1.M9(i);
ref1.M9(l);
ref1.M9(c);
//ref1.M9(ref i); CS1503
//ref1.M9(ref l); CS1503
ref1.M9(ref c);
}
}
";
CompileAndVerify(source, expectedOutput: @"1
1
1
1
2
3
3
3
3
3
3
4
6
5
6
5
6
8
8
8
8
8
10
10
9
10
12
12
12
12
12
11
14
13
14
14
13
14
13
15
15
16
15
15
16
15
18
18
18
18
18
18
17");
}
[Fact]
public void RefOmittedComCall_OverloadResolution_SingleArgument_ErrorCases()
{
var source =
@"
using System;
using System.Runtime.InteropServices;
[ComImport]
[Guid(""A88A175D-2448-447A-B786-64682CBEF156"")]
public interface IRef1
{
void M1(int x);
void M1(ref int x);
void M2(long x);
void M2(ref int x);
void M3(char x);
void M3(ref int x);
void M4(out uint x);
void M4(ref int x);
void M5(ref int x);
void M5(ref long x);
void M6(ref char x);
void M6(ref long x);
void M7(ref long x);
void M7(int x);
void M8(ref long x);
void M8(char x);
void M9(ref char x);
void M9(long x);
}
public class Ref1Impl : IRef1
{
public void M1(int x) { Console.WriteLine(1); }
public void M1(ref int x) { Console.WriteLine(2); }
public void M2(long x) { Console.WriteLine(3); }
public void M2(ref int x) { Console.WriteLine(4); }
public void M3(char x) { Console.WriteLine(5); }
public void M3(ref int x) { Console.WriteLine(6); }
public void M4(out uint x) { x = 0; Console.WriteLine(7); }
public void M4(ref int x) { Console.WriteLine(8); }
public void M5(ref int x) { Console.WriteLine(9); }
public void M5(ref long x) { Console.WriteLine(10); }
public void M6(ref char x) { Console.WriteLine(11); }
public void M6(ref long x) { Console.WriteLine(12); }
public void M7(ref long x) { Console.WriteLine(13); }
public void M7(int x) { Console.WriteLine(14); }
public void M8(ref long x) { Console.WriteLine(15); }
public void M8(char x) { Console.WriteLine(16); }
public void M9(ref char x) { Console.WriteLine(17); }
public void M9(long x) { Console.WriteLine(18); }
}
class Test
{
public static void Main()
{
IRef1 ref1 = new Ref1Impl();
int i = 1;
long l = 1;
char c = 'c';
// void M1(int x);
// void M1(ref int x);
ref1.M1(10L); // CS1503
ref1.M1(l); // CS1503
ref1.M1(ref l); // CS1615
ref1.M1(ref c); // CS1615
// void M2(long x);
// void M2(ref int x);
Console.WriteLine();
ref1.M2(ref l); // CS1615
ref1.M2(ref c); // CS1615
// void M3(char x);
// void M3(ref int x);
Console.WriteLine();
ref1.M3(10L); // CS1503
ref1.M3(l); // CS1503
ref1.M3(ref l); // CS1615
ref1.M3(ref c); // CS1615
// void M4(out uint x);
// void M4(ref int x);
Console.WriteLine();
ref1.M4(10L); // CS1620
ref1.M4(l); // CS1620
ref1.M4(ref l); // CS1620
ref1.M4(ref c); // CS1620
// void M5(ref int x);
// void M5(ref long x);
Console.WriteLine();
ref1.M5(10); // CS0121
ref1.M5('c'); // CS0121
ref1.M5(i); // CS0121
ref1.M5(c); // CS0121
ref1.M5(ref c); // CS1503
// void M6(ref char x);
// void M6(ref long x);
Console.WriteLine();
ref1.M6('c'); // CS0121
ref1.M6(c); // CS0121
ref1.M6(ref i); // CS1503
// void M7(ref long x);
// void M7(int x);
Console.WriteLine();
ref1.M7(ref i); // CS1503
ref1.M7(ref c); // CS1503
// void M8(ref long x);
// void M8(char x);
Console.WriteLine();
ref1.M8(ref i); // CS1503
ref1.M8(ref c); // CS1503
// void M9(ref char x);
// void M9(long x);
Console.WriteLine();
ref1.M9(ref i); // CS1503
ref1.M9(ref l); // CS1503
}
}
";
CreateCompilation(source).VerifyDiagnostics(
// (79,16): error CS1503: Argument 1: cannot convert from 'long' to 'int'
// ref1.M1(10L); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "10L").WithArguments("1", "long", "int"),
// (80,16): error CS1503: Argument 1: cannot convert from 'long' to 'int'
// ref1.M1(l); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("1", "long", "int"),
// (81,20): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// ref1.M1(ref l); // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "l").WithArguments("1", "ref"),
// (82,20): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// ref1.M1(ref c); // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "c").WithArguments("1", "ref"),
// (89,20): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// ref1.M2(ref l); // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "l").WithArguments("1", "ref"),
// (90,20): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// ref1.M2(ref c); // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "c").WithArguments("1", "ref"),
// (97,16): error CS1503: Argument 1: cannot convert from 'long' to 'char'
// ref1.M3(10L); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "10L").WithArguments("1", "long", "char"),
// (98,16): error CS1503: Argument 1: cannot convert from 'long' to 'char'
// ref1.M3(l); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("1", "long", "char"),
// (99,20): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// ref1.M3(ref l); // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "l").WithArguments("1", "ref"),
// (100,20): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// ref1.M3(ref c); // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "c").WithArguments("1", "ref"),
// (107,16): error CS1620: Argument 1 must be passed with the 'out' keyword
// ref1.M4(10L); // CS1620
Diagnostic(ErrorCode.ERR_BadArgRef, "10L").WithArguments("1", "out"),
// (108,16): error CS1620: Argument 1 must be passed with the 'out' keyword
// ref1.M4(l); // CS1620
Diagnostic(ErrorCode.ERR_BadArgRef, "l").WithArguments("1", "out"),
// (109,20): error CS1620: Argument 1 must be passed with the 'out' keyword
// ref1.M4(ref l); // CS1620
Diagnostic(ErrorCode.ERR_BadArgRef, "l").WithArguments("1", "out"),
// (110,20): error CS1620: Argument 1 must be passed with the 'out' keyword
// ref1.M4(ref c); // CS1620
Diagnostic(ErrorCode.ERR_BadArgRef, "c").WithArguments("1", "out"),
// (117,8): error CS0121: The call is ambiguous between the following methods or properties: 'IRef1.M5(ref int)' and 'IRef1.M5(ref long)'
// ref1.M5(10); // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "M5").WithArguments("IRef1.M5(ref int)", "IRef1.M5(ref long)"),
// (118,8): error CS0121: The call is ambiguous between the following methods or properties: 'IRef1.M5(ref int)' and 'IRef1.M5(ref long)'
// ref1.M5('c'); // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "M5").WithArguments("IRef1.M5(ref int)", "IRef1.M5(ref long)"),
// (119,8): error CS0121: The call is ambiguous between the following methods or properties: 'IRef1.M5(ref int)' and 'IRef1.M5(ref long)'
// ref1.M5(i); // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "M5").WithArguments("IRef1.M5(ref int)", "IRef1.M5(ref long)"),
// (120,8): error CS0121: The call is ambiguous between the following methods or properties: 'IRef1.M5(ref int)' and 'IRef1.M5(ref long)'
// ref1.M5(c); // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "M5").WithArguments("IRef1.M5(ref int)", "IRef1.M5(ref long)"),
// (121,20): error CS1503: Argument 1: cannot convert from 'ref char' to 'ref int'
// ref1.M5(ref c); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "c").WithArguments("1", "ref char", "ref int"),
// (128,8): error CS0121: The call is ambiguous between the following methods or properties: 'IRef1.M6(ref char)' and 'IRef1.M6(ref long)'
// ref1.M6('c'); // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "M6").WithArguments("IRef1.M6(ref char)", "IRef1.M6(ref long)"),
// (129,8): error CS0121: The call is ambiguous between the following methods or properties: 'IRef1.M6(ref char)' and 'IRef1.M6(ref long)'
// ref1.M6(c); // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "M6").WithArguments("IRef1.M6(ref char)", "IRef1.M6(ref long)"),
// (130,20): error CS1503: Argument 1: cannot convert from 'ref int' to 'ref char'
// ref1.M6(ref i); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "i").WithArguments("1", "ref int", "ref char"),
// (137,20): error CS1503: Argument 1: cannot convert from 'ref int' to 'ref long'
// ref1.M7(ref i); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "i").WithArguments("1", "ref int", "ref long"),
// (138,20): error CS1503: Argument 1: cannot convert from 'ref char' to 'ref long'
// ref1.M7(ref c); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "c").WithArguments("1", "ref char", "ref long"),
// (145,20): error CS1503: Argument 1: cannot convert from 'ref int' to 'ref long'
// ref1.M8(ref i); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "i").WithArguments("1", "ref int", "ref long"),
// (146,20): error CS1503: Argument 1: cannot convert from 'ref char' to 'ref long'
// ref1.M8(ref c); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "c").WithArguments("1", "ref char", "ref long"),
// (153,20): error CS1503: Argument 1: cannot convert from 'ref int' to 'ref char'
// ref1.M9(ref i); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "i").WithArguments("1", "ref int", "ref char"),
// (154,20): error CS1503: Argument 1: cannot convert from 'ref long' to 'ref char'
// ref1.M9(ref l); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("1", "ref long", "ref char"));
}
[Fact, WorkItem(546176, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546176")]
public void RefOmittedComCall_OverloadResolution_SingleArgument_IndexedProperties()
{
var source1 =
@"
.class interface public abstract import IA
{
.custom instance void [mscorlib]System.Runtime.InteropServices.CoClassAttribute::.ctor(class [mscorlib]System.Type) = ( 01 00 01 41 00 00 )
.custom instance void [mscorlib]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = ( 01 00 24 31 36 35 46 37 35 32 44 2D 45 39 43 34 2D 34 46 37 45 2D 42 30 44 30 2D 43 44 46 44 37 41 33 36 45 32 31 31 00 00 )
.property instance int32 P1(int32)
{
.get instance int32 IA::get_P1(int32)
.set instance void IA::set_P1(int32, int32)
}
.property instance int32 P1(int32&)
{
.get instance int32 IA::get_P1(int32&)
.set instance void IA::set_P1(int32&, int32)
}
.method public abstract virtual instance int32 get_P1(int32 i) { }
.method public abstract virtual instance void set_P1(int32 i, int32 v) { }
.method public abstract virtual instance int32 get_P1(int32& i) { }
.method public abstract virtual instance void set_P1(int32& i, int32 v) { }
.property instance int32 P2(int64)
{
.get instance int32 IA::get_P2(int64)
.set instance void IA::set_P2(int64, int32)
}
.property instance int32 P2(int32&)
{
.get instance int32 IA::get_P2(int32&)
.set instance void IA::set_P2(int32&, int32)
}
.method public abstract virtual instance int32 get_P2(int64 i) { }
.method public abstract virtual instance void set_P2(int64 i, int32 v) { }
.method public abstract virtual instance int32 get_P2(int32& i) { }
.method public abstract virtual instance void set_P2(int32& i, int32 v) { }
.property instance int32 P3(char)
{
.get instance int32 IA::get_P3(char)
.set instance void IA::set_P3(char, int32)
}
.property instance int32 P3(int32&)
{
.get instance int32 IA::get_P3(int32&)
.set instance void IA::set_P3(int32&, int32)
}
.method public abstract virtual instance int32 get_P3(char i) { }
.method public abstract virtual instance void set_P3(char i, int32 v) { }
.method public abstract virtual instance int32 get_P3(int32& i) { }
.method public abstract virtual instance void set_P3(int32& i, int32 v) { }
.property instance int32 P4(int64&)
{
.get instance int32 IA::get_P4(int64&)
.set instance void IA::set_P4(int64&, int32)
}
.property instance int32 P4(int32&)
{
.get instance int32 IA::get_P4(int32&)
.set instance void IA::set_P4(int32&, int32)
}
.method public abstract virtual instance int32 get_P4(int64& i) { }
.method public abstract virtual instance void set_P4(int64& i, int32 v) { }
.method public abstract virtual instance int32 get_P4(int32& i) { }
.method public abstract virtual instance void set_P4(int32& i, int32 v) { }
.property instance int32 P5(int64&)
{
.get instance int32 IA::get_P5(int64&)
.set instance void IA::set_P5(int64&, int32)
}
.property instance int32 P5(char&)
{
.get instance int32 IA::get_P5(char&)
.set instance void IA::set_P5(char&, int32)
}
.method public abstract virtual instance int32 get_P5(int64& i) { }
.method public abstract virtual instance void set_P5(int64& i, int32 v) { }
.method public abstract virtual instance int32 get_P5(char& i) { }
.method public abstract virtual instance void set_P5(char& i, int32 v) { }
.property instance int32 P6(int64&)
{
.get instance int32 IA::get_P6(int64&)
.set instance void IA::set_P6(int64&, int32)
}
.property instance int32 P6(int32)
{
.get instance int32 IA::get_P6(int32)
.set instance void IA::set_P6(int32, int32)
}
.method public abstract virtual instance int32 get_P6(int64& i) { }
.method public abstract virtual instance void set_P6(int64& i, int32 v) { }
.method public abstract virtual instance int32 get_P6(int32 i) { }
.method public abstract virtual instance void set_P6(int32 i, int32 v) { }
.property instance int32 P7(int64&)
{
.get instance int32 IA::get_P7(int64&)
.set instance void IA::set_P7(int64&, int32)
}
.property instance int32 P7(char)
{
.get instance int32 IA::get_P7(char)
.set instance void IA::set_P7(char, int32)
}
.method public abstract virtual instance int32 get_P7(int64& i) { }
.method public abstract virtual instance void set_P7(int64& i, int32 v) { }
.method public abstract virtual instance int32 get_P7(char i) { }
.method public abstract virtual instance void set_P7(char i, int32 v) { }
.property instance int32 P8(int64)
{
.get instance int32 IA::get_P8(int64)
.set instance void IA::set_P8(int64, int32)
}
.property instance int32 P8(char&)
{
.get instance int32 IA::get_P8(char&)
.set instance void IA::set_P8(char&, int32)
}
.method public abstract virtual instance int32 get_P8(int64 i) { }
.method public abstract virtual instance void set_P8(int64 i, int32 v) { }
.method public abstract virtual instance int32 get_P8(char& i) { }
.method public abstract virtual instance void set_P8(char& i, int32 v) { }
}
.class public A implements IA
{
.method public hidebysig specialname rtspecialname instance void .ctor()
{
ret
}
.property instance int32 P1(int32)
{
.get instance int32 A::get_P1(int32)
.set instance void A::set_P1(int32, int32)
}
.property instance int32 P1(int32&)
{
.get instance int32 A::get_P1(int32&)
.set instance void A::set_P1(int32&, int32)
}
.method public virtual instance int32 get_P1(int32 i)
{
ldc.i4.1
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P1(int32 i, int32 v)
{
ldc.i4.2
call void [mscorlib]System.Console::WriteLine(int32)
ret
}
.method public virtual instance int32 get_P1(int32& i)
{
ldc.i4.3
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P1(int32& i, int32 v)
{
ldc.i4.4
call void [mscorlib]System.Console::WriteLine(int32)
ret
}
.property instance int32 P2(int64)
{
.get instance int32 A::get_P2(int64)
.set instance void A::set_P2(int64, int32)
}
.property instance int32 P2(int32&)
{
.get instance int32 A::get_P2(int32&)
.set instance void A::set_P2(int32&, int32)
}
.method public virtual instance int32 get_P2(int64 i)
{
ldc.i4.5
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P2(int64 i, int32 v)
{
ldc.i4.6
call void [mscorlib]System.Console::WriteLine(int32)
ret
}
.method public virtual instance int32 get_P2(int32& i)
{
ldc.i4.7
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P2(int32& i, int32 v)
{
ldc.i4.8
call void [mscorlib]System.Console::WriteLine(int32)
ret
}
.property instance int32 P3(char)
{
.get instance int32 A::get_P3(char)
.set instance void A::set_P3(char, int32)
}
.property instance int32 P3(int32&)
{
.get instance int32 A::get_P3(int32&)
.set instance void A::set_P3(int32&, int32)
}
.method public virtual instance int32 get_P3(char i)
{
ldc.i4.s 9
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P3(char i, int32 v)
{
ldc.i4.s 10
call void [mscorlib]System.Console::WriteLine(int32)
ret
}
.method public virtual instance int32 get_P3(int32& i)
{
ldc.i4.s 11
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P3(int32& i, int32 v)
{
ldc.i4.s 12
call void [mscorlib]System.Console::WriteLine(int32)
ret
}
.property instance int32 P4(int64&)
{
.get instance int32 A::get_P4(int64&)
.set instance void A::set_P4(int64&, int32)
}
.property instance int32 P4(int32&)
{
.get instance int32 A::get_P4(int32&)
.set instance void A::set_P4(int32&, int32)
}
.method public virtual instance int32 get_P4(int64& i)
{
ldc.i4.s 13
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P4(int64& i, int32 v)
{
ldc.i4.s 14
call void [mscorlib]System.Console::WriteLine(int32)
ret
}
.method public virtual instance int32 get_P4(int32& i)
{
ldc.i4.s 15
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P4(int32& i, int32 v)
{
ldc.i4.s 16
call void [mscorlib]System.Console::WriteLine(int32)
ret
}
.property instance int32 P5(int64&)
{
.get instance int32 A::get_P5(int64&)
.set instance void A::set_P5(int64&, int32)
}
.property instance int32 P5(char&)
{
.get instance int32 A::get_P5(char&)
.set instance void A::set_P5(char&, int32)
}
.method public virtual instance int32 get_P5(int64& i)
{
ldc.i4.s 17
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P5(int64& i, int32 v)
{
ldc.i4.s 18
call void [mscorlib]System.Console::WriteLine(int32)
ret
}
.method public virtual instance int32 get_P5(char& i)
{
ldc.i4.s 19
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P5(char& i, int32 v)
{
ldc.i4.s 20
call void [mscorlib]System.Console::WriteLine(int32)
ret
}
.property instance int32 P6(int64&)
{
.get instance int32 A::get_P6(int64&)
.set instance void A::set_P6(int64&, int32)
}
.property instance int32 P6(int32)
{
.get instance int32 A::get_P6(int32)
.set instance void A::set_P6(int32, int32)
}
.method public virtual instance int32 get_P6(int64& i)
{
ldc.i4.s 21
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P6(int64& i, int32 v)
{
ldc.i4.s 22
call void [mscorlib]System.Console::WriteLine(int32)
ret
}
.method public virtual instance int32 get_P6(int32 i)
{
ldc.i4.s 23
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P6(int32 i, int32 v)
{
ldc.i4.s 24
call void [mscorlib]System.Console::WriteLine(int32)
ret
}
.property instance int32 P7(int64&)
{
.get instance int32 A::get_P7(int64&)
.set instance void A::set_P7(int64&, int32)
}
.property instance int32 P7(char)
{
.get instance int32 A::get_P7(char)
.set instance void A::set_P7(char, int32)
}
.method public virtual instance int32 get_P7(int64& i)
{
ldc.i4.s 25
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P7(int64& i, int32 v)
{
ldc.i4.s 26
call void [mscorlib]System.Console::WriteLine(int32)
ret
}
.method public virtual instance int32 get_P7(char i)
{
ldc.i4.s 27
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P7(char i, int32 v)
{
ldc.i4.s 28
call void [mscorlib]System.Console::WriteLine(int32)
ret
}
.property instance int32 P8(int64)
{
.get instance int32 A::get_P8(int64)
.set instance void A::set_P8(int64, int32)
}
.property instance int32 P8(char&)
{
.get instance int32 A::get_P8(char&)
.set instance void A::set_P8(char&, int32)
}
.method public virtual instance int32 get_P8(int64 i)
{
ldc.i4.s 29
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P8(int64 i, int32 v)
{
ldc.i4.s 30
call void [mscorlib]System.Console::WriteLine(int32)
ret
}
.method public virtual instance int32 get_P8(char& i)
{
ldc.i4.s 31
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P8(char& i, int32 v)
{
ldc.i4.s 32
call void [mscorlib]System.Console::WriteLine(int32)
ret
}
}
";
var source2 =
@"
using System;
using System.Runtime.InteropServices;
class Test
{
public static void Main()
{
IA a = new A();
int i = 1;
long l = 1;
char c = 'c';
int value;
// int P1(int) { get; set; }
// int P1(ref int) { get; set; }
value = a.P1[10];
a.P1[10] = value;
//value = a.P1[10L]; CS1503
//a.P1[10L] = value; CS1503
value = a.P1['c'];
a.P1['c'] = value;
value = a.P1[i];
a.P1[i] = value;
//value = a.P1[l]; CS1503
//a.P1[l] = value; CS1503
value = a.P1[c];
a.P1[c] = value;
value = a.P1[ref i];
a.P1[ref i] = value;
//value = a.P1[ref l]; CS1615
//a.P1[ref l] = value; CS1615
//value = a.P1[ref c]; CS1615
//a.P1[ref c] = value; CS1615
// int P2(long) { get; set; }
// int P2(ref int) { get; set; }
Console.WriteLine();
value = a.P2[10];
a.P2[10] = value;
value = a.P2[10L];
a.P2[10L] = value;
value = a.P2['c'];
a.P2['c'] = value;
value = a.P2[i];
a.P2[i] = value;
value = a.P2[l];
a.P2[l] = value;
value = a.P2[c];
a.P2[c] = value;
value = a.P2[ref i];
a.P2[ref i] = value;
//value = a.P2[ref l]; CS1615
//a.P2[ref l] = value; CS1615
//value = a.P2[ref c]; CS1615
//a.P2[ref c] = value; CS1615
// int P3(char) { get; set; }
// int P3(ref int) { get; set; }
Console.WriteLine();
value = a.P3[10];
a.P3[10] = value;
//value = a.P3[10L]; CS1503
//a.P3[10L] = value; CS1503
value = a.P3['c'];
a.P3['c'] = value;
value = a.P3[i];
a.P3[i] = value;
//value = a.P3[l]; CS1503
//a.P3[l] = value; CS1503
value = a.P3[c];
a.P3[c] = value;
value = a.P3[ref i];
a.P3[ref i] = value;
//value = a.P3[ref l]; CS1615
//a.P3[ref l] = value; CS1615
//value = a.P3[ref c]; CS1615
//a.P3[ref c] = value; CS1615
// int P4(ref int) { get; set; }
// int P4(ref long) { get; set; }
Console.WriteLine();
//value = a.P4[10]; CS0121
//a.P4[10] = value; CS0121
value = a.P4[10L];
a.P4[10L] = value;
//value = a.P4['c']; CS0121
//a.P4['c'] = value; CS0121
//value = a.P4[i]; CS0121
//a.P4[i] = value; CS0121
value = a.P4[l];
a.P4[l] = value;
//value = a.P4[c]; CS0121
//a.P4[c] = value; CS0121
value = a.P4[ref i];
a.P4[ref i] = value;
value = a.P4[ref l];
a.P4[ref l] = value;
//value = a.P4[ref c]; CS1503
//a.P4[ref c] = value; CS1503
// int P5(ref char) { get; set; }
// int P5(ref long) { get; set; }
Console.WriteLine();
value = a.P5[10];
a.P5[10] = value;
value = a.P5[10L];
a.P5[10L] = value;
//value = a.P5['c']; CS0121
//a.P5['c'] = value; CS0121
value = a.P5[i];
a.P5[i] = value;
value = a.P5[l];
a.P5[l] = value;
//value = a.P5[c]; CS0121
//a.P5[c] = value; CS0121
//value = a.P5[ref i]; CS1503
//a.P5[ref i] = value; CS1503
value = a.P5[ref l];
a.P5[ref l] = value;
value = a.P5[ref c];
a.P5[ref c] = value;
// int P6(ref long) { get; set; }
// int P6(int) { get; set; }
Console.WriteLine();
value = a.P6[10];
a.P6[10] = value;
value = a.P6[10L];
a.P6[10L] = value;
value = a.P6['c'];
a.P6['c'] = value;
value = a.P6[i];
a.P6[i] = value;
value = a.P6[l];
a.P6[l] = value;
value = a.P6[c];
a.P6[c] = value;
//value = a.P6[ref i]; CS1503
//a.P6[ref i] = value; CS1503
value = a.P6[ref l];
a.P6[ref l] = value;
//value = a.P6[ref c]; CS1503
//a.P6[ref c] = value; CS1503
// int P7(ref long) { get; set; }
// int P7(char) { get; set; }
Console.WriteLine();
value = a.P7[10];
a.P7[10] = value;
value = a.P7[10L];
a.P7[10L] = value;
value = a.P7['c'];
a.P7['c'] = value;
value = a.P7[i];
a.P7[i] = value;
value = a.P7[l];
a.P7[l] = value;
value = a.P7[c];
a.P7[c] = value;
//value = a.P7[ref i]; CS1503
//a.P7[ref i] = value; CS1503
value = a.P7[ref l];
a.P7[ref l] = value;
//value = a.P7[ref c]; CS1503
//a.P7[ref c] = value; CS1503
// int P8(ref char) { get; set; }
// int P8(long) { get; set; }
Console.WriteLine();
value = a.P8[10];
a.P8[10] = value;
value = a.P8[10L];
a.P8[10L] = value;
value = a.P8['c'];
a.P8['c'] = value;
value = a.P8[i];
a.P8[i] = value;
value = a.P8[l];
a.P8[l] = value;
value = a.P8[c];
a.P8[c] = value;
//value = a.P8[ref i]; CS1615
//a.P8[ref i] = value; CS1615
//value = a.P8[ref l]; CS1615
//a.P8[ref l] = value; CS1615
value = a.P8[ref c];
a.P8[ref c] = value;
}
}
";
var expectedOutput = @"1
2
1
2
1
2
1
2
3
4
5
6
5
6
5
6
5
6
5
6
5
6
7
8
11
12
9
10
11
12
9
10
11
12
13
14
13
14
15
16
13
14
17
18
17
18
17
18
17
18
17
18
19
20
23
24
21
22
23
24
23
24
21
22
23
24
21
22
25
26
25
26
27
28
25
26
25
26
27
28
25
26
29
30
29
30
29
30
29
30
29
30
29
30
31
32";
var compilation = CreateCompilationWithILAndMscorlib40(source2, source1, options: TestOptions.ReleaseExe);
CompileAndVerify(compilation, expectedOutput: expectedOutput);
}
[Fact, WorkItem(546176, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546176")]
public void RefOmittedComCall_OverloadResolution_SingleArgument_IndexedProperties_ErrorCases()
{
var source1 =
@"
.class interface public abstract import IA
{
.custom instance void [mscorlib]System.Runtime.InteropServices.CoClassAttribute::.ctor(class [mscorlib]System.Type) = ( 01 00 01 41 00 00 )
.custom instance void [mscorlib]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = ( 01 00 24 31 36 35 46 37 35 32 44 2D 45 39 43 34 2D 34 46 37 45 2D 42 30 44 30 2D 43 44 46 44 37 41 33 36 45 32 31 31 00 00 )
.property instance int32 P1(int32)
{
.get instance int32 IA::get_P1(int32)
.set instance void IA::set_P1(int32, int32)
}
.property instance int32 P1(int32&)
{
.get instance int32 IA::get_P1(int32&)
.set instance void IA::set_P1(int32&, int32)
}
.method public abstract virtual instance int32 get_P1(int32 i) { }
.method public abstract virtual instance void set_P1(int32 i, int32 v) { }
.method public abstract virtual instance int32 get_P1(int32& i) { }
.method public abstract virtual instance void set_P1(int32& i, int32 v) { }
.property instance int32 P2(int64)
{
.get instance int32 IA::get_P2(int64)
.set instance void IA::set_P2(int64, int32)
}
.property instance int32 P2(int32&)
{
.get instance int32 IA::get_P2(int32&)
.set instance void IA::set_P2(int32&, int32)
}
.method public abstract virtual instance int32 get_P2(int64 i) { }
.method public abstract virtual instance void set_P2(int64 i, int32 v) { }
.method public abstract virtual instance int32 get_P2(int32& i) { }
.method public abstract virtual instance void set_P2(int32& i, int32 v) { }
.property instance int32 P3(char)
{
.get instance int32 IA::get_P3(char)
.set instance void IA::set_P3(char, int32)
}
.property instance int32 P3(int32&)
{
.get instance int32 IA::get_P3(int32&)
.set instance void IA::set_P3(int32&, int32)
}
.method public abstract virtual instance int32 get_P3(char i) { }
.method public abstract virtual instance void set_P3(char i, int32 v) { }
.method public abstract virtual instance int32 get_P3(int32& i) { }
.method public abstract virtual instance void set_P3(int32& i, int32 v) { }
.property instance int32 P4(int64&)
{
.get instance int32 IA::get_P4(int64&)
.set instance void IA::set_P4(int64&, int32)
}
.property instance int32 P4(int32&)
{
.get instance int32 IA::get_P4(int32&)
.set instance void IA::set_P4(int32&, int32)
}
.method public abstract virtual instance int32 get_P4(int64& i) { }
.method public abstract virtual instance void set_P4(int64& i, int32 v) { }
.method public abstract virtual instance int32 get_P4(int32& i) { }
.method public abstract virtual instance void set_P4(int32& i, int32 v) { }
.property instance int32 P5(int64&)
{
.get instance int32 IA::get_P5(int64&)
.set instance void IA::set_P5(int64&, int32)
}
.property instance int32 P5(char&)
{
.get instance int32 IA::get_P5(char&)
.set instance void IA::set_P5(char&, int32)
}
.method public abstract virtual instance int32 get_P5(int64& i) { }
.method public abstract virtual instance void set_P5(int64& i, int32 v) { }
.method public abstract virtual instance int32 get_P5(char& i) { }
.method public abstract virtual instance void set_P5(char& i, int32 v) { }
.property instance int32 P6(int64&)
{
.get instance int32 IA::get_P6(int64&)
.set instance void IA::set_P6(int64&, int32)
}
.property instance int32 P6(int32)
{
.get instance int32 IA::get_P6(int32)
.set instance void IA::set_P6(int32, int32)
}
.method public abstract virtual instance int32 get_P6(int64& i) { }
.method public abstract virtual instance void set_P6(int64& i, int32 v) { }
.method public abstract virtual instance int32 get_P6(int32 i) { }
.method public abstract virtual instance void set_P6(int32 i, int32 v) { }
.property instance int32 P7(int64&)
{
.get instance int32 IA::get_P7(int64&)
.set instance void IA::set_P7(int64&, int32)
}
.property instance int32 P7(char)
{
.get instance int32 IA::get_P7(char)
.set instance void IA::set_P7(char, int32)
}
.method public abstract virtual instance int32 get_P7(int64& i) { }
.method public abstract virtual instance void set_P7(int64& i, int32 v) { }
.method public abstract virtual instance int32 get_P7(char i) { }
.method public abstract virtual instance void set_P7(char i, int32 v) { }
.property instance int32 P8(int64)
{
.get instance int32 IA::get_P8(int64)
.set instance void IA::set_P8(int64, int32)
}
.property instance int32 P8(char&)
{
.get instance int32 IA::get_P8(char&)
.set instance void IA::set_P8(char&, int32)
}
.method public abstract virtual instance int32 get_P8(int64 i) { }
.method public abstract virtual instance void set_P8(int64 i, int32 v) { }
.method public abstract virtual instance int32 get_P8(char& i) { }
.method public abstract virtual instance void set_P8(char& i, int32 v) { }
}
.class public A implements IA
{
.method public hidebysig specialname rtspecialname instance void .ctor()
{
ret
}
.property instance int32 P1(int32)
{
.get instance int32 A::get_P1(int32)
.set instance void A::set_P1(int32, int32)
}
.property instance int32 P1(int32&)
{
.get instance int32 A::get_P1(int32&)
.set instance void A::set_P1(int32&, int32)
}
.method public virtual instance int32 get_P1(int32 i)
{
ldc.i4.1
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P1(int32 i, int32 v)
{
ldc.i4.2
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance int32 get_P1(int32& i)
{
ldc.i4.3
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P1(int32& i, int32 v)
{
ldc.i4.4
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.property instance int32 P2(int64)
{
.get instance int32 A::get_P2(int64)
.set instance void A::set_P2(int64, int32)
}
.property instance int32 P2(int32&)
{
.get instance int32 A::get_P2(int32&)
.set instance void A::set_P2(int32&, int32)
}
.method public virtual instance int32 get_P2(int64 i)
{
ldc.i4.5
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P2(int64 i, int32 v)
{
ldc.i4.6
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance int32 get_P2(int32& i)
{
ldc.i4.7
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P2(int32& i, int32 v)
{
ldc.i4.8
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.property instance int32 P3(char)
{
.get instance int32 A::get_P3(char)
.set instance void A::set_P3(char, int32)
}
.property instance int32 P3(int32&)
{
.get instance int32 A::get_P3(int32&)
.set instance void A::set_P3(int32&, int32)
}
.method public virtual instance int32 get_P3(char i)
{
ldc.i4.s 9
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P3(char i, int32 v)
{
ldc.i4.s 10
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance int32 get_P3(int32& i)
{
ldc.i4.s 11
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P3(int32& i, int32 v)
{
ldc.i4.s 12
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.property instance int32 P4(int64&)
{
.get instance int32 A::get_P4(int64&)
.set instance void A::set_P4(int64&, int32)
}
.property instance int32 P4(int32&)
{
.get instance int32 A::get_P4(int32&)
.set instance void A::set_P4(int32&, int32)
}
.method public virtual instance int32 get_P4(int64& i)
{
ldc.i4.s 13
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P4(int64& i, int32 v)
{
ldc.i4.s 14
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance int32 get_P4(int32& i)
{
ldc.i4.s 15
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P4(int32& i, int32 v)
{
ldc.i4.s 16
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.property instance int32 P5(int64&)
{
.get instance int32 A::get_P5(int64&)
.set instance void A::set_P5(int64&, int32)
}
.property instance int32 P5(char&)
{
.get instance int32 A::get_P5(char&)
.set instance void A::set_P5(char&, int32)
}
.method public virtual instance int32 get_P5(int64& i)
{
ldc.i4.s 17
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P5(int64& i, int32 v)
{
ldc.i4.s 18
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance int32 get_P5(char& i)
{
ldc.i4.s 19
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P5(char& i, int32 v)
{
ldc.i4.s 20
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.property instance int32 P6(int64&)
{
.get instance int32 A::get_P6(int64&)
.set instance void A::set_P6(int64&, int32)
}
.property instance int32 P6(int32)
{
.get instance int32 A::get_P6(int32)
.set instance void A::set_P6(int32, int32)
}
.method public virtual instance int32 get_P6(int64& i)
{
ldc.i4.s 21
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P6(int64& i, int32 v)
{
ldc.i4.s 22
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance int32 get_P6(int32 i)
{
ldc.i4.s 23
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P6(int32 i, int32 v)
{
ldc.i4.s 24
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.property instance int32 P7(int64&)
{
.get instance int32 A::get_P7(int64&)
.set instance void A::set_P7(int64&, int32)
}
.property instance int32 P7(char)
{
.get instance int32 A::get_P7(char)
.set instance void A::set_P7(char, int32)
}
.method public virtual instance int32 get_P7(int64& i)
{
ldc.i4.s 25
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P7(int64& i, int32 v)
{
ldc.i4.s 26
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance int32 get_P7(char i)
{
ldc.i4.s 27
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P7(char i, int32 v)
{
ldc.i4.s 28
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.property instance int32 P8(int64)
{
.get instance int32 A::get_P8(int64)
.set instance void A::set_P8(int64, int32)
}
.property instance int32 P8(char&)
{
.get instance int32 A::get_P8(char&)
.set instance void A::set_P8(char&, int32)
}
.method public virtual instance int32 get_P8(int64 i)
{
ldc.i4.s 29
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P8(int64 i, int32 v)
{
ldc.i4.s 30
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance int32 get_P8(char& i)
{
ldc.i4.s 31
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
.method public virtual instance void set_P8(char& i, int32 v)
{
ldc.i4.s 32
call void [mscorlib]System.Console::WriteLine(int32)
ldc.i4.0
ret
}
}
";
var source2 =
@"
class Test
{
public static void Main()
{
IA a = new A();
int i = 1;
long l = 1;
char c = 'c';
int value;
// int P1(int) { get; set; }
// int P1(ref int) { get; set; }
value = a.P1[10L]; // CS1503
a.P1[10L] = value; // CS1503
value = a.P1[l]; // CS1503
a.P1[l] = value; // CS1503
value = a.P1[ref l]; // CS1615
a.P1[ref l] = value; // CS1615
value = a.P1[ref c]; // CS1615
a.P1[ref c] = value; // CS1615
// int P2(long) { get; set; }
// int P2(ref int) { get; set; }
value = a.P2[ref l]; // CS1615
a.P2[ref l] = value; // CS1615
value = a.P2[ref c]; // CS1615
a.P2[ref c] = value; // CS1615
// int P3(char) { get; set; }
// int P3(ref int) { get; set; }
value = a.P3[10L]; // CS1503
a.P3[10L] = value; // CS1503
value = a.P3[l]; // CS1503
a.P3[l] = value; // CS1503
value = a.P3[ref l]; // CS1615
a.P3[ref l] = value; // CS1615
value = a.P3[ref c]; // CS1615
a.P3[ref c] = value; // CS1615
// int P4(ref int) { get; set; }
// int P4(ref long) { get; set; }
value = a.P4[10]; // CS0121
a.P4[10] = value; // CS0121
value = a.P4['c']; // CS0121
a.P4['c'] = value; // CS0121
value = a.P4[i]; // CS0121
a.P4[i] = value; // CS0121
value = a.P4[c]; // CS0121
a.P4[c] = value; // CS0121
value = a.P4[ref c]; // CS1503
a.P4[ref c] = value; // CS1503
// int P5(ref char) { get; set; }
// int P5(ref long) { get; set; }
value = a.P5['c']; // CS0121
a.P5['c'] = value; // CS0121
value = a.P5[c]; // CS0121
a.P5[c] = value; // CS0121
value = a.P5[ref i]; // CS1503
a.P5[ref i] = value; // CS1503
// int P6(ref long) { get; set; }
// int P6(int) { get; set; }
value = a.P6[ref i]; // CS1503
a.P6[ref i] = value; // CS1503
value = a.P6[ref c]; // CS1503
a.P6[ref c] = value; // CS1503
// int P7(ref long) { get; set; }
// int P7(char) { get; set; }
value = a.P7[ref i]; // CS1503
a.P7[ref i] = value; // CS1503
value = a.P7[ref c]; // CS1503
a.P7[ref c] = value; // CS1503
// int P8(ref char) { get; set; }
// int P8(long) { get; set; }
value = a.P8[ref i]; // CS1615
a.P8[ref i] = value; // CS1615
value = a.P8[ref l]; // CS1615
a.P8[ref l] = value; // CS1615
}
}
";
CreateCompilationWithILAndMscorlib40(source2, source1).VerifyDiagnostics(
// (15,21): error CS1503: Argument 1: cannot convert from 'long' to 'int'
// value = a.P1[10L]; // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "10L").WithArguments("1", "long", "int"),
// (16,13): error CS1503: Argument 1: cannot convert from 'long' to 'int'
// a.P1[10L] = value; // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "10L").WithArguments("1", "long", "int"),
// (17,21): error CS1503: Argument 1: cannot convert from 'long' to 'int'
// value = a.P1[l]; // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("1", "long", "int"),
// (18,13): error CS1503: Argument 1: cannot convert from 'long' to 'int'
// a.P1[l] = value; // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("1", "long", "int"),
// (19,25): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// value = a.P1[ref l]; // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "l").WithArguments("1", "ref"),
// (20,17): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// a.P1[ref l] = value; // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "l").WithArguments("1", "ref"),
// (21,25): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// value = a.P1[ref c]; // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "c").WithArguments("1", "ref"),
// (22,17): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// a.P1[ref c] = value; // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "c").WithArguments("1", "ref"),
// (27,25): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// value = a.P2[ref l]; // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "l").WithArguments("1", "ref"),
// (28,17): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// a.P2[ref l] = value; // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "l").WithArguments("1", "ref"),
// (29,25): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// value = a.P2[ref c]; // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "c").WithArguments("1", "ref"),
// (30,17): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// a.P2[ref c] = value; // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "c").WithArguments("1", "ref"),
// (35,21): error CS1503: Argument 1: cannot convert from 'long' to 'char'
// value = a.P3[10L]; // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "10L").WithArguments("1", "long", "char"),
// (36,13): error CS1503: Argument 1: cannot convert from 'long' to 'char'
// a.P3[10L] = value; // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "10L").WithArguments("1", "long", "char"),
// (37,21): error CS1503: Argument 1: cannot convert from 'long' to 'char'
// value = a.P3[l]; // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("1", "long", "char"),
// (38,13): error CS1503: Argument 1: cannot convert from 'long' to 'char'
// a.P3[l] = value; // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("1", "long", "char"),
// (39,25): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// value = a.P3[ref l]; // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "l").WithArguments("1", "ref"),
// (40,17): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// a.P3[ref l] = value; // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "l").WithArguments("1", "ref"),
// (41,25): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// value = a.P3[ref c]; // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "c").WithArguments("1", "ref"),
// (42,17): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// a.P3[ref c] = value; // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "c").WithArguments("1", "ref"),
// (47,16): error CS0121: The call is ambiguous between the following methods or properties: 'IA.P4[ref long]' and 'IA.P4[ref int]'
// value = a.P4[10]; // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "a.P4[10]").WithArguments("IA.P4[ref long]", "IA.P4[ref int]"),
// (58,8): error CS0121: The call is ambiguous between the following methods or properties: 'IA.P4[ref long]' and 'IA.P4[ref int]'
// a.P4[10] = value; // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "a.P4[10]").WithArguments("IA.P4[ref long]", "IA.P4[ref int]"),
// (49,16): error CS0121: The call is ambiguous between the following methods or properties: 'IA.P4[ref long]' and 'IA.P4[ref int]'
// value = a.P4['c']; // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "a.P4['c']").WithArguments("IA.P4[ref long]", "IA.P4[ref int]"),
// (50,8): error CS0121: The call is ambiguous between the following methods or properties: 'IA.P4[ref long]' and 'IA.P4[ref int]'
// a.P4['c'] = value; // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "a.P4['c']").WithArguments("IA.P4[ref long]", "IA.P4[ref int]"),
// (51,16): error CS0121: The call is ambiguous between the following methods or properties: 'IA.P4[ref long]' and 'IA.P4[ref int]'
// value = a.P4[i]; // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "a.P4[i]").WithArguments("IA.P4[ref long]", "IA.P4[ref int]"),
// (52,8): error CS0121: The call is ambiguous between the following methods or properties: 'IA.P4[ref long]' and 'IA.P4[ref int]'
// a.P4[i] = value; // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "a.P4[i]").WithArguments("IA.P4[ref long]", "IA.P4[ref int]"),
// (53,16): error CS0121: The call is ambiguous between the following methods or properties: 'IA.P4[ref long]' and 'IA.P4[ref int]'
// value = a.P4[c]; // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "a.P4[c]").WithArguments("IA.P4[ref long]", "IA.P4[ref int]"),
// (54,8): error CS0121: The call is ambiguous between the following methods or properties: 'IA.P4[ref long]' and 'IA.P4[ref int]'
// a.P4[c] = value; // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "a.P4[c]").WithArguments("IA.P4[ref long]", "IA.P4[ref int]"),
// (55,25): error CS1503: Argument 1: cannot convert from 'ref char' to 'ref long'
// value = a.P4[ref c]; // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "c").WithArguments("1", "ref char", "ref long"),
// (56,17): error CS1503: Argument 1: cannot convert from 'ref char' to 'ref long'
// a.P4[ref c] = value; // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "c").WithArguments("1", "ref char", "ref long"),
// (61,16): error CS0121: The call is ambiguous between the following methods or properties: 'IA.P5[ref long]' and 'IA.P5[ref char]'
// value = a.P5['c']; // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "a.P5['c']").WithArguments("IA.P5[ref long]", "IA.P5[ref char]"),
// (62,8): error CS0121: The call is ambiguous between the following methods or properties: 'IA.P5[ref long]' and 'IA.P5[ref char]'
// a.P5['c'] = value; // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "a.P5['c']").WithArguments("IA.P5[ref long]", "IA.P5[ref char]"),
// (63,16): error CS0121: The call is ambiguous between the following methods or properties: 'IA.P5[ref long]' and 'IA.P5[ref char]'
// value = a.P5[c]; // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "a.P5[c]").WithArguments("IA.P5[ref long]", "IA.P5[ref char]"),
// (64,8): error CS0121: The call is ambiguous between the following methods or properties: 'IA.P5[ref long]' and 'IA.P5[ref char]'
// a.P5[c] = value; // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "a.P5[c]").WithArguments("IA.P5[ref long]", "IA.P5[ref char]"),
// (65,25): error CS1503: Argument 1: cannot convert from 'ref int' to 'ref long'
// value = a.P5[ref i]; // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "i").WithArguments("1", "ref int", "ref long"),
// (66,17): error CS1503: Argument 1: cannot convert from 'ref int' to 'ref long'
// a.P5[ref i] = value; // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "i").WithArguments("1", "ref int", "ref long"),
// (71,25): error CS1503: Argument 1: cannot convert from 'ref int' to 'ref long'
// value = a.P6[ref i]; // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "i").WithArguments("1", "ref int", "ref long"),
// (72,17): error CS1503: Argument 1: cannot convert from 'ref int' to 'ref long'
// a.P6[ref i] = value; // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "i").WithArguments("1", "ref int", "ref long"),
// (73,25): error CS1503: Argument 1: cannot convert from 'ref char' to 'ref long'
// value = a.P6[ref c]; // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "c").WithArguments("1", "ref char", "ref long"),
// (74,17): error CS1503: Argument 1: cannot convert from 'ref char' to 'ref long'
// a.P6[ref c] = value; // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "c").WithArguments("1", "ref char", "ref long"),
// (79,25): error CS1503: Argument 1: cannot convert from 'ref int' to 'ref long'
// value = a.P7[ref i]; // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "i").WithArguments("1", "ref int", "ref long"),
// (80,17): error CS1503: Argument 1: cannot convert from 'ref int' to 'ref long'
// a.P7[ref i] = value; // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "i").WithArguments("1", "ref int", "ref long"),
// (81,25): error CS1503: Argument 1: cannot convert from 'ref char' to 'ref long'
// value = a.P7[ref c]; // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "c").WithArguments("1", "ref char", "ref long"),
// (82,17): error CS1503: Argument 1: cannot convert from 'ref char' to 'ref long'
// a.P7[ref c] = value; // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "c").WithArguments("1", "ref char", "ref long"),
// (87,25): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// value = a.P8[ref i]; // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "i").WithArguments("1", "ref"),
// (88,17): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// a.P8[ref i] = value; // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "i").WithArguments("1", "ref"),
// (89,25): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// value = a.P8[ref l]; // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "l").WithArguments("1", "ref"),
// (90,17): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// a.P8[ref l] = value; // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "l").WithArguments("1", "ref"));
}
[Fact]
public void RefOmittedComCall_OverloadResolution_MultipleArguments()
{
var source =
@"
using System;
using System.Runtime.InteropServices;
[ComImport]
[Guid(""A88A175D-2448-447A-B786-64682CBEF156"")]
public interface IRef1
{
void M1(int x, long y);
void M1(ref int x, int y);
void M2(int x, char y);
void M2(ref int x, int y);
void M3(ref int x, char y);
void M3(ref long x, int y);
void M4(ref int x, long y);
void M4(ref int x, ref int y);
void M5(ref int x, char y);
void M5(ref long x, int y);
void M6(ref int x, int y);
void M6(ref long x, int y);
void M7(ref int x, long y);
void M7(ref long x, ref int y);
void M8(long x, ref int y);
void M8(ref long x, int y);
void M9(ref long x, ref int y);
void M9(ref int x, ref long y);
}
public class Ref1Impl : IRef1
{
public void M1(int x, long y) { Console.WriteLine(1); }
public void M1(ref int x, int y) { Console.WriteLine(2); }
public void M2(int x, char y) { Console.WriteLine(3); }
public void M2(ref int x, int y) { Console.WriteLine(4); }
public void M3(ref int x, char y) { Console.WriteLine(5); }
public void M3(ref long x, int y) { Console.WriteLine(6); }
public void M4(ref int x, long y) { Console.WriteLine(7); }
public void M4(ref int x, ref int y) { Console.WriteLine(8); }
public void M5(ref int x, char y) { Console.WriteLine(9); }
public void M5(ref long x, int y) { Console.WriteLine(10); }
public void M6(ref int x, int y) { Console.WriteLine(11); }
public void M6(ref long x, int y) { Console.WriteLine(12); }
public void M7(ref int x, long y) { Console.WriteLine(13); }
public void M7(ref long x, ref int y) { Console.WriteLine(14); }
public void M8(long x, ref int y) { Console.WriteLine(15); }
public void M8(ref long x, int y) { Console.WriteLine(16); }
public void M9(ref long x, ref int y) { Console.WriteLine(17); }
public void M9(ref int x, ref long y) { Console.WriteLine(18); }
}
class Test
{
public static void Main()
{
IRef1 ref1 = new Ref1Impl();
int i = 1;
long l = 1;
char c = 'c';
// void M1(int x, long y);
// void M1(ref int x, int y);
ref1.M1(i, i);
ref1.M1(i, l);
ref1.M1(i, c);
//ref1.M1(l, i); CS1503
//ref1.M1(l, l); CS1503
//ref1.M1(l, c); CS1503
ref1.M1(c, i);
ref1.M1(c, l);
ref1.M1(c, c);
ref1.M1(ref i, i);
//ref1.M1(ref i, l); CS1615
ref1.M1(ref i, c);
//ref1.M1(ref l, i); CS1615
//ref1.M1(ref l, l); CS1615
//ref1.M1(ref l, c); CS1615
//ref1.M1(ref c, i); CS1615
//ref1.M1(ref c, l); CS1615
//ref1.M1(ref c, c); CS1615
// void M2(int x, char y);
// void M2(ref int x, int y);
Console.WriteLine();
ref1.M2(i, i);
//ref1.M2(i, l); CS1503
ref1.M2(i, c);
//ref1.M2(l, i); CS1503, CS1503
//ref1.M2(l, l); CS1503, CS1503
//ref1.M2(l, c); CS1503
ref1.M2(c, i);
//ref1.M2(c, l); CS1503
ref1.M2(c, c);
ref1.M2(ref i, i);
//ref1.M2(ref i, l); CS1615, CS1503
ref1.M2(ref i, c);
//ref1.M2(ref l, i); CS1615, CS1503
//ref1.M2(ref l, l); CS1615, CS1503
//ref1.M2(ref l, c); CS1615
//ref1.M2(ref c, i); CS1615, CS1503
//ref1.M2(ref c, l); CS1615, CS1503
//ref1.M2(ref c, c); CS1615
// void M3(ref int x, char y);
// void M3(ref long x, int y);
Console.WriteLine();
ref1.M3(i, i);
//ref1.M3(i, l); CS1503
ref1.M3(i, c);
ref1.M3(l, i);
//ref1.M3(l, l); CS1620, CS1503
ref1.M3(l, c);
ref1.M3(c, i);
//ref1.M3(c, l); CS1503
ref1.M3(c, c);
//ref1.M3(ref i, i); CS1503
//ref1.M3(ref i, l); CS1503
ref1.M3(ref i, c);
ref1.M3(ref l, i);
//ref1.M3(ref l, l); CS1503, CS1503
ref1.M3(ref l, c);
//ref1.M3(ref c, i); CS1503, CS1503
//ref1.M3(ref c, l); CS1503, CS1503
//ref1.M3(ref c, c); CS1503
// void M4(ref int x, long y);
// void M4(ref int x, ref int y);
Console.WriteLine();
//ref1.M4(i, i); CS0121
ref1.M4(i, l);
//ref1.M4(i, c); CS0121
//ref1.M4(l, i); CS1620
//ref1.M4(l, l); CS1620
//ref1.M4(l, c); CS1620
//ref1.M4(c, i); CS0121
ref1.M4(c, l);
//ref1.M4(c, c); CS0121
ref1.M4(i, ref i);
//ref1.M4(l, ref i); CS1620, CS1615
ref1.M4(c, ref i);
//ref1.M4(i, ref l); CS1615
//ref1.M4(l, ref l); CS1620
//ref1.M4(c, ref l); CS1615
ref1.M4(ref i, i);
ref1.M4(ref i, l);
ref1.M4(ref i, c);
ref1.M4(ref i, ref i);
// void M5(ref int x, char y);
// void M5(ref long x, int y);
Console.WriteLine();
ref1.M5(i, i);
//ref1.M5(i, l); CS1503
ref1.M5(i, c);
ref1.M5(l, i);
//ref1.M5(l, l); CS1620, CS1503
ref1.M5(l, c);
ref1.M5(c, i);
//ref1.M5(c, l); CS1503
ref1.M5(c, c);
//ref1.M5(ref i, i); CS1503
//ref1.M5(ref i, l); CS1503
ref1.M5(ref i, c);
ref1.M5(ref l, i);
//ref1.M5(ref l, l); CS1503
ref1.M5(ref l, c);
// void M6(ref int x, int y);
// void M6(ref long x, int y);
Console.WriteLine();
//ref1.M6(i, i); CS0121
//ref1.M6(i, l); CS1503
//ref1.M6(i, c); CS0121
ref1.M6(l, i);
//ref1.M6(l, l); CS1620, CS1503
ref1.M6(l, c);
//ref1.M6(c, i); CS0121
//ref1.M6(c, l); CS1503
//ref1.M6(c, c); CS0121
ref1.M6(ref i, i);
//ref1.M6(ref i, l); CS1503
ref1.M6(ref i, c);
ref1.M6(ref l, i);
//ref1.M6(ref l, l); CS1503, CS1503
ref1.M6(ref l, c);
// void M7(ref int x, long y);
// void M7(ref long x, ref int y);
Console.WriteLine();
//ref1.M7(i, i); CS0121
ref1.M7(i, l);
//ref1.M7(i, c); CS0121
ref1.M7(l, i);
//ref1.M7(l, l); CS1620
ref1.M7(l, c);
//ref1.M7(c, i); CS0121
ref1.M7(c, l);
//ref1.M7(c, c); CS0121
ref1.M7(i, ref i);
ref1.M7(l, ref i);
ref1.M7(c, ref i);
//ref1.M7(i, ref l); CS1615
//ref1.M7(l, ref l); CS1620, CS1615
//ref1.M7(c, ref l); CS1615
ref1.M7(ref i, i);
ref1.M7(ref i, l);
ref1.M7(ref i, c);
//ref1.M7(ref i, ref i); CS1615
// void M8(long x, ref int y);
// void M8(ref long x, int y);
Console.WriteLine();
ref1.M8(i, i);
//ref1.M8(i, l); CS1620
//ref1.M8(i, c); CS0121
//ref1.M8(l, i); CS0121
//ref1.M8(l, l); CS1620
ref1.M8(l, c);
ref1.M8(c, i);
//ref1.M8(c, l); CS1620
//ref1.M8(c, c); CS0121
ref1.M8(i, ref i);
ref1.M8(l, ref i);
ref1.M8(c, ref i);
//ref1.M8(i, ref l); CS1503
//ref1.M8(l, ref l); CS1503
//ref1.M8(c, ref l); CS1503
//ref1.M8(ref i, i); CS1615
//ref1.M8(ref i, l); CS1615, CS1620
//ref1.M8(ref i, c); CS1615
ref1.M8(ref l, i);
//ref1.M8(ref l, l); CS1615, CS1620
ref1.M8(ref l, c);
//ref1.M8(ref i, ref i); CS1615
//ref1.M8(ref i, ref l); CS1615, CS1503
//ref1.M8(ref l, ref i); CS1615
//ref1.M8(ref l, ref l); CS1615, CS1503
// void M9(ref long x, ref int y);
// void M9(ref int x, ref long y);
Console.WriteLine();
//ref1.M9(i, i); CS0121
ref1.M9(i, l);
//ref1.M9(i, c); CS0121
ref1.M9(l, i);
//ref1.M9(l, l); CS1620
ref1.M9(l, c);
//ref1.M9(c, i); CS0121
ref1.M9(c, l);
//ref1.M9(c, c); CS0121
ref1.M9(i, ref i);
ref1.M9(l, ref i);
ref1.M9(c, ref i);
ref1.M9(i, ref l);
//ref1.M9(l, ref l); CS1503
ref1.M9(c, ref l);
ref1.M9(ref i, i);
ref1.M9(ref i, l);
ref1.M9(ref i, c);
ref1.M9(ref l, i);
//ref1.M9(ref l, l); CS1620
ref1.M9(ref l, c);
//ref1.M9(ref i, ref i); CS1503
ref1.M9(ref i, ref l);
ref1.M9(ref l, ref i);
//ref1.M9(ref l, ref l); CS1503
}
}
";
CompileAndVerify(source, expectedOutput: @"1
1
1
1
1
1
2
2
4
3
4
3
4
4
6
5
6
6
6
5
5
6
6
7
7
8
8
7
7
7
8
10
9
10
10
10
9
9
10
10
12
12
11
11
12
12
13
14
14
13
14
14
14
13
13
13
16
15
16
15
15
15
16
16
18
17
17
18
17
17
17
18
18
18
18
18
17
17
18
17");
}
[Fact]
public void RefOmittedComCall_OverloadResolution_MultipleArguments_ErrorCases()
{
var source =
@"
using System;
using System.Runtime.InteropServices;
[ComImport]
[Guid(""A88A175D-2448-447A-B786-64682CBEF156"")]
public interface IRef1
{
void M1(int x, long y);
void M1(ref int x, int y);
void M2(int x, char y);
void M2(ref int x, int y);
void M3(ref int x, char y);
void M3(ref long x, int y);
void M4(ref int x, long y);
void M4(ref int x, ref int y);
void M5(ref int x, char y);
void M5(ref long x, int y);
void M6(ref int x, int y);
void M6(ref long x, int y);
void M7(ref int x, long y);
void M7(ref long x, ref int y);
void M8(long x, ref int y);
void M8(ref long x, int y);
void M9(ref long x, ref int y);
void M9(ref int x, ref long y);
}
public class Ref1Impl : IRef1
{
public void M1(int x, long y) { Console.WriteLine(1); }
public void M1(ref int x, int y) { Console.WriteLine(2); }
public void M2(int x, char y) { Console.WriteLine(3); }
public void M2(ref int x, int y) { Console.WriteLine(4); }
public void M3(ref int x, char y) { Console.WriteLine(5); }
public void M3(ref long x, int y) { Console.WriteLine(6); }
public void M4(ref int x, long y) { Console.WriteLine(7); }
public void M4(ref int x, ref int y) { Console.WriteLine(8); }
public void M5(ref int x, char y) { Console.WriteLine(9); }
public void M5(ref long x, int y) { Console.WriteLine(10); }
public void M6(ref int x, int y) { Console.WriteLine(11); }
public void M6(ref long x, int y) { Console.WriteLine(12); }
public void M7(ref int x, long y) { Console.WriteLine(13); }
public void M7(ref long x, ref int y) { Console.WriteLine(14); }
public void M8(long x, ref int y) { Console.WriteLine(15); }
public void M8(ref long x, int y) { Console.WriteLine(16); }
public void M9(ref long x, ref int y) { Console.WriteLine(17); }
public void M9(ref int x, ref long y) { Console.WriteLine(18); }
}
class Test
{
public static void Main()
{
IRef1 ref1 = new Ref1Impl();
int i = 1;
long l = 1;
char c = 'c';
// void M1(int x, long y);
// void M1(ref int x, int y);
ref1.M1(l, i); // CS1503
ref1.M1(l, l); // CS1503
ref1.M1(l, c); // CS1503
ref1.M1(ref i, l); // CS1615
ref1.M1(ref l, i); // CS1615
ref1.M1(ref l, l); // CS1615
ref1.M1(ref l, c); // CS1615
ref1.M1(ref c, i); // CS1615
ref1.M1(ref c, l); // CS1615
ref1.M1(ref c, c); // CS1615
// void M2(int x, char y);
// void M2(ref int x, int y);
Console.WriteLine();
ref1.M2(i, l); // CS1503
ref1.M2(l, i); // CS1503, CS1503
ref1.M2(l, l); // CS1503, CS1503
ref1.M2(l, c); // CS1503
ref1.M2(c, l); // CS1503
ref1.M2(ref i, l); // CS1615, CS1503
ref1.M2(ref l, i); // CS1615, CS1503
ref1.M2(ref l, l); // CS1615, CS1503
ref1.M2(ref l, c); // CS1615
ref1.M2(ref c, i); // CS1615, CS1503
ref1.M2(ref c, l); // CS1615, CS1503
ref1.M2(ref c, c); // CS1615
// void M3(ref int x, char y);
// void M3(ref long x, int y);
Console.WriteLine();
ref1.M3(i, l); // CS1503
ref1.M3(l, l); // CS1620, CS1503
ref1.M3(c, l); // CS1503
ref1.M3(ref i, i); // CS1503
ref1.M3(ref i, l); // CS1503
ref1.M3(ref l, l); // CS1503, CS1503
ref1.M3(ref c, i); // CS1503, CS1503
ref1.M3(ref c, l); // CS1503, CS1503
ref1.M3(ref c, c); // CS1503
// void M4(ref int x, long y);
// void M4(ref int x, ref int y);
Console.WriteLine();
ref1.M4(i, i); // CS0121
ref1.M4(i, c); // CS0121
ref1.M4(l, i); // CS1620
ref1.M4(l, l); // CS1620
ref1.M4(l, c); // CS1620
ref1.M4(c, i); // CS0121
ref1.M4(c, c); // CS0121
ref1.M4(l, ref i); // CS1620, CS1615
ref1.M4(i, ref l); // CS1615
ref1.M4(l, ref l); // CS1620
ref1.M4(c, ref l); // CS1615
// void M5(ref int x, char y);
// void M5(ref long x, int y);
Console.WriteLine();
ref1.M5(i, l); // CS1503
ref1.M5(l, l); // CS1620, CS1503
ref1.M5(c, l); // CS1503
ref1.M5(ref i, i); // CS1503
ref1.M5(ref i, l); // CS1503
ref1.M5(ref l, l); // CS1503
// void M6(ref int x, int y);
// void M6(ref long x, int y);
Console.WriteLine();
ref1.M6(i, i); // CS0121
ref1.M6(i, l); // CS1503
ref1.M6(i, c); // CS0121
ref1.M6(l, l); // CS1620, CS1503
ref1.M6(c, i); // CS0121
ref1.M6(c, l); // CS1503
ref1.M6(c, c); // CS0121
ref1.M6(ref i, l); // CS1503
ref1.M6(ref l, l); // CS1503, CS1503
// void M7(ref int x, long y);
// void M7(ref long x, ref int y);
Console.WriteLine();
ref1.M7(i, i); // CS0121
ref1.M7(i, c); // CS0121
ref1.M7(l, l); // CS1620
ref1.M7(c, i); // CS0121
ref1.M7(c, c); // CS0121
ref1.M7(i, ref l); // CS1615
ref1.M7(l, ref l); // CS1620, CS1615
ref1.M7(c, ref l); // CS1615
ref1.M7(ref i, ref i); // CS1615
// void M8(long x, ref int y);
// void M8(ref long x, int y);
Console.WriteLine();
ref1.M8(i, l); // CS1620
ref1.M8(i, c); // CS0121
ref1.M8(l, i); // CS0121
ref1.M8(l, l); // CS1620
ref1.M8(c, l); // CS1620
ref1.M8(c, c); // CS0121
ref1.M8(i, ref l); // CS1503
ref1.M8(l, ref l); // CS1503
ref1.M8(c, ref l); // CS1503
ref1.M8(ref i, i); // CS1615
ref1.M8(ref i, l); // CS1615, CS1620
ref1.M8(ref i, c); // CS1615
ref1.M8(ref l, l); // CS1615, CS1620
ref1.M8(ref i, ref i); // CS1615
ref1.M8(ref i, ref l); // CS1615, CS1503
ref1.M8(ref l, ref i); // CS1615
ref1.M8(ref l, ref l); // CS1615, CS1503
// void M9(ref long x, ref int y);
// void M9(ref int x, ref long y);
Console.WriteLine();
ref1.M9(i, i); // CS0121
ref1.M9(i, c); // CS0121
ref1.M9(l, l); // CS1620
ref1.M9(c, i); // CS0121
ref1.M9(c, c); // CS0121
ref1.M9(l, ref l); // CS1503
ref1.M9(ref l, l); // CS1620
ref1.M9(ref i, ref i); // CS1503
ref1.M9(ref l, ref l); // CS1503
}
}
";
CreateCompilation(source).VerifyDiagnostics(
// (80,16): error CS1503: Argument 1: cannot convert from 'long' to 'int'
// ref1.M1(l, i); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("1", "long", "int"),
// (81,16): error CS1503: Argument 1: cannot convert from 'long' to 'int'
// ref1.M1(l, l); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("1", "long", "int"),
// (82,16): error CS1503: Argument 1: cannot convert from 'long' to 'int'
// ref1.M1(l, c); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("1", "long", "int"),
// (83,20): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// ref1.M1(ref i, l); // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "i").WithArguments("1", "ref"),
// (84,20): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// ref1.M1(ref l, i); // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "l").WithArguments("1", "ref"),
// (85,20): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// ref1.M1(ref l, l); // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "l").WithArguments("1", "ref"),
// (86,20): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// ref1.M1(ref l, c); // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "l").WithArguments("1", "ref"),
// (87,20): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// ref1.M1(ref c, i); // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "c").WithArguments("1", "ref"),
// (88,20): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// ref1.M1(ref c, l); // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "c").WithArguments("1", "ref"),
// (89,20): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// ref1.M1(ref c, c); // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "c").WithArguments("1", "ref"),
// (96,19): error CS1503: Argument 2: cannot convert from 'long' to 'char'
// ref1.M2(i, l); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("2", "long", "char"),
// (97,16): error CS1503: Argument 1: cannot convert from 'long' to 'int'
// ref1.M2(l, i); // CS1503, CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("1", "long", "int"),
// (97,19): error CS1503: Argument 2: cannot convert from 'int' to 'char'
// ref1.M2(l, i); // CS1503, CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "i").WithArguments("2", "int", "char"),
// (98,16): error CS1503: Argument 1: cannot convert from 'long' to 'int'
// ref1.M2(l, l); // CS1503, CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("1", "long", "int"),
// (98,19): error CS1503: Argument 2: cannot convert from 'long' to 'char'
// ref1.M2(l, l); // CS1503, CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("2", "long", "char"),
// (99,16): error CS1503: Argument 1: cannot convert from 'long' to 'int'
// ref1.M2(l, c); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("1", "long", "int"),
// (100,19): error CS1503: Argument 2: cannot convert from 'long' to 'char'
// ref1.M2(c, l); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("2", "long", "char"),
// (101,20): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// ref1.M2(ref i, l); // CS1615, CS1503
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "i").WithArguments("1", "ref"),
// (101,23): error CS1503: Argument 2: cannot convert from 'long' to 'char'
// ref1.M2(ref i, l); // CS1615, CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("2", "long", "char"),
// (102,20): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// ref1.M2(ref l, i); // CS1615, CS1503
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "l").WithArguments("1", "ref"),
// (102,23): error CS1503: Argument 2: cannot convert from 'int' to 'char'
// ref1.M2(ref l, i); // CS1615, CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "i").WithArguments("2", "int", "char"),
// (103,20): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// ref1.M2(ref l, l); // CS1615, CS1503
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "l").WithArguments("1", "ref"),
// (103,23): error CS1503: Argument 2: cannot convert from 'long' to 'char'
// ref1.M2(ref l, l); // CS1615, CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("2", "long", "char"),
// (104,20): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// ref1.M2(ref l, c); // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "l").WithArguments("1", "ref"),
// (105,20): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// ref1.M2(ref c, i); // CS1615, CS1503
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "c").WithArguments("1", "ref"),
// (105,23): error CS1503: Argument 2: cannot convert from 'int' to 'char'
// ref1.M2(ref c, i); // CS1615, CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "i").WithArguments("2", "int", "char"),
// (106,20): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// ref1.M2(ref c, l); // CS1615, CS1503
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "c").WithArguments("1", "ref"),
// (106,23): error CS1503: Argument 2: cannot convert from 'long' to 'char'
// ref1.M2(ref c, l); // CS1615, CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("2", "long", "char"),
// (107,20): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// ref1.M2(ref c, c); // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "c").WithArguments("1", "ref"),
// (114,19): error CS1503: Argument 2: cannot convert from 'long' to 'char'
// ref1.M3(i, l); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("2", "long", "char"),
// (115,16): error CS1620: Argument 1 must be passed with the 'ref' keyword
// ref1.M3(l, l); // CS1620, CS1503
Diagnostic(ErrorCode.ERR_BadArgRef, "l").WithArguments("1", "ref"),
// (115,19): error CS1503: Argument 2: cannot convert from 'long' to 'char'
// ref1.M3(l, l); // CS1620, CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("2", "long", "char"),
// (116,19): error CS1503: Argument 2: cannot convert from 'long' to 'char'
// ref1.M3(c, l); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("2", "long", "char"),
// (117,23): error CS1503: Argument 2: cannot convert from 'int' to 'char'
// ref1.M3(ref i, i); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "i").WithArguments("2", "int", "char"),
// (118,23): error CS1503: Argument 2: cannot convert from 'long' to 'char'
// ref1.M3(ref i, l); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("2", "long", "char"),
// (119,20): error CS1503: Argument 1: cannot convert from 'ref long' to 'ref int'
// ref1.M3(ref l, l); // CS1503, CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("1", "ref long", "ref int"),
// (119,23): error CS1503: Argument 2: cannot convert from 'long' to 'char'
// ref1.M3(ref l, l); // CS1503, CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("2", "long", "char"),
// (120,20): error CS1503: Argument 1: cannot convert from 'ref char' to 'ref int'
// ref1.M3(ref c, i); // CS1503, CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "c").WithArguments("1", "ref char", "ref int"),
// (120,23): error CS1503: Argument 2: cannot convert from 'int' to 'char'
// ref1.M3(ref c, i); // CS1503, CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "i").WithArguments("2", "int", "char"),
// (121,20): error CS1503: Argument 1: cannot convert from 'ref char' to 'ref int'
// ref1.M3(ref c, l); // CS1503, CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "c").WithArguments("1", "ref char", "ref int"),
// (121,23): error CS1503: Argument 2: cannot convert from 'long' to 'char'
// ref1.M3(ref c, l); // CS1503, CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("2", "long", "char"),
// (122,20): error CS1503: Argument 1: cannot convert from 'ref char' to 'ref int'
// ref1.M3(ref c, c); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "c").WithArguments("1", "ref char", "ref int"),
// (129,8): error CS0121: The call is ambiguous between the following methods or properties: 'IRef1.M4(ref int, long)' and 'IRef1.M4(ref int, ref int)'
// ref1.M4(i, i); // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "M4").WithArguments("IRef1.M4(ref int, long)", "IRef1.M4(ref int, ref int)"),
// (130,8): error CS0121: The call is ambiguous between the following methods or properties: 'IRef1.M4(ref int, long)' and 'IRef1.M4(ref int, ref int)'
// ref1.M4(i, c); // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "M4").WithArguments("IRef1.M4(ref int, long)", "IRef1.M4(ref int, ref int)"),
// (131,16): error CS1620: Argument 1 must be passed with the 'ref' keyword
// ref1.M4(l, i); // CS1620
Diagnostic(ErrorCode.ERR_BadArgRef, "l").WithArguments("1", "ref"),
// (132,16): error CS1620: Argument 1 must be passed with the 'ref' keyword
// ref1.M4(l, l); // CS1620
Diagnostic(ErrorCode.ERR_BadArgRef, "l").WithArguments("1", "ref"),
// (133,16): error CS1620: Argument 1 must be passed with the 'ref' keyword
// ref1.M4(l, c); // CS1620
Diagnostic(ErrorCode.ERR_BadArgRef, "l").WithArguments("1", "ref"),
// (134,8): error CS0121: The call is ambiguous between the following methods or properties: 'IRef1.M4(ref int, long)' and 'IRef1.M4(ref int, ref int)'
// ref1.M4(c, i); // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "M4").WithArguments("IRef1.M4(ref int, long)", "IRef1.M4(ref int, ref int)"),
// (135,8): error CS0121: The call is ambiguous between the following methods or properties: 'IRef1.M4(ref int, long)' and 'IRef1.M4(ref int, ref int)'
// ref1.M4(c, c); // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "M4").WithArguments("IRef1.M4(ref int, long)", "IRef1.M4(ref int, ref int)"),
// (136,16): error CS1620: Argument 1 must be passed with the 'ref' keyword
// ref1.M4(l, ref i); // CS1620, CS1615
Diagnostic(ErrorCode.ERR_BadArgRef, "l").WithArguments("1", "ref"),
// (136,23): error CS1615: Argument 2 should not be passed with the 'ref' keyword
// ref1.M4(l, ref i); // CS1620, CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "i").WithArguments("2", "ref"),
// (137,23): error CS1615: Argument 2 should not be passed with the 'ref' keyword
// ref1.M4(i, ref l); // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "l").WithArguments("2", "ref"),
// (138,16): error CS1620: Argument 1 must be passed with the 'ref' keyword
// ref1.M4(l, ref l); // CS1620
Diagnostic(ErrorCode.ERR_BadArgRef, "l").WithArguments("1", "ref"),
// (138,23): error CS1615: Argument 2 should not be passed with the 'ref' keyword
// ref1.M4(l, ref l); // CS1620
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "l").WithArguments("2", "ref"),
// (139,23): error CS1615: Argument 2 should not be passed with the 'ref' keyword
// ref1.M4(c, ref l); // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "l").WithArguments("2", "ref"),
// (146,19): error CS1503: Argument 2: cannot convert from 'long' to 'char'
// ref1.M5(i, l); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("2", "long", "char"),
// (147,16): error CS1620: Argument 1 must be passed with the 'ref' keyword
// ref1.M5(l, l); // CS1620, CS1503
Diagnostic(ErrorCode.ERR_BadArgRef, "l").WithArguments("1", "ref"),
// (147,19): error CS1503: Argument 2: cannot convert from 'long' to 'char'
// ref1.M5(l, l); // CS1620, CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("2", "long", "char"),
// (148,19): error CS1503: Argument 2: cannot convert from 'long' to 'char'
// ref1.M5(c, l); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("2", "long", "char"),
// (149,23): error CS1503: Argument 2: cannot convert from 'int' to 'char'
// ref1.M5(ref i, i); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "i").WithArguments("2", "int", "char"),
// (150,23): error CS1503: Argument 2: cannot convert from 'long' to 'char'
// ref1.M5(ref i, l); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("2", "long", "char"),
// (151,20): error CS1503: Argument 1: cannot convert from 'ref long' to 'ref int'
// ref1.M5(ref l, l); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("1", "ref long", "ref int"),
// (151,23): error CS1503: Argument 2: cannot convert from 'long' to 'char'
// ref1.M5(ref l, l); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("2", "long", "char"),
// (158,8): error CS0121: The call is ambiguous between the following methods or properties: 'IRef1.M6(ref int, int)' and 'IRef1.M6(ref long, int)'
// ref1.M6(i, i); // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "M6").WithArguments("IRef1.M6(ref int, int)", "IRef1.M6(ref long, int)"),
// (159,19): error CS1503: Argument 2: cannot convert from 'long' to 'int'
// ref1.M6(i, l); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("2", "long", "int"),
// (160,8): error CS0121: The call is ambiguous between the following methods or properties: 'IRef1.M6(ref int, int)' and 'IRef1.M6(ref long, int)'
// ref1.M6(i, c); // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "M6").WithArguments("IRef1.M6(ref int, int)", "IRef1.M6(ref long, int)"),
// (161,16): error CS1620: Argument 1 must be passed with the 'ref' keyword
// ref1.M6(l, l); // CS1620, CS1503
Diagnostic(ErrorCode.ERR_BadArgRef, "l").WithArguments("1", "ref"),
// (161,19): error CS1503: Argument 2: cannot convert from 'long' to 'int'
// ref1.M6(l, l); // CS1620, CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("2", "long", "int"),
// (162,8): error CS0121: The call is ambiguous between the following methods or properties: 'IRef1.M6(ref int, int)' and 'IRef1.M6(ref long, int)'
// ref1.M6(c, i); // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "M6").WithArguments("IRef1.M6(ref int, int)", "IRef1.M6(ref long, int)"),
// (163,19): error CS1503: Argument 2: cannot convert from 'long' to 'int'
// ref1.M6(c, l); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("2", "long", "int"),
// (164,8): error CS0121: The call is ambiguous between the following methods or properties: 'IRef1.M6(ref int, int)' and 'IRef1.M6(ref long, int)'
// ref1.M6(c, c); // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "M6").WithArguments("IRef1.M6(ref int, int)", "IRef1.M6(ref long, int)"),
// (165,23): error CS1503: Argument 2: cannot convert from 'long' to 'int'
// ref1.M6(ref i, l); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("2", "long", "int"),
// (166,20): error CS1503: Argument 1: cannot convert from 'ref long' to 'ref int'
// ref1.M6(ref l, l); // CS1503, CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("1", "ref long", "ref int"),
// (166,23): error CS1503: Argument 2: cannot convert from 'long' to 'int'
// ref1.M6(ref l, l); // CS1503, CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("2", "long", "int"),
// (173,8): error CS0121: The call is ambiguous between the following methods or properties: 'IRef1.M7(ref int, long)' and 'IRef1.M7(ref long, ref int)'
// ref1.M7(i, i); // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "M7").WithArguments("IRef1.M7(ref int, long)", "IRef1.M7(ref long, ref int)"),
// (174,8): error CS0121: The call is ambiguous between the following methods or properties: 'IRef1.M7(ref int, long)' and 'IRef1.M7(ref long, ref int)'
// ref1.M7(i, c); // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "M7").WithArguments("IRef1.M7(ref int, long)", "IRef1.M7(ref long, ref int)"),
// (175,16): error CS1620: Argument 1 must be passed with the 'ref' keyword
// ref1.M7(l, l); // CS1620
Diagnostic(ErrorCode.ERR_BadArgRef, "l").WithArguments("1", "ref"),
// (176,8): error CS0121: The call is ambiguous between the following methods or properties: 'IRef1.M7(ref int, long)' and 'IRef1.M7(ref long, ref int)'
// ref1.M7(c, i); // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "M7").WithArguments("IRef1.M7(ref int, long)", "IRef1.M7(ref long, ref int)"),
// (177,8): error CS0121: The call is ambiguous between the following methods or properties: 'IRef1.M7(ref int, long)' and 'IRef1.M7(ref long, ref int)'
// ref1.M7(c, c); // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "M7").WithArguments("IRef1.M7(ref int, long)", "IRef1.M7(ref long, ref int)"),
// (178,23): error CS1615: Argument 2 should not be passed with the 'ref' keyword
// ref1.M7(i, ref l); // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "l").WithArguments("2", "ref"),
// (179,16): error CS1620: Argument 1 must be passed with the 'ref' keyword
// ref1.M7(l, ref l); // CS1620, CS1615
Diagnostic(ErrorCode.ERR_BadArgRef, "l").WithArguments("1", "ref"),
// (179,23): error CS1615: Argument 2 should not be passed with the 'ref' keyword
// ref1.M7(l, ref l); // CS1620, CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "l").WithArguments("2", "ref"),
// (180,23): error CS1615: Argument 2 should not be passed with the 'ref' keyword
// ref1.M7(c, ref l); // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "l").WithArguments("2", "ref"),
// (181,27): error CS1615: Argument 2 should not be passed with the 'ref' keyword
// ref1.M7(ref i, ref i); // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "i").WithArguments("2", "ref"),
// (188,19): error CS1620: Argument 2 must be passed with the 'ref' keyword
// ref1.M8(i, l); // CS1620
Diagnostic(ErrorCode.ERR_BadArgRef, "l").WithArguments("2", "ref"),
// (189,8): error CS0121: The call is ambiguous between the following methods or properties: 'IRef1.M8(long, ref int)' and 'IRef1.M8(ref long, int)'
// ref1.M8(i, c); // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "M8").WithArguments("IRef1.M8(long, ref int)", "IRef1.M8(ref long, int)"),
// (190,8): error CS0121: The call is ambiguous between the following methods or properties: 'IRef1.M8(long, ref int)' and 'IRef1.M8(ref long, int)'
// ref1.M8(l, i); // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "M8").WithArguments("IRef1.M8(long, ref int)", "IRef1.M8(ref long, int)"),
// (191,19): error CS1620: Argument 2 must be passed with the 'ref' keyword
// ref1.M8(l, l); // CS1620
Diagnostic(ErrorCode.ERR_BadArgRef, "l").WithArguments("2", "ref"),
// (192,19): error CS1620: Argument 2 must be passed with the 'ref' keyword
// ref1.M8(c, l); // CS1620
Diagnostic(ErrorCode.ERR_BadArgRef, "l").WithArguments("2", "ref"),
// (193,8): error CS0121: The call is ambiguous between the following methods or properties: 'IRef1.M8(long, ref int)' and 'IRef1.M8(ref long, int)'
// ref1.M8(c, c); // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "M8").WithArguments("IRef1.M8(long, ref int)", "IRef1.M8(ref long, int)"),
// (194,23): error CS1503: Argument 2: cannot convert from 'ref long' to 'ref int'
// ref1.M8(i, ref l); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("2", "ref long", "ref int"),
// (195,23): error CS1503: Argument 2: cannot convert from 'ref long' to 'ref int'
// ref1.M8(l, ref l); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("2", "ref long", "ref int"),
// (196,23): error CS1503: Argument 2: cannot convert from 'ref long' to 'ref int'
// ref1.M8(c, ref l); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("2", "ref long", "ref int"),
// (197,20): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// ref1.M8(ref i, i); // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "i").WithArguments("1", "ref"),
// (198,20): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// ref1.M8(ref i, l); // CS1615, CS1620
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "i").WithArguments("1", "ref"),
// (198,23): error CS1620: Argument 2 must be passed with the 'ref' keyword
// ref1.M8(ref i, l); // CS1615, CS1620
Diagnostic(ErrorCode.ERR_BadArgRef, "l").WithArguments("2", "ref"),
// (199,20): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// ref1.M8(ref i, c); // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "i").WithArguments("1", "ref"),
// (200,20): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// ref1.M8(ref l, l); // CS1615, CS1620
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "l").WithArguments("1", "ref"),
// (200,23): error CS1620: Argument 2 must be passed with the 'ref' keyword
// ref1.M8(ref l, l); // CS1615, CS1620
Diagnostic(ErrorCode.ERR_BadArgRef, "l").WithArguments("2", "ref"),
// (201,20): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// ref1.M8(ref i, ref i); // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "i").WithArguments("1", "ref"),
// (202,20): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// ref1.M8(ref i, ref l); // CS1615, CS1503
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "i").WithArguments("1", "ref"),
// (202,27): error CS1503: Argument 2: cannot convert from 'ref long' to 'ref int'
// ref1.M8(ref i, ref l); // CS1615, CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("2", "ref long", "ref int"),
// (203,20): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// ref1.M8(ref l, ref i); // CS1615
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "l").WithArguments("1", "ref"),
// (204,20): error CS1615: Argument 1 should not be passed with the 'ref' keyword
// ref1.M8(ref l, ref l); // CS1615, CS1503
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "l").WithArguments("1", "ref"),
// (204,27): error CS1503: Argument 2: cannot convert from 'ref long' to 'ref int'
// ref1.M8(ref l, ref l); // CS1615, CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("2", "ref long", "ref int"),
// (211,8): error CS0121: The call is ambiguous between the following methods or properties: 'IRef1.M9(ref long, ref int)' and 'IRef1.M9(ref int, ref long)'
// ref1.M9(i, i); // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "M9").WithArguments("IRef1.M9(ref long, ref int)", "IRef1.M9(ref int, ref long)"),
// (212,8): error CS0121: The call is ambiguous between the following methods or properties: 'IRef1.M9(ref long, ref int)' and 'IRef1.M9(ref int, ref long)'
// ref1.M9(i, c); // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "M9").WithArguments("IRef1.M9(ref long, ref int)", "IRef1.M9(ref int, ref long)"),
// (213,19): error CS1620: Argument 2 must be passed with the 'ref' keyword
// ref1.M9(l, l); // CS1620
Diagnostic(ErrorCode.ERR_BadArgRef, "l").WithArguments("2", "ref"),
// (214,8): error CS0121: The call is ambiguous between the following methods or properties: 'IRef1.M9(ref long, ref int)' and 'IRef1.M9(ref int, ref long)'
// ref1.M9(c, i); // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "M9").WithArguments("IRef1.M9(ref long, ref int)", "IRef1.M9(ref int, ref long)"),
// (215,8): error CS0121: The call is ambiguous between the following methods or properties: 'IRef1.M9(ref long, ref int)' and 'IRef1.M9(ref int, ref long)'
// ref1.M9(c, c); // CS0121
Diagnostic(ErrorCode.ERR_AmbigCall, "M9").WithArguments("IRef1.M9(ref long, ref int)", "IRef1.M9(ref int, ref long)"),
// (216,23): error CS1503: Argument 2: cannot convert from 'ref long' to 'ref int'
// ref1.M9(l, ref l); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("2", "ref long", "ref int"),
// (217,23): error CS1620: Argument 2 must be passed with the 'ref' keyword
// ref1.M9(ref l, l); // CS1620
Diagnostic(ErrorCode.ERR_BadArgRef, "l").WithArguments("2", "ref"),
// (218,20): error CS1503: Argument 1: cannot convert from 'ref int' to 'ref long'
// ref1.M9(ref i, ref i); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "i").WithArguments("1", "ref int", "ref long"),
// (219,27): error CS1503: Argument 2: cannot convert from 'ref long' to 'ref int'
// ref1.M9(ref l, ref l); // CS1503
Diagnostic(ErrorCode.ERR_BadArgType, "l").WithArguments("2", "ref long", "ref int"));
}
[Fact]
public void FailedToConvertToParameterArrayElementType()
{
var source = @"
class C
{
static void Main()
{
M1(1, null);
M1(null, 1);
M2(""a"", null);
M2(null, ""a"");
M3(1, null);
M3(null, 1);
M3(""a"", null);
M3(null, ""a"");
M1(1, ""A"");
M2(1, ""A"");
M3<int>(1, ""A"");
M3<string>(1, ""A"");
}
static void M1(params int[] a) { }
static void M2(params string[] a) { }
static void M3<T>(params T[] a) { }
}
";
CreateCompilation(source).VerifyDiagnostics(
// (6,15): error CS1503: Argument 2: cannot convert from '<null>' to 'int'
// M1(1, null);
Diagnostic(ErrorCode.ERR_BadArgType, "null").WithArguments("2", "<null>", "int"),
// (7,12): error CS1503: Argument 1: cannot convert from '<null>' to 'int'
// M1(null, 1);
Diagnostic(ErrorCode.ERR_BadArgType, "null").WithArguments("1", "<null>", "int"),
// (12,15): error CS1503: Argument 2: cannot convert from '<null>' to 'int'
// M3(1, null);
Diagnostic(ErrorCode.ERR_BadArgType, "null").WithArguments("2", "<null>", "int"),
// (13,12): error CS1503: Argument 1: cannot convert from '<null>' to 'int'
// M3(null, 1);
Diagnostic(ErrorCode.ERR_BadArgType, "null").WithArguments("1", "<null>", "int"),
// (18,15): error CS1503: Argument 2: cannot convert from 'string' to 'int'
// M1(1, "A");
Diagnostic(ErrorCode.ERR_BadArgType, @"""A""").WithArguments("2", "string", "int"),
// (19,12): error CS1503: Argument 1: cannot convert from 'int' to 'string'
// M2(1, "A");
Diagnostic(ErrorCode.ERR_BadArgType, "1").WithArguments("1", "int", "string"),
// (20,20): error CS1503: Argument 2: cannot convert from 'string' to 'int'
// M3<int>(1, "A");
Diagnostic(ErrorCode.ERR_BadArgType, @"""A""").WithArguments("2", "string", "int"),
// (21,20): error CS1503: Argument 1: cannot convert from 'int' to 'string'
// M3<string>(1, "A");
Diagnostic(ErrorCode.ERR_BadArgType, "1").WithArguments("1", "int", "string"));
}
[Fact]
public void TypeInferenceFailures()
{
var source = @"
public interface I { }
public interface I1<T> { }
public interface I2<S, T> { }
public class A : I { }
public class B { }
public class C { }
public class G1<T> : I1<T> { }
public class G2<S, T> : G1<S>, I2<S, T> { }
public class AggTest {
public static A a = new A();
public static I i = a;
public static G1<A> g1a = new G1<A>();
public static G1<G1<B>> g11b = new G1<G1<B>>();
public static G1<G1<G1<C>>> g111c = new G1<G1<G1<C>>>();
public static G1<G2<A, B>> g12ab = new G1<G2<A, B>>();
public static G2<A, B> g2ab = new G2<A, B>();
public static G2<G1<A>, B> g21ab = new G2<G1<A>, B>();
public static G2<A, G1<B>> g2a1b = new G2<A, G1<B>>();
public static G2<G1<A>, G1<B>> g21a1b = new G2<G1<A>, G1<B>>();
public static G2<G2<A, B>, C> g22abc = new G2<G2<A, B>, C>();
public static G2<A, G2<B, C>> g2a2bc = new G2<A, G2<B, C>>();
public static G2<G2<A, B>, G1<C>> g22ab1c = new G2<G2<A, B>, G1<C>>();
public static G2<G1<A>, G2<B, C>> g21a2bc = new G2<G1<A>, G2<B, C>>();
public class B1 {
// Nesting >= 2
public static void M3<S, T>(G1<G2<S, T>> a) { }
public static void M3<S, T>(G2<G1<S>, T> a) { }
public static void M3<S, T>(G2<S, G1<T>> a) { }
public static void M3<S, T>(G2<G1<S>, G1<T>> a) { }
}
public class ClassTestGen : B1 {
public static void Run() {
M3(null); // Can't infer
M3(a); // Can't infer
M3(i); // Can't infer
M3(g1a); // Can't infer
M3(g11b); // Can't infer
M3(g111c); // Can't infer
M3(g12ab); // OK
M3(g2ab); // Can't infer
M3(g21ab); // OK
M3(g2a1b); // OK
M3(g21a1b); // Ambiguous
M3(g22abc); // OK
M3(g2a2bc); // Can't infer
M3(g22ab1c); // OK
M3(g21a2bc); // OK
}
}
}
";
CreateCompilation(source).VerifyDiagnostics(
// (43,13): error CS0411: The type arguments for method 'AggTest.B1.M3<S, T>(G1<G2<S, T>>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
// M3(null); // Can't infer
Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "M3").WithArguments("AggTest.B1.M3<S, T>(G1<G2<S, T>>)"),
// (44,13): error CS0411: The type arguments for method 'AggTest.B1.M3<S, T>(G1<G2<S, T>>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
// M3(a); // Can't infer
Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "M3").WithArguments("AggTest.B1.M3<S, T>(G1<G2<S, T>>)"),
// (45,13): error CS0411: The type arguments for method 'AggTest.B1.M3<S, T>(G1<G2<S, T>>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
// M3(i); // Can't infer
Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "M3").WithArguments("AggTest.B1.M3<S, T>(G1<G2<S, T>>)"),
// (46,13): error CS0411: The type arguments for method 'AggTest.B1.M3<S, T>(G1<G2<S, T>>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
// M3(g1a); // Can't infer
Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "M3").WithArguments("AggTest.B1.M3<S, T>(G1<G2<S, T>>)"),
// (47,13): error CS0411: The type arguments for method 'AggTest.B1.M3<S, T>(G1<G2<S, T>>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
// M3(g11b); // Can't infer
Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "M3").WithArguments("AggTest.B1.M3<S, T>(G1<G2<S, T>>)"),
// (48,13): error CS0411: The type arguments for method 'AggTest.B1.M3<S, T>(G1<G2<S, T>>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
// M3(g111c); // Can't infer
Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "M3").WithArguments("AggTest.B1.M3<S, T>(G1<G2<S, T>>)"),
// NOTE: Dev10 reports "AggTest.B1.M3<S,T>(G2<G1<S>,T>)" for the last two, but this seems just as good (type inference fails for both).
// (50,13): error CS0411: The type arguments for method 'AggTest.B1.M3<S, T>(G1<G2<S, T>>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
// M3(g2ab); // Can't infer
Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "M3").WithArguments("AggTest.B1.M3<S, T>(G1<G2<S, T>>)"),
// (55,13): error CS0411: The type arguments for method 'AggTest.B1.M3<S, T>(G1<G2<S, T>>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
// M3(g2a2bc); // Can't infer
Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "M3").WithArguments("AggTest.B1.M3<S, T>(G1<G2<S, T>>)"));
}
[WorkItem(528425, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528425")]
[WorkItem(528425, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528425")]
[Fact(Skip = "528425")]
public void ExactInaccessibleMatch()
{
var source = @"
public class C
{
public static void Main()
{
D d = new D();
d.M(4, 5, ""b"");
}
}
public class D
{
public void M(int i)
{
}
private void M(int i, int j, string s)
{
}
}
";
CreateCompilation(source).VerifyDiagnostics(
// (7,9): error CS0122: 'D.M(int, int, string)' is inaccessible due to its protection level
// d.M(4, 5, "b");
Diagnostic(ErrorCode.ERR_BadAccess, "d.M"));
}
[WorkItem(545382, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545382")]
[Fact]
public void Whidbey133503a()
{
var source = @"
class Ambig
{
static void Main()
{
overload1(1, 1);
overload2(1, 1);
}
// causes ambiguity because first and third method, but depending on the order, the compiler
// reports them incorrectly. VSWhidbey:133503
static void overload1(byte b, goo f) { }
static void overload1(sbyte b, bar f) { }
static void overload1(int b, baz f) { }
static void overload2(int b, baz f) { }
static void overload2(sbyte b, bar f) { }
static void overload2(byte b, goo f) { }
}
class @goo
{
public static implicit operator goo(int i)
{
return new goo();
}
}
class @bar
{
public static implicit operator bar(int i)
{
return new bar();
}
}
class @baz
{
public static implicit operator baz(int i)
{
return new baz();
}
public static implicit operator baz(goo f)
{
return new baz();
}
}
";
CreateCompilation(source).VerifyDiagnostics(
// (6,9): error CS0121: The call is ambiguous between the following methods or properties: 'Ambig.overload1(byte, goo)' and 'Ambig.overload1(int, baz)'
// overload1(1, 1);
Diagnostic(ErrorCode.ERR_AmbigCall, "overload1").WithArguments("Ambig.overload1(byte, goo)", "Ambig.overload1(int, baz)").WithLocation(6, 9),
// (7,9): error CS0121: The call is ambiguous between the following methods or properties: 'Ambig.overload2(int, baz)' and 'Ambig.overload2(byte, goo)'
// overload2(1, 1);
Diagnostic(ErrorCode.ERR_AmbigCall, "overload2").WithArguments("Ambig.overload2(int, baz)", "Ambig.overload2(byte, goo)").WithLocation(7, 9)
);
}
[WorkItem(545382, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545382")]
[Fact]
public void Whidbey133503b()
{
var source = @"
class Ambig
{
static void Main()
{
F(new Q());
}
// causes ambiguity because of conversion cycle. So the compiler
// arbitrarily picks the 'first' 2 methods to report (which turn out to be
// the last 2 overloads declared). Also VSWhidbey:133503
public static void F(P1 p)
{
}
public static void F(P2 p)
{
}
public static void F(P3 p)
{
}
}
public class P1
{
public static implicit operator P1(P2 p)
{
return null;
}
}
public class P2
{
public static implicit operator P2(P3 p)
{
return null;
}
}
public class P3
{
public static implicit operator P3(P1 p)
{
return null;
}
}
public class Q
{
public static implicit operator P1(Q p)
{
return null;
}
public static implicit operator P2(Q p)
{
return null;
}
public static implicit operator P3(Q p)
{
return null;
}
}
";
CreateCompilation(source).VerifyDiagnostics(
// (6,9): error CS0121: The call is ambiguous between the following methods or properties: 'Ambig.F(P1)' and 'Ambig.F(P2)'
// F(new Q());
Diagnostic(ErrorCode.ERR_AmbigCall, "F").WithArguments("Ambig.F(P1)", "Ambig.F(P2)"));
}
[WorkItem(545467, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545467")]
[Fact]
public void ClassPlusLambda1()
{
// ACASEY: EricLi's comment provides good context on the
// nature of the problems that arise in such situations and the behavior of the native
// compiler. However, the comments about Roslyn's behavior are no longer accurate.
// Unfortunately, we discovered real-world code that depended on the native behavior
// so we need to replicate it in Roslyn. Effectively, null literal conversions become
// standard implicit conversions (we expect the spec to be revised) and anonymous function
// and method group conversions are specifically allowed if there is an explicit cast
// (this will likely not be spec'd). As for the betterness rule, we only go down the
// delegate path if BOTH target types are delegate types. Otherwise, the normal betterness
// rules apply.
// ERICLI: This test illustrates an unfortunate situation where neither Roslyn nor the
// native compiler are compliant with the specification, and the native compiler's
// behavior is unusual. In this particular situation, the native compiler is
// getting the right answer completely by accident; it is the confluence of two incorrect
// decisions adding up accidentally to a correct decision.
//
// Problem 1:
//
// The spec says that there must be a *standard implicit conversion* from the expression being
// converted to the parameter type of the user-defined implicit conversion. Unfortunately, the
// specification does not say that null literal conversions, constant numeric conversions,
// method group conversions, or lambda conversions are "standard" conversions. It seems reasonable
// that these be allowed; we will probably amend the specification to allow them.
//
// Now we get to the unusual part. The native compiler allows null literal and constant numeric
// conversions to be counted as standard conversions; this is contrary to the exact wording of
// the specification but as we said, it is a reasonable rule and we should allow it in the spec.
// The unusual part is: the native compiler effectively treats a lambda conversion and a method
// group conversion as a standard implicit conversion *if a cast appears in the code*.
//
// That is, suppose there is an implicit conversion from Action to S. The native compiler allows
//
// S s = (S)(()=>{});
//
// but does not allow
//
// S s = ()=>{};
//
// it is strange indeed that an *implicit* conversion should require a *cast*!
//
// Roslyn allows all those conversions to be used when converting the expression to the parameter
// type of the user-defined implicit conversion, regardless of whether a cast appears in the code.
//
// Problem 2:
//
// The native compiler gets the "betterness" rules wrong when lambdas are involved. The right thing
// to do is to first, check to see if one method has a more specific parameter type than the other.
// If betterness cannot be determined by parameter types, and the argument is a lambda, then
// a special rule regarding the inferred return type of the lambda is used. What the native compiler does
// is, if there is a lambda, then it skips doing the parameter type check and goes straight to the
// lambda check.
//
// After some debate, we decided a while back to replicate this bug in Roslyn.
//
// Now we see how these two bugs work together in the native compiler to produce the correct result
// for the wrong reason. Suppose we have a simplified version of the code below: r = r + (x=>x);
// What happens?
//
// The correct behavior according to the spec is to say that there are two possible operators,
// MC + EXPR and MC + MC. Are either of them *applicable*? Clearly both are good in their left
// hand operand. Can the right-hand operand, a lambda, be converted via implicit conversion to
// the expression tree type? Obviously yes. Can the lambda be converted to MainClass?
//
// Not directly, because MainClass is not a delegate or expression tree type. But we examine
// the user-defined conversions on MainClass and discover an implicit conversion from expression
// tree to MainClass. Can we use that?
//
// The spec says no, because the conversion from lambda to expression tree is not a "standard"
// implicit conversion.
//
// The native compiler says no because it enforces that rule when there is no cast in the code.
// Had there been a cast in the code, the native compiler would say yes, there is.
//
// Roslyn says yes; it allows the lambda conversion as a standard conversion regardless of whether
// there is a cast in the code.
//
// In the native compiler there is now only one operator in the candidate set of applicable operators;
// the choice is therefore easy; the MC + EXPR wins.
//
// In Roslyn, there are now two operators in the candidate set of applicable operators. Which one wins?
//
// The correct behavior is to say that the more specific one wins. Since there is an implicit conversion
// from EXPR to MC but not from MC to EXPR, the MC + EXPR candidate must be better, so it wins.
//
// But that is not what Roslyn does; remember, Roslyn is being bug-compatible with the native compiler.
// The native compiler does not check for betterness on types when a lambda is involved.
// Therefore Roslyn checks the lambda, and is unable to deduce from it which candidate is better.
//
// Therefore Roslyn gives an ambiguity error, even though (1) by rights the candidate set should
// contain a single operator, and (2) even if it contains two, one of them is clearly better.
//
var source = @"
class MainClass
{
static void Main()
{
MainClass r = new MainClass();
// The lambda contains an ambiguity error, and therefore we cannot work out
// the overload resolution problem on the outermost addition, so we give
// a bad binary operator error.
r = r + ((MainClass x) => x + ((MainClass y) => (y + null)));
// The lambda body no longer contains an error, thanks to the cast.
// Therefore, this becomes an ambiguity error, for reasons detailed above.
r = r + ((MainClass x) => x + (MainClass)((MainClass y) => (y + null)));
}
public static MainClass operator +(MainClass r1, MainClass r2) { return r1; }
public static MainClass operator +(MainClass r1,
System.Linq.Expressions.Expression<System.Func<MainClass, MainClass>> e)
{ return r1; }
public static implicit operator MainClass(
System.Linq.Expressions.Expression<System.Func<MainClass, MainClass>> e)
{ return new MainClass(); }
}
";
// Roslyn matches the native behavior - it compiles cleanly.
var comp = CreateCompilationWithMscorlib40AndSystemCore(source);
comp.VerifyDiagnostics();
}
[WorkItem(545467, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545467")]
[Fact]
public void ClassPlusLambda2()
{
// Here we remove one of the operators from the previous test. Of course the
// first one is no longer ambiguous, and the second one no longer works because
// now the lambda contains an addition that has no applicable operator, and
// so the outer addition cannot work either.
var source = @"
class MainClass
{
static void Main()
{
MainClass r = new MainClass();
r = r + ((MainClass x) => x + ((MainClass y) => (y + null)));
r = r + ((MainClass x) => x + (MainClass)((MainClass y) => (y + null)));
}
// public static MainClass operator +(MainClass r1, MainClass r2) { return r1; }
public static MainClass operator +(MainClass r1,
System.Linq.Expressions.Expression<System.Func<MainClass, MainClass>> e)
{ return r1; }
public static implicit operator MainClass(
System.Linq.Expressions.Expression<System.Func<MainClass, MainClass>> e)
{ return new MainClass(); }
}
";
var comp = CreateCompilationWithMscorlib40AndSystemCore(source);
comp.VerifyDiagnostics(
// (8,13): error CS0019: Operator '+' cannot be applied to operands of type 'MainClass' and 'lambda expression'
// r = r + ((MainClass x) => x + (MainClass)((MainClass y) => (y + null)));
Diagnostic(ErrorCode.ERR_BadBinaryOps, "r + ((MainClass x) => x + (MainClass)((MainClass y) => (y + null)))").WithArguments("+", "MainClass", "lambda expression"));
}
[WorkItem(545467, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545467")]
[Fact]
public void ClassPlusLambda3()
{
// In this variation we remove the other addition operator. The native compiler
// disallows three of these additions, because as mentioned above, it is inconsistent
// about when a user-defined conversion may be from a lambda. The native compiler says
// that the user-defined conversion may only be from a lambda if a cast appears in
// the source; in three of the four conversions from lambdas here, there is no cast.
//
// Roslyn replicates this bug.
var source = @"
class MainClass
{
public static void Main()
{
MainClass r = new MainClass();
r = r + ((MainClass x) => (x + ((MainClass y) => (y + null))));
r = r + ((MainClass x) => (x + (MainClass)((MainClass y) => (y + null))));
System.Func<MainClass, MainClass> f = x => x + (y => y);
}
public static MainClass operator +(MainClass r1, MainClass r2) { return r1; }
// public static MainClass operator +(MainClass r1,
// System.Linq.Expressions.Expression<System.Func<MainClass, MainClass>> e)
// { return r1; }
public static implicit operator MainClass(
System.Linq.Expressions.Expression<System.Func<MainClass, MainClass>> e)
{ return new MainClass(); }
}
";
// NOTE: roslyn suppresses the error for (x + (...)) in the first assignment,
// but it's still an error (as indicated by the standalone test below).
var comp = CreateCompilationWithMscorlib40AndSystemCore(source);
comp.VerifyDiagnostics(
// (7,13): error CS0019: Operator '+' cannot be applied to operands of type 'MainClass' and 'lambda expression'
// r = r + ((MainClass x) => (x + ((MainClass y) => (y + null))));
Diagnostic(ErrorCode.ERR_BadBinaryOps, "r + ((MainClass x) => (x + ((MainClass y) => (y + null))))").WithArguments("+", "MainClass", "lambda expression"),
// (8,13): error CS0019: Operator '+' cannot be applied to operands of type 'MainClass' and 'lambda expression'
// r = r + ((MainClass x) => (x + (MainClass)((MainClass y) => (y + null))));
Diagnostic(ErrorCode.ERR_BadBinaryOps, "r + ((MainClass x) => (x + (MainClass)((MainClass y) => (y + null))))").WithArguments("+", "MainClass", "lambda expression"),
// (9,52): error CS0019: Operator '+' cannot be applied to operands of type 'MainClass' and 'lambda expression'
// System.Func<MainClass, MainClass> f = x => x + (y => y);
Diagnostic(ErrorCode.ERR_BadBinaryOps, "x + (y => y)").WithArguments("+", "MainClass", "lambda expression"));
}
[WorkItem(545467, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545467")]
[Fact]
public void ClassPlusLambda4()
{
// In this final variation, we remove the user-defined conversion. And now of course we cannot
// add MainClass to the lambda at all; the native compiler and Roslyn agree.
var source = @"
class MainClass
{
static void Main()
{
MainClass r = new MainClass();
r = r + ((MainClass x) => x + ((MainClass y) => (y + null)));
r = r + ((MainClass x) => x + (MainClass)((MainClass y) => (y + null)));
}
public static MainClass operator +(MainClass r1, MainClass r2) { return r1; }
public static MainClass operator +(MainClass r1,
System.Linq.Expressions.Expression<System.Func<MainClass, MainClass>> e)
{ return r1; }
// public static implicit operator MainClass(
// System.Linq.Expressions.Expression<System.Func<MainClass, MainClass>> e)
// { return new MainClass(); }
}
";
var comp = CreateCompilationWithMscorlib40AndSystemCore(source);
comp.VerifyDiagnostics(
// (7,13): error CS0019: Operator '+' cannot be applied to operands of type 'MainClass' and 'lambda expression'
// r = r + ((MainClass x) => x + ((MainClass y) => (y + null)));
Diagnostic(ErrorCode.ERR_BadBinaryOps, "r + ((MainClass x) => x + ((MainClass y) => (y + null)))").WithArguments("+", "MainClass", "lambda expression"),
// (8,13): error CS0019: Operator '+' cannot be applied to operands of type 'MainClass' and 'lambda expression'
// r = r + ((MainClass x) => x + (MainClass)((MainClass y) => (y + null)));
Diagnostic(ErrorCode.ERR_BadBinaryOps, "r + ((MainClass x) => x + (MainClass)((MainClass y) => (y + null)))").WithArguments("+", "MainClass", "lambda expression"));
}
[WorkItem(546875, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546875")]
[WorkItem(530930, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530930")]
[Fact]
public void BigVisitor()
{
// Reduced from Microsoft.Data.Schema.Sql.dll.
var source = @"
public class Test
{
static void Main()
{
var visitor = new ConcreteVisitor();
visitor.Visit(new Class090());
}
}
";
var libRef = TestReferences.SymbolsTests.BigVisitor;
var start = DateTime.UtcNow;
CreateCompilationWithMscorlib40AndSystemCore(source, new[] { libRef }).VerifyDiagnostics();
var elapsed = DateTime.UtcNow - start;
Assert.InRange(elapsed.TotalSeconds, 0, 10.0); // Was originally over 30 minutes, so we have some wiggle room here.
}
[WorkItem(546730, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546730"), WorkItem(546739, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546739")]
[Fact]
public void TestNamedParamsParam()
{
CompileAndVerify(@"
class C
{
static void M(
int x,
double y,
params string[] z)
{
System.Console.WriteLine(1);
}
static void M(
int x,
params string[] z)
{
System.Console.WriteLine(2);
}
static void Main()
{
C.M(0, z: """");
}
}", expectedOutput: "2").VerifyDiagnostics();
}
[WorkItem(531173, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531173")]
[Fact]
public void InvokeMethodOverridingNothing()
{
var source = @"
public class C
{
public override T Override<T>(T t)
{
return t;
}
public void Test<T>(T t)
{
Override(t);
}
}
";
CreateCompilation(source).VerifyDiagnostics(
// (4,20): error CS0115: 'C.Override<T>(T)': no suitable method found to override
// public override T Override<T>(T t)
Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Override").WithArguments("C.Override<T>(T)"));
}
[WorkItem(547186, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/547186")]
[Fact, WorkItem(531613, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531613")]
public void IndexerWithoutAccessors()
{
var source = @"
class Program
{
public static void Main()
{
C c = new C();
c[""""] = 10;
}
}
abstract class A
{
public abstract int this[string arg] { set; }
}
class C : A
{
public override int this[string arg]
// Not finished typing yet.
";
// Doesn't assert.
CreateCompilation(source).VerifyDiagnostics(
// (18,41): error CS1514: { expected
// public override int this[string arg]
Diagnostic(ErrorCode.ERR_LbraceExpected, ""),
// (18,41): error CS1513: } expected
// public override int this[string arg]
Diagnostic(ErrorCode.ERR_RbraceExpected, ""),
// (18,41): error CS1513: } expected
// public override int this[string arg]
Diagnostic(ErrorCode.ERR_RbraceExpected, ""),
// (18,25): error CS0548: 'C.this[string]': property or indexer must have at least one accessor
// public override int this[string arg]
Diagnostic(ErrorCode.ERR_PropertyWithNoAccessors, "this").WithArguments("C.this[string]"),
// (16,7): error CS0534: 'C' does not implement inherited abstract member 'A.this[string].set'
// class C : A
Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "C").WithArguments("C", "A.this[string].set"));
}
[Fact]
public void DynamicVsTypeParameters()
{
string source = @"
using System;
public class B<T>
{
public void F(T p1) { }
public void F(dynamic p1) { }
}
class C
{
void M(B<C> b)
{
b.F(null); //-B<C>.F(C)
}
}";
TestOverloadResolutionWithDiff(source, new[] { CSharpRef, SystemCoreRef });
}
[Fact]
public void DynamicByRef()
{
string source = @"
using System;
public class C
{
public static int F(int p1, char p2, ref dynamic p3) { return 2; }
public static int F(C p1, params dynamic[] p2) { return 3; }
public static implicit operator int(C t) { return 1; }
public static implicit operator C(int t) { return new C(); }
static void M()
{
dynamic d1 = null;
C c = null;
C.F(c, 'a', ref d1); //-C.F(int, char, ref dynamic)
}
}";
TestOverloadResolutionWithDiff(source);
}
[Fact, WorkItem(624410, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/624410")]
public void DynamicTypeInferenceAndPointer()
{
string source = @"
public unsafe class C
{
public static void M()
{
dynamic x = null;
Bar(x);
}
static void Bar<T>(D<T>.E*[] x) { }
}
class D<T>
{
public enum E { }
}
";
// Dev11 reports error CS0411: The type arguments for method 'C.Bar<T>(D<T>.E*[])' cannot be inferred from the usage. Try
// specifying the type arguments explicitly.
CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics();
}
[Fact, WorkItem(598032, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/598032"), WorkItem(1157097, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1157097"), WorkItem(2298, "https://github.com/dotnet/roslyn/issues/2298")]
public void GenericVsOptionalParameter()
{
string source = @"
using System;
class C
{
public static int Goo(int x, string y = null) { return 1; }
public static int Goo<T>(T x) { return 0; }
public static void Main()
{
System.Console.WriteLine(Goo(0));
}
}
";
var compilation = CreateCompilation(source, options: TestOptions.DebugExe);
CompileAndVerify(compilation, expectedOutput: "0");
}
[WorkItem(598029, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/598029")]
[Fact]
public void TypeParameterInterfaceVersusNonInterface()
{
string source = @"
interface IA
{
int Goo(int x = 0);
}
class C : IA
{
public int Goo(int x)
{
return x;
}
static int M<T>(T x) where T : A, IA
{
return x.Goo(); //-IA.Goo(int)
}
}
";
TestOverloadResolutionWithDiff(source);
}
[WorkItem(649807, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/649807")]
[Fact]
public void OverloadResolution649807()
{
var source = @"
public class Test
{
public delegate dynamic @nongenerics(dynamic id);
public delegate T @generics< T>(dynamic id);
public dynamic Goo(nongenerics Meth, dynamic id)
{
return null;
}
public T Goo<T>(generics<T> Meth, dynamic id)
{
return default(T);
}
public dynamic method(dynamic id)
{
return System.String.Empty;
}
public dynamic testGoo(dynamic id)
{
return Goo(method, ""abc"");
}
static void Main(string[] args)
{
}
}";
// Doesn't assert.
CreateCompilationWithMscorlib40AndSystemCore(source).VerifyDiagnostics(
// (20,16): error CS0121: The call is ambiguous between the following methods or properties: 'Test.Goo(Test.nongenerics, dynamic)' and 'Test.Goo<T>(Test.generics<T>, dynamic)'
// return Goo(method, "abc");
Diagnostic(ErrorCode.ERR_AmbigCall, "Goo").WithArguments("Test.Goo(Test.nongenerics, dynamic)", "Test.Goo<T>(Test.generics<T>, dynamic)")
);
}
[WorkItem(662641, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/662641")]
[Fact]
public void GenericMethodConversionToDelegateWithDynamic()
{
var source = @"
using System;
public delegate void D002<T1, T2>(T1 t1, T2 t2);
public delegate void D003(dynamic t1, object t2);
public class Goo
{
static internal void M11<T1, T2>(T1 t1, T2 t2)
{
}
}
public struct @start
{
static void M(D002<dynamic, object> d) {}
static public void Main()
{
dynamic d1 = null;
object o1 = null;
Goo.M11<dynamic, object>(d1, o1);
Goo.M11(d1, o1);
D002<dynamic, object> dd02 = new D002<dynamic, object>(Goo.M11);
D002<dynamic, object> dd03 = Goo.M11;
D002<dynamic, object> dd04 = (D002<dynamic, object>)Goo.M11;
D003 dd05 = Goo.M11;
M(Goo.M11);
Console.WriteLine(dd02);
}
}";
CreateCompilationWithMscorlib40AndSystemCore(source).VerifyDiagnostics(
);
}
[WorkItem(690966, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/690966")]
[Fact]
public void OptionalParameterInDelegateConversion()
{
var source = @"
using System;
class C
{
static void M1(Func<string, int> f) { }
static void M1(Func<string, string, int> f) { }
static int M2(string s, string t = null) { return 0; }
static void Main()
{
M1(M2);
}
}
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics();
var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree);
var callSyntax = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().Single();
Assert.Equal("void C.M1(System.Func<System.String, System.String, System.Int32> f)",
model.GetSymbolInfo(callSyntax).Symbol.ToTestDisplayString());
}
[WorkItem(718294, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/718294")]
[Fact]
public void MethodGroupConversion_BetterCandidateHasOptionalParameter()
{
var source = @"
using System;
class Test
{
void M(IViewable2 v)
{
v.View(v.Add);
}
}
interface IViewable
{
void View(Action viewer);
}
interface IViewable2 : IViewable
{
}
static class Extensions
{
[Obsolete(""A"", error: false)]
public static void Add(this IViewable2 @this) { }
[Obsolete(""B"", error: false)]
public static void Add(this IViewable @this, object obj = null) { }
}
";
CreateCompilationWithMscorlib40AndSystemCore(source).VerifyDiagnostics(
// (8,16): warning CS0618: 'Extensions.Add(IViewable2)' is obsolete: 'A'
// v.View(v.Add);
Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "v.Add").WithArguments("Extensions.Add(IViewable2)", "A"));
}
[WorkItem(718294, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/718294")]
[Fact]
public void MethodGroupConversion_BetterCandidateHasParameterArray()
{
var source = @"
using System;
class Test
{
void M(IViewable2 v)
{
v.View(v.Add);
}
}
interface IViewable
{
void View(Action viewer);
}
interface IViewable2 : IViewable
{
}
static class Extensions
{
[Obsolete(""A"", error: false)]
public static void Add(this IViewable2 @this) { }
[Obsolete(""B"", error: false)]
public static void Add(this IViewable @this, params object[] obj) { }
}
";
CreateCompilationWithMscorlib40AndSystemCore(source).VerifyDiagnostics(
// (8,16): warning CS0618: 'Extensions.Add(IViewable2)' is obsolete: 'A'
// v.View(v.Add);
Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "v.Add").WithArguments("Extensions.Add(IViewable2)", "A"));
}
[WorkItem(709114, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/709114")]
[Fact]
public void RenameTypeParameterInOverride()
{
var source = @"
public class Base
{
public virtual void M<T1>(T1 t) { }
}
public class Derived : Base
{
public override void M<T2>(T2 t) { }
void Test(int c)
{
M(c);
}
}
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics();
var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree);
var callSyntax = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().Single();
var methodSymbol = (IMethodSymbol)model.GetSymbolInfo(callSyntax).Symbol;
Assert.Equal(SpecialType.System_Int32, methodSymbol.TypeArguments.Single().SpecialType);
}
[Fact]
[WorkItem(675327, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/675327")]
public void OverloadInheritanceAsync()
{
string source = @"
using System.Threading.Tasks;
using System;
class Test
{
public virtual async Task<int> Goo<U>(Func<Task<U>> f)
{
await Task.Delay(10);
return 1;
}
}
class TestCase : Test
{
public override async Task<int> Goo<T>(Func<Task<T>> f)
{
await Task.Delay(10);
return 3;
}
public async Task<int> Goo(Func<Task<long>> f)
{
await Task.Delay(10);
return 2;
}
public async void Run()
{
var xxx = await Goo(async () => { // Roslyn error here
await Task.Delay(10);
return 5m; });
Console.WriteLine(xxx); // 3;
}
}";
CreateCompilationWithMscorlib45(source).VerifyDiagnostics();
}
[Fact]
[WorkItem(675327, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/675327")]
public void OverloadInheritance001()
{
string source = @"
using System;
class Test
{
public virtual int Goo<U>(Func<U> f)
{
return 1;
}
}
class TestCase : Test
{
public override int Goo<T>(Func<T> f)
{
return 3;
}
public void Run()
{
var xxx = Goo(() => { // Roslyn error here
return 5m; });
Console.WriteLine(xxx); // 3;
}
}";
CreateCompilationWithMscorlib45(source).VerifyDiagnostics();
}
[Fact, WorkItem(718294, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/718294")]
public void ResolveExtensionMethodGroupOverloadWithOptional()
{
string source = @"
using System;
class Viewable
{
static void Main()
{
IViewable2<object> v = null;
v.View(v.Add);
}
}
interface IViewable<T>
{
void View(Action<T> viewer);
}
interface IViewable2<T> : IViewable<T>
{
}
static class Extensions
{
public static void Add<T>(this IViewable<T> @this, T item)
{
}
public static void Add<T>(this IViewable2<T> @this, T item, object obj = null)
{
}
}";
CreateCompilationWithMscorlib45(source).VerifyDiagnostics();
}
[Fact, WorkItem(667132, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/667132")]
public void ExtensionMethodOnComInterfaceMissingRefToken()
{
string source = @"using System;
using System.Runtime.InteropServices;
[ComImport, Guid(""cb4ac859-0589-483e-934d-b27845d5fe74"")]
interface IGoo
{
}
static class Program
{
public static void Bar(this IGoo self, ref Guid id)
{
id = Guid.NewGuid();
}
static void Main()
{
Goo(null);
}
static void Goo(IGoo o)
{
Guid g = Guid.NewGuid();
Console.WriteLine(g);
o.Bar(g);
Console.WriteLine(g);
}
}";
CreateCompilationWithMscorlib45(source).VerifyDiagnostics();
}
[Fact]
[WorkItem(737971, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/737971")]
public void Repro737971a()
{
var source = @"
using System;
public class Color
{
}
public class ColorToColor
{
public static implicit operator ColorToColor(Func<Color, Color> F) { return null; }
}
public class Test
{
public void M()
{
N(_ => default(Color));
}
public void N(ColorToColor F) { }
public void N(Func<Color, Color> F) { }
}
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics();
var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree);
var syntax = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().Single();
var symbol = model.GetSymbolInfo(syntax).Symbol;
// Func<Color, Color> is convertible to ColorToColor, but the converse is not true.
Assert.Equal("void Test.N(System.Func<Color, Color> F)", symbol.ToTestDisplayString());
}
[Fact]
[WorkItem(737971, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/737971")]
public void Repro737971b()
{
var source = @"
using System;
public class Color
{
}
public class ColorToColor
{
public static implicit operator ColorToColor(Func<Color, Color> F) { throw null; }
}
public class Test
{
public void M()
{
N(() => _ => default(Color));
}
public void N(Func<ColorToColor> F) { }
public void N(Func<Func<Color, Color>> F) { }
}
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics();
var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree);
var syntax = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().Single();
var symbol = model.GetSymbolInfo(syntax).Symbol;
// Func<Func<Color, Color>> is convertible to Func<ColorToColor>, but the converse is not true.
Assert.Equal("void Test.N(System.Func<System.Func<Color, Color>> F)", symbol.ToTestDisplayString());
}
[Fact]
[WorkItem(754406, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/754406")]
public void TestBug754406()
{
string source =
@"interface I {}
class G<T> where T : I {}
class Program
{
static void Main(string[] args)
{
}
static void M<T>(G<T> gt1, params int[] i)
{
M(gt1, 1, 2);
}
}";
var comp = CreateCompilationWithMscorlib40AndSystemCore(source);
comp.VerifyDiagnostics(
// (9,27): error CS0314: The type 'T' cannot be used as type parameter 'T' in the generic type or method 'G<T>'. There is no boxing conversion or type parameter conversion from 'T' to 'I'.
// static void M<T>(G<T> gt1, params int[] i)
Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedTyVar, "gt1").WithArguments("G<T>", "I", "T", "T"),
// (11,9): error CS0314: The type 'T' cannot be used as type parameter 'T' in the generic type or method 'G<T>'. There is no boxing conversion or type parameter conversion from 'T' to 'I'.
// M(gt1, 1, 2);
Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedTyVar, "M").WithArguments("G<T>", "I", "T", "T")
);
}
[Fact]
[WorkItem(528811, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528811")]
public void TestBug528811()
{
string source =
@"using System;
delegate byte DL();
class Test
{
void goo()
{
EventHandler y = null;
y += goo;
y += x => 2;
}
}";
var comp = CreateCompilationWithMscorlib40AndSystemCore(source);
comp.VerifyDiagnostics(
// (9,14): error CS0123: No overload for 'goo' matches delegate 'System.EventHandler'
// y += goo;
Diagnostic(ErrorCode.ERR_MethDelegateMismatch, "goo").WithArguments("goo", "System.EventHandler"),
// (10,14): error CS1593: Delegate 'System.EventHandler' does not take 1 arguments
// y += x => 2;
Diagnostic(ErrorCode.ERR_BadDelArgCount, "x => 2").WithArguments("System.EventHandler", "1")
);
}
[Fact]
public void IndexMemberAccessErr005()
{
var source = @"
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
var d = new Dictionary<int, int>() {[""aaa""] = 3};
}
}
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (8,46): error CS1503: Argument 1: cannot convert from 'string' to 'int'
// var d = new Dictionary<int, int>() {["aaa"] = 3};
Diagnostic(ErrorCode.ERR_BadArgType, @"""aaa""").WithArguments("1", "string", "int").WithLocation(8, 46)
);
}
[Fact]
public void IndexMemberAccessErr006()
{
var source = @"
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
var d = new int[] {[1] = 3 };
}
}
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (8,28): error CS1513: } expected
// var d = new int[] {[1] = 3 };
Diagnostic(ErrorCode.ERR_RbraceExpected, "[").WithLocation(8, 28),
// (8,36): error CS1002: ; expected
// var d = new int[] {[1] = 3 };
Diagnostic(ErrorCode.ERR_SemicolonExpected, "}").WithLocation(8, 36),
// (8,37): error CS1597: Semicolon after method or accessor block is not valid
// var d = new int[] {[1] = 3 };
Diagnostic(ErrorCode.ERR_UnexpectedSemicolon, ";").WithLocation(8, 37),
// (10,1): error CS1022: Type or namespace definition, or end-of-file expected
// }
Diagnostic(ErrorCode.ERR_EOFExpected, "}").WithLocation(10, 1),
// (2,1): info CS8019: Unnecessary using directive.
// using System.Collections.Generic;
Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using System.Collections.Generic;").WithLocation(2, 1)
);
}
[Fact]
[WorkItem(655409, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/655409")]
public void TestBug655409()
{
string source =
@"
using System;
class C
{
static void Main()
{
M(a => M(b => M(c => M(d => M(e => M(f => a))))));
System.Console.WriteLine(""success"");
}
static T M<T>(Func<bool, T> x) { return default(T); }
static T M<T>(Func<byte, T> x) { return default(T); }
static T M<T>(Func<uint, T> x) { return default(T); }
static T M<T>(Func<long, T> x) { return default(T); }
}
";
var comp = CreateCompilationWithMscorlib40AndSystemCore(source);
comp.VerifyDiagnostics(
// (8,44): error CS0121: The call is ambiguous between the following methods or properties: 'C.M<T>(System.Func<bool, T>)' and 'C.M<T>(System.Func<byte, T>)'
// M(a => M(b => M(c => M(d => M(e => M(f => a))))));
Diagnostic(ErrorCode.ERR_AmbigCall, "M").WithArguments("C.M<T>(System.Func<bool, T>)", "C.M<T>(System.Func<byte, T>)").WithLocation(8, 44)
);
}
[Fact, WorkItem(30, "https://roslyn.codeplex.com/workitem/30")]
public void BugCodePlex_30_01()
{
string source1 = @"
using System;
class C
{
static void Main()
{
Goo(() => { return () => 0; ; });
Goo(() => { return () => 0; });
}
static void Goo(Func<Func<short>> x) { Console.WriteLine(1); }
static void Goo(Func<Func<int>> x) { Console.WriteLine(2); }
}
";
CompileAndVerify(source1, expectedOutput: @"2
2");
}
[Fact, WorkItem(30, "https://roslyn.codeplex.com/workitem/30")]
public void BugCodePlex_30_02()
{
string source1 = @"
using System;
class C
{
static void Main()
{
Test(false);
}
static void Test(bool val)
{
Goo(() => { if (val) return () => 0; else return () => (short)0; });
Goo(() => { if (val) return () => (short)0; else return () => 0; });
}
static void Goo(Func<Func<short>> x) { Console.WriteLine(1); }
static void Goo(Func<Func<int>> x) { Console.WriteLine(2); }
}
";
CompileAndVerify(source1, expectedOutput: @"1
1");
}
[Fact, WorkItem(30, "https://roslyn.codeplex.com/workitem/30")]
public void BugCodePlex_30_03()
{
string source1 = @"
using System;
class C
{
static void Main()
{
Test(false);
}
static void Test(bool val)
{
Goo(() => { if (val) return () => 0; else return () => 0; });
}
static void Goo(Func<Func<short>> x) { Console.WriteLine(1); }
static void Goo(Func<Func<int>> x) { Console.WriteLine(2); }
}
";
CompileAndVerify(source1, expectedOutput: @"2");
}
[Fact]
public void ExactlyMatchingAsyncLambda_01()
{
string source1 = @"
using System;
using System.Threading.Tasks;
class C
{
static void Main()
{
#pragma warning disable 1998
Goo(async () => { return 0; ; });
Goo(async () => { return 0; });
Goo(async () => 0);
Goo(async () => { return (short)0; ; });
Goo(async () => { return (short)0; });
Goo(async () => (short)0);
}
static void Goo(Func<Task<short>> x) { Console.WriteLine(1); }
static void Goo(Func<Task<int>> x) { Console.WriteLine(2); }
}
";
var compilation = CreateCompilationWithMscorlib45(source1, options: TestOptions.ReleaseExe);
CompileAndVerify(compilation, expectedOutput: @"2
2
2
1
1
1");
}
[Fact]
public void ExactlyMatchingAsyncLambda_02()
{
string source1 = @"
using System;
using System.Threading.Tasks;
class C
{
static void Main()
{
#pragma warning disable 1998
Goo(() => async () => { return 0; ; });
Goo(() => async () => { return 0; });
Goo(() => async () => 0);
Goo(() => { return async () => 0; ; });
Goo(() => { return async () => 0; });
}
static void Goo(Func<Func<Task<short>>> x) { Console.WriteLine(1); }
static void Goo(Func<Func<Task<int>>> x) { Console.WriteLine(2); }
}
";
var compilation = CreateCompilationWithMscorlib45(source1, options: TestOptions.ReleaseExe);
CompileAndVerify(compilation, expectedOutput: @"2
2
2
2
2");
}
[Fact]
public void ExactlyMatchingAsyncLambda_03()
{
string source1 = @"
using System;
using System.Threading.Tasks;
class C
{
static void Main()
{
#pragma warning disable 1998
Goo(async () => { return () => 0; });
Goo(async () => { return () => (short)0; });
}
static void Goo(Func<Task<Func<short>>> x) { Console.WriteLine(1); }
static void Goo(Func<Task<Func<int>>> x) { Console.WriteLine(2); }
}
";
var compilation = CreateCompilationWithMscorlib45(source1, options: TestOptions.ReleaseExe);
CompileAndVerify(compilation, expectedOutput: @"2
1");
}
[Fact]
[WorkItem(1079899, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1079899")]
[WorkItem(364, "CodePlex")]
public void TestBug1079899()
{
string source =
@"
namespace A.B
{
static class X
{
public static int Test(this int o)
{
return 1;
}
}
}
namespace A.C
{
static class X
{
public static int Test(this int o)
{
return 2;
}
}
}
namespace C
{
using A.B;
using static A.C.X;
class M
{
public static int Main()
{
if (1.Test() != 1)
return 1;
return 0;
}
}
}
";
var comp = CreateCompilationWithMscorlib40AndSystemCore(source);
comp.VerifyDiagnostics(
// (31,19): error CS0121: The call is ambiguous between the following methods or properties: 'X.Test(int)' and 'X.Test(int)'
// if (1.Test() != 1)
Diagnostic(ErrorCode.ERR_AmbigCall, "Test").WithArguments("A.B.X.Test(int)", "A.C.X.Test(int)").WithLocation(30, 19)
);
Assert.Equal("(30,19): error CS0121: The call is ambiguous between the following methods or properties: 'A.B.X.Test(int)' and 'A.C.X.Test(int)'", DiagnosticFormatter.Instance.Format(comp.GetDiagnostics()[0], EnsureEnglishUICulture.PreferredOrNull));
}
[Fact, WorkItem(1080896, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1080896"), WorkItem(367, "Devdiv")]
public void Bug1080896_0()
{
string source1 = @"
using System;
namespace ConsoleApplication2
{
class Program
{
public class Goo {
public static bool IsThing(Goo t) { return false; }
}
public class Bar<T, V> where T : class
{
public static Bar<T, V> Create(Func<T, bool> filter)
{
System.Console.WriteLine(""Create(Func<T, bool> filter)"");
return null;
}
public static Bar<T, V> Create(Func<T, V> propertyPrev, Func<T, bool> filter = null)
{
System.Console.WriteLine(""Create(Func<T, V> propertyPrev, Func<T, bool> filter = null)"");
return null;
}
}
static void Main(string[] args)
{
var x = Bar<Goo, double>.Create(Goo.IsThing);
}
}
}
";
var compilation = CreateCompilation(source1, options: TestOptions.DebugExe);
CompileAndVerify(compilation, expectedOutput: @"Create(Func<T, bool> filter)");
}
[Fact, WorkItem(1080896, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1080896"), WorkItem(367, "Devdiv")]
public void Bug1080896_1()
{
string source1 = @"
using System;
namespace ConsoleApplication2
{
class Program
{
public class Goo {
public static bool IsThing(Goo t) { return false; }
}
public class Bar<T, V> where T : class
{
public static Bar<T, V> Create(Func<T, bool> filter)
{
System.Console.WriteLine(""Create(Func < T, bool > filter)"");
return null;
}
public static Bar<T, V> Create(Func<T, V> propertyPrev, params Func<T, bool>[] filter)
{
System.Console.WriteLine(""Create(Func<T, V> propertyPrev, params Func<T, bool>[] filter"");
return null;
}
}
static void Main(string[] args)
{
var x = Bar<Goo, double>.Create(Goo.IsThing);
}
}
}
";
CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.WithoutImprovedOverloadCandidates).VerifyDiagnostics(
// (25,38): error CS0121: The call is ambiguous between the following methods or properties: 'Program.Bar<T, V>.Create(Func<T, bool>)' and 'Program.Bar<T, V>.Create(Func<T, V>, params Func<T, bool>[])'
// var x = Bar<Goo, double>.Create(Goo.IsThing);
Diagnostic(ErrorCode.ERR_AmbigCall, "Create").WithArguments("ConsoleApplication2.Program.Bar<T, V>.Create(System.Func<T, bool>)", "ConsoleApplication2.Program.Bar<T, V>.Create(System.Func<T, V>, params System.Func<T, bool>[])").WithLocation(25, 38)
);
CreateCompilation(source1, options: TestOptions.DebugExe).VerifyDiagnostics(
);
}
[Fact, WorkItem(1080896, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1080896"), WorkItem(367, "Devdiv")]
public void Bug1080896_2()
{
string source1 = @"
using System;
namespace ConsoleApplication2
{
class Program
{
public class Goo {
public static double IsThing(Goo t) { return 0; }
}
public class Bar<T, V> where T : class
{
public static Bar<T, V> Create(Func<T, bool> filter, params int[] dummy)
{
System.Console.WriteLine(""Create(Func<T, bool> filter, params int[] dummy)"");
return null;
}
public static Bar<T, V> Create(Func<T, V> propertyPrev, Func<T, bool> filter = null)
{
System.Console.WriteLine(""Create(Func<T, V> propertyPrev, Func<T, bool> filter = null)"");
return null;
}
}
static void Main(string[] args)
{
var x = Bar<Goo, double>.Create(Goo.IsThing);
}
}
}
";
var compilation = CreateCompilation(source1, options: TestOptions.DebugExe);
CompileAndVerify(compilation, expectedOutput: @"Create(Func<T, V> propertyPrev, Func<T, bool> filter = null)");
}
[Fact, WorkItem(1080896, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1080896"), WorkItem(367, "Devdiv")]
public void Bug1080896_3()
{
string source1 = @"
using System;
namespace ConsoleApplication2
{
class Program
{
public class Goo {
public static double IsThing(Goo t) { return 0; }
}
public class Bar<T, V> where T : class
{
public static Bar<T, V> Create(Func<T, bool> filter, params int[] dummy)
{
System.Console.WriteLine(""Create(Func<T, bool> filter, params int[] dummy)"");
return null;
}
public static Bar<T, V> Create(Func<T, V> propertyPrev)
{
System.Console.WriteLine(""Create(Func<T, V> propertyPrev)"");
return null;
}
}
static void Main(string[] args)
{
var x = Bar<Goo, double>.Create(Goo.IsThing);
}
}
}
";
CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.WithoutImprovedOverloadCandidates).VerifyDiagnostics(
// (25,38): error CS0121: The call is ambiguous between the following methods or properties: 'Program.Bar<T, V>.Create(Func<T, bool>, params int[])' and 'Program.Bar<T, V>.Create(Func<T, V>)'
// var x = Bar<Goo, double>.Create(Goo.IsThing);
Diagnostic(ErrorCode.ERR_AmbigCall, "Create").WithArguments("ConsoleApplication2.Program.Bar<T, V>.Create(System.Func<T, bool>, params int[])", "ConsoleApplication2.Program.Bar<T, V>.Create(System.Func<T, V>)").WithLocation(25, 38)
);
CreateCompilation(source1, options: TestOptions.DebugExe).VerifyDiagnostics(
);
}
[Fact, WorkItem(1080896, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1080896"), WorkItem(367, "Devdiv")]
public void Bug1080896_4()
{
string source1 = @"
using System;
namespace ConsoleApplication2
{
class Program
{
public class Goo {
public static double IsThing(Goo t) { return 0; }
}
public class Bar<T, V> where T : class
{
public static Bar<T, V> Create(Func<T, V> propertyPrev)
{
System.Console.WriteLine(""Create(Func<T, V> propertyPrev)"");
return null;
}
public static Bar<T, V> Create(Func<T, bool> filter, params int[] dummy)
{
System.Console.WriteLine(""Create(Func<T, bool> filter, params int[] dummy)"");
return null;
}
}
static void Main(string[] args)
{
var x = Bar<Goo, double>.Create(Goo.IsThing);
}
}
}
";
CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.WithoutImprovedOverloadCandidates).VerifyDiagnostics(
// (25,38): error CS0121: The call is ambiguous between the following methods or properties: 'Program.Bar<T, V>.Create(Func<T, V>)' and 'Program.Bar<T, V>.Create(Func<T, bool>, params int[])'
// var x = Bar<Goo, double>.Create(Goo.IsThing);
Diagnostic(ErrorCode.ERR_AmbigCall, "Create").WithArguments("ConsoleApplication2.Program.Bar<T, V>.Create(System.Func<T, V>)", "ConsoleApplication2.Program.Bar<T, V>.Create(System.Func<T, bool>, params int[])").WithLocation(25, 38)
);
CreateCompilation(source1, options: TestOptions.DebugExe).VerifyDiagnostics(
);
}
[Fact, WorkItem(1080896, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1080896"), WorkItem(367, "Devdiv")]
public void Bug1080896_5()
{
string source1 = @"
using System;
namespace ConsoleApplication2
{
class Program
{
public class Goo {
public static bool IsThing(Goo t) { return false; }
}
public class Bar<T, V> where T : class
{
public static Bar<T, V> Create(Func<T, V> propertyPrev, params Func<T, bool>[] filter)
{
System.Console.WriteLine(""Create(Func<T, V> propertyPrev, params Func<T, bool>[] filter"");
return null;
}
public static Bar<T, V> Create(Func<T, bool> filter)
{
System.Console.WriteLine(""Create(Func < T, bool > filter)"");
return null;
}
}
static void Main(string[] args)
{
var x = Bar<Goo, double>.Create(Goo.IsThing);
}
}
}
";
CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.WithoutImprovedOverloadCandidates).VerifyDiagnostics(
// (25,38): error CS0121: The call is ambiguous between the following methods or properties: 'Program.Bar<T, V>.Create(Func<T, V>, params Func<T, bool>[])' and 'Program.Bar<T, V>.Create(Func<T, bool>)'
// var x = Bar<Goo, double>.Create(Goo.IsThing);
Diagnostic(ErrorCode.ERR_AmbigCall, "Create").WithArguments("ConsoleApplication2.Program.Bar<T, V>.Create(System.Func<T, V>, params System.Func<T, bool>[])", "ConsoleApplication2.Program.Bar<T, V>.Create(System.Func<T, bool>)").WithLocation(25, 38)
);
CreateCompilation(source1, options: TestOptions.DebugExe).VerifyDiagnostics(
);
}
[Fact, WorkItem(1080896, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1080896"), WorkItem(367, "Devdiv")]
public void Bug1080896_6()
{
string source1 = @"
using System;
namespace ConsoleApplication2
{
class Program
{
public class Goo {
public static bool IsThing(Goo t) { return false; }
}
public class Bar<T, V> where T : class
{
public static Bar<T, V> Create(Func<T, bool> filter, params int[] extra)
{
return null;
}
public static Bar<T, V> Create(Func<T, V> propertyPrev, params int[] extra)
{
return null;
}
}
static void Main(string[] args)
{
var x = Bar<Goo, double>.Create(Goo.IsThing);
}
}
}
";
CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.WithoutImprovedOverloadCandidates).VerifyDiagnostics(
// (23,38): error CS0121: The call is ambiguous between the following methods or properties: 'Program.Bar<T, V>.Create(Func<T, bool>, params int[])' and 'Program.Bar<T, V>.Create(Func<T, V>, params int[])'
// var x = Bar<Goo, double>.Create(Goo.IsThing);
Diagnostic(ErrorCode.ERR_AmbigCall, "Create").WithArguments("ConsoleApplication2.Program.Bar<T, V>.Create(System.Func<T, bool>, params int[])", "ConsoleApplication2.Program.Bar<T, V>.Create(System.Func<T, V>, params int[])").WithLocation(23, 38)
);
CreateCompilation(source1, options: TestOptions.DebugExe).VerifyDiagnostics(
);
}
[Fact, WorkItem(1081302, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1081302"), WorkItem(371, "Devdiv")]
public void Bug1081302_0()
{
string source1 = @"
using System;
namespace ConsoleApplication2
{
public static class Goo
{
public static U IfNotNull<T, U>(this T value, Func<T, U> selector, U defaultValue = default(U))
{
System.Console.WriteLine(""IfNotNull<T, U>(this T value, Func<T, U> selector, U defaultValue = default(U))"");
return value != null ? selector(value) : defaultValue;
}
public static U IfNotNull<T, U>(this T? source, Func<T, U> selector) where T : struct
{
System.Console.WriteLine(""IfNotNull<T, U>(this T? source, Func<T, U> selector)"");
return source.HasValue ? selector(source.Value) : default(U);
}
}
class Program
{
static void Main(string[] args)
{
double? val = null;
var d1 = val.IfNotNull(v => v / 100);
var d2 = Goo.IfNotNull(val, v => v / 100);
}
}
}
";
var compilation = CreateCompilation(source1, options: TestOptions.DebugExe);
CompileAndVerify(compilation, expectedOutput:
@"IfNotNull<T, U>(this T? source, Func<T, U> selector)
IfNotNull<T, U>(this T? source, Func<T, U> selector)");
}
[Fact, WorkItem(1081302, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1081302"), WorkItem(371, "Devdiv")]
public void Bug1081302_1()
{
string source1 = @"
using System;
namespace ConsoleApplication2
{
public static class Goo
{
public static U IfNotNull<T, U>(this T value, Func<T, U> selector, params U[] defaultValue)
{
System.Console.WriteLine(""IfNotNull<T, U>(this T value, Func<T, U> selector, params U[] defaultValue)"");
return value != null ? selector(value) : defaultValue[0];
}
public static U IfNotNull<T, U>(this T? source, Func<T, U> selector) where T : struct
{
System.Console.WriteLine(""IfNotNull<T, U>(this T? source, Func<T, U> selector)"");
return source.HasValue ? selector(source.Value) : default(U);
}
}
class Program
{
static void Main(string[] args)
{
double? val = null;
var d1 = val.IfNotNull(v => v / 100);
var d2 = Goo.IfNotNull(val, v => v / 100);
}
}
}
";
var compilation = CreateCompilationWithMscorlib40(source1, new[] { TestMetadata.Net40.SystemCore }, options: TestOptions.DebugExe);
compilation.VerifyDiagnostics();
}
[Fact, WorkItem(1081302, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1081302"), WorkItem(371, "Devdiv")]
public void Bug1081302_2()
{
string source1 = @"
using System;
namespace ConsoleApplication2
{
public static class Goo
{
public static U IfNotNull<T, U>(this T? source, Func<T, U> selector) where T : struct
{
System.Console.WriteLine(""IfNotNull<T, U>(this T? source, Func<T, U> selector)"");
return source.HasValue ? selector(source.Value) : default(U);
}
public static U IfNotNull<T, U>(this T value, Func<T, U> selector, params U[] defaultValue)
{
System.Console.WriteLine(""IfNotNull<T, U>(this T value, Func<T, U> selector, params U[] defaultValue)"");
return value != null ? selector(value) : defaultValue[0];
}
}
class Program
{
static void Main(string[] args)
{
double? val = null;
var d1 = val.IfNotNull(v => v / 100);
var d2 = Goo.IfNotNull(val, v => v / 100);
}
}
}
";
var compilation = CreateCompilationWithMscorlib40(source1, new[] { TestMetadata.Net40.SystemCore }, options: TestOptions.DebugExe);
compilation.VerifyDiagnostics();
}
[Fact]
public void ExactParameterMatchAndOptionals()
{
string source1 = @"
class CTest
{
static void Main()
{
M1(0);
}
static void M1(int x)
{
System.Console.WriteLine(""M1(int x)"");
}
static void M1(int x, int y = 0)
{
System.Console.WriteLine(""M1(int x, int y = 0)"");
}
static void M1(int x, params int [] y)
{
System.Console.WriteLine(""M1(int x, params int [] y)"");
}
}
";
var compilation = CreateCompilation(source1, options: TestOptions.DebugExe);
CompileAndVerify(compilation, expectedOutput: @"M1(int x)");
}
[Fact]
[WorkItem(1034429, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1034429")]
public void TestBug1034429()
{
string source =
@"
using System.Security.Permissions;
class Program
{
[A(SecurityAction.Assert)]
[B(p2: SecurityAction.Assert, p1: 0)]
[C(p3: ""again"", p2: SecurityAction.Assert, p1: 0)]
static void Main()
{
}
}
public class A : CodeAccessSecurityAttribute
{
public A(params SecurityAction)
{
}
}
public class B : CodeAccessSecurityAttribute
{
public B(int p1, params SecurityAction p2)
{
}
}
public class C : CodeAccessSecurityAttribute
{
public C(int p1, params SecurityAction p2, string p3)
{
}
}
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (16,35): error CS1001: Identifier expected
// public A(params SecurityAction)
Diagnostic(ErrorCode.ERR_IdentifierExpected, ")").WithLocation(16, 35),
// (30,22): error CS0231: A params parameter must be the last parameter in a parameter list
// public C(int p1, params SecurityAction p2, string p3)
Diagnostic(ErrorCode.ERR_ParamsLast, "params SecurityAction p2").WithLocation(30, 22),
// (14,14): error CS0534: 'A' does not implement inherited abstract member 'SecurityAttribute.CreatePermission()'
// public class A : CodeAccessSecurityAttribute
Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "A").WithArguments("A", "System.Security.Permissions.SecurityAttribute.CreatePermission()").WithLocation(14, 14),
// (28,14): error CS0534: 'C' does not implement inherited abstract member 'SecurityAttribute.CreatePermission()'
// public class C : CodeAccessSecurityAttribute
Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "C").WithArguments("C", "System.Security.Permissions.SecurityAttribute.CreatePermission()").WithLocation(28, 14),
// (21,14): error CS0534: 'B' does not implement inherited abstract member 'SecurityAttribute.CreatePermission()'
// public class B : CodeAccessSecurityAttribute
Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "B").WithArguments("B", "System.Security.Permissions.SecurityAttribute.CreatePermission()").WithLocation(21, 14),
// (16,14): error CS0225: The params parameter must be a single dimensional array
// public A(params SecurityAction)
Diagnostic(ErrorCode.ERR_ParamsMustBeArray, "params").WithLocation(16, 14),
// (23,22): error CS0225: The params parameter must be a single dimensional array
// public B(int p1, params SecurityAction p2)
Diagnostic(ErrorCode.ERR_ParamsMustBeArray, "params").WithLocation(23, 22),
// (30,22): error CS0225: The params parameter must be a single dimensional array
// public C(int p1, params SecurityAction p2, string p3)
Diagnostic(ErrorCode.ERR_ParamsMustBeArray, "params").WithLocation(30, 22),
// (7,6): error CS7048: First argument to a security attribute must be a valid SecurityAction
// [B(p2: SecurityAction.Assert, p1: 0)]
Diagnostic(ErrorCode.ERR_SecurityAttributeMissingAction, "B").WithLocation(7, 6),
// (8,6): error CS7048: First argument to a security attribute must be a valid SecurityAction
// [C(p3: "again", p2: SecurityAction.Assert, p1: 0)]
Diagnostic(ErrorCode.ERR_SecurityAttributeMissingAction, "C").WithLocation(8, 6),
// (16,12): error CS7036: There is no argument given that corresponds to the required parameter 'action' of 'CodeAccessSecurityAttribute.CodeAccessSecurityAttribute(SecurityAction)'
// public A(params SecurityAction)
Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "A").WithArguments("action", "System.Security.Permissions.CodeAccessSecurityAttribute.CodeAccessSecurityAttribute(System.Security.Permissions.SecurityAction)").WithLocation(16, 12),
// (23,12): error CS7036: There is no argument given that corresponds to the required parameter 'action' of 'CodeAccessSecurityAttribute.CodeAccessSecurityAttribute(SecurityAction)'
// public B(int p1, params SecurityAction p2)
Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "B").WithArguments("action", "System.Security.Permissions.CodeAccessSecurityAttribute.CodeAccessSecurityAttribute(System.Security.Permissions.SecurityAction)").WithLocation(23, 12),
// (30,12): error CS7036: There is no argument given that corresponds to the required parameter 'action' of 'CodeAccessSecurityAttribute.CodeAccessSecurityAttribute(SecurityAction)'
// public C(int p1, params SecurityAction p2, string p3)
Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "C").WithArguments("action", "System.Security.Permissions.CodeAccessSecurityAttribute.CodeAccessSecurityAttribute(System.Security.Permissions.SecurityAction)").WithLocation(30, 12));
}
[WorkItem(18875, "https://github.com/dotnet/roslyn/issues/18875")]
[Fact]
public void InvalidParamsPositionCSharp()
{
const string source = @"
public class A
{
public static void Goo(params int[] vals, bool truth)
{
}
public static void Bar()
{
// 1 shouldn't show CS1503 Argument 1: cannot convert from 'int' to 'int'
Goo(1, true);
}
}
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (4,28): error CS0231: A params parameter must be the last parameter in a parameter list
// public static void Goo(params int[] vals, bool truth)
Diagnostic(ErrorCode.ERR_ParamsLast, "params int[] vals"),
// (12,13): error CS1503: Argument 1: cannot convert from 'int' to 'params int[]'
// Goo(1, true);
Diagnostic(ErrorCode.ERR_BadArgType, "1").WithArguments("1", "int", "params int[]").WithLocation(12, 13));
}
[WorkItem(2249, "https://github.com/dotnet/roslyn/issues/2249")]
[Fact]
public void TestRefMethodGroup()
{
var source =
@"using System;
class Program
{
static void M()
{
Console.WriteLine(""pass"");
}
public static void Main(string[] args)
{
Action a1 = new Action(ref M);
a1();
Action a2 = new Action(out a1);
a2();
}
}";
CompileAndVerify(source, expectedOutput: @"pass
pass").VerifyDiagnostics();
CreateCompilation(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular.WithStrictFeature()).VerifyDiagnostics(
// (12,36): error CS1657: Cannot use 'M' as a ref or out value because it is a 'method group'
// Action a1 = new Action(ref M);
Diagnostic(ErrorCode.ERR_RefReadonlyLocalCause, "M").WithArguments("M", "method group").WithLocation(12, 36),
// (14,36): error CS0149: Method name expected
// Action a2 = new Action(out a1);
Diagnostic(ErrorCode.ERR_MethodNameExpected, "a1").WithLocation(14, 36)
);
}
[Fact, WorkItem(1157097, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1157097"), WorkItem(2298, "https://github.com/dotnet/roslyn/issues/2298")]
public void ParamsAndOptionals()
{
string source1 = @"
using System;
using System.Collections.Generic;
using VS2015CompilerBug;
public static class Extensions
{
//extension with params keyword
public static int Properties(this IFirstInterface source, params int[] x)
{
System.Console.WriteLine(""int Properties(this IFirstInterface source, params int[] x)"");
return 0;
}
public static bool Properties(this ISecondInterface source, int x = 0, params int[] y)
{
System.Console.WriteLine(""bool Properties(this ISecondInterface source, int x = 0, params int[] y)"");
return true;
}
//extension without params keyword
public static int Properties2(this IFirstInterface source)
{
System.Console.WriteLine(""int Properties2(this IFirstInterface source)"");
return 0;
}
public static bool Properties2(this ISecondInterface source, int x = 0)
{
System.Console.WriteLine(""bool Properties2(this ISecondInterface source, int x = 0)"");
return true;
}
}
namespace VS2015CompilerBug
{
public interface IFirstInterface
{
}
public interface ISecondInterface
{
}
public interface IFinalInterface : ISecondInterface, IFirstInterface
{
}
public class VS2015CompilerBug
{
public static void Main()
{
IFinalInterface x = default(IFinalInterface);
var properties = x.Properties();
var properties2 = x.Properties2();
(new VS2015CompilerBug()).Test2();
}
private void Test2(int x = 5, params int[] y)
{
System.Console.WriteLine(""void Test2(int x = 5, params int[] y)"");
}
private void Test2(params int[] x)
{
System.Console.WriteLine(""void Test2(params int[] x)"");
}
}
}
";
var compilation = CreateCompilation(source1, options: TestOptions.DebugExe);
CompileAndVerify(compilation, expectedOutput:
@"int Properties(this IFirstInterface source, params int[] x)
int Properties2(this IFirstInterface source)
void Test2(params int[] x)");
}
[Fact, WorkItem(1157097, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1157097"), WorkItem(2298, "https://github.com/dotnet/roslyn/issues/2298")]
public void TieBreakOnNumberOfDeclaredParameters_01()
{
string source1 = @"
namespace VS2015CompilerBug
{
public class VS2015CompilerBug
{
public static void Main()
{
(new VS2015CompilerBug()).Test2(1);
(new VS2015CompilerBug()).Test2(1, 2);
(new VS2015CompilerBug()).Test2(1, 2, 3);
(new VS2015CompilerBug()).Test3(1, 2);
(new VS2015CompilerBug()).Test3(1, 2, 3);
(new VS2015CompilerBug()).Test3(1, 2, 3, 4);
}
private void Test2(int x, params int[] y)
{
System.Console.WriteLine(""void Test2(int x, params int[] y)"");
}
private void Test2(params int[] x)
{
System.Console.WriteLine(""void Test2(params int[] x)"");
}
private void Test3(int x, int y, params int[] z)
{
System.Console.WriteLine(""void Test3(int x, int y, params int[] z)"");
}
private void Test3(int x, params int[] y)
{
System.Console.WriteLine(""void Test3(int x, params int[] y)"");
}
}
}
";
var compilation = CreateCompilation(source1, options: TestOptions.DebugExe);
CompileAndVerify(compilation, expectedOutput:
@"void Test2(int x, params int[] y)
void Test2(int x, params int[] y)
void Test2(int x, params int[] y)
void Test3(int x, int y, params int[] z)
void Test3(int x, int y, params int[] z)
void Test3(int x, int y, params int[] z)");
}
[Fact, WorkItem(1157097, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1157097"), WorkItem(2298, "https://github.com/dotnet/roslyn/issues/2298")]
public void TieBreakOnNumberOfDeclaredParameters_02()
{
string source1 = @"
namespace VS2015CompilerBug
{
public class VS2015CompilerBug
{
public static void Main()
{
(new VS2015CompilerBug()).Test2(1, 2);
(new VS2015CompilerBug()).Test3(1, 2, 3);
}
private void Test2(int x = 0, int y = 0)
{
System.Console.WriteLine(""void Test2(int x = 0, int y = 0)"");
}
private void Test2(int x, int y = 0, int z = 0)
{
System.Console.WriteLine(""void Test2(int x, int y = 0, int z = 0)"");
}
private void Test3(int x, int y, int z = 0, int u = 0)
{
System.Console.WriteLine(""void Test3(int x, int y, int z = 0, int u = 0)"");
}
private void Test3(int x, int y = 0, int z = 0)
{
System.Console.WriteLine(""void Test3(int x, int y = 0, int z = 0)"");
}
}
}
";
var compilation = CreateCompilation(source1, options: TestOptions.DebugExe);
CompileAndVerify(compilation, expectedOutput:
@"void Test2(int x = 0, int y = 0)
void Test3(int x, int y = 0, int z = 0)");
}
[Fact, WorkItem(1157097, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1157097"), WorkItem(2298, "https://github.com/dotnet/roslyn/issues/2298")]
public void TieBreakOnNumberOfDeclaredParameters_03()
{
string source1 = @"
namespace VS2015CompilerBug
{
public class VS2015CompilerBug
{
public static void Main()
{
(new VS2015CompilerBug()).Test2(1);
(new VS2015CompilerBug()).Test3(1, 2);
}
private void Test2(int x = 0, int y = 0)
{
}
private void Test2(int x, int y = 0, int z = 0)
{
}
private void Test3(int x, int y, int z = 0, int u = 0)
{
}
private void Test3(int x, int y = 0, int z = 0)
{
}
}
}
";
var compilation = CreateCompilation(source1, options: TestOptions.DebugExe);
compilation.VerifyDiagnostics(
// (9,39): error CS0121: The call is ambiguous between the following methods or properties: 'VS2015CompilerBug.Test2(int, int)' and 'VS2015CompilerBug.Test2(int, int, int)'
// (new VS2015CompilerBug()).Test2(1);
Diagnostic(ErrorCode.ERR_AmbigCall, "Test2").WithArguments("VS2015CompilerBug.VS2015CompilerBug.Test2(int, int)", "VS2015CompilerBug.VS2015CompilerBug.Test2(int, int, int)").WithLocation(9, 39),
// (10,39): error CS0121: The call is ambiguous between the following methods or properties: 'VS2015CompilerBug.Test3(int, int, int, int)' and 'VS2015CompilerBug.Test3(int, int, int)'
// (new VS2015CompilerBug()).Test3(1, 2);
Diagnostic(ErrorCode.ERR_AmbigCall, "Test3").WithArguments("VS2015CompilerBug.VS2015CompilerBug.Test3(int, int, int, int)", "VS2015CompilerBug.VS2015CompilerBug.Test3(int, int, int)").WithLocation(10, 39)
);
}
[Fact, WorkItem(2533, "https://github.com/dotnet/roslyn/issues/2533")]
public void TieBreakOnNumberOfDeclaredParameters_04()
{
string source1 = @"
public class Test
{
static void M1(object o, object o1, string s, object o2 = null)
{
System.Console.WriteLine(""void M1(object o, object o1, string s, object o2 = null) "");
}
static void M1(string s, object o1, object o2)
{
System.Console.WriteLine(""void M1(string s, object o1, object o2)"");
}
public static void Main()
{
M1(""M"", null, null);
}
}
";
var compilation = CreateCompilation(source1, options: TestOptions.DebugExe);
CompileAndVerify(compilation, expectedOutput: @"void M1(string s, object o1, object o2)");
}
[Fact, WorkItem(2533, "https://github.com/dotnet/roslyn/issues/2533")]
public void TieBreakOnNumberOfDeclaredParameters_05()
{
string source1 = @"
public class Test
{
static void M1(object o, object o1, string s)
{
}
static void M1(string s, object o1, object o2)
{
}
public static void Main()
{
M1(""M"", null, null);
}
}
";
var compilation = CreateCompilation(source1, options: TestOptions.DebugExe);
compilation.VerifyDiagnostics(
// (14,9): error CS0121: The call is ambiguous between the following methods or properties: 'Test.M1(object, object, string)' and 'Test.M1(string, object, object)'
// M1("M", null, null);
Diagnostic(ErrorCode.ERR_AmbigCall, "M1").WithArguments("Test.M1(object, object, string)", "Test.M1(string, object, object)").WithLocation(14, 9)
);
}
[Fact, WorkItem(4424, "https://github.com/dotnet/roslyn/issues/4424")]
public void TieBreakOnNumberOfDeclaredParameters_06()
{
string source1 = @"
class Test
{
static void Fn(string x = """", string y = """", params object[] p)
{
System.Console.WriteLine(1);
}
static void Fn(string x, params object[] p)
{
System.Console.WriteLine(2);
}
static void Main()
{ Fn(""Hello"", p: ""World""); }
}
";
var compilation = CreateCompilation(source1, options: TestOptions.DebugExe);
CompileAndVerify(compilation, expectedOutput: @"2");
}
[Fact, WorkItem(1099752, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1099752"), WorkItem(2291, "https://github.com/dotnet/roslyn/issues/2291")]
public void BetterErrorMessage_01()
{
string source1 = @"
class C
{
static void F1(object x, object y) { }
static void F1(object x, object w, object z) { }
static void F2(object x, object w, object z) { }
static void F2(object x, object y) { }
static void Main()
{
F1(x: 1, y: 2, z: 3);
F2(x: 1, y: 2, z: 3);
M1(0, x: 1);
M2(0, x: 1);
M3(0, x: 1);
M4(0, x: 1);
M5(0, x: 1);
M6(0, x: 1);
M7(0, x: 1);
M9(0, x: 1);
M8(0, x: 1);
M10(0, x: 1);
M11(x: 1, y: 2, z: 3);
M12(1, 2, 3, 4);
M13(1, 2, 3, 4);
M14(1, 2, 3);
M15(1, z: 0);
M16(1, z: 0);
M17(1, x: 2, y: 3);
M18(1, x: 2, y: 3);
M19(1, x: 2, y: 3);
}
static void M1() { }
static void M2() { }
static void M2(int u, int w) { }
static void M3(int u, int w) { }
static void M3() { }
static void M4() { }
static void M4(int u, int w) { }
static void M4(int x) { }
static void M5() { }
static void M5(int x) { }
static void M5(int u, int w) { }
static void M6(int x) { }
static void M6() { }
static void M6(int u, int w) { }
static void M7() { }
static void M7(int u, int w) { }
static void M7(int x) { }
static void M7(int u, int x, int w) { }
static void M8() { }
static void M8(int u, int w) { }
static void M8(int u, int x, int w) { }
static void M8(int x) { }
static void M9() { }
static void M9(int u, int x, int w) { }
static void M9(int u, int w) { }
static void M9(int x) { }
static void M10(int u, int x, int w) { }
static void M10() { }
static void M10(int u, int w) { }
static void M10(int x) { }
static void M11(object x, int y) { }
static void M11(object x, short y) { }
static void M12(object x, object y) { }
static void M12(object x, object y, object z) { }
static void M13(object x, object y, object z) { }
static void M13(object x, object y) { }
static void M14(object x, int y) { }
static void M14(object x, short y) { }
static void M15(object x, int y, object z = null) { }
static void M15(object x, short y, object z = null) { }
static void M16(object x, int y, object z = null) { }
static void M16(object x, short y, object z = null) { }
static void M17(object x, int y, int z) { }
static void M17(object y, short x, int z) { }
static void M18(object y, int x, int z) { }
static void M18(object x, short y, int z) { }
static void M19(object x, int y, int z) { }
static void M19(object x, short y, int z) { }
}
";
var compilation = CreateCompilation(source1);
compilation.VerifyDiagnostics(
// (12,24): error CS1739: The best overload for 'F1' does not have a parameter named 'z'
// F1(x: 1, y: 2, z: 3);
Diagnostic(ErrorCode.ERR_BadNamedArgument, "z").WithArguments("F1", "z").WithLocation(12, 24),
// (13,24): error CS1739: The best overload for 'F2' does not have a parameter named 'z'
// F2(x: 1, y: 2, z: 3);
Diagnostic(ErrorCode.ERR_BadNamedArgument, "z").WithArguments("F2", "z").WithLocation(13, 24),
// (15,9): error CS1501: No overload for method 'M1' takes 2 arguments
// M1(0, x: 1);
Diagnostic(ErrorCode.ERR_BadArgCount, "M1").WithArguments("M1", "2").WithLocation(15, 9),
// (17,15): error CS1739: The best overload for 'M2' does not have a parameter named 'x'
// M2(0, x: 1);
Diagnostic(ErrorCode.ERR_BadNamedArgument, "x").WithArguments("M2", "x").WithLocation(17, 15),
// (18,15): error CS1739: The best overload for 'M3' does not have a parameter named 'x'
// M3(0, x: 1);
Diagnostic(ErrorCode.ERR_BadNamedArgument, "x").WithArguments("M3", "x").WithLocation(18, 15),
// (20,15): error CS1744: Named argument 'x' specifies a parameter for which a positional argument has already been given
// M4(0, x: 1);
Diagnostic(ErrorCode.ERR_NamedArgumentUsedInPositional, "x").WithArguments("x").WithLocation(20, 15),
// (21,15): error CS1744: Named argument 'x' specifies a parameter for which a positional argument has already been given
// M5(0, x: 1);
Diagnostic(ErrorCode.ERR_NamedArgumentUsedInPositional, "x").WithArguments("x").WithLocation(21, 15),
// (22,15): error CS1744: Named argument 'x' specifies a parameter for which a positional argument has already been given
// M6(0, x: 1);
Diagnostic(ErrorCode.ERR_NamedArgumentUsedInPositional, "x").WithArguments("x").WithLocation(22, 15),
// (24,9): error CS7036: There is no argument given that corresponds to the required parameter 'w' of 'C.M7(int, int, int)'
// M7(0, x: 1);
Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "M7").WithArguments("w", "C.M7(int, int, int)").WithLocation(24, 9),
// (25,9): error CS7036: There is no argument given that corresponds to the required parameter 'w' of 'C.M9(int, int, int)'
// M9(0, x: 1);
Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "M9").WithArguments("w", "C.M9(int, int, int)").WithLocation(25, 9),
// (26,9): error CS7036: There is no argument given that corresponds to the required parameter 'w' of 'C.M8(int, int, int)'
// M8(0, x: 1);
Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "M8").WithArguments("w", "C.M8(int, int, int)").WithLocation(26, 9),
// (27,9): error CS7036: There is no argument given that corresponds to the required parameter 'w' of 'C.M10(int, int, int)'
// M10(0, x: 1);
Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "M10").WithArguments("w", "C.M10(int, int, int)").WithLocation(27, 9),
// (29,25): error CS1739: The best overload for 'M11' does not have a parameter named 'z'
// M11(x: 1, y: 2, z: 3);
Diagnostic(ErrorCode.ERR_BadNamedArgument, "z").WithArguments("M11", "z").WithLocation(29, 25),
// (31,9): error CS1501: No overload for method 'M12' takes 4 arguments
// M12(1, 2, 3, 4);
Diagnostic(ErrorCode.ERR_BadArgCount, "M12").WithArguments("M12", "4").WithLocation(31, 9),
// (32,9): error CS1501: No overload for method 'M13' takes 4 arguments
// M13(1, 2, 3, 4);
Diagnostic(ErrorCode.ERR_BadArgCount, "M13").WithArguments("M13", "4").WithLocation(32, 9),
// (34,9): error CS1501: No overload for method 'M14' takes 3 arguments
// M14(1, 2, 3);
Diagnostic(ErrorCode.ERR_BadArgCount, "M14").WithArguments("M14", "3").WithLocation(34, 9),
// (36,9): error CS1501: No overload for method 'M15' takes 2 arguments
// M15(1, z: 0);
Diagnostic(ErrorCode.ERR_BadArgCount, "M15").WithArguments("M15", "2").WithLocation(36, 9),
// (37,9): error CS1501: No overload for method 'M16' takes 2 arguments
// M16(1, z: 0);
Diagnostic(ErrorCode.ERR_BadArgCount, "M16").WithArguments("M16", "2").WithLocation(37, 9),
// (39,22): error CS1744: Named argument 'y' specifies a parameter for which a positional argument has already been given
// M17(1, x: 2, y: 3);
Diagnostic(ErrorCode.ERR_NamedArgumentUsedInPositional, "y").WithArguments("y").WithLocation(39, 22),
// (40,22): error CS1744: Named argument 'y' specifies a parameter for which a positional argument has already been given
// M18(1, x: 2, y: 3);
Diagnostic(ErrorCode.ERR_NamedArgumentUsedInPositional, "y").WithArguments("y").WithLocation(40, 22),
// (41,16): error CS1744: Named argument 'x' specifies a parameter for which a positional argument has already been given
// M19(1, x: 2, y: 3);
Diagnostic(ErrorCode.ERR_NamedArgumentUsedInPositional, "x").WithArguments("x").WithLocation(41, 16)
);
}
[Fact, WorkItem(2631, "https://github.com/dotnet/roslyn/issues/2631")]
public void ArglistCompilerCrash()
{
var source =
@"class Program
{
static void M(object x) { }
static void M(object x, object y) { }
static void M(object x, object y, object z) { }
static void M(object x, object y, object z, __arglist) { }
static void M(object x, params object[] args) { }
static void Main(string[] args)
{
M(x: 1, y: 2, z: 3);
}
}";
var compilation = CreateCompilation(source);
compilation.VerifyDiagnostics();
}
[Fact, WorkItem(1171723, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1171723"), WorkItem(2985, "https://github.com/dotnet/roslyn/issues/2985")]
public void BetterErrorMessage_02()
{
string source1 = @"
using FluentAssertions;
using Extensions;
using System;
using System.Collections.Generic;
using System.Collections;
namespace FluentAssertions
{
public static class AssertionExtensions
{
public static object Should(this object actualValue) { throw null; }
public static object Should(this IEnumerable actualValue) { throw null; }
public static object Should<T>(this IEnumerable<T> actualValue) { throw null; }
public static object Should<TKey, TValue>(this IDictionary<TKey, TValue> actualValue) { throw null; }
}
}
namespace Extensions
{
public static class TestExtensions
{
public static object Should<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> actualValue) { throw null; }
}
}
namespace ClassLibraryOverloadResolution
{
public class Class1
{
void goo()
{
Dictionary<String, String> dict = null;
dict.Should();
}
}
}";
var compilation = CreateCompilationWithMscorlib45(source1);
compilation.VerifyDiagnostics(
// (34,18): error CS0121: The call is ambiguous between the following methods or properties: 'FluentAssertions.AssertionExtensions.Should<TKey, TValue>(System.Collections.Generic.IDictionary<TKey, TValue>)' and 'Extensions.TestExtensions.Should<TKey, TValue>(System.Collections.Generic.IReadOnlyDictionary<TKey, TValue>)'
// dict.Should();
Diagnostic(ErrorCode.ERR_AmbigCall, "Should").WithArguments("FluentAssertions.AssertionExtensions.Should<TKey, TValue>(System.Collections.Generic.IDictionary<TKey, TValue>)", "Extensions.TestExtensions.Should<TKey, TValue>(System.Collections.Generic.IReadOnlyDictionary<TKey, TValue>)").WithLocation(34, 18)
);
}
[Fact, WorkItem(4970, "https://github.com/dotnet/roslyn/issues/4970")]
public void GenericExtensionMethodWithConstraintsAsADelegate()
{
var source =
@"
using System;
public interface IDetail<T>
{
}
public interface IMain<T>
{
}
public class MyClass
{
static void Main()
{
Principal aPrincipal = new Principal();
Test(aPrincipal.RemoveDetail);
Test(aPrincipal.RemoveDetail<Principal,Permission>);
Action<Permission> a;
a = aPrincipal.RemoveDetail;
a(null);
a = aPrincipal.RemoveDetail<Principal,Permission>;
a(null);
}
static void Test(Action<Permission> a)
{
a(null);
}
}
public class Permission : IDetail<Principal>
{
}
public class Principal : IMain<Permission>
{
}
public static class Class
{
public static void RemoveDetail<TMain, TChild>(this TMain main, TChild child)
where TMain : class, IMain<TChild>
where TChild : class, IDetail<TMain>
{
System.Console.WriteLine(""RemoveDetail"");
}
}";
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe);
// ILVerify: Unrecognized arguments for delegate .ctor.
CompileAndVerify(compilation, verify: Verification.FailsILVerify, expectedOutput:
@"RemoveDetail
RemoveDetail
RemoveDetail
RemoveDetail");
}
[Fact, WorkItem(2544, "https://github.com/dotnet/roslyn/issues/2544")]
public void GetSymbolInfo_Inaccessible()
{
var source =
@"
class C
{
private void M(D d)
{
d.M(1);
}
}
class D
{
private void M(int i) { }
private void M(double d) { }
}
";
var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
compilation.VerifyDiagnostics(
// (6,11): error CS0122: 'D.M(int)' is inaccessible due to its protection level
// d.M(1);
Diagnostic(ErrorCode.ERR_BadAccess, "M").WithArguments("D.M(int)").WithLocation(6, 11)
);
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree);
var callSyntax = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().Single();
var symbolInfo = model.GetSymbolInfo(callSyntax);
Assert.Equal(CandidateReason.Inaccessible, symbolInfo.CandidateReason);
var candidates = symbolInfo.CandidateSymbols;
Assert.Equal(2, candidates.Length);
Assert.Equal("void D.M(System.Int32 i)", candidates[0].ToTestDisplayString());
Assert.Equal("void D.M(System.Double d)", candidates[1].ToTestDisplayString());
}
[Fact, WorkItem(12061, "https://github.com/dotnet/roslyn/issues/12061")]
public void RecursiveBetterBetterness01()
{
string source = @"
delegate Del1 Del1();
delegate Del2 Del2();
class Program
{
static void Method(Del1 del1) { }
static void Method(Del2 del2) { }
static void Main()
{
Method(() => null);
}
}
";
CreateCompilation(source).VerifyDiagnostics(
// (11,9): error CS0121: The call is ambiguous between the following methods or properties: 'Program.Method(Del1)' and 'Program.Method(Del2)'
// Method(() => null);
Diagnostic(ErrorCode.ERR_AmbigCall, "Method").WithArguments("Program.Method(Del1)", "Program.Method(Del2)").WithLocation(11, 9)
);
}
[Fact, WorkItem(12061, "https://github.com/dotnet/roslyn/issues/12061")]
public void RecursiveBetterBetterness02()
{
string source = @"
delegate Del2 Del1();
delegate Del1 Del2();
class Program
{
static void Method(Del1 del1) { }
static void Method(Del2 del2) { }
static void Main()
{
Method(() => null);
}
}
";
CreateCompilation(source).VerifyDiagnostics(
// (11,9): error CS0121: The call is ambiguous between the following methods or properties: 'Program.Method(Del1)' and 'Program.Method(Del2)'
// Method(() => null);
Diagnostic(ErrorCode.ERR_AmbigCall, "Method").WithArguments("Program.Method(Del1)", "Program.Method(Del2)").WithLocation(11, 9)
);
}
[Fact, WorkItem(12061, "https://github.com/dotnet/roslyn/issues/12061")]
public void RecursiveBetterBetterness03()
{
string source = @"
delegate Del2<Del1<T>> Del1<T>();
delegate Del1<Del2<T>> Del2<T>();
class Program
{
static void Method(Del1<string> del1) { }
static void Method(Del2<string> del2) { }
static void Main()
{
Method(() => null);
}
}
";
CreateCompilation(source).VerifyDiagnostics(
// (11,9): error CS0121: The call is ambiguous between the following methods or properties: 'Program.Method(Del1<string>)' and 'Program.Method(Del2<string>)'
// Method(() => null);
Diagnostic(ErrorCode.ERR_AmbigCall, "Method").WithArguments("Program.Method(Del1<string>)", "Program.Method(Del2<string>)").WithLocation(11, 9)
);
}
[Fact, WorkItem(12061, "https://github.com/dotnet/roslyn/issues/12061")]
public void RecursiveBetterBetterness04()
{
string source = @"
using System.Threading.Tasks;
delegate Task<Del2> Del1();
delegate Task<Del1> Del2();
class Program
{
static void Method(Del1 del1) { }
static void Method(Del2 del2) { }
static void Main()
{
Method(() => null);
}
}
";
CreateCompilationWithMscorlib40AndSystemCore(source).VerifyDiagnostics(
// (12,9): error CS0121: The call is ambiguous between the following methods or properties: 'Program.Method(Del1)' and 'Program.Method(Del2)'
// Method(() => null);
Diagnostic(ErrorCode.ERR_AmbigCall, "Method").WithArguments("Program.Method(Del1)", "Program.Method(Del2)").WithLocation(12, 9)
);
}
[Fact, WorkItem(13380, "https://github.com/dotnet/roslyn/issues/13380")]
public void ImplicitNullableOperatorInEquality()
{
string source =
@"public class Class1
{
public static void Main(string[] args)
{
var a = default(Registration<Something>);
var x = (a == Something.Bad); //this line fails in VS2015.3
System.Console.WriteLine(x);
}
}
public struct Registration<T> where T : struct
{
public static implicit operator T? (Registration<T> registration)
{
return null;
}
}
public enum Something
{
Good,
Bad
}";
// should be NO errors.
CompileAndVerify(source, expectedOutput: @"False");
}
[Fact, WorkItem(16478, "https://github.com/dotnet/roslyn/issues/16478")]
public void AmbiguousInference_01()
{
string source =
@"
using System;
using System.Collections.Generic;
public class Test
{
public static void Assert<T>(T a, T b)
{
Console.WriteLine(""Non collection"");
}
public static void Assert<T>(IEnumerable<T> a, IEnumerable<T> b)
{
Console.WriteLine(""Collection"");
}
public static void Main()
{
string[] a = new[] { ""A"" };
StringValues b = new StringValues();
Assert(a, b);
Assert(b, a);
}
private class StringValues : List<string>
{
public static implicit operator StringValues(string[] values)
{
return new StringValues();
}
public static implicit operator string[] (StringValues value)
{
return new string[0];
}
}
}";
CompileAndVerify(source, expectedOutput:
@"Collection
Collection");
}
[Fact, WorkItem(16478, "https://github.com/dotnet/roslyn/issues/16478")]
public void AmbiguousInference_02()
{
string source =
@"
using System;
using System.Collections.Generic;
public class Test
{
public static void Assert<T>(T a, T b)
{
Console.WriteLine(""Non collection"");
}
public static void Main()
{
string[] a = new[] { ""A"" };
StringValues b = new StringValues();
Assert(a, b);
Assert(b, a);
}
private class StringValues : List<string>
{
public static implicit operator StringValues(string[] values)
{
return new StringValues();
}
public static implicit operator string[] (StringValues value)
{
return new string[0];
}
}
}";
var comp = CreateCompilationWithMscorlib40AndSystemCore(source);
comp.VerifyDiagnostics(
// (17,9): error CS0411: The type arguments for method 'Test.Assert<T>(T, T)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
// Assert(a, b);
Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "Assert").WithArguments("Test.Assert<T>(T, T)").WithLocation(17, 9),
// (18,9): error CS0411: The type arguments for method 'Test.Assert<T>(T, T)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
// Assert(b, a);
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 = CreateCompilationWithMscorlib40AndSystemCore(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 = CreateCompilationWithMscorlib40AndSystemCore(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));
}
[Fact]
public void CircularImplicitConversions()
{
string source =
@"
class A
{
public static implicit operator B(A a) => null;
}
class B
{
public static implicit operator C(B b) => null;
}
class C
{
public static implicit operator A(C c) => null;
}
class D
{
public static implicit operator A(D d) => null;
public static implicit operator B(D d) => null;
public static implicit operator C(D d) => null;
}
class E
{
public static void F(A a) {}
public static void F(B b) {}
public static void F(C c) {}
}
public class Program
{
public static void Main() => E.F(new D());
}
";
var comp = CreateCompilationWithMscorlib40AndSystemCore(source);
comp.VerifyDiagnostics(
// (28,36): error CS0121: The call is ambiguous between the following methods or properties: 'E.F(A)' and 'E.F(B)'
// public static void Main() => E.F(new D());
Diagnostic(ErrorCode.ERR_AmbigCall, "F").WithArguments("E.F(A)", "E.F(B)").WithLocation(28, 36)
);
var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree);
var callSyntax = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().Single();
var symbolInfo = model.GetSymbolInfo(callSyntax);
Assert.Equal(CandidateReason.OverloadResolutionFailure, symbolInfo.CandidateReason);
var candidates = symbolInfo.CandidateSymbols;
Assert.Equal(3, candidates.Length);
Assert.Equal("void E.F(A a)", candidates[0].ToTestDisplayString());
Assert.Equal("void E.F(B b)", candidates[1].ToTestDisplayString());
Assert.Equal("void E.F(C c)", candidates[2].ToTestDisplayString());
}
[Fact]
public void PassingArgumentsToInParameters_RefKind_None()
{
var code = @"
public static class Program
{
public static void Method(in int p)
{
System.Console.WriteLine(p);
}
public static void Main()
{
int x = 5;
Method(x);
}
}";
CompileAndVerify(code, expectedOutput: "5");
}
[Fact]
public void PassingArgumentsToInParameters_RefKind_Ref()
{
var code = @"
public static class Program
{
public static void Method(in int p)
{
System.Console.WriteLine(p);
}
public static void Main()
{
int x = 5;
Method(ref x);
}
}";
CreateCompilation(code).VerifyDiagnostics(
// (11,20): error CS1615: Argument 1 may not be passed with the 'ref' keyword
// Method(ref x);
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "x").WithArguments("1", "ref").WithLocation(11, 20));
}
[Fact]
public void PassingArgumentsToInParameters_RefKind_Out()
{
var code = @"
public static class Program
{
public static void Method(in int p)
{
System.Console.WriteLine(p);
}
public static void Main()
{
int x;
Method(out x);
}
}";
CreateCompilation(code).VerifyDiagnostics(
// (11,20): error CS1615: Argument 1 may not be passed with the 'out' keyword
// Method(out x);
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "x").WithArguments("1", "out").WithLocation(11, 20));
}
[Fact]
public void PassingArgumentsToInParameters_RefKind_In()
{
var code = @"
public static class Program
{
public static void Method(in int p)
{
System.Console.WriteLine(p);
}
public static void Main()
{
int x = 5;
Method(in x);
}
}";
CompileAndVerify(code, expectedOutput: "5");
}
[WorkItem(20799, "https://github.com/dotnet/roslyn/issues/20799")]
[Fact]
public void PassingArgumentsToInParameters_RefKind_None_WrongType()
{
var code = @"
public static class Program
{
public static void Method(in int p)
{
System.Console.WriteLine(p);
}
public static void Main()
{
System.Exception x = null;
Method(x);
}
}";
CreateCompilation(code).VerifyDiagnostics(
// (11,16): error CS1503: Argument 1: cannot convert from 'System.Exception' to 'in int'
// Method(x);
Diagnostic(ErrorCode.ERR_BadArgType, "x").WithArguments("1", "System.Exception", "in int").WithLocation(11, 16)
);
}
[WorkItem(20799, "https://github.com/dotnet/roslyn/issues/20799")]
[Fact]
public void PassingArgumentsToRefParameters_RefKind_None_WrongType()
{
var code = @"
public static class Program
{
public static void Method(ref int p)
{
System.Console.WriteLine(p);
}
public static void Main()
{
System.Exception x = null;
Method(x);
}
}";
CreateCompilation(code).VerifyDiagnostics(
// (11,16): error CS1620: Argument 1 must be passed with the 'ref' keyword
// Method(x);
Diagnostic(ErrorCode.ERR_BadArgRef, "x").WithArguments("1", "ref").WithLocation(11, 16)
);
}
[Fact]
public void PassingInArgumentsOverloadedOnIn()
{
var code = @"
public static class Program
{
public static void Method(in int x)
{
System.Console.WriteLine(""in: "" + x);
}
public static void Method(int x)
{
System.Console.WriteLine(""val: "" + x);
}
public static void Main()
{
int x = 5;
Method(in x);
Method(x);
Method(5);
}
}";
CompileAndVerify(code, expectedOutput: @"
in: 5
val: 5
val: 5
");
}
[Fact]
public void PassingInArgumentsOverloadedOnIn_Inverse()
{
var code = @"
public static class Program
{
public static void Method(int x)
{
System.Console.WriteLine(""val: "" + x);
}
public static void Method(in int x)
{
System.Console.WriteLine(""in: "" + x);
}
public static void Main()
{
int x = 5;
Method(in x);
Method(x);
Method(5);
}
}";
CompileAndVerify(code, expectedOutput: @"
in: 5
val: 5
val: 5
");
}
[Fact]
public void PassingInArgumentsOverloadedOnIn_BinaryOperators()
{
CompileAndVerify(@"
using System;
class Test
{
public int Value { get; set; }
public static string operator +(Test a, Test b) => ""val"";
public static string operator +(in Test a, in Test b) => ""in"";
}
class Program
{
static void Main()
{
var a = new Test { Value = 1 };
var b = new Test { Value = 2 };
Console.WriteLine(a + b);
}
}",
expectedOutput: "val");
}
[Fact]
public void PassingInArgumentsOverloadedOnIn_BinaryOperators_Inverse()
{
CompileAndVerify(@"
using System;
class Test
{
public int Value { get; set; }
public static string operator +(in Test a, in Test b) => ""in"";
public static string operator +(Test a, Test b) => ""val"";
}
class Program
{
static void Main()
{
var a = new Test { Value = 1 };
var b = new Test { Value = 2 };
Console.WriteLine(a + b);
}
}",
expectedOutput: "val");
}
[Fact]
public void PassingInArgumentsOverloadedOnIn_UnaryOperators()
{
CompileAndVerify(@"
using System;
class Test
{
public int Value { get; set; }
public static string operator !(Test a) => ""val"";
public static string operator !(in Test a) => ""in"";
}
class Program
{
static void Main()
{
var a = new Test { Value = 1 };
Console.WriteLine(!a);
}
}",
expectedOutput: "val");
}
[Fact]
public void PassingInArgumentsOverloadedOnIn_UnaryOperators_Inverse()
{
CompileAndVerify(@"
using System;
class Test
{
public int Value { get; set; }
public static string operator !(in Test a) => ""in"";
public static string operator !(Test a) => ""val"";
}
class Program
{
static void Main()
{
var a = new Test { Value = 1 };
Console.WriteLine(!a);
}
}",
expectedOutput: "val");
}
[Fact]
public void PassingInArgumentsOverloadedOnIn_FirstArgument()
{
var code = @"
public static class Program
{
public static void Method(in int x, int ignore)
{
System.Console.WriteLine(""in: "" + x);
}
public static void Method(int x, int ignore)
{
System.Console.WriteLine(""val: "" + x);
}
public static void Main()
{
int x = 5;
Method(in x, 0);
Method(x, 0);
Method(5, 0);
}
}";
CompileAndVerify(code, expectedOutput: @"
in: 5
val: 5
val: 5
");
}
[Fact]
public void PassingInArgumentsOverloadedOnIn_FirstArgument_Inverse()
{
var code = @"
public static class Program
{
public static void Method(int x, int ignore)
{
System.Console.WriteLine(""val: "" + x);
}
public static void Method(in int x, int ignore)
{
System.Console.WriteLine(""in: "" + x);
}
public static void Main()
{
int x = 5;
Method(in x, 0);
Method(x, 0);
Method(5, 0);
}
}";
CompileAndVerify(code, expectedOutput: @"
in: 5
val: 5
val: 5
");
}
[Fact]
public void PassingInArgumentsOverloadedOnIn_FirstArgument_BinaryOperators()
{
CompileAndVerify(@"
using System;
class Test
{
public int Value { get; set; }
public static string operator +(Test a, Test b) => ""val"";
public static string operator +(in Test a, Test b) => ""in"";
}
class Program
{
static void Main()
{
var a = new Test { Value = 1 };
var b = new Test { Value = 2 };
Console.WriteLine(a + b);
}
}",
expectedOutput: "val");
}
[Fact]
public void PassingInArgumentsOverloadedOnIn_FirstArgument_BinaryOperators_Inverse()
{
CompileAndVerify(@"
using System;
class Test
{
public int Value { get; set; }
public static string operator +(in Test a, Test b) => ""in"";
public static string operator +(Test a, Test b) => ""val"";
}
class Program
{
static void Main()
{
var a = new Test { Value = 1 };
var b = new Test { Value = 2 };
Console.WriteLine(a + b);
}
}",
expectedOutput: "val");
}
[Fact]
public void PassingInArgumentsOverloadedOnIn_SecondArgument()
{
var code = @"
public static class Program
{
public static void Method(int ignore, in int x)
{
System.Console.WriteLine(""in: "" + x);
}
public static void Method(int ignore, int x)
{
System.Console.WriteLine(""val: "" + x);
}
public static void Main()
{
int x = 5;
Method(0, in x);
Method(0, x);
Method(0, 5);
}
}";
CompileAndVerify(code, expectedOutput: @"
in: 5
val: 5
val: 5
");
}
[Fact]
public void PassingInArgumentsOverloadedOnIn_SecondArgument_Inverse()
{
var code = @"
public static class Program
{
public static void Method(int ignore, int x)
{
System.Console.WriteLine(""val: "" + x);
}
public static void Method(int ignore, in int x)
{
System.Console.WriteLine(""in: "" + x);
}
public static void Main()
{
int x = 5;
Method(0, in x);
Method(0, x);
Method(0, 5);
}
}";
CompileAndVerify(code, expectedOutput: @"
in: 5
val: 5
val: 5
");
}
[Fact]
public void PassingInArgumentsOverloadedOnIn_SecondArgument_BinaryOperators()
{
CompileAndVerify(@"
using System;
class Test
{
public int Value { get; set; }
public static string operator +(Test a, Test b) => ""val"";
public static string operator +(Test a, in Test b) => ""in"";
}
class Program
{
static void Main()
{
var a = new Test { Value = 1 };
var b = new Test { Value = 2 };
Console.WriteLine(a + b);
}
}",
expectedOutput: "val");
}
[Fact]
public void PassingInArgumentsOverloadedOnIn_SecondArgument_BinaryOperators_Inverse()
{
CompileAndVerify(@"
using System;
class Test
{
public int Value { get; set; }
public static string operator +(Test a, in Test b) => ""in"";
public static string operator +(Test a, Test b) => ""val"";
}
class Program
{
static void Main()
{
var a = new Test { Value = 1 };
var b = new Test { Value = 2 };
Console.WriteLine(a + b);
}
}",
expectedOutput: "val");
}
[Fact]
public void PassingInArgumentsOverloadedOnIn_ConflictingParameters()
{
var code = @"
public static class Program
{
public static void Method(in int x, int y)
{
System.Console.WriteLine($""in {x} | val {y}"");
}
public static void Method(int x, in int y)
{
System.Console.WriteLine($""val {x} | in {y}"");
}
public static void Main()
{
int x = 1, y = 2;
Method(x, in y);
Method(in x, y);
}
}";
CompileAndVerify(code, expectedOutput: @"
val 1 | in 2
in 1 | val 2
");
}
[Fact]
public void PassingInArgumentsOverloadedOnIn_ConflictingParameters_Inverse()
{
var code = @"
public static class Program
{
public static void Method(int x, in int y)
{
System.Console.WriteLine($""val {x} | in {y}"");
}
public static void Method(in int x, int y)
{
System.Console.WriteLine($""in {x} | val {y}"");
}
public static void Main()
{
int x = 1, y = 2;
Method(x, in y);
Method(in x, y);
}
}";
CompileAndVerify(code, expectedOutput: @"
val 1 | in 2
in 1 | val 2
");
}
[Fact]
public void PassingInArgumentsOverloadedOnIn_ConflictingParameters_Error()
{
var code = @"
public static class Program
{
public static void Method(in int x, int y)
{
System.Console.WriteLine($""in {x} val {y}"");
}
public static void Method(int x, in int y)
{
System.Console.WriteLine($""val {x} in {y}"");
}
public static void Main()
{
int x = 1, y = 2;
Method(x, y);
Method(3, 4);
}
}";
CreateCompilation(code).VerifyDiagnostics(
// (18,9): error CS0121: The call is ambiguous between the following methods or properties: 'Program.Method(in int, int)' and 'Program.Method(int, in int)'
// Method(x, y);
Diagnostic(ErrorCode.ERR_AmbigCall, "Method").WithArguments("Program.Method(in int, int)", "Program.Method(int, in int)").WithLocation(18, 9),
// (19,9): error CS0121: The call is ambiguous between the following methods or properties: 'Program.Method(in int, int)' and 'Program.Method(int, in int)'
// Method(3, 4);
Diagnostic(ErrorCode.ERR_AmbigCall, "Method").WithArguments("Program.Method(in int, int)", "Program.Method(int, in int)").WithLocation(19, 9));
}
[Fact]
public void PassingInArgumentsOverloadedOnIn_ConflictingParameters_Error_Inverse()
{
var code = @"
public static class Program
{
public static void Method(int x, in int y)
{
System.Console.WriteLine($""val {x} in {y}"");
}
public static void Method(in int x, int y)
{
System.Console.WriteLine($""in {x} val {y}"");
}
public static void Main()
{
int x = 1, y = 2;
Method(x, y);
Method(3, 4);
}
}";
CreateCompilation(code).VerifyDiagnostics(
// (18,9): error CS0121: The call is ambiguous between the following methods or properties: 'Program.Method(int, in int)' and 'Program.Method(in int, int)'
// Method(x, y);
Diagnostic(ErrorCode.ERR_AmbigCall, "Method").WithArguments("Program.Method(int, in int)", "Program.Method(in int, int)").WithLocation(18, 9),
// (19,9): error CS0121: The call is ambiguous between the following methods or properties: 'Program.Method(int, in int)' and 'Program.Method(in int, int)'
// Method(3, 4);
Diagnostic(ErrorCode.ERR_AmbigCall, "Method").WithArguments("Program.Method(int, in int)", "Program.Method(in int, int)").WithLocation(19, 9));
}
[Fact]
public void PassingInArgumentsOverloadedOnIn_ThreeConflictingParameters_Error()
{
var code = @"
public static class Program
{
public static void Method(in int x, int y, in int z)
{
System.Console.WriteLine($""in {x} val {y} in {z}"");
}
public static void Method(int x, in int y, int z)
{
System.Console.WriteLine($""val {x} in {y} val {z}"");
}
public static void Main()
{
int x = 1, y = 2, z = 3;
Method(x, y, z);
Method(4, 5, 6);
}
}";
CreateCompilation(code).VerifyDiagnostics(
// (18,9): error CS0121: The call is ambiguous between the following methods or properties: 'Program.Method(in int, int, in int)' and 'Program.Method(int, in int, int)'
// Method(x, y, z);
Diagnostic(ErrorCode.ERR_AmbigCall, "Method").WithArguments("Program.Method(in int, int, in int)", "Program.Method(int, in int, int)").WithLocation(18, 9),
// (19,9): error CS0121: The call is ambiguous between the following methods or properties: 'Program.Method(in int, int, in int)' and 'Program.Method(int, in int, int)'
// Method(4, 5, 6);
Diagnostic(ErrorCode.ERR_AmbigCall, "Method").WithArguments("Program.Method(in int, int, in int)", "Program.Method(int, in int, int)").WithLocation(19, 9));
}
[Fact]
public void PassingInArgumentsOverloadedOnIn_ThreeConflictingParameters_Error_Inverse()
{
var code = @"
public static class Program
{
public static void Method(int x, in int y, int z)
{
System.Console.WriteLine($""val {x} in {y} val {z}"");
}
public static void Method(in int x, int y, in int z)
{
System.Console.WriteLine($""in {x} val {y} in {z}"");
}
public static void Main()
{
int x = 1, y = 2, z = 3;
Method(x, y, z);
Method(4, 5, 6);
}
}";
CreateCompilation(code).VerifyDiagnostics(
// (18,9): error CS0121: The call is ambiguous between the following methods or properties: 'Program.Method(int, in int, int)' and 'Program.Method(in int, int, in int)'
// Method(x, y, z);
Diagnostic(ErrorCode.ERR_AmbigCall, "Method").WithArguments("Program.Method(int, in int, int)", "Program.Method(in int, int, in int)").WithLocation(18, 9),
// (19,9): error CS0121: The call is ambiguous between the following methods or properties: 'Program.Method(int, in int, int)' and 'Program.Method(in int, int, in int)'
// Method(4, 5, 6);
Diagnostic(ErrorCode.ERR_AmbigCall, "Method").WithArguments("Program.Method(int, in int, int)", "Program.Method(in int, int, in int)").WithLocation(19, 9));
}
[Fact]
public void PassingInArgumentsOverloadedOnIn_ConflictingParameters_Error_BinaryOperators()
{
CreateCompilation(@"
using System;
class Test
{
public int Value { get; set; }
public static string operator +(in Test a, Test b) => ""left"";
public static string operator +(Test a, in Test b) => ""right"";
}
class Program
{
static void Main()
{
var a = new Test { Value = 1 };
var b = new Test { Value = 2 };
Console.WriteLine(a + b);
}
}").VerifyDiagnostics(
// (15,27): error CS0034: Operator '+' is ambiguous on operands of type 'Test' and 'Test'
// Console.WriteLine(a + b);
Diagnostic(ErrorCode.ERR_AmbigBinaryOps, "a + b").WithArguments("+", "Test", "Test").WithLocation(15, 27));
}
[Fact]
public void PassingInArgumentsOverloadedOnIn_ConflictingParameters_Error_BinaryOperators_Inverse()
{
CreateCompilation(@"
using System;
class Test
{
public int Value { get; set; }
public static string operator +(Test a, in Test b) => ""right"";
public static string operator +(in Test a, Test b) => ""left"";
}
class Program
{
static void Main()
{
var a = new Test { Value = 1 };
var b = new Test { Value = 2 };
Console.WriteLine(a + b);
}
}").VerifyDiagnostics(
// (15,27): error CS0034: Operator '+' is ambiguous on operands of type 'Test' and 'Test'
// Console.WriteLine(a + b);
Diagnostic(ErrorCode.ERR_AmbigBinaryOps, "a + b").WithArguments("+", "Test", "Test").WithLocation(15, 27));
}
[Fact]
public void PassingInArgumentsOverloadedOnIn_UnusedConflictingParameters()
{
var code = @"
public static class Program
{
public static void Method(in int x, int y = 0)
{
System.Console.WriteLine($""in: {x}"");
}
public static void Method(int x, in int y = 0)
{
System.Console.WriteLine($""val: {x}"");
}
public static void Main()
{
int x = 1;
Method(x);
Method(in x);
Method(2);
}
}";
CompileAndVerify(code, expectedOutput: @"
val: 1
in: 1
val: 2");
}
[Fact]
public void PassingInArgumentsOverloadedOnIn_UnorderedNamedParameters()
{
var code = @"
public static class Program
{
public static void Method(int a, int b)
{
System.Console.WriteLine($""val a: {a} | val b: {b}"");
}
public static void Method(in int b, int a)
{
System.Console.WriteLine($""in b: {b} | val a: {a}"");
}
public static void Main()
{
int a = 1, b = 2;
Method(b: b, a: a);
Method(a: a, b: in b);
}
}";
CompileAndVerify(code, expectedOutput: @"
val a: 1 | val b: 2
in b: 2 | val a: 1");
}
[Fact]
public void PassingInArgumentsOverloadedOnIn_OptionalParameters()
{
var code = @"
public static class Program
{
public static void Method(in int x, int op1 = 0, int op2 = 0)
{
System.Console.WriteLine(""in: "" + x);
}
public static void Method(int x, int op1 = 0, int op2 = 0, int op3 = 0)
{
System.Console.WriteLine(""val: "" + x);
}
public static void Main()
{
int x = 1;
Method(x);
Method(in x);
Method(1);
x = 2;
Method(x, 0);
Method(in x, 0);
Method(2, 0);
x = 3;
Method(x, op3: 0);
}
}";
CompileAndVerify(code, expectedOutput: @"
val: 1
in: 1
val: 1
val: 2
in: 2
val: 2
val: 3
");
}
[Fact]
public void PassingInArgumentsOverloadedOnIn_OptionalParameters_Error()
{
var code = @"
public static class Program
{
public static void Method(in int x, int op1 = 0, int op2 = 0)
{
System.Console.WriteLine(""in: "" + x);
}
public static void Method(int x, int op1 = 0, int op2 = 0, int op3 = 0)
{
System.Console.WriteLine(""val: "" + x);
}
public static void Main()
{
int x = 1;
Method(in x, op3: 0); // ERROR
}
}";
CreateCompilation(code).VerifyDiagnostics(
// (17,19): error CS1615: Argument 1 may not be passed with the 'in' keyword
// Method(in x, op3: 0); // ERROR
Diagnostic(ErrorCode.ERR_BadArgExtraRef, "x").WithArguments("1", "in").WithLocation(17, 19));
}
[Fact]
public void PassingInArgumentsOverloadedOnIn_Named()
{
var code = @"
public static class Program
{
public static void Method(in int inP)
{
System.Console.WriteLine(""in: "" + inP);
}
public static void Method(int valP)
{
System.Console.WriteLine(""val: "" + valP);
}
public static void Main()
{
int x = 5;
Method(in x);
Method(valP: 3);
Method(inP: 2);
}
}";
CompileAndVerify(code, expectedOutput: @"
in: 5
val: 3
in: 2
");
}
[Fact]
public void PassingInArgumentsOverloadedOnInErr()
{
var code = @"
public static class Program
{
public static void Method(in int inP)
{
System.Console.WriteLine(""in: "" + inP);
}
public static void Method(int valP)
{
System.Console.WriteLine(""val: "" + valP);
}
public static void Main()
{
byte x = 5;
Method(in x);
Method('Q');
Method(3);
Method(valP: out 2);
Method(valP: in 2);
}
}";
CreateCompilation(code).VerifyDiagnostics(
// (17,19): error CS1503: Argument 1: cannot convert from 'in byte' to 'in int'
// Method(in x);
Diagnostic(ErrorCode.ERR_BadArgType, "x").WithArguments("1", "in byte", "in int").WithLocation(17, 19),
// (20,26): error CS1510: A ref or out value must be an assignable variable
// Method(valP: out 2);
Diagnostic(ErrorCode.ERR_RefLvalueExpected, "2").WithLocation(20, 26),
// (21,25): error CS8156: An expression cannot be used in this context because it may not be passed or returned by reference
// Method(valP: in 2);
Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "2").WithLocation(21, 25)
);
}
[Fact]
public void PassingInArgumentsOverloadedOnInIndexer()
{
var code = @"
public class Program
{
public int this[in int inP]
{
get
{
System.Console.WriteLine(""in: "" + inP);
return 1;
}
}
public int this[int valP]
{
get
{
System.Console.WriteLine(""val: "" + valP);
return 1;
}
}
public static void Main()
{
var p = new Program();
int x = 5;
_ = p[0];
_ = p[x];
_ = p[in x];
_ = p[valP: 3];
_ = p[inP: 2];
}
}
";
CompileAndVerify(code, expectedOutput: @"
val: 0
val: 5
in: 5
val: 3
in: 2
");
}
[Fact]
public void PassingInArgumentsOverloadedOnInIndexerErr()
{
var code = @"
public class Program
{
public int this[in int inP]
{
get
{
System.Console.WriteLine(""in: "" + inP);
return 1;
}
}
public int this[int valP]
{
get
{
System.Console.WriteLine(""val: "" + valP);
return 1;
}
}
public static void Main()
{
var p = new Program();
byte x = 5;
_ = p[in x];
_ = p['Q'];
_ = p[3];
_ = p[valP: out 2];
_ = p[inP: in 2];
}
}";
CreateCompilation(code).VerifyDiagnostics(
// (27,18): error CS1503: Argument 1: cannot convert from 'in byte' to 'in int'
// _ = p[in x];
Diagnostic(ErrorCode.ERR_BadArgType, "x").WithArguments("1", "in byte", "in int").WithLocation(27, 18),
// (30,25): error CS1510: A ref or out value must be an assignable variable
// _ = p[valP: out 2];
Diagnostic(ErrorCode.ERR_RefLvalueExpected, "2").WithLocation(30, 25),
// (31,23): error CS8156: An expression cannot be used in this context because it may not be passed or returned by reference
// _ = p[inP: in 2];
Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "2").WithLocation(31, 23));
}
[Fact]
public void PassingInArgumentsOverloadedOnInOptionalParameters()
{
var code = @"
public static class Program
{
public static void Method(in int inP = 0)
{
System.Console.WriteLine(""in: "" + inP);
}
public static void Method(int valP = 0)
{
System.Console.WriteLine(""val: "" + valP);
}
public static void Main()
{
Method(valP: 1);
Method(inP: 2);
int x = 3;
Method(in x);
}
}";
CompileAndVerify(code, expectedOutput: @"
val: 1
in: 2
in: 3
");
}
[Fact]
public void PassingInArgumentsOverloadedOnInParams()
{
var code = @"
using System;
class Program
{
void M(in int x) { Console.WriteLine(""in: "" + x); }
void M(params int[] p) { Console.WriteLine(""params: "" + p.Length); }
static void Main()
{
var p = new Program();
p.M();
p.M(1);
p.M(1, 2);
int x = 3;
p.M(in x);
}
}";
CompileAndVerify(code, expectedOutput:
@"params: 0
in: 1
params: 2
in: 3");
}
[Fact]
public void PassingInArgumentsOverloadedOnInParams_Array()
{
var code = @"
using System;
class Program
{
void M(in int[] p) { Console.WriteLine(""in: "" + p.Length); }
void M(params int[] p) { Console.WriteLine(""params: "" + p.Length); }
static void Main()
{
var p = new Program();
p.M();
p.M(1);
p.M(1, 2);
var x = new int[] { };
p.M(x);
p.M(in x);
p.M(new int[] { });
x = new int[] { 1 };
p.M(x);
p.M(in x);
p.M(new int[] { 1 });
}
}";
CompileAndVerify(code, expectedOutput:
@"params: 0
params: 1
params: 2
params: 0
in: 0
params: 0
params: 1
in: 1
params: 1");
}
[Fact]
public void PassingArgumentsToOverloadsOfByValAndInParameters_ExtensionMethods()
{
CompileAndVerify(@"
using System;
static class Extensions
{
public static void M(this Program instance, in int x) { Console.WriteLine(""in: "" + x); }
}
class Program
{
void M(int x) { Console.WriteLine(""val: "" + x); }
static void Main()
{
var instance = new Program();
int x = 1;
instance.M(x);
x = 2;
instance.M(in x);
instance.M(3);
}
}",
expectedOutput:
@"val: 1
in: 2
val: 3");
}
[Fact]
public void PassingArgumentsToOverloadsOfByValAndInParameters_Indexers()
{
CompileAndVerify(@"
using System;
class Program
{
public string this[int x] => ""val: "" + x;
public string this[in int x] => ""in: "" + x;
static void Main()
{
var instance = new Program();
int x = 1;
Console.WriteLine(instance[x]);
x = 2;
Console.WriteLine(instance[in x]);
Console.WriteLine(instance[3]);
}
}",
expectedOutput:
@"val: 1
in: 2
val: 3");
}
[Fact]
public void PassingArgumentsToOverloadsOfByValAndInParameters_TypeConversions_In()
{
CompileAndVerify(@"
using System;
class Program
{
static void M(in byte x) { Console.WriteLine(""in: "" + x); }
static void M(int x) { Console.WriteLine(""val: "" + x); }
static void Main()
{
M(0);
int intX = 1;
byte byteX = 1;
M(intX);
M(byteX);
M((int)2);
M((byte)2);
}
}",
expectedOutput: @"
val: 0
val: 1
in: 1
val: 2
in: 2");
}
[Fact]
public void PassingArgumentsToOverloadsOfByValAndInParameters_TypeConversions_Val()
{
CompileAndVerify(@"
using System;
class Program
{
static void M(byte x) { Console.WriteLine(""val: "" + x); }
static void M(in int x) { Console.WriteLine(""in: "" + x); }
static void Main()
{
M(0);
int intX = 1;
byte byteX = 1;
M(intX);
M(byteX);
M((int)2);
M((byte)2);
}
}",
expectedOutput: @"
in: 0
in: 1
val: 1
in: 2
val: 2");
}
[Fact]
public void PassingArgumentsToOverloadsOfByValAndInParameters_TypeConversions_BinaryOperators()
{
CompileAndVerify(@"
using System;
class Test
{
public int Value { get; set; }
public static string operator +(int a, Test b) => ""val"";
public static string operator +(in byte a, Test b) => ""in"";
}
class Program
{
static void Main()
{
int intX = 1;
byte byteX = 1;
var b = new Test { Value = 2 };
Console.WriteLine(intX + b);
Console.WriteLine(byteX + b);
Console.WriteLine(1 + b);
Console.WriteLine(((byte)1) + b);
}
}",
expectedOutput: @"
val
in
val
in");
}
[Fact]
public void PassingArgumentsToOverloadsOfByValAndInParameters_TypeConversions_NonConvertible()
{
CompileAndVerify(@"
using System;
using System.Text;
class Program
{
static void M(string x) { Console.WriteLine(""val""); }
static void M(in StringBuilder x) { Console.WriteLine(""in""); }
static void Main()
{
M(null);
}
}",
expectedOutput: "val");
}
[Fact]
public void PassingArgumentsToOverloadsOfByValAndInParameters_TypeConversions_NonConvertible_Error()
{
CreateCompilation(@"
using System;
using System.Text;
class Program
{
static void M(string x) { Console.WriteLine(""val""); }
static void M(StringBuilder x) { Console.WriteLine(""in""); }
static void Main()
{
M(null);
}
}").VerifyDiagnostics(
// (11,9): error CS0121: The call is ambiguous between the following methods or properties: 'Program.M(string)' and 'Program.M(StringBuilder)'
// M(null);
Diagnostic(ErrorCode.ERR_AmbigCall, "M").WithArguments("Program.M(string)", "Program.M(System.Text.StringBuilder)").WithLocation(11, 9));
}
[Fact]
public void GenericInferenceOnIn()
{
var code = @"
using System;
class Program
{
public static void M1<T>(in T arg1, in T arg2)
{
System.Console.WriteLine(typeof(T).ToString());
}
static void Main()
{
int x = 1;
byte y = 2;
M1(null, (string)null);
M1(default, 1);
M1(new Object(), new Exception());
M1(new Object(), 1);
M1(in x, in x); // valid, same type
M1(y, in x); // valid, byval x sets lower bound, byte converts to int
}
}
";
CompileAndVerify(code, expectedOutput: @"
System.String
System.Int32
System.Object
System.Object
System.Int32
System.Int32
");
}
[Fact]
public void GenericInferenceOnInErr()
{
var code = @"
class Program
{
public static void M1<T>(in T arg1, in T arg2)
{
System.Console.WriteLine(typeof(T).ToString());
}
static void Main()
{
int x = 1;
byte y = 2;
var rl = default(RefLike);
M1(null, null);
M1(null, 1);
M1(new object(), default(RefLike));
M1(rl, rl);
M1(in rl, in rl);
M1(in y, in x);
M1(in y, x);
}
ref struct RefLike{}
}
";
CreateCompilation(code).VerifyDiagnostics(
// (15,9): error CS0411: The type arguments for method 'Program.M1<T>(in T, in T)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
// M1(null, null);
Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "M1").WithArguments("Program.M1<T>(in T, in T)").WithLocation(15, 9),
// (16,12): error CS1503: Argument 1: cannot convert from '<null>' to 'in int'
// M1(null, 1);
Diagnostic(ErrorCode.ERR_BadArgType, "null").WithArguments("1", "<null>", "in int").WithLocation(16, 12),
// (17,9): error CS0411: The type arguments for method 'Program.M1<T>(in T, in T)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
// M1(new object(), default(RefLike));
Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "M1").WithArguments("Program.M1<T>(in T, in T)").WithLocation(17, 9),
// (19,9): error CS0306: The type 'Program.RefLike' may not be used as a type argument
// M1(rl, rl);
Diagnostic(ErrorCode.ERR_BadTypeArgument, "M1").WithArguments("Program.RefLike").WithLocation(19, 9),
// (20,9): error CS0306: The type 'Program.RefLike' may not be used as a type argument
// M1(in rl, in rl);
Diagnostic(ErrorCode.ERR_BadTypeArgument, "M1").WithArguments("Program.RefLike").WithLocation(20, 9),
// (22,9): error CS0411: The type arguments for method 'Program.M1<T>(in T, in T)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
// M1(in y, in x);
Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "M1").WithArguments("Program.M1<T>(in T, in T)").WithLocation(22, 9),
// (23,9): error CS0411: The type arguments for method 'Program.M1<T>(in T, in T)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
// M1(in y, x);
Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "M1").WithArguments("Program.M1<T>(in T, in T)").WithLocation(23, 9)
);
}
[Fact]
public void GenericInferenceOnInTuples()
{
var code = @"
using System;
class Program
{
public static void Method<T>(in (T arg1, T arg2) p)
{
System.Console.WriteLine(typeof(T).ToString());
}
static void Main()
{
int x = 1;
byte y = 2;
Method((null, (string)null));
Method((default, x));
Method((new Object(), new Exception()));
Method((new Object(), x));
Method((x, x)); // valid, same type
Method((y, x)); // valid, byval x sets lower bound, byte converts to int
}
}
";
CompileAndVerifyWithMscorlib40(code, references: new[] { SystemRuntimeFacadeRef, ValueTupleRef }, expectedOutput: @"
System.String
System.Int32
System.Object
System.Object
System.Int32
System.Int32
");
}
[Fact]
public void GenericInferenceOnInErrTuples()
{
var code = @"
class Program
{
public static void Method<T>(in (T arg1, T arg2) p)
{
System.Console.WriteLine(typeof(T).ToString());
}
static void Main()
{
int x = 1;
byte y = 2;
var rl = default(RefLike);
Method((null, null));
Method((null, 1));
Method((new object(), default(RefLike)));
Method((rl, rl));
Method(in (rl, rl));
Method(in (y, x));
}
ref struct RefLike{}
}
";
CreateCompilationWithMscorlib40(code, references: new[] { SystemRuntimeFacadeRef, ValueTupleRef }).VerifyDiagnostics(
// (15,9): error CS0411: The type arguments for method 'Program.Method<T>(in (T arg1, T arg2))' cannot be inferred from the usage. Try specifying the type arguments explicitly.
// Method((null, null));
Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "Method").WithArguments("Program.Method<T>(in (T arg1, T arg2))").WithLocation(15, 9),
// (16,16): error CS1503: Argument 1: cannot convert from '(<null>, int)' to 'in (int arg1, int arg2)'
// Method((null, 1));
Diagnostic(ErrorCode.ERR_BadArgType, "(null, 1)").WithArguments("1", "(<null>, int)", "in (int arg1, int arg2)").WithLocation(16, 16),
// (17,31): error CS0306: The type 'Program.RefLike' may not be used as a type argument
// Method((new object(), default(RefLike)));
Diagnostic(ErrorCode.ERR_BadTypeArgument, "default(RefLike)").WithArguments("Program.RefLike").WithLocation(17, 31),
// (17,9): error CS0411: The type arguments for method 'Program.Method<T>(in (T arg1, T arg2))' cannot be inferred from the usage. Try specifying the type arguments explicitly.
// Method((new object(), default(RefLike)));
Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "Method").WithArguments("Program.Method<T>(in (T arg1, T arg2))").WithLocation(17, 9),
// (19,17): error CS0306: The type 'Program.RefLike' may not be used as a type argument
// Method((rl, rl));
Diagnostic(ErrorCode.ERR_BadTypeArgument, "rl").WithArguments("Program.RefLike").WithLocation(19, 17),
// (19,21): error CS0306: The type 'Program.RefLike' may not be used as a type argument
// Method((rl, rl));
Diagnostic(ErrorCode.ERR_BadTypeArgument, "rl").WithArguments("Program.RefLike").WithLocation(19, 21),
// (19,9): error CS0306: The type 'Program.RefLike' may not be used as a type argument
// Method((rl, rl));
Diagnostic(ErrorCode.ERR_BadTypeArgument, "Method").WithArguments("Program.RefLike").WithLocation(19, 9),
// (20,20): error CS0306: The type 'Program.RefLike' may not be used as a type argument
// Method(in (rl, rl));
Diagnostic(ErrorCode.ERR_BadTypeArgument, "rl").WithArguments("Program.RefLike").WithLocation(20, 20),
// (20,24): error CS0306: The type 'Program.RefLike' may not be used as a type argument
// Method(in (rl, rl));
Diagnostic(ErrorCode.ERR_BadTypeArgument, "rl").WithArguments("Program.RefLike").WithLocation(20, 24),
// (20,19): error CS8156: An expression cannot be used in this context because it may not be passed or returned by reference
// Method(in (rl, rl));
Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "(rl, rl)").WithLocation(20, 19),
// (22,19): error CS8156: An expression cannot be used in this context because it may not be passed or returned by reference
// Method(in (y, x));
Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "(y, x)").WithLocation(22, 19));
}
[Fact]
public void GenericInferenceErrorRecovery()
{
var code = @"
class Program
{
public static void Method<T>(in T p)
{
System.Console.WriteLine(typeof(T).ToString());
}
static void Main()
{
Method((null, 1));
}
}
";
var comp = CreateCompilation(code);
comp.VerifyDiagnostics(
// (11,9): error CS0411: The type arguments for method 'Program.Method<T>(in T)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
// Method((null, 1));
Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "Method").WithArguments("Program.Method<T>(in T)").WithLocation(11, 9));
}
[Fact]
public void GenericInferenceLambdaVariance()
{
var code = @"
class Program
{
public delegate void D1<T>(in T arg1, in T arg2);
public static void M1<T>(T arg1, T arg2)
{
System.Console.WriteLine(typeof(T).ToString());
}
static void Main()
{
M1((in int arg1, in int arg2) => throw null, (in int arg1, in int arg2) => throw null);
}
}
";
CreateCompilation(code).VerifyDiagnostics(
// (13,9): error CS0411: The type arguments for method 'Program.M1<T>(T, T)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
// M1((in int arg1, in int arg2) => throw null, (in int arg1, in int arg2) => throw null);
Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "M1").WithArguments("Program.M1<T>(T, T)").WithLocation(13, 9)
);
}
[Fact]
public void DelegateConversions()
{
var librarySrc = @"
public class C
{
public void RR_input(in int x) => throw null;
public ref readonly int RR_output() => throw null;
public ref readonly int P => throw null;
public ref readonly int this[in int i] => throw null;
public delegate ref readonly int Delegate(in int i);
}
public static class Extensions
{
public static void RR_extension(in this int x) => throw null;
public static void R_extension(ref this int x) => throw null;
}
";
var libComp = CreateCompilationWithMscorlib40(librarySrc, references: new[] { TestMetadata.Net40.SystemCore }).VerifyDiagnostics();
var code = @"
class D
{
void M(C c, in int y)
{
c.RR_input(y);
VerifyRR(c.RR_output());
VerifyRR(c.P);
VerifyRR(c[y]);
C.Delegate x = VerifyDelegate;
y.RR_extension();
1.RR_extension();
y.R_extension(); // error 1
1.R_extension(); // error 2
}
void VerifyRR(in int y) => throw null;
ref readonly int VerifyDelegate(in int y) => throw null;
}
";
CreateCompilation(code, references: new[] { libComp.EmitToImageReference() }).VerifyDiagnostics(
// (13,10): error CS8329: Cannot use variable 'y' as a ref or out value because it is a readonly variable
// y.R_extension(); // error 1
Diagnostic(ErrorCode.ERR_RefReadonlyNotField, "y").WithArguments("variable", "y").WithLocation(13, 10),
// (14,10): error CS1510: A ref or out value must be an assignable variable
// 1.R_extension(); // error 2
Diagnostic(ErrorCode.ERR_RefLvalueExpected, "1").WithLocation(14, 10)
);
CreateCompilation(code, references: new[] { libComp.ToMetadataReference() }).VerifyDiagnostics(
// (13,10): error CS8329: Cannot use variable 'y' as a ref or out value because it is a readonly variable
// y.R_extension(); // error 1
Diagnostic(ErrorCode.ERR_RefReadonlyNotField, "y").WithArguments("variable", "y").WithLocation(13, 10),
// (14,10): error CS1510: A ref or out value must be an assignable variable
// 1.R_extension(); // error 2
Diagnostic(ErrorCode.ERR_RefLvalueExpected, "1").WithLocation(14, 10)
);
}
[Fact]
public void MethodGroupConversionVal2In()
{
var code = @"
using System;
class Program
{
static void F(in DateTime x)
{
Console.WriteLine(x);
}
static void Main()
{
Action<DateTime> a = F;
a(DateTime.MaxValue);
}
}
";
CreateCompilation(code).VerifyDiagnostics(
// (13,30): error CS0123: No overload for 'F' matches delegate 'Action<DateTime>'
// Action<DateTime> a = F;
Diagnostic(ErrorCode.ERR_MethDelegateMismatch, "F").WithArguments("F", "System.Action<System.DateTime>").WithLocation(13, 30)
);
}
[Fact]
public void MethodGroupConversionVal2Overloaded()
{
var code = @"
using System;
class Program
{
static void F(in DateTime x)
{
Console.WriteLine('1');
}
static void F(DateTime x)
{
Console.WriteLine('2');
}
static void Main()
{
Action<DateTime> a = F;
a(DateTime.MaxValue);
}
}
";
CompileAndVerify(code, expectedOutput: @"2");
}
[Fact]
public void MethodGroupConversionIn2Overloaded()
{
var code = @"
using System;
class Program
{
delegate void D(in DateTime d);
static void F(in DateTime x)
{
Console.WriteLine('1');
}
static void F(DateTime x)
{
Console.WriteLine('2');
}
static void Main()
{
D a = F;
a(DateTime.MaxValue);
}
}
";
CompileAndVerify(code, expectedOutput: @"1", verify: Verification.Fails);
}
[Fact]
public void MethodGroupConversionRoReadonlyReturn()
{
var code = @"
using System;
class Program
{
delegate int D(in DateTime d);
static ref readonly int F(in DateTime x)
{
Console.WriteLine('1');
return ref (new int[1])[0];
}
static void Main()
{
D a = F;
a(DateTime.MaxValue);
}
}
";
CreateCompilation(code).VerifyDiagnostics
(
// (16,15): error CS8189: Ref mismatch between 'Program.F(in DateTime)' and delegate 'Program.D'
// D a = F;
Diagnostic(ErrorCode.ERR_DelegateRefMismatch, "F").WithArguments("Program.F(in System.DateTime)", "Program.D").WithLocation(16, 15)
);
}
[Fact]
public void MethodGroupConversionRoReadonlyReturnType()
{
var code = @"
using System;
class Program
{
delegate ref readonly object D(in DateTime d);
static ref readonly string F(in DateTime x)
{
Console.WriteLine('1');
return ref (new string[1])[0];
}
static void Main()
{
D a = F;
a(DateTime.MaxValue);
}
}
";
CreateCompilation(code).VerifyDiagnostics
(
// (16,15): error CS0407: 'string Program.F(in DateTime)' has the wrong return type
// D a = F;
Diagnostic(ErrorCode.ERR_BadRetType, "F").WithArguments("Program.F(in System.DateTime)", "string").WithLocation(16, 15)
);
}
[Fact, WorkItem(25813, "https://github.com/dotnet/roslyn/issues/25813")]
public void InaccessibleExtensionMethod()
{
var code = @"
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
static void Main(string[] args)
{
var a = new[] { 0, 1, 3 };
var b = new[] { 1, 2, 3, 4, 5 };
Console.WriteLine(b.Count(a.Contains));
}
}
public static class Extensions
{
// NOTE: private access modifier simulates internal class public method in referenced assembly.
private static bool Contains<T>(this System.Collections.Generic.IEnumerable<T> a, T value) =>
throw new NotImplementedException();
}";
// ILVerify: Unrecognized arguments for delegate .ctor.
CompileAndVerify(code, verify: Verification.FailsILVerify, expectedOutput: @"2");
}
[Fact]
public void GenericTypeOverriddenMethod()
{
var source0 =
@"public class Base<TKey, TValue>
where TKey : class
where TValue : class
{
public virtual TValue F(TKey key) => throw null;
}";
var source1 =
@"public class A { }
public class Derived<TValue> : Base<A, TValue>
where TValue : class
{
public override TValue F(A key) => throw null;
}";
var source2 =
@"class B { }
class Program
{
static void M(Derived<B> d, A a)
{
_ = d.F(a);
}
}";
var comp = CreateCompilation(new[] { source0, source1, source2 });
comp.VerifyEmitDiagnostics();
verify(comp, comp.SyntaxTrees[2]);
var ref0 = CreateCompilation(source0).EmitToImageReference();
var ref1 = CreateCompilation(source1, references: new[] { ref0 }).EmitToImageReference();
comp = CreateCompilation(source2, references: new[] { ref0, ref1 });
comp.VerifyEmitDiagnostics();
verify(comp, comp.SyntaxTrees[0]);
static void verify(CSharpCompilation comp, SyntaxTree tree)
{
var model = comp.GetSemanticModel(tree);
var expr = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().Single();
var symbol = model.GetSymbolInfo(expr).Symbol.GetSymbol<MethodSymbol>();
Assert.Equal("B Derived<B>.F(A key)", symbol.ToTestDisplayString());
symbol = symbol.GetLeastOverriddenMethod(accessingTypeOpt: null);
Assert.Equal("B Base<A, B>.F(A key)", symbol.ToTestDisplayString());
}
}
[Fact]
[WorkItem(46549, "https://github.com/dotnet/roslyn/issues/46549")]
public void GenericTypeOverriddenProperty()
{
var source0 =
@"public class Base<TKey, TValue>
where TKey : class
where TValue : class
{
public virtual TValue this[TKey key] => throw null;
}";
var source1 =
@"public class A { }
public class Derived<TValue> : Base<A, TValue>
where TValue : class
{
public override TValue this[A key] => throw null;
}";
var source2 =
@"class B { }
class Program
{
static void M(Derived<B> d, A a)
{
_ = d[a];
}
}";
var comp = CreateCompilation(new[] { source0, source1, source2 });
comp.VerifyEmitDiagnostics();
verify(comp, comp.SyntaxTrees[2]);
var ref0 = CreateCompilation(source0).EmitToImageReference();
var ref1 = CreateCompilation(source1, references: new[] { ref0 }).EmitToImageReference();
comp = CreateCompilation(source2, references: new[] { ref0, ref1 });
comp.VerifyEmitDiagnostics();
verify(comp, comp.SyntaxTrees[0]);
static void verify(CSharpCompilation comp, SyntaxTree tree)
{
var model = comp.GetSemanticModel(tree);
var expr = tree.GetRoot().DescendantNodes().OfType<ElementAccessExpressionSyntax>().Single();
var symbol = model.GetSymbolInfo(expr).Symbol.GetSymbol<PropertySymbol>();
Assert.Equal("B Derived<B>.this[A key] { get; }", symbol.ToTestDisplayString());
symbol = symbol.GetLeastOverriddenProperty(accessingTypeOpt: null);
Assert.Equal("B Base<A, B>.this[A key] { get; }", symbol.ToTestDisplayString());
}
}
[Fact]
[WorkItem(46549, "https://github.com/dotnet/roslyn/issues/46549")]
public void GenericTypeOverriddenEvent()
{
var source0 =
@"public delegate TValue D<TKey, TValue>(TKey key);
public abstract class Base<TKey, TValue>
where TKey : class
where TValue : class
{
public abstract event D<TKey, TValue> E;
}";
var source1 =
@"public class A { }
public class Derived<TValue> : Base<A, TValue>
where TValue : class
{
public override event D<A, TValue> E { add { } remove { } }
}";
var source2 =
@"class B { }
class Program
{
static void M(Derived<B> d, A a)
{
d.E += (A a) => default(B);
}
}";
var comp = CreateCompilation(new[] { source0, source1, source2 });
comp.VerifyEmitDiagnostics();
verify(comp, comp.SyntaxTrees[2]);
var ref0 = CreateCompilation(source0).EmitToImageReference();
var ref1 = CreateCompilation(source1, references: new[] { ref0 }).EmitToImageReference();
comp = CreateCompilation(source2, references: new[] { ref0, ref1 });
comp.VerifyEmitDiagnostics();
verify(comp, comp.SyntaxTrees[0]);
static void verify(CSharpCompilation comp, SyntaxTree tree)
{
var model = comp.GetSemanticModel(tree);
var expr = tree.GetRoot().DescendantNodes().OfType<MemberAccessExpressionSyntax>().Single();
var symbol = model.GetSymbolInfo(expr).Symbol.GetSymbol<EventSymbol>();
Assert.Equal("event D<A, B> Derived<B>.E", symbol.ToTestDisplayString());
symbol = symbol.GetLeastOverriddenEvent(accessingTypeOpt: null);
Assert.Equal("event D<A, B> Base<A, B>.E", symbol.ToTestDisplayString());
}
}
[Fact]
[WorkItem(52701, "https://github.com/dotnet/roslyn/issues/52701")]
public void Issue52701_01()
{
var source =
@"
class A
{
internal void F<T>(T t) where T : class {}
}
class B : A
{
internal new void F<T>(T t) where T : struct { }
void M()
{
System.Action<object> d = F<object>;
}
}
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (11,35): error CS0453: The type 'object' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'B.F<T>(T)'
// System.Action<object> d = F<object>;
Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "F<object>").WithArguments("B.F<T>(T)", "T", "object").WithLocation(11, 35)
);
}
[Fact]
[WorkItem(52701, "https://github.com/dotnet/roslyn/issues/52701")]
public void Issue52701_02()
{
var source =
@"
class A
{
internal void F<T>(T t) where T : class {}
}
class B : A
{
internal new void F<T>(T t) where T : struct { }
void M()
{
F<object>(default);
}
}
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (11,9): error CS0453: The type 'object' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'B.F<T>(T)'
// F<object>(default);
Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "F<object>").WithArguments("B.F<T>(T)", "T", "object").WithLocation(11, 9)
);
}
}
}
|