diff --git a/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs b/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs index 899b07335b2057..4c9fb787870fd1 100644 --- a/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs +++ b/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs @@ -210,6 +210,7 @@ public static partial class ImmutableArray public static System.Collections.Immutable.ImmutableArray ToImmutableArray(this System.ReadOnlySpan items) { throw null; } public static System.Collections.Immutable.ImmutableArray ToImmutableArray(this System.Span items) { throw null; } } + [System.Runtime.CompilerServices.CollectionBuilderAttribute(typeof(System.Collections.Immutable.ImmutableArray), "Create")] public readonly partial struct ImmutableArray : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList, System.Collections.Immutable.IImmutableList, System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IEquatable> { private readonly T[] array; @@ -566,6 +567,7 @@ public static partial class ImmutableHashSet public static System.Collections.Immutable.ImmutableHashSet ToImmutableHashSet(this System.Collections.Immutable.ImmutableHashSet.Builder builder) { throw null; } } + [System.Runtime.CompilerServices.CollectionBuilderAttribute(typeof(System.Collections.Immutable.ImmutableHashSet), "Create")] #if NETCOREAPP public sealed partial class ImmutableHashSet : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.ISet, System.Collections.Generic.IReadOnlySet, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.Immutable.IImmutableSet #else @@ -700,6 +702,7 @@ public static partial class ImmutableList public static System.Collections.Immutable.ImmutableList ToImmutableList(this System.Collections.Generic.IEnumerable source) { throw null; } public static System.Collections.Immutable.ImmutableList ToImmutableList(this System.Collections.Immutable.ImmutableList.Builder builder) { throw null; } } + [System.Runtime.CompilerServices.CollectionBuilderAttribute(typeof(System.Collections.Immutable.ImmutableList), "Create")] public sealed partial class ImmutableList : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList, System.Collections.Immutable.IImmutableList { internal ImmutableList() { } @@ -883,6 +886,7 @@ public static partial class ImmutableQueue public static System.Collections.Immutable.ImmutableQueue Create(System.ReadOnlySpan items) { throw null; } public static System.Collections.Immutable.IImmutableQueue Dequeue(this System.Collections.Immutable.IImmutableQueue queue, out T value) { throw null; } } + [System.Runtime.CompilerServices.CollectionBuilderAttribute(typeof(System.Collections.Immutable.ImmutableQueue), "Create")] public sealed partial class ImmutableQueue : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable, System.Collections.Immutable.IImmutableQueue { internal ImmutableQueue() { } @@ -1064,6 +1068,7 @@ public static partial class ImmutableSortedSet public static System.Collections.Immutable.ImmutableSortedSet ToImmutableSortedSet(this System.Collections.Immutable.ImmutableSortedSet.Builder builder) { throw null; } } + [System.Runtime.CompilerServices.CollectionBuilderAttribute(typeof(System.Collections.Immutable.ImmutableSortedSet), "Create")] #if NETCOREAPP public sealed partial class ImmutableSortedSet : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.Generic.ISet, System.Collections.Generic.IReadOnlySet, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList, System.Collections.Immutable.IImmutableSet #else @@ -1192,6 +1197,7 @@ public static partial class ImmutableStack public static System.Collections.Immutable.ImmutableStack Create(System.ReadOnlySpan items) { throw null; } public static System.Collections.Immutable.IImmutableStack Pop(this System.Collections.Immutable.IImmutableStack stack, out T value) { throw null; } } + [System.Runtime.CompilerServices.CollectionBuilderAttribute(typeof(System.Collections.Immutable.ImmutableStack), "Create")] public sealed partial class ImmutableStack : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable, System.Collections.Immutable.IImmutableStack { internal ImmutableStack() { } diff --git a/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.csproj b/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.csproj index 019651ce0a8140..857da22e765370 100644 --- a/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.csproj +++ b/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.csproj @@ -13,6 +13,10 @@ + + + + diff --git a/src/libraries/System.Collections.Immutable/src/System.Collections.Immutable.csproj b/src/libraries/System.Collections.Immutable/src/System.Collections.Immutable.csproj index 62da301516b2ae..2f270f3d451b89 100644 --- a/src/libraries/System.Collections.Immutable/src/System.Collections.Immutable.csproj +++ b/src/libraries/System.Collections.Immutable/src/System.Collections.Immutable.csproj @@ -147,6 +147,10 @@ The System.Collections.Immutable library is built-in as part of the shared frame + + + + diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.cs index 6c9fdb1341cbaa..4fdbf233159b1c 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.cs @@ -6,10 +6,12 @@ using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; +using System.Runtime.CompilerServices; using System.Runtime.Versioning; namespace System.Collections.Immutable { + [CollectionBuilder(typeof(ImmutableArray), nameof(ImmutableArray.Create))] public readonly partial struct ImmutableArray : IReadOnlyList, IList, IEquatable>, IList, IImmutableArray, IStructuralComparable, IStructuralEquatable, IImmutableList { /// diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet_1.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet_1.cs index b0117e84212154..b2e073484bb4ad 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet_1.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet_1.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Runtime.CompilerServices; namespace System.Collections.Immutable { @@ -11,6 +12,7 @@ namespace System.Collections.Immutable /// An immutable unordered hash set implementation. /// /// The type of elements in the set. + [CollectionBuilder(typeof(ImmutableHashSet), nameof(ImmutableHashSet.Create))] [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(ImmutableEnumerableDebuggerProxy<>))] #if NETCOREAPP diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableList_1.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableList_1.cs index 966244fa4ead4d..f17c38775ec5b2 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableList_1.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableList_1.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; +using System.Runtime.CompilerServices; namespace System.Collections.Immutable { @@ -12,6 +13,7 @@ namespace System.Collections.Immutable /// An immutable list implementation. /// /// The type of elements in the set. + [CollectionBuilder(typeof(ImmutableList), nameof(ImmutableList.Create))] [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(ImmutableEnumerableDebuggerProxy<>))] public sealed partial class ImmutableList : IImmutableList, IList, IList, IOrderedCollection, IImmutableListQueries, IStrongEnumerable.Enumerator> diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableQueue_1.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableQueue_1.cs index b7ee9d7424618b..77411a8e368d82 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableQueue_1.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableQueue_1.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; +using System.Runtime.CompilerServices; namespace System.Collections.Immutable { @@ -12,6 +13,7 @@ namespace System.Collections.Immutable /// An immutable queue. /// /// The type of elements stored in the queue. + [CollectionBuilder(typeof(ImmutableQueue), nameof(ImmutableQueue.Create))] [DebuggerDisplay("IsEmpty = {IsEmpty}")] [DebuggerTypeProxy(typeof(ImmutableEnumerableDebuggerProxy<>))] public sealed partial class ImmutableQueue : IImmutableQueue diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedSet_1.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedSet_1.cs index 493172c31ecba0..2befd4a7c1307d 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedSet_1.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedSet_1.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; +using System.Runtime.CompilerServices; namespace System.Collections.Immutable { @@ -16,6 +17,7 @@ namespace System.Collections.Immutable /// We implement because it adds an ordinal indexer. /// We implement because it gives us , which is important for some folks. /// + [CollectionBuilder(typeof(ImmutableSortedSet), nameof(ImmutableSortedSet.Create))] [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(ImmutableEnumerableDebuggerProxy<>))] #if NETCOREAPP diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableStack_1.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableStack_1.cs index 553ef8bac32bf3..2eefbb8132c562 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableStack_1.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableStack_1.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; +using System.Runtime.CompilerServices; namespace System.Collections.Immutable { @@ -12,6 +13,7 @@ namespace System.Collections.Immutable /// An immutable stack. /// /// The type of element stored by the stack. + [CollectionBuilder(typeof(ImmutableStack), nameof(ImmutableStack.Create))] [DebuggerDisplay("IsEmpty = {IsEmpty}; Top = {_head}")] [DebuggerTypeProxy(typeof(ImmutableEnumerableDebuggerProxy<>))] public sealed partial class ImmutableStack : IImmutableStack diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 2b6f28650abec0..b15194e5f8c370 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -780,6 +780,7 @@ + diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/CollectionBuilderAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/CollectionBuilderAttribute.cs new file mode 100644 index 00000000000000..bbd4978a2f3f82 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/CollectionBuilderAttribute.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Runtime.CompilerServices +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, Inherited = false)] +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class CollectionBuilderAttribute : Attribute + { + /// Initialize the attribute to refer to the method on the type. + /// The type of the builder to use to construct the collection. + /// The name of the method on the builder to use to construct the collection. + /// + /// must refer to a static method that accepts a single parameter of + /// type and returns an instance of the collection being built containing + /// a copy of the data from that span. In future releases of .NET, additional patterns may be supported. + /// + public CollectionBuilderAttribute(Type builderType, string methodName) + { + BuilderType = builderType; + MethodName = methodName; + } + + /// Gets the type of the builder to use to construct the collection. + public Type BuilderType { get; } + + /// Gets the name of the method on the builder to use to construct the collection. + /// This should match the metadata name of the target method. For example, this might be ".ctor" if targeting the type's constructor. + public string MethodName { get; } + } +} diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index 8e10b37e8dd9a0..fcf0e7e159bd63 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -12615,6 +12615,13 @@ public sealed partial class CallerMemberNameAttribute : System.Attribute { public CallerMemberNameAttribute() { } } + [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Interface | System.AttributeTargets.Struct, Inherited = false)] + public sealed class CollectionBuilderAttribute : Attribute + { + public CollectionBuilderAttribute(System.Type builderType, string methodName) { } + public System.Type BuilderType { get { throw null; } } + public string MethodName { get { throw null; } } + } [System.FlagsAttribute] public enum CompilationRelaxations { diff --git a/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/AttributesTests.cs b/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/AttributesTests.cs index 546742b631c8aa..e190690254e036 100644 --- a/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/AttributesTests.cs +++ b/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/AttributesTests.cs @@ -47,6 +47,14 @@ public static void CallerMemberNameAttributeTests() new CallerMemberNameAttribute(); } + [Fact] + public static void CollectionBuilderAttributeTests() + { + var attr = new CollectionBuilderAttribute(typeof(AttributesTests), "Create"); + Assert.Same(typeof(AttributesTests), attr.BuilderType); + Assert.Equal("Create", attr.MethodName); + } + [Fact] public static void CompilationRelaxationsAttributeTests() {