|
// 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.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics
{
public class RefExtensionMethodsTests : CSharpTestBase
{
[Fact]
public void ExtensionMethods_RValues_Ref_NotAllowed()
{
var code = @"
public static class Extensions
{
public static void PrintValue(ref this int p)
{
System.Console.WriteLine(p);
}
}
public static class Program
{
public static void Main()
{
5.PrintValue();
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics(
// (13,9): error CS1510: A ref or out value must be an assignable variable
// 5.PrintValue();
Diagnostic(ErrorCode.ERR_RefLvalueExpected, "5").WithLocation(13, 9));
}
[Fact]
[WorkItem(25862, "https://github.com/dotnet/roslyn/issues/25862")]
public void ExtensionMethods_StructCollectionInitializer()
{
var code = @"
public struct MyStruct : System.Collections.IEnumerable
{
public int i;
public System.Collections.IEnumerator GetEnumerator() => throw new System.NotImplementedException();
}
public static class MyStructExtension
{
public static void Add(ref this MyStruct s, int i)
{
s.i += i;
}
}
public static class Program
{
public static void Main()
{
var s = new MyStruct { 1 };
System.Console.Write(s.i);
}
}";
CompileAndVerify(code, expectedOutput: "1");
}
[Theory, CombinatorialData]
[WorkItem(25862, "https://github.com/dotnet/roslyn/issues/25862")]
public void ExtensionMethods_StructCollectionInitializerInParam([CombinatorialValues("in", "ref readonly")] string modifier)
{
var code = @"
public struct MyStruct : System.Collections.IEnumerable
{
public int i;
public System.Collections.IEnumerator GetEnumerator() => throw new System.NotImplementedException();
}
public static class MyStructExtension
{
public static void Add(ref this MyStruct s, " + modifier + @" MyStruct other)
{
s.i += other.i;
}
}
public static class Program
{
public static void Main()
{
var other = new MyStruct { i = 2 };
var s = new MyStruct { other };
System.Console.Write(s.i);
}
}";
var verifier = CompileAndVerify(code, expectedOutput: "2");
verifier.VerifyIL("Program.Main", @"{
// Code size 47 (0x2f)
.maxstack 2
.locals init (MyStruct V_0, //other
MyStruct V_1)
IL_0000: ldloca.s V_1
IL_0002: initobj ""MyStruct""
IL_0008: ldloca.s V_1
IL_000a: ldc.i4.2
IL_000b: stfld ""int MyStruct.i""
IL_0010: ldloc.1
IL_0011: stloc.0
IL_0012: ldloca.s V_1
IL_0014: initobj ""MyStruct""
IL_001a: ldloca.s V_1
IL_001c: ldloca.s V_0
IL_001e: call ""void MyStructExtension.Add(ref MyStruct, " + modifier + @" MyStruct)""
IL_0023: ldloc.1
IL_0024: ldfld ""int MyStruct.i""
IL_0029: call ""void System.Console.Write(int)""
IL_002e: ret
}");
}
[Theory, CombinatorialData]
[WorkItem(25862, "https://github.com/dotnet/roslyn/issues/25862")]
public void ExtensionMethods_StructCollectionInitializerInParamImplicitTempArg([CombinatorialValues("in", "ref readonly")] string modifier)
{
var code = @"
public struct MyStruct : System.Collections.IEnumerable
{
public int i;
public System.Collections.IEnumerator GetEnumerator() => throw new System.NotImplementedException();
}
public static class MyStructExtension
{
public static void Add(ref this MyStruct s, " + modifier + @" MyStruct other)
{
s.i += other.i;
}
}
public static class Program
{
public static void Main()
{
var s = new MyStruct { new MyStruct { i = 2 } };
System.Console.Write(s.i);
}
}";
var verifier = CompileAndVerify(code, expectedOutput: "2");
verifier.VerifyIL("Program.Main", @"{
// Code size 45 (0x2d)
.maxstack 3
.locals init (MyStruct V_0,
MyStruct V_1)
IL_0000: ldloca.s V_0
IL_0002: initobj ""MyStruct""
IL_0008: ldloca.s V_0
IL_000a: ldloca.s V_1
IL_000c: initobj ""MyStruct""
IL_0012: ldloca.s V_1
IL_0014: ldc.i4.2
IL_0015: stfld ""int MyStruct.i""
IL_001a: ldloca.s V_1
IL_001c: call ""void MyStructExtension.Add(ref MyStruct, " + modifier + @" MyStruct)""
IL_0021: ldloc.0
IL_0022: ldfld ""int MyStruct.i""
IL_0027: call ""void System.Console.Write(int)""
IL_002c: ret
}");
}
[Fact]
[WorkItem(25862, "https://github.com/dotnet/roslyn/issues/25862")]
public void ExtensionMethods_StructCollectionInitializerRefThisRefElement()
{
var code = @"
public struct MyStruct : System.Collections.IEnumerable
{
public int i;
public System.Collections.IEnumerator GetEnumerator() => throw new System.NotImplementedException();
}
public static class MyStructExtension
{
public static void Add(ref this MyStruct s, ref int i)
{
s.i += i;
}
}
public static class Program
{
public static void Main()
{
var s = new MyStruct { 1 };
System.Console.Write(s.i);
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics(
// (20,32): error CS1954: The best overloaded method match 'MyStructExtension.Add(ref MyStruct, ref int)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters.
// var s = new MyStruct { 1 };
Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "1").WithArguments("MyStructExtension.Add(ref MyStruct, ref int)").WithLocation(20, 32));
}
[Fact]
[WorkItem(25862, "https://github.com/dotnet/roslyn/issues/25862")]
public void ExtensionMethods_StructCollectionInitializerInThisRefElement()
{
var code = @"
public struct MyStruct : System.Collections.IEnumerable
{
public int i;
public System.Collections.IEnumerator GetEnumerator() => throw new System.NotImplementedException();
}
public static class MyStructExtension
{
public static void Add(in this MyStruct s, ref int i)
{
}
}
public static class Program
{
public static void Main()
{
var s = new MyStruct { 1 };
System.Console.Write(s.i);
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics(
// (19,32): error CS1954: The best overloaded method match 'MyStructExtension.Add(in MyStruct, ref int)' for the collection initializer element cannot be used. Collection initializer 'Add' methods cannot have ref or out parameters.
// var s = new MyStruct { 1 };
Diagnostic(ErrorCode.ERR_InitializerAddHasParamModifiers, "1").WithArguments("MyStructExtension.Add(in MyStruct, ref int)").WithLocation(19, 32));
}
[Fact]
public void ExtensionMethods_LValues_Ref_Allowed()
{
var code = @"
public static class Extensions
{
public static void PrintValue(ref this int p)
{
System.Console.Write(++p);
}
}
public static class Program
{
public static void Main()
{
int x = 5;
x.PrintValue();
Extensions.PrintValue(ref x);
}
}";
CompileAndVerify(code, expectedOutput: "67");
}
[Fact]
public void ExtensionMethods_RValues_In_Allowed()
{
var code = @"
public static class Extensions
{
public static void PrintValue(in this int p)
{
System.Console.Write(p);
}
}
public static class Program
{
public static void Main()
{
5.PrintValue();
Extensions.PrintValue(5);
}
}";
CompileAndVerify(code, expectedOutput: "55");
}
[Fact]
public void ExtensionMethods_LValues_In_Allowed()
{
var code = @"
public static class Extensions
{
public static void PrintValue(in this int p)
{
System.Console.Write(p);
}
}
public static class Program
{
public static void Main()
{
int x = 5;
x.PrintValue();
Extensions.PrintValue(x);
}
}";
CompileAndVerify(code, expectedOutput: "55");
}
[Fact]
public void ExtensionMethods_NullConditionalOperator_Ref_NotAllowed()
{
var code = @"
public struct TestType
{
public int GetValue() => 0;
}
public static class Extensions
{
public static void Call(ref this TestType obj)
{
var value1 = obj?.GetValue(); // This should be an error
var value2 = obj.GetValue(); // This should be OK
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics(
// (10,25): error CS0023: Operator '?' cannot be applied to operand of type 'TestType'
// var value1 = obj?.GetValue(); // This should be an error
Diagnostic(ErrorCode.ERR_BadUnaryOp, "?").WithArguments("?", "TestType").WithLocation(10, 25));
}
[Fact]
public void ExtensionMethods_NullConditionalOperator_In_NotAllowed()
{
var code = @"
public struct TestType
{
public int GetValue() => 0;
}
public static class Extensions
{
public static void Call(in this TestType obj)
{
var value1 = obj?.GetValue(); // This should be an error
var value2 = obj.GetValue(); // This should be OK
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics(
// (10,25): error CS0023: Operator '?' cannot be applied to operand of type 'TestType'
// var value1 = obj?.GetValue(); // This should be an error
Diagnostic(ErrorCode.ERR_BadUnaryOp, "?").WithArguments("?", "TestType").WithLocation(10, 25));
}
[Fact]
public void RefExtensionMethodsReceiverTypes_ValueTypes_Allowed()
{
var reference = CreateCompilationWithMscorlib40AndSystemCore(@"
public static class Extensions
{
public static void PrintValue(ref this int p)
{
System.Console.Write(p);
}
}
public static class Program
{
public static void Main()
{
int x = 5;
x.PrintValue();
Extensions.PrintValue(ref x);
}
}", options: TestOptions.ReleaseExe);
CompileAndVerify(reference, expectedOutput: "55");
var code = @"
public static class Program2
{
public static void Main()
{
int x = 5;
x.PrintValue();
Extensions.PrintValue(ref x);
}
}";
CompileAndVerify(code, references: new[] { reference.ToMetadataReference() }, expectedOutput: "55");
CompileAndVerify(code, references: new[] { reference.EmitToImageReference() }, expectedOutput: "55");
}
[Fact]
public void RefExtensionMethodsReceiverTypes_ReferenceTypes_NotAllowed()
{
var code = @"
public static class Extensions
{
public static void PrintValue(ref this string p)
{
System.Console.WriteLine(p);
}
}
public static class Program
{
public static void Main()
{
string x = ""test"";
x.PrintValue();
Extensions.PrintValue(ref x);
}
}";
var reference = CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics(
// (4,24): error CS8337: The first parameter of the reference extension method 'PrintValue' must be a value type or a generic type constrained to struct.
// public static void PrintValue(ref this string p)
Diagnostic(ErrorCode.ERR_RefExtensionMustBeValueTypeOrConstrainedToOne, "PrintValue").WithArguments("PrintValue").WithLocation(4, 24),
// (14,11): error CS1061: 'string' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("string", "PrintValue").WithLocation(14, 11));
CreateCompilation(@"
public static class Program2
{
public static void Main()
{
string x = ""test"";
x.PrintValue();
Extensions.PrintValue(ref x);
}
}", references: new[] { reference.ToMetadataReference() }).VerifyDiagnostics(
// (7,11): error CS1061: 'string' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("string", "PrintValue").WithLocation(7, 11));
}
[Fact]
public void RefExtensionMethodsReceiverTypes_InterfaceTypes_NotAllowed()
{
var code = @"
public static class Extensions
{
public static void PrintValue(ref this System.IComparable p)
{
System.Console.WriteLine(p);
}
}
public static class Program
{
public static void Main()
{
System.IComparable x = 5;
x.PrintValue();
Extensions.PrintValue(ref x);
}
}";
var reference = CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics(
// (4,24): error CS8337: The first parameter of the reference extension method 'PrintValue' must be a value type or a generic type constrained to struct.
// public static void PrintValue(ref this System.IComparable p)
Diagnostic(ErrorCode.ERR_RefExtensionMustBeValueTypeOrConstrainedToOne, "PrintValue").WithArguments("PrintValue").WithLocation(4, 24),
// (14,11): error CS1061: 'IComparable' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'IComparable' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("System.IComparable", "PrintValue").WithLocation(14, 11));
CreateCompilation(@"
public static class Program2
{
public static void Main()
{
System.IComparable x = 5;
x.PrintValue();
Extensions.PrintValue(ref x);
}
}", references: new[] { reference.ToMetadataReference() }).VerifyDiagnostics(
// (7,11): error CS1061: 'IComparable' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'IComparable' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("System.IComparable", "PrintValue").WithLocation(7, 11));
}
[Fact]
public void RefExtensionMethodsReceiverTypes_UnconstrainedGenericTypes_NotAllowed()
{
var code = @"
public static class Extensions
{
public static void PrintValue<T>(ref this T p)
{
System.Console.WriteLine(p);
}
}
public static class Program
{
public static void Main()
{
string x = ""test"";
x.PrintValue();
Extensions.PrintValue(ref x);
}
}";
var reference = CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics(
// (4,24): error CS8337: The first parameter of the reference extension method 'PrintValue' must be a value type or a generic type constrained to struct.
// public static void PrintValue<T>(ref this T p)
Diagnostic(ErrorCode.ERR_RefExtensionMustBeValueTypeOrConstrainedToOne, "PrintValue").WithArguments("PrintValue").WithLocation(4, 24),
// (14,11): error CS1061: 'string' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("string", "PrintValue").WithLocation(14, 11));
CreateCompilation(@"
public static class Program2
{
public static void Main()
{
string x = ""test"";
x.PrintValue();
Extensions.PrintValue(ref x);
}
}", references: new[] { reference.ToMetadataReference() }).VerifyDiagnostics(
// (7,11): error CS1061: 'string' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("string", "PrintValue").WithLocation(7, 11));
}
[Fact]
public void RefExtensionMethodsReceiverTypes_StructConstrainedGenericTypes_Allowed()
{
var reference = CreateCompilationWithMscorlib40AndSystemCore(@"
public static class Extensions
{
public static void PrintValue<T>(ref this T p) where T : struct
{
System.Console.Write(p);
}
}
public static class Program
{
public static void Main()
{
int x = 5;
x.PrintValue();
Extensions.PrintValue(ref x);
}
}", options: TestOptions.ReleaseExe);
CompileAndVerify(reference, expectedOutput: "55");
var code = @"
public static class Program2
{
public static void Main()
{
int x = 5;
x.PrintValue();
Extensions.PrintValue(ref x);
}
}";
CompileAndVerify(code, references: new[] { reference.ToMetadataReference() }, expectedOutput: "55");
CompileAndVerify(code, references: new[] { reference.EmitToImageReference() }, expectedOutput: "55");
}
[Fact]
public void RefExtensionMethodsReceiverTypes_ClassConstrainedGenericTypes_NotAllowed()
{
var code = @"
public static class Extensions
{
public static void PrintValue<T>(ref this T p) where T : class
{
System.Console.WriteLine(p);
}
}
public static class Program
{
public static void Main()
{
string x = ""test"";
x.PrintValue();
Extensions.PrintValue(ref x);
}
}";
var reference = CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics(
// (4,24): error CS8337: The first parameter of the reference extension method 'PrintValue' must be a value type or a generic type constrained to struct.
// public static void PrintValue<T>(ref this T p) where T : class
Diagnostic(ErrorCode.ERR_RefExtensionMustBeValueTypeOrConstrainedToOne, "PrintValue").WithArguments("PrintValue").WithLocation(4, 24),
// (14,11): error CS1061: 'string' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("string", "PrintValue").WithLocation(14, 11));
CreateCompilation(@"
public static class Program2
{
public static void Main()
{
string x = ""test"";
x.PrintValue();
Extensions.PrintValue(ref x);
}
}", references: new[] { reference.ToMetadataReference() }).VerifyDiagnostics(
// (7,11): error CS1061: 'string' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("string", "PrintValue").WithLocation(7, 11));
}
[Fact]
public void RefExtensionMethodsReceiverTypes_InterfaceConstrainedGenericTypes_NotAllowed()
{
var code = @"
public static class Extensions
{
public static void PrintValue<T>(ref this T p) where T : System.IComparable
{
System.Console.WriteLine(p);
}
}
public static class Program
{
public static void Main()
{
string x = ""test"";
x.PrintValue();
Extensions.PrintValue(ref x);
}
}";
var reference = CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics(
// (4,24): error CS8337: The first parameter of the reference extension method 'PrintValue' must be a value type or a generic type constrained to struct.
// public static void PrintValue<T>(ref this T p) where T : System.IComparable
Diagnostic(ErrorCode.ERR_RefExtensionMustBeValueTypeOrConstrainedToOne, "PrintValue").WithArguments("PrintValue").WithLocation(4, 24),
// (14,11): error CS1061: 'string' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("string", "PrintValue").WithLocation(14, 11));
CreateCompilation(@"
public static class Program2
{
public static void Main()
{
string x = ""test"";
x.PrintValue();
Extensions.PrintValue(ref x);
}
}", references: new[] { reference.ToMetadataReference() }).VerifyDiagnostics(
// (7,11): error CS1061: 'string' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("string", "PrintValue").WithLocation(7, 11));
}
[Fact]
public void RefExtensionMethodsReceiverTypes_ValueTypes_Allowed_IL()
{
var reference = CompileIL(@"
.class public abstract auto ansi sealed beforefieldinit Extensions extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig static void PrintValue(int32& p) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldind.i4
IL_0003: call void [mscorlib]System.Console::Write(int32)
IL_0008: nop
IL_0009: ret
}
}");
var code = @"
public static class Program
{
public static void Main()
{
int x = 5;
x.PrintValue();
Extensions.PrintValue(ref x);
}
}";
CompileAndVerify(code, references: new[] { reference }, expectedOutput: "55");
}
[Fact]
public void RefExtensionMethodsReceiverTypes_ReferenceTypes_NotAllowed_IL()
{
var reference = CompileIL(@"
.class public abstract auto ansi sealed beforefieldinit Extensions extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig static void PrintValue(string& p) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0003: call void [mscorlib]System.Console::Write(string)
IL_0008: nop
IL_0009: ret
}
}");
var code = @"
public static class Program
{
public static void Main()
{
string x = ""test"";
x.PrintValue();
Extensions.PrintValue(ref x);
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code, references: new[] { reference }).VerifyDiagnostics(
// (7,11): error CS1061: 'string' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("string", "PrintValue").WithLocation(7, 11));
}
[Fact]
public void RefExtensionMethodsReceiverTypes_InterfaceTypes_NotAllowed_IL()
{
var reference = CompileIL(@"
.class public abstract auto ansi sealed beforefieldinit Extensions extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig static void PrintValue(class [mscorlib]System.IComparable& p) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0003: call void [mscorlib]System.Console::Write(string)
IL_0008: nop
IL_0009: ret
}
}");
var code = @"
public static class Program
{
public static void Main()
{
System.IComparable x = 5;
x.PrintValue();
Extensions.PrintValue(ref x);
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code, references: new[] { reference }).VerifyDiagnostics(
// (7,11): error CS1061: 'IComparable' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'IComparable' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("System.IComparable", "PrintValue").WithLocation(7, 11));
}
[Fact]
public void RefExtensionMethodsReceiverTypes_UnconstrainedGenericTypes_NotAllowed_IL()
{
var reference = CompileIL(@"
.class public abstract auto ansi sealed beforefieldinit Extensions extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig static void PrintValue<T>(!!T& p) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0003: call void [mscorlib]System.Console::Write(object)
IL_0008: nop
IL_0009: ret
}
}");
var code = @"
public static class Program
{
public static void Main()
{
string x = ""test"";
x.PrintValue();
Extensions.PrintValue(ref x);
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code, references: new[] { reference }).VerifyDiagnostics(
// (7,11): error CS1061: 'string' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("string", "PrintValue").WithLocation(7, 11));
}
[Fact]
public void RefExtensionMethodsReceiverTypes_StructConstrainedGenericTypes_Allowed_IL()
{
var reference = CompileIL(@"
.class public abstract auto ansi sealed beforefieldinit Extensions extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig static void PrintValue<valuetype .ctor ([mscorlib]System.ValueType) T>(!!T& p) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldobj !!T
IL_0007: box !!T
IL_000c: call void [mscorlib]System.Console::Write(object)
IL_0011: nop
IL_0012: ret
}
}");
var code = @"
public static class Program
{
public static void Main()
{
int x = 5;
x.PrintValue();
Extensions.PrintValue(ref x);
}
}";
CompileAndVerify(code, references: new[] { reference }, expectedOutput: "55");
}
[Fact]
public void RefExtensionMethodsReceiverTypes_ClassConstrainedGenericTypes_NotAllowed_IL()
{
var reference = CompileIL(@"
.class public abstract auto ansi sealed beforefieldinit Extensions extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig static void PrintValue<class T>(!!T& p) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0003: call void [mscorlib]System.Console::Write(object)
IL_0008: nop
IL_0009: ret
}
}");
var code = @"
public static class Program
{
public static void Main()
{
string x = ""test"";
x.PrintValue();
Extensions.PrintValue(ref x);
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code, references: new[] { reference }).VerifyDiagnostics(
// (7,11): error CS1061: 'string' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("string", "PrintValue").WithLocation(7, 11));
}
[Fact]
public void RefExtensionMethodsReceiverTypes_InterfaceConstrainedGenericTypes_NotAllowed_IL()
{
var reference = CompileIL(@"
.class public abstract auto ansi sealed beforefieldinit Extensions extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig static void PrintValue<([mscorlib]System.IComparable) T>(!!T& p) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0003: call void [mscorlib]System.Console::Write(object)
IL_0008: nop
IL_0009: ret
}
}");
var code = @"
public static class Program
{
public static void Main()
{
string x = ""test"";
x.PrintValue();
Extensions.PrintValue(ref x);
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code, references: new[] { reference }).VerifyDiagnostics(
// (7,11): error CS1061: 'string' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("string", "PrintValue").WithLocation(7, 11));
}
[Theory, CombinatorialData]
public void InExtensionMethodsReceiverTypes_ValueTypes_Allowed([CombinatorialValues("in", "ref readonly")] string modifier)
{
var reference = CreateCompilationWithMscorlib40AndSystemCore(@"
public static class Extensions
{
public static void PrintValue(" + modifier + @" this int p)
{
System.Console.Write(p);
}
}
public static class Program
{
public static void Main()
{
int x = 5;
x.PrintValue();
Extensions.PrintValue(x);
}
}", options: TestOptions.ReleaseExe);
CompileAndVerify(reference, expectedOutput: "55");
var code = @"
public static class Program2
{
public static void Main()
{
int x = 5;
x.PrintValue();
Extensions.PrintValue(x);
}
}";
CompileAndVerify(code, references: new[] { reference.ToMetadataReference() }, expectedOutput: "55");
CompileAndVerify(code, references: new[] { reference.EmitToImageReference() }, expectedOutput: "55");
}
[Theory, CombinatorialData]
public void InExtensionMethodsReceiverTypes_ReferenceTypes_NotAllowed([CombinatorialValues("in", "ref readonly")] string modifier)
{
var code = @"
public static class Extensions
{
public static void PrintValue(" + modifier + @" this string p)
{
System.Console.WriteLine(p);
}
}
public static class Program
{
public static void Main()
{
string x = ""test"";
x.PrintValue();
Extensions.PrintValue(" + (modifier == "ref readonly" ? "in " : "") + @"x);
}
}";
var reference = CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics(
// (4,24): error CS8338: The first 'in' or 'ref readonly' parameter of the extension method 'PrintValue' must be a concrete (non-generic) value type.
// public static void PrintValue(in this string p)
Diagnostic(ErrorCode.ERR_InExtensionMustBeValueType, "PrintValue").WithArguments("PrintValue").WithLocation(4, 24),
// (14,11): error CS1061: 'string' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("string", "PrintValue").WithLocation(14, 11));
CreateCompilation(@"
public static class Program2
{
public static void Main()
{
string x = ""test"";
x.PrintValue();
Extensions.PrintValue(" + (modifier == "ref readonly" ? "in " : "") + @"x);
}
}", references: new[] { reference.ToMetadataReference() }).VerifyDiagnostics(
// (7,11): error CS1061: 'string' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("string", "PrintValue").WithLocation(7, 11));
}
[Theory, CombinatorialData]
public void InExtensionMethodsReceiverTypes_InterfaceTypes_NotAllowed([CombinatorialValues("in", "ref readonly")] string modifier)
{
var code = @"
public static class Extensions
{
public static void PrintValue(" + modifier + @" this System.IComparable p)
{
System.Console.WriteLine(p);
}
}
public static class Program
{
public static void Main()
{
System.IComparable x = 5;
x.PrintValue();
Extensions.PrintValue(" + (modifier == "ref readonly" ? "in " : "") + @"x);
}
}";
var reference = CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics(
// (4,24): error CS8338: The first 'in' or 'ref readonly' parameter of the extension method 'PrintValue' must be a concrete (non-generic) value type.
// public static void PrintValue(in this System.IComparable p)
Diagnostic(ErrorCode.ERR_InExtensionMustBeValueType, "PrintValue").WithArguments("PrintValue").WithLocation(4, 24),
// (14,11): error CS1061: 'IComparable' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'IComparable' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("System.IComparable", "PrintValue").WithLocation(14, 11));
CreateCompilation(@"
public static class Program2
{
public static void Main()
{
System.IComparable x = 5;
x.PrintValue();
Extensions.PrintValue(" + (modifier == "ref readonly" ? "in " : "") + @"x);
}
}", references: new[] { reference.ToMetadataReference() }).VerifyDiagnostics(
// (7,11): error CS1061: 'IComparable' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'IComparable' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("System.IComparable", "PrintValue").WithLocation(7, 11));
}
[Theory, CombinatorialData]
public void InExtensionMethodsReceiverTypes_UnconstrainedGenericTypes_NotAllowed([CombinatorialValues("in", "ref readonly")] string modifier)
{
var code = @"
public static class Extensions
{
public static void PrintValue<T>(" + modifier + @" this T p)
{
System.Console.WriteLine(p);
}
}
public static class Program
{
public static void Main()
{
string x = ""test"";
x.PrintValue();
Extensions.PrintValue(" + (modifier == "ref readonly" ? "in " : "") + @"x);
}
}";
var reference = CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics(
// (4,24): error CS8338: The first 'in' or 'ref readonly' parameter of the extension method 'PrintValue' must be a concrete (non-generic) value type.
// public static void PrintValue<T>(in this T p)
Diagnostic(ErrorCode.ERR_InExtensionMustBeValueType, "PrintValue").WithArguments("PrintValue").WithLocation(4, 24),
// (14,11): error CS1061: 'string' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("string", "PrintValue").WithLocation(14, 11));
CreateCompilation(@"
public static class Program2
{
public static void Main()
{
string x = ""test"";
x.PrintValue();
Extensions.PrintValue(" + (modifier == "ref readonly" ? "in " : "") + @"x);
}
}", references: new[] { reference.ToMetadataReference() }).VerifyDiagnostics(
// (7,11): error CS1061: 'string' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("string", "PrintValue").WithLocation(7, 11));
}
[Theory, CombinatorialData]
public void InExtensionMethodsReceiverTypes_StructConstrainedGenericTypes_NotAllowed([CombinatorialValues("in", "ref readonly")] string modifier)
{
var code = @"
public static class Extensions
{
public static void PrintValue<T>(" + modifier + @" this T p) where T : struct
{
System.Console.WriteLine(p);
}
}
public static class Program
{
public static void Main()
{
int x = 5;
x.PrintValue();
Extensions.PrintValue(" + (modifier == "ref readonly" ? "in " : "") + @"x);
}
}";
var reference = CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics(
// (4,24): error CS8338: The first 'in' or 'ref readonly' parameter of the extension method 'PrintValue' must be a concrete (non-generic) value type.
// public static void PrintValue<T>(in this T p) where T : struct
Diagnostic(ErrorCode.ERR_InExtensionMustBeValueType, "PrintValue").WithArguments("PrintValue").WithLocation(4, 24),
// (14,11): error CS1061: 'int' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'int' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("int", "PrintValue").WithLocation(14, 11));
CreateCompilation(@"
public static class Program2
{
public static void Main()
{
int x = 5;
x.PrintValue();
Extensions.PrintValue(" + (modifier == "ref readonly" ? "in " : "") + @"x);
}
}", references: new[] { reference.ToMetadataReference() }).VerifyDiagnostics(
// (7,11): error CS1061: 'int' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'int' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("int", "PrintValue").WithLocation(7, 11));
}
[Theory, CombinatorialData]
public void InExtensionMethodsReceiverTypes_ClassConstrainedGenericTypes_NotAllowed([CombinatorialValues("in", "ref readonly")] string modifier)
{
var code = @"
public static class Extensions
{
public static void PrintValue<T>(" + modifier + @" this T p) where T : class
{
System.Console.WriteLine(p);
}
}
public static class Program
{
public static void Main()
{
string x = ""test"";
x.PrintValue();
Extensions.PrintValue(" + (modifier == "ref readonly" ? "in " : "") + @"x);
}
}";
var reference = CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics(
// (4,24): error CS8338: The first 'in' or 'ref readonly' parameter of the extension method 'PrintValue' must be a concrete (non-generic) value type.
// public static void PrintValue<T>(in this T p) where T : class
Diagnostic(ErrorCode.ERR_InExtensionMustBeValueType, "PrintValue").WithArguments("PrintValue").WithLocation(4, 24),
// (14,11): error CS1061: 'string' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("string", "PrintValue").WithLocation(14, 11));
CreateCompilation(@"
public static class Program2
{
public static void Main()
{
string x = ""test"";
x.PrintValue();
Extensions.PrintValue(" + (modifier == "ref readonly" ? "in " : "") + @"x);
}
}", references: new[] { reference.ToMetadataReference() }).VerifyDiagnostics(
// (7,11): error CS1061: 'string' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("string", "PrintValue").WithLocation(7, 11));
}
[Theory, CombinatorialData]
public void InExtensionMethodsReceiverTypes_InterfaceConstrainedGenericTypes_NotAllowed([CombinatorialValues("in", "ref readonly")] string modifier)
{
var code = @"
public static class Extensions
{
public static void PrintValue<T>(" + modifier + @" this T p) where T : System.IComparable
{
System.Console.WriteLine(p);
}
}
public static class Program
{
public static void Main()
{
string x = ""test"";
x.PrintValue();
Extensions.PrintValue(" + (modifier == "ref readonly" ? "in " : "") + @"x);
}
}";
var reference = CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics(
// (4,24): error CS8338: The first 'in' or 'ref readonly' parameter of the extension method 'PrintValue' must be a value type.
// public static void PrintValue<T>(in this T p) where T : System.IComparable
Diagnostic(ErrorCode.ERR_InExtensionMustBeValueType, "PrintValue").WithArguments("PrintValue").WithLocation(4, 24),
// (14,11): error CS1061: 'string' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("string", "PrintValue").WithLocation(14, 11));
CreateCompilation(@"
public static class Program2
{
public static void Main()
{
string x = ""test"";
x.PrintValue();
Extensions.PrintValue(" + (modifier == "ref readonly" ? "in " : "") + @"x);
}
}", references: new[] { reference.ToMetadataReference() }).VerifyDiagnostics(
// (7,11): error CS1061: 'string' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("string", "PrintValue").WithLocation(7, 11));
}
[Theory, CombinatorialData]
public void InExtensionMethodsReceiverTypes_ValueTypes_Allowed_IL([CombinatorialValues("IsReadOnlyAttribute", "RequiresLocationAttribute")] string attributeName)
{
var reference = CompileIL(ExtraRefReadOnlyIL + @"
.class public abstract auto ansi sealed beforefieldinit Extensions extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig static void PrintValue(int32& p) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.param [1]
.custom instance void System.Runtime.CompilerServices." + attributeName + @"::.ctor() = ( 01 00 00 00 )
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldind.i4
IL_0003: call void [mscorlib]System.Console::Write(int32)
IL_0008: nop
IL_0009: ret
}
}");
var code = @"
public static class Program
{
public static void Main()
{
int x = 5;
x.PrintValue();
Extensions.PrintValue(x);
}
}";
CompileAndVerify(code, references: new[] { reference }, expectedOutput: "55");
}
[Theory, CombinatorialData]
public void InExtensionMethodsReceiverTypes_ReferenceTypes_NotAllowed_IL([CombinatorialValues("IsReadOnlyAttribute", "RequiresLocationAttribute")] string attributeName)
{
var reference = CompileIL(ExtraRefReadOnlyIL + @"
.class public abstract auto ansi sealed beforefieldinit Extensions extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig static void PrintValue(string& p) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.param [1]
.custom instance void System.Runtime.CompilerServices." + attributeName + @"::.ctor() = ( 01 00 00 00 )
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldind.i4
IL_0003: call void [mscorlib]System.Console::Write(string)
IL_0008: nop
IL_0009: ret
}
}");
var code = @"
public static class Program
{
public static void Main()
{
string x = ""test"";
x.PrintValue();
Extensions.PrintValue(" + (attributeName == "RequiresLocationAttribute" ? "in " : "") + @"x);
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code, references: new[] { reference }).VerifyDiagnostics(
// (7,11): error CS1061: 'string' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("string", "PrintValue").WithLocation(7, 11));
}
[Theory, CombinatorialData]
public void InExtensionMethodsReceiverTypes_InterfaceTypes_NotAllowed_IL([CombinatorialValues("IsReadOnlyAttribute", "RequiresLocationAttribute")] string attributeName)
{
var reference = CompileIL(ExtraRefReadOnlyIL + @"
.class public abstract auto ansi sealed beforefieldinit Extensions extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig static void PrintValue(class [mscorlib]System.IComparable& p) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.param [1]
.custom instance void System.Runtime.CompilerServices." + attributeName + @"::.ctor() = ( 01 00 00 00 )
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldind.i4
IL_0003: call void [mscorlib]System.Console::Write(string)
IL_0008: nop
IL_0009: ret
}
}");
var code = @"
public static class Program
{
public static void Main()
{
System.IComparable x = 5;
x.PrintValue();
Extensions.PrintValue(" + (attributeName == "RequiresLocationAttribute" ? "in " : "") + @"x);
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code, references: new[] { reference }).VerifyDiagnostics(
// (7,11): error CS1061: 'IComparable' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'IComparable' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("System.IComparable", "PrintValue").WithLocation(7, 11));
}
[Theory, CombinatorialData]
public void InExtensionMethodsReceiverTypes_UnconstrainedGenericTypes_NotAllowed_IL([CombinatorialValues("IsReadOnlyAttribute", "RequiresLocationAttribute")] string attributeName)
{
var reference = CompileIL(ExtraRefReadOnlyIL + @"
.class public abstract auto ansi sealed beforefieldinit Extensions extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig static void PrintValue<T>(!!T& p) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.param [1]
.custom instance void System.Runtime.CompilerServices." + attributeName + @"::.ctor() = ( 01 00 00 00 )
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldind.i4
IL_0003: call void [mscorlib]System.Console::Write(object)
IL_0008: nop
IL_0009: ret
}
}");
var code = @"
public static class Program
{
public static void Main()
{
string x = ""test"";
x.PrintValue();
Extensions.PrintValue(" + (attributeName == "RequiresLocationAttribute" ? "in " : "") + @"x);
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code, references: new[] { reference }).VerifyDiagnostics(
// (7,11): error CS1061: 'string' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("string", "PrintValue").WithLocation(7, 11));
}
[Theory, CombinatorialData]
public void InExtensionMethodsReceiverTypes_StructConstrainedGenericTypes_NotAllowed_IL([CombinatorialValues("IsReadOnlyAttribute", "RequiresLocationAttribute")] string attributeName)
{
var reference = CompileIL(ExtraRefReadOnlyIL + @"
.class public abstract auto ansi sealed beforefieldinit Extensions extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig static void PrintValue<valuetype .ctor ([mscorlib]System.ValueType) T>(!!T& p) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.param [1]
.custom instance void System.Runtime.CompilerServices." + attributeName + @"::.ctor() = ( 01 00 00 00 )
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldind.i4
IL_0003: call void [mscorlib]System.Console::Write(object)
IL_0008: nop
IL_0009: ret
}
}");
var code = @"
public static class Program
{
public static void Main()
{
int x = 5;
x.PrintValue();
Extensions.PrintValue(" + (attributeName == "RequiresLocationAttribute" ? "in " : "") + @"x);
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code, references: new[] { reference }).VerifyDiagnostics(
// (7,11): error CS1061: 'int' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'int' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("int", "PrintValue").WithLocation(7, 11));
}
[Theory, CombinatorialData]
public void InExtensionMethodsReceiverTypes_ClassConstrainedGenericTypes_NotAllowed_IL([CombinatorialValues("IsReadOnlyAttribute", "RequiresLocationAttribute")] string attributeName)
{
var reference = CompileIL(ExtraRefReadOnlyIL + @"
.class public abstract auto ansi sealed beforefieldinit Extensions extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig static void PrintValue<class T>(!!T& p) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.param [1]
.custom instance void System.Runtime.CompilerServices." + attributeName + @"::.ctor() = ( 01 00 00 00 )
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldind.i4
IL_0003: call void [mscorlib]System.Console::Write(object)
IL_0008: nop
IL_0009: ret
}
}");
var code = @"
public static class Program
{
public static void Main()
{
string x = ""test"";
x.PrintValue();
Extensions.PrintValue(" + (attributeName == "RequiresLocationAttribute" ? "in " : "") + @"x);
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code, references: new[] { reference }).VerifyDiagnostics(
// (7,11): error CS1061: 'string' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("string", "PrintValue").WithLocation(7, 11));
}
[Theory, CombinatorialData]
public void InExtensionMethodsReceiverTypes_InterfaceConstrainedGenericTypes_NotAllowed_IL([CombinatorialValues("IsReadOnlyAttribute", "RequiresLocationAttribute")] string attributeName)
{
var reference = CompileIL(ExtraRefReadOnlyIL + @"
.class public abstract auto ansi sealed beforefieldinit Extensions extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig static void PrintValue<([mscorlib]System.IComparable) T>(!!T& p) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
.param [1]
.custom instance void System.Runtime.CompilerServices." + attributeName + @"::.ctor() = ( 01 00 00 00 )
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldind.i4
IL_0003: call void [mscorlib]System.Console::Write(object)
IL_0008: nop
IL_0009: ret
}
}");
var code = @"
public static class Program
{
public static void Main()
{
string x = ""test"";
x.PrintValue();
Extensions.PrintValue(" + (attributeName == "RequiresLocationAttribute" ? "in " : "") + @"x);
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code, references: new[] { reference }).VerifyDiagnostics(
// (7,11): error CS1061: 'string' does not contain a definition for 'PrintValue' and no extension method 'PrintValue' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
// x.PrintValue();
Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "PrintValue").WithArguments("string", "PrintValue").WithLocation(7, 11));
}
[Fact]
public void InErrorsArePropagatedThroughExtensionMethods()
{
var code = @"
public static class Extensions
{
public static void Modify(in this int p)
{
p++;
}
}
public static class Program
{
public static void Main()
{
int value = 0;
value.Modify();
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics(
// (6,9): error CS8331: Cannot assign to variable 'p' or use it as the right hand side of a ref assignment because it is a readonly variable
// p++;
Diagnostic(ErrorCode.ERR_AssignReadonlyNotField, "p").WithArguments("variable", "p").WithLocation(6, 9));
}
[Fact]
public void RefExtensionMethods_CodeGen()
{
var code = @"
public static class Extensions
{
public static int IncrementAndGet(ref this int x)
{
return x++;
}
}
public class Test
{
public static void Main()
{
int value = 0;
int other = value.IncrementAndGet();
System.Console.Write(value);
System.Console.Write(other);
}
}";
var compilation = CreateCompilationWithMscorlib40AndSystemCore(code, options: TestOptions.ReleaseExe);
var verifier = CompileAndVerify(compilation, expectedOutput: "10");
verifier.VerifyIL("Test.Main", @"
{
// Code size 21 (0x15)
.maxstack 2
.locals init (int V_0) //value
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: ldloca.s V_0
IL_0004: call ""int Extensions.IncrementAndGet(ref int)""
IL_0009: ldloc.0
IL_000a: call ""void System.Console.Write(int)""
IL_000f: call ""void System.Console.Write(int)""
IL_0014: ret
}");
verifier.VerifyIL("Extensions.IncrementAndGet", @"
{
// Code size 10 (0xa)
.maxstack 3
.locals init (int V_0)
IL_0000: ldarg.0
IL_0001: ldarg.0
IL_0002: ldind.i4
IL_0003: stloc.0
IL_0004: ldloc.0
IL_0005: ldc.i4.1
IL_0006: add
IL_0007: stind.i4
IL_0008: ldloc.0
IL_0009: ret
}");
}
[Fact]
public void InExtensionMethods_CodeGen()
{
var code = @"
public static class Extensions
{
public static void Print(in this int x)
{
System.Console.Write(x);
}
}
public class Test
{
public static void Main()
{
int value = 0;
value.Print();
}
}";
var compilation = CreateCompilationWithMscorlib40AndSystemCore(code, options: TestOptions.ReleaseExe);
var verifier = CompileAndVerify(compilation, expectedOutput: "0");
verifier.VerifyIL("Test.Main", @"
{
// Code size 10 (0xa)
.maxstack 1
.locals init (int V_0) //value
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: ldloca.s V_0
IL_0004: call ""void Extensions.Print(in int)""
IL_0009: ret
}");
verifier.VerifyIL("Extensions.Print", @"
{
// Code size 8 (0x8)
.maxstack 1
IL_0000: ldarg.0
IL_0001: ldind.i4
IL_0002: call ""void System.Console.Write(int)""
IL_0007: ret
}");
}
[Fact]
public void Conversions_Numeric_RefExtensionMethods_NotAllowed()
{
var code = @"
public static class Extensions
{
public static void Print(ref this long x)
{
System.Console.WriteLine(x);
}
}
public class Test
{
public static void Main()
{
int intValue = 0;
intValue.Print(); // Should be an error
long longValue = 0;
longValue.Print(); // Should be OK
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics(
// (14,9): error CS1929: 'int' does not contain a definition for 'Print' and the best extension method overload 'Extensions.Print(ref long)' requires a receiver of type 'ref long'
// intValue.Print(); // Should be an error
Diagnostic(ErrorCode.ERR_BadInstanceArgType, "intValue").WithArguments("int", "Print", "Extensions.Print(ref long)", "ref long").WithLocation(14, 9));
}
[Fact]
public void Conversions_Numeric_InExtensionMethods_NotAllowed()
{
var code = @"
public static class Extensions
{
public static void Print(in this long x)
{
System.Console.WriteLine(x);
}
}
public class Test
{
public static void Main()
{
int intValue = 0;
intValue.Print(); // Should be an error
long longValue = 0;
longValue.Print(); // Should be OK
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics(
// (14,9): error CS1929: 'int' does not contain a definition for 'Print' and the best extension method overload 'Extensions.Print(in long)' requires a receiver of type 'in long'
// intValue.Print(); // Should be an error
Diagnostic(ErrorCode.ERR_BadInstanceArgType, "intValue").WithArguments("int", "Print", "Extensions.Print(in long)", "in long").WithLocation(14, 9));
}
[Fact]
public void Conversion_Tuples_RefExtensionMethods_NotAllowed()
{
var code = @"
public static class Extensions
{
public static void Print(ref this (long, long) x)
{
System.Console.WriteLine(x);
}
}
public class Test
{
public static void Main()
{
int intValue1 = 0;
int intValue2 = 0;
var intTuple = (intValue1, intValue2);
intTuple.Print(); // Should be an error
long longValue1 = 0;
long longValue2 = 0;
var longTuple = (longValue1, longValue2);
longTuple.Print(); // Should be OK
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }).VerifyDiagnostics(
// (16,9): error CS1929: '(int intValue1, int intValue2)' does not contain a definition for 'Print' and the best extension method overload 'Extensions.Print(ref (long, long))' requires a receiver of type 'ref (long, long)'
// intTuple.Print(); // Should be an error
Diagnostic(ErrorCode.ERR_BadInstanceArgType, "intTuple").WithArguments("(int intValue1, int intValue2)", "Print", "Extensions.Print(ref (long, long))", "ref (long, long)").WithLocation(16, 9));
}
[Fact]
public void Conversion_Tuples_InExtensionMethods_NotAllowed()
{
var code = @"
public static class Extensions
{
public static void Print(in this (long, long) x)
{
System.Console.WriteLine(x);
}
}
public class Test
{
public static void Main()
{
int intValue1 = 0;
int intValue2 = 0;
var intTuple = (intValue1, intValue2);
intTuple.Print(); // Should be an error
long longValue1 = 0;
long longValue2 = 0;
var longTuple = (longValue1, longValue2);
longTuple.Print(); // Should be OK
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }).VerifyDiagnostics(
// (16,9): error CS1929: '(int intValue1, int intValue2)' does not contain a definition for 'Print' and the best extension method overload 'Extensions.Print(in (long, long))' requires a receiver of type 'in (long, long)'
// intTuple.Print(); // Should be an error
Diagnostic(ErrorCode.ERR_BadInstanceArgType, "intTuple").WithArguments("(int intValue1, int intValue2)", "Print", "Extensions.Print(in (long, long))", "in (long, long)").WithLocation(16, 9));
}
[Fact]
public void Conversions_Nullables_RefExtensionMethods_NotAllowed()
{
var code = @"
public static class Extensions
{
public static void Print(ref this int? x)
{
System.Console.WriteLine(x.Value);
}
}
public class Test
{
public static void Main()
{
0.Print(); // Should be an error
int intValue = 0;
intValue.Print(); // Should be an error
int? nullableValue = intValue;
nullableValue.Print(); // Should be OK
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics(
// (13,9): error CS1929: 'int' does not contain a definition for 'Print' and the best extension method overload 'Extensions.Print(ref int?)' requires a receiver of type 'ref int?'
// 0.Print(); // Should be an error
Diagnostic(ErrorCode.ERR_BadInstanceArgType, "0").WithArguments("int", "Print", "Extensions.Print(ref int?)", "ref int?").WithLocation(13, 9),
// (16,9): error CS1929: 'int' does not contain a definition for 'Print' and the best extension method overload 'Extensions.Print(ref int?)' requires a receiver of type 'ref int?'
// intValue.Print(); // Should be an error
Diagnostic(ErrorCode.ERR_BadInstanceArgType, "intValue").WithArguments("int", "Print", "Extensions.Print(ref int?)", "ref int?").WithLocation(16, 9));
}
[Fact]
public void Conversions_Nullables_InExtensionMethods_NotAllowed()
{
var code = @"
public static class Extensions
{
public static void Print(in this int? x)
{
System.Console.WriteLine(x.Value);
}
}
public class Test
{
public static void Main()
{
0.Print(); // Should be an error
int intValue = 0;
intValue.Print(); // Should be an error
int? nullableValue = intValue;
nullableValue.Print(); // Should be OK
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics(
// (13,9): error CS1929: 'int' does not contain a definition for 'Print' and the best extension method overload 'Extensions.Print(in int?)' requires a receiver of type 'in int?'
// 0.Print(); // Should be an error
Diagnostic(ErrorCode.ERR_BadInstanceArgType, "0").WithArguments("int", "Print", "Extensions.Print(in int?)", "in int?").WithLocation(13, 9),
// (16,9): error CS1929: 'int' does not contain a definition for 'Print' and the best extension method overload 'Extensions.Print(in int?)' requires a receiver of type 'in int?'
// intValue.Print(); // Should be an error
Diagnostic(ErrorCode.ERR_BadInstanceArgType, "intValue").WithArguments("int", "Print", "Extensions.Print(in int?)", "in int?").WithLocation(16, 9));
}
[Fact]
public void Conversions_ImplicitOperators_RefExtensionMethods_NotAllowed()
{
var code = @"
public static class Extensions
{
public static void Print(ref this Test x)
{
System.Console.WriteLine(x);
}
}
public struct Test
{
public static implicit operator Test(string value) => default(Test);
public void TryMethod()
{
string stringValue = ""test"";
stringValue.Print(); // Should be an error
Test testValue = stringValue;
testValue.Print(); // Should be OK
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics(
// (16,9): error CS1929: 'string' does not contain a definition for 'Print' and the best extension method overload 'Extensions.Print(ref Test)' requires a receiver of type 'ref Test'
// stringValue.Print(); // Should be an error
Diagnostic(ErrorCode.ERR_BadInstanceArgType, "stringValue").WithArguments("string", "Print", "Extensions.Print(ref Test)", "ref Test").WithLocation(16, 9));
}
[Fact]
public void Conversions_ImplicitOperators_InExtensionMethods_NotAllowed()
{
var code = @"
public static class Extensions
{
public static void Print(ref this Test x)
{
System.Console.WriteLine(x);
}
}
public struct Test
{
public static implicit operator Test(string value) => default(Test);
public void TryMethod()
{
string stringValue = ""test"";
stringValue.Print(); // Should be an error
Test testValue = stringValue;
testValue.Print(); // Should be OK
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics(
// (16,9): error CS1929: 'string' does not contain a definition for 'Print' and the best extension method overload 'Extensions.Print(ref Test)' requires a receiver of type 'ref Test'
// stringValue.Print(); // Should be an error
Diagnostic(ErrorCode.ERR_BadInstanceArgType, "stringValue").WithArguments("string", "Print", "Extensions.Print(ref Test)", "ref Test").WithLocation(16, 9));
}
[Fact]
public void ColorColorCasesShouldBeResolvedCorrectly_RefExtensionMethods()
{
var code = @"
public struct Color
{
public void Instance()
{
System.Console.Write(""Instance"");
}
public static void Static()
{
System.Console.Write(""Static"");
}
}
public static class Extensions
{
public static void Extension(ref this Color x)
{
System.Console.Write(""Extension"");
}
}
public class Test
{
private static Color Color = new Color();
public static void Main()
{
Color.Instance();
System.Console.Write("","");
Color.Extension();
System.Console.Write("","");
Color.Static();
}
}";
CompileAndVerify(code, expectedOutput: "Instance,Extension,Static");
}
[Fact]
public void ColorColorCasesShouldBeResolvedCorrectly_InExtensionMethods()
{
var code = @"
public struct Color
{
public void Instance()
{
System.Console.Write(""Instance"");
}
public static void Static()
{
System.Console.Write(""Static"");
}
}
public static class Extensions
{
public static void Extension(in this Color x)
{
System.Console.Write(""Extension"");
}
}
public class Test
{
private static Color Color = new Color();
public static void Main()
{
Color.Instance();
System.Console.Write("","");
Color.Extension();
System.Console.Write("","");
Color.Static();
}
}";
CompileAndVerify(code, expectedOutput: "Instance,Extension,Static");
}
[Fact]
public void RecursiveCalling_RefExtensionMethods()
{
var code = @"
public struct S1
{
public int i;
public void Mutate()
{
System.Console.Write(i--);
}
}
public static class Extensions
{
public static void PrintValue(ref this S1 obj)
{
if (obj.i > 0)
{
obj.Mutate();
obj.PrintValue();
}
}
}
public class Program
{
public static void Main()
{
var obj = new S1 { i = 5 };
obj.PrintValue();
}
}";
CompileAndVerify(code, expectedOutput: "54321");
}
[Fact]
public void MutationIsObserved_RefExtensionMethods()
{
var code = @"
public static class Extensions
{
public static void Decrement(ref this int p)
{
p--;
}
}
public class Program
{
public static void Main()
{
int p = 8;
p.Decrement();
System.Console.WriteLine(p);
}
}";
CompileAndVerify(code, expectedOutput: "7");
}
[Fact]
public void RecursiveCalling_InExtensionMethods()
{
var code = @"
public struct S1
{
public int i;
public void Mutate()
{
System.Console.Write(i--);
}
}
public static class Extensions
{
public static void PrintValue(in this S1 obj, S1 other)
{
if (other.i > 0)
{
// should not mutate
obj.Mutate();
// should mutate
other.Mutate();
obj.PrintValue(other);
}
}
}
public class Program
{
public static void Main()
{
var obj = new S1 { i = 5 };
obj.PrintValue(obj);
}
}";
CompileAndVerify(code, expectedOutput: "5554535251");
}
[Fact]
public void AmbiguousRefnessForExtensionMethods_RValue()
{
var code = @"
public static class Ext1
{
public static void Print(ref this int p)
{
System.Console.WriteLine(p);
}
}
public static class Ext2
{
public static void Print(in this int p)
{
System.Console.WriteLine(p);
}
}
public class Program
{
public static void Main()
{
0.Print(); // Error
Ext2.Print(0); // Ok
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics(
// (20,11): error CS0121: The call is ambiguous between the following methods or properties: 'Ext1.Print(ref int)' and 'Ext2.Print(in int)'
// 0.Print(); // Error
Diagnostic(ErrorCode.ERR_AmbigCall, "Print").WithArguments("Ext1.Print(ref int)", "Ext2.Print(in int)").WithLocation(20, 11));
}
[Fact]
public void AmbiguousRefnessForExtensionMethods_LValue()
{
var code = @"
public static class Ext1
{
public static void Print(ref this int p)
{
System.Console.WriteLine(p);
}
}
public static class Ext2
{
public static void Print(in this int p)
{
System.Console.WriteLine(p);
}
}
public class Program
{
public static void Main()
{
int value = 0;
value.Print(); // Error
Ext1.Print(ref value); // Ok
Ext2.Print(value); // Ok
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics(
// (21,15): error CS0121: The call is ambiguous between the following methods or properties: 'Ext1.Print(ref int)' and 'Ext2.Print(in int)'
// value.Print(); // Error
Diagnostic(ErrorCode.ERR_AmbigCall, "Print").WithArguments("Ext1.Print(ref int)", "Ext2.Print(in int)").WithLocation(21, 15));
}
[Fact]
public void ReadOnlynessPreservedThroughMultipleCalls()
{
var code = @"
public static class Ext
{
public static void ReadOnly(in int p)
{
Ref(ref p); // Should be an error
}
public static void Ref(ref int p)
{
Ref(ref p); // Should be OK
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics(
// (6,17): error CS8329: Cannot use variable 'p' as a ref or out value because it is a readonly variable
// Ref(ref p); // Should be an error
Diagnostic(ErrorCode.ERR_RefReadonlyNotField, "p").WithArguments("variable", "p").WithLocation(6, 17));
}
[Fact]
public void ParameterSymbolsRetrievedThroughSemanticModel_RefExtensionMethods()
{
var code = @"
public static class Ext
{
public static void Method(ref this int p) { }
}";
var comp = CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics();
var tree = comp.SyntaxTrees.Single();
var parameter = tree.FindNodeOrTokenByKind(SyntaxKind.Parameter);
Assert.True(parameter.IsNode);
var model = comp.GetSemanticModel(tree);
var symbol = (IParameterSymbol)model.GetDeclaredSymbolForNode(parameter.AsNode());
Assert.Equal(RefKind.Ref, symbol.RefKind);
}
[Fact]
public void ParameterSymbolsRetrievedThroughSemanticModel_InExtensionMethods()
{
var code = @"
public static class Ext
{
public static void Method(in this int p) { }
}";
var comp = CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics();
var tree = comp.SyntaxTrees.Single();
var parameter = tree.FindNodeOrTokenByKind(SyntaxKind.Parameter);
Assert.True(parameter.IsNode);
var model = comp.GetSemanticModel(tree);
var symbol = (IParameterSymbol)model.GetDeclaredSymbolForNode(parameter.AsNode());
Assert.Equal(RefKind.In, symbol.RefKind);
}
[Fact]
public void ParameterSymbolsRetrievedThroughSemanticModel_RefExtensionMethods2()
{
var code = @"
public static class Ext
{
public static void Method(this ref int p) { }
}";
var comp = CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics();
var tree = comp.SyntaxTrees.Single();
var parameter = tree.FindNodeOrTokenByKind(SyntaxKind.Parameter);
Assert.True(parameter.IsNode);
var model = comp.GetSemanticModel(tree);
var symbol = (IParameterSymbol)model.GetDeclaredSymbolForNode(parameter.AsNode());
Assert.Equal(RefKind.Ref, symbol.RefKind);
}
[Fact]
public void ParameterSymbolsRetrievedThroughSemanticModel_InExtensionMethods2()
{
var code = @"
public static class Ext
{
public static void Method(this in int p) { }
}";
var comp = CreateCompilationWithMscorlib40AndSystemCore(code).VerifyDiagnostics();
var tree = comp.SyntaxTrees.Single();
var parameter = tree.FindNodeOrTokenByKind(SyntaxKind.Parameter);
Assert.True(parameter.IsNode);
var model = comp.GetSemanticModel(tree);
var symbol = (IParameterSymbol)model.GetDeclaredSymbolForNode(parameter.AsNode());
Assert.Equal(RefKind.In, symbol.RefKind);
}
[Fact]
public void BadContainingType_ThisWithRef()
{
var test = @"
using System;
public static class GenExtensions<X> where X : struct
{
//No type parameters
public static void Goo1(ref this int i) {}
public static void Goo1(ref this X x) {}
public static void Goo2(this ref int i) {}
public static void Goo2(this ref X x) {}
//Single type parameter
public static void Goo1<T>(ref this T t) where T : struct {}
public static void Goo1<T>(ref this X x) {}
public static void Goo2<T>(this ref T t) where T : struct {}
public static void Goo2<T>(this ref X x) {}
//Multiple type parameters
public static void Goo1<T,U,V>(ref this U u) where U : struct {}
public static void Goo1<T,U,V>(ref this X x) {}
public static void Goo2<T,U,V>(this ref U u) where U : struct {}
public static void Goo2<T,U,V>(this ref X x) {}
}
";
CreateCompilationWithMscorlib40AndSystemCore(test).GetDeclarationDiagnostics().Verify(
// (3,21): error CS1106: Extension method must be defined in a non-generic static class
// public static class GenExtensions<X> where X : struct
Diagnostic(ErrorCode.ERR_BadExtensionAgg, "GenExtensions").WithLocation(3, 21),
// (3,21): error CS1106: Extension method must be defined in a non-generic static class
// public static class GenExtensions<X> where X : struct
Diagnostic(ErrorCode.ERR_BadExtensionAgg, "GenExtensions").WithLocation(3, 21),
// (3,21): error CS1106: Extension method must be defined in a non-generic static class
// public static class GenExtensions<X> where X : struct
Diagnostic(ErrorCode.ERR_BadExtensionAgg, "GenExtensions").WithLocation(3, 21),
// (3,21): error CS1106: Extension method must be defined in a non-generic static class
// public static class GenExtensions<X> where X : struct
Diagnostic(ErrorCode.ERR_BadExtensionAgg, "GenExtensions").WithLocation(3, 21),
// (3,21): error CS1106: Extension method must be defined in a non-generic static class
// public static class GenExtensions<X> where X : struct
Diagnostic(ErrorCode.ERR_BadExtensionAgg, "GenExtensions").WithLocation(3, 21),
// (3,21): error CS1106: Extension method must be defined in a non-generic static class
// public static class GenExtensions<X> where X : struct
Diagnostic(ErrorCode.ERR_BadExtensionAgg, "GenExtensions").WithLocation(3, 21),
// (3,21): error CS1106: Extension method must be defined in a non-generic static class
// public static class GenExtensions<X> where X : struct
Diagnostic(ErrorCode.ERR_BadExtensionAgg, "GenExtensions").WithLocation(3, 21),
// (3,21): error CS1106: Extension method must be defined in a non-generic static class
// public static class GenExtensions<X> where X : struct
Diagnostic(ErrorCode.ERR_BadExtensionAgg, "GenExtensions").WithLocation(3, 21),
// (3,21): error CS1106: Extension method must be defined in a non-generic static class
// public static class GenExtensions<X> where X : struct
Diagnostic(ErrorCode.ERR_BadExtensionAgg, "GenExtensions").WithLocation(3, 21),
// (3,21): error CS1106: Extension method must be defined in a non-generic static class
// public static class GenExtensions<X> where X : struct
Diagnostic(ErrorCode.ERR_BadExtensionAgg, "GenExtensions").WithLocation(3, 21),
// (3,21): error CS1106: Extension method must be defined in a non-generic static class
// public static class GenExtensions<X> where X : struct
Diagnostic(ErrorCode.ERR_BadExtensionAgg, "GenExtensions").WithLocation(3, 21),
// (3,21): error CS1106: Extension method must be defined in a non-generic static class
// public static class GenExtensions<X> where X : struct
Diagnostic(ErrorCode.ERR_BadExtensionAgg, "GenExtensions").WithLocation(3, 21));
}
[Fact]
public void UsingRefExtensionMethodsBeforeVersion7_2ProducesDiagnostics_RefSyntax_SameCompilation()
{
var code = @"
public static class Ext
{
public static void Print(ref this int p)
{
System.Console.WriteLine(p);
}
}
public static class Program
{
public static void Main()
{
int p = 5;
p.Print();
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code, parseOptions: CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp7_1)).VerifyDiagnostics(
// (4,34): error CS8302: Feature 'ref extension methods' is not available in C# 7.1. Please use language version 7.2 or greater.
// public static void Print(ref this int p)
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "this").WithArguments("ref extension methods", "7.2").WithLocation(4, 34),
// (14,9): error CS8302: Feature 'ref extension methods' is not available in C# 7.1. Please use language version 7.2 or greater.
// p.Print();
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "p").WithArguments("ref extension methods", "7.2").WithLocation(14, 9));
CompileAndVerify(code, expectedOutput: "5");
}
[Fact]
public void UsingRefExtensionMethodsBeforeVersion7_2ProducesDiagnostics_RefSyntax_DifferentCompilation()
{
var reference = CreateCompilationWithMscorlib40AndSystemCore(@"
public static class Ext
{
public static void Print(ref this int p)
{
System.Console.WriteLine(p);
}
}");
var code = @"
public static class Program
{
public static void Main()
{
int p = 5;
p.Print();
}
}";
CreateCompilationWithMscorlib40AndSystemCore(
source: code,
parseOptions: CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp7_1),
references: new[] { reference.ToMetadataReference() }).VerifyDiagnostics(
// (7,9): error CS8302: Feature 'ref extension methods' is not available in C# 7.1. Please use language version 7.2 or greater.
// p.Print();
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "p").WithArguments("ref extension methods", "7.2").WithLocation(7, 9));
CreateCompilationWithMscorlib40AndSystemCore(
source: code,
parseOptions: CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp7_1),
references: new[] { reference.EmitToImageReference() }).VerifyDiagnostics(
// (7,9): error CS8302: Feature 'ref extension methods' is not available in C# 7.1. Please use language version 7.2 or greater.
// p.Print();
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "p").WithArguments("ref extension methods", "7.2").WithLocation(7, 9));
CompileAndVerify(code, references: new[] { reference.ToMetadataReference() }, expectedOutput: "5");
CompileAndVerify(code, references: new[] { reference.EmitToImageReference() }, expectedOutput: "5");
}
[Fact]
public void UsingRefExtensionMethodsBeforeVersion7_2ProducesDiagnostics_InSyntax_SameCompilation()
{
var code = @"
public static class Ext
{
public static void Print0(in this int p)
=> System.Console.Write(p);
public static void Print1(this in int p)
=> System.Console.Write(p);
public static void Print2(ref this int p)
=> System.Console.Write(p);
public static void Print3(this ref int p)
=> System.Console.Write(p);
}
public static class Program
{
public static void Main()
{
int p = 5;
p.Print0();
p.Print1();
p.Print2();
p.Print3();
}
}";
CreateCompilationWithMscorlib40AndSystemCore(code, parseOptions: CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp7_1)).VerifyDiagnostics(
// (4,31): error CS8302: Feature 'readonly references' is not available in C# 7.1. Please use language version 7.2 or greater.
// public static void Print0(in this int p)
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "in").WithArguments("readonly references", "7.2").WithLocation(4, 31),
// (4,34): error CS8302: Feature 'ref extension methods' is not available in C# 7.1. Please use language version 7.2 or greater.
// public static void Print0(in this int p)
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "this").WithArguments("ref extension methods", "7.2").WithLocation(4, 34),
// (6,36): error CS8302: Feature 'readonly references' is not available in C# 7.1. Please use language version 7.2 or greater.
// public static void Print1(this in int p)
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "in").WithArguments("readonly references", "7.2").WithLocation(6, 36),
// (6,36): error CS8302: Feature 'ref extension methods' is not available in C# 7.1. Please use language version 7.2 or greater.
// public static void Print1(this in int p)
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "in").WithArguments("ref extension methods", "7.2").WithLocation(6, 36),
// (8,35): error CS8302: Feature 'ref extension methods' is not available in C# 7.1. Please use language version 7.2 or greater.
// public static void Print2(ref this int p)
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "this").WithArguments("ref extension methods", "7.2").WithLocation(8, 35),
// (10,36): error CS8302: Feature 'ref extension methods' is not available in C# 7.1. Please use language version 7.2 or greater.
// public static void Print3(this ref int p)
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "ref").WithArguments("ref extension methods", "7.2").WithLocation(10, 36),
// (18,9): error CS8302: Feature 'ref extension methods' is not available in C# 7.1. Please use language version 7.2 or greater.
// p.Print0();
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "p").WithArguments("ref extension methods", "7.2").WithLocation(18, 9),
// (19,9): error CS8302: Feature 'ref extension methods' is not available in C# 7.1. Please use language version 7.2 or greater.
// p.Print1();
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "p").WithArguments("ref extension methods", "7.2").WithLocation(19, 9),
// (20,9): error CS8302: Feature 'ref extension methods' is not available in C# 7.1. Please use language version 7.2 or greater.
// p.Print2();
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "p").WithArguments("ref extension methods", "7.2").WithLocation(20, 9),
// (21,9): error CS8302: Feature 'ref extension methods' is not available in C# 7.1. Please use language version 7.2 or greater.
// p.Print3();
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "p").WithArguments("ref extension methods", "7.2").WithLocation(21, 9));
CompileAndVerify(code, expectedOutput: "5555");
}
[Fact]
public void UsingRefExtensionMethodsBeforeVersion7_2ProducesDiagnostics_InSyntax_DifferentCompilation()
{
var reference = CreateCompilationWithMscorlib40AndSystemCore(@"
public static class Ext
{
public static void Print(in this int p)
{
System.Console.WriteLine(p);
}
}");
var code = @"
public static class Program
{
public static void Main()
{
int p = 5;
p.Print();
}
}";
CreateCompilationWithMscorlib40AndSystemCore(
source: code,
parseOptions: CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp7_1),
references: new[] { reference.ToMetadataReference() }).VerifyDiagnostics(
// (7,9): error CS8302: Feature 'ref extension methods' is not available in C# 7.1. Please use language version 7.2 or greater.
// p.Print();
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "p").WithArguments("ref extension methods", "7.2").WithLocation(7, 9));
CreateCompilationWithMscorlib40AndSystemCore(
source: code,
parseOptions: CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp7_1),
references: new[] { reference.EmitToImageReference() }).VerifyDiagnostics(
// (7,9): error CS8302: Feature 'ref extension methods' is not available in C# 7.1. Please use language version 7.2 or greater.
// p.Print();
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "p").WithArguments("ref extension methods", "7.2").WithLocation(7, 9));
CompileAndVerify(code, references: new[] { reference.ToMetadataReference() }, expectedOutput: "5");
CompileAndVerify(code, references: new[] { reference.EmitToImageReference() }, expectedOutput: "5");
}
private const string ExtraRefReadOnlyIL = @"
.class private auto ansi sealed beforefieldinit Microsoft.CodeAnalysis.EmbeddedAttribute extends [mscorlib]System.Attribute
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.custom instance void Microsoft.CodeAnalysis.EmbeddedAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed
{
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Attribute::.ctor()
IL_0006: nop
IL_0007: ret
}
}
.class private auto ansi sealed beforefieldinit System.Runtime.CompilerServices.IsReadOnlyAttribute extends [mscorlib]System.Attribute
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.custom instance void Microsoft.CodeAnalysis.EmbeddedAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed
{
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Attribute::.ctor()
IL_0006: nop
IL_0007: ret
}
}
.class private auto ansi sealed beforefieldinit System.Runtime.CompilerServices.RequiresLocationAttribute extends System.Object
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed
{
.maxstack 8
ret
}
}
";
}
}
|