Add tyvars as newtype wrapper on idents
[hiphop-php.git] / hphp / hack / src / rupro / lib / typing_defs / ty.rs
blobebf3d44f5d23d8e8cb50a60054c59c5a48612779
1 // Copyright (c) Facebook, Inc. and its 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.
6 use crate::reason::Reason;
7 use crate::typing_defs::tyvar::Tyvar;
8 use hcons::Hc;
9 use ocamlrep::{Allocator, OpaqueValue, ToOcamlRep};
10 use pos::{Positioned, Symbol, ToOxidized, TypeName};
12 pub use crate::decl_defs::ty::{Exact, Prim};
14 // TODO: Share the representation from decl_defs
15 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
16 pub struct FunParam<R: Reason> {
17     pub pos: R::Pos,
18     pub name: Option<Symbol>,
19     pub ty: Ty<R>,
22 walkable!(FunParam<R> => [ty]);
24 // TODO: Share the representation from decl_defs
25 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
26 pub struct FunType<R: Reason> {
27     pub params: Vec<FunParam<R>>,
28     pub ret: Ty<R>,
31 walkable!(FunType<R> => [params, ret]);
33 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
34 pub enum ParamMode {
35     FPnormal,
36     FPinout,
39 impl From<&oxidized::ast_defs::ParamKind> for ParamMode {
40     fn from(pk: &oxidized::ast_defs::ParamKind) -> Self {
41         match pk {
42             oxidized::ast::ParamKind::Pinout(_) => Self::FPinout,
43             oxidized::ast::ParamKind::Pnormal => Self::FPnormal,
44         }
45     }
48 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
49 pub enum Ty_<R: Reason, TY> {
50     /// A primitive type
51     Tprim(Prim),
53     /// A wrapper around `FunType`, which contains the full type information
54     /// for a function, method, lambda, etc.
55     Tfun(FunType<R>),
57     /// Any type
58     /// TODO: any and err are a bit weird in that they are not actually types
59     /// but rather they represent a set of inconsistent bounds on a tyvar
60     /// we might want to rethink them prefering a sum type _or_
61     /// distinguishing types with `Tany` from those without
62     Tany,
64     /// The type of a generic parameter. The constraints on a generic parameter
65     /// are accessed through the lenv.tpenv component of the environment, which
66     /// is set up when checking the body of a function or method. See uses of
67     /// Typing_phase.add_generic_parameters_and_constraints. The list denotes
68     /// type arguments.
69     Tgeneric(TypeName, Vec<TY>),
71     /// An instance of a class or interface, ty list are the arguments
72     /// If exact=Exact, then this represents instances of *exactly* this class
73     /// If exact=Nonexact, this also includes subclasses
74     Tclass(Positioned<TypeName, R::Pos>, Exact, Vec<TY>),
76     Tvar(Tyvar),
79 walkable!(impl<R: Reason, TY> for Ty_<R, TY> =>  {
80     Ty_::Tprim(_) => [],
81     Ty_::Tfun(fun_type) => [fun_type],
82     Ty_::Tany => [],
83     Ty_::Tgeneric(_, args) => [args],
84     Ty_::Tclass(_, _, args) => [args],
85     Ty_::Tvar(_) => [],
86 });
88 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
89 pub struct Ty<R: Reason>(R, Hc<Ty_<R, Ty<R>>>);
91 walkable!(Ty<R> as visit_ty => [0, 1]);
93 impl<R: Reason> Ty<R> {
94     pub fn new(reason: R, ty: Hc<Ty_<R, Ty<R>>>) -> Self {
95         Self(reason, ty)
96     }
98     pub fn reason(&self) -> &R {
99         &self.0
100     }
102     pub fn node(&self) -> &Hc<Ty_<R, Ty<R>>> {
103         &self.1
104     }
107 impl<'a, R: Reason> ToOxidized<'a> for Ty<R> {
108     type Output = oxidized_by_ref::typing_defs::Ty<'a>;
110     fn to_oxidized(&self, arena: &'a bumpalo::Bump) -> Self::Output {
111         use oxidized_by_ref::typing_defs::Ty_ as OTy_;
112         let r = self.reason().to_oxidized(arena);
113         let ty = match &**self.node() {
114             Ty_::Tvar(tv) => OTy_::Tvar((*tv).into()),
115             Ty_::Tprim(x) => OTy_::Tprim(arena.alloc(*x)),
116             Ty_::Tfun(_) => todo!(),
117             Ty_::Tany => todo!(),
118             Ty_::Tgeneric(_, _) => todo!(),
119             Ty_::Tclass(pos_id, exact, tys) => OTy_::Tclass(&*arena.alloc((
120                 pos_id.to_oxidized(arena),
121                 *exact,
122                 &*arena.alloc_slice_fill_iter(
123                     tys.iter().map(|ty| &*arena.alloc(ty.to_oxidized(arena))),
124                 ),
125             ))),
126         };
127         oxidized_by_ref::typing_defs::Ty(r, ty)
128     }
131 impl<R: Reason> ToOcamlRep for Ty<R> {
132     fn to_ocamlrep<'a, A: Allocator>(&self, alloc: &'a A) -> OpaqueValue<'a> {
133         let arena = &bumpalo::Bump::new();
134         self.to_oxidized(arena).to_ocamlrep(alloc)
135     }