Fix regression of LambdaSymbol.GetHashCode#58247
Conversation
| public override int GetHashCode() | ||
| { | ||
| return syntaxReferenceOpt.GetHashCode(); | ||
| return Syntax.GetHashCode(); |
There was a problem hiding this comment.
Thanks @Youssef1313.
This looks distinct from Equals() which is checking the fields of syntaxReferenceOpt. Should Equals() be reverted as well, to check lambda.Syntax == Syntax instead of checking syntaxReferenceOpt?
There was a problem hiding this comment.
@cston I think both should work the same. I'll go with lambda.Syntax == Syntax. It's more clear, and is the original behavior before the lambda improvements work.
| public override int GetHashCode() | ||
| { | ||
| return syntaxReferenceOpt.GetHashCode(); | ||
| return Syntax.GetHashCode(); |
There was a problem hiding this comment.
Is Syntax.GetHashCode() guaranteed to return the same value each time given that Syntax is implemented as syntaxReferenceOpt.GetSyntax()?
If we want to use the Syntax for GetHashCode() and Equals(), then LambdaSymbol should probably hold onto the SyntaxNode in a readonly field instead. Otherwise GetHashCode() and Equals() should rely on the fields of syntaxReferenceOpt rather than syntaxReferenceOpt.GetSyntax().
For the latter approach, perhaps:
public override int GetHashCode()
{
return Hash.Combine(
syntaxReferenceOpt.SyntaxTree.GetHashCode(),
syntaxReferenceOpt.Span.GetHashCode());
}There was a problem hiding this comment.
@cston From the unit test, it seems to be working as expected. But I'm okay with either holding Syntax as a _syntax field, or implementing it using SyntaxReference.SyntaxTree|Span.
| public override int GetHashCode() | ||
| { | ||
| return syntaxReferenceOpt.GetHashCode(); | ||
| return Syntax.GetHashCode(); |
There was a problem hiding this comment.
I assume this is where the root cause of the problem was. SyntaxReference uses reference equality, therefore distinct syntax references almost always have different hash code. If this is correct, then I think we should simply align this implementation with the original implementation of Equals. I.e. combine hash codes of the tree and span and revert changes to the Equals. #Closed
There was a problem hiding this comment.
@AlekseyTs It was exactly my intention to keep the original implementation. The changes that used the tree and the span along the GetHashCode change were all introduced in #52178. This simply reverts this small portion of #52178. I'm okay with any of the suggested approaches by you or @cston
I just wanted to point out to #52178 since this is what took me this way.
There was a problem hiding this comment.
It was exactly my intention to keep the original implementation.
When I said "original", I meant "original" in context of this PR. And the suggestion to revert Equals is also in context of changes made in this PR.
There was a problem hiding this comment.
To clarify. I think that we shouldn't change Equals in this PR and should simply align implementation of GetHashCode with what Equals is doing.
There was a problem hiding this comment.
@AlekseyTs Thanks. Fixed.
My initial thought was to keep the implementation that has been working for years, but I can also see this is not necessarily correct (ie, it may have changed for a good reason).
Though for this PR, it's likely both implementations will work equivalently anyway, so keeping Equals as-is and do minimal change in GetHashCode does make more sense.
Thanks again :)
|
Done with review pass (commit 2) |
| public override int GetHashCode() | ||
| { | ||
| return syntaxReferenceOpt.GetHashCode(); | ||
| return HashCode.Combine(syntaxReferenceOpt.SyntaxTree, syntaxReferenceOpt.Span); |
|
Done with review pass (commit 3). |
|
It looks like there are related test failures with distinct For instance, var q = from i in new int[] { 4, 5 } where /*pos*/which results in LambdaSymbols for the The simplest solution may be to add back the |
I do not think going back to an extra field is necessary. The correctness problem in the |
Let's add back the @Youssef1313, please add back |
Can the Refers to: src/Compilers/CSharp/Portable/Symbols/Source/LambdaSymbol.cs:268 in a8122f7. [](commit_id = a8122f7, deletion_comment = False) |
| var syntaxRefs = lambdas.SelectAsArray(l => l.SyntaxRef); | ||
| Assert.Equal(syntaxRefs[0].Span, syntaxRefs[1].Span); | ||
| Assert.NotEqual(lambdas[0], lambdas[1]); | ||
| } |
There was a problem hiding this comment.
@Youssef1313, it looks like a couple of namespaces are missing:
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.Operations;There was a problem hiding this comment.
That's what happens when I edit via GitHub directly 😄
| var lambdas = operation.Descendants().OfType<AnonymousFunctionOperation>(). | ||
| Select(op => op.Symbol.GetSymbol<LambdaSymbol>()).ToImmutableArray(); | ||
| Assert.Equal(2, lambdas.Length); | ||
| var syntaxRefs = lambdas.SelectAsArray(l => l.SyntaxRef); |
|
@Youssef1313 Thank you for the contribution. |
…rations * upstream/main: (87 commits) Add support for nullable analysis in interpolated string handler constructors (dotnet#57780) Record list-patterns and newlines in interpolations as done (dotnet#58250) Swithc to acquiring the component model on a BG thread. Fix failure to propagate cancellation token [main] Update dependencies from dotnet/arcade (dotnet#58327) Change PROTOTYPE to issue reference (dotnet#58336) Resolve PROTOTYPE comments in param null checking (dotnet#58324) Address various minor param-nullchecking issues (dotnet#58321) Nullable enable GetTypeByMetadataName (dotnet#58317) Support CodeClass2.Parts returning parts in source generated files Allow the FileCodeModel.Parent to be null Ensure the CodeModel tests are using VisualStudioWorkspaceImpl Fix the bad words in TestDeepAlternation Fix regression in Equals/GetHashCode of LambdaSymbol. (dotnet#58247) Support "Enable nullable reference types" from disable keyword Support "Enable nullable reference types" from restore keyword Support "Enable nullable reference types" on the entire directive Add comment Remove descriptor Update src/Workspaces/Remote/ServiceHub/Services/SemanticClassification/RemoteSemanticClassificationService.cs ...
Fixes #58226