Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support ref field assignment in object initializers #62584

Merged
merged 9 commits into from
Jul 21, 2022
Merged

Conversation

jcouv
Copy link
Member

@jcouv jcouv commented Jul 12, 2022

Fixes #62120
Corresponding spec update: dotnet/csharplang#6277
Relates to test plan #59194

@Youssef1313
Copy link
Member

Youssef1313 commented Jul 13, 2022

Fixes #62578

Should be #62120?


In reply to: 1182886657

@jcouv jcouv force-pushed the ref-init branch 2 times, most recently from fac37f2 to e657188 Compare July 14, 2022 22:57
{
// D = { ..., <identifier> = <expr>, ... }, where D : dynamic
var memberName = ((IdentifierNameSyntax)leftSyntax).Identifier.Text;
boundLeft = new BoundDynamicObjectInitializerMember(leftSyntax, memberName, implicitReceiver.Type, initializerType, hasErrors: false);
Copy link
Member Author

@jcouv jcouv Jul 14, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 The binding of dynamic LHS was moved into BindObjectInitializerMember which handled other bindings of LHS. #Resolved

isObjectInitializer = true;
return this.ParseObjectInitializerNamedAssignment();
}
else
{
return this.ParseExpressionCore();
// <expr>
// ref <expr>
Copy link
Member Author

@jcouv jcouv Jul 14, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 This case and the dictionary initializer case above remain errors in binding, but the parser now tolerates ref (more graceful failure). #Resolved

@jcouv jcouv marked this pull request as ready for review July 15, 2022 17:56
@jcouv jcouv requested a review from a team as a code owner July 15, 2022 17:56
@jcouv jcouv requested review from cston and RikkiGibson July 15, 2022 17:57
@jcouv
Copy link
Member Author

jcouv commented Jul 18, 2022

@cston @RikkiGibson for review. Thanks

@RikkiGibson RikkiGibson self-assigned this Jul 18, 2022
@@ -4866,10 +4877,10 @@ private BoundExpression MakeBadExpressionForObjectCreation(SyntaxNode node, Type

case BoundKind.ArrayAccess:
case BoundKind.PointerElementAccess:
return boundMember;
return CheckValue(boundMember, valueKind, diagnostics);
Copy link
Member

@cston cston Jul 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CheckValue

Was this a missing case previously? #Closed

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. We were returning so bypassing the CheckValueKind check below.
Without this fix, we'd have no error in RefInitializer_OnArray or RefInitializer_OnPointer

}
if (expr is BoundArrayAccess)
{
return "array access";
Copy link
Member

@cston cston Jul 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"array access"

Do these strings need to be localized? #Closed

}
}
";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular11);
Copy link
Member

@cston cston Jul 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parseOptions: TestOptions.Regular11

Should parseOptions be dropped, to ensure we're testing with the latest language version? #Closed

";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics();
}
Copy link
Member

@cston cston Jul 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}

Consider testing assignment of in parameter:

int x = 42;

static void F(in int i)
{
    _ = new R1 { _f = ref i };
    _ = new R2 { _f = ref i };
}

ref struct R1
{
    public ref readonly int _f;
}

ref struct R2
{
    public ref int _f;
}
``` #Closed

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added RefInitializer_AssignInParameter

{
public dynamic D;
}
ref struct R
Copy link
Member

@cston cston Jul 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

R

Minor: R is unused. #Closed

{
var source = @"
int x = 42;
var r = new dynamic { field = ref x }; // 1
Copy link
Member

@cston cston Jul 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps:

int i = 42;
var r = new R<dynamic> { F = ref i };

ref struct R<T>
{
    public ref T F;
}
``` #Closed

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added RefInitializer_DynamicField

@cston
Copy link
Member

cston commented Jul 19, 2022

        comp = CreateCompilation(sourceB, references: new[] { refA }, parseOptions: TestOptions.Regular11);

I think this parseOptions: should be kept, to ensure we're not reporting an error for -langversion:11 specifically, not just the latest version.


In reply to: 1189357786


In reply to: 1189357786


Refers to: src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs:152 in 6980e20. [](commit_id = 6980e20, deletion_comment = True)

@jcouv
Copy link
Member Author

jcouv commented Jul 19, 2022

I think this parseOptions: should be kept, to ensure we're not reporting an error for -langversion:11 specifically, not just the latest version.

Yes, I've reverted that line just after pushing. It was over-eager search & replace


In reply to: 1189360227

@jcouv jcouv requested a review from cston July 19, 2022 17:27
// var r = new R() { field = ref x }; // 1
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion10, "field").WithArguments("ref fields", "11.0").WithLocation(3, 19),
// (6,15): error CS8936: Feature 'ref fields' is not available in C# 10.0. Please use language version 11.0 or greater.
// _ = r2 with { field = ref x }; // 2
Copy link
Contributor

@RikkiGibson RikkiGibson Jul 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we separately have a test which verifies the use site diagnostic when assigning by value here? #Resolved

[Fact]
public void RefInitializer_RHSTypeMustMatch()
{
// The right operand must be an expression that yields an lvalue designating a value of the same type as the left operand.
Copy link
Contributor

@RikkiGibson RikkiGibson Jul 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider testing a case where there is an implicit conversion from the RHS type to the LHS type. #Resolved

// var r = new C { a = ref x }; // 1
Diagnostic(ErrorCode.ERR_BadEventUsage, "a").WithArguments("C.a", "C").WithLocation(3, 17),
// (6,3): error CS0070: The event 'C.a' can only appear on the left hand side of += or -= (except when used from within the type 'C')
// c.a = ref x; // 2
Copy link
Contributor

@RikkiGibson RikkiGibson Jul 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might be nice to verify the behavior here on e.g. void M() { this.a = ref x; } or void M() { this.a += ref x; }. #Resolved

comp.VerifyDiagnostics(
// (3,34): error CS8173: The expression must be of type 'dynamic' because it is being assigned by reference
// var r = new R<dynamic> { F = ref i }; // 1
Diagnostic(ErrorCode.ERR_RefAssignmentMustHaveIdentityConversion, "i").WithArguments("dynamic").WithLocation(3, 34)
Copy link
Contributor

@RikkiGibson RikkiGibson Jul 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider including a success case here (e.g. dynamic i = 42). #Resolved

Diagnostic(ErrorCode.ERR_RefReturnLocal, "field = ref x").WithArguments("x").WithLocation(36, 21)
);

source = @"
Copy link
Contributor

@RikkiGibson RikkiGibson Jul 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider makign this a separate test and/or including a comment which indicates what the difference is between the two scenarios. #Resolved

Container r = default;
{
int x = 42;
var r = new Container { item = { field = ref x } }; // 1
Copy link
Contributor

@RikkiGibson RikkiGibson Jul 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider including some success cases. #Resolved


[Theory]
[InlineData(LanguageVersion.CSharp10)]
[InlineData(LanguageVersionFacts.CSharpNext)]
Copy link
Contributor

@RikkiGibson RikkiGibson Jul 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I expected use of LanguageVersion.CSharp11 here instead. #Resolved

Copy link
Member

@333fred 333fred left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM (commit 6)

}
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics();
Copy link
Member

@cston cston Jul 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the generated code run successfully? Consider running the code. #Resolved

@jcouv jcouv enabled auto-merge (squash) July 21, 2022 03:42
@jcouv jcouv merged commit e7c8471 into dotnet:main Jul 21, 2022
@ghost ghost added this to the Next milestone Jul 21, 2022
@jcouv jcouv deleted the ref-init branch July 21, 2022 06:34
333fred added a commit to 333fred/roslyn that referenced this pull request Jul 21, 2022
* upstream/main: (53 commits)
  Remove 'mangleName' parameter in PENamedTypeSymbolNonGeneric (dotnet#62813)
  Produce errors for 'partial file record' (dotnet#62686)
  [EnC] Allow renaming methods, properties, events etc. (dotnet#62364)
  Update AbstractFileHeaderDiagnosticAnalyzer.cs
  Rename file
  Make static
  Move tests
  Refactor
  Support ref field assignment in object initializers (dotnet#62584)
  Fix cref tags on generated VB's SyntaxFactory (dotnet#62578)
  Simplify
  Simplify
  Simplify
  Simplify
  Simplify
  Simplify
  Simplify
  Simplify
  Move helper methods
  Remove serialization
  ...
@allisonchou allisonchou modified the milestones: Next, 17.4 P1 Jul 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support ref field assignment in object initializers
6 participants