dotnet/roslyn

IsRecord returns false for record structs read from metadata

ericstj opened this issue · 4 comments

Version Used:
4.8.0-1.23374.10

Steps to Reproduce:

  1. Run attached sample.
    syntaxGenTest.zip

Expected Behavior:
Both record structs and record classes return IsRecord=true from both source and metadata.

Actual Behavior:
Record structs return false when read from metadata.

From Source
RecordStruct IsRecord? True
RecordClass IsRecord? True
From Metadata
RecordStruct IsRecord? False
RecordClass IsRecord? True

@ericstj I'm curious about the need to differentiate record struct from struct when it comes from metadata.

At the end of the day, I think one could write a regular struct that gets emitted exactly the same as record struct. In other words, once emitted, there is nothing in metadata that could reliably tell whether it was record struct or struct.

agreed. it matters for classes, since it affects if inheritance is allowed or not (we do not allow cross inheritance between classes and records). But for structs, it doesn't matter at all.

Well - one scenario was SyntaxGenerator giving a more succinct representation and using the record keyword. There could be others - maybe analyzers? The API exists for a reason. If it's not going to return the correct value it should at least be documented that it doesn't return true for record structs.

I can see why this is hard:

internal override bool IsRecord
{
get
{
var discardedUseSiteInfo = CompoundUseSiteInfo<AssemblySymbol>.Discarded;
return SynthesizedRecordClone.FindValidCloneMethod(this, ref discardedUseSiteInfo) != null;
}
}
// Record structs get erased when emitted to metadata
internal override bool IsRecordStruct => false;

The determination from metadata is based on probing for <Clone>$ on classes, but there is no convention to probe for on structs.

Well - one scenario was SyntaxGenerator giving a more succinct representation and using the record keyword.

It's a non-goal for SG (or the compiler for that matter) to produce enough metadata IL to always be able to get back to the original form exactly that hte user wrote.

There could be others - maybe analyzers?

Why would an analyzer care if hte original source for something was a record or not? From metadata the types are identical. So any issue with metadata for one would aply to the other.

If it's not going to return the correct value it should at least be documented that it doesn't return true for record structs.

That seems reasonable to me. We can make this a doc issue.