Skip to content

Commit

Permalink
[flow] Fix handling for react element shorthand
Browse files Browse the repository at this point in the history
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
  • Loading branch information
jbrown215 authored and facebook-github-bot committed Dec 14, 2023
1 parent a44f263 commit 88e865b
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 19 deletions.
36 changes: 22 additions & 14 deletions src/typing/ty_normalizer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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))
Expand Down
4 changes: 0 additions & 4 deletions src/typing/ty_normalizer_env.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}
Expand Down Expand Up @@ -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
4 changes: 4 additions & 0 deletions tests/type_at_pos_reactscript/render_types.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,7 @@ type StarRenders = renders* Foo;

type RendersElement = renders React$Element<typeof Foo>;
// ^

component Poly<T>() { return null }
type PolyElement = renders Poly<number>;
// ^
7 changes: 6 additions & 1 deletion tests/type_at_pos_reactscript/type_at_pos_reactscript.exp
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,14 @@ render_types.js:18:6,18:16

render_types.js:21:6
Flags:
type RendersElement = renders React$Element<Foo>
type RendersElement = renders Foo
render_types.js:21:6,21:19

render_types.js:25:6
Flags:
type PolyElement = renders Poly<number>
render_types.js:25:6,25:16

render_types.js:8:7 = {
"types":{
"unevaluated":{
Expand Down

0 comments on commit 88e865b

Please sign in to comment.