expose top level subtyping functions
[hiphop-php.git] / hphp / hack / src / rupro / ty / prop.rs
blobe0290e981499c83c10facaaa03db38241ad64f2e
1 // Copyright (c) Meta Platforms, Inc. and affiliates.
2 //
3 // This source code is licensed under the MIT license found in the
4 // LICENSE file in the "hack" directory of this source tree.
5 mod constraint;
7 use crate::{
8     local::{Ty, Tyvar},
9     local_error::TypingError,
10     reason::Reason,
12 pub use constraint::Cstr;
13 use hcons::{Conser, Hc};
14 use im::HashSet;
15 use oxidized::ast_defs::Variance;
16 use pos::TypeName;
17 use std::ops::Deref;
19 /// TODO[mjt] Consider making 'constraints' 'types' to avoid this
20 /// or maybe rethink the inference env entirely
21 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
22 pub enum CstrTy<R: Reason> {
23     Locl(Ty<R>),
24     Cstr(Cstr<R>),
27 impl<R: Reason> CstrTy<R> {
28     pub fn tyvars<F>(&self, get_tparam_variance: &F) -> (HashSet<Tyvar>, HashSet<Tyvar>)
29     where
30         F: Fn(TypeName) -> Option<Vec<Variance>>,
31     {
32         match self {
33             CstrTy::Locl(ty) => ty.tyvars(get_tparam_variance),
34             CstrTy::Cstr(cstr) => cstr.tyvars(get_tparam_variance),
35         }
36     }
38     #[inline]
39     pub fn tyvar_opt(&self) -> Option<&Tyvar> {
40         match self {
41             Self::Locl(ty) => ty.tyvar_opt(),
42             Self::Cstr(_) => None,
43         }
44     }
46     pub fn is_var(&self) -> bool {
47         self.tyvar_opt().is_some()
48     }
51 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
52 pub enum PropF<R: Reason, A> {
53     Conj(Vec<A>),
54     Disj(TypingError<R>, Vec<A>),
55     Subtype(CstrTy<R>, CstrTy<R>),
58 impl<R: Reason> PropF<R, Prop<R>> {
59     pub fn inj(self) -> Prop<R> {
60         Prop(Hc::new(self))
61     }
64 impl<R: Reason> hcons::Consable for PropF<R, Prop<R>> {
65     #[inline]
66     fn conser() -> &'static Conser<PropF<R, Prop<R>>> {
67         R::prop_conser()
68     }
71 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
72 pub struct Prop<R: Reason>(Hc<PropF<R, Prop<R>>>);
74 impl<R: Reason> Deref for Prop<R> {
75     type Target = PropF<R, Prop<R>>;
76     fn deref(&self) -> &Self::Target {
77         let Prop(hc_prop_f) = self;
78         Deref::deref(hc_prop_f)
79     }
82 impl<R: Reason> Prop<R> {
83     pub fn conjs(ps: Vec<Prop<R>>) -> Self {
84         PropF::Conj(ps).inj()
85     }
87     pub fn conj(self, other: Self) -> Self {
88         Self::conjs(vec![self, other])
89     }
91     pub fn disjs(ps: Vec<Prop<R>>, fail: TypingError<R>) -> Self {
92         PropF::Disj(fail, ps).inj()
93     }
95     pub fn disj(self, other: Self, fail: TypingError<R>) -> Self {
96         Self::disjs(vec![self, other], fail)
97     }
99     pub fn subtype(cty_sub: CstrTy<R>, cty_sup: CstrTy<R>) -> Self {
100         PropF::Subtype(cty_sub, cty_sup).inj()
101     }
103     pub fn subtype_ty(ty_sub: Ty<R>, ty_sup: Ty<R>) -> Self {
104         Self::subtype(CstrTy::Locl(ty_sub), CstrTy::Locl(ty_sup))
105     }
107     pub fn valid() -> Self {
108         PropF::Conj(vec![]).inj()
109     }
111     pub fn invalid(fail: TypingError<R>) -> Self {
112         PropF::Disj(fail, vec![]).inj()
113     }
115     pub fn is_valid(&self) -> bool {
116         match self.deref() {
117             PropF::Subtype(_, _) => false,
118             PropF::Conj(ps) => ps.iter().all(|p| p.is_valid()),
119             PropF::Disj(_, ps) => ps.iter().any(|p| p.is_valid()),
120         }
121     }
123     pub fn is_unsat(&self) -> bool {
124         match self.deref() {
125             PropF::Subtype(_, _) => false,
126             PropF::Conj(ps) => ps.iter().any(|p| p.is_unsat()),
127             PropF::Disj(_, ps) => ps.iter().all(|p| p.is_unsat()),
128         }
129     }