blob: 9059a2f225d38f9cc764d0276def6ff4660959fe [file] [log] [blame]
#ifndef RUST_TYTY_VARIANCE_ANALYSIS_H
#define RUST_TYTY_VARIANCE_ANALYSIS_H
#include "rust-tyty.h"
#include <rust-bir-free-region.h>
namespace Rust {
namespace TyTy {
namespace VarianceAnalysis {
class Variance;
class GenericTyPerCrateCtx;
/** Per crate context for variance analysis. */
class CrateCtx
{
public:
CrateCtx ();
~CrateCtx ();
/** Add type to variance analysis context. */
void add_type_constraints (ADTType &type);
/** Solve all constraints and print debug output. */
void solve ();
/** Get variance of a type parameters. */
std::vector<Variance> query_generic_variance (const ADTType &type);
/** Get variance of a type body (members, fn parameters...). */
std::vector<Variance> query_type_variances (BaseType *type);
/** Get regions mentioned in a type. */
std::vector<Region> query_type_regions (BaseType *type);
FreeRegions query_field_regions (const ADTType *parent, size_t variant_index,
size_t field_index,
const FreeRegions &parent_regions);
private:
std::unique_ptr<GenericTyPerCrateCtx> private_ctx;
};
std::vector<size_t>
query_field_regions (const ADTType *parent, size_t variant_index,
size_t field_index, const FreeRegions &parent_regions);
/** Variance semilattice */
class Variance
{
enum Kind : uint8_t
{
BIVARIANT = 0, // 0b00
COVARIANT = 1, // 0b01
CONTRAVARIANT = 2, // 0b10
INVARIANT = 3, // 0b11
} kind;
static constexpr auto TOP = BIVARIANT;
static constexpr auto BOTTOM = INVARIANT;
constexpr Variance (Kind kind) : kind (kind) {}
public:
constexpr Variance () : kind (TOP) {}
constexpr bool is_bivariant () const { return kind == BIVARIANT; }
constexpr bool is_covariant () const { return kind == COVARIANT; }
constexpr bool is_contravariant () const { return kind == CONTRAVARIANT; }
constexpr bool is_invariant () const { return kind == INVARIANT; }
static constexpr Variance bivariant () { return {BIVARIANT}; }
static constexpr Variance covariant () { return {COVARIANT}; }
static constexpr Variance contravariant () { return {CONTRAVARIANT}; }
static constexpr Variance invariant () { return {INVARIANT}; }
WARN_UNUSED_RESULT Variance reverse () const;
static WARN_UNUSED_RESULT Variance join (Variance lhs, Variance rhs);
void join (Variance rhs);
/**
* Variance composition function.
*
* For `A<X>` and `B<X>` and the composition `A<B<X>>` the variance of
* `v(A<B<X>>, X)` is defined as:
* ```
* v(A<B<X>>, X) = v(A<X>, X).transform(v(B<X>, X))
* ```
*/
static WARN_UNUSED_RESULT Variance transform (Variance lhs, Variance rhs);
constexpr friend bool operator== (const Variance &lhs, const Variance &rhs)
{
return lhs.kind == rhs.kind;
}
constexpr friend bool operator!= (const Variance &lhs, const Variance &rhs)
{
return !(lhs == rhs);
}
WARN_UNUSED_RESULT std::string as_string () const;
};
} // namespace VarianceAnalysis
} // namespace TyTy
} // namespace Rust
#endif // RUST_TYTY_VARIANCE_ANALYSIS_H