diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEMethodSymbol.cs index 44ee8a05b5a2936b3949d47923e8051cf9b10a81..ee3f984e52c75052809cd1d6faa99746efd31133 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEMethodSymbol.cs @@ -1016,20 +1016,25 @@ internal override DiagnosticInfo GetUseSiteDiagnostic() } return CSDiagnosticInfo.IsEmpty(result) - ? InterlockedOperations.Initialize(ref _uncommonFields._lazyUseSiteDiagnostic, null, CSDiagnosticInfo.EmptyErrorInfo) + ? InterlockedOperations.Initialize(ref AccessUncommonFields()._lazyUseSiteDiagnostic, null, CSDiagnosticInfo.EmptyErrorInfo) : result; } private DiagnosticInfo InitializeUseSiteDiagnostic(DiagnosticInfo diagnostic) { - Debug.Assert(!CSDiagnosticInfo.IsEmpty(diagnostic)); + if (_packedFlags.IsUseSiteDiagnosticPopulated) + { + return _uncommonFields?._lazyUseSiteDiagnostic; + } + if (diagnostic != null) { + Debug.Assert(!CSDiagnosticInfo.IsEmpty(diagnostic)); diagnostic = InterlockedOperations.Initialize(ref AccessUncommonFields()._lazyUseSiteDiagnostic, diagnostic, CSDiagnosticInfo.EmptyErrorInfo); } _packedFlags.SetIsUseSiteDiagnosticPopulated(); - return _uncommonFields?._lazyUseSiteDiagnostic; + return diagnostic; } internal override ImmutableArray GetAppliedConditionalSymbols() diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEPropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEPropertySymbol.cs index 872d0d821ddad966e92d7918c89babe336a9b6bd..f8264cee0b86c93a1232eadb58ba0756378ba6fa 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEPropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEPropertySymbol.cs @@ -68,7 +68,7 @@ private enum Flags : byte var propertyParams = metadataDecoder.GetSignatureForProperty(handle, out callingConvention, out propEx); Debug.Assert(propertyParams.Length > 0); - var isBad = propEx != null; + var isBad = false; var returnInfo = propertyParams[0]; PEPropertySymbol result; @@ -81,7 +81,7 @@ private enum Flags : byte result = new PEPropertySymbolWithCustomModifiers(moduleSymbol, containingType, handle, getMethod, setMethod, propertyParams, metadataDecoder, out isBad); } - if (isBad) + if (propEx != null || isBad) { result._lazyUseSiteDiagnostic = new CSDiagnosticInfo(ErrorCode.ERR_BindToBogus, result); } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/CustomModifierUtils.cs b/src/Compilers/CSharp/Portable/Symbols/Source/CustomModifierUtils.cs index 500bd398fed23fe40a130c2ff61518b6aa6ce141..de541a9c8105b1241b7a3b2571640fa002e67055 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/CustomModifierUtils.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/CustomModifierUtils.cs @@ -35,7 +35,9 @@ internal static class CustomModifierUtils // have already been compared. MethodSymbol constructedSourceMethod = sourceMethod.ConstructIfGeneric(destinationMethod.TypeArguments); - customModifiers = CustomModifiersTuple.Create(constructedSourceMethod.ReturnTypeCustomModifiers, constructedSourceMethod.RefCustomModifiers); + customModifiers = CustomModifiersTuple.Create( + constructedSourceMethod.ReturnTypeCustomModifiers, + destinationMethod.ReturnsByRef || destinationMethod.ReturnsByRefReadonly ? constructedSourceMethod.RefCustomModifiers : ImmutableArray.Empty); parameters = CopyParameterCustomModifiers(constructedSourceMethod.Parameters, destinationMethod.Parameters, alsoCopyParamsModifier); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs index d1e531a05d92eb1269779d88cbe34c73110d455a..1ea8cb6ab03b5b329d052399810a49d86db2af5a 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceDelegateMethodSymbol.cs @@ -231,7 +231,8 @@ internal override LexicalSortKey GetLexicalSortKey() private sealed class InvokeMethod : SourceDelegateMethodSymbol { - private readonly RefKind refKind; + private readonly RefKind _refKind; + private readonly ImmutableArray _refCustomModifiers; internal InvokeMethod( SourceMemberContainerTypeSymbol delegateType, @@ -242,14 +243,14 @@ private sealed class InvokeMethod : SourceDelegateMethodSymbol DiagnosticBag diagnostics) : base(delegateType, returnType, syntax, MethodKind.DelegateInvoke, DeclarationModifiers.Virtual | DeclarationModifiers.Public) { - this.refKind = refKind; + this._refKind = refKind; SyntaxToken arglistToken; var parameters = ParameterHelpers.MakeParameters( binder, this, syntax.ParameterList, out arglistToken, allowRefOrOut: true, allowThis: false, - addIsConstModifier: false, + addIsConstModifier: true, diagnostics: diagnostics); if (arglistToken.Kind() == SyntaxKind.ArgListKeyword) @@ -260,6 +261,16 @@ private sealed class InvokeMethod : SourceDelegateMethodSymbol diagnostics.Add(ErrorCode.ERR_IllegalVarArgs, new SourceLocation(arglistToken)); } + if (_refKind == RefKind.RefReadOnly) + { + var isConstType = binder.GetWellKnownType(WellKnownType.System_Runtime_CompilerServices_IsConst, diagnostics, syntax.ReturnType); + _refCustomModifiers = ImmutableArray.Create(CSharpCustomModifier.CreateRequired(isConstType)); + } + else + { + _refCustomModifiers = ImmutableArray.Empty; + } + InitializeParameters(parameters); } @@ -270,7 +281,7 @@ public override string Name internal override RefKind RefKind { - get { return refKind; } + get { return _refKind; } } internal override LexicalSortKey GetLexicalSortKey() @@ -288,7 +299,7 @@ internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, { base.AfterAddingTypeMembersChecks(conversions, diagnostics); - if (refKind == RefKind.RefReadOnly) + if (_refKind == RefKind.RefReadOnly) { var syntax = (DelegateDeclarationSyntax)SyntaxRef.GetSyntax(); DeclaringCompilation.EnsureIsReadOnlyAttributeExists(diagnostics, syntax.ReturnType.GetLocation(), modifyCompilationForRefReadOnly: true); @@ -296,6 +307,8 @@ internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, ParameterHelpers.EnsureIsReadOnlyAttributeExists(Parameters, diagnostics, modifyCompilationForRefReadOnly: true); } + + public override ImmutableArray RefCustomModifiers => _refCustomModifiers; } private sealed class BeginInvokeMethod : SourceDelegateMethodSymbol diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs index 8460874d9bd123a7e2bd828fe803113c8043ab2e..3c0d0250f3efc7ef2243e5588b84431a25659817 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs @@ -326,7 +326,7 @@ private void MethodChecks(MethodDeclarationSyntax syntax, Binder withTypeParamsB out _lazyParameters, alsoCopyParamsModifier: true); } } - else if (_refKind == RefKind.RefReadOnly && (IsVirtual || IsAbstract)) + else if (_refKind == RefKind.RefReadOnly) { var isConstType = withTypeParamsBinder.GetWellKnownType(WellKnownType.System_Runtime_CompilerServices_IsConst, diagnostics, syntax.ReturnType); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs index c1a2b82ed9db7361e530c9d311a62af195c0d491..35213211ec9c840136f117a639b0de889d716a10 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs @@ -273,7 +273,7 @@ internal sealed class SourcePropertySymbol : PropertySymbol, IAttributeTargetSym _lazyParameters = CustomModifierUtils.CopyParameterCustomModifiers(overriddenOrImplementedProperty.Parameters, _lazyParameters, alsoCopyParamsModifier: isOverride); } } - else if (_refKind == RefKind.RefReadOnly && (IsVirtual || IsAbstract)) + else if (_refKind == RefKind.RefReadOnly) { var isConstType = bodyBinder.GetWellKnownType(WellKnownType.System_Runtime_CompilerServices_IsConst, diagnostics, syntax.Type); diff --git a/src/Compilers/CSharp/Test/Emit/Emit/IsConstModifierTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/IsConstModifierTests.cs index 3a29a81b36845c05e4291699617ca363e1b52fc7..6fb91b0ee6387af88a843cdde7619cbbc3a7be51 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/IsConstModifierTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/IsConstModifierTests.cs @@ -3,15 +3,190 @@ using System.Collections.Immutable; using System.Linq; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; -using Xunit; using Microsoft.CodeAnalysis.Test.Utilities; +using Xunit; namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Emit { public class IsConstModifierTests : CSharpTestBase { [Fact] - public void IsConstModReqIsConsumedInRefCustomModifiersPosition_Methods_Parameters() + public void IsConstModReqIsConsumedInRefCustomModifiersPosition_Code_Methods_Parameters() + { + var reference = CreateStandardCompilation(@" +public class TestRef +{ + public void M(ref readonly int p) + { + System.Console.WriteLine(p); + } +}").EmitToImageReference(); + + var code = @" +public class Test +{ + public static void Main() + { + int value = 5; + var obj = new TestRef(); + obj.M(value); + } +}"; + + CompileAndVerify(code, additionalRefs: new[] { reference }, expectedOutput: "5"); + } + + [Fact] + public void IsConstModReqIsConsumedInRefCustomModifiersPosition_Code_Methods_ReturnTypes() + { + var reference = CreateStandardCompilation(@" +public class TestRef +{ + private int value = 5; + public ref readonly int M() + { + return ref value; + } +}").EmitToImageReference(); + + var code = @" +public class Test +{ + public static void Main() + { + var obj = new TestRef(); + System.Console.WriteLine(obj.M()); + } +}"; + + CompileAndVerify(code, additionalRefs: new[] { reference }, expectedOutput: "5"); + } + + [Fact] + public void IsConstModReqIsConsumedInRefCustomModifiersPosition_Code_Properties() + { + var reference = CreateStandardCompilation(@" +public class TestRef +{ + private int value = 5; + public ref readonly int P => ref value; +}").EmitToImageReference(); + + var code = @" +public class Test +{ + public static void Main() + { + var obj = new TestRef(); + System.Console.WriteLine(obj.P); + } +}"; + + CompileAndVerify(code, additionalRefs: new[] { reference }, expectedOutput: "5"); + } + + [Fact] + public void IsConstModReqIsConsumedInRefCustomModifiersPosition_Code_Indexers_Parameters() + { + var reference = CreateStandardCompilation(@" +public class TestRef +{ + public int this[ref readonly int p] + { + set { System.Console.WriteLine(p); } + } +}").EmitToImageReference(); + + var code = @" +public class Test +{ + public static void Main() + { + int value = 5; + var obj = new TestRef(); + obj[value] = 0; + } +}"; + + CompileAndVerify(code, additionalRefs: new[] { reference }, expectedOutput: "5"); + } + + [Fact] + public void IsConstModReqIsConsumedInRefCustomModifiersPosition_Code_Indexers_ReturnTypes() + { + var reference = CreateStandardCompilation(@" +public class TestRef +{ + private int value = 5; + public ref readonly int this[int p] => ref value; +}").EmitToImageReference(); + + var code = @" +public class Test +{ + public static void Main() + { + var obj = new TestRef(); + System.Console.WriteLine(obj[0]); + } +}"; + + CompileAndVerify(code, additionalRefs: new[] { reference }, expectedOutput: "5"); + } + + [Fact] + public void IsConstModReqIsConsumedInRefCustomModifiersPosition_Code_Delegates_Parameters() + { + var reference = CreateStandardCompilation(@" +public delegate void D(ref readonly int p); +").EmitToImageReference(); + + var code = @" +public class Test +{ + public static void Main() + { + Process((ref readonly int p) => System.Console.WriteLine(p)); + } + + private static void Process(D func) + { + int value = 5; + func(value); + } +}"; + + CompileAndVerify(code, additionalRefs: new[] { reference }, expectedOutput: "5"); + } + + [Fact] + public void IsConstModReqIsConsumedInRefCustomModifiersPosition_Code_Delegates_ReturnTypes() + { + var reference = CreateStandardCompilation(@" +public delegate ref readonly int D(); +").EmitToImageReference(); + + var code = @" +public class Test +{ + private static int value = 5; + + public static void Main() + { + Process(() => ref value); + } + + private static void Process(D func) + { + System.Console.WriteLine(func()); + } +}"; + + CompileAndVerify(code, additionalRefs: new[] { reference }, expectedOutput: "5"); + } + + [Fact] + public void IsConstModReqIsConsumedInRefCustomModifiersPosition_IL_Methods_Parameters() { var ilSource = IsReadOnlyAttributeIL + @" .class public auto ansi beforefieldinit TestRef @@ -60,7 +235,7 @@ public static void Main() } [Fact] - public void IsConstModReqIsConsumedInRefCustomModifiersPosition_Methods_ReturnTypes() + public void IsConstModReqIsConsumedInRefCustomModifiersPosition_IL_Methods_ReturnTypes() { var ilSource = IsReadOnlyAttributeIL + @" .class public auto ansi beforefieldinit TestRef @@ -113,17 +288,74 @@ public static void Main() } [Fact] - public void IsConstModReqIsNotAllowedInCustomModifiersPosition_Methods_Parameters() + public void IsConstModReqIsConsumedInRefCustomModifiersPosition_IL_Properties() { var ilSource = IsReadOnlyAttributeIL + @" .class public auto ansi beforefieldinit TestRef extends [mscorlib]System.Object { - .method public hidebysig newslot virtual - instance void M(int32 modreq([mscorlib]System.Runtime.CompilerServices.IsConst)& x) cil managed + .field private int32 'value' + .method public hidebysig newslot specialname virtual + instance int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst) + get_P() cil managed + { + .param [0] + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldflda int32 TestRef::'value' + IL_0006: ret + } + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldc.i4.5 + IL_0002: stfld int32 TestRef::'value' + IL_0007: ldarg.0 + IL_0008: call instance void [mscorlib]System.Object::.ctor() + IL_000d: nop + IL_000e: ret + } + + .property instance int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst) + P() + { + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + .get instance int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst) TestRef::get_P() + } +}"; + + var reference = CompileIL(ilSource, prependDefaultHeader: false); + + var code = @" +public class Test +{ + public static void Main() + { + var obj = new TestRef(); + System.Console.WriteLine(obj.P); + } +}"; + + CompileAndVerify(code, additionalRefs: new[] { reference }, expectedOutput: "5"); + } + + [Fact] + public void IsConstModReqIsConsumedInRefCustomModifiersPosition_IL_Indexers_Parameters() + { + var ilSource = IsReadOnlyAttributeIL + @" +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string) = ( 01 00 04 49 74 65 6D 00 00 ) + .method public hidebysig newslot specialname virtual + instance void set_Item(int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst) p, int32 'value') cil managed { .param [1] - .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) .maxstack 8 IL_0000: nop IL_0001: ldarg.1 @@ -133,16 +365,19 @@ .maxstack 8 IL_0009: ret } - .method public hidebysig specialname rtspecialname - instance void .ctor() cil managed + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { - // Code size 8 (0x8) .maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Object::.ctor() IL_0006: nop IL_0007: ret } + + .property instance int32 Item(int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst)) + { + .set instance void TestRef::set_Item(int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst), int32) + } }"; var reference = CompileIL(ilSource, prependDefaultHeader: false); @@ -154,30 +389,28 @@ public static void Main() { int value = 5; var obj = new TestRef(); - obj.M(value); + obj[value] = 0; } }"; - CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( - // (8,13): error CS0570: 'TestRef.M(in ?)' is not supported by the language - // obj.M(value); - Diagnostic(ErrorCode.ERR_BindToBogus, "M").WithArguments("TestRef.M(in ?)").WithLocation(8, 13)); + CompileAndVerify(code, additionalRefs: new[] { reference }, expectedOutput: "5"); } [Fact] - public void IsConstModReqIsNotAllowedInCustomModifiersPosition_Methods_ReturnTypes() + public void IsConstModReqIsConsumedInRefCustomModifiersPosition_IL_Indexers_ReturnTypes() { var ilSource = IsReadOnlyAttributeIL + @" .class public auto ansi beforefieldinit TestRef extends [mscorlib]System.Object { + .custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string) = ( 01 00 04 49 74 65 6D 00 00 ) .field private int32 'value' - .method public hidebysig newslot virtual - instance int32 modreq([mscorlib]System.Runtime.CompilerServices.IsConst) & - M() cil managed + .method public hidebysig newslot specialname virtual + instance int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst) + get_Item(int32 p) cil managed { .param [0] - .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) .maxstack 1 .locals init (int32& V_0) IL_0000: nop @@ -200,6 +433,12 @@ .maxstack 8 IL_000d: nop IL_000e: ret } + + .property instance int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst) Item(int32) + { + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + .get instance int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst) TestRef::get_Item(int32) + } }"; var reference = CompileIL(ilSource, prependDefaultHeader: false); @@ -210,46 +449,44 @@ public class Test public static void Main() { var obj = new TestRef(); - System.Console.WriteLine(obj.M()); + System.Console.WriteLine(obj[0]); } }"; - CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( - // (7,38): error CS0570: 'TestRef.M()' is not supported by the language - // System.Console.WriteLine(obj.M()); - Diagnostic(ErrorCode.ERR_BindToBogus, "M").WithArguments("TestRef.M()").WithLocation(7, 38)); + CompileAndVerify(code, additionalRefs: new[] { reference }, expectedOutput: "5"); } [Fact] - public void OtherModReqsAreNotAllowedOnRefCustomModifiersForRefReadOnlySignatures_Methods_Parameters() + public void IsConstModReqIsConsumedInRefCustomModifiersPosition_IL_Delegates_Parameters() { var ilSource = IsReadOnlyAttributeIL + @" -.class public auto ansi beforefieldinit TestRef - extends [mscorlib]System.Object +.class public auto ansi sealed D + extends [mscorlib]System.MulticastDelegate { - .method public hidebysig newslot virtual - instance void M(int32& modreq([mscorlib]System.Runtime.CompilerServices.IsReadOnlyAttribute) x) cil managed + .method public hidebysig specialname rtspecialname + instance void .ctor(object 'object', native int 'method') runtime managed + { + } + + .method public hidebysig newslot virtual instance void Invoke(int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst) p) runtime managed { .param [1] - .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) - .maxstack 8 - IL_0000: nop - IL_0001: ldarg.1 - IL_0002: ldind.i4 - IL_0003: call void [mscorlib]System.Console::WriteLine(int32) - IL_0008: nop - IL_0009: ret + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) } - .method public hidebysig specialname rtspecialname - instance void .ctor() cil managed + .method public hidebysig newslot virtual + instance class [mscorlib]System.IAsyncResult + BeginInvoke(int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst) p, class [mscorlib]System.AsyncCallback callback, object 'object') runtime managed { - // Code size 8 (0x8) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void [mscorlib]System.Object::.ctor() - IL_0006: nop - IL_0007: ret + .param [1] + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + } + + .method public hidebysig newslot virtual + instance void EndInvoke(int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst) p, class [mscorlib]System.IAsyncResult result) runtime managed + { + .param [1] + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) } }"; @@ -259,134 +496,2038 @@ .maxstack 8 public class Test { public static void Main() + { + Process((ref readonly int p) => System.Console.WriteLine(p)); + } + + private static void Process(D func) { int value = 5; - var obj = new TestRef(); - obj.M(value); + func(value); } }"; - CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( - // (8,13): error CS0570: 'TestRef.M(?)' is not supported by the language - // obj.M(value); - Diagnostic(ErrorCode.ERR_BindToBogus, "M").WithArguments("TestRef.M(?)").WithLocation(8, 13)); + CompileAndVerify(code, additionalRefs: new[] { reference }, expectedOutput: "5"); } [Fact] - public void ProperErrorsArePropagatedIfMscorlibIsConstIsNotAvailable_Methods_Parameters() + public void IsConstModReqIsConsumedInRefCustomModifiersPosition_IL_Delegates_ReturnTypes() { - var code = @" -namespace System -{ - public class Object {} - public class Void {} -} -class Test + var ilSource = IsReadOnlyAttributeIL + @" +.class public auto ansi sealed D + extends [mscorlib]System.MulticastDelegate { - public virtual void M(ref readonly object x) { } -}"; + .method public hidebysig specialname rtspecialname + instance void .ctor(object 'object', native int 'method') runtime managed + { + } - CreateCompilation(code).VerifyDiagnostics( - // (9,27): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsConst' is not defined or imported + .method public hidebysig newslot virtual instance int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst) Invoke() runtime managed + { + .param [0] + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + } + + .method public hidebysig newslot virtual + instance class [mscorlib]System.IAsyncResult + BeginInvoke(class [mscorlib]System.AsyncCallback callback, object 'object') runtime managed + { + } + + .method public hidebysig newslot virtual + instance int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst) EndInvoke(class [mscorlib]System.IAsyncResult result) runtime managed + { + .param [0] + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + } +}"; + + var reference = CompileIL(ilSource, prependDefaultHeader: false); + + var code = @" +public class Test +{ + private static int value = 5; + + public static void Main() + { + Process(() => ref value); + } + + private static void Process(D func) + { + System.Console.WriteLine(func()); + } +}"; + + CompileAndVerify(code, additionalRefs: new[] { reference }, expectedOutput: "5"); + } + + [Fact] + public void IsConstModReqIsNotAllowedInCustomModifiersPosition_Methods_Parameters() + { + var ilSource = IsReadOnlyAttributeIL + @" +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .method public hidebysig newslot virtual + instance void M(int32 modreq([mscorlib]System.Runtime.CompilerServices.IsConst)& x) cil managed + { + .param [1] + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldind.i4 + IL_0003: call void [mscorlib]System.Console::WriteLine(int32) + IL_0008: nop + IL_0009: ret + } + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } +}"; + + var reference = CompileIL(ilSource, prependDefaultHeader: false); + + var code = @" +public class Test +{ + public static void Main() + { + int value = 5; + var obj = new TestRef(); + obj.M(value); + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (8,13): error CS0570: 'TestRef.M(in ?)' is not supported by the language + // obj.M(value); + Diagnostic(ErrorCode.ERR_BindToBogus, "M").WithArguments("TestRef.M(in ?)").WithLocation(8, 13)); + } + + [Fact] + public void IsConstModReqIsNotAllowedInCustomModifiersPosition_Methods_ReturnTypes() + { + var ilSource = IsReadOnlyAttributeIL + @" +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .field private int32 'value' + .method public hidebysig newslot virtual + instance int32 modreq([mscorlib]System.Runtime.CompilerServices.IsConst) & + M() cil managed + { + .param [0] + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + .maxstack 1 + .locals init (int32& V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldflda int32 TestRef::'value' + IL_0007: stloc.0 + IL_0008: br.s IL_000a + IL_000a: ldloc.0 + IL_000b: ret + } + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldc.i4.5 + IL_0002: stfld int32 TestRef::'value' + IL_0007: ldarg.0 + IL_0008: call instance void [mscorlib]System.Object::.ctor() + IL_000d: nop + IL_000e: ret + } +}"; + + var reference = CompileIL(ilSource, prependDefaultHeader: false); + + var code = @" +public class Test +{ + public static void Main() + { + var obj = new TestRef(); + System.Console.WriteLine(obj.M()); + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (7,38): error CS0570: 'TestRef.M()' is not supported by the language + // System.Console.WriteLine(obj.M()); + Diagnostic(ErrorCode.ERR_BindToBogus, "M").WithArguments("TestRef.M()").WithLocation(7, 38)); + } + + [Fact] + public void IsConstModReqIsNotAllowedInCustomModifiersPosition_Properties() + { + var ilSource = IsReadOnlyAttributeIL + @" +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .field private int32 'value' + .method public hidebysig newslot specialname virtual + instance int32 modreq([mscorlib]System.Runtime.CompilerServices.IsConst) & + get_P() cil managed + { + .param [0] + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldflda int32 TestRef::'value' + IL_0006: ret + } + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldc.i4.5 + IL_0002: stfld int32 TestRef::'value' + IL_0007: ldarg.0 + IL_0008: call instance void [mscorlib]System.Object::.ctor() + IL_000d: nop + IL_000e: ret + } + + .property instance int32 modreq([mscorlib]System.Runtime.CompilerServices.IsConst) & + P() + { + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + .get instance int32 modreq([mscorlib]System.Runtime.CompilerServices.IsConst) & TestRef::get_P() + } +}"; + + var reference = CompileIL(ilSource, prependDefaultHeader: false); + + var code = @" +public class Test +{ + public static void Main() + { + var obj = new TestRef(); + System.Console.WriteLine(obj.P); + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (7,38): error CS1546: Property, indexer, or event 'TestRef.P' is not supported by the language; try directly calling accessor method 'TestRef.get_P()' + // System.Console.WriteLine(obj.P); + Diagnostic(ErrorCode.ERR_BindToBogusProp1, "P").WithArguments("TestRef.P", "TestRef.get_P()").WithLocation(7, 38)); + + code = @" +public class Test +{ + public static void Main() + { + var obj = new TestRef(); + System.Console.WriteLine(obj.get_P()); + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (7,38): error CS0570: 'TestRef.get_P()' is not supported by the language + // System.Console.WriteLine(obj.get_P()); + Diagnostic(ErrorCode.ERR_BindToBogus, "get_P").WithArguments("TestRef.get_P()").WithLocation(7, 38)); + } + + [Fact] + public void IsConstModReqIsNotAllowedInCustomModifiersPosition_Indexers_Parameters() + { + var ilSource = IsReadOnlyAttributeIL + @" +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string) = ( 01 00 04 49 74 65 6D 00 00 ) + .method public hidebysig newslot specialname virtual + instance void set_Item(int32 modreq([mscorlib]System.Runtime.CompilerServices.IsConst) & p, int32 'value') cil managed + { + .param [1] + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldind.i4 + IL_0003: call void [mscorlib]System.Console::WriteLine(int32) + IL_0008: nop + IL_0009: ret + } + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } + + .property instance int32 Item(int32 modreq([mscorlib]System.Runtime.CompilerServices.IsConst) &) + { + .set instance void TestRef::set_Item(int32 modreq([mscorlib]System.Runtime.CompilerServices.IsConst) &, int32) + } +}"; + + var reference = CompileIL(ilSource, prependDefaultHeader: false); + + var code = @" +public class Test +{ + public static void Main() + { + int value = 5; + var obj = new TestRef(); + obj[value] = 0; + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (8,9): error CS1546: Property, indexer, or event 'TestRef.this[in ?]' is not supported by the language; try directly calling accessor method 'TestRef.set_Item(in ?, ?)' + // obj[value] = 0; + Diagnostic(ErrorCode.ERR_BindToBogusProp1, "obj[value]").WithArguments("TestRef.this[in ?]", "TestRef.set_Item(in ?, ?)").WithLocation(8, 9)); + + code = @" +public class Test +{ + public static void Main() + { + int value = 5; + var obj = new TestRef(); + obj.set_Item(value, 0); + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (8,13): error CS0570: 'TestRef.set_Item(in ?, ?)' is not supported by the language + // obj.set_Item(value, 0); + Diagnostic(ErrorCode.ERR_BindToBogus, "set_Item").WithArguments("TestRef.set_Item(in ?, ?)").WithLocation(8, 13)); + } + + [Fact] + public void IsConstModReqIsNotAllowedInCustomModifiersPosition_Indexers_ReturnTypes() + { + var ilSource = IsReadOnlyAttributeIL + @" +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string) = ( 01 00 04 49 74 65 6D 00 00 ) + .field private int32 'value' + .method public hidebysig newslot specialname virtual + instance int32 modreq([mscorlib]System.Runtime.CompilerServices.IsConst) & + get_Item(int32 p) cil managed + { + .param [0] + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + .maxstack 1 + .locals init (int32& V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldflda int32 TestRef::'value' + IL_0007: stloc.0 + IL_0008: br.s IL_000a + IL_000a: ldloc.0 + IL_000b: ret + } + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldc.i4.5 + IL_0002: stfld int32 TestRef::'value' + IL_0007: ldarg.0 + IL_0008: call instance void [mscorlib]System.Object::.ctor() + IL_000d: nop + IL_000e: ret + } + + .property instance int32 modreq([mscorlib]System.Runtime.CompilerServices.IsConst) & Item(int32) + { + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + .get instance int32 modreq([mscorlib]System.Runtime.CompilerServices.IsConst) & TestRef::get_Item(int32) + } +}"; + + var reference = CompileIL(ilSource, prependDefaultHeader: false); + + var code = @" +public class Test +{ + public static void Main() + { + var obj = new TestRef(); + System.Console.WriteLine(obj[0]); + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (7,34): error CS1546: Property, indexer, or event 'TestRef.this[?]' is not supported by the language; try directly calling accessor method 'TestRef.get_Item(?)' + // System.Console.WriteLine(obj[0]); + Diagnostic(ErrorCode.ERR_BindToBogusProp1, "obj[0]").WithArguments("TestRef.this[?]", "TestRef.get_Item(?)").WithLocation(7, 34)); + + code = @" +public class Test +{ + public static void Main() + { + var obj = new TestRef(); + System.Console.WriteLine(obj.get_Item(0)); + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (7,38): error CS0570: 'TestRef.get_Item(?)' is not supported by the language + // System.Console.WriteLine(obj.get_Item(0)); + Diagnostic(ErrorCode.ERR_BindToBogus, "get_Item").WithArguments("TestRef.get_Item(?)").WithLocation(7, 38)); + } + + [Fact] + public void IsConstModReqIsNotAllowedInCustomModifiersPosition_Delegates_Parameters() + { + var ilSource = IsReadOnlyAttributeIL + @" +.class public auto ansi sealed D + extends [mscorlib]System.MulticastDelegate +{ + .method public hidebysig specialname rtspecialname + instance void .ctor(object 'object', native int 'method') runtime managed + { + } + + .method public hidebysig newslot virtual instance void Invoke(int32 modreq([mscorlib]System.Runtime.CompilerServices.IsConst) & p) runtime managed + { + .param [1] + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + } + + .method public hidebysig newslot virtual + instance class [mscorlib]System.IAsyncResult + BeginInvoke(int32 modreq([mscorlib]System.Runtime.CompilerServices.IsConst) & p, class [mscorlib]System.AsyncCallback callback, object 'object') runtime managed + { + .param [1] + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + } + + .method public hidebysig newslot virtual + instance void EndInvoke(int32 modreq([mscorlib]System.Runtime.CompilerServices.IsConst) & p, class [mscorlib]System.IAsyncResult result) runtime managed + { + .param [1] + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + } +}"; + + var reference = CompileIL(ilSource, prependDefaultHeader: false); + + var code = @" +public class Test +{ + public static void Main() + { + Process((ref readonly int p) => System.Console.WriteLine(p)); + } + + private static void Process(D func) + { + int value = 5; + func(value); + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (6,17): error CS0570: 'D.Invoke(in ?)' is not supported by the language + // Process((ref readonly int p) => System.Console.WriteLine(p)); + Diagnostic(ErrorCode.ERR_BindToBogus, "(ref readonly int p) => System.Console.WriteLine(p)").WithArguments("D.Invoke(in ?)").WithLocation(6, 17), + // (12,9): error CS0570: 'D.Invoke(in ?)' is not supported by the language + // func(value); + Diagnostic(ErrorCode.ERR_BindToBogus, "func(value)").WithArguments("D.Invoke(in ?)").WithLocation(12, 9)); + } + + [Fact] + public void IsConstModReqIsNotAllowedInCustomModifiersPosition_Delegates_ReturnTypes() + { + var ilSource = IsReadOnlyAttributeIL + @" +.class public auto ansi sealed D + extends [mscorlib]System.MulticastDelegate +{ + .method public hidebysig specialname rtspecialname + instance void .ctor(object 'object', native int 'method') runtime managed + { + } + + .method public hidebysig newslot virtual instance int32 modreq([mscorlib]System.Runtime.CompilerServices.IsConst) & Invoke() runtime managed + { + .param [0] + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + } + + .method public hidebysig newslot virtual + instance class [mscorlib]System.IAsyncResult + BeginInvoke(class [mscorlib]System.AsyncCallback callback, object 'object') runtime managed + { + } + + .method public hidebysig newslot virtual + instance int32 modreq([mscorlib]System.Runtime.CompilerServices.IsConst) & EndInvoke(class [mscorlib]System.IAsyncResult result) runtime managed + { + .param [0] + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + } +}"; + + var reference = CompileIL(ilSource, prependDefaultHeader: false); + + var code = @" +public class Test +{ + private static int value = 5; + + public static void Main() + { + Process(() => ref value); + } + + private static void Process(D func) + { + System.Console.WriteLine(func()); + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (8,17): error CS0570: 'D.Invoke()' is not supported by the language + // Process(() => ref value); + Diagnostic(ErrorCode.ERR_BindToBogus, "() => ref value").WithArguments("D.Invoke()").WithLocation(8, 17), + // (13,34): error CS0570: 'D.Invoke()' is not supported by the language + // System.Console.WriteLine(func()); + Diagnostic(ErrorCode.ERR_BindToBogus, "func()").WithArguments("D.Invoke()").WithLocation(13, 34)); + } + + [Fact] + public void OtherModReqsAreNotAllowedOnRefCustomModifiersForRefReadOnlySignatures_Methods_Parameters() + { + var ilSource = IsReadOnlyAttributeIL + @" +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .method public hidebysig newslot virtual + instance void M(int32& modreq([mscorlib]System.Runtime.CompilerServices.IsReadOnlyAttribute) x) cil managed + { + .param [1] + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldind.i4 + IL_0003: call void [mscorlib]System.Console::WriteLine(int32) + IL_0008: nop + IL_0009: ret + } + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } +}"; + + var reference = CompileIL(ilSource, prependDefaultHeader: false); + + var code = @" +public class Test +{ + public static void Main() + { + int value = 5; + var obj = new TestRef(); + obj.M(value); + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (8,13): error CS0570: 'TestRef.M(?)' is not supported by the language + // obj.M(value); + Diagnostic(ErrorCode.ERR_BindToBogus, "M").WithArguments("TestRef.M(?)").WithLocation(8, 13)); + } + + [Fact] + public void OtherModReqsAreNotAllowedOnRefCustomModifiersForRefReadOnlySignatures_Methods_ReturnTypes() + { + var ilSource = IsReadOnlyAttributeIL + @" +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .field private int32 'value' + .method public hidebysig newslot virtual + instance int32& modreq([mscorlib]System.Runtime.CompilerServices.IsReadOnlyAttribute) + M() cil managed + { + .param [0] + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + .maxstack 1 + .locals init (int32& V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldflda int32 TestRef::'value' + IL_0007: stloc.0 + IL_0008: br.s IL_000a + IL_000a: ldloc.0 + IL_000b: ret + } + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldc.i4.5 + IL_0002: stfld int32 TestRef::'value' + IL_0007: ldarg.0 + IL_0008: call instance void [mscorlib]System.Object::.ctor() + IL_000d: nop + IL_000e: ret + } +}"; + + var reference = CompileIL(ilSource, prependDefaultHeader: false); + + var code = @" +public class Test +{ + public static void Main() + { + var obj = new TestRef(); + System.Console.WriteLine(obj.M()); + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (7,38): error CS0570: 'TestRef.M()' is not supported by the language + // System.Console.WriteLine(obj.M()); + Diagnostic(ErrorCode.ERR_BindToBogus, "M").WithArguments("TestRef.M()").WithLocation(7, 38)); + } + + [Fact] + public void OtherModReqsAreNotAllowedOnRefCustomModifiersForRefReadOnlySignatures_Properties() + { + var ilSource = IsReadOnlyAttributeIL + @" +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .field private int32 'value' + .method public hidebysig newslot specialname virtual + instance int32& modreq([mscorlib]System.Runtime.CompilerServices.IsReadOnlyAttribute) + get_P() cil managed + { + .param [0] + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldflda int32 TestRef::'value' + IL_0006: ret + } + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldc.i4.5 + IL_0002: stfld int32 TestRef::'value' + IL_0007: ldarg.0 + IL_0008: call instance void [mscorlib]System.Object::.ctor() + IL_000d: nop + IL_000e: ret + } + + .property instance int32& modreq([mscorlib]System.Runtime.CompilerServices.IsReadOnlyAttribute) + P() + { + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + .get instance int32& modreq([mscorlib]System.Runtime.CompilerServices.IsReadOnlyAttribute) TestRef::get_P() + } +}"; + + var reference = CompileIL(ilSource, prependDefaultHeader: false); + + var code = @" +public class Test +{ + public static void Main() + { + var obj = new TestRef(); + System.Console.WriteLine(obj.P); + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (7,38): error CS1546: Property, indexer, or event 'TestRef.P' is not supported by the language; try directly calling accessor method 'TestRef.get_P()' + // System.Console.WriteLine(obj.P); + Diagnostic(ErrorCode.ERR_BindToBogusProp1, "P").WithArguments("TestRef.P", "TestRef.get_P()").WithLocation(7, 38)); + + code = @" +public class Test +{ + public static void Main() + { + var obj = new TestRef(); + System.Console.WriteLine(obj.get_P()); + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (7,38): error CS0570: 'TestRef.get_P()' is not supported by the language + // System.Console.WriteLine(obj.get_P()); + Diagnostic(ErrorCode.ERR_BindToBogus, "get_P").WithArguments("TestRef.get_P()").WithLocation(7, 38)); + } + + [Fact] + public void OtherModReqsAreNotAllowedOnRefCustomModifiersForRefReadOnlySignatures_Indexers_Parameters() + { + var ilSource = IsReadOnlyAttributeIL + @" +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string) = ( 01 00 04 49 74 65 6D 00 00 ) + .method public hidebysig newslot specialname virtual + instance void set_Item(int32& modreq([mscorlib]System.Runtime.CompilerServices.IsReadOnlyAttribute) p, int32 'value') cil managed + { + .param [1] + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldind.i4 + IL_0003: call void [mscorlib]System.Console::WriteLine(int32) + IL_0008: nop + IL_0009: ret + } + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } + + .property instance int32 Item(int32& modreq([mscorlib]System.Runtime.CompilerServices.IsReadOnlyAttribute)) + { + .set instance void TestRef::set_Item(int32& modreq([mscorlib]System.Runtime.CompilerServices.IsReadOnlyAttribute), int32) + } +}"; + + var reference = CompileIL(ilSource, prependDefaultHeader: false); + + var code = @" +public class Test +{ + public static void Main() + { + int value = 5; + var obj = new TestRef(); + obj[value] = 0; + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (8,9): error CS1546: Property, indexer, or event 'TestRef.this[?]' is not supported by the language; try directly calling accessor method 'TestRef.set_Item(?, ?)' + // obj[value] = 0; + Diagnostic(ErrorCode.ERR_BindToBogusProp1, "obj[value]").WithArguments("TestRef.this[?]", "TestRef.set_Item(?, ?)").WithLocation(8, 9)); + + code = @" +public class Test +{ + public static void Main() + { + int value = 5; + var obj = new TestRef(); + obj.set_Item(value, 0); + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (8,13): error CS0570: 'TestRef.set_Item(?, ?)' is not supported by the language + // obj.set_Item(value, 0); + Diagnostic(ErrorCode.ERR_BindToBogus, "set_Item").WithArguments("TestRef.set_Item(?, ?)").WithLocation(8, 13)); + } + + [Fact] + public void OtherModReqsAreNotAllowedOnRefCustomModifiersForRefReadOnlySignatures_Indexers_ReturnTypes() + { + var ilSource = IsReadOnlyAttributeIL + @" +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string) = ( 01 00 04 49 74 65 6D 00 00 ) + .field private int32 'value' + .method public hidebysig newslot specialname virtual + instance int32& modreq([mscorlib]System.Runtime.CompilerServices.IsReadOnlyAttribute) + get_Item(int32 p) cil managed + { + .param [0] + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + .maxstack 1 + .locals init (int32& V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldflda int32 TestRef::'value' + IL_0007: stloc.0 + IL_0008: br.s IL_000a + IL_000a: ldloc.0 + IL_000b: ret + } + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldc.i4.5 + IL_0002: stfld int32 TestRef::'value' + IL_0007: ldarg.0 + IL_0008: call instance void [mscorlib]System.Object::.ctor() + IL_000d: nop + IL_000e: ret + } + + .property instance int32& modreq([mscorlib]System.Runtime.CompilerServices.IsReadOnlyAttribute) Item(int32) + { + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + .get instance int32& modreq([mscorlib]System.Runtime.CompilerServices.IsReadOnlyAttribute) TestRef::get_Item(int32) + } +}"; + + var reference = CompileIL(ilSource, prependDefaultHeader: false); + + var code = @" +public class Test +{ + public static void Main() + { + var obj = new TestRef(); + System.Console.WriteLine(obj[0]); + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (7,34): error CS1546: Property, indexer, or event 'TestRef.this[?]' is not supported by the language; try directly calling accessor method 'TestRef.get_Item(?)' + // System.Console.WriteLine(obj[0]); + Diagnostic(ErrorCode.ERR_BindToBogusProp1, "obj[0]").WithArguments("TestRef.this[?]", "TestRef.get_Item(?)").WithLocation(7, 34)); + + code = @" +public class Test +{ + public static void Main() + { + var obj = new TestRef(); + System.Console.WriteLine(obj.get_Item(0)); + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (7,38): error CS0570: 'TestRef.get_Item(?)' is not supported by the language + // System.Console.WriteLine(obj.get_Item(0)); + Diagnostic(ErrorCode.ERR_BindToBogus, "get_Item").WithArguments("TestRef.get_Item(?)").WithLocation(7, 38)); + } + + [Fact] + public void OtherModReqsAreNotAllowedOnRefCustomModifiersForRefReadOnlySignatures_Delegates_Parameters() + { + var ilSource = IsReadOnlyAttributeIL + @" +.class public auto ansi sealed D + extends [mscorlib]System.MulticastDelegate +{ + .method public hidebysig specialname rtspecialname + instance void .ctor(object 'object', native int 'method') runtime managed + { + } + + .method public hidebysig newslot virtual instance void Invoke(int32& modreq([mscorlib]System.Runtime.CompilerServices.IsReadOnlyAttribute) p) runtime managed + { + .param [1] + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + } + + .method public hidebysig newslot virtual + instance class [mscorlib]System.IAsyncResult + BeginInvoke(int32& modreq([mscorlib]System.Runtime.CompilerServices.IsReadOnlyAttribute) p, class [mscorlib]System.AsyncCallback callback, object 'object') runtime managed + { + .param [1] + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + } + + .method public hidebysig newslot virtual + instance void EndInvoke(int32& modreq([mscorlib]System.Runtime.CompilerServices.IsReadOnlyAttribute) p, class [mscorlib]System.IAsyncResult result) runtime managed + { + .param [1] + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + } +}"; + + var reference = CompileIL(ilSource, prependDefaultHeader: false); + + var code = @" +public class Test +{ + public static void Main() + { + Process((ref readonly int p) => System.Console.WriteLine(p)); + } + + private static void Process(D func) + { + int value = 5; + func(value); + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (6,17): error CS0570: 'D.Invoke(?)' is not supported by the language + // Process((ref readonly int p) => System.Console.WriteLine(p)); + Diagnostic(ErrorCode.ERR_BindToBogus, "(ref readonly int p) => System.Console.WriteLine(p)").WithArguments("D.Invoke(?)").WithLocation(6, 17), + // (12,9): error CS0570: 'D.Invoke(?)' is not supported by the language + // func(value); + Diagnostic(ErrorCode.ERR_BindToBogus, "func(value)").WithArguments("D.Invoke(?)").WithLocation(12, 9)); + } + + [Fact] + public void OtherModReqsAreNotAllowedOnRefCustomModifiersForRefReadOnlySignatures_Delegates_ReturnTypes() + { + var ilSource = IsReadOnlyAttributeIL + @" +.class public auto ansi sealed D + extends [mscorlib]System.MulticastDelegate +{ + .method public hidebysig specialname rtspecialname + instance void .ctor(object 'object', native int 'method') runtime managed + { + } + + .method public hidebysig newslot virtual instance int32& modreq([mscorlib]System.Runtime.CompilerServices.IsReadOnlyAttribute) Invoke() runtime managed + { + .param [0] + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + } + + .method public hidebysig newslot virtual + instance class [mscorlib]System.IAsyncResult + BeginInvoke(class [mscorlib]System.AsyncCallback callback, object 'object') runtime managed + { + } + + .method public hidebysig newslot virtual + instance int32& modreq([mscorlib]System.Runtime.CompilerServices.IsReadOnlyAttribute) EndInvoke(class [mscorlib]System.IAsyncResult result) runtime managed + { + .param [0] + .custom instance void System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + } +}"; + + var reference = CompileIL(ilSource, prependDefaultHeader: false); + + var code = @" +public class Test +{ + private static int value = 5; + + public static void Main() + { + Process(() => ref value); + } + + private static void Process(D func) + { + System.Console.WriteLine(func()); + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (8,17): error CS0570: 'D.Invoke()' is not supported by the language + // Process(() => ref value); + Diagnostic(ErrorCode.ERR_BindToBogus, "() => ref value").WithArguments("D.Invoke()").WithLocation(8, 17), + // (13,34): error CS0570: 'D.Invoke()' is not supported by the language + // System.Console.WriteLine(func()); + Diagnostic(ErrorCode.ERR_BindToBogus, "func()").WithArguments("D.Invoke()").WithLocation(13, 34)); + } + + [Fact] + public void ProperErrorsArePropagatedIfMscorlibIsConstIsNotAvailable_Methods_Parameters() + { + var code = @" +namespace System +{ + public class Object {} + public class Void {} +} +class Test +{ + public virtual void M(ref readonly object x) { } +}"; + + CreateCompilation(code).VerifyDiagnostics( + // (9,27): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsConst' is not defined or imported // public virtual void M(ref readonly object x) { } Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "ref readonly object x").WithArguments("System.Runtime.CompilerServices.IsConst").WithLocation(9, 27)); } [Fact] - public void ProperErrorsArePropagatedIfMscorlibIsConstIsNotAvailable_Methods_ReturnTypes() + public void ProperErrorsArePropagatedIfMscorlibIsConstIsNotAvailable_Methods_ReturnTypes() + { + var code = @" +namespace System +{ + public class Object {} + public class Void {} +} +class Test +{ + private object value = null; + public virtual ref readonly object M() => ref value; +}"; + + CreateCompilation(code).VerifyDiagnostics( + // (10,20): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsConst' is not defined or imported + // public virtual ref readonly object M() => ref value; + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "ref readonly object").WithArguments("System.Runtime.CompilerServices.IsConst").WithLocation(10, 20)); + } + + [Fact] + public void ProperErrorsArePropagatedIfMscorlibIsConstIsNotAvailable_Properties() + { + var code = @" +namespace System +{ + public class Object {} + public class Void {} +} +class Test +{ + private object value = null; + public virtual ref readonly object M => ref value; +}"; + + CreateCompilation(code).VerifyDiagnostics( + // (10,20): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsConst' is not defined or imported + // public virtual ref readonly object M => ref value; + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "ref readonly object").WithArguments("System.Runtime.CompilerServices.IsConst").WithLocation(10, 20)); + } + + [Fact] + public void ProperErrorsArePropagatedIfMscorlibIsConstIsNotAvailable_Indexers_Parameters() + { + var code = @" +namespace System +{ + public class Object {} + public class Void {} +} +class Test +{ + public virtual object this[ref readonly object p] => null; +}"; + + CreateCompilation(code).VerifyDiagnostics( + // (9,32): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsConst' is not defined or imported + // public virtual object this[ref readonly object p] => null; + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "ref readonly object p").WithArguments("System.Runtime.CompilerServices.IsConst").WithLocation(9, 32)); + } + + [Fact] + public void ProperErrorsArePropagatedIfMscorlibIsConstIsNotAvailable_Indexers_ReturnTypes() + { + var code = @" +namespace System +{ + public class Object {} + public class Void {} +} +class Test +{ + private object value = null; + public virtual ref readonly object this[object p] => ref value; +}"; + + CreateCompilation(code).VerifyDiagnostics( + // (10,20): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsConst' is not defined or imported + // public virtual ref readonly object this[object p] => ref value; + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "ref readonly object").WithArguments("System.Runtime.CompilerServices.IsConst").WithLocation(10, 20)); + } + + [Fact] + public void ProperErrorsArePropagatedIfMscorlibIsConstIsNotAvailable_Delegates_Parameters() + { + var code = @" +namespace System +{ + public class Object {} + public class Void {} + public class IntPtr {} + public class Int32 {} + public class Delegate {} + public class MulticastDelegate : Delegate {} +} +public delegate void D(ref readonly int p);"; + + CreateCompilation(code).VerifyDiagnostics( + // (11,24): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsConst' is not defined or imported + // public delegate void D(ref readonly int p); + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "ref readonly int p").WithArguments("System.Runtime.CompilerServices.IsConst").WithLocation(11, 24)); + } + + [Fact] + public void ProperErrorsArePropagatedIfMscorlibIsConstIsNotAvailable_Delegates_ReturnTypes() + { + var code = @" +namespace System +{ + public class Object {} + public class Void {} + public class IntPtr {} + public class Int32 {} + public class Delegate {} + public class MulticastDelegate : Delegate {} +} +public delegate ref readonly int D();"; + + CreateCompilation(code).VerifyDiagnostics( + // (11,17): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsConst' is not defined or imported + // public delegate ref readonly int D(); + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "ref readonly int").WithArguments("System.Runtime.CompilerServices.IsConst").WithLocation(11, 17)); + } + + [Fact] + public void IsConstIsWrittenOnRefReadOnlyMembers_Methods_Parameters_Virtual() + { + var code = @" +class Test +{ + public virtual void Method(ref readonly int x) { } +}"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("Method").Parameters.Single(); + + Assert.Empty(parameter.CustomModifiers); + AssertSingleIsConstRequiredModifier(parameter.RefCustomModifiers); + }); + } + + [Fact] + public void IsConstIsWrittenOnRefReadOnlyMembers_Methods_Parameters_Abstract() + { + var code = @" +abstract class Test +{ + public abstract void Method(ref readonly int x); +}"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("Method").Parameters.Single(); + + Assert.Empty(parameter.CustomModifiers); + AssertSingleIsConstRequiredModifier(parameter.RefCustomModifiers); + }); + } + + [Fact] + public void IsConstIsWrittenOnRefReadOnlyMembers_Methods_ReturnTypes_Virtual() + { + var code = @" +class Test +{ + private int x = 0; + public virtual ref readonly int Method() => ref x; +}"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var method = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("Method"); + + Assert.Empty(method.ReturnTypeCustomModifiers); + AssertSingleIsConstRequiredModifier(method.RefCustomModifiers); + }); + } + + [Fact] + public void IsConstIsWrittenOnRefReadOnlyMembers_Methods_ReturnTypes_Abstract() + { + var code = @" +abstract class Test +{ + public abstract ref readonly int Method(); +}"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var method = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("Method"); + + Assert.Empty(method.ReturnTypeCustomModifiers); + AssertSingleIsConstRequiredModifier(method.RefCustomModifiers); + }); + } + + [Fact] + public void IsConstIsWrittenOnRefReadOnlyMembers_Methods_ReturnTypes_NoModifiers() + { + var code = @" +class Test +{ + private int x = 0; + public ref readonly int Method() => ref x; +}"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var method = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("Method"); + + Assert.Empty(method.ReturnTypeCustomModifiers); + AssertSingleIsConstRequiredModifier(method.RefCustomModifiers); + }); + } + + [Fact] + public void IsConstIsWrittenOnRefReadOnlyMembers_Methods_ReturnTypes_Static() + { + var code = @" +class Test +{ + private static int x = 0; + public static ref readonly int Method() => ref x; +}"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var method = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("Method"); + + Assert.Empty(method.ReturnTypeCustomModifiers); + AssertSingleIsConstRequiredModifier(method.RefCustomModifiers); + }); + } + + [Fact] + public void IsConstIsWrittenOnRefReadOnlyMembers_Properties_Virtual() + { + var code = @" +class Test +{ + private int x = 0; + public virtual ref readonly int Property => ref x; +}"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var property = module.ContainingAssembly.GetTypeByMetadataName("Test").GetProperty("Property"); + + Assert.Empty(property.TypeCustomModifiers); + AssertSingleIsConstRequiredModifier(property.RefCustomModifiers); + }); + } + + [Fact] + public void IsConstIsWrittenOnRefReadOnlyMembers_Properties_Abstract() + { + var code = @" +abstract class Test +{ + public abstract ref readonly int Property { get; } +}"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var property = module.ContainingAssembly.GetTypeByMetadataName("Test").GetProperty("Property"); + + Assert.Empty(property.TypeCustomModifiers); + AssertSingleIsConstRequiredModifier(property.RefCustomModifiers); + }); + } + + [Fact] + public void IsConstIsWrittenOnRefReadOnlyMembers_Properties_NoModifiers() + { + var code = @" +class Test +{ + private int x = 0; + public ref readonly int Property => ref x; +}"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var property = module.ContainingAssembly.GetTypeByMetadataName("Test").GetProperty("Property"); + + Assert.Empty(property.TypeCustomModifiers); + AssertSingleIsConstRequiredModifier(property.RefCustomModifiers); + }); + } + + [Fact] + public void IsConstIsWrittenOnRefReadOnlyMembers_Properties_Static() + { + var code = @" +class Test +{ + private static int x = 0; + public static ref readonly int Property => ref x; +}"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var property = module.ContainingAssembly.GetTypeByMetadataName("Test").GetProperty("Property"); + + Assert.Empty(property.TypeCustomModifiers); + AssertSingleIsConstRequiredModifier(property.RefCustomModifiers); + }); + } + + [Fact] + public void IsConstIsWrittenOnRefReadOnlyMembers_Indexers_Parameters_Virtual() + { + var code = @" +class Test +{ + public virtual int this[ref readonly int x] => x; +}"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetProperty("this[]").Parameters.Single(); + + Assert.Empty(parameter.CustomModifiers); + AssertSingleIsConstRequiredModifier(parameter.RefCustomModifiers); + }); + } + + [Fact] + public void IsConstIsWrittenOnRefReadOnlyMembers_Indexers_Parameters_Abstract() + { + var code = @" +abstract class Test +{ + public abstract int this[ref readonly int x] { get; } +}"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetProperty("this[]").Parameters.Single(); + + Assert.Empty(parameter.CustomModifiers); + AssertSingleIsConstRequiredModifier(parameter.RefCustomModifiers); + }); + } + + [Fact] + public void IsConstIsWrittenOnRefReadOnlyMembers_Indexers_ReturnTypes_Virtual() + { + var code = @" +class Test +{ + private int x; + public virtual ref readonly int this[int p] => ref x; +}"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var indexer = module.ContainingAssembly.GetTypeByMetadataName("Test").GetProperty("this[]"); + + Assert.Empty(indexer.TypeCustomModifiers); + AssertSingleIsConstRequiredModifier(indexer.RefCustomModifiers); + }); + } + + [Fact] + public void IsConstIsWrittenOnRefReadOnlyMembers_Indexers_ReturnTypes_Abstract() + { + var code = @" +abstract class Test +{ + public abstract ref readonly int this[int p] { get; } +}"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var indexer = module.ContainingAssembly.GetTypeByMetadataName("Test").GetProperty("this[]"); + + Assert.Empty(indexer.TypeCustomModifiers); + AssertSingleIsConstRequiredModifier(indexer.RefCustomModifiers); + }); + } + + [Fact] + public void IsConstIsWrittenOnRefReadOnlyMembers_Indexers_ReturnTypes_NoModifiers() + { + var code = @" +class Test +{ + private int x; + public ref readonly int this[int p] => ref x; +}"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var indexer = module.ContainingAssembly.GetTypeByMetadataName("Test").GetProperty("this[]"); + + Assert.Empty(indexer.TypeCustomModifiers); + AssertSingleIsConstRequiredModifier(indexer.RefCustomModifiers); + }); + } + + [Fact] + public void IsConstIsWrittenOnRefReadOnlyMembers_Delegates_Parameters() + { + var code = "public delegate void D(ref readonly int p);"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var parameter = module.ContainingAssembly.GetTypeByMetadataName("D").DelegateInvokeMethod.Parameters.Single(); + + Assert.Empty(parameter.CustomModifiers); + AssertSingleIsConstRequiredModifier(parameter.RefCustomModifiers); + }); + } + + [Fact] + public void IsConstIsWrittenOnRefReadOnlyMembers_Delegates_ReturnTypes() + { + var code = "public delegate ref readonly int D();"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var method = module.ContainingAssembly.GetTypeByMetadataName("D").DelegateInvokeMethod; + + Assert.Empty(method.ReturnTypeCustomModifiers); + AssertSingleIsConstRequiredModifier(method.RefCustomModifiers); + }); + } + + [Fact] + public void IsConstIsNotWrittenOnRefReadOnlyMembers_Methods_Parameters_NoModifiers() + { + var code = @" +class Test +{ + public void Method(ref readonly int x) { } +}"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("Method").Parameters.Single(); + + Assert.Empty(parameter.CustomModifiers); + Assert.Empty(parameter.RefCustomModifiers); + }); + } + + [Fact] + public void IsConstIsNotWrittenOnRefReadOnlyMembers_Methods_Parameters_Static() + { + var code = @" +class Test +{ + public static void Method(ref readonly int x) { } +}"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("Method").Parameters.Single(); + + Assert.Empty(parameter.CustomModifiers); + Assert.Empty(parameter.RefCustomModifiers); + }); + } + + [Fact] + public void IsConstIsNotWrittenOnRefReadOnlyMembers_Indexers_Parameters_NoModifiers() + { + var code = @" +class Test +{ + public int this[ref readonly int x] => x; +}"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetProperty("this[]").Parameters.Single(); + + Assert.Empty(parameter.CustomModifiers); + Assert.Empty(parameter.RefCustomModifiers); + }); + } + + [Fact] + public void IsConstIsNotWrittenOnRefReadOnlyMembers_Operators_Unary() + { + var code = @" +public class Test +{ + public static bool operator!(ref readonly Test obj) => false; +}"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("op_LogicalNot").Parameters.Single(); + + Assert.Empty(parameter.CustomModifiers); + Assert.Empty(parameter.RefCustomModifiers); + }); + } + + [Fact] + public void IsConstIsNotWrittenOnRefReadOnlyMembers_Operators_Binary() + { + var code = @" +public class Test +{ + public static bool operator+(ref readonly Test obj1, ref readonly Test obj2) => false; +}"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var parameters = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("op_Addition").Parameters; + Assert.Equal(2, parameters.Length); + + Assert.Empty(parameters[0].CustomModifiers); + Assert.Empty(parameters[0].RefCustomModifiers); + + Assert.Empty(parameters[1].CustomModifiers); + Assert.Empty(parameters[1].RefCustomModifiers); + }); + } + + [Fact] + public void IsConstIsNotWrittenOnRefReadOnlyMembers_Constructors() + { + var code = @" +public class Test +{ + public Test(ref readonly int x) { } +}"; + + CompileAndVerify(code, verify: false, symbolValidator: module => + { + var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod(".ctor").Parameters.Single(); + + Assert.Empty(parameter.CustomModifiers); + Assert.Empty(parameter.RefCustomModifiers); + }); + } + + [Fact] + public void IsConstModReqIsRejectedOnSignaturesWithoutIsReadOnlyAttribute_Methods_Parameters() + { + var ilSource = @" +.class public auto ansi beforefieldinit TestRef extends [mscorlib]System.Object +{ + .method public hidebysig newslot virtual instance void M (int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst) x) cil managed + { + .maxstack 8 + IL_0000: nop // Do nothing (No operation) + IL_0001: ret // Return from method, possibly with a value + } + + .method public hidebysig specialname rtspecialname instance void .ctor () cil managed + { + .maxstack 8 + IL_0000: ldarg.0 // Load argument 0 onto the stack + IL_0001: call instance void [mscorlib]System.Object::.ctor() // Call method indicated on the stack with arguments + IL_0006: nop // Do nothing (No operation) + IL_0007: ret // Return from method, possibly with a value + } +}"; + + var code = @" +public class Test +{ + public static void Main() + { + int value = 5; + var obj = new TestRef(); + obj.M(ref value); + } +}"; + + CreateStandardCompilation(code, references: new[] { CompileIL(ilSource) }).VerifyDiagnostics( + // (8,13): error CS0570: 'TestRef.M(ref int)' is not supported by the language + // obj.M(ref value); + Diagnostic(ErrorCode.ERR_BindToBogus, "M").WithArguments("TestRef.M(ref int)").WithLocation(8, 13)); + } + + [Fact] + public void IsConstModReqIsRejectedOnSignaturesWithoutIsReadOnlyAttribute_Methods_ReturnTypes() + { + var ilSource = @" +.class public auto ansi beforefieldinit TestRef extends [mscorlib]System.Object +{ + .field private int32 'value' + + .method public hidebysig newslot virtual instance int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst) M () cil managed + { + .maxstack 1 + .locals init ([0] int32&) + + IL_0000: nop // Do nothing (No operation) + IL_0001: ldarg.0 // Load argument 0 onto the stack + IL_0002: ldflda int32 TestRef::'value' // Push the address of field of object obj on the stack + IL_0007: stloc.0 // Pop a value from stack into local variable 0 + IL_0008: br.s IL_000a // Branch to target, short form + IL_000a: ldloc.0 // Load local variable 0 onto stack + IL_000b: ret // Return from method, possibly with a value + } + + .method public hidebysig specialname rtspecialname instance void .ctor () cil managed + { + .maxstack 8 + IL_0000: ldarg.0 // Load argument 0 onto the stack + IL_0001: ldc.i4.0 // Push 0 onto the stack as int32 + IL_0002: stfld int32 TestRef::'value' // Replace the value of field of the object obj with value + IL_0007: ldarg.0 // Load argument 0 onto the stack + IL_0008: call instance void [mscorlib]System.Object::.ctor() // Call method indicated on the stack with arguments + IL_000d: nop // Do nothing (No operation) + IL_000e: ret // Return from method, possibly with a value + } +}"; + + var code = @" +public class Test +{ + public static void Main() + { + var obj = new TestRef(); + var value = obj.M(); + } +}"; + + CreateStandardCompilation(code, references: new[] { CompileIL(ilSource) }).VerifyDiagnostics( + // (7,25): error CS0570: 'TestRef.M()' is not supported by the language + // var value = obj.M(); + Diagnostic(ErrorCode.ERR_BindToBogus, "M").WithArguments("TestRef.M()").WithLocation(7, 25)); + } + + [Fact] + public void IsConstModReqIsRejectedOnSignaturesWithoutIsReadOnlyAttribute_Properties() + { + var ilSource = @" +.class public auto ansi beforefieldinit TestRef extends [mscorlib]System.Object +{ + .field private int32 'value' + + .method public hidebysig specialname newslot virtual instance int32& get_P () cil managed + { + .maxstack 8 + IL_0000: ldarg.0 // Load argument 0 onto the stack + IL_0001: ldflda int32 TestRef::'value' // Push the address of field of object obj on the stack + IL_0006: ret // Return from method, possibly with a value + } + + .method public hidebysig specialname rtspecialname instance void .ctor () cil managed + { + .maxstack 8 + IL_0000: ldarg.0 // Load argument 0 onto the stack + IL_0001: ldc.i4.0 // Push 0 onto the stack as int32 + IL_0002: stfld int32 TestRef::'value' // Replace the value of field of the object obj with value + IL_0007: ldarg.0 // Load argument 0 onto the stack + IL_0008: call instance void [mscorlib]System.Object::.ctor() // Call method indicated on the stack with arguments + IL_000d: nop // Do nothing (No operation) + IL_000e: ret // Return from method, possibly with a value + } + + .property instance int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst) P() + { + .get instance int32& TestRef::get_P() + } +}"; + + var code = @" +public class Test +{ + public static void Main() + { + var obj = new TestRef(); + var value = obj.P; + } +}"; + + CreateStandardCompilation(code, references: new[] { CompileIL(ilSource) }).VerifyDiagnostics( + // (7,25): error CS0570: 'TestRef.P' is not supported by the language + // var value = obj.P; + Diagnostic(ErrorCode.ERR_BindToBogus, "P").WithArguments("TestRef.P").WithLocation(7, 25)); + } + + [Fact] + public void IsConstModReqIsRejectedOnSignaturesWithoutIsReadOnlyAttribute_Indexers_Parameters() { + var ilSource = @" +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string) = ( 01 00 04 49 74 65 6D 00 00 ) + .method public hidebysig newslot specialname virtual + instance void set_Item(int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst) p, int32 'value') cil managed + { + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: ldind.i4 + IL_0003: call void [mscorlib]System.Console::WriteLine(int32) + IL_0008: nop + IL_0009: ret + } + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } + + .property instance int32 Item(int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst)) + { + .set instance void TestRef::set_Item(int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst), int32) + } +}"; + var code = @" -namespace System +public class Test { - public class Object {} - public class Void {} -} -class Test + public static void Main() + { + int value = 5; + var obj = new TestRef(); + obj[value] = 0; + } +}"; + + CreateStandardCompilation(code, references: new[] { CompileIL(ilSource) }).VerifyDiagnostics( + // (8,9): error CS1546: Property, indexer, or event 'TestRef.this[ref int]' is not supported by the language; try directly calling accessor method 'TestRef.set_Item(ref int, int)' + // obj[value] = 0; + Diagnostic(ErrorCode.ERR_BindToBogusProp1, "obj[value]").WithArguments("TestRef.this[ref int]", "TestRef.set_Item(ref int, int)").WithLocation(8, 9)); + + code = @" +public class Test { - private object value = null; - public virtual ref readonly object M() => ref value; + public static void Main() + { + int value = 5; + var obj = new TestRef(); + obj.set_Item(value, 0); + } }"; - CreateCompilation(code).VerifyDiagnostics( - // (10,20): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsConst' is not defined or imported - // public virtual ref readonly object M() => ref value; - Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "ref readonly object").WithArguments("System.Runtime.CompilerServices.IsConst").WithLocation(10, 20)); + CreateStandardCompilation(code, references: new[] { CompileIL(ilSource) }).VerifyDiagnostics( + // (8,13): error CS0570: 'TestRef.set_Item(ref int, int)' is not supported by the language + // obj.set_Item(value, 0); + Diagnostic(ErrorCode.ERR_BindToBogus, "set_Item").WithArguments("TestRef.set_Item(ref int, int)").WithLocation(8, 13)); } [Fact] - public void ProperErrorsArePropagatedIfMscorlibIsConstIsNotAvailable_Properties() + public void IsConstModReqIsRejectedOnSignaturesWithoutIsReadOnlyAttribute_Indexers_ReturnTypes() { + var ilSource = @" +.class public auto ansi beforefieldinit TestRef extends [mscorlib]System.Object +{ + .custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string) = (01 00 04 49 74 65 6d 00 00) + + .field private int32 'value' + + .method public hidebysig specialname newslot virtual instance int32& get_Item (int32 p) cil managed + { + .maxstack 8 + IL_0000: ldarg.0 // Load argument 0 onto the stack + IL_0001: ldflda int32 TestRef::'value' // Push the address of field of object obj on the stack + IL_0006: ret // Return from method, possibly with a value + } + + .method public hidebysig specialname rtspecialname instance void .ctor () cil managed + { + .maxstack 8 + IL_0000: ldarg.0 // Load argument 0 onto the stack + IL_0001: ldc.i4.0 // Push 0 onto the stack as int32 + IL_0002: stfld int32 TestRef::'value' // Replace the value of field of the object obj with value + IL_0007: ldarg.0 // Load argument 0 onto the stack + IL_0008: call instance void [mscorlib]System.Object::.ctor() // Call method indicated on the stack with arguments + IL_000d: nop // Do nothing (No operation) + IL_000e: ret // Return from method, possibly with a value + } + + .property instance int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst) Item(int32 p) + { + .get instance int32& TestRef::get_Item(int32) + } +}"; + var code = @" -namespace System +public class Test { - public class Object {} - public class Void {} -} -class Test + public static void Main() + { + var obj = new TestRef(); + var value = obj[5]; + } +}"; + + CreateStandardCompilation(code, references: new[] { CompileIL(ilSource) }).VerifyDiagnostics( + // (7,21): error CS0570: 'TestRef.this[int]' is not supported by the language + // var value = obj[5]; + Diagnostic(ErrorCode.ERR_BindToBogus, "obj[5]").WithArguments("TestRef.this[int]").WithLocation(7, 21)); + } + + [Fact] + public void IsConstModReqIsRejectedOnSignaturesWithoutIsReadOnlyAttribute_Delegates_Parameters() + { + var ilSource = @" +.class public auto ansi sealed D + extends [mscorlib]System.MulticastDelegate { - private object value = null; - public virtual ref readonly object M => ref value; + .method public hidebysig specialname rtspecialname + instance void .ctor(object 'object', native int 'method') runtime managed + { + } + + .method public hidebysig newslot virtual instance void Invoke(int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst) p) runtime managed + { + } + + .method public hidebysig newslot virtual + instance class [mscorlib]System.IAsyncResult + BeginInvoke(int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst) p, class [mscorlib]System.AsyncCallback callback, object 'object') runtime managed + { + } + + .method public hidebysig newslot virtual + instance void EndInvoke(int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst) p, class [mscorlib]System.IAsyncResult result) runtime managed + { + } +}"; + + var code = @" +public class Test +{ + public static void Main() + { + Process((ref readonly int p) => System.Console.WriteLine(p)); + } + + private static void Process(D func) + { + int value = 5; + func(value); + } }"; - CreateCompilation(code).VerifyDiagnostics( - // (10,20): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsConst' is not defined or imported - // public virtual ref readonly object M => ref value; - Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "ref readonly object").WithArguments("System.Runtime.CompilerServices.IsConst").WithLocation(10, 20)); + CreateStandardCompilation(code, references: new[] { CompileIL(ilSource) }).VerifyDiagnostics( + // (6,17): error CS0570: 'D.Invoke(ref int)' is not supported by the language + // Process((ref readonly int p) => System.Console.WriteLine(p)); + Diagnostic(ErrorCode.ERR_BindToBogus, "(ref readonly int p) => System.Console.WriteLine(p)").WithArguments("D.Invoke(ref int)").WithLocation(6, 17), + // (12,9): error CS0570: 'D.Invoke(ref int)' is not supported by the language + // func(value); + Diagnostic(ErrorCode.ERR_BindToBogus, "func(value)").WithArguments("D.Invoke(ref int)").WithLocation(12, 9)); } [Fact] - public void ProperErrorsArePropagatedIfMscorlibIsConstIsNotAvailable_Indexers_Parameters() + public void IsConstModReqIsRejectedOnSignaturesWithoutIsReadOnlyAttribute_Delegates_ReturnTypes() { + var ilSource = @" +.class public auto ansi sealed D + extends [mscorlib]System.MulticastDelegate +{ + .method public hidebysig specialname rtspecialname + instance void .ctor(object 'object', native int 'method') runtime managed + { + } + + .method public hidebysig newslot virtual instance int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst) Invoke() runtime managed + { + } + + .method public hidebysig newslot virtual + instance class [mscorlib]System.IAsyncResult + BeginInvoke(class [mscorlib]System.AsyncCallback callback, object 'object') runtime managed + { + } + + .method public hidebysig newslot virtual + instance int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst) EndInvoke(class [mscorlib]System.IAsyncResult result) runtime managed + { + } +}"; + var code = @" -namespace System +public class Test { - public class Object {} - public class Void {} -} -class Test + private static int value = 5; + + public static void Main() + { + Process(() => ref value); + } + + private static void Process(D func) + { + System.Console.WriteLine(func()); + } +}"; + + CreateStandardCompilation(code, references: new[] { CompileIL(ilSource) }).VerifyDiagnostics( + // (8,17): error CS0570: 'D.Invoke()' is not supported by the language + // Process(() => ref value); + Diagnostic(ErrorCode.ERR_BindToBogus, "() => ref value").WithArguments("D.Invoke()").WithLocation(8, 17), + // (13,34): error CS0570: 'D.Invoke()' is not supported by the language + // System.Console.WriteLine(func()); + Diagnostic(ErrorCode.ERR_BindToBogus, "func()").WithArguments("D.Invoke()").WithLocation(13, 34)); + } + + [Fact] + public void WhenImplementingParentWithModifiersCopyThem_Methods_Parameters_Class_Abstract() + { + var reference = CreateStandardCompilation(@" +public abstract class Parent { - public virtual object this[ref readonly object p] => null; + public abstract void M(ref readonly int p); +}"); + + CompileAndVerify(reference, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Parent"); + var parameter = type.GetMethod("M").Parameters.Single(); + + Assert.Empty(parameter.CustomModifiers); + AssertSingleIsConstRequiredModifier(parameter.RefCustomModifiers); + }); + + var code = @" +public class Child : Parent +{ + public override void M(ref readonly int p) { } }"; - CreateCompilation(code).VerifyDiagnostics( - // (9,32): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsConst' is not defined or imported - // public virtual object this[ref readonly object p] => null; - Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "ref readonly object p").WithArguments("System.Runtime.CompilerServices.IsConst").WithLocation(9, 32)); + CompileAndVerify(code, additionalRefs: new[] { reference.EmitToImageReference() }, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Child"); + var parameter = type.GetMethod("M").Parameters.Single(); + + Assert.Empty(parameter.CustomModifiers); + AssertSingleIsConstRequiredModifier(parameter.RefCustomModifiers); + }); + } + + [Fact] + public void WhenImplementingParentWithModifiersCopyThem_Methods_Parameters_Class_Virtual() + { + var reference = CreateStandardCompilation(@" +public class Parent +{ + public virtual void M(ref readonly int p) {} +}"); + + CompileAndVerify(reference, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Parent"); + var parameter = type.GetMethod("M").Parameters.Single(); + + Assert.Empty(parameter.CustomModifiers); + AssertSingleIsConstRequiredModifier(parameter.RefCustomModifiers); + }); + + var code = @" +public class Child : Parent +{ + public override void M(ref readonly int p) { } +}"; + + CompileAndVerify(code, additionalRefs: new[] { reference.EmitToImageReference() }, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Child"); + var parameter = type.GetMethod("M").Parameters.Single(); + + Assert.Empty(parameter.CustomModifiers); + AssertSingleIsConstRequiredModifier(parameter.RefCustomModifiers); + }); } - [Fact] - public void ProperErrorsArePropagatedIfMscorlibIsConstIsNotAvailable_Indexers_ReturnTypes() - { + [Fact] + public void WhenImplementingParentWithModifiersCopyThem_Methods_Parameters_ImplicitInterfaces_NonVirtual() + { + var reference = CreateStandardCompilation(@" +public interface Parent +{ + void M(ref readonly int p); +}"); + + CompileAndVerify(reference, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Parent"); + var parameter = type.GetMethod("M").Parameters.Single(); + + Assert.Empty(parameter.CustomModifiers); + AssertSingleIsConstRequiredModifier(parameter.RefCustomModifiers); + }); + var code = @" -namespace System -{ - public class Object {} - public class Void {} -} -class Test +public class Child : Parent { - private object value = null; - public virtual ref readonly object this[object p] => ref value; + public void M(ref readonly int p) { } }"; - CreateCompilation(code).VerifyDiagnostics( - // (10,20): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsConst' is not defined or imported - // public virtual ref readonly object this[object p] => ref value; - Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "ref readonly object").WithArguments("System.Runtime.CompilerServices.IsConst").WithLocation(10, 20)); + CompileAndVerify(code, additionalRefs: new[] { reference.EmitToImageReference() }, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Child"); + + var implicitParameter = type.GetMethod("M").Parameters.Single(); + Assert.Empty(implicitParameter.CustomModifiers); + Assert.Empty(implicitParameter.RefCustomModifiers); + + var explicitParameter = type.GetMethod("Parent.M").Parameters.Single(); + Assert.Empty(explicitParameter.CustomModifiers); + AssertSingleIsConstRequiredModifier(explicitParameter.RefCustomModifiers); + }); } [Fact] - public void IsConstIsWrittenOnRefReadOnlyMembers_Methods_Parameters_Virtual() + public void WhenImplementingParentWithModifiersCopyThem_Methods_Parameters_ImplicitInterfaces_Virtual() { + var reference = CreateStandardCompilation(@" +public interface Parent +{ + void M(ref readonly int p); +}"); + + CompileAndVerify(reference, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Parent"); + var parameter = type.GetMethod("M").Parameters.Single(); + + Assert.Empty(parameter.CustomModifiers); + AssertSingleIsConstRequiredModifier(parameter.RefCustomModifiers); + }); + var code = @" -class Test +public class Child : Parent { - public virtual void Method(ref readonly int x) { } + public virtual void M(ref readonly int p) { } }"; - CompileAndVerify(code, verify: false, symbolValidator: module => + CompileAndVerify(code, additionalRefs: new[] { reference.EmitToImageReference() }, symbolValidator: module => { - var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("Method").Parameters.Single(); + var type = module.ContainingAssembly.GetTypeByMetadataName("Child"); + var parameter = type.GetMethod("M").Parameters.Single(); Assert.Empty(parameter.CustomModifiers); AssertSingleIsConstRequiredModifier(parameter.RefCustomModifiers); @@ -394,17 +2535,33 @@ class Test } [Fact] - public void IsConstIsWrittenOnRefReadOnlyMembers_Methods_Parameters_Abstract() + public void WhenImplementingParentWithModifiersCopyThem_Methods_Parameters_ExplicitInterfaces() { + var reference = CreateStandardCompilation(@" +public interface Parent +{ + void M(ref readonly int p); +}"); + + CompileAndVerify(reference, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Parent"); + var parameter = type.GetMethod("M").Parameters.Single(); + + Assert.Empty(parameter.CustomModifiers); + AssertSingleIsConstRequiredModifier(parameter.RefCustomModifiers); + }); + var code = @" -abstract class Test +public class Child : Parent { - public abstract void Method(ref readonly int x); + void Parent.M(ref readonly int p) { } }"; - CompileAndVerify(code, verify: false, symbolValidator: module => + CompileAndVerify(code, additionalRefs: new[] { reference.EmitToImageReference() }, symbolValidator: module => { - var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("Method").Parameters.Single(); + var type = module.ContainingAssembly.GetTypeByMetadataName("Child"); + var parameter = type.GetMethod("Parent.M").Parameters.Single(); Assert.Empty(parameter.CustomModifiers); AssertSingleIsConstRequiredModifier(parameter.RefCustomModifiers); @@ -412,18 +2569,33 @@ abstract class Test } [Fact] - public void IsConstIsWrittenOnRefReadOnlyMembers_Methods_ReturnTypes_Virtual() + public void WhenImplementingParentWithModifiersCopyThem_Methods_ReturnTypes_Class_Abstract() { + var reference = CreateStandardCompilation(@" +public abstract class Parent +{ + public abstract ref readonly int M(); +}"); + + CompileAndVerify(reference, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Parent"); + var method = type.GetMethod("M"); + + Assert.Empty(method.ReturnTypeCustomModifiers); + AssertSingleIsConstRequiredModifier(method.RefCustomModifiers); + }); + var code = @" -class Test +public class Child : Parent { - private int x = 0; - public virtual ref readonly int Method() => ref x; + public override ref readonly int M() { throw null; } }"; - CompileAndVerify(code, verify: false, symbolValidator: module => + CompileAndVerify(code, additionalRefs: new[] { reference.EmitToImageReference() }, symbolValidator: module => { - var method = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("Method"); + var type = module.ContainingAssembly.GetTypeByMetadataName("Child"); + var method = type.GetMethod("M"); Assert.Empty(method.ReturnTypeCustomModifiers); AssertSingleIsConstRequiredModifier(method.RefCustomModifiers); @@ -431,17 +2603,33 @@ class Test } [Fact] - public void IsConstIsWrittenOnRefReadOnlyMembers_Methods_ReturnTypes_Abstract() + public void WhenImplementingParentWithModifiersCopyThem_Methods_ReturnTypes_Class_Virtual() { + var reference = CreateStandardCompilation(@" +public class Parent +{ + public virtual ref readonly int M() { throw null; } +}"); + + CompileAndVerify(reference, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Parent"); + var method = type.GetMethod("M"); + + Assert.Empty(method.ReturnTypeCustomModifiers); + AssertSingleIsConstRequiredModifier(method.RefCustomModifiers); + }); + var code = @" -abstract class Test +public class Child : Parent { - public abstract ref readonly int Method(); + public override ref readonly int M() { throw null; } }"; - CompileAndVerify(code, verify: false, symbolValidator: module => + CompileAndVerify(code, additionalRefs: new[] { reference.EmitToImageReference() }, symbolValidator: module => { - var method = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("Method"); + var type = module.ContainingAssembly.GetTypeByMetadataName("Child"); + var method = type.GetMethod("M"); Assert.Empty(method.ReturnTypeCustomModifiers); AssertSingleIsConstRequiredModifier(method.RefCustomModifiers); @@ -449,510 +2637,684 @@ abstract class Test } [Fact] - public void IsConstIsWrittenOnRefReadOnlyMembers_Properties_Virtual() + public void WhenImplementingParentWithModifiersCopyThem_Methods_ReturnTypes_ImplicitInterfaces_NonVirtual() { + var reference = CreateStandardCompilation(@" +public interface Parent +{ + ref readonly int M(); +}"); + + CompileAndVerify(reference, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Parent"); + var method = type.GetMethod("M"); + + Assert.Empty(method.ReturnTypeCustomModifiers); + AssertSingleIsConstRequiredModifier(method.RefCustomModifiers); + }); + var code = @" -class Test +public class Child : Parent { - private int x = 0; - public virtual ref readonly int Property => ref x; + public ref readonly int M() { throw null; } }"; - CompileAndVerify(code, verify: false, symbolValidator: module => + CompileAndVerify(code, additionalRefs: new[] { reference.EmitToImageReference() }, symbolValidator: module => { - var property = module.ContainingAssembly.GetTypeByMetadataName("Test").GetProperty("Property"); + var type = module.ContainingAssembly.GetTypeByMetadataName("Child"); - Assert.Empty(property.TypeCustomModifiers); - AssertSingleIsConstRequiredModifier(property.RefCustomModifiers); + var implicitMethod = type.GetMethod("M"); + Assert.Empty(implicitMethod.ReturnTypeCustomModifiers); + AssertSingleIsConstRequiredModifier(implicitMethod.RefCustomModifiers); }); } [Fact] - public void IsConstIsWrittenOnRefReadOnlyMembers_Properties_Abstract() + public void WhenImplementingParentWithModifiersCopyThem_Methods_ReturnTypes_ImplicitInterfaces_Virtual() { + var reference = CreateStandardCompilation(@" +public interface Parent +{ + ref readonly int M(); +}"); + + CompileAndVerify(reference, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Parent"); + var implicitMethod = type.GetMethod("M"); + + Assert.Empty(implicitMethod.ReturnTypeCustomModifiers); + AssertSingleIsConstRequiredModifier(implicitMethod.RefCustomModifiers); + }); + var code = @" -abstract class Test +public class Child : Parent { - public abstract ref readonly int Property { get; } + public virtual ref readonly int M() { throw null; } }"; - CompileAndVerify(code, verify: false, symbolValidator: module => + CompileAndVerify(code, additionalRefs: new[] { reference.EmitToImageReference() }, symbolValidator: module => { - var property = module.ContainingAssembly.GetTypeByMetadataName("Test").GetProperty("Property"); + var type = module.ContainingAssembly.GetTypeByMetadataName("Child"); + var implicitMethod = type.GetMethod("M"); - Assert.Empty(property.TypeCustomModifiers); - AssertSingleIsConstRequiredModifier(property.RefCustomModifiers); + Assert.Empty(implicitMethod.ReturnTypeCustomModifiers); + AssertSingleIsConstRequiredModifier(implicitMethod.RefCustomModifiers); }); } [Fact] - public void IsConstIsWrittenOnRefReadOnlyMembers_Indexers_Parameters_Virtual() + public void WhenImplementingParentWithModifiersCopyThem_Methods_ReturnTypes_ExplicitInterfaces() { + var reference = CreateStandardCompilation(@" +public interface Parent +{ + ref readonly int M(); +}"); + + CompileAndVerify(reference, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Parent"); + var implicitMethod = type.GetMethod("M"); + + Assert.Empty(implicitMethod.ReturnTypeCustomModifiers); + AssertSingleIsConstRequiredModifier(implicitMethod.RefCustomModifiers); + }); + var code = @" -class Test +public class Child : Parent { - public virtual int this[ref readonly int x] => x; + ref readonly int Parent.M() { throw null; } }"; - CompileAndVerify(code, verify: false, symbolValidator: module => + CompileAndVerify(code, additionalRefs: new[] { reference.EmitToImageReference() }, symbolValidator: module => { - var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetProperty("this[]").Parameters.Single(); + var type = module.ContainingAssembly.GetTypeByMetadataName("Child"); + var implicitMethod = type.GetMethod("Parent.M"); - Assert.Empty(parameter.CustomModifiers); - AssertSingleIsConstRequiredModifier(parameter.RefCustomModifiers); + Assert.Empty(implicitMethod.ReturnTypeCustomModifiers); + AssertSingleIsConstRequiredModifier(implicitMethod.RefCustomModifiers); }); } [Fact] - public void IsConstIsWrittenOnRefReadOnlyMembers_Indexers_Parameters_Abstract() + public void WhenImplementingParentWithModifiersCopyThem_Properties_Class_Abstract() { + var reference = CreateStandardCompilation(@" +public abstract class Parent +{ + public abstract ref readonly int P { get; } +}"); + + CompileAndVerify(reference, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Parent"); + var property = type.GetProperty("P"); + + Assert.Empty(property.TypeCustomModifiers); + AssertSingleIsConstRequiredModifier(property.RefCustomModifiers); + }); + var code = @" -abstract class Test +public class Child : Parent { - public abstract int this[ref readonly int x] { get; } + public override ref readonly int P { get { throw null; } } }"; - CompileAndVerify(code, verify: false, symbolValidator: module => + CompileAndVerify(code, additionalRefs: new[] { reference.EmitToImageReference() }, symbolValidator: module => { - var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetProperty("this[]").Parameters.Single(); + var type = module.ContainingAssembly.GetTypeByMetadataName("Child"); + var property = type.GetProperty("P"); - Assert.Empty(parameter.CustomModifiers); - AssertSingleIsConstRequiredModifier(parameter.RefCustomModifiers); + Assert.Empty(property.TypeCustomModifiers); + AssertSingleIsConstRequiredModifier(property.RefCustomModifiers); }); } [Fact] - public void IsConstIsWrittenOnRefReadOnlyMembers_Indexers_ReturnTypes_Virtual() + public void WhenImplementingParentWithModifiersCopyThem_Properties_Class_Virtual() { + var reference = CreateStandardCompilation(@" +public class Parent +{ + public virtual ref readonly int P { get { throw null; } } +}"); + + CompileAndVerify(reference, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Parent"); + var property = type.GetProperty("P"); + + Assert.Empty(property.TypeCustomModifiers); + AssertSingleIsConstRequiredModifier(property.RefCustomModifiers); + }); + var code = @" -class Test +public class Child : Parent { - private int x; - public virtual ref readonly int this[int p] => ref x; + public override ref readonly int P { get { throw null; } } }"; - CompileAndVerify(code, verify: false, symbolValidator: module => + CompileAndVerify(code, additionalRefs: new[] { reference.EmitToImageReference() }, symbolValidator: module => { - var indexer = module.ContainingAssembly.GetTypeByMetadataName("Test").GetProperty("this[]"); + var type = module.ContainingAssembly.GetTypeByMetadataName("Child"); + var property = type.GetProperty("P"); - Assert.Empty(indexer.TypeCustomModifiers); - AssertSingleIsConstRequiredModifier(indexer.RefCustomModifiers); + Assert.Empty(property.TypeCustomModifiers); + AssertSingleIsConstRequiredModifier(property.RefCustomModifiers); }); } [Fact] - public void IsConstIsWrittenOnRefReadOnlyMembers_Indexers_ReturnTypes_Abstract() + public void WhenImplementingParentWithModifiersCopyThem_Properties_ImplicitInterface_NonVirtual() { + var reference = CreateStandardCompilation(@" +public interface Parent +{ + ref readonly int P { get; } +}"); + + CompileAndVerify(reference, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Parent"); + var property = type.GetProperty("P"); + + Assert.Empty(property.TypeCustomModifiers); + AssertSingleIsConstRequiredModifier(property.RefCustomModifiers); + }); + var code = @" -abstract class Test +public class Child : Parent { - public abstract ref readonly int this[int p] { get; } + public ref readonly int P { get { throw null; } } }"; - CompileAndVerify(code, verify: false, symbolValidator: module => + CompileAndVerify(code, additionalRefs: new[] { reference.EmitToImageReference() }, symbolValidator: module => { - var indexer = module.ContainingAssembly.GetTypeByMetadataName("Test").GetProperty("this[]"); + var type = module.ContainingAssembly.GetTypeByMetadataName("Child"); - Assert.Empty(indexer.TypeCustomModifiers); - AssertSingleIsConstRequiredModifier(indexer.RefCustomModifiers); + var implicitproperty = type.GetProperty("P"); + Assert.Empty(implicitproperty.TypeCustomModifiers); + AssertSingleIsConstRequiredModifier(implicitproperty.RefCustomModifiers); }); } [Fact] - public void IsConstIsNotWrittenOnRefReadOnlyMembers_Methods_Parameters_NoModifiers() + public void WhenImplementingParentWithModifiersCopyThem_Properties_ImplicitInterface_Virtual() { + var reference = CreateStandardCompilation(@" +public interface Parent +{ + ref readonly int P { get; } +}"); + + CompileAndVerify(reference, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Parent"); + var property = type.GetProperty("P"); + + Assert.Empty(property.TypeCustomModifiers); + AssertSingleIsConstRequiredModifier(property.RefCustomModifiers); + }); + var code = @" -class Test +public class Child : Parent { - public void Method(ref readonly int x) { } + public virtual ref readonly int P { get { throw null; } } }"; - CompileAndVerify(code, verify: false, symbolValidator: module => + CompileAndVerify(code, additionalRefs: new[] { reference.EmitToImageReference() }, symbolValidator: module => { - var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("Method").Parameters.Single(); + var type = module.ContainingAssembly.GetTypeByMetadataName("Child"); + var property = type.GetProperty("P"); - Assert.Empty(parameter.CustomModifiers); - Assert.Empty(parameter.RefCustomModifiers); + Assert.Empty(property.TypeCustomModifiers); + AssertSingleIsConstRequiredModifier(property.RefCustomModifiers); }); } [Fact] - public void IsConstIsNotWrittenOnRefReadOnlyMembers_Methods_Parameters_Static() + public void WhenImplementingParentWithModifiersCopyThem_Properties_ExplicitInterface() { + var reference = CreateStandardCompilation(@" +public interface Parent +{ + ref readonly int P { get; } +}"); + + CompileAndVerify(reference, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Parent"); + var property = type.GetProperty("P"); + + Assert.Empty(property.TypeCustomModifiers); + AssertSingleIsConstRequiredModifier(property.RefCustomModifiers); + }); + var code = @" -class Test +public class Child : Parent { - public static void Method(ref readonly int x) { } + ref readonly int Parent.P { get { throw null; } } }"; - CompileAndVerify(code, verify: false, symbolValidator: module => + CompileAndVerify(code, additionalRefs: new[] { reference.EmitToImageReference() }, symbolValidator: module => { - var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("Method").Parameters.Single(); + var type = module.ContainingAssembly.GetTypeByMetadataName("Child"); + var property = type.GetProperty("Parent.P"); + + Assert.Empty(property.TypeCustomModifiers); + AssertSingleIsConstRequiredModifier(property.RefCustomModifiers); + }); + } + + [Fact] + public void WhenImplementingParentWithModifiersCopyThem_Indexers_Parameters_Class_Abstract() + { + var reference = CreateStandardCompilation(@" +public abstract class Parent +{ + public abstract int this[ref readonly int p] { set; } +}"); + + CompileAndVerify(reference, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Parent"); + var parameter = type.GetProperty("this[]").Parameters.Single(); Assert.Empty(parameter.CustomModifiers); - Assert.Empty(parameter.RefCustomModifiers); + AssertSingleIsConstRequiredModifier(parameter.RefCustomModifiers); + }); + + var code = @" +public class Child : Parent +{ + public override int this[ref readonly int p] { set {} } +}"; + + CompileAndVerify(code, additionalRefs: new[] { reference.EmitToImageReference() }, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Child"); + var parameter = type.GetProperty("this[]").Parameters.Single(); + + Assert.Empty(parameter.CustomModifiers); + AssertSingleIsConstRequiredModifier(parameter.RefCustomModifiers); }); } [Fact] - public void IsConstIsNotWrittenOnRefReadOnlyMembers_Methods_ReturnTypes_NoModifiers() + public void WhenImplementingParentWithModifiersCopyThem_Indexers_Parameters_Class_Virtual() { + var reference = CreateStandardCompilation(@" +public class Parent +{ + public virtual int this[ref readonly int p] { set { } } +}"); + + CompileAndVerify(reference, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Parent"); + var parameter = type.GetProperty("this[]").Parameters.Single(); + + Assert.Empty(parameter.CustomModifiers); + AssertSingleIsConstRequiredModifier(parameter.RefCustomModifiers); + }); + var code = @" -class Test +public class Child : Parent { - private int x = 0; - public ref readonly int Method() => ref x; + public override int this[ref readonly int p] { set {} } }"; - CompileAndVerify(code, verify: false, symbolValidator: module => + CompileAndVerify(code, additionalRefs: new[] { reference.EmitToImageReference() }, symbolValidator: module => { - var method = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("Method"); + var type = module.ContainingAssembly.GetTypeByMetadataName("Child"); + var parameter = type.GetProperty("this[]").Parameters.Single(); - Assert.Empty(method.ReturnTypeCustomModifiers); - Assert.Empty(method.RefCustomModifiers); + Assert.Empty(parameter.CustomModifiers); + AssertSingleIsConstRequiredModifier(parameter.RefCustomModifiers); }); } [Fact] - public void IsConstIsNotWrittenOnRefReadOnlyMembers_Methods_ReturnTypes_Static() + public void WhenImplementingParentWithModifiersCopyThem_Indexers_Parameters_ImplicitInterface_NonVirtual() { + var reference = CreateStandardCompilation(@" +public interface Parent +{ + int this[ref readonly int p] { set; } +}"); + + CompileAndVerify(reference, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Parent"); + var parameter = type.GetProperty("this[]").Parameters.Single(); + + Assert.Empty(parameter.CustomModifiers); + AssertSingleIsConstRequiredModifier(parameter.RefCustomModifiers); + }); + var code = @" -class Test +public class Child : Parent { - private static int x = 0; - public static ref readonly int Method() => ref x; + public int this[ref readonly int p] { set {} } }"; - CompileAndVerify(code, verify: false, symbolValidator: module => + CompileAndVerify(code, additionalRefs: new[] { reference.EmitToImageReference() }, symbolValidator: module => { - var method = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("Method"); + var type = module.ContainingAssembly.GetTypeByMetadataName("Child"); - Assert.Empty(method.ReturnTypeCustomModifiers); - Assert.Empty(method.RefCustomModifiers); + var implicitParameter = type.GetProperty("this[]").Parameters.Single(); + Assert.Empty(implicitParameter.CustomModifiers); + Assert.Empty(implicitParameter.RefCustomModifiers); + + var explicitParameter = type.GetMethod("Parent.set_Item").Parameters.First(); + Assert.Empty(explicitParameter.CustomModifiers); + AssertSingleIsConstRequiredModifier(explicitParameter.RefCustomModifiers); }); } [Fact] - public void IsConstIsNotWrittenOnRefReadOnlyMembers_Properties_NoModifiers() + public void WhenImplementingParentWithModifiersCopyThem_Indexers_Parameters_ImplicitInterface_Virtual() { + var reference = CreateStandardCompilation(@" +public interface Parent +{ + int this[ref readonly int p] { set; } +}"); + + CompileAndVerify(reference, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Parent"); + var parameter = type.GetProperty("this[]").Parameters.Single(); + + Assert.Empty(parameter.CustomModifiers); + AssertSingleIsConstRequiredModifier(parameter.RefCustomModifiers); + }); + var code = @" -class Test +public class Child : Parent { - private int x = 0; - public ref readonly int Property => ref x; + public virtual int this[ref readonly int p] { set {} } }"; - CompileAndVerify(code, verify: false, symbolValidator: module => + CompileAndVerify(code, additionalRefs: new[] { reference.EmitToImageReference() }, symbolValidator: module => { - var property = module.ContainingAssembly.GetTypeByMetadataName("Test").GetProperty("Property"); + var type = module.ContainingAssembly.GetTypeByMetadataName("Child"); + var parameter = type.GetProperty("this[]").Parameters.Single(); - Assert.Empty(property.TypeCustomModifiers); - Assert.Empty(property.RefCustomModifiers); + Assert.Empty(parameter.CustomModifiers); + AssertSingleIsConstRequiredModifier(parameter.RefCustomModifiers); }); } [Fact] - public void IsConstIsNotWrittenOnRefReadOnlyMembers_Properties_Static() + public void WhenImplementingParentWithModifiersCopyThem_Indexers_Parameters_ExplicitInterface() { - var code = @" -class Test + var reference = CreateStandardCompilation(@" +public interface Parent { - private static int x = 0; - public static ref readonly int Property => ref x; -}"; + int this[ref readonly int p] { set; } +}"); - CompileAndVerify(code, verify: false, symbolValidator: module => + CompileAndVerify(reference, symbolValidator: module => { - var property = module.ContainingAssembly.GetTypeByMetadataName("Test").GetProperty("Property"); + var type = module.ContainingAssembly.GetTypeByMetadataName("Parent"); + var parameter = type.GetProperty("this[]").Parameters.Single(); - Assert.Empty(property.TypeCustomModifiers); - Assert.Empty(property.RefCustomModifiers); + Assert.Empty(parameter.CustomModifiers); + AssertSingleIsConstRequiredModifier(parameter.RefCustomModifiers); }); - } - [Fact] - public void IsConstIsNotWrittenOnRefReadOnlyMembers_Indexers_Parameters_NoModifiers() - { var code = @" -class Test +public class Child : Parent { - public int this[ref readonly int x] => x; + int Parent.this[ref readonly int p] { set {} } }"; - CompileAndVerify(code, verify: false, symbolValidator: module => + CompileAndVerify(code, additionalRefs: new[] { reference.EmitToImageReference() }, symbolValidator: module => { - var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetProperty("this[]").Parameters.Single(); + var type = module.ContainingAssembly.GetTypeByMetadataName("Child"); + var parameter = type.GetProperty("Parent.Item").Parameters.Single(); Assert.Empty(parameter.CustomModifiers); - Assert.Empty(parameter.RefCustomModifiers); + AssertSingleIsConstRequiredModifier(parameter.RefCustomModifiers); }); } [Fact] - public void IsConstIsNotWrittenOnRefReadOnlyMembers_Indexers_ReturnTypes_NoModifiers() + public void WhenImplementingParentWithModifiersCopyThem_Indexers_ReturnTypes_Class_Abstract() { + var reference = CreateStandardCompilation(@" +public abstract class Parent +{ + public abstract ref readonly int this[int p] { get; } +}"); + + CompileAndVerify(reference, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Parent"); + var indexer = type.GetProperty("this[]"); + + Assert.Empty(indexer.TypeCustomModifiers); + AssertSingleIsConstRequiredModifier(indexer.RefCustomModifiers); + }); + var code = @" -class Test +public class Child : Parent { - private int x; - public ref readonly int this[int p] => ref x; + public override ref readonly int this[int p] { get { throw null; } } }"; - CompileAndVerify(code, verify: false, symbolValidator: module => + CompileAndVerify(code, additionalRefs: new[] { reference.EmitToImageReference() }, symbolValidator: module => { - var indexer = module.ContainingAssembly.GetTypeByMetadataName("Test").GetProperty("this[]"); + var type = module.ContainingAssembly.GetTypeByMetadataName("Child"); + var indexer = type.GetProperty("this[]"); Assert.Empty(indexer.TypeCustomModifiers); - Assert.Empty(indexer.RefCustomModifiers); + AssertSingleIsConstRequiredModifier(indexer.RefCustomModifiers); }); } [Fact] - public void IsConstIsNotWrittenOnRefReadOnlyMembers_Delegates() + public void WhenImplementingParentWithModifiersCopyThem_Indexers_ReturnTypes_Class_Virtual() { - var code = "delegate ref readonly int D(ref readonly int x);"; + var reference = CreateStandardCompilation(@" +public class Parent +{ + public virtual ref readonly int this[int p] { get { throw null; } } +}"); - CompileAndVerify(code, verify: false, symbolValidator: module => + CompileAndVerify(reference, symbolValidator: module => { - var @delegate = module.ContainingAssembly.GetTypeByMetadataName("D").DelegateInvokeMethod; - - Assert.Empty(@delegate.ReturnTypeCustomModifiers); - Assert.Empty(@delegate.RefCustomModifiers); - - var parameter = @delegate.Parameters.Single(); + var type = module.ContainingAssembly.GetTypeByMetadataName("Parent"); + var indexer = type.GetProperty("this[]"); - Assert.Empty(parameter.CustomModifiers); - Assert.Empty(parameter.RefCustomModifiers); + Assert.Empty(indexer.TypeCustomModifiers); + AssertSingleIsConstRequiredModifier(indexer.RefCustomModifiers); }); - } - [Fact] - public void IsConstIsNotWrittenOnRefReadOnlyMembers_Operators() - { var code = @" -public class Test +public class Child : Parent { - public static bool operator!(ref readonly Test obj) => false; + public override ref readonly int this[int p] { get { throw null; } } }"; - CompileAndVerify(code, verify: false, symbolValidator: module => + CompileAndVerify(code, additionalRefs: new[] { reference.EmitToImageReference() }, symbolValidator: module => { - var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("op_LogicalNot").Parameters.Single(); + var type = module.ContainingAssembly.GetTypeByMetadataName("Child"); + var indexer = type.GetProperty("this[]"); - Assert.Empty(parameter.CustomModifiers); - Assert.Empty(parameter.RefCustomModifiers); + Assert.Empty(indexer.TypeCustomModifiers); + AssertSingleIsConstRequiredModifier(indexer.RefCustomModifiers); }); } [Fact] - public void IsConstIsNotWrittenOnRefReadOnlyMembers_Constructors() + public void WhenImplementingParentWithModifiersCopyThem_Indexers_ReturnTypes_ImplicitInterface_NonVirtual() { + var reference = CreateStandardCompilation(@" +public interface Parent +{ + ref readonly int this[int p] { get; } +}"); + + CompileAndVerify(reference, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Parent"); + var indexer = type.GetProperty("this[]"); + + Assert.Empty(indexer.TypeCustomModifiers); + AssertSingleIsConstRequiredModifier(indexer.RefCustomModifiers); + }); + var code = @" -public class Test +public class Child : Parent { - public Test(ref readonly int x) { } + public ref readonly int this[int p] { get { throw null; } } }"; - CompileAndVerify(code, verify: false, symbolValidator: module => + CompileAndVerify(code, additionalRefs: new[] { reference.EmitToImageReference() }, symbolValidator: module => { - var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod(".ctor").Parameters.Single(); + var type = module.ContainingAssembly.GetTypeByMetadataName("Child"); + var indexer = type.GetProperty("this[]"); - Assert.Empty(parameter.CustomModifiers); - Assert.Empty(parameter.RefCustomModifiers); + Assert.Empty(indexer.TypeCustomModifiers); + AssertSingleIsConstRequiredModifier(indexer.RefCustomModifiers); }); } [Fact] - public void IsConstModReqIsRejectedOnSignaturesWithoutIsReadOnlyAttribute_Methods_Parameters() + public void WhenImplementingParentWithModifiersCopyThem_Indexers_ReturnTypes_ImplicitInterface_Virtual() { - var ilSource = @" -.class public auto ansi beforefieldinit TestRef extends [mscorlib]System.Object + var reference = CreateStandardCompilation(@" +public interface Parent { - .method public hidebysig newslot virtual instance void M (int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst) x) cil managed - { - .maxstack 8 - IL_0000: nop // Do nothing (No operation) - IL_0001: ret // Return from method, possibly with a value - } + ref readonly int this[int p] { get; } +}"); - .method public hidebysig specialname rtspecialname instance void .ctor () cil managed - { - .maxstack 8 - IL_0000: ldarg.0 // Load argument 0 onto the stack - IL_0001: call instance void [mscorlib]System.Object::.ctor() // Call method indicated on the stack with arguments - IL_0006: nop // Do nothing (No operation) - IL_0007: ret // Return from method, possibly with a value - } -}"; + CompileAndVerify(reference, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Parent"); + var indexer = type.GetProperty("this[]"); + + Assert.Empty(indexer.TypeCustomModifiers); + AssertSingleIsConstRequiredModifier(indexer.RefCustomModifiers); + }); var code = @" -public class Test +public class Child : Parent { - public static void Main() - { - int value = 5; - var obj = new TestRef(); - obj.M(ref value); - } + public virtual ref readonly int this[int p] { get { throw null; } } }"; - CreateStandardCompilation(code, references: new[] { CompileIL(ilSource) }).VerifyDiagnostics( - // (8,13): error CS0570: 'TestRef.M(ref int)' is not supported by the language - // obj.M(ref value); - Diagnostic(ErrorCode.ERR_BindToBogus, "M").WithArguments("TestRef.M(ref int)").WithLocation(8, 13)); + CompileAndVerify(code, additionalRefs: new[] { reference.EmitToImageReference() }, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Child"); + var indexer = type.GetProperty("this[]"); + + Assert.Empty(indexer.TypeCustomModifiers); + AssertSingleIsConstRequiredModifier(indexer.RefCustomModifiers); + + }); } [Fact] - public void IsConstModReqIsRejectedOnSignaturesWithoutIsReadOnlyAttribute_Methods_ReturnTypes() + public void WhenImplementingParentWithModifiersCopyThem_Indexers_ReturnTypes_ExplicitInterface() { - var ilSource = @" -.class public auto ansi beforefieldinit TestRef extends [mscorlib]System.Object + var reference = CreateStandardCompilation(@" +public interface Parent { - .field private int32 'value' - - .method public hidebysig newslot virtual instance int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst) M () cil managed - { - .maxstack 1 - .locals init ([0] int32&) + ref readonly int this[int p] { get; } +}"); - IL_0000: nop // Do nothing (No operation) - IL_0001: ldarg.0 // Load argument 0 onto the stack - IL_0002: ldflda int32 TestRef::'value' // Push the address of field of object obj on the stack - IL_0007: stloc.0 // Pop a value from stack into local variable 0 - IL_0008: br.s IL_000a // Branch to target, short form - IL_000a: ldloc.0 // Load local variable 0 onto stack - IL_000b: ret // Return from method, possibly with a value - } + CompileAndVerify(reference, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Parent"); + var indexer = type.GetProperty("this[]"); - .method public hidebysig specialname rtspecialname instance void .ctor () cil managed - { - .maxstack 8 - IL_0000: ldarg.0 // Load argument 0 onto the stack - IL_0001: ldc.i4.0 // Push 0 onto the stack as int32 - IL_0002: stfld int32 TestRef::'value' // Replace the value of field of the object obj with value - IL_0007: ldarg.0 // Load argument 0 onto the stack - IL_0008: call instance void [mscorlib]System.Object::.ctor() // Call method indicated on the stack with arguments - IL_000d: nop // Do nothing (No operation) - IL_000e: ret // Return from method, possibly with a value - } -}"; + Assert.Empty(indexer.TypeCustomModifiers); + AssertSingleIsConstRequiredModifier(indexer.RefCustomModifiers); + }); var code = @" -public class Test +public class Child : Parent { - public static void Main() - { - var obj = new TestRef(); - var value = obj.M(); - } + ref readonly int Parent.this[int p] { get { throw null; } } }"; - CreateStandardCompilation(code, references: new[] { CompileIL(ilSource) }).VerifyDiagnostics( - // (7,25): error CS0570: 'TestRef.M()' is not supported by the language - // var value = obj.M(); - Diagnostic(ErrorCode.ERR_BindToBogus, "M").WithArguments("TestRef.M()").WithLocation(7, 25)); + CompileAndVerify(code, additionalRefs: new[] { reference.EmitToImageReference() }, symbolValidator: module => + { + var type = module.ContainingAssembly.GetTypeByMetadataName("Child"); + var indexer = type.GetProperty("Parent.Item"); + + Assert.Empty(indexer.TypeCustomModifiers); + AssertSingleIsConstRequiredModifier(indexer.RefCustomModifiers); + }); } [Fact] - public void IsConstModReqIsRejectedOnSignaturesWithoutIsReadOnlyAttribute_Properties() + public void CreatingLambdasOfDelegatesWithModifiersCanBeExecuted_Parameters() { - var ilSource = @" -.class public auto ansi beforefieldinit TestRef extends [mscorlib]System.Object -{ - .field private int32 'value' - - .method public hidebysig specialname newslot virtual instance int32& get_P () cil managed - { - .maxstack 8 - IL_0000: ldarg.0 // Load argument 0 onto the stack - IL_0001: ldflda int32 TestRef::'value' // Push the address of field of object obj on the stack - IL_0006: ret // Return from method, possibly with a value - } + var reference = CreateStandardCompilation("public delegate void D(ref readonly int p);"); - .method public hidebysig specialname rtspecialname instance void .ctor () cil managed - { - .maxstack 8 - IL_0000: ldarg.0 // Load argument 0 onto the stack - IL_0001: ldc.i4.0 // Push 0 onto the stack as int32 - IL_0002: stfld int32 TestRef::'value' // Replace the value of field of the object obj with value - IL_0007: ldarg.0 // Load argument 0 onto the stack - IL_0008: call instance void [mscorlib]System.Object::.ctor() // Call method indicated on the stack with arguments - IL_000d: nop // Do nothing (No operation) - IL_000e: ret // Return from method, possibly with a value - } + CompileAndVerify(reference, symbolValidator: module => + { + var parameter = module.ContainingAssembly.GetTypeByMetadataName("D").DelegateInvokeMethod.Parameters.Single(); - .property instance int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst) P() - { - .get instance int32& TestRef::get_P() - } -}"; + Assert.Empty(parameter.CustomModifiers); + AssertSingleIsConstRequiredModifier(parameter.RefCustomModifiers); + }); var code = @" public class Test { public static void Main() { - var obj = new TestRef(); - var value = obj.P; + Run((ref readonly int p) => System.Console.WriteLine(p)); + } + + public static void Run(D lambda) + { + lambda(value); } + + private static int value = 5; }"; - CreateStandardCompilation(code, references: new[] { CompileIL(ilSource) }).VerifyDiagnostics( - // (7,25): error CS0570: 'TestRef.P' is not supported by the language - // var value = obj.P; - Diagnostic(ErrorCode.ERR_BindToBogus, "P").WithArguments("TestRef.P").WithLocation(7, 25)); + CompileAndVerify(code, additionalRefs: new[] { reference.EmitToImageReference() }, expectedOutput: "5"); } [Fact] - public void IsConstModReqIsRejectedOnSignaturesWithoutIsReadOnlyAttribute_Indexers_ReturnTypes() + public void CreatingLambdasOfDelegatesWithModifiersCanBeExecuted_ReturnTypes() { - var ilSource = @" -.class public auto ansi beforefieldinit TestRef extends [mscorlib]System.Object -{ - .custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string) = (01 00 04 49 74 65 6d 00 00) - - .field private int32 'value' - - .method public hidebysig specialname newslot virtual instance int32& get_Item (int32 p) cil managed - { - .maxstack 8 - IL_0000: ldarg.0 // Load argument 0 onto the stack - IL_0001: ldflda int32 TestRef::'value' // Push the address of field of object obj on the stack - IL_0006: ret // Return from method, possibly with a value - } + var reference = CreateStandardCompilation("public delegate ref readonly int D();"); - .method public hidebysig specialname rtspecialname instance void .ctor () cil managed - { - .maxstack 8 - IL_0000: ldarg.0 // Load argument 0 onto the stack - IL_0001: ldc.i4.0 // Push 0 onto the stack as int32 - IL_0002: stfld int32 TestRef::'value' // Replace the value of field of the object obj with value - IL_0007: ldarg.0 // Load argument 0 onto the stack - IL_0008: call instance void [mscorlib]System.Object::.ctor() // Call method indicated on the stack with arguments - IL_000d: nop // Do nothing (No operation) - IL_000e: ret // Return from method, possibly with a value - } + CompileAndVerify(reference, symbolValidator: module => + { + var method = module.ContainingAssembly.GetTypeByMetadataName("D").DelegateInvokeMethod; - .property instance int32& modreq([mscorlib]System.Runtime.CompilerServices.IsConst) Item(int32 p) - { - .get instance int32& TestRef::get_Item(int32) - } -}"; + Assert.Empty(method.ReturnTypeCustomModifiers); + AssertSingleIsConstRequiredModifier(method.RefCustomModifiers); + }); var code = @" public class Test { + private static int value = 5; + public static void Main() { - var obj = new TestRef(); - var value = obj[5]; + Run(() => ref value); + } + + public static void Run(D lambda) + { + System.Console.WriteLine(lambda()); } }"; - CreateStandardCompilation(code, references: new[] { CompileIL(ilSource) }).VerifyDiagnostics( - // (7,21): error CS0570: 'TestRef.this[int]' is not supported by the language - // var value = obj[5]; - Diagnostic(ErrorCode.ERR_BindToBogus, "obj[5]").WithArguments("TestRef.this[int]").WithLocation(7, 21)); + CompileAndVerify(code, additionalRefs: new[] { reference.EmitToImageReference() }, expectedOutput: "5"); } private void AssertSingleIsConstRequiredModifier(ImmutableArray modifiers) diff --git a/src/Compilers/Core/Portable/MetadataReader/MetadataDecoder.cs b/src/Compilers/Core/Portable/MetadataReader/MetadataDecoder.cs index 512635fe5e38dcc48e091ed0380f9447cb84f0ea..0f0a075387028d283fcdbe9ed99c4fe1dbaa4941 100644 --- a/src/Compilers/Core/Portable/MetadataReader/MetadataDecoder.cs +++ b/src/Compilers/Core/Portable/MetadataReader/MetadataDecoder.cs @@ -202,7 +202,7 @@ private TypeSymbol DecodeTypeOrThrow(ref BlobReader ppSig, SignatureTypeCode typ int countOfSizes; int countOfLowerBounds; - modifiers = DecodeModifiersOrThrow(ref ppSig, out typeCode); + modifiers = DecodeModifiersOrThrow(ref ppSig, AllowedRequiredModifierType.None, out typeCode, out _); typeSymbol = DecodeTypeOrThrow(ref ppSig, typeCode, out refersToNoPiaLocalType); if (!ppSig.TryReadCompressedInteger(out countOfDimensions) || !ppSig.TryReadCompressedInteger(out countOfSizes)) @@ -285,13 +285,13 @@ private TypeSymbol DecodeTypeOrThrow(ref BlobReader ppSig, SignatureTypeCode typ break; case SignatureTypeCode.SZArray: - modifiers = DecodeModifiersOrThrow(ref ppSig, out typeCode); + modifiers = DecodeModifiersOrThrow(ref ppSig, AllowedRequiredModifierType.None, out typeCode, out _); typeSymbol = DecodeTypeOrThrow(ref ppSig, typeCode, out refersToNoPiaLocalType); typeSymbol = GetSZArrayTypeSymbol(typeSymbol, modifiers); break; case SignatureTypeCode.Pointer: - modifiers = DecodeModifiersOrThrow(ref ppSig, out typeCode); + modifiers = DecodeModifiersOrThrow(ref ppSig, AllowedRequiredModifierType.None, out typeCode, out _); typeSymbol = DecodeTypeOrThrow(ref ppSig, typeCode, out refersToNoPiaLocalType); typeSymbol = MakePointerTypeSymbol(typeSymbol, modifiers); break; @@ -350,7 +350,7 @@ private TypeSymbol DecodeGenericTypeInstanceOrThrow(ref BlobReader ppSig, out bo { bool argumentRefersToNoPia; SignatureTypeCode typeCode; - ImmutableArray> modifiers = DecodeModifiersOrThrow(ref ppSig, out typeCode); + ImmutableArray> modifiers = DecodeModifiersOrThrow(ref ppSig, AllowedRequiredModifierType.None, out typeCode, out _); argumentsBuilder.Add(KeyValuePair.Create(DecodeTypeOrThrow(ref ppSig, typeCode, out argumentRefersToNoPia), modifiers)); argumentRefersToNoPiaLocalTypeBuilder.Add(argumentRefersToNoPia); } @@ -670,52 +670,18 @@ private TypeSymbol GetTypeOfTypeDef(TypeDefinitionHandle typeDef, out bool isNoP } } - /// If the encoded type is invalid. - /// An exception from metadata reader. - private ImmutableArray> DecodeModifiersOrThrow(ref BlobReader signatureReader, out SignatureTypeCode typeCode) - { - ArrayBuilder> modifiers = null; - - for (;;) - { - typeCode = signatureReader.ReadSignatureTypeCode(); - - if (typeCode == SignatureTypeCode.RequiredModifier) - { - throw new UnsupportedSignatureContent(); - } - - if (typeCode == SignatureTypeCode.OptionalModifier) - { - ModifierInfo modifier = new ModifierInfo(true, DecodeModifierTypeOrThrow(ref signatureReader)); - - if (modifiers == null) - { - modifiers = ArrayBuilder>.GetInstance(); - } - - modifiers.Add(modifier); - continue; - } - - break; - } - - return modifiers?.ToImmutableAndFree() ?? default(ImmutableArray>); - } - /// If the encoded type is invalid. /// An exception from metadata reader. private ImmutableArray> DecodeModifiersOrThrow( ref BlobReader signatureReader, + AllowedRequiredModifierType allowedRequiredModifierType, out SignatureTypeCode typeCode, - Func acceptRequiredModifier, out bool requiredModifierFound) { requiredModifierFound = false; ArrayBuilder> modifiers = null; - for (;;) + for (; ; ) { typeCode = signatureReader.ReadSignatureTypeCode(); bool isOptional; @@ -735,10 +701,21 @@ private ImmutableArray> DecodeModifiersOrThrow(ref Blob TypeSymbol type = DecodeModifierTypeOrThrow(ref signatureReader); - // if it is a required modifier, make sure the compiler supports this modifier type if (!isOptional) { - if (acceptRequiredModifier(type)) + var isAllowed = false; + + switch (allowedRequiredModifierType) + { + case AllowedRequiredModifierType.System_Runtime_CompilerServices_IsConst: + isAllowed = IsAcceptedIsConstModifierType(type); + break; + case AllowedRequiredModifierType.System_Runtime_CompilerServices_Volatile: + isAllowed = IsAcceptedVolatileModifierType(type); + break; + } + + if (isAllowed) { requiredModifierFound = true; } @@ -903,7 +880,7 @@ internal LocalInfo DecodeLocalVariableOrThrow(ref BlobReader signatu { SignatureTypeCode typeCode; - var customModifiers = DecodeModifiersOrThrow(ref signatureReader, out typeCode); + var customModifiers = DecodeModifiersOrThrow(ref signatureReader, AllowedRequiredModifierType.None, out typeCode, out _); var constraints = LocalSlotConstraints.None; TypeSymbol typeSymbol; @@ -944,7 +921,7 @@ internal void DecodeLocalConstantBlobOrThrow(ref BlobReader sigReader, out TypeS { SignatureTypeCode typeCode; - var customModifiers = DecodeModifiersOrThrow(ref sigReader, out typeCode); + var customModifiers = DecodeModifiersOrThrow(ref sigReader, AllowedRequiredModifierType.None, out typeCode, out _); if (typeCode == SignatureTypeCode.TypeHandle) { @@ -1150,16 +1127,17 @@ internal ImmutableArray> GetLocalInfo(StandaloneSignatureH /// If the encoded parameter type is invalid. private void DecodeParameterOrThrow(ref BlobReader signatureReader, /*out*/ ref ParamInfo info) { - bool refersToNoPiaLocalType; - - SignatureTypeCode typeCode; - info.CustomModifiers = DecodeModifiersOrThrow(ref signatureReader, out typeCode, IsAcceptedIsConstModifierType, out bool isConstFound); + info.CustomModifiers = DecodeModifiersOrThrow( + ref signatureReader, + AllowedRequiredModifierType.System_Runtime_CompilerServices_IsConst, + out SignatureTypeCode typeCode, + out bool isConstFound); if (typeCode == SignatureTypeCode.ByReference) { info.IsByRef = true; info.RefCustomModifiers = info.CustomModifiers; - info.CustomModifiers = DecodeModifiersOrThrow(ref signatureReader, out typeCode); + info.CustomModifiers = DecodeModifiersOrThrow(ref signatureReader, AllowedRequiredModifierType.None, out typeCode, out _); } else if (isConstFound) { @@ -1167,7 +1145,7 @@ private void DecodeParameterOrThrow(ref BlobReader signatureReader, /*out*/ ref throw new UnsupportedSignatureContent(); } - info.Type = DecodeTypeOrThrow(ref signatureReader, typeCode, out refersToNoPiaLocalType); + info.Type = DecodeTypeOrThrow(ref signatureReader, typeCode, out _); } // MetaImport::DecodeMethodSignature @@ -1907,11 +1885,13 @@ protected TypeSymbol DecodeFieldSignature(ref BlobReader signatureReader, out bo try { SignatureTypeCode typeCode; - customModifiers = DecodeModifiersOrThrow(ref signatureReader, out typeCode, IsAcceptedVolatileModifierType, out isVolatile); + customModifiers = DecodeModifiersOrThrow( + ref signatureReader, + AllowedRequiredModifierType.System_Runtime_CompilerServices_Volatile, + out typeCode, + out isVolatile); - // get the type - bool refersToNoPiaLocalType; - return DecodeTypeOrThrow(ref signatureReader, typeCode, out refersToNoPiaLocalType); + return DecodeTypeOrThrow(ref signatureReader, typeCode, out _); } catch (UnsupportedSignatureContent) { @@ -2426,5 +2406,12 @@ internal bool DoesSignatureMatchEvent(TypeSymbol eventType, ParamInfo - Public Sub NonVirtualReadOnlySignaturesAreRead() + Public Sub ReadOnlySignaturesAreRead_Methods_Parameters_Static() + Dim reference = CreateCSharpCompilation(" +public class TestRef +{ + public static void M(ref readonly int x) + { + System.Console.WriteLine(x); + } +}", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = + + +Class Test + Shared Sub Main() + Dim x = 5 + TestRef.M(x) + End Sub +End Class + + + + CompileAndVerify(source, additionalRefs:={reference}, expectedOutput:="5") + End Sub + + + Public Sub ReadOnlySignaturesAreRead_Methods_Parameters_NoModifiers() Dim reference = CreateCSharpCompilation(" public class TestRef { @@ -35,6 +61,61 @@ End Class CompileAndVerify(source, additionalRefs:={reference}, expectedOutput:="5") End Sub + + Public Sub ReadOnlySignaturesAreRead_Indexers_Parameters_NoModifiers() + Dim reference = CreateCSharpCompilation(" +public class TestRef +{ + public int this[ref readonly int p] + { + set + { + System.Console.WriteLine(p); + } + } +}", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = + + +Class Test + Shared Sub Main() + Dim x = 5 + Dim obj = New TestRef() + obj(x) = 0 + End Sub +End Class + + + + CompileAndVerify(source, additionalRefs:={reference}, expectedOutput:="5") + End Sub + + + Public Sub ReadOnlySignaturesAreRead_Operators_Constructors() + Dim reference = CreateCSharpCompilation(" +public struct TestRef +{ + public TestRef(ref readonly int value) + { + System.Console.WriteLine(value); + } +}", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = + + +Class Test + Shared Sub Main() + Dim obj1 = New TestRef(4) + End Sub +End Class + + + + CompileAndVerify(source, additionalRefs:={reference}, expectedOutput:="4") + End Sub + Public Sub ReadOnlySignaturesAreNotSupported_Methods_Parameters_Virtual() Dim reference = CreateCSharpCompilation(" @@ -68,6 +149,35 @@ BC30657: 'M' has a return type that is not supported or parameter types that are ) End Sub + + Public Sub ReadOnlySignaturesAreNotSupported_Methods_Parameters_Abstract() + Dim reference = CreateCSharpCompilation(" +public abstract class TestRef +{ + public abstract void M(ref readonly int x); +}", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = + + +Class Test + Shared Sub Main(obj As TestRef) + Dim x = 5 + obj.M(x) + End Sub +End Class + + + + Dim compilation = CreateCompilationWithMscorlib(source, references:={reference}) + + AssertTheseDiagnostics(compilation, +BC30657: 'M' has a return type that is not supported or parameter types that are not supported. + obj.M(x) + ~ +) + End Sub + Public Sub ReadOnlySignaturesAreNotSupported_Methods_ReturnTypes_Virtual() Dim reference = CreateCSharpCompilation(" @@ -101,6 +211,99 @@ BC30657: 'M' has a return type that is not supported or parameter types that are ) End Sub + + Public Sub ReadOnlySignaturesAreNotSupported_Methods_ReturnTypes_Abstract() + Dim reference = CreateCSharpCompilation(" +public abstract class TestRef +{ + public abstract ref readonly int M(); +}", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = + + +Class Test + Shared Sub Main(obj As TestRef) + obj.M() + End Sub +End Class + + + + Dim compilation = CreateCompilationWithMscorlib(source, references:={reference}) + + AssertTheseDiagnostics(compilation, +BC30657: 'M' has a return type that is not supported or parameter types that are not supported. + obj.M() + ~ + ) + End Sub + + + Public Sub ReadOnlySignaturesAreNotSupported_Methods_ReturnTypes_Static() + Dim reference = CreateCSharpCompilation(" +public class TestRef +{ + private static int value = 0; + public static ref readonly int M() + { + return ref value; + } +}", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = + + +Class Test + Shared Sub Main() + TestRef.M() + End Sub +End Class + + + + Dim compilation = CreateCompilationWithMscorlib(source, references:={reference}) + + AssertTheseDiagnostics(compilation, +BC30657: 'M' has a return type that is not supported or parameter types that are not supported. + TestRef.M() + ~ + ) + End Sub + + + Public Sub ReadOnlySignaturesAreNotSupported_Methods_ReturnTypes_NoModifiers() + Dim reference = CreateCSharpCompilation(" +public class TestRef +{ + private int value = 0; + public ref readonly int M() + { + return ref value; + } +}", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = + + +Class Test + Shared Sub Main() + Dim obj = New TestRef() + obj.M() + End Sub +End Class + + + + Dim compilation = CreateCompilationWithMscorlib(source, references:={reference}) + + AssertTheseDiagnostics(compilation, +BC30657: 'M' has a return type that is not supported or parameter types that are not supported. + obj.M() + ~ + ) + End Sub + Public Sub ReadOnlySignaturesAreNotSupported_Properties_Virtual() Dim reference = CreateCSharpCompilation(" @@ -131,6 +334,152 @@ BC30643: Property 'P' is of an unsupported type. ) End Sub + + Public Sub ReadOnlySignaturesAreNotSupported_Properties_Static() + Dim reference = CreateCSharpCompilation(" +public class TestRef +{ + private static int value = 0; + public static ref readonly int P => ref value; +}", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = + + +Class Test + Shared Sub Main() + Dim value = TestRef.P + End Sub +End Class + + + + Dim compilation = CreateCompilationWithMscorlib(source, references:={reference}) + + AssertTheseDiagnostics(compilation, +BC30643: Property 'P' is of an unsupported type. + Dim value = TestRef.P + ~ + ) + End Sub + + + Public Sub ReadOnlySignaturesAreNotSupported_Properties_NoModifiers() + Dim reference = CreateCSharpCompilation(" +public class TestRef +{ + private int value = 0; + public ref readonly int P => ref value; +}", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = + + +Class Test + Shared Sub Main() + Dim obj = New TestRef() + Dim value = obj.P + End Sub +End Class + + + + Dim compilation = CreateCompilationWithMscorlib(source, references:={reference}) + + AssertTheseDiagnostics(compilation, +BC30643: Property 'P' is of an unsupported type. + Dim value = obj.P + ~ + ) + End Sub + + + Public Sub ReadOnlySignaturesAreNotSupported_Properties_Abstract() + Dim reference = CreateCSharpCompilation(" +public abstract class TestRef +{ + public abstract ref readonly int P { get; } +}", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = + + +Class Test + Shared Sub Main(obj As TestRef) + Dim value = obj.P + End Sub +End Class + + + + Dim compilation = CreateCompilationWithMscorlib(source, references:={reference}) + + AssertTheseDiagnostics(compilation, +BC30643: Property 'P' is of an unsupported type. + Dim value = obj.P + ~ + ) + End Sub + + + Public Sub ReadOnlySignaturesAreNotSupported_Indexers_Parameters_Virtual() + Dim reference = CreateCSharpCompilation(" +public class TestRef +{ + public virtual int this[ref readonly int p] => 0; +}", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = + + +Class Test + Shared Sub Main() + Dim p = 0 + Dim obj = New TestRef() + Dim value = obj(p) + End Sub +End Class + + + + Dim compilation = CreateCompilationWithMscorlib(source, references:={reference}) + + AssertTheseDiagnostics(compilation, +BC30643: Property 'TestRef.Item(p As )' is of an unsupported type. + Dim value = obj(p) + ~~~ + ) + End Sub + + + Public Sub ReadOnlySignaturesAreNotSupported_Indexers_Parameters_Abstract() + Dim reference = CreateCSharpCompilation(" +public abstract class TestRef +{ + public abstract int this[ref readonly int p] { set; } +}", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = + + +Class Test + Shared Sub Main(obj As TestRef) + Dim p = 0 + Dim value = obj(p) + End Sub +End Class + + + + Dim compilation = CreateCompilationWithMscorlib(source, references:={reference}) + + AssertTheseDiagnostics(compilation, +BC30643: Property 'TestRef.Item(p As )' is of an unsupported type. + Dim value = obj(p) + ~~~ + ) + End Sub + Public Sub ReadOnlySignaturesAreNotSupported_Indexers_ReturnTypes_Virtual() Dim reference = CreateCSharpCompilation(" @@ -162,11 +511,40 @@ BC30643: Property 'TestRef.Item(p As )' is of an unsupported type. End Sub - Public Sub ReadOnlySignaturesAreNotSupported_Indexers_Parameters_Virtual() + Public Sub ReadOnlySignaturesAreNotSupported_Indexers_ReturnTypes_Abstract() + Dim reference = CreateCSharpCompilation(" +public abstract class TestRef +{ + public abstract ref readonly int this[int p] { get; } +}", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = + + +Class Test + Shared Sub Main(obj As TestRef) + Dim value = obj(0) + End Sub +End Class + + + + Dim compilation = CreateCompilationWithMscorlib(source, references:={reference}) + + AssertTheseDiagnostics(compilation, +BC30643: Property 'TestRef.Item(p As )' is of an unsupported type. + Dim value = obj(0) + ~~~ + ) + End Sub + + + Public Sub ReadOnlySignaturesAreNotSupported_Indexers_ReturnTypes_NoModifiers() Dim reference = CreateCSharpCompilation(" public class TestRef { - public virtual int this[ref readonly int p] => 0; + private int value = 0; + public ref readonly int this[int p] => ref value; }", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() Dim source = @@ -174,9 +552,8 @@ public class TestRef Class Test Shared Sub Main() - Dim p = 0 Dim obj = New TestRef() - Dim value = obj(p) + Dim value = obj(0) End Sub End Class @@ -186,10 +563,63 @@ End Class AssertTheseDiagnostics(compilation, BC30643: Property 'TestRef.Item(p As )' is of an unsupported type. - Dim value = obj(p) + Dim value = obj(0) ~~~ ) End Sub + + + Public Sub UsingLambdasOfRefReadOnlyDelegatesIsNotSupported_Parameters() + Dim reference = CreateCSharpCompilation(" +public delegate void D(ref readonly int p); +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = + + +Class Test + Shared Sub Main(lambda As D) + Dim x = 0 + lambda(x) + End Sub +End Class + + + + Dim compilation = CreateCompilationWithMscorlib(source, references:={reference}) + + AssertTheseDiagnostics(compilation, +BC30657: 'D' has a return type that is not supported or parameter types that are not supported. + lambda(x) + ~~~~~~ + ) + End Sub + + + Public Sub UsingLambdasOfRefReadOnlyDelegatesIsNotSupported_ReturnTypes() + Dim reference = CreateCSharpCompilation(" +public delegate ref readonly int D(); +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = + + +Class Test + Shared Sub Main(lambda As D) + Dim x = lambda() + End Sub +End Class + + + + Dim compilation = CreateCompilationWithMscorlib(source, references:={reference}) + + AssertTheseDiagnostics(compilation, +BC30657: 'D' has a return type that is not supported or parameter types that are not supported. + Dim x = lambda() + ~~~~~~ + ) + End Sub End Class End Namespace \ No newline at end of file