From 8b7074e79e2a4c4aa99eab2b7a45bc52b9df59b2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 7 Sep 2026 02:19:48 +0000 Subject: [PATCH 1/3] Share reflection ListBuilder between CoreCLR and Native AOT Co-authored-by: MichalStrehovsky <13110571+MichalStrehovsky@users.noreply.github.com> --- .../Reflection/RuntimeCustomAttributeData.cs | 42 ++--- .../src/System/RuntimeType.CoreCLR.cs | 81 --------- .../src/System.Private.CoreLib.csproj | 1 - .../Reflection/Runtime/General/ListBuilder.cs | 97 ----------- .../Common/tests/Common.Tests.csproj | 4 + .../tests/Tests/System/ListBuilderTests.cs | 161 ++++++++++++++++++ .../System.Private.CoreLib.Shared.projitems | 1 + .../src/System/ListBuilder.cs | 88 ++++++++++ 8 files changed, 275 insertions(+), 200 deletions(-) delete mode 100644 src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ListBuilder.cs create mode 100644 src/libraries/Common/tests/Tests/System/ListBuilderTests.cs create mode 100644 src/libraries/System.Private.CoreLib/src/System/ListBuilder.cs diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs index 3cff671007e030..a738a17f56d956 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs @@ -20,7 +20,7 @@ internal static IList GetCustomAttributesInternal(RuntimeTy Debug.Assert(target is not null); IList cad = GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken); - RuntimeType.ListBuilder pcas = default; + ListBuilder pcas = default; PseudoCustomAttribute.GetCustomAttributes(target, (RuntimeType)typeof(object), ref pcas); return pcas.Count > 0 ? GetCombinedList(cad, ref pcas) : cad; } @@ -30,7 +30,7 @@ internal static IList GetCustomAttributesInternal(RuntimeFi Debug.Assert(target is not null); IList cad = GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken); - RuntimeType.ListBuilder pcas = default; + ListBuilder pcas = default; PseudoCustomAttribute.GetCustomAttributes(target, (RuntimeType)typeof(object), ref pcas); return pcas.Count > 0 ? GetCombinedList(cad, ref pcas) : cad; } @@ -40,7 +40,7 @@ internal static IList GetCustomAttributesInternal(RuntimeMe Debug.Assert(target is not null); IList cad = GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken); - RuntimeType.ListBuilder pcas = default; + ListBuilder pcas = default; PseudoCustomAttribute.GetCustomAttributes(target, (RuntimeType)typeof(object), ref pcas); return pcas.Count > 0 ? GetCombinedList(cad, ref pcas) : cad; } @@ -89,13 +89,13 @@ internal static IList GetCustomAttributesInternal(RuntimePa { Debug.Assert(target is not null); - RuntimeType.ListBuilder pcas = default; + ListBuilder pcas = default; IList cad = GetCustomAttributes(target.GetRuntimeModule()!, target.MetadataToken); PseudoCustomAttribute.GetCustomAttributes(target, (RuntimeType)typeof(object), ref pcas); return pcas.Count > 0 ? GetCombinedList(cad, ref pcas) : cad; } - private static ReadOnlyCollection GetCombinedList(IList customAttributes, ref RuntimeType.ListBuilder pseudoAttributes) + private static ReadOnlyCollection GetCombinedList(IList customAttributes, ref ListBuilder pseudoAttributes) { Debug.Assert(pseudoAttributes.Count != 0); @@ -1253,7 +1253,7 @@ internal static object[] GetCustomAttributes(RuntimeType type, RuntimeType caTyp if (type.IsGenericType && !type.IsGenericTypeDefinition) type = (type.GetGenericTypeDefinition() as RuntimeType)!; - RuntimeType.ListBuilder pcas = default; + ListBuilder pcas = default; PseudoCustomAttribute.GetCustomAttributes(type, caType, ref pcas); // if we are asked to go up the hierarchy chain we have to do it now and regardless of the @@ -1266,7 +1266,7 @@ internal static object[] GetCustomAttributes(RuntimeType type, RuntimeType caTyp return attributes; } - RuntimeType.ListBuilder result = default; + ListBuilder result = default; bool mustBeInheritable = false; for (int i = 0; i < pcas.Count; i++) @@ -1295,7 +1295,7 @@ internal static object[] GetCustomAttributes(RuntimeMethodInfo method, RuntimeTy if (method.IsGenericMethod && !method.IsGenericMethodDefinition) method = (method.GetGenericMethodDefinition() as RuntimeMethodInfo)!; - RuntimeType.ListBuilder pcas = default; + ListBuilder pcas = default; PseudoCustomAttribute.GetCustomAttributes(method, caType, ref pcas); // if we are asked to go up the hierarchy chain we have to do it now and regardless of the @@ -1308,7 +1308,7 @@ internal static object[] GetCustomAttributes(RuntimeMethodInfo method, RuntimeTy return attributes; } - RuntimeType.ListBuilder result = default; + ListBuilder result = default; bool mustBeInheritable = false; for (int i = 0; i < pcas.Count; i++) @@ -1364,7 +1364,7 @@ internal static object[] GetCustomAttributes(RuntimeFieldInfo field, RuntimeType Debug.Assert(field is not null); Debug.Assert(caType is not null); - RuntimeType.ListBuilder pcas = default; + ListBuilder pcas = default; PseudoCustomAttribute.GetCustomAttributes(field, caType, ref pcas); object[] attributes = GetCustomAttributes(field.GetRuntimeModule(), field.MetadataToken, pcas.Count, caType); if (pcas.Count > 0) pcas.CopyTo(attributes, attributes.Length - pcas.Count); @@ -1376,7 +1376,7 @@ internal static object[] GetCustomAttributes(RuntimeParameterInfo parameter, Run Debug.Assert(parameter is not null); Debug.Assert(caType is not null); - RuntimeType.ListBuilder pcas = default; + ListBuilder pcas = default; PseudoCustomAttribute.GetCustomAttributes(parameter, caType, ref pcas); object[] attributes = GetCustomAttributes(parameter.GetRuntimeModule()!, parameter.MetadataToken, pcas.Count, caType); if (pcas.Count > 0) pcas.CopyTo(attributes, attributes.Length - pcas.Count); @@ -1432,7 +1432,7 @@ private static bool IsCustomAttributeDefined( { Debug.Assert(attributeCtorToken == 0); - RuntimeType.ListBuilder derivedAttributes = default; + ListBuilder derivedAttributes = default; for (int i = 0; i < attributeTokens.Length; i++) { @@ -1471,7 +1471,7 @@ private static bool IsCustomAttributeDefined( private static object[] GetCustomAttributes( RuntimeModule decoratedModule, int decoratedMetadataToken, int pcaCount, RuntimeType attributeFilterType) { - RuntimeType.ListBuilder attributes = default; + ListBuilder attributes = default; AddCustomAttributes(ref attributes, decoratedModule, decoratedMetadataToken, attributeFilterType, false, default); @@ -1488,11 +1488,11 @@ private static object[] GetCustomAttributes( "attribute instantiation which is present in the code linker has analyzed." + "As such the reflection usage in this method will never fail as those methods/fields will be present.")] private static void AddCustomAttributes( - ref RuntimeType.ListBuilder attributes, + ref ListBuilder attributes, RuntimeModule decoratedModule, int decoratedMetadataToken, RuntimeType? attributeFilterType, bool mustBeInheritable, // The derivedAttributes list must be passed by value so that it is not modified with the discovered attributes - RuntimeType.ListBuilder derivedAttributes) + ListBuilder derivedAttributes) { CustomAttributeRecord[] car = RuntimeCustomAttributeData.GetCustomAttributeRecords(decoratedModule, decoratedMetadataToken); @@ -1624,7 +1624,7 @@ private static bool FilterCustomAttributeRecord( MetadataToken decoratedToken, RuntimeType attributeFilterType, bool mustBeInheritable, - ref RuntimeType.ListBuilder derivedAttributes, + ref ListBuilder derivedAttributes, out RuntimeType attributeType, out IRuntimeMethodInfo? ctorWithParameters, out bool isVarArg) @@ -1731,7 +1731,7 @@ private static bool MatchesTypeFilter(RuntimeType attributeType, RuntimeType att #region Private Static Methods private static bool AttributeUsageCheck( - RuntimeType attributeType, bool mustBeInheritable, ref RuntimeType.ListBuilder derivedAttributes) + RuntimeType attributeType, bool mustBeInheritable, ref ListBuilder derivedAttributes) { AttributeUsageAttribute? attributeUsageAttribute = null; @@ -1984,7 +1984,7 @@ private static void VerifyPseudoCustomAttribute(RuntimeType pca) #endregion #region Internal Static - internal static void GetCustomAttributes(RuntimeType type, RuntimeType caType, ref RuntimeType.ListBuilder pcas) + internal static void GetCustomAttributes(RuntimeType type, RuntimeType caType, ref ListBuilder pcas) { Debug.Assert(type is not null); Debug.Assert(caType is not null); @@ -2028,7 +2028,7 @@ internal static bool IsDefined(RuntimeType type, RuntimeType? caType) return false; } - internal static void GetCustomAttributes(RuntimeMethodInfo method, RuntimeType caType, ref RuntimeType.ListBuilder pcas) + internal static void GetCustomAttributes(RuntimeMethodInfo method, RuntimeType caType, ref ListBuilder pcas) { Debug.Assert(method is not null); Debug.Assert(caType is not null); @@ -2068,7 +2068,7 @@ internal static bool IsDefined(RuntimeMethodInfo method, RuntimeType? caType) return false; } - internal static void GetCustomAttributes(RuntimeParameterInfo parameter, RuntimeType caType, ref RuntimeType.ListBuilder pcas) + internal static void GetCustomAttributes(RuntimeParameterInfo parameter, RuntimeType caType, ref ListBuilder pcas) { Debug.Assert(parameter is not null); Debug.Assert(caType is not null); @@ -2124,7 +2124,7 @@ internal static bool IsDefined(RuntimeParameterInfo parameter, RuntimeType? caTy return false; } - internal static void GetCustomAttributes(RuntimeFieldInfo field, RuntimeType caType, ref RuntimeType.ListBuilder pcas) + internal static void GetCustomAttributes(RuntimeFieldInfo field, RuntimeType caType, ref ListBuilder pcas) { Debug.Assert(field is not null); Debug.Assert(caType is not null); diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs index 3e4d90b0cb8161..bb55d7f1593c10 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs @@ -48,87 +48,6 @@ internal enum MemberListType HandleToInfo } - // Helper to build lists of MemberInfos. Special cased to avoid allocations for lists of one element. - internal struct ListBuilder where T : class - { - private T[]? _items; - private T _item; - private int _count; - private int _capacity; - - public ListBuilder(int capacity) - { - _items = null; - _item = null!; - _count = 0; - _capacity = capacity; - } - - public T this[int index] - { - get - { - Debug.Assert(index < Count); - return (_items != null) ? _items[index] : _item; - } - } - - public T[] ToArray() - { - if (_count == 0) - return []; - if (_count == 1) - return [_item]; - - Array.Resize(ref _items, _count); - _capacity = _count; - return _items!; - } - - public void CopyTo(object[] array, int index) - { - if (_count == 0) - return; - - if (_count == 1) - { - array[index] = _item; - return; - } - - Array.Copy(_items!, 0, array, index, _count); - } - - public int Count => _count; - - public void Add(T item) - { - if (_count == 0) - { - _item = item; - } - else - { - if (_count == 1) - { - if (_capacity < 2) - _capacity = 4; - _items = new T[_capacity]; - _items[0] = _item; - } - else if (_capacity == _count) - { - int newCapacity = 2 * _capacity; - Array.Resize(ref _items, newCapacity); - _capacity = newCapacity; - } - - _items![_count] = item; - } - _count++; - } - } - internal sealed class RuntimeTypeCache { private const int MAXNAMELEN = 1024; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj index b79d16547ac6fe..e5a0f4b8315a7c 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj @@ -405,7 +405,6 @@ - diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ListBuilder.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ListBuilder.cs deleted file mode 100644 index 6941fcfe9dfe8e..00000000000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ListBuilder.cs +++ /dev/null @@ -1,97 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Diagnostics; - -namespace System.Reflection.Runtime.General -{ - // - // Struct-based list builder that's special cased to avoid allocations for lists of one element. - // - internal struct ListBuilder where T : class - { - public ListBuilder(int capacity) - { - _items = null; - _item = null; - _count = 0; - _capacity = capacity; -#if DEBUG - _toArrayAlreadyCalled = false; -#endif // DEBUG - } - - public T this[int index] - { - get - { - Debug.Assert(index < Count); - return (_items != null) ? _items[index] : _item; - } - } - - public T[] ToArray() - { -#if DEBUG - // ListBuilder does not always allocate a new array, though the ToArray() name connotates that it does (and in fact, we do pass the results - // of this method across api boundaries.) The minimizing of allocations is desirable, however, so instead, we restrict you to one call per ListBuilder. - Debug.Assert(!_toArrayAlreadyCalled, "Cannot call ListBuilder.ToArray() a second time. Copy the one you already got."); -#endif // DEBUG - if (_count == 0) - return Array.Empty(); - if (_count == 1) - return new T[1] { _item }; - - Array.Resize(ref _items, _count); - -#if DEBUG - _toArrayAlreadyCalled = true; -#endif // DEBUG - - return _items; - } - - public int Count - { - get - { - return _count; - } - } - - public void Add(T item) - { - if (_count == 0) - { - _item = item; - } - else - { - if (_count == 1) - { - if (_capacity < 2) - _capacity = 4; - _items = new T[_capacity]; - _items[0] = _item; - } - else if (_capacity == _count) - { - int newCapacity = 2 * _capacity; - Array.Resize(ref _items, newCapacity); - _capacity = newCapacity; - } - - _items[_count] = item; - } - _count++; - } - - private T[] _items; - private T _item; - private int _count; - private int _capacity; -#if DEBUG - private bool _toArrayAlreadyCalled; -#endif // DEBUG - } -} diff --git a/src/libraries/Common/tests/Common.Tests.csproj b/src/libraries/Common/tests/Common.Tests.csproj index dd184b098635f5..443af1568c7e90 100644 --- a/src/libraries/Common/tests/Common.Tests.csproj +++ b/src/libraries/Common/tests/Common.Tests.csproj @@ -111,6 +111,10 @@ + + + + diff --git a/src/libraries/Common/tests/Tests/System/ListBuilderTests.cs b/src/libraries/Common/tests/Tests/System/ListBuilderTests.cs new file mode 100644 index 00000000000000..ceab908411abdc --- /dev/null +++ b/src/libraries/Common/tests/Tests/System/ListBuilderTests.cs @@ -0,0 +1,161 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using Xunit; + +namespace Tests.System; + +public class ListBuilderTests +{ + [Theory] + [InlineData(null)] + [InlineData(0)] + [InlineData(1)] + [InlineData(2)] + [InlineData(3)] + [InlineData(4)] + [InlineData(8)] + public void Add_GrowsAndPreservesItems(int? capacity) + { + ListBuilder builder = capacity.HasValue ? new ListBuilder(capacity.Value) : default; + Assert.Equal(0, builder.Count); + Assert.Same(Array.Empty(), builder.ToArray()); + + object[] items = new object[17]; + for (int i = 0; i < items.Length; i++) + { + items[i] = new object(); + builder.Add(items[i]); + Assert.Equal(i + 1, builder.Count); + for (int j = 0; j <= i; j++) + { + Assert.Same(items[j], builder[j]); + } + } + + Assert.Equal(items, builder.ToArray()); + } + + [Theory] + [InlineData(0)] + [InlineData(1)] + [InlineData(8)] + public void Add_FirstItemDoesNotAllocate(int capacity) + { + object item = new object(); + long before = GC.GetAllocatedBytesForCurrentThread(); + ListBuilder builder = new ListBuilder(capacity); + builder.Add(item); + long after = GC.GetAllocatedBytesForCurrentThread(); + + Assert.Equal(before, after); + Assert.Equal(1, builder.Count); + Assert.Same(item, builder[0]); + } + + [Theory] + [InlineData(0)] + [InlineData(1)] + [InlineData(2)] + [InlineData(3)] + [InlineData(8)] + public void ToArray_PreservesStorageSemantics(int count) + { + ListBuilder builder = new ListBuilder(8); + object[] items = new object[count]; + for (int i = 0; i < count; i++) + { + items[i] = new object(); + builder.Add(items[i]); + } + + object[] array = builder.ToArray(); + Assert.Equal(items, array); + Assert.Equal(count, builder.Count); + + if (count == 0) + { + Assert.Same(Array.Empty(), array); + Assert.Same(array, builder.ToArray()); + } + else if (count == 1) + { + Assert.NotSame(array, builder.ToArray()); + array[0] = new object(); + Assert.Same(items[0], builder[0]); + } + else + { + Assert.Same(array, builder.ToArray()); + object replacement = new object(); + array[0] = replacement; + Assert.Same(replacement, builder[0]); + } + } + + [Theory] + [InlineData(4, 0)] + [InlineData(4, 1)] + [InlineData(4, 2)] + [InlineData(4, 3)] + [InlineData(4, 4)] + [InlineData(8, 2)] + [InlineData(8, 5)] + public void Add_AfterToArray(int capacity, int count) + { + ListBuilder builder = new ListBuilder(capacity); + object[] items = new object[count + 5]; + for (int i = 0; i < items.Length; i++) + { + items[i] = new object(); + } + for (int i = 0; i < count; i++) + { + builder.Add(items[i]); + } + + object[] original = builder.ToArray(); + for (int i = count; i < items.Length; i++) + { + builder.Add(items[i]); + } + + Assert.Equal(items.Length, builder.Count); + Assert.Equal(items, builder.ToArray()); + Assert.Equal(count, original.Length); + for (int i = 0; i < original.Length; i++) + { + Assert.Same(items[i], original[i]); + } + } + + [Theory] + [InlineData(0, 0)] + [InlineData(0, 2)] + [InlineData(1, 0)] + [InlineData(1, 2)] + [InlineData(2, 0)] + [InlineData(2, 2)] + [InlineData(5, 2)] + public void CopyTo_CopiesOnlyItems(int count, int index) + { + string[] items = ["a", "b", "c", "d", "e"]; + ListBuilder builder = default; + for (int i = 0; i < count; i++) + { + builder.Add(items[i]); + } + + object sentinel = new object(); + object[] destination = new object[index + count + 2]; + Array.Fill(destination, sentinel); + builder.CopyTo(destination, index); + + Assert.Equal(count, builder.Count); + for (int i = 0; i < destination.Length; i++) + { + Assert.Same(i >= index && i < index + count ? items[i - index] : sentinel, destination[i]); + } + } +} 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 0fe40b3703b216..d533f9f033e320 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 @@ -590,6 +590,7 @@ + diff --git a/src/libraries/System.Private.CoreLib/src/System/ListBuilder.cs b/src/libraries/System.Private.CoreLib/src/System/ListBuilder.cs new file mode 100644 index 00000000000000..3068bf5d66c1f0 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/ListBuilder.cs @@ -0,0 +1,88 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; + +namespace System; + +// Helper to build lists without allocating backing storage for lists of one element. +internal struct ListBuilder where T : class +{ + private T[]? _items; + private T _item; + private int _count; + private int _capacity; + + public ListBuilder(int capacity) + { + _items = null; + _item = null!; + _count = 0; + _capacity = capacity; + } + + public T this[int index] + { + get + { + Debug.Assert(index < Count); + return (_items is not null) ? _items[index] : _item; + } + } + + // For multiple elements, this returns the backing array, not an independent snapshot. + public T[] ToArray() + { + if (_count == 0) + return []; + if (_count == 1) + return [_item]; + + Array.Resize(ref _items, _count); + _capacity = _count; + return _items!; + } + + public void CopyTo(object[] array, int index) + { + if (_count == 0) + return; + + if (_count == 1) + { + array[index] = _item; + return; + } + + Array.Copy(_items!, 0, array, index, _count); + } + + public int Count => _count; + + public void Add(T item) + { + if (_count == 0) + { + _item = item; + } + else + { + if (_count == 1) + { + if (_capacity < 2) + _capacity = 4; + _items = new T[_capacity]; + _items[0] = _item; + } + else if (_capacity == _count) + { + int newCapacity = 2 * _capacity; + Array.Resize(ref _items, newCapacity); + _capacity = newCapacity; + } + + _items![_count] = item; + } + _count++; + } +} From c15ad7e1ee09f8bd8120726fd3eb4b4ea9ca437c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 7 Sep 2026 02:32:43 +0000 Subject: [PATCH 2/3] Remove obsolete Native AOT ListBuilder namespace imports Co-authored-by: MichalStrehovsky <13110571+MichalStrehovsky@users.noreply.github.com> --- .../System.Private.CoreLib/src/System/ActivatorImplementation.cs | 1 - .../Reflection/Runtime/TypeInfos/RuntimeTypeInfo.BindingFlags.cs | 1 - .../src/System/Reflection/RuntimeCustomAttribute.NativeAot.cs | 1 - 3 files changed, 3 deletions(-) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/ActivatorImplementation.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/ActivatorImplementation.cs index 020b9fadc0cc66..f1f18dc7fba1d7 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/ActivatorImplementation.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/ActivatorImplementation.cs @@ -6,7 +6,6 @@ using System.Globalization; using System.Reflection; using System.Reflection.Runtime.BindingFlagSupport; -using System.Reflection.Runtime.General; using Internal.Runtime.Augments; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.BindingFlags.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.BindingFlags.cs index b17f6b2ce38e33..8643b1e279ecf3 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.BindingFlags.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.BindingFlags.cs @@ -3,7 +3,6 @@ using System.Diagnostics; using System.Reflection.Runtime.BindingFlagSupport; -using System.Reflection.Runtime.General; namespace System.Reflection.Runtime.TypeInfos { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttribute.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttribute.NativeAot.cs index f98920096185db..e91ee3efe99e3d 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttribute.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttribute.NativeAot.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using System.Reflection.Runtime.General; using System.Reflection.Runtime.MethodInfos; using Internal.LowLevelLinq; From 53f92043d2097278df1f46096ac4883e35734e72 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 7 Sep 2026 03:06:21 +0000 Subject: [PATCH 3/3] Remove ListBuilderTests and unused test source inclusions Co-authored-by: MichalStrehovsky <13110571+MichalStrehovsky@users.noreply.github.com> --- .../Common/tests/Common.Tests.csproj | 4 - .../tests/Tests/System/ListBuilderTests.cs | 161 ------------------ 2 files changed, 165 deletions(-) delete mode 100644 src/libraries/Common/tests/Tests/System/ListBuilderTests.cs diff --git a/src/libraries/Common/tests/Common.Tests.csproj b/src/libraries/Common/tests/Common.Tests.csproj index 443af1568c7e90..dd184b098635f5 100644 --- a/src/libraries/Common/tests/Common.Tests.csproj +++ b/src/libraries/Common/tests/Common.Tests.csproj @@ -111,10 +111,6 @@ - - - - diff --git a/src/libraries/Common/tests/Tests/System/ListBuilderTests.cs b/src/libraries/Common/tests/Tests/System/ListBuilderTests.cs deleted file mode 100644 index ceab908411abdc..00000000000000 --- a/src/libraries/Common/tests/Tests/System/ListBuilderTests.cs +++ /dev/null @@ -1,161 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using Xunit; - -namespace Tests.System; - -public class ListBuilderTests -{ - [Theory] - [InlineData(null)] - [InlineData(0)] - [InlineData(1)] - [InlineData(2)] - [InlineData(3)] - [InlineData(4)] - [InlineData(8)] - public void Add_GrowsAndPreservesItems(int? capacity) - { - ListBuilder builder = capacity.HasValue ? new ListBuilder(capacity.Value) : default; - Assert.Equal(0, builder.Count); - Assert.Same(Array.Empty(), builder.ToArray()); - - object[] items = new object[17]; - for (int i = 0; i < items.Length; i++) - { - items[i] = new object(); - builder.Add(items[i]); - Assert.Equal(i + 1, builder.Count); - for (int j = 0; j <= i; j++) - { - Assert.Same(items[j], builder[j]); - } - } - - Assert.Equal(items, builder.ToArray()); - } - - [Theory] - [InlineData(0)] - [InlineData(1)] - [InlineData(8)] - public void Add_FirstItemDoesNotAllocate(int capacity) - { - object item = new object(); - long before = GC.GetAllocatedBytesForCurrentThread(); - ListBuilder builder = new ListBuilder(capacity); - builder.Add(item); - long after = GC.GetAllocatedBytesForCurrentThread(); - - Assert.Equal(before, after); - Assert.Equal(1, builder.Count); - Assert.Same(item, builder[0]); - } - - [Theory] - [InlineData(0)] - [InlineData(1)] - [InlineData(2)] - [InlineData(3)] - [InlineData(8)] - public void ToArray_PreservesStorageSemantics(int count) - { - ListBuilder builder = new ListBuilder(8); - object[] items = new object[count]; - for (int i = 0; i < count; i++) - { - items[i] = new object(); - builder.Add(items[i]); - } - - object[] array = builder.ToArray(); - Assert.Equal(items, array); - Assert.Equal(count, builder.Count); - - if (count == 0) - { - Assert.Same(Array.Empty(), array); - Assert.Same(array, builder.ToArray()); - } - else if (count == 1) - { - Assert.NotSame(array, builder.ToArray()); - array[0] = new object(); - Assert.Same(items[0], builder[0]); - } - else - { - Assert.Same(array, builder.ToArray()); - object replacement = new object(); - array[0] = replacement; - Assert.Same(replacement, builder[0]); - } - } - - [Theory] - [InlineData(4, 0)] - [InlineData(4, 1)] - [InlineData(4, 2)] - [InlineData(4, 3)] - [InlineData(4, 4)] - [InlineData(8, 2)] - [InlineData(8, 5)] - public void Add_AfterToArray(int capacity, int count) - { - ListBuilder builder = new ListBuilder(capacity); - object[] items = new object[count + 5]; - for (int i = 0; i < items.Length; i++) - { - items[i] = new object(); - } - for (int i = 0; i < count; i++) - { - builder.Add(items[i]); - } - - object[] original = builder.ToArray(); - for (int i = count; i < items.Length; i++) - { - builder.Add(items[i]); - } - - Assert.Equal(items.Length, builder.Count); - Assert.Equal(items, builder.ToArray()); - Assert.Equal(count, original.Length); - for (int i = 0; i < original.Length; i++) - { - Assert.Same(items[i], original[i]); - } - } - - [Theory] - [InlineData(0, 0)] - [InlineData(0, 2)] - [InlineData(1, 0)] - [InlineData(1, 2)] - [InlineData(2, 0)] - [InlineData(2, 2)] - [InlineData(5, 2)] - public void CopyTo_CopiesOnlyItems(int count, int index) - { - string[] items = ["a", "b", "c", "d", "e"]; - ListBuilder builder = default; - for (int i = 0; i < count; i++) - { - builder.Add(items[i]); - } - - object sentinel = new object(); - object[] destination = new object[index + count + 2]; - Array.Fill(destination, sentinel); - builder.CopyTo(destination, index); - - Assert.Equal(count, builder.Count); - for (int i = 0; i < destination.Length; i++) - { - Assert.Same(i >= index && i < index + count ? items[i - index] : sentinel, destination[i]); - } - } -}