@@ -58,7 +58,7 @@ type context = {
5858type result =
5959 | Missing of (unit -> unit )
6060 | Exact of locl_ty
61- | Abstract of string * string list * locl_ty option
61+ | Abstract of string * string list * TySet .t
6262
6363let make_reason env id root r =
6464 Reason. Rtypeconst (r, id, Typing_print. error env root, get_reason root)
@@ -158,13 +158,13 @@ let create_root_from_type_constant ctx env root (_class_pos, class_name) class_
158158 if Cls. final class_ || Option. is_none ctx.base then
159159 (env, Exact ty)
160160 else
161- (env, make_abstract env (Some ty))
161+ (env, make_abstract env (TySet. singleton ty))
162162 (* Abstract type constants with constraint *)
163163 | { ttc_constraint = Some cstr ; _ } ->
164164 let (env, cstr) = Phase. localize ~ety_env env cstr in
165- (env, make_abstract env (Some cstr))
165+ (env, make_abstract env (TySet. singleton cstr))
166166 (* Abstract type constant without constraint. *)
167- | _ -> (env, make_abstract env None )))
167+ | _ -> (env, make_abstract env TySet. empty )))
168168
169169(* Cheap intersection operation. Do not call Typing_intersection.intersect
170170 * as this calls into subtype which in turn calls into expand_with_env below
@@ -196,34 +196,15 @@ let rec union_results err rl =
196196 | r1 :: rl ->
197197 let r2 = union_results err rl in
198198
199- (* Union is defined iff both are defined *)
199+ (* Union is defined iff both are defined concretely *)
200200 (match (r1, r2) with
201201 | (Missing err, _)
202202 | (_ , Missing err ) ->
203203 Missing err
204204 (* In essence, this says (C | D)::TP = (C::TP) | (D::TP) *)
205205 | (Exact ty1 , Exact ty2 ) -> Exact (union ty1 ty2)
206- | (Abstract (id1, ids1, tyopt1), Abstract (id2, ids2, tyopt2))
207- when String. equal id1 id2 && List. equal String. equal ids1 ids2 ->
208- (* Take the union of the bounds on abstract type constants *)
209- let tyopt =
210- match (tyopt1, tyopt2) with
211- | (None , _)
212- | (_ , None) ->
213- None
214- | (Some ty1 , Some ty2 ) -> Some (union ty1 ty2)
215- in
216- Abstract (id1, ids1, tyopt)
217- (* If paths don't match, regard the type constant as missing *)
218- | (Abstract _ , Abstract _ ) -> Missing err
219- | (Abstract (id, ids, tyopt), Exact ty)
220- | (Exact ty , Abstract (id , ids , tyopt )) ->
221- Abstract
222- ( id,
223- ids,
224- match tyopt with
225- | None -> None
226- | Some bound -> Some (union ty bound) ))
206+ (* We don't support projecting through any other kind of union *)
207+ | _ -> Missing err)
227208
228209(* Given the results of projecting a type constant from types t1, ..., tn,
229210 * determine the result of projecting a type constant from type (t1 & ... & tn).
@@ -241,27 +222,9 @@ let rec intersect_results err rl =
241222 r
242223 (* In essence, we're saying (C & D)::TP = (C::TP) & (D::TP) *)
243224 | (Exact ty1 , Exact ty2 ) -> Exact (intersect ty1 ty2)
244- | (Abstract (id1, ids1, tyopt1), Abstract (id2, ids2, tyopt2))
245- when String. equal id1 id2 && List. equal String. equal ids1 ids2 ->
246- (* For abstract type constants, take the intersection of the bounds *)
247- let tyopt =
248- match (tyopt1, tyopt2) with
249- | (None, None) -> None
250- | (Some ty, None )
251- | (None, Some ty ) ->
252- Some ty
253- | (Some ty1 , Some ty2 ) -> Some (intersect ty1 ty2)
254- in
255- Abstract (id1, ids1, tyopt)
256- (* The strategy here is to take the last result. It is necessary for
257- poor reasons, unfortunately. Because `type_of_result` bogusly uses
258- `Env.add_upper_bound_global`, local type refinement information can
259- leak outside its scope. To remain consistent with the previous
260- version of the type access algorithm wrt this bug, we pick the last
261- result. See T59317869.
262- The test test/typecheck/tconst/type_refinement_stress.php monitors
263- the situation here. *)
264- | (Abstract _ , Abstract _ ) -> r2
225+ (* Here, we merge the bounds on abstract type constants. Effectively this is intersection. *)
226+ | (Abstract (id1 , ids1 , tyl1 ), Abstract (_id2 , _ids2 , tyl2 )) ->
227+ Abstract (id1, ids1, TySet. union tyl1 tyl2)
265228 (* Exact type overrides abstract type: the bound on abstract type will be checked
266229 * against the exact type at implementation site. *)
267230 | (Abstract _, Exact ty)
@@ -280,9 +243,12 @@ let rec type_of_result ~ignore_errors ctx env root res =
280243 let reason = make_reason env id root Reason. Rnone in
281244 let ty = MakeType. generic reason generic_name in
282245 let env =
283- Option. fold bnd ~init: env ~f: (fun env bnd ->
246+ TySet. fold
247+ (fun bnd env ->
284248 (* TODO(T59317869): play well with flow sensitivity *)
285249 Env. add_upper_bound_global env generic_name bnd)
250+ bnd
251+ env
286252 in
287253 (env, ty)
288254 in
@@ -291,7 +257,7 @@ let rec type_of_result ~ignore_errors ctx env root res =
291257 | Abstract (name , name' :: namel , bnd ) ->
292258 let res' = Abstract (name', namel, bnd) in
293259 let (env, ty) = type_of_result ~ignore_errors ctx env root res' in
294- type_with_bound env false name (Some ty)
260+ type_with_bound env false name (TySet. singleton ty)
295261 | Abstract (name , [] , bnd ) ->
296262 type_with_bound env ctx.abstract_as_tyvar name bnd
297263 | Missing err ->
0 commit comments