简体   繁体   中英

Is an ISymbol from different compilations considered equal in an IIncrementalGenerator

One of the stated benefits benefits of using the IIncrementalGenerator over ISourceGenerator is that different stages of the pipeline can recognize that the results of the current iteration is the same as a previous iteration and use cached results.

In order for this to work, presumably the type parameter of any IncrementalValueProvider or IncrementalValuesProvider would need to be value equatable, (as opposed to the default reference equatable) which is presumably why you see a lot of source generators implemented using record

This leads to the question, if the IncrementalValueProvider equality function includes an ISymbol representing the same semantic object, will they be considered equal for the purposes of the caching comparison during different iterations of the pipeline?

Would it be better to just forgo referencing an ISymbol and just extract the data I need out of it (name, namespace, members, etc.)?

I have dug into the Equals functions of the Symbol implementations, and it is unclear, the base class Symbol.Equals() does use reference comparison, but this appears to be overridden in most (possibly all) of the derived classes. and a spot check of these overrides appear that they are attempting to have a value equality, but again, there are a lot to check, and even if it does end up using the reference equality check, it is also possible that the symbol references are cached between runs and even a reference equals check will be true.

Would it be better to just forgo referencing an ISymbol and just extract the data I need out of it (name, namespace, members, etc.)?

Don't include symbols in the pipeline. Not only that they will compare unequal, but they also root compilations in memory and can lead to high memory usage.

The following small snippet shows how symbols compare unequal, even if they are resulting from the exact same syntax tree:

var trees = new[] { SyntaxFactory.ParseSyntaxTree("public class C  { }") };

var comp1 = CSharpCompilation.Create(null, trees);
var s1 = comp1.GetTypeByMetadataName("C");

var comp2 = CSharpCompilation.Create(null, trees);
var s2 = comp2.GetTypeByMetadataName("C");

Console.WriteLine(s1.Equals(s2, SymbolEqualityComparer.Default));

But even if you provide your own equality comparer, rooting compilations is still an issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM