-
Notifications
You must be signed in to change notification settings - Fork 4k
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
Collection expressions: synthesize single-element list type for IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T> #71147
Conversation
@cston I'd like a review pass on this before I add tests and check well-known members. The enumerator should probably be a nested type.. is there a sample I can follow to make it so? or it's ok for it to be top-level? |
Awesome!! |
...Portable/Symbols/Synthesized/ReadOnlyListType/SynthesizedReadOnlyListEnumeratorTypeSymbol.cs
Show resolved
Hide resolved
...rs/CSharp/Portable/Symbols/Synthesized/ReadOnlyListType/SynthesizedReadOnlyListTypeSymbol.cs
Outdated
Show resolved
Hide resolved
...rs/CSharp/Portable/Symbols/Synthesized/ReadOnlyListType/SynthesizedReadOnlyListTypeSymbol.cs
Show resolved
Hide resolved
Thanks @alrz, the changes so far LGTM!
I agree, the enumerator type should probably be a nested type. I don't know if we have an example of a nested synthesized type, but perhaps the following changes are needed:
|
thanks for the heads up. I haven't started checking well-known members yet so it won't. I will sync once that PR goes in. btw, would this interact with the planned yield-like codegen (from #68785)? also I was wondering what would it take to remove |
Most likely yes :)
I would be fine with synthesizing empty singleton types. :) But, frankly, we likely should just use the known Array.Empty singleton for these instead. |
# Conflicts: # src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs # src/Compilers/CSharp/Portable/Symbols/Synthesized/ReadOnlyListType/SynthesizedReadOnlyListTypeSymbol.cs
src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs
Outdated
Show resolved
Hide resolved
I'm assuming there's a reason that both roslyn/runtime have a special type for this. Maybe saving a tiny bit of memory? |
Having one actual object exist and be pointed to by literally millions of locations in memory is good :) |
@cston @dotnet/roslyn-compiler for review, thanks. |
@dotnet/roslyn-compiler for a second review, thanks. |
1 similar comment
@dotnet/roslyn-compiler for a second review, thanks. |
@333fred, @RikkiGibson, @dotnet/roslyn-compiler, for a second review, thanks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done review pass
@@ -308,32 +308,36 @@ SpecialType.System_Collections_Generic_IReadOnlyCollection_T or | |||
int numberIncludingLastSpread; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know you didn't name this variable, but... number of what? We need to rename this for clarity. If you want to do it now, go for it, if not we can do it in a follow up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tried lastSpreadIndex
here 57dc299 but that's more than a rename. I'll leave it out of this PR.
...rs/CSharp/Portable/Symbols/Synthesized/ReadOnlyListType/SynthesizedReadOnlyListTypeSymbol.cs
Outdated
Show resolved
Hide resolved
# Conflicts: # src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs
// arrayOrList = Array.Empty<ElementType>(); | ||
arrayOrList = CreateEmptyArray(syntax, ArrayTypeSymbol.CreateSZArray(_compilation.Assembly, elementType)); | ||
} | ||
else | ||
{ | ||
var typeArgs = ImmutableArray.Create(elementType); | ||
var synthesizedType = _factory.ModuleBuilderOpt.EnsureReadOnlyListTypeExists(syntax, hasKnownLength: useKnownLength, _diagnostics.DiagnosticBag).Construct(typeArgs); | ||
var kind = useKnownLength | ||
? numberIncludingLastSpread == 0 && elements.Length == 1 && SynthesizedReadOnlyListTypeSymbol.CanCreateSingleElement(_compilation) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CanCreateSingleElement
This runs for every single-element collection expr unlike SynthesizedReadOnlyListTypeSymbol.Create
. Not sure if this matters but I think we can detect this in EnsureReadOnlyListTypeExists
and downgrade instead of checking each time, although that would only optimize the happy path.
Thanks @alrz! |
Contributes to #68785