diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
index 3778f2ba83eb6..5cd2a0ee953bf 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
@@ -5936,7 +5936,7 @@ private BoundExpression BindDynamicMemberAccess(
for (int i = 0; i < typeArgumentsWithAnnotations.Length; ++i)
{
var typeArgument = typeArgumentsWithAnnotations[i];
- if ((typeArgument.Type.IsPointerOrFunctionPointer()) || typeArgument.Type.IsRestrictedType())
+ if (typeArgument.Type.IsPointerOrFunctionPointer() || typeArgument.Type.IsRestrictedType())
{
// "The type '{0}' may not be used as a type argument"
Error(diagnostics, ErrorCode.ERR_BadTypeArgument, typeArgumentsSyntax[i], typeArgument.Type);
diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx
index 888a4fb13de80..c843076619698 100644
--- a/src/Compilers/CSharp/Portable/CSharpResources.resx
+++ b/src/Compilers/CSharp/Portable/CSharpResources.resx
@@ -6576,6 +6576,9 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
The loaded assembly references .NET Framework, which is not supported.
+
+ The type '{0}' may not be used for a field of a record.
+
A function pointer cannot be called with named arguments.
diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
index 32328f7183708..75c4b410b212f 100644
--- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
+++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
@@ -1923,8 +1923,8 @@ internal enum ErrorCode
ERR_FunctionPointersCannotBeCalledWithNamedArguments = 8905,
ERR_EqualityContractRequiresGetter = 8906,
-
WRN_UnreadRecordParameter = 8907,
+ ERR_BadFieldTypeInRecord = 8908,
#endregion diagnostics introduced for C# 9.0
diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordEquals.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordEquals.cs
index 9500036988f01..80e77faa87e1f 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordEquals.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordEquals.cs
@@ -125,14 +125,27 @@ internal override void GenerateMethodBody(TypeCompilationState compilationState,
// field1 == other.field1 && ... && fieldN == other.fieldN
var fields = ArrayBuilder.GetInstance();
+ bool foundBadField = false;
foreach (var f in ContainingType.GetFieldsToEmit())
{
if (!f.IsStatic)
{
fields.Add(f);
+
+ var parameterType = f.Type;
+ if (parameterType.IsUnsafe())
+ {
+ diagnostics.Add(ErrorCode.ERR_BadFieldTypeInRecord, f.Locations.FirstOrNone(), parameterType);
+ foundBadField = true;
+ }
+ else if (parameterType.IsRestrictedType())
+ {
+ // We'll have reported a diagnostic elsewhere (SourceMemberFieldSymbol.TypeChecks)
+ foundBadField = true;
+ }
}
}
- if (fields.Count > 0)
+ if (fields.Count > 0 && !foundBadField)
{
retExpr = MethodBodySynthesizer.GenerateFieldEquals(
retExpr,
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
index cb71497d1e483..2e172d6275fdc 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
@@ -102,6 +102,11 @@
V asynchronním příkazu foreach nejde použít kolekce dynamického typu.
+
+ The type '{0}' may not be used for a field of a record.
+ The type '{0}' may not be used for a field of a record.
+
+ Function pointer '{0}' does not take {1} argumentsFunction pointer '{0}' does not take {1} arguments
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
index 0594538956718..3d7cacdb53eeb 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
@@ -102,6 +102,11 @@
Eine Sammlung des dynamic-Typs kann in einem asynchronen foreach nicht verwendet werden.
+
+ The type '{0}' may not be used for a field of a record.
+ The type '{0}' may not be used for a field of a record.
+
+ Function pointer '{0}' does not take {1} argumentsFunction pointer '{0}' does not take {1} arguments
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
index 51d6d3ef526d6..f716d61ee6958 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
@@ -102,6 +102,11 @@
No se puede usar una colección de tipo dinámico en una instrucción foreach asincrónica.
+
+ The type '{0}' may not be used for a field of a record.
+ The type '{0}' may not be used for a field of a record.
+
+ Function pointer '{0}' does not take {1} argumentsFunction pointer '{0}' does not take {1} arguments
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
index eef1f3457ed65..6204406dff21f 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
@@ -102,6 +102,11 @@
Impossible d'utiliser une collection de type dynamique dans un foreach asynchrone
+
+ The type '{0}' may not be used for a field of a record.
+ The type '{0}' may not be used for a field of a record.
+
+ Function pointer '{0}' does not take {1} argumentsFunction pointer '{0}' does not take {1} arguments
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
index 75e909158c160..f6f9717c0428d 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
@@ -102,6 +102,11 @@
Non è possibile usare una raccolta di tipo dinamico in un'istruzione foreach asincrona
+
+ The type '{0}' may not be used for a field of a record.
+ The type '{0}' may not be used for a field of a record.
+
+ Function pointer '{0}' does not take {1} argumentsFunction pointer '{0}' does not take {1} arguments
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
index 466b81efff2c4..e3e2dea1cecc5 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
@@ -102,6 +102,11 @@
非同期 foreach では動的な型のコレクションを使用できません
+
+ The type '{0}' may not be used for a field of a record.
+ The type '{0}' may not be used for a field of a record.
+
+ Function pointer '{0}' does not take {1} argumentsFunction pointer '{0}' does not take {1} arguments
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
index bf3917fc164e1..ebaec60c21b98 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
@@ -102,6 +102,11 @@
비동기 foreach에는 동적 형식 컬렉션을 사용할 수 없습니다.
+
+ The type '{0}' may not be used for a field of a record.
+ The type '{0}' may not be used for a field of a record.
+
+ Function pointer '{0}' does not take {1} argumentsFunction pointer '{0}' does not take {1} arguments
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
index 97d7654445791..3a6e9b1f0c7df 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
@@ -102,6 +102,11 @@
Nie można użyć kolekcji typu dynamicznego w asynchronicznej instrukcji foreach
+
+ The type '{0}' may not be used for a field of a record.
+ The type '{0}' may not be used for a field of a record.
+
+ Function pointer '{0}' does not take {1} argumentsFunction pointer '{0}' does not take {1} arguments
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
index 4e472032be862..f5923b9d2f758 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
@@ -102,6 +102,11 @@
Não é possível usar uma coleção do tipo dinâmico em uma foreach assíncrona
+
+ The type '{0}' may not be used for a field of a record.
+ The type '{0}' may not be used for a field of a record.
+
+ Function pointer '{0}' does not take {1} argumentsFunction pointer '{0}' does not take {1} arguments
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
index 726348bd95265..a74196c25fc7d 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
@@ -102,6 +102,11 @@
Не удается использовать коллекцию динамического типа в асинхронном операторе foreach
+
+ The type '{0}' may not be used for a field of a record.
+ The type '{0}' may not be used for a field of a record.
+
+ Function pointer '{0}' does not take {1} argumentsFunction pointer '{0}' does not take {1} arguments
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
index 072e8efa215b0..d284345922ddc 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
@@ -102,6 +102,11 @@
Zaman uyumsuz bir foreach içinde dinamik tür koleksiyonu oluşturulamaz
+
+ The type '{0}' may not be used for a field of a record.
+ The type '{0}' may not be used for a field of a record.
+
+ Function pointer '{0}' does not take {1} argumentsFunction pointer '{0}' does not take {1} arguments
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
index 45808d7ac232e..ec8990a22eee7 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
@@ -102,6 +102,11 @@
无法在异步 foreach 中使用动态类型集合
+
+ The type '{0}' may not be used for a field of a record.
+ The type '{0}' may not be used for a field of a record.
+
+ Function pointer '{0}' does not take {1} argumentsFunction pointer '{0}' does not take {1} arguments
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
index 7533ebe7d9c91..70a7a7bed19d1 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
@@ -102,6 +102,11 @@
無法在非同步 foreach 中使用動態類型的集合
+
+ The type '{0}' may not be used for a field of a record.
+ The type '{0}' may not be used for a field of a record.
+
+ Function pointer '{0}' does not take {1} argumentsFunction pointer '{0}' does not take {1} arguments
diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs
index c931a182f377b..14bd1012c5445 100644
--- a/src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs
@@ -819,6 +819,256 @@ public void RecordProperties_10()
);
}
+ [ConditionalFact(typeof(DesktopOnly), Reason = ConditionalSkipReason.RestrictedTypesNeedDesktop)]
+ [WorkItem(48115, "https://github.com/dotnet/roslyn/issues/48115")]
+ public void RestrictedTypesAndPointerTypes()
+ {
+ var src = @"
+class C { }
+static class C2 { }
+ref struct RefLike{}
+
+unsafe record C( // 1
+ int* P1, // 2
+ int*[] P2, // 3
+ C P3,
+ delegate* P4, // 4
+ void P5, // 5
+ C2 P6, // 6, 7
+ System.ArgIterator P7, // 8
+ System.TypedReference P8, // 9
+ RefLike P9); // 10
+";
+
+ var comp = CreateCompilation(new[] { src, IsExternalInitTypeDefinition }, options: TestOptions.UnsafeDebugDll);
+ comp.VerifyEmitDiagnostics(
+ // (6,15): error CS0721: 'C2': static types cannot be used as parameters
+ // unsafe record C( // 1
+ Diagnostic(ErrorCode.ERR_ParameterIsStaticClass, "C").WithArguments("C2").WithLocation(6, 15),
+ // (7,10): error CS8908: The type 'int*' may not be used for a field of a record.
+ // int* P1, // 2
+ Diagnostic(ErrorCode.ERR_BadFieldTypeInRecord, "P1").WithArguments("int*").WithLocation(7, 10),
+ // (8,12): error CS8908: The type 'int*[]' may not be used for a field of a record.
+ // int*[] P2, // 3
+ Diagnostic(ErrorCode.ERR_BadFieldTypeInRecord, "P2").WithArguments("int*[]").WithLocation(8, 12),
+ // (10,25): error CS8908: The type 'delegate*' may not be used for a field of a record.
+ // delegate* P4, // 4
+ Diagnostic(ErrorCode.ERR_BadFieldTypeInRecord, "P4").WithArguments("delegate*").WithLocation(10, 25),
+ // (11,5): error CS1536: Invalid parameter type 'void'
+ // void P5, // 5
+ Diagnostic(ErrorCode.ERR_NoVoidParameter, "void").WithLocation(11, 5),
+ // (12,8): error CS0722: 'C2': static types cannot be used as return types
+ // C2 P6, // 6, 7
+ Diagnostic(ErrorCode.ERR_ReturnTypeIsStaticClass, "P6").WithArguments("C2").WithLocation(12, 8),
+ // (12,8): error CS0721: 'C2': static types cannot be used as parameters
+ // C2 P6, // 6, 7
+ Diagnostic(ErrorCode.ERR_ParameterIsStaticClass, "P6").WithArguments("C2").WithLocation(12, 8),
+ // (13,5): error CS0610: Field or property cannot be of type 'ArgIterator'
+ // System.ArgIterator P7, // 8
+ Diagnostic(ErrorCode.ERR_FieldCantBeRefAny, "System.ArgIterator").WithArguments("System.ArgIterator").WithLocation(13, 5),
+ // (14,5): error CS0610: Field or property cannot be of type 'TypedReference'
+ // System.TypedReference P8, // 9
+ Diagnostic(ErrorCode.ERR_FieldCantBeRefAny, "System.TypedReference").WithArguments("System.TypedReference").WithLocation(14, 5),
+ // (15,5): error CS8345: Field or auto-implemented property cannot be of type 'RefLike' unless it is an instance member of a ref struct.
+ // RefLike P9); // 10
+ Diagnostic(ErrorCode.ERR_FieldAutoPropCantBeByRefLike, "RefLike").WithArguments("RefLike").WithLocation(15, 5)
+ );
+ }
+
+ [ConditionalFact(typeof(DesktopOnly), Reason = ConditionalSkipReason.RestrictedTypesNeedDesktop)]
+ [WorkItem(48115, "https://github.com/dotnet/roslyn/issues/48115")]
+ public void RestrictedTypesAndPointerTypes_NominalMembers()
+ {
+ var src = @"
+public class C { }
+public static class C2 { }
+public ref struct RefLike{}
+
+public unsafe record C
+{
+ public int* f1; // 1
+ public int*[] f2; // 2
+ public C f3;
+ public delegate* f4; // 3
+ public void f5; // 4
+ public C2 f6; // 5
+ public System.ArgIterator f7; // 6
+ public System.TypedReference f8; // 7
+ public RefLike f9; // 8
+}
+";
+
+ var comp = CreateCompilation(new[] { src, IsExternalInitTypeDefinition }, options: TestOptions.UnsafeDebugDll);
+ comp.VerifyEmitDiagnostics(
+ // (8,17): error CS8908: The type 'int*' may not be used for a field of a record.
+ // public int* f1; // 1
+ Diagnostic(ErrorCode.ERR_BadFieldTypeInRecord, "f1").WithArguments("int*").WithLocation(8, 17),
+ // (9,19): error CS8908: The type 'int*[]' may not be used for a field of a record.
+ // public int*[] f2; // 2
+ Diagnostic(ErrorCode.ERR_BadFieldTypeInRecord, "f2").WithArguments("int*[]").WithLocation(9, 19),
+ // (11,32): error CS8908: The type 'delegate*' may not be used for a field of a record.
+ // public delegate* f4; // 3
+ Diagnostic(ErrorCode.ERR_BadFieldTypeInRecord, "f4").WithArguments("delegate*").WithLocation(11, 32),
+ // (12,12): error CS0670: Field cannot have void type
+ // public void f5; // 4
+ Diagnostic(ErrorCode.ERR_FieldCantHaveVoidType, "void").WithLocation(12, 12),
+ // (13,15): error CS0723: Cannot declare a variable of static type 'C2'
+ // public C2 f6; // 5
+ Diagnostic(ErrorCode.ERR_VarDeclIsStaticClass, "f6").WithArguments("C2").WithLocation(13, 15),
+ // (14,12): error CS0610: Field or property cannot be of type 'ArgIterator'
+ // public System.ArgIterator f7; // 6
+ Diagnostic(ErrorCode.ERR_FieldCantBeRefAny, "System.ArgIterator").WithArguments("System.ArgIterator").WithLocation(14, 12),
+ // (15,12): error CS0610: Field or property cannot be of type 'TypedReference'
+ // public System.TypedReference f8; // 7
+ Diagnostic(ErrorCode.ERR_FieldCantBeRefAny, "System.TypedReference").WithArguments("System.TypedReference").WithLocation(15, 12),
+ // (16,12): error CS8345: Field or auto-implemented property cannot be of type 'RefLike' unless it is an instance member of a ref struct.
+ // public RefLike f9; // 8
+ Diagnostic(ErrorCode.ERR_FieldAutoPropCantBeByRefLike, "RefLike").WithArguments("RefLike").WithLocation(16, 12)
+ );
+ }
+
+ [ConditionalFact(typeof(DesktopOnly), Reason = ConditionalSkipReason.RestrictedTypesNeedDesktop)]
+ [WorkItem(48115, "https://github.com/dotnet/roslyn/issues/48115")]
+ public void RestrictedTypesAndPointerTypes_NominalMembers_AutoProperties()
+ {
+ var src = @"
+public class C { }
+public static class C2 { }
+public ref struct RefLike{}
+
+public unsafe record C
+{
+ public int* f1 { get; set; } // 1
+ public int*[] f2 { get; set; } // 2
+ public C f3 { get; set; }
+ public delegate* f4 { get; set; } // 3
+ public void f5 { get; set; } // 4
+ public C2 f6 { get; set; } // 5, 6
+ public System.ArgIterator f7 { get; set; } // 6
+ public System.TypedReference f8 { get; set; } // 7
+ public RefLike f9 { get; set; } // 8
+}
+";
+
+ var comp = CreateCompilation(new[] { src, IsExternalInitTypeDefinition }, options: TestOptions.UnsafeDebugDll);
+ comp.VerifyEmitDiagnostics(
+ // (8,17): error CS8908: The type 'int*' may not be used for a field of a record.
+ // public int* f1 { get; set; } // 1
+ Diagnostic(ErrorCode.ERR_BadFieldTypeInRecord, "f1").WithArguments("int*").WithLocation(8, 17),
+ // (9,19): error CS8908: The type 'int*[]' may not be used for a field of a record.
+ // public int*[] f2 { get; set; } // 2
+ Diagnostic(ErrorCode.ERR_BadFieldTypeInRecord, "f2").WithArguments("int*[]").WithLocation(9, 19),
+ // (11,32): error CS8908: The type 'delegate*' may not be used for a field of a record.
+ // public delegate* f4 { get; set; } // 3
+ Diagnostic(ErrorCode.ERR_BadFieldTypeInRecord, "f4").WithArguments("delegate*").WithLocation(11, 32),
+ // (12,17): error CS0547: 'C.f5': property or indexer cannot have void type
+ // public void f5 { get; set; } // 4
+ Diagnostic(ErrorCode.ERR_PropertyCantHaveVoidType, "f5").WithArguments("C.f5").WithLocation(12, 17),
+ // (13,20): error CS0722: 'C2': static types cannot be used as return types
+ // public C2 f6 { get; set; } // 5, 6
+ Diagnostic(ErrorCode.ERR_ReturnTypeIsStaticClass, "get").WithArguments("C2").WithLocation(13, 20),
+ // (13,25): error CS0721: 'C2': static types cannot be used as parameters
+ // public C2 f6 { get; set; } // 5, 6
+ Diagnostic(ErrorCode.ERR_ParameterIsStaticClass, "set").WithArguments("C2").WithLocation(13, 25),
+ // (14,12): error CS0610: Field or property cannot be of type 'ArgIterator'
+ // public System.ArgIterator f7 { get; set; } // 6
+ Diagnostic(ErrorCode.ERR_FieldCantBeRefAny, "System.ArgIterator").WithArguments("System.ArgIterator").WithLocation(14, 12),
+ // (15,12): error CS0610: Field or property cannot be of type 'TypedReference'
+ // public System.TypedReference f8 { get; set; } // 7
+ Diagnostic(ErrorCode.ERR_FieldCantBeRefAny, "System.TypedReference").WithArguments("System.TypedReference").WithLocation(15, 12),
+ // (16,12): error CS8345: Field or auto-implemented property cannot be of type 'RefLike' unless it is an instance member of a ref struct.
+ // public RefLike f9 { get; set; } // 8
+ Diagnostic(ErrorCode.ERR_FieldAutoPropCantBeByRefLike, "RefLike").WithArguments("RefLike").WithLocation(16, 12)
+ );
+ }
+
+ [Fact]
+ [WorkItem(48115, "https://github.com/dotnet/roslyn/issues/48115")]
+ public void RestrictedTypesAndPointerTypes_PointerTypeAllowedForParameterAndProperty()
+ {
+ var src = @"
+class C { }
+
+unsafe record C(int* P1, int*[] P2, C P3)
+{
+ int* P1
+ {
+ get { System.Console.Write(""P1 ""); return null; }
+ init { }
+ }
+ int*[] P2
+ {
+ get { System.Console.Write(""P2 ""); return null; }
+ init { }
+ }
+ C P3
+ {
+ get { System.Console.Write(""P3 ""); return null; }
+ init { }
+ }
+
+ public unsafe static void Main()
+ {
+ var x = new C(null, null, null);
+ var (x1, x2, x3) = x;
+ System.Console.Write(""RAN"");
+ }
+}
+";
+ var comp = CreateCompilation(new[] { src, IsExternalInitTypeDefinition }, options: TestOptions.UnsafeDebugExe);
+ comp.VerifyEmitDiagnostics(
+ // (4,22): warning CS8907: Parameter 'P1' is unread. Did you forget to use it to initialize the property with that name?
+ // unsafe record C(int* P1, int*[] P2, C P3)
+ Diagnostic(ErrorCode.WRN_UnreadRecordParameter, "P1").WithArguments("P1").WithLocation(4, 22),
+ // (4,33): warning CS8907: Parameter 'P2' is unread. Did you forget to use it to initialize the property with that name?
+ // unsafe record C(int* P1, int*[] P2, C P3)
+ Diagnostic(ErrorCode.WRN_UnreadRecordParameter, "P2").WithArguments("P2").WithLocation(4, 33),
+ // (4,47): warning CS8907: Parameter 'P3' is unread. Did you forget to use it to initialize the property with that name?
+ // unsafe record C(int* P1, int*[] P2, C P3)
+ Diagnostic(ErrorCode.WRN_UnreadRecordParameter, "P3").WithArguments("P3").WithLocation(4, 47)
+ );
+ CompileAndVerify(comp, expectedOutput: "P1 P2 P3 RAN", verify: Verification.Skipped /* pointers */);
+ }
+
+ [ConditionalFact(typeof(DesktopOnly), Reason = ConditionalSkipReason.RestrictedTypesNeedDesktop)]
+ [WorkItem(48115, "https://github.com/dotnet/roslyn/issues/48115")]
+ public void RestrictedTypesAndPointerTypes_StaticFields()
+ {
+ var src = @"
+public class C { }
+public static class C2 { }
+public ref struct RefLike{}
+
+public unsafe record C
+{
+ public static int* f1;
+ public static int*[] f2;
+ public static C f3;
+ public static delegate* f4;
+ public static C2 f6; // 1
+ public static System.ArgIterator f7; // 2
+ public static System.TypedReference f8; // 3
+ public static RefLike f9; // 4
+}
+";
+
+ var comp = CreateCompilation(new[] { src, IsExternalInitTypeDefinition }, options: TestOptions.UnsafeDebugDll);
+ comp.VerifyEmitDiagnostics(
+ // (12,22): error CS0723: Cannot declare a variable of static type 'C2'
+ // public static C2 f6; // 1
+ Diagnostic(ErrorCode.ERR_VarDeclIsStaticClass, "f6").WithArguments("C2").WithLocation(12, 22),
+ // (13,19): error CS0610: Field or property cannot be of type 'ArgIterator'
+ // public static System.ArgIterator f7; // 2
+ Diagnostic(ErrorCode.ERR_FieldCantBeRefAny, "System.ArgIterator").WithArguments("System.ArgIterator").WithLocation(13, 19),
+ // (14,19): error CS0610: Field or property cannot be of type 'TypedReference'
+ // public static System.TypedReference f8; // 3
+ Diagnostic(ErrorCode.ERR_FieldCantBeRefAny, "System.TypedReference").WithArguments("System.TypedReference").WithLocation(14, 19),
+ // (15,19): error CS8345: Field or auto-implemented property cannot be of type 'RefLike' unless it is an instance member of a ref struct.
+ // public static RefLike f9; // 4
+ Diagnostic(ErrorCode.ERR_FieldAutoPropCantBeByRefLike, "RefLike").WithArguments("RefLike").WithLocation(15, 19)
+ );
+ }
+
[Fact, WorkItem(48584, "https://github.com/dotnet/roslyn/issues/48584")]
public void RecordProperties_11_UnreadPositionalParameter()
{