/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/CSharp/Test/Emit3/Attributes/AttributeTests_Nullable.cs
5 438 строк
234 KB
Julien Couvreur
Centralize recognized feature flags (#81591)
11 дек 2025, 01:34
Не верифицирован
11 дек 2025, 01:34
7da6b9c
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable disable using System; using System.Collections.Immutable; using System.Linq; using System.Reflection.Metadata; using System.Reflection.PortableExecutable; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Roslyn.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.CSharp.UnitTests { public class AttributeTests_Nullable : CSharpTestBase { // An empty project should not require System.Attribute. [Fact] public void EmptyProject_MissingAttribute() { var source = ""; var comp = CreateEmptyCompilation(source, parseOptions: TestOptions.Regular8); comp.VerifyEmitDiagnostics( // warning CS8021: No value for RuntimeMetadataVersion found. No assembly containing System.Object was found nor was a value for RuntimeMetadataVersion specified through options. Diagnostic(ErrorCode.WRN_NoRuntimeMetadataVersion).WithLocation(1, 1) ); } [Theory] [InlineData(true)] [InlineData(false)] [WorkItem(40033, "https://github.com/dotnet/roslyn/issues/40033")] public void SynthesizeNullableAttributeBasedOnInterfacesToEmit(bool useImageReferences) { Func<CSharpCompilation, MetadataReference> getReference = c => useImageReferences ? c.EmitToImageReference() : c.ToMetadataReference(); var lib1_source = @" using System.Threading.Tasks; #nullable enable public interface I2<T, TResult> { Task<TResult> ExecuteAsync(T parameter); } public interface I1<T> : I2<T, object> { } "; var lib1_comp = CreateCompilation(lib1_source); lib1_comp.VerifyDiagnostics(); var lib2_source = @" #nullable disable public interface I0 : I1<string> { }"; var lib2_comp = CreateCompilation(lib2_source, references: new[] { getReference(lib1_comp) }); lib2_comp.VerifyDiagnostics(); var imc1 = (TypeSymbol)lib2_comp.GlobalNamespace.GetMember("I0"); AssertEx.SetEqual( new[] { "I1<System.String>" }, imc1.InterfacesNoUseSiteDiagnostics().Select(i => i.ToTestDisplayString(includeNonNullable: true))); AssertEx.SetEqual( new[] { "I1<System.String>", "I2<System.String, System.Object!>" }, imc1.AllInterfacesNoUseSiteDiagnostics.Select(i => i.ToTestDisplayString(includeNonNullable: true))); var client_source = @" public class C { public void M(I0 imc) { imc.ExecuteAsync(""""); } }"; var client_comp = CreateCompilation(client_source, references: new[] { getReference(lib1_comp), getReference(lib2_comp) }); client_comp.VerifyDiagnostics(); var imc2 = (TypeSymbol)client_comp.GlobalNamespace.GetMember("I0"); // Note: it is expected that the symbol shows different Interfaces in PE vs. compilation reference AssertEx.SetEqual( useImageReferences ? new[] { "I1<System.String>", "I2<System.String, System.Object!>" } : new[] { "I1<System.String>" }, imc2.InterfacesNoUseSiteDiagnostics().Select(i => i.ToTestDisplayString(includeNonNullable: true))); AssertEx.SetEqual( new[] { "I1<System.String>", "I2<System.String, System.Object!>" }, imc2.AllInterfacesNoUseSiteDiagnostics.Select(i => i.ToTestDisplayString(includeNonNullable: true))); } [Theory] [InlineData(true)] [InlineData(false)] [WorkItem(40033, "https://github.com/dotnet/roslyn/issues/40033")] public void SynthesizeNullableAttributeBasedOnInterfacesToEmit_NotOnAllInterfaces(bool useImageReferences) { Func<CSharpCompilation, MetadataReference> getReference = c => useImageReferences ? c.EmitToImageReference() : c.ToMetadataReference(); var lib1_source = @" #nullable enable public interface I2<T, TResult> { } public interface I1<T> : I2<T, object> { } "; var lib1_comp = CreateCompilation(lib1_source); lib1_comp.VerifyDiagnostics(); var lib2_source = @" #nullable disable public class C0 : I1<string> { }"; var lib2_comp = CreateCompilation(lib2_source, references: new[] { getReference(lib1_comp) }); lib2_comp.VerifyDiagnostics(); var lib2_c0 = (TypeSymbol)lib2_comp.GlobalNamespace.GetMember("C0"); AssertEx.SetEqual( new[] { "I1<System.String>" }, lib2_c0.InterfacesNoUseSiteDiagnostics().Select(i => i.ToTestDisplayString(includeNonNullable: true))); AssertEx.SetEqual( new[] { "I1<System.String>", "I2<System.String, System.Object!>" }, lib2_c0.AllInterfacesNoUseSiteDiagnostics.Select(i => i.ToTestDisplayString(includeNonNullable: true))); CompileAndVerify(lib2_comp, validator: assembly => { var reader = assembly.GetMetadataReader(); var typeDef = GetTypeDefinitionByName(reader, "C0"); var interfaceHandles = typeDef.GetInterfaceImplementations(); var interfaceImpl1 = reader.GetInterfaceImplementation(interfaceHandles.First()); Assert.Equal("TypeSpecification:I1`1{String}", reader.Dump(interfaceImpl1.Interface)); AssertAttributes(reader, interfaceImpl1.GetCustomAttributes()); var interfaceImpl2 = reader.GetInterfaceImplementation(interfaceHandles.Last()); Assert.Equal("TypeSpecification:I2`2{String, Object}", reader.Dump(interfaceImpl2.Interface)); AssertAttributes(reader, interfaceImpl2.GetCustomAttributes(), "MethodDefinition:Void System.Runtime.CompilerServices.NullableAttribute..ctor(Byte[])"); assertType(reader, exists: true, "NullableAttribute"); }); var lib3_source = @" #nullable disable public class C1 : C0 { }"; var lib3_comp = CreateCompilation(lib3_source, references: new[] { getReference(lib1_comp), getReference(lib2_comp) }); lib3_comp.VerifyDiagnostics(); var lib3_c0 = (TypeSymbol)lib2_comp.GlobalNamespace.GetMember("C0"); AssertEx.SetEqual( new[] { "I1<System.String>" }, lib3_c0.InterfacesNoUseSiteDiagnostics().Select(i => i.ToTestDisplayString(includeNonNullable: true))); AssertEx.SetEqual( new[] { "I1<System.String>", "I2<System.String, System.Object!>" }, lib3_c0.AllInterfacesNoUseSiteDiagnostics.Select(i => i.ToTestDisplayString(includeNonNullable: true))); CompileAndVerify(lib3_comp, validator: assembly => { var reader = assembly.GetMetadataReader(); var typeDef = GetTypeDefinitionByName(reader, "C1"); var interfaceHandles = typeDef.GetInterfaceImplementations(); Assert.True(interfaceHandles.IsEmpty()); assertType(reader, exists: false, "NullableAttribute"); }); void assertType(MetadataReader reader, bool exists, string name) { if (exists) { _ = reader.TypeDefinitions.Single(h => reader.StringComparer.Equals(reader.GetTypeDefinition(h).Name, name)); } else { Assert.False(reader.TypeDefinitions.Any(h => reader.StringComparer.Equals(reader.GetTypeDefinition(h).Name, name))); } } } [Theory] [InlineData(true)] [InlineData(false)] [WorkItem(40033, "https://github.com/dotnet/roslyn/issues/40033")] public void SynthesizeTupleElementNamesAttributeBasedOnInterfacesToEmit_IndirectInterfaces(bool useImageReferences) { Func<CSharpCompilation, MetadataReference> getReference = c => useImageReferences ? c.EmitToImageReference() : c.ToMetadataReference(); var valueTuple_source = @" namespace System { public struct ValueTuple<T1, T2> { public T1 Item1; public T2 Item2; public ValueTuple(T1 item1, T2 item2) { this.Item1 = item1; this.Item2 = item2; } public override string ToString() { return '{' + Item1?.ToString() + "", "" + Item2?.ToString() + '}'; } } }"; var valueTuple_comp = CreateCompilationWithMscorlib40(valueTuple_source); valueTuple_comp.VerifyDiagnostics(); var tupleElementNamesAttribute_source = @" namespace System.Runtime.CompilerServices { public class TupleElementNamesAttribute : Attribute { public TupleElementNamesAttribute(string[] transformNames) { } } }"; var tupleElementNamesAttribute_comp = CreateCompilationWithMscorlib40(tupleElementNamesAttribute_source); tupleElementNamesAttribute_comp.VerifyDiagnostics(); var lib1_source = @" using System.Threading.Tasks; public interface I2<T, TResult> { Task<TResult> ExecuteAsync(T parameter); } public interface I1<T> : I2<T, (object a, object b)> { } "; var lib1_comp = CreateCompilationWithMscorlib40(lib1_source, references: new[] { getReference(valueTuple_comp), getReference(tupleElementNamesAttribute_comp) }); lib1_comp.VerifyDiagnostics(); var lib2_source = @" public interface I0 : I1<string> { }"; var lib2_comp = CreateCompilationWithMscorlib40(lib2_source, references: new[] { getReference(lib1_comp), getReference(valueTuple_comp) }); // missing TupleElementNamesAttribute lib2_comp.VerifyDiagnostics( // (2,18): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public interface I0 : I1<string> Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "I0").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(2, 18) ); lib2_comp.VerifyEmitDiagnostics( // (2,18): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public interface I0 : I1<string> Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "I0").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(2, 18) ); var imc1 = (TypeSymbol)lib2_comp.GlobalNamespace.GetMember("I0"); AssertEx.SetEqual( new[] { "I1<System.String>" }, imc1.InterfacesNoUseSiteDiagnostics().Select(i => i.ToTestDisplayString(includeNonNullable: true))); AssertEx.SetEqual( new[] { "I1<System.String>", "I2<System.String, (System.Object a, System.Object b)>" }, imc1.AllInterfacesNoUseSiteDiagnostics.Select(i => i.ToTestDisplayString(includeNonNullable: true))); } [Fact, WorkItem(40033, "https://github.com/dotnet/roslyn/issues/40033")] public void SynthesizeTupleElementNamesAttributeBasedOnInterfacesToEmit_BaseAndDirectInterface() { var source = @" namespace System { public struct ValueTuple<T1, T2> { public T1 Item1; public T2 Item2; public ValueTuple(T1 item1, T2 item2) { this.Item1 = item1; this.Item2 = item2; } public override string ToString() { return '{' + Item1?.ToString() + "", "" + Item2?.ToString() + '}'; } } } namespace System.Runtime.CompilerServices { public class TupleElementNamesAttribute : Attribute { public TupleElementNamesAttribute() { } // Note: bad signature } } public interface I<T> { } public class Base<T> { } public class C1 : I<(object a, object b)> { } public class C2 : Base<(object a, object b)> { } "; var comp = CreateCompilationWithMscorlib40(source); comp.VerifyEmitDiagnostics( // (34,14): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public class C1 : I<(object a, object b)> { } Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "C1").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(34, 14), // (34,21): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public class C1 : I<(object a, object b)> { } Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(object a, object b)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(34, 21), // (36,24): error CS8137: Cannot define a class or member that utilizes tuples because the compiler required type 'System.Runtime.CompilerServices.TupleElementNamesAttribute' cannot be found. Are you missing a reference? // public class C2 : Base<(object a, object b)> { } Diagnostic(ErrorCode.ERR_TupleElementNamesAttributeMissing, "(object a, object b)").WithArguments("System.Runtime.CompilerServices.TupleElementNamesAttribute").WithLocation(36, 24) ); } [Fact] public void ExplicitAttributeFromSource() { var source = @"namespace System.Runtime.CompilerServices { public sealed class NullableAttribute : Attribute { public NullableAttribute(byte a) { } public NullableAttribute(byte[] b) { } } } class C { static void F(object? x, object?[] y) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNullableEnable(), parseOptions: TestOptions.Regular8); comp.VerifyEmitDiagnostics(); } [Fact] public void ExplicitAttributeFromMetadata() { var source0 = @"namespace System.Runtime.CompilerServices { public sealed class NullableAttribute : Attribute { public NullableAttribute(byte a) { } public NullableAttribute(byte[] b) { } } }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular7); var ref0 = comp0.EmitToImageReference(); var source = @"class C { static void F(object? x, object?[] y) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNullableEnable(), references: new[] { ref0 }, parseOptions: TestOptions.Regular8); comp.VerifyEmitDiagnostics(); } [Fact] public void ExplicitAttribute_MissingSingleByteConstructor() { var source = @"namespace System.Runtime.CompilerServices { public sealed class NullableAttribute : Attribute { public NullableAttribute(byte[] b) { } } } class C { static void F(object? x, object?[] y) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNullableEnable(), parseOptions: TestOptions.Regular8); comp.VerifyEmitDiagnostics( // (5,34): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // public NullableAttribute(byte[] b) { } Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "byte[] b").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(5, 34), // (10,19): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // static void F(object? x, object?[] y) { } Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "object? x").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(10, 19), // (10,30): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // static void F(object? x, object?[] y) { } Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "object?[] y").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(10, 30)); } [Fact] public void ExplicitAttribute_MissingConstructor() { var source = @"namespace System.Runtime.CompilerServices { public sealed class NullableAttribute : Attribute { public NullableAttribute() { } } } class C { static void F(object? x, object?[] y) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNullableEnable(), parseOptions: TestOptions.Regular8); comp.VerifyEmitDiagnostics( // (10,19): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // static void F(object? x, object?[] y) { } Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "object? x").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(10, 19), // (10,30): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // static void F(object? x, object?[] y) { } Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "object?[] y").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(10, 30)); } [Fact] public void ExplicitAttribute_MissingBothNeededConstructors() { var source = @"namespace System.Runtime.CompilerServices { public sealed class NullableAttribute : Attribute { public NullableAttribute(string[] b) { } } } class C { static void F(object? x, object?[] y) { } }"; var comp = CreateCompilation(new[] { source }, options: WithNullableEnable(), parseOptions: TestOptions.Regular8); comp.VerifyEmitDiagnostics( // (5,34): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // public NullableAttribute(string[] b) { } Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "string[] b").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(5, 34), // (10,19): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // static void F(object? x, object?[] y) { } Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "object? x").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(10, 19), // (10,30): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // static void F(object? x, object?[] y) { } Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "object?[] y").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(10, 30)); } [Fact] public void ExplicitAttribute_ReferencedInSource() { var sourceAttribute = @"namespace System.Runtime.CompilerServices { internal class NullableAttribute : System.Attribute { internal NullableAttribute(byte b) { } } }"; var source = @"#pragma warning disable 169 using System.Runtime.CompilerServices; [assembly: Nullable(0)] [module: Nullable(0)] [Nullable(0)] class Program { [Nullable(0)]object F; [Nullable(0)]static object M1() => throw null; [return: Nullable(0)]static object M2() => throw null; static void M3([Nullable(0)]object arg) { } }"; // C#7 var comp = CreateCompilation(new[] { sourceAttribute, source }, parseOptions: TestOptions.Regular7); verifyDiagnostics(comp); // C#8 comp = CreateCompilation(new[] { sourceAttribute, source }); verifyDiagnostics(comp); static void verifyDiagnostics(CSharpCompilation comp) { comp.VerifyDiagnostics( // (5,2): error CS8623: Explicit application of 'System.Runtime.CompilerServices.NullableAttribute' is not allowed. // [Nullable(0)] Diagnostic(ErrorCode.ERR_ExplicitNullableAttribute, "Nullable(0)").WithLocation(5, 2), // (8,6): error CS8623: Explicit application of 'System.Runtime.CompilerServices.NullableAttribute' is not allowed. // [Nullable(0)]object F; Diagnostic(ErrorCode.ERR_ExplicitNullableAttribute, "Nullable(0)").WithLocation(8, 6), // (10,14): error CS8623: Explicit application of 'System.Runtime.CompilerServices.NullableAttribute' is not allowed. // [return: Nullable(0)]static object M2() => throw null; Diagnostic(ErrorCode.ERR_ExplicitNullableAttribute, "Nullable(0)").WithLocation(10, 14), // (11,21): error CS8623: Explicit application of 'System.Runtime.CompilerServices.NullableAttribute' is not allowed. // static void M3([Nullable(0)]object arg) { } Diagnostic(ErrorCode.ERR_ExplicitNullableAttribute, "Nullable(0)").WithLocation(11, 21)); } } [Fact] public void AttributeFromInternalsVisibleTo_01() { var sourceA = @"using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo(""B"")] #nullable enable class A { object? F = null; }"; var options = TestOptions.ReleaseDll.WithMetadataImportOptions(MetadataImportOptions.All); var comp = CreateCompilation(sourceA, assemblyName: "A", options: options); CompileAndVerify(comp, symbolValidator: m => CheckAttribute(m.GlobalNamespace.GetMember("A.F").GetAttributes().Single(), "A")); var refA = comp.EmitToImageReference(); var sourceB = @"#nullable enable class B { object? G = new A(); }"; comp = CreateCompilation(sourceB, references: new[] { refA }, assemblyName: "B", options: options); CompileAndVerify(comp, symbolValidator: m => CheckAttribute(m.GlobalNamespace.GetMember("B.G").GetAttributes().Single(), "B")); } [Fact] public void AttributeFromInternalsVisibleTo_02() { var sourceAttribute = @"namespace System.Runtime.CompilerServices { internal sealed class NullableAttribute : Attribute { public NullableAttribute(byte b) { } public NullableAttribute(byte[] b) { } } }"; var sourceA = @"using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo(""B"")] #nullable enable class A { object? F = null; }"; var options = TestOptions.ReleaseDll.WithMetadataImportOptions(MetadataImportOptions.All); var comp = CreateCompilation(new[] { sourceAttribute, sourceA }, assemblyName: "A", options: options); CompileAndVerify(comp, symbolValidator: m => CheckAttribute(m.GlobalNamespace.GetMember("A.F").GetAttributes().Single(), "A")); var refA = comp.EmitToImageReference(); var sourceB = @"#nullable enable class B { object? G = new A(); }"; comp = CreateCompilation(sourceB, references: new[] { refA }, assemblyName: "B", options: options); CompileAndVerify(comp, symbolValidator: m => CheckAttribute(m.GlobalNamespace.GetMember("B.G").GetAttributes().Single(), "A")); } private static void CheckAttribute(CSharpAttributeData attribute, string assemblyName) { var attributeType = attribute.AttributeClass; Assert.Equal("System.Runtime.CompilerServices", attributeType.ContainingNamespace.QualifiedName); Assert.Equal("NullableAttribute", attributeType.Name); Assert.Equal(assemblyName, attributeType.ContainingAssembly.Name); } [Fact] public void NullableAttribute_MissingByte() { var source0 = @"namespace System { public class Object { } public abstract class ValueType { } public struct Void { } public class Attribute { } }"; var comp0 = CreateEmptyCompilation(source0, parseOptions: TestOptions.Regular7); var ref0 = comp0.EmitToImageReference(); var source = @"class C { object? F() => null; }"; var comp = CreateEmptyCompilation( source, references: new[] { ref0 }, parseOptions: TestOptions.Regular8); comp.VerifyEmitDiagnostics( // (3,11): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. // object? F() => null; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(3, 11), // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute..ctor' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", ".ctor").WithLocation(1, 1), // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute.AllowMultiple' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", "AllowMultiple").WithLocation(1, 1), // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute.Inherited' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", "Inherited").WithLocation(1, 1), // error CS0518: Predefined type 'System.Byte' is not defined or imported Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound).WithArguments("System.Byte").WithLocation(1, 1), // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute..ctor' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", ".ctor").WithLocation(1, 1), // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute.AllowMultiple' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", "AllowMultiple").WithLocation(1, 1), // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute.Inherited' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", "Inherited").WithLocation(1, 1), // error CS0518: Predefined type 'System.Byte' is not defined or imported Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound).WithArguments("System.Byte").WithLocation(1, 1), // error CS0518: Predefined type 'System.Int32' is not defined or imported // Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "").WithArguments("System.Int32").WithLocation(1, 1)); } [Fact] public void NullableAttribute_MissingAttribute() { var source0 = @"namespace System { public class Object { } public abstract class ValueType { } public struct Void { } public struct Byte { } }"; var comp0 = CreateEmptyCompilation(source0, parseOptions: TestOptions.Regular7); var ref0 = comp0.EmitToImageReference(); var source = @"class C { object? F() => null; }"; var comp = CreateEmptyCompilation( source, references: new[] { ref0 }, parseOptions: TestOptions.Regular8); comp.VerifyEmitDiagnostics( // (3,11): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. // object? F() => null; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(3, 11), // error CS0518: Predefined type 'System.Attribute' is not defined or imported Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound).WithArguments("System.Attribute").WithLocation(1, 1), // error CS0518: Predefined type 'System.Attribute' is not defined or imported Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound).WithArguments("System.Attribute").WithLocation(1, 1), // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute..ctor' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", ".ctor").WithLocation(1, 1), // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute.AllowMultiple' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", "AllowMultiple").WithLocation(1, 1), // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute.Inherited' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", "Inherited").WithLocation(1, 1), // error CS0518: Predefined type 'System.Attribute' is not defined or imported Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound).WithArguments("System.Attribute").WithLocation(1, 1), // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute..ctor' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", ".ctor").WithLocation(1, 1), // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute.AllowMultiple' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", "AllowMultiple").WithLocation(1, 1), // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute.Inherited' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", "Inherited").WithLocation(1, 1)); } [Fact] public void NullableAttribute_StaticAttributeConstructorOnly() { var source0 = @"namespace System { public class Object { } public abstract class ValueType { } public struct Void { } public struct Boolean { } public struct Byte { } public class Attribute { static Attribute() { } public Attribute(object o) { } } }"; var comp0 = CreateEmptyCompilation(source0, parseOptions: TestOptions.Regular7); var ref0 = comp0.EmitToImageReference(); var source = @"class C { object? F() => null; }"; var comp = CreateEmptyCompilation( source, references: new[] { ref0 }, parseOptions: TestOptions.Regular8); comp.VerifyEmitDiagnostics( // (3,11): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. // object? F() => null; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(3, 11), // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute..ctor' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", ".ctor").WithLocation(1, 1), // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute.AllowMultiple' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", "AllowMultiple").WithLocation(1, 1), // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute.Inherited' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", "Inherited").WithLocation(1, 1), // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute..ctor' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", ".ctor").WithLocation(1, 1), // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute.AllowMultiple' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", "AllowMultiple").WithLocation(1, 1), // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute.Inherited' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", "Inherited").WithLocation(1, 1), // error CS1729: 'Attribute' does not contain a constructor that takes 0 arguments Diagnostic(ErrorCode.ERR_BadCtorArgCount).WithArguments("System.Attribute", "0").WithLocation(1, 1), // error CS1729: 'Attribute' does not contain a constructor that takes 0 arguments Diagnostic(ErrorCode.ERR_BadCtorArgCount).WithArguments("System.Attribute", "0").WithLocation(1, 1), // error CS1729: 'Attribute' does not contain a constructor that takes 0 arguments Diagnostic(ErrorCode.ERR_BadCtorArgCount).WithArguments("System.Attribute", "0").WithLocation(1, 1), // error CS1729: 'Attribute' does not contain a constructor that takes 0 arguments Diagnostic(ErrorCode.ERR_BadCtorArgCount).WithArguments("System.Attribute", "0").WithLocation(1, 1)); } [Fact] public void MissingAttributeUsageAttribute() { var source = @"#nullable enable class Program { object? F() => null; }"; var parseOptions = TestOptions.Regular.WithNoRefSafetyRulesAttribute(); var comp = CreateCompilation(source, parseOptions: parseOptions); comp.MakeTypeMissing(WellKnownType.System_AttributeUsageAttribute); comp.VerifyEmitDiagnostics( // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute..ctor' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", ".ctor").WithLocation(1, 1), // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute.AllowMultiple' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", "AllowMultiple").WithLocation(1, 1), // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute.Inherited' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", "Inherited").WithLocation(1, 1), // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute..ctor' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", ".ctor").WithLocation(1, 1), // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute.AllowMultiple' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", "AllowMultiple").WithLocation(1, 1), // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute.Inherited' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", "Inherited").WithLocation(1, 1)); comp = CreateCompilation(source, parseOptions: parseOptions); comp.MakeMemberMissing(WellKnownMember.System_AttributeUsageAttribute__ctor); comp.VerifyEmitDiagnostics( // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute..ctor' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", ".ctor").WithLocation(1, 1), // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute..ctor' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", ".ctor").WithLocation(1, 1)); comp = CreateCompilation(source, parseOptions: parseOptions); comp.MakeMemberMissing(WellKnownMember.System_AttributeUsageAttribute__AllowMultiple); comp.VerifyEmitDiagnostics( // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute.AllowMultiple' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", "AllowMultiple").WithLocation(1, 1), // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute.AllowMultiple' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", "AllowMultiple").WithLocation(1, 1)); comp = CreateCompilation(source, parseOptions: parseOptions); comp.MakeMemberMissing(WellKnownMember.System_AttributeUsageAttribute__Inherited); comp.VerifyEmitDiagnostics( // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute.Inherited' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", "Inherited").WithLocation(1, 1), // error CS0656: Missing compiler required member 'System.AttributeUsageAttribute.Inherited' Diagnostic(ErrorCode.ERR_MissingPredefinedMember).WithArguments("System.AttributeUsageAttribute", "Inherited").WithLocation(1, 1)); } [Fact] public void EmitAttribute_NoNullable() { var source = @"public class C { public object F = new object(); }"; // C# 7.0: No NullableAttribute. var comp = CreateCompilation(source, parseOptions: TestOptions.Regular7); CompileAndVerify(comp, symbolValidator: module => { var assembly = module.ContainingAssembly; var type = assembly.GetTypeByMetadataName("C"); var field = (FieldSymbol)type.GetMembers("F").Single(); AssertNoNullableAttribute(field.GetAttributes()); AssertNoNullableAttribute(module.GetAttributes()); AssertAttributes(assembly.GetAttributes(), "System.Runtime.CompilerServices.CompilationRelaxationsAttribute", "System.Runtime.CompilerServices.RuntimeCompatibilityAttribute", "System.Diagnostics.DebuggableAttribute"); }); // C# 8.0: NullableAttribute not included if no ? annotation. comp = CreateCompilation(source, parseOptions: TestOptions.Regular8); CompileAndVerify(comp, symbolValidator: module => { var assembly = module.ContainingAssembly; var type = assembly.GetTypeByMetadataName("C"); var field = (FieldSymbol)type.GetMembers("F").Single(); AssertNoNullableAttribute(field.GetAttributes()); AssertNoNullableAttribute(module.GetAttributes()); AssertAttributes(assembly.GetAttributes(), "System.Runtime.CompilerServices.CompilationRelaxationsAttribute", "System.Runtime.CompilerServices.RuntimeCompatibilityAttribute", "System.Diagnostics.DebuggableAttribute"); }); } [Fact] public void EmitAttribute_LocalFunctionConstraints() { var source = @" class C { #nullable enable void M1() { local(new C()); void local<T>(T t) where T : C? { } } }"; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8); CompileAndVerify(comp, symbolValidator: module => { var assembly = module.ContainingAssembly; Assert.NotNull(assembly.GetTypeByMetadataName("System.Runtime.CompilerServices.NullableAttribute")); }); } [Fact] public void EmitAttribute_OnlyAnnotationsEnabled_LocalFunctionConstraints() { var source = @" class C { #nullable enable annotations void M1() { local(new C()); void local<T>(T t) where T : C? { } } }"; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8); CompileAndVerify(comp, symbolValidator: module => { var assembly = module.ContainingAssembly; Assert.NotNull(assembly.GetTypeByMetadataName("System.Runtime.CompilerServices.NullableAttribute")); }); } [Fact] public void EmitAttribute_NullableEnabledInProject_LocalFunctionConstraints() { var source = @" class C { void M1() { local(new C()); void local<T>(T t) where T : C? { } } }"; var comp = CreateCompilation(new[] { source }, options: WithNullable(NullableContextOptions.Enable), parseOptions: TestOptions.Regular8); CompileAndVerify(comp, symbolValidator: module => { var assembly = module.ContainingAssembly; Assert.NotNull(assembly.GetTypeByMetadataName("System.Runtime.CompilerServices.NullableAttribute")); }); } [Fact] public void EmitAttribute_OnlyAnnotationsEnabledInProject_LocalFunctionConstraints() { var source = @" class C { void M1() { local(new C()); void local<T>(T t) where T : C? { } } }"; var comp = CreateCompilation(new[] { source }, options: WithNullable(NullableContextOptions.Annotations), parseOptions: TestOptions.Regular8); CompileAndVerify(comp, symbolValidator: module => { var assembly = module.ContainingAssembly; Assert.NotNull(assembly.GetTypeByMetadataName("System.Runtime.CompilerServices.NullableAttribute")); }); } [Fact] public void EmitAttribute_LocalFunctionConstraints_Nested() { var source = @" interface I<T> { } class C { #nullable enable void M1() { void local<T>(T t) where T : I<C?> { } } }"; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8); CompileAndVerify(comp, symbolValidator: module => { var assembly = module.ContainingAssembly; Assert.NotNull(assembly.GetTypeByMetadataName("System.Runtime.CompilerServices.NullableAttribute")); }); } [Fact] public void EmitAttribute_LocalFunctionConstraints_NoAnnotation() { var source = @" class C { #nullable enable void M1() { local(new C()); void local<T>(T t) where T : C { } } }"; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8); CompileAndVerify(comp, symbolValidator: module => { var assembly = module.ContainingAssembly; Assert.NotNull(assembly.GetTypeByMetadataName("System.Runtime.CompilerServices.NullableAttribute")); }); } [Fact] public void EmitAttribute_Module() { var source = @"public class C { public object? F = new object(); }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8); CompileAndVerify(comp, symbolValidator: module => { var assembly = module.ContainingAssembly; var type = assembly.GetTypeByMetadataName("C"); var field = (FieldSymbol)type.GetMembers("F").Single(); AssertNullableAttribute(field.GetAttributes()); AssertNoNullableAttribute(module.GetAttributes()); AssertAttributes(assembly.GetAttributes(), "System.Runtime.CompilerServices.CompilationRelaxationsAttribute", "System.Runtime.CompilerServices.RuntimeCompatibilityAttribute", "System.Diagnostics.DebuggableAttribute"); }); } [Fact] public void EmitAttribute_NetModule() { var source = @"public class C { public object? F = new object(); }"; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: WithNullableEnable(TestOptions.ReleaseModule)); comp.VerifyEmitDiagnostics( // (3,20): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // public object? F = new object(); Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "F").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(3, 20)); } [Fact] public void EmitAttribute_NetModuleNoDeclarations() { var source = ""; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseModule); CompileAndVerify(comp, verify: Verification.Skipped, symbolValidator: module => { AssertAttributes(module.GetAttributes()); }); } [Fact] public void EmitAttribute_01() { var source = @"public class Program { public object? F; public object?[]? G; }"; var comp = CreateCompilation(source, options: WithNullableEnable()); var expected = @"[NullableContext(2)] [Nullable(0)] Program System.Object? F System.Object?[]? G Program() "; AssertNullableAttributes(comp, expected); } [Fact] public void EmitAttribute_02() { var source = @"public class Program { public object? F(object?[]? args) => null; public object G(object[] args) => null!; }"; var comp = CreateCompilation(source, options: WithNullableEnable()); var expected = @"Program [NullableContext(2)] System.Object? F(System.Object?[]? args) System.Object?[]? args [NullableContext(1)] System.Object! G(System.Object![]! args) System.Object![]! args "; AssertNullableAttributes(comp, expected); } [Fact] public void EmitAttribute_03() { var source = @"public class Program { public static void F(string x, string y, string z) { } }"; var comp = CreateCompilation(source, options: WithNullableEnable()); var expected = @"Program [NullableContext(1)] void F(System.String! x, System.String! y, System.String! z) System.String! x System.String! y System.String! z "; AssertNullableAttributes(comp, expected); } [Fact] public void EmitAttribute_BaseClass() { var source = @"public class A<T> { } public class B1 : A<object> { } public class B2 : A<object?> { }"; var comp = CreateCompilation(new[] { source }, options: WithNullableEnable(), parseOptions: TestOptions.Regular8); var expected = @"A<T> [Nullable(2)] T [Nullable({ 0, 1 })] B1 [Nullable({ 0, 2 })] B2 "; AssertNullableAttributes(comp, expected); var source2 = @"class C { static void F(A<object> x, A<object?> y) { } static void G(B1 x, B2 y) { F(x, x); F(y, y); } }"; var comp2 = CreateCompilation(new[] { source2 }, options: WithNullableEnable(), parseOptions: TestOptions.Regular8, references: new[] { comp.EmitToImageReference() }); comp2.VerifyDiagnostics( // (8,14): warning CS8620: Argument of type 'B1' cannot be used as an input of type 'A<object?>' for parameter 'y' in 'void C.F(A<object> x, A<object?> y)' due to differences in the nullability of reference types. // F(x, x); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("B1", "A<object?>", "y", "void C.F(A<object> x, A<object?> y)").WithLocation(8, 14), // (9,11): warning CS8620: Argument of type 'B2' cannot be used as an input of type 'A<object>' for parameter 'x' in 'void C.F(A<object> x, A<object?> y)' due to differences in the nullability of reference types. // F(y, y); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("B2", "A<object>", "x", "void C.F(A<object> x, A<object?> y)").WithLocation(9, 11)); } [Fact] public void EmitAttribute_Interface_01() { var source = @"public interface I<T> { } public class A : I<object> { } #nullable disable public class AOblivious : I<object> { } #nullable enable public class B : I<object?> { } "; var comp = CreateCompilation(new[] { source }, options: WithNullableEnable(), parseOptions: TestOptions.Regular8); CompileAndVerify(comp, validator: assembly => { var reader = assembly.GetMetadataReader(); var typeDef = GetTypeDefinitionByName(reader, "A"); var interfaceImpl = reader.GetInterfaceImplementation(typeDef.GetInterfaceImplementations().Single()); AssertAttributes(reader, interfaceImpl.GetCustomAttributes(), "MethodDefinition:Void System.Runtime.CompilerServices.NullableAttribute..ctor(Byte[])"); typeDef = GetTypeDefinitionByName(reader, "B"); interfaceImpl = reader.GetInterfaceImplementation(typeDef.GetInterfaceImplementations().Single()); AssertAttributes(reader, interfaceImpl.GetCustomAttributes(), "MethodDefinition:Void System.Runtime.CompilerServices.NullableAttribute..ctor(Byte[])"); }); var source2 = @"class C { static void F(I<object> x, I<object?> y) { } #nullable disable static void FOblivious(I<object> x) { } #nullable enable static void G(A x, B y, AOblivious z) { F(x, x); F(y, y); F(z, z); FOblivious(x); FOblivious(y); FOblivious(z); } }"; var comp2 = CreateCompilation(new[] { source2 }, options: WithNullableEnable(), parseOptions: TestOptions.Regular8, references: new[] { comp.EmitToImageReference() }); comp2.VerifyDiagnostics( // (9,14): warning CS8620: Argument of type 'A' cannot be used as an input of type 'I<object?>' for parameter 'y' in 'void C.F(I<object> x, I<object?> y)' due to differences in the nullability of reference types. // F(x, x); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "x").WithArguments("A", "I<object?>", "y", "void C.F(I<object> x, I<object?> y)").WithLocation(9, 14), // (10,11): warning CS8620: Argument of type 'B' cannot be used as an input of type 'I<object>' for parameter 'x' in 'void C.F(I<object> x, I<object?> y)' due to differences in the nullability of reference types. // F(y, y); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "y").WithArguments("B", "I<object>", "x", "void C.F(I<object> x, I<object?> y)").WithLocation(10, 11)); } [Fact] public void EmitAttribute_Interface_02() { var source = @"public interface I<T> { } public class A : I<(object X, object Y)> { } public class B : I<(object X, object? Y)> { }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8); CompileAndVerify(comp, validator: assembly => { var reader = assembly.GetMetadataReader(); var typeDef = GetTypeDefinitionByName(reader, "A"); var interfaceImpl = reader.GetInterfaceImplementation(typeDef.GetInterfaceImplementations().Single()); AssertAttributes(reader, interfaceImpl.GetCustomAttributes(), "MemberReference:Void System.Runtime.CompilerServices.TupleElementNamesAttribute..ctor(String[])"); typeDef = GetTypeDefinitionByName(reader, "B"); interfaceImpl = reader.GetInterfaceImplementation(typeDef.GetInterfaceImplementations().Single()); AssertAttributes(reader, interfaceImpl.GetCustomAttributes(), "MemberReference:Void System.Runtime.CompilerServices.TupleElementNamesAttribute..ctor(String[])", "MethodDefinition:Void System.Runtime.CompilerServices.NullableAttribute..ctor(Byte[])"); }); var source2 = @"class C { static void F(I<(object, object)> a, I<(object, object?)> b) { } static void G(A a, B b) { F(a, a); F(b, b); } }"; var comp2 = CreateCompilation(new[] { source2 }, options: WithNullableEnable(), parseOptions: TestOptions.Regular8, references: new[] { comp.EmitToImageReference() }); comp2.VerifyDiagnostics( // (9,11): warning CS8620: Argument of type 'B' cannot be used as an input of type 'I<(object, object)>' for parameter 'a' in 'void C.F(I<(object, object)> a, I<(object, object?)> b)' due to differences in the nullability of reference types. // F(b, b); Diagnostic(ErrorCode.WRN_NullabilityMismatchInArgument, "b").WithArguments("B", "I<(object, object)>", "a", "void C.F(I<(object, object)> a, I<(object, object?)> b)").WithLocation(9, 11)); var type = comp2.GetMember<NamedTypeSymbol>("A"); Assert.Equal("I<(System.Object X, System.Object Y)>", type.Interfaces()[0].ToTestDisplayString()); type = comp2.GetMember<NamedTypeSymbol>("B"); Assert.Equal("I<(System.Object X, System.Object? Y)>", type.Interfaces()[0].ToTestDisplayString()); } [Fact] public void EmitAttribute_ImplementedInterfaces_01() { var source = @"#nullable enable public interface I<T> { } public class A : I<object>, I<string?> { public object FA1; public object FA2; } public class B : #nullable disable I<object>, #nullable enable I<int> { public object FB1; public object FB2; }"; var comp = CreateCompilation(source); var expected = @"[NullableContext(2)] I<T> T [NullableContext(1)] [Nullable(0)] A System.Object! FA1 System.Object! FA2 A() B [Nullable(1)] System.Object! FB1 [Nullable(1)] System.Object! FB2 "; AssertNullableAttributes(comp, expected); } [Fact] public void EmitAttribute_ImplementedInterfaces_02() { var source = @"#nullable enable public interface IA { } public interface IB<T> : IA { } public interface IC<T> : IB< #nullable disable object #nullable enable > { } public class C : IC< #nullable disable string #nullable enable > { public object F1; public object F2; public object F3; }"; var comp = CreateCompilation(source); var expected = @"IB<T> [Nullable(2)] T IC<T> [Nullable(2)] T C [Nullable(1)] System.Object! F1 [Nullable(1)] System.Object! F2 [Nullable(1)] System.Object! F3 "; AssertNullableAttributes(comp, expected); } [Fact] public void EmitAttribute_TypeParameters() { var source = @"#nullable enable public interface I<T, U, V> where U : class where V : struct { T F1(); U F2(); U? F3(); V F4(); V? F5(); #nullable disable T F6(); U F7(); U? F8(); V F9(); V? F10(); }"; var comp = CreateCompilation(source); var expected = @"I<T, U, V> where U : class! where V : struct [Nullable(2)] T [Nullable(1)] U [NullableContext(1)] T F1() [NullableContext(1)] U! F2() [NullableContext(2)] U? F3() [NullableContext(2)] U? F8() "; AssertNullableAttributes(comp, expected); } [Fact] public void EmitAttribute_Constraint_Nullable() { var source = @"public class A { } public class C<T> where T : A? { } public class D<T> where T : A { }"; var comp = CreateCompilation(new[] { source }, options: WithNullableEnable(), parseOptions: TestOptions.Regular8); CompileAndVerify(comp, validator: assembly => { var reader = assembly.GetMetadataReader(); var typeDef = GetTypeDefinitionByName(reader, "C`1"); var typeParameter = reader.GetGenericParameter(typeDef.GetGenericParameters()[0]); var constraint = reader.GetGenericParameterConstraint(typeParameter.GetConstraints()[0]); AssertAttributes(reader, constraint.GetCustomAttributes(), "MethodDefinition:Void System.Runtime.CompilerServices.NullableAttribute..ctor(Byte)"); typeDef = GetTypeDefinitionByName(reader, "D`1"); typeParameter = reader.GetGenericParameter(typeDef.GetGenericParameters()[0]); constraint = reader.GetGenericParameterConstraint(typeParameter.GetConstraints()[0]); AssertAttributes(reader, constraint.GetCustomAttributes(), "MethodDefinition:Void System.Runtime.CompilerServices.NullableAttribute..ctor(Byte)"); }); var source2 = @"class B : A { } class Program { static void Main() { new C<A?>(); new C<A>(); new C<B?>(); new C<B>(); new D<A?>(); // warning new D<A>(); new D<B?>(); // warning new D<B>(); } }"; var comp2 = CreateCompilation(new[] { source, source2 }, options: WithNullableEnable(), parseOptions: TestOptions.Regular8); comp2.VerifyEmitDiagnostics( // (10,15): warning CS8627: The type 'A?' cannot be used as type parameter 'T' in the generic type or method 'D<T>'. Nullability of type argument 'A?' doesn't match constraint type 'A'. // new D<A?>(); // warning Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A?").WithArguments("D<T>", "A", "T", "A?").WithLocation(10, 15), // (12,15): warning CS8627: The type 'B?' cannot be used as type parameter 'T' in the generic type or method 'D<T>'. Nullability of type argument 'B?' doesn't match constraint type 'A'. // new D<B?>(); // warning Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "B?").WithArguments("D<T>", "A", "T", "B?").WithLocation(12, 15)); comp2 = CreateCompilation(new[] { source2 }, options: WithNullableEnable(), parseOptions: TestOptions.Regular8, references: new[] { comp.EmitToImageReference() }); comp2.VerifyEmitDiagnostics( // (10,15): warning CS8627: The type 'A?' cannot be used as type parameter 'T' in the generic type or method 'D<T>'. Nullability of type argument 'A?' doesn't match constraint type 'A'. // new D<A?>(); // warning Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A?").WithArguments("D<T>", "A", "T", "A?").WithLocation(10, 15), // (12,15): warning CS8627: The type 'B?' cannot be used as type parameter 'T' in the generic type or method 'D<T>'. Nullability of type argument 'B?' doesn't match constraint type 'A'. // new D<B?>(); // warning Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "B?").WithArguments("D<T>", "A", "T", "B?").WithLocation(12, 15)); var type = comp2.GetMember<NamedTypeSymbol>("C"); Assert.Equal("A?", type.TypeParameters[0].ConstraintTypesNoUseSiteDiagnostics[0].ToTestDisplayString(true)); type = comp2.GetMember<NamedTypeSymbol>("D"); Assert.Equal("A!", type.TypeParameters[0].ConstraintTypesNoUseSiteDiagnostics[0].ToTestDisplayString(true)); } // https://github.com/dotnet/roslyn/issues/29976: Test with [NonNullTypes]. [Fact] public void EmitAttribute_Constraint_Oblivious() { var source = @"public class A<T> { } public class C<T> where T : A<object> { }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular7); CompileAndVerify(comp, validator: assembly => { var reader = assembly.GetMetadataReader(); var typeDef = GetTypeDefinitionByName(reader, "C`1"); var typeParameter = reader.GetGenericParameter(typeDef.GetGenericParameters()[0]); var constraint = reader.GetGenericParameterConstraint(typeParameter.GetConstraints()[0]); AssertAttributes(reader, constraint.GetCustomAttributes()); }); var source2 = @"class B1 : A<object?> { } class B2 : A<object> { } class Program { static void Main() { new C<A<object?>>(); new C<A<object>>(); new C<A<object?>?>(); new C<A<object>?>(); new C<B1>(); new C<B2>(); new C<B1?>(); new C<B2?>(); } }"; var comp2 = CreateCompilation(new[] { source2 }, options: WithNullableEnable(), parseOptions: TestOptions.Regular8, references: new[] { comp.EmitToImageReference() }); comp2.VerifyDiagnostics(); var type = comp2.GetMember<NamedTypeSymbol>("C"); Assert.Equal("A<System.Object>", type.TypeParameters[0].ConstraintTypesNoUseSiteDiagnostics[0].ToTestDisplayString(true)); } [WorkItem(27742, "https://github.com/dotnet/roslyn/issues/27742")] [Fact] public void EmitAttribute_Constraint_Nested() { var source = @"public class A<T> { } public class B<T> where T : A<object?> { } public class C<T> where T : A<object> { }"; var comp = CreateCompilation(new[] { source }, options: WithNullableEnable(), parseOptions: TestOptions.Regular8); CompileAndVerify(comp, validator: assembly => { var reader = assembly.GetMetadataReader(); var typeDef = GetTypeDefinitionByName(reader, "B`1"); var typeParameter = reader.GetGenericParameter(typeDef.GetGenericParameters()[0]); var constraint = reader.GetGenericParameterConstraint(typeParameter.GetConstraints()[0]); AssertAttributes(reader, constraint.GetCustomAttributes(), "MethodDefinition:Void System.Runtime.CompilerServices.NullableAttribute..ctor(Byte[])"); typeDef = GetTypeDefinitionByName(reader, "C`1"); typeParameter = reader.GetGenericParameter(typeDef.GetGenericParameters()[0]); constraint = reader.GetGenericParameterConstraint(typeParameter.GetConstraints()[0]); AssertAttributes(reader, constraint.GetCustomAttributes(), "MethodDefinition:Void System.Runtime.CompilerServices.NullableAttribute..ctor(Byte)"); }); var source2 = @"class Program { static void Main() { new B<A<object?>>(); new B<A<object>>(); // warning new C<A<object?>>(); // warning new C<A<object>>(); } }"; var comp2 = CreateCompilation(new[] { source, source2 }, options: WithNullableEnable(), parseOptions: TestOptions.Regular8); comp2.VerifyEmitDiagnostics( // (6,15): warning CS8627: The type 'A<object>' cannot be used as type parameter 'T' in the generic type or method 'B<T>'. Nullability of type argument 'A<object>' doesn't match constraint type 'A<object?>'. // new B<A<object>>(); // warning Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A<object>").WithArguments("B<T>", "A<object?>", "T", "A<object>").WithLocation(6, 15), // (7,15): warning CS8627: The type 'A<object?>' cannot be used as type parameter 'T' in the generic type or method 'C<T>'. Nullability of type argument 'A<object?>' doesn't match constraint type 'A<object>'. // new C<A<object?>>(); // warning Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A<object?>").WithArguments("C<T>", "A<object>", "T", "A<object?>").WithLocation(7, 15)); comp2 = CreateCompilation(new[] { source2 }, options: WithNullableEnable(), parseOptions: TestOptions.Regular8, references: new[] { comp.EmitToImageReference() }); comp2.VerifyDiagnostics( // (6,15): warning CS8627: The type 'A<object>' cannot be used as type parameter 'T' in the generic type or method 'B<T>'. Nullability of type argument 'A<object>' doesn't match constraint type 'A<object?>'. // new B<A<object>>(); // warning Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A<object>").WithArguments("B<T>", "A<object?>", "T", "A<object>").WithLocation(6, 15), // (7,15): warning CS8627: The type 'A<object?>' cannot be used as type parameter 'T' in the generic type or method 'C<T>'. Nullability of type argument 'A<object?>' doesn't match constraint type 'A<object>'. // new C<A<object?>>(); // warning Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A<object?>").WithArguments("C<T>", "A<object>", "T", "A<object?>").WithLocation(7, 15)); var type = comp2.GetMember<NamedTypeSymbol>("B"); Assert.Equal("A<System.Object?>!", type.TypeParameters[0].ConstraintTypesNoUseSiteDiagnostics[0].ToTestDisplayString(true)); type = comp2.GetMember<NamedTypeSymbol>("C"); Assert.Equal("A<System.Object!>!", type.TypeParameters[0].ConstraintTypesNoUseSiteDiagnostics[0].ToTestDisplayString(true)); } [Fact] public void EmitAttribute_Constraint_TypeParameter() { var source = @"public class C<T, U> where T : class where U : T? { }"; var comp = CreateCompilation(new[] { source }, options: WithNullableEnable(), parseOptions: TestOptions.Regular8); CompileAndVerify(comp, validator: assembly => { var reader = assembly.GetMetadataReader(); var typeDef = GetTypeDefinitionByName(reader, "C`2"); var typeParameter = reader.GetGenericParameter(typeDef.GetGenericParameters()[1]); var constraint = reader.GetGenericParameterConstraint(typeParameter.GetConstraints()[0]); AssertAttributes(reader, constraint.GetCustomAttributes(), "MethodDefinition:Void System.Runtime.CompilerServices.NullableAttribute..ctor(Byte)"); }); var source2 = @"class Program { static void Main() { new C<object?, string?>(); new C<object?, string>(); new C<object, string?>(); new C<object, string>(); } }"; var comp2 = CreateCompilation(new[] { source, source2 }, options: WithNullableEnable(), parseOptions: TestOptions.Regular8); var expected = new[] { // (5,15): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C<T, U>'. Nullability of type argument 'object?' doesn't match 'class' constraint. // new C<object?, string?>(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "object?").WithArguments("C<T, U>", "T", "object?").WithLocation(5, 15), // (6,15): warning CS8634: The type 'object?' cannot be used as type parameter 'T' in the generic type or method 'C<T, U>'. Nullability of type argument 'object?' doesn't match 'class' constraint. // new C<object?, string>(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "object?").WithArguments("C<T, U>", "T", "object?").WithLocation(6, 15) }; comp2.VerifyEmitDiagnostics(expected); comp2 = CreateCompilation(new[] { source2 }, options: WithNullableEnable(), parseOptions: TestOptions.Regular8, references: new[] { comp.EmitToImageReference() }); comp2.VerifyEmitDiagnostics(expected); var type = comp2.GetMember<NamedTypeSymbol>("C"); Assert.Equal("T?", type.TypeParameters[1].ConstraintTypesNoUseSiteDiagnostics[0].ToTestDisplayString(true)); } [Fact] public void EmitAttribute_Constraints() { var source = @"#nullable enable public abstract class Program { #nullable disable public abstract void M0<T1, T2, T3, T4>() where T1 : class where T2 : class where T3 : class #nullable enable where T4 : class?; public abstract void M1<T1, T2, T3, T4>() where T1 : class where T2 : class where T3 : class #nullable disable where T4 : class; #nullable enable public abstract void M2<T1, T2, T3, T4>() where T1 : class? where T2 : class? where T3 : class? where T4 : class; private object _f1; private object _f2; private object _f3; }"; var comp = CreateCompilation(source); var expected = @"[NullableContext(1)] [Nullable(0)] Program [NullableContext(0)] void M0<T1, T2, T3, T4>() where T1 : class where T2 : class where T3 : class where T4 : class? T1 T2 T3 [Nullable(2)] T4 void M1<T1, T2, T3, T4>() where T1 : class! where T2 : class! where T3 : class! where T4 : class T1 T2 T3 [Nullable(0)] T4 [NullableContext(2)] void M2<T1, T2, T3, T4>() where T1 : class? where T2 : class? where T3 : class? where T4 : class! T1 T2 T3 [Nullable(1)] T4 Program() "; AssertNullableAttributes(comp, expected); } [Fact] public void EmitAttribute_ClassConstraint_SameAsContext() { var source = @"#nullable enable public class Program { public class C0<T0> #nullable disable where T0 : class #nullable enable { #nullable disable public object F01; public object F02; #nullable enable } public class C1<T1> where T1 : class { public object F11; public object F12; } public class C2<T2> where T2 : class? { public object? F21; public object? F22; } public object F31; public object F32; public object F33; }"; var comp = CreateCompilation(source); var expected = @"[NullableContext(1)] [Nullable(0)] Program System.Object! F31 System.Object! F32 System.Object! F33 Program() [NullableContext(0)] Program.C0<T0> where T0 : class T0 System.Object F01 System.Object F02 C0() [Nullable(0)] Program.C1<T1> where T1 : class! T1 System.Object! F11 System.Object! F12 C1() [NullableContext(2)] [Nullable(0)] Program.C2<T2> where T2 : class? T2 System.Object? F21 System.Object? F22 C2() "; CompileAndVerify(comp, symbolValidator: module => { AssertNullableAttributes(module, expected); verifyTypeParameterConstraint("Program.C0", null); verifyTypeParameterConstraint("Program.C1", false); verifyTypeParameterConstraint("Program.C2", true); void verifyTypeParameterConstraint(string typeName, bool? expectedConstraintIsNullable) { var typeParameter = module.GlobalNamespace.GetMember<NamedTypeSymbol>(typeName).TypeParameters.Single(); Assert.True(typeParameter.HasReferenceTypeConstraint); Assert.Equal(expectedConstraintIsNullable, typeParameter.ReferenceTypeConstraintIsNullable); } }); } [Fact] public void EmitAttribute_ClassConstraint_DifferentFromContext() { var source = @"#nullable enable public class Program { #nullable enable public class C0<T0> #nullable disable where T0 : class #nullable enable { public object F01; public object F02; } public class C1<T1> where T1 : class { public object? F11; public object? F12; } public class C2<T2> where T2 : class? { public object F21; public object F22; } public object F31; public object F32; public object F33; }"; var comp = CreateCompilation(source); var expected = @"[NullableContext(1)] [Nullable(0)] Program System.Object! F31 System.Object! F32 System.Object! F33 Program() [NullableContext(0)] Program.C0<T0> where T0 : class T0 [Nullable(1)] System.Object! F01 [Nullable(1)] System.Object! F02 C0() [NullableContext(2)] [Nullable(0)] Program.C1<T1> where T1 : class! [Nullable(1)] T1 System.Object? F11 System.Object? F12 C1() [Nullable(0)] Program.C2<T2> where T2 : class? [Nullable(2)] T2 System.Object! F21 System.Object! F22 C2() "; CompileAndVerify(comp, symbolValidator: module => { AssertNullableAttributes(module, expected); verifyTypeParameterConstraint("Program.C0", null); verifyTypeParameterConstraint("Program.C1", false); verifyTypeParameterConstraint("Program.C2", true); void verifyTypeParameterConstraint(string typeName, bool? expectedConstraintIsNullable) { var typeParameter = module.GlobalNamespace.GetMember<NamedTypeSymbol>(typeName).TypeParameters.Single(); Assert.True(typeParameter.HasReferenceTypeConstraint); Assert.Equal(expectedConstraintIsNullable, typeParameter.ReferenceTypeConstraintIsNullable); } }); } [Fact] public void EmitAttribute_NotNullConstraint() { var source = @"#nullable enable public class C0<T0> where T0 : notnull { #nullable disable public object F01; public object F02; #nullable enable } public class C1<T1> where T1 : notnull { public object F11; public object F12; } public class C2<T2> where T2 : notnull { public object? F21; public object? F22; }"; var comp = CreateCompilation(source); var expected = @"C0<T0> where T0 : notnull [Nullable(1)] T0 [NullableContext(1)] [Nullable(0)] C1<T1> where T1 : notnull T1 System.Object! F11 System.Object! F12 C1() [NullableContext(2)] [Nullable(0)] C2<T2> where T2 : notnull [Nullable(1)] T2 System.Object? F21 System.Object? F22 C2() "; CompileAndVerify(comp, symbolValidator: module => { AssertNullableAttributes(module, expected); verifyTypeParameterConstraint("C0"); verifyTypeParameterConstraint("C1"); verifyTypeParameterConstraint("C2"); void verifyTypeParameterConstraint(string typeName) { var typeParameter = module.GlobalNamespace.GetMember<NamedTypeSymbol>(typeName).TypeParameters.Single(); Assert.True(typeParameter.HasNotNullConstraint); } }); } [Fact] public void EmitAttribute_ConstraintTypes_01() { var source = @"#nullable enable public interface IA { } public interface IB<T> { } public interface I0<T> #nullable disable where T : IA, IB<int> #nullable enable { object F01(); object F02(); } public interface I1<T> where T : IA, IB<int> { object? F11(); object? F12(); } public interface I2<T> where T : IA?, IB<object?>? { object F21(); object F22(); }"; var comp = CreateCompilation(source); var expected = @"[NullableContext(2)] IB<T> T I0<T> where T : IA, IB<System.Int32> [NullableContext(1)] System.Object! F01() [NullableContext(1)] System.Object! F02() [NullableContext(1)] I1<T> where T : IA!, IB<System.Int32>! [Nullable(0)] T [NullableContext(2)] System.Object? F11() [NullableContext(2)] System.Object? F12() [NullableContext(1)] I2<T> where T : IA?, IB<System.Object?>? [Nullable(0)] T System.Object! F21() System.Object! F22() "; AssertNullableAttributes(comp, expected); } [Fact] public void EmitAttribute_ConstraintTypes_02() { var source = @"#nullable enable public interface IA { } public interface IB<T> { } public class Program { public static void M0<T>(object x, object y) #nullable disable where T : IA, IB<int> #nullable enable { } public static void M1<T>(object? x, object? y) where T : IA, IB<int> { } public static void M2<T>(object x, object y) where T : IA?, IB<object?>? { } }"; var comp = CreateCompilation(source); var expected = @"[NullableContext(2)] IB<T> T Program void M0<T>(System.Object! x, System.Object! y) where T : IA, IB<System.Int32> [Nullable(1)] System.Object! x [Nullable(1)] System.Object! y [NullableContext(1)] void M1<T>(System.Object? x, System.Object? y) where T : IA!, IB<System.Int32>! [Nullable(0)] T [Nullable(2)] System.Object? x [Nullable(2)] System.Object? y [NullableContext(1)] void M2<T>(System.Object! x, System.Object! y) where T : IA?, IB<System.Object?>? [Nullable(0)] T System.Object! x System.Object! y "; AssertNullableAttributes(comp, expected); } [Fact] public void EmitAttribute_MethodReturnType() { var source = @"public class C { public object? F() => null; }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8); var expected = @"C [NullableContext(2)] System.Object? F() "; AssertNullableAttributes(comp, expected); } [Fact] public void EmitAttribute_MethodParameters() { var source = @"public class A { public void F(object?[] c) { } } #nullable enable public class B { public void F(object x, object y) { } }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8); var expected = @"A void F(System.Object?[] c) [Nullable({ 0, 2 })] System.Object?[] c B [NullableContext(1)] void F(System.Object! x, System.Object! y) System.Object! x System.Object! y "; AssertNullableAttributes(comp, expected); } [Fact] public void EmitAttribute_ConstructorParameters() { var source = @"public class C { public C(object?[] c) { } }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8); var expected = @"C C(System.Object?[] c) [Nullable({ 0, 2 })] System.Object?[] c "; AssertNullableAttributes(comp, expected); } [Fact] public void EmitAttribute_PropertyType() { var source = @"public class C { public object? P => null; }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8); var expected = @"[NullableContext(2)] [Nullable(0)] C C() System.Object? P { get; } System.Object? P.get "; AssertNullableAttributes(comp, expected); } [Fact] public void EmitAttribute_PropertyParameters() { var source = @"public class A { public object this[object x, object? y] => throw new System.NotImplementedException(); } #nullable enable public class B { public object this[object x, object y] => throw new System.NotImplementedException(); }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8); var expected = @"A System.Object this[System.Object x, System.Object? y] { get; } [Nullable(2)] System.Object? y System.Object this[System.Object x, System.Object? y].get [Nullable(2)] System.Object? y [NullableContext(1)] [Nullable(0)] B B() System.Object! this[System.Object! x, System.Object! y] { get; } System.Object! x System.Object! y System.Object! this[System.Object! x, System.Object! y].get System.Object! x System.Object! y "; AssertNullableAttributes(comp, expected); } [Fact] public void EmitAttribute_Indexers() { var source = @"#nullable enable public class Program { public object this[object? x, object? y] => throw new System.NotImplementedException(); public object this[object? z] { set { } } }"; var comp = CreateCompilation(source); var expected = @"[NullableContext(1)] [Nullable(0)] Program Program() System.Object! this[System.Object? x, System.Object? y] { get; } System.Object? x System.Object? y [NullableContext(2)] [Nullable(1)] System.Object! this[System.Object? x, System.Object? y].get System.Object? x System.Object? y System.Object! this[System.Object? z] { set; } [Nullable(2)] System.Object? z void this[System.Object? z].set [Nullable(2)] System.Object? z System.Object! value "; AssertNullableAttributes(comp, expected); } [Fact] public void EmitAttribute_OperatorReturnType() { var source = @"public class C { public static object? operator+(C a, C b) => null; }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8); var expected = @"C [Nullable(2)] System.Object? operator +(C a, C b) "; AssertNullableAttributes(comp, expected); } [Fact] public void EmitAttribute_OperatorParameters() { var source = @"public class C { public static object operator+(C a, object?[] b) => a; }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8); var expected = @"C System.Object operator +(C a, System.Object?[] b) [Nullable({ 0, 2 })] System.Object?[] b "; AssertNullableAttributes(comp, expected); } [Fact] public void EmitAttribute_DelegateReturnType() { var source = @"public delegate object? D();"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8); var expected = @"D [NullableContext(2)] System.Object? Invoke() [Nullable(2)] System.Object? EndInvoke(System.IAsyncResult result) "; AssertNullableAttributes(comp, expected); } [Fact] public void EmitAttribute_DelegateParameters() { var source = @"public delegate void D(object?[] o);"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8); var expected = @"D void Invoke(System.Object?[] o) [Nullable({ 0, 2 })] System.Object?[] o System.IAsyncResult BeginInvoke(System.Object?[] o, System.AsyncCallback callback, System.Object @object) [Nullable({ 0, 2 })] System.Object?[] o "; AssertNullableAttributes(comp, expected); } [Fact] public void EmitAttribute_NestedEnum() { var source = @"#nullable enable public class Program { public enum E { A, B } public object F1; public object F2; public object F3; }"; var comp = CreateCompilation(source); var expected = @"[NullableContext(1)] [Nullable(0)] Program System.Object! F1 System.Object! F2 System.Object! F3 Program() [NullableContext(0)] Program.E A B E() "; AssertNullableAttributes(comp, expected); } [Fact] public void EmitAttribute_LambdaReturnType_01() { var source = @"delegate T D<T>(); class C { static void F<T>(D<T> d) { } static void G(object o) { F(() => { if (o != new object()) return o; return null; }); } }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8); AssertNoNullableAttributes(comp); } [Fact] public void EmitAttribute_LambdaReturnType_02() { var source = @"delegate T D<T>(); class C { static void F<T>(D<T> d) { } static void Main() { F(string?[] () => null); } }"; CompileAndVerify( source, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), symbolValidator: module => { var method = module.ContainingAssembly.GetTypeByMetadataName("C+<>c").GetMethod("<Main>b__1_0"); AssertAttributes(method.GetAttributes()); AssertNullableAttribute(method.GetReturnTypeAttributes()); }); } [Fact] public void EmitAttribute_LambdaParameters_01() { var source = @"delegate void D<T>(T t); class C { static void F<T>(D<T> d) { } static void G() { F((object? o) => { }); } }"; CompileAndVerify( source, parseOptions: TestOptions.Regular8, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), symbolValidator: module => { var method = module.ContainingAssembly.GetTypeByMetadataName("C+<>c").GetMethod("<G>b__1_0"); AssertAttributes(method.GetAttributes(), "System.Runtime.CompilerServices.NullableContextAttribute"); AssertAttributes(method.Parameters[0].GetAttributes()); }); } [Fact] public void EmitAttribute_LambdaParameters_02() { var source = @"delegate void D<T, U>(T t, U u); class C { static void F<T, U>(D<T, U> d) { } static void G() { F((object x, string? y) => { }); } }"; CompileAndVerify( source, parseOptions: TestOptions.Regular8, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), symbolValidator: module => { var method = module.ContainingAssembly.GetTypeByMetadataName("C+<>c").GetMethod("<G>b__1_0"); AssertAttributes(method.GetReturnTypeAttributes()); AssertAttributes(method.Parameters[0].GetAttributes()); AssertNullableAttribute(method.Parameters[1].GetAttributes()); }); } // See https://github.com/dotnet/roslyn/issues/28862. [Fact] public void EmitAttribute_QueryClauseParameters() { var source0 = @"public class A { public static object?[] F(object[] x) => x; }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular8); var ref0 = comp0.EmitToImageReference(); var source = @"using System.Linq; class B { static void M(object[] c) { var z = from x in A.F(c) let y = x where y != null select y; } }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8, references: new[] { ref0 }); AssertNoNullableAttributes(comp); } [Fact] public void EmitAttribute_LocalFunctionReturnType() { var source = @"class C { static void M() { object?[] L() => throw new System.NotImplementedException(); L(); } }"; CompileAndVerify( source, parseOptions: TestOptions.Regular8, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), symbolValidator: module => { var method = module.ContainingAssembly.GetTypeByMetadataName("C").GetMethod("<M>g__L|0_0"); AssertNullableAttribute(method.GetReturnTypeAttributes()); AssertAttributes(method.GetAttributes(), "System.Runtime.CompilerServices.CompilerGeneratedAttribute"); }); } [Fact] public void EmitAttribute_LocalFunctionParameters() { var source = @"class C { static void M() { void L(object? x, object y) { } L(null, 2); } }"; CompileAndVerify( source, parseOptions: TestOptions.Regular8, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), symbolValidator: module => { var method = module.ContainingAssembly.GetTypeByMetadataName("C").GetMethod("<M>g__L|0_0"); AssertNullableAttribute(method.Parameters[0].GetAttributes()); AssertNoNullableAttribute(method.Parameters[1].GetAttributes()); }); } [WorkItem(36736, "https://github.com/dotnet/roslyn/issues/36736")] [Fact] public void EmitAttribute_Lambda_NetModule() { var source = @"class Program { static void Main() { #nullable enable var a1 = (object x) => { }; a1(1); var a2 = string?[] () => null!; a2(); } }"; var comp = CreateCompilation(source, options: TestOptions.ReleaseModule); // https://github.com/dotnet/roslyn/issues/36736: Not reporting missing NullableContextAttribute. comp.VerifyDiagnostics( // (6,19): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // var a1 = (object x) => { }; Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "object x").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(6, 19), // (8,31): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // var a2 = string?[] () => null!; Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "=>").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(8, 31)); } [WorkItem(36736, "https://github.com/dotnet/roslyn/issues/36736")] [Fact] public void EmitAttribute_LocalFunction_NetModule() { var source = @"class Program { static void Main() { #nullable enable void L1(object? x) { } L1(null); string[]? L2() => null; L2(); } }"; var comp = CreateCompilation(source, options: TestOptions.ReleaseModule); // https://github.com/dotnet/roslyn/issues/36736: Not reporting missing NullableContextAttribute. comp.VerifyDiagnostics( // (6,17): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // void L1(object? x) { } Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "object? x").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(6, 17), // (8,9): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // string[]? L2() => null; Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "string[]?").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(8, 9)); } [Fact] public void EmitAttribute_Lambda_MissingNullableAttributeConstructor() { var sourceA = @"namespace System.Runtime.CompilerServices { public class NullableAttribute : Attribute { private NullableAttribute() { } } }"; var sourceB = @"class Program { static void Main() { #nullable enable var a1 = (object x) => { }; a1(1); var a2 = string?[] () => null!; a2(); } }"; var comp = CreateCompilation(new[] { sourceA, sourceB }); comp.VerifyDiagnostics( // (6,19): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // var a1 = (object x) => { }; Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "object x").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(6, 19), // (8,31): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // var a2 = string?[] () => null!; Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "=>").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(8, 31)); } [Fact] public void EmitAttribute_LocalFunction_MissingNullableAttributeConstructor() { var sourceA = @"namespace System.Runtime.CompilerServices { public class NullableAttribute : Attribute { private NullableAttribute() { } } }"; var sourceB = @"class Program { static void Main() { #nullable enable void L1(object? x) { } L1(null); string[]? L2() => null; L2(); } }"; var comp = CreateCompilation(new[] { sourceA, sourceB }); comp.VerifyDiagnostics( // (6,17): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // void L1(object? x) { } Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "object? x").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(6, 17), // (8,9): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // string[]? L2() => null; Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "string[]?").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(8, 9)); } [WorkItem(36736, "https://github.com/dotnet/roslyn/issues/36736")] [Fact] public void EmitAttribute_Lambda_MissingNullableContextAttributeConstructor() { var sourceA = @"namespace System.Runtime.CompilerServices { public class NullableContextAttribute : Attribute { private NullableContextAttribute() { } } }"; var sourceB = @"class Program { static void Main() { #nullable enable var a1 = (object x) => { }; a1(1); var a2 = string?[] () => null!; a2(); } }"; var comp = CreateCompilation(new[] { sourceA, sourceB }); // https://github.com/dotnet/roslyn/issues/36736: Not reporting missing NullableContextAttribute constructor. comp.VerifyEmitDiagnostics(); } [WorkItem(36736, "https://github.com/dotnet/roslyn/issues/36736")] [Fact] public void EmitAttribute_LocalFunction_MissingNullableContextAttributeConstructor() { var sourceA = @"namespace System.Runtime.CompilerServices { public class NullableContextAttribute : Attribute { private NullableContextAttribute() { } } }"; var sourceB = @"class Program { static void Main() { #nullable enable void L1(object? x) { } L1(null); string[]? L2() => null; L2(); } }"; var comp = CreateCompilation(new[] { sourceA, sourceB }); // https://github.com/dotnet/roslyn/issues/36736: Not reporting missing NullableContextAttribute constructor. comp.VerifyEmitDiagnostics(); } [Fact] public void EmitAttribute_ExplicitImplementationForwardingMethod() { var source0 = @"public class A { public object? F() => null; }"; var comp0 = CreateCompilation(source0, parseOptions: TestOptions.Regular8); var ref0 = comp0.EmitToImageReference(); var source = @"interface I { object? F(); } class B : A, I { }"; CompileAndVerify( source, references: new[] { ref0 }, parseOptions: TestOptions.Regular8, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), symbolValidator: module => { var method = module.ContainingAssembly.GetTypeByMetadataName("B").GetMethod("I.F"); AssertNullableAttribute(method.GetReturnTypeAttributes()); AssertNoNullableAttribute(method.GetAttributes()); }); } [Fact] [WorkItem(30010, "https://github.com/dotnet/roslyn/issues/30010")] public void EmitAttribute_Iterator_01() { var source = @"using System.Collections.Generic; class C { static IEnumerable<object?> F() { yield break; } }"; CompileAndVerify( source, parseOptions: TestOptions.Regular8, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), symbolValidator: module => { var property = module.ContainingAssembly.GetTypeByMetadataName("C").GetTypeMember("<F>d__0").GetProperty("System.Collections.Generic.IEnumerator<System.Object>.Current"); AssertNoNullableAttribute(property.GetAttributes()); var method = property.GetMethod; AssertNullableAttribute(method.GetReturnTypeAttributes()); AssertAttributes(method.GetAttributes(), "System.Diagnostics.DebuggerHiddenAttribute"); }); } [Fact] public void EmitAttribute_Iterator_02() { var source = @"using System.Collections.Generic; class C { static IEnumerable<object?[]> F() { yield break; } }"; CompileAndVerify( source, parseOptions: TestOptions.Regular8, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), symbolValidator: module => { var property = module.ContainingAssembly.GetTypeByMetadataName("C").GetTypeMember("<F>d__0").GetProperty("System.Collections.Generic.IEnumerator<System.Object[]>.Current"); AssertNoNullableAttribute(property.GetAttributes()); var method = property.GetMethod; AssertNullableAttribute(method.GetReturnTypeAttributes()); AssertAttributes(method.GetAttributes(), "System.Diagnostics.DebuggerHiddenAttribute"); }); } [Fact] public void EmitAttribute_UnconstrainedTypeParameter() { var source = @"#nullable enable public class Program { public T F1<T>() => default!; public T? F2<T>() => default; public T F3<T>() where T : class => default!; public T? F4<T>() where T : class => default; public T F5<T>() where T : class? => default!; public T F6<T>() where T : struct => default; public T? F7<T>() where T : struct => default; public T F8<T>() where T : notnull => default; public T? F9<T>() where T : notnull => default!; }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9); var expected = @"[NullableContext(1)] [Nullable(0)] Program T F1<T>() [Nullable(2)] T [NullableContext(2)] T? F2<T>() T T! F3<T>() where T : class! T [Nullable(2)] T? F4<T>() where T : class! T T F5<T>() where T : class? [Nullable(2)] T [NullableContext(0)] T F6<T>() where T : struct T [NullableContext(0)] T? F7<T>() where T : struct T T F8<T>() where T : notnull T [Nullable(2)] T? F9<T>() where T : notnull T Program() "; AssertNullableAttributes(comp, expected); } [Fact] public void EmitAttribute_Byte0() { var source = @"#nullable enable public class Program { #nullable disable public object #nullable enable F1(object x, object y) => null; #nullable disable public object #nullable enable F2(object? x, object? y) => null; }"; var comp = CreateCompilation(source); var expected = @"Program [NullableContext(1)] [Nullable(0)] System.Object F1(System.Object! x, System.Object! y) System.Object! x System.Object! y [NullableContext(2)] [Nullable(0)] System.Object F2(System.Object? x, System.Object? y) System.Object? x System.Object? y "; AssertNullableAttributes(comp, expected); } [Fact] public void EmitPrivateMetadata_BaseTypes() { var source = @"public class Base<T, U> { } namespace Namespace { public class Public : Base<object, string?> { } internal class Internal : Base<object, string?> { } } public class PublicTypes { public class Public : Base<object, string?> { } internal class Internal : Base<object, string?> { } protected class Protected : Base<object, string?> { } protected internal class ProtectedInternal : Base<object, string?> { } private protected class PrivateProtected : Base<object, string?> { } private class Private : Base<object, string?> { } } internal class InternalTypes { public class Public : Base<object, string?> { } internal class Internal : Base<object, string?> { } protected class Protected : Base<object, string?> { } protected internal class ProtectedInternal : Base<object, string?> { } private protected class PrivateProtected : Base<object, string?> { } private class Private : Base<object, string?> { } }"; var expectedPublicOnly = @" [NullableContext(2)] [Nullable(0)] Base<T, U> T U Base() PublicTypes [Nullable({ 0, 1, 2 })] PublicTypes.Public [Nullable({ 0, 1, 2 })] PublicTypes.Protected [Nullable({ 0, 1, 2 })] PublicTypes.ProtectedInternal [Nullable({ 0, 1, 2 })] Namespace.Public "; var expectedPublicAndInternal = @" [NullableContext(2)] [Nullable(0)] Base<T, U> T U Base() PublicTypes [Nullable({ 0, 1, 2 })] PublicTypes.Public [Nullable({ 0, 1, 2 })] PublicTypes.Internal [Nullable({ 0, 1, 2 })] PublicTypes.Protected [Nullable({ 0, 1, 2 })] PublicTypes.ProtectedInternal [Nullable({ 0, 1, 2 })] PublicTypes.PrivateProtected InternalTypes [Nullable({ 0, 1, 2 })] InternalTypes.Public [Nullable({ 0, 1, 2 })] InternalTypes.Internal [Nullable({ 0, 1, 2 })] InternalTypes.Protected [Nullable({ 0, 1, 2 })] InternalTypes.ProtectedInternal [Nullable({ 0, 1, 2 })] InternalTypes.PrivateProtected [Nullable({ 0, 1, 2 })] Namespace.Public [Nullable({ 0, 1, 2 })] Namespace.Internal "; var expectedAll = @" [NullableContext(2)] [Nullable(0)] Base<T, U> T U Base() PublicTypes [Nullable({ 0, 1, 2 })] PublicTypes.Public [Nullable({ 0, 1, 2 })] PublicTypes.Internal [Nullable({ 0, 1, 2 })] PublicTypes.Protected [Nullable({ 0, 1, 2 })] PublicTypes.ProtectedInternal [Nullable({ 0, 1, 2 })] PublicTypes.PrivateProtected [Nullable({ 0, 1, 2 })] PublicTypes.Private InternalTypes [Nullable({ 0, 1, 2 })] InternalTypes.Public [Nullable({ 0, 1, 2 })] InternalTypes.Internal [Nullable({ 0, 1, 2 })] InternalTypes.Protected [Nullable({ 0, 1, 2 })] InternalTypes.ProtectedInternal [Nullable({ 0, 1, 2 })] InternalTypes.PrivateProtected [Nullable({ 0, 1, 2 })] InternalTypes.Private [Nullable({ 0, 1, 2 })] Namespace.Public [Nullable({ 0, 1, 2 })] Namespace.Internal "; EmitPrivateMetadata(source, expectedPublicOnly, expectedPublicAndInternal, expectedAll); } [Fact] public void EmitPrivateMetadata_Delegates() { var source = @"public class Program { protected delegate object ProtectedDelegate(object? arg); internal delegate object InternalDelegate(object? arg); private delegate object PrivateDelegate(object? arg); }"; var expectedPublicOnly = @" Program Program.ProtectedDelegate [NullableContext(1)] System.Object! Invoke(System.Object? arg) [Nullable(2)] System.Object? arg System.IAsyncResult BeginInvoke(System.Object? arg, System.AsyncCallback callback, System.Object @object) [Nullable(2)] System.Object? arg [Nullable(1)] System.Object! EndInvoke(System.IAsyncResult result) "; var expectedPublicAndInternal = @" Program Program.ProtectedDelegate [NullableContext(1)] System.Object! Invoke(System.Object? arg) [Nullable(2)] System.Object? arg System.IAsyncResult BeginInvoke(System.Object? arg, System.AsyncCallback callback, System.Object @object) [Nullable(2)] System.Object? arg [Nullable(1)] System.Object! EndInvoke(System.IAsyncResult result) Program.InternalDelegate [NullableContext(1)] System.Object! Invoke(System.Object? arg) [Nullable(2)] System.Object? arg System.IAsyncResult BeginInvoke(System.Object? arg, System.AsyncCallback callback, System.Object @object) [Nullable(2)] System.Object? arg [Nullable(1)] System.Object! EndInvoke(System.IAsyncResult result) "; var expectedAll = @" Program Program.ProtectedDelegate [NullableContext(1)] System.Object! Invoke(System.Object? arg) [Nullable(2)] System.Object? arg System.IAsyncResult BeginInvoke(System.Object? arg, System.AsyncCallback callback, System.Object @object) [Nullable(2)] System.Object? arg [Nullable(1)] System.Object! EndInvoke(System.IAsyncResult result) Program.InternalDelegate [NullableContext(1)] System.Object! Invoke(System.Object? arg) [Nullable(2)] System.Object? arg System.IAsyncResult BeginInvoke(System.Object? arg, System.AsyncCallback callback, System.Object @object) [Nullable(2)] System.Object? arg [Nullable(1)] System.Object! EndInvoke(System.IAsyncResult result) Program.PrivateDelegate [NullableContext(1)] System.Object! Invoke(System.Object? arg) [Nullable(2)] System.Object? arg System.IAsyncResult BeginInvoke(System.Object? arg, System.AsyncCallback callback, System.Object @object) [Nullable(2)] System.Object? arg [Nullable(1)] System.Object! EndInvoke(System.IAsyncResult result) "; EmitPrivateMetadata(source, expectedPublicOnly, expectedPublicAndInternal, expectedAll); } [Fact] public void EmitPrivateMetadata_Events() { var source = @"#nullable disable public delegate void D<T>(T t); #nullable enable public class Program { public event D<object?>? PublicEvent { add { } remove { } } internal event D<object> InternalEvent { add { } remove { } } protected event D<object?> ProtectedEvent { add { } remove { } } protected internal event D<object?> ProtectedInternalEvent { add { } remove { } } private protected event D<object>? PrivateProtectedEvent { add { } remove { } } private event D<object?>? PrivateEvent { add { } remove { } } }"; var expectedPublicOnly = @" [NullableContext(2)] [Nullable(0)] Program Program() event D<System.Object?>? PublicEvent void PublicEvent.add D<System.Object?>? value void PublicEvent.remove D<System.Object?>? value [Nullable(1)] event D<System.Object!>! InternalEvent [Nullable({ 1, 2 })] event D<System.Object?>! ProtectedEvent void ProtectedEvent.add [Nullable({ 1, 2 })] D<System.Object?>! value void ProtectedEvent.remove [Nullable({ 1, 2 })] D<System.Object?>! value [Nullable({ 1, 2 })] event D<System.Object?>! ProtectedInternalEvent void ProtectedInternalEvent.add [Nullable({ 1, 2 })] D<System.Object?>! value void ProtectedInternalEvent.remove [Nullable({ 1, 2 })] D<System.Object?>! value [Nullable({ 2, 1 })] event D<System.Object!>? PrivateProtectedEvent "; var expectedPublicAndInternal = @" [NullableContext(2)] [Nullable(0)] Program Program() event D<System.Object?>? PublicEvent void PublicEvent.add D<System.Object?>? value void PublicEvent.remove D<System.Object?>? value [Nullable(1)] event D<System.Object!>! InternalEvent [NullableContext(1)] void InternalEvent.add D<System.Object!>! value [NullableContext(1)] void InternalEvent.remove D<System.Object!>! value [Nullable({ 1, 2 })] event D<System.Object?>! ProtectedEvent void ProtectedEvent.add [Nullable({ 1, 2 })] D<System.Object?>! value void ProtectedEvent.remove [Nullable({ 1, 2 })] D<System.Object?>! value [Nullable({ 1, 2 })] event D<System.Object?>! ProtectedInternalEvent void ProtectedInternalEvent.add [Nullable({ 1, 2 })] D<System.Object?>! value void ProtectedInternalEvent.remove [Nullable({ 1, 2 })] D<System.Object?>! value [Nullable({ 2, 1 })] event D<System.Object!>? PrivateProtectedEvent void PrivateProtectedEvent.add [Nullable({ 2, 1 })] D<System.Object!>? value void PrivateProtectedEvent.remove [Nullable({ 2, 1 })] D<System.Object!>? value "; var expectedAll = @" [NullableContext(2)] [Nullable(0)] Program Program() event D<System.Object?>? PublicEvent void PublicEvent.add D<System.Object?>? value void PublicEvent.remove D<System.Object?>? value [Nullable(1)] event D<System.Object!>! InternalEvent [NullableContext(1)] void InternalEvent.add D<System.Object!>! value [NullableContext(1)] void InternalEvent.remove D<System.Object!>! value [Nullable({ 1, 2 })] event D<System.Object?>! ProtectedEvent void ProtectedEvent.add [Nullable({ 1, 2 })] D<System.Object?>! value void ProtectedEvent.remove [Nullable({ 1, 2 })] D<System.Object?>! value [Nullable({ 1, 2 })] event D<System.Object?>! ProtectedInternalEvent void ProtectedInternalEvent.add [Nullable({ 1, 2 })] D<System.Object?>! value void ProtectedInternalEvent.remove [Nullable({ 1, 2 })] D<System.Object?>! value [Nullable({ 2, 1 })] event D<System.Object!>? PrivateProtectedEvent void PrivateProtectedEvent.add [Nullable({ 2, 1 })] D<System.Object!>? value void PrivateProtectedEvent.remove [Nullable({ 2, 1 })] D<System.Object!>? value event D<System.Object?>? PrivateEvent void PrivateEvent.add D<System.Object?>? value void PrivateEvent.remove D<System.Object?>? value "; EmitPrivateMetadata(source, expectedPublicOnly, expectedPublicAndInternal, expectedAll); } [Fact] public void EmitPrivateMetadata_Fields() { var source = @"public class Program { public object PublicField; internal object? InternalField; protected object ProtectedField; protected internal object? ProtectedInternalField; private protected object? PrivateProtectedField; private object? PrivateField; }"; var expectedPublicOnly = @" [NullableContext(1)] [Nullable(0)] Program System.Object! PublicField System.Object! ProtectedField [Nullable(2)] System.Object? ProtectedInternalField Program() "; var expectedPublicAndInternal = @" [NullableContext(2)] [Nullable(0)] Program [Nullable(1)] System.Object! PublicField System.Object? InternalField [Nullable(1)] System.Object! ProtectedField System.Object? ProtectedInternalField System.Object? PrivateProtectedField Program() "; var expectedAll = @" [NullableContext(2)] [Nullable(0)] Program [Nullable(1)] System.Object! PublicField System.Object? InternalField [Nullable(1)] System.Object! ProtectedField System.Object? ProtectedInternalField System.Object? PrivateProtectedField System.Object? PrivateField Program() "; EmitPrivateMetadata(source, expectedPublicOnly, expectedPublicAndInternal, expectedAll); } [Fact] public void EmitPrivateMetadata_Methods() { var source = @"public class Program { public void PublicMethod(object arg) { } internal object? InternalMethod(object? arg) => null; protected object ProtectedMethod(object? arg) => null; protected internal object? ProtectedInternalMethod(object? arg) => null; private protected void PrivateProtectedMethod(object? arg) { } private object? PrivateMethod(object? arg) => null; }"; var expectedPublicOnly = @" [NullableContext(1)] [Nullable(0)] Program void PublicMethod(System.Object! arg) System.Object! arg System.Object! ProtectedMethod(System.Object? arg) [Nullable(2)] System.Object? arg [NullableContext(2)] System.Object? ProtectedInternalMethod(System.Object? arg) System.Object? arg Program() "; var expectedPublicAndInternal = @" [NullableContext(2)] [Nullable(0)] Program [NullableContext(1)] void PublicMethod(System.Object! arg) System.Object! arg System.Object? InternalMethod(System.Object? arg) System.Object? arg [NullableContext(1)] System.Object! ProtectedMethod(System.Object? arg) [Nullable(2)] System.Object? arg System.Object? ProtectedInternalMethod(System.Object? arg) System.Object? arg void PrivateProtectedMethod(System.Object? arg) System.Object? arg Program() "; var expectedAll = @" [NullableContext(2)] [Nullable(0)] Program [NullableContext(1)] void PublicMethod(System.Object! arg) System.Object! arg System.Object? InternalMethod(System.Object? arg) System.Object? arg [NullableContext(1)] System.Object! ProtectedMethod(System.Object? arg) [Nullable(2)] System.Object? arg System.Object? ProtectedInternalMethod(System.Object? arg) System.Object? arg void PrivateProtectedMethod(System.Object? arg) System.Object? arg System.Object? PrivateMethod(System.Object? arg) System.Object? arg Program() "; EmitPrivateMetadata(source, expectedPublicOnly, expectedPublicAndInternal, expectedAll); } [Fact] public void EmitPrivateMetadata_Properties() { var source = @"public class Program { public object PublicProperty => null; internal object? InternalProperty => null; protected object ProtectedProperty => null; protected internal object? ProtectedInternalProperty => null; private protected object? PrivateProtectedProperty => null; private object? PrivateProperty => null; }"; var expectedPublicOnly = @" [NullableContext(2)] [Nullable(0)] Program Program() [Nullable(1)] System.Object! PublicProperty { get; } [NullableContext(1)] System.Object! PublicProperty.get [Nullable(1)] System.Object! ProtectedProperty { get; } [NullableContext(1)] System.Object! ProtectedProperty.get System.Object? ProtectedInternalProperty { get; } System.Object? ProtectedInternalProperty.get "; var expectedPublicAndInternal = @" [NullableContext(2)] [Nullable(0)] Program Program() [Nullable(1)] System.Object! PublicProperty { get; } [NullableContext(1)] System.Object! PublicProperty.get System.Object? InternalProperty { get; } System.Object? InternalProperty.get [Nullable(1)] System.Object! ProtectedProperty { get; } [NullableContext(1)] System.Object! ProtectedProperty.get System.Object? ProtectedInternalProperty { get; } System.Object? ProtectedInternalProperty.get System.Object? PrivateProtectedProperty { get; } System.Object? PrivateProtectedProperty.get "; var expectedAll = @" [NullableContext(2)] [Nullable(0)] Program Program() [Nullable(1)] System.Object! PublicProperty { get; } [NullableContext(1)] System.Object! PublicProperty.get System.Object? InternalProperty { get; } System.Object? InternalProperty.get [Nullable(1)] System.Object! ProtectedProperty { get; } [NullableContext(1)] System.Object! ProtectedProperty.get System.Object? ProtectedInternalProperty { get; } System.Object? ProtectedInternalProperty.get System.Object? PrivateProtectedProperty { get; } System.Object? PrivateProtectedProperty.get System.Object? PrivateProperty { get; } System.Object? PrivateProperty.get "; EmitPrivateMetadata(source, expectedPublicOnly, expectedPublicAndInternal, expectedAll); } [Fact] public void EmitPrivateMetadata_Indexers() { var source = @"public class Program { public class PublicType { public object? this[object? x, object y] => null; } internal class InternalType { public object this[object x, object y] { get => null; set { } } } protected class ProtectedType { public object? this[object x, object? y] { get => null; set { } } } protected internal class ProtectedInternalType { public object this[object x, object y] { set { } } } private protected class PrivateProtectedType { public object this[object x, object y] => null; } private class PrivateType { public object this[object x, object y] => null; } }"; var expectedPublicOnly = @" [NullableContext(2)] [Nullable(0)] Program Program() [Nullable(0)] Program.PublicType PublicType() System.Object? this[System.Object? x, System.Object! y] { get; } System.Object? x [Nullable(1)] System.Object! y System.Object? this[System.Object? x, System.Object! y].get System.Object? x [Nullable(1)] System.Object! y [Nullable(0)] Program.ProtectedType ProtectedType() System.Object? this[System.Object! x, System.Object? y] { get; set; } [Nullable(1)] System.Object! x System.Object? y System.Object? this[System.Object! x, System.Object? y].get [Nullable(1)] System.Object! x System.Object? y void this[System.Object! x, System.Object? y].set [Nullable(1)] System.Object! x System.Object? y System.Object? value [NullableContext(1)] [Nullable(0)] Program.ProtectedInternalType ProtectedInternalType() System.Object! this[System.Object! x, System.Object! y] { set; } System.Object! x System.Object! y void this[System.Object! x, System.Object! y].set System.Object! x System.Object! y System.Object! value "; var expectedPublicAndInternal = @" [NullableContext(1)] [Nullable(0)] Program Program() [NullableContext(2)] [Nullable(0)] Program.PublicType PublicType() System.Object? this[System.Object? x, System.Object! y] { get; } System.Object? x [Nullable(1)] System.Object! y System.Object? this[System.Object? x, System.Object! y].get System.Object? x [Nullable(1)] System.Object! y [Nullable(0)] Program.InternalType InternalType() System.Object! this[System.Object! x, System.Object! y] { get; set; } System.Object! x System.Object! y System.Object! this[System.Object! x, System.Object! y].get System.Object! x System.Object! y void this[System.Object! x, System.Object! y].set System.Object! x System.Object! y System.Object! value [NullableContext(2)] [Nullable(0)] Program.ProtectedType ProtectedType() System.Object? this[System.Object! x, System.Object? y] { get; set; } [Nullable(1)] System.Object! x System.Object? y System.Object? this[System.Object! x, System.Object? y].get [Nullable(1)] System.Object! x System.Object? y void this[System.Object! x, System.Object? y].set [Nullable(1)] System.Object! x System.Object? y System.Object? value [Nullable(0)] Program.ProtectedInternalType ProtectedInternalType() System.Object! this[System.Object! x, System.Object! y] { set; } System.Object! x System.Object! y void this[System.Object! x, System.Object! y].set System.Object! x System.Object! y System.Object! value [Nullable(0)] Program.PrivateProtectedType PrivateProtectedType() System.Object! this[System.Object! x, System.Object! y] { get; } System.Object! x System.Object! y System.Object! this[System.Object! x, System.Object! y].get System.Object! x System.Object! y "; var expectedAll = @" [NullableContext(1)] [Nullable(0)] Program Program() [NullableContext(2)] [Nullable(0)] Program.PublicType PublicType() System.Object? this[System.Object? x, System.Object! y] { get; } System.Object? x [Nullable(1)] System.Object! y System.Object? this[System.Object? x, System.Object! y].get System.Object? x [Nullable(1)] System.Object! y [Nullable(0)] Program.InternalType InternalType() System.Object! this[System.Object! x, System.Object! y] { get; set; } System.Object! x System.Object! y System.Object! this[System.Object! x, System.Object! y].get System.Object! x System.Object! y void this[System.Object! x, System.Object! y].set System.Object! x System.Object! y System.Object! value [NullableContext(2)] [Nullable(0)] Program.ProtectedType ProtectedType() System.Object? this[System.Object! x, System.Object? y] { get; set; } [Nullable(1)] System.Object! x System.Object? y System.Object? this[System.Object! x, System.Object? y].get [Nullable(1)] System.Object! x System.Object? y void this[System.Object! x, System.Object? y].set [Nullable(1)] System.Object! x System.Object? y System.Object? value [Nullable(0)] Program.ProtectedInternalType ProtectedInternalType() System.Object! this[System.Object! x, System.Object! y] { set; } System.Object! x System.Object! y void this[System.Object! x, System.Object! y].set System.Object! x System.Object! y System.Object! value [Nullable(0)] Program.PrivateProtectedType PrivateProtectedType() System.Object! this[System.Object! x, System.Object! y] { get; } System.Object! x System.Object! y System.Object! this[System.Object! x, System.Object! y].get System.Object! x System.Object! y [Nullable(0)] Program.PrivateType PrivateType() System.Object! this[System.Object! x, System.Object! y] { get; } System.Object! x System.Object! y System.Object! this[System.Object! x, System.Object! y].get System.Object! x System.Object! y "; EmitPrivateMetadata(source, expectedPublicOnly, expectedPublicAndInternal, expectedAll); } [Fact] public void EmitPrivateMetadata_TypeParameters() { var source = @"public class Base { } public class Program { protected static void ProtectedMethod<T, U>() where T : notnull where U : class { } internal static void InternalMethod<T, U>() where T : notnull where U : class { } private static void PrivateMethod<T, U>() where T : notnull where U : class { } }"; var expectedPublicOnly = @" Program [NullableContext(1)] void ProtectedMethod<T, U>() where T : notnull where U : class! T U "; var expectedPublicAndInternal = @" [NullableContext(1)] [Nullable(0)] Program void ProtectedMethod<T, U>() where T : notnull where U : class! T U void InternalMethod<T, U>() where T : notnull where U : class! T U Program() "; var expectedAll = @" [NullableContext(1)] [Nullable(0)] Program void ProtectedMethod<T, U>() where T : notnull where U : class! T U void InternalMethod<T, U>() where T : notnull where U : class! T U void PrivateMethod<T, U>() where T : notnull where U : class! T U Program() "; EmitPrivateMetadata(source, expectedPublicOnly, expectedPublicAndInternal, expectedAll); } [Fact] [WorkItem(37161, "https://github.com/dotnet/roslyn/issues/37161")] public void EmitPrivateMetadata_ExplicitImplementation() { var source = @"public interface I<T> { T M(T[] args); T P { get; set; } T[] this[T index] { get; } } public class C : I<object?> { object? I<object?>.M(object?[] args) => throw null!; object? I<object?>.P { get; set; } object?[] I<object?>.this[object? index] => throw null!; }"; // Attributes emitted for explicitly-implemented property and indexer, but not for accessors. var expectedPublicOnly = @" [NullableContext(1)] I<T> [Nullable(2)] T T M(T[]! args) T[]! args T P { get; set; } T P.get void P.set T value T[]! this[T index] { get; } T index T[]! this[T index].get T index C [Nullable(2)] System.Object? I<System.Object>.P { get; set; } [Nullable({ 1, 2 })] System.Object?[]! I<System.Object>.Item[System.Object index] { get; } "; // Attributes emitted for explicitly-implemented property and indexer, but not for accessors. var expectedPublicAndInternal = @" [NullableContext(1)] I<T> [Nullable(2)] T T M(T[]! args) T[]! args T P { get; set; } T P.get void P.set T value T[]! this[T index] { get; } T index T[]! this[T index].get T index C [Nullable(2)] System.Object? I<System.Object>.P { get; set; } [Nullable({ 1, 2 })] System.Object?[]! I<System.Object>.Item[System.Object index] { get; } "; var expectedAll = @" [NullableContext(1)] I<T> [Nullable(2)] T T M(T[]! args) T[]! args T P { get; set; } T P.get void P.set T value T[]! this[T index] { get; } T index T[]! this[T index].get T index [NullableContext(2)] [Nullable(0)] C System.Object? <I<System.Object>.P>k__BackingField System.Object? I<System.Object>.M(System.Object?[]! args) [Nullable({ 1, 2 })] System.Object?[]! args [Nullable({ 1, 2 })] System.Object?[]! I<System.Object>.get_Item(System.Object? index) System.Object? index C() System.Object? I<System.Object>.P { get; set; } System.Object? I<System.Object>.P.get void I<System.Object>.P.set System.Object? value [Nullable({ 1, 2 })] System.Object?[]! I<System.Object>.Item[System.Object? index] { get; } System.Object? index [Nullable({ 1, 2 })] System.Object?[]! I<System.Object>.get_Item(System.Object? index) System.Object? index "; EmitPrivateMetadata(source, expectedPublicOnly, expectedPublicAndInternal, expectedAll); } [Fact] public void EmitPrivateMetadata_SynthesizedFields() { var source = @"public struct S<T> { } public class Public { public static void PublicMethod() { S<object?> s; System.Action a = () => { s.ToString(); }; } }"; var expectedPublicOnly = @" S<T> [Nullable(2)] T "; var expectedPublicAndInternal = @" S<T> [Nullable(2)] T "; var expectedAll = @" S<T> [Nullable(2)] T Public Public.<>c__DisplayClass0_0 [Nullable({ 0, 2 })] S<System.Object?> s "; EmitPrivateMetadata(source, expectedPublicOnly, expectedPublicAndInternal, expectedAll); } [Fact] public void EmitPrivateMetadata_SynthesizedParameters() { var source = @"public class Public { private static void PrivateMethod(string x) { _ = new System.Action<string?>((string y) => { }); } }"; var expectedPublicOnly = @""; var expectedPublicAndInternal = @""; var expectedAll = @" Public [NullableContext(1)] void PrivateMethod(System.String! x) System.String! x Public.<>c [Nullable({ 0, 2 })] System.Action<System.String?> <>9__0_0 [NullableContext(1)] void <PrivateMethod>b__0_0(System.String! y) System.String! y "; EmitPrivateMetadata(source, expectedPublicOnly, expectedPublicAndInternal, expectedAll); } [Fact] public void EmitPrivateMetadata_AnonymousType() { var source = @"public class Program { public static void Main() { _ = new { A = new object(), B = (string?)null }; } }"; var expectedPublicOnly = @""; var expectedPublicAndInternal = @""; var expectedAll = @""; EmitPrivateMetadata(source, expectedPublicOnly, expectedPublicAndInternal, expectedAll); } [Fact] public void EmitPrivateMetadata_Iterator() { var source = @"using System.Collections.Generic; public class Program { public static IEnumerable<object?> F() { yield break; } }"; var expectedPublicOnly = @" Program [Nullable({ 1, 2 })] System.Collections.Generic.IEnumerable<System.Object?>! F() "; var expectedPublicAndInternal = @" Program [Nullable({ 1, 2 })] System.Collections.Generic.IEnumerable<System.Object?>! F() "; var expectedAll = @" Program [Nullable({ 1, 2 })] System.Collections.Generic.IEnumerable<System.Object?>! F() Program.<F>d__0 [Nullable(2)] System.Object? <>2__current System.Object System.Collections.Generic.IEnumerator<System.Object>.Current { get; } [Nullable(2)] System.Object? System.Collections.Generic.IEnumerator<System.Object>.Current.get "; EmitPrivateMetadata(source, expectedPublicOnly, expectedPublicAndInternal, expectedAll); } private void EmitPrivateMetadata(string source, string expectedPublicOnly, string expectedPublicAndInternal, string expectedAll) { var sourceIVTs = @"using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo(""Other"")]"; var options = WithNullableEnable().WithMetadataImportOptions(MetadataImportOptions.All); var parseOptions = TestOptions.Regular8; AssertNullableAttributes(CreateCompilation(source, options: options, parseOptions: parseOptions), expectedAll); AssertNullableAttributes(CreateCompilation(source, options: options, parseOptions: parseOptions.WithFeature(Feature.NullablePublicOnly)), expectedPublicOnly); AssertNullableAttributes(CreateCompilation(new[] { source, sourceIVTs }, options: options, parseOptions: parseOptions), expectedAll); AssertNullableAttributes(CreateCompilation(new[] { source, sourceIVTs }, options: options, parseOptions: parseOptions.WithFeature(Feature.NullablePublicOnly)), expectedPublicAndInternal); } /// <summary> /// Should only require NullableAttribute constructor if nullable annotations are emitted. /// </summary> [Fact] public void EmitPrivateMetadata_MissingAttributeConstructor() { var sourceAttribute = @"namespace System.Runtime.CompilerServices { public sealed class NullableAttribute : Attribute { } }"; var source = @"#pragma warning disable 0067 #pragma warning disable 0169 #pragma warning disable 8321 public class A { private object? F; private static object? M(object arg) => null; private object? P => null; private object? this[object x, object? y] => null; private event D<object?> E; public static void M() { object? f(object arg) => arg; object? l(object arg) { return arg; } D<object> d = () => new object(); } } internal delegate T D<T>(); internal interface I<T> { } internal class B : I<object> { public static object operator!(B b) => b; public event D<object?> E; private (object, object?) F; }"; var options = WithNullableEnable(); var parseOptions = TestOptions.Regular8; var comp = CreateCompilation(new[] { sourceAttribute, source }, options: options, parseOptions: parseOptions); comp.VerifyEmitDiagnostics( // (6,21): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // private object? F; Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "F").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(6, 21), // (7,20): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // private static object? M(object arg) => null; Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "object?").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(7, 20), // (7,30): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // private static object? M(object arg) => null; Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "object arg").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(7, 30), // (8,13): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // private object? P => null; Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "object?").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(8, 13), // (9,13): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // private object? this[object x, object? y] => null; Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "object?").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(9, 13), // (9,26): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // private object? this[object x, object? y] => null; Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "object x").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(9, 26), // (9,36): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // private object? this[object x, object? y] => null; Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "object? y").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(9, 36), // (10,30): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // private event D<object?> E; Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "E").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(10, 30), // (10,30): warning CS8618: Non-nullable event 'E' is uninitialized. Consider declaring the event as nullable. // private event D<object?> E; Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "E").WithArguments("event", "E").WithLocation(10, 30), // (13,9): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // object? f(object arg) => arg; Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "object?").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(13, 9), // (13,19): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // object? f(object arg) => arg; Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "object arg").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(13, 19), // (14,9): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // object? l(object arg) { return arg; } Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "object?").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(14, 9), // (14,19): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // object? l(object arg) { return arg; } Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "object arg").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(14, 19), // (15,26): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // D<object> d = () => new object(); Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "=>").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(15, 26), // (18,19): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // internal delegate T D<T>(); Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "T").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(18, 19), // (18,23): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // internal delegate T D<T>(); Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "T").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(18, 23), // (19,22): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // internal interface I<T> { } Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "T").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(19, 22), // (20,16): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // internal class B : I<object> Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "B").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(20, 16), // (22,19): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // public static object operator!(B b) => b; Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "object").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(22, 19), // (22,36): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // public static object operator!(B b) => b; Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "B b").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(22, 36), // (23,29): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // public event D<object?> E; Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "E").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(23, 29), // (23,29): warning CS8618: Non-nullable event 'E' is uninitialized. Consider declaring the event as nullable. // public event D<object?> E; Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "E").WithArguments("event", "E").WithLocation(23, 29), // (24,31): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // private (object, object?) F; Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "F").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(24, 31)); comp = CreateCompilation(new[] { sourceAttribute, source }, options: options, parseOptions: parseOptions.WithFeature(Feature.NullablePublicOnly)); comp.VerifyEmitDiagnostics( // (8,13): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // private object? P => null; Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "object?").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(8, 13), // (9,13): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // private object? this[object x, object? y] => null; Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "object?").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(9, 13), // (9,26): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // private object? this[object x, object? y] => null; Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "object x").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(9, 26), // (9,36): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // private object? this[object x, object? y] => null; Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "object? y").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(9, 36), // (10,30): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // private event D<object?> E; Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "E").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(10, 30), // (10,30): warning CS8618: Non-nullable event 'E' is uninitialized. Consider declaring the event as nullable. // private event D<object?> E; Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "E").WithArguments("event", "E").WithLocation(10, 30), // (23,29): warning CS8618: Non-nullable event 'E' is uninitialized. Consider declaring the event as nullable. // public event D<object?> E; Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "E").WithArguments("event", "E").WithLocation(23, 29) ); } [Fact] public void EmitPrivateMetadata_MissingAttributeConstructor_NullableDisabled() { var sourceAttribute = @"namespace System.Runtime.CompilerServices { public sealed class NullableAttribute : Attribute { } }"; var source = @"#pragma warning disable 414 public class Program { private object? F = null; private object? P => null; }"; var options = TestOptions.ReleaseDll; var parseOptions = TestOptions.Regular8; var comp = CreateCompilation(new[] { sourceAttribute, source }, options: options, parseOptions: parseOptions); comp.VerifyEmitDiagnostics( // (4,19): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. // private object? F = null; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(4, 19), // (4,21): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // private object? F = null; Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "F").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(4, 21), // (5,13): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // private object? P => null; Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "object?").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(5, 13), // (5,19): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. // private object? P => null; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 19)); comp = CreateCompilation(new[] { sourceAttribute, source }, options: options, parseOptions: parseOptions.WithFeature(Feature.NullablePublicOnly)); comp.VerifyEmitDiagnostics( // (4,19): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. // private object? F = null; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(4, 19), // (5,13): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.NullableAttribute..ctor' // private object? P => null; Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "object?").WithArguments("System.Runtime.CompilerServices.NullableAttribute", ".ctor").WithLocation(5, 13), // (5,19): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. // private object? P => null; Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 19)); } [Fact] public void EmitAttribute_ValueTypes_01() { var source = @"#nullable enable struct S1<T> { } struct S2<T, U> { } class C1<T> { } class C2<T, U> { } class Program { static void F() { } int F11; int? F12; #nullable disable object F21; #nullable enable object F22; S1<int> F31; S1<int?>? F32; S1< #nullable disable object #nullable enable > F33; S1<object?> F34; S2<int, int> F41; S2<int, #nullable disable object #nullable enable > F42; S2< #nullable disable object, #nullable enable int> F43; S2< #nullable disable object, object #nullable enable > F44; S2<int, object> F45; S2<object?, int> F46; S2< #nullable disable object, #nullable enable object> F47; S2<object?, #nullable disable object #nullable enable > F48; S2<object, object?> F49; C1<int #nullable disable > F51; #nullable enable C1<int? #nullable disable > F52; #nullable enable C1<int> F53; C1<int?> F54; C1< #nullable disable object> F55; #nullable enable C1<object #nullable disable > F56; #nullable enable C1< #nullable disable object #nullable enable >? F57; C1<object>? F58; C2<int, #nullable disable object> F60; #nullable enable C2<int, object #nullable disable > F61; #nullable enable C2<object?, int #nullable disable > F62; #nullable enable C2<int, object> F63; C2<object?, int>? F64; }"; var comp = CreateCompilation(source, options: TestOptions.ReleaseDll.WithMetadataImportOptions(MetadataImportOptions.All)); CompileAndVerify(comp, sourceSymbolValidator: validate, symbolValidator: validate); static void validate(ModuleSymbol module) { var globalNamespace = module.GlobalNamespace; VerifyBytes(globalNamespace.GetMember<MethodSymbol>("Program.F").ReturnTypeWithAnnotations, new byte[] { 0 }, new byte[] { }, "void"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F11").TypeWithAnnotations, new byte[] { 0 }, new byte[] { }, "int"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F12").TypeWithAnnotations, new byte[] { 0, 0 }, new byte[] { }, "int?"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F21").TypeWithAnnotations, new byte[] { 0 }, new byte[] { 0 }, "object"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F22").TypeWithAnnotations, new byte[] { 1 }, new byte[] { 1 }, "object!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F31").TypeWithAnnotations, new byte[] { 0, 0 }, new byte[] { 0 }, "S1<int>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F32").TypeWithAnnotations, new byte[] { 0, 0, 0, 0 }, new byte[] { 0 }, "S1<int?>?"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F33").TypeWithAnnotations, new byte[] { 0, 0 }, new byte[] { 0, 0 }, "S1<object>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F34").TypeWithAnnotations, new byte[] { 0, 2 }, new byte[] { 0, 2 }, "S1<object?>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F41").TypeWithAnnotations, new byte[] { 0, 0, 0 }, new byte[] { 0 }, "S2<int, int>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F42").TypeWithAnnotations, new byte[] { 0, 0, 0 }, new byte[] { 0, 0 }, "S2<int, object>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F43").TypeWithAnnotations, new byte[] { 0, 0, 0 }, new byte[] { 0, 0 }, "S2<object, int>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F44").TypeWithAnnotations, new byte[] { 0, 0, 0 }, new byte[] { 0, 0, 0 }, "S2<object, object>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F45").TypeWithAnnotations, new byte[] { 0, 0, 1 }, new byte[] { 0, 1 }, "S2<int, object!>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F46").TypeWithAnnotations, new byte[] { 0, 2, 0 }, new byte[] { 0, 2 }, "S2<object?, int>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F47").TypeWithAnnotations, new byte[] { 0, 0, 1 }, new byte[] { 0, 0, 1 }, "S2<object, object!>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F48").TypeWithAnnotations, new byte[] { 0, 2, 0 }, new byte[] { 0, 2, 0 }, "S2<object?, object>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F49").TypeWithAnnotations, new byte[] { 0, 1, 2 }, new byte[] { 0, 1, 2 }, "S2<object!, object?>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F51").TypeWithAnnotations, new byte[] { 0, 0 }, new byte[] { 0 }, "C1<int>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F52").TypeWithAnnotations, new byte[] { 0, 0, 0 }, new byte[] { 0 }, "C1<int?>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F53").TypeWithAnnotations, new byte[] { 1, 0 }, new byte[] { 1 }, "C1<int>!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F54").TypeWithAnnotations, new byte[] { 1, 0, 0 }, new byte[] { 1 }, "C1<int?>!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F55").TypeWithAnnotations, new byte[] { 0, 0 }, new byte[] { 0, 0 }, "C1<object>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F56").TypeWithAnnotations, new byte[] { 0, 1 }, new byte[] { 0, 1 }, "C1<object!>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F57").TypeWithAnnotations, new byte[] { 2, 0 }, new byte[] { 2, 0 }, "C1<object>?"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F58").TypeWithAnnotations, new byte[] { 2, 1 }, new byte[] { 2, 1 }, "C1<object!>?"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F60").TypeWithAnnotations, new byte[] { 0, 0, 0 }, new byte[] { 0, 0 }, "C2<int, object>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F61").TypeWithAnnotations, new byte[] { 0, 0, 1 }, new byte[] { 0, 1 }, "C2<int, object!>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F62").TypeWithAnnotations, new byte[] { 0, 2, 0 }, new byte[] { 0, 2 }, "C2<object?, int>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F63").TypeWithAnnotations, new byte[] { 1, 0, 1 }, new byte[] { 1, 1 }, "C2<int, object!>!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F64").TypeWithAnnotations, new byte[] { 2, 2, 0 }, new byte[] { 2, 2 }, "C2<object?, int>?"); } } [Fact] public void EmitAttribute_ValueTypes_02() { var source = @"#nullable enable struct S<T> { } class Program { int #nullable disable [] F1; #nullable enable int[] F2; int?[]? F3; int #nullable disable [] #nullable enable [] F4; int?[] #nullable disable [] F5; #nullable enable S<int #nullable disable [] #nullable enable > F6; S<int?[]?>? F7; }"; var comp = CreateCompilation(source, options: TestOptions.ReleaseDll.WithMetadataImportOptions(MetadataImportOptions.All)); CompileAndVerify(comp, sourceSymbolValidator: validate, symbolValidator: validate); static void validate(ModuleSymbol module) { var globalNamespace = module.GlobalNamespace; VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F1").TypeWithAnnotations, new byte[] { 0, 0 }, new byte[] { 0 }, "int[]"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F2").TypeWithAnnotations, new byte[] { 1, 0 }, new byte[] { 1 }, "int[]!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F3").TypeWithAnnotations, new byte[] { 2, 0, 0 }, new byte[] { 2 }, "int?[]?"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F4").TypeWithAnnotations, new byte[] { 0, 1, 0 }, new byte[] { 0, 1 }, "int[]![]"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F5").TypeWithAnnotations, new byte[] { 1, 0, 0, 0 }, new byte[] { 1, 0 }, "int?[][]!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F6").TypeWithAnnotations, new byte[] { 0, 0, 0 }, new byte[] { 0, 0 }, "S<int[]>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F7").TypeWithAnnotations, new byte[] { 0, 0, 2, 0, 0 }, new byte[] { 0, 2 }, "S<int?[]?>?"); } } [Fact] public void EmitAttribute_ValueTypes_03() { var source = @"#nullable enable class Program { System.ValueTuple F0; (int, int) F1; (int?, int?)? F2; #nullable disable (int, object) F3; (object, int) F4; #nullable enable (int, object?) F5; (object, int) F6; ((int, int), ((int, int), int)) F7; ((int, int), ((int, object), int)) F8; #nullable disable (int _1, int _2, int _3, int _4, int _5, int _6, int _7, object _8) F9; #nullable enable (int _1, int _2, int _3, int _4, int _5, int _6, int _7, int _8, int _9) F10; (int _1, int _2, int _3, int _4, int _5, int _6, int _7, int _8, object _9) F11; (int _1, int _2, int _3, int _4, int _5, int _6, int _7, object _8, int _9) F12; }"; var comp = CreateCompilation(source, options: TestOptions.ReleaseDll.WithMetadataImportOptions(MetadataImportOptions.All)); CompileAndVerify(comp, sourceSymbolValidator: validate, symbolValidator: validate); static void validate(ModuleSymbol module) { var globalNamespace = module.GlobalNamespace; VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F0").TypeWithAnnotations, new byte[] { 0 }, new byte[] { }, "System.ValueTuple"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F1").TypeWithAnnotations, new byte[] { 0, 0, 0 }, new byte[] { 0 }, "(int, int)"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F2").TypeWithAnnotations, new byte[] { 0, 0, 0, 0, 0, 0 }, new byte[] { 0 }, "(int?, int?)?"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F3").TypeWithAnnotations, new byte[] { 0, 0, 0 }, new byte[] { 0, 0 }, "(int, object)"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F4").TypeWithAnnotations, new byte[] { 0, 0, 0 }, new byte[] { 0, 0 }, "(object, int)"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F5").TypeWithAnnotations, new byte[] { 0, 0, 2 }, new byte[] { 0, 2 }, "(int, object?)"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F6").TypeWithAnnotations, new byte[] { 0, 1, 0 }, new byte[] { 0, 1 }, "(object!, int)"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F7").TypeWithAnnotations, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, new byte[] { 0, 0, 0, 0 }, "((int, int), ((int, int), int))"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F8").TypeWithAnnotations, new byte[] { 0, 0, 0, 0, 0, 0, 0, 1, 0 }, new byte[] { 0, 0, 0, 0, 1 }, "((int, int), ((int, object!), int))"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F9").TypeWithAnnotations, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, new byte[] { 0, 0, 0 }, "(int _1, int _2, int _3, int _4, int _5, int _6, int _7, object _8)"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F10").TypeWithAnnotations, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, new byte[] { 0, 0 }, "(int _1, int _2, int _3, int _4, int _5, int _6, int _7, int _8, int _9)"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F11").TypeWithAnnotations, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, new byte[] { 0, 0, 1 }, "(int _1, int _2, int _3, int _4, int _5, int _6, int _7, int _8, object! _9)"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F12").TypeWithAnnotations, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 }, new byte[] { 0, 0, 1 }, "(int _1, int _2, int _3, int _4, int _5, int _6, int _7, object! _8, int _9)"); } } [Fact] public void EmitAttribute_ValueTypes_04() { var source = @"#nullable enable struct S0 { internal struct S { } internal class C { } } struct S1<T> { internal struct S { } internal class C { } } class C0 { internal struct S { } internal class C { } } class C1<T> { internal struct S { } internal class C { } } class Program { S0.S F11; #nullable disable S0.C F12; #nullable enable S0.C F13; S1<int>.S F21; #nullable disable S1<int>.C F22; #nullable enable S1<int>.C F23; #nullable disable S1<object>.S F24; #nullable enable S1<object>.S F25; S1< #nullable disable object #nullable enable >.C F26; S1<object #nullable disable >.C F27; #nullable enable S1<int>.S[] F28; S1<C1<object>.S> F29; C0.S F31; #nullable disable C0.C F32; #nullable enable C0.C F33; C1<int>.S F41; #nullable disable C1<int>.C F42; #nullable enable C1<int>.C F43; #nullable disable C1<object>.S F44; #nullable enable C1<object>.S F45; C1< #nullable disable object #nullable enable >.C F46; C1<object #nullable disable >.C F47; #nullable enable C1<int>.S[] F48; C1<S1<object>.S> F49; }"; var comp = CreateCompilation(source, options: TestOptions.ReleaseDll.WithMetadataImportOptions(MetadataImportOptions.All)); CompileAndVerify(comp, sourceSymbolValidator: validate, symbolValidator: validate); static void validate(ModuleSymbol module) { var globalNamespace = module.GlobalNamespace; VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F11").TypeWithAnnotations, new byte[] { 0 }, new byte[] { }, "S0.S"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F12").TypeWithAnnotations, new byte[] { 0 }, new byte[] { 0 }, "S0.C"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F13").TypeWithAnnotations, new byte[] { 1 }, new byte[] { 1 }, "S0.C!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F21").TypeWithAnnotations, new byte[] { 0, 0 }, new byte[] { 0 }, "S1<int>.S"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F22").TypeWithAnnotations, new byte[] { 0, 0 }, new byte[] { 0 }, "S1<int>.C"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F23").TypeWithAnnotations, new byte[] { 1, 0 }, new byte[] { 1 }, "S1<int>.C!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F24").TypeWithAnnotations, new byte[] { 0, 0 }, new byte[] { 0, 0 }, "S1<object>.S"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F25").TypeWithAnnotations, new byte[] { 0, 1 }, new byte[] { 0, 1 }, "S1<object!>.S"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F26").TypeWithAnnotations, new byte[] { 1, 0 }, new byte[] { 1, 0 }, "S1<object>.C!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F27").TypeWithAnnotations, new byte[] { 0, 1 }, new byte[] { 0, 1 }, "S1<object!>.C"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F28").TypeWithAnnotations, new byte[] { 1, 0, 0 }, new byte[] { 1, 0 }, "S1<int>.S[]!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F29").TypeWithAnnotations, new byte[] { 0, 0, 1 }, new byte[] { 0, 0, 1 }, "S1<C1<object!>.S>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F31").TypeWithAnnotations, new byte[] { 0 }, new byte[] { }, "C0.S"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F32").TypeWithAnnotations, new byte[] { 0 }, new byte[] { 0 }, "C0.C"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F33").TypeWithAnnotations, new byte[] { 1 }, new byte[] { 1 }, "C0.C!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F41").TypeWithAnnotations, new byte[] { 0, 0 }, new byte[] { 0 }, "C1<int>.S"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F42").TypeWithAnnotations, new byte[] { 0, 0 }, new byte[] { 0 }, "C1<int>.C"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F43").TypeWithAnnotations, new byte[] { 1, 0 }, new byte[] { 1 }, "C1<int>.C!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F44").TypeWithAnnotations, new byte[] { 0, 0 }, new byte[] { 0, 0 }, "C1<object>.S"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F45").TypeWithAnnotations, new byte[] { 0, 1 }, new byte[] { 0, 1 }, "C1<object!>.S"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F46").TypeWithAnnotations, new byte[] { 1, 0 }, new byte[] { 1, 0 }, "C1<object>.C!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F47").TypeWithAnnotations, new byte[] { 0, 1 }, new byte[] { 0, 1 }, "C1<object!>.C"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F48").TypeWithAnnotations, new byte[] { 1, 0, 0 }, new byte[] { 1, 0 }, "C1<int>.S[]!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F49").TypeWithAnnotations, new byte[] { 1, 0, 1 }, new byte[] { 1, 0, 1 }, "C1<S1<object!>.S>!"); } } [Fact] public void EmitAttribute_ValueTypes_05() { var source = @"#nullable enable interface I0 { internal delegate void D(); internal enum E { } internal interface I { } } interface I1<T> { internal delegate void D(); internal enum E { } internal interface I { } } class Program { I0.D F1; I0.E F2; I0.I F3; I1<int>.D F4; I1<int>.E F5; I1<int>.I F6; #nullable disable I1<object>.D F7; I1<object>.E F8; I1<object>.I F9; #nullable enable I1<object>.E F10; I1<int>.E[] F11; I1<I0.E> F12; I1<I1<object>.E>.E F13; I1<I1<int>.D>.I F14; }"; var comp = CreateCompilation(source, options: TestOptions.ReleaseDll.WithMetadataImportOptions(MetadataImportOptions.All)); CompileAndVerify(comp, sourceSymbolValidator: validate, symbolValidator: validate); static void validate(ModuleSymbol module) { var globalNamespace = module.GlobalNamespace; VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F1").TypeWithAnnotations, new byte[] { 1 }, new byte[] { 1 }, "I0.D!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F2").TypeWithAnnotations, new byte[] { 0 }, new byte[] { }, "I0.E"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F3").TypeWithAnnotations, new byte[] { 1 }, new byte[] { 1 }, "I0.I!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F4").TypeWithAnnotations, new byte[] { 1, 0 }, new byte[] { 1 }, "I1<int>.D!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F5").TypeWithAnnotations, new byte[] { 0, 0 }, new byte[] { 0 }, "I1<int>.E"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F6").TypeWithAnnotations, new byte[] { 1, 0 }, new byte[] { 1 }, "I1<int>.I!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F7").TypeWithAnnotations, new byte[] { 0, 0 }, new byte[] { 0, 0 }, "I1<object>.D"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F8").TypeWithAnnotations, new byte[] { 0, 0 }, new byte[] { 0, 0 }, "I1<object>.E"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F9").TypeWithAnnotations, new byte[] { 0, 0 }, new byte[] { 0, 0 }, "I1<object>.I"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F10").TypeWithAnnotations, new byte[] { 0, 1 }, new byte[] { 0, 1 }, "I1<object!>.E"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F11").TypeWithAnnotations, new byte[] { 1, 0, 0 }, new byte[] { 1, 0 }, "I1<int>.E[]!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F12").TypeWithAnnotations, new byte[] { 1, 0 }, new byte[] { 1 }, "I1<I0.E>!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F13").TypeWithAnnotations, new byte[] { 0, 0, 1 }, new byte[] { 0, 0, 1 }, "I1<I1<object!>.E>.E"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F14").TypeWithAnnotations, new byte[] { 1, 1, 0 }, new byte[] { 1, 1 }, "I1<I1<int>.D!>.I!"); } } [Fact] public void EmitAttribute_ValueTypes_06() { var source = @"#nullable enable struct S<T> { } class C<T> { } unsafe class Program { int* F1; int?* F2; S<int*> F3; S<int>* F4; #nullable disable C<int*> F5; #nullable enable C<int*> F6; }"; var comp = CreateCompilation(source); var globalNamespace = comp.GlobalNamespace; VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F1").TypeWithAnnotations, new byte[] { 0, 0 }, new byte[] { 0 }, "int*"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F2").TypeWithAnnotations, new byte[] { 0, 0, 0 }, new byte[] { 0 }, "int?*"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F3").TypeWithAnnotations, new byte[] { 0, 0, 0 }, new byte[] { 0, 0 }, "S<int*>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F4").TypeWithAnnotations, new byte[] { 0, 0, 0 }, new byte[] { 0, 0 }, "S<int>*"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F5").TypeWithAnnotations, new byte[] { 0, 0, 0 }, new byte[] { 0, 0 }, "C<int*>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F6").TypeWithAnnotations, new byte[] { 1, 0, 0 }, new byte[] { 1, 0 }, "C<int*>!"); } [Fact] public void EmitAttribute_ValueTypes_07() { var source = @"#nullable enable class C<T> { } struct S<T> { } class Program<T, U, V> where U : class where V : struct { T F11; T[] F12; C<T> F13; S<T> F14; #nullable disable U F21; #nullable enable U? F22; U[] F23; C<U> F24; S<U> F25; V F31; V? F32; V[] F33; C<V> F34; S<V> F35; }"; var comp = CreateCompilation(source, options: TestOptions.ReleaseDll.WithMetadataImportOptions(MetadataImportOptions.All)); CompileAndVerify(comp, sourceSymbolValidator: validate, symbolValidator: validate); static void validate(ModuleSymbol module) { var globalNamespace = module.GlobalNamespace; VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F11").TypeWithAnnotations, new byte[] { 1 }, new byte[] { 1 }, "T"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F12").TypeWithAnnotations, new byte[] { 1, 1 }, new byte[] { 1, 1 }, "T[]!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F13").TypeWithAnnotations, new byte[] { 1, 1 }, new byte[] { 1, 1 }, "C<T>!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F14").TypeWithAnnotations, new byte[] { 0, 1 }, new byte[] { 0, 1 }, "S<T>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F21").TypeWithAnnotations, new byte[] { 0 }, new byte[] { 0 }, "U"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F22").TypeWithAnnotations, new byte[] { 2 }, new byte[] { 2 }, "U?"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F23").TypeWithAnnotations, new byte[] { 1, 1 }, new byte[] { 1, 1 }, "U![]!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F24").TypeWithAnnotations, new byte[] { 1, 1 }, new byte[] { 1, 1 }, "C<U!>!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F25").TypeWithAnnotations, new byte[] { 0, 1 }, new byte[] { 0, 1 }, "S<U!>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F31").TypeWithAnnotations, new byte[] { 0 }, new byte[] { 0 }, "V"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F32").TypeWithAnnotations, new byte[] { 0, 0 }, new byte[] { 0 }, "V?"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F33").TypeWithAnnotations, new byte[] { 1, 0 }, new byte[] { 1, 0 }, "V[]!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F34").TypeWithAnnotations, new byte[] { 1, 0 }, new byte[] { 1, 0 }, "C<V>!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F35").TypeWithAnnotations, new byte[] { 0, 0 }, new byte[] { 0, 0 }, "S<V>"); } } [Fact] public void EmitAttribute_ValueTypes_08() { var source0 = @"public struct S0 { } public struct S2<T, U> { }"; var comp = CreateCompilation(source0); var ref0 = comp.EmitToImageReference(); var source1 = @"#nullable enable public class C2<T, U> { } public class Program { public C2<S0, object?> F1; public C2<object, S0>? F2; public S2<S0, object> F3; public S2<object?, S0> F4; public (S0, object) F5; public (object?, S0) F6; }"; // With reference assembly. comp = CreateCompilation(source1, references: new[] { ref0 }); var ref1 = comp.EmitToImageReference(); var globalNamespace = comp.GlobalNamespace; VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F1").TypeWithAnnotations, new byte[] { 1, 0, 2 }, new byte[] { 1, 2 }, "C2<S0, object?>!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F2").TypeWithAnnotations, new byte[] { 2, 1, 0 }, new byte[] { 2, 1 }, "C2<object!, S0>?"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F3").TypeWithAnnotations, new byte[] { 0, 0, 1 }, new byte[] { 0, 1 }, "S2<S0, object!>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F4").TypeWithAnnotations, new byte[] { 0, 2, 0 }, new byte[] { 0, 2 }, "S2<object?, S0>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F5").TypeWithAnnotations, new byte[] { 0, 0, 1 }, new byte[] { 0, 1 }, "(S0, object!)"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F6").TypeWithAnnotations, new byte[] { 0, 2, 0 }, new byte[] { 0, 2 }, "(object?, S0)"); // Without reference assembly. comp = CreateCompilation(source1); globalNamespace = comp.GlobalNamespace; VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F1").TypeWithAnnotations, new byte[] { 1, 0, 2 }, new byte[] { 1, 1, 2 }, "C2<S0!, object?>!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F2").TypeWithAnnotations, new byte[] { 2, 1, 0 }, new byte[] { 2, 1, 1 }, "C2<object!, S0!>?"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F3").TypeWithAnnotations, new byte[] { 0, 0, 1 }, new byte[] { 1, 1, 1 }, "S2<S0!, object!>!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F4").TypeWithAnnotations, new byte[] { 0, 2, 0 }, new byte[] { 1, 2, 1 }, "S2<object?, S0!>!"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F5").TypeWithAnnotations, new byte[] { 0, 0, 1 }, new byte[] { 0, 1, 1 }, "(S0!, object!)"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F6").TypeWithAnnotations, new byte[] { 0, 2, 0 }, new byte[] { 0, 2, 1 }, "(object?, S0!)"); var source2 = @""; // Without reference assembly. comp = CreateCompilation(source2, references: new[] { ref1 }); globalNamespace = comp.GlobalNamespace; VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F1").TypeWithAnnotations, new byte[] { 1, 0, 2 }, new byte[] { 0, 0, 0 }, "C2<S0, object>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F2").TypeWithAnnotations, new byte[] { 2, 1, 0 }, new byte[] { 0, 0, 0 }, "C2<object, S0>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F3").TypeWithAnnotations, new byte[] { 0, 0, 1 }, new byte[] { 0, 0, 0 }, "S2<S0, object>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F4").TypeWithAnnotations, new byte[] { 0, 2, 0 }, new byte[] { 0, 0, 0 }, "S2<object, S0>"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F5").TypeWithAnnotations, new byte[] { 0, 0, 1 }, new byte[] { 0, 0, 0 }, "(S0, object)"); VerifyBytes(globalNamespace.GetMember<FieldSymbol>("Program.F6").TypeWithAnnotations, new byte[] { 0, 2, 0 }, new byte[] { 0, 0, 0 }, "(object, S0)"); } private static readonly SymbolDisplayFormat _displayFormat = SymbolDisplayFormat.TestFormat. WithMiscellaneousOptions(SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier | SymbolDisplayMiscellaneousOptions.IncludeNotNullableReferenceTypeModifier | SymbolDisplayMiscellaneousOptions.UseSpecialTypes). WithCompilerInternalOptions(SymbolDisplayCompilerInternalOptions.None); private static void VerifyBytes(TypeWithAnnotations type, byte[] expectedPreviously, byte[] expectedNow, string expectedDisplay) { var builder = ArrayBuilder<byte>.GetInstance(); type.AddNullableTransforms(builder); var actualBytes = builder.ToImmutableAndFree(); Assert.Equal(expectedNow, actualBytes); Assert.Equal(expectedDisplay, type.ToDisplayString(_displayFormat)); var underlyingType = type.SetUnknownNullabilityForReferenceTypes(); // Verify re-applying the same bytes gives the same result. TypeWithAnnotations updated; int position = 0; Assert.True(underlyingType.ApplyNullableTransforms(0, actualBytes, ref position, out updated)); Assert.True(updated.Equals(type, TypeCompareKind.ConsiderEverything)); // If the expected byte[] is shorter than earlier builds, verify that // applying the previous byte[] does not consume all bytes. if (!expectedPreviously.SequenceEqual(expectedNow)) { position = 0; underlyingType.ApplyNullableTransforms(0, ImmutableArray.Create(expectedPreviously), ref position, out _); Assert.Equal(position, expectedNow.Length); } } [Fact] public void EmitAttribute_ValueTypes_09() { var source1 = @"#nullable enable public interface I { void M1(int x); void M2(int[]? x); void M3(int x, object? y); }"; var comp = CreateCompilation(source1); var expected1 = @"[NullableContext(2)] I void M1(System.Int32 x) System.Int32 x void M2(System.Int32[]? x) System.Int32[]? x void M3(System.Int32 x, System.Object? y) System.Int32 x System.Object? y "; AssertNullableAttributes(comp, expected1); var ref0 = comp.EmitToImageReference(); var source2 = @"#nullable enable class C : I { public void M1(int x) { } public void M2(int[]? x) { } public void M3(int x, object? y) { } }"; comp = CreateCompilation(source2, references: new[] { ref0 }); comp.VerifyDiagnostics(); } [Fact] public void EmitAttribute_ValueTypes_10() { var source1 = @"#nullable enable public class C<T> { } public interface I1 { void M(int x, object? y, object? z); } public interface I2 { void M(C<int>? x, object? y, object? z); }"; var comp = CreateCompilation(source1); var expected1 = @"C<T> [Nullable(2)] T [NullableContext(2)] I1 void M(System.Int32 x, System.Object? y, System.Object? z) System.Int32 x System.Object? y System.Object? z [NullableContext(2)] I2 void M(C<System.Int32>? x, System.Object? y, System.Object? z) C<System.Int32>? x System.Object? y System.Object? z "; AssertNullableAttributes(comp, expected1); var ref0 = comp.EmitToImageReference(); var source2 = @"#nullable enable class C1 : I1 { public void M(int x, object? y, object? z) { } } class C2 : I2 { public void M(C<int>? x, object? y, object? z) { } }"; comp = CreateCompilation(source2, references: new[] { ref0 }); comp.VerifyDiagnostics(); } [Fact] public void EmitAttribute_ValueTypes_11() { var source1 = @"#nullable enable public interface I1<T> { void M(T x, object? y, object? z); } public interface I2<T> where T : class { void M(T? x, object? y, object? z); } public interface I3<T> where T : struct { void M(T x, object? y, object? z); }"; var comp = CreateCompilation(source1); var expected1 = @"[NullableContext(2)] I1<T> T void M(T x, System.Object? y, System.Object? z) [Nullable(1)] T x System.Object? y System.Object? z [NullableContext(1)] I2<T> where T : class! T [NullableContext(2)] void M(T? x, System.Object? y, System.Object? z) T? x System.Object? y System.Object? z I3<T> where T : struct [NullableContext(2)] void M(T x, System.Object? y, System.Object? z) [Nullable(0)] T x System.Object? y System.Object? z "; AssertNullableAttributes(comp, expected1); var ref0 = comp.EmitToImageReference(); var source2 = @"#nullable enable class C1A<T> : I1<T> where T : struct { public void M(T x, object? y, object? z) { } } class C1B : I1<int> { public void M(int x, object? y, object? z) { } } class C2A<T> : I2<T> where T : class { public void M(T? x, object? y, object? z) { } } class C2B : I2<string> { public void M(string? x, object? y, object? z) { } } class C3A<T> : I3<T> where T : struct { public void M(T x, object? y, object? z) { } } class C3B : I3<int> { public void M(int x, object? y, object? z) { } }"; comp = CreateCompilation(source2, references: new[] { ref0 }); comp.VerifyDiagnostics(); } [Fact] public void UseSiteError_LambdaReturnType() { var source0 = @"namespace System { public class Object { } public abstract class ValueType { } public struct Void { } public struct Boolean { } public struct IntPtr { } public class MulticastDelegate { } }"; var comp0 = CreateEmptyCompilation(source0, parseOptions: TestOptions.Regular.WithNoRefSafetyRulesAttribute()); var ref0 = comp0.EmitToImageReference(); var source = @"delegate T D<T>(); class C { static void F<T>(D<T> d) { } static void G(object o) { F(() => { if (o != new object()) return o; return null; }); } }"; var comp = CreateEmptyCompilation( source, references: new[] { ref0 }, parseOptions: TestOptions.Regular8.WithNoRefSafetyRulesAttribute()); comp.VerifyEmitDiagnostics(); } [Fact] public void ModuleMissingAttribute_BaseClass() { var source = @"class A<T> { } class B : A<object?> { }"; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: WithNullableEnable(TestOptions.ReleaseModule)); comp.VerifyEmitDiagnostics( // (1,9): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // class A<T> Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "T").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(1, 9), // (4,7): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // class B : A<object?> Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "B").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(4, 7)); } [Fact] public void ModuleMissingAttribute_Interface() { var source = @"interface I<T> { } class C : I<(object X, object? Y)> { }"; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: WithNullableEnable(TestOptions.ReleaseModule)); comp.VerifyEmitDiagnostics( // (1,11): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableContextAttribute' is not defined or imported // interface I<T> Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "I").WithArguments("System.Runtime.CompilerServices.NullableContextAttribute").WithLocation(1, 11), // (1,13): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // interface I<T> Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "T").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(1, 13), // (4,7): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // class C : I<(object X, object? Y)> Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "C").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(4, 7)); } [Fact] public void ModuleMissingAttribute_MethodReturnType() { var source = @"class C { object? F() => null; }"; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: WithNullableEnable(TestOptions.ReleaseModule)); comp.VerifyEmitDiagnostics( // (3,5): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // object? F() => null; Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "object?").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(3, 5), // (3,13): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableContextAttribute' is not defined or imported // object? F() => null; Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "F").WithArguments("System.Runtime.CompilerServices.NullableContextAttribute").WithLocation(3, 13)); } [Fact] public void ModuleMissingAttribute_MethodParameters() { var source = @"class C { void F(object?[] c) { } }"; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: WithNullableEnable(TestOptions.ReleaseModule)); comp.VerifyEmitDiagnostics( // (3,12): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // void F(object?[] c) { } Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "object?[] c").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(3, 12)); } [Fact] public void ModuleMissingAttribute_ConstructorParameters() { var source = @"class C { C(object?[] c) { } }"; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: WithNullableEnable(TestOptions.ReleaseModule)); comp.VerifyEmitDiagnostics( // (3,7): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // C(object?[] c) { } Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "object?[] c").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(3, 7)); } [Fact] public void ModuleMissingAttribute_PropertyType() { var source = @"class C { object? P => null; }"; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: WithNullableEnable(TestOptions.ReleaseModule)); comp.VerifyEmitDiagnostics( // (1,7): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableContextAttribute' is not defined or imported // class C Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "C").WithArguments("System.Runtime.CompilerServices.NullableContextAttribute").WithLocation(1, 7), // (3,5): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // object? P => null; Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "object?").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(3, 5)); } [Fact] public void ModuleMissingAttribute_PropertyParameters() { var source = @"class C { object this[object x, object? y] => throw new System.NotImplementedException(); }"; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: WithNullableEnable(TestOptions.ReleaseModule)); comp.VerifyEmitDiagnostics( // (1,7): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableContextAttribute' is not defined or imported // class C Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "C").WithArguments("System.Runtime.CompilerServices.NullableContextAttribute").WithLocation(1, 7), // (3,5): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // object this[object x, object? y] => throw new System.NotImplementedException(); Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "object").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(3, 5), // (3,17): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // object this[object x, object? y] => throw new System.NotImplementedException(); Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "object x").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(3, 17), // (3,27): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // object this[object x, object? y] => throw new System.NotImplementedException(); Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "object? y").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(3, 27)); } [Fact] public void ModuleMissingAttribute_OperatorReturnType() { var source = @"class C { public static object? operator+(C a, C b) => null; }"; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: WithNullableEnable(TestOptions.ReleaseModule)); comp.VerifyEmitDiagnostics( // (3,19): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // public static object? operator+(C a, C b) => null; Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "object?").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(3, 19), // (3,35): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableContextAttribute' is not defined or imported // public static object? operator+(C a, C b) => null; Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "+").WithArguments("System.Runtime.CompilerServices.NullableContextAttribute").WithLocation(3, 35), // (3,37): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // public static object? operator+(C a, C b) => null; Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "C a").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(3, 37), // (3,42): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // public static object? operator+(C a, C b) => null; Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "C b").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(3, 42) ); } [Fact] public void ModuleMissingAttribute_OperatorParameters() { var source = @"class C { public static object operator+(C a, object?[] b) => a; }"; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: WithNullableEnable(TestOptions.ReleaseModule)); comp.VerifyEmitDiagnostics( // (3,19): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // public static object operator+(C a, object?[] b) => a; Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "object").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(3, 19), // (3,34): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableContextAttribute' is not defined or imported // public static object operator+(C a, object?[] b) => a; Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "+").WithArguments("System.Runtime.CompilerServices.NullableContextAttribute").WithLocation(3, 34), // (3,36): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // public static object operator+(C a, object?[] b) => a; Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "C a").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(3, 36), // (3,41): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // public static object operator+(C a, object?[] b) => a; Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "object?[] b").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(3, 41)); } [Fact] public void ModuleMissingAttribute_DelegateReturnType() { var source = @"delegate object? D();"; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: WithNullableEnable(TestOptions.ReleaseModule)); comp.VerifyEmitDiagnostics( // (1,10): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // delegate object? D(); Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "object?").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(1, 10), // (1,18): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableContextAttribute' is not defined or imported // delegate object? D(); Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "D").WithArguments("System.Runtime.CompilerServices.NullableContextAttribute").WithLocation(1, 18)); } [Fact] public void ModuleMissingAttribute_DelegateParameters() { var source = @"delegate void D(object?[] o);"; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: WithNullableEnable(TestOptions.ReleaseModule)); comp.VerifyEmitDiagnostics( // (1,17): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // delegate void D(object?[] o); Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "object?[] o").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(1, 17)); } [Fact] public void ModuleMissingAttribute_LambdaReturnType() { var source = @"delegate T D<T>(); class C { static void F<T>(D<T> d) { } static void G(object o) { F(() => { if (o != new object()) return o; return null; }); } }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseModule); // The lambda signature is emitted without a [Nullable] attribute because // the return type is inferred from flow analysis, not from initial binding. // As a result, there is no missing attribute warning. comp.VerifyEmitDiagnostics(); } [Fact] public void ModuleMissingAttribute_LambdaParameters() { var source = @"delegate void D<T>(T t); class C { static void F<T>(D<T> d) { } static void G() { F((object? o) => { }); } }"; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: WithNullableEnable(TestOptions.ReleaseModule)); comp.VerifyEmitDiagnostics( // (1,15): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableContextAttribute' is not defined or imported // delegate void D<T>(T t); Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "D").WithArguments("System.Runtime.CompilerServices.NullableContextAttribute").WithLocation(1, 15), // (1,17): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // delegate void D<T>(T t); Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "T").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(1, 17), // (1,20): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // delegate void D<T>(T t); Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "T t").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(1, 20), // (4,17): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableContextAttribute' is not defined or imported // static void F<T>(D<T> d) Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "F").WithArguments("System.Runtime.CompilerServices.NullableContextAttribute").WithLocation(4, 17), // (4,19): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // static void F<T>(D<T> d) Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "T").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(4, 19), // (4,22): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // static void F<T>(D<T> d) Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "D<T> d").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(4, 22), // (9,12): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // F((object? o) => { }); Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "object? o").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(9, 12)); } [Fact] public void ModuleMissingAttribute_LocalFunctionReturnType() { var source = @"class C { static void M() { object?[] L() => throw new System.NotImplementedException(); L(); } }"; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: WithNullableEnable(TestOptions.ReleaseModule)); comp.VerifyEmitDiagnostics( // (5,9): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // object?[] L() => throw new System.NotImplementedException(); Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "object?[]").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(5, 9)); } [Fact] public void ModuleMissingAttribute_LocalFunctionParameters() { var source = @"class C { static void M() { void L(object? x, object y) { } L(null, 2); } }"; var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.Regular8, options: WithNullableEnable(TestOptions.ReleaseModule)); comp.VerifyEmitDiagnostics( // (5,16): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // void L(object? x, object y) { } Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "object? x").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(5, 16), // (5,27): error CS0518: Predefined type 'System.Runtime.CompilerServices.NullableAttribute' is not defined or imported // void L(object? x, object y) { } Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "object y").WithArguments("System.Runtime.CompilerServices.NullableAttribute").WithLocation(5, 27)); } [Fact] public void Tuples() { var source = @"public class A { public static ((object?, object) _1, object? _2, object _3, ((object?[], object), object?) _4) Nested; public static (object? _1, object _2, object? _3, object _4, object? _5, object _6, object? _7, object _8, object? _9) Long; }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8); CompileAndVerify(comp, validator: assembly => { var reader = assembly.GetMetadataReader(); var typeDef = GetTypeDefinitionByName(reader, "A"); var fieldDefs = typeDef.GetFields().Select(f => reader.GetFieldDefinition(f)).ToArray(); // Nested tuple var field = fieldDefs.Single(f => reader.StringComparer.Equals(f.Name, "Nested")); var customAttributes = field.GetCustomAttributes(); AssertAttributes(reader, customAttributes, "MemberReference:Void System.Runtime.CompilerServices.TupleElementNamesAttribute..ctor(String[])", "MethodDefinition:Void System.Runtime.CompilerServices.NullableAttribute..ctor(Byte[])"); var customAttribute = GetAttributeByConstructorName(reader, customAttributes, "MethodDefinition:Void System.Runtime.CompilerServices.NullableAttribute..ctor(Byte[])"); AssertEx.Equal(ImmutableArray.Create<byte>(0, 0, 2, 0, 2, 0, 0, 0, 0, 2, 0, 2), reader.ReadByteArray(customAttribute.Value)); // Long tuple field = fieldDefs.Single(f => reader.StringComparer.Equals(f.Name, "Long")); customAttributes = field.GetCustomAttributes(); AssertAttributes(reader, customAttributes, "MemberReference:Void System.Runtime.CompilerServices.TupleElementNamesAttribute..ctor(String[])", "MethodDefinition:Void System.Runtime.CompilerServices.NullableAttribute..ctor(Byte[])"); customAttribute = GetAttributeByConstructorName(reader, customAttributes, "MethodDefinition:Void System.Runtime.CompilerServices.NullableAttribute..ctor(Byte[])"); AssertEx.Equal(ImmutableArray.Create<byte>(0, 2, 0, 2, 0, 2, 0, 2, 0, 0, 2), reader.ReadByteArray(customAttribute.Value)); }); var source2 = @"class B { static void Main() { A.Nested._1.Item1.ToString(); // 1 A.Nested._1.Item2.ToString(); A.Nested._2.ToString(); // 2 A.Nested._3.ToString(); A.Nested._4.Item1.Item1.ToString(); A.Nested._4.Item1.Item1[0].ToString(); // 3 A.Nested._4.Item1.Item2.ToString(); A.Nested._4.Item2.ToString(); // 4 A.Long._1.ToString(); // 5 A.Long._2.ToString(); A.Long._3.ToString(); // 6 A.Long._4.ToString(); A.Long._5.ToString(); // 7 A.Long._6.ToString(); A.Long._7.ToString(); // 8 A.Long._8.ToString(); A.Long._9.ToString(); // 9 } }"; var comp2 = CreateCompilation(new[] { source2 }, options: WithNullableEnable(), parseOptions: TestOptions.Regular8, references: new[] { comp.EmitToImageReference() }); comp2.VerifyDiagnostics( // (5,9): warning CS8602: Dereference of a possibly null reference. // A.Nested._1.Item1.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "A.Nested._1.Item1").WithLocation(5, 9), // (7,9): warning CS8602: Dereference of a possibly null reference. // A.Nested._2.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "A.Nested._2").WithLocation(7, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // A.Nested._4.Item1.Item1[0].ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "A.Nested._4.Item1.Item1[0]").WithLocation(10, 9), // (12,9): warning CS8602: Dereference of a possibly null reference. // A.Nested._4.Item2.ToString(); // 4 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "A.Nested._4.Item2").WithLocation(12, 9), // (13,9): warning CS8602: Dereference of a possibly null reference. // A.Long._1.ToString(); // 5 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "A.Long._1").WithLocation(13, 9), // (15,9): warning CS8602: Dereference of a possibly null reference. // A.Long._3.ToString(); // 6 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "A.Long._3").WithLocation(15, 9), // (17,9): warning CS8602: Dereference of a possibly null reference. // A.Long._5.ToString(); // 7 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "A.Long._5").WithLocation(17, 9), // (19,9): warning CS8602: Dereference of a possibly null reference. // A.Long._7.ToString(); // 8 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "A.Long._7").WithLocation(19, 9), // (21,9): warning CS8602: Dereference of a possibly null reference. // A.Long._9.ToString(); // 9 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "A.Long._9").WithLocation(21, 9)); var type = comp2.GetMember<NamedTypeSymbol>("A"); Assert.Equal( "((System.Object?, System.Object) _1, System.Object? _2, System.Object _3, ((System.Object?[], System.Object), System.Object?) _4)", type.GetMember<FieldSymbol>("Nested").TypeWithAnnotations.ToTestDisplayString()); Assert.Equal( "(System.Object? _1, System.Object _2, System.Object? _3, System.Object _4, System.Object? _5, System.Object _6, System.Object? _7, System.Object _8, System.Object? _9)", type.GetMember<FieldSymbol>("Long").TypeWithAnnotations.ToTestDisplayString()); } // DynamicAttribute and NullableAttribute formats should be aligned. [Fact] public void TuplesDynamic() { var source = @"#pragma warning disable 0067 using System; public interface I<T> { } public class A<T> { } public class B<T> : A<(object? _1, (object _2, object? _3), object _4, object? _5, object _6, object? _7, object _8, object? _9)>, I<(object? _1, (object _2, object? _3), object _4, object? _5, object _6, object? _7, object _8, object? _9)> where T : A<(object? _1, (object _2, object? _3), object _4, object? _5, object _6, object? _7, object _8, object? _9)> { public (dynamic? _1, (object _2, dynamic? _3), object _4, dynamic? _5, object _6, dynamic? _7, object _8, dynamic? _9) Field; public event EventHandler<(dynamic? _1, (object _2, dynamic? _3), object _4, dynamic? _5, object _6, dynamic? _7, object _8, dynamic? _9)> Event; public (dynamic? _1, (object _2, dynamic? _3), object _4, dynamic? _5, object _6, dynamic? _7, object _8, dynamic? _9) Method( (dynamic? _1, (object _2, dynamic? _3), object _4, dynamic? _5, object _6, dynamic? _7, object _8, dynamic? _9) arg) => arg; public (dynamic? _1, (object _2, dynamic? _3), object _4, dynamic? _5, object _6, dynamic? _7, object _8, dynamic? _9) Property { get; set; } }"; var comp = CreateCompilation(new[] { source }, options: WithNullableEnable(), parseOptions: TestOptions.Regular8); CompileAndVerify(comp, validator: assembly => { var reader = assembly.GetMetadataReader(); var typeDef = GetTypeDefinitionByName(reader, "B`1"); // Base type checkAttributesNoDynamic(typeDef.GetCustomAttributes(), addOne: 0); // add one for A<T> // Interface implementation var interfaceImpl = reader.GetInterfaceImplementation(typeDef.GetInterfaceImplementations().Single()); checkAttributesNoDynamic(interfaceImpl.GetCustomAttributes(), addOne: 0); // add one for I<T> // Type parameter constraint type var typeParameter = reader.GetGenericParameter(typeDef.GetGenericParameters()[0]); var constraint = reader.GetGenericParameterConstraint(typeParameter.GetConstraints()[0]); checkAttributesNoDynamic(constraint.GetCustomAttributes(), addOne: 1); // add one for A<T> // Field type var field = typeDef.GetFields().Select(f => reader.GetFieldDefinition(f)).Single(f => reader.StringComparer.Equals(f.Name, "Field")); checkAttributes(field.GetCustomAttributes()); // Event type var @event = typeDef.GetEvents().Select(e => reader.GetEventDefinition(e)).Single(e => reader.StringComparer.Equals(e.Name, "Event")); checkAttributes(@event.GetCustomAttributes(), addOne: 1); // add one for EventHandler<T> // Method return type and parameter type var method = typeDef.GetMethods().Select(m => reader.GetMethodDefinition(m)).Single(m => reader.StringComparer.Equals(m.Name, "Method")); var parameters = method.GetParameters().Select(p => reader.GetParameter(p)).ToArray(); checkAttributes(parameters[0].GetCustomAttributes()); // return type checkAttributes(parameters[1].GetCustomAttributes()); // parameter // Property type var property = typeDef.GetProperties().Select(p => reader.GetPropertyDefinition(p)).Single(p => reader.StringComparer.Equals(p.Name, "Property")); checkAttributes(property.GetCustomAttributes()); void checkAttributes(CustomAttributeHandleCollection customAttributes, byte? addOne = null) { AssertAttributes(reader, customAttributes, "MemberReference:Void System.Runtime.CompilerServices.DynamicAttribute..ctor(Boolean[])", "MemberReference:Void System.Runtime.CompilerServices.TupleElementNamesAttribute..ctor(String[])", "MethodDefinition:Void System.Runtime.CompilerServices.NullableAttribute..ctor(Byte[])"); checkNullableAttribute(customAttributes, addOne); } void checkAttributesNoDynamic(CustomAttributeHandleCollection customAttributes, byte? addOne = null) { AssertAttributes(reader, customAttributes, "MemberReference:Void System.Runtime.CompilerServices.TupleElementNamesAttribute..ctor(String[])", "MethodDefinition:Void System.Runtime.CompilerServices.NullableAttribute..ctor(Byte[])"); checkNullableAttribute(customAttributes, addOne); } void checkNullableAttribute(CustomAttributeHandleCollection customAttributes, byte? addOne) { var customAttribute = GetAttributeByConstructorName(reader, customAttributes, "MethodDefinition:Void System.Runtime.CompilerServices.NullableAttribute..ctor(Byte[])"); var expectedBits = ImmutableArray.Create<byte>(0, 2, 0, 1, 2, 1, 2, 1, 2, 1, 0, 2); if (addOne.HasValue) { expectedBits = ImmutableArray.Create(addOne.GetValueOrDefault()).Concat(expectedBits); } AssertEx.Equal(expectedBits, reader.ReadByteArray(customAttribute.Value)); } }); var source2 = @"class C { static void F(B<A<(object?, (object, object?), object, object?, object, object?, object, object?)>> b) { b.Field._8.ToString(); b.Field._9.ToString(); // 1 b.Method(default)._8.ToString(); b.Method(default)._9.ToString(); // 2 b.Property._8.ToString(); b.Property._9.ToString(); // 3 } }"; var comp2 = CreateCompilation(new[] { source2 }, options: WithNullableEnable(), parseOptions: TestOptions.Regular8, references: new[] { comp.EmitToImageReference() }); comp2.VerifyDiagnostics( // (6,9): warning CS8602: Dereference of a possibly null reference. // b.Field._9.ToString(); // 1 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b.Field._9").WithLocation(6, 9), // (8,9): warning CS8602: Dereference of a possibly null reference. // b.Method(default)._9.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b.Method(default)._9").WithLocation(8, 9), // (10,9): warning CS8602: Dereference of a possibly null reference. // b.Property._9.ToString(); // 3 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b.Property._9").WithLocation(10, 9)); var type = comp2.GetMember<NamedTypeSymbol>("B"); Assert.Equal( "A<(System.Object? _1, (System.Object _2, System.Object? _3), System.Object _4, System.Object? _5, System.Object _6, System.Object? _7, System.Object _8, System.Object? _9)>", type.BaseTypeNoUseSiteDiagnostics.ToTestDisplayString()); Assert.Equal( "I<(System.Object? _1, (System.Object _2, System.Object? _3), System.Object _4, System.Object? _5, System.Object _6, System.Object? _7, System.Object _8, System.Object? _9)>", type.Interfaces()[0].ToTestDisplayString()); Assert.Equal( "A<(System.Object? _1, (System.Object _2, System.Object? _3), System.Object _4, System.Object? _5, System.Object _6, System.Object? _7, System.Object _8, System.Object? _9)>", type.TypeParameters[0].ConstraintTypesNoUseSiteDiagnostics[0].ToTestDisplayString()); Assert.Equal( "(dynamic? _1, (System.Object _2, dynamic? _3), System.Object _4, dynamic? _5, System.Object _6, dynamic? _7, System.Object _8, dynamic? _9)", type.GetMember<FieldSymbol>("Field").TypeWithAnnotations.ToTestDisplayString()); Assert.Equal( "System.EventHandler<(dynamic? _1, (System.Object _2, dynamic? _3), System.Object _4, dynamic? _5, System.Object _6, dynamic? _7, System.Object _8, dynamic? _9)>", type.GetMember<EventSymbol>("Event").TypeWithAnnotations.ToTestDisplayString()); Assert.Equal( "(dynamic? _1, (System.Object _2, dynamic? _3), System.Object _4, dynamic? _5, System.Object _6, dynamic? _7, System.Object _8, dynamic? _9) B<T>.Method((dynamic? _1, (System.Object _2, dynamic? _3), System.Object _4, dynamic? _5, System.Object _6, dynamic? _7, System.Object _8, dynamic? _9) arg)", type.GetMember<MethodSymbol>("Method").ToTestDisplayString()); Assert.Equal( "(dynamic? _1, (System.Object _2, dynamic? _3), System.Object _4, dynamic? _5, System.Object _6, dynamic? _7, System.Object _8, dynamic? _9) B<T>.Property { get; set; }", type.GetMember<PropertySymbol>("Property").ToTestDisplayString()); } [Fact] [WorkItem(36934, "https://github.com/dotnet/roslyn/issues/36934")] public void AttributeUsage() { var source = @"#nullable enable public class Program { public object? F; }"; var comp = CreateCompilation(source, options: TestOptions.ReleaseDll.WithMetadataImportOptions(MetadataImportOptions.All)); CompileAndVerify(comp, symbolValidator: module => { var attributeType = module.GlobalNamespace.GetMember<NamedTypeSymbol>("System.Runtime.CompilerServices.NullableAttribute"); AttributeUsageInfo attributeUsage = attributeType.GetAttributeUsageInfo(); Assert.False(attributeUsage.Inherited); Assert.False(attributeUsage.AllowMultiple); Assert.True(attributeUsage.HasValidAttributeTargets); var expectedTargets = AttributeTargets.Class | AttributeTargets.Event | AttributeTargets.Field | AttributeTargets.GenericParameter | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue; Assert.Equal(expectedTargets, attributeUsage.ValidTargets); }); } [Fact] public void NullableFlags_Field_Exists() { var source = @"public class C { public void F(object? x, object y, object z) { } }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8); CompileAndVerify(comp, symbolValidator: module => { var type = module.ContainingAssembly.GetTypeByMetadataName("C"); var method = (MethodSymbol)type.GetMembers("F").Single(); var attributes = method.Parameters[0].GetAttributes(); AssertNullableAttribute(attributes); var nullable = GetNullableAttribute(attributes); var field = nullable.AttributeClass.GetField("NullableFlags"); Assert.NotNull(field); Assert.Equal("System.Byte[]", field.TypeWithAnnotations.ToTestDisplayString()); }); } [Fact] public void NullableFlags_Field_Contains_ConstructorArguments_SingleByteConstructor() { var source = @" #nullable enable using System; using System.Linq; public class C { public void F(object? x, object y, object z) { } public static void Main() { var attribute = typeof(C).GetMethod(""F"").GetParameters()[0].GetCustomAttributes(true).Single(a => a.GetType().Name == ""NullableAttribute""); var field = attribute.GetType().GetField(""NullableFlags""); byte[] flags = (byte[])field.GetValue(attribute); Console.Write($""{{ {string.Join("","", flags)} }}""); } }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8, options: TestOptions.DebugExe); CompileAndVerify(comp, expectedOutput: "{ 2 }", symbolValidator: module => { var expected = @"C [NullableContext(1)] void F(System.Object? x, System.Object! y, System.Object! z) [Nullable(2)] System.Object? x System.Object! y System.Object! z "; AssertNullableAttributes(module, expected); }); } [Fact] public void NullableFlags_Field_Contains_ConstructorArguments_ByteArrayConstructor() { var source = @" #nullable enable using System; using System.Linq; public class C { public void F(Action<object?, Action<object, object?>?> c) { } public static void Main() { var attribute = typeof(C).GetMethod(""F"").GetParameters()[0].GetCustomAttributes(true).Single(a => a.GetType().Name == ""NullableAttribute""); var field = attribute.GetType().GetField(""NullableFlags""); byte[] flags = (byte[])field.GetValue(attribute); System.Console.Write($""{{ {string.Join("","", flags)} }}""); } }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8, options: TestOptions.DebugExe); CompileAndVerify(comp, expectedOutput: "{ 1,2,2,1,2 }", symbolValidator: module => { var expected = @"C void F(System.Action<System.Object?, System.Action<System.Object!, System.Object?>?>! c) [Nullable({ 1, 2, 2, 1, 2 })] System.Action<System.Object?, System.Action<System.Object!, System.Object?>?>! c "; AssertNullableAttributes(module, expected); }); } [Fact] [WorkItem(47221, "https://github.com/dotnet/roslyn/issues/47221")] public void PropertyAccessorWithNullableContextAttribute_01() { var source = @"#nullable enable public class A { public object? this[object x, object? y] => null; public static A F(object x) => new A(); public static A F(object x, object? y) => new A(); }"; var comp = CreateCompilation(source); var expected = @"[NullableContext(1)] [Nullable(0)] A A! F(System.Object! x) System.Object! x A! F(System.Object! x, System.Object? y) System.Object! x [Nullable(2)] System.Object? y A() [Nullable(2)] System.Object? this[System.Object! x, System.Object? y] { get; } [Nullable(1)] System.Object! x System.Object? y [NullableContext(2)] System.Object? this[System.Object! x, System.Object? y].get [Nullable(1)] System.Object! x System.Object? y "; AssertNullableAttributes(comp, expected); } [Fact] [WorkItem(47221, "https://github.com/dotnet/roslyn/issues/47221")] public void PropertyAccessorWithNullableContextAttribute_02() { var source = @"#nullable enable public class A { public object? this[object x, object? y] { set { } } public static A F(object x) => new A(); public static A F(object x, object? y) => new A(); }"; var comp = CreateCompilation(source); var expected = @"[NullableContext(1)] [Nullable(0)] A A! F(System.Object! x) System.Object! x A! F(System.Object! x, System.Object? y) System.Object! x [Nullable(2)] System.Object? y A() [Nullable(2)] System.Object? this[System.Object! x, System.Object? y] { set; } [Nullable(1)] System.Object! x System.Object? y [NullableContext(2)] void this[System.Object! x, System.Object? y].set [Nullable(1)] System.Object! x System.Object? y System.Object? value "; AssertNullableAttributes(comp, expected); } [Fact] [WorkItem(47221, "https://github.com/dotnet/roslyn/issues/47221")] public void PropertyAccessorWithNullableContextAttribute_03() { var source = @"#nullable enable public class A { public object this[object? x, object y] => null; public static A? F0; public static A? F1; public static A? F2; public static A? F3; public static A? F4; }"; var comp = CreateCompilation(source); var expected = @"[NullableContext(2)] [Nullable(0)] A A? F0 A? F1 A? F2 A? F3 A? F4 A() [Nullable(1)] System.Object! this[System.Object? x, System.Object! y] { get; } [Nullable(2)] System.Object? x System.Object! y [NullableContext(1)] System.Object! this[System.Object? x, System.Object! y].get [Nullable(2)] System.Object? x System.Object! y "; AssertNullableAttributes(comp, expected); } [Fact] [WorkItem(47221, "https://github.com/dotnet/roslyn/issues/47221")] public void PropertyAccessorWithNullableContextAttribute_04() { var source = @"#nullable enable public class A { public object this[object? x, object y] { set { } } public static A? F0; public static A? F1; public static A? F2; public static A? F3; public static A? F4; }"; var comp = CreateCompilation(source); var expected = @"[NullableContext(2)] [Nullable(0)] A A? F0 A? F1 A? F2 A? F3 A? F4 A() [Nullable(1)] System.Object! this[System.Object? x, System.Object! y] { set; } [Nullable(2)] System.Object? x System.Object! y [NullableContext(1)] void this[System.Object? x, System.Object! y].set [Nullable(2)] System.Object? x System.Object! y System.Object! value "; AssertNullableAttributes(comp, expected); } private static MetadataReference GetAnnotationUtilsLibrary() { var source = @"using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; public static class Utils { public static string GetAnnotations(this Delegate d) { var method = d.Method; var builder = new StringBuilder(); var contextValue = GetContextValue(method); GetTypeAndAnnotation(builder, method.ReturnType, method.ReturnParameter.GetCustomAttributes(), contextValue); builder.Append("" ""); builder.Append(method.DeclaringType.FullName); builder.Append("".""); builder.Append(method.Name); builder.Append(""(""); foreach (var parameter in method.GetParameters()) { GetTypeAndAnnotation(builder, parameter.ParameterType, parameter.GetCustomAttributes(), contextValue); builder.Append("" ""); builder.Append(parameter.Name); } builder.Append("")""); return builder.ToString(); } private static int GetContextValue(MemberInfo member) { if (GetAttribute(member.GetCustomAttributes(), ""System.Runtime.CompilerServices.NullableContextAttribute"") is { } attribute) { var field = attribute.GetType().GetField(""Flag""); return (int)(byte)field.GetValue(attribute); } if (member.DeclaringType is { } declaringType) { return GetContextValue(declaringType); } return 0; } private static void GetTypeAndAnnotation(StringBuilder builder, Type type, IEnumerable<Attribute> attributes, int contextValue) { builder.Append(type.FullName); if (type.IsValueType) { return; } int value = contextValue; if (GetAttribute(attributes, ""System.Runtime.CompilerServices.NullableAttribute"") is { } attribute) { var field = attribute.GetType().GetField(""NullableFlags""); var bytes = (byte[])field.GetValue(attribute); value = bytes.SingleOrDefault(); } switch (value) { case 1: builder.Append(""!""); break; case 2: builder.Append(""?""); break; } } private static Attribute GetAttribute(IEnumerable<Attribute> attributes, string typeName) { return attributes.SingleOrDefault(attr => attr.GetType().FullName == typeName); } }"; var comp = CreateCompilation(source); return comp.EmitToImageReference(); } [Fact] [WorkItem(55254, "https://github.com/dotnet/roslyn/issues/55254")] public void LambdaAttributes_01() { var source = @"#nullable enable using System; var dump = static (string s, Delegate d) => d.GetAnnotations(); Console.WriteLine(dump(""/"", (string? name) => $""Inline lambda {name}"")); Console.WriteLine(dump(""/o"", (string? name) => { })); "; var library = GetAnnotationUtilsLibrary(); CompileAndVerify(source, options: TestOptions.ReleaseExe, references: new[] { library }, expectedOutput: @"System.String Program+<>c.<<Main>$>b__0_1(System.String? name) System.Void Program+<>c.<<Main>$>b__0_2(System.String? name) "); } [Fact] [WorkItem(55254, "https://github.com/dotnet/roslyn/issues/55254")] public void LambdaAttributes_02() { var source = @"#nullable enable using System; var dump = static (string s, Delegate d) => d.GetAnnotations(); Console.WriteLine(dump(""/"", (string name) => $""Inline lambda {name}"")); Console.WriteLine(dump(""/o"", (string name) => { })); "; var library = GetAnnotationUtilsLibrary(); CompileAndVerify(source, options: TestOptions.ReleaseExe, references: new[] { library }, expectedOutput: @"System.String Program+<>c.<<Main>$>b__0_1(System.String! name) System.Void Program+<>c.<<Main>$>b__0_2(System.String! name) "); } [Fact] [WorkItem(55254, "https://github.com/dotnet/roslyn/issues/55254")] public void LambdaAttributes_03() { var source = @"#nullable enable using System; var dump = static (string s, Delegate d) => d.GetAnnotations(); Console.WriteLine(dump(""/"", #nullable disable (string name) => #nullable disable $""Inline lambda {name}"")); Console.WriteLine(dump(""/o"", #nullable disable (string name) => #nullable disable { })); "; var library = GetAnnotationUtilsLibrary(); CompileAndVerify(source, options: TestOptions.ReleaseExe, references: new[] { library }, expectedOutput: @"System.String Program+<>c.<<Main>$>b__0_1(System.String name) System.Void Program+<>c.<<Main>$>b__0_2(System.String name) "); } [Fact] [WorkItem(55254, "https://github.com/dotnet/roslyn/issues/55254")] public void LambdaAttributes_04() { var source = @"using System; class Program { static void Report(Delegate d) => Console.WriteLine(d.GetAnnotations()); static void Main() { #nullable enable Report((string? s) => { }); object? f(string s) => null; Report(f); } }"; var library = GetAnnotationUtilsLibrary(); CompileAndVerify(source, options: TestOptions.ReleaseExe, references: new[] { library }, expectedOutput: @"System.Void Program+<>c.<Main>b__1_0(System.String? s) System.Object? Program.<Main>g__f|1_1(System.String! s) "); } private static void AssertNoNullableAttribute(ImmutableArray<CSharpAttributeData> attributes) { AssertAttributes(attributes); } private static void AssertNullableAttribute(ImmutableArray<CSharpAttributeData> attributes) { AssertAttributes(attributes, "System.Runtime.CompilerServices.NullableAttribute"); } private static void AssertAttributes(ImmutableArray<CSharpAttributeData> attributes, params string[] expectedNames) { var actualNames = attributes.Select(a => a.AttributeClass.ToTestDisplayString()).ToArray(); AssertEx.SetEqual(expectedNames, actualNames); } private static void AssertNoNullableAttributes(CSharpCompilation comp) { var image = comp.EmitToArray(); using (var reader = new PEReader(image)) { var metadataReader = reader.GetMetadataReader(); var attributes = metadataReader.GetCustomAttributeRows().Select(metadataReader.GetCustomAttributeName).ToArray(); Assert.False(attributes.Contains("NullableContextAttribute")); Assert.False(attributes.Contains("NullableAttribute")); } } private static CSharpAttributeData GetNullableAttribute(ImmutableArray<CSharpAttributeData> attributes) { return attributes.Single(a => a.AttributeClass.ToTestDisplayString() == "System.Runtime.CompilerServices.NullableAttribute"); } private static TypeDefinition GetTypeDefinitionByName(MetadataReader reader, string name) { return reader.GetTypeDefinition(reader.TypeDefinitions.Single(h => reader.StringComparer.Equals(reader.GetTypeDefinition(h).Name, name))); } private static string GetAttributeConstructorName(MetadataReader reader, CustomAttributeHandle handle) { return reader.Dump(reader.GetCustomAttribute(handle).Constructor); } private static CustomAttribute GetAttributeByConstructorName(MetadataReader reader, CustomAttributeHandleCollection handles, string name) { return reader.GetCustomAttribute(handles.FirstOrDefault(h => GetAttributeConstructorName(reader, h) == name)); } private static void AssertAttributes(MetadataReader reader, CustomAttributeHandleCollection handles, params string[] expectedNames) { var actualNames = handles.Select(h => GetAttributeConstructorName(reader, h)).ToArray(); AssertEx.SetEqual(expectedNames, actualNames); } private void AssertNullableAttributes(CSharpCompilation comp, string expected) { CompileAndVerify(comp, symbolValidator: module => AssertNullableAttributes(module, expected)); } private static void AssertNullableAttributes(ModuleSymbol module, string expected) { var actual = NullableAttributesVisitor.GetString((PEModuleSymbol)module); AssertEx.AssertEqualToleratingWhitespaceDifferences(expected, actual); } } }