|
// 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));
}
}
}
|