File: src\tools\illink\src\ILLink.Shared\TrimAnalysis\ArrayValue.cs
Web Access
Project: src\src\tools\illink\src\ILLink.RoslynAnalyzer\ILLink.RoslynAnalyzer.csproj (ILLink.RoslynAnalyzer)
// 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));
		}
	}
}