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 use super::{folded, ty::*};
7 use crate::reason::Reason;
8 use oxidized_by_ref::{ast::Id, s_set::SSet};
9 use pos::{Pos, ToOxidized};
11 use oxidized_by_ref as obr;
13 impl<'a> ToOxidized<'a> for CeVisibility {
14 type Output = obr::typing_defs::CeVisibility<'a>;
16 fn to_oxidized(&self, arena: &'a bumpalo::Bump) -> Self::Output {
17 use obr::typing_defs::CeVisibility as Obr;
19 CeVisibility::Public => Obr::Vpublic,
20 CeVisibility::Private(v) => Obr::Vprivate(v.to_oxidized(arena)),
21 CeVisibility::Protected(v) => Obr::Vprotected(v.to_oxidized(arena)),
22 CeVisibility::Internal(v) => Obr::Vinternal(v.to_oxidized(arena)),
27 impl<'a> ToOxidized<'a> for IfcFunDecl {
28 type Output = obr::typing_defs::IfcFunDecl<'a>;
30 fn to_oxidized(&self, arena: &'a bumpalo::Bump) -> Self::Output {
31 use obr::typing_defs::IfcFunDecl as Obr;
33 IfcFunDecl::FDPolicied(x) => Obr::FDPolicied(x.to_oxidized(arena)),
34 IfcFunDecl::FDInferFlows => Obr::FDInferFlows,
39 impl<'a, P: Pos> ToOxidized<'a> for UserAttribute<P> {
40 type Output = &'a obr::typing_defs::UserAttribute<'a>;
42 fn to_oxidized(&self, arena: &'a bumpalo::Bump) -> Self::Output {
43 arena.alloc(obr::typing_defs::UserAttribute {
44 name: self.name.to_oxidized(arena),
45 classname_params: self.classname_params.to_oxidized(arena),
50 impl<'a, R: Reason> ToOxidized<'a> for Tparam<R, DeclTy<R>> {
51 type Output = &'a obr::typing_defs::Tparam<'a>;
53 fn to_oxidized(&self, arena: &'a bumpalo::Bump) -> Self::Output {
54 arena.alloc(obr::typing_defs::Tparam {
55 variance: self.variance,
56 name: self.name.to_oxidized(arena),
57 tparams: self.tparams.to_oxidized(arena),
58 constraints: arena.alloc_slice_fill_iter(
61 .map(|(x, y)| (*x, y.to_oxidized(arena))),
63 reified: self.reified,
64 user_attributes: self.user_attributes.to_oxidized(arena),
69 impl<'a, R: Reason> ToOxidized<'a> for WhereConstraint<DeclTy<R>> {
70 type Output = &'a obr::typing_defs::WhereConstraint<'a>;
72 fn to_oxidized(&self, arena: &'a bumpalo::Bump) -> Self::Output {
73 arena.alloc(obr::typing_defs::WhereConstraint(
74 self.0.to_oxidized(arena),
76 self.2.to_oxidized(arena),
81 impl<'a, R: Reason> ToOxidized<'a> for DeclTy<R> {
82 type Output = &'a obr::typing_defs::Ty<'a>;
84 fn to_oxidized(&self, arena: &'a bumpalo::Bump) -> Self::Output {
85 arena.alloc(obr::typing_defs::Ty(
86 self.reason().to_oxidized(arena),
87 self.node().to_oxidized(arena),
92 impl<'a, R: Reason> ToOxidized<'a> for ShapeFieldType<R> {
93 type Output = &'a obr::typing_defs::ShapeFieldType<'a>;
95 fn to_oxidized(&self, arena: &'a bumpalo::Bump) -> Self::Output {
96 arena.alloc(obr::typing_defs::ShapeFieldType {
97 optional: self.optional,
98 ty: self.ty.to_oxidized(arena),
103 fn oxidize_shape_field_name<'a, P: Pos>(
104 arena: &'a bumpalo::Bump,
105 name: TshapeFieldName,
106 field_name_pos: &ShapeFieldNamePos<P>,
107 ) -> obr::typing_defs::TshapeFieldName<'a> {
108 use obr::typing_defs::TshapeFieldName as Obr;
109 use ShapeFieldNamePos as SfnPos;
110 let simple_pos = || match field_name_pos {
111 SfnPos::Simple(p) => p.to_oxidized(arena),
112 SfnPos::ClassConst(..) => panic!("expected ShapeFieldNamePos::Simple"),
115 TshapeFieldName::TSFlitInt(x) => Obr::TSFlitInt(arena.alloc(obr::typing_defs::PosString(
117 x.to_oxidized(arena),
119 TshapeFieldName::TSFlitStr(x) => Obr::TSFlitStr(arena.alloc(
120 obr::typing_defs::PosByteString(simple_pos(), x.as_bytes().into()),
122 TshapeFieldName::TSFclassConst(cls, name) => {
123 let (pos1, pos2) = match field_name_pos {
124 SfnPos::ClassConst(p1, p2) => (p1.to_oxidized(arena), p2.to_oxidized(arena)),
125 SfnPos::Simple(..) => panic!("expected ShapeFieldNamePos::ClassConst"),
127 Obr::TSFclassConst(arena.alloc((
128 (pos1, cls.to_oxidized(arena)),
129 obr::typing_defs::PosString(pos2, name.to_oxidized(arena)),
135 impl<'a, R: Reason> ToOxidized<'a> for DeclTy_<R> {
136 type Output = obr::typing_defs::Ty_<'a>;
138 fn to_oxidized(&self, arena: &'a bumpalo::Bump) -> Self::Output {
139 use obr::t_shape_map::{TShapeField, TShapeMap};
140 use obr::typing_defs::Ty_;
142 DeclTy_::DTthis => Ty_::Tthis,
143 DeclTy_::DTapply(x) => Ty_::Tapply(x.to_oxidized(arena)),
144 DeclTy_::DTmixed => Ty_::Tmixed,
145 DeclTy_::DTlike(x) => Ty_::Tlike(x.to_oxidized(arena)),
146 DeclTy_::DTany => Ty_::Tany(obr::tany_sentinel::TanySentinel),
147 DeclTy_::DTerr => Ty_::Terr,
148 DeclTy_::DTnonnull => Ty_::Tnonnull,
149 DeclTy_::DTdynamic => Ty_::Tdynamic,
150 DeclTy_::DToption(x) => Ty_::Toption(x.to_oxidized(arena)),
151 DeclTy_::DTprim(x) => Ty_::Tprim(arena.alloc(*x)),
152 DeclTy_::DTfun(x) => Ty_::Tfun(x.to_oxidized(arena)),
153 DeclTy_::DTtuple(x) => Ty_::Ttuple(x.to_oxidized(arena)),
154 DeclTy_::DTshape(shape) => {
155 let mut shape_fields = arena_collections::AssocListMut::new_in(arena);
156 for (k, v) in shape.1.iter() {
157 let k = oxidize_shape_field_name(arena, *k, &v.field_name_pos);
158 shape_fields.insert_or_replace(TShapeField(k), v.to_oxidized(arena));
160 Ty_::Tshape(arena.alloc((shape.0, TShapeMap::from(shape_fields))))
162 DeclTy_::DTvar(ident) => Ty_::Tvar((*ident).into()),
163 DeclTy_::DTgeneric(x) => Ty_::Tgeneric(x.to_oxidized(arena)),
164 DeclTy_::DTunion(x) => Ty_::Tunion(x.to_oxidized(arena)),
165 DeclTy_::DTintersection(x) => Ty_::Tintersection(x.to_oxidized(arena)),
166 DeclTy_::DTvecOrDict(x) => Ty_::TvecOrDict(x.to_oxidized(arena)),
167 DeclTy_::DTaccess(x) => Ty_::Taccess(x.to_oxidized(arena)),
172 impl<'a, R: Reason> ToOxidized<'a> for TaccessType<R, DeclTy<R>> {
173 type Output = &'a obr::typing_defs::TaccessType<'a>;
175 fn to_oxidized(&self, arena: &'a bumpalo::Bump) -> Self::Output {
176 arena.alloc(obr::typing_defs::TaccessType(
177 self.ty.to_oxidized(arena),
178 self.type_const.to_oxidized(arena),
183 impl<'a, R: Reason> ToOxidized<'a> for FunImplicitParams<R, DeclTy<R>> {
184 type Output = &'a obr::typing_defs::FunImplicitParams<'a>;
186 fn to_oxidized(&self, arena: &'a bumpalo::Bump) -> Self::Output {
187 arena.alloc(obr::typing_defs::FunImplicitParams {
188 capability: match &self.capability {
189 Capability::CapDefaults(p) => {
190 obr::typing_defs::Capability::CapDefaults(p.to_oxidized(arena))
192 Capability::CapTy(ty) => obr::typing_defs::Capability::CapTy(ty.to_oxidized(arena)),
198 impl<'a, R: Reason> ToOxidized<'a> for FunType<R, DeclTy<R>> {
199 type Output = &'a obr::typing_defs::FunType<'a>;
201 fn to_oxidized(&self, arena: &'a bumpalo::Bump) -> Self::Output {
202 arena.alloc(obr::typing_defs::FunType {
203 tparams: self.tparams.to_oxidized(arena),
204 where_constraints: self.where_constraints.to_oxidized(arena),
205 params: self.params.to_oxidized(arena),
206 implicit_params: self.implicit_params.to_oxidized(arena),
207 ret: self.ret.to_oxidized(arena),
209 ifc_decl: self.ifc_decl.to_oxidized(arena),
214 impl<'a, R: Reason> ToOxidized<'a> for PossiblyEnforcedTy<DeclTy<R>> {
215 type Output = &'a obr::typing_defs::PossiblyEnforcedTy<'a>;
217 fn to_oxidized(&self, arena: &'a bumpalo::Bump) -> Self::Output {
218 arena.alloc(obr::typing_defs::PossiblyEnforcedTy {
219 enforced: self.enforced,
220 type_: self.ty.to_oxidized(arena),
225 impl<'a, R: Reason> ToOxidized<'a> for FunParam<R, DeclTy<R>> {
226 type Output = &'a obr::typing_defs::FunParam<'a>;
228 fn to_oxidized(&self, arena: &'a bumpalo::Bump) -> Self::Output {
229 arena.alloc(obr::typing_defs::FunParam {
230 pos: self.pos.to_oxidized(arena),
231 name: self.name.to_oxidized(arena),
232 type_: self.ty.to_oxidized(arena),
238 impl<'a> ToOxidized<'a> for XhpEnumValue {
239 type Output = obr::ast_defs::XhpEnumValue<'a>;
241 fn to_oxidized(&self, arena: &'a bumpalo::Bump) -> Self::Output {
242 use obr::ast_defs::XhpEnumValue as Obr;
244 Self::XEVInt(i) => Obr::XEVInt(*i),
245 Self::XEVString(s) => Obr::XEVString(s.to_oxidized(arena)),
250 impl<'a> ToOxidized<'a> for ClassConstFrom {
251 type Output = obr::typing_defs::ClassConstFrom<'a>;
253 fn to_oxidized(&self, arena: &'a bumpalo::Bump) -> Self::Output {
254 use obr::typing_defs::ClassConstFrom as Obr;
256 Self::Self_ => Obr::Self_,
257 Self::From(ty) => Obr::From(ty.to_oxidized(arena)),
262 impl<'a> ToOxidized<'a> for ClassConstRef {
263 type Output = obr::typing_defs::ClassConstRef<'a>;
265 fn to_oxidized(&self, arena: &'a bumpalo::Bump) -> Self::Output {
266 obr::typing_defs::ClassConstRef(self.0.to_oxidized(arena), self.1.to_oxidized(arena))
270 impl<'a, R: Reason> ToOxidized<'a> for AbstractTypeconst<R> {
271 type Output = &'a obr::typing_defs::AbstractTypeconst<'a>;
273 fn to_oxidized(&self, arena: &'a bumpalo::Bump) -> Self::Output {
274 arena.alloc(obr::typing_defs::AbstractTypeconst {
275 as_constraint: self.as_constraint.to_oxidized(arena),
276 super_constraint: self.super_constraint.to_oxidized(arena),
277 default: self.default.to_oxidized(arena),
282 impl<'a, R: Reason> ToOxidized<'a> for ConcreteTypeconst<R> {
283 type Output = &'a obr::typing_defs::ConcreteTypeconst<'a>;
285 fn to_oxidized(&self, arena: &'a bumpalo::Bump) -> Self::Output {
286 arena.alloc(obr::typing_defs::ConcreteTypeconst {
287 tc_type: self.ty.to_oxidized(arena),
292 impl<'a, R: Reason> ToOxidized<'a> for Typeconst<R> {
293 type Output = obr::typing_defs::Typeconst<'a>;
295 fn to_oxidized(&self, arena: &'a bumpalo::Bump) -> Self::Output {
296 use obr::typing_defs::Typeconst as Obr;
298 Self::TCAbstract(x) => Obr::TCAbstract(x.to_oxidized(arena)),
299 Self::TCConcrete(x) => Obr::TCConcrete(x.to_oxidized(arena)),
304 impl<'a, R: Reason> ToOxidized<'a> for folded::SubstContext<R> {
305 type Output = &'a obr::decl_defs::SubstContext<'a>;
307 fn to_oxidized(&self, arena: &'a bumpalo::Bump) -> Self::Output {
308 arena.alloc(obr::decl_defs::SubstContext {
309 subst: self.subst.to_oxidized(arena),
310 class_context: self.class_context.to_oxidized(arena),
311 from_req_extends: self.from_req_extends,
316 impl<'a, R: Reason> ToOxidized<'a> for folded::TypeConst<R> {
317 type Output = &'a obr::typing_defs::TypeconstType<'a>;
319 fn to_oxidized(&self, arena: &'a bumpalo::Bump) -> Self::Output {
320 arena.alloc(obr::typing_defs::TypeconstType {
321 synthesized: self.is_synthesized,
322 concretized: self.is_concreteized,
324 enforceable: self.enforceable.as_ref().map_or_else(
325 || (obr::pos::Pos::none(), false),
326 |x| (x.to_oxidized(arena), true),
328 reifiable: self.reifiable.as_ref().map(|x| x.to_oxidized(arena)),
329 origin: self.origin.to_oxidized(arena),
330 kind: self.kind.to_oxidized(arena),
331 name: self.name.to_oxidized(arena),
336 impl<'a, R: Reason> ToOxidized<'a> for folded::ClassConst<R> {
337 type Output = &'a obr::typing_defs::ClassConst<'a>;
339 fn to_oxidized(&self, arena: &'a bumpalo::Bump) -> Self::Output {
340 arena.alloc(obr::typing_defs::ClassConst {
341 synthesized: self.is_synthesized,
342 abstract_: self.kind,
343 origin: self.origin.to_oxidized(arena),
344 refs: self.refs.to_oxidized(arena),
345 type_: self.ty.to_oxidized(arena),
346 pos: self.pos.to_oxidized(arena),
351 impl<'a, R: Reason> ToOxidized<'a> for folded::FoldedClass<R> {
352 type Output = obr::decl_defs::DeclClassType<'a>;
354 fn to_oxidized(&self, arena: &'a bumpalo::Bump) -> Self::Output {
355 obr::decl_defs::DeclClassType {
356 name: self.name.to_oxidized(arena),
357 pos: self.pos.to_oxidized(arena),
359 abstract_: self.is_abstract(),
360 final_: self.is_final,
361 const_: self.is_const,
362 internal: self.is_internal,
364 has_xhp_keyword: self.has_xhp_keyword,
365 support_dynamic_type: self.support_dynamic_type,
366 module: self.module.as_ref().map(|m| {
367 let (pos, id) = m.to_oxidized(arena);
370 tparams: self.tparams.to_oxidized(arena),
371 where_constraints: self.where_constraints.to_oxidized(arena),
372 substs: self.substs.to_oxidized(arena),
373 ancestors: self.ancestors.to_oxidized(arena),
374 props: self.props.to_oxidized(arena),
375 sprops: self.static_props.to_oxidized(arena),
376 methods: self.methods.to_oxidized(arena),
377 smethods: self.static_methods.to_oxidized(arena),
378 consts: self.consts.to_oxidized(arena),
379 typeconsts: self.type_consts.to_oxidized(arena),
380 xhp_enum_values: self.xhp_enum_values.to_oxidized(arena),
381 // TODO(milliechen): implement the rest
382 construct: (None, obr::typing_defs::ConsistentKind::Inconsistent),
384 deferred_init_members: SSet::empty(),
386 req_ancestors_extends: SSet::empty(),
387 extends: SSet::empty(),
388 sealed_whitelist: None,
389 xhp_attr_deps: SSet::empty(),
392 condition_types: SSet::empty(),
397 impl<'a> ToOxidized<'a> for folded::FoldedElement {
398 type Output = &'a obr::decl_defs::Element<'a>;
400 fn to_oxidized(&self, arena: &'a bumpalo::Bump) -> Self::Output {
401 arena.alloc(obr::decl_defs::Element {
402 origin: self.origin.to_oxidized(arena),
403 visibility: self.visibility.to_oxidized(arena),
404 deprecated: self.deprecated.map(|x| {
405 bumpalo::collections::String::from_utf8_lossy_in(x.as_bytes(), arena)