diff --git a/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 10.md b/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 10.md
index 48f544a359ebc..b8214835d7dc5 100644
--- a/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 10.md
+++ b/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 10.md
@@ -118,3 +118,22 @@ class C
}
```
+## Variance of `scoped` and `[UnscopedRef]` is more strict
+
+***Introduced in Visual Studio 2022 version 17.13***
+
+Scope can be changed when overriding a method, implementing an interface, or converting a lambda/method to a delegate under
+[some conditions](https://github.com/dotnet/csharplang/blob/05064c2a9567b7a58a07e526dff403ece1866541/proposals/csharp-11.0/low-level-struct-improvements.md#scoped-mismatch)
+(roughly, `scoped` can be added and `[UnscopedRef]` can be removed).
+Previously, the compiler did not report an error/warning for such mismatch under some circumstances, but it is now always reported.
+
+```cs
+D1 d1 = (ref int i) => { }; // previously no mismatch error reported, now:
+ // error CS8986: The 'scoped' modifier of parameter 'i' doesn't match target 'D1'.
+
+D2 d2 = (ref int i) => ref i; // an error was and continues to be reported:
+ // error CS8986: The 'scoped' modifier of parameter 'i' doesn't match target 'D2'.
+
+delegate void D1(scoped ref int x);
+delegate ref int D2(scoped ref int x);
+```
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs
index 7df03440b692e..fae2378ed5b04 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs
@@ -2274,26 +2274,23 @@ private static void CheckParameterModifierMismatchMethodConversion(SyntaxNode sy
return;
}
- if (SourceMemberContainerTypeSymbol.RequiresValidScopedOverrideForRefSafety(delegateMethod))
- {
- SourceMemberContainerTypeSymbol.CheckValidScopedOverride(
- delegateMethod,
- lambdaOrMethod,
- diagnostics,
- static (diagnostics, delegateMethod, lambdaOrMethod, parameter, _, typeAndSyntax) =>
- {
- diagnostics.Add(
- SourceMemberContainerTypeSymbol.ReportInvalidScopedOverrideAsError(delegateMethod, lambdaOrMethod) ?
- ErrorCode.ERR_ScopedMismatchInParameterOfTarget :
- ErrorCode.WRN_ScopedMismatchInParameterOfTarget,
- typeAndSyntax.Syntax.Location,
- new FormattedSymbol(parameter, SymbolDisplayFormat.ShortFormat),
- typeAndSyntax.Type);
- },
- (Type: targetType, Syntax: syntax),
- allowVariance: true,
- invokedAsExtensionMethod: invokedAsExtensionMethod);
- }
+ SourceMemberContainerTypeSymbol.CheckValidScopedOverride(
+ delegateMethod,
+ lambdaOrMethod,
+ diagnostics,
+ static (diagnostics, delegateMethod, lambdaOrMethod, parameter, _, typeAndSyntax) =>
+ {
+ diagnostics.Add(
+ SourceMemberContainerTypeSymbol.ReportInvalidScopedOverrideAsError(delegateMethod, lambdaOrMethod) ?
+ ErrorCode.ERR_ScopedMismatchInParameterOfTarget :
+ ErrorCode.WRN_ScopedMismatchInParameterOfTarget,
+ typeAndSyntax.Syntax.Location,
+ new FormattedSymbol(parameter, SymbolDisplayFormat.ShortFormat),
+ typeAndSyntax.Type);
+ },
+ (Type: targetType, Syntax: syntax),
+ allowVariance: true,
+ invokedAsExtensionMethod: invokedAsExtensionMethod);
SourceMemberContainerTypeSymbol.CheckRefReadonlyInMismatch(
delegateMethod, lambdaOrMethod, diagnostics,
diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol_ImplementationChecks.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol_ImplementationChecks.cs
index 0f2216f4fef46..1addacefa96c7 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol_ImplementationChecks.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol_ImplementationChecks.cs
@@ -1149,25 +1149,22 @@ static void checkValidMethodOverride(
MethodSymbol overridingMethod,
BindingDiagnosticBag diagnostics)
{
- if (RequiresValidScopedOverrideForRefSafety(overriddenMethod))
- {
- CheckValidScopedOverride(
- overriddenMethod,
- overridingMethod,
- diagnostics,
- static (diagnostics, overriddenMethod, overridingMethod, overridingParameter, _, location) =>
- {
- diagnostics.Add(
- ReportInvalidScopedOverrideAsError(overriddenMethod, overridingMethod) ?
- ErrorCode.ERR_ScopedMismatchInParameterOfOverrideOrImplementation :
- ErrorCode.WRN_ScopedMismatchInParameterOfOverrideOrImplementation,
- location,
- new FormattedSymbol(overridingParameter, SymbolDisplayFormat.ShortFormat));
- },
- overridingMemberLocation,
- allowVariance: true,
- invokedAsExtensionMethod: false);
- }
+ CheckValidScopedOverride(
+ overriddenMethod,
+ overridingMethod,
+ diagnostics,
+ static (diagnostics, overriddenMethod, overridingMethod, overridingParameter, _, location) =>
+ {
+ diagnostics.Add(
+ ReportInvalidScopedOverrideAsError(overriddenMethod, overridingMethod) ?
+ ErrorCode.ERR_ScopedMismatchInParameterOfOverrideOrImplementation :
+ ErrorCode.WRN_ScopedMismatchInParameterOfOverrideOrImplementation,
+ location,
+ new FormattedSymbol(overridingParameter, SymbolDisplayFormat.ShortFormat));
+ },
+ overridingMemberLocation,
+ allowVariance: true,
+ invokedAsExtensionMethod: false);
CheckValidNullableMethodOverride(overridingMethod.DeclaringCompilation, overriddenMethod, overridingMethod, diagnostics,
ReportBadReturn,
@@ -1369,53 +1366,6 @@ static bool isValidNullableConversion(
}
#nullable enable
- ///
- /// Returns true if the method signature must match, with respect to scoped for ref safety,
- /// in overrides, interface implementations, or delegate conversions.
- ///
- internal static bool RequiresValidScopedOverrideForRefSafety(MethodSymbol? method)
- {
- if (method is null)
- {
- return false;
- }
-
- var parameters = method.Parameters;
-
- // https://github.com/dotnet/csharplang/blob/main/proposals/csharp-11.0/low-level-struct-improvements.md#scoped-mismatch
- // The compiler will report a diagnostic for _unsafe scoped mismatches_ across overrides, interface implementations, and delegate conversions when:
- // - The method returns a `ref struct` or returns a `ref` or `ref readonly`, or the method has a `ref` or `out` parameter of `ref struct` type, and
- // ...
- int nRefParametersRequired;
- if (method.ReturnType.IsRefLikeOrAllowsRefLikeType() ||
- (method.RefKind is RefKind.Ref or RefKind.RefReadOnly))
- {
- nRefParametersRequired = 1;
- }
- else if (parameters.Any(p => (p.RefKind is RefKind.Ref or RefKind.Out) && p.Type.IsRefLikeOrAllowsRefLikeType()))
- {
- nRefParametersRequired = 2; // including the parameter found above
- }
- else
- {
- return false;
- }
-
- // ...
- // - The method has at least one additional `ref`, `in`, `ref readonly`, or `out` parameter, or a parameter of `ref struct` type.
- int nRefParameters = parameters.Count(p => p.RefKind is RefKind.Ref or RefKind.In or RefKind.RefReadOnlyParameter or RefKind.Out);
- if (nRefParameters >= nRefParametersRequired)
- {
- return true;
- }
- else if (parameters.Any(p => p.RefKind == RefKind.None && p.Type.IsRefLikeOrAllowsRefLikeType()))
- {
- return true;
- }
-
- return false;
- }
-
///
/// Returns true if a scoped mismatch should be reported as an error rather than a warning.
///
diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs
index 61fd5fa1bc95e..4763f5d7fa071 100644
--- a/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs
@@ -1855,25 +1855,23 @@ static void checkMethodOverride(
reportMismatchInParameterType,
(implementingType, isExplicit));
- if (SourceMemberContainerTypeSymbol.RequiresValidScopedOverrideForRefSafety(implementedMethod))
- {
- SourceMemberContainerTypeSymbol.CheckValidScopedOverride(
- implementedMethod,
- implementingMethod,
- diagnostics,
- static (diagnostics, implementedMethod, implementingMethod, implementingParameter, _, arg) =>
- {
- diagnostics.Add(
- SourceMemberContainerTypeSymbol.ReportInvalidScopedOverrideAsError(implementedMethod, implementingMethod) ?
- ErrorCode.ERR_ScopedMismatchInParameterOfOverrideOrImplementation :
- ErrorCode.WRN_ScopedMismatchInParameterOfOverrideOrImplementation,
- GetImplicitImplementationDiagnosticLocation(implementedMethod, arg.implementingType, implementingMethod),
- new FormattedSymbol(implementingParameter, SymbolDisplayFormat.ShortFormat));
- },
- (implementingType, isExplicit),
- allowVariance: true,
- invokedAsExtensionMethod: false);
- }
+ SourceMemberContainerTypeSymbol.CheckValidScopedOverride(
+ implementedMethod,
+ implementingMethod,
+ diagnostics,
+ static (diagnostics, implementedMethod, implementingMethod, implementingParameter, _, arg) =>
+ {
+ diagnostics.Add(
+ SourceMemberContainerTypeSymbol.ReportInvalidScopedOverrideAsError(implementedMethod, implementingMethod) ?
+ ErrorCode.ERR_ScopedMismatchInParameterOfOverrideOrImplementation :
+ ErrorCode.WRN_ScopedMismatchInParameterOfOverrideOrImplementation,
+ GetImplicitImplementationDiagnosticLocation(implementedMethod, arg.implementingType, implementingMethod),
+ new FormattedSymbol(implementingParameter, SymbolDisplayFormat.ShortFormat));
+ },
+ (implementingType, isExplicit),
+ allowVariance: true,
+ invokedAsExtensionMethod: false);
+
SourceMemberContainerTypeSymbol.CheckRefReadonlyInMismatch(
implementedMethod, implementingMethod, diagnostics,
static (diagnostics, implementedMethod, implementingMethod, implementingParameter, _, arg) =>
diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RefEscapingTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RefEscapingTests.cs
index c0c092edba74b..385e0a0bdd50e 100644
--- a/src/Compilers/CSharp/Test/Semantic/Semantics/RefEscapingTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RefEscapingTests.cs
@@ -10358,5 +10358,330 @@ public static void M([UnscopedRef] ref S s)
""";
CreateCompilation(source, targetFramework: TargetFramework.Net70).VerifyDiagnostics();
}
+
+ [Theory, CombinatorialData, WorkItem("https://github.com/dotnet/roslyn/issues/76100")]
+ public void SelfAssignment_ScopeVariance_UnscopedRef_Disallowed_ImplicitInterface(
+ [CombinatorialValues("ref", "out")] string modifier)
+ {
+ var source = $$"""
+ using System.Diagnostics.CodeAnalysis;
+
+ interface I
+ {
+ void M({{modifier}} R r);
+ }
+
+ class C : I
+ {
+ public void M([UnscopedRef] {{modifier}} R r) { }
+ }
+
+ ref struct R;
+ """;
+ CreateCompilation([source, UnscopedRefAttributeDefinition]).VerifyDiagnostics(
+ // (10,17): error CS8987: The 'scoped' modifier of parameter 'r' doesn't match overridden or implemented member.
+ // public void M([UnscopedRef] ref R r) { }
+ Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfOverrideOrImplementation, "M").WithArguments("r").WithLocation(10, 17));
+ }
+
+ [Theory, CombinatorialData, WorkItem("https://github.com/dotnet/roslyn/issues/76100")]
+ public void SelfAssignment_ScopeVariance_UnscopedRef_Disallowed_ExplicitInterface(
+ [CombinatorialValues("ref", "out")] string modifier)
+ {
+ var source = $$"""
+ using System.Diagnostics.CodeAnalysis;
+
+ interface I
+ {
+ void M({{modifier}} R r);
+ }
+
+ class C : I
+ {
+ void I.M([UnscopedRef] {{modifier}} R r) { }
+ }
+
+ ref struct R;
+ """;
+ CreateCompilation([source, UnscopedRefAttributeDefinition]).VerifyDiagnostics(
+ // (10,12): error CS8987: The 'scoped' modifier of parameter 'r' doesn't match overridden or implemented member.
+ // void I.M([UnscopedRef] ref R r) { }
+ Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfOverrideOrImplementation, "M").WithArguments("r").WithLocation(10, 12));
+ }
+
+ [Theory, CombinatorialData, WorkItem("https://github.com/dotnet/roslyn/issues/76100")]
+ public void SelfAssignment_ScopeVariance_UnscopedRef_Disallowed_Override(
+ [CombinatorialValues("ref", "out")] string modifier)
+ {
+ var source = $$"""
+ using System.Diagnostics.CodeAnalysis;
+
+ abstract class B
+ {
+ public abstract void M({{modifier}} R r);
+ }
+
+ class C : B
+ {
+ public override void M([UnscopedRef] {{modifier}} R r) { }
+ }
+
+ ref struct R;
+ """;
+ CreateCompilation([source, UnscopedRefAttributeDefinition]).VerifyDiagnostics(
+ // (10,26): error CS8987: The 'scoped' modifier of parameter 'r' doesn't match overridden or implemented member.
+ // public override void M([UnscopedRef] ref R r) { }
+ Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfOverrideOrImplementation, "M").WithArguments("r").WithLocation(10, 26));
+ }
+
+ [Theory, CombinatorialData, WorkItem("https://github.com/dotnet/roslyn/issues/76100")]
+ public void SelfAssignment_ScopeVariance_UnscopedRef_Disallowed_DelegateConversion(
+ [CombinatorialValues("ref", "out")] string modifier)
+ {
+ var source = $$"""
+ using System.Diagnostics.CodeAnalysis;
+
+ D d = C.M;
+
+ delegate void D({{modifier}} R r);
+
+ static class C
+ {
+ public static void M([UnscopedRef] {{modifier}} R r) { }
+ }
+
+ ref struct R;
+ """;
+ CreateCompilation([source, UnscopedRefAttributeDefinition]).VerifyDiagnostics(
+ // (3,7): error CS8986: The 'scoped' modifier of parameter 'r' doesn't match target 'D'.
+ // D d = C.M;
+ Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfTarget, "C.M").WithArguments("r", "D").WithLocation(3, 7));
+ }
+
+ [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/76100")]
+ [InlineData("[System.Diagnostics.CodeAnalysis.UnscopedRef]", "")]
+ [InlineData("[System.Diagnostics.CodeAnalysis.UnscopedRef]", "[System.Diagnostics.CodeAnalysis.UnscopedRef]")]
+ [InlineData("", "")]
+ public void SelfAssignment_ScopeVariance_UnscopedRef_Allowed_ImplicitInterface(string attr1, string attr2)
+ {
+ var source = $$"""
+ interface I
+ {
+ void M({{attr1}} ref R r);
+ }
+
+ class C : I
+ {
+ public void M({{attr2}} ref R r) { }
+ }
+
+ ref struct R;
+ """;
+ CreateCompilation([source, UnscopedRefAttributeDefinition]).VerifyDiagnostics();
+ }
+
+ [Theory, CombinatorialData, WorkItem("https://github.com/dotnet/roslyn/issues/76100")]
+ public void SelfAssignment_ScopeVariance_ScopedRef_ImplicitInterface(
+ [CombinatorialValues("scoped", "")] string scoped1,
+ [CombinatorialValues("scoped", "")] string scoped2,
+ [CombinatorialValues("ref", "out")] string modifier)
+ {
+ var source = $$"""
+ interface I
+ {
+ void M({{scoped1}} {{modifier}} R r);
+ }
+
+ class C : I
+ {
+ public void M({{scoped2}} {{modifier}} R r) { }
+ }
+
+ ref struct R;
+ """;
+
+ var comp = CreateCompilation(source);
+
+ if (scoped1 == "scoped" && scoped2 == "" && modifier == "ref")
+ {
+ comp.VerifyDiagnostics(
+ // (8,17): error CS8987: The 'scoped' modifier of parameter 'r' doesn't match overridden or implemented member.
+ // public void M( ref R r) { }
+ Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfOverrideOrImplementation, "M").WithArguments("r").WithLocation(8, 17));
+ }
+ else
+ {
+ comp.VerifyDiagnostics();
+ }
+ }
+
+ [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/76100")]
+ [InlineData("[System.Diagnostics.CodeAnalysis.UnscopedRef]", "")]
+ [InlineData("[System.Diagnostics.CodeAnalysis.UnscopedRef]", "[System.Diagnostics.CodeAnalysis.UnscopedRef]")]
+ [InlineData("", "")]
+ public void SelfAssignment_ScopeVariance_UnscopedRef_Allowed_ExplicitInterface(string attr1, string attr2)
+ {
+ var source = $$"""
+ interface I
+ {
+ void M({{attr1}} ref R r);
+ }
+
+ class C : I
+ {
+ void I.M({{attr2}} ref R r) { }
+ }
+
+ ref struct R;
+ """;
+ CreateCompilation([source, UnscopedRefAttributeDefinition]).VerifyDiagnostics();
+ }
+
+ [Theory, CombinatorialData, WorkItem("https://github.com/dotnet/roslyn/issues/76100")]
+ public void SelfAssignment_ScopeVariance_ScopedRef_ExplicitInterface(
+ [CombinatorialValues("scoped", "")] string scoped1,
+ [CombinatorialValues("scoped", "")] string scoped2,
+ [CombinatorialValues("ref", "out")] string modifier)
+ {
+ var source = $$"""
+ interface I
+ {
+ void M({{scoped1}} {{modifier}} R r);
+ }
+
+ class C : I
+ {
+ void I.M({{scoped2}} {{modifier}} R r) { }
+ }
+
+ ref struct R;
+ """;
+
+ var comp = CreateCompilation(source);
+
+ if (scoped1 == "scoped" && scoped2 == "" && modifier == "ref")
+ {
+ comp.VerifyDiagnostics(
+ // (8,12): error CS8987: The 'scoped' modifier of parameter 'r' doesn't match overridden or implemented member.
+ // void I.M( ref R r) { }
+ Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfOverrideOrImplementation, "M").WithArguments("r").WithLocation(8, 12));
+ }
+ else
+ {
+ comp.VerifyDiagnostics();
+ }
+ }
+
+ [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/76100")]
+ [InlineData("[System.Diagnostics.CodeAnalysis.UnscopedRef]", "")]
+ [InlineData("[System.Diagnostics.CodeAnalysis.UnscopedRef]", "[System.Diagnostics.CodeAnalysis.UnscopedRef]")]
+ [InlineData("", "")]
+ public void SelfAssignment_ScopeVariance_UnscopedRef_Allowed_Override(string attr1, string attr2)
+ {
+ var source = $$"""
+ abstract class B
+ {
+ public abstract void M({{attr1}} ref R r);
+ }
+
+ class C : B
+ {
+ public override void M({{attr2}} ref R r) { }
+ }
+
+ ref struct R;
+ """;
+ CreateCompilation([source, UnscopedRefAttributeDefinition]).VerifyDiagnostics();
+ }
+
+ [Theory, CombinatorialData, WorkItem("https://github.com/dotnet/roslyn/issues/76100")]
+ public void SelfAssignment_ScopeVariance_ScopedRef_Override(
+ [CombinatorialValues("scoped", "")] string scoped1,
+ [CombinatorialValues("scoped", "")] string scoped2,
+ [CombinatorialValues("ref", "out")] string modifier)
+ {
+ var source = $$"""
+ abstract class B
+ {
+ public abstract void M({{scoped1}} {{modifier}} R r);
+ }
+
+ class C : B
+ {
+ public override void M({{scoped2}} {{modifier}} R r) { }
+ }
+
+ ref struct R;
+ """;
+
+ var comp = CreateCompilation(source);
+
+ if (scoped1 == "scoped" && scoped2 == "" && modifier == "ref")
+ {
+ comp.VerifyDiagnostics(
+ // (8,26): error CS8987: The 'scoped' modifier of parameter 'r' doesn't match overridden or implemented member.
+ // public override void M( ref R r) { }
+ Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfOverrideOrImplementation, "M").WithArguments("r").WithLocation(8, 26));
+ }
+ else
+ {
+ comp.VerifyDiagnostics();
+ }
+ }
+
+ [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/76100")]
+ [InlineData("[System.Diagnostics.CodeAnalysis.UnscopedRef]", "")]
+ [InlineData("[System.Diagnostics.CodeAnalysis.UnscopedRef]", "[System.Diagnostics.CodeAnalysis.UnscopedRef]")]
+ [InlineData("", "")]
+ public void SelfAssignment_ScopeVariance_UnscopedRef_Allowed_DelegateConversion(string attr1, string attr2)
+ {
+ var source = $$"""
+ D d = C.M;
+
+ delegate void D({{attr1}} ref R r);
+
+ static class C
+ {
+ public static void M({{attr2}} ref R r) { }
+ }
+
+ ref struct R;
+ """;
+ CreateCompilation([source, UnscopedRefAttributeDefinition]).VerifyDiagnostics();
+ }
+
+ [Theory, CombinatorialData, WorkItem("https://github.com/dotnet/roslyn/issues/76100")]
+ public void SelfAssignment_ScopeVariance_ScopedRef_DelegateConversion(
+ [CombinatorialValues("scoped", "")] string scoped1,
+ [CombinatorialValues("scoped", "")] string scoped2,
+ [CombinatorialValues("ref", "out")] string modifier)
+ {
+ var source = $$"""
+ D d = C.M;
+
+ delegate void D({{scoped1}} {{modifier}} R r);
+
+ static class C
+ {
+ public static void M({{scoped2}} {{modifier}} R r) { }
+ }
+
+ ref struct R;
+ """;
+
+ var comp = CreateCompilation(source);
+
+ if (scoped1 == "scoped" && scoped2 == "" && modifier == "ref")
+ {
+ comp.VerifyDiagnostics(
+ // (1,7): error CS8986: The 'scoped' modifier of parameter 'r' doesn't match target 'D'.
+ // D d = C.M;
+ Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfTarget, "C.M").WithArguments("r", "D").WithLocation(1, 7));
+ }
+ else
+ {
+ comp.VerifyDiagnostics();
+ }
+ }
}
}
diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs
index 5e094ed174443..1f8a180901abe 100644
--- a/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs
@@ -16249,21 +16249,27 @@ static void Main()
{{
D0 d0 = ({refModifier} int i) => {{ }};
D1 d1 = ({refModifier} int i) => F();
- D2 d2 = ({refModifier} int i) => ref F(); // 1
- D3 d3 = ({refModifier} int i) => ref F(); // 2
- D4 d4 = ({refModifier} int i) => new R(); // 3
+ D2 d2 = ({refModifier} int i) => ref F();
+ D3 d3 = ({refModifier} int i) => ref F();
+ D4 d4 = ({refModifier} int i) => new R();
}}
}}";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
+ // (12,22): error CS8986: The 'scoped' modifier of parameter 'i' doesn't match target 'D0'.
+ // D0 d0 = (ref int i) => { };
+ Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfTarget, $"({refModifier} int i) => {{ }}").WithArguments("i", "D0").WithLocation(12, 22),
+ // (13,22): error CS8986: The 'scoped' modifier of parameter 'i' doesn't match target 'D1'.
+ // D1 d1 = (ref int i) => F();
+ Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfTarget, $"({refModifier} int i) => F()").WithArguments("i", "D1").WithLocation(13, 22),
// (14,22): error CS8986: The 'scoped' modifier of parameter 'i' doesn't match target 'D2'.
- // D2 d2 = (ref int i) => ref F(); // 1
+ // D2 d2 = (ref int i) => ref F();
Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfTarget, $"({refModifier} int i) => ref F()").WithArguments("i", "D2").WithLocation(14, 22),
// (15,22): error CS8986: The 'scoped' modifier of parameter 'i' doesn't match target 'D3'.
- // D3 d3 = (ref int i) => ref F(); // 2
+ // D3 d3 = (ref int i) => ref F();
Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfTarget, $"({refModifier} int i) => ref F()").WithArguments("i", "D3").WithLocation(15, 22),
// (16,22): error CS8986: The 'scoped' modifier of parameter 'i' doesn't match target 'D4'.
- // D4 d4 = (ref int i) => new R(); // 3
+ // D4 d4 = (ref int i) => new R();
Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfTarget, $"({refModifier} int i) => new R()").WithArguments("i", "D4").WithLocation(16, 22));
}
@@ -16284,18 +16290,24 @@ class Program
static void Main()
{{
D0 d0 = ({refModifier} int i, R r) => {{ }};
- D1 d1 = ({refModifier} int i, ref R r) => {{ }}; // 1
+ D1 d1 = ({refModifier} int i, ref R r) => {{ }};
D2 d2 = ({refModifier} int i, in R r) => {{ }};
- D3 d3 = ({refModifier} int i, out R r) => {{ r = default; }}; // 2
+ D3 d3 = ({refModifier} int i, out R r) => {{ r = default; }};
}}
}}";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
+ // (11,22): error CS8986: The 'scoped' modifier of parameter 'i' doesn't match target 'D0'.
+ // D0 d0 = (ref int i, R r) => { };
+ Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfTarget, $"({refModifier} int i, R r) => {{ }}").WithArguments("i", "D0").WithLocation(11, 22),
// (12,22): error CS8986: The 'scoped' modifier of parameter 'i' doesn't match target 'D1'.
- // D1 d1 = (ref int i, ref R r) => { }; // 1
+ // D1 d1 = (ref int i, ref R r) => { };
Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfTarget, $"({refModifier} int i, ref R r) => {{ }}").WithArguments("i", "D1").WithLocation(12, 22),
+ // (13,22): error CS8986: The 'scoped' modifier of parameter 'i' doesn't match target 'D2'.
+ // D2 d2 = (ref int i, in R r) => { };
+ Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfTarget, $"({refModifier} int i, in R r) => {{ }}").WithArguments("i", "D2").WithLocation(13, 22),
// (14,22): error CS8986: The 'scoped' modifier of parameter 'i' doesn't match target 'D3'.
- // D3 d3 = (ref int i, out R r) => { r = default; }; // 2
+ // D3 d3 = (ref int i, out R r) => { r = default; };
Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfTarget, $"({refModifier} int i, out R r) => {{ r = default; }}").WithArguments("i", "D3").WithLocation(14, 22));
}
@@ -16765,7 +16777,10 @@ public static void M(object? o)
comp.VerifyDiagnostics(
// (3,17): error CS9048: The 'scoped' modifier can be used for refs and ref struct values only.
// delegate R D(scoped T t);
- Diagnostic(ErrorCode.ERR_ScopedRefAndRefStructOnly, "scoped T t").WithLocation(3, 17)
+ Diagnostic(ErrorCode.ERR_ScopedRefAndRefStructOnly, "scoped T t").WithLocation(3, 17),
+ // (14,27): error CS8986: The 'scoped' modifier of parameter 'o2' doesn't match target 'D'.
+ // D d = o2 => throw null!;
+ Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfTarget, "o2 => throw null!").WithArguments("o2", "D").WithLocation(14, 27)
);
var syntaxTree = comp.SyntaxTrees[0];
@@ -17388,7 +17403,10 @@ public class C : Base
Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfOverrideOrImplementation, "get").WithArguments("rs").WithLocation(11, 38),
// (12,45): error CS8987: The 'scoped' modifier of parameter 'rs' doesn't match overridden or implemented member.
// public override RS this[RS rs, int _] { get => default; set { } } // 2
- Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfOverrideOrImplementation, "get").WithArguments("rs").WithLocation(12, 45));
+ Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfOverrideOrImplementation, "get").WithArguments("rs").WithLocation(12, 45),
+ // (12,61): error CS8987: The 'scoped' modifier of parameter 'rs' doesn't match overridden or implemented member.
+ // public override RS this[RS rs, int _] { get => default; set { } } // 2
+ Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfOverrideOrImplementation, "set").WithArguments("rs").WithLocation(12, 61));
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/73384")]
@@ -17417,7 +17435,10 @@ public class C : I
Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfOverrideOrImplementation, "get").WithArguments("rs").WithLocation(11, 29),
// (12,36): error CS8987: The 'scoped' modifier of parameter 'rs' doesn't match overridden or implemented member.
// public RS this[RS rs, int _] { get => default; set { } } // 2
- Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfOverrideOrImplementation, "get").WithArguments("rs").WithLocation(12, 36));
+ Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfOverrideOrImplementation, "get").WithArguments("rs").WithLocation(12, 36),
+ // (12,52): error CS8987: The 'scoped' modifier of parameter 'rs' doesn't match overridden or implemented member.
+ // public RS this[RS rs, int _] { get => default; set { } } // 2
+ Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfOverrideOrImplementation, "set").WithArguments("rs").WithLocation(12, 52));
}
[CombinatorialData]