init config off typechecker options
[hiphop-php.git] / hphp / hack / src / elab / elab.rs
blob0e313538c8504855d9647b93bea84da1ba4e8dca
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.
6 #![feature(box_patterns)]
7 #![feature(is_some_and)]
9 /// Used to combine multiple types implementing `Pass` into nested `Passes` types
10 /// without requiring them to hand write it so :
11 /// `passes![p1, p2, p3]` => `Passes(p1, Passes(p2, p3))`
12 macro_rules! passes {
13     ( $p:expr $(,$ps:expr)+ $(,)? ) => {
14         $crate::pass::Passes { fst: $p, snd: passes!($($ps),*) }
15     };
16     ( $p:expr $(,)? ) => {
17         $p
18     };
21 pub mod config;
22 mod elab_utils;
23 mod pass;
24 mod passes;
25 mod transform;
27 use oxidized::ast;
28 use oxidized::naming_phase_error::NamingPhaseError;
29 use oxidized::typechecker_options::TypecheckerOptions;
30 use pass::Pass;
31 use transform::Transform;
33 pub fn elaborate_program(
34     program: &mut ast::Program,
35     tco: &TypecheckerOptions,
36 ) -> Vec<NamingPhaseError> {
37     let is_hhi = program.first_pos().map_or(false, |pos| {
38         pos.filename().prefix() == relative_path::Prefix::Hhi
39     });
40     elaborate(program, tco, is_hhi)
43 fn elaborate<T: Transform>(
44     node: &mut T,
45     tco: &TypecheckerOptions,
46     is_hhi: bool,
47 ) -> Vec<NamingPhaseError> {
48     #[rustfmt::skip]
49     let mut passes = passes![
50         // Stop on `Invalid` expressions
51         passes::guard_invalid::GuardInvalidPass::default(),
53         // -- Canonicalization passes -----------------------------------------
55         // Remove top-level file attributes, noop and markup statements
56         passes::elab_defs::ElabDefsPass::default(),
58         // Remove function bodies when in hhi mode
59         passes::elab_func_body::ElabFuncBodyPass::default(),
61         // Flatten `Block` statements
62         passes::elab_block::ElabBlockPass::default(),
64         // Strip `Hsoft` hints or replace with `Hlike`
65         passes::elab_hint_hsoft::ElabHintHsoftPass::default(),
67         // Elaborate `Happly` to canonical representation, if any
68         passes::elab_hint_happly::ElabHintHapplyPass::default(),
70         // Elaborate class identifier expressions (`CIexpr`) to canonical
71         // representation: `CIparent`, `CIself`, `CIstatic`, `CI` _or_
72         // `CIexpr (_,_, Lvar _ | This )`
73         passes::elab_class_id::ElabClassIdPass::default(),
75         // Strip type parameters from type parameters when HKTs are not enabled
76         passes::elab_hkt::ElabHktPass::default(),
78         // Elaborate `Collection` to `ValCollection` or `KeyValCollection`
79         passes::elab_expr_collection::ElabExprCollectionPass::default(),
81         // Deduplicate user attributes
82         passes::elab_user_attributes::ElabUserAttributesPass::default(),
84         // Replace import expressions with invalid expression marker
85         passes::elab_expr_import::ElabExprImportPass::default(),
87         // Elaborate local variables to canonical representation
88         passes::elab_expr_lvar::ElabExprLvarPass::default(),
90         // Warn of explicit use of builtin enum classes; make subtyping of
91         // enum classes explicit
92         passes::elab_enum_class::ElabEnumClassPass::default(),
94         // Elaborate class members & xhp attributes
95         passes::elab_class_vars::ElabClassVarsPass::default(),
97         // Elaborate special function calls to canonical representation, if any
98         passes::validate_expr_call_echo::ValidateExprCallEchoPass::default(),
99         passes::elab_expr_call_call_user_func::ElabExprCallCallUserFuncPass::default(),
100         passes::elab_expr_call_hh_meth_caller::ElabExprCallHhMethCallerPass::default(),
102         // Elaborate invariant calls to canonical representation
103         passes::elab_expr_call_hh_invariant::ElabExprCallHhInvariantPass::default(),
105         // -- Mark invalid hints and expressions & miscellaneous validation ---
107         // Replace invalid uses of `void` and `noreturn` with `Herr`
108         // passes::elab_retonly_hint::ElabRetonlyHintPass::default(),
110         // Replace invalid uses of wildcard hints with `Herr`
111         // passes::elab_wildcard_hint::ElabWildcardHintPass::default(),
113         // Replace uses to `self` in shape field names with referenced class
114         // passes::elab_shape_field_name::ElabShapeFieldNamePass::default(),
116         // Replace invalid uses of `this` hints with `Herr`
117         // passes::elab_this_hint::ElabThisHintPass::default(),
119         // Replace invalid `Haccess` root hints with `Herr`
120         // passes::elab_haccess_hint::ElabHaccessHintPass::default(),
122         // Replace empty `Tuple`s with invalid expression marker
123         passes::elab_expr_tuple::ElabExprTuplePass::default(),
125         // Validate / replace invalid uses of dynamic classes in `New` and `Class_get`
126         // expressions
127         // passes::elab_dynamic_class_name::ElabDynamicClassNamePass::default(),
129         // Replace non-constant class or global constant with invalid expression marker
130         // passes::elab_const_expr::ElabConstExprPass::default(),
132         // Replace malformed key / value bindings in as expressions with invalid
133         // local var markers
134         // passes::elab_as_expr::ElabAsExprPass::default(),
136         // Validate hints used in `Cast` expressions
137         passes::validate_expr_cast::ValidateExprCastPass::default(),
139         // Check for duplicate function parameter names
140         // passes::validate_fun_params::ValidateFunParamsPass::default(),
142         // Validate use of `require implements`, `require extends` and
143         // `require class` declarations for traits, interfaces and classes
144         passes::validate_class_req::ValidateClassReqPass::default(),
146         // Validation dealing with common xhp naming errors
147         // passes::validate_xhp_name::ValidateXhpNamePass::default(),
149         // -- Elaboration & validation under typechecker options --------------
151         // Add `supportdyn` and `Like` wrappers everywhere - under `everything-sdt`
152         // typechecker option
153         // passes::elab_everything_sdt::ElabEverythingSdtPass::default(),
155         // Validate use of `Hlike` hints - depends on `enable-like-type-hints`
156         // and `everything_sdt` typechecker options
157         // passes::validate_like_hint::ValidateLikeHintPass::default(),
159         // Validate constructors under
160         // `consistent-explicit_consistent_constructors` typechecker option
161         passes::validate_class_consistent_construct::ValidateClassConsistentConstructPass::default(),
163         // Validate  use of `SupportDyn` class - depends on `enable-supportdyn`
164         // and `everything_sdt` typechecker options
165         // passes::validate_supportdyn::ValidateSupportdynPass::default(),
167         // Validate uses of enum class type constants - depends on:
168         // - `allow_all_locations_for_type_constant_in_enum_class`
169         // - `allowed_locations_for_type_constant_in_enum_class`
170         // typecheck options
171         // passes::validate_enum_class_typeconst::ValidateEnumClassTypeconstPass::default(),
173         // Validate use of module definitions - depends on:
174         // - `allow_all_files_for_module_declarations`
175         // - `allowed_files_for_module_declarations`
176         // typechecker options
177         // passes::validate_module::ValidateModulePass::default(),
178     ];
179     let mut errs = Vec::default();
180     let cfg = config::Config::new(tco, is_hhi);
181     node.transform(&cfg, &mut errs, &mut passes);
182     errs