|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable disable
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
public class AttributeTests_RefReadOnly : CSharpTestBase
{
[Fact]
public void RefReadOnlyIsWrittenToMetadata_SameAssembly_Method()
{
var text = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute { }
}
class Test
{
public ref readonly int M(in int x) { return ref x; }
}
";
CompileAndVerify(text, verify: Verification.Fails, symbolValidator: module =>
{
var method = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("M");
Assert.Equal(RefKind.RefReadOnly, method.RefKind);
Assert.True(method.ReturnsByRefReadonly);
var parameter = method.GetParameters().Single();
Assert.Equal(RefKind.In, parameter.RefKind);
Assert.Empty(parameter.GetAttributes());
Assert.Empty(method.GetReturnTypeAttributes());
var peModule = (PEModuleSymbol)module;
Assert.True(peModule.Module.HasIsReadOnlyAttribute(((PEMethodSymbol)method).Signature.ReturnParam.Handle));
Assert.True(peModule.Module.HasIsReadOnlyAttribute(((PEParameterSymbol)parameter).Handle));
AssertDeclaresType(peModule, WellKnownType.System_Runtime_CompilerServices_IsReadOnlyAttribute, Accessibility.Public);
});
}
[Fact]
public void InIsWrittenToMetadata_NeedsToBeGenerated_Method_Parameter()
{
var text = @"
class Test
{
public void M(in int x) { }
}
";
CompileAndVerify(text, symbolValidator: module =>
{
var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("M").GetParameters().Single();
Assert.Equal(RefKind.In, parameter.RefKind);
Assert.Empty(parameter.GetAttributes());
var peModule = (PEModuleSymbol)module;
Assert.True(peModule.Module.HasIsReadOnlyAttribute(((PEParameterSymbol)parameter).Handle));
AssertDeclaresType(peModule, WellKnownType.System_Runtime_CompilerServices_IsReadOnlyAttribute, Accessibility.Internal);
});
}
[Fact]
public void RefReadOnlyIsWrittenToMetadata_NeedsToBeGenerated_Method_ReturnType()
{
var text = @"
class Test
{
private int x;
public ref readonly int M() { return ref x; }
}
";
CompileAndVerify(text, symbolValidator: module =>
{
var method = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("M");
Assert.Equal(RefKind.RefReadOnly, method.RefKind);
Assert.True(method.ReturnsByRefReadonly);
Assert.Empty(method.GetReturnTypeAttributes());
});
}
[Fact]
public void RefReadOnlyIsWrittenToMetadata_DifferentAssembly_Method()
{
var codeA = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute { }
}";
var referenceA = CreateCompilation(codeA).VerifyDiagnostics().ToMetadataReference();
var codeB = @"
class Test
{
public ref readonly int M(in int x) { return ref x; }
}
";
CompileAndVerify(codeB, verify: Verification.Fails, references: new[] { referenceA }, symbolValidator: module =>
{
var method = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("M");
Assert.Equal(RefKind.RefReadOnly, method.RefKind);
Assert.True(method.ReturnsByRefReadonly);
var parameter = method.GetParameters().Single();
Assert.Equal(RefKind.In, parameter.RefKind);
Assert.Empty(parameter.GetAttributes());
Assert.Empty(method.GetReturnTypeAttributes());
AssertNoIsReadOnlyAttributeExists(module.ContainingAssembly);
});
}
[Fact]
public void RefReadOnlyIsWrittenToMetadata_SameAssembly_Operator()
{
var text = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute { }
}
struct Test
{
public static int operator +(in Test x, in Test y) { return 0; }
}
";
CompileAndVerify(text, symbolValidator: module =>
{
var method = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("op_Addition");
Assert.Equal(2, method.ParameterCount);
foreach (var parameter in method.Parameters)
{
Assert.Equal(RefKind.In, parameter.RefKind);
Assert.Empty(parameter.GetAttributes());
}
});
}
[Fact]
public void InIsWrittenToMetadata_NeedsToBeGenerated_Operator_Parameter()
{
var text = @"
struct Test
{
public static int operator +(in Test x, in Test y) { return 0; }
}
";
CompileAndVerify(text, symbolValidator: module =>
{
var method = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("op_Addition");
Assert.Equal(2, method.ParameterCount);
foreach (var parameter in method.Parameters)
{
Assert.Empty(parameter.GetAttributes());
}
});
}
[Fact]
public void RefReadOnlyIsWrittenToMetadata_Operator_Method()
{
var codeA = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute { }
}";
var referenceA = CreateCompilation(codeA).VerifyDiagnostics().ToMetadataReference();
var codeB = @"
struct Test
{
public static int operator +(in Test x, in Test y) { return 0; }
}
";
CompileAndVerify(codeB, references: new[] { referenceA }, symbolValidator: module =>
{
var method = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("op_Addition");
Assert.Equal(2, method.ParameterCount);
foreach (var parameter in method.Parameters)
{
Assert.Equal(RefKind.In, parameter.RefKind);
Assert.Empty(parameter.GetAttributes());
}
AssertNoIsReadOnlyAttributeExists(module.ContainingAssembly);
});
}
[Fact]
public void RefReadOnlyIsWrittenToMetadata_SameAssembly_Constructor()
{
var text = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute { }
}
class Test
{
public Test(in int x) { }
}
";
CompileAndVerify(text, symbolValidator: module =>
{
var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod(".ctor").Parameters.Single();
Assert.Equal(RefKind.In, parameter.RefKind);
Assert.Empty(parameter.GetAttributes());
});
}
[Fact]
public void InIsWrittenToMetadata_NeedsToBeGenerated_Constructor_Parameter()
{
var text = @"
class Test
{
public Test(in int x) { }
}
";
CompileAndVerify(text, symbolValidator: module =>
{
var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod(".ctor").Parameters.Single();
Assert.Empty(parameter.GetAttributes());
});
}
[Fact]
public void RefReadOnlyIsWrittenToMetadata_Constructor_Method()
{
var codeA = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute { }
}";
var referenceA = CreateCompilation(codeA).VerifyDiagnostics().ToMetadataReference();
var codeB = @"
class Test
{
public Test(in int x) { }
}
";
CompileAndVerify(codeB, references: new[] { referenceA }, symbolValidator: module =>
{
var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod(".ctor").Parameters.Single();
Assert.Equal(RefKind.In, parameter.RefKind);
Assert.Empty(parameter.GetAttributes());
AssertNoIsReadOnlyAttributeExists(module.ContainingAssembly);
});
}
[Fact]
public void RefReadOnlyIsWrittenToMetadata_SameAssembly_Property()
{
var text = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute { }
}
class Test
{
private int x = 0;
public ref readonly int P1 { get { return ref x; } }
public ref readonly int P2 => ref x;
}
";
CompileAndVerify(text, symbolValidator: module =>
{
var type = module.ContainingAssembly.GetTypeByMetadataName("Test");
AssertProperty(type.GetProperty("P1"));
AssertProperty(type.GetProperty("P2"));
void AssertProperty(PropertySymbol property)
{
Assert.Equal(RefKind.RefReadOnly, property.RefKind);
Assert.True(property.ReturnsByRefReadonly);
Assert.Empty(property.GetAttributes());
}
});
}
[Fact]
public void RefReadOnlyIsWrittenToMetadata_NeedsToBeGenerated_Property()
{
var text = @"
class Test
{
private int x = 0;
public ref readonly int P1 { get { return ref x; } }
public ref readonly int P2 => ref x;
}
";
CompileAndVerify(text, symbolValidator: module =>
{
var type = module.ContainingAssembly.GetTypeByMetadataName("Test");
AssertProperty(type.GetProperty("P1"));
AssertProperty(type.GetProperty("P2"));
void AssertProperty(PropertySymbol property)
{
Assert.Equal(RefKind.RefReadOnly, property.RefKind);
Assert.True(property.ReturnsByRefReadonly);
Assert.Empty(property.GetAttributes());
}
});
}
[Fact]
public void RefReadOnlyIsWrittenToMetadata_DifferentAssembly_Property()
{
var codeA = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute { }
}";
var referenceA = CreateCompilation(codeA).VerifyDiagnostics().ToMetadataReference();
var codeB = @"
class Test
{
private int x = 0;
public ref readonly int P1 { get { return ref x; } }
public ref readonly int P2 => ref x;
}
";
CompileAndVerify(codeB, references: new[] { referenceA }, symbolValidator: module =>
{
var type = module.ContainingAssembly.GetTypeByMetadataName("Test");
AssertProperty(type.GetProperty("P1"));
AssertProperty(type.GetProperty("P2"));
void AssertProperty(PropertySymbol property)
{
Assert.Equal(RefKind.RefReadOnly, property.RefKind);
Assert.True(property.ReturnsByRefReadonly);
Assert.Empty(property.GetAttributes());
AssertNoIsReadOnlyAttributeExists(module.ContainingAssembly);
}
});
}
[Fact]
public void RefReadOnlyIsWrittenToMetadata_SameAssembly_Indexer()
{
var text = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute { }
}
class Test
{
public ref readonly int this[in int x] { get { return ref x; } }
}
";
CompileAndVerify(text, verify: Verification.Fails, symbolValidator: module =>
{
var indexer = module.ContainingAssembly.GetTypeByMetadataName("Test").GetProperty("this[]");
Assert.Equal(RefKind.RefReadOnly, indexer.RefKind);
Assert.True(indexer.ReturnsByRefReadonly);
var parameter = indexer.GetParameters().Single();
Assert.Equal(RefKind.In, parameter.RefKind);
Assert.Empty(parameter.GetAttributes());
Assert.Empty(indexer.GetAttributes());
});
}
[Fact]
public void InIsWrittenToMetadata_NeedsToBeGenerated_Indexer_Parameter()
{
var text = @"
class Test
{
public int this[in int x] { get { return x; } }
}
";
CompileAndVerify(text, symbolValidator: module =>
{
var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetProperty("this[]").GetParameters().Single();
Assert.Equal(RefKind.In, parameter.RefKind);
Assert.Empty(parameter.GetAttributes());
});
}
[Fact]
public void RefReadOnlyIsWrittenToMetadata_NeedsToBeGenerated_Indexer_ReturnType()
{
var text = @"
class Test
{
private int x;
public ref readonly int this[int p] { get { return ref x; } }
}
";
CompileAndVerify(text, symbolValidator: module =>
{
var indexer = module.ContainingAssembly.GetTypeByMetadataName("Test").GetProperty("this[]");
Assert.Equal(RefKind.RefReadOnly, indexer.RefKind);
Assert.True(indexer.ReturnsByRefReadonly);
Assert.Empty(indexer.GetAttributes());
});
}
[Fact]
public void RefReadOnlyIsWrittenToMetadata_DifferentAssembly_Indexer()
{
var codeA = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute { }
}";
var referenceA = CreateCompilation(codeA).VerifyDiagnostics().ToMetadataReference();
var codeB = @"
class Test
{
public ref readonly int this[in int x] { get { return ref x; } }
}
";
CompileAndVerify(codeB, verify: Verification.Fails, references: new[] { referenceA }, symbolValidator: module =>
{
var indexer = module.ContainingAssembly.GetTypeByMetadataName("Test").GetProperty("this[]");
Assert.Equal(RefKind.RefReadOnly, indexer.RefKind);
Assert.True(indexer.ReturnsByRefReadonly);
var parameter = indexer.GetParameters().Single();
Assert.Equal(RefKind.In, parameter.RefKind);
Assert.Empty(parameter.GetAttributes());
Assert.Empty(indexer.GetAttributes());
AssertNoIsReadOnlyAttributeExists(module.ContainingAssembly);
});
}
[Fact]
public void RefReadOnlyIsWrittenToMetadata_SameAssembly_Delegate()
{
var text = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute { }
}
public delegate ref readonly int D(in int x);
";
CompileAndVerify(text, symbolValidator: module =>
{
var method = module.ContainingAssembly.GetTypeByMetadataName("D").DelegateInvokeMethod;
Assert.Equal(RefKind.RefReadOnly, method.RefKind);
Assert.True(method.ReturnsByRefReadonly);
var parameter = method.GetParameters().Single();
Assert.Equal(RefKind.In, parameter.RefKind);
Assert.Empty(parameter.GetAttributes());
Assert.Empty(method.GetReturnTypeAttributes());
});
}
[Fact]
public void InIsWrittenToMetadata_NeedsToBeGenerated_Delegate_Parameter()
{
var text = @"
public delegate void D(in int x);
";
CompileAndVerify(text, symbolValidator: module =>
{
var parameter = module.ContainingAssembly.GetTypeByMetadataName("D").DelegateInvokeMethod.GetParameters().Single();
Assert.Equal(RefKind.In, parameter.RefKind);
Assert.Empty(parameter.GetAttributes());
});
}
[Fact]
public void RefReadOnlyIsWrittenToMetadata_NeedsToBeGenerated_Delegate_ReturnType()
{
var text = @"
public delegate ref readonly int D();
";
CompileAndVerify(text, symbolValidator: module =>
{
var method = module.ContainingAssembly.GetTypeByMetadataName("D").DelegateInvokeMethod;
Assert.Equal(RefKind.RefReadOnly, method.RefKind);
Assert.True(method.ReturnsByRefReadonly);
Assert.Empty(method.GetReturnTypeAttributes());
});
}
[Fact]
public void RefReadOnlyIsWrittenToMetadata_DifferentAssembly_Delegate()
{
var codeA = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute { }
}";
var referenceA = CreateCompilation(codeA).VerifyDiagnostics().ToMetadataReference();
var codeB = @"
public delegate ref readonly int D(in int x);
";
CompileAndVerify(codeB, references: new[] { referenceA }, symbolValidator: module =>
{
var method = module.ContainingAssembly.GetTypeByMetadataName("D").DelegateInvokeMethod;
Assert.Equal(RefKind.RefReadOnly, method.RefKind);
Assert.True(method.ReturnsByRefReadonly);
var parameter = method.GetParameters().Single();
Assert.Equal(RefKind.In, parameter.RefKind);
Assert.Empty(parameter.GetAttributes());
Assert.Empty(method.GetReturnTypeAttributes());
AssertNoIsReadOnlyAttributeExists(module.ContainingAssembly);
});
}
[Fact]
public void RefReadOnlyIsWrittenToMetadata_SameAssembly_LocalFunctions()
{
var text = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute { }
}
public class Test
{
public void M()
{
ref readonly int Inner(in int x)
{
return ref x;
}
}
}
";
var options = TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All);
CompileAndVerify(text, verify: Verification.Fails, options: options, symbolValidator: module =>
{
var method = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("<M>g__Inner|0_0");
Assert.Equal(RefKind.RefReadOnly, method.RefKind);
Assert.True(method.ReturnsByRefReadonly);
var parameter = method.GetParameters().Single();
Assert.Equal(RefKind.In, parameter.RefKind);
Assert.Empty(parameter.GetAttributes());
Assert.Empty(method.GetReturnTypeAttributes());
});
}
[Fact]
public void InIsWrittenToMetadata_NeedsToBeGenerated_LocalFunctions_Parameters()
{
var text = @"
public class Test
{
public void M()
{
void Inner(in int x) { }
}
}
";
var options = TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All);
CompileAndVerify(text, options: options, symbolValidator: module =>
{
var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("<M>g__Inner|0_0").GetParameters().Single();
Assert.Equal(RefKind.In, parameter.RefKind);
Assert.Empty(parameter.GetAttributes());
});
}
[Fact]
public void RefReadOnlyIsWrittenToMetadata_NeedsToBeGenerated_LocalFunctions_ReturnType()
{
var text = @"
public class Test
{
private int x;
public void M()
{
ref readonly int Inner()
{
return ref x;
}
}
}
";
var options = TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All);
CompileAndVerify(text, verify: Verification.Fails, options: options, symbolValidator: module =>
{
var method = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("<M>g__Inner|1_0");
Assert.Equal(RefKind.RefReadOnly, method.RefKind);
Assert.True(method.ReturnsByRefReadonly);
Assert.Empty(method.GetReturnTypeAttributes());
});
}
[Fact]
public void RefReadOnlyIsWrittenToMetadata_DifferentAssembly_LocalFunctions()
{
var codeA = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute { }
}";
var referenceA = CreateCompilation(codeA).VerifyDiagnostics().ToMetadataReference();
var codeB = @"
public class Test
{
public void M()
{
ref readonly int Inner(in int x)
{
return ref x;
}
}
}
";
var options = TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All);
CompileAndVerify(codeB, verify: Verification.Fails, references: new[] { referenceA }, options: options, symbolValidator: module =>
{
var method = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("<M>g__Inner|0_0");
Assert.Equal(RefKind.RefReadOnly, method.RefKind);
Assert.True(method.ReturnsByRefReadonly);
var parameter = method.GetParameters().Single();
Assert.Equal(RefKind.In, parameter.RefKind);
Assert.Empty(parameter.GetAttributes());
Assert.Empty(method.GetReturnTypeAttributes());
AssertNoIsReadOnlyAttributeExists(module.ContainingAssembly);
});
}
[Fact]
public void RefReadOnlyIsWrittenToMetadata_SameAssembly_Lambda()
{
var text = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute { }
}
delegate ref readonly int D(in int x);
class Test
{
public void M1()
{
M2((in int x) => ref x);
}
public void M2(D value) { }
}
";
var options = TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All);
CompileAndVerify(text, verify: Verification.Fails, options: options, symbolValidator: module =>
{
var method = module.GlobalNamespace.GetMember<MethodSymbol>("Test.<>c.<M1>b__0_0");
Assert.Equal(RefKind.RefReadOnly, method.RefKind);
Assert.True(method.ReturnsByRefReadonly);
var parameter = method.GetParameters().Single();
Assert.Equal(RefKind.In, parameter.RefKind);
Assert.Empty(parameter.GetAttributes());
Assert.Empty(method.GetReturnTypeAttributes());
});
}
[Fact]
public void InIsWrittenToMetadata_NeedsToBeGenerated_Lambda_Parameter()
{
var text = @"
delegate void D(in int x);
class Test
{
public void M1()
{
M2((in int x) => {});
}
public void M2(D value) { }
}
";
var options = TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All);
CompileAndVerify(text, options: options, symbolValidator: module =>
{
var parameter = module.GlobalNamespace.GetMember<MethodSymbol>("Test.<>c.<M1>b__0_0").GetParameters().Single();
Assert.Equal(RefKind.In, parameter.RefKind);
Assert.Empty(parameter.GetAttributes());
});
}
[Fact]
public void RefReadOnlyIsWrittenToMetadata_NeedsToBeGenerated_Lambda_ReturnType()
{
var text = @"
delegate ref readonly int D();
class Test
{
private int x;
public void M1()
{
M2(() => ref x);
}
public void M2(D value) { }
}
";
var options = TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All);
CompileAndVerify(text, options: options, symbolValidator: module =>
{
var method = module.GlobalNamespace.GetMember<MethodSymbol>("Test.<M1>b__1_0");
Assert.Equal(RefKind.RefReadOnly, method.RefKind);
Assert.True(method.ReturnsByRefReadonly);
Assert.Empty(method.GetReturnTypeAttributes());
});
}
[Fact]
public void RefReadOnlyIsWrittenToMetadata_DifferentAssembly_Lambda()
{
var codeA = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute { }
}";
var referenceA = CreateCompilation(codeA).VerifyDiagnostics().ToMetadataReference();
var codeB = @"
delegate ref readonly int D(in int x);
class Test
{
public void M1()
{
M2((in int x) => ref x);
}
public void M2(D value) { }
}
";
var options = TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All);
CompileAndVerify(codeB, verify: Verification.Fails, options: options, references: new[] { referenceA }, symbolValidator: module =>
{
var method = module.GlobalNamespace.GetMember<MethodSymbol>("Test.<>c.<M1>b__0_0");
Assert.Equal(RefKind.RefReadOnly, method.RefKind);
Assert.True(method.ReturnsByRefReadonly);
var parameter = method.GetParameters().Single();
Assert.Equal(RefKind.In, parameter.RefKind);
Assert.Empty(parameter.GetAttributes());
Assert.Empty(method.GetReturnTypeAttributes());
AssertNoIsReadOnlyAttributeExists(module.ContainingAssembly);
});
}
[Fact]
public void IsReadOnlyAttributeIsDisallowedEverywhereInSource_Delegates()
{
var codeA = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute { }
}";
var referenceA = CreateCompilation(codeA).VerifyDiagnostics().ToMetadataReference();
var codeB = @"
using System.Runtime.CompilerServices;
[IsReadOnly]
public delegate ref readonly int D([IsReadOnly]in int x);
";
CreateCompilation(codeB, references: new[] { referenceA }).VerifyDiagnostics(
// (4,2): error CS8335: Do not use 'System.Runtime.CompilerServices.IsReadOnlyAttribute'. This is reserved for compiler usage.
// [IsReadOnly]
Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "IsReadOnly").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(4, 2),
// (5,37): error CS8335: Do not use 'System.Runtime.CompilerServices.IsReadOnlyAttribute'. This is reserved for compiler usage.
// public delegate ref readonly int D([IsReadOnly]in int x);
Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "IsReadOnly").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(5, 37));
}
[Fact]
public void IsReadOnlyAttributeIsDisallowedEverywhereInSource_Types()
{
var codeA = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute { }
}";
var referenceA = CreateCompilation(codeA).VerifyDiagnostics().ToMetadataReference();
var codeB = @"
using System.Runtime.CompilerServices;
[IsReadOnly]
public class Test
{
}
";
CreateCompilation(codeB, references: new[] { referenceA }).VerifyDiagnostics(
// (4,2): error CS8335: Do not use 'System.Runtime.CompilerServices.IsReadOnlyAttribute'. This is reserved for compiler usage.
// [IsReadOnly]
Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "IsReadOnly").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(4, 2));
}
[Fact]
public void IsReadOnlyAttributeIsDisallowedEverywhereInSource_Fields()
{
var codeA = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute { }
}";
var referenceA = CreateCompilation(codeA).VerifyDiagnostics().ToMetadataReference();
var codeB = @"
using System.Runtime.CompilerServices;
public class Test
{
[IsReadOnly]
private int x = 0;
public int X => x;
}
";
CreateCompilation(codeB, references: new[] { referenceA }).VerifyDiagnostics(
// (6,6): error CS8335: Do not use 'System.Runtime.CompilerServices.IsReadOnlyAttribute'. This is reserved for compiler usage.
// [IsReadOnly]
Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "IsReadOnly").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(6, 6));
}
[Fact]
public void IsReadOnlyAttributeIsDisallowedEverywhereInSource_Properties()
{
var codeA = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute { }
}";
var referenceA = CreateCompilation(codeA).VerifyDiagnostics().ToMetadataReference();
var codeB = @"
using System.Runtime.CompilerServices;
public class Test
{
private int x = 0;
[IsReadOnly]
public ref readonly int Property => ref x;
}
";
CreateCompilation(codeB, references: new[] { referenceA }).VerifyDiagnostics(
// (8,6): error CS8335: Do not use 'System.Runtime.CompilerServices.IsReadOnlyAttribute'. This is reserved for compiler usage.
// [IsReadOnly]
Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "IsReadOnly").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(8, 6));
}
[Fact]
public void IsReadOnlyAttributeIsDisallowedEverywhereInSource_Methods()
{
var codeA = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute { }
}";
var referenceA = CreateCompilation(codeA).VerifyDiagnostics().ToMetadataReference();
var codeB = @"
using System.Runtime.CompilerServices;
public class Test
{
[IsReadOnly]
[return: IsReadOnly]
public ref readonly int Method([IsReadOnly]in int x)
{
return ref x;
}
}
";
CreateCompilation(codeB, references: new[] { referenceA }).VerifyDiagnostics(
// (6,6): error CS8335: Do not use 'System.Runtime.CompilerServices.IsReadOnlyAttribute'. This is reserved for compiler usage.
// [IsReadOnly]
Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "IsReadOnly").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(6, 6),
// (7,14): error CS8335: Do not use 'System.Runtime.CompilerServices.IsReadOnlyAttribute'. This is reserved for compiler usage.
// [return: IsReadOnly]
Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "IsReadOnly").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(7, 14),
// (8,37): error CS8335: Do not use 'System.Runtime.CompilerServices.IsReadOnlyAttribute'. This is reserved for compiler usage.
// public ref readonly int Method([IsReadOnly]in int x)
Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "IsReadOnly").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(8, 37));
}
[Fact]
public void IsReadOnlyAttributeIsDisallowedEverywhereInSource_Indexers()
{
var codeA = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute { }
}";
var referenceA = CreateCompilation(codeA).VerifyDiagnostics().ToMetadataReference();
var codeB = @"
using System.Runtime.CompilerServices;
public class Test
{
[IsReadOnly]
public ref readonly int this[[IsReadOnly]in int x] { get { return ref x; } }
}
";
CreateCompilation(codeB, references: new[] { referenceA }).VerifyDiagnostics(
// (6,6): error CS8335: Do not use 'System.Runtime.CompilerServices.IsReadOnlyAttribute'. This is reserved for compiler usage.
// [IsReadOnly]
Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "IsReadOnly").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(6, 6),
// (7,35): error CS8335: Do not use 'System.Runtime.CompilerServices.IsReadOnlyAttribute'. This is reserved for compiler usage.
// public ref readonly int this[[IsReadOnly]in int x] { get { return ref x; } }
Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "IsReadOnly").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(7, 35));
}
[Fact]
public void UserReferencingEmbeddedAttributeShouldResultInAnError()
{
var code = @"
[Embedded]
public class Test
{
public ref readonly int M(in int p) => ref p;
}";
CreateCompilation(code).VerifyDiagnostics(
// (2,2): error CS0246: The type or namespace name 'EmbeddedAttribute' could not be found (are you missing a using directive or an assembly reference?)
// [Embedded]
Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Embedded").WithArguments("EmbeddedAttribute").WithLocation(2, 2),
// (2,2): error CS0246: The type or namespace name 'Embedded' could not be found (are you missing a using directive or an assembly reference?)
// [Embedded]
Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Embedded").WithArguments("Embedded").WithLocation(2, 2));
}
[Fact]
public void UserReferencingIsReadOnlyAttributeShouldResultInAnError()
{
var code = @"
[IsReadOnly]
public class Test
{
public ref readonly int M(in int p) => ref p;
}";
CreateCompilation(code).VerifyDiagnostics(
// (2,2): error CS0246: The type or namespace name 'IsReadOnlyAttribute' could not be found (are you missing a using directive or an assembly reference?)
// [IsReadOnly]
Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "IsReadOnly").WithArguments("IsReadOnlyAttribute").WithLocation(2, 2),
// (2,2): error CS0246: The type or namespace name 'IsReadOnly' could not be found (are you missing a using directive or an assembly reference?)
// [IsReadOnly]
Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "IsReadOnly").WithArguments("IsReadOnly").WithLocation(2, 2));
}
[Fact]
public void TypeReferencingAnotherTypeThatUsesAPublicAttributeFromAThirdNotReferencedAssemblyShouldGenerateItsOwn()
{
var options = TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All);
var code1 = CreateCompilation(@"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute { }
}");
var code2 = CreateCompilation(@"
public class Test1
{
public static ref readonly int M(in int p) => ref p;
}", references: new[] { code1.ToMetadataReference() }, options: options);
CompileAndVerify(code2, verify: Verification.Fails, symbolValidator: module =>
{
// IsReadOnly is not generated in assembly
var isReadOnlyAttributeName = WellKnownTypes.GetMetadataName(WellKnownType.System_Runtime_CompilerServices_IsReadOnlyAttribute);
Assert.Null(module.ContainingAssembly.GetTypeByMetadataName(isReadOnlyAttributeName));
});
var code3 = CreateCompilation(@"
public class Test2
{
public static ref readonly int M(in int p) => ref Test1.M(p);
}", references: new[] { code2.ToMetadataReference() }, options: options);
CompileAndVerify(code3, symbolValidator: module =>
{
// IsReadOnly is generated in assembly
AssertGeneratedEmbeddedAttribute(module.ContainingAssembly, AttributeDescription.CodeAnalysisEmbeddedAttribute.FullName);
AssertGeneratedEmbeddedAttribute(module.ContainingAssembly, AttributeDescription.IsReadOnlyAttribute.FullName);
});
}
[Fact]
public void BuildingAModuleRequiresIsReadOnlyAttributeToBeThere_Missing_SourceMethod()
{
var code = @"
public class Test
{
public void M(in int x) { }
}";
CreateCompilation(code, options: TestOptions.ReleaseModule).VerifyDiagnostics(
// (4,19): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsReadOnlyAttribute' is not defined or imported
// public void M(in int x) { }
Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "in int x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(4, 19));
}
[Fact]
public void BuildingAModuleRequiresIsReadOnlyAttributeToBeThere_Missing_SourceMethod_MultipleLocations()
{
var code = @"
public class Test
{
public void M1(in int x) { }
public void M2(in int x) { }
}";
CreateCompilation(code, options: TestOptions.ReleaseModule).VerifyDiagnostics(
// (4,20): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsReadOnlyAttribute' is not defined or imported
// public void M1(in int x) { }
Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "in int x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(4, 20),
// (5,20): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsReadOnlyAttribute' is not defined or imported
// public void M2(in int x) { }
Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "in int x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(5, 20));
}
[Fact]
public void BuildingAModuleRequiresIsReadOnlyAttributeToBeThere_Missing_LocalFunctions()
{
var code = @"
public class Test
{
public void Parent()
{
void child(in int p) { }
int x = 0;
child(x);
}
}";
CreateCompilation(code, options: TestOptions.ReleaseModule).VerifyDiagnostics(
// (6,20): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsReadOnlyAttribute' is not defined or imported
// void child(in int p) { }
Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "in int p").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(6, 20));
}
[Fact]
public void BuildingAModuleRequiresIsReadOnlyAttributeToBeThere_InAReference()
{
var reference = CreateCompilation(@"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute { }
}").ToMetadataReference();
var code = @"
public class Test
{
public void M(in int x) { }
}";
CompileAndVerify(code, verify: Verification.Fails, references: new[] { reference }, options: TestOptions.ReleaseModule, symbolValidator: module =>
{
AssertNoIsReadOnlyAttributeExists(module.ContainingAssembly);
var parameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("M").GetParameters().Single();
Assert.Equal(RefKind.In, parameter.RefKind);
Assert.Empty(parameter.GetAttributes());
});
}
[Fact]
public void ReferencingAnEmbeddedIsReadOnlyAttributeDoesNotUseIt_InternalsVisible()
{
var options = TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All);
var code1 = @"
[assembly:System.Runtime.CompilerServices.InternalsVisibleToAttribute(""Assembly2"")]
public class Test1
{
public static ref readonly int M(in int p) => ref p;
}";
var comp1 = CompileAndVerify(code1, options: options, verify: Verification.Fails, symbolValidator: module =>
{
AssertGeneratedEmbeddedAttribute(module.ContainingAssembly, AttributeDescription.CodeAnalysisEmbeddedAttribute.FullName);
AssertGeneratedEmbeddedAttribute(module.ContainingAssembly, AttributeDescription.IsReadOnlyAttribute.FullName);
});
var code2 = @"
public class Test2
{
public static ref readonly int M(in int p) => ref Test1.M(p);
}";
CompileAndVerify(code2, options: options.WithModuleName("Assembly2"), references: new[] { comp1.Compilation.ToMetadataReference() }, symbolValidator: module =>
{
AssertGeneratedEmbeddedAttribute(module.ContainingAssembly, AttributeDescription.CodeAnalysisEmbeddedAttribute.FullName);
AssertGeneratedEmbeddedAttribute(module.ContainingAssembly, AttributeDescription.IsReadOnlyAttribute.FullName);
});
}
[Fact]
public void IfIsReadOnlyAttributeIsDefinedThenEmbeddedIsNotGenerated()
{
var text = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute { }
}
class Test
{
public ref readonly int M(in int x) { return ref x; }
}
";
CompileAndVerify(text, references: new[] { RefSafetyRulesAttributeLib }, verify: Verification.Fails, symbolValidator: module =>
{
Assert.Null(module.ContainingAssembly.GetTypeByMetadataName(AttributeDescription.CodeAnalysisEmbeddedAttribute.FullName));
});
}
[Fact]
public void IsReadOnlyAttributeExistsWithWrongConstructorSignature_NetModule()
{
var text = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute
{
public IsReadOnlyAttribute(int p) { }
}
}
class Test
{
public void M(in int x) { }
}";
CreateCompilation(text, options: TestOptions.ReleaseModule).VerifyDiagnostics(
// (11,19): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor'
// public void M(in int x) { }
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "in int x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(11, 19));
}
[Fact]
public void IsReadOnlyAttributeExistsWithWrongConstructorSignature_Assembly()
{
var text = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute
{
public IsReadOnlyAttribute(int p) { }
}
}
class Test
{
public void M(in int x) { }
}";
CreateCompilation(text).VerifyEmitDiagnostics(
// (11,19): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor'
// public void M(in int x) { }
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "in int x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(11, 19));
}
[Fact]
public void IsReadOnlyAttributeExistsWithWrongConstructorSignature_PrivateConstructor()
{
var text = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute
{
private IsReadOnlyAttribute() { }
}
}
class Test
{
public void M(in int x) { }
}";
CreateCompilation(text).VerifyEmitDiagnostics(
// (11,19): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor'
// public void M(in int x) { }
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "in int x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(11, 19));
}
[Fact]
public void IsReadOnlyAttributesAreNotPortedInNoPia()
{
var comAssembly = CreateCompilationWithMscorlib40(@"
using System;
using System.Runtime.InteropServices;
[assembly: ImportedFromTypeLib(""test.dll"")]
[assembly: Guid(""9784f9a1-594a-4351-8f69-0fd2d2df03d3"")]
[ComImport()]
[Guid(""9784f9a1-594a-4351-8f69-0fd2d2df03d3"")]
public interface Test
{
ref readonly int Property { get; }
ref readonly int Method(in int x);
}");
CompileAndVerify(comAssembly, symbolValidator: module =>
{
var type = module.ContainingAssembly.GetTypeByMetadataName("Test");
var property = type.GetMember<PEPropertySymbol>("Property");
Assert.NotNull(property);
Assert.Empty(property.GetAttributes());
var method = type.GetMethod("Method");
Assert.NotNull(method);
Assert.Empty(method.GetReturnTypeAttributes());
var parameter = method.Parameters.Single();
Assert.NotNull(parameter);
Assert.Empty(parameter.GetAttributes());
});
var code = @"
class User
{
public void M(Test p)
{
p.Method(p.Property);
}
}";
var options = TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All);
var compilation_CompilationReference = CreateCompilationWithMscorlib40(code, options: options, references: new[] { comAssembly.ToMetadataReference(embedInteropTypes: true) });
CompileAndVerify(compilation_CompilationReference, symbolValidator: symbolValidator);
var compilation_BinaryReference = CreateCompilationWithMscorlib40(code, options: options, references: new[] { comAssembly.EmitToImageReference(embedInteropTypes: true) });
CompileAndVerify(compilation_BinaryReference, symbolValidator: symbolValidator);
void symbolValidator(ModuleSymbol module)
{
// No attribute is copied
AssertNoIsReadOnlyAttributeExists(module.ContainingAssembly);
var type = module.ContainingAssembly.GetTypeByMetadataName("Test");
var property = type.GetMember<PEPropertySymbol>("Property");
Assert.NotNull(property);
Assert.Empty(property.GetAttributes());
var method = type.GetMethod("Method");
Assert.NotNull(method);
Assert.Empty(method.GetReturnTypeAttributes());
var parameter = method.Parameters.Single();
Assert.NotNull(parameter);
Assert.Empty(parameter.GetAttributes());
}
}
[Fact]
public void TryingToBindFromSemanticModelDoesNotPolluteCompilation_Lambdas_Parameters()
{
var reference = CreateCompilation(@"
public delegate int D (in int x);
").VerifyEmitDiagnostics();
Assert.True(NeedsGeneratedIsReadOnlyAttribute(reference));
var compilation = CreateCompilation(@"
public class Test
{
public void Process(D lambda) { }
void User()
{
}
}", references: new[] { reference.ToMetadataReference() });
compilation.VerifyEmitDiagnostics();
Assert.False(NeedsGeneratedIsReadOnlyAttribute(compilation));
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree, ignoreAccessibility: false);
var userFunction = tree.GetRoot().DescendantNodes().OfType<MethodDeclarationSyntax>().Single(method => method.Identifier.Text == "User");
var position = userFunction.Body.CloseBraceToken.Position;
var newInvocation = SyntaxFactory.ParseExpression("Process((in int x) => x)");
var result = model.GetSpeculativeSymbolInfo(position, newInvocation, SpeculativeBindingOption.BindAsExpression);
Assert.NotNull(result.Symbol);
Assert.Equal(CandidateReason.None, result.CandidateReason);
Assert.Empty(result.CandidateSymbols);
Assert.False(NeedsGeneratedIsReadOnlyAttribute(compilation));
}
[Fact]
public void TryingToBindFromSemanticModelDoesNotPolluteCompilation_Lambdas_ReturnTypes()
{
var reference = CreateCompilation(@"
public delegate ref readonly int D ();
").VerifyEmitDiagnostics();
Assert.True(NeedsGeneratedIsReadOnlyAttribute(reference));
var compilation = CreateCompilation(@"
public class Test
{
private int x;
public void Process(D lambda)
{
x = lambda();
}
void User()
{
}
}", references: new[] { reference.ToMetadataReference() });
compilation.VerifyEmitDiagnostics();
Assert.False(NeedsGeneratedIsReadOnlyAttribute(compilation));
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree, ignoreAccessibility: false);
var userFunction = tree.GetRoot().DescendantNodes().OfType<MethodDeclarationSyntax>().Single(method => method.Identifier.Text == "User");
var position = userFunction.Body.CloseBraceToken.Position;
var newInvocation = SyntaxFactory.ParseExpression("Process(() => ref x)");
var result = model.GetSpeculativeSymbolInfo(position, newInvocation, SpeculativeBindingOption.BindAsExpression);
Assert.NotNull(result.Symbol);
Assert.Equal(CandidateReason.None, result.CandidateReason);
Assert.Empty(result.CandidateSymbols);
Assert.False(NeedsGeneratedIsReadOnlyAttribute(compilation));
}
[Fact]
public void TryingToBindFromSemanticModelDoesNotPolluteCompilation_LocalFunctions_Parameters()
{
var compilation = CreateCompilation(@"
public class Test
{
void User()
{
}
}");
compilation.VerifyEmitDiagnostics();
Assert.False(NeedsGeneratedIsReadOnlyAttribute(compilation));
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree, ignoreAccessibility: false);
var userFunction = tree.GetRoot().DescendantNodes().OfType<MethodDeclarationSyntax>().Single(method => method.Identifier.Text == "User");
var position = userFunction.Body.CloseBraceToken.Position;
var localfunction = SyntaxFactory.ParseStatement("int localFunction(in int x) { return x; }");
Assert.True(model.TryGetSpeculativeSemanticModel(position, localfunction, out var newModel));
var localFunctionSymbol = newModel.GetDeclaredSymbol(localfunction);
Assert.NotNull(localFunctionSymbol);
Assert.False(NeedsGeneratedIsReadOnlyAttribute(compilation));
}
[Fact]
public void TryingToBindFromSemanticModelDoesNotPolluteCompilation_LocalFunctions_ReturnTypes()
{
var compilation = CreateCompilation(@"
public class Test
{
void User()
{
}
}");
compilation.VerifyEmitDiagnostics();
Assert.False(NeedsGeneratedIsReadOnlyAttribute(compilation));
var tree = compilation.SyntaxTrees.Single();
var model = compilation.GetSemanticModel(tree, ignoreAccessibility: false);
var userFunction = tree.GetRoot().DescendantNodes().OfType<MethodDeclarationSyntax>().Single(method => method.Identifier.Text == "User");
var position = userFunction.Body.CloseBraceToken.Position;
var localfunction = SyntaxFactory.ParseStatement("ref readonly int localFunction(int x) { return ref x; }");
Assert.True(model.TryGetSpeculativeSemanticModel(position, localfunction, out var newModel));
var localFunctionSymbol = newModel.GetDeclaredSymbol(localfunction);
Assert.NotNull(localFunctionSymbol);
Assert.False(NeedsGeneratedIsReadOnlyAttribute(compilation));
}
[Fact]
public void TryingPossibleBindingsForRefReadOnlyDoesNotPolluteCompilationForInvalidOnes()
{
var reference = CreateCompilation(@"
public delegate ref readonly int D1 ();
public delegate ref int D2 ();
").VerifyEmitDiagnostics();
Assert.True(NeedsGeneratedIsReadOnlyAttribute(reference));
var compilation = CreateCompilation(@"
public class Test
{
public void Process(D1 lambda, int x) { }
public void Process(D2 lambda, byte x) { }
void User()
{
byte byteVar = 0;
Process(() => { throw null; }, byteVar);
}
}", references: new[] { reference.ToMetadataReference() });
compilation.VerifyEmitDiagnostics();
Assert.False(NeedsGeneratedIsReadOnlyAttribute(compilation));
}
[Fact]
public void RefReadOnlyErrorsForLambdasDoNotPolluteCompilationDeclarationsDiagnostics()
{
var reference = CreateCompilation(@"
public delegate int D (in int x);
").EmitToImageReference();
var code = @"
public class Test
{
public void Process(D lambda) { }
void User()
{
Process((in int p) => p);
}
}";
var compilation = CreateCompilation(code, options: TestOptions.ReleaseModule, references: new[] { reference });
compilation.DeclarationDiagnostics.Verify();
compilation.VerifyDiagnostics(
// (8,18): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsReadOnlyAttribute' is not defined or imported
// Process((in int p) => p);
Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "in int p").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(8, 18));
}
[Fact]
public void RefReadOnlyErrorsForLocalFunctionsDoNotPolluteCompilationDeclarationsDiagnostics()
{
var code = @"
public class Test
{
private int x = 0;
void User()
{
void local(in int x) { }
local(x);
}
}";
var compilation = CreateCompilation(code, options: TestOptions.ReleaseModule);
compilation.DeclarationDiagnostics.Verify();
compilation.VerifyDiagnostics(
// (7,20): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsReadOnlyAttribute' is not defined or imported
// void local(in int x) { }
Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "in int x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(7, 20));
}
[Fact]
public void RefReadOnlyDefinitionsInsideUserDefinedIsReadOnlyAttribute_Class_NoParent()
{
var code = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute
{
private int value;
public ref readonly int Method(in int x) => ref value;
public static int operator +(in IsReadOnlyAttribute x, in IsReadOnlyAttribute y) => 0;
public ref readonly int Property => ref value;
public ref readonly int this[in int x] => ref value;
}
}";
CompileAndVerify(code, verify: Verification.Passes, symbolValidator: module =>
{
var isReadOnlyAttributeName = WellKnownTypes.GetMetadataName(WellKnownType.System_Runtime_CompilerServices_IsReadOnlyAttribute);
var type = module.ContainingAssembly.GetTypeByMetadataName(isReadOnlyAttributeName);
var method = type.GetMethod("Method");
Assert.Empty(method.GetReturnTypeAttributes());
Assert.Empty(method.Parameters.Single().GetAttributes());
var @operator = type.GetMethod("op_Addition");
Assert.Empty(@operator.Parameters[0].GetAttributes());
Assert.Empty(@operator.Parameters[1].GetAttributes());
var property = type.GetProperty("Property");
Assert.Empty(property.GetAttributes());
var indexer = type.GetProperty("this[]");
Assert.Empty(indexer.GetAttributes());
Assert.Empty(indexer.Parameters.Single().GetAttributes());
});
}
[Fact]
public void RefReadOnlyDefinitionsInsideUserDefinedIsReadOnlyAttribute_Class_CorrectParent()
{
var code = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute
{
private int value;
public ref readonly int Method(in int x) => ref value;
public static int operator +(in IsReadOnlyAttribute x, in IsReadOnlyAttribute y) => 0;
public ref readonly int Property => ref value;
public ref readonly int this[in int x] => ref value;
}
}";
CompileAndVerify(code, verify: Verification.Passes, symbolValidator: module =>
{
var isReadOnlyAttributeName = WellKnownTypes.GetMetadataName(WellKnownType.System_Runtime_CompilerServices_IsReadOnlyAttribute);
var type = module.ContainingAssembly.GetTypeByMetadataName(isReadOnlyAttributeName);
var method = type.GetMethod("Method");
Assert.Empty(method.GetReturnTypeAttributes());
Assert.Empty(method.Parameters.Single().GetAttributes());
var @operator = type.GetMethod("op_Addition");
Assert.Empty(@operator.Parameters[0].GetAttributes());
Assert.Empty(@operator.Parameters[1].GetAttributes());
var property = type.GetProperty("Property");
Assert.Empty(property.GetAttributes());
var indexer = type.GetProperty("this[]");
Assert.Empty(indexer.GetAttributes());
Assert.Empty(indexer.Parameters.Single().GetAttributes());
});
}
[Fact]
public void RefReadOnlyDefinitionsInsideUserDefinedIsReadOnlyAttribute_ClassInherit()
{
var code = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute
{
}
}
public class Child : System.Runtime.CompilerServices.IsReadOnlyAttribute
{
private int value;
public ref readonly int Method(in int x) => ref value;
public static int operator +(in Child x, in Child y) => 0;
public ref readonly int Property => ref value;
public ref readonly int this[in int x] => ref value;
}";
CompileAndVerify(code, verify: Verification.Passes, symbolValidator: module =>
{
var type = module.ContainingAssembly.GetTypeByMetadataName("Child");
var method = type.GetMethod("Method");
Assert.Empty(method.GetReturnTypeAttributes());
Assert.Empty(method.Parameters.Single().GetAttributes());
var @operator = type.GetMethod("op_Addition");
Assert.Empty(@operator.Parameters[0].GetAttributes());
Assert.Empty(@operator.Parameters[1].GetAttributes());
var property = type.GetProperty("Property");
Assert.Empty(property.GetAttributes());
var indexer = type.GetProperty("this[]");
Assert.Empty(indexer.GetAttributes());
Assert.Empty(indexer.Parameters.Single().GetAttributes());
});
}
[Fact]
public void RefReadOnlyDefinitionsInsideUserDefinedIsReadOnlyAttribute_ClassOverride_SameAssembly()
{
var code = @"
namespace System.Runtime.CompilerServices
{
public abstract class IsReadOnlyAttribute : System.Attribute
{
public IsReadOnlyAttribute() { }
public abstract ref readonly int Method(in int x);
public abstract ref readonly int Property { get; }
public abstract ref readonly int this[in int x] { get; }
}
}
public class Child : System.Runtime.CompilerServices.IsReadOnlyAttribute
{
private int value;
public override ref readonly int Method(in int x) => ref value;
public override ref readonly int Property => ref value;
public override ref readonly int this[in int x] => ref value;
}";
CompileAndVerify(code, verify: Verification.Passes, symbolValidator: module =>
{
var type = module.ContainingAssembly.GetTypeByMetadataName("Child");
var method = type.GetMethod("Method");
Assert.Empty(method.GetReturnTypeAttributes());
Assert.Empty(method.Parameters.Single().GetAttributes());
var property = type.GetProperty("Property");
Assert.Empty(property.GetAttributes());
var indexer = type.GetProperty("this[]");
Assert.Empty(indexer.GetAttributes());
Assert.Empty(indexer.Parameters.Single().GetAttributes());
});
}
[Fact]
public void RefReadOnlyDefinitionsInsideUserDefinedIsReadOnlyAttribute_ClassOverride_ExternalAssembly()
{
var reference = CreateCompilation(@"
namespace System.Runtime.CompilerServices
{
public abstract class IsReadOnlyAttribute : System.Attribute
{
public IsReadOnlyAttribute() { }
public abstract ref readonly int Method(in int x);
public abstract ref readonly int Property { get; }
public abstract ref readonly int this[in int x] { get; }
}
}", assemblyName: "testRef").ToMetadataReference();
var code = @"
public class Child : System.Runtime.CompilerServices.IsReadOnlyAttribute
{
private int value;
public override ref readonly int Method(in int x) => ref value;
public override ref readonly int Property => ref value;
public override ref readonly int this[in int x] => ref value;
}";
CompileAndVerify(code, verify: Verification.Passes, references: new[] { reference }, symbolValidator: module =>
{
var type = module.ContainingAssembly.GetTypeByMetadataName("Child");
var method = type.GetMethod("Method");
Assert.Empty(method.GetReturnTypeAttributes());
Assert.Empty(method.Parameters.Single().GetAttributes());
var property = type.GetProperty("Property");
Assert.Empty(property.GetAttributes());
var indexer = type.GetProperty("this[]");
Assert.Empty(indexer.GetAttributes());
Assert.Empty(indexer.Parameters.Single().GetAttributes());
});
}
[Fact]
public void RefReadOnlyDefinitionsInsideUserDefinedIsReadOnlyAttribute_ClassOverridden_SameAssembly()
{
var code = @"
namespace System.Runtime.CompilerServices
{
public abstract class Parent : System.Attribute
{
public abstract ref readonly int Method(in int x);
public abstract ref readonly int Property { get; }
public abstract ref readonly int this[in int x] { get; }
}
public class IsReadOnlyAttribute : Parent
{
private int value;
public override ref readonly int Method(in int x) => ref value;
public override ref readonly int Property => ref value;
public override ref readonly int this[in int x] => ref value;
}
}";
CompileAndVerify(code, verify: Verification.Passes, symbolValidator: module =>
{
var typeName = WellKnownTypes.GetMetadataName(WellKnownType.System_Runtime_CompilerServices_IsReadOnlyAttribute);
var type = module.ContainingAssembly.GetTypeByMetadataName(typeName);
var method = type.GetMethod("Method");
Assert.Empty(method.GetReturnTypeAttributes());
Assert.Empty(method.Parameters.Single().GetAttributes());
var property = type.GetProperty("Property");
Assert.Empty(property.GetAttributes());
var indexer = type.GetProperty("this[]");
Assert.Empty(indexer.GetAttributes());
Assert.Empty(indexer.Parameters.Single().GetAttributes());
});
}
[Fact]
public void RefReadOnlyDefinitionsInsideUserDefinedIsReadOnlyAttribute_ClassOverridden_ExternalAssembly()
{
var reference = CreateCompilation(@"
namespace System.Runtime.CompilerServices
{
public abstract class Parent : System.Attribute
{
public abstract ref readonly int Method(in int x);
public abstract ref readonly int Property { get; }
public abstract ref readonly int this[in int x] { get; }
}
}").ToMetadataReference();
var code = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : Parent
{
private int value;
public override ref readonly int Method(in int x) => ref value;
public override ref readonly int Property => ref value;
public override ref readonly int this[in int x] => ref value;
}
}";
CompileAndVerify(code, verify: Verification.Passes, references: new[] { reference }, symbolValidator: module =>
{
var typeName = WellKnownTypes.GetMetadataName(WellKnownType.System_Runtime_CompilerServices_IsReadOnlyAttribute);
var type = module.ContainingAssembly.GetTypeByMetadataName(typeName);
var method = type.GetMethod("Method");
Assert.Empty(method.GetReturnTypeAttributes());
Assert.Empty(method.Parameters.Single().GetAttributes());
var property = type.GetProperty("Property");
Assert.Empty(property.GetAttributes());
var indexer = type.GetProperty("this[]");
Assert.Empty(indexer.GetAttributes());
Assert.Empty(indexer.Parameters.Single().GetAttributes());
});
}
[Fact]
public void RefReadOnlyDefinitionsInsideUserDefinedIsReadOnlyAttribute_Class_WrongParent()
{
var code = @"
namespace System.Runtime.CompilerServices
{
public class TestParent { }
public class IsReadOnlyAttribute : TestParent
{
private int value;
public ref readonly int Method(in int x) => ref value;
public static int operator +(in IsReadOnlyAttribute x, in IsReadOnlyAttribute y) => 0;
public ref readonly int Property => ref value;
public ref readonly int this[in int x] => ref value;
}
}";
CompileAndVerify(code, verify: Verification.Passes, symbolValidator: module =>
{
var isReadOnlyAttributeName = WellKnownTypes.GetMetadataName(WellKnownType.System_Runtime_CompilerServices_IsReadOnlyAttribute);
var type = module.ContainingAssembly.GetTypeByMetadataName(isReadOnlyAttributeName);
var method = type.GetMethod("Method");
Assert.Empty(method.GetReturnTypeAttributes());
Assert.Empty(method.Parameters.Single().GetAttributes());
var @operator = type.GetMethod("op_Addition");
Assert.Empty(@operator.Parameters[0].GetAttributes());
Assert.Empty(@operator.Parameters[1].GetAttributes());
var property = type.GetProperty("Property");
Assert.Empty(property.GetAttributes());
var indexer = type.GetProperty("this[]");
Assert.Empty(indexer.GetAttributes());
Assert.Empty(indexer.Parameters.Single().GetAttributes());
});
}
[Fact]
public void RefReadOnlyDefinitionsInsideUserDefinedIsReadOnlyAttribute_Interface()
{
var code = @"
namespace System.Runtime.CompilerServices
{
public interface IsReadOnlyAttribute
{
ref readonly int Method(in int x);
}
}";
CreateCompilation(code).VerifyEmitDiagnostics(
// (6,9): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor'
// ref readonly int Method(in int x);
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "ref readonly int").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(6, 9),
// (6,33): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor'
// ref readonly int Method(in int x);
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "in int x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(6, 33));
}
[Fact]
public void RefReadOnlyDefinitionsInsideUserDefinedIsReadOnlyAttribute_ExplicitInterfaceImplementation_SameAssembly()
{
var code = @"
namespace System.Runtime.CompilerServices
{
public interface ITest
{
ref readonly int Method(in int x);
ref readonly int Property { get; }
ref readonly int this[in int x] { get; }
}
public class IsReadOnlyAttribute : ITest
{
private int value;
ref readonly int ITest.Method(in int x) => ref value;
ref readonly int ITest.Property => ref value;
ref readonly int ITest.this[in int x] => ref value;
}
}";
CompileAndVerify(code, verify: Verification.Passes, symbolValidator: module =>
{
var typeName = WellKnownTypes.GetMetadataName(WellKnownType.System_Runtime_CompilerServices_IsReadOnlyAttribute);
var type = module.ContainingAssembly.GetTypeByMetadataName(typeName);
var method = type.GetMethod("System.Runtime.CompilerServices.ITest.Method");
Assert.Empty(method.GetReturnTypeAttributes());
Assert.Empty(method.Parameters.Single().GetAttributes());
var property = type.GetProperty("System.Runtime.CompilerServices.ITest.Property");
Assert.Empty(property.GetAttributes());
var indexer = type.GetProperty("System.Runtime.CompilerServices.ITest.Item");
Assert.Empty(indexer.GetAttributes());
Assert.Empty(indexer.Parameters.Single().GetAttributes());
});
}
[Fact]
public void RefReadOnlyDefinitionsInsideUserDefinedIsReadOnlyAttribute_ExplicitInterfaceImplementation_ExternalAssembly()
{
var reference = CreateCompilation(@"
namespace System.Runtime.CompilerServices
{
public interface ITest
{
ref readonly int Method(in int x);
ref readonly int Property { get; }
ref readonly int this[in int x] { get; }
}
}").ToMetadataReference();
var code = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : ITest
{
private int value;
ref readonly int ITest.Method(in int x) => ref value;
ref readonly int ITest.Property => ref value;
ref readonly int ITest.this[in int x] => ref value;
}
}";
CompileAndVerify(code, verify: Verification.Passes, references: new[] { reference }, symbolValidator: module =>
{
var typeName = WellKnownTypes.GetMetadataName(WellKnownType.System_Runtime_CompilerServices_IsReadOnlyAttribute);
var type = module.ContainingAssembly.GetTypeByMetadataName(typeName);
var method = type.GetMethod("System.Runtime.CompilerServices.ITest.Method");
Assert.Empty(method.GetReturnTypeAttributes());
Assert.Empty(method.Parameters.Single().GetAttributes());
var property = type.GetProperty("System.Runtime.CompilerServices.ITest.Property");
Assert.Empty(property.GetAttributes());
var indexer = type.GetProperty("System.Runtime.CompilerServices.ITest.Item");
Assert.Empty(indexer.GetAttributes());
Assert.Empty(indexer.Parameters.Single().GetAttributes());
});
}
[Fact]
public void IsReadOnlyAttributeIsGenerated_ExplicitInterfaceImplementation_SameAssembly()
{
var code = @"
public interface ITest
{
ref readonly int Method(in int x);
ref readonly int Property { get; }
ref readonly int this[in int x] { get; }
}
public class TestImpl : ITest
{
private int value;
ref readonly int ITest.Method(in int x) => ref value;
ref readonly int ITest.Property => ref value;
ref readonly int ITest.this[in int x] => ref value;
}";
CompileAndVerify(code, verify: Verification.Passes, symbolValidator: module =>
{
var type = module.ContainingAssembly.GetTypeByMetadataName("TestImpl");
var method = type.GetMethod("ITest.Method");
Assert.Empty(method.GetReturnTypeAttributes());
Assert.Empty(method.Parameters.Single().GetAttributes());
var property = type.GetProperty("ITest.Property");
Assert.Empty(property.GetAttributes());
var indexer = type.GetProperty("ITest.Item");
Assert.Empty(indexer.GetAttributes());
Assert.Empty(indexer.Parameters.Single().GetAttributes());
});
}
[Fact]
public void IsReadOnlyAttributeIsGenerated_ExplicitInterfaceImplementation_ExternalAssembly()
{
var reference = CreateCompilation(@"
public interface ITest
{
ref readonly int Method(in int x);
ref readonly int Property { get; }
ref readonly int this[in int x] { get; }
}").ToMetadataReference();
var code = @"
public class TestImpl : ITest
{
private int value;
ref readonly int ITest.Method(in int x) => ref value;
ref readonly int ITest.Property => ref value;
ref readonly int ITest.this[in int x] => ref value;
}";
CompileAndVerify(code, verify: Verification.Passes, references: new[] { reference }, symbolValidator: module =>
{
var type = module.ContainingAssembly.GetTypeByMetadataName("TestImpl");
var method = type.GetMethod("ITest.Method");
Assert.Empty(method.GetReturnTypeAttributes());
Assert.Empty(method.Parameters.Single().GetAttributes());
var property = type.GetProperty("ITest.Property");
Assert.Empty(property.GetAttributes());
var indexer = type.GetProperty("ITest.Item");
Assert.Empty(indexer.GetAttributes());
Assert.Empty(indexer.Parameters.Single().GetAttributes());
});
}
[Fact]
public void RefReadOnlyDefinitionsInsideUserDefinedIsReadOnlyAttribute_Delegate()
{
var code = @"
namespace System.Runtime.CompilerServices
{
public delegate ref readonly int IsReadOnlyAttribute(in int x);
}";
CreateCompilation(code).VerifyEmitDiagnostics(
// (4,21): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor'
// public delegate ref readonly int IsReadOnlyAttribute(in int x);
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "ref readonly int").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(4, 21),
// (4,58): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor'
// public delegate ref readonly int IsReadOnlyAttribute(in int x);
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "in int x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(4, 58));
}
[Fact]
public void MissingRequiredConstructorWillReportErrorsOnApproriateSyntax_Constructor()
{
var text = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute
{
public IsReadOnlyAttribute(int p) { }
}
}
public class Test
{
public Test(in int x) { }
}";
CreateCompilation(text).VerifyEmitDiagnostics(
// (11,17): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor'
// public Test(in int x) { }
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "in int x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(11, 17));
}
[Fact]
public void MissingRequiredConstructorWillReportErrorsOnApproriateSyntax_Method()
{
var text = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute
{
public IsReadOnlyAttribute(int p) { }
}
}
public class Test
{
public ref readonly int Method(in int x) => ref x;
}";
CreateCompilation(text).VerifyEmitDiagnostics(
// (11,12): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor'
// public ref readonly int Method(in int x) => ref x;
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "ref readonly int").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(11, 12),
// (11,36): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor'
// public ref readonly int Method(in int x) => ref x;
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "in int x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(11, 36));
}
[Fact]
public void MissingRequiredConstructorWillReportErrorsOnApproriateSyntax_LocalFunction()
{
var text = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute
{
public IsReadOnlyAttribute(int p) { }
}
}
public class Test
{
public void M()
{
int x = 0;
ref readonly int local(in int p)
{
return ref p;
}
local(x);
}
}";
CreateCompilation(text).VerifyEmitDiagnostics(
// (15,9): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor'
// ref readonly int local(in int p)
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "ref readonly int").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(15, 9),
// (15,32): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor'
// ref readonly int local(in int p)
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "in int p").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(15, 32));
}
[Fact]
public void MissingRequiredConstructorWillReportErrorsOnApproriateSyntax_Lambda()
{
var reference = CreateCompilation(@"
public delegate ref readonly int D(in int x);
").EmitToImageReference();
var text = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute
{
public IsReadOnlyAttribute(int p) { }
}
}
class Test
{
public void M1()
{
M2((in int x) => ref x);
}
public void M2(D value) { }
}";
CreateCompilation(text, references: new[] { reference }).VerifyEmitDiagnostics(
// (14,33): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor'
// M2((in int x) => ref x);
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "=>").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(14, 23),
// (14,13): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor'
// M2((in int x) => ref x);
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "in int x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(14, 13));
}
[Fact]
public void MissingRequiredConstructorWillReportErrorsOnApproriateSyntax_Property()
{
var text = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute
{
public IsReadOnlyAttribute(int p) { }
}
}
public class Test
{
private int value;
public ref readonly int Property => ref value;
}";
CreateCompilation(text).VerifyEmitDiagnostics(
// (12,12): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor'
// public ref readonly int Property => ref value;
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "ref readonly int").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(12, 12));
}
[Fact]
public void MissingRequiredConstructorWillReportErrorsOnApproriateSyntax_Indexer()
{
var text = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute
{
public IsReadOnlyAttribute(int p) { }
}
}
public class Test
{
public ref readonly int this[in int x] => ref x;
}";
CreateCompilation(text).VerifyEmitDiagnostics(
// (12,12): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor'
// public ref readonly int this[in int x] => ref x;
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "ref readonly int").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(12, 12),
// (12,34): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor'
// public ref readonly int this[in int x] => ref x;
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "in int x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(12, 34));
}
[Fact]
public void MissingRequiredConstructorWillReportErrorsOnApproriateSyntax_Operator()
{
var text = @"
namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : System.Attribute
{
public IsReadOnlyAttribute(int p) { }
}
}
public class Test
{
public static int operator + (in Test x, in Test y) => 0;
}";
CreateCompilation(text).VerifyEmitDiagnostics(
// (11,35): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor'
// public static int operator + (in Test x, in Test y) => 0;
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "in Test x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(11, 35),
// (11,46): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor'
// public static int operator + (in Test x, in Test y) => 0;
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "in Test y").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(11, 46));
}
[Fact]
public void EmitAttribute_LambdaReturnType()
{
var source =
@"class Program
{
static void Main()
{
var f = (ref readonly int () => throw null);
f();
}
}";
CompileAndVerify(
source,
options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All),
symbolValidator: module =>
{
var method = module.ContainingAssembly.GetTypeByMetadataName("Program+<>c").GetMethod("<Main>b__0_0");
Assert.Equal(RefKind.RefReadOnly, method.RefKind);
});
}
[Fact]
public void EmitAttribute_LambdaParameters()
{
var source =
@"class Program
{
static void Main()
{
var f = (in int x, ref int y) => { };
int x = 1;
int y = 2;
f(x, ref y);
}
}";
CompileAndVerify(
source,
options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All),
symbolValidator: module =>
{
var method = module.ContainingAssembly.GetTypeByMetadataName("Program+<>c").GetMethod("<Main>b__0_0");
Assert.Equal(RefKind.RefReadOnly, method.Parameters[0].RefKind);
Assert.Equal(RefKind.Ref, method.Parameters[1].RefKind);
});
}
[Fact]
public void EmitAttribute_LocalFunctionReturnType()
{
var source =
@"class Program
{
static void Main()
{
ref readonly int L() => throw null;
L();
}
}";
CompileAndVerify(
source,
options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All),
symbolValidator: module =>
{
var method = module.ContainingAssembly.GetTypeByMetadataName("Program").GetMethod("<Main>g__L|0_0");
Assert.Equal(RefKind.RefReadOnly, method.RefKind);
});
}
[Fact]
public void EmitAttribute_LocalFunctionParameters()
{
var source =
@"class Program
{
static void Main()
{
void L(ref int x, in int y) { };
int x = 1;
int y = 2;
L(ref x, y);
}
}";
CompileAndVerify(
source,
options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All),
symbolValidator: module =>
{
var method = module.ContainingAssembly.GetTypeByMetadataName("Program").GetMethod("<Main>g__L|0_0");
Assert.Equal(RefKind.Ref, method.Parameters[0].RefKind);
Assert.Equal(RefKind.RefReadOnly, method.Parameters[1].RefKind);
});
}
[Fact]
public void EmitAttribute_Lambda_NetModule()
{
var source =
@"class Program
{
static void Main()
{
var f1 = (in int x, ref int y) => { };
int x = 1;
int y = 2;
f1(x, ref y);
var f2 = (ref readonly int () => throw null);
f2();
}
}";
var comp = CreateCompilation(source, options: TestOptions.ReleaseModule);
comp.VerifyDiagnostics(
// (5,19): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsReadOnlyAttribute' is not defined or imported
// var f1 = (in int x, ref int y) => { };
Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "in int x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(5, 19),
// (9,39): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsReadOnlyAttribute' is not defined or imported
// var f2 = (ref readonly int () => throw null);
Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "=>").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(9, 39));
}
[Fact]
public void EmitAttribute_LocalFunction_NetModule()
{
var source =
@"class Program
{
static void Main()
{
void L1(ref int x, in int y) { };
int x = 1;
int y = 2;
L1(ref x, y);
ref readonly int L2() => throw null;
L2();
}
}";
var comp = CreateCompilation(source, options: TestOptions.ReleaseModule);
comp.VerifyDiagnostics(
// (5,28): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsReadOnlyAttribute' is not defined or imported
// void L1(ref int x, in int y) { };
Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "in int y").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(5, 28),
// (9,9): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsReadOnlyAttribute' is not defined or imported
// ref readonly int L2() => throw null;
Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "ref readonly int").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute").WithLocation(9, 9));
}
[Fact]
public void EmitAttribute_Lambda_MissingAttributeConstructor()
{
var sourceA =
@"namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : Attribute
{
private IsReadOnlyAttribute() { }
}
}";
var sourceB =
@"class Program
{
static void Main()
{
var f1 = (in int x, ref int y) => { };
int x = 1;
int y = 2;
f1(x, ref y);
var f2 = (ref readonly int () => throw null);
f2();
}
}";
var comp = CreateCompilation(new[] { sourceA, sourceB });
comp.VerifyDiagnostics(
// (5,19): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor'
// var f1 = (in int x, ref int y) => { };
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "in int x").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(5, 19),
// (9,39): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor'
// var f2 = (ref readonly int () => throw null);
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "=>").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(9, 39));
}
[Fact]
public void EmitAttribute_LocalFunction_MissingAttributeConstructor()
{
var sourceA =
@"namespace System.Runtime.CompilerServices
{
public class IsReadOnlyAttribute : Attribute
{
private IsReadOnlyAttribute() { }
}
}";
var sourceB =
@"class Program
{
static void Main()
{
void L1(ref int x, in int y) { };
int x = 1;
int y = 2;
L1(ref x, y);
ref readonly int L2() => throw null;
L2();
}
}";
var comp = CreateCompilation(new[] { sourceA, sourceB });
comp.VerifyDiagnostics(
// (5,28): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor'
// void L1(ref int x, in int y) { };
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "in int y").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(5, 28),
// (9,9): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsReadOnlyAttribute..ctor'
// ref readonly int L2() => throw null;
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "ref readonly int").WithArguments("System.Runtime.CompilerServices.IsReadOnlyAttribute", ".ctor").WithLocation(9, 9));
}
private void AssertNoIsReadOnlyAttributeExists(AssemblySymbol assembly)
{
var isReadOnlyAttributeTypeName = WellKnownTypes.GetMetadataName(WellKnownType.System_Runtime_CompilerServices_IsReadOnlyAttribute);
Assert.Null(assembly.GetTypeByMetadataName(isReadOnlyAttributeTypeName));
}
private void AssertGeneratedEmbeddedAttribute(AssemblySymbol assembly, string expectedTypeName)
{
var typeSymbol = assembly.GetTypeByMetadataName(expectedTypeName);
Assert.NotNull(typeSymbol);
Assert.Equal(Accessibility.Internal, typeSymbol.DeclaredAccessibility);
var attributes = typeSymbol.GetAttributes().OrderBy(attribute => attribute.AttributeClass.Name).ToArray();
Assert.Equal(2, attributes.Length);
Assert.Equal(WellKnownTypes.GetMetadataName(WellKnownType.System_Runtime_CompilerServices_CompilerGeneratedAttribute), attributes[0].AttributeClass.ToDisplayString());
Assert.Equal(AttributeDescription.CodeAnalysisEmbeddedAttribute.FullName, attributes[1].AttributeClass.ToDisplayString());
}
private static bool NeedsGeneratedIsReadOnlyAttribute(CSharpCompilation compilation)
{
return (compilation.GetNeedsGeneratedAttributes() & EmbeddableAttributes.IsReadOnlyAttribute) != 0;
}
}
}
|