From 7ca0c7eb991aec6d2434f2b118f0df533922f20d Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Sat, 13 Jun 2020 12:32:46 -0700 Subject: [PATCH] Report better errors when multiple invalid constraints are combined Instead of reporting that a constraint must come first, if there are multiple constraints that must come first, we now report that these constraints cannot be combined. We also suppress these errors if a previous error about inherited constraints was reported. Fixes https://github.com/dotnet/roslyn/issues/45141. --- .../Portable/Binder/Binder_Constraints.cs | 32 +++- .../CSharp/Portable/CSharpResources.resx | 15 ++ .../CSharp/Portable/Errors/ErrorCode.cs | 1 + .../CSharp/Portable/Errors/MessageID.cs | 4 + .../Portable/xlf/CSharpResources.cs.xlf | 25 +++ .../Portable/xlf/CSharpResources.de.xlf | 25 +++ .../Portable/xlf/CSharpResources.es.xlf | 25 +++ .../Portable/xlf/CSharpResources.fr.xlf | 25 +++ .../Portable/xlf/CSharpResources.it.xlf | 25 +++ .../Portable/xlf/CSharpResources.ja.xlf | 25 +++ .../Portable/xlf/CSharpResources.ko.xlf | 25 +++ .../Portable/xlf/CSharpResources.pl.xlf | 25 +++ .../Portable/xlf/CSharpResources.pt-BR.xlf | 25 +++ .../Portable/xlf/CSharpResources.ru.xlf | 25 +++ .../Portable/xlf/CSharpResources.tr.xlf | 25 +++ .../Portable/xlf/CSharpResources.zh-Hans.xlf | 25 +++ .../Portable/xlf/CSharpResources.zh-Hant.xlf | 25 +++ .../Semantics/GenericConstraintsTests.cs | 149 +++++++++++++++++- .../Semantics/InheritanceBindingTests.cs | 26 +-- .../Semantics/NullableReferenceTypesTests.cs | 24 +-- 20 files changed, 543 insertions(+), 33 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs index 9a04811fc3044..df6006e9784c5 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs @@ -126,6 +126,7 @@ internal ImmutableArray BindTypeParameterConstrai Debug.Assert(!InExecutableBinder); // Cannot eagerly report diagnostics handled by LazyMissingNonNullTypesContextDiagnosticInfo bool hasTypeLikeConstraint = false; bool reportedOverrideWithConstraints = false; + MessageID? firstTypeConstraintString = null; for (int i = 0, n = constraintsSyntax.Count; i < n; i++) { @@ -137,7 +138,10 @@ internal ImmutableArray BindTypeParameterConstrai if (i != 0) { - diagnostics.Add(ErrorCode.ERR_RefValBoundMustBeFirst, syntax.GetFirstToken().GetLocation()); + if (!reportedOverrideWithConstraints) + { + reportNotFirstOrCannotCombine(diagnostics, syntax.GetFirstToken().GetLocation(), ErrorCode.ERR_RefValBoundMustBeFirst, MessageID.IDS_Class, firstTypeConstraintString); + } if (isForOverride && (constraints & (TypeParameterConstraintKind.ValueType | TypeParameterConstraintKind.ReferenceType)) != 0) { @@ -145,6 +149,7 @@ internal ImmutableArray BindTypeParameterConstrai } } + firstTypeConstraintString ??= MessageID.IDS_Class; var constraintSyntax = (ClassOrStructConstraintSyntax)syntax; SyntaxToken questionToken = constraintSyntax.QuestionToken; if (questionToken.IsKind(SyntaxKind.QuestionToken)) @@ -175,7 +180,10 @@ internal ImmutableArray BindTypeParameterConstrai if (i != 0) { - diagnostics.Add(ErrorCode.ERR_RefValBoundMustBeFirst, syntax.GetFirstToken().GetLocation()); + if (!reportedOverrideWithConstraints) + { + reportNotFirstOrCannotCombine(diagnostics, syntax.GetFirstToken().GetLocation(), ErrorCode.ERR_RefValBoundMustBeFirst, MessageID.IDS_Struct, firstTypeConstraintString); + } if (isForOverride && (constraints & (TypeParameterConstraintKind.ValueType | TypeParameterConstraintKind.ReferenceType)) != 0) { @@ -183,6 +191,7 @@ internal ImmutableArray BindTypeParameterConstrai } } + firstTypeConstraintString ??= MessageID.IDS_Struct; constraints |= TypeParameterConstraintKind.ValueType; continue; case SyntaxKind.ConstructorConstraint: @@ -233,10 +242,12 @@ internal ImmutableArray BindTypeParameterConstrai case ConstraintContextualKeyword.Unmanaged: if (i != 0) { - diagnostics.Add(ErrorCode.ERR_UnmanagedConstraintMustBeFirst, typeSyntax.GetLocation()); + reportNotFirstOrCannotCombine(diagnostics, typeSyntax.GetLocation(), ErrorCode.ERR_UnmanagedConstraintMustBeFirst, MessageID.IDS_Unmanaged, firstTypeConstraintString); continue; } + firstTypeConstraintString ??= MessageID.IDS_Unmanaged; + // This should produce diagnostics if the types are missing GetWellKnownType(WellKnownType.System_Runtime_InteropServices_UnmanagedType, diagnostics, typeSyntax); GetSpecialType(SpecialType.System_ValueType, diagnostics, typeSyntax); @@ -247,9 +258,10 @@ internal ImmutableArray BindTypeParameterConstrai case ConstraintContextualKeyword.NotNull: if (i != 0) { - diagnostics.Add(ErrorCode.ERR_NotNullConstraintMustBeFirst, typeSyntax.GetLocation()); + reportNotFirstOrCannotCombine(diagnostics, typeSyntax.GetLocation(), ErrorCode.ERR_NotNullConstraintMustBeFirst, MessageID.IDS_Notnull, firstTypeConstraintString); } + firstTypeConstraintString ??= MessageID.IDS_Notnull; constraints |= TypeParameterConstraintKind.NotNull; continue; @@ -286,6 +298,18 @@ static void reportOverrideWithConstraints(ref bool reportedOverrideWithConstrain reportedOverrideWithConstraints = true; } } + + static void reportNotFirstOrCannotCombine(DiagnosticBag diagnostics, Location constraintLocation, ErrorCode notFirstDiagnostic, MessageID currentConstraintString, MessageID? firstConstraintString) + { + if (firstConstraintString is MessageID firstConstraint) + { + diagnostics.Add(ErrorCode.ERR_CannotCombineTypeConstraints, constraintLocation, currentConstraintString.Localize(), firstConstraint.Localize()); + } + else + { + diagnostics.Add(notFirstDiagnostic, constraintLocation); + } + } } internal ImmutableArray GetDefaultTypeParameterConstraintClauses(TypeParameterListSyntax typeParameterList) diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 3dc91256b2b83..b7c56ca1a37d0 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -6262,4 +6262,19 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ A copy constructor in a record must call a copy constructor of the base, or a parameterless object constructor if the record inherits from object. + + class + + + struct + + + unmanaged + + + notnull + + + The '{0}' constraint cannot be combined with the '{1}' constraint + diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 496fa9a5b0222..4f9d29e732d6f 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -1835,6 +1835,7 @@ internal enum ErrorCode ERR_BadRecordMemberForPositionalParameter = 8866, ERR_NoCopyConstructorInBaseType = 8867, ERR_CopyConstructorMustInvokeBaseCopyConstructor = 8868, + ERR_CannotCombineTypeConstraints = 8869, #endregion diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs index fd3b09596ef28..569060b6d242b 100644 --- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs +++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs @@ -206,6 +206,10 @@ internal enum MessageID IDS_FeatureInitOnlySetters = MessageBase + 12781, IDS_FeatureRecords = MessageBase + 12782, IDS_FeatureNullPointerConstantPattern = MessageBase + 12783, + IDS_Class = MessageBase + 12784, + IDS_Struct = MessageBase + 12785, + IDS_Unmanaged = MessageBase + 12786, + IDS_Notnull = MessageBase + 12787, } // Message IDs may refer to strings that need to be localized. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index cb8ae00e53d7a..0134a34ad2bd1 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -152,6 +152,11 @@ Chyba syntaxe příkazového řádku: {0} není platná hodnota možnosti {1}. Hodnota musí mít tvar {2}. + + The '{0}' constraint cannot be combined with the '{1}' constraint + The '{0}' constraint cannot be combined with the '{1}' constraint + + Cannot convert &method group '{0}' to delegate type '{0}'. Cannot convert &method group '{0}' to delegate type '{0}'. @@ -1114,6 +1119,11 @@ Visual C# Compiler Options + + class + class + + default interface implementation implementace výchozího rozhraní @@ -1364,11 +1374,21 @@ <null> + + notnull + notnull + + constraints for override and explicit interface implementation methods omezení pro metody přepsání a explicitní implementace rozhraní + + struct + struct + + <throw expression> <výraz throw> @@ -1389,6 +1409,11 @@ top-level statements + + unmanaged + unmanaged + + <!-- Badly formed XML comment ignored for member "{0}" --> <!-- Badly formed XML comment ignored for member "{0}" --> diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 1eec6bb07f753..008a4101e9d83 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -152,6 +152,11 @@ Fehler in der Befehlszeilensyntax: "{0}" ist kein gültiger Wert für die Option "{1}". Der Wert muss im Format "{2}" vorliegen. + + The '{0}' constraint cannot be combined with the '{1}' constraint + The '{0}' constraint cannot be combined with the '{1}' constraint + + Cannot convert &method group '{0}' to delegate type '{0}'. Cannot convert &method group '{0}' to delegate type '{0}'. @@ -1114,6 +1119,11 @@ Visual C# Compiler Options + + class + class + + default interface implementation Standardschnittstellenimplementierung @@ -1364,11 +1374,21 @@ <NULL> + + notnull + notnull + + constraints for override and explicit interface implementation methods Einschränkungen für Außerkraftsetzung und explizite Schnittstellenimplementierungsmethoden + + struct + struct + + <throw expression> throw-Ausdruck @@ -1389,6 +1409,11 @@ top-level statements + + unmanaged + unmanaged + + <!-- Badly formed XML comment ignored for member "{0}" --> <!-- Badly formed XML comment ignored for member "{0}" --> diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 87013d35769f6..6b96c7f8348ac 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -152,6 +152,11 @@ Error de sintaxis de la línea de comandos: "{0}" no es un valor válido para la opción "{1}". El valor debe tener el formato "{2}". + + The '{0}' constraint cannot be combined with the '{1}' constraint + The '{0}' constraint cannot be combined with the '{1}' constraint + + Cannot convert &method group '{0}' to delegate type '{0}'. Cannot convert &method group '{0}' to delegate type '{0}'. @@ -1114,6 +1119,11 @@ Visual C# Compiler Options + + class + class + + default interface implementation implementación de interfaz predeterminada @@ -1364,11 +1374,21 @@ <NULL> + + notnull + notnull + + constraints for override and explicit interface implementation methods restricciones para métodos de implementación de interfaz explícita e invalidación + + struct + struct + + <throw expression> <expresión throw> @@ -1389,6 +1409,11 @@ top-level statements + + unmanaged + unmanaged + + <!-- Badly formed XML comment ignored for member "{0}" --> <!-- Badly formed XML comment ignored for member "{0}" --> diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 267da2bf78f42..05e3c8d60662b 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -152,6 +152,11 @@ Erreur de syntaxe de ligne de commande : '{0}' est une valeur non valide pour l'option '{1}'. La valeur doit se présenter sous la forme '{2}'. + + The '{0}' constraint cannot be combined with the '{1}' constraint + The '{0}' constraint cannot be combined with the '{1}' constraint + + Cannot convert &method group '{0}' to delegate type '{0}'. Cannot convert &method group '{0}' to delegate type '{0}'. @@ -1114,6 +1119,11 @@ Visual C# Compiler Options + + class + class + + default interface implementation implémentation d'interface par défaut @@ -1364,11 +1374,21 @@ <Null> + + notnull + notnull + + constraints for override and explicit interface implementation methods contraintes des méthodes d'implémentation d'interface par remplacement et explicites + + struct + struct + + <throw expression> <expression throw> @@ -1389,6 +1409,11 @@ top-level statements + + unmanaged + unmanaged + + <!-- Badly formed XML comment ignored for member "{0}" --> <!-- Badly formed XML comment ignored for member "{0}" --> diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 5c66bfbb6fad6..fcd7ef4a114f5 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -152,6 +152,11 @@ Errore di sintassi della riga di comando: '{0}' non è un valore valido per l'opzione '{1}'. Il valore deve essere espresso nel formato '{2}'. + + The '{0}' constraint cannot be combined with the '{1}' constraint + The '{0}' constraint cannot be combined with the '{1}' constraint + + Cannot convert &method group '{0}' to delegate type '{0}'. Cannot convert &method group '{0}' to delegate type '{0}'. @@ -1114,6 +1119,11 @@ Visual C# Compiler Options + + class + class + + default interface implementation implementazione di interfaccia predefinita @@ -1364,11 +1374,21 @@ <Null> + + notnull + notnull + + constraints for override and explicit interface implementation methods vincoli per i metodi di override e di implementazione esplicita dell'interfaccia + + struct + struct + + <throw expression> <espressione throw> @@ -1389,6 +1409,11 @@ top-level statements + + unmanaged + unmanaged + + <!-- Badly formed XML comment ignored for member "{0}" --> <!-- Badly formed XML comment ignored for member "{0}" --> diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 1ce4645e28c3f..9ccb15eb4c1af 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -152,6 +152,11 @@ コマンドライン構文エラー: '{0}' は、'{1}' オプションの有効な値ではありません。値は '{2}' の形式にする必要があります。 + + The '{0}' constraint cannot be combined with the '{1}' constraint + The '{0}' constraint cannot be combined with the '{1}' constraint + + Cannot convert &method group '{0}' to delegate type '{0}'. Cannot convert &method group '{0}' to delegate type '{0}'. @@ -1114,6 +1119,11 @@ Visual C# Compiler Options + + class + class + + default interface implementation 既定のインターフェイスの実装 @@ -1364,11 +1374,21 @@ <null> + + notnull + notnull + + constraints for override and explicit interface implementation methods オーバーライドおよび明示的なインターフェイスの実装メソッドの制約 + + struct + struct + + <throw expression> <スロー式> @@ -1389,6 +1409,11 @@ top-level statements + + unmanaged + unmanaged + + <!-- Badly formed XML comment ignored for member "{0}" --> <!-- Badly formed XML comment ignored for member "{0}" --> diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index e1288e3b47b37..f25e5829f71a4 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -152,6 +152,11 @@ 명령줄 구문 오류: '{0}'은(는) '{1}' 옵션에 유효한 값이 아닙니다. 값은 '{2}' 형식이어야 합니다. + + The '{0}' constraint cannot be combined with the '{1}' constraint + The '{0}' constraint cannot be combined with the '{1}' constraint + + Cannot convert &method group '{0}' to delegate type '{0}'. Cannot convert &method group '{0}' to delegate type '{0}'. @@ -1114,6 +1119,11 @@ Visual C# Compiler Options + + class + class + + default interface implementation 기본 인터페이스 구현 @@ -1364,11 +1374,21 @@ <null> + + notnull + notnull + + constraints for override and explicit interface implementation methods 재정의 및 명시적 인터페이스 구현 메서드에 대한 제약 조건 + + struct + struct + + <throw expression> <Throw 식> @@ -1389,6 +1409,11 @@ top-level statements + + unmanaged + unmanaged + + <!-- Badly formed XML comment ignored for member "{0}" --> <!-- Badly formed XML comment ignored for member "{0}" --> diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 3b4a2d428096b..4b8607c8280a1 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -152,6 +152,11 @@ Błąd składni wiersza polecenia: „{0}” nie jest prawidłową wartością dla opcji „{1}”. Wartość musi mieć postać „{2}”. + + The '{0}' constraint cannot be combined with the '{1}' constraint + The '{0}' constraint cannot be combined with the '{1}' constraint + + Cannot convert &method group '{0}' to delegate type '{0}'. Cannot convert &method group '{0}' to delegate type '{0}'. @@ -1114,6 +1119,11 @@ Visual C# Compiler Options + + class + class + + default interface implementation domyślna implementacja interfejsu @@ -1364,11 +1374,21 @@ <null> + + notnull + notnull + + constraints for override and explicit interface implementation methods ograniczenia dla przesłonięć i jawnych metod implementacji interfejsu + + struct + struct + + <throw expression> <wyrażenie throw> @@ -1389,6 +1409,11 @@ top-level statements + + unmanaged + unmanaged + + <!-- Badly formed XML comment ignored for member "{0}" --> <!-- Badly formed XML comment ignored for member "{0}" --> diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index c08aea3759945..f2b0465eba5ae 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -152,6 +152,11 @@ Erro de sintaxe de linha de comando: '{0}' não é um valor válido para a opção '{1}'. O valor precisa estar no formato '{2}'. + + The '{0}' constraint cannot be combined with the '{1}' constraint + The '{0}' constraint cannot be combined with the '{1}' constraint + + Cannot convert &method group '{0}' to delegate type '{0}'. Cannot convert &method group '{0}' to delegate type '{0}'. @@ -1112,6 +1117,11 @@ Visual C# Compiler Options + + class + class + + default interface implementation implementação de interface padrão @@ -1362,11 +1372,21 @@ <nulo> + + notnull + notnull + + constraints for override and explicit interface implementation methods restrições para métodos de substituição e de implementação explícita da interface + + struct + struct + + <throw expression> <expressão throw> @@ -1387,6 +1407,11 @@ top-level statements + + unmanaged + unmanaged + + <!-- Badly formed XML comment ignored for member "{0}" --> <!-- Badly formed XML comment ignored for member "{0}" --> diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index b71df5fde3119..700c50546cfc4 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -152,6 +152,11 @@ Ошибка в синтаксисе командной строки: "{0}" не является допустимым значением для параметра "{1}". Значение должно иметь форму "{2}". + + The '{0}' constraint cannot be combined with the '{1}' constraint + The '{0}' constraint cannot be combined with the '{1}' constraint + + Cannot convert &method group '{0}' to delegate type '{0}'. Cannot convert &method group '{0}' to delegate type '{0}'. @@ -1114,6 +1119,11 @@ Visual C# Compiler Options + + class + class + + default interface implementation реализация интерфейса по умолчанию @@ -1364,11 +1374,21 @@ <NULL> + + notnull + notnull + + constraints for override and explicit interface implementation methods ограничения для методов переопределения и явной реализации интерфейса + + struct + struct + + <throw expression> <выражение throw> @@ -1389,6 +1409,11 @@ top-level statements + + unmanaged + unmanaged + + <!-- Badly formed XML comment ignored for member "{0}" --> <!-- Badly formed XML comment ignored for member "{0}" --> diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 71286ed2418ac..66531fec5a14e 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -152,6 +152,11 @@ Komut satırı söz dizimi hatası: '{0}', '{1}' seçeneği için geçerli bir değer değil. Değer '{2}' biçiminde olmalıdır. + + The '{0}' constraint cannot be combined with the '{1}' constraint + The '{0}' constraint cannot be combined with the '{1}' constraint + + Cannot convert &method group '{0}' to delegate type '{0}'. Cannot convert &method group '{0}' to delegate type '{0}'. @@ -1114,6 +1119,11 @@ Visual C# Compiler Options + + class + class + + default interface implementation varsayılan arabirim uygulaması @@ -1364,11 +1374,21 @@ <null> + + notnull + notnull + + constraints for override and explicit interface implementation methods geçersiz kılma ve açık arabirim uygulama yöntemleri için kısıtlamalar + + struct + struct + + <throw expression> <throw ifadesi> @@ -1389,6 +1409,11 @@ top-level statements + + unmanaged + unmanaged + + <!-- Badly formed XML comment ignored for member "{0}" --> <!-- Badly formed XML comment ignored for member "{0}" --> diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index b9cdde0c4dc84..856165bd5c7a2 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -152,6 +152,11 @@ 命令行语法错误:“{0}”不是“{1}”选项的有效值。值的格式必须为 "{2}"。 + + The '{0}' constraint cannot be combined with the '{1}' constraint + The '{0}' constraint cannot be combined with the '{1}' constraint + + Cannot convert &method group '{0}' to delegate type '{0}'. Cannot convert &method group '{0}' to delegate type '{0}'. @@ -1114,6 +1119,11 @@ Visual C# Compiler Options + + class + class + + default interface implementation 默认接口实现 @@ -1364,11 +1374,21 @@ <null> + + notnull + notnull + + constraints for override and explicit interface implementation methods 重写和显式接口实现方法的约束 + + struct + struct + + <throw expression> <throw 表达式> @@ -1389,6 +1409,11 @@ top-level statements + + unmanaged + unmanaged + + <!-- Badly formed XML comment ignored for member "{0}" --> <!-- Badly formed XML comment ignored for member "{0}" --> diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 0293eaf68bc9f..4e1fcbd1f0dbd 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -152,6 +152,11 @@ 命令列語法錯誤: '{0}' 對 '{1}' 選項而言不是有效的值。此值的格式必須是 '{2}'。 + + The '{0}' constraint cannot be combined with the '{1}' constraint + The '{0}' constraint cannot be combined with the '{1}' constraint + + Cannot convert &method group '{0}' to delegate type '{0}'. Cannot convert &method group '{0}' to delegate type '{0}'. @@ -1114,6 +1119,11 @@ Visual C# Compiler Options + + class + class + + default interface implementation 預設介面實作 @@ -1364,11 +1374,21 @@ <null> + + notnull + notnull + + constraints for override and explicit interface implementation methods 適用於覆寫和明確介面實作方法的條件約束 + + struct + struct + + <throw expression> <throw 運算式> @@ -1389,6 +1409,11 @@ top-level statements + + unmanaged + unmanaged + + <!-- Badly formed XML comment ignored for member "{0}" --> <!-- Badly formed XML comment ignored for member "{0}" --> diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs index 43d1997792802..b79bb9e82de76 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/GenericConstraintsTests.cs @@ -1827,9 +1827,9 @@ public void UnmanagedConstraint_Compilation_ReferenceType() var c = CreateCompilation("public class Test where T : class, unmanaged {}"); c.VerifyDiagnostics( - // (1,39): error CS8380: The 'unmanaged' constraint must come before any other constraints + // (1,39): error CS8869: The 'unmanaged' constraint cannot be combined with the 'class' constraint // public class Test where T : class, unmanaged {} - Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeFirst, "unmanaged").WithLocation(1, 39)); + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "unmanaged").WithArguments("unmanaged", "class").WithLocation(1, 39)); var typeParameter = c.GlobalNamespace.GetTypeMember("Test").TypeParameters.Single(); Assert.False(typeParameter.HasUnmanagedTypeConstraint); @@ -1845,9 +1845,9 @@ public void UnmanagedConstraint_Compilation_ValueType() var c = CreateCompilation("public class Test where T : struct, unmanaged {}"); c.VerifyDiagnostics( - // (1,40): error CS8380: The 'unmanaged' constraint must come before any other constraints + // (1,40): error CS8869: The 'unmanaged' constraint cannot be combined with the 'struct' constraint // public class Test where T : struct, unmanaged {} - Diagnostic(ErrorCode.ERR_UnmanagedConstraintMustBeFirst, "unmanaged").WithLocation(1, 40)); + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "unmanaged").WithArguments("unmanaged", "struct").WithLocation(1, 40)); var typeParameter = c.GlobalNamespace.GetTypeMember("Test").TypeParameters.Single(); Assert.False(typeParameter.HasUnmanagedTypeConstraint); @@ -4152,5 +4152,146 @@ public static unsafe void Main() Diagnostic(ErrorCode.ERR_FixedNotNeeded, "&ms.field").WithLocation(12, 27) ); } + + [Fact, WorkItem(45141, "https://github.com/dotnet/roslyn/issues/45141")] + public void CannotCombineDiagnostics() + { + var comp = CreateCompilation(@" +class C1 where T1 : class, struct, unmanaged, notnull +{ + void M1() where T2 : class, struct, unmanaged, notnull {} +} +class C2 where T1 : struct, class, unmanaged, notnull +{ + void M2() where T2 : struct, class, unmanaged, notnull {} +} +class C3 where T1 : unmanaged, struct, class, notnull +{ + void M3() where T2 : unmanaged, struct, class, notnull {} +} +class C4 where T1 : notnull, struct, unmanaged, class +{ + void M4() where T2 : notnull, struct, unmanaged, class {} +} +"); + + comp.VerifyDiagnostics( + // (2,32): error CS8869: The 'struct' constraint cannot be combined with the 'class' constraint + // class C1 where T1 : class, struct, unmanaged, notnull + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "struct").WithArguments("struct", "class").WithLocation(2, 32), + // (2,40): error CS8869: The 'unmanaged' constraint cannot be combined with the 'class' constraint + // class C1 where T1 : class, struct, unmanaged, notnull + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "unmanaged").WithArguments("unmanaged", "class").WithLocation(2, 40), + // (2,51): error CS8869: The 'notnull' constraint cannot be combined with the 'class' constraint + // class C1 where T1 : class, struct, unmanaged, notnull + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "notnull").WithArguments("notnull", "class").WithLocation(2, 51), + // (4,37): error CS8869: The 'struct' constraint cannot be combined with the 'class' constraint + // void M1() where T2 : class, struct, unmanaged, notnull {} + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "struct").WithArguments("struct", "class").WithLocation(4, 37), + // (4,45): error CS8869: The 'unmanaged' constraint cannot be combined with the 'class' constraint + // void M1() where T2 : class, struct, unmanaged, notnull {} + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "unmanaged").WithArguments("unmanaged", "class").WithLocation(4, 45), + // (4,56): error CS8869: The 'notnull' constraint cannot be combined with the 'class' constraint + // void M1() where T2 : class, struct, unmanaged, notnull {} + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "notnull").WithArguments("notnull", "class").WithLocation(4, 56), + // (6,33): error CS8869: The 'class' constraint cannot be combined with the 'struct' constraint + // class C2 where T1 : struct, class, unmanaged, notnull + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "class").WithArguments("class", "struct").WithLocation(6, 33), + // (6,40): error CS8869: The 'unmanaged' constraint cannot be combined with the 'struct' constraint + // class C2 where T1 : struct, class, unmanaged, notnull + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "unmanaged").WithArguments("unmanaged", "struct").WithLocation(6, 40), + // (6,51): error CS8869: The 'notnull' constraint cannot be combined with the 'struct' constraint + // class C2 where T1 : struct, class, unmanaged, notnull + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "notnull").WithArguments("notnull", "struct").WithLocation(6, 51), + // (8,38): error CS8869: The 'class' constraint cannot be combined with the 'struct' constraint + // void M2() where T2 : struct, class, unmanaged, notnull {} + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "class").WithArguments("class", "struct").WithLocation(8, 38), + // (8,45): error CS8869: The 'unmanaged' constraint cannot be combined with the 'struct' constraint + // void M2() where T2 : struct, class, unmanaged, notnull {} + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "unmanaged").WithArguments("unmanaged", "struct").WithLocation(8, 45), + // (8,56): error CS8869: The 'notnull' constraint cannot be combined with the 'struct' constraint + // void M2() where T2 : struct, class, unmanaged, notnull {} + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "notnull").WithArguments("notnull", "struct").WithLocation(8, 56), + // (10,36): error CS8869: The 'struct' constraint cannot be combined with the 'unmanaged' constraint + // class C3 where T1 : unmanaged, struct, class, notnull + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "struct").WithArguments("struct", "unmanaged").WithLocation(10, 36), + // (10,44): error CS8869: The 'class' constraint cannot be combined with the 'unmanaged' constraint + // class C3 where T1 : unmanaged, struct, class, notnull + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "class").WithArguments("class", "unmanaged").WithLocation(10, 44), + // (10,51): error CS8869: The 'notnull' constraint cannot be combined with the 'unmanaged' constraint + // class C3 where T1 : unmanaged, struct, class, notnull + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "notnull").WithArguments("notnull", "unmanaged").WithLocation(10, 51), + // (12,41): error CS8869: The 'struct' constraint cannot be combined with the 'unmanaged' constraint + // void M3() where T2 : unmanaged, struct, class, notnull {} + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "struct").WithArguments("struct", "unmanaged").WithLocation(12, 41), + // (12,49): error CS8869: The 'class' constraint cannot be combined with the 'unmanaged' constraint + // void M3() where T2 : unmanaged, struct, class, notnull {} + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "class").WithArguments("class", "unmanaged").WithLocation(12, 49), + // (12,56): error CS8869: The 'notnull' constraint cannot be combined with the 'unmanaged' constraint + // void M3() where T2 : unmanaged, struct, class, notnull {} + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "notnull").WithArguments("notnull", "unmanaged").WithLocation(12, 56), + // (14,34): error CS8869: The 'struct' constraint cannot be combined with the 'notnull' constraint + // class C4 where T1 : notnull, struct, unmanaged, class + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "struct").WithArguments("struct", "notnull").WithLocation(14, 34), + // (14,42): error CS8869: The 'unmanaged' constraint cannot be combined with the 'notnull' constraint + // class C4 where T1 : notnull, struct, unmanaged, class + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "unmanaged").WithArguments("unmanaged", "notnull").WithLocation(14, 42), + // (14,53): error CS8869: The 'class' constraint cannot be combined with the 'notnull' constraint + // class C4 where T1 : notnull, struct, unmanaged, class + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "class").WithArguments("class", "notnull").WithLocation(14, 53), + // (16,39): error CS8869: The 'struct' constraint cannot be combined with the 'notnull' constraint + // void M4() where T2 : notnull, struct, unmanaged, class {} + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "struct").WithArguments("struct", "notnull").WithLocation(16, 39), + // (16,47): error CS8869: The 'unmanaged' constraint cannot be combined with the 'notnull' constraint + // void M4() where T2 : notnull, struct, unmanaged, class {} + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "unmanaged").WithArguments("unmanaged", "notnull").WithLocation(16, 47), + // (16,58): error CS8869: The 'class' constraint cannot be combined with the 'notnull' constraint + // void M4() where T2 : notnull, struct, unmanaged, class {} + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "class").WithArguments("class", "notnull").WithLocation(16, 58) + ); + } + + [Fact, WorkItem(45141, "https://github.com/dotnet/roslyn/issues/45141")] + public void CannotCombineDiagnostics_InheritedClassStruct() + { + var comp = CreateCompilation(@" +class C +{ + public virtual void M() where T1 : class {} +} +class D : C +{ + public override void M() where T1 : C, class, struct {} +} +class E +{ + public virtual void M() where T2 : struct {} +} +class F : E +{ + public override void M() where T2 : E, struct, class {} +} +class G +{ + public virtual void M() where T3 : unmanaged {} +} +class H : G +{ + public override void M() where T3 : G, unmanaged, struct {} +} +"); + + comp.VerifyDiagnostics( + // (8,45): error CS0460: Constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly, except for either a 'class', or a 'struct' constraint. + // public override void M() where T1 : C, class, struct {} + Diagnostic(ErrorCode.ERR_OverrideWithConstraints, "C").WithLocation(8, 45), + // (16,45): error CS0460: Constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly, except for either a 'class', or a 'struct' constraint. + // public override void M() where T2 : E, struct, class {} + Diagnostic(ErrorCode.ERR_OverrideWithConstraints, "E").WithLocation(16, 45), + // (24,45): error CS0460: Constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly, except for either a 'class', or a 'struct' constraint. + // public override void M() where T3 : G, unmanaged, struct {} + Diagnostic(ErrorCode.ERR_OverrideWithConstraints, "G").WithLocation(24, 45) + ); + } } } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/InheritanceBindingTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/InheritanceBindingTests.cs index 1ee00a9b84b2b..a12709cdb25b1 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/InheritanceBindingTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/InheritanceBindingTests.cs @@ -9020,11 +9020,11 @@ public override void Goo(T value) where T : struct, class { } "; var comp = CreateCompilation(source).VerifyDiagnostics( // (8,26): error CS0115: 'Derived.Goo(T)': no suitable method found to override - // public override void Goo(T value) where T : class, struct { } + // public override void Goo(T value) where T : struct, class { } Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Goo").WithArguments("Derived.Goo(T)").WithLocation(8, 26), - // (8,60): error CS0449: The 'class' or 'struct' constraint must come before any other constraints + // (8,60): error CS8869: The 'class' constraint cannot be combined with the 'struct' constraint // public override void Goo(T value) where T : struct, class { } - Diagnostic(ErrorCode.ERR_RefValBoundMustBeFirst, "class").WithLocation(8, 60)); + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "class").WithArguments("class", "struct").WithLocation(8, 60)); } [Fact] @@ -9044,9 +9044,9 @@ public override void Goo(T value) where T : class, struct { } // (8,26): error CS0115: 'Derived.Goo(T)': no suitable method found to override // public override void Goo(T value) where T : class, struct { } Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Goo").WithArguments("Derived.Goo(T)").WithLocation(8, 26), - // (8,59): error CS0449: The 'class' or 'struct' constraint must come before any other constraints + // (8,59): error CS8869: The 'struct' constraint cannot be combined with the 'class' constraint // public override void Goo(T value) where T : class, struct { } - Diagnostic(ErrorCode.ERR_RefValBoundMustBeFirst, "struct").WithLocation(8, 59)); + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "struct").WithArguments("struct", "class").WithLocation(8, 59)); } [Fact] @@ -9064,9 +9064,9 @@ public override void Goo(T value) where T : struct, class { } } "; var comp = CreateCompilation(source).VerifyDiagnostics( - // (9,60): error CS0449: The 'class' or 'struct' constraint must come before any other constraints + // (9,60): error CS8869: The 'class' constraint cannot be combined with the 'struct' constraint // public override void Goo(T value) where T : struct, class { } - Diagnostic(ErrorCode.ERR_RefValBoundMustBeFirst, "class").WithLocation(9, 60)); + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "class").WithArguments("class", "struct").WithLocation(9, 60)); } [Fact] @@ -9086,9 +9086,9 @@ void I.Goo(T value) where T : struct, class { } // (8,12): error CS0539: 'C.Goo(T)' in explicit interface declaration is not found among members of the interface that can be implemented // void I.Goo(T value) where T : struct, class { } Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Goo").WithArguments("C.Goo(T)").WithLocation(8, 12), - // (8,46): error CS0449: The 'class' or 'struct' constraint must come before any other constraints + // (8,46): error CS8869: The 'class' constraint cannot be combined with the 'struct' constraint // void I.Goo(T value) where T : struct, class { } - Diagnostic(ErrorCode.ERR_RefValBoundMustBeFirst, "class").WithLocation(8, 46) + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "class").WithArguments("class", "struct").WithLocation(8, 46) ); } @@ -9109,9 +9109,9 @@ void I.Goo(T value) where T : class, struct { } // (8,12): error CS0539: 'C.Goo(T)' in explicit interface declaration is not found among members of the interface that can be implemented // void I.Goo(T value) where T : class, struct { } Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Goo").WithArguments("C.Goo(T)").WithLocation(8, 12), - // (8,45): error CS0449: The 'class' or 'struct' constraint must come before any other constraints + // (8,45): error CS8869: The 'struct' constraint cannot be combined with the 'class' constraint // void I.Goo(T value) where T : class, struct { } - Diagnostic(ErrorCode.ERR_RefValBoundMustBeFirst, "struct").WithLocation(8, 45)); + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "struct").WithArguments("struct", "class").WithLocation(8, 45)); } [Fact] @@ -9129,9 +9129,9 @@ void I.Goo(T value) where T : struct, class { } } "; var comp = CreateCompilation(source).VerifyDiagnostics( - // (9,46): error CS0449: The 'class' or 'struct' constraint must come before any other constraints + // (9,46): error CS8869: The 'class' constraint cannot be combined with the 'struct' constraint // void I.Goo(T value) where T : struct, class { } - Diagnostic(ErrorCode.ERR_RefValBoundMustBeFirst, "class").WithLocation(9, 46)); + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "class").WithArguments("class", "struct").WithLocation(9, 46)); } [Fact] diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs index 8215db7fc46e5..38f46faa519b1 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs @@ -81658,12 +81658,12 @@ public static void F2(T2? t2) where T2 : notnull, struct }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (8,59): error CS0449: The 'class' or 'struct' constraint must come before any other constraints + // (8,59): error CS8869: The 'struct' constraint cannot be combined with the 'notnull' constraint // public static void F2(T2? t2) where T2 : notnull, struct - Diagnostic(ErrorCode.ERR_RefValBoundMustBeFirst, "struct").WithLocation(8, 59), - // (4,58): error CS8713: The 'notnull' constraint must come before any other constraints + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "struct").WithArguments("struct", "notnull").WithLocation(8, 59), + // (4,58): error CS8869: The 'notnull' constraint cannot be combined with the 'struct' constraint // public static void F1(T1? t1) where T1 : struct, notnull - Diagnostic(ErrorCode.ERR_NotNullConstraintMustBeFirst, "notnull").WithLocation(4, 58) + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "notnull").WithArguments("notnull", "struct").WithLocation(4, 58) ); var m = comp.SourceModule; @@ -81702,12 +81702,12 @@ public static void F2(T2? t2) where T2 : notnull, class }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (4,57): error CS8713: The 'notnull' constraint must come before any other constraints + // (4,57): error CS8869: The 'notnull' constraint cannot be combined with the 'class' constraint // public static void F1(T1? t1) where T1 : class, notnull - Diagnostic(ErrorCode.ERR_NotNullConstraintMustBeFirst, "notnull").WithLocation(4, 57), - // (8,59): error CS0449: The 'class' or 'struct' constraint must come before any other constraints + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "notnull").WithArguments("notnull", "class").WithLocation(4, 57), + // (8,59): error CS8869: The 'class' constraint cannot be combined with the 'notnull' constraint // public static void F2(T2? t2) where T2 : notnull, class - Diagnostic(ErrorCode.ERR_RefValBoundMustBeFirst, "class").WithLocation(8, 59) + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "class").WithArguments("class", "notnull").WithLocation(8, 59) ); var m = comp.SourceModule; @@ -81747,12 +81747,12 @@ public static void F2(T2? t2) where T2 : notnull, class? Assert.True(((MethodSymbol)comp.SourceModule.GlobalNamespace.GetMember("B.F1")).TypeParameters[0].IsNotNullable); comp.VerifyDiagnostics( - // (4,58): error CS8713: The 'notnull' constraint must come before any other constraints + // (4,58): error CS8869: The 'notnull' constraint cannot be combined with the 'class' constraint // public static void F1(T1? t1) where T1 : class?, notnull - Diagnostic(ErrorCode.ERR_NotNullConstraintMustBeFirst, "notnull").WithLocation(4, 58), - // (8,59): error CS0449: The 'class' or 'struct' constraint must come before any other constraints + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "notnull").WithArguments("notnull", "class").WithLocation(4, 58), + // (8,59): error CS8869: The 'class' constraint cannot be combined with the 'notnull' constraint // public static void F2(T2? t2) where T2 : notnull, class? - Diagnostic(ErrorCode.ERR_RefValBoundMustBeFirst, "class").WithLocation(8, 59) + Diagnostic(ErrorCode.ERR_CannotCombineTypeConstraints, "class").WithArguments("class", "notnull").WithLocation(8, 59) ); var m = comp.SourceModule;