From 88e865b87d84eed5bd8a6aabae19920936509adf Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Thu, 14 Dec 2023 12:52:50 -0800 Subject: [PATCH] [flow] Fix handling for react element shorthand Summary: Instead of special-casing when we enter a render type we should directly handle TypeAppTs to account for the component syntax shorthand. Changelog: [internal] Reviewed By: SamChou19815 Differential Revision: D52094619 fbshipit-source-id: eec1690e01d5b35db42cb96ddb9f357388da2b00 --- src/typing/ty_normalizer.ml | 36 +++++++++++-------- src/typing/ty_normalizer_env.ml | 4 --- tests/type_at_pos_reactscript/render_types.js | 4 +++ .../type_at_pos_reactscript.exp | 7 +++- 4 files changed, 32 insertions(+), 19 deletions(-) diff --git a/src/typing/ty_normalizer.ml b/src/typing/ty_normalizer.ml index d5a649b87d2..958b28f71bd 100644 --- a/src/typing/ty_normalizer.ml +++ b/src/typing/ty_normalizer.ml @@ -802,10 +802,6 @@ module Make (I : INPUT) : S = struct | _ -> type_app ~env type_ (Some targs)) | DefT (r, InstanceT { super; inst; _ }) -> instance_t ~env r super inst | DefT (_, ClassT t) -> class_t ~env t - | DefT (reason, ReactAbstractComponentT { component_kind = Nominal (_, name); _ }) - when Env.(env.under_render_type) -> - let symbol = Reason_utils.component_symbol env name reason in - return (Ty.Generic (symbol, Ty.ComponentKind, None)) | DefT (_, ReactAbstractComponentT { config; instance; renders; component_kind = _ }) -> let%bind config = type__ ~env config in let%bind instance = type__ ~env instance in @@ -824,9 +820,7 @@ module Make (I : INPUT) : S = struct in return (Ty.Generic (symbol, Ty.ComponentKind, None)) | DefT (_, RendersT (StructuralRenders { renders_variant; renders_structural_type })) -> - let%bind ty = - type_ctor ~env:(Env.set_under_render_type true env) ~cont renders_structural_type - in + let%bind ty = type_ctor ~env ~cont renders_structural_type in let variant = match renders_variant with | T.RendersNormal -> Ty.RendersNormal @@ -1337,7 +1331,15 @@ module Make (I : INPUT) : S = struct | DefT (_, TypeT (_, DefT (r, InstanceT { inst; _ }))) | DefT (_, ClassT (DefT (r, InstanceT { inst; _ }))) -> instance_app ~env r inst tparams targs - | DefT (r, TypeT (kind, _)) -> type_t_app ~env r kind tparams targs + | DefT (r, TypeT (kind, t)) -> + (match (t, targs) with + | (OpaqueT (_, opaque_type), Some (component :: _)) + when Some opaque_type.Type.opaque_id + = Flow_js_utils.builtin_react_element_opaque_id (Env.get_cx env) -> + (match Lookahead.peek (Env.get_cx env) component with + | Lookahead.LowerBounds [t] -> react_element_shorthand ~env r opaque_type targs t + | _ -> type_t_app ~env r kind tparams targs) + | _ -> type_t_app ~env r kind tparams targs) | DefT ( r, ReactAbstractComponentT @@ -1408,6 +1410,17 @@ module Make (I : INPUT) : S = struct | [] -> Ty.Bot (Ty.NoLowerWithUpper Ty.NoUpper) | t :: ts -> Ty.mk_union ~from_bounds:true (t, ts)) + and react_element_shorthand ~env opaque_reason opaque_type targs t = + match t with + | T.(DefT (reason, ReactAbstractComponentT { component_kind = Nominal (_, name); _ })) -> + let symbol = Reason_utils.component_symbol env name reason in + return (Ty.Generic (symbol, Ty.ComponentKind, None)) + | _ -> + let name = opaque_type.Type.opaque_name in + let opaque_symbol = symbol_from_reason env opaque_reason (Reason.OrdinaryName name) in + let%bind targs = optMapM (type__ ~env) targs in + return (generic_talias opaque_symbol targs) + and opaque_t ~env reason opaque_type = let name = opaque_type.Type.opaque_name in let opaque_symbol = symbol_from_reason env reason (Reason.OrdinaryName name) in @@ -1766,12 +1779,7 @@ module Make (I : INPUT) : S = struct } | _ -> env in - let arg_env = - match d with - | T.ReactPromoteRendersRepresentation _ -> Env.set_under_render_type true env - | _ -> env - in - let%bind ty = type__ ~env:arg_env t in + let%bind ty = type__ ~env t in match d with | T.ReactDRO _ -> return ty | T.NonMaybeType -> return (Ty.Utility (Ty.NonMaybeType ty)) diff --git a/src/typing/ty_normalizer_env.ml b/src/typing/ty_normalizer_env.ml index 363a58c82a2..44f253e98a9 100644 --- a/src/typing/ty_normalizer_env.ml +++ b/src/typing/ty_normalizer_env.ml @@ -179,7 +179,6 @@ type t = { or a unique ID of the type alias to make this distinction, but at the moment keeping this information around introduces a small space regression. *) under_type_alias: SymbolSet.t; - under_render_type: bool; (* Detect recursive types *) seen_tvar_ids: ISet.t; seen_eval_ids: Type.EvalIdSet.t; @@ -194,7 +193,6 @@ let init ~options ~genv ~tparams_rev ~imported_names = infer_tparams = []; imported_names; under_type_alias = SymbolSet.empty; - under_render_type = false; seen_tvar_ids = ISet.empty; seen_eval_ids = Type.EvalIdSet.empty; } @@ -223,6 +221,4 @@ let add_typeparam env typeparam = { env with tparams_rev = typeparam :: env.tpar let set_type_alias name e = { e with under_type_alias = SymbolSet.add name e.under_type_alias } -let set_under_render_type b e = { e with under_render_type = b } - let seen_type_alias name e = SymbolSet.mem name e.under_type_alias diff --git a/tests/type_at_pos_reactscript/render_types.js b/tests/type_at_pos_reactscript/render_types.js index 6b3edf3a206..bae660f4f4d 100644 --- a/tests/type_at_pos_reactscript/render_types.js +++ b/tests/type_at_pos_reactscript/render_types.js @@ -20,3 +20,7 @@ type StarRenders = renders* Foo; type RendersElement = renders React$Element; // ^ + +component Poly() { return null } +type PolyElement = renders Poly; +// ^ diff --git a/tests/type_at_pos_reactscript/type_at_pos_reactscript.exp b/tests/type_at_pos_reactscript/type_at_pos_reactscript.exp index df89ce25420..3752512862f 100644 --- a/tests/type_at_pos_reactscript/type_at_pos_reactscript.exp +++ b/tests/type_at_pos_reactscript/type_at_pos_reactscript.exp @@ -88,9 +88,14 @@ render_types.js:18:6,18:16 render_types.js:21:6 Flags: -type RendersElement = renders React$Element +type RendersElement = renders Foo render_types.js:21:6,21:19 +render_types.js:25:6 +Flags: +type PolyElement = renders Poly +render_types.js:25:6,25:16 + render_types.js:8:7 = { "types":{ "unevaluated":{