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} arguments Function 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} arguments Function 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} arguments Function 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} arguments Function 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} arguments Function 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} arguments Function 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} arguments Function 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} arguments Function 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} arguments Function 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} arguments Function 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} arguments Function 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} arguments Function 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} arguments Function 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() {