Skip to content

fix ref returns in expression bodied local functions#42333

Merged
AlekseyTs merged 7 commits intodotnet:masterfrom
YairHalberstadt:fix-ref-return-expression-bodied-local-functions
Mar 16, 2020
Merged

fix ref returns in expression bodied local functions#42333
AlekseyTs merged 7 commits intodotnet:masterfrom
YairHalberstadt:fix-ref-return-expression-bodied-local-functions

Conversation

@YairHalberstadt
Copy link
Copy Markdown
Contributor

Fix #42259 caused by use of incorrect binder when checking ref return type.

@YairHalberstadt YairHalberstadt requested a review from a team as a code owner March 11, 2020 06:06
RefKind refKind = RefKind.None;
ExpressionSyntax expressionSyntax = expressionBody.Expression.CheckAndUnwrapRefExpression(diagnostics, out refKind);
BindValueKind requiredValueKind = GetRequiredReturnValueKind(refKind);
ExpressionSyntax expressionSyntax = expressionBody.Expression.CheckAndUnwrapRefExpression(diagnostics, out var refKind);
Copy link
Copy Markdown
Contributor

@AlekseyTs AlekseyTs Mar 11, 2020

Choose a reason for hiding this comment

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

var [](start = 119, length = 3)

Please revert the change. At the very least the type of the out declaration should be spelled out #Closed

ExpressionSyntax expressionSyntax = expressionBody.Expression.CheckAndUnwrapRefExpression(diagnostics, out var refKind);
BindValueKind requiredValueKind = bodyBinder.GetRequiredReturnValueKind(refKind);
BoundExpression expression = bodyBinder.BindValue(expressionSyntax, diagnostics, requiredValueKind);
expression = ValidateEscape(expression, Binder.ExternalScope, refKind != RefKind.None, diagnostics);
Copy link
Copy Markdown
Contributor

@AlekseyTs AlekseyTs Mar 11, 2020

Choose a reason for hiding this comment

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

ValidateEscape [](start = 25, length = 14)

It looks like this is an instance method. Let's use bodyBinder to call it as well. Since it is very easy to make a mistake and call something on this, consider extracting a helper method, either a static local function, or a new instance method which will be called with only the right binder available to them. #Closed

CreateCompilation(source).VerifyDiagnostics(
// (4,17): warning CS8321: The local function 'M1' is declared but never used
// ref int M1(in int i) => ref i;
Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "M1").WithArguments("M1").WithLocation(4, 17),
Copy link
Copy Markdown
Contributor

@AlekseyTs AlekseyTs Mar 11, 2020

Choose a reason for hiding this comment

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

WRN_UnreferencedLocalFunction [](start = 37, length = 29)

Consider adding a #pragma to disable this warning for the test scenario. #Closed

class C {
ref int M(){
throw new System.Exception();
ref readonly int M1(in int i) => ref i;
Copy link
Copy Markdown
Contributor

@AlekseyTs AlekseyTs Mar 11, 2020

Choose a reason for hiding this comment

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

ref readonly int M1(in int i) => ref i; [](start = 8, length = 39)

It looks like these scenarios are tested above? Is there something special about this specific scenario? #Closed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is a different bug caused by the same underlying issue, namely #42259 (comment)

CreateCompilation(source).VerifyDiagnostics(
// (5,26): warning CS8321: The local function 'M1' is declared but never used
// ref readonly int M1(in int i) => ref i;
Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "M1").WithArguments("M1").WithLocation(5, 26),
Copy link
Copy Markdown
Contributor

@AlekseyTs AlekseyTs Mar 11, 2020

Choose a reason for hiding this comment

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

WRN_UnreferencedLocalFunction [](start = 41, length = 29)

Same comment, consider adding usage, or disabling the warning with pragma. #Closed

@AlekseyTs
Copy link
Copy Markdown
Contributor

AlekseyTs commented Mar 11, 2020

Done with review pass (iteration 2) #Closed

Diagnostic(ErrorCode.ERR_RefReturnReadonlyNotField, "i").WithArguments("variable", "in int").WithLocation(5, 37),
// (6,43): error CS8333: Cannot return variable 'in int' by writable reference because it is a readonly variable
// ref int M2(in int i) { return ref i; }
Diagnostic(ErrorCode.ERR_RefReturnReadonlyNotField, "i").WithArguments("variable", "in int").WithLocation(6, 43));
Copy link
Copy Markdown
Contributor

@AlekseyTs AlekseyTs Mar 12, 2020

Choose a reason for hiding this comment

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

); [](start = 132, length = 2)

Consider moving ); on a new line. Makes it easier to add/remove expected diagnostics in the future. Also, it looks like the lines we shifted to the right on an extra tab in the 3rd commit. We usually use single tab (4 spaces) offset. #Closed


return bodyBinder.CreateBlockFromExpression(expressionBody, bodyBinder.GetDeclaredLocalsForScope(expressionBody), refKind, expression, expressionSyntax, diagnostics);
// Use static local function to prevent accidentally calling instance methods on `this` instead of `bodyBinder`
static BoundBlock BindExpressionBodyAsBlockInternal(ArrowExpressionClauseSyntax expressionBody, Binder bodyBinder, DiagnosticBag diagnostics)
Copy link
Copy Markdown
Contributor

@AlekseyTs AlekseyTs Mar 12, 2020

Choose a reason for hiding this comment

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

BindExpressionBodyAsBlockInternal [](start = 30, length = 33)

We have a convention to start names of local functions with a small letter. #Closed

Copy link
Copy Markdown
Contributor

@AlekseyTs AlekseyTs left a comment

Choose a reason for hiding this comment

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

LGTM (iteration 3), modulo a style issue and formatting suggestions.

@jaredpar jaredpar added the Community The pull request was submitted by a contributor who is not a Microsoft employee. label Mar 13, 2020
Copy link
Copy Markdown
Member

@jaredpar jaredpar left a comment

Choose a reason for hiding this comment

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

Looks good module minor style issue. Can you get those cleaned up so that we can merge?

Comment thread src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs Outdated
Comment thread src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs Outdated
@YairHalberstadt
Copy link
Copy Markdown
Contributor Author

@jaredpar Done

@AlekseyTs AlekseyTs merged commit 03b8d09 into dotnet:master Mar 16, 2020
@ghost ghost added this to the Next milestone Mar 16, 2020
@AlekseyTs
Copy link
Copy Markdown
Contributor

@YairHalberstadt Thanks for the contribution.

@sharwell sharwell modified the milestones: Next, 16.6.P2 Mar 17, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area-Compilers Community The pull request was submitted by a contributor who is not a Microsoft employee.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Roslyn didn't report CS8333 for local function.

4 participants