Line data Source code
1 : #ifndef RUST_TYTY_VARIANCE_ANALYSIS_H
2 : #define RUST_TYTY_VARIANCE_ANALYSIS_H
3 :
4 : #include "rust-tyty.h"
5 :
6 : #include <rust-bir-free-region.h>
7 :
8 : namespace Rust {
9 : namespace TyTy {
10 : namespace VarianceAnalysis {
11 :
12 : class Variance;
13 : class GenericTyPerCrateCtx;
14 :
15 : /** Per crate context for variance analysis. */
16 : class CrateCtx
17 : {
18 : public:
19 : CrateCtx ();
20 : ~CrateCtx ();
21 :
22 : /** Add type to variance analysis context. */
23 : void add_type_constraints (ADTType &type);
24 :
25 : /** Solve all constraints and print debug output. */
26 : void solve ();
27 :
28 : /** Get variance of a type parameters. */
29 : std::vector<Variance> query_generic_variance (const ADTType &type);
30 :
31 : /** Get variance of a type body (members, fn parameters...). */
32 : std::vector<Variance> query_type_variances (BaseType *type);
33 :
34 : /** Get regions mentioned in a type. */
35 : std::vector<Region> query_type_regions (BaseType *type);
36 : FreeRegions query_field_regions (const ADTType *parent, size_t variant_index,
37 : size_t field_index,
38 : const FreeRegions &parent_regions);
39 :
40 : private:
41 : std::unique_ptr<GenericTyPerCrateCtx> private_ctx;
42 : };
43 :
44 : std::vector<size_t> query_field_regions (const ADTType *parent,
45 : size_t variant_index,
46 : size_t field_index,
47 : const FreeRegions &parent_regions);
48 :
49 : /** Variance semilattice */
50 : class Variance
51 : {
52 : enum Kind : uint8_t
53 : {
54 : BIVARIANT = 0, // 0b00
55 : COVARIANT = 1, // 0b01
56 : CONTRAVARIANT = 2, // 0b10
57 : INVARIANT = 3, // 0b11
58 : } kind;
59 :
60 : static constexpr auto TOP = BIVARIANT;
61 : static constexpr auto BOTTOM = INVARIANT;
62 :
63 1483 : constexpr Variance (Kind kind) : kind (kind) {}
64 :
65 : public:
66 : constexpr Variance () : kind (TOP) {}
67 :
68 : constexpr bool is_bivariant () const { return kind == BIVARIANT; }
69 : constexpr bool is_covariant () const { return kind == COVARIANT; }
70 : constexpr bool is_contravariant () const { return kind == CONTRAVARIANT; }
71 : constexpr bool is_invariant () const { return kind == INVARIANT; }
72 :
73 : static constexpr Variance bivariant () { return {BIVARIANT}; }
74 : static constexpr Variance covariant () { return {COVARIANT}; }
75 : static constexpr Variance contravariant () { return {CONTRAVARIANT}; }
76 : static constexpr Variance invariant () { return {INVARIANT}; }
77 :
78 : WARN_UNUSED_RESULT Variance reverse () const;
79 : static WARN_UNUSED_RESULT Variance join (Variance lhs, Variance rhs);
80 :
81 : void join (Variance rhs);
82 :
83 : /**
84 : * Variance composition function.
85 : *
86 : * For `A<X>` and `B<X>` and the composition `A<B<X>>` the variance of
87 : * `v(A<B<X>>, X)` is defined as:
88 : * ```
89 : * v(A<B<X>>, X) = v(A<X>, X).transform(v(B<X>, X))
90 : * ```
91 : */
92 : static WARN_UNUSED_RESULT Variance transform (Variance lhs, Variance rhs);
93 :
94 163 : constexpr friend bool operator== (const Variance &lhs, const Variance &rhs)
95 : {
96 163 : return lhs.kind == rhs.kind;
97 : }
98 163 : constexpr friend bool operator!= (const Variance &lhs, const Variance &rhs)
99 : {
100 163 : return !(lhs == rhs);
101 : }
102 :
103 : WARN_UNUSED_RESULT std::string as_string () const;
104 : };
105 :
106 : } // namespace VarianceAnalysis
107 :
108 : } // namespace TyTy
109 : } // namespace Rust
110 :
111 : #endif // RUST_TYTY_VARIANCE_ANALYSIS_H
|