// Copyright (c) .NET Foundation and contributors. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Linq; using ILLink.Shared.DataFlow; using MultiValue = ILLink.Shared.DataFlow.ValueSet<ILLink.Shared.DataFlow.SingleValue>; // This is needed due to NativeAOT which doesn't enable nullable globally yet #nullable enable namespace ILLink.Shared.TrimAnalysis { internal sealed partial record ArrayValue : SingleValue { private static ValueSetLattice<SingleValue> MultiValueLattice => default; public readonly SingleValue Size; public partial bool TryGetValueByIndex(int index, out MultiValue value); public static MultiValue SanitizeArrayElementValue(MultiValue input) { // We need to be careful about self-referencing arrays. It's easy to have an array which has one of the elements as itself: // var arr = new object[1]; // arr[0] = arr; // // We can't deep copy this, as it's an infinite recursion. And we can't easily guard against it with checks to self-referencing // arrays - as this could be two or more levels deep. // // We need to deep copy arrays because we don't have a good way to track references (we treat everything as a value type) // and thus we could get bad results if the array is involved in multiple branches for example. // That said, it only matters for us to track arrays to be able to get integers or Type values (and we really only need relatively simple cases) // // So we will simply treat array value as an element value as "too complex to analyze" and give up by storing Unknown instead bool needSanitization = false; foreach (var v in input.AsEnumerable()) { if (v is ArrayValue) needSanitization = true; } if (!needSanitization) return input; return new(input.AsEnumerable().Select(v => v is ArrayValue ? UnknownValue.Instance : v)); } } } |