-
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
Changes from 26 commits
670fe8a
c497c73
8d16231
2ebc77a
2de4a5e
51f63a1
9b80f87
eeec801
109644b
353b988
18e13a0
c565c0c
2162208
01fff67
3775120
a5d6b93
185f693
58e9343
8618a34
c741478
1cd42ff
ae02076
0c427eb
f0e6b62
b171018
93c560e
687ca8c
7710b76
2105c5d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -312,32 +312,36 @@ SpecialType.System_Collections_Generic_IReadOnlyCollection_T or | |
int numberIncludingLastSpread; | ||
bool useKnownLength = ShouldUseKnownLength(node, out numberIncludingLastSpread); | ||
|
||
if (numberIncludingLastSpread == 0 && elements.Length == 0) | ||
if (elements.Length == 0) | ||
{ | ||
Debug.Assert(numberIncludingLastSpread == 0); | ||
// 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 commentThe reason will be displayed to describe this comment to others. Learn more.
This runs for every single-element collection expr unlike |
||
? SynthesizedReadOnlyListKind.SingleElement | ||
: SynthesizedReadOnlyListKind.Array | ||
: SynthesizedReadOnlyListKind.List; | ||
var synthesizedType = _factory.ModuleBuilderOpt.EnsureReadOnlyListTypeExists(syntax, kind: kind, _diagnostics.DiagnosticBag).Construct(typeArgs); | ||
if (synthesizedType.IsErrorType()) | ||
{ | ||
return BadExpression(node); | ||
} | ||
|
||
BoundExpression fieldValue; | ||
if (useKnownLength) | ||
BoundExpression fieldValue = kind switch | ||
{ | ||
// fieldValue = e1; | ||
SynthesizedReadOnlyListKind.SingleElement => this.VisitExpression((BoundExpression)elements.Single()), | ||
// fieldValue = new ElementType[] { e1, ..., eN }; | ||
var arrayType = ArrayTypeSymbol.CreateSZArray(_compilation.Assembly, elementType); | ||
fieldValue = CreateAndPopulateArray(node, arrayType); | ||
} | ||
else | ||
{ | ||
SynthesizedReadOnlyListKind.Array => CreateAndPopulateArray(node, ArrayTypeSymbol.CreateSZArray(_compilation.Assembly, elementType)), | ||
// fieldValue = new List<ElementType> { e1, ..., eN }; | ||
fieldValue = CreateAndPopulateList(node, elementType, elements); | ||
} | ||
SynthesizedReadOnlyListKind.List => CreateAndPopulateList(node, elementType, elements), | ||
var v => throw ExceptionUtilities.UnexpectedValue(v) | ||
}; | ||
|
||
// arrayOrList = new <>z__ReadOnlyList<ElementType>(fieldValue); | ||
arrayOrList = new BoundObjectCreationExpression(syntax, synthesizedType.Constructors.Single(), fieldValue) { WasCompilerGenerated = true }; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for more information. | ||
|
||
using System.Collections.Immutable; | ||
using System.Linq; | ||
|
||
namespace Microsoft.CodeAnalysis.CSharp.Symbols | ||
{ | ||
internal sealed class SynthesizedReadOnlyListEnumeratorConstructor : SynthesizedInstanceConstructor | ||
{ | ||
internal SynthesizedReadOnlyListEnumeratorConstructor(SynthesizedReadOnlyListEnumeratorTypeSymbol containingType, TypeSymbol parameterType) : base(containingType) | ||
{ | ||
Parameters = ImmutableArray.Create( | ||
SynthesizedParameterSymbol.Create(this, TypeWithAnnotations.Create(parameterType), ordinal: 0, RefKind.None, "item")); | ||
} | ||
|
||
public override ImmutableArray<ParameterSymbol> Parameters { get; } | ||
|
||
internal override bool SynthesizesLoweredBoundBody => true; | ||
|
||
internal override void GenerateMethodBody(TypeCompilationState compilationState, BindingDiagnosticBag diagnostics) | ||
{ | ||
SyntheticBoundNodeFactory f = new SyntheticBoundNodeFactory(this, this.GetNonNullSyntaxNode(), compilationState, diagnostics); | ||
f.CurrentFunction = this; | ||
|
||
try | ||
{ | ||
var baseConstructor = ContainingType.BaseTypeNoUseSiteDiagnostics.InstanceConstructors.Single(); | ||
var field = ContainingType.GetFieldsToEmit().First(); | ||
var parameter = Parameters.Single(); | ||
|
||
var block = f.Block( | ||
// object..ctor(); | ||
f.ExpressionStatement(f.Call(f.This(), baseConstructor)), | ||
// _item = item; | ||
f.Assignment(f.Field(f.This(), field), f.Parameter(parameter)), | ||
// return; | ||
f.Return()); | ||
f.CloseMethod(block); | ||
} | ||
catch (SyntheticBoundNodeFactory.MissingPredefinedMember ex) | ||
{ | ||
diagnostics.Add(ex.Diagnostic); | ||
f.CloseMethod(f.ThrowNull()); | ||
} | ||
} | ||
} | ||
} |
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.