1 // Copyright (c) Meta Platforms, Inc. and 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 #![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))`
13 ( $p:expr $(,$ps:expr)+ $(,)? ) => {
14 $crate::pass::Passes { fst: $p, snd: passes!($($ps),*) }
16 ( $p:expr $(,)? ) => {
28 use oxidized::naming_phase_error::NamingPhaseError;
29 use oxidized::typechecker_options::TypecheckerOptions;
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
40 elaborate(program, tco, is_hhi)
43 fn elaborate<T: Transform>(
45 tco: &TypecheckerOptions,
47 ) -> Vec<NamingPhaseError> {
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`
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
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`
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(),
179 let mut errs = Vec::default();
180 let cfg = config::Config::new(tco, is_hhi);
181 node.transform(&cfg, &mut errs, &mut passes);