Skip to content

Commit a9fe12d

Browse files
committed
Feedback
1 parent 3a7a6d5 commit a9fe12d

File tree

3 files changed

+111
-149
lines changed

3 files changed

+111
-149
lines changed

docs/compilers/CSharp/Compiler Breaking Changes - DotNet 10.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ public class EmbeddedAttribute : Attribute {}
196196

197197
## `record` and `record struct` types cannot define pointer type members, even when providing their own Equals implementations
198198

199-
PROTOTYPE: Figure what version this is going into
199+
***Introduced in Visual Studio 2022 version 17.14***
200200

201201
***Introduced in Visual Studio 2022 version 17.14***
202202

@@ -206,7 +206,7 @@ However, this was not enforced correctly when the `record class` or `record stru
206206
The compiler now correctly forbids this.
207207

208208
```cs
209-
unsafe record struct R1(
209+
unsafe record struct R(
210210
int* P // Previously fine, now CS8908
211211
)
212212
{

src/Compilers/CSharp/Test/Emit3/Semantics/RecordTests.cs

+41-91
Original file line numberDiff line numberDiff line change
@@ -1223,87 +1223,33 @@ class P1 { }
12231223
);
12241224
}
12251225

1226-
[Fact]
1226+
[Theory, CombinatorialData]
12271227
[WorkItem(48115, "https://github.com/dotnet/roslyn/issues/48115")]
12281228
[WorkItem("https://github.com/dotnet/roslyn/issues/66312")]
1229-
public void RestrictedTypesAndPointerTypes()
1230-
{
1231-
var src = @"
1232-
class C<T> { }
1233-
static class C2 { }
1234-
ref struct RefLike{}
1235-
1236-
unsafe record C(
1237-
int* P1, // 1
1238-
int*[] P2,
1239-
C<int*[]> P3,
1240-
delegate*<int, int> P4, // 2
1241-
void P5, // 3
1242-
C2 P6, // 4, 5
1243-
System.ArgIterator P7, // 6
1244-
System.TypedReference P8, // 7
1245-
RefLike P9, // 8
1246-
delegate*<void>[] P10);
1247-
1248-
";
1249-
1250-
var comp = CreateCompilation(new[] { src, IsExternalInitTypeDefinition }, options: TestOptions.UnsafeDebugDll, targetFramework: TargetFramework.Mscorlib461);
1251-
DiagnosticDescription[] expected = [
1252-
// 0.cs(7,5): error CS8908: The type 'int*' may not be used for a field of a record.
1253-
// int* P1, // 1
1254-
Diagnostic(ErrorCode.ERR_BadFieldTypeInRecord, "int*").WithArguments("int*").WithLocation(7, 5),
1255-
// 0.cs(10,5): error CS8908: The type 'delegate*<int, int>' may not be used for a field of a record.
1256-
// delegate*<int, int> P4, // 2
1257-
Diagnostic(ErrorCode.ERR_BadFieldTypeInRecord, "delegate*<int, int>").WithArguments("delegate*<int, int>").WithLocation(10, 5),
1258-
// 0.cs(11,5): error CS1536: Invalid parameter type 'void'
1259-
// void P5, // 3
1260-
Diagnostic(ErrorCode.ERR_NoVoidParameter, "void").WithLocation(11, 5),
1261-
// 0.cs(12,5): error CS0721: 'C2': static types cannot be used as parameters
1262-
// C2 P6, // 4, 5
1263-
Diagnostic(ErrorCode.ERR_ParameterIsStaticClass, "C2").WithArguments("C2").WithLocation(12, 5),
1264-
// 0.cs(12,5): error CS0722: 'C2': static types cannot be used as return types
1265-
// C2 P6, // 4, 5
1266-
Diagnostic(ErrorCode.ERR_ReturnTypeIsStaticClass, "C2").WithArguments("C2").WithLocation(12, 5),
1267-
// 0.cs(13,5): error CS0610: Field or property cannot be of type 'ArgIterator'
1268-
// System.ArgIterator P7, // 6
1269-
Diagnostic(ErrorCode.ERR_FieldCantBeRefAny, "System.ArgIterator").WithArguments("System.ArgIterator").WithLocation(13, 5),
1270-
// 0.cs(14,5): error CS0610: Field or property cannot be of type 'TypedReference'
1271-
// System.TypedReference P8, // 7
1272-
Diagnostic(ErrorCode.ERR_FieldCantBeRefAny, "System.TypedReference").WithArguments("System.TypedReference").WithLocation(14, 5),
1273-
// 0.cs(15,5): error CS8345: Field or auto-implemented property cannot be of type 'RefLike' unless it is an instance member of a ref struct.
1274-
// RefLike P9, // 8
1275-
Diagnostic(ErrorCode.ERR_FieldAutoPropCantBeByRefLike, "RefLike").WithArguments("RefLike").WithLocation(15, 5)];
1276-
1277-
comp.VerifyDiagnostics(expected);
1278-
comp.VerifyEmitDiagnostics(expected);
1279-
}
1280-
1281-
[Fact]
1282-
[WorkItem(48115, "https://github.com/dotnet/roslyn/issues/48115")]
1283-
[WorkItem("https://github.com/dotnet/roslyn/issues/66312")]
1284-
public void RestrictedTypesAndPointerTypes_WithEquals()
1285-
{
1286-
var src = @"
1287-
class C<T> { }
1288-
static class C2 { }
1289-
ref struct RefLike{}
1290-
1291-
unsafe record C(
1292-
int* P1, // 1
1293-
int*[] P2,
1294-
C<int*[]> P3,
1295-
delegate*<int, int> P4, // 2
1296-
void P5, // 3
1297-
C2 P6, // 4, 5
1298-
System.ArgIterator P7, // 6
1299-
System.TypedReference P8, // 7
1300-
RefLike P9, // 8
1301-
delegate*<void>[] P10)
1302-
{
1303-
public virtual bool Equals(C c) => true;
1304-
public override int GetHashCode() => 0;
1305-
}
1306-
";
1229+
public void RestrictedTypesAndPointerTypes(bool withEquals)
1230+
{
1231+
var src = $$"""
1232+
1233+
class C<T> { }
1234+
static class C2 { }
1235+
ref struct RefLike{}
1236+
1237+
unsafe record C(
1238+
int* P1, // 1
1239+
int*[] P2,
1240+
C<int*[]> P3,
1241+
delegate*<int, int> P4, // 2
1242+
void P5, // 3
1243+
C2 P6, // 4, 5
1244+
System.ArgIterator P7, // 6
1245+
System.TypedReference P8, // 7
1246+
RefLike P9, // 8
1247+
delegate*<void>[] P10)
1248+
{
1249+
{{(withEquals ? "public virtual bool Equals(C c) => true;" : "")}}
1250+
{{(withEquals ? "public override int GetHashCode() => 0;" : "")}}
1251+
}
1252+
""";
13071253

13081254
var comp = CreateCompilation(new[] { src, IsExternalInitTypeDefinition }, options: TestOptions.UnsafeDebugDll, targetFramework: TargetFramework.Mscorlib461);
13091255
DiagnosticDescription[] expected = [
@@ -1401,6 +1347,7 @@ public ref struct RefLike{}
14011347
public unsafe record C
14021348
{
14031349
public int* f1 { get; set; } // 1
1350+
public int* f1_a { get => field; set; } // 1
14041351
public int*[] f2 { get; set; }
14051352
public C<int*[]> f3 { get; set; }
14061353
public delegate*<int, int> f4 { get; set; } // 2
@@ -1418,24 +1365,27 @@ public unsafe record C
14181365
// 0.cs(8,12): error CS8908: The type 'int*' may not be used for a field of a record.
14191366
// public int* f1 { get; set; } // 1
14201367
Diagnostic(ErrorCode.ERR_BadFieldTypeInRecord, "int*").WithArguments("int*").WithLocation(8, 12),
1421-
// 0.cs(11,12): error CS8908: The type 'delegate*<int, int>' may not be used for a field of a record.
1368+
// 0.cs(9,12): error CS8908: The type 'int*' may not be used for a field of a record.
1369+
// public int* f1_a { get => field; set; } // 1
1370+
Diagnostic(ErrorCode.ERR_BadFieldTypeInRecord, "int*").WithArguments("int*").WithLocation(9, 12),
1371+
// 0.cs(12,12): error CS8908: The type 'delegate*<int, int>' may not be used for a field of a record.
14221372
// public delegate*<int, int> f4 { get; set; } // 2
1423-
Diagnostic(ErrorCode.ERR_BadFieldTypeInRecord, "delegate*<int, int>").WithArguments("delegate*<int, int>").WithLocation(11, 12),
1424-
// 0.cs(12,17): error CS0547: 'C.f5': property or indexer cannot have void type
1373+
Diagnostic(ErrorCode.ERR_BadFieldTypeInRecord, "delegate*<int, int>").WithArguments("delegate*<int, int>").WithLocation(12, 12),
1374+
// 0.cs(13,17): error CS0547: 'C.f5': property or indexer cannot have void type
14251375
// public void f5 { get; set; } // 3
1426-
Diagnostic(ErrorCode.ERR_PropertyCantHaveVoidType, "f5").WithArguments("C.f5").WithLocation(12, 17),
1427-
// 0.cs(13,12): error CS0722: 'C2': static types cannot be used as return types
1376+
Diagnostic(ErrorCode.ERR_PropertyCantHaveVoidType, "f5").WithArguments("C.f5").WithLocation(13, 17),
1377+
// 0.cs(14,12): error CS0722: 'C2': static types cannot be used as return types
14281378
// public C2 f6 { get; set; } // 4, 5
1429-
Diagnostic(ErrorCode.ERR_ReturnTypeIsStaticClass, "C2").WithArguments("C2").WithLocation(13, 12),
1430-
// 0.cs(14,12): error CS0610: Field or property cannot be of type 'ArgIterator'
1379+
Diagnostic(ErrorCode.ERR_ReturnTypeIsStaticClass, "C2").WithArguments("C2").WithLocation(14, 12),
1380+
// 0.cs(15,12): error CS0610: Field or property cannot be of type 'ArgIterator'
14311381
// public System.ArgIterator f7 { get; set; } // 6
1432-
Diagnostic(ErrorCode.ERR_FieldCantBeRefAny, "System.ArgIterator").WithArguments("System.ArgIterator").WithLocation(14, 12),
1433-
// 0.cs(15,12): error CS0610: Field or property cannot be of type 'TypedReference'
1382+
Diagnostic(ErrorCode.ERR_FieldCantBeRefAny, "System.ArgIterator").WithArguments("System.ArgIterator").WithLocation(15, 12),
1383+
// 0.cs(16,12): error CS0610: Field or property cannot be of type 'TypedReference'
14341384
// public System.TypedReference f8 { get; set; } // 7
1435-
Diagnostic(ErrorCode.ERR_FieldCantBeRefAny, "System.TypedReference").WithArguments("System.TypedReference").WithLocation(15, 12),
1436-
// 0.cs(16,12): error CS8345: Field or auto-implemented property cannot be of type 'RefLike' unless it is an instance member of a ref struct.
1385+
Diagnostic(ErrorCode.ERR_FieldCantBeRefAny, "System.TypedReference").WithArguments("System.TypedReference").WithLocation(16, 12),
1386+
// 0.cs(17,12): error CS8345: Field or auto-implemented property cannot be of type 'RefLike' unless it is an instance member of a ref struct.
14371387
// public RefLike f9 { get; set; } // 8
1438-
Diagnostic(ErrorCode.ERR_FieldAutoPropCantBeByRefLike, "RefLike").WithArguments("RefLike").WithLocation(16, 12)];
1388+
Diagnostic(ErrorCode.ERR_FieldAutoPropCantBeByRefLike, "RefLike").WithArguments("RefLike").WithLocation(17, 12)];
14391389

14401390
comp.VerifyDiagnostics(expected);
14411391
comp.VerifyEmitDiagnostics(expected);

src/Compilers/CSharp/Test/Semantic/Semantics/RecordStructTests.cs

+68-56
Original file line numberDiff line numberDiff line change
@@ -1479,28 +1479,34 @@ record struct C9 : System.ICloneable
14791479
);
14801480
}
14811481

1482-
[Fact]
1482+
[Theory, CombinatorialData]
14831483
[WorkItem(48115, "https://github.com/dotnet/roslyn/issues/48115")]
14841484
[WorkItem("https://github.com/dotnet/roslyn/issues/66312")]
1485-
public void RestrictedTypesAndPointerTypes()
1486-
{
1487-
var src = @"
1488-
class C<T> { }
1489-
static class C2 { }
1490-
ref struct RefLike{}
1491-
1492-
unsafe record struct C(
1493-
int* P1, // 1
1494-
int*[] P2,
1495-
C<int*[]> P3,
1496-
delegate*<int, int> P4, // 2
1497-
void P5, // 3
1498-
C2 P6, // 4, 5
1499-
System.ArgIterator P7, // 6
1500-
System.TypedReference P8, // 7
1501-
RefLike P9, // 8
1502-
delegate*<void>[] P10); // 9
1503-
";
1485+
public void RestrictedTypesAndPointerTypes(bool withEquals)
1486+
{
1487+
var src = $$"""
1488+
1489+
class C<T> { }
1490+
static class C2 { }
1491+
ref struct RefLike{}
1492+
1493+
unsafe record struct C(
1494+
int* P1, // 1
1495+
int*[] P2,
1496+
C<int*[]> P3,
1497+
delegate*<int, int> P4, // 2
1498+
void P5, // 3
1499+
C2 P6, // 4, 5
1500+
System.ArgIterator P7, // 6
1501+
System.TypedReference P8, // 7
1502+
RefLike P9, // 8
1503+
delegate*<void>[] P10) // 9
1504+
{
1505+
{{(withEquals ? "public bool Equals(C c) => true;" : "")}}
1506+
{{(withEquals ? "public override int GetHashCode() => 0;" : "")}}
1507+
}
1508+
1509+
""";
15041510

15051511
var comp = CreateCompilation(new[] { src, IsExternalInitTypeDefinition }, options: TestOptions.UnsafeDebugDll, targetFramework: TargetFramework.Mscorlib461);
15061512
DiagnosticDescription[] expected = [
@@ -1536,27 +1542,29 @@ unsafe record struct C(
15361542
[WorkItem("https://github.com/dotnet/roslyn/issues/66312")]
15371543
public void RestrictedTypesAndPointerTypes_WithEquals()
15381544
{
1539-
var src = @"
1540-
class C<T> { }
1541-
static class C2 { }
1542-
ref struct RefLike{}
1545+
var src = $$"""
1546+
1547+
class C<T> { }
1548+
static class C2 { }
1549+
ref struct RefLike{}
1550+
1551+
unsafe record struct C(
1552+
int* P1, // 1
1553+
int*[] P2,
1554+
C<int*[]> P3,
1555+
delegate*<int, int> P4, // 2
1556+
void P5, // 3
1557+
C2 P6, // 4, 5
1558+
System.ArgIterator P7, // 6
1559+
System.TypedReference P8, // 7
1560+
RefLike P9, // 8
1561+
delegate*<void>[] P10)
1562+
{
1563+
public bool Equals(C c) => true;
1564+
public override int GetHashCode() => 0;
1565+
}
15431566
1544-
unsafe record struct C(
1545-
int* P1, // 1
1546-
int*[] P2,
1547-
C<int*[]> P3,
1548-
delegate*<int, int> P4, // 2
1549-
void P5, // 3
1550-
C2 P6, // 4, 5
1551-
System.ArgIterator P7, // 6
1552-
System.TypedReference P8, // 7
1553-
RefLike P9, // 8
1554-
delegate*<void>[] P10)
1555-
{
1556-
public bool Equals(C c) => true;
1557-
public override int GetHashCode() => 0;
1558-
}
1559-
";
1567+
""";
15601568

15611569
var comp = CreateCompilation(new[] { src, IsExternalInitTypeDefinition }, options: TestOptions.UnsafeDebugDll, targetFramework: TargetFramework.Mscorlib461);
15621570
DiagnosticDescription[] expected = [
@@ -1654,6 +1662,7 @@ public ref struct RefLike{}
16541662
public unsafe record struct C
16551663
{
16561664
public int* f1 { get; set; } // 1
1665+
public int* f1_a { get => field; set; } // 1
16571666
public int*[] f2 { get; set; }
16581667
public C<int*[]> f3 { get; set; }
16591668
public delegate*<int, int> f4 { get; set; } // 2
@@ -1671,24 +1680,27 @@ public unsafe record struct C
16711680
// 0.cs(8,12): error CS8908: The type 'int*' may not be used for a field of a record.
16721681
// public int* f1 { get; set; } // 1
16731682
Diagnostic(ErrorCode.ERR_BadFieldTypeInRecord, "int*").WithArguments("int*").WithLocation(8, 12),
1674-
// 0.cs(11,12): error CS8908: The type 'delegate*<int, int>' may not be used for a field of a record.
1683+
// 0.cs(9,12): error CS8908: The type 'int*' may not be used for a field of a record.
1684+
// public int* f1_a { get => field; set; } // 1
1685+
Diagnostic(ErrorCode.ERR_BadFieldTypeInRecord, "int*").WithArguments("int*").WithLocation(9, 12),
1686+
// 0.cs(12,12): error CS8908: The type 'delegate*<int, int>' may not be used for a field of a record.
16751687
// public delegate*<int, int> f4 { get; set; } // 2
1676-
Diagnostic(ErrorCode.ERR_BadFieldTypeInRecord, "delegate*<int, int>").WithArguments("delegate*<int, int>").WithLocation(11, 12),
1677-
// 0.cs(12,17): error CS0547: 'C.f5': property or indexer cannot have void type
1688+
Diagnostic(ErrorCode.ERR_BadFieldTypeInRecord, "delegate*<int, int>").WithArguments("delegate*<int, int>").WithLocation(12, 12),
1689+
// 0.cs(13,17): error CS0547: 'C.f5': property or indexer cannot have void type
16781690
// public void f5 { get; set; } // 3
1679-
Diagnostic(ErrorCode.ERR_PropertyCantHaveVoidType, "f5").WithArguments("C.f5").WithLocation(12, 17),
1680-
// 0.cs(13,12): error CS0722: 'C2': static types cannot be used as return types
1681-
// public C2 f6 { get; set; } // 4, 5
1682-
Diagnostic(ErrorCode.ERR_ReturnTypeIsStaticClass, "C2").WithArguments("C2").WithLocation(13, 12),
1683-
// 0.cs(14,12): error CS0610: Field or property cannot be of type 'ArgIterator'
1684-
// public System.ArgIterator f7 { get; set; } // 6
1685-
Diagnostic(ErrorCode.ERR_FieldCantBeRefAny, "System.ArgIterator").WithArguments("System.ArgIterator").WithLocation(14, 12),
1686-
// 0.cs(15,12): error CS0610: Field or property cannot be of type 'TypedReference'
1687-
// public System.TypedReference f8 { get; set; } // 7
1688-
Diagnostic(ErrorCode.ERR_FieldCantBeRefAny, "System.TypedReference").WithArguments("System.TypedReference").WithLocation(15, 12),
1689-
// 0.cs(16,12): error CS8345: Field or auto-implemented property cannot be of type 'RefLike' unless it is an instance member of a ref struct.
1690-
// public RefLike f9 { get; set; } // 8
1691-
Diagnostic(ErrorCode.ERR_FieldAutoPropCantBeByRefLike, "RefLike").WithArguments("RefLike").WithLocation(16, 12)];
1691+
Diagnostic(ErrorCode.ERR_PropertyCantHaveVoidType, "f5").WithArguments("C.f5").WithLocation(13, 17),
1692+
// 0.cs(14,12): error CS0722: 'C2': static types cannot be used as return types
1693+
// public C2 f6 { get; set; } // 4
1694+
Diagnostic(ErrorCode.ERR_ReturnTypeIsStaticClass, "C2").WithArguments("C2").WithLocation(14, 12),
1695+
// 0.cs(15,12): error CS0610: Field or property cannot be of type 'ArgIterator'
1696+
// public System.ArgIterator f7 { get; set; } // 5
1697+
Diagnostic(ErrorCode.ERR_FieldCantBeRefAny, "System.ArgIterator").WithArguments("System.ArgIterator").WithLocation(15, 12),
1698+
// 0.cs(16,12): error CS0610: Field or property cannot be of type 'TypedReference'
1699+
// public System.TypedReference f8 { get; set; } // 6
1700+
Diagnostic(ErrorCode.ERR_FieldCantBeRefAny, "System.TypedReference").WithArguments("System.TypedReference").WithLocation(16, 12),
1701+
// 0.cs(17,12): error CS8345: Field or auto-implemented property cannot be of type 'RefLike' unless it is an instance member of a ref struct.
1702+
// public RefLike f9 { get; set; } // 7
1703+
Diagnostic(ErrorCode.ERR_FieldAutoPropCantBeByRefLike, "RefLike").WithArguments("RefLike").WithLocation(17, 12)];
16921704
comp.VerifyDiagnostics(expected);
16931705
comp.VerifyEmitDiagnostics(expected);
16941706
}

0 commit comments

Comments
 (0)