@@ -211,9 +211,20 @@ class virtual ['a] type_subst_base =
211211 Context. make_export_map cx exps'
212212 end
213213
214+ module Purpose = struct
215+ type t =
216+ | Normal
217+ (* In generic conditional type, we have a step to replace all GenericT with any, to see whether
218+ * the check will still fail (so that we can always take the false branch).
219+ * During the substitution, we might encounter `Subst_name.Synthetic`. We shouldn't crash
220+ * over there. Instead, we should keep them as is. *)
221+ | ConditionalTypeAnySubst
222+ end
223+
214224let substituter =
215225 object (self )
216- inherit [replacement Subst_name.Map. t * bool * bool * use_op option ] type_subst_base as super
226+ inherit
227+ [replacement Subst_name.Map. t * bool * bool * Purpose. t * use_op option ] type_subst_base as super
217228
218229 val mutable change_id = false
219230
@@ -223,14 +234,17 @@ let substituter =
223234 val mutable obj_reachable_targs = None
224235
225236 method! type_ cx map_cx t =
226- let (map, force, placeholder_no_infer, use_op) = map_cx in
237+ let (map, force, placeholder_no_infer, purpose, use_op) = map_cx in
227238 if Subst_name.Map. is_empty map then
228239 t
229240 else
230241 let t_out =
231242 match t with
232243 | GenericT { name = Subst_name. Synthetic { name; op_kind; ts = ids } ; reason; _ } ->
233- if Base.List. exists ~f: (fun name -> Subst_name.Map. mem name map) ids then
244+ if
245+ purpose = Purpose. Normal
246+ && Base.List. exists ~f: (fun name -> Subst_name.Map. mem name map) ids
247+ then
234248 failwith
235249 (Utils_js. spf
236250 " Cannot substitute through synthetic name %s(kind=%s) at %s."
@@ -272,14 +286,17 @@ let substituter =
272286 Nel. fold_left
273287 (fun (xs , map , changed ) typeparam ->
274288 let bound =
275- self#type_ cx (map, force, placeholder_no_infer, use_op) typeparam.Type. bound
289+ self#type_
290+ cx
291+ (map, force, placeholder_no_infer, purpose, use_op)
292+ typeparam.Type. bound
276293 in
277294 let default =
278295 match typeparam.default with
279296 | None -> None
280297 | Some default ->
281298 let default_ =
282- self#type_ cx (map, force, placeholder_no_infer, use_op) default
299+ self#type_ cx (map, force, placeholder_no_infer, purpose, use_op) default
283300 in
284301 if default_ == default then
285302 typeparam.default
@@ -296,7 +313,7 @@ let substituter =
296313 in
297314 let xs = xs |> List. rev |> Nel. of_list in
298315 let xs = Base.Option. value_exn xs in
299- let inner_ = self#type_ cx (map, false , placeholder_no_infer, None ) inner in
316+ let inner_ = self#type_ cx (map, false , placeholder_no_infer, purpose, None ) inner in
300317 let changed = changed || inner_ != inner in
301318 let id =
302319 if change_id then
@@ -311,7 +328,9 @@ let substituter =
311328 t
312329 | ThisInstanceT (r , this , i , this_name ) ->
313330 let (name, map) = avoid_capture map this_name in
314- let this_ = self#instance_type cx (map, force, placeholder_no_infer, use_op) this in
331+ let this_ =
332+ self#instance_type cx (map, force, placeholder_no_infer, purpose, use_op) this
333+ in
315334 if this_ == this && name == this_name then
316335 t
317336 else
@@ -352,10 +371,10 @@ let substituter =
352371 mod_reason_of_t (Reason. replace_desc_reason desc) t_out
353372 | _ -> t_out
354373
355- method! predicate cx (map, force, placeholder_no_infer, use_op) p =
374+ method! predicate cx map_cx p =
356375 match p with
357- | LatentP _ -> super#predicate cx (map, force, placeholder_no_infer, use_op) p
358- | LatentThisP _ -> super#predicate cx (map, force, placeholder_no_infer, use_op) p
376+ | LatentP _ -> super#predicate cx map_cx p
377+ | LatentThisP _ -> super#predicate cx map_cx p
359378 | p -> p
360379
361380 method! obj_type cx map_cx t =
@@ -385,27 +404,29 @@ let substituter =
385404 (Some name, map)
386405
387406 method! destructor cx map_cx t =
388- let (map, _, placeholder_no_infer, _) = map_cx in
407+ let (map, _, placeholder_no_infer, purpose, _) = map_cx in
389408 match t with
390409 | ConditionalType { distributive_tparam_name; infer_tparams; extends_t; true_t; false_t } ->
391410 let (distributive_tparam_name, map) =
392411 self#distributive_tparam_name distributive_tparam_name map
393412 in
394- let false_t' = self#type_ cx (map, false , placeholder_no_infer, None ) false_t in
413+ let false_t' = self#type_ cx (map, false , placeholder_no_infer, purpose, None ) false_t in
395414 let (tparams_rev, map, changed) =
396415 Base.List. fold
397416 infer_tparams
398417 ~init: ([] , map, false )
399418 ~f: (fun (xs , map , changed ) typeparam ->
400419 let bound =
401- self#type_ cx (map, false , placeholder_no_infer, None ) typeparam.Type. bound
420+ self#type_ cx (map, false , placeholder_no_infer, purpose, None ) typeparam.Type. bound
402421 in
403422 let (name, map) = avoid_capture map typeparam.name in
404423 ({ typeparam with bound; name } :: xs, map, changed || bound != typeparam.bound)
405424 )
406425 in
407- let extends_t' = self#type_ cx (map, false , placeholder_no_infer, None ) extends_t in
408- let true_t' = self#type_ cx (map, false , placeholder_no_infer, None ) true_t in
426+ let extends_t' =
427+ self#type_ cx (map, false , placeholder_no_infer, purpose, None ) extends_t
428+ in
429+ let true_t' = self#type_ cx (map, false , placeholder_no_infer, purpose, None ) true_t in
409430 if changed || extends_t != extends_t' || true_t != true_t' || false_t != false_t' then
410431 ConditionalType
411432 {
@@ -421,11 +442,13 @@ let substituter =
421442 let (distributive_tparam_name, map) =
422443 self#distributive_tparam_name distributive_tparam_name map
423444 in
424- let property_type' = self#type_ cx (map, false , placeholder_no_infer, None ) property_type in
445+ let property_type' =
446+ self#type_ cx (map, false , placeholder_no_infer, purpose, None ) property_type
447+ in
425448 let homomorphic' =
426449 match homomorphic with
427450 | SemiHomomorphic t ->
428- let t' = self#type_ cx (map, false , placeholder_no_infer, None ) t in
451+ let t' = self#type_ cx (map, false , placeholder_no_infer, purpose, None ) t in
429452 if t' == t then
430453 homomorphic
431454 else
@@ -451,14 +474,23 @@ let substituter =
451474 method eval_id _cx _map_cx _id = assert false
452475 end
453476
454- let subst cx ?use_op ?(force = true ) ?(placeholder_no_infer = false ) map ty =
477+ let subst
478+ cx ?use_op ?(force = true ) ?(placeholder_no_infer = false ) ?(purpose = Purpose. Normal ) map ty =
455479 let map = Subst_name.Map. map (fun t -> TypeSubst (t, free_var_finder cx t)) map in
456- substituter#type_ cx (map, force, placeholder_no_infer, use_op) ty
480+ substituter#type_ cx (map, force, placeholder_no_infer, purpose, use_op) ty
457481
458- let subst_destructor cx ?use_op ?(force = true ) ?(placeholder_no_infer = false ) map des =
482+ let subst_destructor
483+ cx ?use_op ?(force = true ) ?(placeholder_no_infer = false ) ?(purpose = Purpose. Normal ) map des =
459484 let map = Subst_name.Map. map (fun t -> TypeSubst (t, free_var_finder cx t)) map in
460- substituter#destructor cx (map, force, placeholder_no_infer, use_op) des
461-
462- let subst_instance_type cx ?use_op ?(force = true ) ?(placeholder_no_infer = false ) map instance_t =
485+ substituter#destructor cx (map, force, placeholder_no_infer, purpose, use_op) des
486+
487+ let subst_instance_type
488+ cx
489+ ?use_op
490+ ?(force = true )
491+ ?(placeholder_no_infer = false )
492+ ?(purpose = Purpose. Normal )
493+ map
494+ instance_t =
463495 let map = Subst_name.Map. map (fun t -> TypeSubst (t, free_var_finder cx t)) map in
464- substituter#instance_type cx (map, force, placeholder_no_infer, use_op) instance_t
496+ substituter#instance_type cx (map, force, placeholder_no_infer, purpose, use_op) instance_t
0 commit comments