Skip to content

Commit

Permalink
Throw error when cannot resolve first argument's type in `type_struct…
Browse files Browse the repository at this point in the history
…ure`

Summary:
The following fatals in HHVM and is not caught by Hack.

```
<?hh

type MyCoolType = shape(
  'a' => int,
  ...
);

<<__EntryPoint>>
function main(): void {
    PHP\var_dump(type_structure(MyCoolType::class, 'TUhOh'));
}
```

This diff makes Hack throw an error when we can't properly resolve the type of the first argument to `type_structure`. Previously, we were typing the result of this to be `Tany` and not reporting an error.

We should not allow type alias's here at all in part because we cannot support the type alias resolution at HackC time and HHVM does not support resolving type aliases here.

Reviewed By: Wilfred

Differential Revision: D39483470

fbshipit-source-id: 7bced5c09f5ac0210c752774a566a70d365dce42
  • Loading branch information
Thomas Jiang authored and facebook-github-bot committed Sep 20, 2022
1 parent 7323b1c commit 7481994
Show file tree
Hide file tree
Showing 10 changed files with 62 additions and 13 deletions.
17 changes: 9 additions & 8 deletions hphp/hack/src/errors/typing_error.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2058,7 +2058,10 @@ module Primary = struct
}
| Assign_during_case of Pos.t
| Invalid_classname of Pos.t
| Illegal_type_structure of Pos.t
| Illegal_type_structure of {
pos: Pos.t;
msg: string;
}
| Illegal_typeconst_direct_access of Pos.t
| Wrong_expression_kind_attribute of {
pos: Pos.t;
Expand Down Expand Up @@ -3860,17 +3863,15 @@ module Primary = struct
lazy [],
[] )

let illegal_type_structure pos =
let illegal_type_structure pos msg =
let claim =
lazy
(let errmsg = "second argument is not a string" in
let msg =
(let msg =
"The two arguments to `type_structure()` must be:"
^ "\n - first: `ValidClassname::class` or an object of that class"
^ "\n - second: a single-quoted string literal containing the name"
^ " of a type constant of that class"
^ "\n"
^ errmsg
^ " of a type constant of that class\n"
^ msg
in
(pos, msg))
in
Expand Down Expand Up @@ -5796,7 +5797,7 @@ module Primary = struct
local_variable_modified_twice pos pos_modifieds
| Assign_during_case pos -> assign_during_case pos
| Invalid_classname pos -> invalid_classname pos
| Illegal_type_structure pos -> illegal_type_structure pos
| Illegal_type_structure { pos; msg } -> illegal_type_structure pos msg
| Illegal_typeconst_direct_access pos -> illegal_typeconst_direct_access pos
| Wrong_expression_kind_attribute
{
Expand Down
5 changes: 4 additions & 1 deletion hphp/hack/src/errors/typing_error.mli
Original file line number Diff line number Diff line change
Expand Up @@ -803,7 +803,10 @@ module Primary : sig
}
| Assign_during_case of Pos.t
| Invalid_classname of Pos.t
| Illegal_type_structure of Pos.t
| Illegal_type_structure of {
pos: Pos.t;
msg: string;
}
| Illegal_typeconst_direct_access of Pos.t
| Wrong_expression_kind_attribute of {
pos: Pos.t;
Expand Down
15 changes: 14 additions & 1 deletion hphp/hack/src/typing/typing.ml
Original file line number Diff line number Diff line change
Expand Up @@ -6956,10 +6956,23 @@ and dispatch_call
((), p1, CIexpr e1_)
in
let result = class_const ~incl_tc:true env p (cid, (p, cst)) in
let () =
match result with
| (_, (ty, _, _), _) when Typing_utils.is_any env ty ->
Errors.add_typing_error
Typing_error.(
primary
@@ Primary.Illegal_type_structure
{ pos; msg = "Could not resolve the type constant" })
| _ -> ()
in
(result, should_forget_fakes)
| _ ->
Errors.add_typing_error
Typing_error.(primary @@ Primary.Illegal_type_structure pos);
Typing_error.(
primary
@@ Primary.Illegal_type_structure
{ pos; msg = "Second argument is not a string" });
let result = expr_error env (Reason.Rwitness pos) e in
(result, should_forget_fakes))
| _ -> assert false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ File "pseudofunction_with_signature.php", line 8, characters 15-22:
Unexpected `inout` annotation for argument (Typing[4183])
File "Shapes.hhi", line 40, characters 17-22:
This is a normal parameter (does not have `inout`)
File "pseudofunction_with_signature.php", line 9, characters 3-16:
The two arguments to `type_structure()` must be:
- first: `ValidClassname::class` or an object of that class
- second: a single-quoted string literal containing the name of a type constant of that class
Could not resolve the type constant (Typing[4150])
File "pseudofunction_with_signature.php", line 9, characters 28-30:
No class constant `T` in `dict` (Typing[4090])
File "hackarray.hhi", line 29, characters 22-25:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
File "type_structure4.php", line 4, characters 18-33:
Unbound name: `NonExistentClass` (an object type) (Naming[2049])
File "type_structure4.php", line 4, characters 3-16:
The two arguments to `type_structure()` must be:
- first: `ValidClassname::class` or an object of that class
- second: a single-quoted string literal containing the name of a type constant of that class
Could not resolve the type constant (Typing[4150])
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ File "type_structure5.php", line 6, characters 3-16:
The two arguments to `type_structure()` must be:
- first: `ValidClassname::class` or an object of that class
- second: a single-quoted string literal containing the name of a type constant of that class
second argument is not a string (Typing[4150])
Second argument is not a string (Typing[4150])
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
File "type_structure6.php", line 6, characters 3-16:
The two arguments to `type_structure()` must be:
- first: `ValidClassname::class` or an object of that class
- second: a single-quoted string literal containing the name of a type constant of that class
Could not resolve the type constant (Typing[4150])
File "type_structure6.php", line 6, characters 28-30:
No class constant `T` in `C` (Typing[4090])
File "type_structure6.php", line 3, characters 7-7:
Declaration of `C` is here
File "type_structure6.php", line 3, characters 7-7:
Declaration of `C` is here
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
File "type_structure8.php", line 8, characters 3-16:
The two arguments to `type_structure()` must be:
- first: `ValidClassname::class` or an object of that class
- second: a single-quoted string literal containing the name of a type constant of that class
Could not resolve the type constant (Typing[4150])
File "type_structure8.php", line 8, characters 18-20:
Was expecting a class, but got a string (Typing[4026])
7 changes: 7 additions & 0 deletions hphp/hack/test/typecheck/type_structure_typename.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?hh

type MyTypename = int;

function test(): void {
type_structure(MyTypename::class, 'Nonsense');
}
5 changes: 5 additions & 0 deletions hphp/hack/test/typecheck/type_structure_typename.php.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
File "type_structure_typename.php", line 6, characters 3-16:
The two arguments to `type_structure()` must be:
- first: `ValidClassname::class` or an object of that class
- second: a single-quoted string literal containing the name of a type constant of that class
Could not resolve the type constant (Typing[4150])

0 comments on commit 7481994

Please sign in to comment.