A newtype is a subtype of mixed
commit59fe6772520c8813030a571fbb4ba0037b05822d
authorSasha Manzyuk <manzyuk@fb.com>
Wed, 1 Aug 2018 14:32:06 +0000 (1 07:32 -0700)
committerHhvm Bot <hhvm-bot@users.noreply.github.com>
Wed, 1 Aug 2018 14:42:58 +0000 (1 07:42 -0700)
tree52eed50dc8ae6b1c52258d77734a992f57d4665b
parent8c361f6866785b39b6b822ad4b75363ae607aa1a
A newtype is a subtype of mixed

Summary:
Checking if a type is a subtype of `mixed = ?nonnull` is actually trickier than you think.  Checking if the supertype matches `(_, Toption (_, Tnonnull))` is not enough because there may be other equivalent ways to express `mixed` that are syntactically different from `?nonnull`.  E.g., `?T` where `T` is constrained using `super nonnull`.

To solve this issue for newtypes, we can treat an unconstrained newtype as one that has an implicit upper bound `?nonnull` (i.e., as if it was explicitly constrained using `as mixed`).  Checking `N <: ?t_super` where `N` is a newtype defined as `newtype N as t_upper = t;` works by trying two choices: first we try to satisfy `N < t_super` and if that fails we try to satisfy `t_upper <: ?t_super`.  By adding `?nonnull` as an implicit upper bound to a fully opaque newtype `N` when checking `N <: ?t_super`, we create a choice between `N <: t_super` and `?nonnull <: ?t_super` (equivalent to `nonnull <: t_super`).  This allows us to type-check more code.

Reviewed By: andrewjkennedy

Differential Revision: D9028981

fbshipit-source-id: 859763d3d43a4617885dc130f852c412514969d5
hphp/hack/src/decl/decl_pos_utils.ml
hphp/hack/src/typing/typing_reason.ml
hphp/hack/src/typing/typing_subtype.ml
hphp/hack/test/typecheck/newtype_subtype_mixed_bad.php [new file with mode: 0644]
hphp/hack/test/typecheck/newtype_subtype_mixed_bad.php.exp [new file with mode: 0644]
hphp/hack/test/typecheck/newtype_subtype_mixed_bad.php.no_format [new file with mode: 0644]
hphp/hack/test/typecheck/newtype_subtype_mixed_good.php [new file with mode: 0644]
hphp/hack/test/typecheck/newtype_subtype_mixed_good.php.exp [new file with mode: 0644]
hphp/hack/test/typecheck/newtype_subtype_mixed_good.php.no_format [new file with mode: 0644]