From 4c0a9ee9df0482ab85c32a6951847279e35ebb62 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Thu, 6 Dec 2018 13:57:24 -0800 Subject: [PATCH 01/40] Allow unmanaged generic structs (#31148) * Add unmanaged generic struct tests * Don't bail out of managed type checks when type arguments are present * Simplify test * Delegate HasPointerType to underlying field in WrappedFieldSymbol * Add test for recursive expansion of struct with T : unmanaged * Delay constraint checking on field types until after type members are added * Update comment * Add expected diagnostic to UnmanagedRecursiveTypeArgument test * Add unmanaged recursive type argument tests with constraint violations * Don't search fields whose type is circular struct when determining if a type is managed * Update some tests * Use TypeSyntax.Location for Type.CheckAllConstraints * Add prototype comment * Update GenericConstraintsTests * Update IsManagedType asserts in UnsafeTests * Fix ManagedAddressOfTests.DisallowSizeof * Use SourceMemberFieldSymbol.SyntaxNode.Location for consistency in diagnostics * Add some tests and diagnostics * Fix more tests * Fix BaseClassTests * Add test for partially constructed generic struct which violates unmanaged constraint * Consider nullability when running AfterTypeMembersChecks * Update NullableReferenceTypesTests.Constraint_Oblivious due to differences from delayed constraint checks on field types * Check if NRT enabled in compilation to use correct nullability in constraint checks * Make UnmanagedConstraint_StructMismatchInImplements behave consistently * Disable ResourceTests.AddResourceToModule in Mono * Remove prototype comment * Remove invalid comments from UnmanagedConstraints_NestedInGenericType * Use ErrorLocation instead of SyntaxNode.Location * Rename our pipeline YAML files Originally created when everything was VSTS. This gets us back inline with the new branding. * Fix tests now that we use ErrorLocation for field constraint checks --- azure-pipelines-integration.yml | 41 ++ .vsts-ci.yml => azure-pipelines-official.yml | 0 .vsts-dnceng.yml => azure-pipelines.yml | 0 .../Portable/Symbols/BaseTypeAnalysis.cs | 11 +- .../Symbols/Source/SourceMemberFieldSymbol.cs | 9 +- .../Symbols/Wrapped/WrappedFieldSymbol.cs | 2 + .../Test/Emit/CodeGen/CodeGenTupleTest.cs | 8 +- .../CSharp/Test/Emit/Emit/ResourceTests.cs | 2 +- .../Semantics/GenericConstraintsTests.cs | 395 +++++++++++++++++- .../Semantics/NullableReferenceTypesTests.cs | 28 +- .../Semantic/Semantics/SemanticErrorTests.cs | 122 +----- .../Test/Semantic/Semantics/UnsafeTests.cs | 59 ++- .../Symbol/Symbols/Source/BaseClassTests.cs | 26 +- .../ManagedAddressOfTests.cs | 5 - 14 files changed, 509 insertions(+), 199 deletions(-) create mode 100644 azure-pipelines-integration.yml rename .vsts-ci.yml => azure-pipelines-official.yml (100%) rename .vsts-dnceng.yml => azure-pipelines.yml (100%) diff --git a/azure-pipelines-integration.yml b/azure-pipelines-integration.yml new file mode 100644 index 0000000000000..71c2116917f8e --- /dev/null +++ b/azure-pipelines-integration.yml @@ -0,0 +1,41 @@ +phases: +- phase: Windows_VisualStudio_Integration_Tests + queue: + name: dotnet-external-temp-vs2017 + timeoutInMinutes: 90 + parallel: 2 + matrix: + debug: + _configuration: Debug + release: + _configuration: Release + + steps: + - script: build/scripts/cibuild.cmd -configuration $(_configuration) -testVsi + displayName: Build and Test + + - task: PublishTestResults@1 + inputs: + testRunner: XUnit + testResultsFiles: '**/xUnitResults/*.xml' + mergeTestResults: true + testRunTitle: 'Windows Visual Studio Integration $(_configuration)' + condition: succeededOrFailed() + + - task: PublishBuildArtifacts@1 + displayName: Publish Logs + inputs: + PathtoPublish: '$(Build.SourcesDirectory)\Binaries\$(_configuration)\Logs' + ArtifactName: 'Windows Visual Studio Integration $(_configuration)' + publishLocation: Container + continueOnError: true + condition: or(failed(), canceled()) + + - task: PublishBuildArtifacts@1 + displayName: Publish Screenshots + inputs: + PathtoPublish: '$(Build.SourcesDirectory)\Binaries\$(_configuration)\UnitTests\Microsoft.VisualStudio.LanguageServices.IntegrationTests\xUnitResults/' + ArtifactName: 'Screenshots $(_configuration)' + publishLocation: Container + continueOnError: true + condition: or(failed(), canceled()) diff --git a/.vsts-ci.yml b/azure-pipelines-official.yml similarity index 100% rename from .vsts-ci.yml rename to azure-pipelines-official.yml diff --git a/.vsts-dnceng.yml b/azure-pipelines.yml similarity index 100% rename from .vsts-dnceng.yml rename to azure-pipelines.yml diff --git a/src/Compilers/CSharp/Portable/Symbols/BaseTypeAnalysis.cs b/src/Compilers/CSharp/Portable/Symbols/BaseTypeAnalysis.cs index 22e06ab2ce227..7d47f02ec0259 100644 --- a/src/Compilers/CSharp/Portable/Symbols/BaseTypeAnalysis.cs +++ b/src/Compilers/CSharp/Portable/Symbols/BaseTypeAnalysis.cs @@ -93,8 +93,7 @@ private static void StructDependsClosure(NamedTypeSymbol type, HashSet p /// IsManagedType is simple for most named types: /// enums are not managed; /// non-enum, non-struct named types are managed; - /// generic types and their nested types are managed; - /// type parameters are managed; + /// type parameters are managed unless an 'unmanaged' constraint is present; /// all special types have spec'd values (basically, (non-string) primitives) are not managed; /// /// Only structs are complicated, because the definition is recursive. A struct type is managed @@ -184,7 +183,8 @@ private static bool DependsOnDefinitelyManagedType(NamedTypeSymbol type, HashSet case ThreeState.False: continue; case ThreeState.Unknown: - if (DependsOnDefinitelyManagedType(fieldNamedType, partialClosure)) + if (!fieldNamedType.OriginalDefinition.KnownCircularStruct && + DependsOnDefinitelyManagedType(fieldNamedType, partialClosure)) { return true; } @@ -238,11 +238,6 @@ private static ThreeState IsManagedTypeHelper(NamedTypeSymbol type) break; // Proceed with additional checks. } - if (type.AllTypeArgumentCount() > 0) - { - return ThreeState.True; - } - switch (type.TypeKind) { case TypeKind.Enum: diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs index a09913b3cbf2f..3cf0c2c8e609c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs @@ -429,7 +429,7 @@ internal sealed override TypeSymbolWithAnnotations GetFieldType(ConsList _underlyingField.HasPointerType; + internal override bool IsMarshalledExplicitly { get diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs index 1ab777dcb3f82..978a30678dd05 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs @@ -9633,9 +9633,9 @@ class C // (16,12): error CS0452: The type 'U' must be a reference type in order to use it as parameter 'T2' in the generic type or method 'ValueTuple' // (U, U) M(U x) Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "M").WithArguments("System.ValueTuple", "T2", "U").WithLocation(16, 12), - // (15,14): error CS0452: The type 'T' must be a reference type in order to use it as parameter 'T2' in the generic type or method 'ValueTuple' + // (15,18): error CS0452: The type 'T' must be a reference type in order to use it as parameter 'T2' in the generic type or method 'ValueTuple' // List<(T, T)> field = null; - Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "T").WithArguments("System.ValueTuple", "T2", "T").WithLocation(15, 14), + Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "field").WithArguments("System.ValueTuple", "T2", "T").WithLocation(15, 18), // (20,28): error CS0452: The type 'U' must be a reference type in order to use it as parameter 'T2' in the generic type or method 'ValueTuple' // return default((U, U)); Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "U").WithArguments("System.ValueTuple", "T2", "U").WithLocation(20, 28), @@ -9714,9 +9714,9 @@ class C where T : class // (16,12): error CS0453: The type 'U' must be a non-nullable value type in order to use it as parameter 'T2' in the generic type or method 'ValueTuple' // (U, U) M(U x) where U : class Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "M").WithArguments("System.ValueTuple", "T2", "U").WithLocation(16, 12), - // (15,14): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'T2' in the generic type or method 'ValueTuple' + // (15,18): error CS0453: The type 'T' must be a non-nullable value type in order to use it as parameter 'T2' in the generic type or method 'ValueTuple' // List<(T, T)> field = null; - Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "T").WithArguments("System.ValueTuple", "T2", "T").WithLocation(15, 14), + Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "field").WithArguments("System.ValueTuple", "T2", "T").WithLocation(15, 18), // (18,24): error CS0452: The type 'int' must be a reference type in order to use it as parameter 'T' in the generic type or method 'C' // var t0 = new C(); Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "int").WithArguments("C", "T", "int").WithLocation(18, 24), diff --git a/src/Compilers/CSharp/Test/Emit/Emit/ResourceTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/ResourceTests.cs index ac20a3df43709..f50cba03d39b3 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/ResourceTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/ResourceTests.cs @@ -433,7 +433,7 @@ public void AddManagedResource() c1 = null; } - [ConditionalFact(typeof(DesktopOnly))] + [ConditionalFact(typeof(WindowsDesktopOnly))] public void AddResourceToModule() { bool metadataOnly = false; diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs index 1984839bc6eee..0ab0338c32e53 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs @@ -2286,6 +2286,10 @@ public override void M() where T : unmanaged { } public void UnmanagedConstraint_StructMismatchInImplements() { CreateCompilation(@" +public struct Segment { + public T[] array; +} + public interface I1 where T : unmanaged { void Test(G x) where G : unmanaged; @@ -2296,22 +2300,22 @@ public class C2 : I1 where T : struct public void Test(G x) where G : struct { I1 i = this; - i.Test(default(System.ArraySegment)); + i.Test(default(Segment)); } } ").VerifyDiagnostics( - // (7,14): error CS8379: The type 'T' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'I1' + // (11,14): error CS8377: The type 'T' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'I1' // public class C2 : I1 where T : struct - Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "C2").WithArguments("I1", "T", "T").WithLocation(7, 14), - // (9,17): error CS0425: The constraints for type parameter 'G' of method 'C2.Test(G)' must match the constraints for type parameter 'G' of interface method 'I1.Test(G)'. Consider using an explicit interface implementation instead. + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "C2").WithArguments("I1", "T", "T").WithLocation(11, 14), + // (13,17): error CS0425: The constraints for type parameter 'G' of method 'C2.Test(G)' must match the constraints for type parameter 'G' of interface method 'I1.Test(G)'. Consider using an explicit interface implementation instead. // public void Test(G x) where G : struct - Diagnostic(ErrorCode.ERR_ImplBadConstraints, "Test").WithArguments("G", "C2.Test(G)", "G", "I1.Test(G)").WithLocation(9, 17), - // (11,12): error CS8379: The type 'T' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'I1' + Diagnostic(ErrorCode.ERR_ImplBadConstraints, "Test").WithArguments("G", "C2.Test(G)", "G", "I1.Test(G)").WithLocation(13, 17), + // (15,12): error CS8377: The type 'T' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'I1' // I1 i = this; - Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "T").WithArguments("I1", "T", "T").WithLocation(11, 12), - // (12,11): error CS8379: The type 'ArraySegment' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'G' in the generic type or method 'I1.Test(G)' - // i.Test(default(System.ArraySegment)); - Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "Test").WithArguments("I1.Test(G)", "G", "System.ArraySegment").WithLocation(12, 11) + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "T").WithArguments("I1", "T", "T").WithLocation(15, 12), + // (16,11): error CS8377: The type 'Segment' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'G' in the generic type or method 'I1.Test(G)' + // i.Test(default(Segment)); + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "Test").WithArguments("I1.Test(G)", "G", "Segment").WithLocation(16, 11) ); } @@ -2976,7 +2980,7 @@ void User() IsStruct.E>(); IsNew.E>(); - IsUnmanaged.S>(); // Invalid + IsUnmanaged.S>(); IsEnum.S>(); // Invalid IsStruct.S>(); IsNew.S>(); @@ -2986,7 +2990,7 @@ void User() IsStruct.E>(); IsNew.E>(); - IsUnmanaged.S>(); // Invalid + IsUnmanaged.S>(); IsEnum.S>(); // Invalid IsStruct.S>(); IsNew.S>(); @@ -2994,15 +2998,9 @@ void User() }"; CreateCompilation(code).VerifyDiagnostics( - // (27,9): error CS8377: The type 'Wrapper.S' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.IsUnmanaged()' - // IsUnmanaged.S>(); // Invalid - Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "IsUnmanaged.S>").WithArguments("Test.IsUnmanaged()", "T", "Wrapper.S").WithLocation(27, 9), // (28,9): error CS0315: The type 'Wrapper.S' cannot be used as type parameter 'T' in the generic type or method 'Test.IsEnum()'. There is no boxing conversion from 'Wrapper.S' to 'System.Enum'. // IsEnum.S>(); // Invalid Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "IsEnum.S>").WithArguments("Test.IsEnum()", "System.Enum", "T", "Wrapper.S").WithLocation(28, 9), - // (37,9): error CS8377: The type 'Wrapper.S' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.IsUnmanaged()' - // IsUnmanaged.S>(); // Invalid - Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "IsUnmanaged.S>").WithArguments("Test.IsUnmanaged()", "T", "Wrapper.S").WithLocation(37, 9), // (38,9): error CS0315: The type 'Wrapper.S' cannot be used as type parameter 'T' in the generic type or method 'Test.IsEnum()'. There is no boxing conversion from 'Wrapper.S' to 'System.Enum'. // IsEnum.S>(); // Invalid Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "IsEnum.S>").WithArguments("Test.IsEnum()", "System.Enum", "T", "Wrapper.S").WithLocation(38, 9)); @@ -3270,5 +3268,366 @@ void Test() // UnmanagedWithInterface(&a); // fail (does not match interface) Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "UnmanagedWithInterface").WithArguments("C.UnmanagedWithInterface(T*)", "System.IDisposable", "T", "int").WithLocation(20, 9)); } + + [Fact] + public void UnmanagedGenericStructPointer() + { + var code = @" +public struct MyStruct +{ + public T field; +} + +public class C +{ + public unsafe void M() + { + MyStruct myStruct; + M2(&myStruct); + } + + public unsafe void M2(MyStruct* ms) { } +} +"; + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll) + .VerifyDiagnostics(); + } + + [Fact] + public void ManagedGenericStructPointer() + { + var code = @" +public struct MyStruct +{ + public T field; +} + +public class C +{ + public unsafe void M() + { + MyStruct myStruct; + M2(&myStruct); + } + + public unsafe void M2(MyStruct* ms) where T : unmanaged { } +} +"; + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll) + .VerifyDiagnostics( + // (12,12): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('MyStruct') + // M2(&myStruct); + Diagnostic(ErrorCode.ERR_ManagedAddr, "&myStruct").WithArguments("MyStruct").WithLocation(12, 12)); + } + + [Fact] + public void UnmanagedGenericConstraintStructPointer() + { + var code = @" +public struct MyStruct where T : unmanaged +{ + public T field; +} + +public class C +{ + public unsafe void M() + { + MyStruct myStruct; + M2(&myStruct); + } + + public unsafe void M2(MyStruct* ms) { } +} +"; + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll) + .VerifyDiagnostics(); + } + + [Fact] + public void UnmanagedGenericConstraintNestedStructPointer() + { + var code = @" +public struct MyStruct where T : unmanaged +{ + public T field; +} + +public struct OuterStruct +{ + public int x; + public InnerStruct inner; +} + +public struct InnerStruct +{ + public int y; +} + +public class C +{ + public unsafe void M() + { + MyStruct myStruct; + M2(&myStruct); + } + + public unsafe void M2(MyStruct* ms) { } +} +"; + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll) + .VerifyDiagnostics(); + } + + [Fact] + public void UnmanagedGenericConstraintNestedGenericStructPointer() + { + var code = @" +public struct MyStruct where T : unmanaged +{ + public T field; +} + +public struct InnerStruct +{ + public U value; +} + +public class C +{ + public unsafe void M() + { + MyStruct> myStruct; + M2(&myStruct); + } + + public unsafe void M2(MyStruct>* ms) { } +} +"; + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll) + .VerifyDiagnostics(); + } + + [Fact] + public void UnmanagedGenericConstraintPartialConstructedStruct() + { + var code = @" +public struct MyStruct where T : unmanaged +{ + public T field; +} + +public class C +{ + public unsafe void M() + { + MyStruct myStruct; + M2(&myStruct); + } + + public unsafe void M2(MyStruct* ms) { } +} +"; + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll) + .VerifyDiagnostics( + // (11,18): error CS8377: The type 'U' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'MyStruct' + // MyStruct myStruct; + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "U").WithArguments("MyStruct", "T", "U").WithLocation(11, 18), + // (12,15): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('MyStruct') + // M2(&myStruct); + Diagnostic(ErrorCode.ERR_ManagedAddr, "&myStruct").WithArguments("MyStruct").WithLocation(12, 15), + // (15,30): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('MyStruct') + // public unsafe void M2(MyStruct* ms) { } + Diagnostic(ErrorCode.ERR_ManagedAddr, "MyStruct*").WithArguments("MyStruct").WithLocation(15, 30), + // (15,43): error CS8377: The type 'V' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'MyStruct' + // public unsafe void M2(MyStruct* ms) { } + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "ms").WithArguments("MyStruct", "T", "V").WithLocation(15, 43)); + } + + [Fact] + public void GenericStructManagedFieldPointer() + { + var code = @" +public struct MyStruct +{ + public T field; +} + +public class C +{ + public unsafe void M() + { + MyStruct myStruct; + M2(&myStruct); + } + + public unsafe void M2(MyStruct* ms) { } +} +"; + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll) + .VerifyDiagnostics( + // (12,12): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('MyStruct') + // M2(&myStruct); + Diagnostic(ErrorCode.ERR_ManagedAddr, "&myStruct").WithArguments("MyStruct").WithLocation(12, 12), + // (15,27): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('MyStruct') + // public unsafe void M2(MyStruct* ms) { } + Diagnostic(ErrorCode.ERR_ManagedAddr, "MyStruct*").WithArguments("MyStruct").WithLocation(15, 27)); + } + + [Fact] + public void UnmanagedRecursiveGenericStruct() + { + var code = @" +public unsafe struct MyStruct where T : unmanaged +{ + public YourStruct* field; +} + +public unsafe struct YourStruct where T : unmanaged +{ + public MyStruct* field; +} +"; + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll) + .VerifyDiagnostics(); + } + + [Fact] + public void UnmanagedRecursiveStruct() + { + var code = @" +public unsafe struct MyStruct +{ + public YourStruct* field; +} + +public unsafe struct YourStruct +{ + public MyStruct* field; +} +"; + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll) + .VerifyDiagnostics(); + } + + [Fact] + public void UnmanagedExpandingTypeArgument() + { + var code = @" +public struct MyStruct +{ + public YourStruct>> field; +} + +public struct YourStruct where T : unmanaged +{ + public T field; +} +"; + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll) + .VerifyDiagnostics( + // (4,46): error CS0523: Struct member 'MyStruct.field' of type 'YourStruct>>' causes a cycle in the struct layout + // public YourStruct>> field; + Diagnostic(ErrorCode.ERR_StructLayoutCycle, "field").WithArguments("MyStruct.field", "YourStruct>>").WithLocation(4, 46)); + } + + [Fact] + public void UnmanagedCyclic() + { + var code = @" +public struct MyStruct +{ + public YourStruct field; +} + +public struct YourStruct where T : unmanaged +{ + public MyStruct field; +} +"; + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll) + .VerifyDiagnostics( + // (4,26): error CS0523: Struct member 'MyStruct.field' of type 'YourStruct' causes a cycle in the struct layout + // public YourStruct field; + Diagnostic(ErrorCode.ERR_StructLayoutCycle, "field").WithArguments("MyStruct.field", "YourStruct").WithLocation(4, 26), + // (4,26): error CS8377: The type 'T' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'YourStruct' + // public YourStruct field; + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "field").WithArguments("YourStruct", "T", "T").WithLocation(4, 26), + // (9,24): error CS0523: Struct member 'YourStruct.field' of type 'MyStruct' causes a cycle in the struct layout + // public MyStruct field; + Diagnostic(ErrorCode.ERR_StructLayoutCycle, "field").WithArguments("YourStruct.field", "MyStruct").WithLocation(9, 24)); + } + + [Fact] + public void UnmanagedExpandingTypeArgumentManagedGenericField() + { + var code = @" +public struct MyStruct +{ + public YourStruct>> field; + public T myField; +} + +public struct YourStruct where T : unmanaged +{ + public T field; +} +"; + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll) + .VerifyDiagnostics( + // (4,46): error CS0523: Struct member 'MyStruct.field' of type 'YourStruct>>' causes a cycle in the struct layout + // public YourStruct>> field; + Diagnostic(ErrorCode.ERR_StructLayoutCycle, "field").WithArguments("MyStruct.field", "YourStruct>>").WithLocation(4, 46)); + } + + [Fact] + public void UnmanagedExpandingTypeArgumentConstraintViolation() + { + var code = @" +public struct MyStruct +{ + public YourStruct>> field; + public string s; +} + +public struct YourStruct where T : unmanaged +{ + public T field; +} +"; + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll) + .VerifyDiagnostics( + // (4,46): error CS0523: Struct member 'MyStruct.field' of type 'YourStruct>>' causes a cycle in the struct layout + // public YourStruct>> field; + Diagnostic(ErrorCode.ERR_StructLayoutCycle, "field").WithArguments("MyStruct.field", "YourStruct>>").WithLocation(4, 46), + // (4,46): error CS8377: The type 'MyStruct>' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'YourStruct' + // public YourStruct>> field; + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "field").WithArguments("YourStruct", "T", "MyStruct>").WithLocation(4, 46)); + } + + [Fact] + public void UnmanagedRecursiveTypeArgumentConstraintViolation_02() + { + var code = @" +public struct MyStruct +{ + public YourStruct>> field; +} + +public struct YourStruct where T : unmanaged +{ + public T field; + public string s; +} +"; + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll) + .VerifyDiagnostics( + // (4,46): error CS0523: Struct member 'MyStruct.field' of type 'YourStruct>>' causes a cycle in the struct layout + // public YourStruct>> field; + Diagnostic(ErrorCode.ERR_StructLayoutCycle, "field").WithArguments("MyStruct.field", "YourStruct>>").WithLocation(4, 46), + // (4,46): error CS8377: The type 'MyStruct>' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'YourStruct' + // public YourStruct>> field; + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "field").WithArguments("YourStruct", "T", "MyStruct>").WithLocation(4, 46)); + } } } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs index 73b27736ed5da..e60482987668a 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs @@ -50121,9 +50121,6 @@ class D // (4,24): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // class B1 where T : A? { } Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(4, 24), - // (21,8): warning CS8631: The type 'A?' cannot be used as type parameter 'T' in the generic type or method 'B4'. Nullability of type argument 'A?' doesn't match constraint type 'A'. - // B4 F9; // 5 and 6 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A?").WithArguments("B4", "A", "T", "A?").WithLocation(21, 8), // (15,9): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // B1 F3; // 2 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(15, 9), @@ -50139,9 +50136,12 @@ class D // (13,9): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // B0 F1; // 1 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(13, 9), - // (35,8): warning CS8631: The type 'A?' cannot be used as type parameter 'T' in the generic type or method 'B4'. Nullability of type argument 'A?' doesn't match constraint type 'A'. + // (21,12): warning CS8631: The type 'A?' cannot be used as type parameter 'T' in the generic type or method 'B4'. Nullability of type argument 'A?' doesn't match constraint type 'A'. + // B4 F9; // 5 and 6 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "F9").WithArguments("B4", "A", "T", "A?").WithLocation(21, 12), + // (35,12): warning CS8631: The type 'A?' cannot be used as type parameter 'T' in the generic type or method 'B4'. Nullability of type argument 'A?' doesn't match constraint type 'A'. // B4 G9; // 7 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A?").WithArguments("B4", "A", "T", "A?").WithLocation(35, 8) + Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "G9").WithArguments("B4", "A", "T", "A?").WithLocation(35, 12) ); } @@ -50213,18 +50213,18 @@ class D // (13,16): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // B0> F1; // 1 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(13, 16), - // (30,8): warning CS8631: The type 'A' cannot be used as type parameter 'T' in the generic type or method 'B1'. Nullability of type argument 'A' doesn't match constraint type 'A'. + // (21,20): warning CS8631: The type 'A' cannot be used as type parameter 'T' in the generic type or method 'B4'. Nullability of type argument 'A' doesn't match constraint type 'A'. + // B4> F9; // 5 and 6 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "F9").WithArguments("B4", "A", "T", "A").WithLocation(21, 20), + // (30,19): warning CS8631: The type 'A' cannot be used as type parameter 'T' in the generic type or method 'B1'. Nullability of type argument 'A' doesn't match constraint type 'A'. // B1> G4; // 7 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A").WithArguments("B1", "A", "T", "A").WithLocation(30, 8), - // (34,8): warning CS8631: The type 'A' cannot be used as type parameter 'T' in the generic type or method 'B3'. Nullability of type argument 'A' doesn't match constraint type 'A'. + Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "G4").WithArguments("B1", "A", "T", "A").WithLocation(30, 19), + // (34,19): warning CS8631: The type 'A' cannot be used as type parameter 'T' in the generic type or method 'B3'. Nullability of type argument 'A' doesn't match constraint type 'A'. // B3> G8; // 8 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A").WithArguments("B3", "A", "T", "A").WithLocation(34, 8), - // (35,8): warning CS8631: The type 'A' cannot be used as type parameter 'T' in the generic type or method 'B4'. Nullability of type argument 'A' doesn't match constraint type 'A'. + Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "G8").WithArguments("B3", "A", "T", "A").WithLocation(34, 19), + // (35,20): warning CS8631: The type 'A' cannot be used as type parameter 'T' in the generic type or method 'B4'. Nullability of type argument 'A' doesn't match constraint type 'A'. // B4> G9; // 9 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A").WithArguments("B4", "A", "T", "A").WithLocation(35, 8), - // (21,8): warning CS8631: The type 'A' cannot be used as type parameter 'T' in the generic type or method 'B4'. Nullability of type argument 'A' doesn't match constraint type 'A'. - // B4> F9; // 5 and 6 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A").WithArguments("B4", "A", "T", "A").WithLocation(21, 8) + Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "G9").WithArguments("B4", "A", "T", "A").WithLocation(35, 20) ); } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs index f033bc3c95fc1..f1b2ea5fdf918 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs @@ -7801,106 +7801,28 @@ unsafe class C I* i; C* c; }"; - CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics( - // (7,5): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('object') - // object* _object; - Diagnostic(ErrorCode.ERR_ManagedAddr, "object*").WithArguments("object"), - // (22,5): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('string') - // string* _string; - Diagnostic(ErrorCode.ERR_ManagedAddr, "string*").WithArguments("string"), - // (26,5): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('int?') - // int?* _nullable; - Diagnostic(ErrorCode.ERR_ManagedAddr, "int?*").WithArguments("int?"), - // (27,5): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('dynamic') - // dynamic* _dynamic; - Diagnostic(ErrorCode.ERR_ManagedAddr, "dynamic*").WithArguments("dynamic"), - // (29,5): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('D') - // D* d; - Diagnostic(ErrorCode.ERR_ManagedAddr, "D*").WithArguments("D"), - // (31,5): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('I') - // I* i; - Diagnostic(ErrorCode.ERR_ManagedAddr, "I*").WithArguments("I"), - // (32,5): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('C') - // C* c; - Diagnostic(ErrorCode.ERR_ManagedAddr, "C*").WithArguments("C"), - // (7,13): warning CS0169: The field 'C._object' is never used - // object* _object; - Diagnostic(ErrorCode.WRN_UnreferencedField, "_object").WithArguments("C._object"), - // (8,11): warning CS0169: The field 'C._void' is never used - // void* _void; - Diagnostic(ErrorCode.WRN_UnreferencedField, "_void").WithArguments("C._void"), - // (9,11): warning CS0169: The field 'C._bool' is never used - // bool* _bool; - Diagnostic(ErrorCode.WRN_UnreferencedField, "_bool").WithArguments("C._bool"), - // (10,11): warning CS0169: The field 'C._char' is never used - // char* _char; - Diagnostic(ErrorCode.WRN_UnreferencedField, "_char").WithArguments("C._char"), - // (11,12): warning CS0169: The field 'C._sbyte' is never used - // sbyte* _sbyte; - Diagnostic(ErrorCode.WRN_UnreferencedField, "_sbyte").WithArguments("C._sbyte"), - // (12,11): warning CS0169: The field 'C._byte' is never used - // byte* _byte; - Diagnostic(ErrorCode.WRN_UnreferencedField, "_byte").WithArguments("C._byte"), - // (13,12): warning CS0169: The field 'C._short' is never used - // short* _short; - Diagnostic(ErrorCode.WRN_UnreferencedField, "_short").WithArguments("C._short"), - // (14,13): warning CS0169: The field 'C._ushort' is never used - // ushort* _ushort; - Diagnostic(ErrorCode.WRN_UnreferencedField, "_ushort").WithArguments("C._ushort"), - // (15,10): warning CS0169: The field 'C._int' is never used - // int* _int; - Diagnostic(ErrorCode.WRN_UnreferencedField, "_int").WithArguments("C._int"), - // (16,11): warning CS0169: The field 'C._uint' is never used - // uint* _uint; - Diagnostic(ErrorCode.WRN_UnreferencedField, "_uint").WithArguments("C._uint"), - // (17,11): warning CS0169: The field 'C._long' is never used - // long* _long; - Diagnostic(ErrorCode.WRN_UnreferencedField, "_long").WithArguments("C._long"), - // (18,12): warning CS0169: The field 'C._ulong' is never used - // ulong* _ulong; - Diagnostic(ErrorCode.WRN_UnreferencedField, "_ulong").WithArguments("C._ulong"), - // (19,14): warning CS0169: The field 'C._decimal' is never used - // decimal* _decimal; - Diagnostic(ErrorCode.WRN_UnreferencedField, "_decimal").WithArguments("C._decimal"), - // (20,12): warning CS0169: The field 'C._float' is never used - // float* _float; - Diagnostic(ErrorCode.WRN_UnreferencedField, "_float").WithArguments("C._float"), - // (21,13): warning CS0169: The field 'C._double' is never used - // double* _double; - Diagnostic(ErrorCode.WRN_UnreferencedField, "_double").WithArguments("C._double"), - // (22,13): warning CS0169: The field 'C._string' is never used - // string* _string; - Diagnostic(ErrorCode.WRN_UnreferencedField, "_string").WithArguments("C._string"), - // (23,20): warning CS0169: The field 'C._intptr' is never used - // System.IntPtr* _intptr; - Diagnostic(ErrorCode.WRN_UnreferencedField, "_intptr").WithArguments("C._intptr"), - // (24,21): warning CS0169: The field 'C._uintptr' is never used - // System.UIntPtr* _uintptr; - Diagnostic(ErrorCode.WRN_UnreferencedField, "_uintptr").WithArguments("C._uintptr"), - // (25,11): warning CS0169: The field 'C._intptr2' is never used - // int** _intptr2; - Diagnostic(ErrorCode.WRN_UnreferencedField, "_intptr2").WithArguments("C._intptr2"), - // (26,11): warning CS0169: The field 'C._nullable' is never used - // int?* _nullable; - Diagnostic(ErrorCode.WRN_UnreferencedField, "_nullable").WithArguments("C._nullable"), - // (27,14): warning CS0169: The field 'C._dynamic' is never used - // dynamic* _dynamic; - Diagnostic(ErrorCode.WRN_UnreferencedField, "_dynamic").WithArguments("C._dynamic"), - // (28,8): warning CS0169: The field 'C.e' is never used - // E* e; - Diagnostic(ErrorCode.WRN_UnreferencedField, "e").WithArguments("C.e"), - // (29,8): warning CS0169: The field 'C.d' is never used - // D* d; - Diagnostic(ErrorCode.WRN_UnreferencedField, "d").WithArguments("C.d"), - // (30,8): warning CS0169: The field 'C.s' is never used - // S* s; - Diagnostic(ErrorCode.WRN_UnreferencedField, "s").WithArguments("C.s"), - // (31,8): warning CS0169: The field 'C.i' is never used - // I* i; - Diagnostic(ErrorCode.WRN_UnreferencedField, "i").WithArguments("C.i"), - // (32,8): warning CS0169: The field 'C.c' is never used - // C* c; - Diagnostic(ErrorCode.WRN_UnreferencedField, "c").WithArguments("C.c")); + CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.UnsafeReleaseDll) + .GetDiagnostics() + .Where(d => d.Severity == DiagnosticSeverity.Error) + .Verify( + // (7,5): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('object') + // object* _object; + Diagnostic(ErrorCode.ERR_ManagedAddr, "object*").WithArguments("object"), + // (22,5): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('string') + // string* _string; + Diagnostic(ErrorCode.ERR_ManagedAddr, "string*").WithArguments("string"), + // (27,5): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('dynamic') + // dynamic* _dynamic; + Diagnostic(ErrorCode.ERR_ManagedAddr, "dynamic*").WithArguments("dynamic"), + // (29,5): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('D') + // D* d; + Diagnostic(ErrorCode.ERR_ManagedAddr, "D*").WithArguments("D"), + // (31,5): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('I') + // I* i; + Diagnostic(ErrorCode.ERR_ManagedAddr, "I*").WithArguments("I"), + // (32,5): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('C') + // C* c; + Diagnostic(ErrorCode.ERR_ManagedAddr, "C*").WithArguments("C")); } [Fact] diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs index ee4e2e69d04f6..fc41d49780bc7 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs @@ -276,28 +276,15 @@ unsafe class C "; var compilation = CreateCompilation(text, options: TestOptions.UnsafeReleaseDll); - compilation.VerifyDiagnostics( - // (8,7): error CS0306: The type 'int*' may not be used as a type argument - Diagnostic(ErrorCode.ERR_BadTypeArgument, "int*").WithArguments("int*"), - // (9,7): error CS0306: The type 'int**' may not be used as a type argument - Diagnostic(ErrorCode.ERR_BadTypeArgument, "int**").WithArguments("int**"), - - // (4,10): warning CS0169: The field 'C.f0' is never used - Diagnostic(ErrorCode.WRN_UnreferencedField, "f0").WithArguments("C.f0"), - // (5,11): warning CS0169: The field 'C.f1' is never used - Diagnostic(ErrorCode.WRN_UnreferencedField, "f1").WithArguments("C.f1"), - // (6,12): warning CS0169: The field 'C.f2' is never used - Diagnostic(ErrorCode.WRN_UnreferencedField, "f2").WithArguments("C.f2"), - // (7,14): warning CS0169: The field 'C.f3' is never used - Diagnostic(ErrorCode.WRN_UnreferencedField, "f3").WithArguments("C.f3"), - // (8,13): warning CS0169: The field 'C.f4' is never used - Diagnostic(ErrorCode.WRN_UnreferencedField, "f4").WithArguments("C.f4"), - // (9,14): warning CS0169: The field 'C.f5' is never used - Diagnostic(ErrorCode.WRN_UnreferencedField, "f5").WithArguments("C.f5"), - // (10,15): warning CS0169: The field 'C.f6' is never used - Diagnostic(ErrorCode.WRN_UnreferencedField, "f6").WithArguments("C.f6"), - // (11,17): warning CS0169: The field 'C.f7' is never used - Diagnostic(ErrorCode.WRN_UnreferencedField, "f7").WithArguments("C.f7")); + compilation.GetDiagnostics() + .Where(d => d.Severity == DiagnosticSeverity.Error) + .Verify( + // (8,13): error CS0306: The type 'int*' may not be used as a type argument + // C f4; + Diagnostic(ErrorCode.ERR_BadTypeArgument, "f4").WithArguments("int*").WithLocation(8, 13), + // (9,14): error CS0306: The type 'int**' may not be used as a type argument + // C f5; + Diagnostic(ErrorCode.ERR_BadTypeArgument, "f5").WithArguments("int**").WithLocation(9, 14)); var type = compilation.GlobalNamespace.GetMember("C"); @@ -2485,13 +2472,15 @@ class C object f1; string f2; System.Collections.IEnumerable f3; - int? f4; } "; var compilation = CreateCompilation(text); var type = compilation.GlobalNamespace.GetMember("C"); - Assert.True(type.GetMembers().OfType().All(field => field.Type.IsManagedType)); + foreach (var field in type.GetMembers().OfType()) + { + Assert.True(field.Type.IsManagedType, field.ToString()); + } } [Fact] @@ -2514,7 +2503,8 @@ class C float f12; double f13; System.IntPtr f14; - System.UIntPtr f14; + System.UIntPtr f15; + int? f16; } "; var compilation = CreateCompilation(text); @@ -2605,11 +2595,11 @@ struct S { } var compilation = CreateCompilation(text); var globalNamespace = compilation.GlobalNamespace; Assert.False(globalNamespace.GetMember("S").IsManagedType); - Assert.True(globalNamespace.GetMember("P").IsManagedType); + Assert.False(globalNamespace.GetMember("P").IsManagedType); Assert.False(globalNamespace.GetMember("C").GetMember("S").IsManagedType); - Assert.True(globalNamespace.GetMember("D").GetMember("S").IsManagedType); + Assert.False(globalNamespace.GetMember("D").GetMember("S").IsManagedType); Assert.False(globalNamespace.GetMember("Q").GetMember("S").IsManagedType); - Assert.True(globalNamespace.GetMember("R").GetMember("S").IsManagedType); + Assert.False(globalNamespace.GetMember("R").GetMember("S").IsManagedType); } [Fact] @@ -2631,8 +2621,10 @@ struct R { } "; var compilation = CreateCompilation(text); var type = compilation.GlobalNamespace.GetMember("C"); - - Assert.True(type.GetMembers().OfType().All(field => field.Type.IsManagedType)); + Assert.False(type.GetMember("f1").Type.IsManagedType); + Assert.False(type.GetMember("f2").Type.IsManagedType); + Assert.True(type.GetMember("f3").Type.IsManagedType); + Assert.True(type.GetMember("f4").Type.IsManagedType); } [Fact] @@ -2831,7 +2823,7 @@ struct W { X>> x; } var compilation = CreateCompilation(text); var globalNamespace = compilation.GlobalNamespace; Assert.True(globalNamespace.GetMember("X").IsManagedType); // because of X.t - Assert.True(globalNamespace.GetMember("W").IsManagedType); + Assert.False(globalNamespace.GetMember("W").IsManagedType); } [Fact] @@ -7851,10 +7843,7 @@ internal struct Struct1 {} unsafe void NMethodCecilNameHelper_Parameter_AllTogether(ref Goo3.Struct1**[][,,] ppi) { } } "; - CreateCompilation(text, options: TestOptions.UnsafeDebugDll).VerifyDiagnostics( - // (8,67): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('C.Goo3.Struct1') - // unsafe void NMethodCecilNameHelper_Parameter_AllTogether(ref Goo3.Struct1**[][,,] ppi) { } - Diagnostic(ErrorCode.ERR_ManagedAddr, "Goo3.Struct1*").WithArguments("C.Goo3.Struct1").WithLocation(8, 67)); + CreateCompilation(text, options: TestOptions.UnsafeDebugDll).VerifyDiagnostics(); } diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/Source/BaseClassTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/Source/BaseClassTests.cs index 7a68bb1bcd1b0..5fbaf394d46cc 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/Source/BaseClassTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/Source/BaseClassTests.cs @@ -1727,21 +1727,21 @@ static void F(I x) public class D : I {} public interface I2 : I {}"; CreateCompilationWithILAndMscorlib40(csharp, il, appendDefaultHeader: false).VerifyDiagnostics( + // (4,26): error CS0648: 'I' is a type not supported by the language + // static void F(I x) + Diagnostic(ErrorCode.ERR_BogusType, "x").WithArguments("I").WithLocation(4, 26), + // (3,26): error CS0648: 'I' is a type not supported by the language + // public static I x; + Diagnostic(ErrorCode.ERR_BogusType, "x").WithArguments("I").WithLocation(3, 26), // (10,14): error CS0648: 'I' is a type not supported by the language // public class D : I {} - Diagnostic(ErrorCode.ERR_BogusType, "D").WithArguments("I"), + Diagnostic(ErrorCode.ERR_BogusType, "D").WithArguments("I").WithLocation(10, 14), // (11,18): error CS0648: 'I' is a type not supported by the language // public interface I2 : I {} - Diagnostic(ErrorCode.ERR_BogusType, "I2").WithArguments("I"), - // (4,26): error CS0648: 'I' is a type not supported by the language - // static void F(I x) - Diagnostic(ErrorCode.ERR_BogusType, "x").WithArguments("I"), - // (3,19): error CS0648: 'I' is a type not supported by the language - // public static I x; - Diagnostic(ErrorCode.ERR_BogusType, "I").WithArguments("I"), + Diagnostic(ErrorCode.ERR_BogusType, "I2").WithArguments("I").WithLocation(11, 18), // (6,9): error CS0648: 'I' is a type not supported by the language // I t = C.x; - Diagnostic(ErrorCode.ERR_BogusType, "I").WithArguments("I") + Diagnostic(ErrorCode.ERR_BogusType, "I").WithArguments("I").WithLocation(6, 9) ); } @@ -1783,13 +1783,13 @@ static void F(I x) CreateCompilationWithILAndMscorlib40(csharp, il, appendDefaultHeader: false, targetFramework: TargetFramework.Standard).VerifyDiagnostics( // (4,30): error CS0648: 'I' is a type not supported by the language // static void F(I x) - Diagnostic(ErrorCode.ERR_BogusType, "x").WithArguments("I"), - // (3,19): error CS0648: 'I' is a type not supported by the language + Diagnostic(ErrorCode.ERR_BogusType, "x").WithArguments("I").WithLocation(4, 30), + // (3,30): error CS0648: 'I' is a type not supported by the language // public static I x; - Diagnostic(ErrorCode.ERR_BogusType, "I").WithArguments("I"), + Diagnostic(ErrorCode.ERR_BogusType, "x").WithArguments("I").WithLocation(3, 30), // (6,9): error CS0648: 'I' is a type not supported by the language // I t = C.x; - Diagnostic(ErrorCode.ERR_BogusType, "I").WithArguments("I") + Diagnostic(ErrorCode.ERR_BogusType, "I").WithArguments("I").WithLocation(6, 9) ); } diff --git a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/ManagedAddressOfTests.cs b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/ManagedAddressOfTests.cs index 54d4f052e18da..3212453a2d89e 100644 --- a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/ManagedAddressOfTests.cs +++ b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/ManagedAddressOfTests.cs @@ -141,10 +141,6 @@ enum E { A } - -struct Generic -{ -} "; var comp = CreateCompilation(source, options: TestOptions.DebugDll); WithRuntimeInstance(comp, runtime => @@ -158,7 +154,6 @@ struct Generic "I", // interface "T", // type parameter "int[]", - "Generic", "dynamic", }; From 7b278f4cf5a33abd8c032a9a9af5873c7a113acc Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Thu, 6 Dec 2018 16:47:58 -0800 Subject: [PATCH 02/40] Add verification test --- .../Semantics/GenericConstraintsTests.cs | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs index 0ab0338c32e53..85ad5e97dcf45 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs @@ -3629,5 +3629,34 @@ public struct YourStruct where T : unmanaged // public YourStruct>> field; Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "field").WithArguments("YourStruct", "T", "MyStruct>").WithLocation(4, 46)); } + + [Fact] + public void NestedGenericStructContainingPointer() + { + var code = @" +public unsafe struct MyStruct where T : unmanaged +{ + public T* field; + + public T this[int index] + { + get { return field[index]; } + } +} + +public class C +{ + public static unsafe void Main() + { + float f = 42.0f; + var ms = new MyStruct { field = &f }; + //var test = new MyStruct> { field = &ms }; + float value = ms[0]; //test[0][0]; + System.Console.Write(value); + } +} +"; + CompileAndVerify(code, options: TestOptions.UnsafeReleaseExe, expectedOutput: "42.0"); + } } } From 7f630dad0068a1b03f4449b849c7747062efb9a7 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Mon, 10 Dec 2018 15:42:37 -0800 Subject: [PATCH 03/40] Skip verification in NestedGenericStructContainingPointer --- .../Test/Semantic/Semantics/GenericConstraintsTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs index 85ad5e97dcf45..be3d9dadf6fd7 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs @@ -3648,15 +3648,15 @@ public class C { public static unsafe void Main() { - float f = 42.0f; + float f = 42; var ms = new MyStruct { field = &f }; - //var test = new MyStruct> { field = &ms }; - float value = ms[0]; //test[0][0]; + var test = new MyStruct> { field = &ms }; + float value = test[0][0]; System.Console.Write(value); } } "; - CompileAndVerify(code, options: TestOptions.UnsafeReleaseExe, expectedOutput: "42.0"); + CompileAndVerify(code, options: TestOptions.UnsafeReleaseExe, expectedOutput: "42", verify: Verification.Skipped); } } } From 97a570e07bdf3f2756e0b5f25c24e26ebbbca6a9 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Mon, 10 Dec 2018 16:23:43 -0800 Subject: [PATCH 04/40] Add SimpleGenericStructPointer_ILValidation --- .../Semantics/GenericConstraintsTests.cs | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs index be3d9dadf6fd7..538b9b90723bc 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs @@ -3658,5 +3658,39 @@ public static unsafe void Main() "; CompileAndVerify(code, options: TestOptions.UnsafeReleaseExe, expectedOutput: "42", verify: Verification.Skipped); } + + [Fact] + public void SimpleGenericStructPointer_ILValidation() + { + var code = @" +public unsafe struct MyStruct where T : unmanaged +{ + public T field; + + public static void Test() + { + var ms = new MyStruct(); + MyStruct* ptr = &ms; + ptr->field = 42; + } +} +"; + var il = @" +{ + // Code size 19 (0x13) + .maxstack 2 + .locals init (MyStruct V_0) //ms + IL_0000: ldloca.s V_0 + IL_0002: initobj ""MyStruct"" + IL_0008: ldloca.s V_0 + IL_000a: conv.u + IL_000b: ldc.i4.s 42 + IL_000d: stfld ""int MyStruct.field"" + IL_0012: ret +} +"; + CompileAndVerify(code, options: TestOptions.UnsafeReleaseDll, verify: Verification.Skipped) + .VerifyIL("MyStruct.Test", il); + } } } From 80f47aa4c8cffa040d710657140710bc7bd43c7a Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Mon, 10 Dec 2018 16:31:50 -0800 Subject: [PATCH 05/40] Add regression test for issue #31439 --- .../Semantics/GenericConstraintsTests.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs index 538b9b90723bc..3c696a9498d18 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs @@ -3692,5 +3692,21 @@ .locals init (MyStruct V_0) //ms CompileAndVerify(code, options: TestOptions.UnsafeReleaseDll, verify: Verification.Skipped) .VerifyIL("MyStruct.Test", il); } + + [Fact] + public void CircularGenericUnmanagedInstantation() + { + var code = @" +public struct X + where T : unmanaged +{ +} + +public struct Z +{ + public X field; +}"; + CreateCompilation(code).VerifyDiagnostics(); + } } } From b7f02508cc33ec543890ba7a354c6cc71384865d Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Mon, 17 Dec 2018 13:01:03 -0800 Subject: [PATCH 06/40] Add tests ensuring CSharp8 language version is required for the feature --- .../Semantics/GenericConstraintsTests.cs | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs index 3c696a9498d18..6366c4df98149 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs @@ -3708,5 +3708,144 @@ public struct Z }"; CreateCompilation(code).VerifyDiagnostics(); } + + [Fact] + public void GenericStructAddressOfRequiresCSharp8() + { + var code = @" +public struct MyStruct +{ + public T field; + + public static unsafe void Test() + { + var ms = new MyStruct(); + var ptr = &ms; + } +} +"; + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular7_3) + .VerifyDiagnostics( + // (9,19): error CS8370: Feature 'unmanaged generic structs' is not available in C# 7.3. Please use language version 8.0 or greater. + // var ptr = &ms; + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "&ms").WithArguments("unmanaged generic structs", "8.0").WithLocation(9, 19) + ); + } + + [Fact] + public void GenericStructFixedRequiresCSharp8() + { + var code = @" +public struct MyStruct +{ + public T field; +} + +public class MyClass +{ + public MyStruct ms; + public static unsafe void Test(MyClass c) + { + fixed (MyStruct* ptr = &c.ms) + { + } + } +} +"; + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular7_3) + .VerifyDiagnostics( + // (12,16): error CS8370: Feature 'unmanaged generic structs' is not available in C# 7.3. Please use language version 8.0 or greater. + // fixed (MyStruct* ptr = &c.ms) + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "MyStruct*").WithArguments("unmanaged generic structs", "8.0").WithLocation(12, 16) + ); + } + + [Fact] + public void GenericStructSizeofRequiresCSharp8() + { + var code = @" +public struct MyStruct +{ + public T field; + + public static unsafe void Test() + { + var size = sizeof(MyStruct); + } +} +"; + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular7_3) + .VerifyDiagnostics( + // (8,27): error CS8370: Feature 'unmanaged generic structs' is not available in C# 7.3. Please use language version 8.0 or greater. + // var size = sizeof(MyStruct); + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "MyStruct").WithArguments("unmanaged generic structs", "8.0").WithLocation(8, 27) + ); + } + + [Fact] + public void GenericImplicitStackallocRequiresCSharp8() + { + var code = @" +public struct MyStruct +{ + public T field; + + public static unsafe void Test() + { + var arr = stackalloc[] { new MyStruct() }; + } +} +"; + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular7_3) + .VerifyDiagnostics( + // (8,27): error CS8370: Feature 'unmanaged generic structs' is not available in C# 7.3. Please use language version 8.0 or greater. + // var size = sizeof(MyStruct); + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "MyStruct").WithArguments("unmanaged generic structs", "8.0").WithLocation(8, 27) + ); + } + + [Fact] + public void GenericStackallocRequiresCSharp8() + { + var code = @" +public struct MyStruct +{ + public T field; + + public static unsafe void Test() + { + var arr = stackalloc MyStruct[4]; + } +} +"; + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular7_3) + .VerifyDiagnostics( + // (8,30): error CS8370: Feature 'unmanaged generic structs' is not available in C# 7.3. Please use language version 8.0 or greater. + // var arr = stackalloc MyStruct[4]; + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "MyStruct").WithArguments("unmanaged generic structs", "8.0").WithLocation(8, 30) + ); + } + + [Fact] + public void GenericStructPointerFieldRequiresCSharp8() + { + var code = @" +public struct MyStruct +{ + public T field; +} + +public unsafe struct OtherStruct +{ + public MyStruct* ms; +} +"; + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular7_3) + .VerifyDiagnostics( + // (9,12): error CS8370: Feature 'unmanaged generic structs' is not available in C# 7.3. Please use language version 8.0 or greater. + // public MyStruct* ms; + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "MyStruct*").WithArguments("unmanaged generic structs", "8.0").WithLocation(9, 12) + ); + } } } From 1f66018acb7a32ff851fa12f3c12851cfb4633d7 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Mon, 17 Dec 2018 13:03:40 -0800 Subject: [PATCH 07/40] Add MessageID.IDS_FeatureUnmanagedGenericStructs --- .../CSharp/Portable/CSharpResources.Designer.cs | 11 ++++++++++- src/Compilers/CSharp/Portable/CSharpResources.resx | 3 +++ src/Compilers/CSharp/Portable/Errors/MessageID.cs | 2 ++ .../CSharp/Portable/xlf/CSharpResources.cs.xlf | 5 +++++ .../CSharp/Portable/xlf/CSharpResources.de.xlf | 5 +++++ .../CSharp/Portable/xlf/CSharpResources.es.xlf | 5 +++++ .../CSharp/Portable/xlf/CSharpResources.fr.xlf | 5 +++++ .../CSharp/Portable/xlf/CSharpResources.it.xlf | 5 +++++ .../CSharp/Portable/xlf/CSharpResources.ja.xlf | 5 +++++ .../CSharp/Portable/xlf/CSharpResources.ko.xlf | 5 +++++ .../CSharp/Portable/xlf/CSharpResources.pl.xlf | 5 +++++ .../CSharp/Portable/xlf/CSharpResources.pt-BR.xlf | 5 +++++ .../CSharp/Portable/xlf/CSharpResources.ru.xlf | 5 +++++ .../CSharp/Portable/xlf/CSharpResources.tr.xlf | 5 +++++ .../CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf | 5 +++++ .../CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf | 5 +++++ 16 files changed, 80 insertions(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs index 350e5e6c0ccee..76338713470f2 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs +++ b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs @@ -19,7 +19,7 @@ namespace Microsoft.CodeAnalysis.CSharp { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class CSharpResources { @@ -11338,6 +11338,15 @@ internal static string IDS_FeatureUnconstrainedTypeParameterInNullCoalescingOper } } + /// + /// Looks up a localized string similar to unmanaged generic structs. + /// + internal static string IDS_FeatureUnmanagedGenericStructs { + get { + return ResourceManager.GetString("IDS_FeatureUnmanagedGenericStructs", resourceCulture); + } + } + /// /// Looks up a localized string similar to unmanaged generic type constraints. /// diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 9e20a01339454..8fb19c4fb1e9e 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -213,6 +213,9 @@ async streams + + unmanaged generic structs + default literal diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs index a28ea45ecbd89..8fde90695fa95 100644 --- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs +++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs @@ -170,6 +170,7 @@ internal enum MessageID IDS_FeatureIndexOperator = MessageBase + 12750, IDS_FeatureRangeOperator = MessageBase + 12751, IDS_FeatureAsyncStreams = MessageBase + 12752, + IDS_FeatureUnmanagedGenericStructs = MessageBase + 12753 } // Message IDs may refer to strings that need to be localized. @@ -243,6 +244,7 @@ internal static LanguageVersion RequiredVersion(this MessageID feature) case MessageID.IDS_FeatureIndexOperator: // semantic check case MessageID.IDS_FeatureRangeOperator: // semantic check case MessageID.IDS_FeatureAsyncStreams: + case MessageID.IDS_FeatureUnmanagedGenericStructs: // semantic check return LanguageVersion.CSharp8; // C# 7.3 features. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 220580c2c942e..5c4c12b6da0ca 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -312,6 +312,11 @@ unconstrained type parameters in null coalescing operator + + unmanaged generic structs + unmanaged generic structs + + unmanaged generic type constraints unmanaged generic type constraints diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index bf76a55bc82dd..6db25ab029607 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -312,6 +312,11 @@ unconstrained type parameters in null coalescing operator + + unmanaged generic structs + unmanaged generic structs + + unmanaged generic type constraints unmanaged generic type constraints diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 5c7daa00f5e6d..361dc32ba773f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -312,6 +312,11 @@ unconstrained type parameters in null coalescing operator + + unmanaged generic structs + unmanaged generic structs + + unmanaged generic type constraints unmanaged generic type constraints diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 7b76f282f9b4d..1f23c563a0b9e 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -312,6 +312,11 @@ unconstrained type parameters in null coalescing operator + + unmanaged generic structs + unmanaged generic structs + + unmanaged generic type constraints unmanaged generic type constraints diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 3d2ccdc565e34..ee77318238337 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -312,6 +312,11 @@ unconstrained type parameters in null coalescing operator + + unmanaged generic structs + unmanaged generic structs + + unmanaged generic type constraints unmanaged generic type constraints diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 63560bb9a650d..c5e731e7b982b 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -312,6 +312,11 @@ unconstrained type parameters in null coalescing operator + + unmanaged generic structs + unmanaged generic structs + + unmanaged generic type constraints unmanaged generic type constraints diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 886dce844012f..ec2e1c06b4996 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -312,6 +312,11 @@ unconstrained type parameters in null coalescing operator + + unmanaged generic structs + unmanaged generic structs + + unmanaged generic type constraints unmanaged generic type constraints diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 43e49f167187d..14525ca514f0d 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -312,6 +312,11 @@ unconstrained type parameters in null coalescing operator + + unmanaged generic structs + unmanaged generic structs + + unmanaged generic type constraints unmanaged generic type constraints diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 330194b769c93..26dfd03b9852b 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -312,6 +312,11 @@ unconstrained type parameters in null coalescing operator + + unmanaged generic structs + unmanaged generic structs + + unmanaged generic type constraints unmanaged generic type constraints diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 9d74c7081d003..60dd097f221b5 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -312,6 +312,11 @@ unconstrained type parameters in null coalescing operator + + unmanaged generic structs + unmanaged generic structs + + unmanaged generic type constraints unmanaged generic type constraints diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 062dd67a4fd17..cebbce34967c7 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -312,6 +312,11 @@ unconstrained type parameters in null coalescing operator + + unmanaged generic structs + unmanaged generic structs + + unmanaged generic type constraints unmanaged generic type constraints diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 159c6ee31f67f..1778ebec165f0 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -312,6 +312,11 @@ unconstrained type parameters in null coalescing operator + + unmanaged generic structs + unmanaged generic structs + + unmanaged generic type constraints unmanaged generic type constraints diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 7ceb647bd594f..ffb19738d1457 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -312,6 +312,11 @@ unconstrained type parameters in null coalescing operator + + unmanaged generic structs + unmanaged generic structs + + unmanaged generic type constraints unmanaged generic type constraints From 80721b4553bb1a0682f41f285a507a1cc877aa29 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Mon, 17 Dec 2018 13:05:19 -0800 Subject: [PATCH 08/40] Update ManagedAddr binder checks to require CSharp8 for unmanaged generic structs --- .../Portable/Binder/Binder_Expressions.cs | 49 ++++++++++++++++--- .../Portable/Binder/Binder_Operators.cs | 19 +++++-- .../Portable/Binder/Binder_Statements.cs | 10 ++++ .../CSharp/Portable/Binder/Binder_Symbols.cs | 13 +++-- 4 files changed, 77 insertions(+), 14 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index 90976e30df0a1..be9f4dbaeebc0 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -1132,10 +1132,23 @@ private BoundExpression BindSizeOf(SizeOfExpressionSyntax node, DiagnosticBag di bool typeHasErrors = type.IsErrorType(); - if (!typeHasErrors && type.IsManagedType) + if (!typeHasErrors) { - diagnostics.Add(ErrorCode.ERR_ManagedAddr, node.Location, type); - typeHasErrors = true; + if (type.IsManagedType) + { + diagnostics.Add(ErrorCode.ERR_ManagedAddr, typeSyntax.Location, type); + typeHasErrors = true; + } + else if (type.GetArity() != 0) + { + var unsupported = Compilation.LanguageVersion < MessageID.IDS_FeatureUnmanagedGenericStructs.RequiredVersion(); + if (unsupported) + { + // PROTOTYPE + MessageID.IDS_FeatureUnmanagedGenericStructs.CheckFeatureAvailability(Compilation.LanguageVersion, diagnostics, typeSyntax.Location); + typeHasErrors = true; + } + } } BoundTypeExpression boundType = new BoundTypeExpression(typeSyntax, alias, type, typeHasErrors); @@ -2870,9 +2883,16 @@ private BoundExpression BindImplicitStackAllocArrayCreationExpression(ImplicitSt bestType = CreateErrorType(); } - if (!bestType.IsErrorType() && bestType.IsManagedType) + if (!bestType.IsErrorType()) { - Error(diagnostics, ErrorCode.ERR_ManagedAddr, node, bestType); + if (bestType.IsManagedType) + { + Error(diagnostics, ErrorCode.ERR_ManagedAddr, node, bestType); + } + else if (bestType.GetArity() != 0) + { + MessageID.IDS_FeatureUnmanagedGenericStructs.CheckFeatureAvailability(Compilation.LanguageVersion, diagnostics, node.Location); + } } return BindStackAllocWithInitializer( @@ -3223,10 +3243,23 @@ private BoundExpression BindStackAllocArrayCreationExpression( var elementType = BindType(elementTypeSyntax, diagnostics); TypeSymbol type = GetStackAllocType(node, elementType, diagnostics, out bool hasErrors); - if (!elementType.IsErrorType() && elementType.IsManagedType) + if (!elementType.IsErrorType()) { - Error(diagnostics, ErrorCode.ERR_ManagedAddr, elementTypeSyntax, elementType.TypeSymbol); - hasErrors = true; + if (elementType.IsManagedType) + { + Error(diagnostics, ErrorCode.ERR_ManagedAddr, elementTypeSyntax, elementType.TypeSymbol); + hasErrors = true; + } + else if (elementType.TypeSymbol.GetArity() != 0) + { + var unsupported = Compilation.LanguageVersion < MessageID.IDS_FeatureUnmanagedGenericStructs.RequiredVersion(); + if (unsupported) + { + // PROTOTYPE + MessageID.IDS_FeatureUnmanagedGenericStructs.CheckFeatureAvailability(Compilation.LanguageVersion, diagnostics, elementTypeSyntax.Location); + hasErrors = true; + } + } } SyntaxList rankSpecifiers = arrayTypeSyntax.RankSpecifiers; diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs index fac79146f0a33..47bdc6b12ffaf 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs @@ -2131,10 +2131,23 @@ private BoundExpression BindAddressOfExpression(PrefixUnaryExpressionSyntax node bool allowManagedAddressOf = Flags.Includes(BinderFlags.AllowManagedAddressOf); if (!allowManagedAddressOf) { - if (!hasErrors && isManagedType) + if (!hasErrors) { - hasErrors = true; - Error(diagnostics, ErrorCode.ERR_ManagedAddr, node, operandType); + if (isManagedType) + { + hasErrors = true; + Error(diagnostics, ErrorCode.ERR_ManagedAddr, node, operandType); + } + else if (operandType.GetArity() != 0) + { + var supported = MessageID.IDS_FeatureUnmanagedGenericStructs.RequiredVersion() >= Compilation.LanguageVersion; + if (!supported) + { + // PROTOTYPE + MessageID.IDS_FeatureUnmanagedGenericStructs.CheckFeatureAvailability(Compilation.LanguageVersion, diagnostics, node.Location); + hasErrors = true; + } + } } if (!hasErrors) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs index 4a8ff5348bebf..9b4f29e30cf40 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs @@ -1167,6 +1167,16 @@ private bool IsValidFixedVariableInitializer(TypeSymbol declType, SourceLocalSym Error(diagnostics, ErrorCode.ERR_ManagedAddr, initializerSyntax, elementType); hasErrors = true; } + else if (elementType.GetArity() != 0) + { + var supported = MessageID.IDS_FeatureUnmanagedGenericStructs.RequiredVersion() >= Compilation.LanguageVersion; + if (!supported) + { + // PROTOTYPE + MessageID.IDS_FeatureUnmanagedGenericStructs.CheckFeatureAvailability(Compilation.LanguageVersion, diagnostics, initializerSyntax.Location); + hasErrors = true; + } + } initializerOpt = GetFixedLocalCollectionInitializer(initializerOpt, elementType, declType, fixedPatternMethod, hasErrors, diagnostics); return true; diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs index e804c3918a752..62a634a279ed3 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs @@ -465,10 +465,17 @@ internal NamespaceOrTypeOrAliasSymbolWithAnnotations BindNamespaceOrTypeOrAliasS // Invalid constraint type. A type used as a constraint must be an interface, a non-sealed class or a type parameter. Error(diagnostics, ErrorCode.ERR_BadConstraintType, node); } - else if (elementType.IsManagedType) + else { - // "Cannot take the address of, get the size of, or declare a pointer to a managed type ('{0}')" - Error(diagnostics, ErrorCode.ERR_ManagedAddr, node, elementType.TypeSymbol); + if (elementType.IsManagedType) + { + // "Cannot take the address of, get the size of, or declare a pointer to a managed type ('{0}')" + Error(diagnostics, ErrorCode.ERR_ManagedAddr, node, elementType.TypeSymbol); + } + else if (elementType.TypeSymbol.GetArity() != 0) + { + MessageID.IDS_FeatureUnmanagedGenericStructs.CheckFeatureAvailability(Compilation.LanguageVersion, diagnostics, syntax.Location); + } } return TypeSymbolWithAnnotations.Create(new PointerTypeSymbol(elementType)); From b0c39b5342a357779a4bf95621a2bb0937e88e7a Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Wed, 19 Dec 2018 11:19:59 -0800 Subject: [PATCH 09/40] Fix sizeof error location --- .../CSharp/Portable/Binder/Binder_Expressions.cs | 4 ++-- .../Test/Semantic/Semantics/GenericConstraintsTests.cs | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index be9f4dbaeebc0..f5d4f5d0a3a10 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -1136,7 +1136,7 @@ private BoundExpression BindSizeOf(SizeOfExpressionSyntax node, DiagnosticBag di { if (type.IsManagedType) { - diagnostics.Add(ErrorCode.ERR_ManagedAddr, typeSyntax.Location, type); + diagnostics.Add(ErrorCode.ERR_ManagedAddr, node.Location, type); typeHasErrors = true; } else if (type.GetArity() != 0) @@ -1145,7 +1145,7 @@ private BoundExpression BindSizeOf(SizeOfExpressionSyntax node, DiagnosticBag di if (unsupported) { // PROTOTYPE - MessageID.IDS_FeatureUnmanagedGenericStructs.CheckFeatureAvailability(Compilation.LanguageVersion, diagnostics, typeSyntax.Location); + MessageID.IDS_FeatureUnmanagedGenericStructs.CheckFeatureAvailability(Compilation.LanguageVersion, diagnostics, node.Location); typeHasErrors = true; } } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs index 6366c4df98149..201dce0c0aac0 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs @@ -3776,9 +3776,9 @@ public static unsafe void Test() "; CreateCompilation(code, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular7_3) .VerifyDiagnostics( - // (8,27): error CS8370: Feature 'unmanaged generic structs' is not available in C# 7.3. Please use language version 8.0 or greater. + // (8,20): error CS8370: Feature 'unmanaged generic structs' is not available in C# 7.3. Please use language version 8.0 or greater. // var size = sizeof(MyStruct); - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "MyStruct").WithArguments("unmanaged generic structs", "8.0").WithLocation(8, 27) + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "sizeof(MyStruct)").WithArguments("unmanaged generic structs", "8.0").WithLocation(8, 20) ); } @@ -3798,9 +3798,9 @@ public static unsafe void Test() "; CreateCompilation(code, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular7_3) .VerifyDiagnostics( - // (8,27): error CS8370: Feature 'unmanaged generic structs' is not available in C# 7.3. Please use language version 8.0 or greater. - // var size = sizeof(MyStruct); - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "MyStruct").WithArguments("unmanaged generic structs", "8.0").WithLocation(8, 27) + // (8,19): error CS8370: Feature 'unmanaged generic structs' is not available in C# 7.3. Please use language version 8.0 or greater. + // var arr = stackalloc[] { new MyStruct() }; + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "stackalloc[] { new MyStruct() }").WithArguments("unmanaged generic structs", "8.0").WithLocation(8, 19) ); } From d5697c6ff8482374cc92484395c02b66f7c7ce90 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Wed, 19 Dec 2018 11:21:42 -0800 Subject: [PATCH 10/40] Fix supported feature check for AddressOf --- src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs index 47bdc6b12ffaf..735c1205eb7ca 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs @@ -2140,8 +2140,8 @@ private BoundExpression BindAddressOfExpression(PrefixUnaryExpressionSyntax node } else if (operandType.GetArity() != 0) { - var supported = MessageID.IDS_FeatureUnmanagedGenericStructs.RequiredVersion() >= Compilation.LanguageVersion; - if (!supported) + var unsupported = Compilation.LanguageVersion < MessageID.IDS_FeatureUnmanagedGenericStructs.RequiredVersion(); + if (unsupported) { // PROTOTYPE MessageID.IDS_FeatureUnmanagedGenericStructs.CheckFeatureAvailability(Compilation.LanguageVersion, diagnostics, node.Location); From 1d694ad0541c59815fc6b691f8230c4b5ff077c6 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Wed, 19 Dec 2018 11:47:19 -0800 Subject: [PATCH 11/40] Add simple ref struct test --- .../Semantics/GenericConstraintsTests.cs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs index 201dce0c0aac0..76bf055d9710d 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs @@ -3847,5 +3847,31 @@ public unsafe struct OtherStruct Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "MyStruct*").WithArguments("unmanaged generic structs", "8.0").WithLocation(9, 12) ); } + + [Fact] + public void GenericRefStructAddressOf() + { + var code = @" +public ref struct MyStruct +{ + public T field; +} + +public class MyClass +{ + public static unsafe void Main() + { + var ms = new MyStruct() { field = 42 }; + var ptr = &ms; + System.Console.Write(ptr->field); + } +} +"; + + CompileAndVerify(code, + options: TestOptions.UnsafeReleaseExe, + verify: Verification.Skipped, + expectedOutput: "42"); + } } } From 777365012987db16741033c16fe328499b5e5152 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Wed, 19 Dec 2018 12:32:53 -0800 Subject: [PATCH 12/40] Add simple fixed statement tests for generic structs --- .../Semantics/GenericConstraintsTests.cs | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs index 76bf055d9710d..4a2f6c0bcf058 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs @@ -3873,5 +3873,63 @@ public static unsafe void Main() verify: Verification.Skipped, expectedOutput: "42"); } + + [Fact] + public void GenericStructFixedStatement() + { + var code = @" +public struct MyStruct +{ + public T field; +} + +public class MyClass +{ + public MyStruct ms; + public static unsafe void Main() + { + var c = new MyClass(); + c.ms.field = 42; + fixed (MyStruct* ptr = &c.ms) + { + System.Console.Write(ptr->field); + } + } +} +"; + + CompileAndVerify(code, + options: TestOptions.UnsafeReleaseExe, + verify: Verification.Skipped, + expectedOutput: "42"); + } + + [Fact] + public void GenericStructLocalFixedStatement() + { + var code = @" +public struct MyStruct +{ + public T field; +} + +public class MyClass +{ + public static unsafe void Main() + { + var ms = new MyStruct(); + fixed (int* ptr = &ms.field) + { + } + } +} +"; + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll) + .VerifyDiagnostics( + // (12,27): error CS0213: You cannot use the fixed statement to take the address of an already fixed expression + // fixed (int* ptr = &ms.field) + Diagnostic(ErrorCode.ERR_FixedNotNeeded, "&ms.field").WithLocation(12, 27) + ); + } } } From 361b608ebbce1e8ad2295ac05f079cd41ae0044e Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Wed, 19 Dec 2018 12:35:59 -0800 Subject: [PATCH 13/40] Add IsManagedType_GenericStruct test --- .../Test/Semantic/Semantics/UnsafeTests.cs | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs index fc41d49780bc7..c585f5540e410 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs @@ -2623,10 +2623,31 @@ struct R { } var type = compilation.GlobalNamespace.GetMember("C"); Assert.False(type.GetMember("f1").Type.IsManagedType); Assert.False(type.GetMember("f2").Type.IsManagedType); - Assert.True(type.GetMember("f3").Type.IsManagedType); + Assert.True(type.GetMember("f3").Type.IsManagedType); // is managed due to being ErrorType due to protection level (CS0169) Assert.True(type.GetMember("f4").Type.IsManagedType); } + [Fact] + public void IsManagedType_GenericStruct() + { + var text = @" +class C +{ + S f1; + S f2; +} + +struct S +{ + T field; +} +"; + var compilation = CreateCompilation(text); + var type = compilation.GlobalNamespace.GetMember("C"); + Assert.True(type.GetMember("f1").Type.IsManagedType); + Assert.False(type.GetMember("f2").Type.IsManagedType); + } + [Fact] public void IsManagedType_NonEmptyStruct() { From cb9e361cd9faa2bf93df00018ccdd426cbe18bd1 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Thu, 20 Dec 2018 13:06:52 -0800 Subject: [PATCH 14/40] Allow multiple feature diagnostics for generic struct fixed statement --- .../Test/Semantic/Semantics/GenericConstraintsTests.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs index 4a2f6c0bcf058..7bccc4931b961 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs @@ -3756,7 +3756,10 @@ public static unsafe void Test(MyClass c) .VerifyDiagnostics( // (12,16): error CS8370: Feature 'unmanaged generic structs' is not available in C# 7.3. Please use language version 8.0 or greater. // fixed (MyStruct* ptr = &c.ms) - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "MyStruct*").WithArguments("unmanaged generic structs", "8.0").WithLocation(12, 16) + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "MyStruct*").WithArguments("unmanaged generic structs", "8.0").WithLocation(12, 16), + // (12,37): error CS8370: Feature 'unmanaged generic structs' is not available in C# 7.3. Please use language version 8.0 or greater. + // fixed (MyStruct* ptr = &c.ms) + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "&c.ms").WithArguments("unmanaged generic structs", "8.0").WithLocation(12, 37) ); } From 994ca3544f8bbe7463071d05dd7d9b4492284f87 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Thu, 20 Dec 2018 13:13:13 -0800 Subject: [PATCH 15/40] Add IsManagedType_GenericStruct_ErrorTypeArg test --- .../Test/Semantic/Semantics/UnsafeTests.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs index c585f5540e410..d7287ddae11c8 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs @@ -2648,6 +2648,25 @@ struct S Assert.False(type.GetMember("f2").Type.IsManagedType); } + [Fact] + public void IsManagedType_GenericStruct_ErrorTypeArg() + { + var text = @" +class C +{ + S f1; +} + +struct S +{ + T field; +} +"; + var compilation = CreateCompilation(text); + var type = compilation.GlobalNamespace.GetMember("C"); + Assert.True(type.GetMember("f1").Type.IsManagedType); + } + [Fact] public void IsManagedType_NonEmptyStruct() { From 6c744197dacafb3f900780479fdc44e9c3b2ba43 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Thu, 20 Dec 2018 13:30:21 -0800 Subject: [PATCH 16/40] Simplify most FeatureUnmanagedGenericStructs.CheckFeatureAvailability calls --- .../CSharp/Portable/Binder/Binder_Expressions.cs | 16 ++-------------- .../CSharp/Portable/Binder/Binder_Operators.cs | 8 +------- 2 files changed, 3 insertions(+), 21 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index f5d4f5d0a3a10..d3fc7fa5f663f 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -1141,13 +1141,7 @@ private BoundExpression BindSizeOf(SizeOfExpressionSyntax node, DiagnosticBag di } else if (type.GetArity() != 0) { - var unsupported = Compilation.LanguageVersion < MessageID.IDS_FeatureUnmanagedGenericStructs.RequiredVersion(); - if (unsupported) - { - // PROTOTYPE - MessageID.IDS_FeatureUnmanagedGenericStructs.CheckFeatureAvailability(Compilation.LanguageVersion, diagnostics, node.Location); - typeHasErrors = true; - } + MessageID.IDS_FeatureUnmanagedGenericStructs.CheckFeatureAvailability(Compilation.LanguageVersion, diagnostics, node.Location); } } @@ -3252,13 +3246,7 @@ private BoundExpression BindStackAllocArrayCreationExpression( } else if (elementType.TypeSymbol.GetArity() != 0) { - var unsupported = Compilation.LanguageVersion < MessageID.IDS_FeatureUnmanagedGenericStructs.RequiredVersion(); - if (unsupported) - { - // PROTOTYPE - MessageID.IDS_FeatureUnmanagedGenericStructs.CheckFeatureAvailability(Compilation.LanguageVersion, diagnostics, elementTypeSyntax.Location); - hasErrors = true; - } + MessageID.IDS_FeatureUnmanagedGenericStructs.CheckFeatureAvailability(Compilation.LanguageVersion, diagnostics, elementTypeSyntax.Location); } } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs index 735c1205eb7ca..be02df34c3099 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs @@ -2140,13 +2140,7 @@ private BoundExpression BindAddressOfExpression(PrefixUnaryExpressionSyntax node } else if (operandType.GetArity() != 0) { - var unsupported = Compilation.LanguageVersion < MessageID.IDS_FeatureUnmanagedGenericStructs.RequiredVersion(); - if (unsupported) - { - // PROTOTYPE - MessageID.IDS_FeatureUnmanagedGenericStructs.CheckFeatureAvailability(Compilation.LanguageVersion, diagnostics, node.Location); - hasErrors = true; - } + MessageID.IDS_FeatureUnmanagedGenericStructs.CheckFeatureAvailability(Compilation.LanguageVersion, diagnostics, node.Location); } } From 9405b94d976b93ca77a0f0b946b23539fc3fe862 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Mon, 31 Dec 2018 13:27:20 -0800 Subject: [PATCH 17/40] Add tests for array of generic struct as fixed initializer --- .../Test/Semantic/Semantics/UnsafeTests.cs | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs index d7287ddae11c8..0715e41748b9d 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs @@ -6637,6 +6637,60 @@ unsafe static void Main() Diagnostic(ErrorCode.ERR_ManagedAddr, "a").WithArguments("string")); } + [Fact] + public void NormalInitializerType_ArrayOfGenericStruct8() + { + var text = @" +public struct MyStruct +{ + public T field; +} + +class Program +{ + unsafe static void Main() + { + var a = new MyStruct[2]; + a[0].field = 42; + + fixed (MyStruct* p = a) + { + System.Console.Write(p->field); + } + } +} +"; + CompileAndVerify(text, options: TestOptions.UnsafeReleaseExe, verify: Verification.Skipped, expectedOutput: "42"); + } + + [Fact] + public void NormalInitializerType_ArrayOfGenericStruct_RequiresCSharp8() + { + var text = @" +public struct MyStruct +{ + public T field; +} + +class Program +{ + unsafe static void Main() + { + var a = new MyStruct[2]; + + fixed (void* p = a) + { + } + } +} +"; + CreateCompilation(text, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular7_3).VerifyDiagnostics( + // (13,26): error CS8370: Feature 'unmanaged generic structs' is not available in C# 7.3. Please use language version 8.0 or greater. + // fixed (void* p = a) + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "a").WithArguments("unmanaged generic structs", "8.0").WithLocation(13, 26) + ); + } + [Fact] public void NormalInitializerType_Array() { From 7dc214221a973e8789fc383d69a9ee5b650a367f Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Mon, 31 Dec 2018 13:40:25 -0800 Subject: [PATCH 18/40] Quick fix for fixed initializers of array of generic struct --- src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs index 9b4f29e30cf40..1241dea86e7bd 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs @@ -1169,8 +1169,8 @@ private bool IsValidFixedVariableInitializer(TypeSymbol declType, SourceLocalSym } else if (elementType.GetArity() != 0) { - var supported = MessageID.IDS_FeatureUnmanagedGenericStructs.RequiredVersion() >= Compilation.LanguageVersion; - if (!supported) + var unsupported = MessageID.IDS_FeatureUnmanagedGenericStructs.RequiredVersion() > Compilation.LanguageVersion; + if (unsupported) { // PROTOTYPE MessageID.IDS_FeatureUnmanagedGenericStructs.CheckFeatureAvailability(Compilation.LanguageVersion, diagnostics, initializerSyntax.Location); From ffcd0d9fb9309db043cb8961728f6a0d3393cbcb Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Wed, 2 Jan 2019 14:41:51 -0800 Subject: [PATCH 19/40] Use Binder CheckFeatureAvailability for simplicity. Set hasErrors based on feature checks as needed. --- src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs | 6 +++++- src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs | 6 ++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs index be02df34c3099..f0e5e8ac5c625 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs @@ -2140,7 +2140,11 @@ private BoundExpression BindAddressOfExpression(PrefixUnaryExpressionSyntax node } else if (operandType.GetArity() != 0) { - MessageID.IDS_FeatureUnmanagedGenericStructs.CheckFeatureAvailability(Compilation.LanguageVersion, diagnostics, node.Location); + var supported = CheckFeatureAvailability(node, MessageID.IDS_FeatureUnmanagedGenericStructs, diagnostics); + if (!supported) + { + hasErrors = true; + } } } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs index 1241dea86e7bd..7ef55f410ae3a 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs @@ -1169,11 +1169,9 @@ private bool IsValidFixedVariableInitializer(TypeSymbol declType, SourceLocalSym } else if (elementType.GetArity() != 0) { - var unsupported = MessageID.IDS_FeatureUnmanagedGenericStructs.RequiredVersion() > Compilation.LanguageVersion; - if (unsupported) + var supported = CheckFeatureAvailability(initializerSyntax, MessageID.IDS_FeatureUnmanagedGenericStructs, diagnostics); + if (!supported) { - // PROTOTYPE - MessageID.IDS_FeatureUnmanagedGenericStructs.CheckFeatureAvailability(Compilation.LanguageVersion, diagnostics, initializerSyntax.Location); hasErrors = true; } } From 597b7e96f7700c2eab3eba4bc3d213595553041b Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Wed, 2 Jan 2019 15:45:01 -0800 Subject: [PATCH 20/40] Add CheckManagedAddr helper --- .../Portable/Binder/Binder_Expressions.cs | 51 ++++++++----------- .../Portable/Binder/Binder_Operators.cs | 14 +---- .../Portable/Binder/Binder_Statements.cs | 11 +--- .../CSharp/Portable/Binder/Binder_Symbols.cs | 10 +--- 4 files changed, 23 insertions(+), 63 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index d3fc7fa5f663f..2073afac239fc 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -1130,20 +1130,7 @@ private BoundExpression BindSizeOf(SizeOfExpressionSyntax node, DiagnosticBag di AliasSymbol alias; TypeSymbol type = this.BindType(typeSyntax, diagnostics, out alias).TypeSymbol; - bool typeHasErrors = type.IsErrorType(); - - if (!typeHasErrors) - { - if (type.IsManagedType) - { - diagnostics.Add(ErrorCode.ERR_ManagedAddr, node.Location, type); - typeHasErrors = true; - } - else if (type.GetArity() != 0) - { - MessageID.IDS_FeatureUnmanagedGenericStructs.CheckFeatureAvailability(Compilation.LanguageVersion, diagnostics, node.Location); - } - } + bool typeHasErrors = type.IsErrorType() || CheckManagedAddr(type, node, diagnostics); BoundTypeExpression boundType = new BoundTypeExpression(typeSyntax, alias, type, typeHasErrors); ConstantValue constantValue = GetConstantSizeOf(type); @@ -1152,6 +1139,23 @@ private BoundExpression BindSizeOf(SizeOfExpressionSyntax node, DiagnosticBag di this.GetSpecialType(SpecialType.System_Int32, diagnostics, node), hasErrors); } + /// true if managed type-related errors were found, otherwise false. + private static bool CheckManagedAddr(TypeSymbol type, SyntaxNode node, DiagnosticBag diagnostics) + { + if (type.IsManagedType) + { + diagnostics.Add(ErrorCode.ERR_ManagedAddr, node.Location, type); + return true; + } + else if (type.GetArity() != 0) + { + var supported = CheckFeatureAvailability(node, MessageID.IDS_FeatureUnmanagedGenericStructs, diagnostics); + return !supported; + } + + return false; + } + internal static ConstantValue GetConstantSizeOf(TypeSymbol type) { return ConstantValue.CreateSizeOf((type.GetEnumUnderlyingType() ?? type).SpecialType); @@ -2879,14 +2883,7 @@ private BoundExpression BindImplicitStackAllocArrayCreationExpression(ImplicitSt if (!bestType.IsErrorType()) { - if (bestType.IsManagedType) - { - Error(diagnostics, ErrorCode.ERR_ManagedAddr, node, bestType); - } - else if (bestType.GetArity() != 0) - { - MessageID.IDS_FeatureUnmanagedGenericStructs.CheckFeatureAvailability(Compilation.LanguageVersion, diagnostics, node.Location); - } + CheckManagedAddr(bestType, node, diagnostics); } return BindStackAllocWithInitializer( @@ -3239,15 +3236,7 @@ private BoundExpression BindStackAllocArrayCreationExpression( TypeSymbol type = GetStackAllocType(node, elementType, diagnostics, out bool hasErrors); if (!elementType.IsErrorType()) { - if (elementType.IsManagedType) - { - Error(diagnostics, ErrorCode.ERR_ManagedAddr, elementTypeSyntax, elementType.TypeSymbol); - hasErrors = true; - } - else if (elementType.TypeSymbol.GetArity() != 0) - { - MessageID.IDS_FeatureUnmanagedGenericStructs.CheckFeatureAvailability(Compilation.LanguageVersion, diagnostics, elementTypeSyntax.Location); - } + hasErrors = hasErrors || CheckManagedAddr(elementType.TypeSymbol, elementTypeSyntax, diagnostics); } SyntaxList rankSpecifiers = arrayTypeSyntax.RankSpecifiers; diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs index f0e5e8ac5c625..7ef220b53f562 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs @@ -2133,19 +2133,7 @@ private BoundExpression BindAddressOfExpression(PrefixUnaryExpressionSyntax node { if (!hasErrors) { - if (isManagedType) - { - hasErrors = true; - Error(diagnostics, ErrorCode.ERR_ManagedAddr, node, operandType); - } - else if (operandType.GetArity() != 0) - { - var supported = CheckFeatureAvailability(node, MessageID.IDS_FeatureUnmanagedGenericStructs, diagnostics); - if (!supported) - { - hasErrors = true; - } - } + hasErrors = CheckManagedAddr(operandType, node, diagnostics); } if (!hasErrors) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs index 7ef55f410ae3a..2b4debd7cae85 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs @@ -1162,19 +1162,10 @@ private bool IsValidFixedVariableInitializer(TypeSymbol declType, SourceLocalSym } } - if (elementType.IsManagedType) + if (CheckManagedAddr(elementType, initializerSyntax, diagnostics)) { - Error(diagnostics, ErrorCode.ERR_ManagedAddr, initializerSyntax, elementType); hasErrors = true; } - else if (elementType.GetArity() != 0) - { - var supported = CheckFeatureAvailability(initializerSyntax, MessageID.IDS_FeatureUnmanagedGenericStructs, diagnostics); - if (!supported) - { - hasErrors = true; - } - } initializerOpt = GetFixedLocalCollectionInitializer(initializerOpt, elementType, declType, fixedPatternMethod, hasErrors, diagnostics); return true; diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs index 62a634a279ed3..17132bfe688d9 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs @@ -467,15 +467,7 @@ internal NamespaceOrTypeOrAliasSymbolWithAnnotations BindNamespaceOrTypeOrAliasS } else { - if (elementType.IsManagedType) - { - // "Cannot take the address of, get the size of, or declare a pointer to a managed type ('{0}')" - Error(diagnostics, ErrorCode.ERR_ManagedAddr, node, elementType.TypeSymbol); - } - else if (elementType.TypeSymbol.GetArity() != 0) - { - MessageID.IDS_FeatureUnmanagedGenericStructs.CheckFeatureAvailability(Compilation.LanguageVersion, diagnostics, syntax.Location); - } + CheckManagedAddr(elementType.TypeSymbol, node, diagnostics); } return TypeSymbolWithAnnotations.Create(new PointerTypeSymbol(elementType)); From 99a53026cb5cbcda4f95abb0b5c767ddf5b52176 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Wed, 2 Jan 2019 17:13:08 -0800 Subject: [PATCH 21/40] Add partial reproducer for #32103 --- .../Semantics/GenericConstraintsTests.cs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs index 7bccc4931b961..e8c45876b14cc 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs @@ -3851,6 +3851,32 @@ public unsafe struct OtherStruct ); } + [Fact] + public void StructContainingTuple_Pointer_RequiresCSharp8() + { + var code = @" +public struct MyStruct +{ + public (int, int) field; +} + +public class C +{ + public unsafe void M() where T : unmanaged { var t = default(T); var ptr = &t; } + + public void M2() + { + M(); + } +} +"; + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular7_3) + .VerifyDiagnostics( + // PROTOTYPE: placeholder while we figure out how to get the compiler to produce the error in this context + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "MyStruct") + ); + } + [Fact] public void GenericRefStructAddressOf() { From f6f8498f3a209a881b8852ea73e97edeecdc9d8b Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Wed, 2 Jan 2019 17:14:41 -0800 Subject: [PATCH 22/40] Add feature availability checks when using a generic struct as an unmanaged type argument --- .../Portable/Symbols/ConstraintsHelper.cs | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs b/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs index e6c57c5ab180b..ae258e6ea8701 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs @@ -905,11 +905,27 @@ private static bool CheckConstraints( } } - if (typeParameter.HasUnmanagedTypeConstraint && (typeArgument.IsManagedType || !typeArgument.TypeSymbol.IsNonNullableValueType())) + if (typeParameter.HasUnmanagedTypeConstraint) { - // "The type '{2}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}'" - diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, containingSymbol.ConstructedFrom(), typeParameter, typeArgument.TypeSymbol))); - return false; + if (typeArgument.IsManagedType || !typeArgument.TypeSymbol.IsNonNullableValueType()) + { + // "The type '{2}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}'" + diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, containingSymbol.ConstructedFrom(), typeParameter, typeArgument.TypeSymbol))); + return false; + } + else if (typeArgument.TypeSymbol.GetArity() > 0 && + currentCompilation is CSharpCompilation csCompilation && + csCompilation.LanguageVersion < MessageID.IDS_FeatureUnmanagedGenericStructs.RequiredVersion()) + { + var diagnostics = DiagnosticBag.GetInstance(); + MessageID.IDS_FeatureUnmanagedGenericStructs.CheckFeatureAvailability(csCompilation.LanguageVersion, diagnostics, typeArgument.TypeSymbol.Locations[0]); + foreach (var diagnostic in diagnostics.AsEnumerable()) + { + // PROTOTYPE + var typeParameterDiagnostic = new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo((ErrorCode) diagnostic.Code, diagnostic.Arguments)); + diagnosticsBuilder.Add(typeParameterDiagnostic); + } + } } if (typeParameter.HasValueTypeConstraint && !typeArgument.TypeSymbol.IsNonNullableValueType()) From 9b1187e41399eba8ef4ff363d6a70b6e5161264c Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Thu, 3 Jan 2019 16:06:33 -0800 Subject: [PATCH 23/40] Add ManagedKind property on TypeSymbol --- .../Portable/Binder/Binder_Expressions.cs | 5 +- .../Portable/Symbols/ArrayTypeSymbol.cs | 4 +- .../Portable/Symbols/BaseTypeAnalysis.cs | 57 ++++++++++++------- .../Portable/Symbols/ConstraintsHelper.cs | 7 ++- .../Portable/Symbols/DynamicTypeSymbol.cs | 4 +- .../Portable/Symbols/NamedTypeSymbol.cs | 4 +- .../Portable/Symbols/PointerTypeSymbol.cs | 8 +-- .../Source/SourceMemberContainerSymbol.cs | 30 +++++----- .../SynthesizedEmbeddedAttributeSymbol.cs | 2 +- .../Symbols/Tuples/TupleTypeSymbol.cs | 4 +- .../Portable/Symbols/TypeParameterSymbol.cs | 6 +- .../CSharp/Portable/Symbols/TypeSymbol.cs | 5 +- .../Semantics/GenericConstraintsTests.cs | 11 +++- .../Semantics/NullableReferenceTypesTests.cs | 4 +- .../Core/Portable/Symbols/ManagedKind.cs | 18 ++++++ 15 files changed, 105 insertions(+), 64 deletions(-) create mode 100644 src/Compilers/Core/Portable/Symbols/ManagedKind.cs diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index 2073afac239fc..c08e87a72f9e3 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -1142,12 +1142,13 @@ private BoundExpression BindSizeOf(SizeOfExpressionSyntax node, DiagnosticBag di /// true if managed type-related errors were found, otherwise false. private static bool CheckManagedAddr(TypeSymbol type, SyntaxNode node, DiagnosticBag diagnostics) { - if (type.IsManagedType) + var managedKind = type.ManagedKind; + if (managedKind == ManagedKind.Managed) { diagnostics.Add(ErrorCode.ERR_ManagedAddr, node.Location, type); return true; } - else if (type.GetArity() != 0) + else if (managedKind == ManagedKind.UnmanagedWithGenerics) { var supported = CheckFeatureAvailability(node, MessageID.IDS_FeatureUnmanagedGenericStructs, diagnostics); return !supported; diff --git a/src/Compilers/CSharp/Portable/Symbols/ArrayTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/ArrayTypeSymbol.cs index 7ca8893987b84..dbf18d45e7058 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ArrayTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ArrayTypeSymbol.cs @@ -220,11 +220,11 @@ public override bool IsValueType } } - internal sealed override bool IsManagedType + internal sealed override ManagedKind ManagedKind { get { - return true; + return ManagedKind.Managed; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/BaseTypeAnalysis.cs b/src/Compilers/CSharp/Portable/Symbols/BaseTypeAnalysis.cs index 7d47f02ec0259..045d302fdc091 100644 --- a/src/Compilers/CSharp/Portable/Symbols/BaseTypeAnalysis.cs +++ b/src/Compilers/CSharp/Portable/Symbols/BaseTypeAnalysis.cs @@ -105,30 +105,38 @@ private static void StructDependsClosure(NamedTypeSymbol type, HashSet p /// be managed even if it had no fields. e.g. struct S { S s; } is not managed, but struct S { S s; object o; } /// is because we can point to object. /// - internal static bool IsManagedType(NamedTypeSymbol type) + internal static ManagedKind GetManagedKind(NamedTypeSymbol type) { - // If this is a type with an obvious answer, return quickly. - switch (IsManagedTypeHelper(type)) + var hasGenerics = false; + var isManaged = IsManagedTypeHelper(type, ref hasGenerics); + var definitelyManaged = isManaged == ThreeState.True; + if (isManaged == ThreeState.Unknown) { - case ThreeState.True: - return true; - case ThreeState.False: - return false; + // Otherwise, we have to build and inspect the closure of depended-upon types. + var hs = PooledHashSet.GetInstance(); + definitelyManaged = DependsOnDefinitelyManagedType(type, hs, ref hasGenerics); + hs.Free(); } - // Otherwise, we have to build and inspect the closure of depended-upon types. - var hs = PooledHashSet.GetInstance(); - bool result = DependsOnDefinitelyManagedType(type, hs); - hs.Free(); - return result; + + if (definitelyManaged) + { + return ManagedKind.Managed; + } + else if (hasGenerics) + { + return ManagedKind.UnmanagedWithGenerics; + } + else + { + return ManagedKind.Unmanaged; + } } - private static bool DependsOnDefinitelyManagedType(NamedTypeSymbol type, HashSet partialClosure) + private static bool DependsOnDefinitelyManagedType(NamedTypeSymbol type, HashSet partialClosure, ref bool hasGenerics) { Debug.Assert((object)type != null); - // NOTE: unlike in StructDependsClosure, we don't have to check for expanding cycles, - // because as soon as we see something with non-zero arity we kick out (generic => managed). if (partialClosure.Add(type)) { foreach (var member in type.GetInstanceFieldsAndEvents()) @@ -174,17 +182,23 @@ private static bool DependsOnDefinitelyManagedType(NamedTypeSymbol type, HashSet } else { - // NOTE: don't use IsManagedType on a NamedTypeSymbol - that could lead + // NOTE: don't use ManagedKind.get on a NamedTypeSymbol - that could lead // to infinite recursion. - switch (IsManagedTypeHelper(fieldNamedType)) + switch (IsManagedTypeHelper(fieldNamedType, ref hasGenerics)) { case ThreeState.True: return true; + case ThreeState.False: + if (fieldNamedType.GetArity() > 0) + { + hasGenerics = true; + } continue; + case ThreeState.Unknown: if (!fieldNamedType.OriginalDefinition.KnownCircularStruct && - DependsOnDefinitelyManagedType(fieldNamedType, partialClosure)) + DependsOnDefinitelyManagedType(fieldNamedType, partialClosure, ref hasGenerics)) { return true; } @@ -201,8 +215,13 @@ private static bool DependsOnDefinitelyManagedType(NamedTypeSymbol type, HashSet /// Returns a boolean value if we can determine whether the type is managed /// without looking at its fields and Unset otherwise. /// - private static ThreeState IsManagedTypeHelper(NamedTypeSymbol type) + private static ThreeState IsManagedTypeHelper(NamedTypeSymbol type, ref bool hasGenerics) { + if (type.TupleUnderlyingTypeOrSelf().GetArity() > 0) + { + hasGenerics = true; + } + // To match dev10, we treat enums as their underlying types. if (type.IsEnumType()) { diff --git a/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs b/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs index ae258e6ea8701..3df1e6490954c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs @@ -907,13 +907,14 @@ private static bool CheckConstraints( if (typeParameter.HasUnmanagedTypeConstraint) { - if (typeArgument.IsManagedType || !typeArgument.TypeSymbol.IsNonNullableValueType()) + var managedKind = typeArgument.TypeSymbol.ManagedKind; + if (managedKind == ManagedKind.Managed || !typeArgument.TypeSymbol.IsNonNullableValueType()) { // "The type '{2}' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}'" diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, containingSymbol.ConstructedFrom(), typeParameter, typeArgument.TypeSymbol))); return false; } - else if (typeArgument.TypeSymbol.GetArity() > 0 && + else if (managedKind == ManagedKind.UnmanagedWithGenerics && currentCompilation is CSharpCompilation csCompilation && csCompilation.LanguageVersion < MessageID.IDS_FeatureUnmanagedGenericStructs.RequiredVersion()) { @@ -922,7 +923,7 @@ currentCompilation is CSharpCompilation csCompilation && foreach (var diagnostic in diagnostics.AsEnumerable()) { // PROTOTYPE - var typeParameterDiagnostic = new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo((ErrorCode) diagnostic.Code, diagnostic.Arguments)); + var typeParameterDiagnostic = new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo((ErrorCode) diagnostic.Code, args: (object[]) diagnostic.Arguments)); diagnosticsBuilder.Add(typeParameterDiagnostic); } } diff --git a/src/Compilers/CSharp/Portable/Symbols/DynamicTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/DynamicTypeSymbol.cs index a9525f3c2f8b6..eb72e29ae97b4 100644 --- a/src/Compilers/CSharp/Portable/Symbols/DynamicTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/DynamicTypeSymbol.cs @@ -104,11 +104,11 @@ public override bool IsValueType } } - internal sealed override bool IsManagedType + internal sealed override ManagedKind ManagedKind { get { - return true; + return ManagedKind.Managed; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs index db8d6cb9f5375..137b20bc62f74 100644 --- a/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs @@ -395,14 +395,14 @@ public override bool IsValueType } } - internal override bool IsManagedType + internal override ManagedKind ManagedKind { get { // CONSIDER: we could cache this, but it's only expensive for non-special struct types // that are pointed to. For now, only cache on SourceMemberContainerSymbol since it fits // nicely into the flags variable. - return BaseTypeAnalysis.IsManagedType(this); + return BaseTypeAnalysis.GetManagedKind(this); } } diff --git a/src/Compilers/CSharp/Portable/Symbols/PointerTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/PointerTypeSymbol.cs index cabc47f1402da..72113136530e5 100644 --- a/src/Compilers/CSharp/Portable/Symbols/PointerTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/PointerTypeSymbol.cs @@ -99,13 +99,7 @@ public override bool IsValueType } } - internal sealed override bool IsManagedType - { - get - { - return false; - } - } + internal sealed override ManagedKind ManagedKind => ManagedKind.Unmanaged; internal sealed override bool IsByRefLikeType { diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs index 4a6edd640d076..ee182c1c74c07 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs @@ -41,15 +41,15 @@ private struct Flags private const int DeclarationModifiersOffset = SpecialTypeSize; private const int DeclarationModifiersSize = 23; - private const int IsManagedTypeOffset = DeclarationModifiersOffset + DeclarationModifiersSize; - private const int IsManagedTypeSize = 2; + private const int ManagedKindOffset = DeclarationModifiersOffset + DeclarationModifiersSize; + private const int ManagedKindSize = 2; - private const int FieldDefinitionsNotedOffset = IsManagedTypeOffset + IsManagedTypeSize; + private const int FieldDefinitionsNotedOffset = ManagedKindOffset + ManagedKindSize; private const int FieldDefinitionsNotedSize = 1; private const int SpecialTypeMask = (1 << SpecialTypeSize) - 1; private const int DeclarationModifiersMask = (1 << DeclarationModifiersSize) - 1; - private const int IsManagedTypeMask = (1 << IsManagedTypeSize) - 1; + private const int ManagedKindMask = (1 << ManagedKindSize) - 1; private const int FieldDefinitionsNotedBit = 1 << FieldDefinitionsNotedOffset; @@ -79,9 +79,9 @@ public DeclarationModifiers DeclarationModifiers get { return (DeclarationModifiers)((_flags >> DeclarationModifiersOffset) & DeclarationModifiersMask); } } - public ThreeState IsManagedType + public ManagedKind ManagedKind { - get { return (ThreeState)((_flags >> IsManagedTypeOffset) & IsManagedTypeMask); } + get { return (ManagedKind)((_flags >> ManagedKindOffset) & ManagedKindMask); } } public bool FieldDefinitionsNoted @@ -146,9 +146,9 @@ private static bool BitsAreUnsetOrSame(int bits, int mask) return (bits & mask) == 0 || (bits & mask) == mask; } - public void SetIsManagedType(bool isManagedType) + public void SetManagedKind(ManagedKind managedKind) { - int bitsToSet = ((int)isManagedType.ToThreeState() & IsManagedTypeMask) << IsManagedTypeOffset; + int bitsToSet = ((int)managedKind & ManagedKindMask) << ManagedKindOffset; Debug.Assert(BitsAreUnsetOrSame(_flags, bitsToSet)); ThreadSafeFlagOperations.Set(ref _flags, bitsToSet); } @@ -682,18 +682,18 @@ internal sealed override bool IsInterface } } - internal override bool IsManagedType + internal override ManagedKind ManagedKind { get { - var isManagedType = _flags.IsManagedType; - if (!isManagedType.HasValue()) + var managedKind = _flags.ManagedKind; + if (managedKind == ManagedKind.Unknown) { - bool value = base.IsManagedType; - _flags.SetIsManagedType(value); - return value; + var baseKind = base.ManagedKind; + _flags.SetManagedKind(baseKind); + return baseKind; } - return isManagedType.Value(); + return managedKind; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedAttributeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedAttributeSymbol.cs index 45346ce40eac4..d12caed2d337a 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedAttributeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedEmbeddedAttributeSymbol.cs @@ -88,7 +88,7 @@ private static NamedTypeSymbol MakeBaseType(CSharpCompilation compilation, Diagn public override bool IsImplicitlyDeclared => true; - internal override bool IsManagedType => false; + internal override ManagedKind ManagedKind => ManagedKind.Managed; public override NamedTypeSymbol ConstructedFrom => this; diff --git a/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs index 13feaadca1d23..3d8865db637e6 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs @@ -686,11 +686,11 @@ internal override ImmutableArray InterfacesNoUseSiteDiagnostics return _underlyingType.InterfacesNoUseSiteDiagnostics(basesBeingResolved); } - internal sealed override bool IsManagedType + internal sealed override ManagedKind ManagedKind { get { - return _underlyingType.IsManagedType; + return _underlyingType.ManagedKind; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/TypeParameterSymbol.cs index 51b361ae92a27..d9109c23baeb4 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypeParameterSymbol.cs @@ -584,12 +584,12 @@ internal bool GetIsValueType(ConsList inProgress) } public sealed override bool IsValueType => GetIsValueType(ConsList.Empty); - - internal sealed override bool IsManagedType + + internal sealed override ManagedKind ManagedKind { get { - return !this.HasUnmanagedTypeConstraint; + return HasUnmanagedTypeConstraint ? ManagedKind.Unmanaged : ManagedKind.Managed; } } diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs index 1777c2e77ae7b..e5ea5d6356fe5 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs @@ -622,7 +622,10 @@ public virtual NamedTypeSymbol TupleUnderlyingType /// /// See Type::computeManagedType. /// - internal abstract bool IsManagedType { get; } + internal bool IsManagedType => ManagedKind == ManagedKind.Managed; + + // PROTOTYPE + internal abstract ManagedKind ManagedKind { get; } internal bool ContainsNullableReferenceTypes() { diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs index e8c45876b14cc..b36f62664d55e 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs @@ -3862,18 +3862,23 @@ public struct MyStruct public class C { - public unsafe void M() where T : unmanaged { var t = default(T); var ptr = &t; } + public unsafe void M() where T : unmanaged { } public void M2() { M(); + M<(int, int)>(); } } "; CreateCompilation(code, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular7_3) .VerifyDiagnostics( - // PROTOTYPE: placeholder while we figure out how to get the compiler to produce the error in this context - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "MyStruct") + // (13,9): error CS8370: Feature 'unmanaged generic structs' is not available in C# 7.3. Please use language version 8.0 or greater. + // M(); + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "M").WithArguments("unmanaged generic structs", "8.0").WithLocation(13, 9), + // (14,9): error CS8370: Feature 'unmanaged generic structs' is not available in C# 7.3. Please use language version 8.0 or greater. + // M<(int, int)>(); + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "M<(int, int)>").WithArguments("unmanaged generic structs", "8.0").WithLocation(14, 9) ); } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs index e60482987668a..787899323d7a2 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs @@ -1327,7 +1327,7 @@ interface I { } Assert.False(type.IsGenericType); Assert.True(type.IsImplicitlyDeclared); Assert.False(type.IsInterface); - Assert.False(type.IsManagedType); + Assert.Equal(ManagedKind.Managed, type.ManagedKind); Assert.False(type.IsNamespace); Assert.True(type.IsReferenceType); Assert.True(type.IsSealed); @@ -1404,7 +1404,7 @@ public void NonNullTypesAttribute_Injected_InCSharp7() Assert.False(type.IsGenericType); Assert.True(type.IsImplicitlyDeclared); Assert.False(type.IsInterface); - Assert.False(type.IsManagedType); + Assert.Equal(ManagedKind.Managed, type.ManagedKind); Assert.False(type.IsNamespace); Assert.True(type.IsReferenceType); Assert.True(type.IsSealed); diff --git a/src/Compilers/Core/Portable/Symbols/ManagedKind.cs b/src/Compilers/Core/Portable/Symbols/ManagedKind.cs new file mode 100644 index 0000000000000..c2636f94e1a29 --- /dev/null +++ b/src/Compilers/Core/Portable/Symbols/ManagedKind.cs @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; + +namespace Microsoft.CodeAnalysis +{ + /// + /// PROTOTYPE + /// + [Flags] + internal enum ManagedKind : byte + { + Unknown = 0, + Unmanaged = 1, + UnmanagedWithGenerics = 2, + Managed = 3, + } +} From 3529e2d40162a488f97d7c29aff5ae65739276af Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Thu, 3 Jan 2019 17:00:49 -0800 Subject: [PATCH 24/40] Fix MockNamedTypeSymbol --- .../CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs index f19146ef56512..8cd44ea1f7149 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs @@ -245,11 +245,11 @@ internal override ImmutableArray GetDeclaredInterfaces(ConsList internal override bool HasCodeAnalysisEmbeddedAttribute => false; - internal sealed override bool IsManagedType + internal sealed override ManagedKind ManagedKind { get { - return true; + return ManagedKind.Managed; } } From 15f2c61427eafec410505560ad8a001e9f1b3849 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Fri, 4 Jan 2019 11:21:39 -0800 Subject: [PATCH 25/40] Remove redundant arity check --- src/Compilers/CSharp/Portable/Symbols/BaseTypeAnalysis.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Symbols/BaseTypeAnalysis.cs b/src/Compilers/CSharp/Portable/Symbols/BaseTypeAnalysis.cs index 045d302fdc091..4cee1eb646400 100644 --- a/src/Compilers/CSharp/Portable/Symbols/BaseTypeAnalysis.cs +++ b/src/Compilers/CSharp/Portable/Symbols/BaseTypeAnalysis.cs @@ -190,10 +190,6 @@ private static bool DependsOnDefinitelyManagedType(NamedTypeSymbol type, HashSet return true; case ThreeState.False: - if (fieldNamedType.GetArity() > 0) - { - hasGenerics = true; - } continue; case ThreeState.Unknown: From 87d19f770a84f30034d4c519b2a3b23d9129fd88 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Fri, 4 Jan 2019 12:31:58 -0800 Subject: [PATCH 26/40] Check StructContainingTuple in C# 8 --- .../CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs index b36f62664d55e..57f7a8bddcc71 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs @@ -3852,7 +3852,7 @@ public unsafe struct OtherStruct } [Fact] - public void StructContainingTuple_Pointer_RequiresCSharp8() + public void StructContainingTuple_Unmanaged_RequiresCSharp8() { var code = @" public struct MyStruct @@ -3880,6 +3880,8 @@ public void M2() // M<(int, int)>(); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "M<(int, int)>").WithArguments("unmanaged generic structs", "8.0").WithLocation(14, 9) ); + + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(); } [Fact] From e7615902292a6561f982e2e8c4c0eeadbb68d80b Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Mon, 7 Jan 2019 12:53:55 -0800 Subject: [PATCH 27/40] Fix test name --- src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs index 0715e41748b9d..12a81883b59fc 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs @@ -6638,7 +6638,7 @@ unsafe static void Main() } [Fact] - public void NormalInitializerType_ArrayOfGenericStruct8() + public void NormalInitializerType_ArrayOfGenericStruct() { var text = @" public struct MyStruct From 45388ce96db6c5c40ef796be1bdc8eb6d1413319 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Mon, 7 Jan 2019 12:56:15 -0800 Subject: [PATCH 28/40] Use IsFeatureEnabled API --- src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs b/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs index 3df1e6490954c..fccd229899338 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs @@ -916,7 +916,7 @@ private static bool CheckConstraints( } else if (managedKind == ManagedKind.UnmanagedWithGenerics && currentCompilation is CSharpCompilation csCompilation && - csCompilation.LanguageVersion < MessageID.IDS_FeatureUnmanagedGenericStructs.RequiredVersion()) + !csCompilation.IsFeatureEnabled(MessageID.IDS_FeatureUnmanagedGenericStructs)) { var diagnostics = DiagnosticBag.GetInstance(); MessageID.IDS_FeatureUnmanagedGenericStructs.CheckFeatureAvailability(csCompilation.LanguageVersion, diagnostics, typeArgument.TypeSymbol.Locations[0]); From f0def6050aa3bbd3bc4f654ab7dec2190c2c0c90 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Mon, 7 Jan 2019 15:25:14 -0800 Subject: [PATCH 29/40] Use expression bodies for simple ManagedKind overrides --- src/Compilers/CSharp/Portable/Symbols/ArrayTypeSymbol.cs | 8 +------- .../CSharp/Portable/Symbols/DynamicTypeSymbol.cs | 8 +------- .../CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs | 8 +------- .../CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs | 8 +------- 4 files changed, 4 insertions(+), 28 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Symbols/ArrayTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/ArrayTypeSymbol.cs index dbf18d45e7058..ddfa6a34cd1a5 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ArrayTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ArrayTypeSymbol.cs @@ -220,13 +220,7 @@ public override bool IsValueType } } - internal sealed override ManagedKind ManagedKind - { - get - { - return ManagedKind.Managed; - } - } + internal sealed override ManagedKind ManagedKind => ManagedKind.Managed; internal sealed override bool IsByRefLikeType { diff --git a/src/Compilers/CSharp/Portable/Symbols/DynamicTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/DynamicTypeSymbol.cs index eb72e29ae97b4..c85f4567d160a 100644 --- a/src/Compilers/CSharp/Portable/Symbols/DynamicTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/DynamicTypeSymbol.cs @@ -104,13 +104,7 @@ public override bool IsValueType } } - internal sealed override ManagedKind ManagedKind - { - get - { - return ManagedKind.Managed; - } - } + internal sealed override ManagedKind ManagedKind => ManagedKind.Managed; internal sealed override bool IsByRefLikeType { diff --git a/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs index 3d8865db637e6..ce2e769ee0a61 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs @@ -686,13 +686,7 @@ internal override ImmutableArray InterfacesNoUseSiteDiagnostics return _underlyingType.InterfacesNoUseSiteDiagnostics(basesBeingResolved); } - internal sealed override ManagedKind ManagedKind - { - get - { - return _underlyingType.ManagedKind; - } - } + internal sealed override ManagedKind ManagedKind => _underlyingType.ManagedKind; public override bool IsTupleType { diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs index 8cd44ea1f7149..52ab079dd8c89 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/MockNamedTypeSymbol.cs @@ -245,13 +245,7 @@ internal override ImmutableArray GetDeclaredInterfaces(ConsList internal override bool HasCodeAnalysisEmbeddedAttribute => false; - internal sealed override ManagedKind ManagedKind - { - get - { - return ManagedKind.Managed; - } - } + internal sealed override ManagedKind ManagedKind => ManagedKind.Managed; internal override bool ShouldAddWinRTMembers { From 7be853897f8abf859676a65d1459ab1034823c14 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Tue, 8 Jan 2019 14:21:28 -0800 Subject: [PATCH 30/40] Add ManagedKind API tests to UnsafeTests.cs --- .../CSharp/Test/Semantic/Semantics/UnsafeTests.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs index 12a81883b59fc..7f5327bec588a 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs @@ -2511,6 +2511,7 @@ class C var type = compilation.GlobalNamespace.GetMember("C"); Assert.True(type.GetMembers().OfType().All(field => !field.Type.IsManagedType)); + Assert.Equal(ManagedKind.UnmanagedWithGenerics, type.GetField("f16").Type.TypeSymbol.ManagedKind); } [Fact] @@ -2595,7 +2596,9 @@ struct S { } var compilation = CreateCompilation(text); var globalNamespace = compilation.GlobalNamespace; Assert.False(globalNamespace.GetMember("S").IsManagedType); + Assert.Equal(ManagedKind.Unmanaged, globalNamespace.GetMember("S").ManagedKind); Assert.False(globalNamespace.GetMember("P").IsManagedType); + Assert.Equal(ManagedKind.UnmanagedWithGenerics, globalNamespace.GetMember("P").ManagedKind); Assert.False(globalNamespace.GetMember("C").GetMember("S").IsManagedType); Assert.False(globalNamespace.GetMember("D").GetMember("S").IsManagedType); Assert.False(globalNamespace.GetMember("Q").GetMember("S").IsManagedType); @@ -2622,9 +2625,15 @@ struct R { } var compilation = CreateCompilation(text); var type = compilation.GlobalNamespace.GetMember("C"); Assert.False(type.GetMember("f1").Type.IsManagedType); + Assert.Equal(ManagedKind.UnmanagedWithGenerics, type.GetMember("f1").Type.TypeSymbol.ManagedKind); Assert.False(type.GetMember("f2").Type.IsManagedType); - Assert.True(type.GetMember("f3").Type.IsManagedType); // is managed due to being ErrorType due to protection level (CS0169) + Assert.Equal(ManagedKind.UnmanagedWithGenerics, type.GetMember("f2").Type.TypeSymbol.ManagedKind); + + // these are managed due to S`1.R being ErrorType due to protection level (CS0169) + Assert.True(type.GetMember("f3").Type.IsManagedType); + Assert.Equal(ManagedKind.Managed, type.GetMember("f3").Type.TypeSymbol.ManagedKind); Assert.True(type.GetMember("f4").Type.IsManagedType); + Assert.Equal(ManagedKind.Managed, type.GetMember("f4").Type.TypeSymbol.ManagedKind); } [Fact] @@ -2645,7 +2654,9 @@ struct S var compilation = CreateCompilation(text); var type = compilation.GlobalNamespace.GetMember("C"); Assert.True(type.GetMember("f1").Type.IsManagedType); + Assert.Equal(ManagedKind.Managed, type.GetMember("f1").Type.TypeSymbol.ManagedKind); Assert.False(type.GetMember("f2").Type.IsManagedType); + Assert.Equal(ManagedKind.UnmanagedWithGenerics, type.GetMember("f2").Type.TypeSymbol.ManagedKind); } [Fact] @@ -2864,6 +2875,7 @@ struct W { X>> x; } var globalNamespace = compilation.GlobalNamespace; Assert.True(globalNamespace.GetMember("X").IsManagedType); // because of X.t Assert.False(globalNamespace.GetMember("W").IsManagedType); + Assert.Equal(ManagedKind.UnmanagedWithGenerics, globalNamespace.GetMember("W").ManagedKind); } [Fact] From ac8852cb6289006ab2fec33eb5896940450514d4 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Tue, 8 Jan 2019 14:29:32 -0800 Subject: [PATCH 31/40] Add StructContainingGenericTuple_Unmanaged --- .../Semantics/GenericConstraintsTests.cs | 44 ++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs index 57f7a8bddcc71..523bff684c60e 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs @@ -3880,10 +3880,52 @@ public void M2() // M<(int, int)>(); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "M<(int, int)>").WithArguments("unmanaged generic structs", "8.0").WithLocation(14, 9) ); - + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(); } + [Fact] + public void StructContainingGenericTuple_Unmanaged() + { + var code = @" +public struct MyStruct +{ + public (T, T) field; +} + +public class C +{ + public unsafe void M() where T : unmanaged { } + + public void M2() where U : unmanaged + { + M>(); + } + + public void M3() + { + M>(); + } +} +"; + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular7_3) + .VerifyDiagnostics( + // (13,9): error CS8370: Feature 'unmanaged generic structs' is not available in C# 7.3. Please use language version 8.0 or greater. + // M>(); + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "M>").WithArguments("unmanaged generic structs", "8.0").WithLocation(13, 9), + // (18,9): error CS8377: The type 'MyStruct' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'C.M()' + // M>(); + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "M>").WithArguments("C.M()", "T", "MyStruct").WithLocation(18, 9) + ); + + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll) + .VerifyDiagnostics( + // (18,9): error CS8377: The type 'MyStruct' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'C.M()' + // M>(); + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "M>").WithArguments("C.M()", "T", "MyStruct").WithLocation(18, 9) + ); + } + [Fact] public void GenericRefStructAddressOf() { From 2af8c74c3f06b8de2fb70aae27c6311727b21852 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Tue, 8 Jan 2019 14:42:22 -0800 Subject: [PATCH 32/40] Add doc comments for ManagedKind --- src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs | 5 ++++- src/Compilers/Core/Portable/Symbols/ManagedKind.cs | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs index e5ea5d6356fe5..fc9601991fb72 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs @@ -624,7 +624,10 @@ public virtual NamedTypeSymbol TupleUnderlyingType /// internal bool IsManagedType => ManagedKind == ManagedKind.Managed; - // PROTOTYPE + /// + /// Indicates whether a type is managed or not (i.e. you can take a pointer to it). + /// Contains additional cases to help implement FeatureNotAvailable diagnostics. + /// internal abstract ManagedKind ManagedKind { get; } internal bool ContainsNullableReferenceTypes() diff --git a/src/Compilers/Core/Portable/Symbols/ManagedKind.cs b/src/Compilers/Core/Portable/Symbols/ManagedKind.cs index c2636f94e1a29..9fd47c99db17d 100644 --- a/src/Compilers/Core/Portable/Symbols/ManagedKind.cs +++ b/src/Compilers/Core/Portable/Symbols/ManagedKind.cs @@ -5,14 +5,14 @@ namespace Microsoft.CodeAnalysis { /// - /// PROTOTYPE + /// Enumeration of the possible "degrees of managed" for a type. /// [Flags] internal enum ManagedKind : byte { Unknown = 0, Unmanaged = 1, - UnmanagedWithGenerics = 2, + UnmanagedWithGenerics = 2, // considered "managed" in C# 7.3 and earlier Managed = 3, } } From ca410a24b411c138bc60ef6f98647dbabe40fa40 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Tue, 8 Jan 2019 15:33:44 -0800 Subject: [PATCH 33/40] Simplify feature not available diagnostic in constraint checker --- .../CSharp/Portable/Binder/Binder_Symbols.cs | 2 +- .../CSharp/Portable/Symbols/ConstraintsHelper.cs | 11 +++-------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs index 17132bfe688d9..12ec3c48d8692 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs @@ -2248,7 +2248,7 @@ internal static bool CheckFeatureAvailability(SyntaxTree tree, MessageID feature return false; } - private static CSDiagnosticInfo GetFeatureAvailabilityDiagnosticInfo(SyntaxTree tree, MessageID feature) + internal static CSDiagnosticInfo GetFeatureAvailabilityDiagnosticInfo(SyntaxTree tree, MessageID feature) { CSharpParseOptions options = (CSharpParseOptions)tree.Options; diff --git a/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs b/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs index fccd229899338..3a0931854fcc2 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs @@ -918,14 +918,9 @@ private static bool CheckConstraints( currentCompilation is CSharpCompilation csCompilation && !csCompilation.IsFeatureEnabled(MessageID.IDS_FeatureUnmanagedGenericStructs)) { - var diagnostics = DiagnosticBag.GetInstance(); - MessageID.IDS_FeatureUnmanagedGenericStructs.CheckFeatureAvailability(csCompilation.LanguageVersion, diagnostics, typeArgument.TypeSymbol.Locations[0]); - foreach (var diagnostic in diagnostics.AsEnumerable()) - { - // PROTOTYPE - var typeParameterDiagnostic = new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo((ErrorCode) diagnostic.Code, args: (object[]) diagnostic.Arguments)); - diagnosticsBuilder.Add(typeParameterDiagnostic); - } + var csDiagnostic = Binder.GetFeatureAvailabilityDiagnosticInfo(csCompilation.SyntaxTrees[0], MessageID.IDS_FeatureUnmanagedGenericStructs); + var typeParameterDiagnostic = new TypeParameterDiagnosticInfo(typeParameter, csDiagnostic); + diagnosticsBuilder.Add(typeParameterDiagnostic); } } From ce2726557595242f77cf38c645d7a495c26b7943 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Tue, 8 Jan 2019 17:06:51 -0800 Subject: [PATCH 34/40] Move from ref param to tuple return --- .../Portable/Symbols/BaseTypeAnalysis.cs | 48 ++++++++++--------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Symbols/BaseTypeAnalysis.cs b/src/Compilers/CSharp/Portable/Symbols/BaseTypeAnalysis.cs index 4cee1eb646400..a411a850cb90c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/BaseTypeAnalysis.cs +++ b/src/Compilers/CSharp/Portable/Symbols/BaseTypeAnalysis.cs @@ -107,14 +107,15 @@ private static void StructDependsClosure(NamedTypeSymbol type, HashSet p /// internal static ManagedKind GetManagedKind(NamedTypeSymbol type) { - var hasGenerics = false; - var isManaged = IsManagedTypeHelper(type, ref hasGenerics); + var (isManaged, hasGenerics) = IsManagedTypeHelper(type); var definitelyManaged = isManaged == ThreeState.True; if (isManaged == ThreeState.Unknown) { // Otherwise, we have to build and inspect the closure of depended-upon types. var hs = PooledHashSet.GetInstance(); - definitelyManaged = DependsOnDefinitelyManagedType(type, hs, ref hasGenerics); + var result = DependsOnDefinitelyManagedType(type, hs); + definitelyManaged = result.definitelyManaged; + hasGenerics = hasGenerics || result.hasGenerics; hs.Free(); } @@ -133,10 +134,11 @@ internal static ManagedKind GetManagedKind(NamedTypeSymbol type) } } - private static bool DependsOnDefinitelyManagedType(NamedTypeSymbol type, HashSet partialClosure, ref bool hasGenerics) + private static (bool definitelyManaged, bool hasGenerics) DependsOnDefinitelyManagedType(NamedTypeSymbol type, HashSet partialClosure) { Debug.Assert((object)type != null); + var hasGenerics = false; if (partialClosure.Add(type)) { foreach (var member in type.GetInstanceFieldsAndEvents()) @@ -177,26 +179,32 @@ private static bool DependsOnDefinitelyManagedType(NamedTypeSymbol type, HashSet { if (fieldType.IsManagedType) { - return true; + return (true, hasGenerics); } } else { + var result = IsManagedTypeHelper(fieldNamedType); + hasGenerics = hasGenerics || result.hasGenerics; // NOTE: don't use ManagedKind.get on a NamedTypeSymbol - that could lead // to infinite recursion. - switch (IsManagedTypeHelper(fieldNamedType, ref hasGenerics)) + switch (result.isManaged) { case ThreeState.True: - return true; + return (true, hasGenerics); case ThreeState.False: continue; case ThreeState.Unknown: - if (!fieldNamedType.OriginalDefinition.KnownCircularStruct && - DependsOnDefinitelyManagedType(fieldNamedType, partialClosure, ref hasGenerics)) + if (!fieldNamedType.OriginalDefinition.KnownCircularStruct) { - return true; + var (definitelyManaged, childHasGenerics) = DependsOnDefinitelyManagedType(fieldNamedType, partialClosure); + hasGenerics = hasGenerics || childHasGenerics; + if (definitelyManaged) + { + return (true, hasGenerics); + } } continue; } @@ -204,26 +212,23 @@ private static bool DependsOnDefinitelyManagedType(NamedTypeSymbol type, HashSet } } - return false; + return (false, hasGenerics); } /// /// Returns a boolean value if we can determine whether the type is managed /// without looking at its fields and Unset otherwise. /// - private static ThreeState IsManagedTypeHelper(NamedTypeSymbol type, ref bool hasGenerics) + private static (ThreeState isManaged, bool hasGenerics) IsManagedTypeHelper(NamedTypeSymbol type) { - if (type.TupleUnderlyingTypeOrSelf().GetArity() > 0) - { - hasGenerics = true; - } - // To match dev10, we treat enums as their underlying types. if (type.IsEnumType()) { type = type.GetEnumUnderlyingType(); } + bool hasGenerics = type.TupleUnderlyingTypeOrSelf().GetArity() > 0; + // Short-circuit common cases. switch (type.SpecialType) { @@ -246,21 +251,20 @@ private static ThreeState IsManagedTypeHelper(NamedTypeSymbol type, ref bool has case SpecialType.System_TypedReference: case SpecialType.System_ArgIterator: case SpecialType.System_RuntimeArgumentHandle: - return ThreeState.False; + return (ThreeState.False, hasGenerics); case SpecialType.None: default: // CONSIDER: could provide cases for other common special types. break; // Proceed with additional checks. } - switch (type.TypeKind) { case TypeKind.Enum: - return ThreeState.False; + return (ThreeState.False, hasGenerics); case TypeKind.Struct: - return ThreeState.Unknown; + return (ThreeState.Unknown, hasGenerics); default: - return ThreeState.True; + return (ThreeState.True, hasGenerics); } } From 0a83014d1cb07ec9b1e2f55e9cdc12f0c39a3f34 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Wed, 9 Jan 2019 14:12:40 -0800 Subject: [PATCH 35/40] UnmanagedGenericStructs -> UnmanagedConstructedTypes --- .../Portable/Binder/Binder_Expressions.cs | 2 +- .../Portable/CSharpResources.Designer.cs | 8 ++-- .../CSharp/Portable/CSharpResources.resx | 4 +- .../CSharp/Portable/Errors/MessageID.cs | 4 +- .../Portable/Symbols/ConstraintsHelper.cs | 4 +- .../Portable/xlf/CSharpResources.cs.xlf | 6 +-- .../Portable/xlf/CSharpResources.de.xlf | 6 +-- .../Portable/xlf/CSharpResources.es.xlf | 6 +-- .../Portable/xlf/CSharpResources.fr.xlf | 6 +-- .../Portable/xlf/CSharpResources.it.xlf | 6 +-- .../Portable/xlf/CSharpResources.ja.xlf | 6 +-- .../Portable/xlf/CSharpResources.ko.xlf | 6 +-- .../Portable/xlf/CSharpResources.pl.xlf | 6 +-- .../Portable/xlf/CSharpResources.pt-BR.xlf | 6 +-- .../Portable/xlf/CSharpResources.ru.xlf | 6 +-- .../Portable/xlf/CSharpResources.tr.xlf | 6 +-- .../Portable/xlf/CSharpResources.zh-Hans.xlf | 6 +-- .../Portable/xlf/CSharpResources.zh-Hant.xlf | 6 +-- .../Semantics/GenericConstraintsTests.cs | 40 +++++++++---------- .../Test/Semantic/Semantics/UnsafeTests.cs | 4 +- 20 files changed, 72 insertions(+), 72 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index c08e87a72f9e3..c20007304a1bd 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -1150,7 +1150,7 @@ private static bool CheckManagedAddr(TypeSymbol type, SyntaxNode node, Diagnosti } else if (managedKind == ManagedKind.UnmanagedWithGenerics) { - var supported = CheckFeatureAvailability(node, MessageID.IDS_FeatureUnmanagedGenericStructs, diagnostics); + var supported = CheckFeatureAvailability(node, MessageID.IDS_FeatureUnmanagedConstructedTypes, diagnostics); return !supported; } diff --git a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs index 76338713470f2..73b833e3eea29 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs +++ b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs @@ -19,7 +19,7 @@ namespace Microsoft.CodeAnalysis.CSharp { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class CSharpResources { @@ -11339,11 +11339,11 @@ internal static string IDS_FeatureUnconstrainedTypeParameterInNullCoalescingOper } /// - /// Looks up a localized string similar to unmanaged generic structs. + /// Looks up a localized string similar to unmanaged constructed types. /// - internal static string IDS_FeatureUnmanagedGenericStructs { + internal static string IDS_FeatureUnmanagedConstructedTypes { get { - return ResourceManager.GetString("IDS_FeatureUnmanagedGenericStructs", resourceCulture); + return ResourceManager.GetString("IDS_FeatureUnmanagedConstructedTypes", resourceCulture); } } diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 8fb19c4fb1e9e..8cb61b13557b2 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -213,8 +213,8 @@ async streams - - unmanaged generic structs + + unmanaged constructed types default literal diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs index 8fde90695fa95..dc1839e4de054 100644 --- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs +++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs @@ -170,7 +170,7 @@ internal enum MessageID IDS_FeatureIndexOperator = MessageBase + 12750, IDS_FeatureRangeOperator = MessageBase + 12751, IDS_FeatureAsyncStreams = MessageBase + 12752, - IDS_FeatureUnmanagedGenericStructs = MessageBase + 12753 + IDS_FeatureUnmanagedConstructedTypes = MessageBase + 12753 } // Message IDs may refer to strings that need to be localized. @@ -244,7 +244,7 @@ internal static LanguageVersion RequiredVersion(this MessageID feature) case MessageID.IDS_FeatureIndexOperator: // semantic check case MessageID.IDS_FeatureRangeOperator: // semantic check case MessageID.IDS_FeatureAsyncStreams: - case MessageID.IDS_FeatureUnmanagedGenericStructs: // semantic check + case MessageID.IDS_FeatureUnmanagedConstructedTypes: // semantic check return LanguageVersion.CSharp8; // C# 7.3 features. diff --git a/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs b/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs index 3a0931854fcc2..7728775de90bb 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs @@ -916,9 +916,9 @@ private static bool CheckConstraints( } else if (managedKind == ManagedKind.UnmanagedWithGenerics && currentCompilation is CSharpCompilation csCompilation && - !csCompilation.IsFeatureEnabled(MessageID.IDS_FeatureUnmanagedGenericStructs)) + !csCompilation.IsFeatureEnabled(MessageID.IDS_FeatureUnmanagedConstructedTypes)) { - var csDiagnostic = Binder.GetFeatureAvailabilityDiagnosticInfo(csCompilation.SyntaxTrees[0], MessageID.IDS_FeatureUnmanagedGenericStructs); + var csDiagnostic = Binder.GetFeatureAvailabilityDiagnosticInfo(csCompilation.SyntaxTrees[0], MessageID.IDS_FeatureUnmanagedConstructedTypes); var typeParameterDiagnostic = new TypeParameterDiagnosticInfo(typeParameter, csDiagnostic); diagnosticsBuilder.Add(typeParameterDiagnostic); } diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 5c4c12b6da0ca..a18e9aa13a01f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -312,9 +312,9 @@ unconstrained type parameters in null coalescing operator - - unmanaged generic structs - unmanaged generic structs + + unmanaged constructed types + unmanaged constructed types diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 6db25ab029607..64fc02b153cdb 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -312,9 +312,9 @@ unconstrained type parameters in null coalescing operator - - unmanaged generic structs - unmanaged generic structs + + unmanaged constructed types + unmanaged constructed types diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 361dc32ba773f..19d11ce5d0c64 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -312,9 +312,9 @@ unconstrained type parameters in null coalescing operator - - unmanaged generic structs - unmanaged generic structs + + unmanaged constructed types + unmanaged constructed types diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 1f23c563a0b9e..0a04c13291426 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -312,9 +312,9 @@ unconstrained type parameters in null coalescing operator - - unmanaged generic structs - unmanaged generic structs + + unmanaged constructed types + unmanaged constructed types diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index ee77318238337..28f15722c9b78 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -312,9 +312,9 @@ unconstrained type parameters in null coalescing operator - - unmanaged generic structs - unmanaged generic structs + + unmanaged constructed types + unmanaged constructed types diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index c5e731e7b982b..c7fe8570ebca9 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -312,9 +312,9 @@ unconstrained type parameters in null coalescing operator - - unmanaged generic structs - unmanaged generic structs + + unmanaged constructed types + unmanaged constructed types diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index ec2e1c06b4996..c27073b800fd1 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -312,9 +312,9 @@ unconstrained type parameters in null coalescing operator - - unmanaged generic structs - unmanaged generic structs + + unmanaged constructed types + unmanaged constructed types diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 14525ca514f0d..51f8403680bbf 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -312,9 +312,9 @@ unconstrained type parameters in null coalescing operator - - unmanaged generic structs - unmanaged generic structs + + unmanaged constructed types + unmanaged constructed types diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 26dfd03b9852b..e174c0545ba77 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -312,9 +312,9 @@ unconstrained type parameters in null coalescing operator - - unmanaged generic structs - unmanaged generic structs + + unmanaged constructed types + unmanaged constructed types diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 60dd097f221b5..c4881f78350e9 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -312,9 +312,9 @@ unconstrained type parameters in null coalescing operator - - unmanaged generic structs - unmanaged generic structs + + unmanaged constructed types + unmanaged constructed types diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index cebbce34967c7..b9894f73c3354 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -312,9 +312,9 @@ unconstrained type parameters in null coalescing operator - - unmanaged generic structs - unmanaged generic structs + + unmanaged constructed types + unmanaged constructed types diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 1778ebec165f0..cd6f34785251a 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -312,9 +312,9 @@ unconstrained type parameters in null coalescing operator - - unmanaged generic structs - unmanaged generic structs + + unmanaged constructed types + unmanaged constructed types diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index ffb19738d1457..dee4177e25615 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -312,9 +312,9 @@ unconstrained type parameters in null coalescing operator - - unmanaged generic structs - unmanaged generic structs + + unmanaged constructed types + unmanaged constructed types diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs index 523bff684c60e..ac74d9c180743 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs @@ -3726,9 +3726,9 @@ public static unsafe void Test() "; CreateCompilation(code, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular7_3) .VerifyDiagnostics( - // (9,19): error CS8370: Feature 'unmanaged generic structs' is not available in C# 7.3. Please use language version 8.0 or greater. + // (9,19): error CS8370: Feature 'unmanaged constructed types' is not available in C# 7.3. Please use language version 8.0 or greater. // var ptr = &ms; - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "&ms").WithArguments("unmanaged generic structs", "8.0").WithLocation(9, 19) + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "&ms").WithArguments("unmanaged constructed types", "8.0").WithLocation(9, 19) ); } @@ -3754,12 +3754,12 @@ public static unsafe void Test(MyClass c) "; CreateCompilation(code, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular7_3) .VerifyDiagnostics( - // (12,16): error CS8370: Feature 'unmanaged generic structs' is not available in C# 7.3. Please use language version 8.0 or greater. + // (12,16): error CS8370: Feature 'unmanaged constructed types' is not available in C# 7.3. Please use language version 8.0 or greater. // fixed (MyStruct* ptr = &c.ms) - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "MyStruct*").WithArguments("unmanaged generic structs", "8.0").WithLocation(12, 16), - // (12,37): error CS8370: Feature 'unmanaged generic structs' is not available in C# 7.3. Please use language version 8.0 or greater. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "MyStruct*").WithArguments("unmanaged constructed types", "8.0").WithLocation(12, 16), + // (12,37): error CS8370: Feature 'unmanaged constructed types' is not available in C# 7.3. Please use language version 8.0 or greater. // fixed (MyStruct* ptr = &c.ms) - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "&c.ms").WithArguments("unmanaged generic structs", "8.0").WithLocation(12, 37) + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "&c.ms").WithArguments("unmanaged constructed types", "8.0").WithLocation(12, 37) ); } @@ -3779,9 +3779,9 @@ public static unsafe void Test() "; CreateCompilation(code, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular7_3) .VerifyDiagnostics( - // (8,20): error CS8370: Feature 'unmanaged generic structs' is not available in C# 7.3. Please use language version 8.0 or greater. + // (8,20): error CS8370: Feature 'unmanaged constructed types' is not available in C# 7.3. Please use language version 8.0 or greater. // var size = sizeof(MyStruct); - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "sizeof(MyStruct)").WithArguments("unmanaged generic structs", "8.0").WithLocation(8, 20) + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "sizeof(MyStruct)").WithArguments("unmanaged constructed types", "8.0").WithLocation(8, 20) ); } @@ -3801,9 +3801,9 @@ public static unsafe void Test() "; CreateCompilation(code, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular7_3) .VerifyDiagnostics( - // (8,19): error CS8370: Feature 'unmanaged generic structs' is not available in C# 7.3. Please use language version 8.0 or greater. + // (8,19): error CS8370: Feature 'unmanaged constructed types' is not available in C# 7.3. Please use language version 8.0 or greater. // var arr = stackalloc[] { new MyStruct() }; - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "stackalloc[] { new MyStruct() }").WithArguments("unmanaged generic structs", "8.0").WithLocation(8, 19) + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "stackalloc[] { new MyStruct() }").WithArguments("unmanaged constructed types", "8.0").WithLocation(8, 19) ); } @@ -3823,9 +3823,9 @@ public static unsafe void Test() "; CreateCompilation(code, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular7_3) .VerifyDiagnostics( - // (8,30): error CS8370: Feature 'unmanaged generic structs' is not available in C# 7.3. Please use language version 8.0 or greater. + // (8,30): error CS8370: Feature 'unmanaged constructed types' is not available in C# 7.3. Please use language version 8.0 or greater. // var arr = stackalloc MyStruct[4]; - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "MyStruct").WithArguments("unmanaged generic structs", "8.0").WithLocation(8, 30) + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "MyStruct").WithArguments("unmanaged constructed types", "8.0").WithLocation(8, 30) ); } @@ -3845,9 +3845,9 @@ public unsafe struct OtherStruct "; CreateCompilation(code, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular7_3) .VerifyDiagnostics( - // (9,12): error CS8370: Feature 'unmanaged generic structs' is not available in C# 7.3. Please use language version 8.0 or greater. + // (9,12): error CS8370: Feature 'unmanaged constructed types' is not available in C# 7.3. Please use language version 8.0 or greater. // public MyStruct* ms; - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "MyStruct*").WithArguments("unmanaged generic structs", "8.0").WithLocation(9, 12) + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "MyStruct*").WithArguments("unmanaged constructed types", "8.0").WithLocation(9, 12) ); } @@ -3873,12 +3873,12 @@ public void M2() "; CreateCompilation(code, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular7_3) .VerifyDiagnostics( - // (13,9): error CS8370: Feature 'unmanaged generic structs' is not available in C# 7.3. Please use language version 8.0 or greater. + // (13,9): error CS8370: Feature 'unmanaged constructed types' is not available in C# 7.3. Please use language version 8.0 or greater. // M(); - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "M").WithArguments("unmanaged generic structs", "8.0").WithLocation(13, 9), - // (14,9): error CS8370: Feature 'unmanaged generic structs' is not available in C# 7.3. Please use language version 8.0 or greater. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "M").WithArguments("unmanaged constructed types", "8.0").WithLocation(13, 9), + // (14,9): error CS8370: Feature 'unmanaged constructed types' is not available in C# 7.3. Please use language version 8.0 or greater. // M<(int, int)>(); - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "M<(int, int)>").WithArguments("unmanaged generic structs", "8.0").WithLocation(14, 9) + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "M<(int, int)>").WithArguments("unmanaged constructed types", "8.0").WithLocation(14, 9) ); CreateCompilation(code, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(); @@ -3910,9 +3910,9 @@ public void M3() "; CreateCompilation(code, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular7_3) .VerifyDiagnostics( - // (13,9): error CS8370: Feature 'unmanaged generic structs' is not available in C# 7.3. Please use language version 8.0 or greater. + // (13,9): error CS8370: Feature 'unmanaged constructed types' is not available in C# 7.3. Please use language version 8.0 or greater. // M>(); - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "M>").WithArguments("unmanaged generic structs", "8.0").WithLocation(13, 9), + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "M>").WithArguments("unmanaged constructed types", "8.0").WithLocation(13, 9), // (18,9): error CS8377: The type 'MyStruct' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'C.M()' // M>(); Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "M>").WithArguments("C.M()", "T", "MyStruct").WithLocation(18, 9) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs index 7f5327bec588a..a76e75ba84039 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs @@ -6697,9 +6697,9 @@ unsafe static void Main() } "; CreateCompilation(text, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular7_3).VerifyDiagnostics( - // (13,26): error CS8370: Feature 'unmanaged generic structs' is not available in C# 7.3. Please use language version 8.0 or greater. + // (13,26): error CS8370: Feature 'unmanaged constructed types' is not available in C# 7.3. Please use language version 8.0 or greater. // fixed (void* p = a) - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "a").WithArguments("unmanaged generic structs", "8.0").WithLocation(13, 26) + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "a").WithArguments("unmanaged constructed types", "8.0").WithLocation(13, 26) ); } From 71a1f820a0e66df2760f9d739a8f5c5d01d26087 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Thu, 10 Jan 2019 13:51:12 -0800 Subject: [PATCH 36/40] Fixes from feedback Fixed a bug in constraint checking where the wrong Compilation would be used. --- .../CSharp/Portable/Binder/Binder_Symbols.cs | 22 +++++++++++-------- .../CSharp/Portable/Binder/Imports.cs | 2 +- .../OverloadResolution/OverloadResolution.cs | 2 +- .../OverloadResolutionResult.cs | 2 +- .../CSharp/Portable/Symbols/AliasSymbol.cs | 2 +- .../Portable/Symbols/ConstraintsHelper.cs | 21 +++++++++++------- .../Symbols/Source/SourceCustomEventSymbol.cs | 2 +- .../Symbols/Source/SourceEventSymbol.cs | 2 +- .../Symbols/Source/SourceMemberFieldSymbol.cs | 2 +- .../Source/SourceNamedTypeSymbol_Bases.cs | 4 ++-- .../Source/SourceOrdinaryMethodSymbol.cs | 6 ++--- .../Symbols/Source/SourcePropertySymbol.cs | 6 ++--- .../Source/SourceTypeParameterSymbol.cs | 2 +- .../SourceUserDefinedOperatorSymbolBase.cs | 4 ++-- .../Symbols/TypeSymbolWithAnnotations.cs | 4 ++-- .../Semantics/GenericConstraintsTests.cs | 15 +++++++++++++ 16 files changed, 61 insertions(+), 37 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs index 12ec3c48d8692..d6d6ab2307db9 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs @@ -2248,7 +2248,18 @@ internal static bool CheckFeatureAvailability(SyntaxTree tree, MessageID feature return false; } - internal static CSDiagnosticInfo GetFeatureAvailabilityDiagnosticInfo(SyntaxTree tree, MessageID feature) + internal static CSDiagnosticInfo GetLanguageVersionDiagnosticInfo(LanguageVersion availableVersion, MessageID feature) + { + LanguageVersion requiredVersion = feature.RequiredVersion(); + if (requiredVersion > availableVersion) + { + return new CSDiagnosticInfo(availableVersion.GetErrorCode(), feature.Localize(), new CSharpRequiredLanguageVersion(requiredVersion)); + } + + return null; + } + + private static CSDiagnosticInfo GetFeatureAvailabilityDiagnosticInfo(SyntaxTree tree, MessageID feature) { CSharpParseOptions options = (CSharpParseOptions)tree.Options; @@ -2263,14 +2274,7 @@ internal static CSDiagnosticInfo GetFeatureAvailabilityDiagnosticInfo(SyntaxTree return new CSDiagnosticInfo(ErrorCode.ERR_FeatureIsExperimental, feature.Localize(), requiredFeature); } - LanguageVersion availableVersion = options.LanguageVersion; - LanguageVersion requiredVersion = feature.RequiredVersion(); - if (requiredVersion > availableVersion) - { - return new CSDiagnosticInfo(availableVersion.GetErrorCode(), feature.Localize(), new CSharpRequiredLanguageVersion(requiredVersion)); - } - - return null; + return GetLanguageVersionDiagnosticInfo(options.LanguageVersion, feature); } } } diff --git a/src/Compilers/CSharp/Portable/Binder/Imports.cs b/src/Compilers/CSharp/Portable/Binder/Imports.cs index 2a5a446f65022..25afdc6f15c26 100644 --- a/src/Compilers/CSharp/Portable/Binder/Imports.cs +++ b/src/Compilers/CSharp/Portable/Binder/Imports.cs @@ -585,7 +585,7 @@ private void Validate() { var typeSymbol = (TypeSymbol)@using.NamespaceOrType; var location = @using.UsingDirective?.Name.Location ?? NoLocation.Singleton; - typeSymbol.CheckAllConstraints(conversions, location, semanticDiagnostics); + typeSymbol.CheckAllConstraints(_compilation, conversions, location, semanticDiagnostics); } } diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs index 15f6920361470..4dd191c685420 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs @@ -3188,7 +3188,7 @@ private MemberResolutionResult IsApplicable( var parameterTypes = leastOverriddenMember.GetParameterTypes(); for (int i = 0; i < parameterTypes.Length; i++) { - if (!parameterTypes[i].TypeSymbol.CheckAllConstraints(Conversions)) + if (!parameterTypes[i].TypeSymbol.CheckAllConstraints(Compilation, Conversions)) { return new MemberResolutionResult(member, leastOverriddenMember, MemberAnalysisResult.ConstructedParameterFailedConstraintsCheck(i)); } diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolutionResult.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolutionResult.cs index 9c7336a61bdc8..fa529f3e31358 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolutionResult.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolutionResult.cs @@ -974,7 +974,7 @@ private bool HadConstructedParameterFailedConstraintCheck( // formal parameter type. TypeSymbol formalParameterType = method.ParameterTypes[result.Result.BadParameter].TypeSymbol; - formalParameterType.CheckAllConstraints(conversions, location, diagnostics); + formalParameterType.CheckAllConstraints((CSharpCompilation)compilation, conversions, location, diagnostics); return true; } diff --git a/src/Compilers/CSharp/Portable/Symbols/AliasSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/AliasSymbol.cs index 6478e0d2be91f..accc406e43594 100644 --- a/src/Compilers/CSharp/Portable/Symbols/AliasSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/AliasSymbol.cs @@ -304,7 +304,7 @@ internal void CheckConstraints(DiagnosticBag diagnostics) { var corLibrary = this.ContainingAssembly.CorLibrary; var conversions = new TypeConversions(corLibrary); - target.CheckAllConstraints(conversions, _locations[0], diagnostics); + target.CheckAllConstraints(DeclaringCompilation, conversions, _locations[0], diagnostics); } } diff --git a/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs b/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs index 7728775de90bb..f00415d7d7689 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs @@ -457,19 +457,21 @@ private static void CheckOverrideConstraints( /// public static void CheckAllConstraints( this TypeSymbol type, + CSharpCompilation compilation, ConversionsBase conversions, Location location, DiagnosticBag diagnostics) { - type.VisitType(s_checkConstraintsSingleTypeFunc, new CheckConstraintsArgs(type.DeclaringCompilation, conversions, location, diagnostics)); + type.VisitType(s_checkConstraintsSingleTypeFunc, new CheckConstraintsArgs(compilation, conversions, location, diagnostics)); } public static bool CheckAllConstraints( this TypeSymbol type, + CSharpCompilation compilation, ConversionsBase conversions) { var diagnostics = DiagnosticBag.GetInstance(); - type.CheckAllConstraints(conversions, NoLocation.Singleton, diagnostics); + type.CheckAllConstraints(compilation, conversions, NoLocation.Singleton, diagnostics); bool ok = !diagnostics.HasAnyErrors(); diagnostics.Free(); return ok; @@ -914,13 +916,16 @@ private static bool CheckConstraints( diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, containingSymbol.ConstructedFrom(), typeParameter, typeArgument.TypeSymbol))); return false; } - else if (managedKind == ManagedKind.UnmanagedWithGenerics && - currentCompilation is CSharpCompilation csCompilation && - !csCompilation.IsFeatureEnabled(MessageID.IDS_FeatureUnmanagedConstructedTypes)) + else if (managedKind == ManagedKind.UnmanagedWithGenerics) { - var csDiagnostic = Binder.GetFeatureAvailabilityDiagnosticInfo(csCompilation.SyntaxTrees[0], MessageID.IDS_FeatureUnmanagedConstructedTypes); - var typeParameterDiagnostic = new TypeParameterDiagnosticInfo(typeParameter, csDiagnostic); - diagnosticsBuilder.Add(typeParameterDiagnostic); + var csCompilation = (CSharpCompilation)currentCompilation; + var csDiagnosticInfo = Binder.GetLanguageVersionDiagnosticInfo(csCompilation.LanguageVersion, MessageID.IDS_FeatureUnmanagedConstructedTypes); + if (csDiagnosticInfo != null) + { + var typeParameterDiagnosticInfo = new TypeParameterDiagnosticInfo(typeParameter, csDiagnosticInfo); + diagnosticsBuilder.Add(typeParameterDiagnosticInfo); + return false; + } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceCustomEventSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceCustomEventSymbol.cs index fa1606e860ece..95dd99bdecc33 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceCustomEventSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceCustomEventSymbol.cs @@ -183,7 +183,7 @@ internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, { var explicitInterfaceSpecifier = this.ExplicitInterfaceSpecifier; Debug.Assert(explicitInterfaceSpecifier != null); - _explicitInterfaceType.CheckAllConstraints(conversions, new SourceLocation(explicitInterfaceSpecifier.Name), diagnostics); + _explicitInterfaceType.CheckAllConstraints(DeclaringCompilation, conversions, new SourceLocation(explicitInterfaceSpecifier.Name), diagnostics); } if (!_explicitInterfaceImplementations.IsEmpty) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventSymbol.cs index 5a12942208cf9..179562dab4962 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventSymbol.cs @@ -686,7 +686,7 @@ internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, var location = this.Locations[0]; this.CheckModifiersAndType(diagnostics); - this.Type.CheckAllConstraints(conversions, location, diagnostics); + this.Type.CheckAllConstraints(DeclaringCompilation, conversions, location, diagnostics); if (this.Type.ContainsNullableReferenceTypes()) { diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs index 3cf0c2c8e609c..f6f128784dfd9 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs @@ -575,7 +575,7 @@ protected sealed override ConstantValue MakeConstantValue(HashSet 1) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs index e3df2b1ca91c7..169d569299bca 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs @@ -1021,14 +1021,14 @@ internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, { var syntax = this.GetSyntax(); Debug.Assert(syntax.ExplicitInterfaceSpecifier != null); - _explicitInterfaceType.CheckAllConstraints(conversions, new SourceLocation(syntax.ExplicitInterfaceSpecifier.Name), diagnostics); + _explicitInterfaceType.CheckAllConstraints(DeclaringCompilation, conversions, new SourceLocation(syntax.ExplicitInterfaceSpecifier.Name), diagnostics); } - this.ReturnType.CheckAllConstraints(conversions, this.Locations[0], diagnostics); + this.ReturnType.CheckAllConstraints(DeclaringCompilation, conversions, this.Locations[0], diagnostics); foreach (var parameter in this.Parameters) { - parameter.Type.CheckAllConstraints(conversions, parameter.Locations[0], diagnostics); + parameter.Type.CheckAllConstraints(DeclaringCompilation, conversions, parameter.Locations[0], diagnostics); } var implementingPart = this.SourcePartialImplementation; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs index 6548d3f21cfa0..66c16a0047cb4 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs @@ -743,7 +743,7 @@ internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, { var explicitInterfaceSpecifier = GetExplicitInterfaceSpecifier(this.CSharpSyntaxNode); Debug.Assert(explicitInterfaceSpecifier != null); - _explicitInterfaceType.CheckAllConstraints(conversions, new SourceLocation(explicitInterfaceSpecifier.Name), diagnostics); + _explicitInterfaceType.CheckAllConstraints(DeclaringCompilation, conversions, new SourceLocation(explicitInterfaceSpecifier.Name), diagnostics); // Note: we delayed nullable-related checks that could pull on NonNullTypes PropertySymbol overriddenOrImplementedProperty = null; @@ -1389,7 +1389,7 @@ internal override void ForceComplete(SourceLocation locationOpt, CancellationTok foreach (var parameter in this.Parameters) { parameter.ForceComplete(locationOpt, cancellationToken); - parameter.Type.CheckAllConstraints(conversions, parameter.Locations[0], diagnostics); + parameter.Type.CheckAllConstraints(DeclaringCompilation, conversions, parameter.Locations[0], diagnostics); } this.AddDeclarationDiagnostics(diagnostics); @@ -1415,7 +1415,7 @@ internal override void ForceComplete(SourceLocation locationOpt, CancellationTok { var diagnostics = DiagnosticBag.GetInstance(); var conversions = new TypeConversions(this.ContainingAssembly.CorLibrary); - this.Type.CheckAllConstraints(conversions, _location, diagnostics); + this.Type.CheckAllConstraints(DeclaringCompilation, conversions, _location, diagnostics); var type = this.Type.TypeSymbol; if (type.IsRestrictedType(ignoreSpanLikeTypes: true)) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceTypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceTypeParameterSymbol.cs index aff2acf7a46ed..37996fc1d643e 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceTypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceTypeParameterSymbol.cs @@ -270,7 +270,7 @@ private void CheckConstraintTypeConstraints(DiagnosticBag diagnostics) if (!diagnostics.Add(location, useSiteDiagnostics)) { - constraintType.CheckAllConstraints(conversions, location, diagnostics); + constraintType.CheckAllConstraints(DeclaringCompilation, conversions, location, diagnostics); } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbolBase.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbolBase.cs index 25d5d69be297c..6ba561076d578 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbolBase.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbolBase.cs @@ -644,11 +644,11 @@ internal sealed override void AfterAddingTypeMembersChecks(ConversionsBase conve // method name location for any such errors. We'll do the same for return // type errors but for parameter errors, we'll use the parameter location. - this.ReturnType.CheckAllConstraints(conversions, this.Locations[0], diagnostics); + this.ReturnType.CheckAllConstraints(DeclaringCompilation, conversions, this.Locations[0], diagnostics); foreach (var parameter in this.Parameters) { - parameter.Type.CheckAllConstraints(conversions, parameter.Locations[0], diagnostics); + parameter.Type.CheckAllConstraints(DeclaringCompilation, conversions, parameter.Locations[0], diagnostics); } ParameterHelpers.EnsureIsReadOnlyAttributeExists(Parameters, diagnostics, modifyCompilation: true); diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeSymbolWithAnnotations.cs b/src/Compilers/CSharp/Portable/Symbols/TypeSymbolWithAnnotations.cs index 4e6c4276d8dc2..8c31aa6f12543 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypeSymbolWithAnnotations.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypeSymbolWithAnnotations.cs @@ -627,9 +627,9 @@ public bool GetUnificationUseSiteDiagnosticRecursive(ref DiagnosticInfo result, Symbol.GetUnificationUseSiteDiagnosticRecursive(ref result, this.CustomModifiers, owner, ref checkedTypes); } - public void CheckAllConstraints(ConversionsBase conversions, Location location, DiagnosticBag diagnostics) + public void CheckAllConstraints(CSharpCompilation compilation, ConversionsBase conversions, Location location, DiagnosticBag diagnostics) { - TypeSymbol.CheckAllConstraints(conversions, location, diagnostics); + TypeSymbol.CheckAllConstraints(compilation, conversions, location, diagnostics); } public bool IsAtLeastAsVisibleAs(Symbol sym, ref HashSet useSiteDiagnostics) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs index ac74d9c180743..488c64b0239d1 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs @@ -3406,6 +3406,21 @@ public unsafe void M2(MyStruct>* ms) { } "; CreateCompilation(code, options: TestOptions.UnsafeReleaseDll) .VerifyDiagnostics(); + + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular7_3) + .VerifyDiagnostics( + // (16,18): error CS8370: Feature 'unmanaged constructed types' is not available in C# 7.3. Please use language version 8.0 or greater. + // MyStruct> myStruct; + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "InnerStruct").WithArguments("unmanaged constructed types", "8.0").WithLocation(16, 18), + // (17,12): error CS8370: Feature 'unmanaged constructed types' is not available in C# 7.3. Please use language version 8.0 or greater. + // M2(&myStruct); + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "&myStruct").WithArguments("unmanaged constructed types", "8.0").WithLocation(17, 12), + // (20,27): error CS8370: Feature 'unmanaged constructed types' is not available in C# 7.3. Please use language version 8.0 or greater. + // public unsafe void M2(MyStruct>* ms) { } + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "MyStruct>*").WithArguments("unmanaged constructed types", "8.0").WithLocation(20, 27), + // (20,55): error CS8370: Feature 'unmanaged constructed types' is not available in C# 7.3. Please use language version 8.0 or greater. + // public unsafe void M2(MyStruct>* ms) { } + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "ms").WithArguments("unmanaged constructed types", "8.0").WithLocation(20, 55)); } [Fact] From b9e214f8bd4cd9dce89285178761a8dd2f5dfdbc Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Thu, 10 Jan 2019 14:07:00 -0800 Subject: [PATCH 37/40] Add test demonstrating expected behavior around multiple constraint violations --- .../Semantics/GenericConstraintsTests.cs | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs index 488c64b0239d1..406dfdd59cd92 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs @@ -3423,6 +3423,45 @@ public unsafe void M2(MyStruct>* ms) { } Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "ms").WithArguments("unmanaged constructed types", "8.0").WithLocation(20, 55)); } + [Fact] + public void UnmanagedGenericStructMultipleConstraints() + { + // A diagnostic will only be produced for the first violated constraint. + var code = @" +public struct MyStruct where T : unmanaged, System.IDisposable +{ + public T field; +} + +public struct InnerStruct +{ + public U value; +} + +public class C +{ + public unsafe void M() + { + MyStruct> myStruct = default; + _ = myStruct; + } +} +"; + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll) + .VerifyDiagnostics( + // (16,18): error CS0315: The type 'InnerStruct' cannot be used as type parameter 'T' in the generic type or method 'MyStruct'. There is no boxing conversion from 'InnerStruct' to 'System.IDisposable'. + // MyStruct> myStruct = default; + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "InnerStruct").WithArguments("MyStruct", "System.IDisposable", "T", "InnerStruct").WithLocation(16, 18) + ); + + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll, parseOptions: TestOptions.Regular7_3) + .VerifyDiagnostics( + // (16,18): error CS8370: Feature 'unmanaged constructed types' is not available in C# 7.3. Please use language version 8.0 or greater. + // MyStruct> myStruct = default; + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "InnerStruct").WithArguments("unmanaged constructed types", "8.0").WithLocation(16, 18) + ); + } + [Fact] public void UnmanagedGenericConstraintPartialConstructedStruct() { From 86f0984dde917d8c7ea22fddbf374a9823045c97 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Tue, 15 Jan 2019 10:58:59 -0800 Subject: [PATCH 38/40] Fix merge conflicts and test failures --- .../CSharp/Portable/Errors/MessageID.cs | 15 +- .../Source/SourceNamedTypeSymbol_Bases.cs | 7 +- .../Semantics/NullableReferenceTypesTests.cs | 291 +----------------- .../Test/Semantic/Semantics/UnsafeTests.cs | 16 +- 4 files changed, 26 insertions(+), 303 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs index 4dd818df54f4a..ec8392d31938c 100644 --- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs +++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs @@ -165,14 +165,6 @@ internal enum MessageID IDS_FeatureAltInterpolatedVerbatimStrings = MessageBase + 12745, IDS_FeatureCoalesceAssignmentExpression = MessageBase + 12746, IDS_FeatureUnconstrainedTypeParameterInNullCoalescingOperator = MessageBase + 12747, -<<<<<<< HEAD - IDS_InjectedDeclaration = MessageBase + 12748, - IDS_FeatureObjectGenericTypeConstraint = MessageBase + 12749, - IDS_FeatureIndexOperator = MessageBase + 12750, - IDS_FeatureRangeOperator = MessageBase + 12751, - IDS_FeatureAsyncStreams = MessageBase + 12752, - IDS_FeatureUnmanagedConstructedTypes = MessageBase + 12753 -======= IDS_FeatureObjectGenericTypeConstraint = MessageBase + 12748, IDS_FeatureIndexOperator = MessageBase + 12749, IDS_FeatureRangeOperator = MessageBase + 12750, @@ -181,7 +173,7 @@ internal enum MessageID IDS_Disposable = MessageBase + 12753, IDS_FeatureUsingDeclarations = MessageBase + 12754, IDS_FeatureStaticLocalFunctions = MessageBase + 12755, ->>>>>>> upstream/dev16.1-preview1 + IDS_FeatureUnmanagedConstructedTypes = MessageBase + 12756 } // Message IDs may refer to strings that need to be localized. @@ -258,13 +250,10 @@ internal static LanguageVersion RequiredVersion(this MessageID feature) case MessageID.IDS_FeatureIndexOperator: // semantic check case MessageID.IDS_FeatureRangeOperator: // semantic check case MessageID.IDS_FeatureAsyncStreams: -<<<<<<< HEAD - case MessageID.IDS_FeatureUnmanagedConstructedTypes: // semantic check -======= case MessageID.IDS_FeatureRecursivePatterns: case MessageID.IDS_FeatureUsingDeclarations: case MessageID.IDS_FeatureStaticLocalFunctions: ->>>>>>> upstream/dev16.1-preview1 + case MessageID.IDS_FeatureUnmanagedConstructedTypes: // semantic check return LanguageVersion.CSharp8; // C# 7.3 features. diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol_Bases.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol_Bases.cs index 8aa1114a8b298..c37b47043ad52 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol_Bases.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol_Bases.cs @@ -135,16 +135,11 @@ protected override void CheckInterfaces(DiagnosticBag diagnostics) foreach (var pair in interfaces) { -<<<<<<< HEAD - @interface.CheckAllConstraints(DeclaringCompilation, conversions, location, diagnostics); - } -======= MultiDictionary.ValueSet set = pair.Value; ->>>>>>> upstream/dev16.1-preview1 foreach (var @interface in set) { - @interface.CheckAllConstraints(conversions, location, diagnostics); + @interface.CheckAllConstraints(DeclaringCompilation, conversions, location, diagnostics); } if (set.Count > 1) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs index 2b5d4dfe5451f..2655d8c942105 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs @@ -2193,181 +2193,8 @@ class C4 { }"; [Fact] public void Nullable_False_InCSharp7() { -<<<<<<< HEAD - var source = @" -" + NonNullTypesOn() + @" -[module: Microsoft.CodeAnalysis.Embedded] - -[Microsoft.CodeAnalysis.Embedded] -public class C -{ - [Microsoft.CodeAnalysis.Embedded] - public int field = 0; - [Microsoft.CodeAnalysis.Embedded] - void M() { } -} -[Microsoft.CodeAnalysis.Embedded] -interface I { } -"; - var comp = CreateCompilation(source); - comp.VerifyEmitDiagnostics(); - - var type = (NamedTypeSymbol)comp.GlobalNamespace.GetMember("Microsoft.CodeAnalysis.EmbeddedAttribute"); - Assert.NotNull(type); - Assert.Equal(0, type.Arity); - Assert.Equal("System.Attribute", type.BaseTypeNoUseSiteDiagnostics.ToTestDisplayString()); - Assert.True(type.CanBeReferencedByName); - Assert.Equal("Microsoft.CodeAnalysis.EmbeddedAttribute..ctor()", type.Constructors.Single().ToTestDisplayString()); - Assert.Null(type.ContainingType); - Assert.Empty(type.DeclaringSyntaxReferences); - Assert.True(type.HasCodeAnalysisEmbeddedAttribute); - Assert.False(type.HasDeclarativeSecurity); - Assert.False(type.HasSpecialName); - Assert.False(type.HasUnsupportedMetadata); - Assert.Empty(type.Indexers); - Assert.Equal("Microsoft.CodeAnalysis.EmbeddedAttribute..ctor()", type.InstanceConstructors.Single().ToTestDisplayString()); - Assert.False(type.IsAbstract); - Assert.False(type.IsAnonymousType); - Assert.False(type.IsByRefLikeType); - Assert.False(type.IsComImport); - Assert.False(type.IsConditional); - Assert.True(type.IsDefinition); - Assert.False(type.IsExtern); - Assert.False(type.IsGenericType); - Assert.True(type.IsImplicitlyDeclared); - Assert.False(type.IsInterface); - Assert.Equal(ManagedKind.Managed, type.ManagedKind); - Assert.False(type.IsNamespace); - Assert.True(type.IsReferenceType); - Assert.True(type.IsSealed); - Assert.False(type.IsSerializable); - Assert.False(type.IsStatic); - Assert.False(type.IsTupleType); - Assert.True(type.IsType); - Assert.Equal(SymbolKind.NamedType, type.Kind); - Assert.Equal("C#", type.Language); - Assert.Empty(type.Locations); - Assert.Equal(new[] { ".ctor" }, type.MemberNames); - Assert.False(type.MightContainExtensionMethods); - Assert.Equal("EmbeddedAttribute", type.Name); - Assert.Null(type.NonNullTypes); - Assert.Equal(SpecialType.None, type.SpecialType); - Assert.Empty(type.StaticConstructors); - Assert.Equal(TypeKind.Class, type.TypeKind); - - var codeAnalysis = type.ContainingNamespace; - verifyEmptyNamespace(codeAnalysis, "CodeAnalysis"); - - var microsoft = codeAnalysis.ContainingNamespace; - verifyEmptyNamespace(microsoft, "Microsoft"); - - Assert.True(microsoft.ContainingNamespace.IsGlobalNamespace); - - var type2 = comp.GetWellKnownType(WellKnownType.Microsoft_CodeAnalysis_EmbeddedAttribute); - Assert.True(type.Equals(type2)); - Assert.Equal(Accessibility.Internal, type.DeclaredAccessibility); - - void verifyEmptyNamespace(INamespaceSymbol symbol, string expectedName) - { - Assert.Equal(expectedName, symbol.Name); - Assert.Empty(symbol.DeclaringSyntaxReferences); - Assert.Empty(symbol.Locations); - Assert.True(symbol.IsImplicitlyDeclared); - Assert.Equal(NamespaceKind.Module, symbol.NamespaceKind); - } - } - - [Fact] - public void NonNullTypesAttribute_Injected_InCSharp7() - { - var comp = CreateCompilation("", options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular7); - comp.VerifyDiagnostics( - // error CS8630: Invalid 'Nullable' value: 'True' for C# 7.0. Please use language version 8.0 or greater. - Diagnostic(ErrorCode.ERR_NullableOptionNotAvailable).WithArguments("Nullable", "True", "7.0", "8.0").WithLocation(1, 1) - ); - - Assert.True(comp.SourceModule.NonNullTypes); - Assert.Empty(comp.SourceModule.GetAttributes()); - - var type = (NamedTypeSymbol)comp.GlobalNamespace.GetMember("System.Runtime.CompilerServices.NonNullTypesAttribute"); - Assert.NotNull(type); - Assert.Equal(0, type.Arity); - Assert.Equal("System.Attribute", type.BaseTypeNoUseSiteDiagnostics.ToTestDisplayString()); - Assert.True(type.CanBeReferencedByName); - Assert.Equal("System.Runtime.CompilerServices.NonNullTypesAttribute..ctor([System.Boolean flag = true])", type.Constructors.Single().ToTestDisplayString()); - Assert.Null(type.ContainingType); - Assert.Empty(type.DeclaringSyntaxReferences); - Assert.True(type.HasCodeAnalysisEmbeddedAttribute); - Assert.False(type.HasDeclarativeSecurity); - Assert.False(type.HasSpecialName); - Assert.False(type.HasUnsupportedMetadata); - Assert.Empty(type.Indexers); - Assert.Equal("System.Runtime.CompilerServices.NonNullTypesAttribute..ctor([System.Boolean flag = true])", type.InstanceConstructors.Single().ToTestDisplayString()); - Assert.False(type.IsAbstract); - Assert.False(type.IsAnonymousType); - Assert.False(type.IsByRefLikeType); - Assert.False(type.IsComImport); - Assert.False(type.IsConditional); - Assert.True(type.IsDefinition); - Assert.False(type.IsExtern); - Assert.False(type.IsGenericType); - Assert.True(type.IsImplicitlyDeclared); - Assert.False(type.IsInterface); - Assert.Equal(ManagedKind.Managed, type.ManagedKind); - Assert.False(type.IsNamespace); - Assert.True(type.IsReferenceType); - Assert.True(type.IsSealed); - Assert.False(type.IsSerializable); - Assert.False(type.IsStatic); - Assert.False(type.IsTupleType); - Assert.True(type.IsType); - Assert.Equal(SymbolKind.NamedType, type.Kind); - Assert.Equal("C#", type.Language); - Assert.Empty(type.Locations); - Assert.Equal(new[] { ".ctor" }, type.MemberNames); - Assert.False(type.MightContainExtensionMethods); - Assert.Equal("NonNullTypesAttribute", type.Name); - Assert.True(type.NonNullTypes); - Assert.Equal(SpecialType.None, type.SpecialType); - Assert.Empty(type.StaticConstructors); - Assert.Equal(TypeKind.Class, type.TypeKind); - - var compilerServices = type.ContainingNamespace; - verifyEmptyNamespace(compilerServices, "CompilerServices"); - - var runtime = compilerServices.ContainingNamespace; - verifyEmptyNamespace(runtime, "Runtime"); - - var system = runtime.ContainingNamespace; - verifyEmptyNamespace(system, "System"); - - Assert.True(system.ContainingNamespace.IsGlobalNamespace); - - var type2 = comp.GetWellKnownType(WellKnownType.System_Runtime_CompilerServices_NonNullTypesAttribute); - Assert.True(type.Equals(type2)); - Assert.Equal(Accessibility.Internal, type.DeclaredAccessibility); - - // https://github.com/dotnet/roslyn/issues/29683 CSharpCompilation.AbstractSymbolSearcher needs to inject namespaces and types too - //Assert.True(comp.ContainsSymbolsWithName("NonNullTypesAttribute", SymbolFilter.Type)); - //Assert.Equal("System.Runtime.CompilerServices.NonNullTypesAttribute", comp.GetSymbolsWithName("NonNullTypesAttribute", SymbolFilter.Type).Single().ToTestDisplayString()); - //Assert.Equal("System.Runtime.CompilerServices.NonNullTypesAttribute", comp.GetSymbolsWithName(n => n == "NonNullTypesAttribute", SymbolFilter.Type).Single().ToTestDisplayString()); - - //Assert.True(comp.ContainsSymbolsWithName("EmbeddedAttribute", SymbolFilter.Type)); - //Assert.Equal("Microsoft.CodeAnalysis.EmbeddedAttribute", comp.GetSymbolsWithName("EmbeddedAttribute", SymbolFilter.Type).Single().ToTestDisplayString()); - //Assert.Equal("Microsoft.CodeAnalysis.EmbeddedAttribute", comp.GetSymbolsWithName(n => n == "EmbeddedAttribute", SymbolFilter.Type).Single().ToTestDisplayString()); - - void verifyEmptyNamespace(INamespaceSymbol symbol, string expectedName) - { - Assert.Equal(expectedName, symbol.Name); - Assert.Empty(symbol.DeclaringSyntaxReferences); - Assert.Empty(symbol.Locations); - Assert.True(symbol.IsImplicitlyDeclared); - Assert.Equal(NamespaceKind.Module, symbol.NamespaceKind); - } -======= var comp = CreateCompilation("", options: WithNonNullTypesFalse(), parseOptions: TestOptions.Regular7); comp.VerifyDiagnostics(); ->>>>>>> upstream/dev16.1-preview1 } [Fact] @@ -53311,27 +53138,27 @@ class D }"; var comp = CreateCompilation(new[] { source }, references: new[] { ref0 }); comp.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.WRN_UninitializedNonNullableField).Verify( - // (4,24): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. - // class B1 where T : A? { } - Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(4, 24), // (15,9): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // B1 F3; // 2 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(15, 9), + // (4,24): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. + // class B1 where T : A? { } + Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(4, 24), // (17,9): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // B2 F5; // 3 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(17, 9), // (19,9): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // B3 F7; // 4 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(19, 9), + // (35,12): warning CS8631: The type 'A?' cannot be used as type parameter 'T' in the generic type or method 'B4'. Nullability of type argument 'A?' doesn't match constraint type 'A'. + // B4 G9; // 7 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "G9").WithArguments("B4", "A", "T", "A?").WithLocation(35, 12), // (21,9): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // B4 F9; // 5 and 6 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(21, 9), // (13,9): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // B0 F1; // 1 - Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(13, 9), - // (35,8): warning CS8631: The type 'A?' cannot be used as type parameter 'T' in the generic type or method 'B4'. Nullability of type argument 'A?' doesn't match constraint type 'A'. - // B4 G9; // 7 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A?").WithArguments("B4", "A", "T", "A?").WithLocation(35, 8) + Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(13, 9) ); } @@ -53403,15 +53230,15 @@ class D // (13,16): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. // B0> F1; // 1 Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(13, 16), - // (30,8): warning CS8631: The type 'A' cannot be used as type parameter 'T' in the generic type or method 'B1'. Nullability of type argument 'A' doesn't match constraint type 'A'. + // (30,19): warning CS8631: The type 'A' cannot be used as type parameter 'T' in the generic type or method 'B1'. Nullability of type argument 'A' doesn't match constraint type 'A'. // B1> G4; // 7 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A").WithArguments("B1", "A", "T", "A").WithLocation(30, 8), - // (34,8): warning CS8631: The type 'A' cannot be used as type parameter 'T' in the generic type or method 'B3'. Nullability of type argument 'A' doesn't match constraint type 'A'. + Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "G4").WithArguments("B1", "A", "T", "A").WithLocation(30, 19), + // (34,19): warning CS8631: The type 'A' cannot be used as type parameter 'T' in the generic type or method 'B3'. Nullability of type argument 'A' doesn't match constraint type 'A'. // B3> G8; // 8 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A").WithArguments("B3", "A", "T", "A").WithLocation(34, 8), - // (35,8): warning CS8631: The type 'A' cannot be used as type parameter 'T' in the generic type or method 'B4'. Nullability of type argument 'A' doesn't match constraint type 'A'. + Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "G8").WithArguments("B3", "A", "T", "A").WithLocation(34, 19), + // (35,20): warning CS8631: The type 'A' cannot be used as type parameter 'T' in the generic type or method 'B4'. Nullability of type argument 'A' doesn't match constraint type 'A'. // B4> G9; // 9 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A").WithArguments("B4", "A", "T", "A").WithLocation(35, 8) + Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "G9").WithArguments("B4", "A", "T", "A").WithLocation(35, 20) ); } @@ -64430,48 +64257,6 @@ void M0(U x0) y0.ToString(); } } -<<<<<<< HEAD -" + NonNullTypesOn() + @" -class D -{ - B0 G1; - B0 G2; - B1 G3; - B1 G4; - B2 G5; - B2 G6; - B3 G7; - B3 G8; - B4 G9; // 7 - B4 G10; -}"; - var comp = CreateCompilation(new[] { source }, references: new[] { ref0 }); - comp.VerifyDiagnostics( - // (4,24): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. - // class B1 where T : A? { } - Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(4, 24), - // (15,9): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. - // B1 F3; // 2 - Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(15, 9), - // (17,9): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. - // B2 F5; // 3 - Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(17, 9), - // (19,9): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. - // B3 F7; // 4 - Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(19, 9), - // (21,9): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. - // B4 F9; // 5 and 6 - Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(21, 9), - // (13,9): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. - // B0 F1; // 1 - Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(13, 9), - // (21,12): warning CS8631: The type 'A?' cannot be used as type parameter 'T' in the generic type or method 'B4'. Nullability of type argument 'A?' doesn't match constraint type 'A'. - // B4 F9; // 5 and 6 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "F9").WithArguments("B4", "A", "T", "A?").WithLocation(21, 12), - // (35,12): warning CS8631: The type 'A?' cannot be used as type parameter 'T' in the generic type or method 'B4'. Nullability of type argument 'A?' doesn't match constraint type 'A'. - // B4 G9; // 7 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "G9").WithArguments("B4", "A", "T", "A?").WithLocation(35, 12) -======= "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( @@ -64481,7 +64266,6 @@ class D // (8,9): warning CS8602: Possible dereference of a null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(8, 9) ->>>>>>> upstream/dev16.1-preview1 ); } @@ -64499,54 +64283,6 @@ void M0(U x0) y0.ToString(); } } -<<<<<<< HEAD -" + NonNullTypesOn() + @" -class D -{ - B0> G1; - B0> G2; - B1> G3; - B1> G4; // 7 - B2> G5; - B2> G6; - B3> G7; - B3> G8; // 8 - B4> G9; // 9 - B4> G10; -}"; - var comp = CreateCompilation(new[] { source }, references: new[] { ref0 }); - comp.VerifyDiagnostics( - // (4,31): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. - // class B1 where T : A { } - Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(4, 31), - // (15,16): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. - // B1> F3; // 2 - Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(15, 16), - // (17,16): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. - // B2> F5; // 3 - Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(17, 16), - // (19,16): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. - // B3> F7; // 4 - Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(19, 16), - // (21,16): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. - // B4> F9; // 5 and 6 - Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(21, 16), - // (13,16): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context. - // B0> F1; // 1 - Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(13, 16), - // (21,20): warning CS8631: The type 'A' cannot be used as type parameter 'T' in the generic type or method 'B4'. Nullability of type argument 'A' doesn't match constraint type 'A'. - // B4> F9; // 5 and 6 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "F9").WithArguments("B4", "A", "T", "A").WithLocation(21, 20), - // (30,19): warning CS8631: The type 'A' cannot be used as type parameter 'T' in the generic type or method 'B1'. Nullability of type argument 'A' doesn't match constraint type 'A'. - // B1> G4; // 7 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "G4").WithArguments("B1", "A", "T", "A").WithLocation(30, 19), - // (34,19): warning CS8631: The type 'A' cannot be used as type parameter 'T' in the generic type or method 'B3'. Nullability of type argument 'A' doesn't match constraint type 'A'. - // B3> G8; // 8 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "G8").WithArguments("B3", "A", "T", "A").WithLocation(34, 19), - // (35,20): warning CS8631: The type 'A' cannot be used as type parameter 'T' in the generic type or method 'B4'. Nullability of type argument 'A' doesn't match constraint type 'A'. - // B4> G9; // 9 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "G9").WithArguments("B4", "A", "T", "A").WithLocation(35, 20) -======= "; CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( @@ -64556,7 +64292,6 @@ class D // (9,9): warning CS8602: Possible dereference of a null reference. // y0.ToString(); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y0").WithLocation(9, 9) ->>>>>>> upstream/dev16.1-preview1 ); } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs index 7fa232313cd57..d0743f7a2ad3a 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs @@ -3073,8 +3073,10 @@ unsafe void M() where U : unmanaged var s1 = new S1(); var s2 = new S2(); var s3 = new S3(); - var s4 = new S4(); - var s5 = new S4(); + var s4_0 = new S4(); + var s4_1 = new S4(); + var s4_2 = new S4(); + var s5 = new S5(); var i0 = 0; var e1 = new E1(); var o1 = new object(); @@ -3094,13 +3096,15 @@ unsafe void M() where U : unmanaged // sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, or bool. // Any enum_type. // Any pointer_type. - // Any user-defined struct_type that is not a constructed type and contains fields of unmanaged_types only. + // Any user-defined struct_type that contains fields of unmanaged_types only. // A type parameter with an unmanaged constraint Assert.True(getLocalType("s1").IsUnmanagedType); Assert.True(getLocalType("s2").IsUnmanagedType); Assert.False(getLocalType("s3").IsUnmanagedType); - Assert.False(getLocalType("s4").IsUnmanagedType); - Assert.False(getLocalType("s5").IsUnmanagedType); + Assert.True(getLocalType("s4_0").IsUnmanagedType); + Assert.False(getLocalType("s4_1").IsUnmanagedType); + Assert.True(getLocalType("s4_2").IsUnmanagedType); + Assert.True(getLocalType("s5").IsUnmanagedType); Assert.True(getLocalType("i0").IsUnmanagedType); Assert.True(getLocalType("e1").IsUnmanagedType); Assert.False(getLocalType("o1").IsUnmanagedType); @@ -3110,7 +3114,7 @@ unsafe void M() where U : unmanaged Assert.True(getLocalType("p1").IsUnmanagedType); Assert.False(getLocalType("a1").IsUnmanagedType); Assert.False(getLocalType("a2").IsUnmanagedType); - Assert.False(getLocalType("t2").IsUnmanagedType); + Assert.True(getLocalType("t2").IsUnmanagedType); ITypeSymbol getLocalType(string name) { From 8f97bd95c2941ee7ca3614dfd658ffb54e847ad2 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Tue, 22 Jan 2019 13:45:49 -0800 Subject: [PATCH 39/40] Finish testing for unmanaged constructed types (#32591) * Test generic struct with private field from metadata * Expand generic ref struct testing * Reference generic unmanaged tuple issue in relevant tests * Add fixed size buffer tests * Add IsManagedType checks in test cases involving circular structs * Verify that unsafe scenarios disallowed in 7.3 are allowed latest * Test IsManagedType API in more recursive scenarios --- .../Semantics/GenericConstraintsTests.cs | 100 +++++++++--- .../Test/Semantic/Semantics/UnsafeTests.cs | 144 ++++++++++++++++++ 2 files changed, 225 insertions(+), 19 deletions(-) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs index 98161a6a49340..babc6584249a3 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs @@ -3542,8 +3542,10 @@ public unsafe struct YourStruct where T : unmanaged public MyStruct* field; } "; - CreateCompilation(code, options: TestOptions.UnsafeReleaseDll) - .VerifyDiagnostics(); + var compilation = CreateCompilation(code, options: TestOptions.UnsafeReleaseDll); + compilation.VerifyDiagnostics(); + Assert.False(compilation.GetMember("MyStruct").IsManagedType); + Assert.False(compilation.GetMember("YourStruct").IsManagedType); } [Fact] @@ -3560,8 +3562,11 @@ public unsafe struct YourStruct public MyStruct* field; } "; - CreateCompilation(code, options: TestOptions.UnsafeReleaseDll) - .VerifyDiagnostics(); + var compilation = CreateCompilation(code, options: TestOptions.UnsafeReleaseDll); + compilation.VerifyDiagnostics(); + Assert.False(compilation.GetMember("MyStruct").IsManagedType); + Assert.False(compilation.GetMember("YourStruct").IsManagedType); + } [Fact] @@ -3578,11 +3583,14 @@ public struct YourStruct where T : unmanaged public T field; } "; - CreateCompilation(code, options: TestOptions.UnsafeReleaseDll) - .VerifyDiagnostics( + var compilation = CreateCompilation(code, options: TestOptions.UnsafeReleaseDll); + compilation.VerifyDiagnostics( // (4,46): error CS0523: Struct member 'MyStruct.field' of type 'YourStruct>>' causes a cycle in the struct layout // public YourStruct>> field; Diagnostic(ErrorCode.ERR_StructLayoutCycle, "field").WithArguments("MyStruct.field", "YourStruct>>").WithLocation(4, 46)); + + Assert.False(compilation.GetMember("MyStruct").IsManagedType); + Assert.False(compilation.GetMember("YourStruct").IsManagedType); } [Fact] @@ -3599,8 +3607,8 @@ public struct YourStruct where T : unmanaged public MyStruct field; } "; - CreateCompilation(code, options: TestOptions.UnsafeReleaseDll) - .VerifyDiagnostics( + var compilation = CreateCompilation(code, options: TestOptions.UnsafeReleaseDll); + compilation.VerifyDiagnostics( // (4,26): error CS0523: Struct member 'MyStruct.field' of type 'YourStruct' causes a cycle in the struct layout // public YourStruct field; Diagnostic(ErrorCode.ERR_StructLayoutCycle, "field").WithArguments("MyStruct.field", "YourStruct").WithLocation(4, 26), @@ -3610,6 +3618,9 @@ public struct YourStruct where T : unmanaged // (9,24): error CS0523: Struct member 'YourStruct.field' of type 'MyStruct' causes a cycle in the struct layout // public MyStruct field; Diagnostic(ErrorCode.ERR_StructLayoutCycle, "field").WithArguments("YourStruct.field", "MyStruct").WithLocation(9, 24)); + + Assert.False(compilation.GetMember("MyStruct").IsManagedType); + Assert.False(compilation.GetMember("YourStruct").IsManagedType); } [Fact] @@ -3627,11 +3638,14 @@ public struct YourStruct where T : unmanaged public T field; } "; - CreateCompilation(code, options: TestOptions.UnsafeReleaseDll) - .VerifyDiagnostics( + var compilation = CreateCompilation(code, options: TestOptions.UnsafeReleaseDll); + compilation.VerifyDiagnostics( // (4,46): error CS0523: Struct member 'MyStruct.field' of type 'YourStruct>>' causes a cycle in the struct layout // public YourStruct>> field; Diagnostic(ErrorCode.ERR_StructLayoutCycle, "field").WithArguments("MyStruct.field", "YourStruct>>").WithLocation(4, 46)); + + Assert.True(compilation.GetMember("MyStruct").IsManagedType); + Assert.False(compilation.GetMember("YourStruct").IsManagedType); } [Fact] @@ -3649,14 +3663,17 @@ public struct YourStruct where T : unmanaged public T field; } "; - CreateCompilation(code, options: TestOptions.UnsafeReleaseDll) - .VerifyDiagnostics( + var compilation = CreateCompilation(code, options: TestOptions.UnsafeReleaseDll); + compilation.VerifyDiagnostics( // (4,46): error CS0523: Struct member 'MyStruct.field' of type 'YourStruct>>' causes a cycle in the struct layout // public YourStruct>> field; Diagnostic(ErrorCode.ERR_StructLayoutCycle, "field").WithArguments("MyStruct.field", "YourStruct>>").WithLocation(4, 46), // (4,46): error CS8377: The type 'MyStruct>' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'YourStruct' // public YourStruct>> field; Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "field").WithArguments("YourStruct", "T", "MyStruct>").WithLocation(4, 46)); + + Assert.True(compilation.GetMember("MyStruct").IsManagedType); + Assert.False(compilation.GetMember("YourStruct").IsManagedType); } [Fact] @@ -3674,14 +3691,17 @@ public struct YourStruct where T : unmanaged public string s; } "; - CreateCompilation(code, options: TestOptions.UnsafeReleaseDll) - .VerifyDiagnostics( + var compilation = CreateCompilation(code, options: TestOptions.UnsafeReleaseDll); + compilation.VerifyDiagnostics( // (4,46): error CS0523: Struct member 'MyStruct.field' of type 'YourStruct>>' causes a cycle in the struct layout // public YourStruct>> field; Diagnostic(ErrorCode.ERR_StructLayoutCycle, "field").WithArguments("MyStruct.field", "YourStruct>>").WithLocation(4, 46), // (4,46): error CS8377: The type 'MyStruct>' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'YourStruct' // public YourStruct>> field; Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "field").WithArguments("YourStruct", "T", "MyStruct>").WithLocation(4, 46)); + + Assert.True(compilation.GetMember("MyStruct").IsManagedType); + Assert.True(compilation.GetMember("YourStruct").IsManagedType); } [Fact] @@ -3760,7 +3780,11 @@ public struct Z { public X field; }"; - CreateCompilation(code).VerifyDiagnostics(); + var compilation = CreateCompilation(code); + compilation.VerifyDiagnostics(); + + Assert.False(compilation.GetMember("X").IsManagedType); + Assert.False(compilation.GetMember("Z").IsManagedType); } [Fact] @@ -3784,6 +3808,8 @@ public static unsafe void Test() // var ptr = &ms; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "&ms").WithArguments("unmanaged constructed types", "8.0").WithLocation(9, 19) ); + + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(); } [Fact] @@ -3815,6 +3841,8 @@ public static unsafe void Test(MyClass c) // fixed (MyStruct* ptr = &c.ms) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "&c.ms").WithArguments("unmanaged constructed types", "8.0").WithLocation(12, 37) ); + + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(); } [Fact] @@ -3837,6 +3865,8 @@ public static unsafe void Test() // var size = sizeof(MyStruct); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "sizeof(MyStruct)").WithArguments("unmanaged constructed types", "8.0").WithLocation(8, 20) ); + + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(); } [Fact] @@ -3859,6 +3889,8 @@ public static unsafe void Test() // var arr = stackalloc[] { new MyStruct() }; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "stackalloc[] { new MyStruct() }").WithArguments("unmanaged constructed types", "8.0").WithLocation(8, 19) ); + + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(); } [Fact] @@ -3881,6 +3913,8 @@ public static unsafe void Test() // var arr = stackalloc MyStruct[4]; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "MyStruct").WithArguments("unmanaged constructed types", "8.0").WithLocation(8, 30) ); + + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(); } [Fact] @@ -3903,9 +3937,11 @@ public unsafe struct OtherStruct // public MyStruct* ms; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "MyStruct*").WithArguments("unmanaged constructed types", "8.0").WithLocation(9, 12) ); + + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(); } - [Fact] + [Fact, WorkItem(32103, "https://github.com/dotnet/roslyn/issues/32103")] public void StructContainingTuple_Unmanaged_RequiresCSharp8() { var code = @" @@ -3934,11 +3970,11 @@ public void M2() // M<(int, int)>(); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "M<(int, int)>").WithArguments("unmanaged constructed types", "8.0").WithLocation(14, 9) ); - + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(); } - [Fact] + [Fact, WorkItem(32103, "https://github.com/dotnet/roslyn/issues/32103")] public void StructContainingGenericTuple_Unmanaged() { var code = @" @@ -3981,7 +4017,7 @@ public void M3() } [Fact] - public void GenericRefStructAddressOf() + public void GenericRefStructAddressOf_01() { var code = @" public ref struct MyStruct @@ -4006,6 +4042,32 @@ public static unsafe void Main() expectedOutput: "42"); } + [Fact] + public void GenericRefStructAddressOf_02() + { + var code = @" +public ref struct MyStruct +{ + public T field; +} + +public class MyClass +{ + public unsafe void M() + { + var ms = new MyStruct(); + var ptr = &ms; + } +} +"; + + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics( + // (12,19): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('MyStruct') + // var ptr = &ms; + Diagnostic(ErrorCode.ERR_ManagedAddr, "&ms").WithArguments("MyStruct").WithLocation(12, 19) + ); + } + [Fact] public void GenericStructFixedStatement() { diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs index d0743f7a2ad3a..c759325e465a9 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs @@ -85,6 +85,91 @@ unsafe void M(byte* p) Diagnostic(ErrorCode.WRN_UnifyReferenceMajMin).WithArguments("mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "assembly1", "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "mscorlib").WithLocation(1, 1)); } + [Fact] + public void FixedSizeBuffer_GenericStruct_01() + { + var code = @" +unsafe struct MyStruct +{ + public fixed char buf[16]; + public static void M() + { + var ms = new MyStruct(); + var ptr = &ms; + } +} +"; + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(); + } + + [Fact] + public void FixedSizeBuffer_GenericStruct_02() + { + var code = @" +unsafe struct MyStruct +{ + public fixed T buf[16]; + public static void M() + { + var ms = new MyStruct(); + var ptr = &ms; + } +} +"; + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics( + // (4,18): error CS1663: Fixed size buffer type must be one of the following: bool, byte, short, int, long, char, sbyte, ushort, uint, ulong, float or double + // public fixed T buf[16]; + Diagnostic(ErrorCode.ERR_IllegalFixedType, "T").WithLocation(4, 18) + ); + } + + [Fact] + public void FixedSizeBuffer_GenericStruct_03() + { + var code = @" +unsafe struct MyStruct where T : unmanaged +{ + public fixed T buf[16]; + public static void M() + { + var ms = new MyStruct(); + var ptr = &ms; + } +} +"; + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics( + // (4,18): error CS1663: Fixed size buffer type must be one of the following: bool, byte, short, int, long, char, sbyte, ushort, uint, ulong, float or double + // public fixed T buf[16]; + Diagnostic(ErrorCode.ERR_IllegalFixedType, "T").WithLocation(4, 18) + ); + } + + [Fact] + public void FixedSizeBuffer_GenericStruct_04() + { + var code = @" +public unsafe struct MyStruct +{ + public T field; +} + +unsafe struct OuterStruct +{ + public fixed MyStruct buf[16]; + public static void M() + { + var os = new OuterStruct(); + var ptr = &os; + } +} +"; + CreateCompilation(code, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics( + // (9,18): error CS1663: Fixed size buffer type must be one of the following: bool, byte, short, int, long, char, sbyte, ushort, uint, ulong, float or double + // public fixed MyStruct buf[16]; + Diagnostic(ErrorCode.ERR_IllegalFixedType, "MyStruct").WithLocation(9, 18) + ); + } + [Fact] public void CompilationNotUnsafe1() { @@ -3125,6 +3210,65 @@ ITypeSymbol getLocalType(string name) } } + [Fact] + public void GenericStructPrivateFieldInMetadata() + { + var externalCode = @" +public struct External +{ + private T field; +} +"; + var metadata = CreateCompilation(externalCode).EmitToImageReference(); + + var code = @" +public class C +{ + public unsafe void M() where T : unmanaged + { + var good = new External(); + var goodPtr = &good; + + var good2 = new External(); + var goodPtr2 = &good2; + + var bad = new External(); + var badPtr = &bad; + + var bad2 = new External(); + var badPtr2 = &bad2; + } +} +"; + var tree = SyntaxFactory.ParseSyntaxTree(code, TestOptions.Regular); + var compilation = CreateCompilation(tree, new[] { metadata }, TestOptions.UnsafeReleaseDll); + + compilation.VerifyDiagnostics( + // (13,22): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('External') + // var badPtr = &bad; + Diagnostic(ErrorCode.ERR_ManagedAddr, "&bad").WithArguments("External").WithLocation(13, 22), + // (16,23): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('External') + // var badPtr2 = &bad2; + Diagnostic(ErrorCode.ERR_ManagedAddr, "&bad2").WithArguments("External").WithLocation(16, 23) + ); + + var model = compilation.GetSemanticModel(tree); + var root = tree.GetRoot(); + + Assert.True(getLocalType("good").IsUnmanagedType); + Assert.True(getLocalType("good2").IsUnmanagedType); + Assert.False(getLocalType("bad").IsUnmanagedType); + Assert.False(getLocalType("bad2").IsUnmanagedType); + + ITypeSymbol getLocalType(string name) + { + var decl = root.DescendantNodes() + .OfType() + .Single(n => n.Identifier.ValueText == name); + return ((ILocalSymbol)model.GetDeclaredSymbol(decl)).Type; + } + } + #endregion IsManagedType #region AddressOf operand kinds From 8ccfd1ed7f67b736e79707cb561a60770ed54a7b Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Tue, 22 Jan 2019 14:14:45 -0800 Subject: [PATCH 40/40] Fix merge conflicts --- .../Symbols/Source/SourceMemberFieldSymbol.cs | 7 +------ .../Semantics/GenericConstraintsTests.cs | 16 ---------------- .../Test/Semantic/Semantics/UnsafeTests.cs | 12 ------------ 3 files changed, 1 insertion(+), 34 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs index 407e4789b2c5b..b17ed13e2ddf2 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs @@ -574,14 +574,9 @@ protected sealed override ConstantValue MakeConstantValue(HashSet>>>>>> upstream/dev16.1-preview1 + Type.CheckAllConstraints(DeclaringCompilation, conversions.WithNullability(includeNullability), ErrorLocation, diagnostics); base.AfterAddingTypeMembersChecks(conversions, diagnostics); } } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs index b7ca398e3e61c..a1b45b6a7666f 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs @@ -3269,7 +3269,6 @@ void Test() Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "UnmanagedWithInterface").WithArguments("C.UnmanagedWithInterface(T*)", "System.IDisposable", "T", "int").WithLocation(20, 9)); } -<<<<<<< HEAD [Fact] public void UnmanagedGenericStructPointer() { @@ -3768,12 +3767,8 @@ .locals init (MyStruct V_0) //ms .VerifyIL("MyStruct.Test", il); } - [Fact] - public void CircularGenericUnmanagedInstantation() -======= [Fact, WorkItem(31439, "https://github.com/dotnet/roslyn/issues/31439")] public void CircularTypeArgumentUnmanagedConstraint() ->>>>>>> upstream/dev16.1-preview1 { var code = @" public struct X @@ -3784,7 +3779,6 @@ public struct X public struct Z { public X field; -<<<<<<< HEAD }"; var compilation = CreateCompilation(code); compilation.VerifyDiagnostics(); @@ -4131,15 +4125,5 @@ public static unsafe void Main() Diagnostic(ErrorCode.ERR_FixedNotNeeded, "&ms.field").WithLocation(12, 27) ); } -======= -} -"; - CreateCompilation(code).VerifyDiagnostics( - // (9,17): error CS8377: The type 'Z' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'X' - // public X field; - Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "field").WithArguments("X", "T", "Z").WithLocation(9, 17) - ); - } ->>>>>>> upstream/dev16.1-preview1 } } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs index 0498560c89141..cbacf377f529d 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/UnsafeTests.cs @@ -361,17 +361,6 @@ unsafe class C "; var compilation = CreateCompilation(text, options: TestOptions.UnsafeReleaseDll); -<<<<<<< HEAD - compilation.GetDiagnostics() - .Where(d => d.Severity == DiagnosticSeverity.Error) - .Verify( - // (8,13): error CS0306: The type 'int*' may not be used as a type argument - // C f4; - Diagnostic(ErrorCode.ERR_BadTypeArgument, "f4").WithArguments("int*").WithLocation(8, 13), - // (9,14): error CS0306: The type 'int**' may not be used as a type argument - // C f5; - Diagnostic(ErrorCode.ERR_BadTypeArgument, "f5").WithArguments("int**").WithLocation(9, 14)); -======= compilation.VerifyDiagnostics( // (8,13): error CS0306: The type 'int*' may not be used as a type argument // C f4; @@ -396,7 +385,6 @@ unsafe class C Diagnostic(ErrorCode.WRN_UnreferencedField, "f6").WithArguments("C.f6"), // (11,17): warning CS0169: The field 'C.f7' is never used Diagnostic(ErrorCode.WRN_UnreferencedField, "f7").WithArguments("C.f7")); ->>>>>>> upstream/dev16.1-preview1 var type = compilation.GlobalNamespace.GetMember("C");