Skip to content

Commit

Permalink
Trait names are not Enforceable
Browse files Browse the repository at this point in the history
Summary: Hack considered trait names as enforceable and allowed passing them explicitly to enforceable reified generics.  This diff makes trait names non-enforceable.

Reviewed By: madgen

Differential Revision: D57335063

fbshipit-source-id: ca988f4c53fb5e4b67207a61cb1dbd92c3d1c03b
  • Loading branch information
Francesco Zappa Nardelli authored and facebook-github-bot committed May 18, 2024
1 parent 0bd9816 commit 9001bd2
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 57 deletions.
93 changes: 51 additions & 42 deletions hphp/hack/src/typing/typing_enforceable_hint.ml
Original file line number Diff line number Diff line change
Expand Up @@ -70,50 +70,59 @@ let validator =
method! on_class acc r cls tyl =
match Env.get_class acc.Type_validator.env (snd cls) with
| Decl_entry.Found tc ->
let tparams = Cls.tparams tc in
begin
match tyl with
| [] -> acc
(* this case should really be handled by the fold2,
but we still allow class hints without args in certain places *)
| targs ->
List.Or_unequal_lengths.(
begin
match
List.fold2 ~init:acc targs tparams ~f:(fun acc targ tparam ->
let inside_reified_class_generic_position =
acc.Type_validator.inside_reified_class_generic_position
in
if this#is_wildcard targ then begin
if inside_reified_class_generic_position then
this#invalid
acc
r
"a reified type containing a wildcard (`_`)"
else
(match Cls.kind tc with
| Ast_defs.Ctrait -> this#invalid acc r "a trait name"
| _ ->
let tparams = Cls.tparams tc in
begin
match tyl with
| [] -> acc
(* this case should really be handled by the fold2,
but we still allow class hints without args in certain places *)
| targs ->
List.Or_unequal_lengths.(
begin
match
List.fold2
~init:acc
targs
tparams
~f:(fun acc targ tparam ->
let inside_reified_class_generic_position =
acc
end else if
Aast.(equal_reify_kind tparam.tp_reified Reified)
then
this#on_type
{
acc with
Type_validator.inside_reified_class_generic_position =
true;
}
targ
else if inside_reified_class_generic_position then
this#on_type acc targ
else
let error_message =
"a type with an erased generic type argument"
.Type_validator
.inside_reified_class_generic_position
in
this#invalid acc r error_message)
with
| Ok new_acc -> new_acc
| Unequal_lengths -> acc (* arity error elsewhere *)
end)
end
if this#is_wildcard targ then begin
if inside_reified_class_generic_position then
this#invalid
acc
r
"a reified type containing a wildcard (`_`)"
else
acc
end else if
Aast.(equal_reify_kind tparam.tp_reified Reified)
then
this#on_type
{
acc with
Type_validator
.inside_reified_class_generic_position = true;
}
targ
else if inside_reified_class_generic_position then
this#on_type acc targ
else
let error_message =
"a type with an erased generic type argument"
in
this#invalid acc r error_message)
with
| Ok new_acc -> new_acc
| Unequal_lengths -> acc (* arity error elsewhere *)
end)
end)
| Decl_entry.DoesNotExist
| Decl_entry.NotYetAvailable ->
acc
Expand Down
4 changes: 4 additions & 0 deletions hphp/hack/test/typecheck/as_expression/trait.php.exp
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,7 @@ ERROR: File "trait.php", line 6, characters 9-12:
`TFoo` is uninstantiable (Typing[4002])
File "trait.php", line 3, characters 7-10:
Declaration is here
ERROR: File "trait.php", line 6, characters 9-12:
Invalid `as` expression hint (Typing[4195])
File "trait.php", line 6, characters 9-12:
The `as` operator cannot be used with a trait name
4 changes: 4 additions & 0 deletions hphp/hack/test/typecheck/instanceof/trait_instanceof.php.exp
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,7 @@ ERROR: File "trait_instanceof.php", line 10, characters 16-16:
`X` is uninstantiable (Typing[4002])
File "trait_instanceof.php", line 3, characters 7-7:
Declaration is here
ERROR: File "trait_instanceof.php", line 10, characters 16-16:
Invalid `is` expression hint (Typing[4195])
File "trait_instanceof.php", line 10, characters 16-16:
The `is` operator cannot be used with a trait name
4 changes: 4 additions & 0 deletions hphp/hack/test/typecheck/is_expression/trait.php.exp
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,7 @@ ERROR: File "trait.php", line 6, characters 16-19:
`TFoo` is uninstantiable (Typing[4002])
File "trait.php", line 3, characters 7-10:
Declaration is here
ERROR: File "trait.php", line 6, characters 16-19:
Invalid `is` expression hint (Typing[4195])
File "trait.php", line 6, characters 16-19:
The `is` operator cannot be used with a trait name
14 changes: 14 additions & 0 deletions hphp/hack/test/typecheck/trait_not_enforceable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?hh

trait FooTrait {}

class C{}

function foo<<<__Enforceable>> reify T>(mixed $in): void {
$in as T;
}

function test(): void {
foo<FooTrait>(42);
foo<C>(42);
}
6 changes: 6 additions & 0 deletions hphp/hack/test/typecheck/trait_not_enforceable.php.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
ERROR: File "trait_not_enforceable.php", line 12, characters 7-14:
Invalid type (Typing[4302])
File "trait_not_enforceable.php", line 7, characters 38-38:
Type parameter `T` was declared `__Enforceable` here
File "trait_not_enforceable.php", line 12, characters 7-14:
This type is not enforceable because it has a trait name
14 changes: 0 additions & 14 deletions hphp/hack/test/typecheck/typehole/T67202194.php

This file was deleted.

1 change: 0 additions & 1 deletion hphp/hack/test/typecheck/typehole/T67202194.php.exp

This file was deleted.

0 comments on commit 9001bd2

Please sign in to comment.