Open eiriktsarpalis opened 1 year ago
Diagnostics do not have value-semantics (and arbritrary parts of our stack produce different instances of them which themselves are not comparable). You should store the data you collect to create the diagnostic in some value-record and store that in your model.
@CyrusNajmabadi This was not true in the compiler, as far as I know, which is why the abstract Diagnostic
class implements IEquatable
. If this isn't the case, what are the expected semantics for Diagnostic.Equals
?
In particular, the observed behavior is caused by this line:
I suspect that the use of ==
there, which always produces a reference-equality comparison of the message arguments, is a bug. The right thing to do was probably a.Equals(b)
, which would have done a virtual call.
This interpretation as a bug also lines up with the hash code implementation, which does a virtual call to GetHashCode
. If only reference equality mattered, a hash code implementation specific to the reference (RuntimeHelpers.GetHashCode
) could be used instead, but it wasn't.
OK, went back and looked at the pre-github source code. I'm confident this is a bug.
At first, we had arguments in SimpleDiagnostic. Then, we briefly decide to move them elsewhere in the hierarchy. Later, we decided to bring them back, in much the same form they are in right now. However, the contact added (a, b) => a == b
where it wasn't there before, despite the semantics being equivalent to the previous design. I think this was a typo, and the behavior should have matched the original version, which effectively called object.Equals
for each argument.
Not entirely sure why this landed on me -- @mavasani or @agocke does this need to be moved to the compiler?
I just encountered this bug while developing my source generator.
After some time investigating what was causing the bug in my source generator I found this bug via debugging.
I had to use a silly Dictionary<string, string>
that looks up the first instance of that string (in my used context at least) by equal strings so that the Equals
method of SimpleDiagnostc
would give me true
for two "equal" instances.
Whether or not diagnostic arguments are compared sequentially is somewhat of a moot point from the perspective of source generators. Diagnostics know their Location
s, and because Location
s know what SyntaxTree
they come from, that will change every time a file is edited. Making the message arguments compare correctly will not make Diagnostic
safe to be used in a source generator model.
Arguably, we should never have made it possible to report diagnostics from a source generator itself, but instead forced the use of analyzers to report issues. It's basically impossible to do this correctly.
Whether or not diagnostic arguments are compared sequentially is somewhat of a moot point from the perspective of source generators.
Following up from https://github.com/dotnet/runtime/issues/92509#issuecomment-2277595397, the incremental source generator API has been shipped to customers with diagnostics support, so it stands to reason that a trivial bug like this one should be fixed. It's without question substantially less expensive compared to asking sg authors to migrate all their diagnostics to separate analyzers.
Encountered the following issue when trying to debug an incremental source generator false positive:
Minimal reproduction
The issue appears to be caused by the following line:
https://github.com/dotnet/roslyn/blob/687921ffae8ad91a5464473cb1759fd463c345f2/src/Compilers/Core/Portable/Diagnostic/Diagnostic_SimpleDiagnostic.cs#L165