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 oxidized_by_ref as obr;
10 use crate::decl::folded;
11 use crate::decl::shallow;
15 use crate::reason::Reason;
18 fn slice<T: Copy + Into<U>, U>(items: &[T]) -> Box<[U]> {
19 items.iter().copied().map(Into::into).collect()
23 fn map<'a, K1, V1, K2, V2, M>(items: impl Iterator<Item = (&'a K1, &'a V1)>) -> M
25 K1: Copy + Into<K2> + 'a,
26 V1: Copy + Into<V2> + 'a,
27 M: FromIterator<(K2, V2)>,
29 items.map(|(&k, &v)| (k.into(), v.into())).collect()
32 impl From<obr::ast_defs::XhpEnumValue<'_>> for ty::XhpEnumValue {
33 fn from(x: obr::ast_defs::XhpEnumValue<'_>) -> Self {
34 use obr::ast_defs::XhpEnumValue as Obr;
36 Obr::XEVInt(i) => Self::XEVInt(i),
37 Obr::XEVString(s) => Self::XEVString(s.into()),
42 impl From<obr::typing_defs::CeVisibility<'_>> for ty::CeVisibility {
43 fn from(x: obr::typing_defs::CeVisibility<'_>) -> Self {
44 use obr::typing_defs::CeVisibility as Obr;
46 Obr::Vpublic => Self::Public,
47 Obr::Vprivate(s) => Self::Private(s.into()),
48 Obr::Vprotected(s) => Self::Protected(s.into()),
49 Obr::Vinternal(s) => Self::Internal(s.into()),
54 impl From<obr::typing_defs::IfcFunDecl<'_>> for ty::IfcFunDecl {
55 fn from(x: obr::typing_defs::IfcFunDecl<'_>) -> Self {
56 use obr::typing_defs_core::IfcFunDecl as Obr;
58 Obr::FDPolicied(s) => Self::FDPolicied(s.map(Into::into)),
59 Obr::FDInferFlows => Self::FDInferFlows,
64 fn tshape_field_name_from_decl<P: Pos>(
65 x: obr::typing_defs::TshapeFieldName<'_>,
66 ) -> (ty::ShapeFieldNamePos<P>, ty::TshapeFieldName) {
67 use obr::typing_defs_core::TshapeFieldName as Obr;
68 use ty::ShapeFieldNamePos as SfnPos;
69 use ty::TshapeFieldName;
71 Obr::TSFlitInt(&pos_id) => (
72 SfnPos::Simple(pos_id.0.into()),
73 TshapeFieldName::TSFlitInt(pos_id.1.into()),
75 Obr::TSFlitStr(&pos_bytes) => (
76 SfnPos::Simple(pos_bytes.0.into()),
77 TshapeFieldName::TSFlitStr(pos_bytes.1.into()),
79 Obr::TSFclassConst(&(pos_id1, pos_id2)) => (
80 SfnPos::ClassConst(pos_id1.0.into(), pos_id2.0.into()),
81 TshapeFieldName::TSFclassConst(pos_id1.1.into(), pos_id2.1.into()),
86 impl<P: Pos> From<&obr::typing_defs::UserAttribute<'_>> for ty::UserAttribute<P> {
87 fn from(attr: &obr::typing_defs::UserAttribute<'_>) -> Self {
89 name: attr.name.into(),
90 classname_params: (attr.classname_params.iter())
98 impl<R: Reason> From<&obr::typing_defs::Tparam<'_>> for ty::Tparam<R, Ty<R>> {
99 fn from(tparam: &obr::typing_defs::Tparam<'_>) -> Self {
101 variance: tparam.variance,
102 name: tparam.name.into(),
103 tparams: slice(tparam.tparams),
104 constraints: (tparam.constraints.iter())
105 .map(|(kind, ty)| (*kind, (*ty).into()))
107 reified: tparam.reified,
108 user_attributes: slice(tparam.user_attributes),
113 impl<R: Reason> From<&obr::typing_defs::WhereConstraint<'_>> for ty::WhereConstraint<Ty<R>> {
114 fn from(x: &obr::typing_defs::WhereConstraint<'_>) -> Self {
115 Self(x.0.into(), x.1, x.2.into())
119 fn decl_shape_field_type<R: Reason>(
120 field_name_pos: ty::ShapeFieldNamePos<R::Pos>,
121 sft: &obr::typing_defs::ShapeFieldType<'_>,
122 ) -> ty::ShapeFieldType<R> {
125 optional: sft.optional,
130 impl<R: Reason> From<&obr::typing_defs::Ty<'_>> for Ty<R> {
131 fn from(ty: &obr::typing_defs::Ty<'_>) -> Self {
132 use obr::typing_defs_core;
134 let reason = R::from(*ty.0);
135 let ty_ = match ty.1 {
136 typing_defs_core::Ty_::Tthis => Tthis,
137 typing_defs_core::Ty_::Tapply(&(pos_id, tys)) => {
138 Tapply(Box::new((pos_id.into(), slice(tys))))
140 typing_defs_core::Ty_::Tmixed => Tmixed,
141 typing_defs_core::Ty_::Tlike(ty) => Tlike(ty.into()),
142 typing_defs_core::Ty_::Tany(_) => Tany,
143 typing_defs_core::Ty_::Tnonnull => Tnonnull,
144 typing_defs_core::Ty_::Tdynamic => Tdynamic,
145 typing_defs_core::Ty_::Toption(ty) => Toption(ty.into()),
146 typing_defs_core::Ty_::Tprim(prim) => Tprim(*prim),
147 typing_defs_core::Ty_::Tfun(ft) => Tfun(Box::new(ft.into())),
148 typing_defs_core::Ty_::Ttuple(tys) => Ttuple(slice(tys)),
149 typing_defs_core::Ty_::Tshape(&(kind, fields)) => Tshape(Box::new((
154 let (field_name_pos, name) = tshape_field_name_from_decl(name.0);
155 (name, decl_shape_field_type(field_name_pos, ty))
159 typing_defs_core::Ty_::Trefinement(&(ty, cr)) => {
160 Trefinement(Box::new(decl::TrefinementType {
162 refinement: ty::ClassRefinement {
163 consts: (cr.cr_consts.iter())
164 .map(|(k, v)| ((*k).into(), (*v).into()))
169 typing_defs_core::Ty_::Tvar(ident) => Tvar(ident.into()),
170 typing_defs_core::Ty_::Tgeneric(&(pos_id, tys)) => {
171 Tgeneric(Box::new((pos_id.into(), slice(tys))))
173 typing_defs_core::Ty_::Tunion(tys) => Tunion(slice(tys)),
174 typing_defs_core::Ty_::Tintersection(tys) => Tintersection(slice(tys)),
175 typing_defs_core::Ty_::TvecOrDict(&(ty1, ty2)) => {
176 TvecOrDict(Box::new((ty1.into(), ty2.into())))
178 typing_defs_core::Ty_::Taccess(taccess_type) => Taccess(Box::new(taccess_type.into())),
179 typing_defs_core::Ty_::TunappliedAlias(_)
180 | typing_defs_core::Ty_::Tnewtype(_)
181 | typing_defs_core::Ty_::Tdependent(_)
182 | typing_defs_core::Ty_::Tclass(_)
183 | typing_defs_core::Ty_::Tneg(_) => {
184 unreachable!("Not used in decl tys")
191 impl<R: Reason> From<obr::typing_defs::RefinedConst<'_>> for ty::RefinedConst<Ty<R>> {
192 fn from(rc: obr::typing_defs::RefinedConst<'_>) -> Self {
194 bound: rc.bound.into(),
195 is_ctx: rc.is_ctx.into(),
200 impl<R: Reason> From<obr::typing_defs::RefinedConstBound<'_>> for ty::RefinedConstBound<Ty<R>> {
201 fn from(ctr: obr::typing_defs::RefinedConstBound<'_>) -> Self {
202 use obr::typing_defs::RefinedConstBound::*;
204 TRexact(ty) => Self::Exact(ty.into()),
205 TRloose(bounds) => Self::Loose(bounds.into()),
210 impl<R: Reason> From<&obr::typing_defs::RefinedConstBounds<'_>> for ty::RefinedConstBounds<Ty<R>> {
211 fn from(bounds: &obr::typing_defs::RefinedConstBounds<'_>) -> Self {
213 lower: slice(bounds.lower),
214 upper: slice(bounds.upper),
219 impl<R: Reason> From<&obr::typing_defs::TaccessType<'_>> for ty::TaccessType<R, Ty<R>> {
220 fn from(taccess_type: &obr::typing_defs::TaccessType<'_>) -> Self {
222 ty: taccess_type.0.into(),
223 type_const: taccess_type.1.into(),
228 impl<R: Reason> From<obr::typing_defs::Capability<'_>> for ty::Capability<R, Ty<R>> {
229 fn from(cap: obr::typing_defs::Capability<'_>) -> Self {
230 use obr::typing_defs_core::Capability as Obr;
232 Obr::CapDefaults(pos) => Self::CapDefaults(pos.into()),
233 Obr::CapTy(ty) => Self::CapTy(ty.into()),
238 impl<R: Reason> From<&obr::typing_defs::FunImplicitParams<'_>> for ty::FunImplicitParams<R, Ty<R>> {
239 fn from(x: &obr::typing_defs::FunImplicitParams<'_>) -> Self {
241 capability: x.capability.into(),
246 impl<R: Reason> From<&obr::typing_defs::FunType<'_>> for ty::FunType<R, Ty<R>> {
247 fn from(ft: &obr::typing_defs::FunType<'_>) -> Self {
249 tparams: slice(ft.tparams),
250 where_constraints: slice(ft.where_constraints),
251 params: slice(ft.params),
252 implicit_params: ft.implicit_params.into(),
255 ifc_decl: ft.ifc_decl.into(),
260 impl<R: Reason> From<&obr::typing_defs_core::PossiblyEnforcedTy<'_>>
261 for decl::ty::PossiblyEnforcedTy<Ty<R>>
263 fn from(ty: &obr::typing_defs_core::PossiblyEnforcedTy<'_>) -> Self {
266 enforced: ty.enforced,
271 impl<R: Reason> From<&obr::typing_defs_core::FunParam<'_>> for ty::FunParam<R, Ty<R>> {
272 fn from(fp: &obr::typing_defs_core::FunParam<'_>) -> Self {
275 name: fp.name.map(Into::into),
282 impl From<obr::typing_defs::ClassConstFrom<'_>> for ty::ClassConstFrom {
283 fn from(x: obr::typing_defs::ClassConstFrom<'_>) -> Self {
284 use obr::typing_defs::ClassConstFrom as Obr;
286 Obr::Self_ => Self::Self_,
287 Obr::From(s) => Self::From(s.into()),
292 impl From<obr::typing_defs::ClassConstRef<'_>> for ty::ClassConstRef {
293 fn from(x: obr::typing_defs::ClassConstRef<'_>) -> Self {
294 Self(x.0.into(), x.1.into())
298 impl<R: Reason> From<&obr::typing_defs::AbstractTypeconst<'_>> for ty::AbstractTypeconst<R> {
299 fn from(x: &obr::typing_defs::AbstractTypeconst<'_>) -> Self {
301 as_constraint: x.as_constraint.map(Into::into),
302 super_constraint: x.super_constraint.map(Into::into),
303 default: x.default.map(Into::into),
308 impl<R: Reason> From<&obr::typing_defs::ConcreteTypeconst<'_>> for ty::ConcreteTypeconst<R> {
309 fn from(x: &obr::typing_defs::ConcreteTypeconst<'_>) -> Self {
311 ty: x.tc_type.into(),
316 impl<R: Reason> From<obr::typing_defs::Typeconst<'_>> for ty::Typeconst<R> {
317 fn from(x: obr::typing_defs::Typeconst<'_>) -> Self {
318 use obr::typing_defs::Typeconst as Obr;
320 Obr::TCAbstract(atc) => Self::TCAbstract(atc.into()),
321 Obr::TCConcrete(ctc) => Self::TCConcrete(ctc.into()),
326 impl<R: Reason> From<&obr::typing_defs::EnumType<'_>> for ty::EnumType<R> {
327 fn from(x: &obr::typing_defs::EnumType<'_>) -> Self {
330 constraint: x.constraint.map(Into::into),
331 includes: slice(x.includes),
336 impl<P: Pos> From<(&obr::pos::Pos<'_>, bool)> for ty::Enforceable<P> {
337 fn from((pos, is_enforceable): (&obr::pos::Pos<'_>, bool)) -> Self {
339 Self(Some(pos.into()))
346 impl<R: Reason> From<&obr::shallow_decl_defs::ShallowClassConst<'_>>
347 for shallow::ShallowClassConst<R>
349 fn from(scc: &obr::shallow_decl_defs::ShallowClassConst<'_>) -> Self {
352 name: scc.name.into(),
353 ty: scc.type_.into(),
354 refs: slice(scc.refs),
359 impl<R: Reason> From<&obr::shallow_decl_defs::ShallowTypeconst<'_>>
360 for shallow::ShallowTypeconst<R>
362 fn from(stc: &obr::shallow_decl_defs::ShallowTypeconst<'_>) -> Self {
364 name: stc.name.into(),
365 kind: stc.kind.into(),
366 enforceable: <ty::Enforceable<R::Pos>>::from(stc.enforceable),
367 reifiable: stc.reifiable.map(Into::into),
373 impl<R: Reason> From<&obr::shallow_decl_defs::ShallowMethod<'_>> for shallow::ShallowMethod<R> {
374 fn from(sm: &obr::shallow_decl_defs::ShallowMethod<'_>) -> Self {
376 name: sm.name.into(),
378 visibility: sm.visibility,
379 deprecated: sm.deprecated.map(Into::into),
380 attributes: slice(sm.attributes),
386 impl<R: Reason> From<&obr::shallow_decl_defs::ShallowProp<'_>> for shallow::ShallowProp<R> {
387 fn from(sp: &obr::shallow_decl_defs::ShallowProp<'_>) -> Self {
389 name: sp.name.into(),
390 xhp_attr: sp.xhp_attr,
392 visibility: sp.visibility,
398 impl<R: Reason> From<&obr::shallow_decl_defs::ClassDecl<'_>> for shallow::ShallowClass<R> {
399 fn from(sc: &obr::shallow_decl_defs::ClassDecl<'_>) -> Self {
400 // Destructure to help ensure we convert every field.
401 let obr::shallow_decl_defs::ClassDecl {
421 support_dynamic_type,
436 is_abstract: *abstract_,
437 is_internal: *internal,
439 has_xhp_keyword: *has_xhp_keyword,
441 module: module.map(Into::into),
442 name: (*name).into(),
443 tparams: slice(tparams),
444 where_constraints: slice(where_constraints),
445 extends: slice(extends),
447 xhp_attr_uses: slice(xhp_attr_uses),
448 xhp_enum_values: (xhp_enum_values.iter())
449 .map(|(&k, v)| (k.into(), slice(v)))
451 req_extends: slice(req_extends),
452 req_implements: slice(req_implements),
453 req_class: slice(req_class),
454 implements: slice(implements),
455 support_dynamic_type: *support_dynamic_type,
456 consts: slice(consts),
457 typeconsts: slice(typeconsts),
459 static_props: slice(sprops),
460 constructor: constructor.map(Into::into),
461 static_methods: slice(static_methods),
462 methods: slice(methods),
463 user_attributes: slice(user_attributes),
464 enum_type: enum_type.map(Into::into),
465 docs_url: docs_url.map(Into::into),
470 impl<R: Reason> From<&obr::shallow_decl_defs::FunDecl<'_>> for shallow::FunDecl<R> {
471 fn from(sf: &obr::shallow_decl_defs::FunDecl<'_>) -> Self {
475 deprecated: sf.deprecated.map(Into::into),
476 module: sf.module.map(Into::into),
477 internal: sf.internal,
478 php_std_lib: sf.php_std_lib,
479 support_dynamic_type: sf.support_dynamic_type,
480 no_auto_dynamic: sf.no_auto_dynamic,
485 impl<R: Reason> From<&obr::shallow_decl_defs::TypedefDecl<'_>> for shallow::TypedefDecl<R> {
486 fn from(x: &obr::shallow_decl_defs::TypedefDecl<'_>) -> Self {
488 module: x.module.map(Into::into),
491 tparams: slice(x.tparams),
492 as_constraint: x.as_constraint.map(Into::into),
493 super_constraint: x.super_constraint.map(Into::into),
496 attributes: slice(x.attributes),
497 internal: x.internal,
498 docs_url: x.docs_url.map(Into::into),
503 impl<R: Reason> From<&obr::shallow_decl_defs::ConstDecl<'_>> for shallow::ConstDecl<R> {
504 fn from(x: &obr::shallow_decl_defs::ConstDecl<'_>) -> Self {
512 impl From<obr::typing_defs::ModuleReference<'_>> for ty::ModuleReference {
513 fn from(x: obr::typing_defs::ModuleReference<'_>) -> Self {
514 use obr::typing_defs::ModuleReference as Obr;
516 Obr::MRGlobal => Self::MRGlobal,
517 Obr::MRPrefix(m) => Self::MRPrefix(m.into()),
518 Obr::MRExact(m) => Self::MRExact(m.into()),
523 impl<R: Reason> From<&obr::shallow_decl_defs::ModuleDefType<'_>> for shallow::ModuleDecl<R> {
524 fn from(x: &obr::shallow_decl_defs::ModuleDefType<'_>) -> Self {
527 exports: x.exports.map(slice),
528 imports: x.imports.map(slice),
533 impl<R: Reason> From<&obr::shallow_decl_defs::Decl<'_>> for shallow::Decl<R> {
534 fn from(decl: &obr::shallow_decl_defs::Decl<'_>) -> Self {
535 use obr::shallow_decl_defs::Decl as Obr;
537 Obr::Class(x) => Self::Class(x.into()),
538 Obr::Fun(x) => Self::Fun(x.into()),
539 Obr::Typedef(x) => Self::Typedef(x.into()),
540 Obr::Const(x) => Self::Const(x.into()),
541 Obr::Module(x) => Self::Module(x.into()),
546 impl<R: Reason> From<&(&str, obr::shallow_decl_defs::Decl<'_>)> for shallow::NamedDecl<R> {
547 fn from(decl: &(&str, obr::shallow_decl_defs::Decl<'_>)) -> Self {
548 use obr::shallow_decl_defs::Decl as Obr;
550 (name, Obr::Class(x)) => Self::Class(name.into(), x.into()),
551 (name, Obr::Fun(x)) => Self::Fun(name.into(), x.into()),
552 (name, Obr::Typedef(x)) => Self::Typedef(name.into(), x.into()),
553 (name, Obr::Const(x)) => Self::Const(name.into(), x.into()),
554 (name, Obr::Module(x)) => Self::Module(name.into(), x.into()),
559 impl From<&obr::decl_defs::Element<'_>> for folded::FoldedElement {
560 fn from(x: &obr::decl_defs::Element<'_>) -> Self {
563 origin: x.origin.into(),
564 visibility: x.visibility.into(),
565 deprecated: x.deprecated.map(Into::into),
570 impl<R: Reason> From<&obr::decl_defs::SubstContext<'_>> for folded::SubstContext<R> {
571 fn from(x: &obr::decl_defs::SubstContext<'_>) -> Self {
573 subst: folded::Subst(map(x.subst.iter())),
574 class_context: x.class_context.into(),
575 from_req_extends: x.from_req_extends,
580 impl<R: Reason> From<&obr::typing_defs::TypeconstType<'_>> for folded::TypeConst<R> {
581 fn from(x: &obr::typing_defs::TypeconstType<'_>) -> Self {
583 is_synthesized: x.synthesized,
586 origin: x.origin.into(),
587 enforceable: x.enforceable.into(),
588 reifiable: x.reifiable.map(Into::into),
589 is_concretized: x.concretized,
595 impl<R: Reason> From<&obr::typing_defs::ClassConst<'_>> for folded::ClassConst<R> {
596 fn from(x: &obr::typing_defs::ClassConst<'_>) -> Self {
598 is_synthesized: x.synthesized,
602 origin: x.origin.into(),
608 impl<R: Reason> From<&obr::decl_defs::Requirement<'_>> for folded::Requirement<R> {
609 fn from(req: &obr::decl_defs::Requirement<'_>) -> Self {
617 impl From<(Option<&obr::decl_defs::Element<'_>>, ty::ConsistentKind)> for folded::Constructor {
618 fn from(construct: (Option<&obr::decl_defs::Element<'_>>, ty::ConsistentKind)) -> Self {
619 Self::new(construct.0.map(Into::into), construct.1)
623 impl<P> From<obr::decl_defs::DeclError<'_>> for crate::decl_error::DeclError<P>
625 P: for<'a> From<&'a obr::pos::Pos<'a>>,
627 fn from(decl_error: obr::decl_defs::DeclError<'_>) -> Self {
628 use obr::decl_defs::DeclError as Obr;
630 Obr::WrongExtendKind {
637 } => Self::WrongExtendKind {
641 parent_pos: parent_pos.into(),
643 parent_name: parent_name.into(),
645 Obr::CyclicClassDef { pos, stack } => {
646 Self::CyclicClassDef(pos.into(), stack.iter().copied().map(Into::into).collect())
652 impl<R: Reason> From<&obr::decl_defs::DeclClassType<'_>> for folded::FoldedClass<R> {
653 fn from(cls: &obr::decl_defs::DeclClassType<'_>) -> Self {
654 // Destructure to help ensure we convert every field. A couple fields
655 // are ignored because they're redundant with other fields (and
656 // `folded::FoldedClass` just omits the redundant fields).
657 let obr::decl_defs::DeclClassType {
661 abstract_: _, // `Self::is_abstract()` just reads the `kind` field
667 support_dynamic_type,
681 need_init: _, // `Self::has_concrete_constructor()` reads the `constructor` field
682 deferred_init_members,
684 req_ancestors_extends,
694 name: (*name).into(),
699 is_internal: *internal,
701 has_xhp_keyword: *has_xhp_keyword,
702 support_dynamic_type: *support_dynamic_type,
703 enum_type: enum_type.map(Into::into),
704 module: module.map(Into::into),
705 tparams: slice(tparams),
706 where_constraints: slice(where_constraints),
707 substs: map(substs.iter()),
708 ancestors: map(ancestors.iter()),
709 props: map(props.iter()),
710 static_props: map(sprops.iter()),
711 methods: map(methods.iter()),
712 static_methods: map(smethods.iter()),
713 constructor: (*construct).into(),
714 consts: map(consts.iter()),
715 type_consts: map(typeconsts.iter()),
716 xhp_enum_values: (xhp_enum_values.iter())
717 .map(|(&s, &evs)| (s.into(), slice(evs)))
719 extends: extends.iter().copied().map(Into::into).collect(),
720 xhp_attr_deps: xhp_attr_deps.iter().copied().map(Into::into).collect(),
721 req_ancestors: req_ancestors.iter().copied().map(Into::into).collect(),
722 req_ancestors_extends: (req_ancestors_extends.iter())
726 req_class_ancestors: (req_class_ancestors.iter())
730 sealed_whitelist: (sealed_whitelist)
731 .map(|l| l.iter().copied().map(Into::into).collect()),
732 deferred_init_members: (deferred_init_members.iter())
736 decl_errors: slice(*decl_errors),
737 docs_url: docs_url.map(Into::into),