diff --git a/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 6.md b/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 6.md
index 4dab166db115b..a530a0ab2d7dc 100644
--- a/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 6.md
+++ b/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 6.md
@@ -108,4 +108,3 @@ These are _function_type_conversions_.
}
}
```
-
diff --git a/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 7.md b/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 7.md
index 483e0973945c6..dd8a7a6b5b2af 100644
--- a/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 7.md
+++ b/docs/compilers/CSharp/Compiler Breaking Changes - DotNet 7.md
@@ -34,3 +34,25 @@
public CustomHandler(int literalLength, int formattedCount, C c) {}
}
```
+
+
+3. In Visual Studio 17.1, `ref`/`ref readonly`/`in`/`out` are not allowed to be used on return/parameters of a method attributed with `UnmanagedCallersOnly`.
+https://github.com/dotnet/roslyn/issues/57025
+
+ ```cs
+ using System.Runtime.InteropServices;
+ [UnmanagedCallersOnly]
+ static ref int M1() => throw null; // error CS8977: Cannot use 'ref', 'in', or 'out' in a method attributed with 'UnmanagedCallersOnly'.
+
+ [UnmanagedCallersOnly]
+ static ref readonly int M2() => throw null; // error CS8977: Cannot use 'ref', 'in', or 'out' in a method attributed with 'UnmanagedCallersOnly'.
+
+ [UnmanagedCallersOnly]
+ static void M3(ref int o) => throw null; // error CS8977: Cannot use 'ref', 'in', or 'out' in a method attributed with 'UnmanagedCallersOnly'.
+
+ [UnmanagedCallersOnly]
+ static void M4(in int o) => throw null; // error CS8977: Cannot use 'ref', 'in', or 'out' in a method attributed with 'UnmanagedCallersOnly'.
+
+ [UnmanagedCallersOnly]
+ static void M5(out int o) => throw null; // error CS8977: Cannot use 'ref', 'in', or 'out' in a method attributed with 'UnmanagedCallersOnly'.
+ ```
diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx
index f24f7a61748b1..f087cfe9f7fab 100644
--- a/src/Compilers/CSharp/Portable/CSharpResources.resx
+++ b/src/Compilers/CSharp/Portable/CSharpResources.resx
@@ -6875,6 +6875,9 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
The operation may overflow at runtime (use 'unchecked' syntax to override)
+
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+
newlines in interpolations
diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
index 698f6c0f0c041..9e0628ba2ae13 100644
--- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
+++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
@@ -2003,6 +2003,10 @@ internal enum ErrorCode
ERR_LambdaExplicitReturnTypeVar = 8975,
ERR_InterpolatedStringsReferencingInstanceCannotBeInObjectInitializers = 8976,
+ // Added in VS 17.1. Technically a breaking change, but the code it breaks was already guaranteed to throw
+ // at runtime.
+ ERR_CannotUseRefInUnmanagedCallersOnly = 8977,
+
#endregion
// Note: you will need to re-generate compiler code after adding warnings (eng\generate-compiler-code.cmd)
diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbolWithAttributes.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbolWithAttributes.cs
index f10521a2f2eea..60a068e423039 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbolWithAttributes.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbolWithAttributes.cs
@@ -918,14 +918,19 @@ private void DecodeUnmanagedCallersOnlyAttribute(ref DecodeWellKnownAttributeArg
return;
}
- checkAndReportManagedTypes(ReturnType, returnTypeSyntax, isParam: false, diagnostics);
+ checkAndReportManagedTypes(ReturnType, this.RefKind, returnTypeSyntax, isParam: false, diagnostics);
foreach (var param in Parameters)
{
- checkAndReportManagedTypes(param.Type, param.GetNonNullSyntaxNode(), isParam: true, diagnostics);
+ checkAndReportManagedTypes(param.Type, param.RefKind, param.GetNonNullSyntaxNode(), isParam: true, diagnostics);
}
- static void checkAndReportManagedTypes(TypeSymbol type, SyntaxNode syntax, bool isParam, BindingDiagnosticBag diagnostics)
+ static void checkAndReportManagedTypes(TypeSymbol type, RefKind refKind, SyntaxNode syntax, bool isParam, BindingDiagnosticBag diagnostics)
{
+ if (refKind != RefKind.None)
+ {
+ diagnostics.Add(ErrorCode.ERR_CannotUseRefInUnmanagedCallersOnly, syntax.Location);
+ }
+
// use-site diagnostics will be reported at actual parameter declaration site, we're only interested
// in reporting managed types being used
switch (type.ManagedKindNoUseSiteDiagnostics)
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
index 36b79b5d27e7e..a4f1cfc656e02 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
@@ -257,6 +257,11 @@
Rozšiřující metoda, kde jako cíl je nastavený příjemce, se nedá použít jako cíl operátoru &.
+
+
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+
+ Argumenty InterpolatedStringHandlerArgumentAttribute nemůžou odkazovat na parametr, na kterém se atribut používá.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
index ea9a4b108bb5b..5c4c4a23cd108 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
@@ -257,6 +257,11 @@
Eine Erweiterungsmethode mit einem Empfänger kann nicht als Ziel eines &-Operators verwendet werden.
+
+
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+
+ InterpolatedStringHandlerArgumentAttribute-Argumente können nicht auf den Parameter verweisen, für den das Attribut verwendet wird.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
index 84eb3f4e34c14..1721a208a37b2 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
@@ -257,6 +257,11 @@
No se puede usar un método de extensión con un receptor como destino de un operador "&".
+
+
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+
+ Los argumentos de InterpolatedStringHandlerArgumentAttribute no pueden hacer referencia al parámetro en el que se usa el atributo.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
index 43cbc9f71c0ff..3453e677f9b85 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
@@ -257,6 +257,11 @@
Impossible d'utiliser une méthode d'extension avec un récepteur en tant que cible d'un opérateur '&'.
+
+
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+
+ Les arguments de l'attribut InterpolatedStringHandlerArgumentAttribute ne peuvent pas faire référence au paramètre sur lequel l'attribut est utilisé.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
index 6d68d0e2a28db..280fe68d0e27a 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
@@ -257,6 +257,11 @@
Non è possibile usare un metodo di estensione con un ricevitore come destinazione di un operatore '&'.
+
+
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+
+ Gli argomenti di InterpolatedStringHandlerArgumentAttribute non possono fare riferimento al parametro in cui viene usato l'attributo.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
index 6686d8170cd10..cf43686b0a572 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
@@ -257,6 +257,11 @@
レシーバーが '&' 演算子の対象となっている拡張メソッドを使用することはできません。
+
+
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+
+ InterpolatedStringHandlerArgumentAttribute 引数は、属性が使用されているパラメーターを参照できません。
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
index d9cf71f76db93..2b5bc617b8ecd 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
@@ -257,6 +257,11 @@
'&' 연산자의 대상으로 수신기가 있는 확장 메서드는 사용할 수 없습니다.
+
+
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+
+ InterpolatedStringHandlerArgumentAttribute 인수는 특성이 사용되는 매개 변수를 참조할 수 없습니다.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
index 2e03abfd4e69f..74433560dff33 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
@@ -257,6 +257,11 @@
Nie można użyć metody rozszerzenia z odbiornikiem jako elementem docelowym operatora „&”.
+
+
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+
+ Argumenty atrybutu InterpolatedStringHandlerArgumentAttribute nie mogą odwoływać się do parametru, na podstawie którego jest używany atrybut.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
index b348d4a78a1c7..4f30545b2875a 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
@@ -257,6 +257,11 @@
Não é possível usar um método de extensão com um receptor como destino de um operador '&'.
+
+
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+
+ Argumentos InterpolatedStringHandlerArgumentAttribute não podem fazer referência ao parâmetro no qual o atributo é usado.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
index 581e5a79fabaf..2ca6fb8dbd751 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
@@ -257,6 +257,11 @@
Невозможно использовать метод расширения с приемником в качестве целевого объекта оператора "&".
+
+
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+
+ Аргументы InterpolatedStringHandlerArgumentAttribute не могут ссылаться на параметр, в котором используется атрибут.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
index a9a8389af8605..8ce4eb90089d1 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
@@ -257,6 +257,11 @@
'&' operatörünün hedefi olarak alıcı içeren bir genişletme metodu kullanılamaz.
+
+
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+
+ InterpolatedStringHandlerArgumentAttribute bağımsız değişkenleri özniteliğin kullanıldığı parametreye başvuramaz.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
index d816902b21770..48cca0a62aa42 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
@@ -257,6 +257,11 @@
不可将具有接收器的扩展方法用作 "&" 运算符的目标。
+
+
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+
+ InterpolatedStringHandlerArgumentAttribute 参数不能引用在其上使用该属性的参数。
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
index cd774fac38ef1..de9a812af5bee 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
@@ -257,6 +257,11 @@
無法使用具有接收器的擴充方法作為 '&' 運算子的目標。
+
+
+ Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+
+ InterpolatedStringHandlerArgumentAttribute 引數無法參考屬性所使用的參數。
diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenFunctionPointersTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenFunctionPointersTests.cs
index 900bbe013a54a..9fd93e28050f4 100644
--- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenFunctionPointersTests.cs
+++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenFunctionPointersTests.cs
@@ -8111,6 +8111,49 @@ static void M8(T t) where T : unmanaged {}
);
}
+ [Fact, WorkItem(57025, "https://github.com/dotnet/roslyn/issues/57025")]
+ public void UnmanagedCallersOnlyRequiresNonRef_Errors()
+ {
+ var comp = CreateCompilation(new[] { @"
+using System.Runtime.InteropServices;
+class C
+{
+ [UnmanagedCallersOnly]
+ static ref int M1() => throw null;
+
+ [UnmanagedCallersOnly]
+ static ref readonly int M2() => throw null;
+
+ [UnmanagedCallersOnly]
+ static void M3(ref int o) => throw null;
+
+ [UnmanagedCallersOnly]
+ static void M4(in int o) => throw null;
+
+ [UnmanagedCallersOnly]
+ static void M5(out int o) => throw null;
+}
+", UnmanagedCallersOnlyAttribute });
+
+ comp.VerifyDiagnostics(
+ // (6,12): error CS8977: Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+ // static ref int M1() => throw null;
+ Diagnostic(ErrorCode.ERR_CannotUseRefInUnmanagedCallersOnly, "ref int").WithLocation(6, 12),
+ // (9,12): error CS8977: Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+ // static ref readonly int M2() => throw null;
+ Diagnostic(ErrorCode.ERR_CannotUseRefInUnmanagedCallersOnly, "ref readonly int").WithLocation(9, 12),
+ // (12,20): error CS8977: Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+ // static void M3(ref int o) => throw null;
+ Diagnostic(ErrorCode.ERR_CannotUseRefInUnmanagedCallersOnly, "ref int o").WithLocation(12, 20),
+ // (15,20): error CS8977: Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+ // static void M4(in int o) => throw null;
+ Diagnostic(ErrorCode.ERR_CannotUseRefInUnmanagedCallersOnly, "in int o").WithLocation(15, 20),
+ // (18,20): error CS8977: Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+ // static void M5(out int o) => throw null;
+ Diagnostic(ErrorCode.ERR_CannotUseRefInUnmanagedCallersOnly, "out int o").WithLocation(18, 20)
+ );
+ }
+
[Fact]
public void UnmanagedCallersOnlyRequiresUnmanagedTypes_Valid()
{
@@ -9471,7 +9514,13 @@ static class CExt
Diagnostic(ErrorCode.ERR_UnmanagedCallersOnlyMethodsCannotBeCalledDirectly, "ls").WithArguments("CExt.Deconstruct(S, out int, out int)").WithLocation(11, 32),
// (12,18): error CS8901: 'CExt.Deconstruct(S, out int, out int)' is attributed with 'UnmanagedCallersOnly' and cannot be called directly. Obtain a function pointer to this method.
// _ = s is (int _, int _);
- Diagnostic(ErrorCode.ERR_UnmanagedCallersOnlyMethodsCannotBeCalledDirectly, "(int _, int _)").WithArguments("CExt.Deconstruct(S, out int, out int)").WithLocation(12, 18)
+ Diagnostic(ErrorCode.ERR_UnmanagedCallersOnlyMethodsCannotBeCalledDirectly, "(int _, int _)").WithArguments("CExt.Deconstruct(S, out int, out int)").WithLocation(12, 18),
+ // (18,46): error CS8977: Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+ // public static void Deconstruct(this S s, out int i1, out int i2) => throw null;
+ Diagnostic(ErrorCode.ERR_CannotUseRefInUnmanagedCallersOnly, "out int i1").WithLocation(18, 46),
+ // (18,58): error CS8977: Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+ // public static void Deconstruct(this S s, out int i1, out int i2) => throw null;
+ Diagnostic(ErrorCode.ERR_CannotUseRefInUnmanagedCallersOnly, "out int i2").WithLocation(18, 58)
);
}
@@ -9574,7 +9623,10 @@ static class CExt
comp.VerifyDiagnostics(
// (10,29): error CS8901: 'CExt.GetPinnableReference(S)' is attributed with 'UnmanagedCallersOnly' and cannot be called directly. Obtain a function pointer to this method.
// fixed (int* i = s)
- Diagnostic(ErrorCode.ERR_UnmanagedCallersOnlyMethodsCannotBeCalledDirectly, "s").WithArguments("CExt.GetPinnableReference(S)").WithLocation(10, 29)
+ Diagnostic(ErrorCode.ERR_UnmanagedCallersOnlyMethodsCannotBeCalledDirectly, "s").WithArguments("CExt.GetPinnableReference(S)").WithLocation(10, 29),
+ // (20,19): error CS8977: Cannot use 'ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'.
+ // public static ref int GetPinnableReference(this S s) => throw null;
+ Diagnostic(ErrorCode.ERR_CannotUseRefInUnmanagedCallersOnly, "ref int").WithLocation(20, 19)
);
}