1 // Copyright (c) Facebook, Inc. and its affiliates.
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;
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> {
18 pub name: Option<Symbol>,
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>>,
31 walkable!(FunType<R> => [params, ret]);
33 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
39 impl From<&oxidized::ast_defs::ParamKind> for ParamMode {
40 fn from(pk: &oxidized::ast_defs::ParamKind) -> Self {
42 oxidized::ast::ParamKind::Pinout(_) => Self::FPinout,
43 oxidized::ast::ParamKind::Pnormal => Self::FPnormal,
48 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
49 pub enum Ty_<R: Reason, TY> {
53 /// A wrapper around `FunType`, which contains the full type information
54 /// for a function, method, lambda, etc.
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
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
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>),
79 walkable!(impl<R: Reason, TY> for Ty_<R, TY> => {
81 Ty_::Tfun(fun_type) => [fun_type],
83 Ty_::Tgeneric(_, args) => [args],
84 Ty_::Tclass(_, _, args) => [args],
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 {
98 pub fn reason(&self) -> &R {
102 pub fn node(&self) -> &Hc<Ty_<R, Ty<R>>> {
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),
122 &*arena.alloc_slice_fill_iter(
123 tys.iter().map(|ty| &*arena.alloc(ty.to_oxidized(arena))),
127 oxidized_by_ref::typing_defs::Ty(r, ty)
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)