Skip to content

Change of behavior in symbol comparison with SymbolEqualityComparer #58226

@tamasvajk

Description

@tamasvajk

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Area-CompilersuntriagedIssues and PRs which have not yet been triaged by a lead

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions