File: src\tools\illink\src\ILLink.Shared\DataFlow\MaybeLattice.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;
 
// This is needed due to NativeAOT which doesn't enable nullable globally yet
#nullable enable
 
namespace ILLink.Shared.DataFlow
{
	// Wrapper for Nullable<T> which implements IEquatable so that this may
	// be used as a lattice value. Nullable types can't satisfy interface constraints;
	// see for example https://learn.microsoft.com/dotnet/csharp/misc/cs0313.
	public struct Maybe<T> : IEquatable<Maybe<T>>, IDeepCopyValue<Maybe<T>>
		where T : struct, IEquatable<T>
	{
		public T? MaybeValue;
		public Maybe (T value) => MaybeValue = value;
		public bool Equals (Maybe<T> other) => MaybeValue?.Equals (other.MaybeValue) ?? other.MaybeValue == null;
		public override bool Equals (object? obj) => obj is Maybe<T> other && Equals (other);
		public override int GetHashCode () => MaybeValue?.GetHashCode () ?? 0;
		public Maybe<T> DeepCopy ()
		{
			if (MaybeValue is not T value)
				return default;
			if (value is IDeepCopyValue<T> copyValue)
				return new (copyValue.DeepCopy ());
			return new (value);
		}
 
		public static bool operator == (Maybe<T> left, Maybe<T> right) => left.Equals (right);
		public static bool operator != (Maybe<T> left, Maybe<T> right) => !(left == right);
	}
 
	public struct MaybeLattice<T, TValueLattice> : ILattice<Maybe<T>>
		where T : struct, IEquatable<T>
		where TValueLattice : ILattice<T>
	{
		public readonly TValueLattice ValueLattice;
		public MaybeLattice (TValueLattice valueLattice)
		{
			ValueLattice = valueLattice;
			Top = default;
		}
		public Maybe<T> Top { get; }
		public Maybe<T> Meet (Maybe<T> left, Maybe<T> right)
		{
			if (left.MaybeValue is not T leftValue)
				return right.DeepCopy ();
			if (right.MaybeValue is not T rightValue)
				return left.DeepCopy ();
			return new Maybe<T> (ValueLattice.Meet (leftValue, rightValue));
		}
	}
}