Skip to content

Commit

Permalink
[flow] Separately guard against placeholders for conditional types
Browse files Browse the repository at this point in the history
Summary:
Currently, we conveniently guard both placeholders and unresolved inputs for conditional types, because they both return placeholder anyways. However, it's worth noting that they represent very different problems:

1. "placeholder in, placeholder out" is something that should hold regardless of whether we are in implicit instantiation. In practice, it only happens in implicit instantiation since placeholders should never leak beyond that. Doing this helps a later diff, when I will wrap all EvalT computation with fully resolved inputs into an lazy OpenT, which might not be forced under the same environment as before.
2. unresolved tvar input should only happen in implicit instantiation, but in practice they do happen outside, but normally these tvars shouldn't get any new bounds in the future. In the future, guarding these unresolved inputs should happen on the EvalT level, since EvalT behavior is not well defined for unresolved inputs, and it's actually one of the motivation to do LTI.

Therefore, this diff splits the check.

Changelog: [internal]

Reviewed By: panagosg7

Differential Revision: D56023910

fbshipit-source-id: 186d62026ca8984be7056f1323b1e7aa6258fe83
  • Loading branch information
SamChou19815 authored and facebook-github-bot committed Apr 12, 2024
1 parent 5356860 commit 6d9a35d
Showing 1 changed file with 16 additions and 11 deletions.
27 changes: 16 additions & 11 deletions src/typing/implicit_instantiation.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1603,23 +1603,28 @@ module Kit (FlowJs : Flow_common.S) (Instantiation_helper : Flow_js_utils.Instan

let run_conditional cx trace ~use_op ~reason ~tparams ~check_t ~extends_t ~true_t ~false_t =
if
Context.in_implicit_instantiation cx
&& (Tvar_resolver.has_unresolved_tvars_or_placeholders cx check_t
|| Tvar_resolver.has_unresolved_tvars_or_placeholders cx extends_t
|| Tvar_resolver.has_unresolved_tvars_or_placeholders cx true_t
|| Tvar_resolver.has_unresolved_tvars_or_placeholders cx false_t
)
Tvar_resolver.has_placeholders cx check_t
|| Tvar_resolver.has_placeholders cx extends_t
|| Tvar_resolver.has_placeholders cx true_t
|| Tvar_resolver.has_placeholders cx false_t
then (
Debug_js.Verbose.print_if_verbose
cx
[
"Conditional type refuses to evaluate because ";
"we are in implicit instantiation, and we don't have fully resolved inputs";
];
["Conditional type refuses to evaluate because we have placeholders"];
(* Placeholder in, placeholder out *)
Context.mk_placeholder cx reason
) else if
Context.in_implicit_instantiation cx
&& (Tvar_resolver.has_unresolved_tvars cx check_t
|| Tvar_resolver.has_unresolved_tvars cx extends_t
|| Tvar_resolver.has_unresolved_tvars cx true_t
|| Tvar_resolver.has_unresolved_tvars cx false_t
)
then
(* When we are in nested instantiation, we can't meaningfully decide which branch to take,
so we will give up and produce placeholder instead. *)
Context.mk_placeholder cx reason
) else
else
let t =
match
Context.run_in_implicit_instantiation_mode cx (fun () ->
Expand Down

0 comments on commit 6d9a35d

Please sign in to comment.