From d75c0204cace3af6dedb98bd4527832f71c883f3 Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Tue, 18 Jul 2023 11:59:22 -0700 Subject: [PATCH 01/14] Collection expressions: use inline array for ReadOnlySpan argument to builder method --- .../Portable/Binder/Binder_Expressions.cs | 2 +- .../CSharp/Portable/BoundTree/BoundNodes.xml | 1 - .../Portable/Emitter/Model/PEModuleBuilder.cs | 22 + .../Generated/BoundNodes.xml.Generated.cs | 18 +- .../LocalRewriter_CollectionExpression.cs | 95 +- .../SynthesizedInlineArrayTypeSymbol.cs | 240 ++++++ .../Semantics/CollectionExpressionTests.cs | 810 ++++++++++++------ .../Symbol/Symbols/MissingSpecialMember.cs | 1 + .../CodeGen/PrivateImplementationDetails.cs | 34 +- .../Core/Portable/WellKnownMember.cs | 1 + .../Core/Portable/WellKnownMembers.cs | 15 + .../WellKnownTypeValidationTests.vb | 2 + 12 files changed, 938 insertions(+), 303 deletions(-) create mode 100644 src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInlineArrayTypeSymbol.cs diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index a880b0ded9dd2..685ffeb66fdef 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -4729,7 +4729,7 @@ private BoundExpression BindCollectionExpression(CollectionExpressionSyntax synt { builder.Add(bindElement(element, diagnostics)); } - return new BoundUnconvertedCollectionExpression(syntax, builder.ToImmutableAndFree(), this); + return new BoundUnconvertedCollectionExpression(syntax, builder.ToImmutableAndFree()); BoundExpression bindElement(CollectionElementSyntax syntax, BindingDiagnosticBag diagnostics) { diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml b/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml index da3ecdae85db3..a4b3d444936e8 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml +++ b/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml @@ -1877,7 +1877,6 @@ - diff --git a/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs b/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs index d234b1d67673f..67fd3f9c16a75 100644 --- a/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs +++ b/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs @@ -1970,6 +1970,28 @@ internal MethodSymbol EnsureInlineArrayAsSpanExists(SyntaxNode syntaxNode, Named diagnostics); } + internal NamedTypeSymbol EnsureInlineArrayTypeExists(SyntaxNode syntaxNode, SyntheticBoundNodeFactory factory, int arrayLength, DiagnosticBag diagnostics) + { + Debug.Assert(Compilation.Assembly.RuntimeSupportsInlineArrayTypes); + + string typeName = PrivateImplementationDetails.GetInlineArrayTypeName(arrayLength); + var privateImplClass = GetPrivateImplClass(syntaxNode, diagnostics); + var typeAdapter = privateImplClass.GetType(typeName); + + if (typeAdapter is null) + { + var attributeConstructor = (MethodSymbol)factory.SpecialMember(SpecialMember.System_Runtime_CompilerServices_InlineArrayAttribute__ctor); + Debug.Assert(attributeConstructor is { }); + + var typeSymbol = new SynthesizedInlineArrayTypeSymbol(SourceModule, typeName, arrayLength, attributeConstructor); + privateImplClass.TryAddSynthesizedType(typeSymbol.GetCciAdapter()); + typeAdapter = privateImplClass.GetType(typeName)!; + } + + Debug.Assert(typeAdapter.Name == typeName); + return (NamedTypeSymbol)typeAdapter.GetInternalSymbol()!; + } + internal MethodSymbol EnsureInlineArrayAsReadOnlySpanExists(SyntaxNode syntaxNode, NamedTypeSymbol spanType, NamedTypeSymbol intType, DiagnosticBag diagnostics) { Debug.Assert(intType.SpecialType == SpecialType.System_Int32); diff --git a/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs b/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs index cc08d6d698c51..cef843334e51e 100644 --- a/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs @@ -6282,29 +6282,26 @@ public BoundObjectCreationExpression Update(MethodSymbol constructor, ImmutableA internal sealed partial class BoundUnconvertedCollectionExpression : BoundExpression { - public BoundUnconvertedCollectionExpression(SyntaxNode syntax, ImmutableArray elements, Binder binder, bool hasErrors = false) + public BoundUnconvertedCollectionExpression(SyntaxNode syntax, ImmutableArray elements, bool hasErrors = false) : base(BoundKind.UnconvertedCollectionExpression, syntax, null, hasErrors || elements.HasErrors()) { RoslynDebug.Assert(!elements.IsDefault, "Field 'elements' cannot be null (use Null=\"allow\" in BoundNodes.xml to remove this check)"); - RoslynDebug.Assert(binder is object, "Field 'binder' cannot be null (make the type nullable in BoundNodes.xml to remove this check)"); this.Elements = elements; - this.Binder = binder; } public new TypeSymbol? Type => base.Type; public ImmutableArray Elements { get; } - public Binder Binder { get; } [DebuggerStepThrough] public override BoundNode? Accept(BoundTreeVisitor visitor) => visitor.VisitUnconvertedCollectionExpression(this); - public BoundUnconvertedCollectionExpression Update(ImmutableArray elements, Binder binder) + public BoundUnconvertedCollectionExpression Update(ImmutableArray elements) { - if (elements != this.Elements || binder != this.Binder) + if (elements != this.Elements) { - var result = new BoundUnconvertedCollectionExpression(this.Syntax, elements, binder, this.HasErrors); + var result = new BoundUnconvertedCollectionExpression(this.Syntax, elements, this.HasErrors); result.CopyAttributes(this); return result; } @@ -11569,7 +11566,7 @@ internal abstract partial class BoundTreeRewriter : BoundTreeVisitor { ImmutableArray elements = this.VisitList(node.Elements); TypeSymbol? type = this.VisitType(node.Type); - return node.Update(elements, node.Binder); + return node.Update(elements); } public override BoundNode? VisitCollectionExpression(BoundCollectionExpression node) { @@ -13782,12 +13779,12 @@ public NullabilityRewriter(ImmutableDictionary new TreeDumperNode("unconvertedCollectionExpression", null, new TreeDumperNode[] { new TreeDumperNode("elements", null, from x in node.Elements select Visit(x, null)), - new TreeDumperNode("binder", node.Binder, null), new TreeDumperNode("type", node.Type, null), new TreeDumperNode("isSuppressed", node.IsSuppressed, null), new TreeDumperNode("hasErrors", node.HasErrors, null) diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs index d61e5fd565741..7d51aa4622d4c 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs @@ -27,7 +27,7 @@ internal sealed partial class LocalRewriter case CollectionExpressionTypeKind.Span: case CollectionExpressionTypeKind.ReadOnlySpan: Debug.Assert(elementType is { }); - return VisitArrayOrSpanCollectionExpression(node, node.Type, elementType); + return VisitArrayOrSpanCollectionExpression(node, node.Type, TypeWithAnnotations.Create(elementType)); case CollectionExpressionTypeKind.CollectionBuilder: return VisitCollectionBuilderCollectionExpression(node); case CollectionExpressionTypeKind.ListInterface: @@ -37,7 +37,7 @@ internal sealed partial class LocalRewriter } } - private BoundExpression VisitArrayOrSpanCollectionExpression(BoundCollectionExpression node, TypeSymbol collectionType, TypeSymbol elementType) + private BoundExpression VisitArrayOrSpanCollectionExpression(BoundCollectionExpression node, TypeSymbol collectionType, TypeWithAnnotations elementType) { Debug.Assert(!_inExpressionLambda); @@ -50,8 +50,8 @@ private BoundExpression VisitArrayOrSpanCollectionExpression(BoundCollectionExpr Debug.Assert(collectionType.Name is "Span" or "ReadOnlySpan"); // We're constructing a Span or ReadOnlySpan rather than T[]. var spanType = (NamedTypeSymbol)collectionType; - Debug.Assert(elementType.Equals(spanType.TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0].Type, TypeCompareKind.AllIgnoreOptions)); - arrayType = ArrayTypeSymbol.CreateSZArray(_compilation.Assembly, TypeWithAnnotations.Create(elementType)); + Debug.Assert(elementType.Equals(spanType.TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0], TypeCompareKind.AllIgnoreOptions)); + arrayType = ArrayTypeSymbol.CreateSZArray(_compilation.Assembly, elementType); spanConstructor = ((MethodSymbol)_compilation.GetWellKnownTypeMember( collectionType.Name == "Span" ? WellKnownMember.System_Span_T__ctor_Array : WellKnownMember.System_ReadOnlySpan_T__ctor_Array)!).AsMember(spanType); } @@ -64,7 +64,7 @@ private BoundExpression VisitArrayOrSpanCollectionExpression(BoundCollectionExpr // The array initializer includes at least one spread element, so we'll create an intermediate List instance. // https://github.com/dotnet/roslyn/issues/68785: Avoid intermediate List if all spread elements have Length property. // https://github.com/dotnet/roslyn/issues/68785: Emit Enumerable.TryGetNonEnumeratedCount() and avoid intermediate List at runtime. - var listType = _compilation.GetWellKnownType(WellKnownType.System_Collections_Generic_List_T).Construct(elementType); + var listType = _compilation.GetWellKnownType(WellKnownType.System_Collections_Generic_List_T).Construct(ImmutableArray.Create(elementType)); var listToArray = ((MethodSymbol)_compilation.GetWellKnownTypeMember(WellKnownMember.System_Collections_Generic_List_T__ToArray)!).AsMember(listType); var list = VisitCollectionInitializerCollectionExpression(node, collectionType); array = _factory.Call(list, listToArray); @@ -159,16 +159,35 @@ private BoundExpression VisitCollectionBuilderCollectionExpression(BoundCollecti Debug.Assert(!_inExpressionLambda); Debug.Assert(node.Type is { }); + var syntax = node.Syntax; + var elements = node.Elements; var constructMethod = node.CollectionBuilderMethod; + Debug.Assert(constructMethod is { }); Debug.Assert(constructMethod.ReturnType.Equals(node.Type, TypeCompareKind.AllIgnoreOptions)); var spanType = (NamedTypeSymbol)constructMethod.Parameters[0].Type; Debug.Assert(spanType.OriginalDefinition.Equals(_compilation.GetWellKnownType(WellKnownType.System_ReadOnlySpan_T), TypeCompareKind.AllIgnoreOptions)); - var span = VisitArrayOrSpanCollectionExpression(node, spanType, spanType.TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0].Type); - return new BoundCall( - node.Syntax, + var elementType = spanType.TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0]; + var locals = ArrayBuilder.GetInstance(); + var sideEffects = ArrayBuilder.GetInstance(); + BoundExpression span; + + // PROTOTYPE: Check also ReadOnlySpan parameter is not [UnscopedRef]. + if (elements.Length > 0 + && !elements.Any(i => i is BoundCollectionExpressionSpreadElement) + && _compilation.Assembly.RuntimeSupportsInlineArrayTypes) + { + span = CreateAndPopulateInlineArray(syntax, elementType, elements, locals, sideEffects); + } + else + { + span = VisitArrayOrSpanCollectionExpression(node, spanType, elementType); + } + + var call = new BoundCall( + syntax, receiverOpt: null, method: constructMethod, arguments: ImmutableArray.Create(span), @@ -181,6 +200,66 @@ private BoundExpression VisitCollectionBuilderCollectionExpression(BoundCollecti defaultArguments: default, resultKind: LookupResultKind.Viable, type: constructMethod.ReturnType); + + return new BoundSequence( + syntax, + locals.ToImmutableAndFree(), + sideEffects.ToImmutableAndFree(), + call, + call.Type); + } + + private BoundExpression CreateAndPopulateInlineArray( + SyntaxNode syntax, + TypeWithAnnotations elementType, + ImmutableArray elements, + ArrayBuilder locals, + ArrayBuilder sideEffects) + { + Debug.Assert(elements.Length > 0); + Debug.Assert(_factory.ModuleBuilderOpt is { }); + Debug.Assert(_diagnostics.DiagnosticBag is { }); + Debug.Assert(_compilation.Assembly.RuntimeSupportsInlineArrayTypes); + + int arrayLength = elements.Length; + var inlineArrayType = _factory.ModuleBuilderOpt.EnsureInlineArrayTypeExists(syntax, _factory, arrayLength, _diagnostics.DiagnosticBag).Construct(ImmutableArray.Create(elementType)); + Debug.Assert(inlineArrayType.HasInlineArrayAttribute(out int inlineArrayLength) && inlineArrayLength == arrayLength); + + var intType = _factory.SpecialType(SpecialType.System_Int32); + var elementRef = _factory.ModuleBuilderOpt.EnsureInlineArrayElementRefExists(syntax, intType, _diagnostics.DiagnosticBag); + elementRef = elementRef.Construct(ImmutableArray.Create(TypeWithAnnotations.Create(inlineArrayType), elementType)); + + // Create an inline array and assign to a local. + BoundAssignmentOperator assignmentToTemp; + BoundLocal inlineArrayLocal = _factory.StoreToTemp(new BoundDefaultExpression(syntax, inlineArrayType), out assignmentToTemp, isKnownToReferToTempIfReferenceType: true); + sideEffects.Add(assignmentToTemp); + locals.Add(inlineArrayLocal.LocalSymbol); + + for (int i = 0; i < arrayLength; i++) + { + var element = VisitExpression(elements[i]); + var call = _factory.Call(null, elementRef, inlineArrayLocal, _factory.Literal(i), useStrictArgumentRefKinds: true); + var assignment = new BoundAssignmentOperator(syntax, call, element, type: call.Type) { WasCompilerGenerated = true }; + sideEffects.Add(assignment); + } + + // Get a span to the inline array. + var spanType = _factory.WellKnownType(WellKnownType.System_Span_T); // PROTOTYPE: Test missing type. + var inlineArrayAsSpan = _factory.ModuleBuilderOpt.EnsureInlineArrayAsSpanExists(syntax, spanType, intType, _diagnostics.DiagnosticBag); + inlineArrayAsSpan = inlineArrayAsSpan.Construct(ImmutableArray.Create(TypeWithAnnotations.Create(inlineArrayType), elementType)); + + spanType = spanType.Construct(ImmutableArray.Create(elementType)); + // PROTOTYPE: Test missing operator. + var spanOperator = _factory.WellKnownMethod(WellKnownMember.System_Span_T__op_Implicit_Span).AsMember(spanType); + return _factory.Call( + receiver: null, + spanOperator, + _factory.Call( + receiver: null, + inlineArrayAsSpan, + inlineArrayLocal, + _factory.Literal(arrayLength), + useStrictArgumentRefKinds: true)); } private BoundExpression MakeCollectionExpressionSpreadElement(BoundCollectionExpressionSpreadElement initializer) diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInlineArrayTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInlineArrayTypeSymbol.cs new file mode 100644 index 0000000000000..dc6cdfce9c923 --- /dev/null +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInlineArrayTypeSymbol.cs @@ -0,0 +1,240 @@ +// 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; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Runtime.InteropServices; +using Microsoft.CodeAnalysis.CSharp.Emit; +using Microsoft.CodeAnalysis.PooledObjects; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.CSharp.Symbols +{ + internal sealed class SynthesizedInlineArrayTypeSymbol : NamedTypeSymbol + { + private readonly ModuleSymbol _containingModule; + private readonly int _arrayLength; + private readonly MethodSymbol _inlineArrayAttributeConstructor; + private readonly ImmutableArray _fields; + + internal SynthesizedInlineArrayTypeSymbol(SourceModuleSymbol containingModule, string name, int arrayLength, MethodSymbol inlineArrayAttributeConstructor) + { + Debug.Assert(arrayLength > 0); + + var typeParameter = new InlineArrayTypeParameterSymbol(this); + var field = new SynthesizedFieldSymbol(this, typeParameter, "_element0"); + + _containingModule = containingModule; + _arrayLength = arrayLength; + _inlineArrayAttributeConstructor = inlineArrayAttributeConstructor; + _fields = ImmutableArray.Create(field); + Name = name; + TypeParameters = ImmutableArray.Create(typeParameter); + } + + public override int Arity => 1; + + public override ImmutableArray TypeParameters { get; } + + public override NamedTypeSymbol ConstructedFrom => this; + + public override bool MightContainExtensionMethods => false; + + public override string Name { get; } + + public override IEnumerable MemberNames => GetMembers().SelectAsArray(m => m.Name); + + public override Accessibility DeclaredAccessibility => Accessibility.Internal; + + public override bool IsSerializable => false; + + public override bool AreLocalsZeroed => true; // PROTOTYPE: Is this correct? + + public override TypeKind TypeKind => TypeKind.Struct; + + public override bool IsRefLikeType => false; + + public override bool IsReadOnly => true; + + public override Symbol? ContainingSymbol => null; + + internal override ModuleSymbol ContainingModule => _containingModule; + + public override AssemblySymbol ContainingAssembly => _containingModule.ContainingAssembly; + + public override NamespaceSymbol ContainingNamespace => _containingModule.GlobalNamespace; + + public override ImmutableArray Locations => ImmutableArray.Empty; + + public override ImmutableArray DeclaringSyntaxReferences => throw new NotImplementedException(); + + public override bool IsStatic => false; + + public override bool IsAbstract => false; + + public override bool IsSealed => true; + + internal override ImmutableArray TypeArgumentsWithAnnotationsNoUseSiteDiagnostics => GetTypeParametersAsTypeArguments(); + + internal override bool IsFileLocal => false; + + internal override FileIdentifier? AssociatedFileIdentifier => null; + + internal override bool MangleName => false; // PROTOTYPE: Is this correct? + + internal override bool HasDeclaredRequiredMembers => false; + + internal override bool HasCodeAnalysisEmbeddedAttribute => false; + + internal override bool IsInterpolatedStringHandlerType => false; + + internal override bool HasSpecialName => false; + + internal override bool IsComImport => false; + + internal override bool IsWindowsRuntimeImport => false; + + internal override bool ShouldAddWinRTMembers => false; + + internal override TypeLayout Layout => default; // PROTOTYPE: Is this correct? + + internal override CharSet MarshallingCharSet => DefaultMarshallingCharSet; + + internal override bool HasDeclarativeSecurity => false; + + internal override bool IsInterface => false; + + internal override NamedTypeSymbol? NativeIntegerUnderlyingType => null; + + internal override NamedTypeSymbol BaseTypeNoUseSiteDiagnostics => ContainingAssembly.GetSpecialType(SpecialType.System_ValueType); + + internal override bool IsRecord => false; + + internal override bool IsRecordStruct => false; + + internal override ObsoleteAttributeData? ObsoleteAttributeData => null; + + public override ImmutableArray GetMembers() => ImmutableArray.Empty; + + public override ImmutableArray GetMembers(string name) => GetMembers().WhereAsArray(m => m.Name == name); + + public override ImmutableArray GetTypeMembers() => ImmutableArray.Empty; + + public override ImmutableArray GetTypeMembers(ReadOnlyMemory name, int arity) => ImmutableArray.Empty; + + public override ImmutableArray GetTypeMembers(ReadOnlyMemory name) => ImmutableArray.Empty; + + protected override NamedTypeSymbol WithTupleDataCore(TupleExtraData newData) => throw ExceptionUtilities.Unreachable(); + + internal override NamedTypeSymbol AsNativeInteger() => throw ExceptionUtilities.Unreachable(); + + internal override ImmutableArray GetAppliedConditionalSymbols() => ImmutableArray.Empty; + + internal override AttributeUsageInfo GetAttributeUsageInfo() => default; + + internal override NamedTypeSymbol GetDeclaredBaseType(ConsList basesBeingResolved) => BaseTypeNoUseSiteDiagnostics; + + internal override ImmutableArray GetDeclaredInterfaces(ConsList basesBeingResolved) => ImmutableArray.Empty; + + internal override ImmutableArray GetEarlyAttributeDecodingMembers() => GetMembersUnordered(); + + internal override ImmutableArray GetEarlyAttributeDecodingMembers(string name) => GetMembers(name); + + internal override IEnumerable GetFieldsToEmit() => _fields; + + internal override ImmutableArray GetInterfacesToEmit() => ImmutableArray.Empty; + + internal override IEnumerable GetSecurityInformation() => SpecializedCollections.EmptyEnumerable(); + + internal override bool HasCollectionBuilderAttribute(out TypeSymbol? builderType, out string? methodName) + { + builderType = null; + methodName = null; + return false; + } + + internal override bool HasInlineArrayAttribute(out int length) + { + length = _arrayLength; + return true; + } + + internal override bool HasPossibleWellKnownCloneMethod() => false; + + internal override ImmutableArray InterfacesNoUseSiteDiagnostics(ConsList? basesBeingResolved = null) => ImmutableArray.Empty; + + internal override IEnumerable<(MethodSymbol Body, MethodSymbol Implemented)> SynthesizedInterfaceMethodImpls() => SpecializedCollections.EmptyEnumerable<(MethodSymbol Body, MethodSymbol Implemented)>(); + + internal override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder attributes) + { + base.AddSynthesizedAttributes(moduleBuilder, ref attributes); + + var compilation = _containingModule.DeclaringCompilation; + Debug.Assert(compilation is { }); + + AddSynthesizedAttribute( + ref attributes, + new SynthesizedAttributeData( + _inlineArrayAttributeConstructor, + arguments: ImmutableArray.Create(new TypedConstant(compilation.GetSpecialType(SpecialType.System_Int32), TypedConstantKind.Primitive, _arrayLength)), + namedArguments: ImmutableArray>.Empty)); + } + + private sealed class InlineArrayTypeParameterSymbol : TypeParameterSymbol + { + private readonly SynthesizedInlineArrayTypeSymbol _container; + + internal InlineArrayTypeParameterSymbol(SynthesizedInlineArrayTypeSymbol container) + { + _container = container; + } + + public override string Name => "T"; + + public override int Ordinal => 0; + + public override bool HasConstructorConstraint => false; + + public override TypeParameterKind TypeParameterKind => TypeParameterKind.Type; + + public override bool HasReferenceTypeConstraint => false; + + public override bool IsReferenceTypeFromConstraintTypes => false; + + public override bool HasNotNullConstraint => false; + + public override bool HasValueTypeConstraint => false; + + public override bool IsValueTypeFromConstraintTypes => false; + + public override bool HasUnmanagedTypeConstraint => false; + + public override VarianceKind Variance => VarianceKind.None; + + public override Symbol ContainingSymbol => _container; + + public override ImmutableArray Locations => ImmutableArray.Empty; + + public override ImmutableArray DeclaringSyntaxReferences => ImmutableArray.Empty; + + internal override bool? IsNotNullable => null; + + internal override bool? ReferenceTypeConstraintIsNullable => null; + + internal override void EnsureAllConstraintsAreResolved() + { + } + + internal override ImmutableArray GetConstraintTypes(ConsList inProgress) => ImmutableArray.Empty; + + internal override TypeSymbol GetDeducedBaseType(ConsList inProgress) => ContainingAssembly.GetSpecialType(SpecialType.System_Object); + + internal override NamedTypeSymbol GetEffectiveBaseClass(ConsList inProgress) => ContainingAssembly.GetSpecialType(SpecialType.System_Object); + + internal override ImmutableArray GetInterfaces(ConsList inProgress) => ImmutableArray.Empty; + } + } +} diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index 4f450382a0f78..be5c37c59f96c 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -5682,7 +5682,7 @@ public static MyCollection Create(ReadOnlySpan items) } } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB1 = """ @@ -5694,7 +5694,7 @@ static void Main() x.Report(); MyCollection y = F1(); y.Report(); - MyCollection z = F2(4, 5); + MyCollection z = F2(3, 4); z.Report(); } static MyCollection F0() @@ -5703,7 +5703,7 @@ static MyCollection F0() } static MyCollection F1() { - return [1, 2, 3]; + return [0, 1, 2]; } static MyCollection F2(int x, object y) { @@ -5712,7 +5712,12 @@ static MyCollection F2(int x, object y) } """; - var verifier = CompileAndVerify(new[] { sourceB1, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net70, expectedOutput: "[], [1, 2, 3], [4, 5, null], "); + var verifier = CompileAndVerify( + new[] { sourceB1, s_collectionExtensions }, + references: new[] { refA }, + targetFramework: TargetFramework.Net80, + verify: Verification.Fails, + expectedOutput: "[], [0, 1, 2], [3, 4, null], "); verifier.VerifyIL("Program.F0", """ { @@ -5728,33 +5733,64 @@ .maxstack 1 verifier.VerifyIL("Program.F1", """ { - // Code size 16 (0x10) - .maxstack 1 - IL_0000: ldtoken ".__StaticArrayInitTypeSize=12_Align=4 .4636993D3E1DA4E9D6B8F87B79E8F7C6D018580D52661950EABC3845C5897A4D4" - IL_0005: call "System.ReadOnlySpan System.Runtime.CompilerServices.RuntimeHelpers.CreateSpan(System.RuntimeFieldHandle)" - IL_000a: call "MyCollection MyCollectionBuilder.Create(System.ReadOnlySpan)" - IL_000f: ret + // Code size 57 (0x39) + .maxstack 2 + .locals init ($InlineArray3 V_0) + IL_0000: ldloca.s V_0 + IL_0002: initobj "$InlineArray3" + IL_0008: ldloca.s V_0 + IL_000a: ldc.i4.0 + IL_000b: call "InlineArrayElementRef<$InlineArray3, int>(ref $InlineArray3, int)" + IL_0010: ldc.i4.0 + IL_0011: stind.i4 + IL_0012: ldloca.s V_0 + IL_0014: ldc.i4.1 + IL_0015: call "InlineArrayElementRef<$InlineArray3, int>(ref $InlineArray3, int)" + IL_001a: ldc.i4.1 + IL_001b: stind.i4 + IL_001c: ldloca.s V_0 + IL_001e: ldc.i4.2 + IL_001f: call "InlineArrayElementRef<$InlineArray3, int>(ref $InlineArray3, int)" + IL_0024: ldc.i4.2 + IL_0025: stind.i4 + IL_0026: ldloca.s V_0 + IL_0028: ldc.i4.3 + IL_0029: call "InlineArrayAsSpan<$InlineArray3, int>(ref $InlineArray3, int)" + IL_002e: call "System.ReadOnlySpan System.Span.op_Implicit(System.Span)" + IL_0033: call "MyCollection MyCollectionBuilder.Create(System.ReadOnlySpan)" + IL_0038: ret } """); verifier.VerifyIL("Program.F2", """ { - // Code size 30 (0x1e) - .maxstack 4 - IL_0000: ldc.i4.3 - IL_0001: newarr "object" - IL_0006: dup - IL_0007: ldc.i4.0 - IL_0008: ldarg.0 - IL_0009: box "int" - IL_000e: stelem.ref - IL_000f: dup - IL_0010: ldc.i4.1 - IL_0011: ldarg.1 - IL_0012: stelem.ref - IL_0013: newobj "System.ReadOnlySpan..ctor(object[])" - IL_0018: call "MyCollection MyCollectionBuilder.Create(System.ReadOnlySpan)" - IL_001d: ret + // Code size 62 (0x3e) + .maxstack 2 + .locals init ($InlineArray3 V_0) + IL_0000: ldloca.s V_0 + IL_0002: initobj "$InlineArray3" + IL_0008: ldloca.s V_0 + IL_000a: ldc.i4.0 + IL_000b: call "InlineArrayElementRef<$InlineArray3, object>(ref $InlineArray3, int)" + IL_0010: ldarg.0 + IL_0011: box "int" + IL_0016: stind.ref + IL_0017: ldloca.s V_0 + IL_0019: ldc.i4.1 + IL_001a: call "InlineArrayElementRef<$InlineArray3, object>(ref $InlineArray3, int)" + IL_001f: ldarg.1 + IL_0020: stind.ref + IL_0021: ldloca.s V_0 + IL_0023: ldc.i4.2 + IL_0024: call "InlineArrayElementRef<$InlineArray3, object>(ref $InlineArray3, int)" + IL_0029: ldnull + IL_002a: stind.ref + IL_002b: ldloca.s V_0 + IL_002d: ldc.i4.3 + IL_002e: call "InlineArrayAsSpan<$InlineArray3, object>(ref $InlineArray3, int)" + IL_0033: call "System.ReadOnlySpan System.Span.op_Implicit(System.Span)" + IL_0038: call "MyCollection MyCollectionBuilder.Create(System.ReadOnlySpan)" + IL_003d: ret } """); @@ -5773,7 +5809,12 @@ static MyCollection F2(MyCollection c) } """; - verifier = CompileAndVerify(new[] { sourceB2, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net70, expectedOutput: "[1, 2, 3], "); + verifier = CompileAndVerify( + new[] { sourceB2, s_collectionExtensions }, + references: new[] { refA }, + targetFramework: TargetFramework.Net80, + verify: Verification.Fails, + expectedOutput: "[1, 2, 3], "); verifier.VerifyIL("Program.F2", """ { @@ -5822,6 +5863,212 @@ .locals init (System.Collections.Generic.List V_0, """); } + [CombinatorialData] + [ConditionalTheory(typeof(CoreClrOnly))] + public void CollectionBuilder_02A( + [CombinatorialValues(TargetFramework.Net70, TargetFramework.Net80)] TargetFramework targetFramework, + bool useCompilationReference) + { + string sourceA = """ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Runtime.CompilerServices; + [CollectionBuilder(typeof(MyCollectionBuilder), nameof(MyCollectionBuilder.Create))] + public struct MyCollection : IEnumerable + { + private readonly List _list; + public MyCollection(List list) { _list = list; } + public IEnumerator GetEnumerator() => _list.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } + public class MyCollectionBuilder + { + public static MyCollection Create(ReadOnlySpan items) + { + return new MyCollection(new List(items.ToArray())); + } + } + """; + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: targetFramework); + var refA = AsReference(comp, useCompilationReference); + + string sourceB = """ + class Program + { + static void Main() + { + var x = F(); + x.Report(); + } + static MyCollection F() + { + return [1, 2, null]; + } + } + """; + comp = CreateCompilation(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: targetFramework, options: TestOptions.ReleaseExe); + comp.VerifyEmitDiagnostics(); + + var verifier = CompileAndVerify( + comp, + symbolValidator: module => + { + var type = module.GlobalNamespace.GetTypeMembers("$InlineArray3").SingleOrDefault(); + if (targetFramework == TargetFramework.Net80) + { + Assert.NotNull(type); + } + else + { + Assert.Null(type); + } + }, + verify: targetFramework == TargetFramework.Net80 ? Verification.Fails : Verification.Passes, + expectedOutput: "[1, 2, null], "); + if (targetFramework == TargetFramework.Net80) + { + verifier.VerifyIL("Program.F", + """ + { + // Code size 79 (0x4f) + .maxstack 2 + .locals init ($InlineArray3 V_0) + IL_0000: ldloca.s V_0 + IL_0002: initobj "$InlineArray3" + IL_0008: ldloca.s V_0 + IL_000a: ldc.i4.0 + IL_000b: call "InlineArrayElementRef<$InlineArray3, int?>(ref $InlineArray3, int)" + IL_0010: ldc.i4.1 + IL_0011: newobj "int?..ctor(int)" + IL_0016: stobj "int?" + IL_001b: ldloca.s V_0 + IL_001d: ldc.i4.1 + IL_001e: call "InlineArrayElementRef<$InlineArray3, int?>(ref $InlineArray3, int)" + IL_0023: ldc.i4.2 + IL_0024: newobj "int?..ctor(int)" + IL_0029: stobj "int?" + IL_002e: ldloca.s V_0 + IL_0030: ldc.i4.2 + IL_0031: call "InlineArrayElementRef<$InlineArray3, int?>(ref $InlineArray3, int)" + IL_0036: initobj "int?" + IL_003c: ldloca.s V_0 + IL_003e: ldc.i4.3 + IL_003f: call "InlineArrayAsSpan<$InlineArray3, int?>(ref $InlineArray3, int)" + IL_0044: call "System.ReadOnlySpan System.Span.op_Implicit(System.Span)" + IL_0049: call "MyCollection MyCollectionBuilder.Create(System.ReadOnlySpan)" + IL_004e: ret + } + """); + } + else + { + verifier.VerifyIL("Program.F", + """ + { + // Code size 43 (0x2b) + .maxstack 4 + IL_0000: ldc.i4.3 + IL_0001: newarr "int?" + IL_0006: dup + IL_0007: ldc.i4.0 + IL_0008: ldc.i4.1 + IL_0009: newobj "int?..ctor(int)" + IL_000e: stelem "int?" + IL_0013: dup + IL_0014: ldc.i4.1 + IL_0015: ldc.i4.2 + IL_0016: newobj "int?..ctor(int)" + IL_001b: stelem "int?" + IL_0020: newobj "System.ReadOnlySpan..ctor(int?[])" + IL_0025: call "MyCollection MyCollectionBuilder.Create(System.ReadOnlySpan)" + IL_002a: ret + } + """); + } + } + + // As above, but with TargetFramework.NetFramework. + [ConditionalFact(typeof(DesktopOnly))] + public void CollectionBuilder_02B() + { + string sourceA = """ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Runtime.CompilerServices; + [CollectionBuilder(typeof(MyCollectionBuilder), nameof(MyCollectionBuilder.Create))] + public struct MyCollection : IEnumerable + { + private readonly List _list; + public MyCollection(List list) { _list = list; } + public IEnumerator GetEnumerator() => _list.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } + public class MyCollectionBuilder + { + public static MyCollection Create(ReadOnlySpan items) + { + var list = new List(); + foreach (var i in items) list.Add(i); + return new MyCollection(list); + } + } + """; + string sourceB = """ + class Program + { + static void Main() + { + var x = F(); + x.Report(); + } + static MyCollection F() + { + return [1, 2, null]; + } + } + """; + var comp = CreateCompilationWithSpanAndMemoryExtensions( + new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition, s_collectionExtensions }, + targetFramework: TargetFramework.NetFramework, + options: TestOptions.ReleaseExe); + comp.VerifyEmitDiagnostics(); + + var verifier = CompileAndVerify( + comp, + symbolValidator: module => + { + var type = module.GlobalNamespace.GetTypeMembers("$InlineArray3").SingleOrDefault(); + Assert.Null(type); + }, + expectedOutput: "[1, 2, null], "); + verifier.VerifyIL("Program.F", + """ + { + // Code size 43 (0x2b) + .maxstack 4 + IL_0000: ldc.i4.3 + IL_0001: newarr "int?" + IL_0006: dup + IL_0007: ldc.i4.0 + IL_0008: ldc.i4.1 + IL_0009: newobj "int?..ctor(int)" + IL_000e: stelem "int?" + IL_0013: dup + IL_0014: ldc.i4.1 + IL_0015: ldc.i4.2 + IL_0016: newobj "int?..ctor(int)" + IL_001b: stelem "int?" + IL_0020: newobj "System.ReadOnlySpan..ctor(int?[])" + IL_0025: call "MyCollection MyCollectionBuilder.Create(System.ReadOnlySpan)" + IL_002a: ret + } + """); + } + + // PROTOTYPE: Test sharing synthesized type across all uses within the same assembly, but not across assemblies. + [CombinatorialData] [ConditionalTheory(typeof(CoreClrOnly))] public void CollectionBuilder_RefStructCollection(bool useCompilationReference, bool useScoped) @@ -5847,7 +6094,7 @@ public static MyCollection Create({{qualifier}}ReadOnlySpan items) } } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -5868,33 +6115,40 @@ static MyCollection F() } """; - var verifier = CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net70, verify: Verification.Fails, expectedOutput: "1, 2, 3, "); - // https://github.com/dotnet/roslyn/issues/68785: Avoid heap allocation for 'scoped' case. + var verifier = CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "1, 2, 3, "); + // PROTOTYPE: Use heap for non-scoped case. verifier.VerifyIL("Program.F", $$""" { - // Code size 44 (0x2c) - .maxstack 4 - IL_0000: ldc.i4.3 - IL_0001: newarr "object" - IL_0006: dup - IL_0007: ldc.i4.0 - IL_0008: ldc.i4.1 - IL_0009: box "int" - IL_000e: stelem.ref - IL_000f: dup + // Code size 72 (0x48) + .maxstack 2 + .locals init ($InlineArray3 V_0) + IL_0000: ldloca.s V_0 + IL_0002: initobj "$InlineArray3" + IL_0008: ldloca.s V_0 + IL_000a: ldc.i4.0 + IL_000b: call "InlineArrayElementRef<$InlineArray3, object>(ref $InlineArray3, int)" IL_0010: ldc.i4.1 - IL_0011: ldc.i4.2 - IL_0012: box "int" - IL_0017: stelem.ref - IL_0018: dup - IL_0019: ldc.i4.2 - IL_001a: ldc.i4.3 - IL_001b: box "int" - IL_0020: stelem.ref - IL_0021: newobj "System.ReadOnlySpan..ctor(object[])" - IL_0026: call "MyCollection MyCollectionBuilder.Create({{qualifier}}System.ReadOnlySpan)" - IL_002b: ret + IL_0011: box "int" + IL_0016: stind.ref + IL_0017: ldloca.s V_0 + IL_0019: ldc.i4.1 + IL_001a: call "InlineArrayElementRef<$InlineArray3, object>(ref $InlineArray3, int)" + IL_001f: ldc.i4.2 + IL_0020: box "int" + IL_0025: stind.ref + IL_0026: ldloca.s V_0 + IL_0028: ldc.i4.2 + IL_0029: call "InlineArrayElementRef<$InlineArray3, object>(ref $InlineArray3, int)" + IL_002e: ldc.i4.3 + IL_002f: box "int" + IL_0034: stind.ref + IL_0035: ldloca.s V_0 + IL_0037: ldc.i4.3 + IL_0038: call "InlineArrayAsSpan<$InlineArray3, object>(ref $InlineArray3, int)" + IL_003d: call "System.ReadOnlySpan System.Span.op_Implicit(System.Span)" + IL_0042: call "MyCollection MyCollectionBuilder.Create({{qualifier}}System.ReadOnlySpan)" + IL_0047: ret } """); } @@ -5922,7 +6176,7 @@ public static MyCollection Create(ReadOnlySpan items) => new MyCollection(new List(items.ToArray())); } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -5937,7 +6191,7 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net70, expectedOutput: "[], [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "[], [1, 2, 3], "); } [CombinatorialData] @@ -5966,7 +6220,7 @@ public sealed class MyCollection : IMyCollection } } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -5981,7 +6235,7 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net70, expectedOutput: "(MyCollectionBuilder.MyCollection) [], (MyCollectionBuilder.MyCollection) [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "(MyCollectionBuilder.MyCollection) [], (MyCollectionBuilder.MyCollection) [1, 2, 3], "); } [CombinatorialData] @@ -6010,7 +6264,7 @@ public sealed class MyCollection : IMyCollection } } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -6023,7 +6277,7 @@ static void Main() } } """; - comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net70); + comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // (5,35): error CS9187: Could not find an accessible 'Create' method with the expected signature: a static method with a single parameter of type 'ReadOnlySpan' and return type 'IMyCollection'. // IMyCollection x = []; @@ -6059,7 +6313,7 @@ public static MyCollection Create(ReadOnlySpan items) } } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -6074,7 +6328,7 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net70, expectedOutput: "(Container.MyCollection) [], (Container.MyCollection) [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "(Container.MyCollection) [], (Container.MyCollection) [1, 2, 3], "); } [CombinatorialData] @@ -6094,7 +6348,7 @@ public class MyCollectionBuilder public static MyCollection Create(ReadOnlySpan items) => default; } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -6109,7 +6363,7 @@ static void Main() } } """; - comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net70); + comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // (6,34): error CS9188: 'MyCollection' has a CollectionBuilderAttribute but no element type. // MyCollection x = []; @@ -6156,7 +6410,7 @@ public static MyCollection Create(ReadOnlySpan items) => new MyCollection(items.ToArray()); } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -6176,7 +6430,7 @@ static IEnumerable GetElements(MyCollection c) } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net70, expectedOutput: "[], [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "[], [1, 2, 3], "); } [CombinatorialData] @@ -6216,7 +6470,7 @@ public static MyCollection Create(ReadOnlySpan items) => new MyCollection(items.ToArray()); } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -6236,7 +6490,7 @@ static IEnumerable GetElements(MyCollection c) } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net70, expectedOutput: "[], [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "[], [1, 2, 3], "); } [CombinatorialData] @@ -6260,7 +6514,7 @@ public static MyCollection Create(ReadOnlySpan items) => new MyCollection(items.ToArray()); } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -6275,7 +6529,7 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net70, expectedOutput: "[], [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "[], [1, 2, 3], "); } [CombinatorialData] @@ -6297,7 +6551,7 @@ public class MyCollectionBuilder public static MyCollection Create(ReadOnlySpan items) => default; } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -6312,7 +6566,7 @@ static void Main() } } """; - comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net70); + comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // (6,34): error CS9187: Could not find an accessible 'Create' method with the expected signature: a static method with a single parameter of type 'ReadOnlySpan' and return type 'MyCollection'. // MyCollection x = []; @@ -6351,7 +6605,7 @@ public static C Create(ReadOnlySpan> items) => new C(new List>(items.ToArray())); } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -6366,7 +6620,7 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net70, expectedOutput: "(C) [null], (C) [E(1), null], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "(C) [null], (C) [E(1), null], "); } [CombinatorialData] @@ -6396,7 +6650,7 @@ public static MyImmutableDictionary Create(ReadOnlySpan new MyImmutableDictionary(items); } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -6412,7 +6666,7 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net70, expectedOutput: "[], [[one, 1], [two, 2]], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "[], [[one, 1], [two, 2]], "); } [ConditionalFact(typeof(CoreClrOnly))] @@ -6423,7 +6677,7 @@ public class MyCollectionBuilder { } """; - var comp = CreateCompilation(sourceA, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(sourceA, targetFramework: TargetFramework.Net80); var refA = comp.EmitToImageReference(); string sourceB = """ @@ -6437,7 +6691,7 @@ public struct MyCollection : IEnumerable IEnumerator IEnumerable.GetEnumerator() => default; } """; - comp = CreateCompilation(new[] { sourceB, CollectionBuilderAttributeDefinition }, references: new[] { refA }, targetFramework: TargetFramework.Net70); + comp = CreateCompilation(new[] { sourceB, CollectionBuilderAttributeDefinition }, references: new[] { refA }, targetFramework: TargetFramework.Net80); var refB = comp.EmitToImageReference(); string sourceC = """ @@ -6452,7 +6706,7 @@ static void Main() } } """; - comp = CreateCompilation(sourceC, references: new[] { refB }, targetFramework: TargetFramework.Net70); + comp = CreateCompilation(sourceC, references: new[] { refB }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // (6,31): error CS9187: Could not find an accessible 'Create' method with the expected signature: a static method with a single parameter of type 'ReadOnlySpan' and return type 'MyCollection'. // MyCollection x = []; @@ -6480,7 +6734,7 @@ public class MyCollectionBuilder { } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -6495,7 +6749,7 @@ static void Main() } } """; - comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net70); + comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // (6,31): error CS9187: Could not find an accessible 'Create' method with the expected signature: a static method with a single parameter of type 'ReadOnlySpan' and return type 'MyCollection'. // MyCollection x = []; @@ -6531,7 +6785,7 @@ static void Main() } } """; - var comp = CreateCompilation(new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // 0.cs(4,2): error CS9185: The CollectionBuilderAttribute builder type must be a non-generic class or struct. // [CollectionBuilder(null, "Create")] @@ -6615,7 +6869,7 @@ static void Main() } } """; - var comp = CreateCompilation(new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // 0.cs(5,2): error CS9185: The CollectionBuilderAttribute builder type must be a non-generic class or struct. // [CollectionBuilder(typeof(MyCollectionBuilder), "Create")] @@ -6707,7 +6961,7 @@ static void Main() } } """; - var comp = CreateCompilation(new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // 0.cs(5,2): error CS9185: The CollectionBuilderAttribute builder type must be a non-generic class or struct. // [CollectionBuilder(typeof(MyCollectionBuilder), "ToString")] @@ -6748,7 +7002,7 @@ static void Main() } } """; - var comp = CreateCompilation(new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // 0.cs(4,2): error CS9185: The CollectionBuilderAttribute builder type must be a non-generic class or struct. // [CollectionBuilder(typeof(int*), "ToString")] @@ -6788,7 +7042,7 @@ static void Main() } } """; - var comp = CreateCompilation(new[] { source, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { source, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // 0.cs(6,24): error CS0416: 'T': an attribute argument cannot use type parameters // [CollectionBuilder(typeof(T), "ToString")] @@ -6828,7 +7082,7 @@ static void Main() } } """; - var comp = CreateCompilation(new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // 0.cs(4,2): error CS9186: The CollectionBuilderAttribute method name is invalid. // [CollectionBuilder(typeof(MyCollectionBuilder), "")] @@ -6910,7 +7164,7 @@ public class MyCollectionBuilder public MyCollection Create(ReadOnlySpan items) => default; } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -6925,7 +7179,7 @@ static void Main() } } """; - comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net70); + comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // (6,31): error CS9187: Could not find an accessible 'Create' method with the expected signature: a static method with a single parameter of type 'ReadOnlySpan' and return type 'MyCollection'. // MyCollection x = []; @@ -6959,7 +7213,7 @@ public class MyCollectionBuilder {{createMember}} } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -6974,7 +7228,7 @@ static void Main() } } """; - comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net70); + comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // (6,26): error CS9187: Could not find an accessible 'Create' method with the expected signature: a static method with a single parameter of type 'ReadOnlySpan' and return type 'MyCollection'. // MyCollection x = []; @@ -7013,7 +7267,7 @@ public static MyCollection Create(ReadOnlySpan items) => new MyCollection(new List(items.ToArray())); } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = $$""" @@ -7034,7 +7288,7 @@ static IEnumerable GetElements(MyCollection c) } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net70, expectedOutput: $"[], [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: $"[], [1, 2, 3], "); } [CombinatorialData] @@ -7045,14 +7299,6 @@ public void CollectionBuilder_TypeDifferences_TupleElementNames(bool useCompilat CollectionBuilder_TypeDifferences("(int A, int B)", "(int, int)", "(1, 2), default", "[(1, 2), (0, 0)]", useCompilationReference); } - [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] - public void CollectionBuilder_TypeDifferences_Nullability(bool useCompilationReference) - { - CollectionBuilder_TypeDifferences("object", "object?", "1, 2, 3", "[1, 2, 3]", useCompilationReference); - CollectionBuilder_TypeDifferences("object?", "object", "1, null, 3", "[1, null, 3]", useCompilationReference); - } - private void CollectionBuilder_TypeDifferences(string collectionElementType, string builderElementType, string values, string expectedOutput, bool useCompilationReference) { string sourceA = $$""" @@ -7075,7 +7321,7 @@ public static MyCollection Create(ReadOnlySpan<{{builderElementType}}> items) => new MyCollection(new List<{{collectionElementType}}>(items.ToArray())); } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = $$""" @@ -7092,7 +7338,7 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net70, expectedOutput: $"[], {expectedOutput}, "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: $"[], {expectedOutput}, "); } // If there are multiple attributes, the first is used. @@ -7135,7 +7381,7 @@ public static MyCollection Create2(ReadOnlySpan items) => throw null; } """; - var comp = CreateCompilation(new[] { sourceAttribute, sourceA }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceAttribute, sourceA }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -7148,7 +7394,7 @@ static void Main() } } """; - var verifier = CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net70, expectedOutput: "[1, 2, 3], "); + var verifier = CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "[1, 2, 3], "); comp = (CSharpCompilation)verifier.Compilation; var collectionType = (NamedTypeSymbol)comp.GetMember("Program.F").ReturnType; @@ -7191,7 +7437,7 @@ static void Main() } } """; - var comp = CreateCompilation(new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // 0.cs(5,2): error CS9185: The CollectionBuilderAttribute builder type must be a non-generic class or struct. // [CollectionBuilder(typeof(MyCollectionBuilder<>), "Create")] @@ -7235,7 +7481,7 @@ static void Main() } } """; - var comp = CreateCompilation(new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // 0.cs(5,2): error CS9185: The CollectionBuilderAttribute builder type must be a non-generic class or struct. // [CollectionBuilder(typeof(MyCollectionBuilder), "Create")] @@ -7283,7 +7529,7 @@ static void Main() } } """; - var comp = CreateCompilation(new[] { source, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { source, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // 0.cs(7,24): error CS0416: 'Container.MyCollectionBuilder': an attribute argument cannot use type parameters // [CollectionBuilder(typeof(MyCollectionBuilder), "Create")] @@ -7319,7 +7565,7 @@ public static Container.MyCollection Create(ReadOnlySpan items) => new Container.MyCollection(new List(items.ToArray())); } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -7334,7 +7580,7 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net70, expectedOutput: "(Container.MyCollection) [], (Container.MyCollection) [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "(Container.MyCollection) [], (Container.MyCollection) [1, 2, 3], "); } [CombinatorialData] @@ -7363,7 +7609,7 @@ public static Container.MyCollection Create(ReadOnlySpan items) => new Container.MyCollection(new List(items.ToArray())); } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -7378,7 +7624,7 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net70, expectedOutput: "(Container.MyCollection) [], (Container.MyCollection) [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "(Container.MyCollection) [], (Container.MyCollection) [1, 2, 3], "); } [CombinatorialData] @@ -7407,7 +7653,7 @@ public static Container.MyCollection Create(ReadOnlySpan items) => new Container.MyCollection(new List(items.ToArray())); } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -7422,7 +7668,7 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net70, expectedOutput: "(Container.MyCollection) [], (Container.MyCollection) [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "(Container.MyCollection) [], (Container.MyCollection) [1, 2, 3], "); } [CombinatorialData] @@ -7448,7 +7694,7 @@ public static MyCollection Create(ReadOnlySpan items) => new MyCollection(new List(items.ToArray())); } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -7463,7 +7709,7 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net70, expectedOutput: "(MyCollection) [], (MyCollection) [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "(MyCollection) [], (MyCollection) [1, 2, 3], "); } [CombinatorialData] @@ -7489,7 +7735,7 @@ public static MyCollection Create(ReadOnlySpan items) => new MyCollection(new List(items.ToArray())); } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -7504,7 +7750,7 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net70, expectedOutput: "(MyCollection) [], (MyCollection) [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "(MyCollection) [], (MyCollection) [1, 2, 3], "); } [CombinatorialData] @@ -7527,7 +7773,7 @@ internal class MyCollectionBuilder public static MyCollection Create(ReadOnlySpan items) => default; } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -7542,7 +7788,7 @@ static void Main() } } """; - comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net70); + comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // (6,31): error CS9187: Could not find an accessible 'Create' method with the expected signature: a static method with a single parameter of type 'ReadOnlySpan' and return type 'MyCollection'. // MyCollection x = []; @@ -7575,7 +7821,7 @@ public static MyCollection Create(ReadOnlySpan items) } } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -7591,7 +7837,7 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net70, expectedOutput: "[], [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "[], [1, 2, 3], "); } [CombinatorialData] @@ -7615,7 +7861,7 @@ protected class MyCollectionBuilder static readonly MyCollection _instance = [1, 2, 3]; } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -7630,7 +7876,7 @@ static void Main() } } """; - comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net70); + comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // (6,26): error CS9187: Could not find an accessible 'Create' method with the expected signature: a static method with a single parameter of type 'ReadOnlySpan' and return type 'MyCollection'. // MyCollection x = []; @@ -7661,7 +7907,7 @@ public class MyCollectionBuilder internal static MyCollection Create(ReadOnlySpan items) => default; } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -7676,7 +7922,7 @@ static void Main() } } """; - comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net70); + comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // (6,31): error CS9187: Could not find an accessible 'Create' method with the expected signature: a static method with a single parameter of type 'ReadOnlySpan' and return type 'MyCollection'. // MyCollection x = []; @@ -7723,7 +7969,7 @@ public static MyCollection Create(ReadOnlySpan items, int index = 0) } } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -7738,7 +7984,7 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net70, expectedOutput: "[], [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "[], [1, 2, 3], "); } [CombinatorialData] @@ -7770,7 +8016,7 @@ public static MyCollection Create(ReadOnlySpan items) } } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -7785,7 +8031,7 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net70, expectedOutput: "[], [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "[], [1, 2, 3], "); } [CombinatorialData] @@ -7825,7 +8071,7 @@ public class MyCollectionBuilder {{methodDeclaration}} } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -7840,7 +8086,7 @@ static void Main() } } """; - comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net70); + comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // (6,34): error CS9187: Could not find an accessible 'Create' method with the expected signature: a static method with a single parameter of type 'ReadOnlySpan' and return type 'MyCollection'. // MyCollection x = []; @@ -7870,7 +8116,7 @@ public class MyCollectionBuilder public static MyCollection Create(ReadOnlySpan items) => default; } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -7885,7 +8131,7 @@ static void Main() } } """; - comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net70); + comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // (6,26): error CS9187: Could not find an accessible 'Create' method with the expected signature: a static method with a single parameter of type 'ReadOnlySpan' and return type 'MyCollection'. // MyCollection x = []; @@ -7915,7 +8161,7 @@ public sealed class MyCollectionBuilder public static MyCollection Create(ReadOnlySpan items) => default; } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -7930,7 +8176,7 @@ static void Main() } } """; - comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net70); + comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // (6,39): error CS9187: Could not find an accessible 'Create' method with the expected signature: a static method with a single parameter of type 'ReadOnlySpan' and return type 'MyCollection'. // MyCollection x = []; @@ -7973,7 +8219,7 @@ public sealed class MyCollectionBuilder public static MyCollectionBase Create(ReadOnlySpan items) => new MyCollection(); } """; - var comp = CreateCompilation(new[] { sourceA, sourceAttribute }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, sourceAttribute }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -7987,7 +8233,7 @@ static void Main() } } """; - comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net70); + comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // (6,27): error CS1061: 'MyCollection' does not contain a definition for 'Add' and no accessible extension method 'Add' accepting a first argument of type 'MyCollection' could be found (are you missing a using directive or an assembly reference?) // MyCollection y = [2]; @@ -8017,7 +8263,7 @@ public sealed class MyCollectionBuilder : MyCollectionBuilderBase { } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -8031,7 +8277,7 @@ static void Main() } } """; - comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net70); + comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // (5,26): error CS9187: Could not find an accessible 'Create' method with the expected signature: a static method with a single parameter of type 'ReadOnlySpan' and return type 'MyCollection'. // MyCollection x = []; @@ -8062,7 +8308,7 @@ public class MyCollectionBuilder public static MyCollection Create(ReadOnlySpan items) => default; } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -8077,7 +8323,7 @@ static void Main() } } """; - comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net70); + comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // (6,34): warning CS0612: 'MyCollectionBuilder' is obsolete // MyCollection x = []; @@ -8119,7 +8365,7 @@ static void Main() } } """; - var comp = CreateCompilation(new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // 0.cs(5,27): error CS0619: 'MyCollectionBuilder' is obsolete: 'message 2' // [CollectionBuilder(typeof(MyCollectionBuilder), "Create")] @@ -8153,7 +8399,7 @@ public class MyCollectionBuilder public static MyCollection Create(ReadOnlySpan items) => default; } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -8168,7 +8414,7 @@ static void Main() } } """; - comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net70); + comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // (6,34): warning CS0612: 'MyCollectionBuilder.Create(ReadOnlySpan)' is obsolete // MyCollection x = []; @@ -8199,7 +8445,7 @@ public class MyCollectionBuilder public static MyCollection Create(ReadOnlySpan items) => default; } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -8214,7 +8460,7 @@ static void Main() } } """; - comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net70); + comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // (6,34): error CS0619: 'MyCollectionBuilder.Create(ReadOnlySpan)' is obsolete: 'message 4' // MyCollection x = []; @@ -8257,7 +8503,7 @@ static void Main() } } """; - var comp = CreateCompilation(new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // 1.cs(6,34): error CS8901: 'MyCollectionBuilder.Create(ReadOnlySpan)' is attributed with 'UnmanagedCallersOnly' and cannot be called directly. Obtain a function pointer to this method. // MyCollection x = []; @@ -8296,7 +8542,7 @@ public static MyCollection Create(ReadOnlySpan items) where T : struct => new MyCollection(new List(items.ToArray())); } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB1 = """ @@ -8311,7 +8557,7 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB1, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net70, expectedOutput: "[], [1, 2, 3], "); + CompileAndVerify(new[] { sourceB1, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "[], [1, 2, 3], "); string sourceB2 = """ #pragma warning disable 219 @@ -8324,7 +8570,7 @@ static void Main() } } """; - comp = CreateCompilation(sourceB2, references: new[] { refA }, targetFramework: TargetFramework.Net70); + comp = CreateCompilation(sourceB2, references: new[] { refA }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // (6,32): error CS0453: The type 'int?' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'MyCollectionBuilder.Create(ReadOnlySpan)' // MyCollection x = [4, null]; @@ -8354,7 +8600,7 @@ public static MyCollection Create(ReadOnlySpan items) where T : struct => new MyCollection(new List(items.ToArray())); } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB1 = """ @@ -8369,7 +8615,7 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB1, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net70, expectedOutput: "[], [1, 2, 3], "); + CompileAndVerify(new[] { sourceB1, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "[], [1, 2, 3], "); string sourceB2 = """ #pragma warning disable 219 @@ -8382,7 +8628,7 @@ static void Main() } } """; - comp = CreateCompilation(sourceB2, references: new[] { refA }, targetFramework: TargetFramework.Net70); + comp = CreateCompilation(sourceB2, references: new[] { refA }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // (6,32): error CS0453: The type 'int?' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'MyCollectionBuilder.Create(ReadOnlySpan)' // MyCollection x = [4, null]; @@ -8423,7 +8669,7 @@ static void Main() } } """; - var comp = CreateCompilation(new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // 1.cs(7,22): error CS0452: The type 'int' must be a reference type in order to use it as parameter 'T' in the generic type or method 'MyCollection' // MyCollection y = [1, 2, 3]; @@ -8453,7 +8699,7 @@ public class MyCollectionBuilder public static MyCollection Create(ReadOnlySpan items) => default; } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); var refA = AsReference(comp, useCompilationReference); string sourceB = """ @@ -8470,7 +8716,7 @@ static void F(MyCollection c) } } """; - comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net70); + comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics(); var collectionType = (NamedTypeSymbol)comp.GetMember("Program.F").Parameters[0].Type; @@ -8524,7 +8770,7 @@ static void F(MyCollection c) } } """; - var comp = CreateCompilation(new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // 0.cs(5,2): error CS9185: The CollectionBuilderAttribute builder type must be a non-generic class or struct. // [CollectionBuilder(typeof(Container.MyCollectionBuilder), "Create")] @@ -8582,7 +8828,7 @@ static void F(Container.MyCollection c) } } """; - var comp = CreateCompilation(new[] { source, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { source, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // 0.cs(7,24): error CS0416: 'Container.MyCollectionBuilder': an attribute argument cannot use type parameters // [CollectionBuilder(typeof(MyCollectionBuilder), "Create")] @@ -8686,7 +8932,7 @@ static void Main() } } """; - var comp = CreateCompilation(new[] { source, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { source, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // 0.cs(24,31): error CS9188: 'MyCollection' has a CollectionBuilderAttribute but no element type. // MyCollection c = []; @@ -8714,7 +8960,7 @@ static class Extensions static MyCollection F() => []; } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics(); var refA = comp.EmitToImageReference(); @@ -8728,7 +8974,7 @@ static void Main() } } """; - comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net70); + comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // (6,31): error CS9188: 'MyCollection' has a CollectionBuilderAttribute but no element type. // MyCollection c = []; @@ -8760,7 +9006,7 @@ static void Main() } } """; - var comp = CreateCompilation(new[] { source, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { source, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // 0.cs(8,42): error CS9188: 'MyCollection' has a CollectionBuilderAttribute but no element type. // public static MyCollection F() => []; @@ -8798,7 +9044,7 @@ public class MyCollectionBuilder public static MyCollection Create({{builderParameterModifier}} ReadOnlySpan items) => new(items); } """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics(); var refA = AsReference(comp, useCompilationReference); @@ -8821,7 +9067,7 @@ static List GetItems(MyCollection c) } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net70, expectedOutput: "[], [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "[], [1, 2, 3], "); } [ConditionalFact(typeof(CoreClrOnly))] @@ -8858,7 +9104,7 @@ static void Main() } } """; - var comp = CreateCompilation(new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // 0.cs(16,78): error CS8347: Cannot use a result of 'MyCollection.MyCollection(ReadOnlySpan)' in this context because it may expose variables referenced by parameter 'items' outside of their declaration scope // public static MyCollection Create(scoped ReadOnlySpan items) => new(items); @@ -8912,138 +9158,148 @@ static async Task F(int i) } } """; - var verifier = CompileAndVerify(new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition, s_collectionExtensions }, targetFramework: TargetFramework.Net70, expectedOutput: "[1, 2, 3], "); + var verifier = CompileAndVerify(new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition, s_collectionExtensions }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "[1, 2, 3], "); verifier.VerifyIL("Program.d__1.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", """ { - // Code size 285 (0x11d) - .maxstack 4 + // Code size 329 (0x149) + .maxstack 3 .locals init (int V_0, MyCollection V_1, int V_2, - System.Runtime.CompilerServices.TaskAwaiter V_3, - System.Exception V_4) + int V_3, + System.Runtime.CompilerServices.TaskAwaiter V_4, + System.Exception V_5) IL_0000: ldarg.0 IL_0001: ldfld "int Program.d__1.<>1__state" IL_0006: stloc.0 .try { IL_0007: ldloc.0 - IL_0008: brfalse.s IL_0049 + IL_0008: brfalse.s IL_0057 IL_000a: ldloc.0 IL_000b: ldc.i4.1 - IL_000c: beq IL_00a7 - IL_0011: ldc.i4.1 - IL_0012: call "System.Threading.Tasks.Task Program.F(int)" - IL_0017: callvirt "System.Runtime.CompilerServices.TaskAwaiter System.Threading.Tasks.Task.GetAwaiter()" - IL_001c: stloc.3 - IL_001d: ldloca.s V_3 - IL_001f: call "bool System.Runtime.CompilerServices.TaskAwaiter.IsCompleted.get" - IL_0024: brtrue.s IL_0065 - IL_0026: ldarg.0 - IL_0027: ldc.i4.0 - IL_0028: dup - IL_0029: stloc.0 - IL_002a: stfld "int Program.d__1.<>1__state" - IL_002f: ldarg.0 - IL_0030: ldloc.3 - IL_0031: stfld "System.Runtime.CompilerServices.TaskAwaiter Program.d__1.<>u__1" - IL_0036: ldarg.0 - IL_0037: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder> Program.d__1.<>t__builder" - IL_003c: ldloca.s V_3 - IL_003e: ldarg.0 - IL_003f: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder>.AwaitUnsafeOnCompleted, Program.d__1>(ref System.Runtime.CompilerServices.TaskAwaiter, ref Program.d__1)" - IL_0044: leave IL_011c - IL_0049: ldarg.0 - IL_004a: ldfld "System.Runtime.CompilerServices.TaskAwaiter Program.d__1.<>u__1" - IL_004f: stloc.3 - IL_0050: ldarg.0 - IL_0051: ldflda "System.Runtime.CompilerServices.TaskAwaiter Program.d__1.<>u__1" - IL_0056: initobj "System.Runtime.CompilerServices.TaskAwaiter" - IL_005c: ldarg.0 - IL_005d: ldc.i4.m1 - IL_005e: dup - IL_005f: stloc.0 - IL_0060: stfld "int Program.d__1.<>1__state" - IL_0065: ldarg.0 - IL_0066: ldloca.s V_3 - IL_0068: call "int System.Runtime.CompilerServices.TaskAwaiter.GetResult()" - IL_006d: stfld "int Program.d__1.<>7__wrap1" - IL_0072: ldc.i4.3 - IL_0073: call "System.Threading.Tasks.Task Program.F(int)" - IL_0078: callvirt "System.Runtime.CompilerServices.TaskAwaiter System.Threading.Tasks.Task.GetAwaiter()" - IL_007d: stloc.3 - IL_007e: ldloca.s V_3 - IL_0080: call "bool System.Runtime.CompilerServices.TaskAwaiter.IsCompleted.get" - IL_0085: brtrue.s IL_00c3 - IL_0087: ldarg.0 - IL_0088: ldc.i4.1 - IL_0089: dup - IL_008a: stloc.0 - IL_008b: stfld "int Program.d__1.<>1__state" - IL_0090: ldarg.0 - IL_0091: ldloc.3 - IL_0092: stfld "System.Runtime.CompilerServices.TaskAwaiter Program.d__1.<>u__1" - IL_0097: ldarg.0 - IL_0098: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder> Program.d__1.<>t__builder" - IL_009d: ldloca.s V_3 - IL_009f: ldarg.0 - IL_00a0: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder>.AwaitUnsafeOnCompleted, Program.d__1>(ref System.Runtime.CompilerServices.TaskAwaiter, ref Program.d__1)" - IL_00a5: leave.s IL_011c - IL_00a7: ldarg.0 - IL_00a8: ldfld "System.Runtime.CompilerServices.TaskAwaiter Program.d__1.<>u__1" - IL_00ad: stloc.3 + IL_000c: beq IL_00cf + IL_0011: ldarg.0 + IL_0012: ldflda "$InlineArray3 Program.d__1.<>7__wrap1" + IL_0017: initobj "$InlineArray3" + IL_001d: ldc.i4.1 + IL_001e: call "System.Threading.Tasks.Task Program.F(int)" + IL_0023: callvirt "System.Runtime.CompilerServices.TaskAwaiter System.Threading.Tasks.Task.GetAwaiter()" + IL_0028: stloc.s V_4 + IL_002a: ldloca.s V_4 + IL_002c: call "bool System.Runtime.CompilerServices.TaskAwaiter.IsCompleted.get" + IL_0031: brtrue.s IL_0074 + IL_0033: ldarg.0 + IL_0034: ldc.i4.0 + IL_0035: dup + IL_0036: stloc.0 + IL_0037: stfld "int Program.d__1.<>1__state" + IL_003c: ldarg.0 + IL_003d: ldloc.s V_4 + IL_003f: stfld "System.Runtime.CompilerServices.TaskAwaiter Program.d__1.<>u__1" + IL_0044: ldarg.0 + IL_0045: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder> Program.d__1.<>t__builder" + IL_004a: ldloca.s V_4 + IL_004c: ldarg.0 + IL_004d: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder>.AwaitUnsafeOnCompleted, Program.d__1>(ref System.Runtime.CompilerServices.TaskAwaiter, ref Program.d__1)" + IL_0052: leave IL_0148 + IL_0057: ldarg.0 + IL_0058: ldfld "System.Runtime.CompilerServices.TaskAwaiter Program.d__1.<>u__1" + IL_005d: stloc.s V_4 + IL_005f: ldarg.0 + IL_0060: ldflda "System.Runtime.CompilerServices.TaskAwaiter Program.d__1.<>u__1" + IL_0065: initobj "System.Runtime.CompilerServices.TaskAwaiter" + IL_006b: ldarg.0 + IL_006c: ldc.i4.m1 + IL_006d: dup + IL_006e: stloc.0 + IL_006f: stfld "int Program.d__1.<>1__state" + IL_0074: ldloca.s V_4 + IL_0076: call "int System.Runtime.CompilerServices.TaskAwaiter.GetResult()" + IL_007b: stloc.2 + IL_007c: ldarg.0 + IL_007d: ldflda "$InlineArray3 Program.d__1.<>7__wrap1" + IL_0082: ldc.i4.0 + IL_0083: call "InlineArrayElementRef<$InlineArray3, int>(ref $InlineArray3, int)" + IL_0088: ldloc.2 + IL_0089: stind.i4 + IL_008a: ldarg.0 + IL_008b: ldflda "$InlineArray3 Program.d__1.<>7__wrap1" + IL_0090: ldc.i4.1 + IL_0091: call "InlineArrayElementRef<$InlineArray3, int>(ref $InlineArray3, int)" + IL_0096: ldc.i4.2 + IL_0097: stind.i4 + IL_0098: ldc.i4.3 + IL_0099: call "System.Threading.Tasks.Task Program.F(int)" + IL_009e: callvirt "System.Runtime.CompilerServices.TaskAwaiter System.Threading.Tasks.Task.GetAwaiter()" + IL_00a3: stloc.s V_4 + IL_00a5: ldloca.s V_4 + IL_00a7: call "bool System.Runtime.CompilerServices.TaskAwaiter.IsCompleted.get" + IL_00ac: brtrue.s IL_00ec IL_00ae: ldarg.0 - IL_00af: ldflda "System.Runtime.CompilerServices.TaskAwaiter Program.d__1.<>u__1" - IL_00b4: initobj "System.Runtime.CompilerServices.TaskAwaiter" - IL_00ba: ldarg.0 - IL_00bb: ldc.i4.m1 - IL_00bc: dup - IL_00bd: stloc.0 - IL_00be: stfld "int Program.d__1.<>1__state" - IL_00c3: ldloca.s V_3 - IL_00c5: call "int System.Runtime.CompilerServices.TaskAwaiter.GetResult()" - IL_00ca: stloc.2 - IL_00cb: ldc.i4.3 - IL_00cc: newarr "int" - IL_00d1: dup - IL_00d2: ldc.i4.0 - IL_00d3: ldarg.0 - IL_00d4: ldfld "int Program.d__1.<>7__wrap1" - IL_00d9: stelem.i4 - IL_00da: dup - IL_00db: ldc.i4.1 - IL_00dc: ldc.i4.2 - IL_00dd: stelem.i4 - IL_00de: dup - IL_00df: ldc.i4.2 - IL_00e0: ldloc.2 - IL_00e1: stelem.i4 - IL_00e2: newobj "System.ReadOnlySpan..ctor(int[])" - IL_00e7: call "MyCollection MyCollectionBuilder.Create(System.ReadOnlySpan)" - IL_00ec: stloc.1 - IL_00ed: leave.s IL_0108 + IL_00af: ldc.i4.1 + IL_00b0: dup + IL_00b1: stloc.0 + IL_00b2: stfld "int Program.d__1.<>1__state" + IL_00b7: ldarg.0 + IL_00b8: ldloc.s V_4 + IL_00ba: stfld "System.Runtime.CompilerServices.TaskAwaiter Program.d__1.<>u__1" + IL_00bf: ldarg.0 + IL_00c0: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder> Program.d__1.<>t__builder" + IL_00c5: ldloca.s V_4 + IL_00c7: ldarg.0 + IL_00c8: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder>.AwaitUnsafeOnCompleted, Program.d__1>(ref System.Runtime.CompilerServices.TaskAwaiter, ref Program.d__1)" + IL_00cd: leave.s IL_0148 + IL_00cf: ldarg.0 + IL_00d0: ldfld "System.Runtime.CompilerServices.TaskAwaiter Program.d__1.<>u__1" + IL_00d5: stloc.s V_4 + IL_00d7: ldarg.0 + IL_00d8: ldflda "System.Runtime.CompilerServices.TaskAwaiter Program.d__1.<>u__1" + IL_00dd: initobj "System.Runtime.CompilerServices.TaskAwaiter" + IL_00e3: ldarg.0 + IL_00e4: ldc.i4.m1 + IL_00e5: dup + IL_00e6: stloc.0 + IL_00e7: stfld "int Program.d__1.<>1__state" + IL_00ec: ldloca.s V_4 + IL_00ee: call "int System.Runtime.CompilerServices.TaskAwaiter.GetResult()" + IL_00f3: stloc.3 + IL_00f4: ldarg.0 + IL_00f5: ldflda "$InlineArray3 Program.d__1.<>7__wrap1" + IL_00fa: ldc.i4.2 + IL_00fb: call "InlineArrayElementRef<$InlineArray3, int>(ref $InlineArray3, int)" + IL_0100: ldloc.3 + IL_0101: stind.i4 + IL_0102: ldarg.0 + IL_0103: ldflda "$InlineArray3 Program.d__1.<>7__wrap1" + IL_0108: ldc.i4.3 + IL_0109: call "InlineArrayAsSpan<$InlineArray3, int>(ref $InlineArray3, int)" + IL_010e: call "System.ReadOnlySpan System.Span.op_Implicit(System.Span)" + IL_0113: call "MyCollection MyCollectionBuilder.Create(System.ReadOnlySpan)" + IL_0118: stloc.1 + IL_0119: leave.s IL_0134 } catch System.Exception { - IL_00ef: stloc.s V_4 - IL_00f1: ldarg.0 - IL_00f2: ldc.i4.s -2 - IL_00f4: stfld "int Program.d__1.<>1__state" - IL_00f9: ldarg.0 - IL_00fa: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder> Program.d__1.<>t__builder" - IL_00ff: ldloc.s V_4 - IL_0101: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder>.SetException(System.Exception)" - IL_0106: leave.s IL_011c + IL_011b: stloc.s V_5 + IL_011d: ldarg.0 + IL_011e: ldc.i4.s -2 + IL_0120: stfld "int Program.d__1.<>1__state" + IL_0125: ldarg.0 + IL_0126: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder> Program.d__1.<>t__builder" + IL_012b: ldloc.s V_5 + IL_012d: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder>.SetException(System.Exception)" + IL_0132: leave.s IL_0148 } - IL_0108: ldarg.0 - IL_0109: ldc.i4.s -2 - IL_010b: stfld "int Program.d__1.<>1__state" - IL_0110: ldarg.0 - IL_0111: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder> Program.d__1.<>t__builder" - IL_0116: ldloc.1 - IL_0117: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder>.SetResult(MyCollection)" - IL_011c: ret + IL_0134: ldarg.0 + IL_0135: ldc.i4.s -2 + IL_0137: stfld "int Program.d__1.<>1__state" + IL_013c: ldarg.0 + IL_013d: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder> Program.d__1.<>t__builder" + IL_0142: ldloc.1 + IL_0143: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder>.SetResult(MyCollection)" + IL_0148: ret } """); } @@ -9071,7 +9327,7 @@ static class MyCollectionBuilder public static MyCollection Create(ReadOnlySpan items) => null; } """; - var comp = CreateCompilation(new[] { source, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net70); + var comp = CreateCompilation(new[] { source, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); comp.VerifyEmitDiagnostics( // 0.cs(6,49): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type // [CollectionBuilder(typeof(MyCollectionBuilder), MyCollectionBuilder.GetName([1, 2, 3]))] diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs index a7754e33cfaba..9c23237a15bda 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs @@ -951,6 +951,7 @@ public void AllWellKnownTypeMembers() case WellKnownMember.System_Span_T__get_Item: case WellKnownMember.System_Span_T__get_Length: case WellKnownMember.System_Span_T__Slice_Int_Int: + case WellKnownMember.System_Span_T__op_Implicit_Span: case WellKnownMember.System_ReadOnlySpan_T__ctor_Pointer: case WellKnownMember.System_ReadOnlySpan_T__ctor_Array: case WellKnownMember.System_ReadOnlySpan_T__ctor_Array_Start_Length: diff --git a/src/Compilers/Core/Portable/CodeGen/PrivateImplementationDetails.cs b/src/Compilers/Core/Portable/CodeGen/PrivateImplementationDetails.cs index 2150191642108..a56e447776a25 100644 --- a/src/Compilers/Core/Portable/CodeGen/PrivateImplementationDetails.cs +++ b/src/Compilers/Core/Portable/CodeGen/PrivateImplementationDetails.cs @@ -7,7 +7,6 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection.Metadata; using System.Runtime.InteropServices; @@ -82,8 +81,12 @@ internal sealed class PrivateImplementationDetails : DefaultTypeDef, Cci.INamesp private readonly ConcurrentDictionary _synthesizedMethods = new ConcurrentDictionary(); + // synthesized inline array types + private readonly ConcurrentDictionary _synthesizedInlineArrayTypes = + new ConcurrentDictionary(); + // field types for different block sizes. - private ImmutableArray _orderedProxyTypes; + private ImmutableArray _orderedNestedTypes; private readonly ConcurrentDictionary<(uint Size, ushort Alignment), Cci.ITypeReference> _proxyTypes = new ConcurrentDictionary<(uint Size, ushort Alignment), Cci.ITypeReference>(); internal PrivateImplementationDetails( @@ -132,6 +135,12 @@ private static string GetClassName(string moduleName, int submissionSlotIndex, b return name; } + internal static string GetInlineArrayTypeName(int arrayLength) + { + Debug.Assert(arrayLength > 0); + return $"$InlineArray{arrayLength}"; + } + internal void Freeze() { var wasFrozen = Interlocked.Exchange(ref _frozen, 1); @@ -155,8 +164,10 @@ internal void Freeze() // Sort methods. _orderedSynthesizedMethods = _synthesizedMethods.OrderBy(kvp => kvp.Key).Select(kvp => kvp.Value).AsImmutable(); - // Sort proxy types. - _orderedProxyTypes = _proxyTypes.OrderBy(kvp => kvp.Key.Size).ThenBy(kvp => kvp.Key.Alignment).Select(kvp => kvp.Value).AsImmutable(); + // Sort nested types. + var orderedProxyTypes = _proxyTypes.OrderBy(kvp => kvp.Key.Size).ThenBy(kvp => kvp.Key.Alignment).Select(kvp => kvp.Value).OfType(); + var orderedInlineArrayTypes = _synthesizedInlineArrayTypes.OrderBy(kvp => kvp.Key).Select(kvp => (Cci.INestedTypeDefinition)kvp.Value); + _orderedNestedTypes = orderedProxyTypes.Concat(orderedInlineArrayTypes).AsImmutable(); } private bool IsFrozen => _frozen != 0; @@ -300,6 +311,13 @@ internal bool TryAddSynthesizedMethod(Cci.IMethodDefinition method) #nullable enable } + internal bool TryAddSynthesizedType(Cci.INamedTypeDefinition type) + { + Debug.Assert(!IsFrozen); + Debug.Assert(type.Name is { }); + return _synthesizedInlineArrayTypes.TryAdd(type.Name, type); + } + public override IEnumerable GetFields(EmitContext context) { Debug.Assert(IsFrozen); @@ -320,10 +338,16 @@ internal bool TryAddSynthesizedMethod(Cci.IMethodDefinition method) return method; } + internal Cci.INamedTypeDefinition? GetType(string name) + { + _synthesizedInlineArrayTypes.TryGetValue(name, out var type); + return type; + } + public override IEnumerable GetNestedTypes(EmitContext context) { Debug.Assert(IsFrozen); - return _orderedProxyTypes.OfType(); + return _orderedNestedTypes; } public override string ToString() => this.Name; diff --git a/src/Compilers/Core/Portable/WellKnownMember.cs b/src/Compilers/Core/Portable/WellKnownMember.cs index 567b7a28023f0..c5d5c8212730c 100644 --- a/src/Compilers/Core/Portable/WellKnownMember.cs +++ b/src/Compilers/Core/Portable/WellKnownMember.cs @@ -491,6 +491,7 @@ internal enum WellKnownMember System_Span_T__get_Item, System_Span_T__get_Length, System_Span_T__Slice_Int_Int, + System_Span_T__op_Implicit_Span, System_ReadOnlySpan_T__ctor_Pointer, System_ReadOnlySpan_T__ctor_Array, diff --git a/src/Compilers/Core/Portable/WellKnownMembers.cs b/src/Compilers/Core/Portable/WellKnownMembers.cs index 7d6d3ff7cb1c2..bca4576665fcc 100644 --- a/src/Compilers/Core/Portable/WellKnownMembers.cs +++ b/src/Compilers/Core/Portable/WellKnownMembers.cs @@ -3412,6 +3412,20 @@ static WellKnownMembers() (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Int32, (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Int32, + // System_Span_T__op_Implicit_Span + (byte)(MemberFlags.Method | MemberFlags.Static), // Flags + (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Span_T - WellKnownType.ExtSentinel), // DeclaringTypeId + 0, // Arity + 1, // Method Signature + (byte)SignatureTypeCode.GenericTypeInstance, // Return Type + (byte)SignatureTypeCode.TypeHandle, (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_ReadOnlySpan_T - WellKnownType.ExtSentinel), + 1, + (byte)SignatureTypeCode.GenericTypeParameter, 0, + (byte)SignatureTypeCode.GenericTypeInstance, + (byte)SignatureTypeCode.TypeHandle, (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Span_T - WellKnownType.ExtSentinel), + 1, + (byte)SignatureTypeCode.GenericTypeParameter, 0, + // System_ReadOnlySpan_T__ctor_Pointer (byte)(MemberFlags.Constructor), // Flags (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_ReadOnlySpan_T - WellKnownType.ExtSentinel), // DeclaringTypeId @@ -4489,6 +4503,7 @@ static WellKnownMembers() "get_Item", // System_Span_T__get_Item "get_Length", // System_Span_T__get_Length "Slice", // System_Span_T__Slice_Int_Int + "op_Implicit", // System_Span_T__op_Implicit_Span ".ctor", // System_ReadOnlySpan_T__ctor_Pointer ".ctor", // System_ReadOnlySpan_T__ctor_Array ".ctor", // System_ReadOnlySpan_T__ctor_Array_Start_Length diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb index af42a03164159..73d897398fb60 100644 --- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb @@ -694,6 +694,7 @@ End Namespace WellKnownMember.System_Span_T__get_Item, WellKnownMember.System_Span_T__get_Length, WellKnownMember.System_Span_T__Slice_Int_Int, + WellKnownMember.System_Span_T__op_Implicit_Span, WellKnownMember.System_ReadOnlySpan_T__ctor_Pointer, WellKnownMember.System_ReadOnlySpan_T__ctor_Array, WellKnownMember.System_ReadOnlySpan_T__ctor_Array_Start_Length, @@ -891,6 +892,7 @@ End Namespace WellKnownMember.System_Span_T__get_Item, WellKnownMember.System_Span_T__get_Length, WellKnownMember.System_Span_T__Slice_Int_Int, + WellKnownMember.System_Span_T__op_Implicit_Span, WellKnownMember.System_ReadOnlySpan_T__ctor_Pointer, WellKnownMember.System_ReadOnlySpan_T__ctor_Array, WellKnownMember.System_ReadOnlySpan_T__ctor_Array_Start_Length, From 56afdf68410ddea7e4d4ed774508e63945e1737d Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Thu, 27 Jul 2023 16:22:48 -0700 Subject: [PATCH 02/14] Address PROTOTYPE comments --- .../LocalRewriter_CollectionExpression.cs | 46 +-- .../SynthesizedInlineArrayTypeSymbol.cs | 6 +- .../Semantics/CollectionExpressionTests.cs | 272 +++++++++++++++--- 3 files changed, 264 insertions(+), 60 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs index 7d51aa4622d4c..ab9923e7120bc 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs @@ -18,22 +18,31 @@ internal sealed partial class LocalRewriter Debug.Assert(!_inExpressionLambda); Debug.Assert(node.Type is { }); - var collectionTypeKind = ConversionsBase.GetCollectionExpressionTypeKind(_compilation, node.Type, out var elementType); - switch (collectionTypeKind) + var previousSyntax = _factory.Syntax; + _factory.Syntax = node.Syntax; + try { - case CollectionExpressionTypeKind.CollectionInitializer: - return VisitCollectionInitializerCollectionExpression(node, node.Type); - case CollectionExpressionTypeKind.Array: - case CollectionExpressionTypeKind.Span: - case CollectionExpressionTypeKind.ReadOnlySpan: - Debug.Assert(elementType is { }); - return VisitArrayOrSpanCollectionExpression(node, node.Type, TypeWithAnnotations.Create(elementType)); - case CollectionExpressionTypeKind.CollectionBuilder: - return VisitCollectionBuilderCollectionExpression(node); - case CollectionExpressionTypeKind.ListInterface: - return VisitListInterfaceCollectionExpression(node); - default: - throw ExceptionUtilities.UnexpectedValue(collectionTypeKind); + var collectionTypeKind = ConversionsBase.GetCollectionExpressionTypeKind(_compilation, node.Type, out var elementType); + switch (collectionTypeKind) + { + case CollectionExpressionTypeKind.CollectionInitializer: + return VisitCollectionInitializerCollectionExpression(node, node.Type); + case CollectionExpressionTypeKind.Array: + case CollectionExpressionTypeKind.Span: + case CollectionExpressionTypeKind.ReadOnlySpan: + Debug.Assert(elementType is { }); + return VisitArrayOrSpanCollectionExpression(node, node.Type, TypeWithAnnotations.Create(elementType)); + case CollectionExpressionTypeKind.CollectionBuilder: + return VisitCollectionBuilderCollectionExpression(node); + case CollectionExpressionTypeKind.ListInterface: + return VisitListInterfaceCollectionExpression(node); + default: + throw ExceptionUtilities.UnexpectedValue(collectionTypeKind); + } + } + finally + { + _factory.Syntax = previousSyntax; } } @@ -174,10 +183,10 @@ private BoundExpression VisitCollectionBuilderCollectionExpression(BoundCollecti var sideEffects = ArrayBuilder.GetInstance(); BoundExpression span; - // PROTOTYPE: Check also ReadOnlySpan parameter is not [UnscopedRef]. if (elements.Length > 0 && !elements.Any(i => i is BoundCollectionExpressionSpreadElement) - && _compilation.Assembly.RuntimeSupportsInlineArrayTypes) + && _compilation.Assembly.RuntimeSupportsInlineArrayTypes + && (!constructMethod.ReturnType.IsRefLikeType || constructMethod.Parameters[0].EffectiveScope == ScopedKind.ScopedValue)) { span = CreateAndPopulateInlineArray(syntax, elementType, elements, locals, sideEffects); } @@ -244,12 +253,11 @@ private BoundExpression CreateAndPopulateInlineArray( } // Get a span to the inline array. - var spanType = _factory.WellKnownType(WellKnownType.System_Span_T); // PROTOTYPE: Test missing type. + var spanType = _factory.WellKnownType(WellKnownType.System_Span_T); var inlineArrayAsSpan = _factory.ModuleBuilderOpt.EnsureInlineArrayAsSpanExists(syntax, spanType, intType, _diagnostics.DiagnosticBag); inlineArrayAsSpan = inlineArrayAsSpan.Construct(ImmutableArray.Create(TypeWithAnnotations.Create(inlineArrayType), elementType)); spanType = spanType.Construct(ImmutableArray.Create(elementType)); - // PROTOTYPE: Test missing operator. var spanOperator = _factory.WellKnownMethod(WellKnownMember.System_Span_T__op_Implicit_Span).AsMember(spanType); return _factory.Call( receiver: null, diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInlineArrayTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInlineArrayTypeSymbol.cs index dc6cdfce9c923..5f1782f830415 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInlineArrayTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInlineArrayTypeSymbol.cs @@ -51,7 +51,7 @@ internal SynthesizedInlineArrayTypeSymbol(SourceModuleSymbol containingModule, s public override bool IsSerializable => false; - public override bool AreLocalsZeroed => true; // PROTOTYPE: Is this correct? + public override bool AreLocalsZeroed => true; public override TypeKind TypeKind => TypeKind.Struct; @@ -83,7 +83,7 @@ internal SynthesizedInlineArrayTypeSymbol(SourceModuleSymbol containingModule, s internal override FileIdentifier? AssociatedFileIdentifier => null; - internal override bool MangleName => false; // PROTOTYPE: Is this correct? + internal override bool MangleName => false; internal override bool HasDeclaredRequiredMembers => false; @@ -99,7 +99,7 @@ internal SynthesizedInlineArrayTypeSymbol(SourceModuleSymbol containingModule, s internal override bool ShouldAddWinRTMembers => false; - internal override TypeLayout Layout => default; // PROTOTYPE: Is this correct? + internal override TypeLayout Layout => default; internal override CharSet MarshallingCharSet => DefaultMarshallingCharSet; diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index be5c37c59f96c..74c0e73c7b127 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -4,6 +4,7 @@ #nullable disable +using System.Collections.Immutable; using System.Linq; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Symbols.Retargeting; @@ -6067,7 +6068,111 @@ .maxstack 4 """); } - // PROTOTYPE: Test sharing synthesized type across all uses within the same assembly, but not across assemblies. + [ConditionalFact(typeof(CoreClrOnly))] + public void CollectionBuilder_InlineArrayTypes() + { + string sourceA = """ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Runtime.CompilerServices; + [CollectionBuilder(typeof(MyCollectionBuilder), nameof(MyCollectionBuilder.Create))] + public struct MyCollection : IEnumerable + { + private readonly List _list; + public MyCollection(List list) { _list = list; } + public IEnumerator GetEnumerator() => _list.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } + public class MyCollectionBuilder + { + public static MyCollection Create(ReadOnlySpan items) + { + return new MyCollection(new List(items.ToArray())); + } + } + class A + { + static void M() + { + MyCollection x; + x = []; + x = [null, null]; + x = [1, 2, 3]; + } + } + """; + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); + CompileAndVerify( + comp, + symbolValidator: module => + { + AssertEx.Equal(new[] { "$InlineArray2", "$InlineArray3" }, getInlineArrayTypeNames(module)); + }, + verify: Verification.Skipped); + var refA = comp.EmitToImageReference(); + + string sourceB = """ + class B + { + static void M(MyCollection c) + { + } + static void M1() + { + M([1]); + } + static void M2() + { + M([4, 5, 6]); + M(["a"]); + M(["b"]); + } + } + """; + comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); + CompileAndVerify( + comp, + symbolValidator: module => + { + AssertEx.Equal(new[] { "$InlineArray1", "$InlineArray3" }, getInlineArrayTypeNames(module)); + }, + verify: Verification.Skipped); + + const int n = 1025; + var builder = new System.Text.StringBuilder(); + for (int i = 0; i < n; i++) + { + if (i > 0) builder.Append(", "); + builder.Append(i); + } + string sourceC = $$""" + using System; + using System.Linq; + class Program + { + static void Main() + { + MyCollection c = ([{{builder.ToString()}}]); + Console.WriteLine(c.Count()); + } + } + """; + comp = CreateCompilation(sourceC, references: new[] { refA }, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe); + CompileAndVerify( + comp, + symbolValidator: module => + { + AssertEx.Equal(new[] { $"$InlineArray{n}" }, getInlineArrayTypeNames(module)); + }, + verify: Verification.Skipped, + expectedOutput: $"{n}"); + + static ImmutableArray getInlineArrayTypeNames(ModuleSymbol module) + { + return module.GlobalNamespace.GetTypeMembers().WhereAsArray(t => t.Name.StartsWith("$InlineArray")).SelectAsArray(t => t.Name); + } + } [CombinatorialData] [ConditionalTheory(typeof(CoreClrOnly))] @@ -6115,42 +6220,74 @@ static MyCollection F() } """; - var verifier = CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "1, 2, 3, "); - // PROTOTYPE: Use heap for non-scoped case. - verifier.VerifyIL("Program.F", - $$""" - { - // Code size 72 (0x48) - .maxstack 2 - .locals init ($InlineArray3 V_0) - IL_0000: ldloca.s V_0 - IL_0002: initobj "$InlineArray3" - IL_0008: ldloca.s V_0 - IL_000a: ldc.i4.0 - IL_000b: call "InlineArrayElementRef<$InlineArray3, object>(ref $InlineArray3, int)" - IL_0010: ldc.i4.1 - IL_0011: box "int" - IL_0016: stind.ref - IL_0017: ldloca.s V_0 - IL_0019: ldc.i4.1 - IL_001a: call "InlineArrayElementRef<$InlineArray3, object>(ref $InlineArray3, int)" - IL_001f: ldc.i4.2 - IL_0020: box "int" - IL_0025: stind.ref - IL_0026: ldloca.s V_0 - IL_0028: ldc.i4.2 - IL_0029: call "InlineArrayElementRef<$InlineArray3, object>(ref $InlineArray3, int)" - IL_002e: ldc.i4.3 - IL_002f: box "int" - IL_0034: stind.ref - IL_0035: ldloca.s V_0 - IL_0037: ldc.i4.3 - IL_0038: call "InlineArrayAsSpan<$InlineArray3, object>(ref $InlineArray3, int)" - IL_003d: call "System.ReadOnlySpan System.Span.op_Implicit(System.Span)" - IL_0042: call "MyCollection MyCollectionBuilder.Create({{qualifier}}System.ReadOnlySpan)" - IL_0047: ret - } - """); + var verifier = CompileAndVerify(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "1, 2, 3, "); + if (useScoped) + { + verifier.VerifyIL("Program.F", + $$""" + { + // Code size 72 (0x48) + .maxstack 2 + .locals init ($InlineArray3 V_0) + IL_0000: ldloca.s V_0 + IL_0002: initobj "$InlineArray3" + IL_0008: ldloca.s V_0 + IL_000a: ldc.i4.0 + IL_000b: call "InlineArrayElementRef<$InlineArray3, object>(ref $InlineArray3, int)" + IL_0010: ldc.i4.1 + IL_0011: box "int" + IL_0016: stind.ref + IL_0017: ldloca.s V_0 + IL_0019: ldc.i4.1 + IL_001a: call "InlineArrayElementRef<$InlineArray3, object>(ref $InlineArray3, int)" + IL_001f: ldc.i4.2 + IL_0020: box "int" + IL_0025: stind.ref + IL_0026: ldloca.s V_0 + IL_0028: ldc.i4.2 + IL_0029: call "InlineArrayElementRef<$InlineArray3, object>(ref $InlineArray3, int)" + IL_002e: ldc.i4.3 + IL_002f: box "int" + IL_0034: stind.ref + IL_0035: ldloca.s V_0 + IL_0037: ldc.i4.3 + IL_0038: call "InlineArrayAsSpan<$InlineArray3, object>(ref $InlineArray3, int)" + IL_003d: call "System.ReadOnlySpan System.Span.op_Implicit(System.Span)" + IL_0042: call "MyCollection MyCollectionBuilder.Create({{qualifier}}System.ReadOnlySpan)" + IL_0047: ret + } + """); + } + else + { + verifier.VerifyIL("Program.F", + $$""" + { + // Code size 44 (0x2c) + .maxstack 4 + IL_0000: ldc.i4.3 + IL_0001: newarr "object" + IL_0006: dup + IL_0007: ldc.i4.0 + IL_0008: ldc.i4.1 + IL_0009: box "int" + IL_000e: stelem.ref + IL_000f: dup + IL_0010: ldc.i4.1 + IL_0011: ldc.i4.2 + IL_0012: box "int" + IL_0017: stelem.ref + IL_0018: dup + IL_0019: ldc.i4.2 + IL_001a: ldc.i4.3 + IL_001b: box "int" + IL_0020: stelem.ref + IL_0021: newobj "System.ReadOnlySpan..ctor(object[])" + IL_0026: call "MyCollection MyCollectionBuilder.Create(System.ReadOnlySpan)" + IL_002b: ret + } + """); + } } [CombinatorialData] @@ -9067,7 +9204,12 @@ static List GetItems(MyCollection c) } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "[], [1, 2, 3], "); + CompileAndVerify( + new[] { sourceB, s_collectionExtensions }, + references: new[] { refA }, + targetFramework: TargetFramework.Net80, + verify: builderParameterModifier == "scoped" ? Verification.Fails : Verification.Passes, + expectedOutput: "[], [1, 2, 3], "); } [ConditionalFact(typeof(CoreClrOnly))] @@ -9114,6 +9256,60 @@ static void Main() Diagnostic(ErrorCode.ERR_EscapeVariable, "items").WithArguments("scoped System.ReadOnlySpan items").WithLocation(16, 82)); } + [CombinatorialData] + [ConditionalTheory(typeof(CoreClrOnly))] + public void CollectionBuilder_MissingSpanMembers(bool useCompilationReference) + { + string sourceA = """ + using System; + using System.Collections.Generic; + using System.Runtime.CompilerServices; + [CollectionBuilder(typeof(MyCollectionBuilder), nameof(MyCollectionBuilder.Create))] + public struct MyCollection + { + public IEnumerator GetEnumerator() => default; + } + public class MyCollectionBuilder + { + public static MyCollection Create(ReadOnlySpan items) => default; + } + """; + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); + var refA = AsReference(comp, useCompilationReference); + + string sourceB = """ + #pragma warning disable 219 + class Program + { + static void Main() + { + MyCollection x = []; + MyCollection y = [1, 2, 3]; + MyCollection z = new(); + } + } + """; + comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); + comp.MakeTypeMissing(WellKnownType.System_Span_T); + comp.VerifyEmitDiagnostics( + // error CS0656: Missing compiler required member 'System.Runtime.InteropServices.MemoryMarshal.CreateSpan' + // + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "").WithArguments("System.Runtime.InteropServices.MemoryMarshal", "CreateSpan").WithLocation(1, 1), + // (7,31): error CS0518: Predefined type 'System.Span`1' is not defined or imported + // MyCollection y = [1, 2, 3]; + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "[1, 2, 3]").WithArguments("System.Span`1").WithLocation(7, 31), + // (7,31): error CS0656: Missing compiler required member 'System.Span`1.op_Implicit' + // MyCollection y = [1, 2, 3]; + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "[1, 2, 3]").WithArguments("System.Span`1", "op_Implicit").WithLocation(7, 31)); + + comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); + comp.MakeMemberMissing(WellKnownMember.System_Span_T__op_Implicit_Span); + comp.VerifyEmitDiagnostics( + // (7,31): error CS0656: Missing compiler required member 'System.Span`1.op_Implicit' + // MyCollection y = [1, 2, 3]; + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "[1, 2, 3]").WithArguments("System.Span`1", "op_Implicit").WithLocation(7, 31)); + } + [ConditionalFact(typeof(CoreClrOnly))] public void CollectionBuilder_Async() { From c5002c0059c6b1b24c97e257aebe82ffba9d29a1 Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Thu, 27 Jul 2023 23:21:13 -0700 Subject: [PATCH 03/14] Address feedback --- .../LocalRewriter_CollectionExpression.cs | 4 +- .../SynthesizedInlineArrayTypeSymbol.cs | 12 ++- .../Semantics/CollectionExpressionTests.cs | 82 +++++++++---------- .../CodeGen/PrivateImplementationDetails.cs | 2 +- .../Core/Portable/WellKnownMembers.cs | 2 +- 5 files changed, 50 insertions(+), 52 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs index ab9923e7120bc..b44f2c9c41aec 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs @@ -235,8 +235,8 @@ private BoundExpression CreateAndPopulateInlineArray( Debug.Assert(inlineArrayType.HasInlineArrayAttribute(out int inlineArrayLength) && inlineArrayLength == arrayLength); var intType = _factory.SpecialType(SpecialType.System_Int32); - var elementRef = _factory.ModuleBuilderOpt.EnsureInlineArrayElementRefExists(syntax, intType, _diagnostics.DiagnosticBag); - elementRef = elementRef.Construct(ImmutableArray.Create(TypeWithAnnotations.Create(inlineArrayType), elementType)); + MethodSymbol elementRef = _factory.ModuleBuilderOpt.EnsureInlineArrayElementRefExists(syntax, intType, _diagnostics.DiagnosticBag). + Construct(ImmutableArray.Create(TypeWithAnnotations.Create(inlineArrayType), elementType)); // Create an inline array and assign to a local. BoundAssignmentOperator assignmentToTemp; diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInlineArrayTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInlineArrayTypeSymbol.cs index 5f1782f830415..75495b1888d5c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInlineArrayTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInlineArrayTypeSymbol.cs @@ -18,19 +18,17 @@ internal sealed class SynthesizedInlineArrayTypeSymbol : NamedTypeSymbol private readonly ModuleSymbol _containingModule; private readonly int _arrayLength; private readonly MethodSymbol _inlineArrayAttributeConstructor; - private readonly ImmutableArray _fields; + private readonly FieldSymbol _field; internal SynthesizedInlineArrayTypeSymbol(SourceModuleSymbol containingModule, string name, int arrayLength, MethodSymbol inlineArrayAttributeConstructor) { Debug.Assert(arrayLength > 0); var typeParameter = new InlineArrayTypeParameterSymbol(this); - var field = new SynthesizedFieldSymbol(this, typeParameter, "_element0"); - _containingModule = containingModule; _arrayLength = arrayLength; _inlineArrayAttributeConstructor = inlineArrayAttributeConstructor; - _fields = ImmutableArray.Create(field); + _field = new SynthesizedFieldSymbol(this, typeParameter, "_element0"); Name = name; TypeParameters = ImmutableArray.Create(typeParameter); } @@ -69,7 +67,7 @@ internal SynthesizedInlineArrayTypeSymbol(SourceModuleSymbol containingModule, s public override ImmutableArray Locations => ImmutableArray.Empty; - public override ImmutableArray DeclaringSyntaxReferences => throw new NotImplementedException(); + public override ImmutableArray DeclaringSyntaxReferences => ImmutableArray.Empty; public override bool IsStatic => false; @@ -117,7 +115,7 @@ internal SynthesizedInlineArrayTypeSymbol(SourceModuleSymbol containingModule, s internal override ObsoleteAttributeData? ObsoleteAttributeData => null; - public override ImmutableArray GetMembers() => ImmutableArray.Empty; + public override ImmutableArray GetMembers() => ImmutableArray.Create(_field); public override ImmutableArray GetMembers(string name) => GetMembers().WhereAsArray(m => m.Name == name); @@ -143,7 +141,7 @@ internal SynthesizedInlineArrayTypeSymbol(SourceModuleSymbol containingModule, s internal override ImmutableArray GetEarlyAttributeDecodingMembers(string name) => GetMembers(name); - internal override IEnumerable GetFieldsToEmit() => _fields; + internal override IEnumerable GetFieldsToEmit() => SpecializedCollections.SingletonEnumerable(_field); internal override ImmutableArray GetInterfacesToEmit() => ImmutableArray.Empty; diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index 74c0e73c7b127..1620b5cbfc032 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -5736,27 +5736,27 @@ .maxstack 1 { // Code size 57 (0x39) .maxstack 2 - .locals init ($InlineArray3 V_0) + .locals init (__InlineArray3 V_0) IL_0000: ldloca.s V_0 - IL_0002: initobj "$InlineArray3" + IL_0002: initobj "__InlineArray3" IL_0008: ldloca.s V_0 IL_000a: ldc.i4.0 - IL_000b: call "InlineArrayElementRef<$InlineArray3, int>(ref $InlineArray3, int)" + IL_000b: call "InlineArrayElementRef<__InlineArray3, int>(ref __InlineArray3, int)" IL_0010: ldc.i4.0 IL_0011: stind.i4 IL_0012: ldloca.s V_0 IL_0014: ldc.i4.1 - IL_0015: call "InlineArrayElementRef<$InlineArray3, int>(ref $InlineArray3, int)" + IL_0015: call "InlineArrayElementRef<__InlineArray3, int>(ref __InlineArray3, int)" IL_001a: ldc.i4.1 IL_001b: stind.i4 IL_001c: ldloca.s V_0 IL_001e: ldc.i4.2 - IL_001f: call "InlineArrayElementRef<$InlineArray3, int>(ref $InlineArray3, int)" + IL_001f: call "InlineArrayElementRef<__InlineArray3, int>(ref __InlineArray3, int)" IL_0024: ldc.i4.2 IL_0025: stind.i4 IL_0026: ldloca.s V_0 IL_0028: ldc.i4.3 - IL_0029: call "InlineArrayAsSpan<$InlineArray3, int>(ref $InlineArray3, int)" + IL_0029: call "InlineArrayAsSpan<__InlineArray3, int>(ref __InlineArray3, int)" IL_002e: call "System.ReadOnlySpan System.Span.op_Implicit(System.Span)" IL_0033: call "MyCollection MyCollectionBuilder.Create(System.ReadOnlySpan)" IL_0038: ret @@ -5767,28 +5767,28 @@ .locals init ($InlineArray3 V_0) { // Code size 62 (0x3e) .maxstack 2 - .locals init ($InlineArray3 V_0) + .locals init (__InlineArray3 V_0) IL_0000: ldloca.s V_0 - IL_0002: initobj "$InlineArray3" + IL_0002: initobj "__InlineArray3" IL_0008: ldloca.s V_0 IL_000a: ldc.i4.0 - IL_000b: call "InlineArrayElementRef<$InlineArray3, object>(ref $InlineArray3, int)" + IL_000b: call "InlineArrayElementRef<__InlineArray3, object>(ref __InlineArray3, int)" IL_0010: ldarg.0 IL_0011: box "int" IL_0016: stind.ref IL_0017: ldloca.s V_0 IL_0019: ldc.i4.1 - IL_001a: call "InlineArrayElementRef<$InlineArray3, object>(ref $InlineArray3, int)" + IL_001a: call "InlineArrayElementRef<__InlineArray3, object>(ref __InlineArray3, int)" IL_001f: ldarg.1 IL_0020: stind.ref IL_0021: ldloca.s V_0 IL_0023: ldc.i4.2 - IL_0024: call "InlineArrayElementRef<$InlineArray3, object>(ref $InlineArray3, int)" + IL_0024: call "InlineArrayElementRef<__InlineArray3, object>(ref __InlineArray3, int)" IL_0029: ldnull IL_002a: stind.ref IL_002b: ldloca.s V_0 IL_002d: ldc.i4.3 - IL_002e: call "InlineArrayAsSpan<$InlineArray3, object>(ref $InlineArray3, int)" + IL_002e: call "InlineArrayAsSpan<__InlineArray3, object>(ref __InlineArray3, int)" IL_0033: call "System.ReadOnlySpan System.Span.op_Implicit(System.Span)" IL_0038: call "MyCollection MyCollectionBuilder.Create(System.ReadOnlySpan)" IL_003d: ret @@ -5915,7 +5915,7 @@ static void Main() comp, symbolValidator: module => { - var type = module.GlobalNamespace.GetTypeMembers("$InlineArray3").SingleOrDefault(); + var type = module.GlobalNamespace.GetTypeMembers("__InlineArray3").SingleOrDefault(); if (targetFramework == TargetFramework.Net80) { Assert.NotNull(type); @@ -5934,28 +5934,28 @@ static void Main() { // Code size 79 (0x4f) .maxstack 2 - .locals init ($InlineArray3 V_0) + .locals init (__InlineArray3 V_0) IL_0000: ldloca.s V_0 - IL_0002: initobj "$InlineArray3" + IL_0002: initobj "__InlineArray3" IL_0008: ldloca.s V_0 IL_000a: ldc.i4.0 - IL_000b: call "InlineArrayElementRef<$InlineArray3, int?>(ref $InlineArray3, int)" + IL_000b: call "InlineArrayElementRef<__InlineArray3, int?>(ref __InlineArray3, int)" IL_0010: ldc.i4.1 IL_0011: newobj "int?..ctor(int)" IL_0016: stobj "int?" IL_001b: ldloca.s V_0 IL_001d: ldc.i4.1 - IL_001e: call "InlineArrayElementRef<$InlineArray3, int?>(ref $InlineArray3, int)" + IL_001e: call "InlineArrayElementRef<__InlineArray3, int?>(ref __InlineArray3, int)" IL_0023: ldc.i4.2 IL_0024: newobj "int?..ctor(int)" IL_0029: stobj "int?" IL_002e: ldloca.s V_0 IL_0030: ldc.i4.2 - IL_0031: call "InlineArrayElementRef<$InlineArray3, int?>(ref $InlineArray3, int)" + IL_0031: call "InlineArrayElementRef<__InlineArray3, int?>(ref __InlineArray3, int)" IL_0036: initobj "int?" IL_003c: ldloca.s V_0 IL_003e: ldc.i4.3 - IL_003f: call "InlineArrayAsSpan<$InlineArray3, int?>(ref $InlineArray3, int)" + IL_003f: call "InlineArrayAsSpan<__InlineArray3, int?>(ref __InlineArray3, int)" IL_0044: call "System.ReadOnlySpan System.Span.op_Implicit(System.Span)" IL_0049: call "MyCollection MyCollectionBuilder.Create(System.ReadOnlySpan)" IL_004e: ret @@ -6040,7 +6040,7 @@ static void Main() comp, symbolValidator: module => { - var type = module.GlobalNamespace.GetTypeMembers("$InlineArray3").SingleOrDefault(); + var type = module.GlobalNamespace.GetTypeMembers("__InlineArray3").SingleOrDefault(); Assert.Null(type); }, expectedOutput: "[1, 2, null], "); @@ -6107,7 +6107,7 @@ static void M() comp, symbolValidator: module => { - AssertEx.Equal(new[] { "$InlineArray2", "$InlineArray3" }, getInlineArrayTypeNames(module)); + AssertEx.Equal(new[] { "__InlineArray2", "__InlineArray3" }, getInlineArrayTypeNames(module)); }, verify: Verification.Skipped); var refA = comp.EmitToImageReference(); @@ -6135,7 +6135,7 @@ static void M2() comp, symbolValidator: module => { - AssertEx.Equal(new[] { "$InlineArray1", "$InlineArray3" }, getInlineArrayTypeNames(module)); + AssertEx.Equal(new[] { "__InlineArray1", "__InlineArray3" }, getInlineArrayTypeNames(module)); }, verify: Verification.Skipped); @@ -6153,7 +6153,7 @@ class Program { static void Main() { - MyCollection c = ([{{builder.ToString()}}]); + MyCollection c = [{{builder.ToString()}}]; Console.WriteLine(c.Count()); } } @@ -6163,14 +6163,14 @@ static void Main() comp, symbolValidator: module => { - AssertEx.Equal(new[] { $"$InlineArray{n}" }, getInlineArrayTypeNames(module)); + AssertEx.Equal(new[] { $"__InlineArray{n}" }, getInlineArrayTypeNames(module)); }, verify: Verification.Skipped, expectedOutput: $"{n}"); static ImmutableArray getInlineArrayTypeNames(ModuleSymbol module) { - return module.GlobalNamespace.GetTypeMembers().WhereAsArray(t => t.Name.StartsWith("$InlineArray")).SelectAsArray(t => t.Name); + return module.GlobalNamespace.GetTypeMembers().WhereAsArray(t => t.Name.StartsWith("__InlineArray")).SelectAsArray(t => t.Name); } } @@ -6228,30 +6228,30 @@ static MyCollection F() { // Code size 72 (0x48) .maxstack 2 - .locals init ($InlineArray3 V_0) + .locals init (__InlineArray3 V_0) IL_0000: ldloca.s V_0 - IL_0002: initobj "$InlineArray3" + IL_0002: initobj "__InlineArray3" IL_0008: ldloca.s V_0 IL_000a: ldc.i4.0 - IL_000b: call "InlineArrayElementRef<$InlineArray3, object>(ref $InlineArray3, int)" + IL_000b: call "InlineArrayElementRef<__InlineArray3, object>(ref __InlineArray3, int)" IL_0010: ldc.i4.1 IL_0011: box "int" IL_0016: stind.ref IL_0017: ldloca.s V_0 IL_0019: ldc.i4.1 - IL_001a: call "InlineArrayElementRef<$InlineArray3, object>(ref $InlineArray3, int)" + IL_001a: call "InlineArrayElementRef<__InlineArray3, object>(ref __InlineArray3, int)" IL_001f: ldc.i4.2 IL_0020: box "int" IL_0025: stind.ref IL_0026: ldloca.s V_0 IL_0028: ldc.i4.2 - IL_0029: call "InlineArrayElementRef<$InlineArray3, object>(ref $InlineArray3, int)" + IL_0029: call "InlineArrayElementRef<__InlineArray3, object>(ref __InlineArray3, int)" IL_002e: ldc.i4.3 IL_002f: box "int" IL_0034: stind.ref IL_0035: ldloca.s V_0 IL_0037: ldc.i4.3 - IL_0038: call "InlineArrayAsSpan<$InlineArray3, object>(ref $InlineArray3, int)" + IL_0038: call "InlineArrayAsSpan<__InlineArray3, object>(ref __InlineArray3, int)" IL_003d: call "System.ReadOnlySpan System.Span.op_Implicit(System.Span)" IL_0042: call "MyCollection MyCollectionBuilder.Create({{qualifier}}System.ReadOnlySpan)" IL_0047: ret @@ -9377,8 +9377,8 @@ .locals init (int V_0, IL_000b: ldc.i4.1 IL_000c: beq IL_00cf IL_0011: ldarg.0 - IL_0012: ldflda "$InlineArray3 Program.d__1.<>7__wrap1" - IL_0017: initobj "$InlineArray3" + IL_0012: ldflda "__InlineArray3 Program.d__1.<>7__wrap1" + IL_0017: initobj "__InlineArray3" IL_001d: ldc.i4.1 IL_001e: call "System.Threading.Tasks.Task Program.F(int)" IL_0023: callvirt "System.Runtime.CompilerServices.TaskAwaiter System.Threading.Tasks.Task.GetAwaiter()" @@ -9415,15 +9415,15 @@ .locals init (int V_0, IL_0076: call "int System.Runtime.CompilerServices.TaskAwaiter.GetResult()" IL_007b: stloc.2 IL_007c: ldarg.0 - IL_007d: ldflda "$InlineArray3 Program.d__1.<>7__wrap1" + IL_007d: ldflda "__InlineArray3 Program.d__1.<>7__wrap1" IL_0082: ldc.i4.0 - IL_0083: call "InlineArrayElementRef<$InlineArray3, int>(ref $InlineArray3, int)" + IL_0083: call "InlineArrayElementRef<__InlineArray3, int>(ref __InlineArray3, int)" IL_0088: ldloc.2 IL_0089: stind.i4 IL_008a: ldarg.0 - IL_008b: ldflda "$InlineArray3 Program.d__1.<>7__wrap1" + IL_008b: ldflda "__InlineArray3 Program.d__1.<>7__wrap1" IL_0090: ldc.i4.1 - IL_0091: call "InlineArrayElementRef<$InlineArray3, int>(ref $InlineArray3, int)" + IL_0091: call "InlineArrayElementRef<__InlineArray3, int>(ref __InlineArray3, int)" IL_0096: ldc.i4.2 IL_0097: stind.i4 IL_0098: ldc.i4.3 @@ -9462,15 +9462,15 @@ .locals init (int V_0, IL_00ee: call "int System.Runtime.CompilerServices.TaskAwaiter.GetResult()" IL_00f3: stloc.3 IL_00f4: ldarg.0 - IL_00f5: ldflda "$InlineArray3 Program.d__1.<>7__wrap1" + IL_00f5: ldflda "__InlineArray3 Program.d__1.<>7__wrap1" IL_00fa: ldc.i4.2 - IL_00fb: call "InlineArrayElementRef<$InlineArray3, int>(ref $InlineArray3, int)" + IL_00fb: call "InlineArrayElementRef<__InlineArray3, int>(ref __InlineArray3, int)" IL_0100: ldloc.3 IL_0101: stind.i4 IL_0102: ldarg.0 - IL_0103: ldflda "$InlineArray3 Program.d__1.<>7__wrap1" + IL_0103: ldflda "__InlineArray3 Program.d__1.<>7__wrap1" IL_0108: ldc.i4.3 - IL_0109: call "InlineArrayAsSpan<$InlineArray3, int>(ref $InlineArray3, int)" + IL_0109: call "InlineArrayAsSpan<__InlineArray3, int>(ref __InlineArray3, int)" IL_010e: call "System.ReadOnlySpan System.Span.op_Implicit(System.Span)" IL_0113: call "MyCollection MyCollectionBuilder.Create(System.ReadOnlySpan)" IL_0118: stloc.1 diff --git a/src/Compilers/Core/Portable/CodeGen/PrivateImplementationDetails.cs b/src/Compilers/Core/Portable/CodeGen/PrivateImplementationDetails.cs index a56e447776a25..ed00a288ba80c 100644 --- a/src/Compilers/Core/Portable/CodeGen/PrivateImplementationDetails.cs +++ b/src/Compilers/Core/Portable/CodeGen/PrivateImplementationDetails.cs @@ -138,7 +138,7 @@ private static string GetClassName(string moduleName, int submissionSlotIndex, b internal static string GetInlineArrayTypeName(int arrayLength) { Debug.Assert(arrayLength > 0); - return $"$InlineArray{arrayLength}"; + return $"__InlineArray{arrayLength}"; } internal void Freeze() diff --git a/src/Compilers/Core/Portable/WellKnownMembers.cs b/src/Compilers/Core/Portable/WellKnownMembers.cs index bca4576665fcc..c43c31e8495ed 100644 --- a/src/Compilers/Core/Portable/WellKnownMembers.cs +++ b/src/Compilers/Core/Portable/WellKnownMembers.cs @@ -3413,7 +3413,7 @@ static WellKnownMembers() (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Int32, // System_Span_T__op_Implicit_Span - (byte)(MemberFlags.Method | MemberFlags.Static), // Flags + (byte)(MemberFlags.Method | MemberFlags.Static), // Flags (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Span_T - WellKnownType.ExtSentinel), // DeclaringTypeId 0, // Arity 1, // Method Signature From b47e209a2f4b488f97360114ce8762dad4a53c60 Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Fri, 28 Jul 2023 06:51:02 -0700 Subject: [PATCH 04/14] Address feedback --- .../LocalRewriter_CollectionExpression.cs | 11 +++++++--- .../SynthesizedInlineArrayTypeSymbol.cs | 21 ++++++++++++------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs index b44f2c9c41aec..9228d3e6945c7 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs @@ -239,11 +239,16 @@ private BoundExpression CreateAndPopulateInlineArray( Construct(ImmutableArray.Create(TypeWithAnnotations.Create(inlineArrayType), elementType)); // Create an inline array and assign to a local. + // var tmp = new __InlineArrayN(); BoundAssignmentOperator assignmentToTemp; BoundLocal inlineArrayLocal = _factory.StoreToTemp(new BoundDefaultExpression(syntax, inlineArrayType), out assignmentToTemp, isKnownToReferToTempIfReferenceType: true); sideEffects.Add(assignmentToTemp); locals.Add(inlineArrayLocal.LocalSymbol); + // Populate the inline array. + // InlineArrayElementRef<__InlineArrayN, T>(ref tmp, 0) = element0; + // InlineArrayElementRef<__InlineArrayN, T>(ref tmp, 1) = element1; + // ... for (int i = 0; i < arrayLength; i++) { var element = VisitExpression(elements[i]); @@ -253,11 +258,11 @@ private BoundExpression CreateAndPopulateInlineArray( } // Get a span to the inline array. - var spanType = _factory.WellKnownType(WellKnownType.System_Span_T); - var inlineArrayAsSpan = _factory.ModuleBuilderOpt.EnsureInlineArrayAsSpanExists(syntax, spanType, intType, _diagnostics.DiagnosticBag); + // ... (ReadOnlySpan)InlineArrayAsSpan<__InlineArrayN, T>(ref tmp, N) + var inlineArrayAsSpan = _factory.ModuleBuilderOpt.EnsureInlineArrayAsSpanExists(syntax, _factory.WellKnownType(WellKnownType.System_Span_T), intType, _diagnostics.DiagnosticBag); inlineArrayAsSpan = inlineArrayAsSpan.Construct(ImmutableArray.Create(TypeWithAnnotations.Create(inlineArrayType), elementType)); - spanType = spanType.Construct(ImmutableArray.Create(elementType)); + var spanType = (NamedTypeSymbol)inlineArrayAsSpan.ReturnType; var spanOperator = _factory.WellKnownMethod(WellKnownMember.System_Span_T__op_Implicit_Span).AsMember(spanType); return _factory.Call( receiver: null, diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInlineArrayTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInlineArrayTypeSymbol.cs index 75495b1888d5c..7840c00bbf44f 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInlineArrayTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInlineArrayTypeSymbol.cs @@ -13,22 +13,31 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols { + /// + /// A synthesized type used during emit to allow temp locals of Span<T> + /// of a specific length where the span storage is on the stack. + /// + /// [InlineArray(N)] struct __InlineArrayN<T> { private T _element0; } + /// + /// internal sealed class SynthesizedInlineArrayTypeSymbol : NamedTypeSymbol { private readonly ModuleSymbol _containingModule; private readonly int _arrayLength; private readonly MethodSymbol _inlineArrayAttributeConstructor; - private readonly FieldSymbol _field; + private readonly ImmutableArray _fields; internal SynthesizedInlineArrayTypeSymbol(SourceModuleSymbol containingModule, string name, int arrayLength, MethodSymbol inlineArrayAttributeConstructor) { Debug.Assert(arrayLength > 0); var typeParameter = new InlineArrayTypeParameterSymbol(this); + var field = new SynthesizedFieldSymbol(this, typeParameter, "_element0"); + _containingModule = containingModule; _arrayLength = arrayLength; _inlineArrayAttributeConstructor = inlineArrayAttributeConstructor; - _field = new SynthesizedFieldSymbol(this, typeParameter, "_element0"); + _fields = ImmutableArray.Create(field); Name = name; TypeParameters = ImmutableArray.Create(typeParameter); } @@ -57,14 +66,12 @@ internal SynthesizedInlineArrayTypeSymbol(SourceModuleSymbol containingModule, s public override bool IsReadOnly => true; - public override Symbol? ContainingSymbol => null; + public override Symbol? ContainingSymbol => _containingModule.GlobalNamespace; internal override ModuleSymbol ContainingModule => _containingModule; public override AssemblySymbol ContainingAssembly => _containingModule.ContainingAssembly; - public override NamespaceSymbol ContainingNamespace => _containingModule.GlobalNamespace; - public override ImmutableArray Locations => ImmutableArray.Empty; public override ImmutableArray DeclaringSyntaxReferences => ImmutableArray.Empty; @@ -115,7 +122,7 @@ internal SynthesizedInlineArrayTypeSymbol(SourceModuleSymbol containingModule, s internal override ObsoleteAttributeData? ObsoleteAttributeData => null; - public override ImmutableArray GetMembers() => ImmutableArray.Create(_field); + public override ImmutableArray GetMembers() => ImmutableArray.CastUp(_fields); public override ImmutableArray GetMembers(string name) => GetMembers().WhereAsArray(m => m.Name == name); @@ -141,7 +148,7 @@ internal SynthesizedInlineArrayTypeSymbol(SourceModuleSymbol containingModule, s internal override ImmutableArray GetEarlyAttributeDecodingMembers(string name) => GetMembers(name); - internal override IEnumerable GetFieldsToEmit() => SpecializedCollections.SingletonEnumerable(_field); + internal override IEnumerable GetFieldsToEmit() => _fields; internal override ImmutableArray GetInterfacesToEmit() => ImmutableArray.Empty; From aefb9666928bf99fff66d343ae247e05a2dcc53b Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Fri, 28 Jul 2023 13:35:56 -0700 Subject: [PATCH 05/14] Rename WellKnownMember --- .../LocalRewriter/LocalRewriter_CollectionExpression.cs | 2 +- .../CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs | 2 +- .../CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs | 2 +- src/Compilers/Core/Portable/WellKnownMember.cs | 2 +- src/Compilers/Core/Portable/WellKnownMembers.cs | 4 ++-- .../Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb | 4 ++-- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs index 9228d3e6945c7..460198592d604 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs @@ -263,7 +263,7 @@ private BoundExpression CreateAndPopulateInlineArray( inlineArrayAsSpan = inlineArrayAsSpan.Construct(ImmutableArray.Create(TypeWithAnnotations.Create(inlineArrayType), elementType)); var spanType = (NamedTypeSymbol)inlineArrayAsSpan.ReturnType; - var spanOperator = _factory.WellKnownMethod(WellKnownMember.System_Span_T__op_Implicit_Span).AsMember(spanType); + var spanOperator = _factory.WellKnownMethod(WellKnownMember.System_Span_T__op_Implicit_ReadOnlySpan_Span).AsMember(spanType); return _factory.Call( receiver: null, spanOperator, diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index 1620b5cbfc032..f564660466dc3 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -9303,7 +9303,7 @@ static void Main() Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "[1, 2, 3]").WithArguments("System.Span`1", "op_Implicit").WithLocation(7, 31)); comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); - comp.MakeMemberMissing(WellKnownMember.System_Span_T__op_Implicit_Span); + comp.MakeMemberMissing(WellKnownMember.System_Span_T__op_Implicit_ReadOnlySpan_Span); comp.VerifyEmitDiagnostics( // (7,31): error CS0656: Missing compiler required member 'System.Span`1.op_Implicit' // MyCollection y = [1, 2, 3]; diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs index 9c23237a15bda..36b45b0ba9540 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs @@ -951,7 +951,7 @@ public void AllWellKnownTypeMembers() case WellKnownMember.System_Span_T__get_Item: case WellKnownMember.System_Span_T__get_Length: case WellKnownMember.System_Span_T__Slice_Int_Int: - case WellKnownMember.System_Span_T__op_Implicit_Span: + case WellKnownMember.System_Span_T__op_Implicit_ReadOnlySpan_Span: case WellKnownMember.System_ReadOnlySpan_T__ctor_Pointer: case WellKnownMember.System_ReadOnlySpan_T__ctor_Array: case WellKnownMember.System_ReadOnlySpan_T__ctor_Array_Start_Length: diff --git a/src/Compilers/Core/Portable/WellKnownMember.cs b/src/Compilers/Core/Portable/WellKnownMember.cs index c5d5c8212730c..cb7acd1604718 100644 --- a/src/Compilers/Core/Portable/WellKnownMember.cs +++ b/src/Compilers/Core/Portable/WellKnownMember.cs @@ -491,7 +491,7 @@ internal enum WellKnownMember System_Span_T__get_Item, System_Span_T__get_Length, System_Span_T__Slice_Int_Int, - System_Span_T__op_Implicit_Span, + System_Span_T__op_Implicit_ReadOnlySpan_Span, System_ReadOnlySpan_T__ctor_Pointer, System_ReadOnlySpan_T__ctor_Array, diff --git a/src/Compilers/Core/Portable/WellKnownMembers.cs b/src/Compilers/Core/Portable/WellKnownMembers.cs index c43c31e8495ed..6e3130110d256 100644 --- a/src/Compilers/Core/Portable/WellKnownMembers.cs +++ b/src/Compilers/Core/Portable/WellKnownMembers.cs @@ -3412,7 +3412,7 @@ static WellKnownMembers() (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Int32, (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Int32, - // System_Span_T__op_Implicit_Span + // System_Span_T__op_Implicit_ReadOnlySpan_Span (byte)(MemberFlags.Method | MemberFlags.Static), // Flags (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Span_T - WellKnownType.ExtSentinel), // DeclaringTypeId 0, // Arity @@ -4503,7 +4503,7 @@ static WellKnownMembers() "get_Item", // System_Span_T__get_Item "get_Length", // System_Span_T__get_Length "Slice", // System_Span_T__Slice_Int_Int - "op_Implicit", // System_Span_T__op_Implicit_Span + "op_Implicit", // System_Span_T__op_Implicit_ReadOnlySpan_Span ".ctor", // System_ReadOnlySpan_T__ctor_Pointer ".ctor", // System_ReadOnlySpan_T__ctor_Array ".ctor", // System_ReadOnlySpan_T__ctor_Array_Start_Length diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb index 73d897398fb60..0036ccb877721 100644 --- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb @@ -694,7 +694,7 @@ End Namespace WellKnownMember.System_Span_T__get_Item, WellKnownMember.System_Span_T__get_Length, WellKnownMember.System_Span_T__Slice_Int_Int, - WellKnownMember.System_Span_T__op_Implicit_Span, + WellKnownMember.System_Span_T__op_Implicit_ReadOnlySpan_Span, WellKnownMember.System_ReadOnlySpan_T__ctor_Pointer, WellKnownMember.System_ReadOnlySpan_T__ctor_Array, WellKnownMember.System_ReadOnlySpan_T__ctor_Array_Start_Length, @@ -892,7 +892,7 @@ End Namespace WellKnownMember.System_Span_T__get_Item, WellKnownMember.System_Span_T__get_Length, WellKnownMember.System_Span_T__Slice_Int_Int, - WellKnownMember.System_Span_T__op_Implicit_Span, + WellKnownMember.System_Span_T__op_Implicit_ReadOnlySpan_Span, WellKnownMember.System_ReadOnlySpan_T__ctor_Pointer, WellKnownMember.System_ReadOnlySpan_T__ctor_Array, WellKnownMember.System_ReadOnlySpan_T__ctor_Array_Start_Length, From 4cfe4e17ec8bd6ae4deafd3234f4fa2bf1ebbf4e Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Fri, 28 Jul 2023 13:52:03 -0700 Subject: [PATCH 06/14] Run tests on all platforms --- .../Semantics/CollectionExpressionTests.cs | 236 +++++++++--------- 1 file changed, 119 insertions(+), 117 deletions(-) diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index f564660466dc3..0bb3c4c82de1b 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -18,6 +18,8 @@ namespace Microsoft.CodeAnalysis.CSharp.UnitTests { public class CollectionExpressionTests : CSharpTestBase { + private static string IncludeExpectedOutput(string expectedOutput) => ExecutionConditionUtil.IsMonoOrCoreClr ? expectedOutput : null; + private const string s_collectionExtensions = """ using System; using System.Collections; @@ -1605,7 +1607,7 @@ static void Main() Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "F2").WithArguments("Program.F2(T[][], T[][])").WithLocation(8, 17)); } - [ConditionalFact(typeof(CoreClrOnly))] + [Fact] public void TypeInference_24() { string source = """ @@ -1628,10 +1630,10 @@ static void Main() new[] { source, s_collectionExtensionsWithSpan }, targetFramework: TargetFramework.Net70, verify: Verification.Skipped, - expectedOutput: "[0, 2], [null, 4], "); + expectedOutput: IncludeExpectedOutput("[0, 2], [null, 4], ")); } - [ConditionalFact(typeof(CoreClrOnly))] + [Fact] public void TypeInference_25() { string source = """ @@ -2664,7 +2666,7 @@ static void Main() Diagnostic(ErrorCode.ERR_CollectionExpressionTargetTypeNotConstructible, "[[1, 2], [3, 4]]").WithArguments("int[*,*]").WithLocation(5, 20)); } - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] [CombinatorialData] public void Span_01(bool useReadOnlySpan) { @@ -2686,7 +2688,7 @@ static void Main() } } """; - var verifier = CompileAndVerify(new[] { source, s_collectionExtensionsWithSpan }, targetFramework: TargetFramework.Net70, verify: Verification.Skipped, expectedOutput: "[], [1, 2], [3, 4, 5], [null, 7], "); + var verifier = CompileAndVerify(new[] { source, s_collectionExtensionsWithSpan }, targetFramework: TargetFramework.Net70, verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput("[], [1, 2], [3, 4, 5], [null, 7], ")); verifier.VerifyIL("Program.Create1", $$""" { // Code size 12 (0xc) @@ -2763,7 +2765,7 @@ .maxstack 4 """); } - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] [CombinatorialData] public void Span_02(bool useReadOnlySpan) { @@ -2781,10 +2783,10 @@ static void Main() } } """; - CompileAndVerify(new[] { source, s_collectionExtensionsWithSpan }, targetFramework: TargetFramework.Net70, verify: Verification.Skipped, expectedOutput: "[], [1, 2, 3], "); + CompileAndVerify(new[] { source, s_collectionExtensionsWithSpan }, targetFramework: TargetFramework.Net70, verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); } - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] [CombinatorialData] public void Span_03(bool useReadOnlySpan) { @@ -2802,10 +2804,10 @@ static void Main() } } """; - CompileAndVerify(new[] { source, s_collectionExtensionsWithSpan }, targetFramework: TargetFramework.Net70, verify: Verification.Skipped, expectedOutput: "[], [1, 2, 3], "); + CompileAndVerify(new[] { source, s_collectionExtensionsWithSpan }, targetFramework: TargetFramework.Net70, verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); } - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] [CombinatorialData] public void Span_04(bool useReadOnlySpan) { @@ -2834,7 +2836,7 @@ class Program Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "[]").WithLocation(6, 28)); } - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] [CombinatorialData] public void Span_05(bool useReadOnlySpan) { @@ -2857,7 +2859,7 @@ class Program comp.VerifyEmitDiagnostics(); } - [ConditionalFact(typeof(CoreClrOnly))] + [Fact] public void Span_MissingConstructor() { string source = """ @@ -4282,7 +4284,7 @@ static void Main() Diagnostic(ErrorCode.ERR_SyntaxError, "4").WithArguments(",").WithLocation(9, 16)); } - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] [CombinatorialData] public void SpreadElement_01( [CombinatorialValues("IEnumerable", "int[]", "List", "Span", "ReadOnlySpan")] string spreadType, @@ -4307,7 +4309,7 @@ static void Main() options: TestOptions.ReleaseExe, targetFramework: TargetFramework.Net70, verify: Verification.Skipped, - expectedOutput: "[1, 2, 3], "); + expectedOutput: IncludeExpectedOutput("[1, 2, 3], ")); // Verify some of the cases. string expectedIL = (spreadType, collectionType) switch @@ -4468,7 +4470,7 @@ .locals init (System.Collections.Generic.List V_0, } } - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] [InlineData("int[]")] [InlineData("System.Collections.Generic.List")] [InlineData("System.Span")] @@ -4498,7 +4500,7 @@ static void Main() options: TestOptions.ReleaseExe, targetFramework: TargetFramework.Net70, verify: Verification.Skipped, - expectedOutput: "[1, 2], "); + expectedOutput: IncludeExpectedOutput("[1, 2], ")); if (collectionType == "System.ReadOnlySpan") { @@ -4958,7 +4960,7 @@ .locals init (System.Collections.Generic.List V_0, """); } - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] [InlineData("List")] [InlineData("Span")] [InlineData("ReadOnlySpan")] @@ -4986,7 +4988,7 @@ static void Main() new[] { source, s_collectionExtensionsWithSpan }, targetFramework: TargetFramework.Net70, verify: Verification.Skipped, - expectedOutput: "[1, 2, 3], [1, 2, 3], "); + expectedOutput: IncludeExpectedOutput("[1, 2, 3], [1, 2, 3], ")); } [Fact] @@ -5589,7 +5591,7 @@ .maxstack 5 """); } - [ConditionalFact(typeof(CoreClrOnly))] + [Fact] public void SemanticModel() { string source = """ @@ -5659,7 +5661,7 @@ private static void VerifyTypes(SemanticModel model, ExpressionSyntax expr, stri } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_01(bool useCompilationReference) { string sourceA = """ @@ -5718,7 +5720,7 @@ static MyCollection F2(int x, object y) references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, - expectedOutput: "[], [0, 1, 2], [3, 4, null], "); + expectedOutput: IncludeExpectedOutput("[], [0, 1, 2], [3, 4, null], ")); verifier.VerifyIL("Program.F0", """ { @@ -5815,7 +5817,7 @@ static MyCollection F2(MyCollection c) references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, - expectedOutput: "[1, 2, 3], "); + expectedOutput: IncludeExpectedOutput("[1, 2, 3], ")); verifier.VerifyIL("Program.F2", """ { @@ -5865,7 +5867,7 @@ .locals init (System.Collections.Generic.List V_0, } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_02A( [CombinatorialValues(TargetFramework.Net70, TargetFramework.Net80)] TargetFramework targetFramework, bool useCompilationReference) @@ -5925,8 +5927,8 @@ static void Main() Assert.Null(type); } }, - verify: targetFramework == TargetFramework.Net80 ? Verification.Fails : Verification.Passes, - expectedOutput: "[1, 2, null], "); + verify: targetFramework == TargetFramework.Net80 ? Verification.Fails : Verification.FailsPEVerify, + expectedOutput: IncludeExpectedOutput("[1, 2, null], ")); if (targetFramework == TargetFramework.Net80) { verifier.VerifyIL("Program.F", @@ -6068,7 +6070,7 @@ .maxstack 4 """); } - [ConditionalFact(typeof(CoreClrOnly))] + [Fact] public void CollectionBuilder_InlineArrayTypes() { string sourceA = """ @@ -6166,7 +6168,7 @@ static void Main() AssertEx.Equal(new[] { $"__InlineArray{n}" }, getInlineArrayTypeNames(module)); }, verify: Verification.Skipped, - expectedOutput: $"{n}"); + expectedOutput: IncludeExpectedOutput($"{n}")); static ImmutableArray getInlineArrayTypeNames(ModuleSymbol module) { @@ -6175,7 +6177,7 @@ static ImmutableArray getInlineArrayTypeNames(ModuleSymbol module) } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_RefStructCollection(bool useCompilationReference, bool useScoped) { string qualifier = useScoped ? "scoped " : ""; @@ -6220,7 +6222,7 @@ static MyCollection F() } """; - var verifier = CompileAndVerify(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "1, 2, 3, "); + var verifier = CompileAndVerify(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("1, 2, 3, ")); if (useScoped) { verifier.VerifyIL("Program.F", @@ -6291,7 +6293,7 @@ .maxstack 4 } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_NonGenericCollection(bool useCompilationReference) { string sourceA = """ @@ -6328,11 +6330,11 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "[], [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_InterfaceCollection_ReturnInterface(bool useCompilationReference) { string sourceA = """ @@ -6372,11 +6374,11 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "(MyCollectionBuilder.MyCollection) [], (MyCollectionBuilder.MyCollection) [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("(MyCollectionBuilder.MyCollection) [], (MyCollectionBuilder.MyCollection) [1, 2, 3], ")); } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_InterfaceCollection_ReturnImplementation(bool useCompilationReference) { string sourceA = """ @@ -6425,7 +6427,7 @@ static void Main() } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_NestedCollectionAndBuilder(bool useCompilationReference) { string sourceA = """ @@ -6465,11 +6467,11 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "(Container.MyCollection) [], (Container.MyCollection) [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("(Container.MyCollection) [], (Container.MyCollection) [1, 2, 3], ")); } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_NoElementType(bool useCompilationReference) { string sourceA = """ @@ -6511,7 +6513,7 @@ static void Main() } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_ElementTypeFromPattern_01(bool useCompilationReference) { string sourceA = """ @@ -6567,11 +6569,11 @@ static IEnumerable GetElements(MyCollection c) } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "[], [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_ElementTypeFromPattern_02(bool useCompilationReference) { string sourceA = """ @@ -6627,11 +6629,11 @@ static IEnumerable GetElements(MyCollection c) } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "[], [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_ObjectElementType_01(bool useCompilationReference) { string sourceA = """ @@ -6666,11 +6668,11 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "[], [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_ObjectElementType_02(bool useCompilationReference) { string sourceA = """ @@ -6714,7 +6716,7 @@ static void Main() } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_ConstructedElementType(bool useCompilationReference) { string sourceA = """ @@ -6757,11 +6759,11 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "(C) [null], (C) [E(1), null], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("(C) [null], (C) [E(1), null], ")); } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_Dictionary(bool useCompilationReference) { string sourceA = """ @@ -6803,10 +6805,10 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "[], [[one, 1], [two, 2]], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("[], [[one, 1], [two, 2]], ")); } - [ConditionalFact(typeof(CoreClrOnly))] + [Fact] public void CollectionBuilder_MissingBuilderType() { string sourceA = """ @@ -6854,7 +6856,7 @@ static void Main() } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_MissingBuilderMethod(bool useCompilationReference) { string sourceA = """ @@ -6896,7 +6898,7 @@ static void Main() Diagnostic(ErrorCode.ERR_CollectionBuilderAttributeMethodNotFound, "[null]").WithArguments("Create", "T", "MyCollection").WithLocation(7, 34)); } - [ConditionalFact(typeof(CoreClrOnly))] + [Fact] public void CollectionBuilder_NullBuilderType() { string sourceA = """ @@ -6975,7 +6977,7 @@ static void Main() Diagnostic(ErrorCode.ERR_CollectionBuilderAttributeMethodNotFound, "[null]").WithArguments("Create", "T", "MyCollection").WithLocation(7, 34)); } - [ConditionalFact(typeof(CoreClrOnly))] + [Fact] public void CollectionBuilder_InvalidBuilderType_Interface() { string sourceA = """ @@ -7069,7 +7071,7 @@ static void Main() } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_InvalidBuilderType_03( [CombinatorialValues("public delegate void MyCollectionBuilder();", "public enum MyCollectionBuilder { }")] string builderTypeDefinition) { @@ -7112,7 +7114,7 @@ static void Main() } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_InvalidBuilderType_04( [CombinatorialValues("int[]", "int*", "(object, object)")] string builderTypeName) { @@ -7152,7 +7154,7 @@ static void Main() Diagnostic(ErrorCode.ERR_CollectionBuilderAttributeMethodNotFound, "[null]").WithArguments("ToString", "T", "MyCollection").WithLocation(7, 34)); } - [ConditionalFact(typeof(CoreClrOnly))] + [Fact] public void CollectionBuilder_InvalidBuilderType_TypeParameter() { string source = """ @@ -7190,7 +7192,7 @@ static void Main() } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_NullOrEmptyMethodName([CombinatorialValues("null", "\"\"")] string methodName) { string sourceA = $$""" @@ -7282,7 +7284,7 @@ static void Main() } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_InstanceMethod(bool useCompilationReference) { string sourceA = """ @@ -7327,7 +7329,7 @@ static void Main() } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_OtherMember_01( [CombinatorialValues( "public MyCollection Create = null;", @@ -7376,14 +7378,14 @@ static void Main() } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_TypeDifferences_Dynamic_01(bool useCompilationReference) { CollectionBuilder_TypeDifferences("object", "dynamic", "1, 2, 3", "[1, 2, 3]", useCompilationReference); } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_TypeDifferences_Dynamic_02(bool useCompilationReference) { string sourceA = $$""" @@ -7425,11 +7427,11 @@ static IEnumerable GetElements(MyCollection c) } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: $"[], [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput($"[], [1, 2, 3], ")); } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_TypeDifferences_TupleElementNames(bool useCompilationReference) { CollectionBuilder_TypeDifferences("(int, int)", "(int A, int B)", "(1, 2), default", "[(1, 2), (0, 0)]", useCompilationReference); @@ -7475,12 +7477,12 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: $"[], {expectedOutput}, "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput($"[], {expectedOutput}, ")); } // If there are multiple attributes, the first is used. [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_MultipleAttributes(bool useCompilationReference) { string sourceAttribute = """ @@ -7531,7 +7533,7 @@ static void Main() } } """; - var verifier = CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "[1, 2, 3], "); + var verifier = CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("[1, 2, 3], ")); comp = (CSharpCompilation)verifier.Compilation; var collectionType = (NamedTypeSymbol)comp.GetMember("Program.F").ReturnType; @@ -7543,7 +7545,7 @@ static void Main() Assert.Equal("Create1", methodName); } - [ConditionalFact(typeof(CoreClrOnly))] + [Fact] public void CollectionBuilder_GenericBuilderType_01() { string sourceA = """ @@ -7587,7 +7589,7 @@ static void Main() Diagnostic(ErrorCode.ERR_CollectionBuilderAttributeMethodNotFound, "[null]").WithArguments("Create", "T", "MyCollection").WithLocation(7, 34)); } - [ConditionalFact(typeof(CoreClrOnly))] + [Fact] public void CollectionBuilder_GenericBuilderType_02() { string sourceA = """ @@ -7631,7 +7633,7 @@ static void Main() Diagnostic(ErrorCode.ERR_CollectionBuilderAttributeMethodNotFound, "[null]").WithArguments("Create", "T", "MyCollection").WithLocation(7, 34)); } - [ConditionalFact(typeof(CoreClrOnly))] + [Fact] public void CollectionBuilder_GenericBuilderType_03() { string source = """ @@ -7677,7 +7679,7 @@ static void Main() } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_GenericCollectionContainerType_01(bool useCompilationReference) { string sourceA = """ @@ -7717,11 +7719,11 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "(Container.MyCollection) [], (Container.MyCollection) [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("(Container.MyCollection) [], (Container.MyCollection) [1, 2, 3], ")); } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_GenericCollectionContainerType_02(bool useCompilationReference) { string sourceA = """ @@ -7761,11 +7763,11 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "(Container.MyCollection) [], (Container.MyCollection) [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("(Container.MyCollection) [], (Container.MyCollection) [1, 2, 3], ")); } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_GenericCollectionContainerType_03(bool useCompilationReference) { string sourceA = """ @@ -7805,11 +7807,11 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "(Container.MyCollection) [], (Container.MyCollection) [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("(Container.MyCollection) [], (Container.MyCollection) [1, 2, 3], ")); } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_GenericType_ElementTypeFirstOfTwo(bool useCompilationReference) { string sourceA = """ @@ -7846,11 +7848,11 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "(MyCollection) [], (MyCollection) [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("(MyCollection) [], (MyCollection) [1, 2, 3], ")); } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_GenericType_ElementTypeSecondOfTwo(bool useCompilationReference) { string sourceA = """ @@ -7887,11 +7889,11 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "(MyCollection) [], (MyCollection) [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("(MyCollection) [], (MyCollection) [1, 2, 3], ")); } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_InaccessibleBuilderType_01(bool useCompilationReference) { string sourceA = """ @@ -7936,7 +7938,7 @@ static void Main() } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_NestedBuilderType(bool useCompilationReference) { string sourceA = """ @@ -7974,11 +7976,11 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "[], [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_InaccessibleBuilderType_02(bool useCompilationReference) { string sourceA = """ @@ -8024,7 +8026,7 @@ static void Main() } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_InaccessibleMethod(bool useCompilationReference) { string sourceA = """ @@ -8070,7 +8072,7 @@ static void Main() } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_Overloads_01(bool useCompilationReference) { string sourceA = """ @@ -8121,11 +8123,11 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "[], [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_Overloads_02(bool useCompilationReference) { string sourceA = """ @@ -8168,11 +8170,11 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "[], [1, 2, 3], "); + CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_UnexpectedSignature_01( [CombinatorialValues( "public static MyCollection Create(ReadOnlySpan items) => default;", // constructed parameter and return types @@ -8234,7 +8236,7 @@ static void Main() } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_UnexpectedSignature_MoreTypeParameters(bool useCompilationReference) { string sourceA = """ @@ -8279,7 +8281,7 @@ static void Main() } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_UnexpectedSignature_FewerTypeParameters(bool useCompilationReference) { string sourceA = """ @@ -8324,7 +8326,7 @@ static void Main() } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_InheritedAttributeOnBaseCollection(bool useCompilationReference) { string sourceAttribute = """ @@ -8378,7 +8380,7 @@ static void Main() } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_CreateMethodOnBase(bool useCompilationReference) { string sourceA = """ @@ -8425,7 +8427,7 @@ static void Main() } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_ObsoleteBuilderType_01(bool useCompilationReference) { string sourceA = """ @@ -8470,7 +8472,7 @@ static void Main() Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "[1, 2, 3]").WithArguments("MyCollectionBuilder").WithLocation(7, 31)); } - [ConditionalFact(typeof(CoreClrOnly))] + [Fact] public void CollectionBuilder_ObsoleteBuilderType_02() { string sourceA = """ @@ -8516,7 +8518,7 @@ static void Main() } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_ObsoleteBuilderMethod_01(bool useCompilationReference) { string sourceA = """ @@ -8562,7 +8564,7 @@ static void Main() } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_ObsoleteBuilderMethod_02(bool useCompilationReference) { string sourceA = """ @@ -8607,7 +8609,7 @@ static void Main() Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "[1, 2, 3]").WithArguments("MyCollectionBuilder.Create(System.ReadOnlySpan)", "message 4").WithLocation(7, 31)); } - [ConditionalFact(typeof(CoreClrOnly))] + [Fact] public void CollectionBuilder_UnmanagedCallersOnly() { string sourceA = """ @@ -8657,7 +8659,7 @@ static void Main() } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_Constraints_CollectionAndBuilder(bool useCompilationReference) { string sourceA = """ @@ -8694,7 +8696,7 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB1, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "[], [1, 2, 3], "); + CompileAndVerify(new[] { sourceB1, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); string sourceB2 = """ #pragma warning disable 219 @@ -8715,7 +8717,7 @@ static void Main() } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_Constraints_BuilderOnly(bool useCompilationReference) { string sourceA = """ @@ -8752,7 +8754,7 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB1, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "[], [1, 2, 3], "); + CompileAndVerify(new[] { sourceB1, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); string sourceB2 = """ #pragma warning disable 219 @@ -8772,7 +8774,7 @@ static void Main() Diagnostic(ErrorCode.ERR_ValConstraintNotSatisfied, "[4, null]").WithArguments("MyCollectionBuilder.Create(System.ReadOnlySpan)", "T", "int?").WithLocation(6, 32)); } - [ConditionalFact(typeof(CoreClrOnly))] + [Fact] public void CollectionBuilder_Constraints_CollectionOnly() { string sourceA = """ @@ -8817,7 +8819,7 @@ static void Main() } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_Substituted_01(bool useCompilationReference) { string sourceA = """ @@ -8871,7 +8873,7 @@ static void F(MyCollection c) Assert.Equal("Create", methodName); } - [ConditionalFact(typeof(CoreClrOnly))] + [Fact] public void CollectionBuilder_Substituted_02() { string sourceA = """ @@ -8931,7 +8933,7 @@ static void F(MyCollection c) Assert.Equal("Create", methodName); } - [ConditionalFact(typeof(CoreClrOnly))] + [Fact] public void CollectionBuilder_Substituted_03() { string source = """ @@ -9038,7 +9040,7 @@ static void F(MyCollection c) Assert.Equal("Create", methodName); } - [ConditionalFact(typeof(CoreClrOnly))] + [Fact] public void CollectionBuilder_ExtensionMethodGetEnumerator_01() { string source = """ @@ -9076,7 +9078,7 @@ static void Main() Diagnostic(ErrorCode.ERR_CollectionBuilderNoElementType, "[]").WithArguments("MyCollection").WithLocation(24, 31)); } - [ConditionalFact(typeof(CoreClrOnly))] + [Fact] public void CollectionBuilder_ExtensionMethodGetEnumerator_02() { string sourceA = """ @@ -9118,7 +9120,7 @@ static void Main() Diagnostic(ErrorCode.ERR_CollectionBuilderNoElementType, "[]").WithArguments("MyCollection").WithLocation(6, 31)); } - [ConditionalFact(typeof(CoreClrOnly))] + [Fact] public void CollectionBuilder_InaccessibleGetEnumerator() { string source = """ @@ -9159,7 +9161,7 @@ static void Main() [InlineData("scoped", "", true)] [InlineData("scoped", "scoped", false)] [InlineData("scoped", "scoped", true)] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_Scoped(string constructorParameterModifier, string builderParameterModifier, bool useCompilationReference) { string sourceA = $$""" @@ -9208,11 +9210,11 @@ static List GetItems(MyCollection c) new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, - verify: builderParameterModifier == "scoped" ? Verification.Fails : Verification.Passes, - expectedOutput: "[], [1, 2, 3], "); + verify: builderParameterModifier == "scoped" ? Verification.Fails : Verification.FailsPEVerify, + expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); } - [ConditionalFact(typeof(CoreClrOnly))] + [Fact] public void CollectionBuilder_ScopedBuilderParameterOnly() { string sourceA = $$""" @@ -9257,7 +9259,7 @@ static void Main() } [CombinatorialData] - [ConditionalTheory(typeof(CoreClrOnly))] + [Theory] public void CollectionBuilder_MissingSpanMembers(bool useCompilationReference) { string sourceA = """ @@ -9310,7 +9312,7 @@ static void Main() Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "[1, 2, 3]").WithArguments("System.Span`1", "op_Implicit").WithLocation(7, 31)); } - [ConditionalFact(typeof(CoreClrOnly))] + [Fact] public void CollectionBuilder_Async() { string sourceA = """ @@ -9354,7 +9356,7 @@ static async Task F(int i) } } """; - var verifier = CompileAndVerify(new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition, s_collectionExtensions }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: "[1, 2, 3], "); + var verifier = CompileAndVerify(new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition, s_collectionExtensions }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("[1, 2, 3], ")); verifier.VerifyIL("Program.d__1.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", """ { @@ -9500,7 +9502,7 @@ .locals init (int V_0, """); } - [ConditionalFact(typeof(CoreClrOnly))] + [Fact] public void CollectionBuilder_AttributeCycle() { string source = """ @@ -9730,7 +9732,7 @@ static T[] Create(T a, T b) """); } - [ConditionalFact(typeof(CoreClrOnly))] + [Fact] public void IOperation_Span() { string source = """ From 75ead79825f1abbb073cf323960f02d5c8eeaa74 Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Sun, 30 Jul 2023 23:34:37 -0700 Subject: [PATCH 07/14] Remove unneeded WellKnownMember --- .../LocalRewriter_CollectionExpression.cs | 20 +-- .../Semantics/CollectionExpressionTests.cs | 139 +++++------------- .../Symbol/Symbols/MissingSpecialMember.cs | 1 - .../Core/Portable/WellKnownMember.cs | 1 - .../Core/Portable/WellKnownMembers.cs | 15 -- .../WellKnownTypeValidationTests.vb | 2 - 6 files changed, 47 insertions(+), 131 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs index 460198592d604..2d2a402baee8e 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs @@ -258,21 +258,15 @@ private BoundExpression CreateAndPopulateInlineArray( } // Get a span to the inline array. - // ... (ReadOnlySpan)InlineArrayAsSpan<__InlineArrayN, T>(ref tmp, N) - var inlineArrayAsSpan = _factory.ModuleBuilderOpt.EnsureInlineArrayAsSpanExists(syntax, _factory.WellKnownType(WellKnownType.System_Span_T), intType, _diagnostics.DiagnosticBag); - inlineArrayAsSpan = inlineArrayAsSpan.Construct(ImmutableArray.Create(TypeWithAnnotations.Create(inlineArrayType), elementType)); - - var spanType = (NamedTypeSymbol)inlineArrayAsSpan.ReturnType; - var spanOperator = _factory.WellKnownMethod(WellKnownMember.System_Span_T__op_Implicit_ReadOnlySpan_Span).AsMember(spanType); + // ... InlineArrayAsReadOnlySpan<__InlineArrayN, T>(in tmp, N) + var inlineArrayAsReadOnlySpan = _factory.ModuleBuilderOpt.EnsureInlineArrayAsReadOnlySpanExists(syntax, _factory.WellKnownType(WellKnownType.System_ReadOnlySpan_T), intType, _diagnostics.DiagnosticBag). + Construct(ImmutableArray.Create(TypeWithAnnotations.Create(inlineArrayType), elementType)); return _factory.Call( receiver: null, - spanOperator, - _factory.Call( - receiver: null, - inlineArrayAsSpan, - inlineArrayLocal, - _factory.Literal(arrayLength), - useStrictArgumentRefKinds: true)); + inlineArrayAsReadOnlySpan, + inlineArrayLocal, + _factory.Literal(arrayLength), + useStrictArgumentRefKinds: true); } private BoundExpression MakeCollectionExpressionSpreadElement(BoundCollectionExpressionSpreadElement initializer) diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index 0bb3c4c82de1b..7c878ca49a8ea 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -5736,7 +5736,7 @@ .maxstack 1 verifier.VerifyIL("Program.F1", """ { - // Code size 57 (0x39) + // Code size 52 (0x34) .maxstack 2 .locals init (__InlineArray3 V_0) IL_0000: ldloca.s V_0 @@ -5758,16 +5758,15 @@ .locals init (__InlineArray3 V_0) IL_0025: stind.i4 IL_0026: ldloca.s V_0 IL_0028: ldc.i4.3 - IL_0029: call "InlineArrayAsSpan<__InlineArray3, int>(ref __InlineArray3, int)" - IL_002e: call "System.ReadOnlySpan System.Span.op_Implicit(System.Span)" - IL_0033: call "MyCollection MyCollectionBuilder.Create(System.ReadOnlySpan)" - IL_0038: ret + IL_0029: call "InlineArrayAsReadOnlySpan<__InlineArray3, int>(in __InlineArray3, int)" + IL_002e: call "MyCollection MyCollectionBuilder.Create(System.ReadOnlySpan)" + IL_0033: ret } """); verifier.VerifyIL("Program.F2", """ { - // Code size 62 (0x3e) + // Code size 57 (0x39) .maxstack 2 .locals init (__InlineArray3 V_0) IL_0000: ldloca.s V_0 @@ -5790,10 +5789,9 @@ .locals init (__InlineArray3 V_0) IL_002a: stind.ref IL_002b: ldloca.s V_0 IL_002d: ldc.i4.3 - IL_002e: call "InlineArrayAsSpan<__InlineArray3, object>(ref __InlineArray3, int)" - IL_0033: call "System.ReadOnlySpan System.Span.op_Implicit(System.Span)" - IL_0038: call "MyCollection MyCollectionBuilder.Create(System.ReadOnlySpan)" - IL_003d: ret + IL_002e: call "InlineArrayAsReadOnlySpan<__InlineArray3, object>(in __InlineArray3, int)" + IL_0033: call "MyCollection MyCollectionBuilder.Create(System.ReadOnlySpan)" + IL_0038: ret } """); @@ -5934,7 +5932,7 @@ static void Main() verifier.VerifyIL("Program.F", """ { - // Code size 79 (0x4f) + // Code size 74 (0x4a) .maxstack 2 .locals init (__InlineArray3 V_0) IL_0000: ldloca.s V_0 @@ -5957,10 +5955,9 @@ .locals init (__InlineArray3 V_0) IL_0036: initobj "int?" IL_003c: ldloca.s V_0 IL_003e: ldc.i4.3 - IL_003f: call "InlineArrayAsSpan<__InlineArray3, int?>(ref __InlineArray3, int)" - IL_0044: call "System.ReadOnlySpan System.Span.op_Implicit(System.Span)" - IL_0049: call "MyCollection MyCollectionBuilder.Create(System.ReadOnlySpan)" - IL_004e: ret + IL_003f: call "InlineArrayAsReadOnlySpan<__InlineArray3, int?>(in __InlineArray3, int)" + IL_0044: call "MyCollection MyCollectionBuilder.Create(System.ReadOnlySpan)" + IL_0049: ret } """); } @@ -6228,7 +6225,7 @@ static MyCollection F() verifier.VerifyIL("Program.F", $$""" { - // Code size 72 (0x48) + // Code size 67 (0x43) .maxstack 2 .locals init (__InlineArray3 V_0) IL_0000: ldloca.s V_0 @@ -6253,10 +6250,9 @@ .locals init (__InlineArray3 V_0) IL_0034: stind.ref IL_0035: ldloca.s V_0 IL_0037: ldc.i4.3 - IL_0038: call "InlineArrayAsSpan<__InlineArray3, object>(ref __InlineArray3, int)" - IL_003d: call "System.ReadOnlySpan System.Span.op_Implicit(System.Span)" - IL_0042: call "MyCollection MyCollectionBuilder.Create({{qualifier}}System.ReadOnlySpan)" - IL_0047: ret + IL_0038: call "InlineArrayAsReadOnlySpan<__InlineArray3, object>(in __InlineArray3, int)" + IL_003d: call "MyCollection MyCollectionBuilder.Create(scoped System.ReadOnlySpan)" + IL_0042: ret } """); } @@ -9258,60 +9254,6 @@ static void Main() Diagnostic(ErrorCode.ERR_EscapeVariable, "items").WithArguments("scoped System.ReadOnlySpan items").WithLocation(16, 82)); } - [CombinatorialData] - [Theory] - public void CollectionBuilder_MissingSpanMembers(bool useCompilationReference) - { - string sourceA = """ - using System; - using System.Collections.Generic; - using System.Runtime.CompilerServices; - [CollectionBuilder(typeof(MyCollectionBuilder), nameof(MyCollectionBuilder.Create))] - public struct MyCollection - { - public IEnumerator GetEnumerator() => default; - } - public class MyCollectionBuilder - { - public static MyCollection Create(ReadOnlySpan items) => default; - } - """; - var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); - var refA = AsReference(comp, useCompilationReference); - - string sourceB = """ - #pragma warning disable 219 - class Program - { - static void Main() - { - MyCollection x = []; - MyCollection y = [1, 2, 3]; - MyCollection z = new(); - } - } - """; - comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); - comp.MakeTypeMissing(WellKnownType.System_Span_T); - comp.VerifyEmitDiagnostics( - // error CS0656: Missing compiler required member 'System.Runtime.InteropServices.MemoryMarshal.CreateSpan' - // - Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "").WithArguments("System.Runtime.InteropServices.MemoryMarshal", "CreateSpan").WithLocation(1, 1), - // (7,31): error CS0518: Predefined type 'System.Span`1' is not defined or imported - // MyCollection y = [1, 2, 3]; - Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "[1, 2, 3]").WithArguments("System.Span`1").WithLocation(7, 31), - // (7,31): error CS0656: Missing compiler required member 'System.Span`1.op_Implicit' - // MyCollection y = [1, 2, 3]; - Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "[1, 2, 3]").WithArguments("System.Span`1", "op_Implicit").WithLocation(7, 31)); - - comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); - comp.MakeMemberMissing(WellKnownMember.System_Span_T__op_Implicit_ReadOnlySpan_Span); - comp.VerifyEmitDiagnostics( - // (7,31): error CS0656: Missing compiler required member 'System.Span`1.op_Implicit' - // MyCollection y = [1, 2, 3]; - Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "[1, 2, 3]").WithArguments("System.Span`1", "op_Implicit").WithLocation(7, 31)); - } - [Fact] public void CollectionBuilder_Async() { @@ -9360,7 +9302,7 @@ static async Task F(int i) verifier.VerifyIL("Program.d__1.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", """ { - // Code size 329 (0x149) + // Code size 324 (0x144) .maxstack 3 .locals init (int V_0, MyCollection V_1, @@ -9401,7 +9343,7 @@ .locals init (int V_0, IL_004a: ldloca.s V_4 IL_004c: ldarg.0 IL_004d: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder>.AwaitUnsafeOnCompleted, Program.d__1>(ref System.Runtime.CompilerServices.TaskAwaiter, ref Program.d__1)" - IL_0052: leave IL_0148 + IL_0052: leave IL_0143 IL_0057: ldarg.0 IL_0058: ldfld "System.Runtime.CompilerServices.TaskAwaiter Program.d__1.<>u__1" IL_005d: stloc.s V_4 @@ -9448,7 +9390,7 @@ .locals init (int V_0, IL_00c5: ldloca.s V_4 IL_00c7: ldarg.0 IL_00c8: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder>.AwaitUnsafeOnCompleted, Program.d__1>(ref System.Runtime.CompilerServices.TaskAwaiter, ref Program.d__1)" - IL_00cd: leave.s IL_0148 + IL_00cd: leave.s IL_0143 IL_00cf: ldarg.0 IL_00d0: ldfld "System.Runtime.CompilerServices.TaskAwaiter Program.d__1.<>u__1" IL_00d5: stloc.s V_4 @@ -9472,32 +9414,31 @@ .locals init (int V_0, IL_0102: ldarg.0 IL_0103: ldflda "__InlineArray3 Program.d__1.<>7__wrap1" IL_0108: ldc.i4.3 - IL_0109: call "InlineArrayAsSpan<__InlineArray3, int>(ref __InlineArray3, int)" - IL_010e: call "System.ReadOnlySpan System.Span.op_Implicit(System.Span)" - IL_0113: call "MyCollection MyCollectionBuilder.Create(System.ReadOnlySpan)" - IL_0118: stloc.1 - IL_0119: leave.s IL_0134 + IL_0109: call "InlineArrayAsReadOnlySpan<__InlineArray3, int>(in __InlineArray3, int)" + IL_010e: call "MyCollection MyCollectionBuilder.Create(System.ReadOnlySpan)" + IL_0113: stloc.1 + IL_0114: leave.s IL_012f } catch System.Exception { - IL_011b: stloc.s V_5 - IL_011d: ldarg.0 - IL_011e: ldc.i4.s -2 - IL_0120: stfld "int Program.d__1.<>1__state" - IL_0125: ldarg.0 - IL_0126: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder> Program.d__1.<>t__builder" - IL_012b: ldloc.s V_5 - IL_012d: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder>.SetException(System.Exception)" - IL_0132: leave.s IL_0148 + IL_0116: stloc.s V_5 + IL_0118: ldarg.0 + IL_0119: ldc.i4.s -2 + IL_011b: stfld "int Program.d__1.<>1__state" + IL_0120: ldarg.0 + IL_0121: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder> Program.d__1.<>t__builder" + IL_0126: ldloc.s V_5 + IL_0128: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder>.SetException(System.Exception)" + IL_012d: leave.s IL_0143 } - IL_0134: ldarg.0 - IL_0135: ldc.i4.s -2 - IL_0137: stfld "int Program.d__1.<>1__state" - IL_013c: ldarg.0 - IL_013d: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder> Program.d__1.<>t__builder" - IL_0142: ldloc.1 - IL_0143: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder>.SetResult(MyCollection)" - IL_0148: ret + IL_012f: ldarg.0 + IL_0130: ldc.i4.s -2 + IL_0132: stfld "int Program.d__1.<>1__state" + IL_0137: ldarg.0 + IL_0138: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder> Program.d__1.<>t__builder" + IL_013d: ldloc.1 + IL_013e: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder>.SetResult(MyCollection)" + IL_0143: ret } """); } diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs index 36b45b0ba9540..a7754e33cfaba 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs @@ -951,7 +951,6 @@ public void AllWellKnownTypeMembers() case WellKnownMember.System_Span_T__get_Item: case WellKnownMember.System_Span_T__get_Length: case WellKnownMember.System_Span_T__Slice_Int_Int: - case WellKnownMember.System_Span_T__op_Implicit_ReadOnlySpan_Span: case WellKnownMember.System_ReadOnlySpan_T__ctor_Pointer: case WellKnownMember.System_ReadOnlySpan_T__ctor_Array: case WellKnownMember.System_ReadOnlySpan_T__ctor_Array_Start_Length: diff --git a/src/Compilers/Core/Portable/WellKnownMember.cs b/src/Compilers/Core/Portable/WellKnownMember.cs index cb7acd1604718..567b7a28023f0 100644 --- a/src/Compilers/Core/Portable/WellKnownMember.cs +++ b/src/Compilers/Core/Portable/WellKnownMember.cs @@ -491,7 +491,6 @@ internal enum WellKnownMember System_Span_T__get_Item, System_Span_T__get_Length, System_Span_T__Slice_Int_Int, - System_Span_T__op_Implicit_ReadOnlySpan_Span, System_ReadOnlySpan_T__ctor_Pointer, System_ReadOnlySpan_T__ctor_Array, diff --git a/src/Compilers/Core/Portable/WellKnownMembers.cs b/src/Compilers/Core/Portable/WellKnownMembers.cs index 6e3130110d256..7d6d3ff7cb1c2 100644 --- a/src/Compilers/Core/Portable/WellKnownMembers.cs +++ b/src/Compilers/Core/Portable/WellKnownMembers.cs @@ -3412,20 +3412,6 @@ static WellKnownMembers() (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Int32, (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Int32, - // System_Span_T__op_Implicit_ReadOnlySpan_Span - (byte)(MemberFlags.Method | MemberFlags.Static), // Flags - (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Span_T - WellKnownType.ExtSentinel), // DeclaringTypeId - 0, // Arity - 1, // Method Signature - (byte)SignatureTypeCode.GenericTypeInstance, // Return Type - (byte)SignatureTypeCode.TypeHandle, (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_ReadOnlySpan_T - WellKnownType.ExtSentinel), - 1, - (byte)SignatureTypeCode.GenericTypeParameter, 0, - (byte)SignatureTypeCode.GenericTypeInstance, - (byte)SignatureTypeCode.TypeHandle, (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Span_T - WellKnownType.ExtSentinel), - 1, - (byte)SignatureTypeCode.GenericTypeParameter, 0, - // System_ReadOnlySpan_T__ctor_Pointer (byte)(MemberFlags.Constructor), // Flags (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_ReadOnlySpan_T - WellKnownType.ExtSentinel), // DeclaringTypeId @@ -4503,7 +4489,6 @@ static WellKnownMembers() "get_Item", // System_Span_T__get_Item "get_Length", // System_Span_T__get_Length "Slice", // System_Span_T__Slice_Int_Int - "op_Implicit", // System_Span_T__op_Implicit_ReadOnlySpan_Span ".ctor", // System_ReadOnlySpan_T__ctor_Pointer ".ctor", // System_ReadOnlySpan_T__ctor_Array ".ctor", // System_ReadOnlySpan_T__ctor_Array_Start_Length diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb index 0036ccb877721..af42a03164159 100644 --- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb @@ -694,7 +694,6 @@ End Namespace WellKnownMember.System_Span_T__get_Item, WellKnownMember.System_Span_T__get_Length, WellKnownMember.System_Span_T__Slice_Int_Int, - WellKnownMember.System_Span_T__op_Implicit_ReadOnlySpan_Span, WellKnownMember.System_ReadOnlySpan_T__ctor_Pointer, WellKnownMember.System_ReadOnlySpan_T__ctor_Array, WellKnownMember.System_ReadOnlySpan_T__ctor_Array_Start_Length, @@ -892,7 +891,6 @@ End Namespace WellKnownMember.System_Span_T__get_Item, WellKnownMember.System_Span_T__get_Length, WellKnownMember.System_Span_T__Slice_Int_Int, - WellKnownMember.System_Span_T__op_Implicit_ReadOnlySpan_Span, WellKnownMember.System_ReadOnlySpan_T__ctor_Pointer, WellKnownMember.System_ReadOnlySpan_T__ctor_Array, WellKnownMember.System_ReadOnlySpan_T__ctor_Array_Start_Length, From d36040bd218e8f2916b28f9abd3d60ab1f98dcdf Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Mon, 31 Jul 2023 12:36:23 -0700 Subject: [PATCH 08/14] Misc. --- src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs index 74464c5b9805c..10438a88f7954 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs @@ -574,7 +574,7 @@ private BoundCollectionExpression BindArrayOrSpanCollectionExpression( TypeSymbol elementType, BindingDiagnosticBag diagnostics) { - var syntax = (CSharpSyntaxNode)node.Syntax; + var syntax = node.Syntax; switch (collectionTypeKind) { From 99717d6231f459d998964ddc8ea46ec3cabef674 Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Mon, 31 Jul 2023 12:54:37 -0700 Subject: [PATCH 09/14] Address feedback --- .../LocalRewriter/LocalRewriter_CollectionExpression.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs index 2d2a402baee8e..f759fdb870226 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs @@ -239,15 +239,15 @@ private BoundExpression CreateAndPopulateInlineArray( Construct(ImmutableArray.Create(TypeWithAnnotations.Create(inlineArrayType), elementType)); // Create an inline array and assign to a local. - // var tmp = new __InlineArrayN(); + // var tmp = new __InlineArrayN(); BoundAssignmentOperator assignmentToTemp; BoundLocal inlineArrayLocal = _factory.StoreToTemp(new BoundDefaultExpression(syntax, inlineArrayType), out assignmentToTemp, isKnownToReferToTempIfReferenceType: true); sideEffects.Add(assignmentToTemp); locals.Add(inlineArrayLocal.LocalSymbol); // Populate the inline array. - // InlineArrayElementRef<__InlineArrayN, T>(ref tmp, 0) = element0; - // InlineArrayElementRef<__InlineArrayN, T>(ref tmp, 1) = element1; + // InlineArrayElementRef<__InlineArrayN, ElementType>(ref tmp, 0) = element0; + // InlineArrayElementRef<__InlineArrayN, ElementType>(ref tmp, 1) = element1; // ... for (int i = 0; i < arrayLength; i++) { @@ -258,7 +258,7 @@ private BoundExpression CreateAndPopulateInlineArray( } // Get a span to the inline array. - // ... InlineArrayAsReadOnlySpan<__InlineArrayN, T>(in tmp, N) + // ... InlineArrayAsReadOnlySpan<__InlineArrayN, ElementType>(in tmp, N) var inlineArrayAsReadOnlySpan = _factory.ModuleBuilderOpt.EnsureInlineArrayAsReadOnlySpanExists(syntax, _factory.WellKnownType(WellKnownType.System_ReadOnlySpan_T), intType, _diagnostics.DiagnosticBag). Construct(ImmutableArray.Create(TypeWithAnnotations.Create(inlineArrayType), elementType)); return _factory.Call( From d4c2081de374094f3e05f9e0565fbf9af1d76939 Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Mon, 31 Jul 2023 14:58:37 -0700 Subject: [PATCH 10/14] Make inline array type a top-level type --- .../Portable/Emitter/Model/PEModuleBuilder.cs | 3 +- .../LocalRewriter_CollectionExpression.cs | 8 +- .../Symbols/Synthesized/GeneratedNameKind.cs | 3 +- .../SynthesizedInlineArrayTypeSymbol.cs | 2 +- .../Semantics/CollectionExpressionTests.cs | 80 +++++++++---------- .../CodeGen/PrivateImplementationDetails.cs | 33 ++++---- .../Portable/Emit/CommonPEModuleBuilder.cs | 7 ++ 7 files changed, 73 insertions(+), 63 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs b/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs index 67fd3f9c16a75..d3daa560df987 100644 --- a/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs +++ b/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs @@ -1973,8 +1973,9 @@ internal MethodSymbol EnsureInlineArrayAsSpanExists(SyntaxNode syntaxNode, Named internal NamedTypeSymbol EnsureInlineArrayTypeExists(SyntaxNode syntaxNode, SyntheticBoundNodeFactory factory, int arrayLength, DiagnosticBag diagnostics) { Debug.Assert(Compilation.Assembly.RuntimeSupportsInlineArrayTypes); + Debug.Assert(arrayLength > 0); - string typeName = PrivateImplementationDetails.GetInlineArrayTypeName(arrayLength); + string typeName = $"<>y__InlineArray{arrayLength}"; // see GeneratedNameKind.InlineArrayType var privateImplClass = GetPrivateImplClass(syntaxNode, diagnostics); var typeAdapter = privateImplClass.GetType(typeName); diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs index f759fdb870226..69e671205551a 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CollectionExpression.cs @@ -239,15 +239,15 @@ private BoundExpression CreateAndPopulateInlineArray( Construct(ImmutableArray.Create(TypeWithAnnotations.Create(inlineArrayType), elementType)); // Create an inline array and assign to a local. - // var tmp = new __InlineArrayN(); + // var tmp = new <>y__InlineArrayN(); BoundAssignmentOperator assignmentToTemp; BoundLocal inlineArrayLocal = _factory.StoreToTemp(new BoundDefaultExpression(syntax, inlineArrayType), out assignmentToTemp, isKnownToReferToTempIfReferenceType: true); sideEffects.Add(assignmentToTemp); locals.Add(inlineArrayLocal.LocalSymbol); // Populate the inline array. - // InlineArrayElementRef<__InlineArrayN, ElementType>(ref tmp, 0) = element0; - // InlineArrayElementRef<__InlineArrayN, ElementType>(ref tmp, 1) = element1; + // InlineArrayElementRef<<>y__InlineArrayN, ElementType>(ref tmp, 0) = element0; + // InlineArrayElementRef<<>y__InlineArrayN, ElementType>(ref tmp, 1) = element1; // ... for (int i = 0; i < arrayLength; i++) { @@ -258,7 +258,7 @@ private BoundExpression CreateAndPopulateInlineArray( } // Get a span to the inline array. - // ... InlineArrayAsReadOnlySpan<__InlineArrayN, ElementType>(in tmp, N) + // ... InlineArrayAsReadOnlySpan<<>y__InlineArrayN, ElementType>(in tmp, N) var inlineArrayAsReadOnlySpan = _factory.ModuleBuilderOpt.EnsureInlineArrayAsReadOnlySpanExists(syntax, _factory.WellKnownType(WellKnownType.System_ReadOnlySpan_T), intType, _diagnostics.DiagnosticBag). Construct(ImmutableArray.Create(TypeWithAnnotations.Create(inlineArrayType), elementType)); return _factory.Call( diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/GeneratedNameKind.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/GeneratedNameKind.cs index 02e82a25f81a8..71a19beb2651b 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/GeneratedNameKind.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/GeneratedNameKind.cs @@ -47,7 +47,8 @@ internal enum GeneratedNameKind DynamicCallSiteField = 'p', AsyncIteratorPromiseOfValueOrEndBackingField = 'v', DisposeModeField = 'w', - CombinedTokensField = 'x', // last + CombinedTokensField = 'x', + InlineArrayType = 'y', // last // Deprecated - emitted by Dev12, but not by Roslyn. // Don't reuse the values because the debugger might encounter them when consuming old binaries. diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInlineArrayTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInlineArrayTypeSymbol.cs index 7840c00bbf44f..28ee328562a82 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInlineArrayTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInlineArrayTypeSymbol.cs @@ -17,7 +17,7 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols /// A synthesized type used during emit to allow temp locals of Span<T> /// of a specific length where the span storage is on the stack. /// - /// [InlineArray(N)] struct __InlineArrayN<T> { private T _element0; } + /// [InlineArray(N)] struct <>y__InlineArrayN<T> { private T _element0; } /// /// internal sealed class SynthesizedInlineArrayTypeSymbol : NamedTypeSymbol diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index 7c878ca49a8ea..1593545ecd69d 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -5738,27 +5738,27 @@ .maxstack 1 { // Code size 52 (0x34) .maxstack 2 - .locals init (__InlineArray3 V_0) + .locals init (<>y__InlineArray3 V_0) IL_0000: ldloca.s V_0 - IL_0002: initobj "__InlineArray3" + IL_0002: initobj "<>y__InlineArray3" IL_0008: ldloca.s V_0 IL_000a: ldc.i4.0 - IL_000b: call "InlineArrayElementRef<__InlineArray3, int>(ref __InlineArray3, int)" + IL_000b: call "InlineArrayElementRef<<>y__InlineArray3, int>(ref <>y__InlineArray3, int)" IL_0010: ldc.i4.0 IL_0011: stind.i4 IL_0012: ldloca.s V_0 IL_0014: ldc.i4.1 - IL_0015: call "InlineArrayElementRef<__InlineArray3, int>(ref __InlineArray3, int)" + IL_0015: call "InlineArrayElementRef<<>y__InlineArray3, int>(ref <>y__InlineArray3, int)" IL_001a: ldc.i4.1 IL_001b: stind.i4 IL_001c: ldloca.s V_0 IL_001e: ldc.i4.2 - IL_001f: call "InlineArrayElementRef<__InlineArray3, int>(ref __InlineArray3, int)" + IL_001f: call "InlineArrayElementRef<<>y__InlineArray3, int>(ref <>y__InlineArray3, int)" IL_0024: ldc.i4.2 IL_0025: stind.i4 IL_0026: ldloca.s V_0 IL_0028: ldc.i4.3 - IL_0029: call "InlineArrayAsReadOnlySpan<__InlineArray3, int>(in __InlineArray3, int)" + IL_0029: call "InlineArrayAsReadOnlySpan<<>y__InlineArray3, int>(in <>y__InlineArray3, int)" IL_002e: call "MyCollection MyCollectionBuilder.Create(System.ReadOnlySpan)" IL_0033: ret } @@ -5768,28 +5768,28 @@ .locals init (__InlineArray3 V_0) { // Code size 57 (0x39) .maxstack 2 - .locals init (__InlineArray3 V_0) + .locals init (<>y__InlineArray3 V_0) IL_0000: ldloca.s V_0 - IL_0002: initobj "__InlineArray3" + IL_0002: initobj "<>y__InlineArray3" IL_0008: ldloca.s V_0 IL_000a: ldc.i4.0 - IL_000b: call "InlineArrayElementRef<__InlineArray3, object>(ref __InlineArray3, int)" + IL_000b: call "InlineArrayElementRef<<>y__InlineArray3, object>(ref <>y__InlineArray3, int)" IL_0010: ldarg.0 IL_0011: box "int" IL_0016: stind.ref IL_0017: ldloca.s V_0 IL_0019: ldc.i4.1 - IL_001a: call "InlineArrayElementRef<__InlineArray3, object>(ref __InlineArray3, int)" + IL_001a: call "InlineArrayElementRef<<>y__InlineArray3, object>(ref <>y__InlineArray3, int)" IL_001f: ldarg.1 IL_0020: stind.ref IL_0021: ldloca.s V_0 IL_0023: ldc.i4.2 - IL_0024: call "InlineArrayElementRef<__InlineArray3, object>(ref __InlineArray3, int)" + IL_0024: call "InlineArrayElementRef<<>y__InlineArray3, object>(ref <>y__InlineArray3, int)" IL_0029: ldnull IL_002a: stind.ref IL_002b: ldloca.s V_0 IL_002d: ldc.i4.3 - IL_002e: call "InlineArrayAsReadOnlySpan<__InlineArray3, object>(in __InlineArray3, int)" + IL_002e: call "InlineArrayAsReadOnlySpan<<>y__InlineArray3, object>(in <>y__InlineArray3, int)" IL_0033: call "MyCollection MyCollectionBuilder.Create(System.ReadOnlySpan)" IL_0038: ret } @@ -5915,7 +5915,7 @@ static void Main() comp, symbolValidator: module => { - var type = module.GlobalNamespace.GetTypeMembers("__InlineArray3").SingleOrDefault(); + var type = module.GlobalNamespace.GetTypeMembers("<>y__InlineArray3").SingleOrDefault(); if (targetFramework == TargetFramework.Net80) { Assert.NotNull(type); @@ -5934,28 +5934,28 @@ static void Main() { // Code size 74 (0x4a) .maxstack 2 - .locals init (__InlineArray3 V_0) + .locals init (<>y__InlineArray3 V_0) IL_0000: ldloca.s V_0 - IL_0002: initobj "__InlineArray3" + IL_0002: initobj "<>y__InlineArray3" IL_0008: ldloca.s V_0 IL_000a: ldc.i4.0 - IL_000b: call "InlineArrayElementRef<__InlineArray3, int?>(ref __InlineArray3, int)" + IL_000b: call "InlineArrayElementRef<<>y__InlineArray3, int?>(ref <>y__InlineArray3, int)" IL_0010: ldc.i4.1 IL_0011: newobj "int?..ctor(int)" IL_0016: stobj "int?" IL_001b: ldloca.s V_0 IL_001d: ldc.i4.1 - IL_001e: call "InlineArrayElementRef<__InlineArray3, int?>(ref __InlineArray3, int)" + IL_001e: call "InlineArrayElementRef<<>y__InlineArray3, int?>(ref <>y__InlineArray3, int)" IL_0023: ldc.i4.2 IL_0024: newobj "int?..ctor(int)" IL_0029: stobj "int?" IL_002e: ldloca.s V_0 IL_0030: ldc.i4.2 - IL_0031: call "InlineArrayElementRef<__InlineArray3, int?>(ref __InlineArray3, int)" + IL_0031: call "InlineArrayElementRef<<>y__InlineArray3, int?>(ref <>y__InlineArray3, int)" IL_0036: initobj "int?" IL_003c: ldloca.s V_0 IL_003e: ldc.i4.3 - IL_003f: call "InlineArrayAsReadOnlySpan<__InlineArray3, int?>(in __InlineArray3, int)" + IL_003f: call "InlineArrayAsReadOnlySpan<<>y__InlineArray3, int?>(in <>y__InlineArray3, int)" IL_0044: call "MyCollection MyCollectionBuilder.Create(System.ReadOnlySpan)" IL_0049: ret } @@ -6039,7 +6039,7 @@ static void Main() comp, symbolValidator: module => { - var type = module.GlobalNamespace.GetTypeMembers("__InlineArray3").SingleOrDefault(); + var type = module.GlobalNamespace.GetTypeMembers("<>y__InlineArray3").SingleOrDefault(); Assert.Null(type); }, expectedOutput: "[1, 2, null], "); @@ -6106,7 +6106,7 @@ static void M() comp, symbolValidator: module => { - AssertEx.Equal(new[] { "__InlineArray2", "__InlineArray3" }, getInlineArrayTypeNames(module)); + AssertEx.Equal(new[] { "<>y__InlineArray2", "<>y__InlineArray3" }, getInlineArrayTypeNames(module)); }, verify: Verification.Skipped); var refA = comp.EmitToImageReference(); @@ -6134,7 +6134,7 @@ static void M2() comp, symbolValidator: module => { - AssertEx.Equal(new[] { "__InlineArray1", "__InlineArray3" }, getInlineArrayTypeNames(module)); + AssertEx.Equal(new[] { "<>y__InlineArray1", "<>y__InlineArray3" }, getInlineArrayTypeNames(module)); }, verify: Verification.Skipped); @@ -6162,14 +6162,14 @@ static void Main() comp, symbolValidator: module => { - AssertEx.Equal(new[] { $"__InlineArray{n}" }, getInlineArrayTypeNames(module)); + AssertEx.Equal(new[] { $"<>y__InlineArray{n}" }, getInlineArrayTypeNames(module)); }, verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput($"{n}")); static ImmutableArray getInlineArrayTypeNames(ModuleSymbol module) { - return module.GlobalNamespace.GetTypeMembers().WhereAsArray(t => t.Name.StartsWith("__InlineArray")).SelectAsArray(t => t.Name); + return module.GlobalNamespace.GetTypeMembers().WhereAsArray(t => t.Name.StartsWith("<>y__InlineArray")).SelectAsArray(t => t.Name); } } @@ -6227,30 +6227,30 @@ static MyCollection F() { // Code size 67 (0x43) .maxstack 2 - .locals init (__InlineArray3 V_0) + .locals init (<>y__InlineArray3 V_0) IL_0000: ldloca.s V_0 - IL_0002: initobj "__InlineArray3" + IL_0002: initobj "<>y__InlineArray3" IL_0008: ldloca.s V_0 IL_000a: ldc.i4.0 - IL_000b: call "InlineArrayElementRef<__InlineArray3, object>(ref __InlineArray3, int)" + IL_000b: call "InlineArrayElementRef<<>y__InlineArray3, object>(ref <>y__InlineArray3, int)" IL_0010: ldc.i4.1 IL_0011: box "int" IL_0016: stind.ref IL_0017: ldloca.s V_0 IL_0019: ldc.i4.1 - IL_001a: call "InlineArrayElementRef<__InlineArray3, object>(ref __InlineArray3, int)" + IL_001a: call "InlineArrayElementRef<<>y__InlineArray3, object>(ref <>y__InlineArray3, int)" IL_001f: ldc.i4.2 IL_0020: box "int" IL_0025: stind.ref IL_0026: ldloca.s V_0 IL_0028: ldc.i4.2 - IL_0029: call "InlineArrayElementRef<__InlineArray3, object>(ref __InlineArray3, int)" + IL_0029: call "InlineArrayElementRef<<>y__InlineArray3, object>(ref <>y__InlineArray3, int)" IL_002e: ldc.i4.3 IL_002f: box "int" IL_0034: stind.ref IL_0035: ldloca.s V_0 IL_0037: ldc.i4.3 - IL_0038: call "InlineArrayAsReadOnlySpan<__InlineArray3, object>(in __InlineArray3, int)" + IL_0038: call "InlineArrayAsReadOnlySpan<<>y__InlineArray3, object>(in <>y__InlineArray3, int)" IL_003d: call "MyCollection MyCollectionBuilder.Create(scoped System.ReadOnlySpan)" IL_0042: ret } @@ -9321,8 +9321,8 @@ .locals init (int V_0, IL_000b: ldc.i4.1 IL_000c: beq IL_00cf IL_0011: ldarg.0 - IL_0012: ldflda "__InlineArray3 Program.d__1.<>7__wrap1" - IL_0017: initobj "__InlineArray3" + IL_0012: ldflda "<>y__InlineArray3 Program.d__1.<>7__wrap1" + IL_0017: initobj "<>y__InlineArray3" IL_001d: ldc.i4.1 IL_001e: call "System.Threading.Tasks.Task Program.F(int)" IL_0023: callvirt "System.Runtime.CompilerServices.TaskAwaiter System.Threading.Tasks.Task.GetAwaiter()" @@ -9359,15 +9359,15 @@ .locals init (int V_0, IL_0076: call "int System.Runtime.CompilerServices.TaskAwaiter.GetResult()" IL_007b: stloc.2 IL_007c: ldarg.0 - IL_007d: ldflda "__InlineArray3 Program.d__1.<>7__wrap1" + IL_007d: ldflda "<>y__InlineArray3 Program.d__1.<>7__wrap1" IL_0082: ldc.i4.0 - IL_0083: call "InlineArrayElementRef<__InlineArray3, int>(ref __InlineArray3, int)" + IL_0083: call "InlineArrayElementRef<<>y__InlineArray3, int>(ref <>y__InlineArray3, int)" IL_0088: ldloc.2 IL_0089: stind.i4 IL_008a: ldarg.0 - IL_008b: ldflda "__InlineArray3 Program.d__1.<>7__wrap1" + IL_008b: ldflda "<>y__InlineArray3 Program.d__1.<>7__wrap1" IL_0090: ldc.i4.1 - IL_0091: call "InlineArrayElementRef<__InlineArray3, int>(ref __InlineArray3, int)" + IL_0091: call "InlineArrayElementRef<<>y__InlineArray3, int>(ref <>y__InlineArray3, int)" IL_0096: ldc.i4.2 IL_0097: stind.i4 IL_0098: ldc.i4.3 @@ -9406,15 +9406,15 @@ .locals init (int V_0, IL_00ee: call "int System.Runtime.CompilerServices.TaskAwaiter.GetResult()" IL_00f3: stloc.3 IL_00f4: ldarg.0 - IL_00f5: ldflda "__InlineArray3 Program.d__1.<>7__wrap1" + IL_00f5: ldflda "<>y__InlineArray3 Program.d__1.<>7__wrap1" IL_00fa: ldc.i4.2 - IL_00fb: call "InlineArrayElementRef<__InlineArray3, int>(ref __InlineArray3, int)" + IL_00fb: call "InlineArrayElementRef<<>y__InlineArray3, int>(ref <>y__InlineArray3, int)" IL_0100: ldloc.3 IL_0101: stind.i4 IL_0102: ldarg.0 - IL_0103: ldflda "__InlineArray3 Program.d__1.<>7__wrap1" + IL_0103: ldflda "<>y__InlineArray3 Program.d__1.<>7__wrap1" IL_0108: ldc.i4.3 - IL_0109: call "InlineArrayAsReadOnlySpan<__InlineArray3, int>(in __InlineArray3, int)" + IL_0109: call "InlineArrayAsReadOnlySpan<<>y__InlineArray3, int>(in <>y__InlineArray3, int)" IL_010e: call "MyCollection MyCollectionBuilder.Create(System.ReadOnlySpan)" IL_0113: stloc.1 IL_0114: leave.s IL_012f diff --git a/src/Compilers/Core/Portable/CodeGen/PrivateImplementationDetails.cs b/src/Compilers/Core/Portable/CodeGen/PrivateImplementationDetails.cs index ed00a288ba80c..b3e845dac8064 100644 --- a/src/Compilers/Core/Portable/CodeGen/PrivateImplementationDetails.cs +++ b/src/Compilers/Core/Portable/CodeGen/PrivateImplementationDetails.cs @@ -82,11 +82,11 @@ internal sealed class PrivateImplementationDetails : DefaultTypeDef, Cci.INamesp new ConcurrentDictionary(); // synthesized inline array types - private readonly ConcurrentDictionary _synthesizedInlineArrayTypes = - new ConcurrentDictionary(); + private ImmutableArray _orderedInlineArrayTypes; + private readonly ConcurrentDictionary _synthesizedInlineArrayTypes = new ConcurrentDictionary(); // field types for different block sizes. - private ImmutableArray _orderedNestedTypes; + private ImmutableArray _orderedProxyTypes; private readonly ConcurrentDictionary<(uint Size, ushort Alignment), Cci.ITypeReference> _proxyTypes = new ConcurrentDictionary<(uint Size, ushort Alignment), Cci.ITypeReference>(); internal PrivateImplementationDetails( @@ -135,12 +135,6 @@ private static string GetClassName(string moduleName, int submissionSlotIndex, b return name; } - internal static string GetInlineArrayTypeName(int arrayLength) - { - Debug.Assert(arrayLength > 0); - return $"__InlineArray{arrayLength}"; - } - internal void Freeze() { var wasFrozen = Interlocked.Exchange(ref _frozen, 1); @@ -164,10 +158,11 @@ internal void Freeze() // Sort methods. _orderedSynthesizedMethods = _synthesizedMethods.OrderBy(kvp => kvp.Key).Select(kvp => kvp.Value).AsImmutable(); - // Sort nested types. - var orderedProxyTypes = _proxyTypes.OrderBy(kvp => kvp.Key.Size).ThenBy(kvp => kvp.Key.Alignment).Select(kvp => kvp.Value).OfType(); - var orderedInlineArrayTypes = _synthesizedInlineArrayTypes.OrderBy(kvp => kvp.Key).Select(kvp => (Cci.INestedTypeDefinition)kvp.Value); - _orderedNestedTypes = orderedProxyTypes.Concat(orderedInlineArrayTypes).AsImmutable(); + // Sort top-level types. + _orderedInlineArrayTypes = _synthesizedInlineArrayTypes.OrderBy(kvp => kvp.Key).Select(kvp => (Cci.INamespaceTypeDefinition)kvp.Value).AsImmutable(); + + // Sort proxy types. + _orderedProxyTypes = _proxyTypes.OrderBy(kvp => kvp.Key.Size).ThenBy(kvp => kvp.Key.Alignment).Select(kvp => kvp.Value).AsImmutable(); } private bool IsFrozen => _frozen != 0; @@ -311,7 +306,7 @@ internal bool TryAddSynthesizedMethod(Cci.IMethodDefinition method) #nullable enable } - internal bool TryAddSynthesizedType(Cci.INamedTypeDefinition type) + internal bool TryAddSynthesizedType(Cci.INamespaceTypeDefinition type) { Debug.Assert(!IsFrozen); Debug.Assert(type.Name is { }); @@ -338,16 +333,22 @@ internal bool TryAddSynthesizedType(Cci.INamedTypeDefinition type) return method; } - internal Cci.INamedTypeDefinition? GetType(string name) + internal Cci.INamespaceTypeDefinition? GetType(string name) { _synthesizedInlineArrayTypes.TryGetValue(name, out var type); return type; } + internal IEnumerable GetAdditionalTopLevelTypes() + { + Debug.Assert(IsFrozen); + return _orderedInlineArrayTypes; + } + public override IEnumerable GetNestedTypes(EmitContext context) { Debug.Assert(IsFrozen); - return _orderedNestedTypes; + return _orderedProxyTypes.OfType(); } public override string ToString() => this.Name; diff --git a/src/Compilers/Core/Portable/Emit/CommonPEModuleBuilder.cs b/src/Compilers/Core/Portable/Emit/CommonPEModuleBuilder.cs index 651e9cfdacb18..1762c723de65d 100644 --- a/src/Compilers/Core/Portable/Emit/CommonPEModuleBuilder.cs +++ b/src/Compilers/Core/Portable/Emit/CommonPEModuleBuilder.cs @@ -664,6 +664,13 @@ protected bool ContainsTopLevelType(string fullEmittedName) AddTopLevelType(names, privateImpl); VisitTopLevelType(typeReferenceIndexer, privateImpl); yield return privateImpl; + + foreach (var typeDef in privateImpl.GetAdditionalTopLevelTypes()) + { + AddTopLevelType(names, typeDef); + VisitTopLevelType(typeReferenceIndexer, typeDef); + yield return typeDef; + } } if (EmbeddedTypesManagerOpt != null) From c419b512d40de6301df570bf43545de9d8382152 Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Mon, 31 Jul 2023 15:10:28 -0700 Subject: [PATCH 11/14] Break lines --- .../Semantics/CollectionExpressionTests.cs | 171 +++++++++++++++--- 1 file changed, 146 insertions(+), 25 deletions(-) diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index 1593545ecd69d..2db0b06b8dabf 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -2688,7 +2688,11 @@ static void Main() } } """; - var verifier = CompileAndVerify(new[] { source, s_collectionExtensionsWithSpan }, targetFramework: TargetFramework.Net70, verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput("[], [1, 2], [3, 4, 5], [null, 7], ")); + var verifier = CompileAndVerify( + new[] { source, s_collectionExtensionsWithSpan }, + targetFramework: TargetFramework.Net70, + verify: Verification.Skipped, + expectedOutput: IncludeExpectedOutput("[], [1, 2], [3, 4, 5], [null, 7], ")); verifier.VerifyIL("Program.Create1", $$""" { // Code size 12 (0xc) @@ -2783,7 +2787,11 @@ static void Main() } } """; - CompileAndVerify(new[] { source, s_collectionExtensionsWithSpan }, targetFramework: TargetFramework.Net70, verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); + CompileAndVerify( + new[] { source, s_collectionExtensionsWithSpan }, + targetFramework: TargetFramework.Net70, + verify: Verification.Skipped, + expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); } [Theory] @@ -2804,7 +2812,11 @@ static void Main() } } """; - CompileAndVerify(new[] { source, s_collectionExtensionsWithSpan }, targetFramework: TargetFramework.Net70, verify: Verification.Skipped, expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); + CompileAndVerify( + new[] { source, s_collectionExtensionsWithSpan }, + targetFramework: TargetFramework.Net70, + verify: Verification.Skipped, + expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); } [Theory] @@ -6326,7 +6338,12 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); + CompileAndVerify( + new[] { sourceB, s_collectionExtensions }, + references: new[] { refA }, + targetFramework: TargetFramework.Net80, + verify: Verification.Fails, + expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); } [CombinatorialData] @@ -6370,7 +6387,12 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("(MyCollectionBuilder.MyCollection) [], (MyCollectionBuilder.MyCollection) [1, 2, 3], ")); + CompileAndVerify( + new[] { sourceB, s_collectionExtensions }, + references: new[] { refA }, + targetFramework: TargetFramework.Net80, + verify: Verification.Fails, + expectedOutput: IncludeExpectedOutput("(MyCollectionBuilder.MyCollection) [], (MyCollectionBuilder.MyCollection) [1, 2, 3], ")); } [CombinatorialData] @@ -6463,7 +6485,12 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("(Container.MyCollection) [], (Container.MyCollection) [1, 2, 3], ")); + CompileAndVerify( + new[] { sourceB, s_collectionExtensions }, + references: new[] { refA }, + targetFramework: TargetFramework.Net80, + verify: Verification.Fails, + expectedOutput: IncludeExpectedOutput("(Container.MyCollection) [], (Container.MyCollection) [1, 2, 3], ")); } [CombinatorialData] @@ -6565,7 +6592,12 @@ static IEnumerable GetElements(MyCollection c) } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); + CompileAndVerify( + new[] { sourceB, s_collectionExtensions }, + references: new[] { refA }, + targetFramework: TargetFramework.Net80, + verify: Verification.Fails, + expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); } [CombinatorialData] @@ -6625,7 +6657,12 @@ static IEnumerable GetElements(MyCollection c) } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); + CompileAndVerify( + new[] { sourceB, s_collectionExtensions }, + references: new[] { refA }, + targetFramework: TargetFramework.Net80, + verify: Verification.Fails, + expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); } [CombinatorialData] @@ -6664,7 +6701,12 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); + CompileAndVerify( + new[] { sourceB, s_collectionExtensions }, + references: new[] { refA }, + targetFramework: TargetFramework.Net80, + verify: Verification.Fails, + expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); } [CombinatorialData] @@ -6755,7 +6797,12 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("(C) [null], (C) [E(1), null], ")); + CompileAndVerify( + new[] { sourceB, s_collectionExtensions }, + references: new[] { refA }, + targetFramework: TargetFramework.Net80, + verify: Verification.Fails, + expectedOutput: IncludeExpectedOutput("(C) [null], (C) [E(1), null], ")); } [CombinatorialData] @@ -6801,7 +6848,12 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("[], [[one, 1], [two, 2]], ")); + CompileAndVerify( + new[] { sourceB, s_collectionExtensions }, + references: new[] { refA }, + targetFramework: TargetFramework.Net80, + verify: Verification.Fails, + expectedOutput: IncludeExpectedOutput("[], [[one, 1], [two, 2]], ")); } [Fact] @@ -7423,7 +7475,12 @@ static IEnumerable GetElements(MyCollection c) } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput($"[], [1, 2, 3], ")); + CompileAndVerify( + new[] { sourceB, s_collectionExtensions }, + references: new[] { refA }, + targetFramework: TargetFramework.Net80, + verify: Verification.Fails, + expectedOutput: IncludeExpectedOutput($"[], [1, 2, 3], ")); } [CombinatorialData] @@ -7473,7 +7530,12 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput($"[], {expectedOutput}, ")); + CompileAndVerify( + new[] { sourceB, s_collectionExtensions }, + references: new[] { refA }, + targetFramework: TargetFramework.Net80, + verify: Verification.Fails, + expectedOutput: IncludeExpectedOutput($"[], {expectedOutput}, ")); } // If there are multiple attributes, the first is used. @@ -7529,7 +7591,12 @@ static void Main() } } """; - var verifier = CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("[1, 2, 3], ")); + var verifier = CompileAndVerify( + new[] { sourceB, s_collectionExtensions }, + references: new[] { refA }, + targetFramework: TargetFramework.Net80, + verify: Verification.Fails, + expectedOutput: IncludeExpectedOutput("[1, 2, 3], ")); comp = (CSharpCompilation)verifier.Compilation; var collectionType = (NamedTypeSymbol)comp.GetMember("Program.F").ReturnType; @@ -7715,7 +7782,12 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("(Container.MyCollection) [], (Container.MyCollection) [1, 2, 3], ")); + CompileAndVerify( + new[] { sourceB, s_collectionExtensions }, + references: new[] { refA }, + targetFramework: TargetFramework.Net80, + verify: Verification.Fails, + expectedOutput: IncludeExpectedOutput("(Container.MyCollection) [], (Container.MyCollection) [1, 2, 3], ")); } [CombinatorialData] @@ -7759,7 +7831,12 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("(Container.MyCollection) [], (Container.MyCollection) [1, 2, 3], ")); + CompileAndVerify( + new[] { sourceB, s_collectionExtensions }, + references: new[] { refA }, + targetFramework: TargetFramework.Net80, + verify: Verification.Fails, + expectedOutput: IncludeExpectedOutput("(Container.MyCollection) [], (Container.MyCollection) [1, 2, 3], ")); } [CombinatorialData] @@ -7803,7 +7880,12 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("(Container.MyCollection) [], (Container.MyCollection) [1, 2, 3], ")); + CompileAndVerify( + new[] { sourceB, s_collectionExtensions }, + references: new[] { refA }, + targetFramework: TargetFramework.Net80, + verify: Verification.Fails, + expectedOutput: IncludeExpectedOutput("(Container.MyCollection) [], (Container.MyCollection) [1, 2, 3], ")); } [CombinatorialData] @@ -7844,7 +7926,12 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("(MyCollection) [], (MyCollection) [1, 2, 3], ")); + CompileAndVerify( + new[] { sourceB, s_collectionExtensions }, + references: new[] { refA }, + targetFramework: TargetFramework.Net80, + verify: Verification.Fails, + expectedOutput: IncludeExpectedOutput("(MyCollection) [], (MyCollection) [1, 2, 3], ")); } [CombinatorialData] @@ -7885,7 +7972,12 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("(MyCollection) [], (MyCollection) [1, 2, 3], ")); + CompileAndVerify( + new[] { sourceB, s_collectionExtensions }, + references: new[] { refA }, + targetFramework: TargetFramework.Net80, + verify: Verification.Fails, + expectedOutput: IncludeExpectedOutput("(MyCollection) [], (MyCollection) [1, 2, 3], ")); } [CombinatorialData] @@ -7972,7 +8064,12 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); + CompileAndVerify( + new[] { sourceB, s_collectionExtensions }, + references: new[] { refA }, + targetFramework: TargetFramework.Net80, + verify: Verification.Fails, + expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); } [CombinatorialData] @@ -8119,7 +8216,12 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); + CompileAndVerify( + new[] { sourceB, s_collectionExtensions }, + references: new[] { refA }, + targetFramework: TargetFramework.Net80, + verify: Verification.Fails, + expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); } [CombinatorialData] @@ -8166,7 +8268,12 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); + CompileAndVerify( + new[] { sourceB, s_collectionExtensions }, + references: new[] { refA }, + targetFramework: TargetFramework.Net80, + verify: Verification.Fails, + expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); } [CombinatorialData] @@ -8692,7 +8799,12 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB1, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); + CompileAndVerify( + new[] { sourceB1, s_collectionExtensions }, + references: new[] { refA }, + targetFramework: TargetFramework.Net80, + verify: Verification.Fails, + expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); string sourceB2 = """ #pragma warning disable 219 @@ -8750,7 +8862,12 @@ static void Main() } } """; - CompileAndVerify(new[] { sourceB1, s_collectionExtensions }, references: new[] { refA }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); + CompileAndVerify( + new[] { sourceB1, s_collectionExtensions }, + references: new[] { refA }, + targetFramework: TargetFramework.Net80, + verify: Verification.Fails, + expectedOutput: IncludeExpectedOutput("[], [1, 2, 3], ")); string sourceB2 = """ #pragma warning disable 219 @@ -9298,7 +9415,11 @@ static async Task F(int i) } } """; - var verifier = CompileAndVerify(new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition, s_collectionExtensions }, targetFramework: TargetFramework.Net80, verify: Verification.Fails, expectedOutput: IncludeExpectedOutput("[1, 2, 3], ")); + var verifier = CompileAndVerify( + new[] { sourceA, sourceB, CollectionBuilderAttributeDefinition, s_collectionExtensions }, + targetFramework: TargetFramework.Net80, + verify: Verification.Fails, + expectedOutput: IncludeExpectedOutput("[1, 2, 3], ")); verifier.VerifyIL("Program.d__1.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", """ { From 60e248e579c8119ab03c4921d6a1e67ca8a19972 Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Mon, 31 Jul 2023 15:35:28 -0700 Subject: [PATCH 12/14] Fix build --- .../Symbols/Synthesized/SynthesizedInlineArrayTypeSymbol.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInlineArrayTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInlineArrayTypeSymbol.cs index 28ee328562a82..fcbbce9b0ed9b 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInlineArrayTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedInlineArrayTypeSymbol.cs @@ -17,7 +17,7 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols /// A synthesized type used during emit to allow temp locals of Span<T> /// of a specific length where the span storage is on the stack. /// - /// [InlineArray(N)] struct <>y__InlineArrayN<T> { private T _element0; } + /// [InlineArray(N)] struct <>y__InlineArrayN<T> { private T _element0; } /// /// internal sealed class SynthesizedInlineArrayTypeSymbol : NamedTypeSymbol From adae5cd6660a524145f426c023c049278c07d721 Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Tue, 1 Aug 2023 09:41:09 -0700 Subject: [PATCH 13/14] Address feedback --- .../Portable/Emitter/Model/PEModuleBuilder.cs | 6 +-- .../Semantics/CollectionExpressionTests.cs | 47 +++++++++++++++++++ .../CodeGen/PrivateImplementationDetails.cs | 28 +++++------ 3 files changed, 64 insertions(+), 17 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs b/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs index d3daa560df987..41ebcfef52aad 100644 --- a/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs +++ b/src/Compilers/CSharp/Portable/Emitter/Model/PEModuleBuilder.cs @@ -1975,9 +1975,9 @@ internal NamedTypeSymbol EnsureInlineArrayTypeExists(SyntaxNode syntaxNode, Synt Debug.Assert(Compilation.Assembly.RuntimeSupportsInlineArrayTypes); Debug.Assert(arrayLength > 0); - string typeName = $"<>y__InlineArray{arrayLength}"; // see GeneratedNameKind.InlineArrayType + string typeName = $"<>{(char)GeneratedNameKind.InlineArrayType}__InlineArray{arrayLength}"; var privateImplClass = GetPrivateImplClass(syntaxNode, diagnostics); - var typeAdapter = privateImplClass.GetType(typeName); + var typeAdapter = privateImplClass.GetSynthesizedType(typeName); if (typeAdapter is null) { @@ -1986,7 +1986,7 @@ internal NamedTypeSymbol EnsureInlineArrayTypeExists(SyntaxNode syntaxNode, Synt var typeSymbol = new SynthesizedInlineArrayTypeSymbol(SourceModule, typeName, arrayLength, attributeConstructor); privateImplClass.TryAddSynthesizedType(typeSymbol.GetCciAdapter()); - typeAdapter = privateImplClass.GetType(typeName)!; + typeAdapter = privateImplClass.GetSynthesizedType(typeName)!; } Debug.Assert(typeAdapter.Name == typeName); diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index 2db0b06b8dabf..11cb71d8613f0 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -9371,6 +9371,53 @@ static void Main() Diagnostic(ErrorCode.ERR_EscapeVariable, "items").WithArguments("scoped System.ReadOnlySpan items").WithLocation(16, 82)); } + [CombinatorialData] + [Theory] + public void CollectionBuilder_MissingInt32(bool useCompilationReference) + { + string sourceA = """ + using System; + using System.Collections.Generic; + using System.Runtime.CompilerServices; + [CollectionBuilder(typeof(MyCollectionBuilder), nameof(MyCollectionBuilder.Create))] + public struct MyCollection + { + public IEnumerator GetEnumerator() => default; + } + public class MyCollectionBuilder + { + public static MyCollection Create(ReadOnlySpan items) => default; + } + """; + var comp = CreateCompilation(new[] { sourceA, CollectionBuilderAttributeDefinition }, targetFramework: TargetFramework.Net80); + var refA = AsReference(comp, useCompilationReference); + + string sourceB = """ + #pragma warning disable 219 + class Program + { + static void Main() + { + MyCollection x = []; + MyCollection y = ["2"]; + MyCollection z = new(); + } + } + """; + comp = CreateCompilation(sourceB, references: new[] { refA }, targetFramework: TargetFramework.Net80); + comp.MakeTypeMissing(SpecialType.System_Int32); + comp.VerifyEmitDiagnostics( + // (7,34): error CS0518: Predefined type 'System.Int32' is not defined or imported + // MyCollection y = ["2"]; + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, @"[""2""]").WithArguments("System.Int32").WithLocation(7, 34), + // (7,34): error CS0518: Predefined type 'System.Int32' is not defined or imported + // MyCollection y = ["2"]; + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, @"[""2""]").WithArguments("System.Int32").WithLocation(7, 34), + // (7,34): error CS0518: Predefined type 'System.Int32' is not defined or imported + // MyCollection y = ["2"]; + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, @"[""2""]").WithArguments("System.Int32").WithLocation(7, 34)); + } + [Fact] public void CollectionBuilder_Async() { diff --git a/src/Compilers/Core/Portable/CodeGen/PrivateImplementationDetails.cs b/src/Compilers/Core/Portable/CodeGen/PrivateImplementationDetails.cs index b3e845dac8064..0da329ec67684 100644 --- a/src/Compilers/Core/Portable/CodeGen/PrivateImplementationDetails.cs +++ b/src/Compilers/Core/Portable/CodeGen/PrivateImplementationDetails.cs @@ -81,9 +81,9 @@ internal sealed class PrivateImplementationDetails : DefaultTypeDef, Cci.INamesp private readonly ConcurrentDictionary _synthesizedMethods = new ConcurrentDictionary(); - // synthesized inline array types - private ImmutableArray _orderedInlineArrayTypes; - private readonly ConcurrentDictionary _synthesizedInlineArrayTypes = new ConcurrentDictionary(); + // synthesized top-level types (for inline arrays currently) + private ImmutableArray _orderedTopLevelTypes; + private readonly ConcurrentDictionary _synthesizedTopLevelTypes = new ConcurrentDictionary(); // field types for different block sizes. private ImmutableArray _orderedProxyTypes; @@ -159,7 +159,7 @@ internal void Freeze() _orderedSynthesizedMethods = _synthesizedMethods.OrderBy(kvp => kvp.Key).Select(kvp => kvp.Value).AsImmutable(); // Sort top-level types. - _orderedInlineArrayTypes = _synthesizedInlineArrayTypes.OrderBy(kvp => kvp.Key).Select(kvp => (Cci.INamespaceTypeDefinition)kvp.Value).AsImmutable(); + _orderedTopLevelTypes = _synthesizedTopLevelTypes.OrderBy(kvp => kvp.Key).Select(kvp => (Cci.INamespaceTypeDefinition)kvp.Value).AsImmutable(); // Sort proxy types. _orderedProxyTypes = _proxyTypes.OrderBy(kvp => kvp.Key.Size).ThenBy(kvp => kvp.Key.Alignment).Select(kvp => kvp.Value).AsImmutable(); @@ -306,13 +306,6 @@ internal bool TryAddSynthesizedMethod(Cci.IMethodDefinition method) #nullable enable } - internal bool TryAddSynthesizedType(Cci.INamespaceTypeDefinition type) - { - Debug.Assert(!IsFrozen); - Debug.Assert(type.Name is { }); - return _synthesizedInlineArrayTypes.TryAdd(type.Name, type); - } - public override IEnumerable GetFields(EmitContext context) { Debug.Assert(IsFrozen); @@ -333,16 +326,23 @@ internal bool TryAddSynthesizedType(Cci.INamespaceTypeDefinition type) return method; } - internal Cci.INamespaceTypeDefinition? GetType(string name) + internal bool TryAddSynthesizedType(Cci.INamespaceTypeDefinition type) + { + Debug.Assert(!IsFrozen); + Debug.Assert(type.Name is { }); + return _synthesizedTopLevelTypes.TryAdd(type.Name, type); + } + + internal Cci.INamespaceTypeDefinition? GetSynthesizedType(string name) { - _synthesizedInlineArrayTypes.TryGetValue(name, out var type); + _synthesizedTopLevelTypes.TryGetValue(name, out var type); return type; } internal IEnumerable GetAdditionalTopLevelTypes() { Debug.Assert(IsFrozen); - return _orderedInlineArrayTypes; + return _orderedTopLevelTypes; } public override IEnumerable GetNestedTypes(EmitContext context) From 6fc3312cc1a32d121176f3f7df2f1b825c81745d Mon Sep 17 00:00:00 2001 From: Charles Stoner <10732005+cston@users.noreply.github.com> Date: Tue, 1 Aug 2023 11:59:42 -0700 Subject: [PATCH 14/14] Add back deleted test --- .../Test/Emit2/Semantics/CollectionExpressionTests.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index 11cb71d8613f0..0657236b044dc 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -7491,6 +7491,14 @@ public void CollectionBuilder_TypeDifferences_TupleElementNames(bool useCompilat CollectionBuilder_TypeDifferences("(int A, int B)", "(int, int)", "(1, 2), default", "[(1, 2), (0, 0)]", useCompilationReference); } + [CombinatorialData] + [Theory] + public void CollectionBuilder_TypeDifferences_Nullability(bool useCompilationReference) + { + CollectionBuilder_TypeDifferences("object", "object?", "1, 2, 3", "[1, 2, 3]", useCompilationReference); + CollectionBuilder_TypeDifferences("object?", "object", "1, null, 3", "[1, null, 3]", useCompilationReference); + } + private void CollectionBuilder_TypeDifferences(string collectionElementType, string builderElementType, string values, string expectedOutput, bool useCompilationReference) { string sourceA = $$"""