enable class constants in folded classes
[hiphop-php.git] / hphp / hack / src / rupro / lib / typing_toplevel.rs
blob020d884e20ded493f68f4f41df9afca0462b60e7
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 #![allow(dead_code)]
7 use std::sync::Arc;
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;
20 use crate::tast;
22 pub struct TypingToplevel<'a, R: Reason> {
23     ctx: Arc<TypingCtx<R>>,
24     env: &'a TEnv<R>,
27 impl<'a, R: Reason> TypingToplevel<'a, R> {
28     fn decl_hint_env(&self) -> DeclHintEnv<R> {
29         DeclHintEnv::new(self.ctx.alloc)
30     }
32     fn hint_fun_header<'ast>(
33         &self,
34         params: &'ast [oxidized::aast::FunParam<(), ()>],
35         ret: &oxidized::aast::TypeHint<()>,
36     ) -> (
37         Option<DeclTy<R>>,
38         Vec<(&'ast oxidized::aast::FunParam<(), ()>, Option<DeclTy<R>>)>,
39     ) {
40         let ret = ret.1.as_ref().map(|h| self.decl_hint_env().hint(h));
41         let params = params
42             .iter()
43             .map(|fp| {
44                 (
45                     fp,
46                     fp.type_hint
47                         .1
48                         .as_ref()
49                         .map(|h| self.decl_hint_env().hint(h)),
50                 )
51             })
52             .collect();
53         (ret, params)
54     }
56     fn fun_def_impl(&mut self, fd: &oxidized::aast::FunDef<(), ()>) -> tast::FunDef<R> {
57         let f = &fd.fun;
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(
65                 self.env,
66                 &|env, ty| Phase::localize_no_subst(env, false, None, ty),
67                 ty,
68             ),
69         };
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()),
73         };
74         let return_ = TypingReturn::make_info(
75             self.env,
76             ret_pos,
77             &f.fun_kind,
78             &f.user_attributes,
79             f.ret.1.is_some(),
80             return_ty.clone(),
81             return_decl_ty,
82         );
83         let param_tys: Vec<_> = params_decl_ty
84             .iter()
85             .map(|(param, hint)| {
86                 (
87                     param,
88                     TypingParam::make_param_local_ty(self.env, hint.clone(), param),
89                 )
90             })
91             .collect();
92         param_tys
93             .iter()
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
97             .iter()
98             .map(|(param, ty)| {
99                 Typing::bind_param(
100                     self.env,
101                     BindParamFlags {
102                         immutable: false,
103                         can_read_globals: true,
104                     },
105                     ty.clone(),
106                     param,
107                 )
108             })
109             .collect();
110         // TODO(variance)
111         // TODO(memoize)
112         let tb = Typing::fun_(
113             self.env,
114             Default::default(),
115             return_,
116             fpos.clone(),
117             &f.body,
118             &f.fun_kind,
119         );
120         match f.ret.1 {
121             Some(_) => {}
122             None => self
123                 .env
124                 .add_error(TypingError::primary(Primary::ExpectingReturnTypeHint(fpos))),
125         }
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(),
133             tparams: vec![],
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(),
144         };
145         oxidized::aast::FunDef {
146             namespace: fd.namespace.clone(),
147             file_attributes: vec![],
148             mode: fd.mode,
149             fun,
150         }
151     }
153     pub fn fun_def(
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())
160     }