Skip to content

Commit c620d4a

Browse files
author
Julien Couvreur
committed
Check modifiers on record positional members
1 parent bf301b0 commit c620d4a

File tree

4 files changed

+155
-13
lines changed

4 files changed

+155
-13
lines changed

src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -986,7 +986,7 @@ private void CompileMethod(
986986
body = (BoundBlock)body.WithHasErrors();
987987
}
988988

989-
if (body != null && methodSymbol.IsConstructor())
989+
if (body != null && methodSymbol.IsConstructor() && !(methodSymbol is SynthesizedRecordConstructor))
990990
{
991991
UnassignedFieldsWalker.Analyze(_compilation, methodSymbol, body, diagsForCurrentMethod);
992992
}

src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbolBase.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ protected sealed override void MethodChecks(DiagnosticBag diagnostics)
4848
SyntaxToken arglistToken;
4949
_lazyParameters = ParameterHelpers.MakeParameters(
5050
signatureBinder, this, parameterList, out arglistToken,
51-
allowRefOrOut: true,
51+
allowRefOrOut: AllowRefOrOut,
5252
allowThis: false,
5353
addRefReadOnlyModifier: false,
5454
diagnostics: diagnostics);
@@ -72,6 +72,8 @@ protected sealed override void MethodChecks(DiagnosticBag diagnostics)
7272

7373
#nullable enable
7474
protected abstract ParameterListSyntax GetParameterList();
75+
76+
protected virtual bool AllowRefOrOut => true;
7577
#nullable restore
7678

7779
internal sealed override void AfterAddingTypeMembersChecks(ConversionsBase conversions, DiagnosticBag diagnostics)
@@ -98,7 +100,7 @@ public sealed override bool IsVararg
98100
}
99101
}
100102

101-
public sealed override bool IsImplicitlyDeclared
103+
public override bool IsImplicitlyDeclared
102104
{
103105
get
104106
{

src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordConstructor.cs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,8 @@
44

55
#nullable enable
66

7-
using System.Collections.Immutable;
87
using System.Diagnostics;
98
using Microsoft.CodeAnalysis.CSharp.Syntax;
10-
using Microsoft.CodeAnalysis.PooledObjects;
11-
using Roslyn.Utilities;
129

1310
namespace Microsoft.CodeAnalysis.CSharp.Symbols
1411
{
@@ -36,13 +33,11 @@ internal RecordDeclarationSyntax GetSyntax()
3633
return GetSyntax().PrimaryConstructorBaseType;
3734
}
3835

39-
internal override bool IsExpressionBodied
40-
{
41-
get
42-
{
43-
return false;
44-
}
45-
}
36+
protected override bool AllowRefOrOut => false;
37+
38+
internal override bool IsExpressionBodied => false;
39+
40+
public override bool IsImplicitlyDeclared => true;
4641

4742
protected override bool IsWithinExpressionOrBlockBody(int position, out int offset)
4843
{

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

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15638,5 +15638,150 @@ record R(int P1, int* P2, delegate*<int> P3);";
1563815638
p = comp.GlobalNamespace.GetTypeMember("R").GetMember<SourcePropertySymbolBase>("P3");
1563915639
Assert.True(p.HasPointerType);
1564015640
}
15641+
15642+
[Fact, WorkItem(45008, "https://github.com/dotnet/roslyn/issues/45008")]
15643+
public void PositionalMemberModifiers_RefOrOut()
15644+
{
15645+
var src = @"
15646+
record R(ref int P1, out int P2);
15647+
";
15648+
15649+
var comp = CreateCompilation(src);
15650+
comp.VerifyDiagnostics(
15651+
// (2,10): error CS0631: ref and out are not valid in this context
15652+
// record R(ref int P1, out int P2, in int P3);
15653+
Diagnostic(ErrorCode.ERR_IllegalRefParam, "ref").WithLocation(2, 10),
15654+
// (2,22): error CS0631: ref and out are not valid in this context
15655+
// record R(ref int P1, out int P2, in int P3);
15656+
Diagnostic(ErrorCode.ERR_IllegalRefParam, "out").WithLocation(2, 22)
15657+
);
15658+
}
15659+
15660+
[Fact, WorkItem(45008, "https://github.com/dotnet/roslyn/issues/45008")]
15661+
public void PositionalMemberModifiers_In()
15662+
{
15663+
var src = @"
15664+
record R(in int P1);
15665+
";
15666+
15667+
var comp = CreateCompilation(src);
15668+
comp.VerifyDiagnostics();
15669+
15670+
var actualMembers = comp.GetMember<NamedTypeSymbol>("R").GetMembers().ToTestDisplayStrings();
15671+
var expectedMembers = new[]
15672+
{
15673+
"R R.<>Clone()",
15674+
"System.Type R.EqualityContract.get",
15675+
"System.Type R.EqualityContract { get; }",
15676+
"R..ctor(in System.Int32 P1)",
15677+
"System.Int32 R.<P1>k__BackingField",
15678+
"System.Int32 R.P1.get",
15679+
"void modreq(System.Runtime.CompilerServices.IsExternalInit) R.P1.init",
15680+
"System.Int32 R.P1 { get; init; }",
15681+
"System.Int32 R.GetHashCode()",
15682+
"System.Boolean R.Equals(System.Object? obj)",
15683+
"System.Boolean R.Equals(R? )",
15684+
"R..ctor(R )",
15685+
"void R.Deconstruct(out System.Int32 P1)"
15686+
};
15687+
AssertEx.Equal(expectedMembers, actualMembers);
15688+
}
15689+
15690+
[Fact, WorkItem(45008, "https://github.com/dotnet/roslyn/issues/45008")]
15691+
public void PositionalMemberModifiers_This()
15692+
{
15693+
var src = @"
15694+
record R(this int i);
15695+
";
15696+
15697+
var comp = CreateCompilation(src);
15698+
comp.VerifyDiagnostics(
15699+
// (2,10): error CS0027: Keyword 'this' is not available in the current context
15700+
// record R(this int i);
15701+
Diagnostic(ErrorCode.ERR_ThisInBadContext, "this").WithLocation(2, 10)
15702+
);
15703+
}
15704+
15705+
[Fact, WorkItem(45008, "https://github.com/dotnet/roslyn/issues/45008")]
15706+
public void PositionalMemberModifiers_Params()
15707+
{
15708+
var src = @"
15709+
record R(params int[] Array);
15710+
";
15711+
15712+
var comp = CreateCompilation(src);
15713+
comp.VerifyDiagnostics();
15714+
15715+
var actualMembers = comp.GetMember<NamedTypeSymbol>("R").GetMembers().ToTestDisplayStrings();
15716+
var expectedMembers = new[]
15717+
{
15718+
"R R.<>Clone()",
15719+
"System.Type R.EqualityContract.get",
15720+
"System.Type R.EqualityContract { get; }",
15721+
"R..ctor(params System.Int32[] Array)",
15722+
"System.Int32[] R.<Array>k__BackingField",
15723+
"System.Int32[] R.Array.get",
15724+
"void modreq(System.Runtime.CompilerServices.IsExternalInit) R.Array.init",
15725+
"System.Int32[] R.Array { get; init; }",
15726+
"System.Int32 R.GetHashCode()",
15727+
"System.Boolean R.Equals(System.Object? obj)",
15728+
"System.Boolean R.Equals(R? )",
15729+
"R..ctor(R )",
15730+
"void R.Deconstruct(out System.Int32[] Array)"
15731+
};
15732+
AssertEx.Equal(expectedMembers, actualMembers);
15733+
}
15734+
15735+
[Fact, WorkItem(45008, "https://github.com/dotnet/roslyn/issues/45008")]
15736+
public void PositionalMemberDefaultValue()
15737+
{
15738+
var src = @"
15739+
record R(int P = 42)
15740+
{
15741+
public static void Main()
15742+
{
15743+
var r = new R();
15744+
System.Console.Write(r.P);
15745+
}
15746+
}
15747+
";
15748+
15749+
var comp = CreateCompilation(new[] { src, IsExternalInitTypeDefinition }, parseOptions: TestOptions.RegularPreview, options: TestOptions.DebugExe);
15750+
comp.VerifyDiagnostics();
15751+
CompileAndVerify(comp, expectedOutput: "42");
15752+
}
15753+
15754+
[Fact, WorkItem(45008, "https://github.com/dotnet/roslyn/issues/45008")]
15755+
public void PositionalMemberDefaultValue_AndPropertyInitializer()
15756+
{
15757+
var src = @"
15758+
record R(int P = 1)
15759+
{
15760+
public int P { get; init; } = 42;
15761+
15762+
public static void Main()
15763+
{
15764+
var r = new R();
15765+
System.Console.Write(r.P);
15766+
}
15767+
}
15768+
";
15769+
var comp = CreateCompilation(new[] { src, IsExternalInitTypeDefinition }, parseOptions: TestOptions.RegularPreview, options: TestOptions.DebugExe);
15770+
comp.VerifyDiagnostics();
15771+
var verifier = CompileAndVerify(comp, expectedOutput: "42");
15772+
15773+
verifier.VerifyIL("R..ctor(int)", @"
15774+
{
15775+
// Code size 16 (0x10)
15776+
.maxstack 2
15777+
IL_0000: ldarg.0
15778+
IL_0001: ldc.i4.s 42
15779+
IL_0003: stfld ""int R.<P>k__BackingField""
15780+
IL_0008: ldarg.0
15781+
IL_0009: call ""object..ctor()""
15782+
IL_000e: nop
15783+
IL_000f: ret
15784+
}");
15785+
}
1564115786
}
1564215787
}

0 commit comments

Comments
 (0)