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.
9 use crate::decl_defs::DeclTy;
10 use crate::decl_hint::DeclHintEnv;
11 use crate::reason::Reason;
12 use crate::typing::{BindParamFlags, Typing};
13 use crate::typing_ctx::TypingCtx;
14 use crate::typing_env::TEnv;
15 use crate::typing_error::{Primary, TypingError};
16 use crate::typing_param::TypingParam;
17 use crate::typing_phase::Phase;
18 use crate::typing_return::TypingReturn;
22 pub struct TypingToplevel<'a, R: Reason> {
23 ctx: Arc<TypingCtx<R>>,
27 impl<'a, R: Reason> TypingToplevel<'a, R> {
28 fn decl_hint_env(&self) -> DeclHintEnv<R> {
29 DeclHintEnv::new(self.ctx.alloc)
32 fn hint_fun_header<'ast>(
34 params: &'ast [oxidized::aast::FunParam<(), ()>],
35 ret: &oxidized::aast::TypeHint<()>,
38 Vec<(&'ast oxidized::aast::FunParam<(), ()>, Option<DeclTy<R>>)>,
40 let ret = ret.1.as_ref().map(|h| self.decl_hint_env().hint(h));
49 .map(|h| self.decl_hint_env().hint(h)),
56 fn fun_def_impl(&mut self, fd: &oxidized::aast::FunDef<(), ()>) -> tast::FunDef<R> {
58 let fname = self.ctx.alloc.symbol(&f.name.1);
59 let fpos = self.ctx.alloc.pos_from_ast(&f.name.0);
61 let (return_decl_ty, params_decl_ty) = self.hint_fun_header(&f.params, &f.ret);
62 let return_ty = match return_decl_ty.clone() {
63 None => TypingReturn::make_default_return(self.env, false, &fpos, fname),
64 Some(ty) => TypingReturn::make_return_type(
66 &|env, ty| Phase::localize_no_subst(env, false, None, ty),
70 let ret_pos = match &f.ret.1 {
71 Some(h) => self.ctx.alloc.pos_from_ast(&h.0),
72 None => self.ctx.alloc.pos_from_ast(f.name.pos()),
74 let return_ = TypingReturn::make_info(
83 let param_tys: Vec<_> = params_decl_ty
85 .map(|(param, hint)| {
88 TypingParam::make_param_local_ty(self.env, hint.clone(), param),
94 .for_each(|(param, ty)| TypingParam::check_param_has_hint(self.env, param, ty));
95 // TOOD(hrust): capabilities, immutable
96 let typed_params: Vec<_> = param_tys
103 can_read_globals: true,
112 let tb = Typing::fun_(
124 .add_error(TypingError::primary(Primary::ExpectingReturnTypeHint(fpos))),
126 let fun = oxidized::aast::Fun_ {
127 annotation: self.env.save(()),
128 readonly_this: f.readonly_this.clone(),
129 span: f.span.clone(),
130 readonly_ret: f.readonly_ret.clone(),
131 ret: oxidized::aast::TypeHint(return_ty, f.ret.1.clone()),
132 name: f.name.clone(),
134 where_constraints: vec![],
135 variadic: oxidized::aast::FunVariadicity::FVnonVariadic,
136 params: typed_params,
137 ctxs: f.ctxs.clone(),
138 unsafe_ctxs: f.unsafe_ctxs.clone(),
139 fun_kind: f.fun_kind.clone(),
140 user_attributes: vec![],
141 body: oxidized::aast::FuncBody { fb_ast: tb },
142 external: f.external.clone(),
143 doc_comment: f.doc_comment.clone(),
145 oxidized::aast::FunDef {
146 namespace: fd.namespace.clone(),
147 file_attributes: vec![],
154 ctx: Arc<TypingCtx<R>>,
155 fd: &oxidized::aast::FunDef<(), ()>,
156 ) -> (tast::FunDef<R>, Vec<TypingError<R>>) {
157 let env = TEnv::fun_env(Arc::clone(&ctx), fd);
158 let def = TypingToplevel { ctx, env: &env }.fun_def_impl(fd);
159 (def, env.destruct())