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

Track enclosing symbol in data flow analysis, which might be a field or property. #28252

Merged
merged 2 commits into from
Jul 3, 2018

Conversation

gafter
Copy link
Member

@gafter gafter commented Jul 3, 2018

Code used to assume it was (and typed it as) a method.
Fixes #19845
Fixes #27969

@dotnet/roslyn-compiler May I please have a couple of reviews?

Customer scenario

Code containing a reference to a property in an initializer undergoes region analysis. The compiler crashes.

Bugs this fixes

Fixes #19845
Fixes #27969

Workarounds, if any

None known.

Risk

Low. This is a localized correction that widens the type of a field so that we can track the enclosing symbol when it is not a method.

Performance impact

None expected.

Is this a regression from a previous update?

Probably.

Root cause analysis

How was the bug found?

Customer reported.

Test documentation updated?

N/A

…or property.

Code used to assume it was (and typed it as) a method.
Fixes dotnet#19845
Fixes dotnet#27969
@gafter gafter added this to the 15.8 milestone Jul 3, 2018
@gafter gafter self-assigned this Jul 3, 2018
@gafter gafter requested review from agocke and a team July 3, 2018 00:23

static object Create(object name, Func<string, bool> f) => throw null;
}
");
Copy link
Member

@cston cston Jul 3, 2018

Choose a reason for hiding this comment

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

Is this test distinct from 01? #Resolved

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, it uses P instead of nameof(P).


In reply to: 199827816 [](ancestors = 199827816)

/// </summary>
protected MethodSymbol currentMethodOrLambda { get; private set; }
protected Symbol currentMember { get; private set; }
Copy link
Member

@agocke agocke Jul 3, 2018

Choose a reason for hiding this comment

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

Is it worth it to just call this CurrentSymbol? It's not necessarily a member (possibly a lambda or local function) and now it may not even be a function. This name just seems confusing.

Also, I believe our style guidelines require protected properties to be capitalized. #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.

We are more consistent in this area using lowercase spelling (e.g. topLevelMethod, nextVariableSlot). If we're going to make a change, I'd rather we not do it piecemeal.


In reply to: 199903748 [](ancestors = 199903748)

Copy link
Member

@agocke agocke Jul 3, 2018

Choose a reason for hiding this comment

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

Sounds good. #Closed

@@ -283,7 +282,7 @@ protected override ImmutableArray<PendingBranch> RemoveReturns()

protected virtual void ReportUnassignedOutParameter(ParameterSymbol parameter, SyntaxNode node, Location location)
{
if (!_requireOutParamsAssigned && topLevelMethod == currentMethodOrLambda)
if (!_requireOutParamsAssigned && topLevelMethod == (object)currentMember)
Copy link
Member

@agocke agocke Jul 3, 2018

Choose a reason for hiding this comment

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

ReferenceEquals seems clearer here. I thought our (object) pattern was only for comparing to null. #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.

The cast to object can be used whenever needed to avoid the use of the declared operator ==, but I'm happy to use ReferenceEquals here.


In reply to: 199904132 [](ancestors = 199904132)

@@ -439,7 +438,7 @@ private static bool IsCaptured(Symbol variable, MethodSymbol containingMethodOrL
currentFunction != null;
Copy link
Member

@agocke agocke Jul 3, 2018

Choose a reason for hiding this comment

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

May want to add an object cast here too. #Resolved

@gafter
Copy link
Member Author

gafter commented Jul 3, 2018

@agocke I think the changes I've just pushed address your comments.

Copy link
Member

@agocke agocke left a comment

Choose a reason for hiding this comment

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

LGTM

}
");
var dataFlowAnalysisResults = analysisResults;
Assert.Equal("x", GetSymbolNamesJoined(dataFlowAnalysisResults.VariablesDeclared));
Copy link
Member

Choose a reason for hiding this comment

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

Assert.Equal [](start = 12, length = 12)

Not related to this PR: consider adding a helper method in this test file to do the assert plus the GetSymbolNamesJoined, so that GetSymbolNamesJoined doesn't have to be repeated.

It could look like: ValidateSymbolNames("x", dataFlowAnalysisResults.VariablesDeclared)

Copy link
Member Author

Choose a reason for hiding this comment

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

Filed #28273


In reply to: 199961497 [](ancestors = 199961497)

@@ -1443,7 +1442,7 @@ private void EnterParameters(ImmutableArray<ParameterSymbol> parameters)

protected virtual void EnterParameter(ParameterSymbol parameter)
{
if (parameter.RefKind == RefKind.Out && !this.currentMethodOrLambda.IsAsync) // out parameters not allowed in async
if (parameter.RefKind == RefKind.Out && !(this.currentSymbol is MethodSymbol currentMethod && currentMethod.IsAsync)) // out parameters not allowed in async
Copy link
Member

@jcouv jcouv Jul 3, 2018

Choose a reason for hiding this comment

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

is [](start = 73, length = 2)

recursive pattern? ;-) #Resolved

Copy link
Member

@jcouv jcouv left a comment

Choose a reason for hiding this comment

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

LGTM Thanks (iteration 2)

@jcouv
Copy link
Member

jcouv commented Jul 3, 2018

@jaredpar for ask-mode approval. Thanks

@jaredpar
Copy link
Member

jaredpar commented Jul 3, 2018

approved

@gafter gafter merged commit 2868849 into dotnet:master Jul 3, 2018
333fred added a commit to 333fred/roslyn that referenced this pull request Jul 11, 2018
…atures/compiler

* dotnet/features/compiler: (137 commits)
  Actually fix tabs.
  Added back breaking changes doc.
  Addressed PR feedback.
  Track enclosing symbol in data flow analysis, which might be a field or property. (dotnet#28252)
  Change text from 'Spell check' to 'Fix typo'.
  Implement FAR for GetAwaiter methods (dotnet#28230)
  Fix typo
  Fix typo
  Fix import.
  Address PR feedback and fix failing test.
  Lower expressions of in arguments to correct temp locals (dotnet#28181)
  Move to 2.0.7 runtime
  Produce errors on ref-assignment to non-ref parameters
  Fix spelling.
  Preserve left-to-right evaluation order for dynamic compound addition and subtraction.
  inline.
  Provide a spellchecking suggestion when someone mispells a constructor.
  Typo (dotnet#28177)
  PR Comments
  Fix regression in bitness of Interactive Window host (dotnet#28006)
  ...
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.

Crash in DataFlowAnalysis ExtractMethodCodeRefactoringProvider throws on property reference in initializer
5 participants