Skip to content

Commit

Permalink
Add enum<E> type to match enumname<E>
Browse files Browse the repository at this point in the history
Summary: This adds a type `enum<E>` that expands to `class<BuiltinEnum<E>>` during decling. This mirrors the HHI alias `enumname<E> = classname<BuiltinEnum<E>>`. The type shares the syntax node for class pointer types, just varying the keyword, and its hint representation is just is a variant of the class pointer hint.

Reviewed By: viratyosin

Differential Revision: D66044536

fbshipit-source-id: de9f987e5fe8933907f6449e04b77dff1fee9094
  • Loading branch information
vassilmladenov authored and facebook-github-bot committed Nov 21, 2024
1 parent d770154 commit 624d056
Show file tree
Hide file tree
Showing 35 changed files with 463 additions and 76 deletions.
6 changes: 5 additions & 1 deletion hphp/hack/src/annotated_ast/aast_defs.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1228,14 +1228,18 @@ and hint_fun = {
hf_is_readonly_return: Ast_defs.readonly_kind option; [@transform.opaque]
}

and class_ptr_kind =
| CKclass
| CKenum

and hint_ =
| Hprim of (tprim[@transform.opaque])
| Happly of class_name * hint list
| Hoption of hint
| Hlike of hint
| Hfun of hint_fun
| Htuple of tuple_info
| Hclass_ptr of hint
| Hclass_ptr of class_ptr_kind * hint
| Hshape of nast_shape_info
| Haccess of hint * sid list
(** Accessing a type constant. Type constants are accessed like normal
Expand Down
8 changes: 7 additions & 1 deletion hphp/hack/src/decl/decl_hint.ml
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,13 @@ and hint_ p env = function
| Habstr (x, argl) ->
let argl = List.map argl ~f:(hint env) in
Tgeneric (x, argl)
| Hclass_ptr h -> Tclass_ptr (hint env h)
| Hclass_ptr (k, h) ->
let h =
match k with
| CKclass -> h
| CKenum -> (p, Happly ((p, SN.Classes.cHH_BuiltinEnum), [h]))
in
Tclass_ptr (hint env h)
| Hoption h ->
let h = hint env h in
Toption h
Expand Down
31 changes: 18 additions & 13 deletions hphp/hack/src/decl/direct_decl_smart_constructors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5748,29 +5748,34 @@ impl<'a, 'o, 't, S: SourceTextAllocator<'t, 'a>> FlattenSmartConstructors

fn make_class_ptr_type_specifier(
&mut self,
class: Self::Output,
kw: Self::Output,
_lt: Self::Output,
targ: Self::Output,
_trailing_comma: Self::Output,
gt: Self::Output,
) -> Self::Output {
if self.opts.enable_class_pointer_hint {
let pos = self.merge_positions(class, gt);
let pos = self.merge_positions(kw, gt);
let reason = self.alloc(Reason::FromWitnessDecl(self.alloc(WitnessDecl::Hint(pos))));
let cls = match self.node_to_ty(targ) {
Some(ty) => ty,
None => return Node::Ignored(SK::ClassPtrTypeSpecifier),
let cls = match (kw.token_kind(), self.node_to_ty(targ)) {
(Some(TokenKind::Class), Some(ty)) => ty,
(Some(TokenKind::Enum), Some(ty)) => self.alloc(Ty(
reason,
Ty_::Tapply(self.alloc((
(pos, naming_special_names::classes::HH_BUILTIN_ENUM),
self.alloc([ty]),
))),
)),
_ => return Node::Ignored(SK::ClassPtrTypeSpecifier),
};
Node::Ty(self.alloc(Ty(reason, Ty_::TclassPtr(cls))))
} else {
self.make_apply(
(
self.get_pos(class),
naming_special_names::classes::CLASS_NAME,
),
targ,
self.get_pos(targ),
)
let id = match kw.token_kind() {
Some(TokenKind::Class) => naming_special_names::classes::CLASS_NAME,
Some(TokenKind::Enum) => naming_special_names::classes::ENUM_NAME,
_ => return Node::Ignored(SK::ClassPtrTypeSpecifier),
};
self.make_apply((self.get_pos(kw), id), targ, self.get_pos(targ))
}
}

Expand Down
40 changes: 39 additions & 1 deletion hphp/hack/src/elab/pass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// This source code is licensed under the MIT license found in the
// LICENSE file in the "hack" directory of this source tree.
//
// @generated SignedSource<<6d53e3dd14519a317916703b215c4c38>>
// @generated SignedSource<<dd90fc34a9b41bbb91c8ab6d91388dbd>>
//
// To regenerate this file, run:
// hphp/hack/src/oxidized_regen.sh
Expand Down Expand Up @@ -1136,6 +1136,22 @@ pub trait Pass: PassClone {
Continue(())
}
#[inline(always)]
fn on_ty_class_ptr_kind_top_down(
&mut self,
env: &Env,
elem: &mut ClassPtrKind,
) -> ControlFlow<()> {
Continue(())
}
#[inline(always)]
fn on_ty_class_ptr_kind_bottom_up(
&mut self,
env: &Env,
elem: &mut ClassPtrKind,
) -> ControlFlow<()> {
Continue(())
}
#[inline(always)]
fn on_ty_hint__top_down(&mut self, env: &Env, elem: &mut Hint_) -> ControlFlow<()> {
Continue(())
}
Expand Down Expand Up @@ -2972,6 +2988,28 @@ impl Pass for Passes {
Continue(())
}
#[inline(always)]
fn on_ty_class_ptr_kind_top_down(
&mut self,
env: &Env,
elem: &mut ClassPtrKind,
) -> ControlFlow<()> {
for pass in &mut self.passes {
pass.on_ty_class_ptr_kind_top_down(env, elem)?;
}
Continue(())
}
#[inline(always)]
fn on_ty_class_ptr_kind_bottom_up(
&mut self,
env: &Env,
elem: &mut ClassPtrKind,
) -> ControlFlow<()> {
for pass in &mut self.passes {
pass.on_ty_class_ptr_kind_bottom_up(env, elem)?;
}
Continue(())
}
#[inline(always)]
fn on_ty_hint__top_down(&mut self, env: &Env, elem: &mut Hint_) -> ControlFlow<()> {
for pass in &mut self.passes {
pass.on_ty_hint__top_down(env, elem)?;
Expand Down
25 changes: 23 additions & 2 deletions hphp/hack/src/elab/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// This source code is licensed under the MIT license found in the
// LICENSE file in the "hack" directory of this source tree.
//
// @generated SignedSource<<5f86f1eac058855eef67b7959dd0012b>>
// @generated SignedSource<<6f5e023411c62a93f680149e18b781cf>>
//
// To regenerate this file, run:
// hphp/hack/src/oxidized_regen.sh
Expand Down Expand Up @@ -2356,6 +2356,22 @@ impl Transform for HintFun {
}
}
}
impl Transform for ClassPtrKind {
fn transform(&mut self, env: &Env, pass: &mut (impl Pass + Clone)) {
let mut in_pass = pass.clone();
if let Break(..) = pass.on_ty_class_ptr_kind_top_down(env, self) {
return;
}
stack_limit::maybe_grow(|| self.traverse(env, pass));
in_pass.on_ty_class_ptr_kind_bottom_up(env, self);
}
fn traverse(&mut self, env: &Env, pass: &mut (impl Pass + Clone)) {
match self {
ClassPtrKind::CKclass => {}
ClassPtrKind::CKenum => {}
}
}
}
impl Transform for Hint_ {
fn transform(&mut self, env: &Env, pass: &mut (impl Pass + Clone)) {
let mut in_pass = pass.clone();
Expand All @@ -2378,7 +2394,12 @@ impl Transform for Hint_ {
Hint_::Hlike(ref mut __binding_0) => __binding_0.transform(env, &mut pass.clone()),
Hint_::Hfun(ref mut __binding_0) => __binding_0.transform(env, &mut pass.clone()),
Hint_::Htuple(ref mut __binding_0) => __binding_0.transform(env, &mut pass.clone()),
Hint_::HclassPtr(ref mut __binding_0) => __binding_0.transform(env, &mut pass.clone()),
Hint_::HclassPtr(ref mut __binding_0, ref mut __binding_1) => {
{
__binding_0.transform(env, &mut pass.clone())
}
{ __binding_1.transform(env, &mut pass.clone()) }
}
Hint_::Hshape(ref mut __binding_0) => __binding_0.transform(env, &mut pass.clone()),
Hint_::Haccess(ref mut __binding_0, ref mut __binding_1) => {
{
Expand Down
2 changes: 1 addition & 1 deletion hphp/hack/src/elab/typed_local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ impl TypedLocal {
fn simplify_hint(&self, hint: &mut Hint) {
let Hint(pos, box hint_) = hint;
match hint_ {
Hint_::Hoption(h) | Hint_::Hlike(h) | Hint_::HclassPtr(h) => self.simplify_hint(h),
Hint_::Hoption(h) | Hint_::Hlike(h) | Hint_::HclassPtr(_, h) => self.simplify_hint(h),
Hint_::Htuple(_) => {
// enforce tuples as just vec
*hint_ = Hint_::Happly(
Expand Down
2 changes: 1 addition & 1 deletion hphp/hack/src/hackc/emitter/emit_type_constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ fn hint_to_type_constant_list(
}
}
Hint_::Habstr(_, _)
| Hint_::HclassPtr(_)
| Hint_::HclassPtr(_, _)
| Hint_::Hdynamic
| Hint_::HfunContext(_)
| Hint_::Hmixed
Expand Down
12 changes: 6 additions & 6 deletions hphp/hack/src/hackc/emitter/emit_type_hint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ pub fn fmt_hint(tparams: &[&str], strip_tparams: bool, hint: &Hint) -> Result<St
Htuple(TupleInfo { required, .. }) => format!("({})", fmt_hints(tparams, required)?),
Hlike(t) => format!("~{}", fmt_hint(tparams, false, t)?),
Hsoft(t) => format!("@{}", fmt_hint(tparams, false, t)?),
HclassPtr(_)
HclassPtr(_, _)
| HfunContext(_)
| Hdynamic
| Hintersection(_)
Expand All @@ -175,7 +175,7 @@ fn hint_to_string<'a>(h: &'a Hint_) -> &'a str {
Habstr(_, _)
| Haccess(_, _)
| Happly(_, _)
| HclassPtr(_)
| HclassPtr(_, _)
| Hfun(_)
| HfunContext(_)
| Hlike(_)
Expand Down Expand Up @@ -214,7 +214,7 @@ fn can_be_nullable(hint: &Hint_) -> bool {
id != "\\HH\\dynamic" && id != "\\HH\\nonnull" && id != "\\HH\\mixed"
}
Habstr(_, _)
| HclassPtr(_)
| HclassPtr(_, _)
| HfunContext(_)
| Hintersection(_)
| Hlike(_)
Expand Down Expand Up @@ -317,7 +317,7 @@ fn hint_to_type_constraint(
hint_to_type_constraint(kind, tparams, skipawaitable, hint)?
}
// TODO: should probably just return Result::Err for some of these
HclassPtr(_)
HclassPtr(_, _)
| HfunContext(_)
| Hnonnull
| Hnothing
Expand Down Expand Up @@ -431,7 +431,7 @@ fn param_hint_to_type_info(
Habstr(s, hs) => hs.is_empty() && !tparams.contains(&s.as_str()),
Hprim(_)
| Htuple(_)
| HclassPtr(_)
| HclassPtr(_, _)
| Hshape(_)
| Hrefinement(_, _)
| Hwildcard
Expand Down Expand Up @@ -572,7 +572,7 @@ fn get_flags(tparams: &[&str], flags: TypeConstraintFlags, hint: &Hint_) -> Type
}
Habstr(_, _)
| Happly(_, _)
| HclassPtr(_)
| HclassPtr(_, _)
| Hdynamic
| Hfun(_)
| HfunContext(_)
Expand Down
6 changes: 3 additions & 3 deletions hphp/hack/src/hackc/emitter/reified_generics_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ pub(crate) fn has_reified_type_constraint<'a>(env: &Env<'a>, h: &aast::Hint) ->
})
}
}
Hint_::Hsoft(h) | Hint_::Hlike(h) | Hint_::HclassPtr(h) | Hint_::Hoption(h) => {
Hint_::Hsoft(h) | Hint_::Hlike(h) | Hint_::HclassPtr(_, h) | Hint_::Hoption(h) => {
has_reified_type_constraint(env, h)
}
Hint_::Hprim(_)
Expand Down Expand Up @@ -122,7 +122,7 @@ fn remove_awaitable(aast::Hint(pos, hint): aast::Hint) -> aast::Hint {
| Hint_::Hfun(_)
| Hint_::Haccess(_, _)
| Hint_::Hrefinement(_, _)
| Hint_::HclassPtr(_)
| Hint_::HclassPtr(_, _)
| Hint_::Happly(_, _)
| Hint_::HfunContext(_)
| Hint_::Hvar(_)
Expand Down Expand Up @@ -189,7 +189,7 @@ pub(crate) fn remove_erased_generics<'a>(env: &Env<'a>, h: aast::Hint) -> aast::
}
Hint_::Hsoft(h) => Hint_::Hsoft(rec(env, h)),
Hint_::Hlike(h) => Hint_::Hlike(rec(env, h)),
Hint_::HclassPtr(h) => Hint_::HclassPtr(rec(env, h)),
Hint_::HclassPtr(k, h) => Hint_::HclassPtr(k, rec(env, h)),
Hint_::Hoption(h) => Hint_::Hoption(rec(env, h)),
Hint_::Htuple(TupleInfo { required, extra }) => {
let extra = match extra {
Expand Down
2 changes: 2 additions & 0 deletions hphp/hack/src/naming/naming_special_names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ pub mod classes {

pub const CLASS_NAME: &str = "\\HH\\classname";

pub const ENUM_NAME: &str = "\\HH\\enumname";

pub const TYPE_NAME: &str = "\\HH\\typename";

pub const IDISPOSABLE: &str = "\\IDisposable";
Expand Down
26 changes: 24 additions & 2 deletions hphp/hack/src/oxidized/aast_visitor/node_impl_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// This source code is licensed under the MIT license found in the
// LICENSE file in the "hack" directory of this source tree.
//
// @generated SignedSource<<9082b9e1996be3d1efe1b22a9ce27050>>
// @generated SignedSource<<f9b16cc0200f54dc8df0c1dd98d77b5f>>
//
// To regenerate this file, run:
// hphp/hack/src/oxidized_regen.sh
Expand Down Expand Up @@ -390,6 +390,25 @@ impl<P: Params> Node<P> for ClassId_<P::Ex, P::En> {
}
}
}
impl<P: Params> Node<P> for ClassPtrKind {
fn accept<'node>(
&'node self,
c: &mut P::Context,
v: &mut dyn Visitor<'node, Params = P>,
) -> Result<(), P::Error> {
v.visit_class_ptr_kind(c, self)
}
fn recurse<'node>(
&'node self,
c: &mut P::Context,
v: &mut dyn Visitor<'node, Params = P>,
) -> Result<(), P::Error> {
match self {
ClassPtrKind::CKclass => Ok(()),
ClassPtrKind::CKenum => Ok(()),
}
}
}
impl<P: Params> Node<P> for ClassReq {
fn accept<'node>(
&'node self,
Expand Down Expand Up @@ -1412,7 +1431,10 @@ impl<P: Params> Node<P> for Hint_ {
Hint_::Hlike(a0) => a0.accept(c, v),
Hint_::Hfun(a0) => a0.accept(c, v),
Hint_::Htuple(a0) => a0.accept(c, v),
Hint_::HclassPtr(a0) => a0.accept(c, v),
Hint_::HclassPtr(a0, a1) => {
a0.accept(c, v)?;
a1.accept(c, v)
}
Hint_::Hshape(a0) => a0.accept(c, v),
Hint_::Haccess(a0, a1) => {
a0.accept(c, v)?;
Expand Down
26 changes: 24 additions & 2 deletions hphp/hack/src/oxidized/aast_visitor/node_mut_impl_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// This source code is licensed under the MIT license found in the
// LICENSE file in the "hack" directory of this source tree.
//
// @generated SignedSource<<07a3c9483c37d2d68f66b562ef1bdffc>>
// @generated SignedSource<<7203202959e16b93cba85b61420c6432>>
//
// To regenerate this file, run:
// hphp/hack/src/oxidized_regen.sh
Expand Down Expand Up @@ -390,6 +390,25 @@ impl<P: Params> NodeMut<P> for ClassId_<P::Ex, P::En> {
}
}
}
impl<P: Params> NodeMut<P> for ClassPtrKind {
fn accept<'node>(
&'node mut self,
c: &mut P::Context,
v: &mut dyn VisitorMut<'node, Params = P>,
) -> Result<(), P::Error> {
v.visit_class_ptr_kind(c, self)
}
fn recurse<'node>(
&'node mut self,
c: &mut P::Context,
v: &mut dyn VisitorMut<'node, Params = P>,
) -> Result<(), P::Error> {
match self {
ClassPtrKind::CKclass => Ok(()),
ClassPtrKind::CKenum => Ok(()),
}
}
}
impl<P: Params> NodeMut<P> for ClassReq {
fn accept<'node>(
&'node mut self,
Expand Down Expand Up @@ -1412,7 +1431,10 @@ impl<P: Params> NodeMut<P> for Hint_ {
Hint_::Hlike(a0) => a0.accept(c, v),
Hint_::Hfun(a0) => a0.accept(c, v),
Hint_::Htuple(a0) => a0.accept(c, v),
Hint_::HclassPtr(a0) => a0.accept(c, v),
Hint_::HclassPtr(a0, a1) => {
a0.accept(c, v)?;
a1.accept(c, v)
}
Hint_::Hshape(a0) => a0.accept(c, v),
Hint_::Haccess(a0, a1) => {
a0.accept(c, v)?;
Expand Down
Loading

0 comments on commit 624d056

Please sign in to comment.