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

Change of behavior in symbol comparison with SymbolEqualityComparer #58226

Closed
tamasvajk opened this issue Dec 9, 2021 · 2 comments · Fixed by #58247
Closed

Change of behavior in symbol comparison with SymbolEqualityComparer #58226

tamasvajk opened this issue Dec 9, 2021 · 2 comments · Fixed by #58247
Labels
Area-Compilers untriaged Issues and PRs which have not yet been triaged by a lead

Comments

@tamasvajk
Copy link
Contributor

Version Used:
Microsoft.CodeAnalysis.CSharp nuget package version 3.10.0 and 3.11.0

Steps to Reproduce:
The following code behaves differently on version 3.10.0 and 3.11.0

using System;
using System.Linq;
using System.Collections.Generic;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

var code = @"
using System.Linq;

M1(args => string.Join("" "", args.Select(a => a.ToString())));
void M1<TResult>(Func<object?[], TResult>? f) { }";

var compilation = CSharpCompilation.Create(null)
    .AddSyntaxTrees(SyntaxFactory.ParseSyntaxTree(code))
    .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location));

var tree = compilation.SyntaxTrees.Single();
var lambdaSyntax = tree.GetRoot().DescendantNodes().OfType<SimpleLambdaExpressionSyntax>().First();
var semanticModel1 = compilation.GetSemanticModel(tree);
var semanticModel2 = compilation.GetSemanticModel(tree);

var lambdaSymbol = (IMethodSymbol)semanticModel1.GetSymbolInfo(lambdaSyntax).Symbol;
var p1 = lambdaSymbol.Parameters.Single();

var p2 = semanticModel2.GetDeclaredSymbol(lambdaSyntax.Parameter);

Console.WriteLine(p1.Equals(p2));                                // 3.10.0: True  | 3.11.0: True
Console.WriteLine(p1 == p2);                                     // 3.10.0: False | 3.11.0: False
Console.WriteLine(SymbolEqualityComparer.Default.Equals(p1, p2));// 3.10.0: True  | 3.11.0: True

Console.WriteLine(p1.GetHashCode() == p2.GetHashCode());         // 3.10.0: True  | 3.11.0: False <- DIFFERS
var s = new HashSet<ISymbol>(SymbolEqualityComparer.Default);
s.Add(p1);
Console.WriteLine(s.Contains(p2));                               // 3.10.0: True  | 3.11.0: False <- DIFFERS

Expected Behavior:
I expected s.Contains(p2) to be true on the last line. This is also the suggested behavior by dotnet/roslyn-analyzers#4568.

@dotnet-issue-labeler dotnet-issue-labeler bot added Area-Compilers untriaged Issues and PRs which have not yet been triaged by a lead labels Dec 9, 2021
@Youssef1313
Copy link
Member

Console.WriteLine(p1.GetHashCode() == p2.GetHashCode()); // 3.10.0: True | 3.11.0: False <- DIFFERS

That should be the bug.

@jaredpar Per issue description, this is a regression that's very likely to have large effect, even in Roslyn itself:

var metadataSymbolUsed = new HashSet<ISymbol>(SymbolEqualityComparer.Default);

@Youssef1313
Copy link
Member

Youssef1313 commented Dec 10, 2021

I think regression is between these two commits:

b08653e...a5b853c

3.11.0-1.21263.2 Works.

3.11.0-1.21263.10 Doesn't work.

This line is highly suspicious:

return syntaxReferenceOpt.GetHashCode();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Compilers untriaged Issues and PRs which have not yet been triaged by a lead
Projects
None yet
2 participants