diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx
index ac21571f750df..31f88b937ad7e 100644
--- a/src/Compilers/CSharp/Portable/CSharpResources.resx
+++ b/src/Compilers/CSharp/Portable/CSharpResources.resx
@@ -3851,6 +3851,9 @@ You should consider suppressing the warning only if you're sure that you don't w
Invalid variance: The type parameter '{1}' must be {3} valid on '{0}'. '{1}' is {2}.
+
+ Invalid variance: The type parameter '{1}' must be {3} valid on '{0}' unless language version '{4}' or greater is used. '{1}' is {2}.
+
'{0}': cannot derive from the dynamic type
@@ -6348,4 +6351,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
A module initializer must be an ordinary member method
+
+ variance safety for static interface members
+
diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
index 7ddf7a993bd77..4d3516595b7a4 100644
--- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
+++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
@@ -1868,6 +1868,9 @@ internal enum ErrorCode
ERR_NonPrivateAPIInRecord = 8879,
#endregion diagnostics introduced for C# 9.0
+
+ ERR_UnexpectedVarianceStaticMember = 9100,
+
// Note: you will need to re-generate compiler code after adding warnings (eng\generate-compiler-code.cmd)
}
}
diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs
index cfb7b66dba2f5..262809a089c5c 100644
--- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs
+++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs
@@ -209,6 +209,7 @@ internal enum MessageID
IDS_FeatureNullPointerConstantPattern = MessageBase + 12783,
IDS_FeatureModuleInitializers = MessageBase + 12784,
IDS_FeatureTargetTypedConditional = MessageBase + 12785,
+ IDS_FeatureVarianceSafetyForStaticInterfaceMembers = MessageBase + 12786,
}
// Message IDs may refer to strings that need to be localized.
@@ -336,6 +337,7 @@ internal static LanguageVersion RequiredVersion(this MessageID feature)
case MessageID.IDS_FeatureTargetTypedConditional: // semantic check
case MessageID.IDS_FeatureStaticAnonymousFunction: // syntax check
case MessageID.IDS_FeatureModuleInitializers: // semantic check on method attribute
+ case MessageID.IDS_FeatureVarianceSafetyForStaticInterfaceMembers: //semantic check
return LanguageVersion.Preview;
// C# 8.0 features.
diff --git a/src/Compilers/CSharp/Portable/Symbols/VarianceSafety.cs b/src/Compilers/CSharp/Portable/Symbols/VarianceSafety.cs
index d867858b582b7..dabb102cd2093 100644
--- a/src/Compilers/CSharp/Portable/Symbols/VarianceSafety.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/VarianceSafety.cs
@@ -145,6 +145,11 @@ private static void CheckMethodVarianceSafety(this MethodSymbol method, Diagnost
private static void CheckMethodVarianceSafety(this MethodSymbol method, LocationProvider returnTypeLocationProvider, DiagnosticBag diagnostics)
{
+ if (SkipVarianceSafetyChecks(method))
+ {
+ return;
+ }
+
// Spec 13.2.1: "Furthermore, each class type constraint, interface type constraint and
// type parameter constraint on any type parameter of the method must be input-safe."
CheckTypeParametersVarianceSafety(method.TypeParameters, method, diagnostics);
@@ -162,11 +167,26 @@ private static void CheckMethodVarianceSafety(this MethodSymbol method, Location
CheckParametersVarianceSafety(method.Parameters, method, diagnostics);
}
+ private static bool SkipVarianceSafetyChecks(Symbol member)
+ {
+ if (member.IsStatic)
+ {
+ return MessageID.IDS_FeatureVarianceSafetyForStaticInterfaceMembers.RequiredVersion() <= member.DeclaringCompilation.LanguageVersion;
+ }
+
+ return false;
+ }
+
///
/// Accumulate diagnostics related to the variance safety of an interface property.
///
private static void CheckPropertyVarianceSafety(PropertySymbol property, DiagnosticBag diagnostics)
{
+ if (SkipVarianceSafetyChecks(property))
+ {
+ return;
+ }
+
bool hasGetter = (object)property.GetMethod != null;
bool hasSetter = (object)property.SetMethod != null;
if (hasGetter || hasSetter)
@@ -193,6 +213,11 @@ private static void CheckPropertyVarianceSafety(PropertySymbol property, Diagnos
///
private static void CheckEventVarianceSafety(EventSymbol @event, DiagnosticBag diagnostics)
{
+ if (SkipVarianceSafetyChecks(@event))
+ {
+ return;
+ }
+
IsVarianceUnsafe(
@event.Type,
requireOutputSafety: false,
@@ -442,7 +467,15 @@ private static void AddVarianceError(
// "requires output-safe", and "requires input-safe and output-safe". This would make the error codes much easier to document and
// much more actionable.
// UNDONE: related location for use is much more useful
- diagnostics.Add(ErrorCode.ERR_UnexpectedVariance, location, context, unsafeTypeParameter, actualVariance.Localize(), expectedVariance.Localize());
+ if (!(context is TypeSymbol) && context.IsStatic)
+ {
+ diagnostics.Add(ErrorCode.ERR_UnexpectedVarianceStaticMember, location, context, unsafeTypeParameter, actualVariance.Localize(), expectedVariance.Localize(),
+ new CSharpRequiredLanguageVersion(MessageID.IDS_FeatureVarianceSafetyForStaticInterfaceMembers.RequiredVersion()));
+ }
+ else
+ {
+ diagnostics.Add(ErrorCode.ERR_UnexpectedVariance, location, context, unsafeTypeParameter, actualVariance.Localize(), expectedVariance.Localize());
+ }
}
private static T GetDeclaringSyntax(this Symbol symbol) where T : SyntaxNode
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
index 67706e1184e5e..83c3a365c671c 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
@@ -862,6 +862,11 @@
A constructor declared in a record with parameters must have 'this' constructor initializer.
+
+
+ Invalid variance: The type parameter '{1}' must be {3} valid on '{0}' unless language version '{4}' or greater is used. '{1}' is {2}.
+
+ {0}: Nejde zadat třídu omezení a zároveň omezení unmanaged.
@@ -1486,6 +1491,11 @@
deklarace using
+
+
+ variance safety for static interface members
+
+ <null>
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
index 647e546a29c0b..78edc4f3aec81 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
@@ -862,6 +862,11 @@
A constructor declared in a record with parameters must have 'this' constructor initializer.
+
+
+ Invalid variance: The type parameter '{1}' must be {3} valid on '{0}' unless language version '{4}' or greater is used. '{1}' is {2}.
+
+ "{0}": Eine Einschränkungsklasse kann nicht gleichzeitig mit einer unmanaged-Einschränkung angegeben werden.
@@ -1486,6 +1491,11 @@
Using-Deklarationen
+
+
+ variance safety for static interface members
+
+ <NULL>
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
index 7408480b97336..828e53e3adbd5 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
@@ -862,6 +862,11 @@
A constructor declared in a record with parameters must have 'this' constructor initializer.
+
+
+ Invalid variance: The type parameter '{1}' must be {3} valid on '{0}' unless language version '{4}' or greater is used. '{1}' is {2}.
+
+ "{0}": no se puede especificar a la vez una clase de restricción y la restricción "unmanaged"
@@ -1486,6 +1491,11 @@
declaraciones using
+
+
+ variance safety for static interface members
+
+ <NULL>
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
index 5ed60113522ae..fd50759b51000 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
@@ -862,6 +862,11 @@
A constructor declared in a record with parameters must have 'this' constructor initializer.
+
+
+ Invalid variance: The type parameter '{1}' must be {3} valid on '{0}' unless language version '{4}' or greater is used. '{1}' is {2}.
+
+ '{0}' : impossible de spécifier à la fois une classe de contrainte et la contrainte 'unmanaged'
@@ -1486,6 +1491,11 @@
Déclarations using
+
+
+ variance safety for static interface members
+
+ <Null>
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
index d047313f33244..7c37069b61a7f 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
@@ -862,6 +862,11 @@
A constructor declared in a record with parameters must have 'this' constructor initializer.
+
+
+ Invalid variance: The type parameter '{1}' must be {3} valid on '{0}' unless language version '{4}' or greater is used. '{1}' is {2}.
+
+ '{0}': non è possibile specificare sia una classe constraint che il vincolo 'unmanaged'
@@ -1486,6 +1491,11 @@
dichiarazioni using
+
+
+ variance safety for static interface members
+
+ <Null>
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
index fcb3f384ed1b2..d61d620e8e519 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
@@ -862,6 +862,11 @@
A constructor declared in a record with parameters must have 'this' constructor initializer.
+
+
+ Invalid variance: The type parameter '{1}' must be {3} valid on '{0}' unless language version '{4}' or greater is used. '{1}' is {2}.
+
+ '{0}': 制約クラスと 'unmanaged' 制約の両方を指定することはできません
@@ -1486,6 +1491,11 @@
using 宣言
+
+
+ variance safety for static interface members
+
+ <null>
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
index 3f38b24ab4b1b..e708e2d63f58d 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
@@ -862,6 +862,11 @@
A constructor declared in a record with parameters must have 'this' constructor initializer.
+
+
+ Invalid variance: The type parameter '{1}' must be {3} valid on '{0}' unless language version '{4}' or greater is used. '{1}' is {2}.
+
+ '{0}': constraint 클래스와 'unmanaged' 제약 조건을 둘 다 지정할 수는 없습니다.
@@ -1486,6 +1491,11 @@
using 선언
+
+
+ variance safety for static interface members
+
+ <null>
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
index da8b9557460ba..23064b9436870 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
@@ -862,6 +862,11 @@
A constructor declared in a record with parameters must have 'this' constructor initializer.
+
+
+ Invalid variance: The type parameter '{1}' must be {3} valid on '{0}' unless language version '{4}' or greater is used. '{1}' is {2}.
+
+ „{0}”: nie można jednocześnie określić klasy ograniczenia i ograniczenia „unmanaged”
@@ -1486,6 +1491,11 @@
deklaracje using
+
+
+ variance safety for static interface members
+
+ <null>
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
index 7dd2f85929a88..ba0235152bce7 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
@@ -862,6 +862,11 @@
A constructor declared in a record with parameters must have 'this' constructor initializer.
+
+
+ Invalid variance: The type parameter '{1}' must be {3} valid on '{0}' unless language version '{4}' or greater is used. '{1}' is {2}.
+
+ '{0}': não é possível especificar uma classe de restrição e a restrição 'unmanaged'
@@ -1484,6 +1489,11 @@
declarações using
+
+
+ variance safety for static interface members
+
+ <nulo>
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
index 589e2349f6ee6..4d84bcc89ab0f 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
@@ -862,6 +862,11 @@
A constructor declared in a record with parameters must have 'this' constructor initializer.
+
+
+ Invalid variance: The type parameter '{1}' must be {3} valid on '{0}' unless language version '{4}' or greater is used. '{1}' is {2}.
+
+ "{0}": невозможно одновременно задать класс ограничения и ограничение "unmanaged"
@@ -1486,6 +1491,11 @@
объявления using
+
+
+ variance safety for static interface members
+
+ <NULL>
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
index 2d769a5a0b11a..341f92044c214 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
@@ -862,6 +862,11 @@
A constructor declared in a record with parameters must have 'this' constructor initializer.
+
+
+ Invalid variance: The type parameter '{1}' must be {3} valid on '{0}' unless language version '{4}' or greater is used. '{1}' is {2}.
+
+ '{0}': hem bir kısıtlama sınıfı hem de 'unmanaged' kısıtlaması belirtilemez
@@ -1486,6 +1491,11 @@
using bildirimleri
+
+
+ variance safety for static interface members
+
+ <null>
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
index b969ffe8a241e..786004ec1fe85 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
@@ -862,6 +862,11 @@
A constructor declared in a record with parameters must have 'this' constructor initializer.
+
+
+ Invalid variance: The type parameter '{1}' must be {3} valid on '{0}' unless language version '{4}' or greater is used. '{1}' is {2}.
+
+ “{0}”: 不能既指定约束类又指定 “unmanaged” 约束
@@ -1486,6 +1491,11 @@
Using 声明
+
+
+ variance safety for static interface members
+
+ <null>
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
index 41d869502e6fa..df095239c7fcb 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
@@ -862,6 +862,11 @@
A constructor declared in a record with parameters must have 'this' constructor initializer.
+
+
+ Invalid variance: The type parameter '{1}' must be {3} valid on '{0}' unless language version '{4}' or greater is used. '{1}' is {2}.
+
+ '{0}': 不可在指定條件約束類型的同時,又指定 'unmanaged' 條件約束
@@ -1486,6 +1491,11 @@
using 宣告
+
+
+ variance safety for static interface members
+
+ <null>
diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs
index 73f7476e891ba..3d419b8d63617 100644
--- a/src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs
+++ b/src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs
@@ -59246,6 +59246,168 @@ private void M1(T1 x) {}
);
}
+ [Fact]
+ public void VarianceSafety_13()
+ {
+ var source1 =
+@"
+class Program
+{
+ static void Main()
+ {
+ I2.P1 = ""a"";
+ I2.P2 = ""b"";
+ System.Console.WriteLine(I2.P1);
+ System.Console.WriteLine(I2.P2);
+ }
+}
+
+interface I2
+{
+ static T1 P1 { get; set; }
+ static T2 P2 { get; set; }
+}
+";
+
+ var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe,
+ parseOptions: TestOptions.Regular8,
+ targetFramework: TargetFramework.NetStandardLatest);
+ compilation1.VerifyDiagnostics(
+ // (15,12): error CS9100: Invalid variance: The type parameter 'T1' must be invariantly valid on 'I2.P1' unless language version 'preview' or greater is used. 'T1' is covariant.
+ // static T1 P1 { get; set; }
+ Diagnostic(ErrorCode.ERR_UnexpectedVarianceStaticMember, "T1").WithArguments("I2.P1", "T1", "covariant", "invariantly", "preview").WithLocation(15, 12),
+ // (16,12): error CS9100: Invalid variance: The type parameter 'T2' must be invariantly valid on 'I2.P2' unless language version 'preview' or greater is used. 'T2' is contravariant.
+ // static T2 P2 { get; set; }
+ Diagnostic(ErrorCode.ERR_UnexpectedVarianceStaticMember, "T2").WithArguments("I2.P2", "T2", "contravariant", "invariantly", "preview").WithLocation(16, 12)
+ );
+
+ compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe,
+ parseOptions: TestOptions.RegularPreview,
+ targetFramework: TargetFramework.NetStandardLatest);
+
+#if false // PROTOTYPE: enable this branch once https://github.com/dotnet/runtime/issues/39612 is fixed
+ CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null :
+@"a
+b").VerifyDiagnostics();
+#else
+ compilation1.VerifyEmitDiagnostics();
+#endif
+ }
+
+ [Fact]
+ public void VarianceSafety_14()
+ {
+ var source1 =
+@"
+class Program
+{
+ static void Main()
+ {
+ System.Console.WriteLine(I2.M1(""a""));
+ System.Console.WriteLine(I2.M2(""b""));
+ }
+}
+
+interface I2
+{
+ static T1 M1(T1 x) => x;
+ static T2 M2(T2 x) => x;
+}
+";
+
+ var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe,
+ parseOptions: TestOptions.Regular8,
+ targetFramework: TargetFramework.NetStandardLatest);
+ compilation1.VerifyDiagnostics(
+ // (13,18): error CS9100: Invalid variance: The type parameter 'T1' must be contravariantly valid on 'I2.M1(T1)' unless language version 'preview' or greater is used. 'T1' is covariant.
+ // static T1 M1(T1 x) => x;
+ Diagnostic(ErrorCode.ERR_UnexpectedVarianceStaticMember, "T1").WithArguments("I2.M1(T1)", "T1", "covariant", "contravariantly", "preview").WithLocation(13, 18),
+ // (14,12): error CS9100: Invalid variance: The type parameter 'T2' must be covariantly valid on 'I2.M2(T2)' unless language version 'preview' or greater is used. 'T2' is contravariant.
+ // static T2 M2(T2 x) => x;
+ Diagnostic(ErrorCode.ERR_UnexpectedVarianceStaticMember, "T2").WithArguments("I2.M2(T2)", "T2", "contravariant", "covariantly", "preview").WithLocation(14, 12)
+ );
+
+ compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe,
+ parseOptions: TestOptions.RegularPreview,
+ targetFramework: TargetFramework.NetStandardLatest);
+
+#if false // PROTOTYPE: enable this branch once https://github.com/dotnet/runtime/issues/39612 is fixed
+ CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null :
+@"a
+b").VerifyDiagnostics();
+#else
+ compilation1.VerifyEmitDiagnostics();
+#endif
+ }
+
+ [Fact]
+ public void VarianceSafety_15()
+ {
+ var source1 =
+@"
+class Program
+{
+ static void Main()
+ {
+ I2.E1 += Print1;
+ I2.E2 += Print2;
+ I2.Raise();
+ }
+
+ static void Print1(System.Func x)
+ {
+ System.Console.WriteLine(x(""a""));
+ }
+
+ static void Print2(System.Func x)
+ {
+ System.Console.WriteLine(x(""b""));
+ }
+}
+
+interface I2
+{
+ static event System.Action> E1;
+ static event System.Action> E2;
+
+ static void Raise()
+ {
+ E1(Print);
+ E2(Print);
+ }
+
+ static T3 Print(T3 x)
+ {
+ return x;
+ }
+}
+";
+
+ var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe,
+ parseOptions: TestOptions.Regular8,
+ targetFramework: TargetFramework.NetStandardLatest);
+ compilation1.VerifyDiagnostics(
+ // (24,53): error CS9100: Invalid variance: The type parameter 'T1' must be contravariantly valid on 'I2.E1' unless language version 'preview' or greater is used. 'T1' is covariant.
+ // static event System.Action> E1;
+ Diagnostic(ErrorCode.ERR_UnexpectedVarianceStaticMember, "E1").WithArguments("I2.E1", "T1", "covariant", "contravariantly", "preview").WithLocation(24, 53),
+ // (25,53): error CS9100: Invalid variance: The type parameter 'T2' must be covariantly valid on 'I2.E2' unless language version 'preview' or greater is used. 'T2' is contravariant.
+ // static event System.Action> E2;
+ Diagnostic(ErrorCode.ERR_UnexpectedVarianceStaticMember, "E2").WithArguments("I2.E2", "T2", "contravariant", "covariantly", "preview").WithLocation(25, 53)
+ );
+
+ compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe,
+ parseOptions: TestOptions.RegularPreview,
+ targetFramework: TargetFramework.NetStandardLatest);
+
+#if false // PROTOTYPE: enable this branch once https://github.com/dotnet/runtime/issues/39612 is fixed
+ CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null :
+@"a
+b").VerifyDiagnostics();
+#else
+ compilation1.VerifyEmitDiagnostics();
+#endif
+ }
+
[Fact]
[WorkItem(1029574, "https://dev.azure.com/devdiv/DevDiv/_workitems/edit/1029574")]
public void Errors_01()
diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs
index dc843c5c1a770..53d59fa955c88 100644
--- a/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs
+++ b/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs
@@ -946,5 +946,19 @@ public void N()
",
expectedActionSet: Enumerable.Empty());
}
+
+ [Fact]
+ public async Task UpgradeProjectForVarianceSafetyForStaticInterfaceMembers_CS9100()
+ {
+ await TestLanguageVersionUpgradedAsync(
+@"
+interface I2
+{
+ static T1 M1([|T1|] x) => x;
+}
+",
+ expected: LanguageVersion.Preview,
+ new CSharpParseOptions(LanguageVersion.CSharp8));
+ }
}
}
diff --git a/src/Features/CSharp/Portable/UpgradeProject/CSharpUpgradeProjectCodeFixProvider.cs b/src/Features/CSharp/Portable/UpgradeProject/CSharpUpgradeProjectCodeFixProvider.cs
index f6d4610797baf..9b3f46ef7705c 100644
--- a/src/Features/CSharp/Portable/UpgradeProject/CSharpUpgradeProjectCodeFixProvider.cs
+++ b/src/Features/CSharp/Portable/UpgradeProject/CSharpUpgradeProjectCodeFixProvider.cs
@@ -46,6 +46,7 @@ public CSharpUpgradeProjectCodeFixProvider()
"CS8652", // error CS8652: The feature '' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
"CS8703", // error CS8703: The modifier '{0}' is not valid for this item in C# {1}. Please use language version '{2}' or greater.
"CS8706", // error CS8706: '{0}' cannot implement interface member '{1}' in type '{2}' because feature '{3}' is not available in C# {4}. Please use language version '{5}' or greater.
+ "CS9100", // error CS9100: Invalid variance: The type parameter 'T1' must be contravariantly valid on 'I2.M1(T1)' unless language version 'preview' or greater is used. 'T1' is covariant.
});
public override string UpgradeThisProjectResource => CSharpFeaturesResources.Upgrade_this_project_to_csharp_language_version_0;