From fcacbc5529a6cf942ee42bddf2088820432e84d3 Mon Sep 17 00:00:00 2001 From: Omar Tawfik Date: Tue, 23 Jan 2018 17:58:47 -0800 Subject: [PATCH 01/13] Support System.Enum as a valid generic type constraint (#24199) * Support System.Enum as a valid generic type constraint * More tests * More feedback * More tests * More tests --- .../Portable/Binder/Binder_Constraints.cs | 15 +- .../Portable/CSharpResources.Designer.cs | 9 + .../CSharp/Portable/CSharpResources.resx | 6 +- .../CSharp/Portable/Errors/ErrorCode.cs | 2 +- .../CSharp/Portable/Errors/MessageID.cs | 2 + .../Portable/xlf/CSharpResources.cs.xlf | 5 + .../Portable/xlf/CSharpResources.de.xlf | 5 + .../Portable/xlf/CSharpResources.es.xlf | 5 + .../Portable/xlf/CSharpResources.fr.xlf | 5 + .../Portable/xlf/CSharpResources.it.xlf | 5 + .../Portable/xlf/CSharpResources.ja.xlf | 5 + .../Portable/xlf/CSharpResources.ko.xlf | 5 + .../Portable/xlf/CSharpResources.pl.xlf | 5 + .../Portable/xlf/CSharpResources.pt-BR.xlf | 5 + .../Portable/xlf/CSharpResources.ru.xlf | 5 + .../Portable/xlf/CSharpResources.tr.xlf | 5 + .../Portable/xlf/CSharpResources.zh-Hans.xlf | 5 + .../Portable/xlf/CSharpResources.zh-Hant.xlf | 5 + .../CSharp/Test/Emit/CodeGen/CodeGenTests.cs | 32 + .../Semantics/GenericConstraintsTests.cs | 583 ++++++++++++++++++ .../SymbolDisplay/SymbolDisplayTests.cs | 13 + .../Test/Symbol/Symbols/SymbolErrorTests.cs | 4 +- .../SymbolsTests/GenericConstraintTests.vb | 35 ++ .../SymbolCompletionProviderTests.cs | 9 + .../UpgradeProject/UpgradeProjectTests.cs | 15 +- .../QuickInfo/SemanticQuickInfoSourceTests.cs | 12 + 26 files changed, 791 insertions(+), 11 deletions(-) create mode 100644 src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs index 12eea0080e2d2..10d5b6ea9f9fe 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs @@ -171,9 +171,13 @@ private TypeParameterConstraintClause BindTypeParameterConstraints( if ((constraints & (TypeParameterConstraintKind.ReferenceType | TypeParameterConstraintKind.ValueType)) != 0) { - // "'{0}': cannot specify both a constraint class and the 'class' or 'struct' constraint" - Error(diagnostics, ErrorCode.ERR_RefValBoundWithClass, syntax, type); - continue; + // System.Enum is allowed to exist with class and struct constraints + if (type.SpecialType != SpecialType.System_Enum) + { + // "'{0}': cannot specify both a constraint class and the 'class' or 'struct' constraint" + Error(diagnostics, ErrorCode.ERR_RefValBoundWithClass, syntax, type); + continue; + } } } @@ -196,9 +200,12 @@ private static bool IsValidConstraintType(TypeConstraintSyntax syntax, TypeSymbo { switch (type.SpecialType) { + case SpecialType.System_Enum: + CheckFeatureAvailability(syntax, MessageID.IDS_FeatureEnumGenericTypeConstraint, diagnostics); + break; + case SpecialType.System_Object: case SpecialType.System_ValueType: - case SpecialType.System_Enum: case SpecialType.System_Delegate: case SpecialType.System_MulticastDelegate: case SpecialType.System_Array: diff --git a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs index cd9fd1a408974..6f94d1648ae1b 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs +++ b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs @@ -10376,6 +10376,15 @@ internal static string IDS_FeatureDynamic { } } + /// + /// Looks up a localized string similar to enum generic type constraints. + /// + internal static string IDS_FeatureEnumGenericTypeConstraint { + get { + return ResourceManager.GetString("IDS_FeatureEnumGenericTypeConstraint", resourceCulture); + } + } + /// /// Looks up a localized string similar to exception filter. /// diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 6798c28542aff..5ee80ff140222 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -1473,7 +1473,6 @@ If such a class is used as a base class and if the deriving class defines a dest Predefined type '{0}' is not defined or imported - Predefined type '{0}' is not defined or imported @@ -5247,4 +5246,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ A default literal 'default' is not valid as a pattern. Use another literal (e.g. '0' or 'null') as appropriate. To match everything, use a discard pattern 'var _'. - + + enum generic type constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 6663497accd44..04961391e125f 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -1429,7 +1429,7 @@ internal enum ErrorCode #endregion diagnostics for ref locals and ref returns introduced in C# 7 #region stragglers for C# 7 - ERR_PredefinedValueTupleTypeNotFound = 8179, + ERR_PredefinedValueTupleTypeNotFound = 8179, // We need a specific error code for ValueTuple as an IDE codefix depends on it (AddNuget) ERR_SemiOrLBraceOrArrowExpected = 8180, ERR_NewWithTupleTypeSyntax = 8181, ERR_PredefinedValueTupleTypeMustBeStruct = 8182, diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs index 38a3e15fcdaaa..5bcb553d4dfb8 100644 --- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs +++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs @@ -147,6 +147,7 @@ internal enum MessageID IDS_FeaturePrivateProtected = MessageBase + 12730, IDS_FeatureAttributesOnBackingFields = MessageBase + 12731, + IDS_FeatureEnumGenericTypeConstraint = MessageBase + 12732, } // Message IDs may refer to strings that need to be localized. @@ -188,6 +189,7 @@ internal static LanguageVersion RequiredVersion(this MessageID feature) { // C# 7.3 features. case MessageID.IDS_FeatureAttributesOnBackingFields: // semantic check + case MessageID.IDS_FeatureEnumGenericTypeConstraint: // semantic check return LanguageVersion.CSharp7_3; // C# 7.2 features. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 88c7ad6466c9c..db4f65137ba32 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -8600,6 +8600,11 @@ Pokud chcete odstranit toto varování, můžete místo toho použít /reference Field-targeted attributes on auto-properties are not supported in this version of the language. + + enum generic type constraints + enum generic type constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 7860711d60ed6..19cbf57eae9c5 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -8600,6 +8600,11 @@ Um die Warnung zu beheben, können Sie stattdessen /reference verwenden (Einbett Field-targeted attributes on auto-properties are not supported in this version of the language. + + enum generic type constraints + enum generic type constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index e399ce1d98a36..abe58e72503f2 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -8600,6 +8600,11 @@ Para eliminar la advertencia puede usar /reference (establezca la propiedad Embe Field-targeted attributes on auto-properties are not supported in this version of the language. + + enum generic type constraints + enum generic type constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 87b7f2544f591..37ab3c12b9da8 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -8600,6 +8600,11 @@ Pour supprimer l'avertissement, vous pouvez utiliser la commande /reference (dé Field-targeted attributes on auto-properties are not supported in this version of the language. + + enum generic type constraints + enum generic type constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index e9c4974e49f28..ab77395165871 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -8600,6 +8600,11 @@ Per rimuovere l'avviso, è invece possibile usare /reference (impostare la propr Field-targeted attributes on auto-properties are not supported in this version of the language. + + enum generic type constraints + enum generic type constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 45db902686c18..6d93f8c9ddffd 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -8600,6 +8600,11 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Field-targeted attributes on auto-properties are not supported in this version of the language. + + enum generic type constraints + enum generic type constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 6e2eb9aded1cf..e7981d615704d 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -8600,6 +8600,11 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Field-targeted attributes on auto-properties are not supported in this version of the language. + + enum generic type constraints + enum generic type constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 4f79730fea56d..8b0fc8b02f87f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -8600,6 +8600,11 @@ Aby usunąć ostrzeżenie, możesz zamiast tego użyć opcji /reference (ustaw w Field-targeted attributes on auto-properties are not supported in this version of the language. + + enum generic type constraints + enum generic type constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 2a21850a2f2dd..cbbabefc475e7 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -8600,6 +8600,11 @@ Para incorporar informações de tipo de interoperabilidade para os dois assembl Field-targeted attributes on auto-properties are not supported in this version of the language. + + enum generic type constraints + enum generic type constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 56f3194120f5e..3c2cdb770007b 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -8600,6 +8600,11 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Field-targeted attributes on auto-properties are not supported in this version of the language. + + enum generic type constraints + enum generic type constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 2bd0df06f7079..43691445961e2 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -8600,6 +8600,11 @@ Uyarıyı kaldırmak için, /reference kullanabilirsiniz (Birlikte Çalışma T Field-targeted attributes on auto-properties are not supported in this version of the language. + + enum generic type constraints + enum generic type constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 46d35562eced2..855b945e44d74 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -8600,6 +8600,11 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Field-targeted attributes on auto-properties are not supported in this version of the language. + + enum generic type constraints + enum generic type constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index b4bbf0a64e1aa..66200630464ae 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -8600,6 +8600,11 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Field-targeted attributes on auto-properties are not supported in this version of the language. + + enum generic type constraints + enum generic type constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTests.cs index ff2b2c17a5596..8769b64b157c0 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTests.cs @@ -16073,5 +16073,37 @@ public static explicit operator Test(Span value) CompileAndVerify(comp, expectedOutput: "SpanOpCalled", verify: Verification.Fails); } + + [Fact] + public void EnumConstraint_NoBoxing() + { + var code = @" +enum E1 +{ + A = 5 +} +class Test1 +{ + public static void M(T arg) where T : struct, System.Enum + { + } +} +class Test2 +{ + public void M() + { + Test1.M(E1.A); + } +}"; + + CompileAndVerify(code).VerifyIL("Test2.M", @" +{ + // Code size 7 (0x7) + .maxstack 1 + IL_0000: ldc.i4.5 + IL_0001: call ""void Test1.M(E1)"" + IL_0006: ret +}"); + } } } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs new file mode 100644 index 0000000000000..96175927b3156 --- /dev/null +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs @@ -0,0 +1,583 @@ +// 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; +using System.Linq; +using Microsoft.CodeAnalysis.CSharp.Symbols; +using Microsoft.CodeAnalysis.CSharp.UnitTests; +using Microsoft.CodeAnalysis.Test.Utilities; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.Semantic.UnitTests.Semantics +{ + public class GenericConstraintsTests : CompilingTestBase + { + [Fact] + public void EnumConstraint_Compilation_Alone() + { + CreateStandardCompilation(@" +public class Test where T : System.Enum +{ +} +public enum E1 +{ + A +} +public class Test2 +{ + public void M() where U : System.Enum + { + var a = new Test(); // enum + var b = new Test(); // value type + var c = new Test(); // reference type + var d = new Test(); // Enum type + var e = new Test(); // Generic type constrained to enum + } +}").VerifyDiagnostics( + // (14,26): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no boxing conversion from 'int' to 'System.Enum'. + // var b = new Test(); // value type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "int").WithArguments("Test", "System.Enum", "T", "int").WithLocation(14, 26), + // (15,26): error CS0311: The type 'string' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no implicit reference conversion from 'string' to 'System.Enum'. + // var c = new Test(); // reference type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "string").WithArguments("Test", "System.Enum", "T", "string").WithLocation(15, 26)); + } + + [Fact] + public void EnumConstraint_Compilation_ReferenceType() + { + CreateStandardCompilation(@" +public class Test where T : class, System.Enum +{ +} +public enum E1 +{ + A +} +public class Test2 +{ + public void M() where U : class, System.Enum + { + var a = new Test(); // enum + var b = new Test(); // value type + var c = new Test(); // reference type + var d = new Test(); // Enum type + var e = new Test(); // Generic type constrained to enum + } +}").VerifyDiagnostics( + // (13,26): error CS0452: The type 'E1' must be a reference type in order to use it as parameter 'T' in the generic type or method 'Test' + // var a = new Test(); // enum + Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "E1").WithArguments("Test", "T", "E1").WithLocation(13, 26), + // (14,26): error CS0452: The type 'int' must be a reference type in order to use it as parameter 'T' in the generic type or method 'Test' + // var b = new Test(); // value type + Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "int").WithArguments("Test", "T", "int").WithLocation(14, 26), + // (15,26): error CS0311: The type 'string' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no implicit reference conversion from 'string' to 'System.Enum'. + // var c = new Test(); // reference type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "string").WithArguments("Test", "System.Enum", "T", "string").WithLocation(15, 26)); + } + + [Fact] + public void EnumConstraint_Compilation_ValueType() + { + CreateStandardCompilation(@" +public class Test where T : struct, System.Enum +{ +} +public enum E1 +{ + A +} +public class Test2 +{ + public void M() where U : struct, System.Enum + { + var a = new Test(); // enum + var b = new Test(); // value type + var c = new Test(); // reference type + var d = new Test(); // Enum type + var e = new Test(); // Generic type constrained to enum + } +}").VerifyDiagnostics( + // (14,26): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no boxing conversion from 'int' to 'System.Enum'. + // var b = new Test(); // value type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "int").WithArguments("Test", "System.Enum", "T", "int").WithLocation(14, 26), + // (15,26): error CS0453: The type 'string' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Test' + // var c = new Test(); // reference type + Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "string").WithArguments("Test", "T", "string").WithLocation(15, 26), + // (16,26): error CS0453: The type 'Enum' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Test' + // var d = new Test(); // Enum type + Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "System.Enum").WithArguments("Test", "T", "System.Enum").WithLocation(16, 26)); + } + + [Fact] + public void EnumConstraint_Compilation_Constructor() + { + CreateStandardCompilation(@" +public class Test where T : System.Enum, new() +{ +} +public enum E1 +{ + A +} +public class Test2 +{ + public void M() where U : System.Enum, new() + { + var a = new Test(); // enum + var b = new Test(); // value type + var c = new Test(); // reference type + var d = new Test(); // Enum type + var e = new Test(); // Generic type constrained to enum + } +}").VerifyDiagnostics( + // (14,26): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no boxing conversion from 'int' to 'System.Enum'. + // var b = new Test(); // value type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "int").WithArguments("Test", "System.Enum", "T", "int").WithLocation(14, 26), + // (15,26): error CS0311: The type 'string' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no implicit reference conversion from 'string' to 'System.Enum'. + // var c = new Test(); // reference type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "string").WithArguments("Test", "System.Enum", "T", "string").WithLocation(15, 26), + // (15,26): error CS0310: 'string' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'Test' + // var c = new Test(); // reference type + Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "string").WithArguments("Test", "T", "string").WithLocation(15, 26), + // (16,26): error CS0310: 'Enum' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'Test' + // var d = new Test(); // Enum type + Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "System.Enum").WithArguments("Test", "T", "System.Enum").WithLocation(16, 26)); + } + + [Fact] + public void EnumConstraint_Reference_Alone() + { + var reference = CreateStandardCompilation(@" +public class Test where T : System.Enum +{ +}" + ).EmitToImageReference(); + + var code = @" +public enum E1 +{ + A +} + +public class Test2 +{ + public void M() where U : System.Enum + { + var a = new Test(); // enum + var b = new Test(); // value type + var c = new Test(); // reference type + var d = new Test(); // Enum type + var e = new Test(); // Generic type constrained to enum + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (12,26): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no boxing conversion from 'int' to 'System.Enum'. + // var b = new Test(); // value type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "int").WithArguments("Test", "System.Enum", "T", "int").WithLocation(12, 26), + // (13,26): error CS0311: The type 'string' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no implicit reference conversion from 'string' to 'System.Enum'. + // var c = new Test(); // reference type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "string").WithArguments("Test", "System.Enum", "T", "string").WithLocation(13, 26)); + } + + [Fact] + public void EnumConstraint_Reference_ReferenceType() + { + var reference = CreateStandardCompilation(@" +public class Test where T : class, System.Enum +{ +}" + ).EmitToImageReference(); + + var code = @" +public enum E1 +{ + A +} + +public class Test2 +{ + public void M() where U : class, System.Enum + { + var a = new Test(); // enum + var b = new Test(); // value type + var c = new Test(); // reference type + var d = new Test(); // Enum type + var e = new Test(); // Generic type constrained to enum + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (11,26): error CS0452: The type 'E1' must be a reference type in order to use it as parameter 'T' in the generic type or method 'Test' + // var a = new Test(); // enum + Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "E1").WithArguments("Test", "T", "E1").WithLocation(11, 26), + // (12,26): error CS0452: The type 'int' must be a reference type in order to use it as parameter 'T' in the generic type or method 'Test' + // var b = new Test(); // value type + Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "int").WithArguments("Test", "T", "int").WithLocation(12, 26), + // (13,26): error CS0311: The type 'string' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no implicit reference conversion from 'string' to 'System.Enum'. + // var c = new Test(); // reference type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "string").WithArguments("Test", "System.Enum", "T", "string").WithLocation(13, 26)); + } + + [Fact] + public void EnumConstraint_Reference_ValueType() + { + var reference = CreateStandardCompilation(@" +public class Test where T : struct, System.Enum +{ +}" + ).EmitToImageReference(); + + var code = @" +public enum E1 +{ + A +} + +public class Test2 +{ + public void M() where U : struct, System.Enum + { + var a = new Test(); // enum + var b = new Test(); // value type + var c = new Test(); // reference type + var d = new Test(); // Enum type + var e = new Test(); // Generic type constrained to enum + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (12,26): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no boxing conversion from 'int' to 'System.Enum'. + // var b = new Test(); // value type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "int").WithArguments("Test", "System.Enum", "T", "int").WithLocation(12, 26), + // (13,26): error CS0453: The type 'string' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Test' + // var c = new Test(); // reference type + Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "string").WithArguments("Test", "T", "string").WithLocation(13, 26), + // (14,26): error CS0453: The type 'Enum' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Test' + // var d = new Test(); // Enum type + Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "System.Enum").WithArguments("Test", "T", "System.Enum").WithLocation(14, 26)); + } + + [Fact] + public void EnumConstraint_Reference_Constructor() + { + var reference = CreateStandardCompilation(@" +public class Test where T : System.Enum, new() +{ +}" + ).EmitToImageReference(); + + var code = @" +public enum E1 +{ + A +} + +public class Test2 +{ + public void M() where U : System.Enum, new() + { + var a = new Test(); // enum + var b = new Test(); // value type + var c = new Test(); // reference type + var d = new Test(); // Enum type + var e = new Test(); // Generic type constrained to enum + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (12,26): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no boxing conversion from 'int' to 'System.Enum'. + // var b = new Test(); // value type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "int").WithArguments("Test", "System.Enum", "T", "int").WithLocation(12, 26), + // (13,26): error CS0311: The type 'string' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no implicit reference conversion from 'string' to 'System.Enum'. + // var c = new Test(); // reference type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "string").WithArguments("Test", "System.Enum", "T", "string").WithLocation(13, 26), + // (13,26): error CS0310: 'string' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'Test' + // var c = new Test(); // reference type + Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "string").WithArguments("Test", "T", "string").WithLocation(13, 26), + // (14,26): error CS0310: 'Enum' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'Test' + // var d = new Test(); // Enum type + Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "System.Enum").WithArguments("Test", "T", "System.Enum").WithLocation(14, 26)); + } + + [Fact] + public void EnumConstraint_Before_7_3() + { + var code = @" +public class Test where T : System.Enum +{ +}"; + + CreateStandardCompilation(code, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp7_2)).VerifyDiagnostics( + // (2,32): error CS8320: Feature 'enum generic type constraints' is not available in C# 7.2. Please use language version 7.3 or greater. + // public class Test where T : System.Enum + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "System.Enum").WithArguments("enum generic type constraints", "7.3").WithLocation(2, 32)); + } + + [Theory] + [InlineData("byte")] + [InlineData("sbyte")] + [InlineData("short")] + [InlineData("ushort")] + [InlineData("int")] + [InlineData("uint")] + [InlineData("long")] + [InlineData("ulong")] + public void EnumConstraint_DifferentBaseTypes(string type) + { + CreateStandardCompilation($@" +public class Test where T : System.Enum +{{ +}} +public enum E1 : {type} +{{ + A +}} +public class Test2 +{{ + public void M() + {{ + var a = new Test(); // Valid + var b = new Test(); // Invalid + }} +}} +").VerifyDiagnostics( + // (14,26): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no boxing conversion from 'int' to 'System.Enum'. + // var b = new Test(); // Invalid + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "int").WithArguments("Test", "System.Enum", "T", "int").WithLocation(14, 26)); + } + + [Fact] + public void EnumConstraint_InheritanceChain() + { + CreateStandardCompilation(@" +public enum E +{ + A +} +public class Test where U : System.Enum, T +{ +} +public class Test2 +{ + public void M() + { + var a = new Test(); + + var b = new Test(); + var c = new Test(); + + var d = new Test(); + var e = new Test(); + } +}").VerifyDiagnostics( + // (13,33): error CS0315: The type 'E' cannot be used as type parameter 'U' in the generic type or method 'Test'. There is no boxing conversion from 'E' to 'Test2'. + // var a = new Test(); + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "E").WithArguments("Test", "Test2", "U", "E").WithLocation(13, 33), + // (18,29): error CS0311: The type 'System.Enum' cannot be used as type parameter 'U' in the generic type or method 'Test'. There is no implicit reference conversion from 'System.Enum' to 'E'. + // var d = new Test(); + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "System.Enum").WithArguments("Test", "E", "U", "System.Enum").WithLocation(18, 29)); + } + + [Fact] + public void EnumConstraint_IsReflectedinSymbols_Alone() + { + var code = "public class Test where T : System.Enum { }"; + + Action validator = module => + { + var typeParameter = module.GlobalNamespace.GetTypeMember("Test").TypeParameters.Single(); + Assert.False(typeParameter.HasValueTypeConstraint); + Assert.False(typeParameter.HasReferenceTypeConstraint); + Assert.Equal(SpecialType.System_Enum, typeParameter.ConstraintTypes().Single().SpecialType); + }; + + CompileAndVerify(code, sourceSymbolValidator: validator, symbolValidator: validator); + } + + [Fact] + public void EnumConstraint_IsReflectedinSymbols_ValueType() + { + var code = "public class Test where T : struct, System.Enum { }"; + + Action validator = module => + { + var typeParameter = module.GlobalNamespace.GetTypeMember("Test").TypeParameters.Single(); + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.False(typeParameter.HasReferenceTypeConstraint); + Assert.False(typeParameter.HasConstructorConstraint); + Assert.Equal(SpecialType.System_Enum, typeParameter.ConstraintTypes().Single().SpecialType); + }; + + CompileAndVerify(code, sourceSymbolValidator: validator, symbolValidator: validator); + } + + [Fact] + public void EnumConstraint_IsReflectedinSymbols_ReferenceType() + { + var code = "public class Test where T : class, System.Enum { }"; + + Action validator = module => + { + var typeParameter = module.GlobalNamespace.GetTypeMember("Test").TypeParameters.Single(); + Assert.False(typeParameter.HasValueTypeConstraint); + Assert.True(typeParameter.HasReferenceTypeConstraint); + Assert.False(typeParameter.HasConstructorConstraint); + Assert.Equal(SpecialType.System_Enum, typeParameter.ConstraintTypes().Single().SpecialType); + }; + + CompileAndVerify(code, sourceSymbolValidator: validator, symbolValidator: validator); + } + + [Fact] + public void EnumConstraint_IsReflectedinSymbols_Constructor() + { + var code = "public class Test where T : System.Enum, new() { }"; + + Action validator = module => + { + var typeParameter = module.GlobalNamespace.GetTypeMember("Test").TypeParameters.Single(); + Assert.False(typeParameter.HasValueTypeConstraint); + Assert.False(typeParameter.HasReferenceTypeConstraint); + Assert.True(typeParameter.HasConstructorConstraint); + Assert.Equal(SpecialType.System_Enum, typeParameter.ConstraintTypes().Single().SpecialType); + }; + + CompileAndVerify(code, sourceSymbolValidator: validator, symbolValidator: validator); + } + + [Fact] + public void EnumConstraint_EnforcedInInheritanceChain_Downwards_Source() + { + CreateStandardCompilation(@" +public abstract class A +{ + public abstract void M() where T : System.Enum; +} +public class B : A +{ + public override void M() { } + + public void Test() + { + this.M(); + this.M(); + } +} +public enum E +{ +}").VerifyDiagnostics( + // (12,9): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'B.M()'. There is no boxing conversion from 'int' to 'System.Enum'. + // this.M(); + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "this.M").WithArguments("B.M()", "System.Enum", "T", "int").WithLocation(12, 9)); + } + + [Fact] + public void EnumConstraint_EnforcedInInheritanceChain_Downwards_Reference() + { + var reference = CreateStandardCompilation(@" +public abstract class A +{ + public abstract void M() where T : System.Enum; +}").EmitToImageReference(); + + CreateStandardCompilation(@" +public class B : A +{ + public override void M() { } + + public void Test() + { + this.M(); + this.M(); + } +} +public enum E +{ +}", references: new[] { reference }).VerifyDiagnostics( + // (8,9): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'B.M()'. There is no boxing conversion from 'int' to 'System.Enum'. + // this.M(); + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "this.M").WithArguments("B.M()", "System.Enum", "T", "int").WithLocation(8, 9)); + } + + [Fact] + public void EnumConstraint_EnforcedInInheritanceChain_Upwards_Source() + { + CreateStandardCompilation(@" +public abstract class A +{ + public abstract void M(); +} +public class B : A +{ + public override void M() where T : System.Enum { } +}").VerifyDiagnostics( + // (8,33): error CS0460: Constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly + // public override void M() where T : System.Enum { } + Diagnostic(ErrorCode.ERR_OverrideWithConstraints, "where").WithLocation(8, 33)); + } + + [Fact] + public void EnumConstraint_EnforcedInInheritanceChain_Upwards_Reference() + { + var reference = CreateStandardCompilation(@" +public abstract class A +{ + public abstract void M(); +}").EmitToImageReference(); + + CreateStandardCompilation(@" +public class B : A +{ + public override void M() where T : System.Enum { } +}", references: new[] { reference }).VerifyDiagnostics( + // (4,33): error CS0460: Constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly + // public override void M() where T : System.Enum { } + Diagnostic(ErrorCode.ERR_OverrideWithConstraints, "where").WithLocation(4, 33)); + } + + [Fact] + public void EnumConstraint_ResolveParentConstraints() + { + var comp = CreateStandardCompilation(@" +public enum MyEnum +{ +} +public abstract class A +{ + public abstract void F() where U : System.Enum, T; +} +public class B : A +{ + public override void F() { } +}"); + + Action validator = module => + { + var method = module.GlobalNamespace.GetTypeMember("B").GetMethod("F"); + var constraintTypeNames = method.TypeParameters.Single().ConstraintTypes().Select(type => type.ToTestDisplayString()); + + AssertEx.SetEqual(new[] { "System.Enum", "MyEnum" }, constraintTypeNames); + }; + + CompileAndVerify(comp, sourceSymbolValidator: validator, symbolValidator: validator); + } + + [Fact] + public void EnumConstraint_TypeNotAvailable() + { + CreateCompilation(@" +namespace System +{ + public class Object {} + public class Void {} +} +public class Test where T : System.Enum +{ +}").VerifyDiagnostics( + // (7,39): error CS0234: The type or namespace name 'Enum' does not exist in the namespace 'System' (are you missing an assembly reference?) + // public class Test where T : System.Enum + Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNS, "Enum").WithArguments("Enum", "System").WithLocation(7, 39)); + } + } +} diff --git a/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs b/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs index e486aa84c6b89..32b99f410a880 100644 --- a/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs @@ -6304,5 +6304,18 @@ Structure X SymbolDisplayPartKind.Space, SymbolDisplayPartKind.StructName); } + + [Fact] + public void EnumConstraint() + { + TestSymbolDescription( + "class X where T : System.Enum { }", + global => global.GetTypeMember("X").TypeParameters.Single().ConstraintTypes().Single(), + SymbolDisplayFormat.TestFormat, + "System.Enum", + SymbolDisplayPartKind.NamespaceName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.ClassName); + } } } diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs index 27320c92718fc..465f41475afe7 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs @@ -12281,7 +12281,7 @@ public void CS0702ERR_SpecialTypeAsBound() @"using System; interface IA where T : object { } interface IB where T : System.Object { } -interface IC where T : ValueType where U : Enum { } +interface IC where T : ValueType { } interface ID where T : Array { } interface IE where T : Delegate where U : MulticastDelegate { }"; CreateStandardCompilation(source).VerifyDiagnostics( @@ -12291,8 +12291,6 @@ interface IE where T : Delegate where U : MulticastDelegate { }"; Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "System.Object").WithArguments("object").WithLocation(3, 27), // (4,30): error CS0702: Constraint cannot be special class 'System.ValueType' Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "ValueType").WithArguments("System.ValueType").WithLocation(4, 30), - // (4,50): error CS0702: Constraint cannot be special class 'System.Enum' - Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "Enum").WithArguments("System.Enum").WithLocation(4, 50), // (5,27): error CS0702: Constraint cannot be special class 'System.Array' Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "Array").WithArguments("System.Array").WithLocation(5, 27), // (6,30): error CS0702: Constraint cannot be special class 'System.Delegate' diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/GenericConstraintTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/GenericConstraintTests.vb index 64460c45058e9..0bf9b2d85374e 100644 --- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/GenericConstraintTests.vb +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/GenericConstraintTests.vb @@ -5719,6 +5719,41 @@ BC40008: 'Class2' is obsolete. ) End Sub + + Public Sub EnumConstraint_FromCSharp() + Dim reference = CreateCSharpCompilation(" +public class Test where T : System.Enum +{ +}", parseOptions:=New CSharp.CSharpParseOptions(CSharp.LanguageVersion.CSharp7_3)).EmitToImageReference() + + Dim compilation = CompilationUtils.CreateCompilationWithMscorlibAndVBRuntime( + + +Public Enum E1 + A +End Enum +Public Class Test2 + Public Sub M() + Dim a = new Test(Of E1)() ' enum + Dim b = new Test(Of Integer)() ' value type + Dim c = new Test(Of string)() ' reference type + Dim d = new Test(Of System.Enum)() ' Enum type + End Sub +End Class + +, {reference}) + + AssertTheseDiagnostics(compilation, + +BC32044: Type argument 'Integer' does not inherit from or implement the constraint type '[Enum]'. + Dim b = new Test(Of Integer)() ' value type + ~~~~~~~ +BC32044: Type argument 'String' does not inherit from or implement the constraint type '[Enum]'. + Dim c = new Test(Of string)() ' reference type + ~~~~~~ +) + End Sub + End Class End Namespace diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs index f3c0849264fd6..e761651a64900 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs @@ -9201,5 +9201,14 @@ public async Task DoNotCrashInExtensionMethoWithExpressionBodiedMember() "; await VerifyItemExistsAsync(markup, "o"); } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task EnumConstraint() + { + var markup = +@"public class X where T : System.$$ +"; + await VerifyItemExistsAsync(markup, "Enum"); + } } } diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs index 81385aad7d088..01a8abee2d407 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs @@ -257,7 +257,20 @@ class Program LanguageVersion.Latest, new CSharpParseOptions(LanguageVersion.CSharp7_2)); } -#endregion C# 7.3 + + [Fact] + public async Task UpgradeProjectFromCSharp7_2ToLatest_EnumConstraint() + { + await TestLanguageVersionUpgradedAsync( +@"public class X where T : [|System.Enum|] +{ +} +", + LanguageVersion.CSharp7_3, + new CSharpParseOptions(LanguageVersion.CSharp7_2), + index: 1); + } + #endregion C# 7.3 [Fact] public async Task UpgradeAllProjectsToDefault() diff --git a/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs b/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs index 2000e4c3c5742..bf91ab874e455 100644 --- a/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs +++ b/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs @@ -5152,5 +5152,17 @@ class Bar }", MainDescription($"void Program.Test()")); } + + [Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)] + public async Task EnumConstraint() + { + await TestInMethodAsync( +@" +class X where T : System.Enum +{ + private $$T x; +}", + MainDescription($"T {FeaturesResources.in_} X where T : Enum")); + } } } From c23d361432474cc589de1ab19be434508a83adc1 Mon Sep 17 00:00:00 2001 From: Omar Tawfik Date: Mon, 29 Jan 2018 15:51:40 -0800 Subject: [PATCH 02/13] Support Delegate and MulticastDelegate as generic type constraints (#24443) * Support Delegate and Multicast delegates as generic type constraints * More tests --- .../Portable/Binder/Binder_Constraints.cs | 22 +- .../Portable/CSharpResources.Designer.cs | 9 + .../CSharp/Portable/CSharpResources.resx | 3 + .../CSharp/Portable/Errors/MessageID.cs | 2 + .../Portable/xlf/CSharpResources.cs.xlf | 5 + .../Portable/xlf/CSharpResources.de.xlf | 5 + .../Portable/xlf/CSharpResources.es.xlf | 5 + .../Portable/xlf/CSharpResources.fr.xlf | 5 + .../Portable/xlf/CSharpResources.it.xlf | 5 + .../Portable/xlf/CSharpResources.ja.xlf | 5 + .../Portable/xlf/CSharpResources.ko.xlf | 5 + .../Portable/xlf/CSharpResources.pl.xlf | 5 + .../Portable/xlf/CSharpResources.pt-BR.xlf | 5 + .../Portable/xlf/CSharpResources.ru.xlf | 5 + .../Portable/xlf/CSharpResources.tr.xlf | 5 + .../Portable/xlf/CSharpResources.zh-Hans.xlf | 5 + .../Portable/xlf/CSharpResources.zh-Hant.xlf | 5 + .../Semantics/GenericConstraintsTests.cs | 960 ++++++++++++++++++ .../SymbolDisplay/SymbolDisplayTests.cs | 98 ++ .../Test/Symbol/Symbols/SymbolErrorTests.cs | 9 +- .../SymbolsTests/GenericConstraintTests.vb | 68 ++ .../SymbolCompletionProviderTests.cs | 18 + .../UpgradeProject/UpgradeProjectTests.cs | 26 + .../QuickInfo/SemanticQuickInfoSourceTests.cs | 24 + 24 files changed, 1290 insertions(+), 14 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs index 10d5b6ea9f9fe..4bbac7ae4e8c5 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs @@ -171,12 +171,17 @@ private TypeParameterConstraintClause BindTypeParameterConstraints( if ((constraints & (TypeParameterConstraintKind.ReferenceType | TypeParameterConstraintKind.ValueType)) != 0) { - // System.Enum is allowed to exist with class and struct constraints - if (type.SpecialType != SpecialType.System_Enum) + switch (type.SpecialType) { - // "'{0}': cannot specify both a constraint class and the 'class' or 'struct' constraint" - Error(diagnostics, ErrorCode.ERR_RefValBoundWithClass, syntax, type); - continue; + case SpecialType.System_Enum: + case SpecialType.System_Delegate: + case SpecialType.System_MulticastDelegate: + break; + + default: + // "'{0}': cannot specify both a constraint class and the 'class' or 'struct' constraint" + Error(diagnostics, ErrorCode.ERR_RefValBoundWithClass, syntax, type); + continue; } } } @@ -204,10 +209,13 @@ private static bool IsValidConstraintType(TypeConstraintSyntax syntax, TypeSymbo CheckFeatureAvailability(syntax, MessageID.IDS_FeatureEnumGenericTypeConstraint, diagnostics); break; - case SpecialType.System_Object: - case SpecialType.System_ValueType: case SpecialType.System_Delegate: case SpecialType.System_MulticastDelegate: + CheckFeatureAvailability(syntax, MessageID.IDS_FeatureDelegateGenericTypeConstraint, diagnostics); + break; + + case SpecialType.System_Object: + case SpecialType.System_ValueType: case SpecialType.System_Array: // "Constraint cannot be special class '{0}'" Error(diagnostics, ErrorCode.ERR_SpecialTypeAsBound, syntax, type); diff --git a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs index 6f94d1648ae1b..4d86431e090cf 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs +++ b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs @@ -10349,6 +10349,15 @@ internal static string IDS_FeatureDefaultLiteral { } } + /// + /// Looks up a localized string similar to delegate generic type constraints. + /// + internal static string IDS_FeatureDelegateGenericTypeConstraint { + get { + return ResourceManager.GetString("IDS_FeatureDelegateGenericTypeConstraint", resourceCulture); + } + } + /// /// Looks up a localized string similar to dictionary initializer. /// diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 5ee80ff140222..d1247c0c7e0f4 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -5249,4 +5249,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ enum generic type constraints + + delegate generic type constraints + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs index 5bcb553d4dfb8..e1b371cf53552 100644 --- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs +++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs @@ -148,6 +148,7 @@ internal enum MessageID IDS_FeatureAttributesOnBackingFields = MessageBase + 12731, IDS_FeatureEnumGenericTypeConstraint = MessageBase + 12732, + IDS_FeatureDelegateGenericTypeConstraint = MessageBase + 12733, } // Message IDs may refer to strings that need to be localized. @@ -190,6 +191,7 @@ internal static LanguageVersion RequiredVersion(this MessageID feature) // C# 7.3 features. case MessageID.IDS_FeatureAttributesOnBackingFields: // semantic check case MessageID.IDS_FeatureEnumGenericTypeConstraint: // semantic check + case MessageID.IDS_FeatureDelegateGenericTypeConstraint: // semantic check return LanguageVersion.CSharp7_3; // C# 7.2 features. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index db4f65137ba32..bf4dc1302ae70 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -8605,6 +8605,11 @@ Pokud chcete odstranit toto varování, můžete místo toho použít /reference enum generic type constraints + + delegate generic type constraints + delegate generic type constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 19cbf57eae9c5..e06a6efdcaebd 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -8605,6 +8605,11 @@ Um die Warnung zu beheben, können Sie stattdessen /reference verwenden (Einbett enum generic type constraints + + delegate generic type constraints + delegate generic type constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index abe58e72503f2..58094e72d25dd 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -8605,6 +8605,11 @@ Para eliminar la advertencia puede usar /reference (establezca la propiedad Embe enum generic type constraints + + delegate generic type constraints + delegate generic type constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 37ab3c12b9da8..e21f5f8eb7ee3 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -8605,6 +8605,11 @@ Pour supprimer l'avertissement, vous pouvez utiliser la commande /reference (dé enum generic type constraints + + delegate generic type constraints + delegate generic type constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index ab77395165871..bce19c9126279 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -8605,6 +8605,11 @@ Per rimuovere l'avviso, è invece possibile usare /reference (impostare la propr enum generic type constraints + + delegate generic type constraints + delegate generic type constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 6d93f8c9ddffd..388fd1ecc3a17 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -8605,6 +8605,11 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ enum generic type constraints + + delegate generic type constraints + delegate generic type constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index e7981d615704d..20e7535f4f4fb 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -8605,6 +8605,11 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ enum generic type constraints + + delegate generic type constraints + delegate generic type constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 8b0fc8b02f87f..33b8c8db8760a 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -8605,6 +8605,11 @@ Aby usunąć ostrzeżenie, możesz zamiast tego użyć opcji /reference (ustaw w enum generic type constraints + + delegate generic type constraints + delegate generic type constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index cbbabefc475e7..d269eb541591c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -8605,6 +8605,11 @@ Para incorporar informações de tipo de interoperabilidade para os dois assembl enum generic type constraints + + delegate generic type constraints + delegate generic type constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 3c2cdb770007b..0a8df165d98db 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -8605,6 +8605,11 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ enum generic type constraints + + delegate generic type constraints + delegate generic type constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 43691445961e2..89e2d76fde432 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -8605,6 +8605,11 @@ Uyarıyı kaldırmak için, /reference kullanabilirsiniz (Birlikte Çalışma T enum generic type constraints + + delegate generic type constraints + delegate generic type constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 855b945e44d74..4eb59040307b5 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -8605,6 +8605,11 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ enum generic type constraints + + delegate generic type constraints + delegate generic type constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 66200630464ae..f13ad18b061d7 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -8605,6 +8605,11 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ enum generic type constraints + + delegate generic type constraints + delegate generic type constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs index 96175927b3156..bd54debe3a1ee 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs @@ -579,5 +579,965 @@ public class Test where T : System.Enum // public class Test where T : System.Enum Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNS, "Enum").WithArguments("Enum", "System").WithLocation(7, 39)); } + + [Fact] + public void EnumConstraint_BindingToMethods() + { + var code = @" +enum A : short { a } +enum B : uint { b } +class Test +{ + public static void Main() + { + Print(A.a); + Print(B.b); + } + static void Print(T obj) where T : System.Enum + { + System.Console.WriteLine(obj.GetTypeCode()); + } +}"; + + CompileAndVerify(code, expectedOutput: @" +Int16 +UInt32"); + } + + [Fact] + public void DelegateConstraint_Compilation_Alone() + { + CreateStandardCompilation(@" +public class Test where T : System.Delegate +{ +} +public delegate void D1(); +public class Test2 +{ + public void M() where U : System.Delegate + { + var a = new Test(); // delegate + var b = new Test(); // value type + var c = new Test(); // reference type + var d = new Test(); // delegate type + } +}").VerifyDiagnostics( + // (11,26): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no boxing conversion from 'int' to 'System.Delegate'. + // var b = new Test(); // value type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "int").WithArguments("Test", "System.Delegate", "T", "int").WithLocation(11, 26), + // (12,26): error CS0311: The type 'string' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no implicit reference conversion from 'string' to 'System.Delegate'. + // var c = new Test(); // reference type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "string").WithArguments("Test", "System.Delegate", "T", "string").WithLocation(12, 26)); + } + + [Fact] + public void DelegateConstraint_Compilation_ReferenceType() + { + CreateStandardCompilation(@" +public class Test where T : class, System.Delegate +{ +} +public delegate void D1(); +public class Test2 +{ + public void M() where U : class, System.Delegate + { + var a = new Test(); // delegate + var b = new Test(); // value type + var c = new Test(); // reference type + var d = new Test(); // delegate type + } +}").VerifyDiagnostics( + // (11,26): error CS0452: The type 'int' must be a reference type in order to use it as parameter 'T' in the generic type or method 'Test' + // var b = new Test(); // value type + Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "int").WithArguments("Test", "T", "int").WithLocation(11, 26), + // (12,26): error CS0311: The type 'string' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no implicit reference conversion from 'string' to 'System.Delegate'. + // var c = new Test(); // reference type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "string").WithArguments("Test", "System.Delegate", "T", "string").WithLocation(12, 26)); + } + + [Fact] + public void DelegateConstraint_Compilation_ValueType() + { + CreateStandardCompilation(@" +public class Test where T : struct, System.Delegate +{ +}").VerifyDiagnostics( + // (2,19): error CS0455: Type parameter 'T' inherits conflicting constraints 'Delegate' and 'ValueType' + // public class Test where T : struct, System.Delegate + Diagnostic(ErrorCode.ERR_BaseConstraintConflict, "T").WithArguments("T", "System.Delegate", "System.ValueType").WithLocation(2, 19)); + } + + [Fact] + public void DelegateConstraint_Compilation_Constructor() + { + CreateStandardCompilation(@" +public class Test where T : System.Delegate, new() +{ +} +public delegate void D1(); +public class Test2 +{ + public void M() where U : System.Delegate, new() + { + var a = new Test(); // delegate + var b = new Test(); // value type + var c = new Test(); // reference type + var d = new Test(); // delegate type + } +}").VerifyDiagnostics( + // (10,26): error CS0310: 'D1' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'Test' + // var a = new Test(); // delegate + Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "D1").WithArguments("Test", "T", "D1").WithLocation(10, 26), + // (11,26): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no boxing conversion from 'int' to 'System.Delegate'. + // var b = new Test(); // value type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "int").WithArguments("Test", "System.Delegate", "T", "int").WithLocation(11, 26), + // (12,26): error CS0311: The type 'string' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no implicit reference conversion from 'string' to 'System.Delegate'. + // var c = new Test(); // reference type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "string").WithArguments("Test", "System.Delegate", "T", "string").WithLocation(12, 26), + // (12,26): error CS0310: 'string' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'Test' + // var c = new Test(); // reference type + Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "string").WithArguments("Test", "T", "string").WithLocation(12, 26)); + } + + [Fact] + public void DelegateConstraint_Reference_Alone() + { + var reference = CreateStandardCompilation(@" +public class Test where T : System.Delegate +{ +}").EmitToImageReference(); + + CreateStandardCompilation(@" +public delegate void D1(); +public class Test2 +{ + public void M() where U : System.Delegate + { + var a = new Test(); // delegate + var b = new Test(); // value type + var c = new Test(); // reference type + var d = new Test(); // delegate type + } +}", references: new[] { reference }).VerifyDiagnostics( + // (8,26): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no boxing conversion from 'int' to 'System.Delegate'. + // var b = new Test(); // value type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "int").WithArguments("Test", "System.Delegate", "T", "int").WithLocation(8, 26), + // (9,26): error CS0311: The type 'string' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no implicit reference conversion from 'string' to 'System.Delegate'. + // var c = new Test(); // reference type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "string").WithArguments("Test", "System.Delegate", "T", "string").WithLocation(9, 26)); + } + + [Fact] + public void DelegateConstraint_Reference_ReferenceType() + { + var reference = CreateStandardCompilation(@" +public class Test where T : class, System.Delegate +{ +}").EmitToImageReference(); + + CreateStandardCompilation(@" +public delegate void D1(); +public class Test2 +{ + public void M() where U : class, System.Delegate + { + var a = new Test(); // delegate + var b = new Test(); // value type + var c = new Test(); // reference type + var d = new Test(); // delegate type + } +}", references: new[] { reference }).VerifyDiagnostics( + // (8,26): error CS0452: The type 'int' must be a reference type in order to use it as parameter 'T' in the generic type or method 'Test' + // var b = new Test(); // value type + Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "int").WithArguments("Test", "T", "int").WithLocation(8, 26), + // (9,26): error CS0311: The type 'string' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no implicit reference conversion from 'string' to 'System.Delegate'. + // var c = new Test(); // reference type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "string").WithArguments("Test", "System.Delegate", "T", "string").WithLocation(9, 26)); + } + + [Fact] + public void DelegateConstraint_Reference_Constructor() + { + var reference = CreateStandardCompilation(@" +public class Test where T : System.Delegate, new() +{ +}").EmitToImageReference(); + + CreateStandardCompilation(@" +public delegate void D1(); +public class Test2 +{ + public void M() where U : System.Delegate, new() + { + var a = new Test(); // delegate + var b = new Test(); // value type + var c = new Test(); // reference type + var d = new Test(); // delegate type + } +}", references: new[] { reference }).VerifyDiagnostics( + // (7,26): error CS0310: 'D1' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'Test' + // var a = new Test(); // delegate + Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "D1").WithArguments("Test", "T", "D1").WithLocation(7, 26), + // (8,26): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no boxing conversion from 'int' to 'System.Delegate'. + // var b = new Test(); // value type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "int").WithArguments("Test", "System.Delegate", "T", "int").WithLocation(8, 26), + // (9,26): error CS0311: The type 'string' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no implicit reference conversion from 'string' to 'System.Delegate'. + // var c = new Test(); // reference type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "string").WithArguments("Test", "System.Delegate", "T", "string").WithLocation(9, 26), + // (9,26): error CS0310: 'string' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'Test' + // var c = new Test(); // reference type + Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "string").WithArguments("Test", "T", "string").WithLocation(9, 26)); + } + + [Fact] + public void DelegateConstraint_Before_7_3() + { + var code = @" +public class Test where T : System.Delegate +{ +}"; + + CreateStandardCompilation(code, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp7_2)).VerifyDiagnostics( + // (2,32): error CS8320: Feature 'delegate generic type constraints' is not available in C# 7.2. Please use language version 7.3 or greater. + // public class Test where T : System.Delegate + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "System.Delegate").WithArguments("delegate generic type constraints", "7.3").WithLocation(2, 32)); + } + + [Fact] + public void DelegateConstraint_InheritanceChain() + { + CreateStandardCompilation(@" +public delegate void D1(); +public class Test where U : System.Delegate, T +{ +} +public class Test2 +{ + public void M() + { + var a = new Test(); + + var b = new Test(); + var c = new Test(); + var d = new Test(); + var e = new Test(); + var f = new Test(); + + var g = new Test(); + var h = new Test(); + } +}").VerifyDiagnostics( + // (10,33): error CS0311: The type 'D1' cannot be used as type parameter 'U' in the generic type or method 'Test'. There is no implicit reference conversion from 'D1' to 'Test2'. + // var a = new Test(); + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "D1").WithArguments("Test", "Test2", "U", "D1").WithLocation(10, 33), + // (14,52): error CS0311: The type 'System.Delegate' cannot be used as type parameter 'U' in the generic type or method 'Test'. There is no implicit reference conversion from 'System.Delegate' to 'System.MulticastDelegate'. + // var d = new Test(); + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "System.Delegate").WithArguments("Test", "System.MulticastDelegate", "U", "System.Delegate").WithLocation(14, 52), + // (18,30): error CS0311: The type 'System.Delegate' cannot be used as type parameter 'U' in the generic type or method 'Test'. There is no implicit reference conversion from 'System.Delegate' to 'D1'. + // var g = new Test(); + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "System.Delegate").WithArguments("Test", "D1", "U", "System.Delegate").WithLocation(18, 30)); + } + + [Fact] + public void DelegateConstraint_IsReflectedinSymbols_Alone() + { + var code = "public class Test where T : System.Delegate { }"; + + Action validator = module => + { + var typeParameter = module.GlobalNamespace.GetTypeMember("Test").TypeParameters.Single(); + Assert.False(typeParameter.HasValueTypeConstraint); + Assert.False(typeParameter.HasReferenceTypeConstraint); + Assert.Equal(SpecialType.System_Delegate, typeParameter.ConstraintTypes().Single().SpecialType); + }; + + CompileAndVerify(code, sourceSymbolValidator: validator, symbolValidator: validator); + } + + [Fact] + public void DelegateConstraint_IsReflectedinSymbols_ValueType() + { + var compilation = CreateStandardCompilation("public class Test where T : struct, System.Delegate { }") + .VerifyDiagnostics( + // (1,19): error CS0455: Type parameter 'T' inherits conflicting constraints 'Delegate' and 'ValueType' + // public class Test where T : struct, System.Delegate { } + Diagnostic(ErrorCode.ERR_BaseConstraintConflict, "T").WithArguments("T", "System.Delegate", "System.ValueType").WithLocation(1, 19)); + + var typeParameter = compilation.GlobalNamespace.GetTypeMember("Test").TypeParameters.Single(); + + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.False(typeParameter.HasReferenceTypeConstraint); + Assert.False(typeParameter.HasConstructorConstraint); + Assert.Equal(SpecialType.System_Delegate, typeParameter.ConstraintTypes().Single().SpecialType); + } + + [Fact] + public void DelegateConstraint_IsReflectedinSymbols_ReferenceType() + { + var code = "public class Test where T : class, System.Delegate { }"; + + Action validator = module => + { + var typeParameter = module.GlobalNamespace.GetTypeMember("Test").TypeParameters.Single(); + Assert.False(typeParameter.HasValueTypeConstraint); + Assert.True(typeParameter.HasReferenceTypeConstraint); + Assert.False(typeParameter.HasConstructorConstraint); + Assert.Equal(SpecialType.System_Delegate, typeParameter.ConstraintTypes().Single().SpecialType); + }; + + CompileAndVerify(code, sourceSymbolValidator: validator, symbolValidator: validator); + } + + [Fact] + public void DelegateConstraint_IsReflectedinSymbols_Constructor() + { + var code = "public class Test where T : System.Delegate, new() { }"; + + Action validator = module => + { + var typeParameter = module.GlobalNamespace.GetTypeMember("Test").TypeParameters.Single(); + Assert.False(typeParameter.HasValueTypeConstraint); + Assert.False(typeParameter.HasReferenceTypeConstraint); + Assert.True(typeParameter.HasConstructorConstraint); + Assert.Equal(SpecialType.System_Delegate, typeParameter.ConstraintTypes().Single().SpecialType); + }; + + CompileAndVerify(code, sourceSymbolValidator: validator, symbolValidator: validator); + } + + [Fact] + public void DelegateConstraint_EnforcedInInheritanceChain_Downwards_Source() + { + CreateStandardCompilation(@" +public abstract class A +{ + public abstract void M() where T : System.Delegate; +} +public delegate void D1(); +public class B : A +{ + public override void M() { } + + public void Test() + { + this.M(); + this.M(); + } +}").VerifyDiagnostics( + // (13,9): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'B.M()'. There is no boxing conversion from 'int' to 'System.Delegate'. + // this.M(); + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "this.M").WithArguments("B.M()", "System.Delegate", "T", "int").WithLocation(13, 9)); + } + + [Fact] + public void DelegateConstraint_EnforcedInInheritanceChain_Downwards_Reference() + { + var reference = CreateStandardCompilation(@" +public abstract class A +{ + public abstract void M() where T : System.Delegate; +}").EmitToImageReference(); + + CreateStandardCompilation(@" +public delegate void D1(); +public class B : A +{ + public override void M() { } + + public void Test() + { + this.M(); + this.M(); + } +}", references: new[] { reference }).VerifyDiagnostics( + // (9,9): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'B.M()'. There is no boxing conversion from 'int' to 'System.Delegate'. + // this.M(); + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "this.M").WithArguments("B.M()", "System.Delegate", "T", "int").WithLocation(9, 9)); + } + + [Fact] + public void DelegateConstraint_EnforcedInInheritanceChain_Upwards_Source() + { + CreateStandardCompilation(@" +public abstract class A +{ + public abstract void M(); +} +public class B : A +{ + public override void M() where T : System.Delegate { } +}").VerifyDiagnostics( + // (8,33): error CS0460: Constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly + // public override void M() where T : System.Delegate { } + Diagnostic(ErrorCode.ERR_OverrideWithConstraints, "where").WithLocation(8, 33)); + } + + [Fact] + public void DelegateConstraint_EnforcedInInheritanceChain_Upwards_Reference() + { + var reference = CreateStandardCompilation(@" +public abstract class A +{ + public abstract void M(); +}").EmitToImageReference(); + + CreateStandardCompilation(@" +public class B : A +{ + public override void M() where T : System.Delegate { } +}", references: new[] { reference }).VerifyDiagnostics( + // (4,33): error CS0460: Constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly + // public override void M() where T : System.Delegate { } + Diagnostic(ErrorCode.ERR_OverrideWithConstraints, "where").WithLocation(4, 33)); + } + + [Fact] + public void DelegateConstraint_ResolveParentConstraints() + { + var comp = CreateStandardCompilation(@" +public delegate void D1(); +public abstract class A +{ + public abstract void F() where U : System.Delegate, T; +} +public class B : A +{ + public override void F() { } +}"); + + Action validator = module => + { + var method = module.GlobalNamespace.GetTypeMember("B").GetMethod("F"); + var constraintTypeNames = method.TypeParameters.Single().ConstraintTypes().Select(type => type.ToTestDisplayString()); + + AssertEx.SetEqual(new[] { "System.Delegate", "D1" }, constraintTypeNames); + }; + + CompileAndVerify(comp, sourceSymbolValidator: validator, symbolValidator: validator); + } + + [Fact] + public void DelegateConstraint_TypeNotAvailable() + { + CreateCompilation(@" +namespace System +{ + public class Object {} + public class Void {} +} +public class Test where T : System.Delegate +{ +}").VerifyDiagnostics( + // (7,39): error CS0234: The type or namespace name 'Delegate' does not exist in the namespace 'System' (are you missing an assembly reference?) + // public class Test where T : System.Delegate + Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNS, "Delegate").WithArguments("Delegate", "System").WithLocation(7, 39)); + } + + [Fact] + public void DelegateConstraint_BindingToMethods() + { + var code = @" +delegate void D1(int a, int b); +class TestClass +{ + public static void Impl(int a, int b) + { + System.Console.WriteLine($""Got {a} and {b}""); + } + public static void Main() + { + Test(Impl); + } + public static void Test(T obj) where T : System.Delegate + { + obj.DynamicInvoke(2, 3); + obj.DynamicInvoke(7, 9); + } +}"; + + CompileAndVerify(code, expectedOutput: @" +Got 2 and 3 +Got 7 and 9"); + } + + [Fact] + public void MulticastDelegateConstraint_Compilation_Alone() + { + CreateStandardCompilation(@" +public class Test where T : System.MulticastDelegate +{ +} +public delegate void D1(); +public class Test2 +{ + public void M() where U : System.MulticastDelegate + { + var a = new Test(); // delegate + var b = new Test(); // value type + var c = new Test(); // reference type + var d = new Test(); // multicast delegate type + } +}").VerifyDiagnostics( + // (11,26): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no boxing conversion from 'int' to 'System.MulticastDelegate'. + // var b = new Test(); // value type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "int").WithArguments("Test", "System.MulticastDelegate", "T", "int").WithLocation(11, 26), + // (12,26): error CS0311: The type 'string' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no implicit reference conversion from 'string' to 'System.MulticastDelegate'. + // var c = new Test(); // reference type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "string").WithArguments("Test", "System.MulticastDelegate", "T", "string").WithLocation(12, 26)); + } + + [Fact] + public void MulticastDelegateConstraint_Compilation_ReferenceType() + { + CreateStandardCompilation(@" +public class Test where T : class, System.MulticastDelegate +{ +} +public delegate void D1(); +public class Test2 +{ + public void M() where U : class, System.MulticastDelegate + { + var a = new Test(); // delegate + var b = new Test(); // value type + var c = new Test(); // reference type + var d = new Test(); // multicast delegate type + } +}").VerifyDiagnostics( + // (11,26): error CS0452: The type 'int' must be a reference type in order to use it as parameter 'T' in the generic type or method 'Test' + // var b = new Test(); // value type + Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "int").WithArguments("Test", "T", "int").WithLocation(11, 26), + // (12,26): error CS0311: The type 'string' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no implicit reference conversion from 'string' to 'System.MulticastDelegate'. + // var c = new Test(); // reference type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "string").WithArguments("Test", "System.MulticastDelegate", "T", "string").WithLocation(12, 26)); + } + + [Fact] + public void MulticastDelegateConstraint_Compilation_ValueType() + { + CreateStandardCompilation(@" +public class Test where T : struct, System.MulticastDelegate +{ +}").VerifyDiagnostics( + // (2,19): error CS0455: Type parameter 'T' inherits conflicting constraints 'MulticastDelegate' and 'ValueType' + // public class Test where T : struct, System.MulticastDelegate + Diagnostic(ErrorCode.ERR_BaseConstraintConflict, "T").WithArguments("T", "System.MulticastDelegate", "System.ValueType").WithLocation(2, 19)); + } + + [Fact] + public void MulticastDelegateConstraint_Compilation_Constructor() + { + CreateStandardCompilation(@" +public class Test where T : System.MulticastDelegate, new() +{ +} +public delegate void D1(); +public class Test2 +{ + public void M() where U : System.MulticastDelegate, new() + { + var a = new Test(); // delegate + var b = new Test(); // value type + var c = new Test(); // reference type + var d = new Test(); // multicast delegate type + } +}").VerifyDiagnostics( + // (10,26): error CS0310: 'D1' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'Test' + // var a = new Test(); // delegate + Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "D1").WithArguments("Test", "T", "D1").WithLocation(10, 26), + // (11,26): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no boxing conversion from 'int' to 'System.MulticastDelegate'. + // var b = new Test(); // value type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "int").WithArguments("Test", "System.MulticastDelegate", "T", "int").WithLocation(11, 26), + // (12,26): error CS0311: The type 'string' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no implicit reference conversion from 'string' to 'System.MulticastDelegate'. + // var c = new Test(); // reference type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "string").WithArguments("Test", "System.MulticastDelegate", "T", "string").WithLocation(12, 26), + // (12,26): error CS0310: 'string' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'Test' + // var c = new Test(); // reference type + Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "string").WithArguments("Test", "T", "string").WithLocation(12, 26)); + } + + [Fact] + public void MulticastDelegateConstraint_Reference_Alone() + { + var reference = CreateStandardCompilation(@" +public class Test where T : System.MulticastDelegate +{ +}").EmitToImageReference(); + + CreateStandardCompilation(@" +public delegate void D1(); +public class Test2 +{ + public void M() where U : System.MulticastDelegate + { + var a = new Test(); // delegate + var b = new Test(); // value type + var c = new Test(); // reference type + var d = new Test(); // multicast delegate type + } +}", references: new[] { reference }).VerifyDiagnostics( + // (8,26): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no boxing conversion from 'int' to 'System.MulticastDelegate'. + // var b = new Test(); // value type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "int").WithArguments("Test", "System.MulticastDelegate", "T", "int").WithLocation(8, 26), + // (9,26): error CS0311: The type 'string' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no implicit reference conversion from 'string' to 'System.MulticastDelegate'. + // var c = new Test(); // reference type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "string").WithArguments("Test", "System.MulticastDelegate", "T", "string").WithLocation(9, 26)); + } + + [Fact] + public void MulticastDelegateConstraint_Reference_ReferenceType() + { + var reference = CreateStandardCompilation(@" +public class Test where T : class, System.MulticastDelegate +{ +}").EmitToImageReference(); + + CreateStandardCompilation(@" +public delegate void D1(); +public class Test2 +{ + public void M() where U : class, System.MulticastDelegate + { + var a = new Test(); // delegate + var b = new Test(); // value type + var c = new Test(); // reference type + var d = new Test(); // multicast delegate type + } +}", references: new[] { reference }).VerifyDiagnostics( + // (8,26): error CS0452: The type 'int' must be a reference type in order to use it as parameter 'T' in the generic type or method 'Test' + // var b = new Test(); // value type + Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "int").WithArguments("Test", "T", "int").WithLocation(8, 26), + // (9,26): error CS0311: The type 'string' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no implicit reference conversion from 'string' to 'System.MulticastDelegate'. + // var c = new Test(); // reference type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "string").WithArguments("Test", "System.MulticastDelegate", "T", "string").WithLocation(9, 26)); + } + + [Fact] + public void MulticastDelegateConstraint_Reference_Constructor() + { + var reference = CreateStandardCompilation(@" +public class Test where T : System.MulticastDelegate, new() +{ +}").EmitToImageReference(); + + CreateStandardCompilation(@" +public delegate void D1(); +public class Test2 +{ + public void M() where U : System.MulticastDelegate, new() + { + var a = new Test(); // delegate + var b = new Test(); // value type + var c = new Test(); // reference type + var d = new Test(); // multicast delegate type + } +}", references: new[] { reference }).VerifyDiagnostics( + // (7,26): error CS0310: 'D1' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'Test' + // var a = new Test(); // delegate + Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "D1").WithArguments("Test", "T", "D1").WithLocation(7, 26), + // (8,26): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no boxing conversion from 'int' to 'System.MulticastDelegate'. + // var b = new Test(); // value type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "int").WithArguments("Test", "System.MulticastDelegate", "T", "int").WithLocation(8, 26), + // (9,26): error CS0311: The type 'string' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no implicit reference conversion from 'string' to 'System.MulticastDelegate'. + // var c = new Test(); // reference type + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "string").WithArguments("Test", "System.MulticastDelegate", "T", "string").WithLocation(9, 26), + // (9,26): error CS0310: 'string' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'Test' + // var c = new Test(); // reference type + Diagnostic(ErrorCode.ERR_NewConstraintNotSatisfied, "string").WithArguments("Test", "T", "string").WithLocation(9, 26)); + } + + [Fact] + public void MulticastDelegateConstraint_Before_7_3() + { + var code = @" +public class Test where T : System.MulticastDelegate +{ +}"; + + CreateStandardCompilation(code, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp7_2)).VerifyDiagnostics( + // (2,32): error CS8320: Feature 'delegate generic type constraints' is not available in C# 7.2. Please use language version 7.3 or greater. + // public class Test where T : System.MulticastDelegate + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "System.MulticastDelegate").WithArguments("delegate generic type constraints", "7.3").WithLocation(2, 32)); + } + + [Fact] + public void MulticastDelegateConstraint_InheritanceChain() + { + CreateStandardCompilation(@" +public delegate void D1(); +public class Test where U : System.MulticastDelegate, T +{ +} +public class Test2 +{ + public void M() + { + var a = new Test(); + + var b = new Test(); + var c = new Test(); + var d = new Test(); + var e = new Test(); + var f = new Test(); + + var g = new Test(); + var h = new Test(); + } +}").VerifyDiagnostics( + // (10,33): error CS0311: The type 'D1' cannot be used as type parameter 'U' in the generic type or method 'Test'. There is no implicit reference conversion from 'D1' to 'Test2'. + // var a = new Test(); + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "D1").WithArguments("Test", "Test2", "U", "D1").WithLocation(10, 33), + // (15,52): error CS0311: The type 'System.Delegate' cannot be used as type parameter 'U' in the generic type or method 'Test'. There is no implicit reference conversion from 'System.Delegate' to 'System.MulticastDelegate'. + // var e = new Test(); + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "System.Delegate").WithArguments("Test", "System.MulticastDelegate", "U", "System.Delegate").WithLocation(15, 52), + // (16,43): error CS0311: The type 'System.Delegate' cannot be used as type parameter 'U' in the generic type or method 'Test'. There is no implicit reference conversion from 'System.Delegate' to 'System.MulticastDelegate'. + // var f = new Test(); + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "System.Delegate").WithArguments("Test", "System.MulticastDelegate", "U", "System.Delegate").WithLocation(16, 43), + // (18,30): error CS0311: The type 'System.MulticastDelegate' cannot be used as type parameter 'U' in the generic type or method 'Test'. There is no implicit reference conversion from 'System.MulticastDelegate' to 'D1'. + // var g = new Test(); + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "System.MulticastDelegate").WithArguments("Test", "D1", "U", "System.MulticastDelegate").WithLocation(18, 30)); + } + + [Fact] + public void MulticastDelegateConstraint_IsReflectedinSymbols_Alone() + { + var code = "public class Test where T : System.MulticastDelegate { }"; + + Action validator = module => + { + var typeParameter = module.GlobalNamespace.GetTypeMember("Test").TypeParameters.Single(); + Assert.False(typeParameter.HasValueTypeConstraint); + Assert.False(typeParameter.HasReferenceTypeConstraint); + Assert.Equal(SpecialType.System_MulticastDelegate, typeParameter.ConstraintTypes().Single().SpecialType); + }; + + CompileAndVerify(code, sourceSymbolValidator: validator, symbolValidator: validator); + } + + [Fact] + public void MulticastDelegateConstraint_IsReflectedinSymbols_ValueType() + { + var compilation = CreateStandardCompilation("public class Test where T : struct, System.MulticastDelegate { }") + .VerifyDiagnostics( + // (1,19): error CS0455: Type parameter 'T' inherits conflicting constraints 'MulticastDelegate' and 'ValueType' + // public class Test where T : struct, System.MulticastDelegate { } + Diagnostic(ErrorCode.ERR_BaseConstraintConflict, "T").WithArguments("T", "System.MulticastDelegate", "System.ValueType").WithLocation(1, 19)); + + var typeParameter = compilation.GlobalNamespace.GetTypeMember("Test").TypeParameters.Single(); + + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.False(typeParameter.HasReferenceTypeConstraint); + Assert.False(typeParameter.HasConstructorConstraint); + Assert.Equal(SpecialType.System_MulticastDelegate, typeParameter.ConstraintTypes().Single().SpecialType); + } + + [Fact] + public void MulticastDelegateConstraint_IsReflectedinSymbols_ReferenceType() + { + var code = "public class Test where T : class, System.MulticastDelegate { }"; + + Action validator = module => + { + var typeParameter = module.GlobalNamespace.GetTypeMember("Test").TypeParameters.Single(); + Assert.False(typeParameter.HasValueTypeConstraint); + Assert.True(typeParameter.HasReferenceTypeConstraint); + Assert.False(typeParameter.HasConstructorConstraint); + Assert.Equal(SpecialType.System_MulticastDelegate, typeParameter.ConstraintTypes().Single().SpecialType); + }; + + CompileAndVerify(code, sourceSymbolValidator: validator, symbolValidator: validator); + } + + [Fact] + public void MulticastDelegateConstraint_IsReflectedinSymbols_Constructor() + { + var code = "public class Test where T : System.MulticastDelegate, new() { }"; + + Action validator = module => + { + var typeParameter = module.GlobalNamespace.GetTypeMember("Test").TypeParameters.Single(); + Assert.False(typeParameter.HasValueTypeConstraint); + Assert.False(typeParameter.HasReferenceTypeConstraint); + Assert.True(typeParameter.HasConstructorConstraint); + Assert.Equal(SpecialType.System_MulticastDelegate, typeParameter.ConstraintTypes().Single().SpecialType); + }; + + CompileAndVerify(code, sourceSymbolValidator: validator, symbolValidator: validator); + } + + [Fact] + public void MulticastDelegateConstraint_EnforcedInInheritanceChain_Downwards_Source() + { + CreateStandardCompilation(@" +public abstract class A +{ + public abstract void M() where T : System.MulticastDelegate; +} +public delegate void D1(); +public class B : A +{ + public override void M() { } + + public void Test() + { + this.M(); + this.M(); + } +}").VerifyDiagnostics( + // (13,9): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'B.M()'. There is no boxing conversion from 'int' to 'System.MulticastDelegate'. + // this.M(); + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "this.M").WithArguments("B.M()", "System.MulticastDelegate", "T", "int").WithLocation(13, 9)); + } + + [Fact] + public void MulticastDelegateConstraint_EnforcedInInheritanceChain_Downwards_Reference() + { + var reference = CreateStandardCompilation(@" +public abstract class A +{ + public abstract void M() where T : System.MulticastDelegate; +}").EmitToImageReference(); + + CreateStandardCompilation(@" +public delegate void D1(); +public class B : A +{ + public override void M() { } + + public void Test() + { + this.M(); + this.M(); + } +}", references: new[] { reference }).VerifyDiagnostics( + // (9,9): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'B.M()'. There is no boxing conversion from 'int' to 'System.MulticastDelegate'. + // this.M(); + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "this.M").WithArguments("B.M()", "System.MulticastDelegate", "T", "int").WithLocation(9, 9)); + } + + [Fact] + public void MulticastDelegateConstraint_EnforcedInInheritanceChain_Upwards_Source() + { + CreateStandardCompilation(@" +public abstract class A +{ + public abstract void M(); +} +public class B : A +{ + public override void M() where T : System.MulticastDelegate { } +}").VerifyDiagnostics( + // (8,33): error CS0460: Constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly + // public override void M() where T : System.MulticastDelegate { } + Diagnostic(ErrorCode.ERR_OverrideWithConstraints, "where").WithLocation(8, 33)); + } + + [Fact] + public void MulticastDelegateConstraint_EnforcedInInheritanceChain_Upwards_Reference() + { + var reference = CreateStandardCompilation(@" +public abstract class A +{ + public abstract void M(); +}").EmitToImageReference(); + + CreateStandardCompilation(@" +public class B : A +{ + public override void M() where T : System.MulticastDelegate { } +}", references: new[] { reference }).VerifyDiagnostics( + // (4,33): error CS0460: Constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly + // public override void M() where T : System.MulticastDelegate { } + Diagnostic(ErrorCode.ERR_OverrideWithConstraints, "where").WithLocation(4, 33)); + } + + [Fact] + public void MulticastDelegateConstraint_ResolveParentConstraints() + { + var comp = CreateStandardCompilation(@" +public delegate void D1(); +public abstract class A +{ + public abstract void F() where U : System.MulticastDelegate, T; +} +public class B : A +{ + public override void F() { } +}"); + + Action validator = module => + { + var method = module.GlobalNamespace.GetTypeMember("B").GetMethod("F"); + var constraintTypeNames = method.TypeParameters.Single().ConstraintTypes().Select(type => type.ToTestDisplayString()); + + AssertEx.SetEqual(new[] { "System.MulticastDelegate", "D1" }, constraintTypeNames); + }; + + CompileAndVerify(comp, sourceSymbolValidator: validator, symbolValidator: validator); + } + + [Fact] + public void MulticastDelegateConstraint_TypeNotAvailable() + { + CreateCompilation(@" +namespace System +{ + public class Object {} + public class Void {} +} +public class Test where T : System.MulticastDelegate +{ +}").VerifyDiagnostics( + // (7,39): error CS0234: The type or namespace name 'MulticastDelegate' does not exist in the namespace 'System' (are you missing an assembly reference?) + // public class Test where T : System.MulticastDelegate + Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNS, "MulticastDelegate").WithArguments("MulticastDelegate", "System").WithLocation(7, 39)); + } + + [Fact] + public void MulticastDelegateConstraint_BindingToMethods() + { + var code = @" +delegate void D1(int a, int b); +class TestClass +{ + public static void Impl(int a, int b) + { + System.Console.WriteLine($""Got {a} and {b}""); + } + public static void Main() + { + Test(Impl); + } + public static void Test(T obj) where T : System.MulticastDelegate + { + obj.DynamicInvoke(2, 3); + obj.DynamicInvoke(7, 9); + } +}"; + + CompileAndVerify(code, expectedOutput: @" +Got 2 and 3 +Got 7 and 9"); + } + + [Fact] + public void ConversionInInheritanceChain_MulticastDelegate() + { + var code = @" +class A where T : System.Delegate { } +class B : A where T : System.MulticastDelegate { }"; + + CreateStandardCompilation(code).VerifyDiagnostics(); + + code = @" +class A where T : System.MulticastDelegate { } +class B : A where T : System.Delegate { }"; + + CreateStandardCompilation(code).VerifyDiagnostics( + // (3,7): error CS0311: The type 'T' cannot be used as type parameter 'T' in the generic type or method 'A'. There is no implicit reference conversion from 'T' to 'System.MulticastDelegate'. + // class B : A where T : System.Delegate { } + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "B").WithArguments("A", "System.MulticastDelegate", "T", "T").WithLocation(3, 7)); + } } } diff --git a/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs b/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs index 32b99f410a880..1720aa1680e1e 100644 --- a/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs @@ -6305,6 +6305,30 @@ Structure X SymbolDisplayPartKind.StructName); } + [Fact] + public void EnumConstraint_Type() + { + TestSymbolDescription( + "class X where T : System.Enum { }", + global => global.GetTypeMember("X"), + SymbolDisplayFormat.TestFormat.WithGenericsOptions(SymbolDisplayGenericsOptions.IncludeTypeParameters | SymbolDisplayGenericsOptions.IncludeTypeConstraints), + "X where T : System.Enum", + SymbolDisplayPartKind.ClassName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.TypeParameterName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.TypeParameterName, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.NamespaceName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.ClassName); + } + [Fact] public void EnumConstraint() { @@ -6317,5 +6341,79 @@ public void EnumConstraint() SymbolDisplayPartKind.Punctuation, SymbolDisplayPartKind.ClassName); } + + [Fact] + public void DelegateConstraint_Type() + { + TestSymbolDescription( + "class X where T : System.Delegate { }", + global => global.GetTypeMember("X"), + SymbolDisplayFormat.TestFormat.WithGenericsOptions(SymbolDisplayGenericsOptions.IncludeTypeParameters | SymbolDisplayGenericsOptions.IncludeTypeConstraints), + "X where T : System.Delegate", + SymbolDisplayPartKind.ClassName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.TypeParameterName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.TypeParameterName, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.NamespaceName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.ClassName); + } + + [Fact] + public void DelegateConstraint() + { + TestSymbolDescription( + "class X where T : System.Delegate { }", + global => global.GetTypeMember("X").TypeParameters.Single().ConstraintTypes().Single(), + SymbolDisplayFormat.TestFormat, + "System.Delegate", + SymbolDisplayPartKind.NamespaceName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.ClassName); + } + + [Fact] + public void MulticastDelegateConstraint_Type() + { + TestSymbolDescription( + "class X where T : System.MulticastDelegate { }", + global => global.GetTypeMember("X"), + SymbolDisplayFormat.TestFormat.WithGenericsOptions(SymbolDisplayGenericsOptions.IncludeTypeParameters | SymbolDisplayGenericsOptions.IncludeTypeConstraints), + "X where T : System.MulticastDelegate", + SymbolDisplayPartKind.ClassName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.TypeParameterName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.TypeParameterName, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.NamespaceName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.ClassName); + } + + [Fact] + public void MulticastDelegateConstraint() + { + TestSymbolDescription( + "class X where T : System.MulticastDelegate { }", + global => global.GetTypeMember("X").TypeParameters.Single().ConstraintTypes().Single(), + SymbolDisplayFormat.TestFormat, + "System.MulticastDelegate", + SymbolDisplayPartKind.NamespaceName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.ClassName); + } } } diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs index 465f41475afe7..e53ac25dc7f66 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs @@ -12282,8 +12282,7 @@ public void CS0702ERR_SpecialTypeAsBound() interface IA where T : object { } interface IB where T : System.Object { } interface IC where T : ValueType { } -interface ID where T : Array { } -interface IE where T : Delegate where U : MulticastDelegate { }"; +interface ID where T : Array { }"; CreateStandardCompilation(source).VerifyDiagnostics( // (2,27): error CS0702: Constraint cannot be special class 'object' Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "object").WithArguments("object").WithLocation(2, 27), @@ -12292,11 +12291,7 @@ interface IE where T : Delegate where U : MulticastDelegate { }"; // (4,30): error CS0702: Constraint cannot be special class 'System.ValueType' Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "ValueType").WithArguments("System.ValueType").WithLocation(4, 30), // (5,27): error CS0702: Constraint cannot be special class 'System.Array' - Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "Array").WithArguments("System.Array").WithLocation(5, 27), - // (6,30): error CS0702: Constraint cannot be special class 'System.Delegate' - Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "Delegate").WithArguments("System.Delegate").WithLocation(6, 30), - // (6,49): error CS0702: Constraint cannot be special class 'System.MulticastDelegate' - Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "MulticastDelegate").WithArguments("System.MulticastDelegate").WithLocation(6, 49)); + Diagnostic(ErrorCode.ERR_SpecialTypeAsBound, "Array").WithArguments("System.Array").WithLocation(5, 27)); } [Fact] diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/GenericConstraintTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/GenericConstraintTests.vb index 0bf9b2d85374e..9b6ea224b809a 100644 --- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/GenericConstraintTests.vb +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/GenericConstraintTests.vb @@ -5754,6 +5754,74 @@ BC32044: Type argument 'String' does not inherit from or implement the constrain ) End Sub + + Public Sub DelegateConstraint_FromCSharp() + Dim reference = CreateCSharpCompilation(" +public class Test where T : System.Delegate +{ +}", parseOptions:=New CSharp.CSharpParseOptions(CSharp.LanguageVersion.CSharp7_3)).EmitToImageReference() + + Dim compilation = CompilationUtils.CreateCompilationWithMscorlibAndVBRuntime( + + +Delegate Sub D1() + +Public Class Test2 + Public Sub M() + Dim a = new Test(Of D1)() ' delegate + Dim b = new Test(Of Integer)() ' value type + Dim c = new Test(Of string)() ' reference type + Dim d = new Test(Of System.Delegate)() ' Delegate type + End Sub +End Class + +, {reference}) + + AssertTheseDiagnostics(compilation, + +BC32044: Type argument 'Integer' does not inherit from or implement the constraint type '[Delegate]'. + Dim b = new Test(Of Integer)() ' value type + ~~~~~~~ +BC32044: Type argument 'String' does not inherit from or implement the constraint type '[Delegate]'. + Dim c = new Test(Of string)() ' reference type + ~~~~~~ +) + End Sub + + + Public Sub MulticastDelegateConstraint_FromCSharp() + Dim reference = CreateCSharpCompilation(" +public class Test where T : System.MulticastDelegate +{ +}", parseOptions:=New CSharp.CSharpParseOptions(CSharp.LanguageVersion.CSharp7_3)).EmitToImageReference() + + Dim compilation = CompilationUtils.CreateCompilationWithMscorlibAndVBRuntime( + + +Delegate Sub D1() + +Public Class Test2 + Public Sub M() + Dim a = new Test(Of D1)() ' delegate + Dim b = new Test(Of Integer)() ' value type + Dim c = new Test(Of string)() ' reference type + Dim d = new Test(Of System.MulticastDelegate)() ' MulticastDelegate type + End Sub +End Class + +, {reference}) + + AssertTheseDiagnostics(compilation, + +BC32044: Type argument 'Integer' does not inherit from or implement the constraint type 'MulticastDelegate'. + Dim b = new Test(Of Integer)() ' value type + ~~~~~~~ +BC32044: Type argument 'String' does not inherit from or implement the constraint type 'MulticastDelegate'. + Dim c = new Test(Of string)() ' reference type + ~~~~~~ +) + End Sub + End Class End Namespace diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs index e761651a64900..8c2eb32a5d7e9 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs @@ -9210,5 +9210,23 @@ public async Task EnumConstraint() "; await VerifyItemExistsAsync(markup, "Enum"); } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task DelegateConstraint() + { + var markup = +@"public class X where T : System.$$ +"; + await VerifyItemExistsAsync(markup, "Delegate"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task MulticastDelegateConstraint() + { + var markup = +@"public class X where T : System.$$ +"; + await VerifyItemExistsAsync(markup, "MulticastDelegate"); + } } } diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs index 01a8abee2d407..4ad8054682884 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs @@ -265,6 +265,32 @@ await TestLanguageVersionUpgradedAsync( @"public class X where T : [|System.Enum|] { } +", + LanguageVersion.CSharp7_3, + new CSharpParseOptions(LanguageVersion.CSharp7_2), + index: 1); + } + + [Fact] + public async Task UpgradeProjectFromCSharp7_2ToLatest_DelegateConstraint() + { + await TestLanguageVersionUpgradedAsync( +@"public class X where T : [|System.Delegate|] +{ +} +", + LanguageVersion.CSharp7_3, + new CSharpParseOptions(LanguageVersion.CSharp7_2), + index: 1); + } + + [Fact] + public async Task UpgradeProjectFromCSharp7_2ToLatest_MulticastDelegateConstraint() + { + await TestLanguageVersionUpgradedAsync( +@"public class X where T : [|System.MulticastDelegate|] +{ +} ", LanguageVersion.CSharp7_3, new CSharpParseOptions(LanguageVersion.CSharp7_2), diff --git a/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs b/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs index bf91ab874e455..335cbc9b923a8 100644 --- a/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs +++ b/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs @@ -5164,5 +5164,29 @@ class X where T : System.Enum }", MainDescription($"T {FeaturesResources.in_} X where T : Enum")); } + + [Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)] + public async Task DelegateConstraint() + { + await TestInMethodAsync( +@" +class X where T : System.Delegate +{ + private $$T x; +}", + MainDescription($"T {FeaturesResources.in_} X where T : Delegate")); + } + + [Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)] + public async Task MulticastDelegateConstraint() + { + await TestInMethodAsync( +@" +class X where T : System.MulticastDelegate +{ + private $$T x; +}", + MainDescription($"T {FeaturesResources.in_} X where T : MulticastDelegate")); + } } } From eabb4a09b2d28758cfae869e2c477bfbddbb8d5b Mon Sep 17 00:00:00 2001 From: Omar Tawfik Date: Sat, 24 Feb 2018 12:18:43 +0200 Subject: [PATCH 03/13] Support unmanaged constraint (#24817) * Source changes for unmanaged (PROTOTYPE for metadata) * Modreqs for unmanaged as well * Finished roundtripping metadata * Added more tests * Fix CI * More tests * Clean up --- .../Portable/Binder/Binder_Constraints.cs | 97 +- .../Portable/Binder/Binder_Expressions.cs | 2 +- .../CSharp/Portable/Binder/Binder_Patterns.cs | 2 +- .../Portable/Binder/Binder_Statements.cs | 4 +- .../CSharp/Portable/Binder/Binder_Symbols.cs | 262 ++-- .../Portable/Binder/ForEachLoopBinder.cs | 2 +- .../Portable/CSharpResources.Designer.cs | 54 + .../CSharp/Portable/CSharpResources.resx | 18 + .../Emitter/Model/PEAssemblyBuilder.cs | 29 + .../Portable/Emitter/Model/PEModuleBuilder.cs | 28 +- .../Model/TypeParameterSymbolAdapter.cs | 63 +- .../CSharp/Portable/Errors/ErrorCode.cs | 6 + .../CSharp/Portable/Errors/MessageID.cs | 2 + .../CSharp/Portable/PublicAPI.Unshipped.txt | 1 + .../AnonymousType.TypeParameterSymbol.cs | 5 + .../Symbols/Compilation_WellKnownMembers.cs | 42 +- .../Portable/Symbols/ConstraintsHelper.cs | 27 +- ...rrorTypeSymbol.ErrorTypeParameterSymbol.cs | 8 + .../Metadata/PE/PETypeParameterSymbol.cs | 178 ++- .../Symbols/Metadata/PE/SymbolFactory.cs | 5 + .../Symbols/Source/CrefTypeParameterSymbol.cs | 5 + .../FieldSymbolWithAttributesAndModifiers.cs | 5 + .../Source/GlobalExpressionVariable.cs | 2 +- .../Source/IndexedTypeParameterSymbol.cs | 5 + .../Symbols/Source/LocalFunctionSymbol.cs | 5 + .../Source/SourceComplexParameterSymbol.cs | 5 + .../Symbols/Source/SourceLocalSymbol.cs | 4 +- .../Source/SourceMemberContainerSymbol.cs | 9 + .../Symbols/Source/SourceMemberFieldSymbol.cs | 2 +- .../Source/SourceMemberMethodSymbol.cs | 10 + .../Symbols/Source/SourceNamedTypeSymbol.cs | 5 + .../Source/SourceOrdinaryMethodSymbol.cs | 8 + .../Symbols/Source/SourcePropertySymbol.cs | 5 + .../Source/SourceTypeParameterSymbol.cs | 42 +- .../Source/TypeParameterConstraintClause.cs | 1 + ...nthesizedSubstitutedTypeParameterSymbol.cs | 13 + .../Portable/Symbols/TypeParameterSymbol.cs | 4 +- .../Portable/Symbols/TypeSymbolExtensions.cs | 8 +- .../Wrapped/WrappedTypeParameterSymbol.cs | 8 + .../Syntax/InternalSyntax/TypeSyntax.cs | 11 +- .../CSharp/Portable/Syntax/TypeSyntax.cs | 10 +- .../Portable/xlf/CSharpResources.cs.xlf | 30 + .../Portable/xlf/CSharpResources.de.xlf | 30 + .../Portable/xlf/CSharpResources.es.xlf | 30 + .../Portable/xlf/CSharpResources.fr.xlf | 30 + .../Portable/xlf/CSharpResources.it.xlf | 30 + .../Portable/xlf/CSharpResources.ja.xlf | 30 + .../Portable/xlf/CSharpResources.ko.xlf | 30 + .../Portable/xlf/CSharpResources.pl.xlf | 30 + .../Portable/xlf/CSharpResources.pt-BR.xlf | 30 + .../Portable/xlf/CSharpResources.ru.xlf | 30 + .../Portable/xlf/CSharpResources.tr.xlf | 30 + .../Portable/xlf/CSharpResources.zh-Hans.xlf | 30 + .../Portable/xlf/CSharpResources.zh-Hant.xlf | 30 + .../Attributes/AttributeTests_IsUnmanaged.cs | 593 +++++++++ .../Emit/Emit/UnmanagedTypeModifierTests.cs | 1098 +++++++++++++++++ .../Semantics/GenericConstraintsTests.cs | 874 ++++++++++++- .../Semantic/Semantics/UsingStatementTests.cs | 31 +- .../Symbol/Symbols/MissingSpecialMember.cs | 2 + .../Syntax/Parsing/ParserErrorMessageTests.cs | 14 +- .../MetadataReader/MetadataDecoder.cs | 57 +- .../Core/Portable/MetadataReader/PEModule.cs | 5 + .../Portable/MetadataReader/SymbolFactory.cs | 2 + .../MetadataReader/TypeNameDecoder.cs | 5 + .../Attributes/AttributeDescription.cs | 2 + .../Core/Portable/WellKnownMember.cs | 2 + .../Core/Portable/WellKnownMembers.cs | 9 + src/Compilers/Core/Portable/WellKnownTypes.cs | 4 + .../Symbols/Metadata/PE/SymbolFactory.vb | 5 + .../Metadata/PE/LoadCustomModifiers.vb | 97 +- .../WellKnownTypeValidationTests.vb | 12 +- .../EditAndContinue/TopLevelEditingTests.cs | 84 +- .../Symbols/EETypeParameterSymbol.cs | 5 + .../Symbols/SimpleTypeParameterSymbol.cs | 5 + 74 files changed, 3984 insertions(+), 314 deletions(-) create mode 100644 src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_IsUnmanaged.cs create mode 100644 src/Compilers/CSharp/Test/Emit/Emit/UnmanagedTypeModifierTests.cs diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs index 4bbac7ae4e8c5..6681b255bc933 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs @@ -92,7 +92,6 @@ private TypeParameterConstraintClause BindTypeParameterConstraints( { var constraints = TypeParameterConstraintKind.None; var constraintTypes = ArrayBuilder.GetInstance(); - var isStruct = false; for (int i = 0, n = constraintsSyntax.Count; i < n; i++) { @@ -113,14 +112,17 @@ private TypeParameterConstraintClause BindTypeParameterConstraints( diagnostics.Add(ErrorCode.ERR_RefValBoundMustBeFirst, syntax.GetFirstToken().GetLocation()); } - isStruct = true; constraints |= TypeParameterConstraintKind.ValueType; continue; case SyntaxKind.ConstructorConstraint: - if (isStruct) + if ((constraints & TypeParameterConstraintKind.ValueType) != 0) { diagnostics.Add(ErrorCode.ERR_NewBoundWithVal, syntax.GetFirstToken().GetLocation()); } + if ((constraints & TypeParameterConstraintKind.Unmanaged) != 0) + { + diagnostics.Add(ErrorCode.ERR_NewBoundWithUnmanaged, syntax.GetFirstToken().GetLocation()); + } if (i != n - 1) { @@ -133,55 +135,80 @@ private TypeParameterConstraintClause BindTypeParameterConstraints( { var typeConstraintSyntax = (TypeConstraintSyntax)syntax; var typeSyntax = typeConstraintSyntax.Type; - if (typeSyntax.Kind() != SyntaxKind.PredefinedType && !SyntaxFacts.IsName(typeSyntax.Kind())) + var typeSyntaxKind = typeSyntax.Kind(); + if (typeSyntaxKind != SyntaxKind.PredefinedType && typeSyntaxKind != SyntaxKind.PointerType && !SyntaxFacts.IsName(typeSyntax.Kind())) { diagnostics.Add(ErrorCode.ERR_BadConstraintType, typeSyntax.GetLocation()); } - var type = this.BindType(typeSyntax, diagnostics); + var type = BindTypeOrUnmanagedKeyword(typeSyntax, diagnostics, out var isUnmanaged); - // Only valid constraint types are included in ConstraintTypes - // since, in general, it may be difficult to support all invalid types. - // In the future, we may want to include some invalid types - // though so the public binding API has the most information. - if (!IsValidConstraintType(typeConstraintSyntax, type, diagnostics)) + if (isUnmanaged) { - continue; - } + if (constraints != 0 || constraintTypes.Any()) + { + diagnostics.Add(ErrorCode.ERR_UnmanagedConstraintMustBeAlone, typeSyntax.GetLocation()); + continue; + } - if (constraintTypes.Contains(type)) - { - // "Duplicate constraint '{0}' for type parameter '{1}'" - Error(diagnostics, ErrorCode.ERR_DuplicateBound, syntax, type, name); + // This should produce diagnostics if the types are missing + GetWellKnownType(WellKnownType.System_Runtime_InteropServices_UnmanagedType, diagnostics, typeSyntax); + GetSpecialType(SpecialType.System_ValueType, diagnostics, typeSyntax); + + constraints |= TypeParameterConstraintKind.Unmanaged; continue; } - - if (type.TypeKind == TypeKind.Class) + else { - // If there is already a struct or class constraint (class constraint could be - // 'class' or explicit type), report an error and drop this class. If we don't - // drop this additional class, we may end up with conflicting class constraints. + // Only valid constraint types are included in ConstraintTypes + // since, in general, it may be difficult to support all invalid types. + // In the future, we may want to include some invalid types + // though so the public binding API has the most information. + if (!IsValidConstraintType(typeConstraintSyntax, type, diagnostics)) + { + continue; + } + + if (constraintTypes.Contains(type)) + { + // "Duplicate constraint '{0}' for type parameter '{1}'" + Error(diagnostics, ErrorCode.ERR_DuplicateBound, syntax, type, name); + continue; + } - if (constraintTypes.Count > 0) + if ((constraints & TypeParameterConstraintKind.Unmanaged) != 0) { - // "The class type constraint '{0}' must come before any other constraints" - Error(diagnostics, ErrorCode.ERR_ClassBoundNotFirst, syntax, type); + diagnostics.Add(ErrorCode.ERR_UnmanagedConstraintMustBeAlone, typeSyntax.GetLocation()); continue; } - if ((constraints & (TypeParameterConstraintKind.ReferenceType | TypeParameterConstraintKind.ValueType)) != 0) + if (type.TypeKind == TypeKind.Class) { - switch (type.SpecialType) + // If there is already a struct or class constraint (class constraint could be + // 'class' or explicit type), report an error and drop this class. If we don't + // drop this additional class, we may end up with conflicting class constraints. + + if (constraintTypes.Count > 0) + { + // "The class type constraint '{0}' must come before any other constraints" + Error(diagnostics, ErrorCode.ERR_ClassBoundNotFirst, syntax, type); + continue; + } + + if ((constraints & (TypeParameterConstraintKind.ReferenceType | TypeParameterConstraintKind.ValueType)) != 0) { - case SpecialType.System_Enum: - case SpecialType.System_Delegate: - case SpecialType.System_MulticastDelegate: - break; - - default: - // "'{0}': cannot specify both a constraint class and the 'class' or 'struct' constraint" - Error(diagnostics, ErrorCode.ERR_RefValBoundWithClass, syntax, type); - continue; + switch (type.SpecialType) + { + case SpecialType.System_Enum: + case SpecialType.System_Delegate: + case SpecialType.System_MulticastDelegate: + break; + + default: + // "'{0}': cannot specify both a constraint class and the 'class' or 'struct' constraint" + Error(diagnostics, ErrorCode.ERR_RefValBoundWithClass, syntax, type); + continue; + } } } } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index b628245f57b56..61e65a7a00be1 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -2340,7 +2340,7 @@ private BoundExpression BindOutVariableDeclarationArgument( if (typeSyntax.IsVar) { var ignored = DiagnosticBag.GetInstance(); - BindTypeOrAlias(typeSyntax, ignored, out isVar); + BindTypeOrAliasOrVarKeyword(typeSyntax, ignored, out isVar); ignored.Free(); if (isVar) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs index a6fa796576238..34dd0ad30edba 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs @@ -245,7 +245,7 @@ private BoundPattern BindDeclarationPattern( bool isVar; AliasSymbol aliasOpt; - TypeSymbol declType = BindType(typeSyntax, diagnostics, out isVar, out aliasOpt); + TypeSymbol declType = BindTypeOrVarKeyword(typeSyntax, diagnostics, out isVar, out aliasOpt); if (isVar) { declType = operandType; diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs index 658eb47cd7b02..9d31a726eae5f 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs @@ -641,7 +641,7 @@ declarationNode is VariableDesignationSyntax || // we want to treat the declaration as an explicitly typed declaration. RefKind refKind; - TypeSymbol declType = BindType(typeSyntax.SkipRef(out refKind), diagnostics, out isVar, out alias); + TypeSymbol declType = BindTypeOrVarKeyword(typeSyntax.SkipRef(out refKind), diagnostics, out isVar, out alias); Debug.Assert((object)declType != null || isVar); if (isVar) @@ -2153,7 +2153,7 @@ internal BoundStatement BindForOrUsingOrFixedDeclarations(VariableDeclarationSyn AliasSymbol alias; bool isVar; - TypeSymbol declType = BindType(typeSyntax, diagnostics, out isVar, out alias); + TypeSymbol declType = BindTypeOrVarKeyword(typeSyntax, diagnostics, out isVar, out alias); Debug.Assert((object)declType != null || isVar); diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs index da9092875fd1f..73b7807fad77e 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs @@ -5,7 +5,6 @@ using System.Collections.Immutable; using System.Diagnostics; using System.Linq; -using Microsoft.CodeAnalysis.Collections; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.PooledObjects; @@ -29,13 +28,33 @@ internal partial class Binder /// Bound type if syntax binds to a type in the current context and /// null if syntax binds to "var" keyword in the current context. /// - internal TypeSymbol BindType(TypeSyntax syntax, DiagnosticBag diagnostics, out bool isVar) + internal TypeSymbol BindTypeOrVarKeyword(TypeSyntax syntax, DiagnosticBag diagnostics, out bool isVar) { - var symbol = BindTypeOrAlias(syntax, diagnostics, out isVar); + var symbol = BindTypeOrAliasOrVarKeyword(syntax, diagnostics, out isVar); Debug.Assert(isVar == ((object)symbol == null)); return isVar ? null : (TypeSymbol)UnwrapAlias(symbol, diagnostics, syntax); } + /// + /// Binds the type for the syntax taking into account possibility of "unmanaged" type. + /// + /// Type syntax to bind. + /// Diagnostics. + /// + /// Set to false if syntax binds to a type in the current context and true if + /// syntax is "unmanaged" and it binds to "unmanaged" keyword in the current context. + /// + /// + /// Bound type if syntax binds to a type in the current context and + /// null if syntax binds to "unmanaged" keyword in the current context. + /// + internal TypeSymbol BindTypeOrUnmanagedKeyword(TypeSyntax syntax, DiagnosticBag diagnostics, out bool isUnmanaged) + { + var symbol = BindTypeOrAliasOrUnmanagedKeyword(syntax, diagnostics, out isUnmanaged); + Debug.Assert(isUnmanaged == ((object)symbol == null)); + return isUnmanaged ? null : (TypeSymbol)UnwrapAlias(symbol, diagnostics, syntax); + } + /// /// Binds the type for the syntax taking into account possibility of "var" type. /// @@ -50,9 +69,9 @@ internal TypeSymbol BindType(TypeSyntax syntax, DiagnosticBag diagnostics, out b /// Bound type if syntax binds to a type in the current context and /// null if syntax binds to "var" keyword in the current context. /// - internal TypeSymbol BindType(TypeSyntax syntax, DiagnosticBag diagnostics, out bool isVar, out AliasSymbol alias) + internal TypeSymbol BindTypeOrVarKeyword(TypeSyntax syntax, DiagnosticBag diagnostics, out bool isVar, out AliasSymbol alias) { - var symbol = BindTypeOrAlias(syntax, diagnostics, out isVar); + var symbol = BindTypeOrAliasOrVarKeyword(syntax, diagnostics, out isVar); Debug.Assert(isVar == ((object)symbol == null)); if (isVar) { @@ -64,137 +83,150 @@ internal TypeSymbol BindType(TypeSyntax syntax, DiagnosticBag diagnostics, out b return (TypeSymbol)UnwrapAlias(symbol, out alias, diagnostics, syntax); } } - - /// - /// Binds the type for the syntax taking into account possibility of "var" type. - /// If the syntax binds to an alias symbol to a type, it returns the alias symbol. - /// - /// Type syntax to bind. - /// Diagnostics. - /// - /// Set to false if syntax binds to a type or alias to a type in the current context and true if - /// syntax is "var" and it binds to "var" keyword in the current context. - /// - /// - /// Bound type or alias if syntax binds to a type or alias to a type in the current context and - /// null if syntax binds to "var" keyword in the current context. - /// - private Symbol BindTypeOrAlias(TypeSyntax syntax, DiagnosticBag diagnostics, out bool isVar) + + private Symbol BindTypeOrAliasOrVarKeyword(TypeSyntax syntax, DiagnosticBag diagnostics, out bool isVar) { - ConsList basesBeingResolved = null; - if (!syntax.IsVar) + if (syntax.IsVar) { - isVar = false; - return BindTypeOrAlias(syntax, diagnostics, basesBeingResolved); + var symbol = BindTypeOrAliasOrKeyword(syntax, diagnostics, out isVar); + + if (isVar) + { + CheckFeatureAvailability(syntax, MessageID.IDS_FeatureImplicitLocal, diagnostics); + } + + return symbol; } else { - // Only IdentifierNameSyntax instances may be 'var'. - var identifierValueText = ((IdentifierNameSyntax)syntax).Identifier.ValueText; + isVar = false; + return BindTypeOrAlias(syntax, diagnostics, basesBeingResolved: null); + } + } + + private Symbol BindTypeOrAliasOrUnmanagedKeyword(TypeSyntax syntax, DiagnosticBag diagnostics, out bool isUnmanaged) + { + if (syntax.IsUnmanaged) + { + var symbol = BindTypeOrAliasOrKeyword(syntax, diagnostics, out isUnmanaged); - Symbol symbol = null; + if (isUnmanaged) + { + CheckFeatureAvailability(syntax, MessageID.IDS_FeatureUnmanagedGenericTypeConstraint, diagnostics); + } - // Perform name lookup without generating diagnostics as it could possibly be - // "var" keyword in the current context. - var lookupResult = LookupResult.GetInstance(); - HashSet useSiteDiagnostics = null; - this.LookupSymbolsInternal(lookupResult, identifierValueText, arity: 0, useSiteDiagnostics: ref useSiteDiagnostics, basesBeingResolved: basesBeingResolved, - options: LookupOptions.NamespacesOrTypesOnly, diagnose: false); - diagnostics.Add(syntax, useSiteDiagnostics); + return symbol; + } + else + { + isUnmanaged = false; + return BindTypeOrAlias(syntax, diagnostics, basesBeingResolved: null); + } + } - // We have following possible cases for lookup: + /// + /// Binds the type for the syntax taking into account possibility of the type being a keyword. + /// If the syntax binds to an alias symbol to a type, it returns the alias symbol. + /// PREREQUISITE: syntax should be checked to match the keyword, like or . + /// Otherwise, call instead. + /// + private Symbol BindTypeOrAliasOrKeyword(TypeSyntax syntax, DiagnosticBag diagnostics, out bool isKeyword) + { + // Keywords can only be IdentifierNameSyntax + var identifierValueText = ((IdentifierNameSyntax)syntax).Identifier.ValueText; + Symbol symbol = null; + + // Perform name lookup without generating diagnostics as it could possibly be a keyword in the current context. + var lookupResult = LookupResult.GetInstance(); + HashSet useSiteDiagnostics = null; + this.LookupSymbolsInternal(lookupResult, identifierValueText, arity: 0, useSiteDiagnostics: ref useSiteDiagnostics, basesBeingResolved: null, options: LookupOptions.NamespacesOrTypesOnly, diagnose: false); - // 1) LookupResultKind.Empty: isVar = true + // We have following possible cases for lookup: - // 2) LookupResultKind.Viable: - // a) Single viable result that corresponds to 1) a non-error type: isVar = false - // 2) an error type: isVar = true - // b) Single viable result that corresponds to namespace: isVar = true - // c) Multi viable result (ambiguous result), we must return an error type: isVar = false + // 1) LookupResultKind.Empty: must be a keyword - // 3) Non viable, non empty lookup result: isVar = true + // 2) LookupResultKind.Viable: + // a) Single viable result that corresponds to 1) a non-error type: cannot be a keyword + // 2) an error type: must be a keyword + // b) Single viable result that corresponds to namespace: must be a keyword + // c) Multi viable result (ambiguous result), we must return an error type: cannot be a keyword - // BREAKING CHANGE: Case (2)(c) is a breaking change from the native compiler. - // BREAKING CHANGE: Native compiler interprets lookup with ambiguous result to correspond to bind - // BREAKING CHANGE: to "var" keyword (isVar = true), rather than reporting an error. - // BREAKING CHANGE: See test SemanticErrorTests.ErrorMeansSuccess_var() for an example. + // 3) Non viable, non empty lookup result: must be a keyword - switch (lookupResult.Kind) - { - case LookupResultKind.Empty: - // Case (1) - isVar = true; - symbol = null; - break; + // BREAKING CHANGE: Case (2)(c) is a breaking change from the native compiler. + // BREAKING CHANGE: Native compiler interprets lookup with ambiguous result to correspond to bind + // BREAKING CHANGE: to "var" keyword (isVar = true), rather than reporting an error. + // BREAKING CHANGE: See test SemanticErrorTests.ErrorMeansSuccess_var() for an example. - case LookupResultKind.Viable: - // Case (2) - DiagnosticBag resultDiagnostics = DiagnosticBag.GetInstance(); - bool wasError; - symbol = ResultSymbol( - lookupResult, - identifierValueText, - arity: 0, - where: syntax, - diagnostics: resultDiagnostics, - suppressUseSiteDiagnostics: false, - wasError: out wasError); - - // Here, we're mimicking behavior of dev10. If "var" fails to bind - // as a type, even if the reason is (e.g.) a type/alias conflict, then treat - // it as the contextual keyword. - if (wasError && lookupResult.IsSingleViable) - { - // NOTE: don't report diagnostics - we're not going to use the lookup result. - resultDiagnostics.Free(); - // Case (2)(a)(2) - goto default; - } + switch (lookupResult.Kind) + { + case LookupResultKind.Empty: + // Case (1) + isKeyword = true; + symbol = null; + break; - diagnostics.AddRange(resultDiagnostics); + case LookupResultKind.Viable: + // Case (2) + DiagnosticBag resultDiagnostics = DiagnosticBag.GetInstance(); + bool wasError; + symbol = ResultSymbol( + lookupResult, + identifierValueText, + arity: 0, + where: syntax, + diagnostics: resultDiagnostics, + suppressUseSiteDiagnostics: false, + wasError: out wasError); + + // Here, we're mimicking behavior of dev10. If the identifier fails to bind + // as a type, even if the reason is (e.g.) a type/alias conflict, then treat + // it as the contextual keyword. + if (wasError && lookupResult.IsSingleViable) + { + // NOTE: don't report diagnostics - we're not going to use the lookup result. resultDiagnostics.Free(); + // Case (2)(a)(2) + goto default; + } - if (lookupResult.IsSingleViable) - { - var type = UnwrapAlias(symbol, diagnostics, syntax) as TypeSymbol; + diagnostics.AddRange(resultDiagnostics); + resultDiagnostics.Free(); - if ((object)type != null) - { - // Case (2)(a)(1) - isVar = false; - } - else - { - // Case (2)(b) - Debug.Assert(UnwrapAliasNoDiagnostics(symbol) is NamespaceSymbol); - isVar = true; - symbol = null; - } + if (lookupResult.IsSingleViable) + { + var type = UnwrapAlias(symbol, diagnostics, syntax) as TypeSymbol; + + if ((object)type != null) + { + // Case (2)(a)(1) + isKeyword = false; } else { - // Case (2)(c) - isVar = false; + // Case (2)(b) + Debug.Assert(UnwrapAliasNoDiagnostics(symbol) is NamespaceSymbol); + isKeyword = true; + symbol = null; } + } + else + { + // Case (2)(c) + isKeyword = false; + } - break; - - default: - // Case (3) - isVar = true; - symbol = null; - break; - } - - lookupResult.Free(); - - if (isVar) - { - CheckFeatureAvailability(syntax, MessageID.IDS_FeatureImplicitLocal, diagnostics); - } + break; - return symbol; + default: + // Case (3) + isKeyword = true; + symbol = null; + break; } + + lookupResult.Free(); + return symbol; } // Binds the given expression syntax as Type. @@ -371,7 +403,13 @@ internal Symbol BindNamespaceOrTypeOrAliasSymbol(ExpressionSyntax syntax, Diagno var elementType = BindType(node.ElementType, diagnostics, basesBeingResolved); ReportUnsafeIfNotAllowed(node, diagnostics); - if (elementType.IsManagedType) + // Checking BinderFlags.GenericConstraintsClause to prevent cycles in binding + if (Flags.HasFlag(BinderFlags.GenericConstraintsClause) && elementType.TypeKind == TypeKind.TypeParameter) + { + // 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) { // "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); diff --git a/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs b/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs index a40f8ba19e49a..913d87110a77d 100644 --- a/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs @@ -221,7 +221,7 @@ private BoundForEachStatement BindForEachPartsWorker(DiagnosticBag diagnostics, bool isVar; AliasSymbol alias; - TypeSymbol declType = BindType(typeSyntax, diagnostics, out isVar, out alias); + TypeSymbol declType = BindTypeOrVarKeyword(typeSyntax, diagnostics, out isVar, out alias); if (isVar) { diff --git a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs index 4d86431e090cf..c000f88187090 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs +++ b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs @@ -3175,6 +3175,15 @@ internal static string ERR_ConvertToStaticClass { } } + /// + /// Looks up a localized string similar to Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}'. + /// + internal static string ERR_ConWithUnmanagedCon { + get { + return ResourceManager.GetString("ERR_ConWithUnmanagedCon", resourceCulture); + } + } + /// /// Looks up a localized string similar to Type parameter '{1}' has the 'struct' constraint so '{1}' cannot be used as a constraint for '{0}'. /// @@ -6757,6 +6766,15 @@ internal static string ERR_NewBoundMustBeLast { } } + /// + /// Looks up a localized string similar to The 'new()' constraint cannot be used with the 'unmanaged' constraint. + /// + internal static string ERR_NewBoundWithUnmanaged { + get { + return ResourceManager.GetString("ERR_NewBoundWithUnmanaged", resourceCulture); + } + } + /// /// Looks up a localized string similar to The 'new()' constraint cannot be used with the 'struct' constraint. /// @@ -9709,6 +9727,33 @@ internal static string ERR_UnimplementedInterfaceMember { } } + /// + /// Looks up a localized string similar to The 'unmanaged' constraint cannot be specified with other constraints.. + /// + internal static string ERR_UnmanagedConstraintMustBeAlone { + get { + return ResourceManager.GetString("ERR_UnmanagedConstraintMustBeAlone", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}'. + /// + internal static string ERR_UnmanagedConstraintNotSatisfied { + get { + return ResourceManager.GetString("ERR_UnmanagedConstraintNotSatisfied", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Using 'unmanaged' constraint on local functions type parameters is not supported.. + /// + internal static string ERR_UnmanagedConstraintWithLocalFunctions { + get { + return ResourceManager.GetString("ERR_UnmanagedConstraintWithLocalFunctions", resourceCulture); + } + } + /// /// Looks up a localized string similar to A previous catch clause already catches all exceptions of this or of a super type ('{0}'). /// @@ -10790,6 +10835,15 @@ internal static string IDS_FeatureTypeVariance { } } + /// + /// Looks up a localized string similar to unmanaged generic type constraints. + /// + internal static string IDS_FeatureUnmanagedGenericTypeConstraint { + get { + return ResourceManager.GetString("IDS_FeatureUnmanagedGenericTypeConstraint", resourceCulture); + } + } + /// /// Looks up a localized string similar to using static. /// diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index d1247c0c7e0f4..a025742e598e6 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -5252,4 +5252,22 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ delegate generic type constraints + + unmanaged generic type constraints + + + The 'new()' constraint cannot be used with the 'unmanaged' constraint + + + The 'unmanaged' constraint cannot be specified with other constraints. + + + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + + + Using 'unmanaged' constraint on local functions type parameters is not supported. + + + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/Emitter/Model/PEAssemblyBuilder.cs b/src/Compilers/CSharp/Portable/Emitter/Model/PEAssemblyBuilder.cs index 3324153ed0cb6..e3d293a46f0b0 100644 --- a/src/Compilers/CSharp/Portable/Emitter/Model/PEAssemblyBuilder.cs +++ b/src/Compilers/CSharp/Portable/Emitter/Model/PEAssemblyBuilder.cs @@ -21,6 +21,7 @@ internal abstract class PEAssemblyBuilderBase : PEModuleBuilder, Cci.IAssemblyRe private SynthesizedEmbeddedAttributeSymbol _lazyEmbeddedAttribute; private SynthesizedEmbeddedAttributeSymbol _lazyIsReadOnlyAttribute; private SynthesizedEmbeddedAttributeSymbol _lazyIsByRefLikeAttribute; + private SynthesizedEmbeddedAttributeSymbol _lazyIsUnmanagedAttribute; /// /// The behavior of the C# command-line compiler is as follows: @@ -81,6 +82,11 @@ internal override ImmutableArray GetEmbeddedTypes(DiagnosticBag builder.Add(_lazyIsReadOnlyAttribute); } + if ((object)_lazyIsUnmanagedAttribute != null) + { + builder.Add(_lazyIsUnmanagedAttribute); + } + if ((object)_lazyIsByRefLikeAttribute != null) { builder.Add(_lazyIsByRefLikeAttribute); @@ -182,6 +188,19 @@ protected override SynthesizedAttributeData TrySynthesizeIsReadOnlyAttribute() return base.TrySynthesizeIsReadOnlyAttribute(); } + protected override SynthesizedAttributeData TrySynthesizeIsUnmanagedAttribute() + { + if ((object)_lazyIsUnmanagedAttribute != null) + { + return new SynthesizedAttributeData( + _lazyIsUnmanagedAttribute.Constructor, + ImmutableArray.Empty, + ImmutableArray>.Empty); + } + + return base.TrySynthesizeIsUnmanagedAttribute(); + } + protected override SynthesizedAttributeData TrySynthesizeIsByRefLikeAttribute() { if ((object)_lazyIsByRefLikeAttribute != null) @@ -216,6 +235,16 @@ private void CreateEmbeddedAttributesIfNeeded(DiagnosticBag diagnostics) diagnostics, AttributeDescription.IsByRefLikeAttribute); } + + if (this.NeedsGeneratedIsUnmanagedAttribute) + { + CreateEmbeddedAttributeItselfIfNeeded(diagnostics); + + CreateEmbeddedAttributeIfNeeded( + ref _lazyIsUnmanagedAttribute, + diagnostics, + AttributeDescription.IsUnmanagedAttribute); + } } private void CreateEmbeddedAttributeItselfIfNeeded(DiagnosticBag diagnostics) diff --git a/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs b/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs index 6f8c168cf03ba..12fc5d1bfdc1b 100644 --- a/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs +++ b/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs @@ -42,7 +42,7 @@ public override NoPia.EmbeddedTypesManager EmbeddedTypesManagerOpt private Dictionary _fixedImplementationTypes; private bool _needsGeneratedIsReadOnlyAttribute_Value; - + private bool _needsGeneratedAttributes_IsFrozen; /// @@ -70,6 +70,15 @@ internal bool NeedsGeneratedIsByRefLikeAttribute } } + internal bool NeedsGeneratedIsUnmanagedAttribute + { + get + { + _needsGeneratedAttributes_IsFrozen = true; + return Compilation.NeedsGeneratedIsUnmanagedAttribute; + } + } + internal PEModuleBuilder( SourceModuleSymbol sourceModule, EmitOptions emitOptions, @@ -1440,6 +1449,17 @@ internal SynthesizedAttributeData SynthesizeIsReadOnlyAttribute(Symbol symbol) return TrySynthesizeIsReadOnlyAttribute(); } + internal SynthesizedAttributeData SynthesizeIsUnmanagedAttribute(Symbol symbol) + { + if ((object)Compilation.SourceModule != symbol.ContainingModule) + { + // For symbols that are not defined in the same compilation (like NoPia), don't synthesize this attribute. + return null; + } + + return TrySynthesizeIsUnmanagedAttribute(); + } + internal SynthesizedAttributeData SynthesizeIsByRefLikeAttribute(Symbol symbol) { if ((object)Compilation.SourceModule != symbol.ContainingModule) @@ -1457,6 +1477,12 @@ protected virtual SynthesizedAttributeData TrySynthesizeIsReadOnlyAttribute() return Compilation.TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_IsReadOnlyAttribute__ctor); } + protected virtual SynthesizedAttributeData TrySynthesizeIsUnmanagedAttribute() + { + // For modules, this attribute should be present. Only assemblies generate and embed this type. + return Compilation.TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_IsUnmanagedAttribute__ctor); + } + protected virtual SynthesizedAttributeData TrySynthesizeIsByRefLikeAttribute() { // For modules, this attribute should be present. Only assemblies generate and embed this type. diff --git a/src/Compilers/CSharp/Portable/Emitter/Model/TypeParameterSymbolAdapter.cs b/src/Compilers/CSharp/Portable/Emitter/Model/TypeParameterSymbolAdapter.cs index f217005d60a91..6254824409c9d 100644 --- a/src/Compilers/CSharp/Portable/Emitter/Model/TypeParameterSymbolAdapter.cs +++ b/src/Compilers/CSharp/Portable/Emitter/Model/TypeParameterSymbolAdapter.cs @@ -223,33 +223,50 @@ Cci.ITypeReference Cci.IGenericTypeParameterReference.DefiningType IEnumerable Cci.IGenericParameter.GetConstraints(EmitContext context) { var moduleBeingBuilt = (PEModuleBuilder)context.Module; - var seenValueType = false; - foreach (var type in this.ConstraintTypesNoUseSiteDiagnostics) + + if (this.HasUnmanagedTypeConstraint) { - switch (type.SpecialType) - { - case SpecialType.System_Object: - // Avoid emitting unnecessary object constraint. - continue; - case SpecialType.System_ValueType: - seenValueType = true; - break; - } - var typeRef = moduleBeingBuilt.Translate(type, - syntaxNodeOpt: (CSharpSyntaxNode)context.SyntaxNodeOpt, - diagnostics: context.Diagnostics); + var typeRef = moduleBeingBuilt.Translate( + typeSymbol: moduleBeingBuilt.Compilation.GetSpecialType(SpecialType.System_ValueType), + syntaxNodeOpt: (CSharpSyntaxNode)context.SyntaxNodeOpt, + diagnostics: context.Diagnostics); - yield return type.GetTypeRefWithAttributes(this.DeclaringCompilation, - typeRef); + var modifier = CSharpCustomModifier.CreateRequired( + moduleBeingBuilt.Compilation.GetWellKnownType(WellKnownType.System_Runtime_InteropServices_UnmanagedType)); + + yield return new Cci.TypeReferenceWithAttributes(new Cci.ModifiedTypeReference(typeRef, ImmutableArray.Create(modifier))); } - if (this.HasValueTypeConstraint && !seenValueType) + else { - // Add System.ValueType constraint to comply with Dev11 output - var typeRef = moduleBeingBuilt.GetSpecialType(SpecialType.System_ValueType, - syntaxNodeOpt: (CSharpSyntaxNode)context.SyntaxNodeOpt, - diagnostics: context.Diagnostics); + var seenValueType = false; + foreach (var type in this.ConstraintTypesNoUseSiteDiagnostics) + { + switch (type.SpecialType) + { + case SpecialType.System_Object: + // Avoid emitting unnecessary object constraint. + continue; + case SpecialType.System_ValueType: + seenValueType = true; + break; + } + var typeRef = moduleBeingBuilt.Translate(type, + syntaxNodeOpt: (CSharpSyntaxNode)context.SyntaxNodeOpt, + diagnostics: context.Diagnostics); + + yield return type.GetTypeRefWithAttributes(this.DeclaringCompilation, + typeRef); + } - yield return new Cci.TypeReferenceWithAttributes(typeRef); + if (this.HasValueTypeConstraint && !seenValueType) + { + // Add System.ValueType constraint to comply with Dev11 output + var typeRef = moduleBeingBuilt.GetSpecialType(SpecialType.System_ValueType, + syntaxNodeOpt: (CSharpSyntaxNode)context.SyntaxNodeOpt, + diagnostics: context.Diagnostics); + + yield return new Cci.TypeReferenceWithAttributes(typeRef); + } } } @@ -265,7 +282,7 @@ bool Cci.IGenericParameter.MustBeValueType { get { - return this.HasValueTypeConstraint; + return this.HasValueTypeConstraint || this.HasUnmanagedTypeConstraint; } } diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 04961391e125f..16110eaa5c743 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -1556,6 +1556,12 @@ internal enum ErrorCode WRN_AttributesOnBackingFieldsNotAvailable = 8371, ERR_DoNotUseFixedBufferAttrOnProperty = 8372, + ERR_NewBoundWithUnmanaged = 8373, + ERR_UnmanagedConstraintMustBeAlone = 8374, + ERR_UnmanagedConstraintNotSatisfied = 8375, + ERR_UnmanagedConstraintWithLocalFunctions = 8376, + ERR_ConWithUnmanagedCon = 8377, + // Note: you will need to re-generate compiler code after adding warnings (build\scripts\generate-compiler-code.cmd) } } diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs index e1b371cf53552..722836d112646 100644 --- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs +++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs @@ -149,6 +149,7 @@ internal enum MessageID IDS_FeatureAttributesOnBackingFields = MessageBase + 12731, IDS_FeatureEnumGenericTypeConstraint = MessageBase + 12732, IDS_FeatureDelegateGenericTypeConstraint = MessageBase + 12733, + IDS_FeatureUnmanagedGenericTypeConstraint = MessageBase + 12734, } // Message IDs may refer to strings that need to be localized. @@ -192,6 +193,7 @@ internal static LanguageVersion RequiredVersion(this MessageID feature) case MessageID.IDS_FeatureAttributesOnBackingFields: // semantic check case MessageID.IDS_FeatureEnumGenericTypeConstraint: // semantic check case MessageID.IDS_FeatureDelegateGenericTypeConstraint: // semantic check + case MessageID.IDS_FeatureUnmanagedGenericTypeConstraint: // semantic check return LanguageVersion.CSharp7_3; // C# 7.2 features. diff --git a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt index 2590058f032b9..d22857673f1c2 100644 --- a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt @@ -15,6 +15,7 @@ Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax.WithRefKindKeyword(Microsoft Microsoft.CodeAnalysis.CSharp.Syntax.RefTypeSyntax.ReadOnlyKeyword.get -> Microsoft.CodeAnalysis.SyntaxToken Microsoft.CodeAnalysis.CSharp.Syntax.RefTypeSyntax.Update(Microsoft.CodeAnalysis.SyntaxToken refKeyword, Microsoft.CodeAnalysis.SyntaxToken readOnlyKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type) -> Microsoft.CodeAnalysis.CSharp.Syntax.RefTypeSyntax Microsoft.CodeAnalysis.CSharp.Syntax.RefTypeSyntax.WithReadOnlyKeyword(Microsoft.CodeAnalysis.SyntaxToken readOnlyKeyword) -> Microsoft.CodeAnalysis.CSharp.Syntax.RefTypeSyntax +Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax.IsUnmanaged.get -> bool static Microsoft.CodeAnalysis.CSharp.CSharpCommandLineParser.Script.get -> Microsoft.CodeAnalysis.CSharp.CSharpCommandLineParser static Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetConversion(this Microsoft.CodeAnalysis.Operations.IConversionOperation conversionExpression) -> Microsoft.CodeAnalysis.CSharp.Conversion static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.Argument(Microsoft.CodeAnalysis.CSharp.Syntax.NameColonSyntax nameColon, Microsoft.CodeAnalysis.SyntaxToken refKindKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expression) -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax diff --git a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.TypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.TypeParameterSymbol.cs index e56a0376cb9a2..c834fc57a7449 100644 --- a/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.TypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/AnonymousTypes/SynthesizedSymbols/AnonymousType.TypeParameterSymbol.cs @@ -73,6 +73,11 @@ public override bool HasValueTypeConstraint get { return false; } } + public override bool HasUnmanagedTypeConstraint + { + get { return false; } + } + public override bool IsImplicitlyDeclared { get { return true; } diff --git a/src/Compilers/CSharp/Portable/Symbols/Compilation_WellKnownMembers.cs b/src/Compilers/CSharp/Portable/Symbols/Compilation_WellKnownMembers.cs index 5e8f3fda81af6..b8719f07869f1 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Compilation_WellKnownMembers.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Compilation_WellKnownMembers.cs @@ -34,6 +34,7 @@ public partial class CSharpCompilation private bool _needsGeneratedIsReadOnlyAttribute_Value; private bool _needsGeneratedIsByRefLikeAttribute_Value; + private bool _needsGeneratedIsUnmanagedAttribute_Value; private bool _needsGeneratedAttributes_IsFrozen; @@ -65,6 +66,20 @@ internal bool NeedsGeneratedIsByRefLikeAttribute } } + /// + /// Returns a value indicating whether this compilation has a member that needs IsUnmanagedAttribute to be generated during emit phase. + /// The value is set during binding the symbols that need that attribute, and is frozen on first trial to get it. + /// Freezing is needed to make sure that nothing tries to modify the value after the value is read. + /// + internal bool NeedsGeneratedIsUnmanagedAttribute + { + get + { + _needsGeneratedAttributes_IsFrozen = true; + return _needsGeneratedIsUnmanagedAttribute_Value; + } + } + /// /// Lookup member declaration in well known type used by this Compilation. /// @@ -484,6 +499,18 @@ internal void EnsureIsByRefLikeAttributeExists(DiagnosticBag diagnostics, Locati } } + internal void EnsureIsUnmanagedAttributeExists(DiagnosticBag diagnostics, Location location, bool modifyCompilationForIsUnmanaged) + { + Debug.Assert(!modifyCompilationForIsUnmanaged || !_needsGeneratedAttributes_IsFrozen); + + var isNeeded = CheckIfIsUnmanagedAttributeShouldBeEmbedded(diagnostics, location); + + if (isNeeded && modifyCompilationForIsUnmanaged) + { + _needsGeneratedIsUnmanagedAttribute_Value = true; + } + } + internal bool CheckIfIsReadOnlyAttributeShouldBeEmbedded(DiagnosticBag diagnosticsOpt, Location locationOpt) { return CheckIfAttributeShouldBeEmbedded( @@ -496,12 +523,21 @@ internal bool CheckIfIsReadOnlyAttributeShouldBeEmbedded(DiagnosticBag diagnosti internal bool CheckIfIsByRefLikeAttributeShouldBeEmbedded(DiagnosticBag diagnosticsOpt, Location locationOpt) { return CheckIfAttributeShouldBeEmbedded( - diagnosticsOpt, - locationOpt, - WellKnownType.System_Runtime_CompilerServices_IsByRefLikeAttribute, + diagnosticsOpt, + locationOpt, + WellKnownType.System_Runtime_CompilerServices_IsByRefLikeAttribute, WellKnownMember.System_Runtime_CompilerServices_IsByRefLikeAttribute__ctor); } + internal bool CheckIfIsUnmanagedAttributeShouldBeEmbedded(DiagnosticBag diagnosticsOpt, Location locationOpt) + { + return CheckIfAttributeShouldBeEmbedded( + diagnosticsOpt, + locationOpt, + WellKnownType.System_Runtime_CompilerServices_IsUnmanagedAttribute, + WellKnownMember.System_Runtime_CompilerServices_IsUnmanagedAttribute__ctor); + } + private bool CheckIfAttributeShouldBeEmbedded(DiagnosticBag diagnosticsOpt, Location locationOpt, WellKnownType attributeType, WellKnownMember attributeCtor) { var userDefinedAttribute = GetWellKnownType(attributeType); diff --git a/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs b/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs index e6076dff7deea..fe90304cebde5 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs @@ -163,10 +163,24 @@ public static TypeParameterBounds ResolveBounds( constraintDeducedBase = constraintTypeParameter.GetDeducedBaseType(constraintsInProgress); AddInterfaces(interfacesBuilder, constraintTypeParameter.GetInterfaces(constraintsInProgress)); - if (constraintTypeParameter.HasValueTypeConstraint && !inherited && currentCompilation != null && constraintTypeParameter.IsFromCompilation(currentCompilation)) + if (!inherited && currentCompilation != null && constraintTypeParameter.IsFromCompilation(currentCompilation)) { - // "Type parameter '{1}' has the 'struct' constraint so '{1}' cannot be used as a constraint for '{0}'" - diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(ErrorCode.ERR_ConWithValCon, typeParameter, constraintTypeParameter))); + ErrorCode errorCode; + if (constraintTypeParameter.HasUnmanagedTypeConstraint) + { + errorCode = ErrorCode.ERR_ConWithUnmanagedCon; + } + else if (constraintTypeParameter.HasValueTypeConstraint) + { + errorCode = ErrorCode.ERR_ConWithValCon; + } + else + { + break; + } + + // "Type parameter '{1}' has the '?' constraint so '{1}' cannot be used as a constraint for '{0}'" + diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(errorCode, typeParameter, constraintTypeParameter))); continue; } } @@ -803,6 +817,13 @@ private static bool CheckConstraints( return false; } + if (typeParameter.HasUnmanagedTypeConstraint && (typeArgument.IsManagedType || !typeArgument.IsNonNullableValueType())) + { + // "The type '{2}' cannot be a reference type, or contain reference type 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))); + return false; + } + if (typeParameter.HasValueTypeConstraint && !typeArgument.IsNonNullableValueType()) { // "The type '{2}' must be a non-nullable value type in order to use it as parameter '{1}' in the generic type or method '{0}'" diff --git a/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.ErrorTypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.ErrorTypeParameterSymbol.cs index 98f5f127d6e6d..46b65e11a84e8 100644 --- a/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.ErrorTypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/ErrorTypeSymbol.ErrorTypeParameterSymbol.cs @@ -71,6 +71,14 @@ public override bool HasValueTypeConstraint } } + public override bool HasUnmanagedTypeConstraint + { + get + { + return false; + } + } + public override int Ordinal { get diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.cs index 05d1f83fd6dde..6c16f53dce4d5 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.cs @@ -25,16 +25,17 @@ internal sealed class PETypeParameterSymbol #region Metadata private readonly string _name; private readonly ushort _ordinal; // 0 for first, 1 for second, ... - private readonly GenericParameterAttributes _flags; #endregion - private TypeParameterBounds _lazyBounds = TypeParameterBounds.Unset; - /// /// First error calculating bounds. /// - private DiagnosticInfo _lazyBoundsErrorInfo = CSDiagnosticInfo.EmptyErrorInfo; // Indicates unknown state. + private DiagnosticInfo _lazyConstraintsUseSiteErrorInfo = CSDiagnosticInfo.EmptyErrorInfo; // Indicates unknown state. + private GenericParameterAttributes _lazyFlags; + private ThreeState _lazyHasIsUnmanagedAttribute; + private TypeParameterBounds _lazyBounds = TypeParameterBounds.Unset; + private ImmutableArray _lazyDeclaredConstraintTypes; private ImmutableArray _lazyCustomAttributes; internal PETypeParameterSymbol( @@ -81,12 +82,12 @@ private PETypeParameterSymbol( _name = string.Empty; } - _lazyBoundsErrorInfo = new CSDiagnosticInfo(ErrorCode.ERR_BindToBogus, this); + _lazyConstraintsUseSiteErrorInfo = new CSDiagnosticInfo(ErrorCode.ERR_BindToBogus, this); } // Clear the '.ctor' flag if both '.ctor' and 'valuetype' are // set since '.ctor' is redundant in that case. - _flags = ((flags & GenericParameterAttributes.NotNullableValueTypeConstraint) == 0) ? flags : (flags & ~GenericParameterAttributes.DefaultConstructorConstraint); + _lazyFlags = ((flags & GenericParameterAttributes.NotNullableValueTypeConstraint) == 0) ? flags : (flags & ~GenericParameterAttributes.DefaultConstructorConstraint); _ordinal = ordinal; _handle = handle; @@ -138,80 +139,99 @@ public override AssemblySymbol ContainingAssembly private ImmutableArray GetDeclaredConstraintTypes() { - PEMethodSymbol containingMethod = null; - PENamedTypeSymbol containingType; - - if (_containingSymbol.Kind == SymbolKind.Method) + if (_lazyDeclaredConstraintTypes.IsDefault) { - containingMethod = (PEMethodSymbol)_containingSymbol; - containingType = (PENamedTypeSymbol)containingMethod.ContainingSymbol; - } - else - { - containingType = (PENamedTypeSymbol)_containingSymbol; - } + ImmutableArray declaredConstraintTypes; - var moduleSymbol = containingType.ContainingPEModule; - var metadataReader = moduleSymbol.Module.MetadataReader; - GenericParameterConstraintHandleCollection constraints; + PEMethodSymbol containingMethod = null; + PENamedTypeSymbol containingType; - try - { - constraints = metadataReader.GetGenericParameter(_handle).GetConstraints(); - } - catch (BadImageFormatException) - { - constraints = default(GenericParameterConstraintHandleCollection); - Interlocked.CompareExchange(ref _lazyBoundsErrorInfo, new CSDiagnosticInfo(ErrorCode.ERR_BindToBogus, this), CSDiagnosticInfo.EmptyErrorInfo); - } + if (_containingSymbol.Kind == SymbolKind.Method) + { + containingMethod = (PEMethodSymbol)_containingSymbol; + containingType = (PENamedTypeSymbol)containingMethod.ContainingSymbol; + } + else + { + containingType = (PENamedTypeSymbol)_containingSymbol; + } - if (constraints.Count > 0) - { - var symbolsBuilder = ArrayBuilder.GetInstance(); - MetadataDecoder tokenDecoder; + var moduleSymbol = containingType.ContainingPEModule; + var metadataReader = moduleSymbol.Module.MetadataReader; + GenericParameterConstraintHandleCollection constraints; - if ((object)containingMethod != null) + try { - tokenDecoder = new MetadataDecoder(moduleSymbol, containingMethod); + constraints = metadataReader.GetGenericParameter(_handle).GetConstraints(); } - else + catch (BadImageFormatException) { - tokenDecoder = new MetadataDecoder(moduleSymbol, containingType); + constraints = default(GenericParameterConstraintHandleCollection); + Interlocked.CompareExchange(ref _lazyConstraintsUseSiteErrorInfo, new CSDiagnosticInfo(ErrorCode.ERR_BindToBogus, this), CSDiagnosticInfo.EmptyErrorInfo); } - foreach (var constraintHandle in constraints) + this.GetAttributes(); + if (_lazyHasIsUnmanagedAttribute.Value() && (_lazyFlags & (GenericParameterAttributes.ReferenceTypeConstraint | GenericParameterAttributes.DefaultConstructorConstraint)) != 0) { - var constraint = metadataReader.GetGenericParameterConstraint(constraintHandle); - var constraintTypeHandle = constraint.Type; + _lazyFlags = _lazyFlags & ~(GenericParameterAttributes.ReferenceTypeConstraint | GenericParameterAttributes.DefaultConstructorConstraint); + _lazyConstraintsUseSiteErrorInfo = new CSDiagnosticInfo(ErrorCode.ERR_BindToBogus, this); + } - TypeSymbol typeSymbol = tokenDecoder.GetTypeOfToken(constraintTypeHandle); + if (constraints.Count > 0) + { + var symbolsBuilder = ArrayBuilder.GetInstance(); + MetadataDecoder tokenDecoder; - // Drop 'System.Object' constraint type. - if (typeSymbol.SpecialType == SpecialType.System_Object) + if ((object)containingMethod != null) { - continue; + tokenDecoder = new MetadataDecoder(moduleSymbol, containingMethod); } - - // Drop 'System.ValueType' constraint type if the 'valuetype' constraint was also specified. - if (((_flags & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0) && - (typeSymbol.SpecialType == SpecialType.System_ValueType)) + else { - continue; + tokenDecoder = new MetadataDecoder(moduleSymbol, containingType); } - typeSymbol = TupleTypeDecoder.DecodeTupleTypesIfApplicable(typeSymbol, - constraintHandle, - moduleSymbol); + foreach (var constraintHandle in constraints) + { + var constraint = metadataReader.GetGenericParameterConstraint(constraintHandle); + var typeSymbol = tokenDecoder.DecodeGenericParameterConstraint(constraint.Type, out bool hasUnmanagedModreq); - symbolsBuilder.Add(typeSymbol); + if (hasUnmanagedModreq != this._lazyHasIsUnmanagedAttribute.Value()) + { + // The presence of UnmanagedType modreq has to match the presence of the IsUnmanagedAttribute + Interlocked.CompareExchange(ref _lazyConstraintsUseSiteErrorInfo, new CSDiagnosticInfo(ErrorCode.ERR_BindToBogus, this), CSDiagnosticInfo.EmptyErrorInfo); + continue; + } + + // Drop 'System.Object' constraint type. + if (typeSymbol.SpecialType == SpecialType.System_Object) + { + continue; + } + + // Drop 'System.ValueType' constraint type if the 'valuetype' constraint was also specified. + if (((_lazyFlags & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0) && + (typeSymbol.SpecialType == SpecialType.System_ValueType)) + { + continue; + } + + typeSymbol = TupleTypeDecoder.DecodeTupleTypesIfApplicable(typeSymbol, constraintHandle, moduleSymbol); + + symbolsBuilder.Add(typeSymbol); + } + + declaredConstraintTypes = symbolsBuilder.ToImmutableAndFree(); + } + else + { + declaredConstraintTypes = ImmutableArray.Empty; } - return symbolsBuilder.ToImmutableAndFree(); - } - else - { - return ImmutableArray.Empty; + ImmutableInterlocked.InterlockedInitialize(ref _lazyDeclaredConstraintTypes, declaredConstraintTypes); } + + return _lazyDeclaredConstraintTypes; } public override ImmutableArray Locations @@ -234,7 +254,8 @@ public override bool HasConstructorConstraint { get { - return (_flags & GenericParameterAttributes.DefaultConstructorConstraint) != 0; + GetDeclaredConstraintTypes(); + return (_lazyFlags & GenericParameterAttributes.DefaultConstructorConstraint) != 0; } } @@ -242,7 +263,8 @@ public override bool HasReferenceTypeConstraint { get { - return (_flags & GenericParameterAttributes.ReferenceTypeConstraint) != 0; + GetDeclaredConstraintTypes(); + return (_lazyFlags & GenericParameterAttributes.ReferenceTypeConstraint) != 0; } } @@ -250,7 +272,17 @@ public override bool HasValueTypeConstraint { get { - return (_flags & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0; + GetDeclaredConstraintTypes(); + return (_lazyFlags & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0 || HasUnmanagedTypeConstraint; + } + } + + public override bool HasUnmanagedTypeConstraint + { + get + { + GetDeclaredConstraintTypes(); + return this._lazyHasIsUnmanagedAttribute.Value(); } } @@ -258,7 +290,8 @@ public override VarianceKind Variance { get { - return (VarianceKind)(_flags & GenericParameterAttributes.VarianceMask); + GetDeclaredConstraintTypes(); + return (VarianceKind)(_lazyFlags & GenericParameterAttributes.VarianceMask); } } @@ -301,9 +334,18 @@ public override ImmutableArray GetAttributes() { if (_lazyCustomAttributes.IsDefault) { - var containingPEModuleSymbol = (PEModuleSymbol)this.ContainingModule; - containingPEModuleSymbol.LoadCustomAttributes(this.Handle, ref _lazyCustomAttributes); + var loadedCustomAttributes = ((PEModuleSymbol)this.ContainingModule).GetCustomAttributesForToken( + this.Handle, + out CustomAttributeHandle isUnmanagedAttribute, + AttributeDescription.IsUnmanagedAttribute, + out _, + default); + + this._lazyHasIsUnmanagedAttribute = (!isUnmanagedAttribute.IsNil).ToThreeState(); + + ImmutableInterlocked.InterlockedInitialize(ref _lazyCustomAttributes, loadedCustomAttributes); } + return _lazyCustomAttributes; } @@ -346,19 +388,19 @@ private TypeParameterBounds GetBounds(ConsList inProgress) diagnostics.Free(); - Interlocked.CompareExchange(ref _lazyBoundsErrorInfo, errorInfo, CSDiagnosticInfo.EmptyErrorInfo); + Interlocked.CompareExchange(ref _lazyConstraintsUseSiteErrorInfo, errorInfo, CSDiagnosticInfo.EmptyErrorInfo); Interlocked.CompareExchange(ref _lazyBounds, bounds, TypeParameterBounds.Unset); } - Debug.Assert(!ReferenceEquals(_lazyBoundsErrorInfo, CSDiagnosticInfo.EmptyErrorInfo)); + Debug.Assert(!ReferenceEquals(_lazyConstraintsUseSiteErrorInfo, CSDiagnosticInfo.EmptyErrorInfo)); return _lazyBounds; } internal override DiagnosticInfo GetConstraintsUseSiteErrorInfo() { EnsureAllConstraintsAreResolved(); - Debug.Assert(!ReferenceEquals(_lazyBoundsErrorInfo, CSDiagnosticInfo.EmptyErrorInfo)); - return _lazyBoundsErrorInfo; + Debug.Assert(!ReferenceEquals(_lazyConstraintsUseSiteErrorInfo, CSDiagnosticInfo.EmptyErrorInfo)); + return _lazyConstraintsUseSiteErrorInfo; } private NamedTypeSymbol GetDefaultBaseType() diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/SymbolFactory.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/SymbolFactory.cs index 8873480c2a77e..a979e0aaa0fbb 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/SymbolFactory.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/SymbolFactory.cs @@ -62,6 +62,11 @@ internal override bool IsAcceptedInAttributeModifierType(TypeSymbol type) return type.IsWellKnownTypeInAttribute(); } + internal override bool IsAcceptedUnmanagedTypeModifierType(TypeSymbol type) + { + return type.IsWellKnownTypeUnmanagedType(); + } + internal override TypeSymbol GetSZArrayTypeSymbol(PEModuleSymbol moduleSymbol, TypeSymbol elementType, ImmutableArray> customModifiers) { if (elementType is UnsupportedMetadataTypeSymbol) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/CrefTypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/CrefTypeParameterSymbol.cs index 5bc75fda6242a..d6a00e421987b 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/CrefTypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/CrefTypeParameterSymbol.cs @@ -126,6 +126,11 @@ public override bool HasReferenceTypeConstraint get { return false; } } + public override bool HasUnmanagedTypeConstraint + { + get { return false; } + } + public override bool HasConstructorConstraint { get { return false; } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/FieldSymbolWithAttributesAndModifiers.cs b/src/Compilers/CSharp/Portable/Symbols/Source/FieldSymbolWithAttributesAndModifiers.cs index 8cc9d2edc2605..c0b65baeba477 100755 --- a/src/Compilers/CSharp/Portable/Symbols/Source/FieldSymbolWithAttributesAndModifiers.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/FieldSymbolWithAttributesAndModifiers.cs @@ -206,6 +206,11 @@ internal override void DecodeWellKnownAttribute(ref DecodeWellKnownAttributeArgu // IsReadOnlyAttribute should not be set explicitly. arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, AttributeDescription.IsReadOnlyAttribute.FullName); } + else if (attribute.IsTargetAttribute(this, AttributeDescription.IsUnmanagedAttribute)) + { + // IsUnmanagedAttribute should not be set explicitly. + arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, AttributeDescription.IsUnmanagedAttribute.FullName); + } else if (attribute.IsTargetAttribute(this, AttributeDescription.IsByRefLikeAttribute)) { // IsByRefLikeAttribute should not be set explicitly. diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/GlobalExpressionVariable.cs b/src/Compilers/CSharp/Portable/Symbols/Source/GlobalExpressionVariable.cs index 526396520b9c9..fcf25587189bb 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/GlobalExpressionVariable.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/GlobalExpressionVariable.cs @@ -78,7 +78,7 @@ internal override TypeSymbol GetFieldType(ConsList fieldsBeingBound var binder = binderFactory.GetBinder(typeSyntax); bool isVar; - type = binder.BindType(typeSyntax, diagnostics, out isVar); + type = binder.BindTypeOrVarKeyword(typeSyntax, diagnostics, out isVar); Debug.Assert((object)type != null || isVar); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/IndexedTypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/IndexedTypeParameterSymbol.cs index 46fc07791c2a3..2592ff648a431 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/IndexedTypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/IndexedTypeParameterSymbol.cs @@ -125,6 +125,11 @@ public override bool HasReferenceTypeConstraint get { return false; } } + public override bool HasUnmanagedTypeConstraint + { + get { return false; } + } + public override bool HasConstructorConstraint { get { return false; } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs index 182b3db4ae931..6b81275172ef9 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs @@ -108,6 +108,11 @@ internal void GetDeclarationDiagnostics(DiagnosticBag addTo) foreach (var typeParam in _typeParameters) { typeParam.ForceComplete(null, default(CancellationToken)); + + if (typeParam.HasUnmanagedTypeConstraint) + { + addTo.Add(ErrorCode.ERR_UnmanagedConstraintWithLocalFunctions, typeParam.GetNonNullSyntaxNode().Location); + } } // force lazy init diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs index 7608653e1348d..4ff82b92a6e8e 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceComplexParameterSymbol.cs @@ -561,6 +561,11 @@ internal override void DecodeWellKnownAttribute(ref DecodeWellKnownAttributeArgu // IsReadOnlyAttribute should not be set explicitly. arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, AttributeDescription.IsReadOnlyAttribute.FullName); } + else if (attribute.IsTargetAttribute(this, AttributeDescription.IsUnmanagedAttribute)) + { + // IsUnmanagedAttribute should not be set explicitly. + arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, AttributeDescription.IsUnmanagedAttribute.FullName); + } else if (attribute.IsTargetAttribute(this, AttributeDescription.IsByRefLikeAttribute)) { // IsByRefLikeAttribute should not be set explicitly. diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs index 751ecb11441a5..bd2e25822c144 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs @@ -310,7 +310,7 @@ public bool IsVar if (_typeSyntax.IsVar) { bool isVar; - TypeSymbol declType = this.TypeSyntaxBinder.BindType(_typeSyntax, new DiagnosticBag(), out isVar); + TypeSymbol declType = this.TypeSyntaxBinder.BindTypeOrVarKeyword(_typeSyntax, new DiagnosticBag(), out isVar); return isVar; } @@ -326,7 +326,7 @@ private TypeSymbol GetTypeSymbol() bool isVar; RefKind refKind; - TypeSymbol declType = typeBinder.BindType(_typeSyntax.SkipRef(out refKind), diagnostics, out isVar); + TypeSymbol declType = typeBinder.BindTypeOrVarKeyword(_typeSyntax.SkipRef(out refKind), diagnostics, out isVar); if (isVar) { diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs index 974a5a357c54c..ac9a659f76d95 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs @@ -482,6 +482,15 @@ internal override void ForceComplete(SourceLocation locationOpt, CancellationTok foreach (var typeParameter in this.TypeParameters) { typeParameter.ForceComplete(locationOpt, cancellationToken); + var diagnostics = DiagnosticBag.GetInstance(); + + if (typeParameter.HasUnmanagedTypeConstraint) + { + this.DeclaringCompilation.EnsureIsUnmanagedAttributeExists(diagnostics, typeParameter.GetNonNullSyntaxNode().Location, modifyCompilationForIsUnmanaged: true); + } + + AddDeclarationDiagnostics(diagnostics); + diagnostics.Free(); } state.NotePartComplete(CompletionPart.TypeParameters); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs index d283ea77968e4..669de6e3e1893 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs @@ -439,7 +439,7 @@ internal sealed override TypeSymbol GetFieldType(ConsList fieldsBei else { bool isVar; - type = binder.BindType(typeSyntax, diagnostics, out isVar); + type = binder.BindTypeOrVarKeyword(typeSyntax, diagnostics, out isVar); Debug.Assert((object)type != null || isVar); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs index 6066c790ae5d0..091903a62f1df 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs @@ -1110,6 +1110,11 @@ private void DecodeWellKnownAttributeAppliedToMethod(ref DecodeWellKnownAttribut // IsReadOnlyAttribute should not be set explicitly. arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, AttributeDescription.IsReadOnlyAttribute.FullName); } + else if (attribute.IsTargetAttribute(this, AttributeDescription.IsUnmanagedAttribute)) + { + // IsUnmanagedAttribute should not be set explicitly. + arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, AttributeDescription.IsUnmanagedAttribute.FullName); + } else if (attribute.IsTargetAttribute(this, AttributeDescription.IsByRefLikeAttribute)) { // IsByRefLikeAttribute should not be set explicitly. @@ -1235,6 +1240,11 @@ private void DecodeWellKnownAttributeAppliedToReturnValue(ref DecodeWellKnownAtt // DynamicAttribute should not be set explicitly. arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitDynamicAttr, arguments.AttributeSyntaxOpt.Location); } + else if (attribute.IsTargetAttribute(this, AttributeDescription.IsUnmanagedAttribute)) + { + // IsUnmanagedAttribute should not be set explicitly. + arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, AttributeDescription.IsUnmanagedAttribute.FullName); + } else if (attribute.IsTargetAttribute(this, AttributeDescription.IsReadOnlyAttribute)) { // IsReadOnlyAttribute should not be set explicitly. diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs index 8de5fc066cdcb..677994582b63a 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs @@ -723,6 +723,11 @@ internal sealed override void DecodeWellKnownAttribute(ref DecodeWellKnownAttrib // IsReadOnlyAttribute should not be set explicitly. arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, AttributeDescription.IsReadOnlyAttribute.FullName); } + else if (attribute.IsTargetAttribute(this, AttributeDescription.IsUnmanagedAttribute)) + { + // IsUnmanagedAttribute should not be set explicitly. + arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, AttributeDescription.IsUnmanagedAttribute.FullName); + } else if (attribute.IsTargetAttribute(this, AttributeDescription.IsByRefLikeAttribute)) { // IsByRefLikeAttribute should not be set explicitly. diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs index 1f4723485ea33..1f9546182584c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs @@ -368,6 +368,14 @@ private void MethodChecks(MethodDeclarationSyntax syntax, Binder withTypeParamsB } CheckModifiers(location, diagnostics); + + foreach (var typeParameter in _typeParameters) + { + if (typeParameter.HasUnmanagedTypeConstraint) + { + DeclaringCompilation.EnsureIsUnmanagedAttributeExists(diagnostics, typeParameter.GetNonNullSyntaxNode().Location, modifyCompilationForIsUnmanaged: true); + } + } } // This is also used for async lambdas. Probably not the best place to locate this method, but where else could it go? diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs index 72907a72cbf79..2654ef88be59c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs @@ -1263,6 +1263,11 @@ internal override void DecodeWellKnownAttribute(ref DecodeWellKnownAttributeArgu // IsReadOnlyAttribute should not be set explicitly. arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, AttributeDescription.IsReadOnlyAttribute.FullName); } + else if (attribute.IsTargetAttribute(this, AttributeDescription.IsUnmanagedAttribute)) + { + // IsUnmanagedAttribute should not be set explicitly. + arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitReservedAttr, arguments.AttributeSyntaxOpt.Location, AttributeDescription.IsUnmanagedAttribute.FullName); + } else if (attribute.IsTargetAttribute(this, AttributeDescription.IsByRefLikeAttribute)) { // IsByRefLikeAttribute should not be set explicitly. diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceTypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceTypeParameterSymbol.cs index 8ed6ae131e6c6..cda2a3900c78c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceTypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceTypeParameterSymbol.cs @@ -8,6 +8,7 @@ using Roslyn.Utilities; using System.Collections.Generic; using System.Linq; +using Microsoft.CodeAnalysis.CSharp.Emit; namespace Microsoft.CodeAnalysis.CSharp.Symbols { @@ -304,6 +305,16 @@ internal override void ForceComplete(SourceLocation locationOpt, CancellationTok _state.SpinWaitComplete(incompletePart, cancellationToken); } } + + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) + { + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); + + if (this.HasUnmanagedTypeConstraint) + { + AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeIsUnmanagedAttribute(this)); + } + } } internal sealed class SourceTypeParameterSymbol : SourceTypeParameterSymbolBase @@ -350,7 +361,7 @@ public override bool HasValueTypeConstraint get { var constraints = this.GetDeclaredConstraints(); - return (constraints & TypeParameterConstraintKind.ValueType) != 0; + return (constraints & (TypeParameterConstraintKind.ValueType | TypeParameterConstraintKind.Unmanaged)) != 0; } } @@ -363,6 +374,15 @@ public override bool HasReferenceTypeConstraint } } + public override bool HasUnmanagedTypeConstraint + { + get + { + var constraints = this.GetDeclaredConstraints(); + return (constraints & TypeParameterConstraintKind.Unmanaged) != 0; + } + } + protected override ImmutableArray ContainerTypeParameters { get { return _owner.TypeParameters; } @@ -420,7 +440,7 @@ public override bool HasValueTypeConstraint get { var constraints = this.GetDeclaredConstraints(); - return (constraints & TypeParameterConstraintKind.ValueType) != 0; + return (constraints & (TypeParameterConstraintKind.ValueType | TypeParameterConstraintKind.Unmanaged)) != 0; } } @@ -433,6 +453,15 @@ public override bool HasReferenceTypeConstraint } } + public override bool HasUnmanagedTypeConstraint + { + get + { + var constraints = this.GetDeclaredConstraints(); + return (constraints & TypeParameterConstraintKind.Unmanaged) != 0; + } + } + protected override ImmutableArray ContainerTypeParameters { get { return _owner.TypeParameters; } @@ -627,6 +656,15 @@ public override bool HasReferenceTypeConstraint } } + public override bool HasUnmanagedTypeConstraint + { + get + { + var typeParameter = this.OverriddenTypeParameter; + return ((object)typeParameter != null) && typeParameter.HasUnmanagedTypeConstraint; + } + } + protected override ImmutableArray ContainerTypeParameters { get { return this.Owner.TypeParameters; } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/TypeParameterConstraintClause.cs b/src/Compilers/CSharp/Portable/Symbols/Source/TypeParameterConstraintClause.cs index 57fa1a48c78d9..86cf5dee6e730 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/TypeParameterConstraintClause.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/TypeParameterConstraintClause.cs @@ -16,6 +16,7 @@ internal enum TypeParameterConstraintKind ReferenceType = 0x01, ValueType = 0x02, Constructor = 0x04, + Unmanaged = 0x08, } /// diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedSubstitutedTypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedSubstitutedTypeParameterSymbol.cs index 9c03e26d494cd..6efb1d2193a70 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedSubstitutedTypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedSubstitutedTypeParameterSymbol.cs @@ -1,5 +1,8 @@ // 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 Microsoft.CodeAnalysis.CSharp.Emit; +using Microsoft.CodeAnalysis.PooledObjects; + namespace Microsoft.CodeAnalysis.CSharp.Symbols { /// @@ -16,5 +19,15 @@ public override bool IsImplicitlyDeclared { get { return true; } } + + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) + { + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); + + if (this.HasUnmanagedTypeConstraint) + { + AddSynthesizedAttribute(ref attributes, moduleBuilder.SynthesizeIsUnmanagedAttribute(this)); + } + } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/TypeParameterSymbol.cs index b81e90f23f2e0..fa1ea1ee1a483 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypeParameterSymbol.cs @@ -465,7 +465,7 @@ internal sealed override bool IsManagedType { get { - return true; + return !this.HasUnmanagedTypeConstraint; } } @@ -496,6 +496,8 @@ internal sealed override ObsoleteAttributeData ObsoleteAttributeData public abstract bool HasValueTypeConstraint { get; } + public abstract bool HasUnmanagedTypeConstraint { get; } + public abstract VarianceKind Variance { get; } internal sealed override bool GetUnificationUseSiteDiagnosticRecursive(ref DiagnosticInfo result, Symbol owner, ref HashSet checkedTypes) diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs b/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs index 2fb92536bb557..25deaa57e9f33 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs @@ -1528,9 +1528,13 @@ internal static Cci.TypeReferenceWithAttributes GetTypeRefWithAttributes( return new Cci.TypeReferenceWithAttributes(typeRef); } - internal static bool IsWellKnownTypeInAttribute(this ITypeSymbol typeSymbol) + internal static bool IsWellKnownTypeInAttribute(this ITypeSymbol typeSymbol) => typeSymbol.IsWellKnownInteropServicesTopLevelType("InAttribute"); + + internal static bool IsWellKnownTypeUnmanagedType(this ITypeSymbol typeSymbol) => typeSymbol.IsWellKnownInteropServicesTopLevelType("UnmanagedType"); + + private static bool IsWellKnownInteropServicesTopLevelType(this ITypeSymbol typeSymbol, string name) { - if (typeSymbol.Name != "InAttribute" || typeSymbol.ContainingType != null) + if (typeSymbol.Name != name || typeSymbol.ContainingType != null) { return false; } diff --git a/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedTypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedTypeParameterSymbol.cs index 0329e9a653a76..fc60e10ecad87 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedTypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedTypeParameterSymbol.cs @@ -73,6 +73,14 @@ public override bool HasReferenceTypeConstraint } } + public override bool HasUnmanagedTypeConstraint + { + get + { + return _underlyingTypeParameter.HasUnmanagedTypeConstraint; + } + } + public override bool HasValueTypeConstraint { get diff --git a/src/Compilers/CSharp/Portable/Syntax/InternalSyntax/TypeSyntax.cs b/src/Compilers/CSharp/Portable/Syntax/InternalSyntax/TypeSyntax.cs index 57b762b76a7da..2b3fa55215fb8 100644 --- a/src/Compilers/CSharp/Portable/Syntax/InternalSyntax/TypeSyntax.cs +++ b/src/Compilers/CSharp/Portable/Syntax/InternalSyntax/TypeSyntax.cs @@ -4,13 +4,8 @@ namespace Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax { internal abstract partial class TypeSyntax { - public bool IsVar - { - get - { - var ts = this as IdentifierNameSyntax; - return ts != null && ts.Identifier.ToString() == "var"; - } - } + public bool IsVar => this is IdentifierNameSyntax name && name.Identifier.ToString() == "var"; + + public bool IsUnmanaged => this is IdentifierNameSyntax name && name.Identifier.ToString() == "unmanaged"; } } diff --git a/src/Compilers/CSharp/Portable/Syntax/TypeSyntax.cs b/src/Compilers/CSharp/Portable/Syntax/TypeSyntax.cs index 8cdb0e5c92a96..741b77a5d8875 100644 --- a/src/Compilers/CSharp/Portable/Syntax/TypeSyntax.cs +++ b/src/Compilers/CSharp/Portable/Syntax/TypeSyntax.cs @@ -4,12 +4,8 @@ namespace Microsoft.CodeAnalysis.CSharp.Syntax { public abstract partial class TypeSyntax { - public bool IsVar - { - get - { - return ((InternalSyntax.TypeSyntax)this.Green).IsVar; - } - } + public bool IsVar => ((InternalSyntax.TypeSyntax)this.Green).IsVar; + + public bool IsUnmanaged => ((InternalSyntax.TypeSyntax)this.Green).IsUnmanaged; } } diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index bf4dc1302ae70..0e720c1ca6b35 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -8610,6 +8610,36 @@ Pokud chcete odstranit toto varování, můžete místo toho použít /reference delegate generic type constraints + + unmanaged generic type constraints + unmanaged generic type constraints + + + + The 'new()' constraint cannot be used with the 'unmanaged' constraint + The 'new()' constraint cannot be used with the 'unmanaged' constraint + + + + The 'unmanaged' constraint cannot be specified with other constraints. + The 'unmanaged' constraint cannot be specified with other constraints. + + + + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + + + + Using 'unmanaged' constraint on local functions type parameters is not supported. + Using 'unmanaged' constraint on local functions type parameters is not supported. + + + + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index e06a6efdcaebd..cd98274fca9c0 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -8610,6 +8610,36 @@ Um die Warnung zu beheben, können Sie stattdessen /reference verwenden (Einbett delegate generic type constraints + + unmanaged generic type constraints + unmanaged generic type constraints + + + + The 'new()' constraint cannot be used with the 'unmanaged' constraint + The 'new()' constraint cannot be used with the 'unmanaged' constraint + + + + The 'unmanaged' constraint cannot be specified with other constraints. + The 'unmanaged' constraint cannot be specified with other constraints. + + + + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + + + + Using 'unmanaged' constraint on local functions type parameters is not supported. + Using 'unmanaged' constraint on local functions type parameters is not supported. + + + + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 58094e72d25dd..24608fad39d77 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -8610,6 +8610,36 @@ Para eliminar la advertencia puede usar /reference (establezca la propiedad Embe delegate generic type constraints + + unmanaged generic type constraints + unmanaged generic type constraints + + + + The 'new()' constraint cannot be used with the 'unmanaged' constraint + The 'new()' constraint cannot be used with the 'unmanaged' constraint + + + + The 'unmanaged' constraint cannot be specified with other constraints. + The 'unmanaged' constraint cannot be specified with other constraints. + + + + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + + + + Using 'unmanaged' constraint on local functions type parameters is not supported. + Using 'unmanaged' constraint on local functions type parameters is not supported. + + + + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index e21f5f8eb7ee3..763166eecb1f4 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -8610,6 +8610,36 @@ Pour supprimer l'avertissement, vous pouvez utiliser la commande /reference (dé delegate generic type constraints + + unmanaged generic type constraints + unmanaged generic type constraints + + + + The 'new()' constraint cannot be used with the 'unmanaged' constraint + The 'new()' constraint cannot be used with the 'unmanaged' constraint + + + + The 'unmanaged' constraint cannot be specified with other constraints. + The 'unmanaged' constraint cannot be specified with other constraints. + + + + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + + + + Using 'unmanaged' constraint on local functions type parameters is not supported. + Using 'unmanaged' constraint on local functions type parameters is not supported. + + + + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index bce19c9126279..5d386fd057de8 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -8610,6 +8610,36 @@ Per rimuovere l'avviso, è invece possibile usare /reference (impostare la propr delegate generic type constraints + + unmanaged generic type constraints + unmanaged generic type constraints + + + + The 'new()' constraint cannot be used with the 'unmanaged' constraint + The 'new()' constraint cannot be used with the 'unmanaged' constraint + + + + The 'unmanaged' constraint cannot be specified with other constraints. + The 'unmanaged' constraint cannot be specified with other constraints. + + + + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + + + + Using 'unmanaged' constraint on local functions type parameters is not supported. + Using 'unmanaged' constraint on local functions type parameters is not supported. + + + + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 388fd1ecc3a17..4528a1d9edafd 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -8610,6 +8610,36 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ delegate generic type constraints + + unmanaged generic type constraints + unmanaged generic type constraints + + + + The 'new()' constraint cannot be used with the 'unmanaged' constraint + The 'new()' constraint cannot be used with the 'unmanaged' constraint + + + + The 'unmanaged' constraint cannot be specified with other constraints. + The 'unmanaged' constraint cannot be specified with other constraints. + + + + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + + + + Using 'unmanaged' constraint on local functions type parameters is not supported. + Using 'unmanaged' constraint on local functions type parameters is not supported. + + + + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 20e7535f4f4fb..3167969dda8b9 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -8610,6 +8610,36 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ delegate generic type constraints + + unmanaged generic type constraints + unmanaged generic type constraints + + + + The 'new()' constraint cannot be used with the 'unmanaged' constraint + The 'new()' constraint cannot be used with the 'unmanaged' constraint + + + + The 'unmanaged' constraint cannot be specified with other constraints. + The 'unmanaged' constraint cannot be specified with other constraints. + + + + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + + + + Using 'unmanaged' constraint on local functions type parameters is not supported. + Using 'unmanaged' constraint on local functions type parameters is not supported. + + + + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 33b8c8db8760a..4aef236731d7b 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -8610,6 +8610,36 @@ Aby usunąć ostrzeżenie, możesz zamiast tego użyć opcji /reference (ustaw w delegate generic type constraints + + unmanaged generic type constraints + unmanaged generic type constraints + + + + The 'new()' constraint cannot be used with the 'unmanaged' constraint + The 'new()' constraint cannot be used with the 'unmanaged' constraint + + + + The 'unmanaged' constraint cannot be specified with other constraints. + The 'unmanaged' constraint cannot be specified with other constraints. + + + + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + + + + Using 'unmanaged' constraint on local functions type parameters is not supported. + Using 'unmanaged' constraint on local functions type parameters is not supported. + + + + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index d269eb541591c..f615a43dac76a 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -8610,6 +8610,36 @@ Para incorporar informações de tipo de interoperabilidade para os dois assembl delegate generic type constraints + + unmanaged generic type constraints + unmanaged generic type constraints + + + + The 'new()' constraint cannot be used with the 'unmanaged' constraint + The 'new()' constraint cannot be used with the 'unmanaged' constraint + + + + The 'unmanaged' constraint cannot be specified with other constraints. + The 'unmanaged' constraint cannot be specified with other constraints. + + + + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + + + + Using 'unmanaged' constraint on local functions type parameters is not supported. + Using 'unmanaged' constraint on local functions type parameters is not supported. + + + + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 0a8df165d98db..c4526f6a3934b 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -8610,6 +8610,36 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ delegate generic type constraints + + unmanaged generic type constraints + unmanaged generic type constraints + + + + The 'new()' constraint cannot be used with the 'unmanaged' constraint + The 'new()' constraint cannot be used with the 'unmanaged' constraint + + + + The 'unmanaged' constraint cannot be specified with other constraints. + The 'unmanaged' constraint cannot be specified with other constraints. + + + + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + + + + Using 'unmanaged' constraint on local functions type parameters is not supported. + Using 'unmanaged' constraint on local functions type parameters is not supported. + + + + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 89e2d76fde432..539719c8d8c93 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -8610,6 +8610,36 @@ Uyarıyı kaldırmak için, /reference kullanabilirsiniz (Birlikte Çalışma T delegate generic type constraints + + unmanaged generic type constraints + unmanaged generic type constraints + + + + The 'new()' constraint cannot be used with the 'unmanaged' constraint + The 'new()' constraint cannot be used with the 'unmanaged' constraint + + + + The 'unmanaged' constraint cannot be specified with other constraints. + The 'unmanaged' constraint cannot be specified with other constraints. + + + + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + + + + Using 'unmanaged' constraint on local functions type parameters is not supported. + Using 'unmanaged' constraint on local functions type parameters is not supported. + + + + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 4eb59040307b5..bb15165df1bb1 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -8610,6 +8610,36 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ delegate generic type constraints + + unmanaged generic type constraints + unmanaged generic type constraints + + + + The 'new()' constraint cannot be used with the 'unmanaged' constraint + The 'new()' constraint cannot be used with the 'unmanaged' constraint + + + + The 'unmanaged' constraint cannot be specified with other constraints. + The 'unmanaged' constraint cannot be specified with other constraints. + + + + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + + + + Using 'unmanaged' constraint on local functions type parameters is not supported. + Using 'unmanaged' constraint on local functions type parameters is not supported. + + + + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index f13ad18b061d7..e6a1e4ccbda9c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -8610,6 +8610,36 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ delegate generic type constraints + + unmanaged generic type constraints + unmanaged generic type constraints + + + + The 'new()' constraint cannot be used with the 'unmanaged' constraint + The 'new()' constraint cannot be used with the 'unmanaged' constraint + + + + The 'unmanaged' constraint cannot be specified with other constraints. + The 'unmanaged' constraint cannot be specified with other constraints. + + + + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + + + + Using 'unmanaged' constraint on local functions type parameters is not supported. + Using 'unmanaged' constraint on local functions type parameters is not supported. + + + + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_IsUnmanaged.cs b/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_IsUnmanaged.cs new file mode 100644 index 0000000000000..a7c38d6729b40 --- /dev/null +++ b/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_IsUnmanaged.cs @@ -0,0 +1,593 @@ +// 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 Microsoft.CodeAnalysis.CSharp.Symbols; +using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Test.Utilities; +using Microsoft.CodeAnalysis.CSharp.UnitTests; +using Microsoft.CodeAnalysis.Test.Utilities; +using Roslyn.Test.Utilities; +using Roslyn.Utilities; +using System; +using System.Collections.Immutable; +using System.Linq; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests +{ + public class AttributeTests_IsUnmanaged : CSharpTestBase + { + [Fact] + public void AttributeUsedIfExists_FromSource_Method() + { + var text = @" +namespace System.Runtime.CompilerServices +{ + public class IsUnmanagedAttribute : System.Attribute { } +} +public class Test +{ + public void M() where T : unmanaged { } +} +"; + + CompileAndVerify(text, symbolValidator: module => + { + var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("M").TypeParameters.Single(); + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.True(typeParameter.HasUnmanagedTypeConstraint); + + Assert.Null(module.ContainingAssembly.GetTypeByMetadataName(AttributeDescription.CodeAnalysisEmbeddedAttribute.FullName)); + AssertReferencedIsUnmanagedAttribute(Accessibility.Public, typeParameter, module.ContainingAssembly.Name); + }); + } + + [Fact] + public void AttributeUsedIfExists_FromSource_Class() + { + var text = @" +namespace System.Runtime.CompilerServices +{ + public class IsUnmanagedAttribute : System.Attribute { } +} +public class Test where T : unmanaged +{ +} +"; + + CompileAndVerify(text, symbolValidator: module => + { + var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Test`1").TypeParameters.Single(); + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.True(typeParameter.HasUnmanagedTypeConstraint); + + Assert.Null(module.ContainingAssembly.GetTypeByMetadataName(AttributeDescription.CodeAnalysisEmbeddedAttribute.FullName)); + AssertReferencedIsUnmanagedAttribute(Accessibility.Public, typeParameter, module.ContainingAssembly.Name); + }); + } + + [Fact] + public void AttributeUsedIfExists_FromReference_Method_Reference() + { + var reference = CreateStandardCompilation(@" +namespace System.Runtime.CompilerServices +{ + public class IsUnmanagedAttribute : System.Attribute { } +}").EmitToImageReference(); + + var text = @" +public class Test +{ + public void M() where T : unmanaged { } +} +"; + + CompileAndVerify(text, additionalRefs: new[] { reference }, symbolValidator: module => + { + var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("M").TypeParameters.Single(); + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.True(typeParameter.HasUnmanagedTypeConstraint); + + AssertReferencedIsUnmanagedAttribute(Accessibility.Public, typeParameter, reference.Display); + AssertNoIsUnmanagedAttributeExists(module.ContainingAssembly); + }); + } + + [Fact] + public void AttributeUsedIfExists_FromReference_Class_Reference() + { + var reference = CreateStandardCompilation(@" +namespace System.Runtime.CompilerServices +{ + public class IsUnmanagedAttribute : System.Attribute { } +}").EmitToImageReference(); + + var text = @" +public class Test where T : unmanaged +{ +} +"; + + CompileAndVerify(text, additionalRefs: new[] { reference }, symbolValidator: module => + { + var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Test`1").TypeParameters.Single(); + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.True(typeParameter.HasUnmanagedTypeConstraint); + + AssertReferencedIsUnmanagedAttribute(Accessibility.Public, typeParameter, reference.Display); + AssertNoIsUnmanagedAttributeExists(module.ContainingAssembly); + }); + } + + [Fact] + public void AttributeUsedIfExists_FromReference_Method_Module() + { + var reference = CreateStandardCompilation(@" +namespace System.Runtime.CompilerServices +{ + public class IsUnmanagedAttribute : System.Attribute { } +}").EmitToImageReference(); + + var text = @" +public class Test +{ + public void M() where T : unmanaged { } +} +"; + + CompileAndVerify(text, verify: Verification.Fails, additionalRefs: new[] { reference }, options: TestOptions.ReleaseModule, symbolValidator: module => + { + var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("M").TypeParameters.Single(); + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.True(typeParameter.HasUnmanagedTypeConstraint); + + AssertReferencedIsUnmanagedAttribute(Accessibility.Public, typeParameter, reference.Display); + AssertNoIsUnmanagedAttributeExists(module.ContainingAssembly); + }); + } + + [Fact] + public void AttributeUsedIfExists_FromReference_Class_Module() + { + var reference = CreateStandardCompilation(@" +namespace System.Runtime.CompilerServices +{ + public class IsUnmanagedAttribute : System.Attribute { } +}").EmitToImageReference(); + + var text = @" +public class Test where T : unmanaged +{ +} +"; + + CompileAndVerify(text, verify: Verification.Fails, additionalRefs: new[] { reference }, options: TestOptions.ReleaseModule, symbolValidator: module => + { + var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Test`1").TypeParameters.Single(); + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.True(typeParameter.HasUnmanagedTypeConstraint); + + AssertReferencedIsUnmanagedAttribute(Accessibility.Public, typeParameter, reference.Display); + AssertNoIsUnmanagedAttributeExists(module.ContainingAssembly); + }); + } + + [Fact] + public void AttributeGeneratedIfNotExists_FromSource_Method() + { + var text = @" +public class Test +{ + public void M() where T : unmanaged { } +} +"; + + CompileAndVerify(text, symbolValidator: module => + { + var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("M").TypeParameters.Single(); + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.True(typeParameter.HasUnmanagedTypeConstraint); + + AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, typeParameter, module.ContainingAssembly.Name); + }); + } + + [Fact] + public void AttributeGeneratedIfNotExists_FromSource_Class() + { + var text = @" +public class Test where T : unmanaged +{ +} +"; + + CompileAndVerify(text, symbolValidator: module => + { + var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Test`1").TypeParameters.Single(); + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.True(typeParameter.HasUnmanagedTypeConstraint); + + AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, typeParameter, module.ContainingAssembly.Name); + }); + } + + [Fact] + public void IsUnmanagedAttributeIsDisallowedEverywhereInSource_Delegates() + { + var code = @" +using System.Runtime.CompilerServices; + +namespace System.Runtime.CompilerServices +{ + public class IsUnmanagedAttribute : System.Attribute { } +} + +[IsUnmanaged] +public delegate void D([IsUnmanaged]int x); +"; + + CreateStandardCompilation(code).VerifyDiagnostics( + // (9,2): error CS8335: Do not use 'System.Runtime.CompilerServices.IsUnmanagedAttribute'. This is reserved for compiler usage. + // [IsUnmanaged] + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "IsUnmanaged").WithArguments("System.Runtime.CompilerServices.IsUnmanagedAttribute").WithLocation(9, 2), + // (10,25): error CS8335: Do not use 'System.Runtime.CompilerServices.IsUnmanagedAttribute'. This is reserved for compiler usage. + // public delegate void D([IsUnmanaged]int x); + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "IsUnmanaged").WithArguments("System.Runtime.CompilerServices.IsUnmanagedAttribute").WithLocation(10, 25)); + } + + [Fact] + public void IsUnmanagedAttributeIsDisallowedEverywhereInSource_Types() + { + var code = @" +using System.Runtime.CompilerServices; + +namespace System.Runtime.CompilerServices +{ + public class IsUnmanagedAttribute : System.Attribute { } +} + +[IsUnmanaged] +public class Test +{ +} +"; + + CreateStandardCompilation(code).VerifyDiagnostics( + // (9,2): error CS8335: Do not use 'System.Runtime.CompilerServices.IsUnmanagedAttribute'. This is reserved for compiler usage. + // [IsUnmanaged] + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "IsUnmanaged").WithArguments("System.Runtime.CompilerServices.IsUnmanagedAttribute").WithLocation(9, 2)); + } + + [Fact] + public void IsUnmanagedAttributeIsDisallowedEverywhereInSource_Fields() + { + var code = @" +using System.Runtime.CompilerServices; + +namespace System.Runtime.CompilerServices +{ + public class IsUnmanagedAttribute : System.Attribute { } +} + +public class Test +{ + [IsUnmanaged] + public int x = 0; +} +"; + + CreateStandardCompilation(code).VerifyDiagnostics( + // (11,6): error CS8335: Do not use 'System.Runtime.CompilerServices.IsUnmanagedAttribute'. This is reserved for compiler usage. + // [IsUnmanaged] + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "IsUnmanaged").WithArguments("System.Runtime.CompilerServices.IsUnmanagedAttribute").WithLocation(11, 6)); + } + + [Fact] + public void IsUnmanagedAttributeIsDisallowedEverywhereInSource_Properties() + { + var code = @" +using System.Runtime.CompilerServices; + +namespace System.Runtime.CompilerServices +{ + public class IsUnmanagedAttribute : System.Attribute { } +} + +public class Test +{ + [IsUnmanaged] + public int Property => 0; +} +"; + + CreateStandardCompilation(code).VerifyDiagnostics( + // (11,6): error CS8335: Do not use 'System.Runtime.CompilerServices.IsUnmanagedAttribute'. This is reserved for compiler usage. + // [IsUnmanaged] + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "IsUnmanaged").WithArguments("System.Runtime.CompilerServices.IsUnmanagedAttribute").WithLocation(11, 6)); + } + + [Fact] + public void IsUnmanagedAttributeIsDisallowedEverywhereInSource_Methods() + { + var code = @" +using System.Runtime.CompilerServices; + +namespace System.Runtime.CompilerServices +{ + public class IsUnmanagedAttribute : System.Attribute { } +} + +public class Test +{ + [IsUnmanaged] + [return: IsUnmanaged] + public int Method([IsUnmanaged]int x) + { + return x; + } +} +"; + + CreateStandardCompilation(code).VerifyDiagnostics( + // (11,6): error CS8335: Do not use 'System.Runtime.CompilerServices.IsUnmanagedAttribute'. This is reserved for compiler usage. + // [IsUnmanaged] + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "IsUnmanaged").WithArguments("System.Runtime.CompilerServices.IsUnmanagedAttribute").WithLocation(11, 6), + // (12,14): error CS8335: Do not use 'System.Runtime.CompilerServices.IsUnmanagedAttribute'. This is reserved for compiler usage. + // [return: IsUnmanaged] + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "IsUnmanaged").WithArguments("System.Runtime.CompilerServices.IsUnmanagedAttribute").WithLocation(12, 14), + // (13,24): error CS8335: Do not use 'System.Runtime.CompilerServices.IsUnmanagedAttribute'. This is reserved for compiler usage. + // public int Method([IsUnmanaged]int x) + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "IsUnmanaged").WithArguments("System.Runtime.CompilerServices.IsUnmanagedAttribute").WithLocation(13, 24)); + } + + [Fact] + public void IsUnmanagedAttributeIsDisallowedEverywhereInSource_Indexers() + { + var code = @" +using System.Runtime.CompilerServices; + +namespace System.Runtime.CompilerServices +{ + public class IsUnmanagedAttribute : System.Attribute { } +} + +public class Test +{ + [IsUnmanaged] + public int this[[IsUnmanaged]int x] => x; +} +"; + + CreateStandardCompilation(code).VerifyDiagnostics( + // (11,6): error CS8335: Do not use 'System.Runtime.CompilerServices.IsUnmanagedAttribute'. This is reserved for compiler usage. + // [IsUnmanaged] + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "IsUnmanaged").WithArguments("System.Runtime.CompilerServices.IsUnmanagedAttribute").WithLocation(11, 6), + // (12,22): error CS8335: Do not use 'System.Runtime.CompilerServices.IsUnmanagedAttribute'. This is reserved for compiler usage. + // public int this[[IsUnmanaged]int x] => x; + Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "IsUnmanaged").WithArguments("System.Runtime.CompilerServices.IsUnmanagedAttribute").WithLocation(12, 22)); + } + + [Fact] + public void UserReferencingIsUnmanagedAttributeShouldResultInAnError() + { + var code = @" +[IsUnmanaged] +public class Test +{ +} +"; + + CreateStandardCompilation(code).VerifyDiagnostics( + // (2,2): error CS0246: The type or namespace name 'IsUnmanagedAttribute' could not be found (are you missing a using directive or an assembly reference?) + // [IsUnmanaged] + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "IsUnmanaged").WithArguments("IsUnmanagedAttribute").WithLocation(2, 2), + // (2,2): error CS0246: The type or namespace name 'IsUnmanaged' could not be found (are you missing a using directive or an assembly reference?) + // [IsUnmanaged] + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "IsUnmanaged").WithArguments("IsUnmanaged").WithLocation(2, 2)); + } + + [Fact] + public void TypeReferencingAnotherTypeThatUsesAPublicAttributeFromAThirdNotReferencedAssemblyShouldGenerateItsOwn() + { + var options = TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All); + + var code1 = CreateStandardCompilation(@" +namespace System.Runtime.CompilerServices +{ + public class IsUnmanagedAttribute : System.Attribute { } +}"); + + var code2 = CreateStandardCompilation(@" +public class Test1 where T : unmanaged { } +", references: new[] { code1.ToMetadataReference() }, options: options); + + CompileAndVerify(code2, symbolValidator: module => + { + AssertNoIsUnmanagedAttributeExists(module.ContainingAssembly); + }); + + var code3 = CreateStandardCompilation(@" +public class Test2 : Test1 where T : unmanaged { } +", references: new[] { code2.ToMetadataReference() }, options: options); + + CompileAndVerify(code3, symbolValidator: module => + { + var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Test2`1").TypeParameters.Single(); + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.True(typeParameter.HasUnmanagedTypeConstraint); + + AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, typeParameter, module.ContainingAssembly.Name); + }); + } + + [Fact] + public void BuildingAModuleRequiresIsUnmanagedAttributeToBeThere_Missing_Type() + { + var code = @" +public class Test where T : unmanaged +{ +}"; + + CreateStandardCompilation(code, options: TestOptions.ReleaseModule).VerifyDiagnostics( + // (2,19): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsUnmanagedAttribute' is not defined or imported + // public class Test where T : unmanaged + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "T").WithArguments("System.Runtime.CompilerServices.IsUnmanagedAttribute").WithLocation(2, 19)); + } + + [Fact] + public void BuildingAModuleRequiresIsUnmanagedAttributeToBeThere_Missing_Method() + { + var code = @" +public class Test +{ + public void M() where T : unmanaged {} +}"; + + CreateStandardCompilation(code, options: TestOptions.ReleaseModule).VerifyDiagnostics( + // (4,19): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsUnmanagedAttribute' is not defined or imported + // public void M() where T : unmanaged {} + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "T").WithArguments("System.Runtime.CompilerServices.IsUnmanagedAttribute").WithLocation(4, 19)); + } + + [Fact] + public void ReferencingAnEmbeddedIsUnmanagedAttributeDoesNotUseIt_InternalsVisible() + { + var options = TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All); + + var code1 = @" +[assembly:System.Runtime.CompilerServices.InternalsVisibleToAttribute(""Assembly2"")] +public class Test1 where T : unmanaged +{ +}"; + + var comp1 = CompileAndVerify(code1, options: options, symbolValidator: module => + { + var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Test1`1").TypeParameters.Single(); + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.True(typeParameter.HasUnmanagedTypeConstraint); + + AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, typeParameter, module.ContainingAssembly.Name); + }); + + var code2 = @" +public class Test2 : Test1 where T : unmanaged +{ +}"; + + CompileAndVerify(code2, options: options.WithModuleName("Assembly2"), additionalRefs: new[] { comp1.Compilation.ToMetadataReference() }, symbolValidator: module => + { + var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Test2`1").TypeParameters.Single(); + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.True(typeParameter.HasUnmanagedTypeConstraint); + + AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, typeParameter, module.ContainingAssembly.Name); + }); + } + + [Theory] + [InlineData(OutputKind.DynamicallyLinkedLibrary)] + [InlineData(OutputKind.NetModule)] + public void IsUnmanagedAttributeExistsWithWrongConstructorSignature(OutputKind outputKind) + { + var text = @" +namespace System.Runtime.CompilerServices +{ + public class IsUnmanagedAttribute : System.Attribute + { + public IsUnmanagedAttribute(int p) { } + } +} +class Test where T : unmanaged +{ +}"; + + CreateStandardCompilation(text, options: new CSharpCompilationOptions(outputKind)).VerifyDiagnostics( + // (9,12): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsUnmanagedAttribute..ctor' + // class Test where T : unmanaged + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "T").WithArguments("System.Runtime.CompilerServices.IsUnmanagedAttribute", ".ctor").WithLocation(9, 12)); + } + + [Theory] + [InlineData(OutputKind.DynamicallyLinkedLibrary)] + [InlineData(OutputKind.NetModule)] + public void IsUnmanagedAttributeExistsWithPrivateConstructor(OutputKind outputKind) + { + var text = @" +namespace System.Runtime.CompilerServices +{ + public class IsUnmanagedAttribute : System.Attribute + { + private IsUnmanagedAttribute() { } + } +} +class Test where T : unmanaged +{ +}"; + + CreateStandardCompilation(text, options: new CSharpCompilationOptions(outputKind)).VerifyDiagnostics( + // (9,12): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsUnmanagedAttribute..ctor' + // class Test where T : unmanaged + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "T").WithArguments("System.Runtime.CompilerServices.IsUnmanagedAttribute", ".ctor").WithLocation(9, 12)); + } + + [Theory] + [InlineData(OutputKind.DynamicallyLinkedLibrary)] + [InlineData(OutputKind.NetModule)] + public void IsUnmanagedAttributeExistsAsInterface(OutputKind outputKind) + { + var text = @" +namespace System.Runtime.CompilerServices +{ + public interface IsUnmanagedAttribute { } +} +class Test where T : unmanaged +{ +}"; + + CreateStandardCompilation(text, options: new CSharpCompilationOptions(outputKind)).VerifyDiagnostics( + // (6,12): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsUnmanagedAttribute..ctor' + // class Test where T : unmanaged + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "T").WithArguments("System.Runtime.CompilerServices.IsUnmanagedAttribute", ".ctor").WithLocation(6, 12)); + } + + internal static void AssertReferencedIsUnmanagedAttribute(Accessibility accessibility, TypeParameterSymbol typeParameter, string assemblyName) + { + var attributes = ((PEModuleSymbol)typeParameter.ContainingModule).GetCustomAttributesForToken(((PETypeParameterSymbol)typeParameter).Handle); + NamedTypeSymbol attributeType = attributes.Single().AttributeClass; + + Assert.Equal("IsUnmanagedAttribute", attributeType.Name); + Assert.Equal(assemblyName, attributeType.ContainingAssembly.Name); + Assert.Equal(accessibility, attributeType.DeclaredAccessibility); + + switch (accessibility) + { + case Accessibility.Internal: + { + var isUnmanagedTypeAttributes = attributeType.GetAttributes().OrderBy(attribute => attribute.AttributeClass.Name).ToArray(); + Assert.Equal(2, isUnmanagedTypeAttributes.Length); + + Assert.Equal(WellKnownTypes.GetMetadataName(WellKnownType.System_Runtime_CompilerServices_CompilerGeneratedAttribute), isUnmanagedTypeAttributes[0].AttributeClass.ToDisplayString()); + Assert.Equal(AttributeDescription.CodeAnalysisEmbeddedAttribute.FullName, isUnmanagedTypeAttributes[1].AttributeClass.ToDisplayString()); + break; + } + + case Accessibility.Public: + { + Assert.Null(attributeType.ContainingAssembly.GetTypeByMetadataName(AttributeDescription.CodeAnalysisEmbeddedAttribute.FullName)); + + break; + } + + default: + throw ExceptionUtilities.UnexpectedValue(accessibility); + } + + } + + private void AssertNoIsUnmanagedAttributeExists(AssemblySymbol assembly) + { + var isUnmanagedAttributeTypeName = WellKnownTypes.GetMetadataName(WellKnownType.System_Runtime_CompilerServices_IsUnmanagedAttribute); + Assert.Null(assembly.GetTypeByMetadataName(isUnmanagedAttributeTypeName)); + } + } +} diff --git a/src/Compilers/CSharp/Test/Emit/Emit/UnmanagedTypeModifierTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/UnmanagedTypeModifierTests.cs new file mode 100644 index 0000000000000..835a4a3ffe17d --- /dev/null +++ b/src/Compilers/CSharp/Test/Emit/Emit/UnmanagedTypeModifierTests.cs @@ -0,0 +1,1098 @@ +// 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.Linq; +using Microsoft.CodeAnalysis.CSharp.Test.Utilities; +using Microsoft.CodeAnalysis.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Emit +{ + public class UnmanagedTypeModifierTests : CSharpTestBase + { + [Fact] + public void LoadingADifferentModifierTypeForUnmanagedConstraint() + { + var ilSource = IsUnmanagedAttributeIL + @" +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .method public hidebysig instance void + M1() cil managed + { + .param type T + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method TestRef::M1 + + .method public hidebysig instance void + M2() cil managed + { + .param type T + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method TestRef::M2 + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method TestRef::.ctor + +}"; + + var reference = CompileIL(ilSource, prependDefaultHeader: false); + + var code = @" +public class Test +{ + public static void Main() + { + var obj = new TestRef(); + + obj.M1(); // valid + obj.M2(); // invalid + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (9,9): error CS0570: 'T' is not supported by the language + // obj.M2(); // invalid + Diagnostic(ErrorCode.ERR_BindToBogus, "obj.M2").WithArguments("T").WithLocation(9, 9)); + } + + [Fact] + public void LoadingUnmanagedTypeModifier_OptionalIsError() + { + var ilSource = IsUnmanagedAttributeIL + @" +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .method public hidebysig instance void + M1() cil managed + { + .param type T + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method TestRef::M1 + + .method public hidebysig instance void + M2() cil managed + { + .param type T + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method TestRef::M2 + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method TestRef::.ctor + +}"; + + var reference = CompileIL(ilSource, prependDefaultHeader: false); + + var code = @" +public class Test +{ + public static void Main() + { + var obj = new TestRef(); + + obj.M1(); // valid + obj.M2(); // invalid + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (9,9): error CS0570: 'T' is not supported by the language + // obj.M2(); // invalid + Diagnostic(ErrorCode.ERR_BindToBogus, "obj.M2").WithArguments("T").WithLocation(9, 9)); + } + + [Fact] + public void LoadingUnmanagedTypeModifier_ModreqWithoutAttribute() + { + var ilSource = IsUnmanagedAttributeIL + @" +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .method public hidebysig instance void + M1() cil managed + { + .param type T + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method TestRef::M1 + + .method public hidebysig instance void + M2() cil managed + { + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method TestRef::M2 + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method TestRef::.ctor + +}"; + + var reference = CompileIL(ilSource, prependDefaultHeader: false); + + var code = @" +public class Test +{ + public static void Main() + { + var obj = new TestRef(); + + obj.M1(); // valid + obj.M2(); // invalid + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (9,9): error CS0570: 'T' is not supported by the language + // obj.M2(); // invalid + Diagnostic(ErrorCode.ERR_BindToBogus, "obj.M2").WithArguments("T").WithLocation(9, 9)); + } + + [Fact] + public void LoadingUnmanagedTypeModifier_AttributeWithoutModreq() + { + var ilSource = IsUnmanagedAttributeIL + @" +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .method public hidebysig instance void + M1() cil managed + { + .param type T + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method TestRef::M1 + + .method public hidebysig instance void + M2() cil managed + { + .param type T + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method TestRef::M2 + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method TestRef::.ctor + +}"; + + var reference = CompileIL(ilSource, prependDefaultHeader: false); + + var code = @" +public class Test +{ + public static void Main() + { + var obj = new TestRef(); + + obj.M1(); // valid + obj.M2(); // invalid + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (9,9): error CS0570: 'T' is not supported by the language + // obj.M2(); // invalid + Diagnostic(ErrorCode.ERR_BindToBogus, "obj.M2").WithArguments("T").WithLocation(9, 9)); + } + + [Fact] + public void ProperErrorsArePropagatedIfModreqTypeIsNotAvailable_Class() + { + var code = @" +namespace System +{ + public class Object {} + public class Void {} + public class ValueType {} +} +class Test where T : unmanaged +{ +}"; + + CreateCompilation(code).VerifyDiagnostics( + // (8,25): error CS0518: Predefined type 'System.Runtime.InteropServices.UnmanagedType' is not defined or imported + // class Test where T : unmanaged + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "unmanaged").WithArguments("System.Runtime.InteropServices.UnmanagedType").WithLocation(8, 25)); + } + + [Fact] + public void ProperErrorsArePropagatedIfModreqTypeIsNotAvailable_Method() + { + var code = @" +namespace System +{ + public class Object {} + public class Void {} + public class ValueType {} +} +class Test +{ + public void M() where T : unmanaged {} +}"; + + CreateCompilation(code).VerifyDiagnostics( + // (10,34): error CS0518: Predefined type 'System.Runtime.InteropServices.UnmanagedType' is not defined or imported + // public void M() where T : unmanaged {} + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "unmanaged").WithArguments("System.Runtime.InteropServices.UnmanagedType").WithLocation(10, 34)); + } + + [Fact] + public void ProperErrorsArePropagatedIfModreqTypeIsNotAvailable_Delegate() + { + var code = @" +namespace System +{ + public class Object {} + public class Void {} + public class ValueType {} + public class IntPtr {} + public class MulticastDelegate {} +} +public delegate void D() where T : unmanaged;"; + + CreateCompilation(code).VerifyDiagnostics( + // (10,39): error CS0518: Predefined type 'System.Runtime.InteropServices.UnmanagedType' is not defined or imported + // public delegate void D() where T : unmanaged; + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "unmanaged").WithArguments("System.Runtime.InteropServices.UnmanagedType").WithLocation(10, 39)); + } + + [Fact] + public void ProperErrorsArePropagatedIfValueTypeIsNotAvailable_Class() + { + var code = @" +namespace System +{ + public class Object {} + public class Void {} + + namespace Runtime + { + namespace InteropServices + { + public class UnmanagedType {} + } + } +} +class Test where T : unmanaged +{ +}"; + + CreateCompilation(code).VerifyDiagnostics( + // (15,25): error CS0518: Predefined type 'System.ValueType' is not defined or imported + // class Test where T : unmanaged + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "unmanaged").WithArguments("System.ValueType").WithLocation(15, 25)); + } + + [Fact] + public void ProperErrorsArePropagatedIfValueTypeIsNotAvailable_Method() + { + var code = @" +namespace System +{ + public class Object {} + public class Void {} + + namespace Runtime + { + namespace InteropServices + { + public class UnmanagedType {} + } + } +} +class Test +{ + public void M() where T : unmanaged {} +}"; + + CreateCompilation(code).VerifyDiagnostics( + // (17,34): error CS0518: Predefined type 'System.ValueType' is not defined or imported + // public void M() where T : unmanaged {} + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "unmanaged").WithArguments("System.ValueType").WithLocation(17, 34)); + } + + [Fact] + public void ProperErrorsArePropagatedIfValueTypeIsNotAvailable_Delegate() + { + var code = @" +namespace System +{ + public class Object {} + public class Void {} + public class IntPtr {} + public class MulticastDelegate {} + + namespace Runtime + { + namespace InteropServices + { + public class UnmanagedType {} + } + } +} +public delegate void M() where T : unmanaged;"; + + CreateCompilation(code).VerifyDiagnostics( + // (17,39): error CS0518: Predefined type 'System.ValueType' is not defined or imported + // public delegate void M() where T : unmanaged; + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "unmanaged").WithArguments("System.ValueType").WithLocation(17, 39)); + } + + [Fact] + public void UnmanagedTypeModreqIsCopiedToOverrides_Virtual_Compilation() + { + var reference = CompileAndVerify(@" +public class Parent +{ + public virtual string M() where T : unmanaged => ""Parent""; +} +public class Child : Parent +{ + public override string M() => ""Child""; +}", symbolValidator: module => + { + var parentTypeParameter = module.ContainingAssembly.GetTypeByMetadataName("Parent").GetMethod("M").TypeParameters.Single(); + Assert.True(parentTypeParameter.HasValueTypeConstraint); + Assert.True(parentTypeParameter.HasUnmanagedTypeConstraint); + + AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, parentTypeParameter, module.ContainingAssembly.Name); + + var childTypeParameter = module.ContainingAssembly.GetTypeByMetadataName("Child").GetMethod("M").TypeParameters.Single(); + Assert.True(childTypeParameter.HasValueTypeConstraint); + Assert.True(childTypeParameter.HasUnmanagedTypeConstraint); + + AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, childTypeParameter, module.ContainingAssembly.Name); + }); + + CompileAndVerify(@" +class Program +{ + public static void Main() + { + System.Console.WriteLine(new Parent().M()); + System.Console.WriteLine(new Child().M()); + } +}", additionalRefs: new[] { reference.Compilation.EmitToImageReference() }, expectedOutput: @" +Parent +Child"); + } + + [Fact] + public void UnmanagedTypeModreqIsCopiedToOverrides_Virtual_Reference() + { + var parent = CompileAndVerify(@" +public class Parent +{ + public virtual string M() where T : unmanaged => ""Parent""; +}", symbolValidator: module => + { + var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Parent").GetMethod("M").TypeParameters.Single(); + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.True(typeParameter.HasUnmanagedTypeConstraint); + + AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, typeParameter, module.ContainingAssembly.Name); + }); + + + var child = CompileAndVerify(@" +public class Child : Parent +{ + public override string M() => ""Child""; +}", additionalRefs: new[] { parent.Compilation.EmitToImageReference() }, symbolValidator: module => + { + var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Child").GetMethod("M").TypeParameters.Single(); + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.True(typeParameter.HasUnmanagedTypeConstraint); + + AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, typeParameter, module.ContainingAssembly.Name); + }); + + CompileAndVerify(@" +class Program +{ + public static void Main() + { + System.Console.WriteLine(new Parent().M()); + System.Console.WriteLine(new Child().M()); + } +}", additionalRefs: new[] { parent.Compilation.EmitToImageReference(), child.Compilation.EmitToImageReference() }, expectedOutput: @" +Parent +Child"); + } + + [Fact] + public void UnmanagedTypeModreqIsCopiedToOverrides_Abstract_Compilation() + { + var reference = CompileAndVerify(@" +public abstract class Parent +{ + public abstract string M() where T : unmanaged; +} +public class Child : Parent +{ + public override string M() => ""Child""; +}", symbolValidator: module => + { + var parentTypeParameter = module.ContainingAssembly.GetTypeByMetadataName("Parent").GetMethod("M").TypeParameters.Single(); + Assert.True(parentTypeParameter.HasValueTypeConstraint); + Assert.True(parentTypeParameter.HasUnmanagedTypeConstraint); + + AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, parentTypeParameter, module.ContainingAssembly.Name); + + var childTypeParameter = module.ContainingAssembly.GetTypeByMetadataName("Child").GetMethod("M").TypeParameters.Single(); + Assert.True(childTypeParameter.HasValueTypeConstraint); + Assert.True(childTypeParameter.HasUnmanagedTypeConstraint); + + AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, childTypeParameter, module.ContainingAssembly.Name); + }); + + CompileAndVerify(@" +class Program +{ + public static void Main() + { + System.Console.WriteLine(new Child().M()); + } +}", additionalRefs: new[] { reference.Compilation.EmitToImageReference() }, expectedOutput: "Child"); + } + + [Fact] + public void UnmanagedTypeModreqIsCopiedToOverrides_Abstract_Reference() + { + var parent = CompileAndVerify(@" +public abstract class Parent +{ + public abstract string M() where T : unmanaged; +}", symbolValidator: module => + { + var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Parent").GetMethod("M").TypeParameters.Single(); + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.True(typeParameter.HasUnmanagedTypeConstraint); + + AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, typeParameter, module.ContainingAssembly.Name); + }); + + + var child = CompileAndVerify(@" +public class Child : Parent +{ + public override string M() => ""Child""; +}", additionalRefs: new[] { parent.Compilation.EmitToImageReference() }, symbolValidator: module => + { + var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Child").GetMethod("M").TypeParameters.Single(); + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.True(typeParameter.HasUnmanagedTypeConstraint); + + AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, typeParameter, module.ContainingAssembly.Name); + }); + + CompileAndVerify(@" +class Program +{ + public static void Main() + { + System.Console.WriteLine(new Child().M()); + } +}", additionalRefs: new[] { parent.Compilation.EmitToImageReference(), child.Compilation.EmitToImageReference() }, expectedOutput: "Child"); + } + + [Fact] + public void UnmanagedTypeModreqIsCopiedToOverrides_Interface_Implicit_Nonvirtual_Compilation() + { + var reference = CompileAndVerify(@" +public interface Parent +{ + string M() where T : unmanaged; +} +public class Child : Parent +{ + public string M() where T : unmanaged => ""Child""; +}", symbolValidator: module => + { + var parentTypeParameter = module.ContainingAssembly.GetTypeByMetadataName("Parent").GetMethod("M").TypeParameters.Single(); + Assert.True(parentTypeParameter.HasValueTypeConstraint); + Assert.True(parentTypeParameter.HasUnmanagedTypeConstraint); + + AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, parentTypeParameter, module.ContainingAssembly.Name); + + var childTypeParameter = module.ContainingAssembly.GetTypeByMetadataName("Child").GetMethod("M").TypeParameters.Single(); + Assert.True(childTypeParameter.HasValueTypeConstraint); + Assert.True(childTypeParameter.HasUnmanagedTypeConstraint); + + AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, childTypeParameter, module.ContainingAssembly.Name); + }); + + CompileAndVerify(@" +class Program +{ + public static void Main() + { + System.Console.WriteLine(new Child().M()); + } +}", additionalRefs: new[] { reference.Compilation.EmitToImageReference() }, expectedOutput: "Child"); + } + + [Fact] + public void UnmanagedTypeModreqIsCopiedToOverrides_Interface_Implicit_Nonvirtual_Reference() + { + var parent = CompileAndVerify(@" +public interface Parent +{ + string M() where T : unmanaged; +}", symbolValidator: module => + { + var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Parent").GetMethod("M").TypeParameters.Single(); + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.True(typeParameter.HasUnmanagedTypeConstraint); + + AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, typeParameter, module.ContainingAssembly.Name); + }); + + + var child = CompileAndVerify(@" +public class Child : Parent +{ + public string M() where T : unmanaged => ""Child""; +}", additionalRefs: new[] { parent.Compilation.EmitToImageReference() }, symbolValidator: module => + { + var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Child").GetMethod("M").TypeParameters.Single(); + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.True(typeParameter.HasUnmanagedTypeConstraint); + + AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, typeParameter, module.ContainingAssembly.Name); + }); + + CompileAndVerify(@" +class Program +{ + public static void Main() + { + System.Console.WriteLine(new Child().M()); + } +}", additionalRefs: new[] { parent.Compilation.EmitToImageReference(), child.Compilation.EmitToImageReference() }, expectedOutput: "Child"); + } + + [Fact] + public void UnmanagedTypeModreqIsCopiedToOverrides_Interface_Implicit_Virtual_Compilation() + { + var reference = CompileAndVerify(@" +public interface Parent +{ + string M() where T : unmanaged; +} +public class Child : Parent +{ + public virtual string M() where T : unmanaged => ""Child""; +}", symbolValidator: module => + { + var parentTypeParameter = module.ContainingAssembly.GetTypeByMetadataName("Parent").GetMethod("M").TypeParameters.Single(); + Assert.True(parentTypeParameter.HasValueTypeConstraint); + Assert.True(parentTypeParameter.HasUnmanagedTypeConstraint); + + AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, parentTypeParameter, module.ContainingAssembly.Name); + + var childTypeParameter = module.ContainingAssembly.GetTypeByMetadataName("Child").GetMethod("M").TypeParameters.Single(); + Assert.True(childTypeParameter.HasValueTypeConstraint); + Assert.True(childTypeParameter.HasUnmanagedTypeConstraint); + + AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, childTypeParameter, module.ContainingAssembly.Name); + }); + + CompileAndVerify(@" +class Program +{ + public static void Main() + { + System.Console.WriteLine(new Child().M()); + } +}", additionalRefs: new[] { reference.Compilation.EmitToImageReference() }, expectedOutput: "Child"); + } + + [Fact] + public void UnmanagedTypeModreqIsCopiedToOverrides_Interface_Implicit_Virtual_Reference() + { + var parent = CompileAndVerify(@" +public interface Parent +{ + string M() where T : unmanaged; +}", symbolValidator: module => + { + var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Parent").GetMethod("M").TypeParameters.Single(); + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.True(typeParameter.HasUnmanagedTypeConstraint); + + AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, typeParameter, module.ContainingAssembly.Name); + }); + + + var child = CompileAndVerify(@" +public class Child : Parent +{ + public virtual string M() where T : unmanaged => ""Child""; +}", additionalRefs: new[] { parent.Compilation.EmitToImageReference() }, symbolValidator: module => + { + var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Child").GetMethod("M").TypeParameters.Single(); + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.True(typeParameter.HasUnmanagedTypeConstraint); + + AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, typeParameter, module.ContainingAssembly.Name); + }); + + CompileAndVerify(@" +class Program +{ + public static void Main() + { + System.Console.WriteLine(new Child().M()); + } +}", additionalRefs: new[] { parent.Compilation.EmitToImageReference(), child.Compilation.EmitToImageReference() }, expectedOutput: "Child"); + } + + [Fact] + public void UnmanagedTypeModreqIsCopiedToOverrides_Interface_Explicit_Compilation() + { + var reference = CompileAndVerify(@" +public interface Parent +{ + string M() where T : unmanaged; +} +public class Child : Parent +{ + string Parent.M() => ""Child""; +}", symbolValidator: module => + { + var parentTypeParameter = module.ContainingAssembly.GetTypeByMetadataName("Parent").GetMethod("M").TypeParameters.Single(); + Assert.True(parentTypeParameter.HasValueTypeConstraint); + Assert.True(parentTypeParameter.HasUnmanagedTypeConstraint); + + AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, parentTypeParameter, module.ContainingAssembly.Name); + + var childTypeParameter = module.ContainingAssembly.GetTypeByMetadataName("Child").GetMethod("Parent.M").TypeParameters.Single(); + Assert.True(childTypeParameter.HasValueTypeConstraint); + Assert.True(childTypeParameter.HasUnmanagedTypeConstraint); + + AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, childTypeParameter, module.ContainingAssembly.Name); + }); + + CompileAndVerify(@" +class Program +{ + public static void Main() + { + Parent obj = new Child(); + System.Console.WriteLine(obj.M()); + } +}", additionalRefs: new[] { reference.Compilation.EmitToImageReference() }, expectedOutput: "Child"); + } + + [Fact] + public void UnmanagedTypeModreqIsCopiedToOverrides_Interface_Explicit_Reference() + { + var parent = CompileAndVerify(@" +public interface Parent +{ + string M() where T : unmanaged; +}", symbolValidator: module => + { + var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Parent").GetMethod("M").TypeParameters.Single(); + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.True(typeParameter.HasUnmanagedTypeConstraint); + + AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, typeParameter, module.ContainingAssembly.Name); + }); + + + var child = CompileAndVerify(@" +public class Child : Parent +{ + string Parent.M() => ""Child""; +}", additionalRefs: new[] { parent.Compilation.EmitToImageReference() }, symbolValidator: module => + { + var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Child").GetMethod("Parent.M").TypeParameters.Single(); + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.True(typeParameter.HasUnmanagedTypeConstraint); + + AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, typeParameter, module.ContainingAssembly.Name); + }); + + CompileAndVerify(@" +class Program +{ + public static void Main() + { + Parent obj = new Child(); + System.Console.WriteLine(obj.M()); + } +}", additionalRefs: new[] { parent.Compilation.EmitToImageReference(), child.Compilation.EmitToImageReference() }, expectedOutput: "Child"); + } + + [Fact] + public void UnmanagedTypeModreqIsCopiedToLambda_Compilation() + { + CompileAndVerify(@" +public delegate T D() where T : unmanaged; +public class TestRef +{ + public static void Print(D lambda) where T : unmanaged + { + System.Console.WriteLine(lambda()); + } +} +public class Program +{ + static void Test(T arg) where T : unmanaged + { + TestRef.Print(() => arg); + } + + public static void Main() + { + Test(5); + } +}", + expectedOutput: "5", + options: TestOptions.ReleaseExe.WithMetadataImportOptions(MetadataImportOptions.All), + symbolValidator: module => + { + var delegateTypeParameter = module.ContainingAssembly.GetTypeByMetadataName("D`1").TypeParameters.Single(); + Assert.True(delegateTypeParameter.HasValueTypeConstraint); + Assert.True(delegateTypeParameter.HasUnmanagedTypeConstraint); + + AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, delegateTypeParameter, module.ContainingAssembly.Name); + + var lambdaTypeParameter = module.ContainingAssembly.GetTypeByMetadataName("Program").GetTypeMember("<>c__DisplayClass0_0").TypeParameters.Single(); + Assert.True(lambdaTypeParameter.HasValueTypeConstraint); + Assert.True(lambdaTypeParameter.HasUnmanagedTypeConstraint); + + AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, lambdaTypeParameter, module.ContainingAssembly.Name); + }); + } + + [Fact] + public void UnmanagedTypeModreqIsCopiedToLambda_Reference() + { + var reference = CompileAndVerify(@" +public delegate T D() where T : unmanaged; +public class TestRef +{ + public static void Print(D lambda) where T : unmanaged + { + System.Console.WriteLine(lambda()); + } +}", symbolValidator: module => + { + var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("D`1").TypeParameters.Single(); + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.True(typeParameter.HasUnmanagedTypeConstraint); + + AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, typeParameter, module.ContainingAssembly.Name); + }); + + + CompileAndVerify(@" +public class Program +{ + static void Test(T arg) where T : unmanaged + { + TestRef.Print(() => arg); + } + + public static void Main() + { + Test(5); + } +}", + expectedOutput: "5", + additionalRefs: new[] { reference.Compilation.EmitToImageReference() }, + options: TestOptions.ReleaseExe.WithMetadataImportOptions(MetadataImportOptions.All), + symbolValidator: module => + { + var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Program").GetTypeMember("<>c__DisplayClass0_0").TypeParameters.Single(); + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.True(typeParameter.HasUnmanagedTypeConstraint); + + AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, typeParameter, module.ContainingAssembly.Name); + }); + } + + [Fact] + public void DuplicateUnmanagedTypeInReferences() + { + var refCode = @" +namespace System.Runtime.InteropServices +{ + public class UnmanagedType {} +}"; + + var ref1 = CreateStandardCompilation(refCode).EmitToImageReference(); + var ref2 = CreateStandardCompilation(refCode).EmitToImageReference(); + + var user = @" +public class Test where T : unmanaged +{ +}"; + + CreateStandardCompilation(user, references: new[] { ref1, ref2 }).VerifyDiagnostics( + // (2,32): error CS0518: Predefined type 'System.Runtime.InteropServices.UnmanagedType' is not defined or imported + // public class Test where T : unmanaged + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "unmanaged").WithArguments("System.Runtime.InteropServices.UnmanagedType").WithLocation(2, 32)); + } + + [Fact] + public void UnmanagedConstraintWithClassConstraint_IL() + { + var ilSource = IsUnmanagedAttributeIL + @" +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .method public hidebysig instance void + M() cil managed + { + .param type T + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method TestRef::M + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method TestRef::.ctor + +}"; + + var reference = CompileIL(ilSource, prependDefaultHeader: false); + + var code = @" +public class Test +{ + public static void Main() + { + new TestRef().M(); + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (6,9): error CS0570: 'T' is not supported by the language + // new TestRef().M(); + Diagnostic(ErrorCode.ERR_BindToBogus, "new TestRef().M").WithArguments("T").WithLocation(6, 9)); + } + + [Fact] + public void UnmanagedConstraintWithConstructorConstraint_IL() + { + var ilSource = IsUnmanagedAttributeIL + @" +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .method public hidebysig instance void + M<.ctor (class [mscorlib]System.ValueType modreq([mscorlib]System.Runtime.InteropServices.UnmanagedType)) T>() cil managed + { + .param type T + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method TestRef::M + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method TestRef::.ctor + +}"; + + var reference = CompileIL(ilSource, prependDefaultHeader: false); + + var code = @" +public class Test +{ + public static void Main() + { + new TestRef().M(); + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (6,9): error CS0570: 'T' is not supported by the language + // new TestRef().M(); + Diagnostic(ErrorCode.ERR_BindToBogus, "new TestRef().M").WithArguments("T").WithLocation(6, 9)); + } + + [Fact] + public void UnmanagedConstraintWithTypeConstraint_IL() + { + var ilSource = IsUnmanagedAttributeIL + @" +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .method public hidebysig instance void + M() cil managed + { + .param type T + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method TestRef::M + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method TestRef::.ctor + +}"; + + var reference = CompileIL(ilSource, prependDefaultHeader: false); + + var code = @" +public class Test +{ + public static void Main() + { + new TestRef().M(); + } +}"; + + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (6,9): error CS0570: 'T' is not supported by the language + // new TestRef().M(); + Diagnostic(ErrorCode.ERR_BindToBogus, "new TestRef().M").WithArguments("T").WithLocation(6, 9)); + } + + private const string IsUnmanagedAttributeIL = @" +.assembly extern mscorlib +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) + .ver 4:0:0:0 +} +.assembly Test +{ + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module Test.dll +.imagebase 0x10000000 +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + +.class private auto ansi sealed beforefieldinit Microsoft.CodeAnalysis.EmbeddedAttribute + extends [mscorlib]System.Attribute +{ + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void Microsoft.CodeAnalysis.EmbeddedAttribute::.ctor() = ( 01 00 00 00 ) + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Attribute::.ctor() + IL_0006: nop + IL_0007: ret + } +} + +.class private auto ansi sealed beforefieldinit System.Runtime.CompilerServices.IsUnmanagedAttribute + extends [mscorlib]System.Attribute +{ + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void Microsoft.CodeAnalysis.EmbeddedAttribute::.ctor() = ( 01 00 00 00 ) + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Attribute::.ctor() + IL_0006: nop + IL_0007: ret + } +} +"; + } +} diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs index bd54debe3a1ee..efb4f15ca31b5 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs @@ -3,6 +3,8 @@ using System; using System.Linq; using Microsoft.CodeAnalysis.CSharp.Symbols; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.CSharp.UnitTests; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; @@ -755,7 +757,7 @@ public void M() where U : class, System.Delegate // var c = new Test(); // reference type Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "string").WithArguments("Test", "System.Delegate", "T", "string").WithLocation(9, 26)); } - + [Fact] public void DelegateConstraint_Reference_Constructor() { @@ -1539,5 +1541,875 @@ class B : A where T : System.Delegate { }"; // class B : A where T : System.Delegate { } Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "B").WithArguments("A", "System.MulticastDelegate", "T", "T").WithLocation(3, 7)); } + + [Fact] + public void UnmanagedConstraint_Compilation_Alone_Type() + { + CreateStandardCompilation(@" +public class Test where T : unmanaged +{ +} +public struct GoodType { public int I; } +public struct BadType { public string S; } +public class Test2 +{ + public void M() where U : unmanaged + { + var a = new Test(); // unmanaged struct + var b = new Test(); // managed struct + var c = new Test(); // reference type + var d = new Test(); // value type + var e = new Test(); // generic type constrained to unmanaged + var f = new Test(); // unconstrained generic type + } +}").VerifyDiagnostics( + // (12,26): error CS8375: The type 'BadType' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test' + // var b = new Test(); // managed struct + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "BadType").WithArguments("Test", "T", "BadType").WithLocation(12, 26), + // (13,26): error CS8375: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test' + // var c = new Test(); // reference type + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "string").WithArguments("Test", "T", "string").WithLocation(13, 26), + // (16,26): error CS8375: The type 'W' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test' + // var f = new Test(); // unconstrained generic type + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "W").WithArguments("Test", "T", "W").WithLocation(16, 26)); + } + + [Fact] + public void UnmanagedConstraint_Compilation_Alone_Method() + { + CreateStandardCompilation(@" +public class Test +{ + public int M() where T : unmanaged => 0; +} +public struct GoodType { public int I; } +public struct BadType { public string S; } +public class Test2 +{ + public void M() where U : unmanaged + { + var a = new Test().M(); // unmanaged struct + var b = new Test().M(); // managed struct + var c = new Test().M(); // reference type + var d = new Test().M(); // value type + var e = new Test().M(); // generic type constrained to unmanaged + var f = new Test().M(); // unconstrained generic type + } +}").VerifyDiagnostics( + // (13,17): error CS8375: The type 'BadType' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' + // var b = new Test().M(); // managed struct + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "new Test().M").WithArguments("Test.M()", "T", "BadType").WithLocation(13, 17), + // (14,17): error CS8375: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' + // var c = new Test().M(); // reference type + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "new Test().M").WithArguments("Test.M()", "T", "string").WithLocation(14, 17), + // (17,17): error CS8375: The type 'W' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' + // var f = new Test().M(); // unconstrained generic type + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "new Test().M").WithArguments("Test.M()", "T", "W").WithLocation(17, 17)); + } + + [Fact] + public void UnmanagedConstraint_Compilation_Alone_Delegate() + { + CreateStandardCompilation(@" +public delegate void D() where T : unmanaged; +public struct GoodType { public int I; } +public struct BadType { public string S; } +public abstract class Test2 where U : unmanaged +{ + public abstract D a(); // unmanaged struct + public abstract D b(); // managed struct + public abstract D c(); // reference type + public abstract D d(); // value type + public abstract D e(); // generic type constrained to unmanaged + public abstract D f(); // unconstrained generic type +}").VerifyDiagnostics( + // (8,32): error CS8375: The type 'BadType' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'D' + // public abstract D b(); // managed struct + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "b").WithArguments("D", "T", "BadType").WithLocation(8, 32), + // (9,31): error CS8375: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'D' + // public abstract D c(); // reference type + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "c").WithArguments("D", "T", "string").WithLocation(9, 31), + // (12,26): error CS8375: The type 'W' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'D' + // public abstract D f(); // unconstrained generic type + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "f").WithArguments("D", "T", "W").WithLocation(12, 26)); + } + + [Fact] + public void UnmanagedConstraint_Compilation_Alone_LocalFunction() + { + CreateStandardCompilation(@" +public abstract class Test2 where U : unmanaged +{ + public void M() + { + void local() where T : unmanaged { } + + local(); + } +}").VerifyDiagnostics( + // (6,20): error CS8376: Using unmanaged constraint on local functions type parameters is not supported. + // void local() where T : unmanaged { } + Diagnostic(ErrorCode.ERR_UnmanagedConstraintWithLocalFunctions, "T").WithLocation(6, 20)); + } + + [Fact] + public void UnmanagedConstraint_Compilation_ReferenceType() + { + CreateStandardCompilation("public class Test where T : class, unmanaged {}").VerifyDiagnostics( + // (1,39): error CS8374: The 'unmanaged' constraint cannot be specified with other constraints. + // public class Test where T : class, unmanaged {} + Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeAlone, "unmanaged").WithLocation(1, 39)); + } + + [Fact] + public void UnmanagedConstraint_Compilation_ValueType() + { + CreateStandardCompilation("public class Test where T : struct, unmanaged {}").VerifyDiagnostics( + // (1,40): error CS8374: The 'unmanaged' constraint cannot be specified with other constraints. + // public class Test where T : struct, unmanaged {} + Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeAlone, "unmanaged").WithLocation(1, 40)); + } + + [Fact] + public void UnmanagedConstraint_Compilation_Constructor() + { + CreateStandardCompilation("public class Test where T : unmanaged, new() {}").VerifyDiagnostics( + // (1,43): error CS8373: The 'new()' constraint cannot be used with the 'unmanaged' constraint + // public class Test where T : unmanaged, new() {} + Diagnostic(ErrorCode.ERR_NewBoundWithUnmanaged, "new").WithLocation(1, 43)); + } + + [Fact] + public void UnmanagedConstraint_Compilation_AnotherType_Before() + { + CreateStandardCompilation("public class Test where T : unmanaged, System.Exception { }").VerifyDiagnostics( + // (1,43): error CS8374: The 'unmanaged' constraint cannot be specified with other constraints. + // public class Test where T : unmanaged, System.Exception { } + Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeAlone, "System.Exception").WithLocation(1, 43)); + } + + [Fact] + public void UnmanagedConstraint_Compilation_AnotherType_After() + { + CreateStandardCompilation("public class Test where T : System.Exception, unmanaged { }").VerifyDiagnostics( + // (1,50): error CS8374: The 'unmanaged' constraint cannot be specified with other constraints. + // public class Test where T : System.Exception, unmanaged { } + Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeAlone, "unmanaged").WithLocation(1, 50)); + } + + [Fact] + public void UnmanagedConstraint_Compilation_AnotherParameter_After() + { + CreateStandardCompilation("public class Test where T : U, unmanaged { }").VerifyDiagnostics( + // (1,38): error CS8374: The 'unmanaged' constraint cannot be specified with other constraints. + // public class Test where T : U, unmanaged { } + Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeAlone, "unmanaged").WithLocation(1, 38)); + } + + [Fact] + public void UnmanagedConstraint_Compilation_AnotherParameter_Before() + { + CreateStandardCompilation("public class Test where T : unmanaged, U { }").VerifyDiagnostics( + // (1,46): error CS8374: The 'unmanaged' constraint cannot be specified with other constraints. + // public class Test where T : unmanaged, U { } + Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeAlone, "U").WithLocation(1, 46)); + } + + [Fact] + public void UnmanagedConstraint_UnmanagedEnumNotAvailable() + { + CreateCompilation(@" +namespace System +{ + public class Object {} + public class Void {} + public class ValueType {} +} +public class Test where T : unmanaged +{ +}").VerifyDiagnostics( + // (8,32): error CS0518: Predefined type 'System.Runtime.InteropServices.UnmanagedType' is not defined or imported + // public class Test where T : unmanaged + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "unmanaged").WithArguments("System.Runtime.InteropServices.UnmanagedType").WithLocation(8, 32)); + } + + [Fact] + public void UnmanagedConstraint_ValueTypeNotAvailable() + { + CreateCompilation(@" +namespace System +{ + public class Object {} + public class Void {} + public class Enum {} + public class Int32 {} + namespace Runtime + { + namespace InteropServices + { + public enum UnmanagedType {} + } + } +} +public class Test where T : unmanaged +{ +}").VerifyDiagnostics( + // (16,32): error CS0518: Predefined type 'System.ValueType' is not defined or imported + // public class Test where T : unmanaged + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "unmanaged").WithArguments("System.ValueType").WithLocation(16, 32)); + } + + [Fact] + public void UnmanagedConstraint_Reference_Alone_Type() + { + var reference = CreateStandardCompilation(@" +public class Test where T : unmanaged +{ +}").EmitToImageReference(); + + var code = @" +public struct GoodType { public int I; } +public struct BadType { public string S; } +public class Test2 +{ + public void M() where U : unmanaged + { + var a = new Test(); // unmanaged struct + var b = new Test(); // managed struct + var c = new Test(); // reference type + var d = new Test(); // value type + var e = new Test(); // generic type constrained to unmanaged + var f = new Test(); // unconstrained generic type + } +}"; + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (9,26): error CS8375: The type 'BadType' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test' + // var b = new Test(); // managed struct + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "BadType").WithArguments("Test", "T", "BadType").WithLocation(9, 26), + // (10,26): error CS8375: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test' + // var c = new Test(); // reference type + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "string").WithArguments("Test", "T", "string").WithLocation(10, 26), + // (13,26): error CS8375: The type 'W' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test' + // var f = new Test(); // unconstrained generic type + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "W").WithArguments("Test", "T", "W").WithLocation(13, 26)); + } + + [Fact] + public void UnmanagedConstraint_Reference_Alone_Method() + { + var reference = CreateStandardCompilation(@" +public class Test +{ + public int M() where T : unmanaged => 0; +}").EmitToImageReference(); + + var code = @" +public struct GoodType { public int I; } +public struct BadType { public string S; } +public class Test2 +{ + public void M() where U : unmanaged + { + var a = new Test().M(); // unmanaged struct + var b = new Test().M(); // managed struct + var c = new Test().M(); // reference type + var d = new Test().M(); // value type + var e = new Test().M(); // generic type constrained to unmanaged + var f = new Test().M(); // unconstrained generic type + } +}"; + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (9,17): error CS8375: The type 'BadType' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' + // var b = new Test().M(); // managed struct + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "new Test().M").WithArguments("Test.M()", "T", "BadType").WithLocation(9, 17), + // (10,17): error CS8375: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' + // var c = new Test().M(); // reference type + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "new Test().M").WithArguments("Test.M()", "T", "string").WithLocation(10, 17), + // (13,17): error CS8375: The type 'W' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' + // var f = new Test().M(); // unconstrained generic type + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "new Test().M").WithArguments("Test.M()", "T", "W").WithLocation(13, 17)); + } + + [Fact] + public void UnmanagedConstraint_Reference_Alone_Delegate() + { + var reference = CreateStandardCompilation(@" +public delegate void D() where T : unmanaged; +").EmitToImageReference(); + + var code = @" +public struct GoodType { public int I; } +public struct BadType { public string S; } +public abstract class Test2 where U : unmanaged +{ + public abstract D a(); // unmanaged struct + public abstract D b(); // managed struct + public abstract D c(); // reference type + public abstract D d(); // value type + public abstract D e(); // generic type constrained to unmanaged + public abstract D f(); // unconstrained generic type +}"; + CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (7,32): error CS8375: The type 'BadType' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'D' + // public abstract D b(); // managed struct + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "b").WithArguments("D", "T", "BadType").WithLocation(7, 32), + // (8,31): error CS8375: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'D' + // public abstract D c(); // reference type + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "c").WithArguments("D", "T", "string").WithLocation(8, 31), + // (11,26): error CS8375: The type 'W' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'D' + // public abstract D f(); // unconstrained generic type + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "f").WithArguments("D", "T", "W").WithLocation(11, 26)); + } + + [Fact] + public void UnmanagedConstraint_Before_7_3() + { + var code = @" +public class Test where T : unmanaged +{ +}"; + + CreateStandardCompilation(code, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp7_2)).VerifyDiagnostics( + // (2,32): error CS8320: Feature 'unmanaged generic type constraints' is not available in C# 7.2. Please use language version 7.3 or greater. + // public class Test where T : unmanaged + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "unmanaged").WithArguments("unmanaged generic type constraints", "7.3").WithLocation(2, 32)); + } + + [Fact] + public void UnmanagedConstraint_IsReflectedinSymbols_Alone_Type() + { + var code = "public class Test where T : unmanaged { }"; + + Action validator = module => + { + var typeParameter = module.GlobalNamespace.GetTypeMember("Test").TypeParameters.Single(); + Assert.True(typeParameter.HasUnmanagedTypeConstraint); + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.False(typeParameter.HasReferenceTypeConstraint); + Assert.False(typeParameter.HasConstructorConstraint); + Assert.Empty(typeParameter.ConstraintTypes()); + }; + + CompileAndVerify(code, sourceSymbolValidator: validator, symbolValidator: validator); + } + + [Fact] + public void UnmanagedConstraint_IsReflectedinSymbols_Alone_Method() + { + var code = @" +public class Test +{ + public void M() where T : unmanaged {} +}"; + + Action validator = module => + { + var typeParameter = module.GlobalNamespace.GetTypeMember("Test").GetMethod("M").TypeParameters.Single(); + Assert.True(typeParameter.HasUnmanagedTypeConstraint); + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.False(typeParameter.HasReferenceTypeConstraint); + Assert.False(typeParameter.HasConstructorConstraint); + Assert.Empty(typeParameter.ConstraintTypes()); + }; + + CompileAndVerify(code, sourceSymbolValidator: validator, symbolValidator: validator); + } + + [Fact] + public void UnmanagedConstraint_IsReflectedinSymbols_Alone_Delegate() + { + var code = "public delegate void D() where T : unmanaged;"; + + Action validator = module => + { + var typeParameter = module.GlobalNamespace.GetTypeMember("D").TypeParameters.Single(); + Assert.True(typeParameter.HasUnmanagedTypeConstraint); + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.False(typeParameter.HasReferenceTypeConstraint); + Assert.False(typeParameter.HasConstructorConstraint); + Assert.Empty(typeParameter.ConstraintTypes()); + }; + + CompileAndVerify(code, sourceSymbolValidator: validator, symbolValidator: validator); + } + + [Fact] + public void UnmanagedConstraint_EnforcedInInheritanceChain_Downwards_Source() + { + CreateStandardCompilation(@" +struct Test +{ + public string RefMember { get; set; } +} +public abstract class A +{ + public abstract void M() where T : unmanaged; +} +public class B : A +{ + public override void M() { } + + public void Test() + { + this.M(); + this.M(); + this.M(); + } +}").VerifyDiagnostics( + // (17,9): error CS8375: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'B.M()' + // this.M(); + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "this.M").WithArguments("B.M()", "T", "string").WithLocation(17, 9), + // (18,9): error CS8375: The type 'Test' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'B.M()' + // this.M(); + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "this.M").WithArguments("B.M()", "T", "Test").WithLocation(18, 9)); + } + + [Fact] + public void UnmanagedConstraint_EnforcedInInheritanceChain_Downwards_Reference() + { + var reference = CreateStandardCompilation(@" +public abstract class A +{ + public abstract void M() where T : unmanaged; +}").EmitToImageReference(); + + CreateStandardCompilation(@" +struct Test +{ + public string RefMember { get; set; } +} +public class B : A +{ + public override void M() { } + + public void Test() + { + this.M(); + this.M(); + this.M(); + } +}", references: new[] { reference }).VerifyDiagnostics( + // (13,9): error CS8375: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'B.M()' + // this.M(); + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "this.M").WithArguments("B.M()", "T", "string").WithLocation(13, 9), + // (14,9): error CS8375: The type 'Test' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'B.M()' + // this.M(); + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "this.M").WithArguments("B.M()", "T", "Test").WithLocation(14, 9)); + } + + [Fact] + public void UnmanagedConstraint_EnforcedInInheritanceChain_Upwards_Source() + { + CreateStandardCompilation(@" +public abstract class A +{ + public abstract void M(); +} +public class B : A +{ + public override void M() where T : unmanaged { } +}").VerifyDiagnostics( + // (8,33): error CS0460: Constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly + // public override void M() where T : unmanaged { } + Diagnostic(ErrorCode.ERR_OverrideWithConstraints, "where").WithLocation(8, 33)); + } + + [Fact] + public void UnmanagedConstraint_EnforcedInInheritanceChain_Upwards_Reference() + { + var reference = CreateStandardCompilation(@" +public abstract class A +{ + public abstract void M(); +}").EmitToImageReference(); + + CreateStandardCompilation(@" +public class B : A +{ + public override void M() where T : unmanaged { } +}", references: new[] { reference }).VerifyDiagnostics( + // (4,33): error CS0460: Constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly + // public override void M() where T : unmanaged { } + Diagnostic(ErrorCode.ERR_OverrideWithConstraints, "where").WithLocation(4, 33)); + } + + [Fact] + public void UnmanagedConstraints_PointerOperations_Invalid() + { + CreateStandardCompilation(@" +class Test +{ + void M(T arg) where T : unmanaged + { + } + void N() + { + M(""test""); + } +}").VerifyDiagnostics( + // (9,9): error CS8375: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M(T)' + // M("test"); + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "M").WithArguments("Test.M(T)", "T", "string").WithLocation(9, 9)); + } + + [Theory] + [InlineData("(sbyte)1", "System.SByte", 1)] + [InlineData("(byte)1", "System.Byte", 1)] + [InlineData("(short)1", "System.Int16", 2)] + [InlineData("(ushort)1", "System.UInt16", 2)] + [InlineData("(int)1", "System.Int32", 4)] + [InlineData("(uint)1", "System.UInt32", 4)] + [InlineData("(long)1", "System.Int64", 8)] + [InlineData("(ulong)1", "System.UInt64", 8)] + [InlineData("'a'", "System.Char", 2)] + [InlineData("(float)1", "System.Single", 4)] + [InlineData("(double)1", "System.Double", 8)] + [InlineData("(decimal)1", "System.Decimal", 16)] + [InlineData("false", "System.Boolean", 1)] + [InlineData("E.A", "E", 4)] + [InlineData("new S { a = 1, b = 2, c = 3 }", "S", 12)] + public void UnmanagedConstraints_PointerOperations_SimpleTypes(string arg, string type, int size) + { + CompileAndVerify(@" +enum E +{ + A +} +struct S +{ + public int a; + public int b; + public int c; +} +unsafe class Test +{ + static T* M(T arg) where T : unmanaged + { + T* ptr = &arg; + System.Console.WriteLine(ptr->GetType()); // method access + System.Console.WriteLine(sizeof(T)); // sizeof operator + + T* ar = stackalloc T [10]; + return ar; + } + static void Main() + { + M(" + arg + @"); + } +}", + options: TestOptions.UnsafeReleaseExe, expectedOutput: string.Join(Environment.NewLine, type, size)).VerifyIL("Test.M", @" +{ + // Code size 43 (0x2b) + .maxstack 2 + IL_0000: ldarga.s V_0 + IL_0002: conv.u + IL_0003: constrained. ""T"" + IL_0009: callvirt ""System.Type object.GetType()"" + IL_000e: call ""void System.Console.WriteLine(object)"" + IL_0013: sizeof ""T"" + IL_0019: call ""void System.Console.WriteLine(int)"" + IL_001e: ldc.i4.s 10 + IL_0020: conv.u + IL_0021: sizeof ""T"" + IL_0027: mul.ovf.un + IL_0028: localloc + IL_002a: ret +}"); + } + + [Fact] + public void UnmanagedConstraints_NestedStructs_Flat() + { + CompileAndVerify(@" +struct TestData +{ + public int A; + public TestData(int a) + { + A = a; + } +} +unsafe class Test +{ + public static void Main() + { + N(); + } + static void N() where T : unmanaged + { + System.Console.WriteLine(sizeof(T)); + } +}", options: TestOptions.UnsafeReleaseExe, expectedOutput: "4"); + } + + [Fact] + public void UnmanagedConstraints_NestedStructs_Nested() + { + CompileAndVerify(@" +struct InnerTestData +{ + public int B; + public InnerTestData(int b) + { + B = b; + } +} +struct TestData +{ + public int A; + public InnerTestData B; + public TestData(int a, int b) + { + A = a; + B = new InnerTestData(b); + } +} +unsafe class Test +{ + public static void Main() + { + N(); + } + static void N() where T : unmanaged + { + System.Console.WriteLine(sizeof(T)); + } +}", options: TestOptions.UnsafeReleaseExe, expectedOutput: "8"); + } + + [Fact] + public void UnmanagedConstraints_NestedStructs_Error() + { + CreateStandardCompilation(@" +struct InnerTestData +{ + public string B; + public InnerTestData(string b) + { + B = b; + } +} +struct TestData +{ + public int A; + public InnerTestData B; + public TestData(int a, string b) + { + A = a; + B = new InnerTestData(b); + } +} +class Test +{ + public static void Main() + { + N(); + } + static void N() where T : unmanaged + { + } +}").VerifyDiagnostics( + // (24,9): error CS8375: The type 'TestData' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.N()' + // N(); + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "N").WithArguments("Test.N()", "T", "TestData").WithLocation(24, 9)); + } + + [Fact] + public void UnmanagedConstraints_ExistingUnmanagedKeywordType_InScope() + { + CompileAndVerify(@" +class unmanaged +{ + public void Print() + { + System.Console.WriteLine(""success""); + } +} +class Test +{ + public static void Main() + { + M(new unmanaged()); + } + static void M(T arg) where T : unmanaged + { + arg.Print(); + } +}", expectedOutput: "success"); + } + + [Fact] + public void UnmanagedConstraints_ExistingUnmanagedKeywordType_OutOfScope() + { + CreateStandardCompilation(@" +namespace hidden +{ + class unmanaged + { + public void Print() + { + System.Console.WriteLine(""success""); + } + } +} +class Test +{ + public static void Main() + { + M(""test""); + } + static void M(T arg) where T : unmanaged + { + arg.Print(); + } +}").VerifyDiagnostics( + // (16,9): error CS8375: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M(T)' + // M("test"); + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "M").WithArguments("Test.M(T)", "T", "string").WithLocation(16, 9), + // (20,13): error CS1061: 'T' does not contain a definition for 'Print' and no extension method 'Print' accepting a first argument of type 'T' could be found (are you missing a using directive or an assembly reference?) + // arg.Print(); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Print").WithArguments("T", "Print").WithLocation(20, 13)); + } + + [Fact] + public void UnmanagedConstraints_UnmanagedIsValidForStructConstraint_Methods() + { + CompileAndVerify(@" +class Program +{ + static void A(T arg) where T : struct + { + System.Console.WriteLine(arg); + } + static void B(T arg) where T : unmanaged + { + A(arg); + } + static void Main() + { + B(5); + } +}", expectedOutput: "5"); + } + + [Fact] + public void UnmanagedConstraints_UnmanagedIsValidForStructConstraint_Types() + { + CompileAndVerify(@" +class A where T : struct +{ + public void M(T arg) + { + System.Console.WriteLine(arg); + } +} +class B : A where T : unmanaged +{ +} +class Program +{ + static void Main() + { + new B().M(5); + } +}", expectedOutput: "5"); + } + + [Fact] + public void UnmanagedConstraints_UnmanagedIsValidForStructConstraint_Interfaces() + { + CompileAndVerify(@" +interface A where T : struct +{ + void M(T arg); +} +class B : A where T : unmanaged +{ + public void M(T arg) + { + System.Console.WriteLine(arg); + } +} +class Program +{ + static void Main() + { + new B().M(5); + } +}", expectedOutput: "5"); + } + + [Fact] + public void UnmanagedConstraints_PointerTypeSubstitution() + { + var compilation = CreateStandardCompilation(@" +unsafe public class Test +{ + public T* M() where T : unmanaged => throw null; + + public void N() + { + var result = M(); + } +}", options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(); + + var tree = compilation.SyntaxTrees.Single(); + var model = compilation.GetSemanticModel(tree, ignoreAccessibility: true); + + var value = ((VariableDeclaratorSyntax)tree.FindNodeOrTokenByKind(SyntaxKind.VariableDeclarator)).Initializer.Value; + Assert.Equal("M()", value.ToFullString()); + + var symbol = (MethodSymbol)model.GetSymbolInfo(value).Symbol; + Assert.Equal("System.Int32*", symbol.ReturnType.ToTestDisplayString()); + } + + [Fact] + public void UnmanagedConstraints_CannotConstraintToTypeParameterConstrainedByUnmanaged() + { + CreateStandardCompilation(@" +class Test where U : unmanaged +{ + void M() where T : U + { + } +}").VerifyDiagnostics( + // (4,12): error CS8377: Type parameter 'U' has the 'unmanaged' constraint so 'U' cannot be used as a constraint for 'T' + // void M() where T : U + Diagnostic(ErrorCode.ERR_ConWithUnmanagedCon, "T").WithArguments("T", "U").WithLocation(4, 12)); + } + + [Fact] + public void UnmanagedConstraints_UnmanagedAsTypeConstraintName() + { + CreateStandardCompilation(@" +class Test where unmanaged : System.IDisposable +{ + void M(T arg) where T : unmanaged + { + arg.Dispose(); + arg.NonExistentMethod(); + } +}").VerifyDiagnostics( + // (7,13): error CS1061: 'T' does not contain a definition for 'NonExistentMethod' and no extension method 'NonExistentMethod' accepting a first argument of type 'T' could be found (are you missing a using directive or an assembly reference?) + // arg.NonExistentMethod(); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "NonExistentMethod").WithArguments("T", "NonExistentMethod").WithLocation(7, 13)); + } + + [Fact] + public void UnmanagedConstraints_CircularReferenceToUnmanagedTypeWillBindSuccessfully() + { + CreateStandardCompilation(@" +public unsafe class C where U : unmanaged +{ + public void M1() where T : T* { } + public void M2() where T : U* { } +}", options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics( + // (5,35): error CS0706: Invalid constraint type. A type used as a constraint must be an interface, a non-sealed class or a type parameter. + // public void M2() where T : U* { } + Diagnostic(ErrorCode.ERR_BadConstraintType, "U*").WithLocation(5, 35), + // (4,35): error CS0706: Invalid constraint type. A type used as a constraint must be an interface, a non-sealed class or a type parameter. + // public void M1() where T : T* { } + Diagnostic(ErrorCode.ERR_BadConstraintType, "T*").WithLocation(4, 35)); + } } } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/UsingStatementTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/UsingStatementTests.cs index 91fe0e4622985..d8c5e83e79800 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/UsingStatementTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/UsingStatementTests.cs @@ -642,6 +642,11 @@ public static void Main() public void MissingIDisposable() { var source = @" +namespace System +{ + public class Object { } + public class Void { } +} class C { void M() @@ -651,30 +656,12 @@ void M() }"; CreateCompilation(source).VerifyDiagnostics( - // Related to the using statement: - - // (6,30): warning CS0642: Possible mistaken empty statement + // (11,20): error CS0815: Cannot assign to an implicitly-typed variable // using (var v = null) ; - Diagnostic(ErrorCode.WRN_PossibleMistakenNullStatement, ";"), - - // Cascading from the lack of mscorlib: - - // (2,7): error CS0518: Predefined type 'System.Object' is not defined or imported - // class C - Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "C").WithArguments("System.Object"), - // (4,5): error CS0518: Predefined type 'System.Void' is not defined or imported - // void M() - Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "void").WithArguments("System.Void"), - // (6,16): error CS0518: Predefined type 'System.Object' is not defined or imported - // using (var v = null) ; - Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "var").WithArguments("System.Object"), - // (6,20): error CS0815: Cannot assign to an implicitly-typed variable + Diagnostic(ErrorCode.ERR_ImplicitlyTypedVariableAssignedBadValue, "v = null").WithArguments("").WithLocation(11, 20), + // (11,30): warning CS0642: Possible mistaken empty statement // using (var v = null) ; - Diagnostic(ErrorCode.ERR_ImplicitlyTypedVariableAssignedBadValue, "v = null").WithArguments(""), - // (2,7): error CS1729: 'object' does not contain a constructor that takes 0 arguments - // class C - Diagnostic(ErrorCode.ERR_BadCtorArgCount, "C").WithArguments("object", "0") - ); + Diagnostic(ErrorCode.WRN_PossibleMistakenNullStatement, ";").WithLocation(11, 30)); } diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs index 14cdf74ae1b6a..7d3983e598f17 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs @@ -562,6 +562,7 @@ public void AllWellKnownTypes() case WellKnownType.System_Runtime_CompilerServices_IsByRefLikeAttribute: case WellKnownType.System_Span_T: case WellKnownType.System_ReadOnlySpan_T: + case WellKnownType.System_Runtime_CompilerServices_IsUnmanagedAttribute: // Not yet in the platform. case WellKnownType.Microsoft_CodeAnalysis_Runtime_Instrumentation: // Not always available. @@ -871,6 +872,7 @@ public void AllWellKnownTypeMembers() case WellKnownMember.Microsoft_CodeAnalysis_Runtime_Instrumentation__CreatePayloadForMethodsSpanningMultipleFiles: case WellKnownMember.System_Runtime_CompilerServices_IsReadOnlyAttribute__ctor: case WellKnownMember.System_Runtime_CompilerServices_IsByRefLikeAttribute__ctor: + case WellKnownMember.System_Runtime_CompilerServices_IsUnmanagedAttribute__ctor: // Not always available. continue; } diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs index 5e927a546c1cb..f70ba49b9a5d8 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs @@ -853,24 +853,26 @@ void M() }"; CreateStandardCompilation(source).VerifyDiagnostics( // (2,15): error CS0706: Invalid constraint type. A type used as a constraint must be an interface, a non-sealed class or a type parameter. + // where U : T* Diagnostic(ErrorCode.ERR_BadConstraintType, "T*").WithLocation(2, 15), // (3,15): error CS0706: Invalid constraint type. A type used as a constraint must be an interface, a non-sealed class or a type parameter. + // where V : T[] Diagnostic(ErrorCode.ERR_BadConstraintType, "T[]").WithLocation(3, 15), // (9,19): error CS0706: Invalid constraint type. A type used as a constraint must be an interface, a non-sealed class or a type parameter. + // where U : T* Diagnostic(ErrorCode.ERR_BadConstraintType, "T*").WithLocation(9, 19), // (10,19): error CS0706: Invalid constraint type. A type used as a constraint must be an interface, a non-sealed class or a type parameter. + // where V : T[]; Diagnostic(ErrorCode.ERR_BadConstraintType, "T[]").WithLocation(10, 19), // CONSIDER: Dev10 doesn't report these cascading errors. // (2,15): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context - Diagnostic(ErrorCode.ERR_UnsafeNeeded, "T*"), - // (2,15): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('T') - Diagnostic(ErrorCode.ERR_ManagedAddr, "T*").WithArguments("T"), + // where U : T* + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "T*").WithLocation(2, 15), // (9,19): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context - Diagnostic(ErrorCode.ERR_UnsafeNeeded, "T*"), - // (9,19): error CS0208: Cannot take the address of, get the size of, or declare a pointer to a managed type ('T') - Diagnostic(ErrorCode.ERR_ManagedAddr, "T*").WithArguments("T")); + // where U : T* + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "T*").WithLocation(9, 19)); } [Fact] diff --git a/src/Compilers/Core/Portable/MetadataReader/MetadataDecoder.cs b/src/Compilers/Core/Portable/MetadataReader/MetadataDecoder.cs index 01478078c5a50..5d1a7f24ae2f0 100644 --- a/src/Compilers/Core/Portable/MetadataReader/MetadataDecoder.cs +++ b/src/Compilers/Core/Portable/MetadataReader/MetadataDecoder.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; -using System.IO; using System.Reflection.Metadata; using System.Runtime.InteropServices; using Microsoft.CodeAnalysis.PooledObjects; @@ -714,6 +713,9 @@ private ImmutableArray> DecodeModifiersOrThrow( case AllowedRequiredModifierType.System_Runtime_CompilerServices_Volatile: isAllowed = IsAcceptedVolatileModifierType(type); break; + case AllowedRequiredModifierType.System_Runtime_InteropServices_UnmanagedType: + isAllowed = IsAcceptedUnmanagedTypeModifierType(type); + break; } if (isAllowed) @@ -875,6 +877,58 @@ internal ImmutableArray> DecodeLocalSignatureOrThrow(ref B } } + internal TypeSymbol DecodeGenericParameterConstraint(EntityHandle token, out bool isUnmanagedConstraint) + { + isUnmanagedConstraint = false; + + switch (token.Kind) + { + case HandleKind.TypeSpecification: + { + try + { + var memoryReader = this.Module.GetTypeSpecificationSignatureReaderOrThrow((TypeSpecificationHandle)token); + var modifiers = DecodeModifiersOrThrow(ref memoryReader, AllowedRequiredModifierType.System_Runtime_InteropServices_UnmanagedType, out var typeCode, out var modReqFound); + var type = DecodeTypeOrThrow(ref memoryReader, typeCode, out _); + + if (modReqFound) + { + if (type.SpecialType == SpecialType.System_ValueType) + { + isUnmanagedConstraint = true; + } + else + { + return GetUnsupportedMetadataTypeSymbol(); + } + } + else if (!modifiers.IsDefaultOrEmpty) + { + // Optional modifiers (also, other required parameters) not allowed on generic parameters + // http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/528856 + return GetUnsupportedMetadataTypeSymbol(); + } + + return type; + } + catch (BadImageFormatException mrEx) + { + return GetUnsupportedMetadataTypeSymbol(mrEx); + } + catch (UnsupportedSignatureContent) + { + return GetUnsupportedMetadataTypeSymbol(); + } + } + case HandleKind.TypeReference: + return GetTypeOfTypeRef((TypeReferenceHandle)token, out _); + case HandleKind.TypeDefinition: + return GetTypeOfTypeDef((TypeDefinitionHandle)token); + default: + return GetUnsupportedMetadataTypeSymbol(); + } + } + /// If the encoded local variable type is invalid. /// An exception from metadata reader. internal LocalInfo DecodeLocalVariableOrThrow(ref BlobReader signatureReader) @@ -2393,6 +2447,7 @@ private enum AllowedRequiredModifierType None, System_Runtime_CompilerServices_Volatile, System_Runtime_InteropServices_InAttribute, + System_Runtime_InteropServices_UnmanagedType, } } } diff --git a/src/Compilers/Core/Portable/MetadataReader/PEModule.cs b/src/Compilers/Core/Portable/MetadataReader/PEModule.cs index c016b6ddf73c2..3b47c7c00ff8b 100644 --- a/src/Compilers/Core/Portable/MetadataReader/PEModule.cs +++ b/src/Compilers/Core/Portable/MetadataReader/PEModule.cs @@ -944,6 +944,11 @@ internal bool HasIsReadOnlyAttribute(EntityHandle token) return FindTargetAttribute(token, AttributeDescription.IsReadOnlyAttribute).HasValue; } + internal bool HasIsUnmanagedAttribute(EntityHandle token) + { + return FindTargetAttribute(token, AttributeDescription.IsUnmanagedAttribute).HasValue; + } + internal bool HasExtensionAttribute(EntityHandle token, bool ignoreCase) { return FindTargetAttribute(token, ignoreCase ? AttributeDescription.CaseInsensitiveExtensionAttribute : AttributeDescription.CaseSensitiveExtensionAttribute).HasValue; diff --git a/src/Compilers/Core/Portable/MetadataReader/SymbolFactory.cs b/src/Compilers/Core/Portable/MetadataReader/SymbolFactory.cs index b3dcff2d71bd9..75087772f0f86 100644 --- a/src/Compilers/Core/Portable/MetadataReader/SymbolFactory.cs +++ b/src/Compilers/Core/Portable/MetadataReader/SymbolFactory.cs @@ -42,6 +42,8 @@ internal abstract TypeSymbol GetMDArrayTypeSymbol(ModuleSymbol moduleSymbol, int internal abstract bool IsAcceptedVolatileModifierType(ModuleSymbol moduleSymbol, TypeSymbol type); internal abstract bool IsAcceptedInAttributeModifierType(TypeSymbol type); + internal abstract bool IsAcceptedUnmanagedTypeModifierType(TypeSymbol type); + internal abstract Cci.PrimitiveTypeCode GetPrimitiveTypeCode(ModuleSymbol moduleSymbol, TypeSymbol type); } } diff --git a/src/Compilers/Core/Portable/MetadataReader/TypeNameDecoder.cs b/src/Compilers/Core/Portable/MetadataReader/TypeNameDecoder.cs index d1b3825b99452..a206ac3b34c3d 100644 --- a/src/Compilers/Core/Portable/MetadataReader/TypeNameDecoder.cs +++ b/src/Compilers/Core/Portable/MetadataReader/TypeNameDecoder.cs @@ -98,6 +98,11 @@ protected bool IsAcceptedInAttributeModifierType(TypeSymbol type) return _factory.IsAcceptedInAttributeModifierType(type); } + protected bool IsAcceptedUnmanagedTypeModifierType(TypeSymbol type) + { + return _factory.IsAcceptedUnmanagedTypeModifierType(type); + } + protected Microsoft.Cci.PrimitiveTypeCode GetPrimitiveTypeCode(TypeSymbol type) { return _factory.GetPrimitiveTypeCode(this.moduleSymbol, type); diff --git a/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs b/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs index ea72272358e4c..2e8ae248834d1 100644 --- a/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs +++ b/src/Compilers/Core/Portable/Symbols/Attributes/AttributeDescription.cs @@ -257,6 +257,7 @@ static AttributeDescription() private static readonly byte[][] s_signaturesOfInAttribute = { s_signature_HasThis_Void }; private static readonly byte[][] s_signaturesOfOutAttribute = { s_signature_HasThis_Void }; private static readonly byte[][] s_signaturesOfIsReadOnlyAttribute = { s_signature_HasThis_Void }; + private static readonly byte[][] s_signaturesOfIsUnmanagedAttribute = { s_signature_HasThis_Void }; private static readonly byte[][] s_signaturesOfFixedBufferAttribute = { s_signature_HasThis_Void_Type_Int32 }; private static readonly byte[][] s_signaturesOfSuppressUnmanagedCodeSecurityAttribute = { s_signature_HasThis_Void }; private static readonly byte[][] s_signaturesOfPrincipalPermissionAttribute = { s_signature_HasThis_Void_SecurityAction }; @@ -453,6 +454,7 @@ static AttributeDescription() internal static readonly AttributeDescription InAttribute = new AttributeDescription("System.Runtime.InteropServices", "InAttribute", s_signaturesOfInAttribute); internal static readonly AttributeDescription OutAttribute = new AttributeDescription("System.Runtime.InteropServices", "OutAttribute", s_signaturesOfOutAttribute); internal static readonly AttributeDescription IsReadOnlyAttribute = new AttributeDescription("System.Runtime.CompilerServices", "IsReadOnlyAttribute", s_signaturesOfIsReadOnlyAttribute); + internal static readonly AttributeDescription IsUnmanagedAttribute = new AttributeDescription("System.Runtime.CompilerServices", "IsUnmanagedAttribute", s_signaturesOfIsUnmanagedAttribute); internal static readonly AttributeDescription CoClassAttribute = new AttributeDescription("System.Runtime.InteropServices", "CoClassAttribute", s_signaturesOfCoClassAttribute); internal static readonly AttributeDescription GuidAttribute = new AttributeDescription("System.Runtime.InteropServices", "GuidAttribute", s_signaturesOfGuidAttribute); internal static readonly AttributeDescription CLSCompliantAttribute = new AttributeDescription("System", "CLSCompliantAttribute", s_signaturesOfCLSCompliantAttribute); diff --git a/src/Compilers/Core/Portable/WellKnownMember.cs b/src/Compilers/Core/Portable/WellKnownMember.cs index d925f8e800335..618eee3d90949 100644 --- a/src/Compilers/Core/Portable/WellKnownMember.cs +++ b/src/Compilers/Core/Portable/WellKnownMember.cs @@ -430,6 +430,8 @@ internal enum WellKnownMember System_ReadOnlySpan_T__get_Item, System_ReadOnlySpan_T__get_Length, + System_Runtime_CompilerServices_IsUnmanagedAttribute__ctor, + Count } } diff --git a/src/Compilers/Core/Portable/WellKnownMembers.cs b/src/Compilers/Core/Portable/WellKnownMembers.cs index 4ecc3e33c0596..807a55e39188b 100644 --- a/src/Compilers/Core/Portable/WellKnownMembers.cs +++ b/src/Compilers/Core/Portable/WellKnownMembers.cs @@ -2959,6 +2959,14 @@ static WellKnownMembers() 0, // Arity 0, // Method Signature (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Int32, + + // System_Runtime_CompilerServices_IsUnmanagedAttribute__ctor + (byte)(MemberFlags.Constructor), // Flags + (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Runtime_CompilerServices_IsUnmanagedAttribute - WellKnownType.ExtSentinel), // DeclaringTypeId + 0, // Arity + 0, // Method Signature + (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Void, + }; string[] allNames = new string[(int)WellKnownMember.Count] @@ -3328,6 +3336,7 @@ static WellKnownMembers() "get_Length", // System_Span__get_Length "get_Item", // System_ReadOnlySpan__get_Item "get_Length", // System_ReadOnlySpan__get_Length + ".ctor", // System_Runtime_CompilerServices_IsUnmanagedAttribute__ctor }; s_descriptors = MemberDescriptor.InitializeFromStream(new System.IO.MemoryStream(initializationBytes, writable: false), allNames); diff --git a/src/Compilers/Core/Portable/WellKnownTypes.cs b/src/Compilers/Core/Portable/WellKnownTypes.cs index 05c42a71fff9d..3876f36b9078a 100644 --- a/src/Compilers/Core/Portable/WellKnownTypes.cs +++ b/src/Compilers/Core/Portable/WellKnownTypes.cs @@ -271,6 +271,8 @@ internal enum WellKnownType System_ObsoleteAttribute, System_Span_T, System_ReadOnlySpan_T, + System_Runtime_InteropServices_UnmanagedType, + System_Runtime_CompilerServices_IsUnmanagedAttribute, NextAvailable, } @@ -537,6 +539,8 @@ internal static class WellKnownTypes "System.ObsoleteAttribute", "System.Span`1", "System.ReadOnlySpan`1", + "System.Runtime.InteropServices.UnmanagedType", + "System.Runtime.CompilerServices.IsUnmanagedAttribute", }; private readonly static Dictionary s_nameToTypeIdMap = new Dictionary((int)Count); diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/SymbolFactory.vb b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/SymbolFactory.vb index 2099086cd0f02..f00dca652a2d6 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/SymbolFactory.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/SymbolFactory.vb @@ -54,6 +54,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE Return False End Function + Friend Overrides Function IsAcceptedUnmanagedTypeModifierType(type As TypeSymbol) As Boolean + ' VB doesn't deal with unmanaged generic type constraints + Return False + End Function + Friend Overrides Function GetSZArrayTypeSymbol(moduleSymbol As PEModuleSymbol, elementType As TypeSymbol, customModifiers As ImmutableArray(Of ModifierInfo(Of TypeSymbol))) As TypeSymbol If TypeOf elementType Is UnsupportedMetadataTypeSymbol Then Return elementType diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Metadata/PE/LoadCustomModifiers.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Metadata/PE/LoadCustomModifiers.vb index 0c7314bddcddd..7ccf513b2ddcd 100644 --- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Metadata/PE/LoadCustomModifiers.vb +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Metadata/PE/LoadCustomModifiers.vb @@ -9,7 +9,7 @@ Imports Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE Imports Microsoft.CodeAnalysis.VisualBasic.Symbols Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Imports Roslyn.Test.Utilities - +Imports Microsoft.CodeAnalysis.CSharp Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Symbols.Metadata.PE @@ -103,6 +103,101 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Symbols.Metadata.PE Assert.Equal("System.Runtime.CompilerServices.IsConst", m7Mod.Modifier.ToTestDisplayString()) End Sub + + Public Sub UnmanagedConstraint_RejectedSymbol_OnClass() + Dim reference = CreateCSharpCompilation(" +public class TestRef where T : unmanaged +{ +}", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = + + +Class Test + Shared Sub Main() + Dim x = New TestRef(Of String)() + End Sub +End Class + + + + Dim compilation = CreateCompilationWithMscorlib(source, references:={reference}) + + AssertTheseDiagnostics(compilation, +BC30649: '' is an unsupported type. + Dim x = New TestRef(Of String)() + ~~~~~~ +BC32044: Type argument 'String' does not inherit from or implement the constraint type '?'. + Dim x = New TestRef(Of String)() + ~~~~~~ +BC32105: Type argument 'String' does not satisfy the 'Structure' constraint for type parameter 'T'. + Dim x = New TestRef(Of String)() + ~~~~~~ + ) + End Sub + + + Public Sub UnmanagedConstraint_RejectedSymbol_OnMethod() + Dim reference = CreateCSharpCompilation(" +public class TestRef +{ + public void M() where T : unmanaged + { + } +}", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = + + +Class Test + Shared Sub Main() + Dim x = New TestRef() + x.M(Of String)() + End Sub +End Class + + + + Dim compilation = CreateCompilationWithMscorlib(source, references:={reference}) + + AssertTheseDiagnostics(compilation, +BC30649: '' is an unsupported type. + x.M(Of String)() + ~~~~~~~~~~~~~~~~ + ) + End Sub + + + Public Sub UnmanagedConstraint_RejectedSymbol_OnDelegate() + Dim reference = CreateCSharpCompilation(" +public delegate T D() where T : unmanaged; +", parseOptions:=New CSharpParseOptions(CSharp.LanguageVersion.Latest)).EmitToImageReference() + + Dim source = + + +Class Test + Shared Sub Main(del As D(Of String)) + End Sub +End Class + + + + Dim compilation = CreateCompilationWithMscorlib(source, references:={reference}) + + AssertTheseDiagnostics(compilation, +BC30649: '' is an unsupported type. + Shared Sub Main(del As D(Of String)) + ~~~ +BC32044: Type argument 'String' does not inherit from or implement the constraint type '?'. + Shared Sub Main(del As D(Of String)) + ~~~ +BC32105: Type argument 'String' does not satisfy the 'Structure' constraint for type parameter 'T'. + Shared Sub Main(del As D(Of String)) + ~~~ + ) + End Sub + End Class End Namespace diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb index 7049a7071cf1f..c18b8baea1cd9 100644 --- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb @@ -511,7 +511,8 @@ End Namespace Continue For Case WellKnownType.Microsoft_CodeAnalysis_Runtime_Instrumentation, WellKnownType.System_Runtime_CompilerServices_IsReadOnlyAttribute, - WellKnownType.System_Runtime_CompilerServices_IsByRefLikeAttribute + WellKnownType.System_Runtime_CompilerServices_IsByRefLikeAttribute, + WellKnownType.System_Runtime_CompilerServices_IsUnmanagedAttribute ' Not always available. Continue For End Select @@ -550,7 +551,8 @@ End Namespace Continue For Case WellKnownType.Microsoft_CodeAnalysis_Runtime_Instrumentation, WellKnownType.System_Runtime_CompilerServices_IsReadOnlyAttribute, - WellKnownType.System_Runtime_CompilerServices_IsByRefLikeAttribute + WellKnownType.System_Runtime_CompilerServices_IsByRefLikeAttribute, + WellKnownType.System_Runtime_CompilerServices_IsUnmanagedAttribute ' Not always available. Continue For End Select @@ -596,7 +598,8 @@ End Namespace Case WellKnownMember.Microsoft_CodeAnalysis_Runtime_Instrumentation__CreatePayloadForMethodsSpanningSingleFile, WellKnownMember.Microsoft_CodeAnalysis_Runtime_Instrumentation__CreatePayloadForMethodsSpanningMultipleFiles, WellKnownMember.System_Runtime_CompilerServices_IsReadOnlyAttribute__ctor, - WellKnownMember.System_Runtime_CompilerServices_IsByRefLikeAttribute__ctor + WellKnownMember.System_Runtime_CompilerServices_IsByRefLikeAttribute__ctor, + WellKnownMember.System_Runtime_CompilerServices_IsUnmanagedAttribute__ctor ' Not always available. Continue For End Select @@ -684,7 +687,8 @@ End Namespace Case WellKnownMember.Microsoft_CodeAnalysis_Runtime_Instrumentation__CreatePayloadForMethodsSpanningSingleFile, WellKnownMember.Microsoft_CodeAnalysis_Runtime_Instrumentation__CreatePayloadForMethodsSpanningMultipleFiles, WellKnownMember.System_Runtime_CompilerServices_IsReadOnlyAttribute__ctor, - WellKnownMember.System_Runtime_CompilerServices_IsByRefLikeAttribute__ctor + WellKnownMember.System_Runtime_CompilerServices_IsByRefLikeAttribute__ctor, + WellKnownMember.System_Runtime_CompilerServices_IsUnmanagedAttribute__ctor ' Not always available. Continue For End Select diff --git a/src/EditorFeatures/CSharpTest/EditAndContinue/TopLevelEditingTests.cs b/src/EditorFeatures/CSharpTest/EditAndContinue/TopLevelEditingTests.cs index 9c5d1c0cd46b3..55213cdd038c1 100644 --- a/src/EditorFeatures/CSharpTest/EditAndContinue/TopLevelEditingTests.cs +++ b/src/EditorFeatures/CSharpTest/EditAndContinue/TopLevelEditingTests.cs @@ -8678,7 +8678,7 @@ public void TypeTypeParameterAttributeUpdate() #region Type Parameter Constraints [Fact] - public void TypeConstraintInsert() + public void TypeConstraintInsert_Class() { var src1 = "class C { }"; var src2 = "class C where T : class { }"; @@ -8693,7 +8693,22 @@ public void TypeConstraintInsert() } [Fact] - public void TypeConstraintInsert2() + public void TypeConstraintInsert_Unmanaged() + { + var src1 = "class C { }"; + var src2 = "class C where T : unmanaged { }"; + + var edits = GetTopEdits(src1, src2); + + edits.VerifyEdits( + "Insert [where T : unmanaged]@11"); + + edits.VerifyRudeDiagnostics( + Diagnostic(RudeEditKind.Insert, "where T : unmanaged", FeaturesResources.type_constraint)); + } + + [Fact] + public void TypeConstraintInsert_DoubleStatement_New() { var src1 = "class C where T : class { }"; var src2 = "class C where S : new() where T : class { }"; @@ -8708,7 +8723,22 @@ public void TypeConstraintInsert2() } [Fact] - public void TypeConstraintDelete1() + public void TypeConstraintInsert_DoubleStatement_Unmanaged() + { + var src1 = "class C where T : class { }"; + var src2 = "class C where S : unmanaged where T : class { }"; + + var edits = GetTopEdits(src1, src2); + + edits.VerifyEdits( + "Insert [where S : unmanaged]@13"); + + edits.VerifyRudeDiagnostics( + Diagnostic(RudeEditKind.Insert, "where S : unmanaged", FeaturesResources.type_constraint)); + } + + [Fact] + public void TypeConstraintDelete_Class() { var src1 = "class C where T : class { }"; var src2 = "class C { }"; @@ -8723,7 +8753,22 @@ public void TypeConstraintDelete1() } [Fact] - public void TypeConstraintDelete2() + public void TypeConstraintDelete_Unmanaged() + { + var src1 = "class C where T : unmanaged { }"; + var src2 = "class C { }"; + + var edits = GetTopEdits(src1, src2); + + edits.VerifyEdits( + "Delete [where T : unmanaged]@13"); + + edits.VerifyRudeDiagnostics( + Diagnostic(RudeEditKind.Delete, "class C", FeaturesResources.type_constraint)); + } + + [Fact] + public void TypeConstraintDelete_DoubleStatement_New() { var src1 = "class C where S : new() where T : class { }"; var src2 = "class C where T : class { }"; @@ -8738,7 +8783,22 @@ public void TypeConstraintDelete2() } [Fact] - public void TypeConstraintReorder() + public void TypeConstraintDelete_DoubleStatement_Unmanaged() + { + var src1 = "class C where S : unmanaged where T : class { }"; + var src2 = "class C where T : class { }"; + + var edits = GetTopEdits(src1, src2); + + edits.VerifyEdits( + "Delete [where S : unmanaged]@13"); + + edits.VerifyRudeDiagnostics( + Diagnostic(RudeEditKind.Delete, "class C", FeaturesResources.type_constraint)); + } + + [Fact] + public void TypeConstraintReorder_Class() { var src1 = "class C where S : struct where T : class { }"; var src2 = "class C where T : class where S : struct { }"; @@ -8751,6 +8811,20 @@ public void TypeConstraintReorder() edits.VerifyRudeDiagnostics(); } + [Fact] + public void TypeConstraintReorder_Unmanaged() + { + var src1 = "class C where S : struct where T : unmanaged { }"; + var src2 = "class C where T : unmanaged where S : struct { }"; + + var edits = GetTopEdits(src1, src2); + + edits.VerifyEdits( + "Reorder [where T : unmanaged]@30 -> @13"); + + edits.VerifyRudeDiagnostics(); + } + [Fact] public void TypeConstraintUpdateAndReorder() { diff --git a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EETypeParameterSymbol.cs b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EETypeParameterSymbol.cs index c7a514e1eff37..50fc84128c438 100644 --- a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EETypeParameterSymbol.cs +++ b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/EETypeParameterSymbol.cs @@ -60,6 +60,11 @@ public override bool HasValueTypeConstraint get { return _sourceTypeParameter.HasValueTypeConstraint; } } + public override bool HasUnmanagedTypeConstraint + { + get { return _sourceTypeParameter.HasUnmanagedTypeConstraint; } + } + public override ImmutableArray Locations { get { throw ExceptionUtilities.Unreachable; } diff --git a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/SimpleTypeParameterSymbol.cs b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/SimpleTypeParameterSymbol.cs index fad03dd5e587a..2f32b6ba9e0bb 100644 --- a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/SimpleTypeParameterSymbol.cs +++ b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Symbols/SimpleTypeParameterSymbol.cs @@ -53,6 +53,11 @@ public override bool HasValueTypeConstraint get { return false; } } + public override bool HasUnmanagedTypeConstraint + { + get { return false; } + } + public override VarianceKind Variance { get { return VarianceKind.None; } From e7814b1fe1a5dcb878426cc7f361872fb863a82e Mon Sep 17 00:00:00 2001 From: Omar Tawfik Date: Mon, 19 Feb 2018 02:16:15 -0800 Subject: [PATCH 04/13] Fixed IDE services touching `unmanaged` constraint --- .../SymbolDisplayVisitor.Types.cs | 5 + .../SymbolDisplay/SymbolDisplayTests.cs | 75 +++++ .../Core/Portable/PublicAPI.Unshipped.txt | 1 + .../Portable/Symbols/ITypeParameterSymbol.cs | 7 +- .../Portable/Symbols/TypeParameterSymbol.vb | 6 + .../Classification/SemanticClassifierTests.cs | 113 ++++++++ .../SyntacticClassifierTests.cs | 258 ++++++++++++++++++ .../Classification/TotalClassifierTests.cs | 258 ++++++++++++++++++ .../UpgradeProject/UpgradeProjectTests.cs | 37 +++ .../ExtractInterface/ExtractInterfaceTests.cs | 32 +++ .../ImplementInterfaceTests.cs | 24 ++ .../QuickInfo/SemanticQuickInfoSourceTests.cs | 31 +++ .../UnmanagedKeywordRecommenderTests.cs | 168 ++++++++++++ ...stractMetadataAsSourceTests.TestContext.cs | 14 +- .../MetadataAsSource/MetadataAsSourceTests.cs | 110 ++++++++ .../KeywordCompletionProvider.cs | 1 + .../UnmanagedKeywordRecommender.cs | 24 ++ .../MethodExtractor.CodeGenerator.cs | 3 +- ...zedMemberService.AbstractInvocationInfo.cs | 3 +- .../Classification/ClassificationHelpers.cs | 15 +- .../NameSyntaxClassifier.cs | 24 +- .../ITypeParameterSymbolExtensions.cs | 4 + .../CodeGenerationSymbolFactory.cs | 5 +- .../CodeGenerationTypeParameterSymbol.cs | 5 +- .../Extensions/IMethodSymbolExtensions.cs | 1 + 25 files changed, 1202 insertions(+), 22 deletions(-) create mode 100644 src/EditorFeatures/CSharpTest2/Recommendations/UnmanagedKeywordRecommenderTests.cs create mode 100644 src/Features/CSharp/Portable/Completion/KeywordRecommenders/UnmanagedKeywordRecommender.cs diff --git a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs index c9ea1b39edfa7..515e26fb4e116 100644 --- a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs +++ b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs @@ -690,6 +690,11 @@ private void AddTypeParameterConstraints(ImmutableArray typeArgumen AddKeyword(SyntaxKind.ClassKeyword); needComma = true; } + else if (typeParam.HasUnmanagedTypeConstraint) + { + builder.Add(new SymbolDisplayPart(SymbolDisplayPartKind.Keyword, null, "unmanaged")); + needComma = true; + } else if (typeParam.HasValueTypeConstraint) { AddKeyword(SyntaxKind.StructKeyword); diff --git a/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs b/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs index 1720aa1680e1e..64d14149ded41 100644 --- a/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs @@ -6415,5 +6415,80 @@ public void MulticastDelegateConstraint() SymbolDisplayPartKind.Punctuation, SymbolDisplayPartKind.ClassName); } + + [Fact] + public void UnmanagedConstraint_Type() + { + TestSymbolDescription( + "class X where T : unmanaged { }", + global => global.GetTypeMember("X"), + SymbolDisplayFormat.TestFormat.AddGenericsOptions(SymbolDisplayGenericsOptions.IncludeTypeConstraints), + "X where T : unmanaged", + SymbolDisplayPartKind.ClassName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.TypeParameterName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.TypeParameterName, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword); + } + + [Fact] + public void UnmanagedConstraint_Method() + { + TestSymbolDescription(@" +class X +{ + void M() where T : unmanaged { } +}", + global => global.GetTypeMember("X").GetMethod("M"), + SymbolDisplayFormat.TestFormat.AddGenericsOptions(SymbolDisplayGenericsOptions.IncludeTypeConstraints), + "void X.M() where T : unmanaged", + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.ClassName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.MethodName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.TypeParameterName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.TypeParameterName, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword); + } + + [Fact] + public void UnmanagedConstraint_Delegate() + { + TestSymbolDescription( + "delegate void D() where T : unmanaged;", + global => global.GetTypeMember("D"), + SymbolDisplayFormat.TestFormat.AddGenericsOptions(SymbolDisplayGenericsOptions.IncludeTypeConstraints), + "D where T : unmanaged", + SymbolDisplayPartKind.DelegateName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.TypeParameterName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.TypeParameterName, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword); + } } } diff --git a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt index 7efb1a07267bc..a73dc5a2cb424 100644 --- a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt @@ -52,6 +52,7 @@ Microsoft.CodeAnalysis.IOperation.Syntax.get -> Microsoft.CodeAnalysis.SyntaxNod Microsoft.CodeAnalysis.IOperation.Type.get -> Microsoft.CodeAnalysis.ITypeSymbol Microsoft.CodeAnalysis.IPropertySymbol.RefKind.get -> Microsoft.CodeAnalysis.RefKind Microsoft.CodeAnalysis.IPropertySymbol.ReturnsByRefReadonly.get -> bool +Microsoft.CodeAnalysis.ITypeParameterSymbol.HasUnmanagedTypeConstraint.get -> bool Microsoft.CodeAnalysis.ModuleMetadata.IsDisposed.get -> bool Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.AddressOf = 64 -> Microsoft.CodeAnalysis.OperationKind diff --git a/src/Compilers/Core/Portable/Symbols/ITypeParameterSymbol.cs b/src/Compilers/Core/Portable/Symbols/ITypeParameterSymbol.cs index 5a56c4ef83798..7225315d141e7 100644 --- a/src/Compilers/Core/Portable/Symbols/ITypeParameterSymbol.cs +++ b/src/Compilers/Core/Portable/Symbols/ITypeParameterSymbol.cs @@ -46,10 +46,15 @@ public interface ITypeParameterSymbol : ITypeSymbol bool HasReferenceTypeConstraint { get; } /// - /// True if the value type constraint (struct)was specified for the type parameter. + /// True if the value type constraint (struct) was specified for the type parameter. /// bool HasValueTypeConstraint { get; } + /// + /// True if the value type constraint (unmanaged) was specified for the type parameter. + /// + bool HasUnmanagedTypeConstraint { get; } + /// /// True if the parameterless constructor constraint (new()) was specified for the type parameter. /// diff --git a/src/Compilers/VisualBasic/Portable/Symbols/TypeParameterSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/TypeParameterSymbol.vb index f353cf64ee8a4..da2988db6e29a 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/TypeParameterSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/TypeParameterSymbol.vb @@ -314,6 +314,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Public MustOverride ReadOnly Property HasValueTypeConstraint As Boolean Implements ITypeParameterSymbol.HasValueTypeConstraint + Private ReadOnly Property HasUnmanagedTypeConstraint As Boolean Implements ITypeParameterSymbol.HasUnmanagedTypeConstraint + Get + Return False + End Get + End Property + Public MustOverride ReadOnly Property Variance As VarianceKind Implements ITypeParameterSymbol.Variance ''' diff --git a/src/EditorFeatures/CSharpTest/Classification/SemanticClassifierTests.cs b/src/EditorFeatures/CSharpTest/Classification/SemanticClassifierTests.cs index 43f527b5a14c8..b9e30142619d7 100644 --- a/src/EditorFeatures/CSharpTest/Classification/SemanticClassifierTests.cs +++ b/src/EditorFeatures/CSharpTest/Classification/SemanticClassifierTests.cs @@ -2325,5 +2325,118 @@ void Main(string s) } }", Keyword("var")); } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_InsideMethod() + { + await TestInMethodAsync( + "var unmanaged = 0;", + Keyword("var")); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_Type_Keyword() + { + await TestAsync( + "class X where T : unmanaged { }", + TypeParameter("T"), + Keyword("unmanaged")); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_Type_ExistingInterface() + { + await TestAsync(@" +interface unmanaged {} +class X where T : unmanaged { }", + TypeParameter("T"), + Interface("unmanaged")); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_Type_ExistingInterfaceButOutOfScope() + { + await TestAsync(@" +namespace OtherScope +{ + interface unmanaged {} +} +class X where T : unmanaged { }", + TypeParameter("T"), + Keyword("unmanaged")); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_Method_Keyword() + { + await TestAsync(@" +class X +{ + void M() where T : unmanaged { } +}", + TypeParameter("T"), + Keyword("unmanaged")); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_Method_ExistingInterface() + { + await TestAsync(@" +interface unmanaged {} +class X +{ + void M() where T : unmanaged { } +}", + TypeParameter("T"), + Interface("unmanaged")); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_Method_ExistingInterfaceButOutOfScope() + { + await TestAsync(@" +namespace OtherScope +{ + interface unmanaged {} +} +class X +{ + void M() where T : unmanaged { } +}", + TypeParameter("T"), + Keyword("unmanaged")); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_Delegate_Keyword() + { + await TestAsync( + "delegate void D() where T : unmanaged;", + TypeParameter("T"), + Keyword("unmanaged")); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_Delegate_ExistingInterface() + { + await TestAsync(@" +interface unmanaged {} +delegate void D() where T : unmanaged;", + TypeParameter("T"), + Interface("unmanaged")); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_Delegate_ExistingInterfaceButOutOfScope() + { + await TestAsync(@" +namespace OtherScope +{ + interface unmanaged {} +} +delegate void D() where T : unmanaged;", + TypeParameter("T"), + Keyword("unmanaged")); + } } } diff --git a/src/EditorFeatures/CSharpTest/Classification/SyntacticClassifierTests.cs b/src/EditorFeatures/CSharpTest/Classification/SyntacticClassifierTests.cs index cd155591ca2e9..127e54bda849d 100644 --- a/src/EditorFeatures/CSharpTest/Classification/SyntacticClassifierTests.cs +++ b/src/EditorFeatures/CSharpTest/Classification/SyntacticClassifierTests.cs @@ -4011,5 +4011,263 @@ await TestAsync( Comment(">>>>>>> End"), Punctuation.CloseCurly); } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_InsideMethod() + { + await TestInMethodAsync( + "var unmanaged = 0;", + Keyword("var"), + Identifier("unmanaged"), + Operators.Equals, + Number("0"), + Punctuation.Semicolon); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_Type_Keyword() + { + await TestAsync( + "class X where T : unmanaged { }", + Keyword("class"), + Class("X"), + Punctuation.OpenAngle, + TypeParameter("T"), + Punctuation.CloseAngle, + Keyword("where"), + Identifier("T"), + Punctuation.Colon, + Keyword("unmanaged"), + Punctuation.OpenCurly, + Punctuation.CloseCurly); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_Type_ExistingInterface() + { + await TestAsync(@" +interface unmanaged {} +class X where T : unmanaged { }", + Keyword("interface"), + Interface("unmanaged"), + Punctuation.OpenCurly, + Punctuation.CloseCurly, + Keyword("class"), + Class("X"), + Punctuation.OpenAngle, + TypeParameter("T"), + Punctuation.CloseAngle, + Keyword("where"), + Identifier("T"), + Punctuation.Colon, + Keyword("unmanaged"), + Punctuation.OpenCurly, + Punctuation.CloseCurly); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_Type_ExistingInterfaceButOutOfScope() + { + await TestAsync(@" +namespace OtherScope +{ + interface unmanaged {} +} +class X where T : unmanaged { }", + Keyword("namespace"), + Identifier("OtherScope"), + Punctuation.OpenCurly, + Keyword("interface"), + Interface("unmanaged"), + Punctuation.OpenCurly, + Punctuation.CloseCurly, + Punctuation.CloseCurly, + Keyword("class"), + Class("X"), + Punctuation.OpenAngle, + TypeParameter("T"), + Punctuation.CloseAngle, + Keyword("where"), + Identifier("T"), + Punctuation.Colon, + Keyword("unmanaged"), + Punctuation.OpenCurly, + Punctuation.CloseCurly); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_Method_Keyword() + { + await TestAsync(@" +class X +{ + void M() where T : unmanaged { } +}", + Keyword("class"), + Class("X"), + Punctuation.OpenCurly, + Keyword("void"), + Identifier("M"), + Punctuation.OpenAngle, + TypeParameter("T"), + Punctuation.CloseAngle, + Punctuation.OpenParen, + Punctuation.CloseParen, + Keyword("where"), + Identifier("T"), + Punctuation.Colon, + Keyword("unmanaged"), + Punctuation.OpenCurly, + Punctuation.CloseCurly, + Punctuation.CloseCurly); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_Method_ExistingInterface() + { + await TestAsync(@" +interface unmanaged {} +class X +{ + void M() where T : unmanaged { } +}", + Keyword("interface"), + Interface("unmanaged"), + Punctuation.OpenCurly, + Punctuation.CloseCurly, + Keyword("class"), + Class("X"), + Punctuation.OpenCurly, + Keyword("void"), + Identifier("M"), + Punctuation.OpenAngle, + TypeParameter("T"), + Punctuation.CloseAngle, + Punctuation.OpenParen, + Punctuation.CloseParen, + Keyword("where"), + Identifier("T"), + Punctuation.Colon, + Keyword("unmanaged"), + Punctuation.OpenCurly, + Punctuation.CloseCurly, + Punctuation.CloseCurly); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_Method_ExistingInterfaceButOutOfScope() + { + await TestAsync(@" +namespace OtherScope +{ + interface unmanaged {} +} +class X +{ + void M() where T : unmanaged { } +}", + Keyword("namespace"), + Identifier("OtherScope"), + Punctuation.OpenCurly, + Keyword("interface"), + Interface("unmanaged"), + Punctuation.OpenCurly, + Punctuation.CloseCurly, + Punctuation.CloseCurly, + Keyword("class"), + Class("X"), + Punctuation.OpenCurly, + Keyword("void"), + Identifier("M"), + Punctuation.OpenAngle, + TypeParameter("T"), + Punctuation.CloseAngle, + Punctuation.OpenParen, + Punctuation.CloseParen, + Keyword("where"), + Identifier("T"), + Punctuation.Colon, + Keyword("unmanaged"), + Punctuation.OpenCurly, + Punctuation.CloseCurly, + Punctuation.CloseCurly); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_Delegate_Keyword() + { + await TestAsync( + "delegate void D() where T : unmanaged;", + Keyword("delegate"), + Keyword("void"), + Delegate("D"), + Punctuation.OpenAngle, + TypeParameter("T"), + Punctuation.CloseAngle, + Punctuation.OpenParen, + Punctuation.CloseParen, + Keyword("where"), + Identifier("T"), + Punctuation.Colon, + Keyword("unmanaged"), + Punctuation.Semicolon); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_Delegate_ExistingInterface() + { + await TestAsync(@" +interface unmanaged {} +delegate void D() where T : unmanaged;", + Keyword("interface"), + Interface("unmanaged"), + Punctuation.OpenCurly, + Punctuation.CloseCurly, + Keyword("delegate"), + Keyword("void"), + Delegate("D"), + Punctuation.OpenAngle, + TypeParameter("T"), + Punctuation.CloseAngle, + Punctuation.OpenParen, + Punctuation.CloseParen, + Keyword("where"), + Identifier("T"), + Punctuation.Colon, + Keyword("unmanaged"), + Punctuation.Semicolon); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_Delegate_ExistingInterfaceButOutOfScope() + { + await TestAsync(@" +namespace OtherScope +{ + interface unmanaged {} +} +delegate void D() where T : unmanaged;", + Keyword("namespace"), + Identifier("OtherScope"), + Punctuation.OpenCurly, + Keyword("interface"), + Interface("unmanaged"), + Punctuation.OpenCurly, + Punctuation.CloseCurly, + Punctuation.CloseCurly, + Keyword("delegate"), + Keyword("void"), + Delegate("D"), + Punctuation.OpenAngle, + TypeParameter("T"), + Punctuation.CloseAngle, + Punctuation.OpenParen, + Punctuation.CloseParen, + Keyword("where"), + Identifier("T"), + Punctuation.Colon, + Keyword("unmanaged"), + Punctuation.Semicolon); + } } } diff --git a/src/EditorFeatures/CSharpTest/Classification/TotalClassifierTests.cs b/src/EditorFeatures/CSharpTest/Classification/TotalClassifierTests.cs index e4a58ec82e036..8b2e97cfb4948 100644 --- a/src/EditorFeatures/CSharpTest/Classification/TotalClassifierTests.cs +++ b/src/EditorFeatures/CSharpTest/Classification/TotalClassifierTests.cs @@ -849,5 +849,263 @@ class Program : IReadOnlyCollection Punctuation.OpenCurly, Punctuation.CloseCurly); } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_InsideMethod() + { + await TestInMethodAsync( + "var unmanaged = 0;", + Keyword("var"), + Identifier("unmanaged"), + Operators.Equals, + Number("0"), + Punctuation.Semicolon); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_Type_Keyword() + { + await TestAsync( + "class X where T : unmanaged { }", + Keyword("class"), + Class("X"), + Punctuation.OpenAngle, + TypeParameter("T"), + Punctuation.CloseAngle, + Keyword("where"), + TypeParameter("T"), + Punctuation.Colon, + Keyword("unmanaged"), + Punctuation.OpenCurly, + Punctuation.CloseCurly); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_Type_ExistingInterface() + { + await TestAsync(@" +interface unmanaged {} +class X where T : unmanaged { }", + Keyword("interface"), + Interface("unmanaged"), + Punctuation.OpenCurly, + Punctuation.CloseCurly, + Keyword("class"), + Class("X"), + Punctuation.OpenAngle, + TypeParameter("T"), + Punctuation.CloseAngle, + Keyword("where"), + TypeParameter("T"), + Punctuation.Colon, + Interface("unmanaged"), + Punctuation.OpenCurly, + Punctuation.CloseCurly); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_Type_ExistingInterfaceButOutOfScope() + { + await TestAsync(@" +namespace OtherScope +{ + interface unmanaged {} +} +class X where T : unmanaged { }", + Keyword("namespace"), + Identifier("OtherScope"), + Punctuation.OpenCurly, + Keyword("interface"), + Interface("unmanaged"), + Punctuation.OpenCurly, + Punctuation.CloseCurly, + Punctuation.CloseCurly, + Keyword("class"), + Class("X"), + Punctuation.OpenAngle, + TypeParameter("T"), + Punctuation.CloseAngle, + Keyword("where"), + TypeParameter("T"), + Punctuation.Colon, + Keyword("unmanaged"), + Punctuation.OpenCurly, + Punctuation.CloseCurly); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_Method_Keyword() + { + await TestAsync(@" +class X +{ + void M() where T : unmanaged { } +}", + Keyword("class"), + Class("X"), + Punctuation.OpenCurly, + Keyword("void"), + Identifier("M"), + Punctuation.OpenAngle, + TypeParameter("T"), + Punctuation.CloseAngle, + Punctuation.OpenParen, + Punctuation.CloseParen, + Keyword("where"), + TypeParameter("T"), + Punctuation.Colon, + Keyword("unmanaged"), + Punctuation.OpenCurly, + Punctuation.CloseCurly, + Punctuation.CloseCurly); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_Method_ExistingInterface() + { + await TestAsync(@" +interface unmanaged {} +class X +{ + void M() where T : unmanaged { } +}", + Keyword("interface"), + Interface("unmanaged"), + Punctuation.OpenCurly, + Punctuation.CloseCurly, + Keyword("class"), + Class("X"), + Punctuation.OpenCurly, + Keyword("void"), + Identifier("M"), + Punctuation.OpenAngle, + TypeParameter("T"), + Punctuation.CloseAngle, + Punctuation.OpenParen, + Punctuation.CloseParen, + Keyword("where"), + TypeParameter("T"), + Punctuation.Colon, + Interface("unmanaged"), + Punctuation.OpenCurly, + Punctuation.CloseCurly, + Punctuation.CloseCurly); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_Method_ExistingInterfaceButOutOfScope() + { + await TestAsync(@" +namespace OtherScope +{ + interface unmanaged {} +} +class X +{ + void M() where T : unmanaged { } +}", + Keyword("namespace"), + Identifier("OtherScope"), + Punctuation.OpenCurly, + Keyword("interface"), + Interface("unmanaged"), + Punctuation.OpenCurly, + Punctuation.CloseCurly, + Punctuation.CloseCurly, + Keyword("class"), + Class("X"), + Punctuation.OpenCurly, + Keyword("void"), + Identifier("M"), + Punctuation.OpenAngle, + TypeParameter("T"), + Punctuation.CloseAngle, + Punctuation.OpenParen, + Punctuation.CloseParen, + Keyword("where"), + TypeParameter("T"), + Punctuation.Colon, + Keyword("unmanaged"), + Punctuation.OpenCurly, + Punctuation.CloseCurly, + Punctuation.CloseCurly); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_Delegate_Keyword() + { + await TestAsync( + "delegate void D() where T : unmanaged;", + Keyword("delegate"), + Keyword("void"), + Delegate("D"), + Punctuation.OpenAngle, + TypeParameter("T"), + Punctuation.CloseAngle, + Punctuation.OpenParen, + Punctuation.CloseParen, + Keyword("where"), + TypeParameter("T"), + Punctuation.Colon, + Keyword("unmanaged"), + Punctuation.Semicolon); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_Delegate_ExistingInterface() + { + await TestAsync(@" +interface unmanaged {} +delegate void D() where T : unmanaged;", + Keyword("interface"), + Interface("unmanaged"), + Punctuation.OpenCurly, + Punctuation.CloseCurly, + Keyword("delegate"), + Keyword("void"), + Delegate("D"), + Punctuation.OpenAngle, + TypeParameter("T"), + Punctuation.CloseAngle, + Punctuation.OpenParen, + Punctuation.CloseParen, + Keyword("where"), + TypeParameter("T"), + Punctuation.Colon, + Interface("unmanaged"), + Punctuation.Semicolon); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Classification)] + public async Task TestUnmanagedConstraint_Delegate_ExistingInterfaceButOutOfScope() + { + await TestAsync(@" +namespace OtherScope +{ + interface unmanaged {} +} +delegate void D() where T : unmanaged;", + Keyword("namespace"), + Identifier("OtherScope"), + Punctuation.OpenCurly, + Keyword("interface"), + Interface("unmanaged"), + Punctuation.OpenCurly, + Punctuation.CloseCurly, + Punctuation.CloseCurly, + Keyword("delegate"), + Keyword("void"), + Delegate("D"), + Punctuation.OpenAngle, + TypeParameter("T"), + Punctuation.CloseAngle, + Punctuation.OpenParen, + Punctuation.CloseParen, + Keyword("where"), + TypeParameter("T"), + Punctuation.Colon, + Keyword("unmanaged"), + Punctuation.Semicolon); + } } } diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs index 4ad8054682884..9ed4cf918ee4c 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs @@ -472,5 +472,42 @@ void A() string.Format(CSharpFeaturesResources.Upgrade_all_csharp_projects_to_language_version_0, "7.0") }); } + + [Fact] + public async Task UpgradeProjectWithUnmanagedConstraintTo7_3_Type() + { + await TestLanguageVersionUpgradedAsync( +@" +class Test where T : [|unmanaged|] +{ +}", + LanguageVersion.CSharp7_3, + new CSharpParseOptions(LanguageVersion.CSharp7), + index: 1); + } + + [Fact] + public async Task UpgradeProjectWithUnmanagedConstraintTo7_3_Method() + { + await TestLanguageVersionUpgradedAsync( +@" +class Test +{ + public void M() where T : [|unmanaged|] { } +}", + LanguageVersion.CSharp7_3, + new CSharpParseOptions(LanguageVersion.CSharp7), + index: 1); + } + + [Fact] + public async Task UpgradeProjectWithUnmanagedConstraintTo7_3_Delegate() + { + await TestLanguageVersionUpgradedAsync( +@"delegate void D() where T : [|unmanaged|];", + LanguageVersion.CSharp7_3, + new CSharpParseOptions(LanguageVersion.CSharp7), + index: 1); + } } } diff --git a/src/EditorFeatures/CSharpTest/ExtractInterface/ExtractInterfaceTests.cs b/src/EditorFeatures/CSharpTest/ExtractInterface/ExtractInterfaceTests.cs index 524caf9ffdbea..6ac66ada76711 100644 --- a/src/EditorFeatures/CSharpTest/ExtractInterface/ExtractInterfaceTests.cs +++ b/src/EditorFeatures/CSharpTest/ExtractInterface/ExtractInterfaceTests.cs @@ -1177,6 +1177,38 @@ await TestExtractInterfaceCommandCSharpAsync(markup, expectedSuccess: true, expe @"interface ITestClass { ref readonly int this[int p1] { get; } +}"); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ExtractInterface)] + public async Task TestUnmanagedConstraint_Type() + { + var markup = @" +class $$TestClass where T : unmanaged +{ + public void M(T arg) => throw null; +}"; + + await TestExtractInterfaceCommandCSharpAsync(markup, expectedSuccess: true, expectedInterfaceCode: +@"interface ITestClass where T : unmanaged +{ + void M(T arg); +}"); + } + + [WpfFact, Trait(Traits.Feature, Traits.Features.ExtractInterface)] + public async Task TestUnmanagedConstraint_Method() + { + var markup = @" +class $$TestClass +{ + public void M() where T : unmanaged => throw null; +}"; + + await TestExtractInterfaceCommandCSharpAsync(markup, expectedSuccess: true, expectedInterfaceCode: +@"interface ITestClass +{ + void M() where T : unmanaged; }"); } } diff --git a/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs b/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs index c8323436ed4c4..af5ef87815c62 100644 --- a/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs +++ b/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs @@ -6941,6 +6941,30 @@ public class Test : [|ITest|] public class Test : ITest { public ref readonly int this[int p] => throw new System.NotImplementedException(); +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] + public async Task TestUnmanagedConstraint() + { + await TestInRegularAndScriptAsync( +@"public interface ITest +{ + void M() where T : unmanaged; +} +public class Test : [|ITest|] +{ +}", +@"public interface ITest +{ + void M() where T : unmanaged; +} +public class Test : ITest +{ + public void M() where T : unmanaged + { + throw new System.NotImplementedException(); + } }"); } } diff --git a/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs b/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs index 335cbc9b923a8..ae3815a99d5c9 100644 --- a/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs +++ b/src/EditorFeatures/CSharpTest/QuickInfo/SemanticQuickInfoSourceTests.cs @@ -5188,5 +5188,36 @@ class X where T : System.MulticastDelegate }", MainDescription($"T {FeaturesResources.in_} X where T : MulticastDelegate")); } + + [Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)] + public async Task UnmanagedConstraint_Type() + { + await TestAsync( +@" +class $$X where T : unmanaged +{ +}", + MainDescription("class X where T : unmanaged")); + } + + [Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)] + public async Task UnmanagedConstraint_Method() + { + await TestAsync( +@" +class X +{ + void $$M() where T : unmanaged { } +}", + MainDescription("void X.M() where T : unmanaged")); + } + + [Fact, Trait(Traits.Feature, Traits.Features.QuickInfo)] + public async Task UnmanagedConstraint_Delegate() + { + await TestAsync( + "delegate void $$D() where T : unmanaged;", + MainDescription("delegate void D() where T : unmanaged")); + } } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/UnmanagedKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/UnmanagedKeywordRecommenderTests.cs new file mode 100644 index 0000000000000..641e101e2f567 --- /dev/null +++ b/src/EditorFeatures/CSharpTest2/Recommendations/UnmanagedKeywordRecommenderTests.cs @@ -0,0 +1,168 @@ +// 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.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp.Completion.KeywordRecommenders; +using Microsoft.CodeAnalysis.Text; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Recommendations +{ + public class UnmanagedKeywordRecommenderTests : RecommenderTests + { + private readonly UnmanagedKeywordRecommender _recommender = new UnmanagedKeywordRecommender(); + + public UnmanagedKeywordRecommenderTests() + { + this.keywordText = "unmanaged"; + this.RecommendKeywordsAsync = (position, context) => _recommender.RecommendKeywordsAsync(position, context, CancellationToken.None); + } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestAtRoot_Interactive() + { + await VerifyAbsenceAsync(SourceCodeKind.Script, +@"$$"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestNotInUsingAlias() + { + await VerifyAbsenceAsync( +@"using Goo = $$"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestNotAfterName_Type() + { + await VerifyAbsenceAsync( +@"class Test $$"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestNotAfterWhereClause_Type() + { + await VerifyAbsenceAsync( +@"class Test where $$"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestNotAfterWhereClauseType_Type() + { + await VerifyAbsenceAsync( +@"class Test where T $$"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestAfterWhereClauseColon_Type() + { + await VerifyKeywordAsync( +@"class Test where T : $$"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestNotAfterTypeConstraint_Type() + { + await VerifyAbsenceAsync( +@"class Test where T : I $$"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestAfterTypeConstraintComma_Type() + { + await VerifyKeywordAsync( +@"class Test where T : I, $$"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestNotAfterName_Method() + { + await VerifyAbsenceAsync( +@"class Test { + void M $$"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestNotAfterWhereClause_Method() + { + await VerifyAbsenceAsync( +@"class Test { + void M where $$"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestNotAfterWhereClauseType_Method() + { + await VerifyAbsenceAsync( +@"class Test { + void M where T $$"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestAfterWhereClauseColon_Method() + { + await VerifyKeywordAsync( +@"class Test { + void M where T : $$"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestNotAfterTypeConstraint_Method() + { + await VerifyAbsenceAsync( +@"class Test { + void M where T : I $$"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestAfterTypeConstraintComma_Method() + { + await VerifyKeywordAsync( +@"class Test { + void M where T : I, $$"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestNotAfterName_Delegate() + { + await VerifyAbsenceAsync( +@"delegate void D $$"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestNotAfterWhereClause_Delegate() + { + await VerifyAbsenceAsync( +@"delegate void D() where $$"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestNotAfterWhereClauseType_Delegate() + { + await VerifyAbsenceAsync( +@"delegate void D() where T $$"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestAfterWhereClauseColon_Delegate() + { + await VerifyKeywordAsync( +@"delegate void D() where T : $$"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestNotAfterTypeConstraint_Delegate() + { + await VerifyAbsenceAsync( +@"delegate void D() where T : I $$"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestAfterTypeConstraintComma_Delegate() + { + await VerifyKeywordAsync( +@"delegate void D() where T : I, $$"); + } + } +} diff --git a/src/EditorFeatures/Test/MetadataAsSource/AbstractMetadataAsSourceTests.TestContext.cs b/src/EditorFeatures/Test/MetadataAsSource/AbstractMetadataAsSourceTests.TestContext.cs index bf59b1d16c946..100e1c3cf8bf6 100644 --- a/src/EditorFeatures/Test/MetadataAsSource/AbstractMetadataAsSourceTests.TestContext.cs +++ b/src/EditorFeatures/Test/MetadataAsSource/AbstractMetadataAsSourceTests.TestContext.cs @@ -216,14 +216,11 @@ private static TestWorkspace CreateWorkspace( bool includeXmlDocComments, string sourceWithSymbolReference, string languageVersion) { + string languageVersionAttribute = languageVersion is null ? "" : $@" LanguageVersion=""{languageVersion}"""; + var xmlString = string.Concat(@" - + {1} ", metadataLanguage, SecurityElement.Escape(source), - includeXmlDocComments.ToString())); + includeXmlDocComments.ToString(), + languageVersionAttribute)); } if (sourceWithSymbolReference != null) diff --git a/src/EditorFeatures/Test/MetadataAsSource/MetadataAsSourceTests.cs b/src/EditorFeatures/Test/MetadataAsSource/MetadataAsSourceTests.cs index b64a7d37881f6..223270e0944e6 100644 --- a/src/EditorFeatures/Test/MetadataAsSource/MetadataAsSourceTests.cs +++ b/src/EditorFeatures/Test/MetadataAsSource/MetadataAsSourceTests.cs @@ -1399,5 +1399,115 @@ Function Method1() As Uri End Interface"; await GenerateAndVerifySourceAsync(source, symbolName, LanguageNames.VisualBasic, expectedVB, includeXmlDocComments: true); } + + [Fact, Trait(Traits.Feature, Traits.Features.MetadataAsSource)] + public async Task TestUnmanagedCSharpConstraint_Type() + { + var metadata = @"using System; +public class TestType where T : unmanaged +{ +}"; + var sourceWithSymbolReference = @" +class C +{ + void M() + { + var obj = new [|TestType|]<int>(); + } +}"; + var expected = $@"#region {FeaturesResources.Assembly} ReferencedAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null +// {CodeAnalysisResources.InMemoryAssembly} +#endregion + +public class [|TestType|] where T : unmanaged +{{ + public TestType(); +}}"; + + using (var context = TestContext.Create( + LanguageNames.CSharp, + SpecializedCollections.SingletonEnumerable(metadata), + includeXmlDocComments: false, + languageVersion: "CSharp7_3", + sourceWithSymbolReference: sourceWithSymbolReference)) + { + var navigationSymbol = await context.GetNavigationSymbolAsync(); + var metadataAsSourceFile = await context.GenerateSourceAsync(navigationSymbol); + context.VerifyResult(metadataAsSourceFile, expected); + } + } + + [Fact, Trait(Traits.Feature, Traits.Features.MetadataAsSource)] + public async Task TestUnmanagedCSharpConstraint_Method() + { + var metadata = @"using System; +public class TestType +{ + public void M() where T : unmanaged + { + } +}"; + var sourceWithSymbolReference = @" +class C +{ + void M() + { + var obj = new TestType().[|M|]<int>(); + } +}"; + var expected = $@"#region {FeaturesResources.Assembly} ReferencedAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null +// {CodeAnalysisResources.InMemoryAssembly} +#endregion + +public class TestType +{{ + public TestType(); + + public void [|M|]() where T : unmanaged; +}}"; + + using (var context = TestContext.Create( + LanguageNames.CSharp, + SpecializedCollections.SingletonEnumerable(metadata), + includeXmlDocComments: false, + languageVersion: "CSharp7_3", + sourceWithSymbolReference: sourceWithSymbolReference)) + { + var navigationSymbol = await context.GetNavigationSymbolAsync(); + var metadataAsSourceFile = await context.GenerateSourceAsync(navigationSymbol); + context.VerifyResult(metadataAsSourceFile, expected); + } + } + + [Fact, Trait(Traits.Feature, Traits.Features.MetadataAsSource)] + public async Task TestUnmanagedCSharpConstraint_Delegate() + { + var metadata = @"using System; +public delegate void D() where T : unmanaged;"; + var sourceWithSymbolReference = @" +class C +{ + void M([|D|]<int> lambda) + { + } +}"; + var expected = $@"#region {FeaturesResources.Assembly} ReferencedAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null +// {CodeAnalysisResources.InMemoryAssembly} +#endregion + +public delegate void [|D|]() where T : unmanaged;"; + + using (var context = TestContext.Create( + LanguageNames.CSharp, + SpecializedCollections.SingletonEnumerable(metadata), + includeXmlDocComments: false, + languageVersion: "CSharp7_3", + sourceWithSymbolReference: sourceWithSymbolReference)) + { + var navigationSymbol = await context.GetNavigationSymbolAsync(); + var metadataAsSourceFile = await context.GenerateSourceAsync(navigationSymbol); + context.VerifyResult(metadataAsSourceFile, expected); + } + } } } diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/KeywordCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/KeywordCompletionProvider.cs index 908bec90f65af..ce748080329f8 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/KeywordCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/KeywordCompletionProvider.cs @@ -140,6 +140,7 @@ private static ImmutableArray> GetKeywo new ULongKeywordRecommender(), new UncheckedKeywordRecommender(), new UndefKeywordRecommender(), + new UnmanagedKeywordRecommender(), new UnsafeKeywordRecommender(), new UShortKeywordRecommender(), new UsingKeywordRecommender(), diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/UnmanagedKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/UnmanagedKeywordRecommender.cs new file mode 100644 index 0000000000000..40ca34676169c --- /dev/null +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/UnmanagedKeywordRecommender.cs @@ -0,0 +1,24 @@ +// 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.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Completion.Providers; +using Microsoft.CodeAnalysis.CSharp.Extensions.ContextQuery; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.CSharp.Completion.KeywordRecommenders +{ + internal class UnmanagedKeywordRecommender : IKeywordRecommender + { + public Task> RecommendKeywordsAsync(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) + { + if (context.SyntaxTree.IsTypeParameterConstraintContext(position, context.LeftToken, cancellationToken)) + { + return Task.FromResult(SpecializedCollections.SingletonEnumerable(new RecommendedKeyword("unmanaged"))); + } + + return Task.FromResult>(null); + } + } +} diff --git a/src/Features/Core/Portable/ExtractMethod/MethodExtractor.CodeGenerator.cs b/src/Features/Core/Portable/ExtractMethod/MethodExtractor.CodeGenerator.cs index 9b9f5b8cf71a8..17bb143675c00 100644 --- a/src/Features/Core/Portable/ExtractMethod/MethodExtractor.CodeGenerator.cs +++ b/src/Features/Core/Portable/ExtractMethod/MethodExtractor.CodeGenerator.cs @@ -289,7 +289,8 @@ protected ImmutableArray CreateMethodTypeParameters(Cancel typeParameters.Add(CodeGenerationSymbolFactory.CreateTypeParameter( parameter.GetAttributes(), parameter.Variance, parameter.Name, ImmutableArray.Create(), - parameter.HasConstructorConstraint, parameter.HasReferenceTypeConstraint, parameter.HasValueTypeConstraint, parameter.Ordinal)); + parameter.HasConstructorConstraint, parameter.HasReferenceTypeConstraint, parameter.HasValueTypeConstraint, + parameter.HasUnmanagedTypeConstraint, parameter.Ordinal)); } return typeParameters.ToImmutableAndFree(); diff --git a/src/Features/Core/Portable/GenerateMember/GenerateParameterizedMember/AbstractGenerateParameterizedMemberService.AbstractInvocationInfo.cs b/src/Features/Core/Portable/GenerateMember/GenerateParameterizedMember/AbstractGenerateParameterizedMemberService.AbstractInvocationInfo.cs index 78e3d706893be..6f837df37e864 100644 --- a/src/Features/Core/Portable/GenerateMember/GenerateParameterizedMember/AbstractGenerateParameterizedMemberService.AbstractInvocationInfo.cs +++ b/src/Features/Core/Portable/GenerateMember/GenerateParameterizedMember/AbstractGenerateParameterizedMemberService.AbstractInvocationInfo.cs @@ -72,7 +72,8 @@ private ITypeParameterSymbol MassageTypeParameter( constraintTypes: constraints.AsImmutable(), hasConstructorConstraint: typeParameter.HasConstructorConstraint, hasReferenceConstraint: typeParameter.HasReferenceTypeConstraint, - hasValueConstraint: typeParameter.HasValueTypeConstraint); + hasValueConstraint: typeParameter.HasValueTypeConstraint, + hasUnmanagedConstraint: typeParameter.HasUnmanagedTypeConstraint); } private List MergeClassTypes(List classTypes, CancellationToken cancellationToken) diff --git a/src/Workspaces/CSharp/Portable/Classification/ClassificationHelpers.cs b/src/Workspaces/CSharp/Portable/Classification/ClassificationHelpers.cs index b4c201845d701..7da9f6b27ece3 100644 --- a/src/Workspaces/CSharp/Portable/Classification/ClassificationHelpers.cs +++ b/src/Workspaces/CSharp/Portable/Classification/ClassificationHelpers.cs @@ -14,6 +14,8 @@ internal static class ClassificationHelpers private const string FromKeyword = "from"; private const string ValueKeyword = "value"; private const string VarKeyword = "var"; + private const string UnmanagedKeyword = "unmanaged"; + private const string DynamicKeyword = "dynamic"; private const string AwaitKeyword = "await"; /// @@ -284,6 +286,11 @@ token.Parent is IdentifierNameSyntax && token.Parent.Parent is VariableDeclarationSyntax && !(token.Parent.Parent.Parent is FieldDeclarationSyntax) && !(token.Parent.Parent.Parent is EventFieldDeclarationSyntax); + + case UnmanagedKeyword: + return token.Parent is IdentifierNameSyntax + && token.Parent.Parent is TypeConstraintSyntax + && token.Parent.Parent.Parent is TypeParameterConstraintClauseSyntax; } } @@ -325,15 +332,15 @@ internal static ClassifiedSpan AdjustStaleClassification(SourceText rawText, Cla var token = SyntaxFactory.ParseToken(text); if (token.Span.Length == span.Length) { - // var and dynamic are not contextual keywords. They are always identifiers + // var, dynamic, and unmanaged are not contextual keywords. They are always identifiers // (that we classify as keywords). Because we are just parsing a token we don't // know if we're in the right context for them to be identifiers or keywords. // So, we base on decision on what they were before. i.e. if we had a keyword - // before, then assume it stays a keyword if we see 'var' or 'dynamic. + // before, then assume it stays a keyword if we see 'var', 'dynamic', or 'unmanaged'. + var tokenString = token.ToString(); var isKeyword = SyntaxFacts.IsKeywordKind(token.Kind()) || (wasKeyword && SyntaxFacts.GetContextualKeywordKind(text) != SyntaxKind.None) - || (wasKeyword && token.ToString() == "var") - || (wasKeyword && token.ToString() == "dynamic"); + || (wasKeyword && (tokenString == VarKeyword || tokenString == DynamicKeyword || tokenString == UnmanagedKeyword)); var isIdentifier = token.Kind() == SyntaxKind.IdentifierToken; diff --git a/src/Workspaces/CSharp/Portable/Classification/SyntaxClassification/NameSyntaxClassifier.cs b/src/Workspaces/CSharp/Portable/Classification/SyntaxClassification/NameSyntaxClassifier.cs index bd6091f361662..30f399c776b71 100644 --- a/src/Workspaces/CSharp/Portable/Classification/SyntaxClassification/NameSyntaxClassifier.cs +++ b/src/Workspaces/CSharp/Portable/Classification/SyntaxClassification/NameSyntaxClassifier.cs @@ -135,7 +135,7 @@ private bool TryClassifySymbol( var alias = semanticModel.GetAliasInfo(name, cancellationToken); if (alias == null || alias.Name != "var") { - if (!IsSymbolCalledVar(symbol)) + if (!IsSymbolWithName(symbol, "var")) { // We bound to a symbol. If we bound to a symbol called "var" then we want to // classify this appropriately as a type. Otherwise, we want to classify this as @@ -146,6 +146,22 @@ private bool TryClassifySymbol( } } + if (name.IsUnmanaged && name.Parent.IsKind(SyntaxKind.TypeConstraint)) + { + var alias = semanticModel.GetAliasInfo(name, cancellationToken); + if (alias == null || alias.Name != "unmanaged") + { + if (!IsSymbolWithName(symbol, "unmanaged")) + { + // We bound to a symbol. If we bound to a symbol called "unmanaged" then we want to + // classify this appropriately as a type. Otherwise, we want to classify this as + // a keyword. + classifiedSpan = new ClassifiedSpan(name.Span, ClassificationTypeNames.Keyword); + return true; + } + } + } + // Use .Equals since we can't rely on object identity for constructed types. if (symbol is ITypeSymbol typeSymbol) { @@ -279,14 +295,14 @@ private bool TryClassifyNameOfIdentifier( return false; } - private bool IsSymbolCalledVar(ISymbol symbol) + private bool IsSymbolWithName(ISymbol symbol, string name) { if (symbol is INamedTypeSymbol namedType) { - return namedType.Arity == 0 && symbol.Name == "var"; + return namedType.Arity == 0 && symbol.Name == name; } - return symbol != null && symbol.Name == "var"; + return symbol != null && symbol.Name == name; } } } diff --git a/src/Workspaces/CSharp/Portable/Extensions/ITypeParameterSymbolExtensions.cs b/src/Workspaces/CSharp/Portable/Extensions/ITypeParameterSymbolExtensions.cs index c02d81f87cc21..82f6396a7c0ea 100644 --- a/src/Workspaces/CSharp/Portable/Extensions/ITypeParameterSymbolExtensions.cs +++ b/src/Workspaces/CSharp/Portable/Extensions/ITypeParameterSymbolExtensions.cs @@ -42,6 +42,10 @@ private static void AddConstraintClauses( { constraints.Add(SyntaxFactory.ClassOrStructConstraint(SyntaxKind.ClassConstraint)); } + else if (typeParameter.HasUnmanagedTypeConstraint) + { + constraints.Add(SyntaxFactory.TypeConstraint(SyntaxFactory.IdentifierName("unmanaged"))); + } else if (typeParameter.HasValueTypeConstraint) { constraints.Add(SyntaxFactory.ClassOrStructConstraint(SyntaxKind.StructConstraint)); diff --git a/src/Workspaces/Core/Portable/CodeGeneration/CodeGenerationSymbolFactory.cs b/src/Workspaces/Core/Portable/CodeGeneration/CodeGenerationSymbolFactory.cs index c913cbfee4c68..39a130d0780c7 100644 --- a/src/Workspaces/Core/Portable/CodeGeneration/CodeGenerationSymbolFactory.cs +++ b/src/Workspaces/Core/Portable/CodeGeneration/CodeGenerationSymbolFactory.cs @@ -252,7 +252,7 @@ public static ITypeParameterSymbol CreateTypeParameterSymbol(string name, int or attributes: default, varianceKind: VarianceKind.None, name: name, constraintTypes: ImmutableArray.Create(), hasConstructorConstraint: false, hasReferenceConstraint: false, hasValueConstraint: false, - ordinal: ordinal); + hasUnmanagedConstraint: false, ordinal: ordinal); } /// @@ -264,9 +264,10 @@ public static ITypeParameterSymbol CreateTypeParameter( ImmutableArray constraintTypes, bool hasConstructorConstraint = false, bool hasReferenceConstraint = false, + bool hasUnmanagedConstraint = false, bool hasValueConstraint = false, int ordinal = 0) { - return new CodeGenerationTypeParameterSymbol(null, attributes, varianceKind, name, constraintTypes, hasConstructorConstraint, hasReferenceConstraint, hasValueConstraint, ordinal); + return new CodeGenerationTypeParameterSymbol(null, attributes, varianceKind, name, constraintTypes, hasConstructorConstraint, hasReferenceConstraint, hasValueConstraint, hasUnmanagedConstraint, ordinal); } /// diff --git a/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationTypeParameterSymbol.cs b/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationTypeParameterSymbol.cs index 93c4857e883a1..9ede82e472325 100644 --- a/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationTypeParameterSymbol.cs +++ b/src/Workspaces/Core/Portable/CodeGeneration/Symbols/CodeGenerationTypeParameterSymbol.cs @@ -13,6 +13,7 @@ internal class CodeGenerationTypeParameterSymbol : CodeGenerationTypeSymbol, ITy public bool HasConstructorConstraint { get; } public bool HasReferenceTypeConstraint { get; } public bool HasValueTypeConstraint { get; } + public bool HasUnmanagedTypeConstraint { get; } public int Ordinal { get; } public CodeGenerationTypeParameterSymbol( @@ -24,6 +25,7 @@ public CodeGenerationTypeParameterSymbol( bool hasConstructorConstraint, bool hasReferenceConstraint, bool hasValueConstraint, + bool hasUnmanagedConstraint, int ordinal) : base(containingType, attributes, Accessibility.NotApplicable, default, name, SpecialType.None) { @@ -33,6 +35,7 @@ public CodeGenerationTypeParameterSymbol( this.HasConstructorConstraint = hasConstructorConstraint; this.HasReferenceTypeConstraint = hasReferenceConstraint; this.HasValueTypeConstraint = hasValueConstraint; + this.HasUnmanagedTypeConstraint = hasUnmanagedConstraint; } protected override CodeGenerationSymbol Clone() @@ -40,7 +43,7 @@ protected override CodeGenerationSymbol Clone() return new CodeGenerationTypeParameterSymbol( this.ContainingType, this.GetAttributes(), this.Variance, this.Name, this.ConstraintTypes, this.HasConstructorConstraint, this.HasReferenceTypeConstraint, - this.HasValueTypeConstraint, this.Ordinal); + this.HasValueTypeConstraint, this.HasUnmanagedTypeConstraint, this.Ordinal); } public new ITypeParameterSymbol OriginalDefinition => this; diff --git a/src/Workspaces/Core/Portable/Shared/Extensions/IMethodSymbolExtensions.cs b/src/Workspaces/Core/Portable/Shared/Extensions/IMethodSymbolExtensions.cs index 92b96cc7fa351..b83c77f2a4266 100644 --- a/src/Workspaces/Core/Portable/Shared/Extensions/IMethodSymbolExtensions.cs +++ b/src/Workspaces/Core/Portable/Shared/Extensions/IMethodSymbolExtensions.cs @@ -131,6 +131,7 @@ private static ImmutableArray RenameTypeParameters( typeParameter.HasConstructorConstraint, typeParameter.HasReferenceTypeConstraint, typeParameter.HasValueTypeConstraint, + typeParameter.HasUnmanagedTypeConstraint, typeParameter.Ordinal); newTypeParameters.Add(newTypeParameter); From d97ac6332616953f7ef68442a66164d91ce89f99 Mon Sep 17 00:00:00 2001 From: Omar Tawfik Date: Mon, 26 Feb 2018 13:23:54 +0200 Subject: [PATCH 05/13] Added missing tests --- .../GenerateMethod/GenerateMethodTests.cs | 102 ++++++++++-------- .../Diagnostics/SpellCheck/SpellCheckTests.cs | 12 +++ .../ImplementAbstractClassTests.cs | 24 +++++ .../GenericNameSignatureHelpProviderTests.cs | 27 +++++ .../RenameTrackingTaggerProviderTests.cs | 43 ++++++++ .../GoToDefinition/GoToDefinitionTests.vb | 35 ++++++ .../GenericNameSignatureHelpProvider.cs | 5 + .../CoreTest/FindReferencesTests.cs | 20 ++++ 8 files changed, 222 insertions(+), 46 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/GenerateMethod/GenerateMethodTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/GenerateMethod/GenerateMethodTests.cs index 05a067cde54f3..2adf3e8dfff08 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/GenerateMethod/GenerateMethodTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/GenerateMethod/GenerateMethodTests.cs @@ -4095,42 +4095,47 @@ internal static void Test(global::Outer.Inner inner) new TestParameters(Options.Regular)); } + [Theory] + [InlineData("class")] + [InlineData("struct")] + [InlineData("new()")] + [InlineData("unmanaged")] [WorkItem(542529, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542529")] - [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateMethod)] - public async Task TestTypeParameterConstraints1() + [Trait(Traits.Feature, Traits.Features.CodeActionsGenerateMethod)] + public async Task TestTypeParameterConstraints(string constraint) { await TestInRegularAndScriptAsync( -@"using System; +$@"using System; -class A where T : class -{ -} +class A where T : {constraint} +{{ +}} class Program -{ - static void Goo(A x) where T : class - { +{{ + static void Goo(A x) where T : {constraint} + {{ [|Bar|](x); - } -}", -@"using System; + }} +}}", +$@"using System; -class A where T : class -{ -} +class A where T : {constraint} +{{ +}} class Program -{ - static void Goo(A x) where T : class - { +{{ + static void Goo(A x) where T : {constraint} + {{ Bar(x); - } + }} - private static void Bar(A x) where T : class - { + private static void Bar(A x) where T : {constraint} + {{ throw new NotImplementedException(); - } -}"); + }} +}}"); } [WorkItem(542622, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542622")] @@ -4165,42 +4170,47 @@ private static void Bar(Func> p) }"); } + [Theory] + [InlineData("class")] + [InlineData("struct")] + [InlineData("new()")] + [InlineData("unmanaged")] [WorkItem(542626, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542626")] - [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateMethod)] - public async Task TestMethodConstraints1() + [Trait(Traits.Feature, Traits.Features.CodeActionsGenerateMethod)] + public async Task TestMethodConstraints(string constraint) { await TestInRegularAndScriptAsync( -@"using System; +$@"using System; -class A where T : class -{ -} +class A where T : {constraint} +{{ +}} class Program -{ - static void Goo(A x) where T : class - { +{{ + static void Goo(A x) where T : {constraint} + {{ [|Bar|](x); - } -}", -@"using System; + }} +}}", +$@"using System; -class A where T : class -{ -} +class A where T : {constraint} +{{ +}} class Program -{ - static void Goo(A x) where T : class - { +{{ + static void Goo(A x) where T : {constraint} + {{ Bar(x); - } + }} - private static void Bar(A x) where T : class - { + private static void Bar(A x) where T : {constraint} + {{ throw new NotImplementedException(); - } -}"); + }} +}}"); } [WorkItem(542627, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542627")] diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/SpellCheck/SpellCheckTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/SpellCheck/SpellCheckTests.cs index 1145816fded1e..384cef1abd9e1 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/SpellCheck/SpellCheckTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/SpellCheck/SpellCheckTests.cs @@ -564,6 +564,18 @@ void M() var y = [|var|] } +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSpellcheck)] + public async Task TestUnmanagedConstraint() + { + await TestInRegularAndScriptAsync( +@"class C where T : [|umanaged|] +{ +}", +@"class C where T : unmanaged +{ }"); } } diff --git a/src/EditorFeatures/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests.cs b/src/EditorFeatures/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests.cs index dfda238a0aac1..1e5a1c54397fc 100644 --- a/src/EditorFeatures/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests.cs +++ b/src/EditorFeatures/CSharpTest/ImplementAbstractClass/ImplementAbstractClassTests.cs @@ -1681,6 +1681,30 @@ public class [|Test|] : TestParent public class Test : TestParent { public override ref readonly int this[int p] => throw new System.NotImplementedException(); +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] + public async Task TestUnmanagedConstraint() + { + await TestInRegularAndScriptAsync( +@"public abstract class ParentTest +{ + public abstract void M() where T : unmanaged; +} +public class [|Test|] : ParentTest +{ +}", +@"public abstract class ParentTest +{ + public abstract void M() where T : unmanaged; +} +public class Test : ParentTest +{ + public override void M() + { + throw new System.NotImplementedException(); + } }"); } } diff --git a/src/EditorFeatures/CSharpTest/SignatureHelp/GenericNameSignatureHelpProviderTests.cs b/src/EditorFeatures/CSharpTest/SignatureHelp/GenericNameSignatureHelpProviderTests.cs index a2e74367d7f45..0b57e64ae24c5 100644 --- a/src/EditorFeatures/CSharpTest/SignatureHelp/GenericNameSignatureHelpProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/SignatureHelp/GenericNameSignatureHelpProviderTests.cs @@ -624,6 +624,33 @@ void Bar() await TestAsync(markup, expectedOrderedItems); } + [Fact, Trait(Traits.Feature, Traits.Features.SignatureHelp)] + public async Task TestUnmanagedConstraint() + { + var markup = @" + +class C +{ + /// + /// summary headline + /// + /// T documentation + void M(T arg) where T : unmanaged + { + } + + void Bar() + { + [|M<$$|]> + } +}"; + + await TestAsync(markup, new List + { + new SignatureHelpTestItem("void C.M(T arg) where T : unmanaged", "summary headline", "T documentation", currentParameterIndex: 0) + }); + } + #endregion #region "Trigger tests" diff --git a/src/EditorFeatures/Test/RenameTracking/RenameTrackingTaggerProviderTests.cs b/src/EditorFeatures/Test/RenameTracking/RenameTrackingTaggerProviderTests.cs index 12194c9701bd2..948efeaa1e4b3 100644 --- a/src/EditorFeatures/Test/RenameTracking/RenameTrackingTaggerProviderTests.cs +++ b/src/EditorFeatures/Test/RenameTracking/RenameTrackingTaggerProviderTests.cs @@ -1503,5 +1503,48 @@ void M() } } + [WpfFact] + [Trait(Traits.Feature, Traits.Features.RenameTracking)] + public async Task RenameTracking_UnmanagedConstraint_Keyword() + { + var code = @" +class C<T> where T : $$unmanaged +{ +}"; + using (var state = RenameTrackingTestState.Create(code, LanguageNames.CSharp)) + { + await state.AssertNoTag(); + } + } + + [WpfFact] + [Trait(Traits.Feature, Traits.Features.RenameTracking)] + public async Task RenameTracking_UnmanagedConstraint_Type() + { + var code = @" +interface unmanaged +{ +} +class C<T> where T : $$unmanaged +{ +}"; + using (var state = RenameTrackingTestState.Create(code, LanguageNames.CSharp)) + { + state.EditorOperations.InsertText("my"); + + await state.AssertTag("unmanaged", "myunmanaged", invokeAction: true); + + // Make sure the rename completed + var expectedCode = @" +interface myunmanaged +{ +} +class C where T : myunmanaged +{ +}"; + Assert.Equal(expectedCode, state.HostDocument.TextBuffer.CurrentSnapshot.GetText()); + await state.AssertNoTag(); + } + } } } diff --git a/src/EditorFeatures/Test2/GoToDefinition/GoToDefinitionTests.vb b/src/EditorFeatures/Test2/GoToDefinition/GoToDefinitionTests.vb index d0c0670850b3e..165b462d21b74 100644 --- a/src/EditorFeatures/Test2/GoToDefinition/GoToDefinitionTests.vb +++ b/src/EditorFeatures/Test2/GoToDefinition/GoToDefinitionTests.vb @@ -813,6 +813,41 @@ class C Test(workspace) End Sub + + Public Sub TestCSharpGoToUnmanaged_Keyword() + Dim workspace = + + + + class C<T> where T : un$$managed + { + } + + + + + Test(workspace, expectedResult:=False) + End Sub + + + Public Sub TestCSharpGoToUnmanaged_Type() + Dim workspace = + + + + interface [|unmanaged|] + { + } + class C<T> where T : un$$managed + { + } + + + + + Test(workspace) + End Sub + #End Region #Region "CSharp TupleTests" diff --git a/src/Features/CSharp/Portable/SignatureHelp/GenericNameSignatureHelpProvider.cs b/src/Features/CSharp/Portable/SignatureHelp/GenericNameSignatureHelpProvider.cs index 918c99e3c1b4c..52fa63c540f22 100644 --- a/src/Features/CSharp/Portable/SignatureHelp/GenericNameSignatureHelpProvider.cs +++ b/src/Features/CSharp/Portable/SignatureHelp/GenericNameSignatureHelpProvider.cs @@ -247,6 +247,11 @@ private IList GetSelectedDisplayParts( parts.Add(Keyword(SyntaxKind.ClassKeyword)); needComma = true; } + else if (typeParam.HasUnmanagedTypeConstraint) + { + parts.Add(new SymbolDisplayPart(SymbolDisplayPartKind.Keyword, null, "unmanaged")); + needComma = true; + } else if (typeParam.HasValueTypeConstraint) { parts.Add(Keyword(SyntaxKind.StructKeyword)); diff --git a/src/Workspaces/CoreTest/FindReferencesTests.cs b/src/Workspaces/CoreTest/FindReferencesTests.cs index 74d5f62d8efe1..02f69357369b4 100644 --- a/src/Workspaces/CoreTest/FindReferencesTests.cs +++ b/src/Workspaces/CoreTest/FindReferencesTests.cs @@ -320,6 +320,26 @@ public override void SomeMethod() { } Assert.Equal(refsFromVirtualSorted, refsFromOverrideSorted); } + [Fact] + public async Task FindRefereceToUnmanagedConstraint_Type() + { + var text = @" +interface unmanaged // Line 1 +{ +} +abstract class C where T : unmanaged // Line 4 +{ +}"; + var solution = GetSingleDocumentSolution(text); + var project = solution.Projects.First(); + var comp = await project.GetCompilationAsync(); + + var constraint = comp.GetTypeByMetadataName("C`1").TypeParameters.Single().ConstraintTypes.Single(); + var result = (await SymbolFinder.FindReferencesAsync(constraint, solution)).Single(); + + Verify(result, new HashSet { 1, 4 }); + } + private static void Verify(ReferencedSymbol reference, HashSet expectedMatchedLines) { void verifier(Location location) From 19f6a2dd5d7183f67467035e54eed6f77374cc1f Mon Sep 17 00:00:00 2001 From: Omar Tawfik Date: Sat, 3 Mar 2018 20:12:11 +0200 Subject: [PATCH 06/13] PR comments --- .../AbstractCSharpClassifierTests.cs | 8 +-- .../Classification/SemanticClassifierTests.cs | 6 ++- .../SyntacticClassifierTests.cs | 8 ++- .../Classification/TotalClassifierTests.cs | 8 ++- .../UpgradeProject/UpgradeProjectTests.cs | 50 +++++++++++++++++++ ...tionBuilder.OperatorClassificationTypes.cs | 9 ++++ .../NameSyntaxClassifier.cs | 9 +++- 7 files changed, 87 insertions(+), 11 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/Classification/AbstractCSharpClassifierTests.cs b/src/EditorFeatures/CSharpTest/Classification/AbstractCSharpClassifierTests.cs index f7a9be5667bd4..f362b3bbcf9d1 100644 --- a/src/EditorFeatures/CSharpTest/Classification/AbstractCSharpClassifierTests.cs +++ b/src/EditorFeatures/CSharpTest/Classification/AbstractCSharpClassifierTests.cs @@ -79,11 +79,11 @@ public override string ToString() switch (_text) { case "(": - return "Punctation.OpenParen"; + return "Punctuation.OpenParen"; case ")": - return "Punctation.CloseParen"; + return "Punctuation.CloseParen"; case ";": - return "Punctation.Semicolon"; + return "Punctuation.Semicolon"; case ":": return "Punctuation.Colon"; case ",": @@ -96,6 +96,8 @@ public override string ToString() { case "=": return "Operators.Equals"; + case "++": + return "Operators.DoublePlus"; } goto default; diff --git a/src/EditorFeatures/CSharpTest/Classification/SemanticClassifierTests.cs b/src/EditorFeatures/CSharpTest/Classification/SemanticClassifierTests.cs index b9e30142619d7..8de16a694d166 100644 --- a/src/EditorFeatures/CSharpTest/Classification/SemanticClassifierTests.cs +++ b/src/EditorFeatures/CSharpTest/Classification/SemanticClassifierTests.cs @@ -2329,8 +2329,10 @@ void Main(string s) [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestUnmanagedConstraint_InsideMethod() { - await TestInMethodAsync( - "var unmanaged = 0;", + // Asserts no Keyword("unmanaged") because it is an identifier. + await TestInMethodAsync(@" +var unmanaged = 0; +unmanaged++;", Keyword("var")); } diff --git a/src/EditorFeatures/CSharpTest/Classification/SyntacticClassifierTests.cs b/src/EditorFeatures/CSharpTest/Classification/SyntacticClassifierTests.cs index 127e54bda849d..5c979370d420c 100644 --- a/src/EditorFeatures/CSharpTest/Classification/SyntacticClassifierTests.cs +++ b/src/EditorFeatures/CSharpTest/Classification/SyntacticClassifierTests.cs @@ -4015,12 +4015,16 @@ await TestAsync( [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestUnmanagedConstraint_InsideMethod() { - await TestInMethodAsync( - "var unmanaged = 0;", + await TestInMethodAsync(@" +var unmanaged = 0; +unmanaged++;", Keyword("var"), Identifier("unmanaged"), Operators.Equals, Number("0"), + Punctuation.Semicolon, + Identifier("unmanaged"), + Operators.DoublePlus, Punctuation.Semicolon); } diff --git a/src/EditorFeatures/CSharpTest/Classification/TotalClassifierTests.cs b/src/EditorFeatures/CSharpTest/Classification/TotalClassifierTests.cs index 8b2e97cfb4948..05b711d58df7d 100644 --- a/src/EditorFeatures/CSharpTest/Classification/TotalClassifierTests.cs +++ b/src/EditorFeatures/CSharpTest/Classification/TotalClassifierTests.cs @@ -853,12 +853,16 @@ class Program : IReadOnlyCollection [Fact, Trait(Traits.Feature, Traits.Features.Classification)] public async Task TestUnmanagedConstraint_InsideMethod() { - await TestInMethodAsync( - "var unmanaged = 0;", + await TestInMethodAsync(@" +var unmanaged = 0; +unmanaged++;", Keyword("var"), Identifier("unmanaged"), Operators.Equals, Number("0"), + Punctuation.Semicolon, + Identifier("unmanaged"), + Operators.DoublePlus, Punctuation.Semicolon); } diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs index 9ed4cf918ee4c..54c81348bbf26 100644 --- a/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs +++ b/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs @@ -486,6 +486,23 @@ class Test where T : [|unmanaged|] index: 1); } + [Fact] + public async Task UpgradeProjectWithUnmanagedConstraintTo7_3_Type_AlreadyDefined() + { + await TestExactActionSetOfferedAsync( +@" + + +interface unmanaged { } +class Test<T> where T : [|unmanaged|] +{ +} + + +", + expectedActionSet: Enumerable.Empty()); + } + [Fact] public async Task UpgradeProjectWithUnmanagedConstraintTo7_3_Method() { @@ -500,6 +517,24 @@ public void M() where T : [|unmanaged|] { } index: 1); } + [Fact] + public async Task UpgradeProjectWithUnmanagedConstraintTo7_3_Method_AlreadyDefined() + { + await TestExactActionSetOfferedAsync( +@" + + +interface unmanaged { } +class Test +{ + public void M<T>() where T : [|unmanaged|] { } +} + + +", + expectedActionSet: Enumerable.Empty()); + } + [Fact] public async Task UpgradeProjectWithUnmanagedConstraintTo7_3_Delegate() { @@ -509,5 +544,20 @@ await TestLanguageVersionUpgradedAsync( new CSharpParseOptions(LanguageVersion.CSharp7), index: 1); } + + [Fact] + public async Task UpgradeProjectWithUnmanagedConstraintTo7_3_Delegate_AlreadyDefined() + { + await TestExactActionSetOfferedAsync( +@" + + +interface unmanaged { } +delegate void D<T>() where T : [| unmanaged |]; + + +", + expectedActionSet: Enumerable.Empty()); + } } } diff --git a/src/EditorFeatures/TestUtilities/Classification/ClassificationBuilder.OperatorClassificationTypes.cs b/src/EditorFeatures/TestUtilities/Classification/ClassificationBuilder.OperatorClassificationTypes.cs index 1f3787804457e..f97a512db942b 100644 --- a/src/EditorFeatures/TestUtilities/Classification/ClassificationBuilder.OperatorClassificationTypes.cs +++ b/src/EditorFeatures/TestUtilities/Classification/ClassificationBuilder.OperatorClassificationTypes.cs @@ -42,6 +42,15 @@ public Tuple DoubleEquals } } + public Tuple DoublePlus + { + [DebuggerStepThrough] + get + { + return New("++"); + } + } + public Tuple DoublePipe { [DebuggerStepThrough] diff --git a/src/Workspaces/CSharp/Portable/Classification/SyntaxClassification/NameSyntaxClassifier.cs b/src/Workspaces/CSharp/Portable/Classification/SyntaxClassification/NameSyntaxClassifier.cs index 30f399c776b71..2a3000da6ae48 100644 --- a/src/Workspaces/CSharp/Portable/Classification/SyntaxClassification/NameSyntaxClassifier.cs +++ b/src/Workspaces/CSharp/Portable/Classification/SyntaxClassification/NameSyntaxClassifier.cs @@ -297,12 +297,17 @@ private bool TryClassifyNameOfIdentifier( private bool IsSymbolWithName(ISymbol symbol, string name) { + if (symbol is null || symbol.Name != name) + { + return false; + } + if (symbol is INamedTypeSymbol namedType) { - return namedType.Arity == 0 && symbol.Name == name; + return namedType.Arity == 0; } - return symbol != null && symbol.Name == name; + return true; } } } From 95f34175dd9c58c36b7e6c2c1855da92069e853a Mon Sep 17 00:00:00 2001 From: Omar Tawfik Date: Tue, 6 Mar 2018 21:53:07 +0800 Subject: [PATCH 07/13] Verify bad parameter symbols from VB side --- .../SymbolsTests/Metadata/PE/LoadCustomModifiers.vb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Metadata/PE/LoadCustomModifiers.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Metadata/PE/LoadCustomModifiers.vb index 7ccf513b2ddcd..5a3e7fa72272f 100644 --- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Metadata/PE/LoadCustomModifiers.vb +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Metadata/PE/LoadCustomModifiers.vb @@ -134,6 +134,9 @@ BC32105: Type argument 'String' does not satisfy the 'Structure' constraint for Dim x = New TestRef(Of String)() ~~~~~~ ) + + Dim badTypeParameter = compilation.GetTypeByMetadataName("TestRef`1").TypeParameters.Single() + Assert.True(badTypeParameter.HasValueTypeConstraint) End Sub @@ -165,6 +168,9 @@ BC30649: '' is an unsupported type. x.M(Of String)() ~~~~~~~~~~~~~~~~ ) + + Dim badTypeParameter = compilation.GetTypeByMetadataName("TestRef").GetMethod("M").TypeParameters.Single() + Assert.True(badTypeParameter.HasValueTypeConstraint) End Sub @@ -196,6 +202,9 @@ BC32105: Type argument 'String' does not satisfy the 'Structure' constraint for Shared Sub Main(del As D(Of String)) ~~~ ) + + Dim badTypeParameter = compilation.GetTypeByMetadataName("D`1").TypeParameters.Single() + Assert.True(badTypeParameter.HasValueTypeConstraint) End Sub End Class From c912526ceb35926f321e0087ae13793d17ace5e8 Mon Sep 17 00:00:00 2001 From: vsadov Date: Wed, 7 Mar 2018 10:20:17 -0800 Subject: [PATCH 08/13] merge from features/compiler ito features/constraints --- .../CSharp/Portable/Errors/MessageID.cs | 7 +- .../CSharp/Portable/PublicAPI.Unshipped.txt | 3 +- .../Metadata/PE/PETypeParameterSymbol.cs | 6 +- .../Portable/xlf/CSharpResources.cs.xlf | 40 +++ .../Portable/xlf/CSharpResources.de.xlf | 40 +++ .../Portable/xlf/CSharpResources.es.xlf | 40 +++ .../Portable/xlf/CSharpResources.fr.xlf | 40 +++ .../Portable/xlf/CSharpResources.it.xlf | 40 +++ .../Portable/xlf/CSharpResources.ja.xlf | 40 +++ .../Portable/xlf/CSharpResources.ko.xlf | 40 +++ .../Portable/xlf/CSharpResources.pl.xlf | 40 +++ .../Portable/xlf/CSharpResources.pt-BR.xlf | 40 +++ .../Portable/xlf/CSharpResources.ru.xlf | 40 +++ .../Portable/xlf/CSharpResources.tr.xlf | 40 +++ .../Portable/xlf/CSharpResources.zh-Hans.xlf | 40 +++ .../Portable/xlf/CSharpResources.zh-Hant.xlf | 40 +++ .../Attributes/AttributeTests_IsUnmanaged.cs | 48 +-- .../Emit/Emit/UnmanagedTypeModifierTests.cs | 99 ++++--- .../Semantics/GenericConstraintsTests.cs | 280 +++++++++--------- .../Core/Portable/PublicAPI.Unshipped.txt | 1 + .../SymbolsTests/GenericConstraintTests.vb | 6 +- .../Metadata/PE/LoadCustomModifiers.vb | 6 +- .../Classification/SemanticClassifierTests.cs | 3 +- .../SyntacticClassifierTests.cs | 10 +- .../Classification/TotalClassifierTests.cs | 12 +- .../Classification/FormattedClassification.cs | 2 + 26 files changed, 774 insertions(+), 229 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs index bf5a948fba7f5..a1d8e4adc4abd 100644 --- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs +++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs @@ -149,10 +149,9 @@ internal enum MessageID IDS_FeatureRefConditional = MessageBase + 12731, IDS_FeatureAttributesOnBackingFields = MessageBase + 12732, IDS_FeatureImprovedOverloadCandidates = MessageBase + 12733, - IDS_FeatureAttributesOnBackingFields = MessageBase + 12734, - IDS_FeatureEnumGenericTypeConstraint = MessageBase + 12735, - IDS_FeatureDelegateGenericTypeConstraint = MessageBase + 12736, - IDS_FeatureUnmanagedGenericTypeConstraint = MessageBase + 12737, + IDS_FeatureEnumGenericTypeConstraint = MessageBase + 12734, + IDS_FeatureDelegateGenericTypeConstraint = MessageBase + 12735, + IDS_FeatureUnmanagedGenericTypeConstraint = MessageBase + 12736, } // Message IDs may refer to strings that need to be localized. diff --git a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt index 90241730d320d..b3ca14527c7d8 100644 --- a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt @@ -1,10 +1,10 @@ +*REMOVED*Microsoft.CodeAnalysis.CSharp.CSharpCompilationOptions.CSharpCompilationOptions(Microsoft.CodeAnalysis.OutputKind outputKind, bool reportSuppressedDiagnostics = false, string moduleName = null, string mainTypeName = null, string scriptClassName = null, System.Collections.Generic.IEnumerable usings = null, Microsoft.CodeAnalysis.OptimizationLevel optimizationLevel = Microsoft.CodeAnalysis.OptimizationLevel.Debug, bool checkOverflow = false, bool allowUnsafe = false, string cryptoKeyContainer = null, string cryptoKeyFile = null, System.Collections.Immutable.ImmutableArray cryptoPublicKey = default(System.Collections.Immutable.ImmutableArray), bool? delaySign = null, Microsoft.CodeAnalysis.Platform platform = Microsoft.CodeAnalysis.Platform.AnyCpu, Microsoft.CodeAnalysis.ReportDiagnostic generalDiagnosticOption = Microsoft.CodeAnalysis.ReportDiagnostic.Default, int warningLevel = 4, System.Collections.Generic.IEnumerable> specificDiagnosticOptions = null, bool concurrentBuild = true, bool deterministic = false, Microsoft.CodeAnalysis.XmlReferenceResolver xmlReferenceResolver = null, Microsoft.CodeAnalysis.SourceReferenceResolver sourceReferenceResolver = null, Microsoft.CodeAnalysis.MetadataReferenceResolver metadataReferenceResolver = null, Microsoft.CodeAnalysis.AssemblyIdentityComparer assemblyIdentityComparer = null, Microsoft.CodeAnalysis.StrongNameProvider strongNameProvider = null, bool publicSign = false) -> void *REMOVED*Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax.Update(Microsoft.CodeAnalysis.CSharp.Syntax.NameColonSyntax nameColon, Microsoft.CodeAnalysis.SyntaxToken refOrOutKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expression) -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax *REMOVED*Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax.WithRefKindKeyword(Microsoft.CodeAnalysis.SyntaxToken refOrOutKeyword) -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax *REMOVED*Microsoft.CodeAnalysis.CSharp.Syntax.CrefParameterSyntax.Update(Microsoft.CodeAnalysis.SyntaxToken refOrOutKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type) -> Microsoft.CodeAnalysis.CSharp.Syntax.CrefParameterSyntax *REMOVED*static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.Argument(Microsoft.CodeAnalysis.CSharp.Syntax.NameColonSyntax nameColon, Microsoft.CodeAnalysis.SyntaxToken refOrOutKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expression) -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax *REMOVED*static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.CrefParameter(Microsoft.CodeAnalysis.SyntaxToken refOrOutKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type) -> Microsoft.CodeAnalysis.CSharp.Syntax.CrefParameterSyntax Microsoft.CodeAnalysis.CSharp.CSharpCompilationOptions.CSharpCompilationOptions(Microsoft.CodeAnalysis.OutputKind outputKind, bool reportSuppressedDiagnostics = false, string moduleName = null, string mainTypeName = null, string scriptClassName = null, System.Collections.Generic.IEnumerable usings = null, Microsoft.CodeAnalysis.OptimizationLevel optimizationLevel = Microsoft.CodeAnalysis.OptimizationLevel.Debug, bool checkOverflow = false, bool allowUnsafe = false, string cryptoKeyContainer = null, string cryptoKeyFile = null, System.Collections.Immutable.ImmutableArray cryptoPublicKey = default(System.Collections.Immutable.ImmutableArray), bool? delaySign = null, Microsoft.CodeAnalysis.Platform platform = Microsoft.CodeAnalysis.Platform.AnyCpu, Microsoft.CodeAnalysis.ReportDiagnostic generalDiagnosticOption = Microsoft.CodeAnalysis.ReportDiagnostic.Default, int warningLevel = 4, System.Collections.Generic.IEnumerable> specificDiagnosticOptions = null, bool concurrentBuild = true, bool deterministic = false, Microsoft.CodeAnalysis.XmlReferenceResolver xmlReferenceResolver = null, Microsoft.CodeAnalysis.SourceReferenceResolver sourceReferenceResolver = null, Microsoft.CodeAnalysis.MetadataReferenceResolver metadataReferenceResolver = null, Microsoft.CodeAnalysis.AssemblyIdentityComparer assemblyIdentityComparer = null, Microsoft.CodeAnalysis.StrongNameProvider strongNameProvider = null, bool publicSign = false, Microsoft.CodeAnalysis.MetadataImportOptions metadataImportOptions = Microsoft.CodeAnalysis.MetadataImportOptions.Public) -> void -*REMOVED*Microsoft.CodeAnalysis.CSharp.CSharpCompilationOptions.CSharpCompilationOptions(Microsoft.CodeAnalysis.OutputKind outputKind, bool reportSuppressedDiagnostics = false, string moduleName = null, string mainTypeName = null, string scriptClassName = null, System.Collections.Generic.IEnumerable usings = null, Microsoft.CodeAnalysis.OptimizationLevel optimizationLevel = Microsoft.CodeAnalysis.OptimizationLevel.Debug, bool checkOverflow = false, bool allowUnsafe = false, string cryptoKeyContainer = null, string cryptoKeyFile = null, System.Collections.Immutable.ImmutableArray cryptoPublicKey = default(System.Collections.Immutable.ImmutableArray), bool? delaySign = null, Microsoft.CodeAnalysis.Platform platform = Microsoft.CodeAnalysis.Platform.AnyCpu, Microsoft.CodeAnalysis.ReportDiagnostic generalDiagnosticOption = Microsoft.CodeAnalysis.ReportDiagnostic.Default, int warningLevel = 4, System.Collections.Generic.IEnumerable> specificDiagnosticOptions = null, bool concurrentBuild = true, bool deterministic = false, Microsoft.CodeAnalysis.XmlReferenceResolver xmlReferenceResolver = null, Microsoft.CodeAnalysis.SourceReferenceResolver sourceReferenceResolver = null, Microsoft.CodeAnalysis.MetadataReferenceResolver metadataReferenceResolver = null, Microsoft.CodeAnalysis.AssemblyIdentityComparer assemblyIdentityComparer = null, Microsoft.CodeAnalysis.StrongNameProvider strongNameProvider = null, bool publicSign = false) -> void Microsoft.CodeAnalysis.CSharp.CSharpCompilationOptions.CSharpCompilationOptions(Microsoft.CodeAnalysis.OutputKind outputKind, bool reportSuppressedDiagnostics, string moduleName, string mainTypeName, string scriptClassName, System.Collections.Generic.IEnumerable usings, Microsoft.CodeAnalysis.OptimizationLevel optimizationLevel, bool checkOverflow, bool allowUnsafe, string cryptoKeyContainer, string cryptoKeyFile, System.Collections.Immutable.ImmutableArray cryptoPublicKey, bool? delaySign, Microsoft.CodeAnalysis.Platform platform, Microsoft.CodeAnalysis.ReportDiagnostic generalDiagnosticOption, int warningLevel, System.Collections.Generic.IEnumerable> specificDiagnosticOptions, bool concurrentBuild, bool deterministic, Microsoft.CodeAnalysis.XmlReferenceResolver xmlReferenceResolver, Microsoft.CodeAnalysis.SourceReferenceResolver sourceReferenceResolver, Microsoft.CodeAnalysis.MetadataReferenceResolver metadataReferenceResolver, Microsoft.CodeAnalysis.AssemblyIdentityComparer assemblyIdentityComparer, Microsoft.CodeAnalysis.StrongNameProvider strongNameProvider, bool publicSign) -> void Microsoft.CodeAnalysis.CSharp.CSharpCompilationOptions.WithMetadataImportOptions(Microsoft.CodeAnalysis.MetadataImportOptions value) -> Microsoft.CodeAnalysis.CSharp.CSharpCompilationOptions Microsoft.CodeAnalysis.CSharp.DeconstructionInfo @@ -18,6 +18,7 @@ Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax.WithRefKindKeyword(Microsoft Microsoft.CodeAnalysis.CSharp.Syntax.CrefParameterSyntax.RefKindKeyword.get -> Microsoft.CodeAnalysis.SyntaxToken Microsoft.CodeAnalysis.CSharp.Syntax.CrefParameterSyntax.Update(Microsoft.CodeAnalysis.SyntaxToken refKindKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type) -> Microsoft.CodeAnalysis.CSharp.Syntax.CrefParameterSyntax Microsoft.CodeAnalysis.CSharp.Syntax.CrefParameterSyntax.WithRefKindKeyword(Microsoft.CodeAnalysis.SyntaxToken refKindKeyword) -> Microsoft.CodeAnalysis.CSharp.Syntax.CrefParameterSyntax +Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax.IsUnmanaged.get -> bool static Microsoft.CodeAnalysis.CSharp.CSharpCommandLineParser.Script.get -> Microsoft.CodeAnalysis.CSharp.CSharpCommandLineParser static Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeconstructionInfo(this Microsoft.CodeAnalysis.SemanticModel semanticModel, Microsoft.CodeAnalysis.CSharp.Syntax.AssignmentExpressionSyntax assignment) -> Microsoft.CodeAnalysis.CSharp.DeconstructionInfo static Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeconstructionInfo(this Microsoft.CodeAnalysis.SemanticModel semanticModel, Microsoft.CodeAnalysis.CSharp.Syntax.ForEachVariableStatementSyntax foreach) -> Microsoft.CodeAnalysis.CSharp.DeconstructionInfo diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.cs index 6c16f53dce4d5..0c8f856c40ad4 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.cs @@ -338,7 +338,11 @@ public override ImmutableArray GetAttributes() this.Handle, out CustomAttributeHandle isUnmanagedAttribute, AttributeDescription.IsUnmanagedAttribute, - out _, + out _, + default, + out _, + default, + out _, default); this._lazyHasIsUnmanagedAttribute = (!isUnmanagedAttribute.IsNil).ToThreeState(); diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index db653a61c65af..99fff2a3e36f7 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -8620,6 +8620,46 @@ Pokud chcete odstranit toto varování, můžete místo toho použít /reference Invalid hash algorithm name: '{0}' + + enum generic type constraints + enum generic type constraints + + + + delegate generic type constraints + delegate generic type constraints + + + + unmanaged generic type constraints + unmanaged generic type constraints + + + + The 'new()' constraint cannot be used with the 'unmanaged' constraint + The 'new()' constraint cannot be used with the 'unmanaged' constraint + + + + The 'unmanaged' constraint cannot be specified with other constraints. + The 'unmanaged' constraint cannot be specified with other constraints. + + + + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + + + + Using 'unmanaged' constraint on local functions type parameters is not supported. + Using 'unmanaged' constraint on local functions type parameters is not supported. + + + + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index d8334b79922ab..99a73391356d9 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -8620,6 +8620,46 @@ Um die Warnung zu beheben, können Sie stattdessen /reference verwenden (Einbett Invalid hash algorithm name: '{0}' + + enum generic type constraints + enum generic type constraints + + + + delegate generic type constraints + delegate generic type constraints + + + + unmanaged generic type constraints + unmanaged generic type constraints + + + + The 'new()' constraint cannot be used with the 'unmanaged' constraint + The 'new()' constraint cannot be used with the 'unmanaged' constraint + + + + The 'unmanaged' constraint cannot be specified with other constraints. + The 'unmanaged' constraint cannot be specified with other constraints. + + + + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + + + + Using 'unmanaged' constraint on local functions type parameters is not supported. + Using 'unmanaged' constraint on local functions type parameters is not supported. + + + + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index a14abc7a4a1ed..8372af2e9e8b2 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -8620,6 +8620,46 @@ Para eliminar la advertencia puede usar /reference (establezca la propiedad Embe Invalid hash algorithm name: '{0}' + + enum generic type constraints + enum generic type constraints + + + + delegate generic type constraints + delegate generic type constraints + + + + unmanaged generic type constraints + unmanaged generic type constraints + + + + The 'new()' constraint cannot be used with the 'unmanaged' constraint + The 'new()' constraint cannot be used with the 'unmanaged' constraint + + + + The 'unmanaged' constraint cannot be specified with other constraints. + The 'unmanaged' constraint cannot be specified with other constraints. + + + + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + + + + Using 'unmanaged' constraint on local functions type parameters is not supported. + Using 'unmanaged' constraint on local functions type parameters is not supported. + + + + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 95bcf6690654c..62c97e0fe3df0 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -8620,6 +8620,46 @@ Pour supprimer l'avertissement, vous pouvez utiliser la commande /reference (dé Invalid hash algorithm name: '{0}' + + enum generic type constraints + enum generic type constraints + + + + delegate generic type constraints + delegate generic type constraints + + + + unmanaged generic type constraints + unmanaged generic type constraints + + + + The 'new()' constraint cannot be used with the 'unmanaged' constraint + The 'new()' constraint cannot be used with the 'unmanaged' constraint + + + + The 'unmanaged' constraint cannot be specified with other constraints. + The 'unmanaged' constraint cannot be specified with other constraints. + + + + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + + + + Using 'unmanaged' constraint on local functions type parameters is not supported. + Using 'unmanaged' constraint on local functions type parameters is not supported. + + + + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 2ff1be727314c..b7af13b999e90 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -8620,6 +8620,46 @@ Per rimuovere l'avviso, è invece possibile usare /reference (impostare la propr Invalid hash algorithm name: '{0}' + + enum generic type constraints + enum generic type constraints + + + + delegate generic type constraints + delegate generic type constraints + + + + unmanaged generic type constraints + unmanaged generic type constraints + + + + The 'new()' constraint cannot be used with the 'unmanaged' constraint + The 'new()' constraint cannot be used with the 'unmanaged' constraint + + + + The 'unmanaged' constraint cannot be specified with other constraints. + The 'unmanaged' constraint cannot be specified with other constraints. + + + + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + + + + Using 'unmanaged' constraint on local functions type parameters is not supported. + Using 'unmanaged' constraint on local functions type parameters is not supported. + + + + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index c3ecb93739b26..626687f28377e 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -8620,6 +8620,46 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Invalid hash algorithm name: '{0}' + + enum generic type constraints + enum generic type constraints + + + + delegate generic type constraints + delegate generic type constraints + + + + unmanaged generic type constraints + unmanaged generic type constraints + + + + The 'new()' constraint cannot be used with the 'unmanaged' constraint + The 'new()' constraint cannot be used with the 'unmanaged' constraint + + + + The 'unmanaged' constraint cannot be specified with other constraints. + The 'unmanaged' constraint cannot be specified with other constraints. + + + + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + + + + Using 'unmanaged' constraint on local functions type parameters is not supported. + Using 'unmanaged' constraint on local functions type parameters is not supported. + + + + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 10da4795b62dc..1e5432223ba54 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -8620,6 +8620,46 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Invalid hash algorithm name: '{0}' + + enum generic type constraints + enum generic type constraints + + + + delegate generic type constraints + delegate generic type constraints + + + + unmanaged generic type constraints + unmanaged generic type constraints + + + + The 'new()' constraint cannot be used with the 'unmanaged' constraint + The 'new()' constraint cannot be used with the 'unmanaged' constraint + + + + The 'unmanaged' constraint cannot be specified with other constraints. + The 'unmanaged' constraint cannot be specified with other constraints. + + + + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + + + + Using 'unmanaged' constraint on local functions type parameters is not supported. + Using 'unmanaged' constraint on local functions type parameters is not supported. + + + + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 1d8fb4457a3aa..a10a478a3b5f0 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -8620,6 +8620,46 @@ Aby usunąć ostrzeżenie, możesz zamiast tego użyć opcji /reference (ustaw w Invalid hash algorithm name: '{0}' + + enum generic type constraints + enum generic type constraints + + + + delegate generic type constraints + delegate generic type constraints + + + + unmanaged generic type constraints + unmanaged generic type constraints + + + + The 'new()' constraint cannot be used with the 'unmanaged' constraint + The 'new()' constraint cannot be used with the 'unmanaged' constraint + + + + The 'unmanaged' constraint cannot be specified with other constraints. + The 'unmanaged' constraint cannot be specified with other constraints. + + + + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + + + + Using 'unmanaged' constraint on local functions type parameters is not supported. + Using 'unmanaged' constraint on local functions type parameters is not supported. + + + + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 0eed3fd3c5579..daf2f701c96a2 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -8620,6 +8620,46 @@ Para incorporar informações de tipo de interoperabilidade para os dois assembl Invalid hash algorithm name: '{0}' + + enum generic type constraints + enum generic type constraints + + + + delegate generic type constraints + delegate generic type constraints + + + + unmanaged generic type constraints + unmanaged generic type constraints + + + + The 'new()' constraint cannot be used with the 'unmanaged' constraint + The 'new()' constraint cannot be used with the 'unmanaged' constraint + + + + The 'unmanaged' constraint cannot be specified with other constraints. + The 'unmanaged' constraint cannot be specified with other constraints. + + + + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + + + + Using 'unmanaged' constraint on local functions type parameters is not supported. + Using 'unmanaged' constraint on local functions type parameters is not supported. + + + + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index dbaf2fc7d917a..9a557897d7489 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -8620,6 +8620,46 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Invalid hash algorithm name: '{0}' + + enum generic type constraints + enum generic type constraints + + + + delegate generic type constraints + delegate generic type constraints + + + + unmanaged generic type constraints + unmanaged generic type constraints + + + + The 'new()' constraint cannot be used with the 'unmanaged' constraint + The 'new()' constraint cannot be used with the 'unmanaged' constraint + + + + The 'unmanaged' constraint cannot be specified with other constraints. + The 'unmanaged' constraint cannot be specified with other constraints. + + + + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + + + + Using 'unmanaged' constraint on local functions type parameters is not supported. + Using 'unmanaged' constraint on local functions type parameters is not supported. + + + + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index a8e681ff00aa6..8bdec0f9242ea 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -8620,6 +8620,46 @@ Uyarıyı kaldırmak için, /reference kullanabilirsiniz (Birlikte Çalışma T Invalid hash algorithm name: '{0}' + + enum generic type constraints + enum generic type constraints + + + + delegate generic type constraints + delegate generic type constraints + + + + unmanaged generic type constraints + unmanaged generic type constraints + + + + The 'new()' constraint cannot be used with the 'unmanaged' constraint + The 'new()' constraint cannot be used with the 'unmanaged' constraint + + + + The 'unmanaged' constraint cannot be specified with other constraints. + The 'unmanaged' constraint cannot be specified with other constraints. + + + + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + + + + Using 'unmanaged' constraint on local functions type parameters is not supported. + Using 'unmanaged' constraint on local functions type parameters is not supported. + + + + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index ad89236056c58..d8168558c8764 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -8620,6 +8620,46 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Invalid hash algorithm name: '{0}' + + enum generic type constraints + enum generic type constraints + + + + delegate generic type constraints + delegate generic type constraints + + + + unmanaged generic type constraints + unmanaged generic type constraints + + + + The 'new()' constraint cannot be used with the 'unmanaged' constraint + The 'new()' constraint cannot be used with the 'unmanaged' constraint + + + + The 'unmanaged' constraint cannot be specified with other constraints. + The 'unmanaged' constraint cannot be specified with other constraints. + + + + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + + + + Using 'unmanaged' constraint on local functions type parameters is not supported. + Using 'unmanaged' constraint on local functions type parameters is not supported. + + + + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 2f16d8e5972e8..5d4f335832f32 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -8620,6 +8620,46 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Invalid hash algorithm name: '{0}' + + enum generic type constraints + enum generic type constraints + + + + delegate generic type constraints + delegate generic type constraints + + + + unmanaged generic type constraints + unmanaged generic type constraints + + + + The 'new()' constraint cannot be used with the 'unmanaged' constraint + The 'new()' constraint cannot be used with the 'unmanaged' constraint + + + + The 'unmanaged' constraint cannot be specified with other constraints. + The 'unmanaged' constraint cannot be specified with other constraints. + + + + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' + + + + Using 'unmanaged' constraint on local functions type parameters is not supported. + Using 'unmanaged' constraint on local functions type parameters is not supported. + + + + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_IsUnmanaged.cs b/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_IsUnmanaged.cs index a7c38d6729b40..c1a05e8b519d9 100644 --- a/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_IsUnmanaged.cs +++ b/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_IsUnmanaged.cs @@ -69,7 +69,7 @@ public class Test where T : unmanaged [Fact] public void AttributeUsedIfExists_FromReference_Method_Reference() { - var reference = CreateStandardCompilation(@" + var reference = CreateCompilation(@" namespace System.Runtime.CompilerServices { public class IsUnmanagedAttribute : System.Attribute { } @@ -82,7 +82,7 @@ public void M() where T : unmanaged { } } "; - CompileAndVerify(text, additionalRefs: new[] { reference }, symbolValidator: module => + CompileAndVerify(text, references: new[] { reference }, symbolValidator: module => { var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("M").TypeParameters.Single(); Assert.True(typeParameter.HasValueTypeConstraint); @@ -96,7 +96,7 @@ public void M() where T : unmanaged { } [Fact] public void AttributeUsedIfExists_FromReference_Class_Reference() { - var reference = CreateStandardCompilation(@" + var reference = CreateCompilation(@" namespace System.Runtime.CompilerServices { public class IsUnmanagedAttribute : System.Attribute { } @@ -108,7 +108,7 @@ public class Test where T : unmanaged } "; - CompileAndVerify(text, additionalRefs: new[] { reference }, symbolValidator: module => + CompileAndVerify(text, references: new[] { reference }, symbolValidator: module => { var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Test`1").TypeParameters.Single(); Assert.True(typeParameter.HasValueTypeConstraint); @@ -122,7 +122,7 @@ public class Test where T : unmanaged [Fact] public void AttributeUsedIfExists_FromReference_Method_Module() { - var reference = CreateStandardCompilation(@" + var reference = CreateCompilation(@" namespace System.Runtime.CompilerServices { public class IsUnmanagedAttribute : System.Attribute { } @@ -135,7 +135,7 @@ public void M() where T : unmanaged { } } "; - CompileAndVerify(text, verify: Verification.Fails, additionalRefs: new[] { reference }, options: TestOptions.ReleaseModule, symbolValidator: module => + CompileAndVerify(text, verify: Verification.Fails, references: new[] { reference }, options: TestOptions.ReleaseModule, symbolValidator: module => { var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Test").GetMethod("M").TypeParameters.Single(); Assert.True(typeParameter.HasValueTypeConstraint); @@ -149,7 +149,7 @@ public void M() where T : unmanaged { } [Fact] public void AttributeUsedIfExists_FromReference_Class_Module() { - var reference = CreateStandardCompilation(@" + var reference = CreateCompilation(@" namespace System.Runtime.CompilerServices { public class IsUnmanagedAttribute : System.Attribute { } @@ -161,7 +161,7 @@ public class Test where T : unmanaged } "; - CompileAndVerify(text, verify: Verification.Fails, additionalRefs: new[] { reference }, options: TestOptions.ReleaseModule, symbolValidator: module => + CompileAndVerify(text, verify: Verification.Fails, references: new[] { reference }, options: TestOptions.ReleaseModule, symbolValidator: module => { var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Test`1").TypeParameters.Single(); Assert.True(typeParameter.HasValueTypeConstraint); @@ -226,7 +226,7 @@ public class IsUnmanagedAttribute : System.Attribute { } public delegate void D([IsUnmanaged]int x); "; - CreateStandardCompilation(code).VerifyDiagnostics( + CreateCompilation(code).VerifyDiagnostics( // (9,2): error CS8335: Do not use 'System.Runtime.CompilerServices.IsUnmanagedAttribute'. This is reserved for compiler usage. // [IsUnmanaged] Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "IsUnmanaged").WithArguments("System.Runtime.CompilerServices.IsUnmanagedAttribute").WithLocation(9, 2), @@ -252,7 +252,7 @@ public class Test } "; - CreateStandardCompilation(code).VerifyDiagnostics( + CreateCompilation(code).VerifyDiagnostics( // (9,2): error CS8335: Do not use 'System.Runtime.CompilerServices.IsUnmanagedAttribute'. This is reserved for compiler usage. // [IsUnmanaged] Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "IsUnmanaged").WithArguments("System.Runtime.CompilerServices.IsUnmanagedAttribute").WithLocation(9, 2)); @@ -276,7 +276,7 @@ public class Test } "; - CreateStandardCompilation(code).VerifyDiagnostics( + CreateCompilation(code).VerifyDiagnostics( // (11,6): error CS8335: Do not use 'System.Runtime.CompilerServices.IsUnmanagedAttribute'. This is reserved for compiler usage. // [IsUnmanaged] Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "IsUnmanaged").WithArguments("System.Runtime.CompilerServices.IsUnmanagedAttribute").WithLocation(11, 6)); @@ -300,7 +300,7 @@ public class Test } "; - CreateStandardCompilation(code).VerifyDiagnostics( + CreateCompilation(code).VerifyDiagnostics( // (11,6): error CS8335: Do not use 'System.Runtime.CompilerServices.IsUnmanagedAttribute'. This is reserved for compiler usage. // [IsUnmanaged] Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "IsUnmanaged").WithArguments("System.Runtime.CompilerServices.IsUnmanagedAttribute").WithLocation(11, 6)); @@ -328,7 +328,7 @@ public int Method([IsUnmanaged]int x) } "; - CreateStandardCompilation(code).VerifyDiagnostics( + CreateCompilation(code).VerifyDiagnostics( // (11,6): error CS8335: Do not use 'System.Runtime.CompilerServices.IsUnmanagedAttribute'. This is reserved for compiler usage. // [IsUnmanaged] Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "IsUnmanaged").WithArguments("System.Runtime.CompilerServices.IsUnmanagedAttribute").WithLocation(11, 6), @@ -358,7 +358,7 @@ public class Test } "; - CreateStandardCompilation(code).VerifyDiagnostics( + CreateCompilation(code).VerifyDiagnostics( // (11,6): error CS8335: Do not use 'System.Runtime.CompilerServices.IsUnmanagedAttribute'. This is reserved for compiler usage. // [IsUnmanaged] Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "IsUnmanaged").WithArguments("System.Runtime.CompilerServices.IsUnmanagedAttribute").WithLocation(11, 6), @@ -377,7 +377,7 @@ public class Test } "; - CreateStandardCompilation(code).VerifyDiagnostics( + CreateCompilation(code).VerifyDiagnostics( // (2,2): error CS0246: The type or namespace name 'IsUnmanagedAttribute' could not be found (are you missing a using directive or an assembly reference?) // [IsUnmanaged] Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "IsUnmanaged").WithArguments("IsUnmanagedAttribute").WithLocation(2, 2), @@ -391,13 +391,13 @@ public void TypeReferencingAnotherTypeThatUsesAPublicAttributeFromAThirdNotRefer { var options = TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All); - var code1 = CreateStandardCompilation(@" + var code1 = CreateCompilation(@" namespace System.Runtime.CompilerServices { public class IsUnmanagedAttribute : System.Attribute { } }"); - var code2 = CreateStandardCompilation(@" + var code2 = CreateCompilation(@" public class Test1 where T : unmanaged { } ", references: new[] { code1.ToMetadataReference() }, options: options); @@ -406,7 +406,7 @@ public class Test1 where T : unmanaged { } AssertNoIsUnmanagedAttributeExists(module.ContainingAssembly); }); - var code3 = CreateStandardCompilation(@" + var code3 = CreateCompilation(@" public class Test2 : Test1 where T : unmanaged { } ", references: new[] { code2.ToMetadataReference() }, options: options); @@ -428,7 +428,7 @@ public class Test where T : unmanaged { }"; - CreateStandardCompilation(code, options: TestOptions.ReleaseModule).VerifyDiagnostics( + CreateCompilation(code, options: TestOptions.ReleaseModule).VerifyDiagnostics( // (2,19): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsUnmanagedAttribute' is not defined or imported // public class Test where T : unmanaged Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "T").WithArguments("System.Runtime.CompilerServices.IsUnmanagedAttribute").WithLocation(2, 19)); @@ -443,7 +443,7 @@ public class Test public void M() where T : unmanaged {} }"; - CreateStandardCompilation(code, options: TestOptions.ReleaseModule).VerifyDiagnostics( + CreateCompilation(code, options: TestOptions.ReleaseModule).VerifyDiagnostics( // (4,19): error CS0518: Predefined type 'System.Runtime.CompilerServices.IsUnmanagedAttribute' is not defined or imported // public void M() where T : unmanaged {} Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "T").WithArguments("System.Runtime.CompilerServices.IsUnmanagedAttribute").WithLocation(4, 19)); @@ -474,7 +474,7 @@ public class Test2 : Test1 where T : unmanaged { }"; - CompileAndVerify(code2, options: options.WithModuleName("Assembly2"), additionalRefs: new[] { comp1.Compilation.ToMetadataReference() }, symbolValidator: module => + CompileAndVerify(code2, options: options.WithModuleName("Assembly2"), references: new[] { comp1.Compilation.ToMetadataReference() }, symbolValidator: module => { var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Test2`1").TypeParameters.Single(); Assert.True(typeParameter.HasValueTypeConstraint); @@ -501,7 +501,7 @@ class Test where T : unmanaged { }"; - CreateStandardCompilation(text, options: new CSharpCompilationOptions(outputKind)).VerifyDiagnostics( + CreateCompilation(text, options: new CSharpCompilationOptions(outputKind)).VerifyDiagnostics( // (9,12): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsUnmanagedAttribute..ctor' // class Test where T : unmanaged Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "T").WithArguments("System.Runtime.CompilerServices.IsUnmanagedAttribute", ".ctor").WithLocation(9, 12)); @@ -524,7 +524,7 @@ class Test where T : unmanaged { }"; - CreateStandardCompilation(text, options: new CSharpCompilationOptions(outputKind)).VerifyDiagnostics( + CreateCompilation(text, options: new CSharpCompilationOptions(outputKind)).VerifyDiagnostics( // (9,12): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsUnmanagedAttribute..ctor' // class Test where T : unmanaged Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "T").WithArguments("System.Runtime.CompilerServices.IsUnmanagedAttribute", ".ctor").WithLocation(9, 12)); @@ -544,7 +544,7 @@ class Test where T : unmanaged { }"; - CreateStandardCompilation(text, options: new CSharpCompilationOptions(outputKind)).VerifyDiagnostics( + CreateCompilation(text, options: new CSharpCompilationOptions(outputKind)).VerifyDiagnostics( // (6,12): error CS0656: Missing compiler required member 'System.Runtime.CompilerServices.IsUnmanagedAttribute..ctor' // class Test where T : unmanaged Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "T").WithArguments("System.Runtime.CompilerServices.IsUnmanagedAttribute", ".ctor").WithLocation(6, 12)); diff --git a/src/Compilers/CSharp/Test/Emit/Emit/UnmanagedTypeModifierTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/UnmanagedTypeModifierTests.cs index 835a4a3ffe17d..5eec86a54c217 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/UnmanagedTypeModifierTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/UnmanagedTypeModifierTests.cs @@ -65,10 +65,11 @@ public static void Main() } }"; - CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( - // (9,9): error CS0570: 'T' is not supported by the language + CreateCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (9,13): error CS0570: 'T' is not supported by the language // obj.M2(); // invalid - Diagnostic(ErrorCode.ERR_BindToBogus, "obj.M2").WithArguments("T").WithLocation(9, 9)); + Diagnostic(ErrorCode.ERR_BindToBogus, "M2").WithArguments("T").WithLocation(9, 13) + ); } [Fact] @@ -127,10 +128,11 @@ public static void Main() } }"; - CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( - // (9,9): error CS0570: 'T' is not supported by the language + CreateCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (9,13): error CS0570: 'T' is not supported by the language // obj.M2(); // invalid - Diagnostic(ErrorCode.ERR_BindToBogus, "obj.M2").WithArguments("T").WithLocation(9, 9)); + Diagnostic(ErrorCode.ERR_BindToBogus, "M2").WithArguments("T").WithLocation(9, 13) + ); } [Fact] @@ -187,10 +189,11 @@ public static void Main() } }"; - CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( - // (9,9): error CS0570: 'T' is not supported by the language + CreateCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (9,13): error CS0570: 'T' is not supported by the language // obj.M2(); // invalid - Diagnostic(ErrorCode.ERR_BindToBogus, "obj.M2").WithArguments("T").WithLocation(9, 9)); + Diagnostic(ErrorCode.ERR_BindToBogus, "M2").WithArguments("T").WithLocation(9, 13) + ); } [Fact] @@ -249,10 +252,11 @@ public static void Main() } }"; - CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( - // (9,9): error CS0570: 'T' is not supported by the language + CreateCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (9,13): error CS0570: 'T' is not supported by the language // obj.M2(); // invalid - Diagnostic(ErrorCode.ERR_BindToBogus, "obj.M2").WithArguments("T").WithLocation(9, 9)); + Diagnostic(ErrorCode.ERR_BindToBogus, "M2").WithArguments("T").WithLocation(9, 13) + ); } [Fact] @@ -269,7 +273,7 @@ class Test where T : unmanaged { }"; - CreateCompilation(code).VerifyDiagnostics( + CreateEmptyCompilation(code).VerifyDiagnostics( // (8,25): error CS0518: Predefined type 'System.Runtime.InteropServices.UnmanagedType' is not defined or imported // class Test where T : unmanaged Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "unmanaged").WithArguments("System.Runtime.InteropServices.UnmanagedType").WithLocation(8, 25)); @@ -290,7 +294,7 @@ class Test public void M() where T : unmanaged {} }"; - CreateCompilation(code).VerifyDiagnostics( + CreateEmptyCompilation(code).VerifyDiagnostics( // (10,34): error CS0518: Predefined type 'System.Runtime.InteropServices.UnmanagedType' is not defined or imported // public void M() where T : unmanaged {} Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "unmanaged").WithArguments("System.Runtime.InteropServices.UnmanagedType").WithLocation(10, 34)); @@ -310,7 +314,7 @@ public class MulticastDelegate {} } public delegate void D() where T : unmanaged;"; - CreateCompilation(code).VerifyDiagnostics( + CreateEmptyCompilation(code).VerifyDiagnostics( // (10,39): error CS0518: Predefined type 'System.Runtime.InteropServices.UnmanagedType' is not defined or imported // public delegate void D() where T : unmanaged; Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "unmanaged").WithArguments("System.Runtime.InteropServices.UnmanagedType").WithLocation(10, 39)); @@ -337,7 +341,7 @@ class Test where T : unmanaged { }"; - CreateCompilation(code).VerifyDiagnostics( + CreateEmptyCompilation(code).VerifyDiagnostics( // (15,25): error CS0518: Predefined type 'System.ValueType' is not defined or imported // class Test where T : unmanaged Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "unmanaged").WithArguments("System.ValueType").WithLocation(15, 25)); @@ -365,7 +369,7 @@ class Test public void M() where T : unmanaged {} }"; - CreateCompilation(code).VerifyDiagnostics( + CreateEmptyCompilation(code).VerifyDiagnostics( // (17,34): error CS0518: Predefined type 'System.ValueType' is not defined or imported // public void M() where T : unmanaged {} Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "unmanaged").WithArguments("System.ValueType").WithLocation(17, 34)); @@ -392,7 +396,7 @@ public class UnmanagedType {} } public delegate void M() where T : unmanaged;"; - CreateCompilation(code).VerifyDiagnostics( + CreateEmptyCompilation(code).VerifyDiagnostics( // (17,39): error CS0518: Predefined type 'System.ValueType' is not defined or imported // public delegate void M() where T : unmanaged; Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "unmanaged").WithArguments("System.ValueType").WithLocation(17, 39)); @@ -432,7 +436,7 @@ public static void Main() System.Console.WriteLine(new Parent().M()); System.Console.WriteLine(new Child().M()); } -}", additionalRefs: new[] { reference.Compilation.EmitToImageReference() }, expectedOutput: @" +}", references: new[] { reference.Compilation.EmitToImageReference() }, expectedOutput: @" Parent Child"); } @@ -458,7 +462,7 @@ public class Parent public class Child : Parent { public override string M() => ""Child""; -}", additionalRefs: new[] { parent.Compilation.EmitToImageReference() }, symbolValidator: module => +}", references: new[] { parent.Compilation.EmitToImageReference() }, symbolValidator: module => { var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Child").GetMethod("M").TypeParameters.Single(); Assert.True(typeParameter.HasValueTypeConstraint); @@ -475,7 +479,7 @@ public static void Main() System.Console.WriteLine(new Parent().M()); System.Console.WriteLine(new Child().M()); } -}", additionalRefs: new[] { parent.Compilation.EmitToImageReference(), child.Compilation.EmitToImageReference() }, expectedOutput: @" +}", references: new[] { parent.Compilation.EmitToImageReference(), child.Compilation.EmitToImageReference() }, expectedOutput: @" Parent Child"); } @@ -513,7 +517,7 @@ public static void Main() { System.Console.WriteLine(new Child().M()); } -}", additionalRefs: new[] { reference.Compilation.EmitToImageReference() }, expectedOutput: "Child"); +}", references: new[] { reference.Compilation.EmitToImageReference() }, expectedOutput: "Child"); } [Fact] @@ -537,7 +541,7 @@ public abstract class Parent public class Child : Parent { public override string M() => ""Child""; -}", additionalRefs: new[] { parent.Compilation.EmitToImageReference() }, symbolValidator: module => +}", references: new[] { parent.Compilation.EmitToImageReference() }, symbolValidator: module => { var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Child").GetMethod("M").TypeParameters.Single(); Assert.True(typeParameter.HasValueTypeConstraint); @@ -553,7 +557,7 @@ public static void Main() { System.Console.WriteLine(new Child().M()); } -}", additionalRefs: new[] { parent.Compilation.EmitToImageReference(), child.Compilation.EmitToImageReference() }, expectedOutput: "Child"); +}", references: new[] { parent.Compilation.EmitToImageReference(), child.Compilation.EmitToImageReference() }, expectedOutput: "Child"); } [Fact] @@ -589,7 +593,7 @@ public static void Main() { System.Console.WriteLine(new Child().M()); } -}", additionalRefs: new[] { reference.Compilation.EmitToImageReference() }, expectedOutput: "Child"); +}", references: new[] { reference.Compilation.EmitToImageReference() }, expectedOutput: "Child"); } [Fact] @@ -613,7 +617,7 @@ public interface Parent public class Child : Parent { public string M() where T : unmanaged => ""Child""; -}", additionalRefs: new[] { parent.Compilation.EmitToImageReference() }, symbolValidator: module => +}", references: new[] { parent.Compilation.EmitToImageReference() }, symbolValidator: module => { var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Child").GetMethod("M").TypeParameters.Single(); Assert.True(typeParameter.HasValueTypeConstraint); @@ -629,7 +633,7 @@ public static void Main() { System.Console.WriteLine(new Child().M()); } -}", additionalRefs: new[] { parent.Compilation.EmitToImageReference(), child.Compilation.EmitToImageReference() }, expectedOutput: "Child"); +}", references: new[] { parent.Compilation.EmitToImageReference(), child.Compilation.EmitToImageReference() }, expectedOutput: "Child"); } [Fact] @@ -665,7 +669,7 @@ public static void Main() { System.Console.WriteLine(new Child().M()); } -}", additionalRefs: new[] { reference.Compilation.EmitToImageReference() }, expectedOutput: "Child"); +}", references: new[] { reference.Compilation.EmitToImageReference() }, expectedOutput: "Child"); } [Fact] @@ -689,7 +693,7 @@ public interface Parent public class Child : Parent { public virtual string M() where T : unmanaged => ""Child""; -}", additionalRefs: new[] { parent.Compilation.EmitToImageReference() }, symbolValidator: module => +}", references: new[] { parent.Compilation.EmitToImageReference() }, symbolValidator: module => { var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Child").GetMethod("M").TypeParameters.Single(); Assert.True(typeParameter.HasValueTypeConstraint); @@ -705,7 +709,7 @@ public static void Main() { System.Console.WriteLine(new Child().M()); } -}", additionalRefs: new[] { parent.Compilation.EmitToImageReference(), child.Compilation.EmitToImageReference() }, expectedOutput: "Child"); +}", references: new[] { parent.Compilation.EmitToImageReference(), child.Compilation.EmitToImageReference() }, expectedOutput: "Child"); } [Fact] @@ -742,7 +746,7 @@ public static void Main() Parent obj = new Child(); System.Console.WriteLine(obj.M()); } -}", additionalRefs: new[] { reference.Compilation.EmitToImageReference() }, expectedOutput: "Child"); +}", references: new[] { reference.Compilation.EmitToImageReference() }, expectedOutput: "Child"); } [Fact] @@ -766,7 +770,7 @@ public interface Parent public class Child : Parent { string Parent.M() => ""Child""; -}", additionalRefs: new[] { parent.Compilation.EmitToImageReference() }, symbolValidator: module => +}", references: new[] { parent.Compilation.EmitToImageReference() }, symbolValidator: module => { var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Child").GetMethod("Parent.M").TypeParameters.Single(); Assert.True(typeParameter.HasValueTypeConstraint); @@ -783,7 +787,7 @@ public static void Main() Parent obj = new Child(); System.Console.WriteLine(obj.M()); } -}", additionalRefs: new[] { parent.Compilation.EmitToImageReference(), child.Compilation.EmitToImageReference() }, expectedOutput: "Child"); +}", references: new[] { parent.Compilation.EmitToImageReference(), child.Compilation.EmitToImageReference() }, expectedOutput: "Child"); } [Fact] @@ -863,7 +867,7 @@ public static void Main() } }", expectedOutput: "5", - additionalRefs: new[] { reference.Compilation.EmitToImageReference() }, + references: new[] { reference.Compilation.EmitToImageReference() }, options: TestOptions.ReleaseExe.WithMetadataImportOptions(MetadataImportOptions.All), symbolValidator: module => { @@ -884,15 +888,15 @@ namespace System.Runtime.InteropServices public class UnmanagedType {} }"; - var ref1 = CreateStandardCompilation(refCode).EmitToImageReference(); - var ref2 = CreateStandardCompilation(refCode).EmitToImageReference(); + var ref1 = CreateCompilation(refCode).EmitToImageReference(); + var ref2 = CreateCompilation(refCode).EmitToImageReference(); var user = @" public class Test where T : unmanaged { }"; - CreateStandardCompilation(user, references: new[] { ref1, ref2 }).VerifyDiagnostics( + CreateCompilation(user, references: new[] { ref1, ref2 }).VerifyDiagnostics( // (2,32): error CS0518: Predefined type 'System.Runtime.InteropServices.UnmanagedType' is not defined or imported // public class Test where T : unmanaged Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "unmanaged").WithArguments("System.Runtime.InteropServices.UnmanagedType").WithLocation(2, 32)); @@ -940,10 +944,11 @@ public static void Main() } }"; - CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( - // (6,9): error CS0570: 'T' is not supported by the language + CreateCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (6,23): error CS0570: 'T' is not supported by the language // new TestRef().M(); - Diagnostic(ErrorCode.ERR_BindToBogus, "new TestRef().M").WithArguments("T").WithLocation(6, 9)); + Diagnostic(ErrorCode.ERR_BindToBogus, "M").WithArguments("T").WithLocation(6, 23) + ); } [Fact] @@ -988,10 +993,11 @@ public static void Main() } }"; - CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( - // (6,9): error CS0570: 'T' is not supported by the language + CreateCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (6,23): error CS0570: 'T' is not supported by the language // new TestRef().M(); - Diagnostic(ErrorCode.ERR_BindToBogus, "new TestRef().M").WithArguments("T").WithLocation(6, 9)); + Diagnostic(ErrorCode.ERR_BindToBogus, "M").WithArguments("T").WithLocation(6, 23) + ); } [Fact] @@ -1036,10 +1042,11 @@ public static void Main() } }"; - CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( - // (6,9): error CS0570: 'T' is not supported by the language + CreateCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (6,23): error CS0570: 'T' is not supported by the language // new TestRef().M(); - Diagnostic(ErrorCode.ERR_BindToBogus, "new TestRef().M").WithArguments("T").WithLocation(6, 9)); + Diagnostic(ErrorCode.ERR_BindToBogus, "M").WithArguments("T").WithLocation(6, 23) + ); } private const string IsUnmanagedAttributeIL = @" diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs index efb4f15ca31b5..019b4813548b8 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs @@ -17,7 +17,7 @@ public class GenericConstraintsTests : CompilingTestBase [Fact] public void EnumConstraint_Compilation_Alone() { - CreateStandardCompilation(@" + CreateCompilation(@" public class Test where T : System.Enum { } @@ -47,7 +47,7 @@ public void M() where U : System.Enum [Fact] public void EnumConstraint_Compilation_ReferenceType() { - CreateStandardCompilation(@" + CreateCompilation(@" public class Test where T : class, System.Enum { } @@ -80,7 +80,7 @@ public void M() where U : class, System.Enum [Fact] public void EnumConstraint_Compilation_ValueType() { - CreateStandardCompilation(@" + CreateCompilation(@" public class Test where T : struct, System.Enum { } @@ -113,7 +113,7 @@ public void M() where U : struct, System.Enum [Fact] public void EnumConstraint_Compilation_Constructor() { - CreateStandardCompilation(@" + CreateCompilation(@" public class Test where T : System.Enum, new() { } @@ -149,7 +149,7 @@ public class Test2 [Fact] public void EnumConstraint_Reference_Alone() { - var reference = CreateStandardCompilation(@" + var reference = CreateCompilation(@" public class Test where T : System.Enum { }" @@ -173,7 +173,7 @@ public void M() where U : System.Enum } }"; - CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + CreateCompilation(code, references: new[] { reference }).VerifyDiagnostics( // (12,26): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no boxing conversion from 'int' to 'System.Enum'. // var b = new Test(); // value type Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "int").WithArguments("Test", "System.Enum", "T", "int").WithLocation(12, 26), @@ -185,7 +185,7 @@ public void M() where U : System.Enum [Fact] public void EnumConstraint_Reference_ReferenceType() { - var reference = CreateStandardCompilation(@" + var reference = CreateCompilation(@" public class Test where T : class, System.Enum { }" @@ -209,7 +209,7 @@ public void M() where U : class, System.Enum } }"; - CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + CreateCompilation(code, references: new[] { reference }).VerifyDiagnostics( // (11,26): error CS0452: The type 'E1' must be a reference type in order to use it as parameter 'T' in the generic type or method 'Test' // var a = new Test(); // enum Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "E1").WithArguments("Test", "T", "E1").WithLocation(11, 26), @@ -224,7 +224,7 @@ public void M() where U : class, System.Enum [Fact] public void EnumConstraint_Reference_ValueType() { - var reference = CreateStandardCompilation(@" + var reference = CreateCompilation(@" public class Test where T : struct, System.Enum { }" @@ -248,7 +248,7 @@ public void M() where U : struct, System.Enum } }"; - CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + CreateCompilation(code, references: new[] { reference }).VerifyDiagnostics( // (12,26): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no boxing conversion from 'int' to 'System.Enum'. // var b = new Test(); // value type Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "int").WithArguments("Test", "System.Enum", "T", "int").WithLocation(12, 26), @@ -263,7 +263,7 @@ public void M() where U : struct, System.Enum [Fact] public void EnumConstraint_Reference_Constructor() { - var reference = CreateStandardCompilation(@" + var reference = CreateCompilation(@" public class Test where T : System.Enum, new() { }" @@ -287,7 +287,7 @@ public class Test2 } }"; - CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + CreateCompilation(code, references: new[] { reference }).VerifyDiagnostics( // (12,26): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'Test'. There is no boxing conversion from 'int' to 'System.Enum'. // var b = new Test(); // value type Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "int").WithArguments("Test", "System.Enum", "T", "int").WithLocation(12, 26), @@ -310,7 +310,7 @@ public class Test where T : System.Enum { }"; - CreateStandardCompilation(code, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp7_2)).VerifyDiagnostics( + CreateCompilation(code, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp7_2)).VerifyDiagnostics( // (2,32): error CS8320: Feature 'enum generic type constraints' is not available in C# 7.2. Please use language version 7.3 or greater. // public class Test where T : System.Enum Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "System.Enum").WithArguments("enum generic type constraints", "7.3").WithLocation(2, 32)); @@ -327,7 +327,7 @@ public class Test where T : System.Enum [InlineData("ulong")] public void EnumConstraint_DifferentBaseTypes(string type) { - CreateStandardCompilation($@" + CreateCompilation($@" public class Test where T : System.Enum {{ }} @@ -352,7 +352,7 @@ public void M() [Fact] public void EnumConstraint_InheritanceChain() { - CreateStandardCompilation(@" + CreateCompilation(@" public enum E { A @@ -451,7 +451,7 @@ public void EnumConstraint_IsReflectedinSymbols_Constructor() [Fact] public void EnumConstraint_EnforcedInInheritanceChain_Downwards_Source() { - CreateStandardCompilation(@" + CreateCompilation(@" public abstract class A { public abstract void M() where T : System.Enum; @@ -469,21 +469,22 @@ public void Test() public enum E { }").VerifyDiagnostics( - // (12,9): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'B.M()'. There is no boxing conversion from 'int' to 'System.Enum'. + // (12,14): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'B.M()'. There is no boxing conversion from 'int' to 'System.Enum'. // this.M(); - Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "this.M").WithArguments("B.M()", "System.Enum", "T", "int").WithLocation(12, 9)); + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "M").WithArguments("B.M()", "System.Enum", "T", "int").WithLocation(12, 14) + ); } [Fact] public void EnumConstraint_EnforcedInInheritanceChain_Downwards_Reference() { - var reference = CreateStandardCompilation(@" + var reference = CreateCompilation(@" public abstract class A { public abstract void M() where T : System.Enum; }").EmitToImageReference(); - CreateStandardCompilation(@" + CreateCompilation(@" public class B : A { public override void M() { } @@ -497,15 +498,16 @@ public void Test() public enum E { }", references: new[] { reference }).VerifyDiagnostics( - // (8,9): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'B.M()'. There is no boxing conversion from 'int' to 'System.Enum'. + // (8,14): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'B.M()'. There is no boxing conversion from 'int' to 'System.Enum'. // this.M(); - Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "this.M").WithArguments("B.M()", "System.Enum", "T", "int").WithLocation(8, 9)); + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "M").WithArguments("B.M()", "System.Enum", "T", "int").WithLocation(8, 14) + ); } [Fact] public void EnumConstraint_EnforcedInInheritanceChain_Upwards_Source() { - CreateStandardCompilation(@" + CreateCompilation(@" public abstract class A { public abstract void M(); @@ -522,13 +524,13 @@ public override void M() where T : System.Enum { } [Fact] public void EnumConstraint_EnforcedInInheritanceChain_Upwards_Reference() { - var reference = CreateStandardCompilation(@" + var reference = CreateCompilation(@" public abstract class A { public abstract void M(); }").EmitToImageReference(); - CreateStandardCompilation(@" + CreateCompilation(@" public class B : A { public override void M() where T : System.Enum { } @@ -541,7 +543,7 @@ public override void M() where T : System.Enum { } [Fact] public void EnumConstraint_ResolveParentConstraints() { - var comp = CreateStandardCompilation(@" + var comp = CreateCompilation(@" public enum MyEnum { } @@ -568,7 +570,7 @@ public override void F() { } [Fact] public void EnumConstraint_TypeNotAvailable() { - CreateCompilation(@" + CreateEmptyCompilation(@" namespace System { public class Object {} @@ -609,7 +611,7 @@ static void Print(T obj) where T : System.Enum [Fact] public void DelegateConstraint_Compilation_Alone() { - CreateStandardCompilation(@" + CreateCompilation(@" public class Test where T : System.Delegate { } @@ -635,7 +637,7 @@ public void M() where U : System.Delegate [Fact] public void DelegateConstraint_Compilation_ReferenceType() { - CreateStandardCompilation(@" + CreateCompilation(@" public class Test where T : class, System.Delegate { } @@ -661,7 +663,7 @@ public void M() where U : class, System.Delegate [Fact] public void DelegateConstraint_Compilation_ValueType() { - CreateStandardCompilation(@" + CreateCompilation(@" public class Test where T : struct, System.Delegate { }").VerifyDiagnostics( @@ -673,7 +675,7 @@ public class Test where T : struct, System.Delegate [Fact] public void DelegateConstraint_Compilation_Constructor() { - CreateStandardCompilation(@" + CreateCompilation(@" public class Test where T : System.Delegate, new() { } @@ -705,12 +707,12 @@ public class Test2 [Fact] public void DelegateConstraint_Reference_Alone() { - var reference = CreateStandardCompilation(@" + var reference = CreateCompilation(@" public class Test where T : System.Delegate { }").EmitToImageReference(); - CreateStandardCompilation(@" + CreateCompilation(@" public delegate void D1(); public class Test2 { @@ -733,12 +735,12 @@ public void M() where U : System.Delegate [Fact] public void DelegateConstraint_Reference_ReferenceType() { - var reference = CreateStandardCompilation(@" + var reference = CreateCompilation(@" public class Test where T : class, System.Delegate { }").EmitToImageReference(); - CreateStandardCompilation(@" + CreateCompilation(@" public delegate void D1(); public class Test2 { @@ -761,12 +763,12 @@ public void M() where U : class, System.Delegate [Fact] public void DelegateConstraint_Reference_Constructor() { - var reference = CreateStandardCompilation(@" + var reference = CreateCompilation(@" public class Test where T : System.Delegate, new() { }").EmitToImageReference(); - CreateStandardCompilation(@" + CreateCompilation(@" public delegate void D1(); public class Test2 { @@ -800,7 +802,7 @@ public class Test where T : System.Delegate { }"; - CreateStandardCompilation(code, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp7_2)).VerifyDiagnostics( + CreateCompilation(code, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp7_2)).VerifyDiagnostics( // (2,32): error CS8320: Feature 'delegate generic type constraints' is not available in C# 7.2. Please use language version 7.3 or greater. // public class Test where T : System.Delegate Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "System.Delegate").WithArguments("delegate generic type constraints", "7.3").WithLocation(2, 32)); @@ -809,7 +811,7 @@ public class Test where T : System.Delegate [Fact] public void DelegateConstraint_InheritanceChain() { - CreateStandardCompilation(@" + CreateCompilation(@" public delegate void D1(); public class Test where U : System.Delegate, T { @@ -860,7 +862,7 @@ public void DelegateConstraint_IsReflectedinSymbols_Alone() [Fact] public void DelegateConstraint_IsReflectedinSymbols_ValueType() { - var compilation = CreateStandardCompilation("public class Test where T : struct, System.Delegate { }") + var compilation = CreateCompilation("public class Test where T : struct, System.Delegate { }") .VerifyDiagnostics( // (1,19): error CS0455: Type parameter 'T' inherits conflicting constraints 'Delegate' and 'ValueType' // public class Test where T : struct, System.Delegate { } @@ -911,7 +913,7 @@ public void DelegateConstraint_IsReflectedinSymbols_Constructor() [Fact] public void DelegateConstraint_EnforcedInInheritanceChain_Downwards_Source() { - CreateStandardCompilation(@" + CreateCompilation(@" public abstract class A { public abstract void M() where T : System.Delegate; @@ -927,21 +929,22 @@ public void Test() this.M(); } }").VerifyDiagnostics( - // (13,9): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'B.M()'. There is no boxing conversion from 'int' to 'System.Delegate'. + // (13,14): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'B.M()'. There is no boxing conversion from 'int' to 'System.Delegate'. // this.M(); - Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "this.M").WithArguments("B.M()", "System.Delegate", "T", "int").WithLocation(13, 9)); + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "M").WithArguments("B.M()", "System.Delegate", "T", "int").WithLocation(13, 14) + ); } [Fact] public void DelegateConstraint_EnforcedInInheritanceChain_Downwards_Reference() { - var reference = CreateStandardCompilation(@" + var reference = CreateCompilation(@" public abstract class A { public abstract void M() where T : System.Delegate; }").EmitToImageReference(); - CreateStandardCompilation(@" + CreateCompilation(@" public delegate void D1(); public class B : A { @@ -953,15 +956,16 @@ public void Test() this.M(); } }", references: new[] { reference }).VerifyDiagnostics( - // (9,9): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'B.M()'. There is no boxing conversion from 'int' to 'System.Delegate'. + // (9,14): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'B.M()'. There is no boxing conversion from 'int' to 'System.Delegate'. // this.M(); - Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "this.M").WithArguments("B.M()", "System.Delegate", "T", "int").WithLocation(9, 9)); + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "M").WithArguments("B.M()", "System.Delegate", "T", "int").WithLocation(9, 14) + ); } [Fact] public void DelegateConstraint_EnforcedInInheritanceChain_Upwards_Source() { - CreateStandardCompilation(@" + CreateCompilation(@" public abstract class A { public abstract void M(); @@ -978,13 +982,13 @@ public override void M() where T : System.Delegate { } [Fact] public void DelegateConstraint_EnforcedInInheritanceChain_Upwards_Reference() { - var reference = CreateStandardCompilation(@" + var reference = CreateCompilation(@" public abstract class A { public abstract void M(); }").EmitToImageReference(); - CreateStandardCompilation(@" + CreateCompilation(@" public class B : A { public override void M() where T : System.Delegate { } @@ -997,7 +1001,7 @@ public override void M() where T : System.Delegate { } [Fact] public void DelegateConstraint_ResolveParentConstraints() { - var comp = CreateStandardCompilation(@" + var comp = CreateCompilation(@" public delegate void D1(); public abstract class A { @@ -1022,7 +1026,7 @@ public override void F() { } [Fact] public void DelegateConstraint_TypeNotAvailable() { - CreateCompilation(@" + CreateEmptyCompilation(@" namespace System { public class Object {} @@ -1066,7 +1070,7 @@ Got 2 and 3 [Fact] public void MulticastDelegateConstraint_Compilation_Alone() { - CreateStandardCompilation(@" + CreateCompilation(@" public class Test where T : System.MulticastDelegate { } @@ -1092,7 +1096,7 @@ public void M() where U : System.MulticastDelegate [Fact] public void MulticastDelegateConstraint_Compilation_ReferenceType() { - CreateStandardCompilation(@" + CreateCompilation(@" public class Test where T : class, System.MulticastDelegate { } @@ -1118,7 +1122,7 @@ public void M() where U : class, System.MulticastDelegate [Fact] public void MulticastDelegateConstraint_Compilation_ValueType() { - CreateStandardCompilation(@" + CreateCompilation(@" public class Test where T : struct, System.MulticastDelegate { }").VerifyDiagnostics( @@ -1130,7 +1134,7 @@ public class Test where T : struct, System.MulticastDelegate [Fact] public void MulticastDelegateConstraint_Compilation_Constructor() { - CreateStandardCompilation(@" + CreateCompilation(@" public class Test where T : System.MulticastDelegate, new() { } @@ -1162,12 +1166,12 @@ public class Test2 [Fact] public void MulticastDelegateConstraint_Reference_Alone() { - var reference = CreateStandardCompilation(@" + var reference = CreateCompilation(@" public class Test where T : System.MulticastDelegate { }").EmitToImageReference(); - CreateStandardCompilation(@" + CreateCompilation(@" public delegate void D1(); public class Test2 { @@ -1190,12 +1194,12 @@ public void M() where U : System.MulticastDelegate [Fact] public void MulticastDelegateConstraint_Reference_ReferenceType() { - var reference = CreateStandardCompilation(@" + var reference = CreateCompilation(@" public class Test where T : class, System.MulticastDelegate { }").EmitToImageReference(); - CreateStandardCompilation(@" + CreateCompilation(@" public delegate void D1(); public class Test2 { @@ -1218,12 +1222,12 @@ public void M() where U : class, System.MulticastDelegate [Fact] public void MulticastDelegateConstraint_Reference_Constructor() { - var reference = CreateStandardCompilation(@" + var reference = CreateCompilation(@" public class Test where T : System.MulticastDelegate, new() { }").EmitToImageReference(); - CreateStandardCompilation(@" + CreateCompilation(@" public delegate void D1(); public class Test2 { @@ -1257,7 +1261,7 @@ public class Test where T : System.MulticastDelegate { }"; - CreateStandardCompilation(code, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp7_2)).VerifyDiagnostics( + CreateCompilation(code, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp7_2)).VerifyDiagnostics( // (2,32): error CS8320: Feature 'delegate generic type constraints' is not available in C# 7.2. Please use language version 7.3 or greater. // public class Test where T : System.MulticastDelegate Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "System.MulticastDelegate").WithArguments("delegate generic type constraints", "7.3").WithLocation(2, 32)); @@ -1266,7 +1270,7 @@ public class Test where T : System.MulticastDelegate [Fact] public void MulticastDelegateConstraint_InheritanceChain() { - CreateStandardCompilation(@" + CreateCompilation(@" public delegate void D1(); public class Test where U : System.MulticastDelegate, T { @@ -1320,7 +1324,7 @@ public void MulticastDelegateConstraint_IsReflectedinSymbols_Alone() [Fact] public void MulticastDelegateConstraint_IsReflectedinSymbols_ValueType() { - var compilation = CreateStandardCompilation("public class Test where T : struct, System.MulticastDelegate { }") + var compilation = CreateCompilation("public class Test where T : struct, System.MulticastDelegate { }") .VerifyDiagnostics( // (1,19): error CS0455: Type parameter 'T' inherits conflicting constraints 'MulticastDelegate' and 'ValueType' // public class Test where T : struct, System.MulticastDelegate { } @@ -1371,7 +1375,7 @@ public void MulticastDelegateConstraint_IsReflectedinSymbols_Constructor() [Fact] public void MulticastDelegateConstraint_EnforcedInInheritanceChain_Downwards_Source() { - CreateStandardCompilation(@" + CreateCompilation(@" public abstract class A { public abstract void M() where T : System.MulticastDelegate; @@ -1387,21 +1391,22 @@ public void Test() this.M(); } }").VerifyDiagnostics( - // (13,9): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'B.M()'. There is no boxing conversion from 'int' to 'System.MulticastDelegate'. + // (13,14): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'B.M()'. There is no boxing conversion from 'int' to 'System.MulticastDelegate'. // this.M(); - Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "this.M").WithArguments("B.M()", "System.MulticastDelegate", "T", "int").WithLocation(13, 9)); + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "M").WithArguments("B.M()", "System.MulticastDelegate", "T", "int").WithLocation(13, 14) + ); } [Fact] public void MulticastDelegateConstraint_EnforcedInInheritanceChain_Downwards_Reference() { - var reference = CreateStandardCompilation(@" + var reference = CreateCompilation(@" public abstract class A { public abstract void M() where T : System.MulticastDelegate; }").EmitToImageReference(); - CreateStandardCompilation(@" + CreateCompilation(@" public delegate void D1(); public class B : A { @@ -1413,15 +1418,16 @@ public void Test() this.M(); } }", references: new[] { reference }).VerifyDiagnostics( - // (9,9): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'B.M()'. There is no boxing conversion from 'int' to 'System.MulticastDelegate'. + // (9,14): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'B.M()'. There is no boxing conversion from 'int' to 'System.MulticastDelegate'. // this.M(); - Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "this.M").WithArguments("B.M()", "System.MulticastDelegate", "T", "int").WithLocation(9, 9)); + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "M").WithArguments("B.M()", "System.MulticastDelegate", "T", "int").WithLocation(9, 14) + ); } [Fact] public void MulticastDelegateConstraint_EnforcedInInheritanceChain_Upwards_Source() { - CreateStandardCompilation(@" + CreateCompilation(@" public abstract class A { public abstract void M(); @@ -1438,13 +1444,13 @@ public override void M() where T : System.MulticastDelegate { } [Fact] public void MulticastDelegateConstraint_EnforcedInInheritanceChain_Upwards_Reference() { - var reference = CreateStandardCompilation(@" + var reference = CreateCompilation(@" public abstract class A { public abstract void M(); }").EmitToImageReference(); - CreateStandardCompilation(@" + CreateCompilation(@" public class B : A { public override void M() where T : System.MulticastDelegate { } @@ -1457,7 +1463,7 @@ public override void M() where T : System.MulticastDelegate { } [Fact] public void MulticastDelegateConstraint_ResolveParentConstraints() { - var comp = CreateStandardCompilation(@" + var comp = CreateCompilation(@" public delegate void D1(); public abstract class A { @@ -1482,7 +1488,7 @@ public override void F() { } [Fact] public void MulticastDelegateConstraint_TypeNotAvailable() { - CreateCompilation(@" + CreateEmptyCompilation(@" namespace System { public class Object {} @@ -1530,13 +1536,13 @@ public void ConversionInInheritanceChain_MulticastDelegate() class A where T : System.Delegate { } class B : A where T : System.MulticastDelegate { }"; - CreateStandardCompilation(code).VerifyDiagnostics(); + CreateCompilation(code).VerifyDiagnostics(); code = @" class A where T : System.MulticastDelegate { } class B : A where T : System.Delegate { }"; - CreateStandardCompilation(code).VerifyDiagnostics( + CreateCompilation(code).VerifyDiagnostics( // (3,7): error CS0311: The type 'T' cannot be used as type parameter 'T' in the generic type or method 'A'. There is no implicit reference conversion from 'T' to 'System.MulticastDelegate'. // class B : A where T : System.Delegate { } Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "B").WithArguments("A", "System.MulticastDelegate", "T", "T").WithLocation(3, 7)); @@ -1545,7 +1551,7 @@ class B : A where T : System.Delegate { }"; [Fact] public void UnmanagedConstraint_Compilation_Alone_Type() { - CreateStandardCompilation(@" + CreateCompilation(@" public class Test where T : unmanaged { } @@ -1577,7 +1583,7 @@ public void M() where U : unmanaged [Fact] public void UnmanagedConstraint_Compilation_Alone_Method() { - CreateStandardCompilation(@" + CreateCompilation(@" public class Test { public int M() where T : unmanaged => 0; @@ -1596,21 +1602,22 @@ public void M() where U : unmanaged var f = new Test().M(); // unconstrained generic type } }").VerifyDiagnostics( - // (13,17): error CS8375: The type 'BadType' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' + // (13,28): error CS8375: The type 'BadType' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' // var b = new Test().M(); // managed struct - Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "new Test().M").WithArguments("Test.M()", "T", "BadType").WithLocation(13, 17), - // (14,17): error CS8375: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "M").WithArguments("Test.M()", "T", "BadType").WithLocation(13, 28), + // (14,28): error CS8375: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' // var c = new Test().M(); // reference type - Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "new Test().M").WithArguments("Test.M()", "T", "string").WithLocation(14, 17), - // (17,17): error CS8375: The type 'W' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "M").WithArguments("Test.M()", "T", "string").WithLocation(14, 28), + // (17,28): error CS8375: The type 'W' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' // var f = new Test().M(); // unconstrained generic type - Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "new Test().M").WithArguments("Test.M()", "T", "W").WithLocation(17, 17)); + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "M").WithArguments("Test.M()", "T", "W").WithLocation(17, 28) + ); } [Fact] public void UnmanagedConstraint_Compilation_Alone_Delegate() { - CreateStandardCompilation(@" + CreateCompilation(@" public delegate void D() where T : unmanaged; public struct GoodType { public int I; } public struct BadType { public string S; } @@ -1637,7 +1644,7 @@ public abstract class Test2 where U : unmanaged [Fact] public void UnmanagedConstraint_Compilation_Alone_LocalFunction() { - CreateStandardCompilation(@" + CreateCompilation(@" public abstract class Test2 where U : unmanaged { public void M() @@ -1655,7 +1662,7 @@ void local() where T : unmanaged { } [Fact] public void UnmanagedConstraint_Compilation_ReferenceType() { - CreateStandardCompilation("public class Test where T : class, unmanaged {}").VerifyDiagnostics( + CreateCompilation("public class Test where T : class, unmanaged {}").VerifyDiagnostics( // (1,39): error CS8374: The 'unmanaged' constraint cannot be specified with other constraints. // public class Test where T : class, unmanaged {} Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeAlone, "unmanaged").WithLocation(1, 39)); @@ -1664,7 +1671,7 @@ public void UnmanagedConstraint_Compilation_ReferenceType() [Fact] public void UnmanagedConstraint_Compilation_ValueType() { - CreateStandardCompilation("public class Test where T : struct, unmanaged {}").VerifyDiagnostics( + CreateCompilation("public class Test where T : struct, unmanaged {}").VerifyDiagnostics( // (1,40): error CS8374: The 'unmanaged' constraint cannot be specified with other constraints. // public class Test where T : struct, unmanaged {} Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeAlone, "unmanaged").WithLocation(1, 40)); @@ -1673,7 +1680,7 @@ public void UnmanagedConstraint_Compilation_ValueType() [Fact] public void UnmanagedConstraint_Compilation_Constructor() { - CreateStandardCompilation("public class Test where T : unmanaged, new() {}").VerifyDiagnostics( + CreateCompilation("public class Test where T : unmanaged, new() {}").VerifyDiagnostics( // (1,43): error CS8373: The 'new()' constraint cannot be used with the 'unmanaged' constraint // public class Test where T : unmanaged, new() {} Diagnostic(ErrorCode.ERR_NewBoundWithUnmanaged, "new").WithLocation(1, 43)); @@ -1682,7 +1689,7 @@ public void UnmanagedConstraint_Compilation_Constructor() [Fact] public void UnmanagedConstraint_Compilation_AnotherType_Before() { - CreateStandardCompilation("public class Test where T : unmanaged, System.Exception { }").VerifyDiagnostics( + CreateCompilation("public class Test where T : unmanaged, System.Exception { }").VerifyDiagnostics( // (1,43): error CS8374: The 'unmanaged' constraint cannot be specified with other constraints. // public class Test where T : unmanaged, System.Exception { } Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeAlone, "System.Exception").WithLocation(1, 43)); @@ -1691,7 +1698,7 @@ public void UnmanagedConstraint_Compilation_AnotherType_Before() [Fact] public void UnmanagedConstraint_Compilation_AnotherType_After() { - CreateStandardCompilation("public class Test where T : System.Exception, unmanaged { }").VerifyDiagnostics( + CreateCompilation("public class Test where T : System.Exception, unmanaged { }").VerifyDiagnostics( // (1,50): error CS8374: The 'unmanaged' constraint cannot be specified with other constraints. // public class Test where T : System.Exception, unmanaged { } Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeAlone, "unmanaged").WithLocation(1, 50)); @@ -1700,7 +1707,7 @@ public void UnmanagedConstraint_Compilation_AnotherType_After() [Fact] public void UnmanagedConstraint_Compilation_AnotherParameter_After() { - CreateStandardCompilation("public class Test where T : U, unmanaged { }").VerifyDiagnostics( + CreateCompilation("public class Test where T : U, unmanaged { }").VerifyDiagnostics( // (1,38): error CS8374: The 'unmanaged' constraint cannot be specified with other constraints. // public class Test where T : U, unmanaged { } Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeAlone, "unmanaged").WithLocation(1, 38)); @@ -1709,7 +1716,7 @@ public void UnmanagedConstraint_Compilation_AnotherParameter_After() [Fact] public void UnmanagedConstraint_Compilation_AnotherParameter_Before() { - CreateStandardCompilation("public class Test where T : unmanaged, U { }").VerifyDiagnostics( + CreateCompilation("public class Test where T : unmanaged, U { }").VerifyDiagnostics( // (1,46): error CS8374: The 'unmanaged' constraint cannot be specified with other constraints. // public class Test where T : unmanaged, U { } Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeAlone, "U").WithLocation(1, 46)); @@ -1718,7 +1725,7 @@ public void UnmanagedConstraint_Compilation_AnotherParameter_Before() [Fact] public void UnmanagedConstraint_UnmanagedEnumNotAvailable() { - CreateCompilation(@" + CreateEmptyCompilation(@" namespace System { public class Object {} @@ -1736,7 +1743,7 @@ public class Test where T : unmanaged [Fact] public void UnmanagedConstraint_ValueTypeNotAvailable() { - CreateCompilation(@" + CreateEmptyCompilation(@" namespace System { public class Object {} @@ -1762,7 +1769,7 @@ public class Test where T : unmanaged [Fact] public void UnmanagedConstraint_Reference_Alone_Type() { - var reference = CreateStandardCompilation(@" + var reference = CreateCompilation(@" public class Test where T : unmanaged { }").EmitToImageReference(); @@ -1782,7 +1789,7 @@ public void M() where U : unmanaged var f = new Test(); // unconstrained generic type } }"; - CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + CreateCompilation(code, references: new[] { reference }).VerifyDiagnostics( // (9,26): error CS8375: The type 'BadType' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test' // var b = new Test(); // managed struct Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "BadType").WithArguments("Test", "T", "BadType").WithLocation(9, 26), @@ -1797,7 +1804,7 @@ public void M() where U : unmanaged [Fact] public void UnmanagedConstraint_Reference_Alone_Method() { - var reference = CreateStandardCompilation(@" + var reference = CreateCompilation(@" public class Test { public int M() where T : unmanaged => 0; @@ -1818,22 +1825,23 @@ public void M() where U : unmanaged var f = new Test().M(); // unconstrained generic type } }"; - CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( - // (9,17): error CS8375: The type 'BadType' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' + CreateCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (9,28): error CS8375: The type 'BadType' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' // var b = new Test().M(); // managed struct - Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "new Test().M").WithArguments("Test.M()", "T", "BadType").WithLocation(9, 17), - // (10,17): error CS8375: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "M").WithArguments("Test.M()", "T", "BadType").WithLocation(9, 28), + // (10,28): error CS8375: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' // var c = new Test().M(); // reference type - Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "new Test().M").WithArguments("Test.M()", "T", "string").WithLocation(10, 17), - // (13,17): error CS8375: The type 'W' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "M").WithArguments("Test.M()", "T", "string").WithLocation(10, 28), + // (13,28): error CS8375: The type 'W' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' // var f = new Test().M(); // unconstrained generic type - Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "new Test().M").WithArguments("Test.M()", "T", "W").WithLocation(13, 17)); + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "M").WithArguments("Test.M()", "T", "W").WithLocation(13, 28) + ); } [Fact] public void UnmanagedConstraint_Reference_Alone_Delegate() { - var reference = CreateStandardCompilation(@" + var reference = CreateCompilation(@" public delegate void D() where T : unmanaged; ").EmitToImageReference(); @@ -1849,7 +1857,7 @@ public abstract class Test2 where U : unmanaged public abstract D e(); // generic type constrained to unmanaged public abstract D f(); // unconstrained generic type }"; - CreateStandardCompilation(code, references: new[] { reference }).VerifyDiagnostics( + CreateCompilation(code, references: new[] { reference }).VerifyDiagnostics( // (7,32): error CS8375: The type 'BadType' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'D' // public abstract D b(); // managed struct Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "b").WithArguments("D", "T", "BadType").WithLocation(7, 32), @@ -1869,7 +1877,7 @@ public class Test where T : unmanaged { }"; - CreateStandardCompilation(code, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp7_2)).VerifyDiagnostics( + CreateCompilation(code, parseOptions: new CSharpParseOptions(LanguageVersion.CSharp7_2)).VerifyDiagnostics( // (2,32): error CS8320: Feature 'unmanaged generic type constraints' is not available in C# 7.2. Please use language version 7.3 or greater. // public class Test where T : unmanaged Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_2, "unmanaged").WithArguments("unmanaged generic type constraints", "7.3").WithLocation(2, 32)); @@ -1936,7 +1944,7 @@ public void UnmanagedConstraint_IsReflectedinSymbols_Alone_Delegate() [Fact] public void UnmanagedConstraint_EnforcedInInheritanceChain_Downwards_Source() { - CreateStandardCompilation(@" + CreateCompilation(@" struct Test { public string RefMember { get; set; } @@ -1956,24 +1964,25 @@ public void Test() this.M(); } }").VerifyDiagnostics( - // (17,9): error CS8375: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'B.M()' + // (17,14): error CS8375: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'B.M()' // this.M(); - Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "this.M").WithArguments("B.M()", "T", "string").WithLocation(17, 9), - // (18,9): error CS8375: The type 'Test' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'B.M()' + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "M").WithArguments("B.M()", "T", "string").WithLocation(17, 14), + // (18,14): error CS8375: The type 'Test' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'B.M()' // this.M(); - Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "this.M").WithArguments("B.M()", "T", "Test").WithLocation(18, 9)); + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "M").WithArguments("B.M()", "T", "Test").WithLocation(18, 14) + ); } [Fact] public void UnmanagedConstraint_EnforcedInInheritanceChain_Downwards_Reference() { - var reference = CreateStandardCompilation(@" + var reference = CreateCompilation(@" public abstract class A { public abstract void M() where T : unmanaged; }").EmitToImageReference(); - CreateStandardCompilation(@" + CreateCompilation(@" struct Test { public string RefMember { get; set; } @@ -1989,18 +1998,19 @@ public void Test() this.M(); } }", references: new[] { reference }).VerifyDiagnostics( - // (13,9): error CS8375: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'B.M()' + // (13,14): error CS8375: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'B.M()' // this.M(); - Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "this.M").WithArguments("B.M()", "T", "string").WithLocation(13, 9), - // (14,9): error CS8375: The type 'Test' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'B.M()' + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "M").WithArguments("B.M()", "T", "string").WithLocation(13, 14), + // (14,14): error CS8375: The type 'Test' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'B.M()' // this.M(); - Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "this.M").WithArguments("B.M()", "T", "Test").WithLocation(14, 9)); + Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "M").WithArguments("B.M()", "T", "Test").WithLocation(14, 14) + ); } [Fact] public void UnmanagedConstraint_EnforcedInInheritanceChain_Upwards_Source() { - CreateStandardCompilation(@" + CreateCompilation(@" public abstract class A { public abstract void M(); @@ -2017,13 +2027,13 @@ public override void M() where T : unmanaged { } [Fact] public void UnmanagedConstraint_EnforcedInInheritanceChain_Upwards_Reference() { - var reference = CreateStandardCompilation(@" + var reference = CreateCompilation(@" public abstract class A { public abstract void M(); }").EmitToImageReference(); - CreateStandardCompilation(@" + CreateCompilation(@" public class B : A { public override void M() where T : unmanaged { } @@ -2036,7 +2046,7 @@ public override void M() where T : unmanaged { } [Fact] public void UnmanagedConstraints_PointerOperations_Invalid() { - CreateStandardCompilation(@" + CreateCompilation(@" class Test { void M(T arg) where T : unmanaged @@ -2097,7 +2107,7 @@ static void Main() M(" + arg + @"); } }", - options: TestOptions.UnsafeReleaseExe, expectedOutput: string.Join(Environment.NewLine, type, size)).VerifyIL("Test.M", @" + options: TestOptions.UnsafeReleaseExe, verify: Verification.Fails, expectedOutput: string.Join(Environment.NewLine, type, size)).VerifyIL("Test.M", @" { // Code size 43 (0x2b) .maxstack 2 @@ -2139,7 +2149,7 @@ static void N() where T : unmanaged { System.Console.WriteLine(sizeof(T)); } -}", options: TestOptions.UnsafeReleaseExe, expectedOutput: "4"); +}", options: TestOptions.UnsafeReleaseExe, verify: Verification.Passes, expectedOutput: "4"); } [Fact] @@ -2174,13 +2184,13 @@ static void N() where T : unmanaged { System.Console.WriteLine(sizeof(T)); } -}", options: TestOptions.UnsafeReleaseExe, expectedOutput: "8"); +}", options: TestOptions.UnsafeReleaseExe, verify: Verification.Passes, expectedOutput: "8"); } [Fact] public void UnmanagedConstraints_NestedStructs_Error() { - CreateStandardCompilation(@" + CreateCompilation(@" struct InnerTestData { public string B; @@ -2241,7 +2251,7 @@ static void M(T arg) where T : unmanaged [Fact] public void UnmanagedConstraints_ExistingUnmanagedKeywordType_OutOfScope() { - CreateStandardCompilation(@" + CreateCompilation(@" namespace hidden { class unmanaged @@ -2342,7 +2352,7 @@ static void Main() [Fact] public void UnmanagedConstraints_PointerTypeSubstitution() { - var compilation = CreateStandardCompilation(@" + var compilation = CreateCompilation(@" unsafe public class Test { public T* M() where T : unmanaged => throw null; @@ -2366,7 +2376,7 @@ public void N() [Fact] public void UnmanagedConstraints_CannotConstraintToTypeParameterConstrainedByUnmanaged() { - CreateStandardCompilation(@" + CreateCompilation(@" class Test where U : unmanaged { void M() where T : U @@ -2381,7 +2391,7 @@ void M() where T : U [Fact] public void UnmanagedConstraints_UnmanagedAsTypeConstraintName() { - CreateStandardCompilation(@" + CreateCompilation(@" class Test where unmanaged : System.IDisposable { void M(T arg) where T : unmanaged @@ -2398,7 +2408,7 @@ void M(T arg) where T : unmanaged [Fact] public void UnmanagedConstraints_CircularReferenceToUnmanagedTypeWillBindSuccessfully() { - CreateStandardCompilation(@" + CreateCompilation(@" public unsafe class C where U : unmanaged { public void M1() where T : T* { } diff --git a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt index fb66d90c7371e..0b6b07f112530 100644 --- a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt @@ -5,6 +5,7 @@ Microsoft.CodeAnalysis.Emit.EmitOptions.EmitOptions(bool metadataOnly, Microsoft Microsoft.CodeAnalysis.Emit.EmitOptions.PdbChecksumAlgorithm.get -> System.Security.Cryptography.HashAlgorithmName Microsoft.CodeAnalysis.Emit.EmitOptions.WithPdbChecksumAlgorithm(System.Security.Cryptography.HashAlgorithmName name) -> Microsoft.CodeAnalysis.Emit.EmitOptions Microsoft.CodeAnalysis.INamedTypeSymbol.IsSerializable.get -> bool +Microsoft.CodeAnalysis.ITypeParameterSymbol.HasUnmanagedTypeConstraint.get -> bool Microsoft.CodeAnalysis.MetadataImportOptions Microsoft.CodeAnalysis.MetadataImportOptions.All = 2 -> Microsoft.CodeAnalysis.MetadataImportOptions Microsoft.CodeAnalysis.MetadataImportOptions.Internal = 1 -> Microsoft.CodeAnalysis.MetadataImportOptions diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/GenericConstraintTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/GenericConstraintTests.vb index 5aea8779df19b..c973e61567213 100644 --- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/GenericConstraintTests.vb +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/GenericConstraintTests.vb @@ -5726,7 +5726,7 @@ public class Test where T : System.Enum { }", parseOptions:=New CSharp.CSharpParseOptions(CSharp.LanguageVersion.CSharp7_3)).EmitToImageReference() - Dim compilation = CompilationUtils.CreateCompilationWithMscorlibAndVBRuntime( + Dim compilation = CompilationUtils.CreateCompilationWithMscorlib45AndVBRuntime( Public Enum E1 @@ -5761,7 +5761,7 @@ public class Test where T : System.Delegate { }", parseOptions:=New CSharp.CSharpParseOptions(CSharp.LanguageVersion.CSharp7_3)).EmitToImageReference() - Dim compilation = CompilationUtils.CreateCompilationWithMscorlibAndVBRuntime( + Dim compilation = CompilationUtils.CreateCompilationWithMscorlib45AndVBRuntime( Delegate Sub D1() @@ -5795,7 +5795,7 @@ public class Test where T : System.MulticastDelegate { }", parseOptions:=New CSharp.CSharpParseOptions(CSharp.LanguageVersion.CSharp7_3)).EmitToImageReference() - Dim compilation = CompilationUtils.CreateCompilationWithMscorlibAndVBRuntime( + Dim compilation = CompilationUtils.CreateCompilationWithMscorlib45AndVBRuntime( Delegate Sub D1() diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Metadata/PE/LoadCustomModifiers.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Metadata/PE/LoadCustomModifiers.vb index 5a3e7fa72272f..3dad316294b92 100644 --- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Metadata/PE/LoadCustomModifiers.vb +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/Metadata/PE/LoadCustomModifiers.vb @@ -121,7 +121,7 @@ End Class - Dim compilation = CreateCompilationWithMscorlib(source, references:={reference}) + Dim compilation = CreateCompilationWithMscorlib45AndVBRuntime(source, references:={reference}) AssertTheseDiagnostics(compilation, BC30649: '' is an unsupported type. @@ -161,7 +161,7 @@ End Class - Dim compilation = CreateCompilationWithMscorlib(source, references:={reference}) + Dim compilation = CreateCompilationWithMscorlib45AndVBRuntime(source, references:={reference}) AssertTheseDiagnostics(compilation, BC30649: '' is an unsupported type. @@ -189,7 +189,7 @@ End Class - Dim compilation = CreateCompilationWithMscorlib(source, references:={reference}) + Dim compilation = CreateCompilationWithMscorlib45AndVBRuntime(source, references:={reference}) AssertTheseDiagnostics(compilation, BC30649: '' is an unsupported type. diff --git a/src/EditorFeatures/CSharpTest/Classification/SemanticClassifierTests.cs b/src/EditorFeatures/CSharpTest/Classification/SemanticClassifierTests.cs index ab186f25e6926..f74788f626fc5 100644 --- a/src/EditorFeatures/CSharpTest/Classification/SemanticClassifierTests.cs +++ b/src/EditorFeatures/CSharpTest/Classification/SemanticClassifierTests.cs @@ -2396,7 +2396,8 @@ public async Task TestUnmanagedConstraint_InsideMethod() await TestInMethodAsync(@" var unmanaged = 0; unmanaged++;", - Keyword("var")); + Keyword("var"), + Local("unmanaged")); } [Fact, Trait(Traits.Feature, Traits.Features.Classification)] diff --git a/src/EditorFeatures/CSharpTest/Classification/SyntacticClassifierTests.cs b/src/EditorFeatures/CSharpTest/Classification/SyntacticClassifierTests.cs index 1d979b42379a5..c1bc72f061d45 100644 --- a/src/EditorFeatures/CSharpTest/Classification/SyntacticClassifierTests.cs +++ b/src/EditorFeatures/CSharpTest/Classification/SyntacticClassifierTests.cs @@ -4012,12 +4012,12 @@ await TestInMethodAsync(@" var unmanaged = 0; unmanaged++;", Keyword("var"), - Identifier("unmanaged"), + Local("unmanaged"), Operators.Equals, Number("0"), Punctuation.Semicolon, Identifier("unmanaged"), - Operators.DoublePlus, + Operators.PlusPlus, Punctuation.Semicolon); } @@ -4104,7 +4104,7 @@ void M() where T : unmanaged { } Class("X"), Punctuation.OpenCurly, Keyword("void"), - Identifier("M"), + Method("M"), Punctuation.OpenAngle, TypeParameter("T"), Punctuation.CloseAngle, @@ -4136,7 +4136,7 @@ void M() where T : unmanaged { } Class("X"), Punctuation.OpenCurly, Keyword("void"), - Identifier("M"), + Method("M"), Punctuation.OpenAngle, TypeParameter("T"), Punctuation.CloseAngle, @@ -4175,7 +4175,7 @@ void M() where T : unmanaged { } Class("X"), Punctuation.OpenCurly, Keyword("void"), - Identifier("M"), + Method("M"), Punctuation.OpenAngle, TypeParameter("T"), Punctuation.CloseAngle, diff --git a/src/EditorFeatures/CSharpTest/Classification/TotalClassifierTests.cs b/src/EditorFeatures/CSharpTest/Classification/TotalClassifierTests.cs index 13e5d0e6c82e6..02b7e937d2f70 100644 --- a/src/EditorFeatures/CSharpTest/Classification/TotalClassifierTests.cs +++ b/src/EditorFeatures/CSharpTest/Classification/TotalClassifierTests.cs @@ -938,12 +938,12 @@ await TestInMethodAsync(@" var unmanaged = 0; unmanaged++;", Keyword("var"), - Identifier("unmanaged"), + Local("unmanaged"), Operators.Equals, Number("0"), Punctuation.Semicolon, - Identifier("unmanaged"), - Operators.DoublePlus, + Local("unmanaged"), + Operators.PlusPlus, Punctuation.Semicolon); } @@ -1030,7 +1030,7 @@ void M() where T : unmanaged { } Class("X"), Punctuation.OpenCurly, Keyword("void"), - Identifier("M"), + Method("M"), Punctuation.OpenAngle, TypeParameter("T"), Punctuation.CloseAngle, @@ -1062,7 +1062,7 @@ void M() where T : unmanaged { } Class("X"), Punctuation.OpenCurly, Keyword("void"), - Identifier("M"), + Method("M"), Punctuation.OpenAngle, TypeParameter("T"), Punctuation.CloseAngle, @@ -1101,7 +1101,7 @@ void M() where T : unmanaged { } Class("X"), Punctuation.OpenCurly, Keyword("void"), - Identifier("M"), + Method("M"), Punctuation.OpenAngle, TypeParameter("T"), Punctuation.CloseAngle, diff --git a/src/EditorFeatures/TestUtilities/Classification/FormattedClassification.cs b/src/EditorFeatures/TestUtilities/Classification/FormattedClassification.cs index 88e6516e9ee7d..2961e4ffb3aa3 100644 --- a/src/EditorFeatures/TestUtilities/Classification/FormattedClassification.cs +++ b/src/EditorFeatures/TestUtilities/Classification/FormattedClassification.cs @@ -58,6 +58,8 @@ public override string ToString() { case "=": return "Operators.Equals"; + case "++": + return "Operators.PlusPlus"; } goto default; From e29812368137a0812d61ace39ae95131767bb545 Mon Sep 17 00:00:00 2001 From: vsadov Date: Fri, 9 Mar 2018 19:06:38 -0800 Subject: [PATCH 09/13] constraints fixups --- .../Portable/Binder/Binder_Constraints.cs | 26 +- .../Portable/CSharpResources.Designer.cs | 15 +- .../CSharp/Portable/CSharpResources.resx | 7 +- .../EditAndContinue/CSharpSymbolMatcher.cs | 1 + .../Model/TypeParameterSymbolAdapter.cs | 64 +++-- .../CSharp/Portable/Errors/ErrorCode.cs | 4 +- .../Symbols/MemberSignatureComparer.cs | 1 + .../Metadata/PE/PETypeParameterSymbol.cs | 70 +++-- .../Portable/xlf/CSharpResources.cs.xlf | 15 +- .../Portable/xlf/CSharpResources.de.xlf | 15 +- .../Portable/xlf/CSharpResources.es.xlf | 15 +- .../Portable/xlf/CSharpResources.fr.xlf | 15 +- .../Portable/xlf/CSharpResources.it.xlf | 15 +- .../Portable/xlf/CSharpResources.ja.xlf | 15 +- .../Portable/xlf/CSharpResources.ko.xlf | 15 +- .../Portable/xlf/CSharpResources.pl.xlf | 15 +- .../Portable/xlf/CSharpResources.pt-BR.xlf | 15 +- .../Portable/xlf/CSharpResources.ru.xlf | 15 +- .../Portable/xlf/CSharpResources.tr.xlf | 15 +- .../Portable/xlf/CSharpResources.zh-Hans.xlf | 15 +- .../Portable/xlf/CSharpResources.zh-Hant.xlf | 15 +- .../Emit/Emit/UnmanagedTypeModifierTests.cs | 39 ++- .../Semantics/GenericConstraintsTests.cs | 267 ++++++++++++++++-- .../SymbolDisplay/SymbolDisplayTests.cs | 11 +- 24 files changed, 518 insertions(+), 182 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs index 6681b255bc933..6ba15a5f99d07 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs @@ -147,7 +147,8 @@ private TypeParameterConstraintClause BindTypeParameterConstraints( { if (constraints != 0 || constraintTypes.Any()) { - diagnostics.Add(ErrorCode.ERR_UnmanagedConstraintMustBeAlone, typeSyntax.GetLocation()); + // TODO: VS first + diagnostics.Add(ErrorCode.ERR_UnmanagedConstraintMustBeFirst, typeSyntax.GetLocation()); continue; } @@ -176,12 +177,6 @@ private TypeParameterConstraintClause BindTypeParameterConstraints( continue; } - if ((constraints & TypeParameterConstraintKind.Unmanaged) != 0) - { - diagnostics.Add(ErrorCode.ERR_UnmanagedConstraintMustBeAlone, typeSyntax.GetLocation()); - continue; - } - if (type.TypeKind == TypeKind.Class) { // If there is already a struct or class constraint (class constraint could be @@ -195,7 +190,7 @@ private TypeParameterConstraintClause BindTypeParameterConstraints( continue; } - if ((constraints & (TypeParameterConstraintKind.ReferenceType | TypeParameterConstraintKind.ValueType)) != 0) + if ((constraints & (TypeParameterConstraintKind.ReferenceType)) != 0) { switch (type.SpecialType) { @@ -210,6 +205,21 @@ private TypeParameterConstraintClause BindTypeParameterConstraints( continue; } } + else if (type.SpecialType != SpecialType.System_Enum) + { + if ((constraints & TypeParameterConstraintKind.ValueType) != 0) + { + // "'{0}': cannot specify both a constraint class and the 'class' or 'struct' constraint" + Error(diagnostics, ErrorCode.ERR_RefValBoundWithClass, syntax, type); + continue; + } + else if ((constraints & TypeParameterConstraintKind.ValueType) != 0) + { + // "'{0}': cannot specify both a constraint class and the 'unmanaged' constraint" + Error(diagnostics, ErrorCode.ERR_UnmanagedBoundWithClass, syntax, type); + continue; + } + } } } diff --git a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs index 710288f503d0e..24c400a57fd42 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs +++ b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs @@ -9755,11 +9755,20 @@ internal static string ERR_UnimplementedInterfaceMember { } /// - /// Looks up a localized string similar to The 'unmanaged' constraint cannot be specified with other constraints.. + /// Looks up a localized string similar to '{0}': cannot specify both a constraint class and the 'unmanaged' constraint. /// - internal static string ERR_UnmanagedConstraintMustBeAlone { + internal static string ERR_UnmanagedBoundWithClass { get { - return ResourceManager.GetString("ERR_UnmanagedConstraintMustBeAlone", resourceCulture); + return ResourceManager.GetString("ERR_UnmanagedBoundWithClass", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The 'unmanaged' constraint must come before any other constraints. + /// + internal static string ERR_UnmanagedConstraintMustBeFirst { + get { + return ResourceManager.GetString("ERR_UnmanagedConstraintMustBeFirst", resourceCulture); } } diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 30cc98b030d20..0fddf5e9556b5 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -1329,6 +1329,9 @@ '{0}': cannot specify both a constraint class and the 'class' or 'struct' constraint + + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint + The 'new()' constraint cannot be used with the 'struct' constraint @@ -5267,8 +5270,8 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ The 'new()' constraint cannot be used with the 'unmanaged' constraint - - The 'unmanaged' constraint cannot be specified with other constraints. + + The 'unmanaged' constraint must come before any other constraints The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' diff --git a/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/CSharpSymbolMatcher.cs b/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/CSharpSymbolMatcher.cs index d38e5ca9da354..54323231324f3 100644 --- a/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/CSharpSymbolMatcher.cs +++ b/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/CSharpSymbolMatcher.cs @@ -772,6 +772,7 @@ private static bool AreTypeParametersEqual(TypeParameterSymbol type, TypeParamet // edit. Furthermore, comparing constraint types might lead to a cycle. Debug.Assert(type.HasConstructorConstraint == other.HasConstructorConstraint); Debug.Assert(type.HasValueTypeConstraint == other.HasValueTypeConstraint); + Debug.Assert(type.HasUnmanagedTypeConstraint == other.HasUnmanagedTypeConstraint); Debug.Assert(type.HasReferenceTypeConstraint == other.HasReferenceTypeConstraint); Debug.Assert(type.ConstraintTypesNoUseSiteDiagnostics.Length == other.ConstraintTypesNoUseSiteDiagnostics.Length); return true; diff --git a/src/Compilers/CSharp/Portable/Emitter/Model/TypeParameterSymbolAdapter.cs b/src/Compilers/CSharp/Portable/Emitter/Model/TypeParameterSymbolAdapter.cs index 6254824409c9d..d59224eb95c10 100644 --- a/src/Compilers/CSharp/Portable/Emitter/Model/TypeParameterSymbolAdapter.cs +++ b/src/Compilers/CSharp/Portable/Emitter/Model/TypeParameterSymbolAdapter.cs @@ -224,49 +224,50 @@ Cci.ITypeReference Cci.IGenericTypeParameterReference.DefiningType { var moduleBeingBuilt = (PEModuleBuilder)context.Module; + var seenValueType = false; if (this.HasUnmanagedTypeConstraint) { - var typeRef = moduleBeingBuilt.Translate( - typeSymbol: moduleBeingBuilt.Compilation.GetSpecialType(SpecialType.System_ValueType), - syntaxNodeOpt: (CSharpSyntaxNode)context.SyntaxNodeOpt, - diagnostics: context.Diagnostics); + var typeRef = moduleBeingBuilt.GetSpecialType(SpecialType.System_ValueType, + syntaxNodeOpt: (CSharpSyntaxNode)context.SyntaxNodeOpt, + diagnostics: context.Diagnostics); var modifier = CSharpCustomModifier.CreateRequired( moduleBeingBuilt.Compilation.GetWellKnownType(WellKnownType.System_Runtime_InteropServices_UnmanagedType)); + // emit "(class [mscorlib]System.ValueType modreq([mscorlib]System.Runtime.InteropServices.UnmanagedType" pattern as "unmanaged" yield return new Cci.TypeReferenceWithAttributes(new Cci.ModifiedTypeReference(typeRef, ImmutableArray.Create(modifier))); + + // do not emit another one for Dev11 similarities + seenValueType = true; } - else + + foreach (var type in this.ConstraintTypesNoUseSiteDiagnostics) { - var seenValueType = false; - foreach (var type in this.ConstraintTypesNoUseSiteDiagnostics) + switch (type.SpecialType) { - switch (type.SpecialType) - { - case SpecialType.System_Object: - // Avoid emitting unnecessary object constraint. - continue; - case SpecialType.System_ValueType: - seenValueType = true; - break; - } - var typeRef = moduleBeingBuilt.Translate(type, - syntaxNodeOpt: (CSharpSyntaxNode)context.SyntaxNodeOpt, - diagnostics: context.Diagnostics); - - yield return type.GetTypeRefWithAttributes(this.DeclaringCompilation, - typeRef); + case SpecialType.System_Object: + // Avoid emitting unnecessary object constraint. + continue; + case SpecialType.System_ValueType: + seenValueType = true; + break; } + var typeRef = moduleBeingBuilt.Translate(type, + syntaxNodeOpt: (CSharpSyntaxNode)context.SyntaxNodeOpt, + diagnostics: context.Diagnostics); - if (this.HasValueTypeConstraint && !seenValueType) - { - // Add System.ValueType constraint to comply with Dev11 output - var typeRef = moduleBeingBuilt.GetSpecialType(SpecialType.System_ValueType, - syntaxNodeOpt: (CSharpSyntaxNode)context.SyntaxNodeOpt, - diagnostics: context.Diagnostics); + yield return type.GetTypeRefWithAttributes(this.DeclaringCompilation, + typeRef); + } - yield return new Cci.TypeReferenceWithAttributes(typeRef); - } + if (this.HasValueTypeConstraint && !seenValueType) + { + // Add System.ValueType constraint to comply with Dev11 output + var typeRef = moduleBeingBuilt.GetSpecialType(SpecialType.System_ValueType, + syntaxNodeOpt: (CSharpSyntaxNode)context.SyntaxNodeOpt, + diagnostics: context.Diagnostics); + + yield return new Cci.TypeReferenceWithAttributes(typeRef); } } @@ -292,7 +293,8 @@ bool Cci.IGenericParameter.MustHaveDefaultConstructor { // add constructor constraint for value type constrained // type parameters to comply with Dev11 output - return this.HasConstructorConstraint || this.HasValueTypeConstraint; + // do this for "unmanaged" constraint too + return this.HasConstructorConstraint || this.HasValueTypeConstraint || this.HasUnmanagedTypeConstraint; } } diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 78d19bcdcfd97..2a67c13ac933a 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -1560,11 +1560,13 @@ internal enum ErrorCode ERR_DoNotUseFixedBufferAttrOnProperty = 8372, ERR_NewBoundWithUnmanaged = 8373, - ERR_UnmanagedConstraintMustBeAlone = 8374, + ERR_UnmanagedConstraintMustBeFirst = 8374, ERR_UnmanagedConstraintNotSatisfied = 8375, ERR_UnmanagedConstraintWithLocalFunctions = 8376, ERR_ConWithUnmanagedCon = 8377, + ERR_UnmanagedBoundWithClass = 8378, + // Note: you will need to re-generate compiler code after adding warnings (build\scripts\generate-compiler-code.cmd) } } diff --git a/src/Compilers/CSharp/Portable/Symbols/MemberSignatureComparer.cs b/src/Compilers/CSharp/Portable/Symbols/MemberSignatureComparer.cs index cd440de323eef..818bf99427401 100644 --- a/src/Compilers/CSharp/Portable/Symbols/MemberSignatureComparer.cs +++ b/src/Compilers/CSharp/Portable/Symbols/MemberSignatureComparer.cs @@ -555,6 +555,7 @@ public static bool HaveSameConstraints(TypeParameterSymbol typeParameter1, TypeM if ((typeParameter1.HasConstructorConstraint != typeParameter2.HasConstructorConstraint) || (typeParameter1.HasReferenceTypeConstraint != typeParameter2.HasReferenceTypeConstraint) || (typeParameter1.HasValueTypeConstraint != typeParameter2.HasValueTypeConstraint) || + (typeParameter1.HasUnmanagedTypeConstraint != typeParameter2.HasUnmanagedTypeConstraint) || (typeParameter1.Variance != typeParameter2.Variance)) { return false; diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.cs index 0c8f856c40ad4..d504881b64368 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.cs @@ -33,7 +33,7 @@ internal sealed class PETypeParameterSymbol private DiagnosticInfo _lazyConstraintsUseSiteErrorInfo = CSDiagnosticInfo.EmptyErrorInfo; // Indicates unknown state. private GenericParameterAttributes _lazyFlags; - private ThreeState _lazyHasIsUnmanagedAttribute; + private ThreeState _lazyHasIsUnmanagedConstraint; private TypeParameterBounds _lazyBounds = TypeParameterBounds.Unset; private ImmutableArray _lazyDeclaredConstraintTypes; private ImmutableArray _lazyCustomAttributes; @@ -170,12 +170,7 @@ private ImmutableArray GetDeclaredConstraintTypes() Interlocked.CompareExchange(ref _lazyConstraintsUseSiteErrorInfo, new CSDiagnosticInfo(ErrorCode.ERR_BindToBogus, this), CSDiagnosticInfo.EmptyErrorInfo); } - this.GetAttributes(); - if (_lazyHasIsUnmanagedAttribute.Value() && (_lazyFlags & (GenericParameterAttributes.ReferenceTypeConstraint | GenericParameterAttributes.DefaultConstructorConstraint)) != 0) - { - _lazyFlags = _lazyFlags & ~(GenericParameterAttributes.ReferenceTypeConstraint | GenericParameterAttributes.DefaultConstructorConstraint); - _lazyConstraintsUseSiteErrorInfo = new CSDiagnosticInfo(ErrorCode.ERR_BindToBogus, this); - } + bool hasUnmanagedModreqPattern = false; if (constraints.Count > 0) { @@ -196,11 +191,19 @@ private ImmutableArray GetDeclaredConstraintTypes() var constraint = metadataReader.GetGenericParameterConstraint(constraintHandle); var typeSymbol = tokenDecoder.DecodeGenericParameterConstraint(constraint.Type, out bool hasUnmanagedModreq); - if (hasUnmanagedModreq != this._lazyHasIsUnmanagedAttribute.Value()) + if (typeSymbol.SpecialType == SpecialType.System_ValueType) { - // The presence of UnmanagedType modreq has to match the presence of the IsUnmanagedAttribute - Interlocked.CompareExchange(ref _lazyConstraintsUseSiteErrorInfo, new CSDiagnosticInfo(ErrorCode.ERR_BindToBogus, this), CSDiagnosticInfo.EmptyErrorInfo); - continue; + // recognize "(class [mscorlib]System.ValueType modreq([mscorlib]System.Runtime.InteropServices.UnmanagedType" pattern as "unmanaged" + if (hasUnmanagedModreq) + { + hasUnmanagedModreqPattern = true; + } + + // Drop 'System.ValueType' constraint type if the 'valuetype' constraint was also specified. + if (((_lazyFlags & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0)) + { + continue; + } } // Drop 'System.Object' constraint type. @@ -209,13 +212,6 @@ private ImmutableArray GetDeclaredConstraintTypes() continue; } - // Drop 'System.ValueType' constraint type if the 'valuetype' constraint was also specified. - if (((_lazyFlags & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0) && - (typeSymbol.SpecialType == SpecialType.System_ValueType)) - { - continue; - } - typeSymbol = TupleTypeDecoder.DecodeTupleTypesIfApplicable(typeSymbol, constraintHandle, moduleSymbol); symbolsBuilder.Add(typeSymbol); @@ -228,6 +224,17 @@ private ImmutableArray GetDeclaredConstraintTypes() declaredConstraintTypes = ImmutableArray.Empty; } + // - presence of unmanaged pattern has to be matched with `valuetype` + // - IsUnmanagedAttribute is alloweed iif there is an unmanaged pattern + if (hasUnmanagedModreqPattern && (_lazyFlags & GenericParameterAttributes.NotNullableValueTypeConstraint) == 0 || + hasUnmanagedModreqPattern != moduleSymbol.Module.HasIsUnmanagedAttribute(_handle)) + { + // we do not recognize thse combinations as "unmanaged" + hasUnmanagedModreqPattern = false; + Interlocked.CompareExchange(ref _lazyConstraintsUseSiteErrorInfo, new CSDiagnosticInfo(ErrorCode.ERR_BindToBogus, this), CSDiagnosticInfo.EmptyErrorInfo); + } + + _lazyHasIsUnmanagedConstraint = hasUnmanagedModreqPattern.ToThreeState(); ImmutableInterlocked.InterlockedInitialize(ref _lazyDeclaredConstraintTypes, declaredConstraintTypes); } @@ -254,7 +261,6 @@ public override bool HasConstructorConstraint { get { - GetDeclaredConstraintTypes(); return (_lazyFlags & GenericParameterAttributes.DefaultConstructorConstraint) != 0; } } @@ -263,7 +269,6 @@ public override bool HasReferenceTypeConstraint { get { - GetDeclaredConstraintTypes(); return (_lazyFlags & GenericParameterAttributes.ReferenceTypeConstraint) != 0; } } @@ -272,8 +277,7 @@ public override bool HasValueTypeConstraint { get { - GetDeclaredConstraintTypes(); - return (_lazyFlags & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0 || HasUnmanagedTypeConstraint; + return (_lazyFlags & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0; } } @@ -282,7 +286,7 @@ public override bool HasUnmanagedTypeConstraint get { GetDeclaredConstraintTypes(); - return this._lazyHasIsUnmanagedAttribute.Value(); + return this._lazyHasIsUnmanagedConstraint.Value(); } } @@ -290,7 +294,6 @@ public override VarianceKind Variance { get { - GetDeclaredConstraintTypes(); return (VarianceKind)(_lazyFlags & GenericParameterAttributes.VarianceMask); } } @@ -334,18 +337,13 @@ public override ImmutableArray GetAttributes() { if (_lazyCustomAttributes.IsDefault) { - var loadedCustomAttributes = ((PEModuleSymbol)this.ContainingModule).GetCustomAttributesForToken( - this.Handle, - out CustomAttributeHandle isUnmanagedAttribute, - AttributeDescription.IsUnmanagedAttribute, - out _, - default, - out _, - default, - out _, - default); - - this._lazyHasIsUnmanagedAttribute = (!isUnmanagedAttribute.IsNil).ToThreeState(); + var containingPEModuleSymbol = (PEModuleSymbol)this.ContainingModule; + + var loadedCustomAttributes = containingPEModuleSymbol.GetCustomAttributesForToken( + Handle, + out _, + // Filter out [IsUnmanagedAttribute] + HasUnmanagedTypeConstraint ? AttributeDescription.IsUnmanagedAttribute : default); ImmutableInterlocked.InterlockedInitialize(ref _lazyCustomAttributes, loadedCustomAttributes); } diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index fa8b5acde37e5..5eecb77a6245b 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -8635,11 +8635,6 @@ Pokud chcete odstranit toto varování, můžete místo toho použít /reference The 'new()' constraint cannot be used with the 'unmanaged' constraint - - The 'unmanaged' constraint cannot be specified with other constraints. - The 'unmanaged' constraint cannot be specified with other constraints. - - The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' @@ -8655,6 +8650,16 @@ Pokud chcete odstranit toto varování, můžete místo toho použít /reference Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint + + + + The 'unmanaged' constraint must come before any other constraints + The 'unmanaged' constraint must come before any other constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 250cf76ac2cdf..d4d834f183d06 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -8635,11 +8635,6 @@ Um die Warnung zu beheben, können Sie stattdessen /reference verwenden (Einbett The 'new()' constraint cannot be used with the 'unmanaged' constraint - - The 'unmanaged' constraint cannot be specified with other constraints. - The 'unmanaged' constraint cannot be specified with other constraints. - - The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' @@ -8655,6 +8650,16 @@ Um die Warnung zu beheben, können Sie stattdessen /reference verwenden (Einbett Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint + + + + The 'unmanaged' constraint must come before any other constraints + The 'unmanaged' constraint must come before any other constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 17d15aa6c719f..67831eea3bc27 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -8635,11 +8635,6 @@ Para eliminar la advertencia puede usar /reference (establezca la propiedad Embe The 'new()' constraint cannot be used with the 'unmanaged' constraint - - The 'unmanaged' constraint cannot be specified with other constraints. - The 'unmanaged' constraint cannot be specified with other constraints. - - The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' @@ -8655,6 +8650,16 @@ Para eliminar la advertencia puede usar /reference (establezca la propiedad Embe Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint + + + + The 'unmanaged' constraint must come before any other constraints + The 'unmanaged' constraint must come before any other constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 0ba597ed5b197..378c27632bd22 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -8635,11 +8635,6 @@ Pour supprimer l'avertissement, vous pouvez utiliser la commande /reference (dé The 'new()' constraint cannot be used with the 'unmanaged' constraint - - The 'unmanaged' constraint cannot be specified with other constraints. - The 'unmanaged' constraint cannot be specified with other constraints. - - The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' @@ -8655,6 +8650,16 @@ Pour supprimer l'avertissement, vous pouvez utiliser la commande /reference (dé Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint + + + + The 'unmanaged' constraint must come before any other constraints + The 'unmanaged' constraint must come before any other constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 1f7095b3bdc1a..8f28974d3c5ea 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -8635,11 +8635,6 @@ Per rimuovere l'avviso, è invece possibile usare /reference (impostare la propr The 'new()' constraint cannot be used with the 'unmanaged' constraint - - The 'unmanaged' constraint cannot be specified with other constraints. - The 'unmanaged' constraint cannot be specified with other constraints. - - The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' @@ -8655,6 +8650,16 @@ Per rimuovere l'avviso, è invece possibile usare /reference (impostare la propr Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint + + + + The 'unmanaged' constraint must come before any other constraints + The 'unmanaged' constraint must come before any other constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 9e41ea1e4a9ad..119aeaf8b50dd 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -8635,11 +8635,6 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ The 'new()' constraint cannot be used with the 'unmanaged' constraint - - The 'unmanaged' constraint cannot be specified with other constraints. - The 'unmanaged' constraint cannot be specified with other constraints. - - The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' @@ -8655,6 +8650,16 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint + + + + The 'unmanaged' constraint must come before any other constraints + The 'unmanaged' constraint must come before any other constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 6845d54ba8381..ba557ca8147ef 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -8635,11 +8635,6 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ The 'new()' constraint cannot be used with the 'unmanaged' constraint - - The 'unmanaged' constraint cannot be specified with other constraints. - The 'unmanaged' constraint cannot be specified with other constraints. - - The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' @@ -8655,6 +8650,16 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint + + + + The 'unmanaged' constraint must come before any other constraints + The 'unmanaged' constraint must come before any other constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 6eb6268d324e3..830582a68ecaa 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -8635,11 +8635,6 @@ Aby usunąć ostrzeżenie, możesz zamiast tego użyć opcji /reference (ustaw w The 'new()' constraint cannot be used with the 'unmanaged' constraint - - The 'unmanaged' constraint cannot be specified with other constraints. - The 'unmanaged' constraint cannot be specified with other constraints. - - The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' @@ -8655,6 +8650,16 @@ Aby usunąć ostrzeżenie, możesz zamiast tego użyć opcji /reference (ustaw w Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint + + + + The 'unmanaged' constraint must come before any other constraints + The 'unmanaged' constraint must come before any other constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index de6aaefe6aa37..8434acd3f4207 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -8635,11 +8635,6 @@ Para incorporar informações de tipo de interoperabilidade para os dois assembl The 'new()' constraint cannot be used with the 'unmanaged' constraint - - The 'unmanaged' constraint cannot be specified with other constraints. - The 'unmanaged' constraint cannot be specified with other constraints. - - The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' @@ -8655,6 +8650,16 @@ Para incorporar informações de tipo de interoperabilidade para os dois assembl Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint + + + + The 'unmanaged' constraint must come before any other constraints + The 'unmanaged' constraint must come before any other constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index cf72a8cde9b72..2ce8e1d103a0f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -8635,11 +8635,6 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ The 'new()' constraint cannot be used with the 'unmanaged' constraint - - The 'unmanaged' constraint cannot be specified with other constraints. - The 'unmanaged' constraint cannot be specified with other constraints. - - The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' @@ -8655,6 +8650,16 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint + + + + The 'unmanaged' constraint must come before any other constraints + The 'unmanaged' constraint must come before any other constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index c25680ab4ce59..d4631ae05f38d 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -8635,11 +8635,6 @@ Uyarıyı kaldırmak için, /reference kullanabilirsiniz (Birlikte Çalışma T The 'new()' constraint cannot be used with the 'unmanaged' constraint - - The 'unmanaged' constraint cannot be specified with other constraints. - The 'unmanaged' constraint cannot be specified with other constraints. - - The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' @@ -8655,6 +8650,16 @@ Uyarıyı kaldırmak için, /reference kullanabilirsiniz (Birlikte Çalışma T Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint + + + + The 'unmanaged' constraint must come before any other constraints + The 'unmanaged' constraint must come before any other constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 10e68c5c35d76..3def7f78a7a9d 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -8635,11 +8635,6 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ The 'new()' constraint cannot be used with the 'unmanaged' constraint - - The 'unmanaged' constraint cannot be specified with other constraints. - The 'unmanaged' constraint cannot be specified with other constraints. - - The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' @@ -8655,6 +8650,16 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint + + + + The 'unmanaged' constraint must come before any other constraints + The 'unmanaged' constraint must come before any other constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 453c20e2e6217..056028da42b9f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -8635,11 +8635,6 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ The 'new()' constraint cannot be used with the 'unmanaged' constraint - - The 'unmanaged' constraint cannot be specified with other constraints. - The 'unmanaged' constraint cannot be specified with other constraints. - - The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' The type '{2}' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter '{1}' in the generic type or method '{0}' @@ -8655,6 +8650,16 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Type parameter '{1}' has the 'unmanaged' constraint so '{1}' cannot be used as a constraint for '{0}' + + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint + '{0}': cannot specify both a constraint class and the 'unmanaged' constraint + + + + The 'unmanaged' constraint must come before any other constraints + The 'unmanaged' constraint must come before any other constraints + + \ No newline at end of file diff --git a/src/Compilers/CSharp/Test/Emit/Emit/UnmanagedTypeModifierTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/UnmanagedTypeModifierTests.cs index 5eec86a54c217..c71f5c0bf3b0a 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/UnmanagedTypeModifierTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/UnmanagedTypeModifierTests.cs @@ -66,9 +66,15 @@ public static void Main() }"; CreateCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (9,13): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'TestRef.M2()'. There is no boxing conversion from 'int' to '?'. + // obj.M2(); // invalid + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "M2").WithArguments("TestRef.M2()", "?", "T", "int").WithLocation(9, 13), // (9,13): error CS0570: 'T' is not supported by the language // obj.M2(); // invalid - Diagnostic(ErrorCode.ERR_BindToBogus, "M2").WithArguments("T").WithLocation(9, 13) + Diagnostic(ErrorCode.ERR_BindToBogus, "M2").WithArguments("T").WithLocation(9, 13), + // (9,13): error CS0648: '' is a type not supported by the language + // obj.M2(); // invalid + Diagnostic(ErrorCode.ERR_BogusType, "M2").WithArguments("").WithLocation(9, 13) ); } @@ -129,9 +135,15 @@ public static void Main() }"; CreateCompilation(code, references: new[] { reference }).VerifyDiagnostics( + // (9,13): error CS0315: The type 'int' cannot be used as type parameter 'T' in the generic type or method 'TestRef.M2()'. There is no boxing conversion from 'int' to '?'. + // obj.M2(); // invalid + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "M2").WithArguments("TestRef.M2()", "?", "T", "int").WithLocation(9, 13), // (9,13): error CS0570: 'T' is not supported by the language // obj.M2(); // invalid - Diagnostic(ErrorCode.ERR_BindToBogus, "M2").WithArguments("T").WithLocation(9, 13) + Diagnostic(ErrorCode.ERR_BindToBogus, "M2").WithArguments("T").WithLocation(9, 13), + // (9,13): error CS0648: '' is a type not supported by the language + // obj.M2(); // invalid + Diagnostic(ErrorCode.ERR_BogusType, "M2").WithArguments("").WithLocation(9, 13) ); } @@ -941,13 +953,20 @@ public class Test public static void Main() { new TestRef().M(); + new TestRef().M(); } }"; CreateCompilation(code, references: new[] { reference }).VerifyDiagnostics( - // (6,23): error CS0570: 'T' is not supported by the language + // (6,23): error CS0452: The type 'int' must be a reference type in order to use it as parameter 'T' in the generic type or method 'TestRef.M()' // new TestRef().M(); - Diagnostic(ErrorCode.ERR_BindToBogus, "M").WithArguments("T").WithLocation(6, 23) + Diagnostic(ErrorCode.ERR_RefConstraintNotSatisfied, "M").WithArguments("TestRef.M()", "T", "int").WithLocation(6, 23), + // (7,23): error CS0311: The type 'string' cannot be used as type parameter 'T' in the generic type or method 'TestRef.M()'. There is no implicit reference conversion from 'string' to 'System.ValueType'. + // new TestRef().M(); + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "M").WithArguments("TestRef.M()", "System.ValueType", "T", "string").WithLocation(7, 23), + // (7,23): error CS0570: 'T' is not supported by the language + // new TestRef().M(); + Diagnostic(ErrorCode.ERR_BindToBogus, "M").WithArguments("T").WithLocation(7, 23) ); } @@ -1038,14 +1057,20 @@ public class Test { public static void Main() { + // OK new TestRef().M(); + + // Not IComparable + new TestRef().M(); } + + struct S1{} }"; CreateCompilation(code, references: new[] { reference }).VerifyDiagnostics( - // (6,23): error CS0570: 'T' is not supported by the language - // new TestRef().M(); - Diagnostic(ErrorCode.ERR_BindToBogus, "M").WithArguments("T").WithLocation(6, 23) + // (10,23): error CS0315: The type 'Test.S1' cannot be used as type parameter 'T' in the generic type or method 'TestRef.M()'. There is no boxing conversion from 'Test.S1' to 'System.IComparable'. + // new TestRef().M(); + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "M").WithArguments("TestRef.M()", "System.IComparable", "T", "Test.S1").WithLocation(10, 23) ); } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs index 019b4813548b8..edd2143bc910e 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs @@ -667,9 +667,10 @@ public void DelegateConstraint_Compilation_ValueType() public class Test where T : struct, System.Delegate { }").VerifyDiagnostics( - // (2,19): error CS0455: Type parameter 'T' inherits conflicting constraints 'Delegate' and 'ValueType' + // (2,40): error CS0450: 'Delegate': cannot specify both a constraint class and the 'class' or 'struct' constraint // public class Test where T : struct, System.Delegate - Diagnostic(ErrorCode.ERR_BaseConstraintConflict, "T").WithArguments("T", "System.Delegate", "System.ValueType").WithLocation(2, 19)); + Diagnostic(ErrorCode.ERR_RefValBoundWithClass, "System.Delegate").WithArguments("System.Delegate").WithLocation(2, 40) + ); } [Fact] @@ -864,16 +865,17 @@ public void DelegateConstraint_IsReflectedinSymbols_ValueType() { var compilation = CreateCompilation("public class Test where T : struct, System.Delegate { }") .VerifyDiagnostics( - // (1,19): error CS0455: Type parameter 'T' inherits conflicting constraints 'Delegate' and 'ValueType' - // public class Test where T : struct, System.Delegate { } - Diagnostic(ErrorCode.ERR_BaseConstraintConflict, "T").WithArguments("T", "System.Delegate", "System.ValueType").WithLocation(1, 19)); + // (1,40): error CS0450: 'Delegate': cannot specify both a constraint class and the 'class' or 'struct' constraint + // public class Test where T : struct, System.Delegate { } + Diagnostic(ErrorCode.ERR_RefValBoundWithClass, "System.Delegate").WithArguments("System.Delegate").WithLocation(1, 40) + ); var typeParameter = compilation.GlobalNamespace.GetTypeMember("Test").TypeParameters.Single(); Assert.True(typeParameter.HasValueTypeConstraint); Assert.False(typeParameter.HasReferenceTypeConstraint); Assert.False(typeParameter.HasConstructorConstraint); - Assert.Equal(SpecialType.System_Delegate, typeParameter.ConstraintTypes().Single().SpecialType); + Assert.Empty(typeParameter.ConstraintTypes()); } [Fact] @@ -1126,9 +1128,10 @@ public void MulticastDelegateConstraint_Compilation_ValueType() public class Test where T : struct, System.MulticastDelegate { }").VerifyDiagnostics( - // (2,19): error CS0455: Type parameter 'T' inherits conflicting constraints 'MulticastDelegate' and 'ValueType' + // (2,40): error CS0450: 'MulticastDelegate': cannot specify both a constraint class and the 'class' or 'struct' constraint // public class Test where T : struct, System.MulticastDelegate - Diagnostic(ErrorCode.ERR_BaseConstraintConflict, "T").WithArguments("T", "System.MulticastDelegate", "System.ValueType").WithLocation(2, 19)); + Diagnostic(ErrorCode.ERR_RefValBoundWithClass, "System.MulticastDelegate").WithArguments("System.MulticastDelegate").WithLocation(2, 40) + ); } [Fact] @@ -1326,16 +1329,17 @@ public void MulticastDelegateConstraint_IsReflectedinSymbols_ValueType() { var compilation = CreateCompilation("public class Test where T : struct, System.MulticastDelegate { }") .VerifyDiagnostics( - // (1,19): error CS0455: Type parameter 'T' inherits conflicting constraints 'MulticastDelegate' and 'ValueType' - // public class Test where T : struct, System.MulticastDelegate { } - Diagnostic(ErrorCode.ERR_BaseConstraintConflict, "T").WithArguments("T", "System.MulticastDelegate", "System.ValueType").WithLocation(1, 19)); + // (1,40): error CS0450: 'MulticastDelegate': cannot specify both a constraint class and the 'class' or 'struct' constraint + // public class Test where T : struct, System.MulticastDelegate { } + Diagnostic(ErrorCode.ERR_RefValBoundWithClass, "System.MulticastDelegate").WithArguments("System.MulticastDelegate").WithLocation(1, 40) + ); var typeParameter = compilation.GlobalNamespace.GetTypeMember("Test").TypeParameters.Single(); Assert.True(typeParameter.HasValueTypeConstraint); Assert.False(typeParameter.HasReferenceTypeConstraint); Assert.False(typeParameter.HasConstructorConstraint); - Assert.Equal(SpecialType.System_MulticastDelegate, typeParameter.ConstraintTypes().Single().SpecialType); + Assert.Empty(typeParameter.ConstraintTypes()); } [Fact] @@ -1663,18 +1667,18 @@ void local() where T : unmanaged { } public void UnmanagedConstraint_Compilation_ReferenceType() { CreateCompilation("public class Test where T : class, unmanaged {}").VerifyDiagnostics( - // (1,39): error CS8374: The 'unmanaged' constraint cannot be specified with other constraints. + // (1,39): error CS8374: The 'unmanaged' constraint must come before any other constraints // public class Test where T : class, unmanaged {} - Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeAlone, "unmanaged").WithLocation(1, 39)); + Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeFirst, "unmanaged").WithLocation(1, 39)); } [Fact] public void UnmanagedConstraint_Compilation_ValueType() { CreateCompilation("public class Test where T : struct, unmanaged {}").VerifyDiagnostics( - // (1,40): error CS8374: The 'unmanaged' constraint cannot be specified with other constraints. + // (1,40): error CS8374: The 'unmanaged' constraint must come before any other constraints // public class Test where T : struct, unmanaged {} - Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeAlone, "unmanaged").WithLocation(1, 40)); + Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeFirst, "unmanaged").WithLocation(1, 40)); } [Fact] @@ -1690,36 +1694,47 @@ public void UnmanagedConstraint_Compilation_Constructor() public void UnmanagedConstraint_Compilation_AnotherType_Before() { CreateCompilation("public class Test where T : unmanaged, System.Exception { }").VerifyDiagnostics( - // (1,43): error CS8374: The 'unmanaged' constraint cannot be specified with other constraints. + // (1,19): error CS0455: Type parameter 'T' inherits conflicting constraints 'Exception' and 'ValueType' // public class Test where T : unmanaged, System.Exception { } - Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeAlone, "System.Exception").WithLocation(1, 43)); + Diagnostic(ErrorCode.ERR_BaseConstraintConflict, "T").WithArguments("T", "System.Exception", "System.ValueType").WithLocation(1, 19) + ); + } + + [Fact] + public void UnmanagedConstraint_Compilation_AnotherType_Before1() + { + CreateCompilation("public class Test where T : unmanaged, System.Enum { }").VerifyDiagnostics(); + + CreateCompilation("public class Test where T : unmanaged, System.Delegate { }").VerifyDiagnostics( + // (1,19): error CS0455: Type parameter 'T' inherits conflicting constraints 'Delegate' and 'ValueType' + // public class Test where T : unmanaged, System.Delegate { } + Diagnostic(ErrorCode.ERR_BaseConstraintConflict, "T").WithArguments("T", "System.Delegate", "System.ValueType").WithLocation(1, 19) + ); } [Fact] public void UnmanagedConstraint_Compilation_AnotherType_After() { CreateCompilation("public class Test where T : System.Exception, unmanaged { }").VerifyDiagnostics( - // (1,50): error CS8374: The 'unmanaged' constraint cannot be specified with other constraints. + // (1,50): error CS8374: The 'unmanaged' constraint must come before any other constraints // public class Test where T : System.Exception, unmanaged { } - Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeAlone, "unmanaged").WithLocation(1, 50)); + Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeFirst, "unmanaged").WithLocation(1, 50)); } [Fact] public void UnmanagedConstraint_Compilation_AnotherParameter_After() { CreateCompilation("public class Test where T : U, unmanaged { }").VerifyDiagnostics( - // (1,38): error CS8374: The 'unmanaged' constraint cannot be specified with other constraints. + // (1,38): error CS8374: The 'unmanaged' constraint must come before any other constraints // public class Test where T : U, unmanaged { } - Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeAlone, "unmanaged").WithLocation(1, 38)); + Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeFirst, "unmanaged").WithLocation(1, 38)); } [Fact] public void UnmanagedConstraint_Compilation_AnotherParameter_Before() { - CreateCompilation("public class Test where T : unmanaged, U { }").VerifyDiagnostics( - // (1,46): error CS8374: The 'unmanaged' constraint cannot be specified with other constraints. - // public class Test where T : unmanaged, U { } - Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeAlone, "U").WithLocation(1, 46)); + CreateCompilation("public class Test where T : unmanaged, U { }").VerifyDiagnostics(); + CreateCompilation("public class Test where U: class where T : unmanaged, U, System.IDisposable { }").VerifyDiagnostics(); } [Fact] @@ -2024,6 +2039,153 @@ public override void M() where T : unmanaged { } Diagnostic(ErrorCode.ERR_OverrideWithConstraints, "where").WithLocation(8, 33)); } + [Fact] + public void UnmanagedConstraint_StructMismatchInImplements() + { + CreateCompilation(@" +public interface I1 where T : unmanaged +{ + void Test(G x) where G : unmanaged; +} + +public class C2 : I1 where T : struct +{ + public void Test(G x) where G : struct + { + I1 i = this; + i.Test(default(System.ArraySegment)); + } +} +").VerifyDiagnostics( + // (7,14): error CS8375: The type 'T' cannot be a reference type, or contain reference type 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. + // 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 CS8375: The type 'T' cannot be a reference type, or contain reference type 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 CS8375: The type 'ArraySegment' cannot be a reference type, or contain reference type 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) + ); + } + + [Fact] + public void UnmanagedConstraint_TypeMismatchInImplements() + { + CreateCompilation(@" +public interface I1 where T : unmanaged, System.IDisposable +{ + void Test(G x) where G : unmanaged, System.Enum; +} + +public class C2 : I1 where T : unmanaged +{ + public void Test(G x) where G : unmanaged + { + I1 i = this; + i.Test(default(System.AttributeTargets)); // <-- this one is OK + i.Test(0); + } +} +").VerifyDiagnostics( + // (7,14): error CS0314: The type 'T' cannot be used as type parameter 'T' in the generic type or method 'I1'. There is no boxing conversion or type parameter conversion from 'T' to 'System.IDisposable'. + // public class C2 : I1 where T : unmanaged + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedTyVar, "C2").WithArguments("I1", "System.IDisposable", "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. + // public void Test(G x) where G : unmanaged + Diagnostic(ErrorCode.ERR_ImplBadConstraints, "Test").WithArguments("G", "C2.Test(G)", "G", "I1.Test(G)").WithLocation(9, 17), + // (11,12): error CS0314: The type 'T' cannot be used as type parameter 'T' in the generic type or method 'I1'. There is no boxing conversion or type parameter conversion from 'T' to 'System.IDisposable'. + // I1 i = this; + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedTyVar, "T").WithArguments("I1", "System.IDisposable", "T", "T").WithLocation(11, 12), + // (13,11): error CS0315: The type 'int' cannot be used as type parameter 'G' in the generic type or method 'I1.Test(G)'. There is no boxing conversion from 'int' to 'System.Enum'. + // i.Test(0); + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "Test").WithArguments("I1.Test(G)", "System.Enum", "G", "int").WithLocation(13, 11) + ); + } + + [Fact] + public void UnmanagedConstraint_TypeMismatchInImplementsMeta() + { + var reference = CreateCompilation(@" +public interface I1 where T : unmanaged, System.IDisposable +{ + void Test(G x) where G : unmanaged, System.Enum; +} +").EmitToImageReference(); + + CreateCompilation(@" +public class C2 : I1 where T : unmanaged +{ + public void Test(G x) where G : unmanaged + { + I1 i = this; + i.Test(default(System.AttributeTargets)); // <-- this one is OK + i.Test(0); + } +}", references: new[] { reference }).VerifyDiagnostics( + // (2,14): error CS0314: The type 'T' cannot be used as type parameter 'T' in the generic type or method 'I1'. There is no boxing conversion or type parameter conversion from 'T' to 'System.IDisposable'. + // public class C2 : I1 where T : unmanaged + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedTyVar, "C2").WithArguments("I1", "System.IDisposable", "T", "T").WithLocation(2, 14), + // (4,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 : unmanaged + Diagnostic(ErrorCode.ERR_ImplBadConstraints, "Test").WithArguments("G", "C2.Test(G)", "G", "I1.Test(G)").WithLocation(4, 17), + // (6,12): error CS0314: The type 'T' cannot be used as type parameter 'T' in the generic type or method 'I1'. There is no boxing conversion or type parameter conversion from 'T' to 'System.IDisposable'. + // I1 i = this; + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedTyVar, "T").WithArguments("I1", "System.IDisposable", "T", "T").WithLocation(6, 12), + // (8,11): error CS0315: The type 'int' cannot be used as type parameter 'G' in the generic type or method 'I1.Test(G)'. There is no boxing conversion from 'int' to 'System.Enum'. + // i.Test(0); + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "Test").WithArguments("I1.Test(G)", "System.Enum", "G", "int").WithLocation(8, 11) + ); + } + + [Fact] + public void UnmanagedConstraint_TypeMismatchInImplementsMeta2() + { + var reference = CreateCompilation(@" + public interface I1 + { + void Test(ref G x) where G : unmanaged, System.IDisposable; + } +").EmitToImageReference(); + + var reference1 = CreateCompilation(@" +public class C1 : I1 +{ + void I1.Test(ref G x) + { + x.Dispose(); + } +}", references: new[] { reference }).EmitToImageReference(); ; + + CompileAndVerify(@" +struct S : System.IDisposable +{ + public int a; + + public void Dispose() + { + a += 123; + } +} + +class Test +{ + static void Main() + { + S local = default; + I1 i = new C1(); + i.Test(ref local); + System.Console.WriteLine(local.a); + } +}", + + // NOTE: must pass verification (IDisposable constraint is copied over to the implementing method) + options: TestOptions.UnsafeReleaseExe, references: new[] { reference, reference1 }, verify: Verification.Passes, expectedOutput: "123"); + } + [Fact] public void UnmanagedConstraint_EnforcedInInheritanceChain_Upwards_Reference() { @@ -2127,6 +2289,59 @@ .maxstack 2 }"); } + [Fact] + public void UnmanagedConstraints_InterfaceMethod() + { + CompileAndVerify(@" +struct S : System.IDisposable +{ + public int a; + + public void Dispose() + { + a += 123; + } +} +unsafe class Test +{ + static void M(ref T arg) where T : unmanaged, System.IDisposable + { + arg.Dispose(); + + fixed(T* ptr = &arg) + { + ptr->Dispose(); + } + } + + static void Main() + { + S local = default; + M(ref local); + System.Console.WriteLine(local.a); + } +}", + options: TestOptions.UnsafeReleaseExe, verify: Verification.Fails, expectedOutput: "246").VerifyIL("Test.M", @" +{ + // Code size 31 (0x1f) + .maxstack 1 + .locals init (pinned T& V_0) + IL_0000: ldarg.0 + IL_0001: constrained. ""T"" + IL_0007: callvirt ""void System.IDisposable.Dispose()"" + IL_000c: ldarg.0 + IL_000d: stloc.0 + IL_000e: ldloc.0 + IL_000f: conv.u + IL_0010: constrained. ""T"" + IL_0016: callvirt ""void System.IDisposable.Dispose()"" + IL_001b: ldc.i4.0 + IL_001c: conv.u + IL_001d: stloc.0 + IL_001e: ret +}"); + } + [Fact] public void UnmanagedConstraints_NestedStructs_Flat() { diff --git a/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs b/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs index 6eb6e70f3714f..e24ecdfbcd7e1 100644 --- a/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs @@ -6488,11 +6488,11 @@ public void UnmanagedConstraint_Method() TestSymbolDescription(@" class X { - void M() where T : unmanaged { } + void M() where T : unmanaged, System.IDisposable { } }", global => global.GetTypeMember("X").GetMethod("M"), SymbolDisplayFormat.TestFormat.AddGenericsOptions(SymbolDisplayGenericsOptions.IncludeTypeConstraints), - "void X.M() where T : unmanaged", + "void X.M() where T : unmanaged, System.IDisposable", SymbolDisplayPartKind.Keyword, SymbolDisplayPartKind.Space, SymbolDisplayPartKind.ClassName, @@ -6510,7 +6510,12 @@ void M() where T : unmanaged { } SymbolDisplayPartKind.Space, SymbolDisplayPartKind.Punctuation, SymbolDisplayPartKind.Space, - SymbolDisplayPartKind.Keyword); + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.NamespaceName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.InterfaceName); } [Fact] From 1367a28a729c7a1d76cbcb691b1cfbd060167bb5 Mon Sep 17 00:00:00 2001 From: vsadov Date: Fri, 9 Mar 2018 19:09:41 -0800 Subject: [PATCH 10/13] remove TODO --- src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs index 6ba15a5f99d07..8b8184ebd8565 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs @@ -147,7 +147,6 @@ private TypeParameterConstraintClause BindTypeParameterConstraints( { if (constraints != 0 || constraintTypes.Any()) { - // TODO: VS first diagnostics.Add(ErrorCode.ERR_UnmanagedConstraintMustBeFirst, typeSyntax.GetLocation()); continue; } From 8f034bf22116eb21704647bc1d12b172ef354e58 Mon Sep 17 00:00:00 2001 From: vsadov Date: Mon, 12 Mar 2018 13:56:01 -0700 Subject: [PATCH 11/13] PR feedback --- .../Portable/Binder/Binder_Constraints.cs | 2 +- .../Model/TypeParameterSymbolAdapter.cs | 7 +- .../Metadata/PE/PETypeParameterSymbol.cs | 20 +++--- .../Emit/Emit/UnmanagedTypeModifierTests.cs | 67 ++++++++++++++++++- .../Semantics/GenericConstraintsTests.cs | 50 ++++++++++++-- 5 files changed, 125 insertions(+), 21 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs index 8b8184ebd8565..f1944cf6f8bd2 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs @@ -212,7 +212,7 @@ private TypeParameterConstraintClause BindTypeParameterConstraints( Error(diagnostics, ErrorCode.ERR_RefValBoundWithClass, syntax, type); continue; } - else if ((constraints & TypeParameterConstraintKind.ValueType) != 0) + else if ((constraints & TypeParameterConstraintKind.Unmanaged) != 0) { // "'{0}': cannot specify both a constraint class and the 'unmanaged' constraint" Error(diagnostics, ErrorCode.ERR_UnmanagedBoundWithClass, syntax, type); diff --git a/src/Compilers/CSharp/Portable/Emitter/Model/TypeParameterSymbolAdapter.cs b/src/Compilers/CSharp/Portable/Emitter/Model/TypeParameterSymbolAdapter.cs index d59224eb95c10..95656cd43b086 100644 --- a/src/Compilers/CSharp/Portable/Emitter/Model/TypeParameterSymbolAdapter.cs +++ b/src/Compilers/CSharp/Portable/Emitter/Model/TypeParameterSymbolAdapter.cs @@ -227,9 +227,10 @@ Cci.ITypeReference Cci.IGenericTypeParameterReference.DefiningType var seenValueType = false; if (this.HasUnmanagedTypeConstraint) { - var typeRef = moduleBeingBuilt.GetSpecialType(SpecialType.System_ValueType, - syntaxNodeOpt: (CSharpSyntaxNode)context.SyntaxNodeOpt, - diagnostics: context.Diagnostics); + var typeRef = moduleBeingBuilt.GetSpecialType( + SpecialType.System_ValueType, + syntaxNodeOpt: (CSharpSyntaxNode)context.SyntaxNodeOpt, + diagnostics: context.Diagnostics); var modifier = CSharpCustomModifier.CreateRequired( moduleBeingBuilt.Compilation.GetWellKnownType(WellKnownType.System_Runtime_InteropServices_UnmanagedType)); diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.cs index d504881b64368..8ae36d66cdd22 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PETypeParameterSymbol.cs @@ -32,7 +32,7 @@ internal sealed class PETypeParameterSymbol /// private DiagnosticInfo _lazyConstraintsUseSiteErrorInfo = CSDiagnosticInfo.EmptyErrorInfo; // Indicates unknown state. - private GenericParameterAttributes _lazyFlags; + private readonly GenericParameterAttributes _flags; private ThreeState _lazyHasIsUnmanagedConstraint; private TypeParameterBounds _lazyBounds = TypeParameterBounds.Unset; private ImmutableArray _lazyDeclaredConstraintTypes; @@ -87,7 +87,7 @@ private PETypeParameterSymbol( // Clear the '.ctor' flag if both '.ctor' and 'valuetype' are // set since '.ctor' is redundant in that case. - _lazyFlags = ((flags & GenericParameterAttributes.NotNullableValueTypeConstraint) == 0) ? flags : (flags & ~GenericParameterAttributes.DefaultConstructorConstraint); + _flags = ((flags & GenericParameterAttributes.NotNullableValueTypeConstraint) == 0) ? flags : (flags & ~GenericParameterAttributes.DefaultConstructorConstraint); _ordinal = ordinal; _handle = handle; @@ -200,7 +200,7 @@ private ImmutableArray GetDeclaredConstraintTypes() } // Drop 'System.ValueType' constraint type if the 'valuetype' constraint was also specified. - if (((_lazyFlags & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0)) + if (((_flags & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0)) { continue; } @@ -225,11 +225,11 @@ private ImmutableArray GetDeclaredConstraintTypes() } // - presence of unmanaged pattern has to be matched with `valuetype` - // - IsUnmanagedAttribute is alloweed iif there is an unmanaged pattern - if (hasUnmanagedModreqPattern && (_lazyFlags & GenericParameterAttributes.NotNullableValueTypeConstraint) == 0 || + // - IsUnmanagedAttribute is allowed iif there is an unmanaged pattern + if (hasUnmanagedModreqPattern && (_flags & GenericParameterAttributes.NotNullableValueTypeConstraint) == 0 || hasUnmanagedModreqPattern != moduleSymbol.Module.HasIsUnmanagedAttribute(_handle)) { - // we do not recognize thse combinations as "unmanaged" + // we do not recognize these combinations as "unmanaged" hasUnmanagedModreqPattern = false; Interlocked.CompareExchange(ref _lazyConstraintsUseSiteErrorInfo, new CSDiagnosticInfo(ErrorCode.ERR_BindToBogus, this), CSDiagnosticInfo.EmptyErrorInfo); } @@ -261,7 +261,7 @@ public override bool HasConstructorConstraint { get { - return (_lazyFlags & GenericParameterAttributes.DefaultConstructorConstraint) != 0; + return (_flags & GenericParameterAttributes.DefaultConstructorConstraint) != 0; } } @@ -269,7 +269,7 @@ public override bool HasReferenceTypeConstraint { get { - return (_lazyFlags & GenericParameterAttributes.ReferenceTypeConstraint) != 0; + return (_flags & GenericParameterAttributes.ReferenceTypeConstraint) != 0; } } @@ -277,7 +277,7 @@ public override bool HasValueTypeConstraint { get { - return (_lazyFlags & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0; + return (_flags & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0; } } @@ -294,7 +294,7 @@ public override VarianceKind Variance { get { - return (VarianceKind)(_lazyFlags & GenericParameterAttributes.VarianceMask); + return (VarianceKind)(_flags & GenericParameterAttributes.VarianceMask); } } diff --git a/src/Compilers/CSharp/Test/Emit/Emit/UnmanagedTypeModifierTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/UnmanagedTypeModifierTests.cs index c71f5c0bf3b0a..465572c2dae79 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/UnmanagedTypeModifierTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/UnmanagedTypeModifierTests.cs @@ -860,6 +860,7 @@ public static void Print(D lambda) where T : unmanaged var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("D`1").TypeParameters.Single(); Assert.True(typeParameter.HasValueTypeConstraint); Assert.True(typeParameter.HasUnmanagedTypeConstraint); + Assert.True(typeParameter.HasConstructorConstraint); AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, typeParameter, module.ContainingAssembly.Name); }); @@ -886,6 +887,7 @@ public static void Main() var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Program").GetTypeMember("<>c__DisplayClass0_0").TypeParameters.Single(); Assert.True(typeParameter.HasValueTypeConstraint); Assert.True(typeParameter.HasUnmanagedTypeConstraint); + Assert.True(typeParameter.HasConstructorConstraint); AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, typeParameter, module.ContainingAssembly.Name); }); @@ -1027,7 +1029,7 @@ .class public auto ansi beforefieldinit TestRef extends [mscorlib]System.Object { .method public hidebysig instance void - M() cil managed + M() cil managed { .param type T .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) @@ -1074,6 +1076,69 @@ struct S1{} ); } + [Fact] + public void UnmanagedConstraintWithNoCtorConstraint_IL() + { + var ilSource = IsUnmanagedAttributeIL + @" +.class public auto ansi beforefieldinit TestRef + extends [mscorlib]System.Object +{ + .method public hidebysig instance void + M() cil managed + { + .param type T + .custom instance void System.Runtime.CompilerServices.IsUnmanagedAttribute::.ctor() = ( 01 00 00 00 ) + // Code size 2 (0x2) + .maxstack 8 + IL_0000: nop + IL_0001: ret + } // end of method TestRef::M + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method TestRef::.ctor + +}"; + + var reference = CompileIL(ilSource, prependDefaultHeader: false); + + var code = @" +public class Test +{ + public static void Main() + { + // OK + new TestRef().M(); + + // Not IComparable + new TestRef().M(); + } + + struct S1{} +}"; + + var c = CreateCompilation(code, references: new[] { reference }); + + c.VerifyDiagnostics( + // (10,23): error CS0315: The type 'Test.S1' cannot be used as type parameter 'T' in the generic type or method 'TestRef.M()'. There is no boxing conversion from 'Test.S1' to 'System.IComparable'. + // new TestRef().M(); + Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "M").WithArguments("TestRef.M()", "System.IComparable", "T", "Test.S1").WithLocation(10, 23) + ); + + var typeParameter = c.GlobalNamespace.GetTypeMember("TestRef").GetMethod("M").TypeParameters.Single(); + Assert.True(typeParameter.HasUnmanagedTypeConstraint); + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.False(typeParameter.HasReferenceTypeConstraint); + Assert.False(typeParameter.HasConstructorConstraint); + } + private const string IsUnmanagedAttributeIL = @" .assembly extern mscorlib { diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs index edd2143bc910e..2a065dae6060c 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs @@ -1666,19 +1666,37 @@ void local() where T : unmanaged { } [Fact] public void UnmanagedConstraint_Compilation_ReferenceType() { - CreateCompilation("public class Test where T : class, unmanaged {}").VerifyDiagnostics( + var c = CreateCompilation("public class Test where T : class, unmanaged {}"); + + c.VerifyDiagnostics( // (1,39): error CS8374: The 'unmanaged' constraint must come before any other constraints // public class Test where T : class, unmanaged {} Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeFirst, "unmanaged").WithLocation(1, 39)); + + var typeParameter = c.GlobalNamespace.GetTypeMember("Test").TypeParameters.Single(); + Assert.False(typeParameter.HasUnmanagedTypeConstraint); + Assert.False(typeParameter.HasValueTypeConstraint); + Assert.True(typeParameter.HasReferenceTypeConstraint); + Assert.False(typeParameter.HasConstructorConstraint); + Assert.Empty(typeParameter.ConstraintTypes()); } [Fact] public void UnmanagedConstraint_Compilation_ValueType() { - CreateCompilation("public class Test where T : struct, unmanaged {}").VerifyDiagnostics( + var c = CreateCompilation("public class Test where T : struct, unmanaged {}"); + + c.VerifyDiagnostics( // (1,40): error CS8374: The 'unmanaged' constraint must come before any other constraints // public class Test where T : struct, unmanaged {} Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeFirst, "unmanaged").WithLocation(1, 40)); + + var typeParameter = c.GlobalNamespace.GetTypeMember("Test").TypeParameters.Single(); + Assert.False(typeParameter.HasUnmanagedTypeConstraint); + Assert.True(typeParameter.HasValueTypeConstraint); + Assert.False(typeParameter.HasReferenceTypeConstraint); + Assert.False(typeParameter.HasConstructorConstraint); + Assert.Empty(typeParameter.ConstraintTypes()); } [Fact] @@ -1694,9 +1712,9 @@ public void UnmanagedConstraint_Compilation_Constructor() public void UnmanagedConstraint_Compilation_AnotherType_Before() { CreateCompilation("public class Test where T : unmanaged, System.Exception { }").VerifyDiagnostics( - // (1,19): error CS0455: Type parameter 'T' inherits conflicting constraints 'Exception' and 'ValueType' + // (1,43): error CS8378: 'Exception': cannot specify both a constraint class and the 'unmanaged' constraint // public class Test where T : unmanaged, System.Exception { } - Diagnostic(ErrorCode.ERR_BaseConstraintConflict, "T").WithArguments("T", "System.Exception", "System.ValueType").WithLocation(1, 19) + Diagnostic(ErrorCode.ERR_UnmanagedBoundWithClass, "System.Exception").WithArguments("System.Exception").WithLocation(1, 43) ); } @@ -1706,9 +1724,9 @@ public void UnmanagedConstraint_Compilation_AnotherType_Before1() CreateCompilation("public class Test where T : unmanaged, System.Enum { }").VerifyDiagnostics(); CreateCompilation("public class Test where T : unmanaged, System.Delegate { }").VerifyDiagnostics( - // (1,19): error CS0455: Type parameter 'T' inherits conflicting constraints 'Delegate' and 'ValueType' + // (1,43): error CS8378: 'Delegate': cannot specify both a constraint class and the 'unmanaged' constraint // public class Test where T : unmanaged, System.Delegate { } - Diagnostic(ErrorCode.ERR_BaseConstraintConflict, "T").WithArguments("T", "System.Delegate", "System.ValueType").WithLocation(1, 19) + Diagnostic(ErrorCode.ERR_UnmanagedBoundWithClass, "System.Delegate").WithArguments("System.Delegate").WithLocation(1, 43) ); } @@ -2342,6 +2360,26 @@ .locals init (pinned T& V_0) }"); } + [Fact] + public void UnmanagedConstraints_CtorAndValueTypeAreEmitted() + { + CompileAndVerify(@" +using System.Linq; +class Program +{ + public static void M() where T: unmanaged + { + } + + static void Main(string[] args) + { + var typeParam = typeof(Program).GetMethod(""M"").GetGenericArguments().First(); + System.Console.WriteLine(typeParam.GenericParameterAttributes); + } +}", + options: TestOptions.UnsafeReleaseExe, verify: Verification.Passes, expectedOutput: "NotNullableValueTypeConstraint, DefaultConstructorConstraint"); + } + [Fact] public void UnmanagedConstraints_NestedStructs_Flat() { From b64ca1b255a6736bf16278358b7930d7ecd686da Mon Sep 17 00:00:00 2001 From: vsadov Date: Mon, 12 Mar 2018 14:53:50 -0700 Subject: [PATCH 12/13] Fixed a test. --- .../CSharp/Test/Emit/Emit/UnmanagedTypeModifierTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Compilers/CSharp/Test/Emit/Emit/UnmanagedTypeModifierTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/UnmanagedTypeModifierTests.cs index 465572c2dae79..3af25f2098275 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/UnmanagedTypeModifierTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/UnmanagedTypeModifierTests.cs @@ -860,7 +860,7 @@ public static void Print(D lambda) where T : unmanaged var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("D`1").TypeParameters.Single(); Assert.True(typeParameter.HasValueTypeConstraint); Assert.True(typeParameter.HasUnmanagedTypeConstraint); - Assert.True(typeParameter.HasConstructorConstraint); + Assert.False(typeParameter.HasConstructorConstraint); // .ctor is an artifact of emit, we will ignore it on importing. AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, typeParameter, module.ContainingAssembly.Name); }); @@ -887,7 +887,7 @@ public static void Main() var typeParameter = module.ContainingAssembly.GetTypeByMetadataName("Program").GetTypeMember("<>c__DisplayClass0_0").TypeParameters.Single(); Assert.True(typeParameter.HasValueTypeConstraint); Assert.True(typeParameter.HasUnmanagedTypeConstraint); - Assert.True(typeParameter.HasConstructorConstraint); + Assert.False(typeParameter.HasConstructorConstraint); // .ctor is an artifact of emit, we will ignore it on importing. AttributeTests_IsUnmanaged.AssertReferencedIsUnmanagedAttribute(Accessibility.Internal, typeParameter, module.ContainingAssembly.Name); }); From 711e252a9f7f834ef91551a809ed3c4a0fcfdcc2 Mon Sep 17 00:00:00 2001 From: vsadov Date: Tue, 13 Mar 2018 13:46:25 -0700 Subject: [PATCH 13/13] update error IDs after merge --- .../CSharp/Portable/Errors/ErrorCode.cs | 12 +-- .../Semantics/GenericConstraintsTests.cs | 74 +++++++++---------- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 96c6445d59aff..6508a6bb91878 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -1561,13 +1561,13 @@ internal enum ErrorCode ERR_RefLocalOrParamExpected = 8373, ERR_RefAssignNarrower = 8374, - ERR_NewBoundWithUnmanaged = 8373, - ERR_UnmanagedConstraintMustBeFirst = 8374, - ERR_UnmanagedConstraintNotSatisfied = 8375, - ERR_UnmanagedConstraintWithLocalFunctions = 8376, - ERR_ConWithUnmanagedCon = 8377, + ERR_NewBoundWithUnmanaged = 8375, + ERR_UnmanagedConstraintMustBeFirst = 8376, + ERR_UnmanagedConstraintNotSatisfied = 8377, + ERR_UnmanagedConstraintWithLocalFunctions = 8378, + ERR_ConWithUnmanagedCon = 8379, - ERR_UnmanagedBoundWithClass = 8378, + ERR_UnmanagedBoundWithClass = 8380, // Note: you will need to re-generate compiler code after adding warnings (build\scripts\generate-compiler-code.cmd) } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs index 2a065dae6060c..c01bd009eafeb 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs @@ -1573,13 +1573,13 @@ public void M() where U : unmanaged var f = new Test(); // unconstrained generic type } }").VerifyDiagnostics( - // (12,26): error CS8375: The type 'BadType' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test' + // (12,26): error CS8379: The type 'BadType' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test' // var b = new Test(); // managed struct Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "BadType").WithArguments("Test", "T", "BadType").WithLocation(12, 26), - // (13,26): error CS8375: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test' + // (13,26): error CS8379: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test' // var c = new Test(); // reference type Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "string").WithArguments("Test", "T", "string").WithLocation(13, 26), - // (16,26): error CS8375: The type 'W' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test' + // (16,26): error CS8379: The type 'W' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test' // var f = new Test(); // unconstrained generic type Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "W").WithArguments("Test", "T", "W").WithLocation(16, 26)); } @@ -1606,13 +1606,13 @@ public void M() where U : unmanaged var f = new Test().M(); // unconstrained generic type } }").VerifyDiagnostics( - // (13,28): error CS8375: The type 'BadType' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' + // (13,28): error CS8379: The type 'BadType' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' // var b = new Test().M(); // managed struct Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "M").WithArguments("Test.M()", "T", "BadType").WithLocation(13, 28), - // (14,28): error CS8375: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' + // (14,28): error CS8379: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' // var c = new Test().M(); // reference type Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "M").WithArguments("Test.M()", "T", "string").WithLocation(14, 28), - // (17,28): error CS8375: The type 'W' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' + // (17,28): error CS8379: The type 'W' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' // var f = new Test().M(); // unconstrained generic type Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "M").WithArguments("Test.M()", "T", "W").WithLocation(17, 28) ); @@ -1634,13 +1634,13 @@ public abstract class Test2 where U : unmanaged public abstract D e(); // generic type constrained to unmanaged public abstract D f(); // unconstrained generic type }").VerifyDiagnostics( - // (8,32): error CS8375: The type 'BadType' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'D' + // (8,32): error CS8379: The type 'BadType' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'D' // public abstract D b(); // managed struct Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "b").WithArguments("D", "T", "BadType").WithLocation(8, 32), - // (9,31): error CS8375: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'D' + // (9,31): error CS8379: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'D' // public abstract D c(); // reference type Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "c").WithArguments("D", "T", "string").WithLocation(9, 31), - // (12,26): error CS8375: The type 'W' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'D' + // (12,26): error CS8379: The type 'W' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'D' // public abstract D f(); // unconstrained generic type Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "f").WithArguments("D", "T", "W").WithLocation(12, 26)); } @@ -1658,7 +1658,7 @@ void local() where T : unmanaged { } local(); } }").VerifyDiagnostics( - // (6,20): error CS8376: Using unmanaged constraint on local functions type parameters is not supported. + // (6,20): error CS8380: Using unmanaged constraint on local functions type parameters is not supported. // void local() where T : unmanaged { } Diagnostic(ErrorCode.ERR_UnmanagedConstraintWithLocalFunctions, "T").WithLocation(6, 20)); } @@ -1669,7 +1669,7 @@ public void UnmanagedConstraint_Compilation_ReferenceType() var c = CreateCompilation("public class Test where T : class, unmanaged {}"); c.VerifyDiagnostics( - // (1,39): error CS8374: The 'unmanaged' constraint must come before any other constraints + // (1,39): error CS8380: The 'unmanaged' constraint must come before any other constraints // public class Test where T : class, unmanaged {} Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeFirst, "unmanaged").WithLocation(1, 39)); @@ -1687,7 +1687,7 @@ public void UnmanagedConstraint_Compilation_ValueType() var c = CreateCompilation("public class Test where T : struct, unmanaged {}"); c.VerifyDiagnostics( - // (1,40): error CS8374: The 'unmanaged' constraint must come before any other constraints + // (1,40): error CS8380: The 'unmanaged' constraint must come before any other constraints // public class Test where T : struct, unmanaged {} Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeFirst, "unmanaged").WithLocation(1, 40)); @@ -1703,7 +1703,7 @@ public void UnmanagedConstraint_Compilation_ValueType() public void UnmanagedConstraint_Compilation_Constructor() { CreateCompilation("public class Test where T : unmanaged, new() {}").VerifyDiagnostics( - // (1,43): error CS8373: The 'new()' constraint cannot be used with the 'unmanaged' constraint + // (1,43): error CS8379: The 'new()' constraint cannot be used with the 'unmanaged' constraint // public class Test where T : unmanaged, new() {} Diagnostic(ErrorCode.ERR_NewBoundWithUnmanaged, "new").WithLocation(1, 43)); } @@ -1712,7 +1712,7 @@ public void UnmanagedConstraint_Compilation_Constructor() public void UnmanagedConstraint_Compilation_AnotherType_Before() { CreateCompilation("public class Test where T : unmanaged, System.Exception { }").VerifyDiagnostics( - // (1,43): error CS8378: 'Exception': cannot specify both a constraint class and the 'unmanaged' constraint + // (1,43): error CS8380: 'Exception': cannot specify both a constraint class and the 'unmanaged' constraint // public class Test where T : unmanaged, System.Exception { } Diagnostic(ErrorCode.ERR_UnmanagedBoundWithClass, "System.Exception").WithArguments("System.Exception").WithLocation(1, 43) ); @@ -1724,7 +1724,7 @@ public void UnmanagedConstraint_Compilation_AnotherType_Before1() CreateCompilation("public class Test where T : unmanaged, System.Enum { }").VerifyDiagnostics(); CreateCompilation("public class Test where T : unmanaged, System.Delegate { }").VerifyDiagnostics( - // (1,43): error CS8378: 'Delegate': cannot specify both a constraint class and the 'unmanaged' constraint + // (1,43): error CS8380: 'Delegate': cannot specify both a constraint class and the 'unmanaged' constraint // public class Test where T : unmanaged, System.Delegate { } Diagnostic(ErrorCode.ERR_UnmanagedBoundWithClass, "System.Delegate").WithArguments("System.Delegate").WithLocation(1, 43) ); @@ -1734,7 +1734,7 @@ public void UnmanagedConstraint_Compilation_AnotherType_Before1() public void UnmanagedConstraint_Compilation_AnotherType_After() { CreateCompilation("public class Test where T : System.Exception, unmanaged { }").VerifyDiagnostics( - // (1,50): error CS8374: The 'unmanaged' constraint must come before any other constraints + // (1,50): error CS8380: The 'unmanaged' constraint must come before any other constraints // public class Test where T : System.Exception, unmanaged { } Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeFirst, "unmanaged").WithLocation(1, 50)); } @@ -1743,7 +1743,7 @@ public void UnmanagedConstraint_Compilation_AnotherType_After() public void UnmanagedConstraint_Compilation_AnotherParameter_After() { CreateCompilation("public class Test where T : U, unmanaged { }").VerifyDiagnostics( - // (1,38): error CS8374: The 'unmanaged' constraint must come before any other constraints + // (1,38): error CS8380: The 'unmanaged' constraint must come before any other constraints // public class Test where T : U, unmanaged { } Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeFirst, "unmanaged").WithLocation(1, 38)); } @@ -1823,13 +1823,13 @@ public void M() where U : unmanaged } }"; CreateCompilation(code, references: new[] { reference }).VerifyDiagnostics( - // (9,26): error CS8375: The type 'BadType' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test' + // (9,26): error CS8379: The type 'BadType' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test' // var b = new Test(); // managed struct Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "BadType").WithArguments("Test", "T", "BadType").WithLocation(9, 26), - // (10,26): error CS8375: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test' + // (10,26): error CS8379: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test' // var c = new Test(); // reference type Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "string").WithArguments("Test", "T", "string").WithLocation(10, 26), - // (13,26): error CS8375: The type 'W' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test' + // (13,26): error CS8379: The type 'W' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test' // var f = new Test(); // unconstrained generic type Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "W").WithArguments("Test", "T", "W").WithLocation(13, 26)); } @@ -1859,13 +1859,13 @@ public void M() where U : unmanaged } }"; CreateCompilation(code, references: new[] { reference }).VerifyDiagnostics( - // (9,28): error CS8375: The type 'BadType' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' + // (9,28): error CS8379: The type 'BadType' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' // var b = new Test().M(); // managed struct Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "M").WithArguments("Test.M()", "T", "BadType").WithLocation(9, 28), - // (10,28): error CS8375: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' + // (10,28): error CS8379: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' // var c = new Test().M(); // reference type Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "M").WithArguments("Test.M()", "T", "string").WithLocation(10, 28), - // (13,28): error CS8375: The type 'W' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' + // (13,28): error CS8379: The type 'W' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M()' // var f = new Test().M(); // unconstrained generic type Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "M").WithArguments("Test.M()", "T", "W").WithLocation(13, 28) ); @@ -1891,13 +1891,13 @@ public abstract class Test2 where U : unmanaged public abstract D f(); // unconstrained generic type }"; CreateCompilation(code, references: new[] { reference }).VerifyDiagnostics( - // (7,32): error CS8375: The type 'BadType' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'D' + // (7,32): error CS8379: The type 'BadType' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'D' // public abstract D b(); // managed struct Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "b").WithArguments("D", "T", "BadType").WithLocation(7, 32), - // (8,31): error CS8375: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'D' + // (8,31): error CS8379: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'D' // public abstract D c(); // reference type Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "c").WithArguments("D", "T", "string").WithLocation(8, 31), - // (11,26): error CS8375: The type 'W' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'D' + // (11,26): error CS8379: The type 'W' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'D' // public abstract D f(); // unconstrained generic type Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "f").WithArguments("D", "T", "W").WithLocation(11, 26)); } @@ -1997,10 +1997,10 @@ public void Test() this.M(); } }").VerifyDiagnostics( - // (17,14): error CS8375: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'B.M()' + // (17,14): error CS8379: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'B.M()' // this.M(); Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "M").WithArguments("B.M()", "T", "string").WithLocation(17, 14), - // (18,14): error CS8375: The type 'Test' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'B.M()' + // (18,14): error CS8379: The type 'Test' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'B.M()' // this.M(); Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "M").WithArguments("B.M()", "T", "Test").WithLocation(18, 14) ); @@ -2031,10 +2031,10 @@ public void Test() this.M(); } }", references: new[] { reference }).VerifyDiagnostics( - // (13,14): error CS8375: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'B.M()' + // (13,14): error CS8379: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'B.M()' // this.M(); Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "M").WithArguments("B.M()", "T", "string").WithLocation(13, 14), - // (14,14): error CS8375: The type 'Test' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'B.M()' + // (14,14): error CS8379: The type 'Test' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'B.M()' // this.M(); Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "M").WithArguments("B.M()", "T", "Test").WithLocation(14, 14) ); @@ -2075,16 +2075,16 @@ public void Test(G x) where G : struct } } ").VerifyDiagnostics( - // (7,14): error CS8375: The type 'T' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'I1' + // (7,14): error CS8379: The type 'T' cannot be a reference type, or contain reference type 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. // 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 CS8375: The type 'T' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'I1' + // (11,12): error CS8379: The type 'T' cannot be a reference type, or contain reference type 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 CS8375: The type 'ArraySegment' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'G' in the generic type or method 'I1.Test(G)' + // (12,11): error CS8379: The type 'ArraySegment' cannot be a reference type, or contain reference type 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) ); @@ -2237,7 +2237,7 @@ void N() M(""test""); } }").VerifyDiagnostics( - // (9,9): error CS8375: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M(T)' + // (9,9): error CS8379: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M(T)' // M("test"); Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "M").WithArguments("Test.M(T)", "T", "string").WithLocation(9, 9)); } @@ -2472,7 +2472,7 @@ static void N() where T : unmanaged { } }").VerifyDiagnostics( - // (24,9): error CS8375: The type 'TestData' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.N()' + // (24,9): error CS8379: The type 'TestData' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.N()' // N(); Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "N").WithArguments("Test.N()", "T", "TestData").WithLocation(24, 9)); } @@ -2526,7 +2526,7 @@ static void M(T arg) where T : unmanaged arg.Print(); } }").VerifyDiagnostics( - // (16,9): error CS8375: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M(T)' + // (16,9): error CS8379: The type 'string' cannot be a reference type, or contain reference type fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Test.M(T)' // M("test"); Diagnostic(ErrorCode.ERR_UnmanagedConstraintNotSatisfied, "M").WithArguments("Test.M(T)", "T", "string").WithLocation(16, 9), // (20,13): error CS1061: 'T' does not contain a definition for 'Print' and no extension method 'Print' accepting a first argument of type 'T' could be found (are you missing a using directive or an assembly reference?) @@ -2636,7 +2636,7 @@ void M() where T : U { } }").VerifyDiagnostics( - // (4,12): error CS8377: Type parameter 'U' has the 'unmanaged' constraint so 'U' cannot be used as a constraint for 'T' + // (4,12): error CS8379: Type parameter 'U' has the 'unmanaged' constraint so 'U' cannot be used as a constraint for 'T' // void M() where T : U Diagnostic(ErrorCode.ERR_ConWithUnmanagedCon, "T").WithArguments("T", "U").WithLocation(4, 12)); }