@@ -591,6 +591,62 @@ let build_or_pat env loc lid =
591591 pat pats in
592592 (path, rp { r with pat_loc = loc },ty)
593593
594+ let build_or_pat_for_variant_spread env loc lid expected_ty =
595+ let path, decl = Typetexp. find_type env lid.loc lid.txt in
596+ match decl with
597+ | {type_kind = Type_variant constructors } -> (
598+ (* TODO: Probably problematic that we don't account for type params here? *)
599+ let ty = newty (Tconstr (path, [] , ref Mnil )) in
600+ let gloc = {loc with Location. loc_ghost = true } in
601+ let pats =
602+ constructors
603+ |> List. map
604+ (fun (c : Types.constructor_declaration ) : Typedtree. pattern ->
605+ let lid = Longident. Lident (Ident. name c.cd_id) in
606+ {
607+ pat_desc =
608+ Tpat_construct
609+ ( {loc = Location. none; txt = lid},
610+ Env. lookup_constructor ~loc: c.cd_loc lid env,
611+ match c.cd_args with
612+ | Cstr_tuple [] -> []
613+ | _ ->
614+ [
615+ {
616+ pat_desc = Tpat_any ;
617+ pat_loc = Location. none;
618+ pat_env = env;
619+ pat_type = expected_ty;
620+ pat_extra = [] ;
621+ pat_attributes = [] ;
622+ };
623+ ] );
624+ pat_loc = Location. none;
625+ pat_extra = [] ;
626+ pat_type = expected_ty;
627+ pat_env = env;
628+ pat_attributes = [] ;
629+ })
630+ in
631+ match pats with
632+ | [] -> raise (Error (lid.loc, env, Not_a_variant_type lid.txt))
633+ | pat :: pats ->
634+ let r =
635+ List. fold_left
636+ (fun pat pat0 ->
637+ {
638+ Typedtree. pat_desc = Tpat_or (pat0, pat, None );
639+ pat_extra = [] ;
640+ pat_loc = gloc;
641+ pat_env = env;
642+ pat_type = expected_ty;
643+ pat_attributes = [] ;
644+ })
645+ pat pats
646+ in
647+ (path, rp {r with pat_loc = loc}, ty))
648+ | _ -> raise (Error (lid.loc, env, Not_a_variant_type lid.txt))
649+
594650(* Type paths *)
595651
596652let rec expand_path env p =
@@ -1111,6 +1167,18 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env
11111167 }
11121168 | _ -> assert false
11131169 end
1170+ | Ppat_alias ({ppat_desc =Ppat_type lid ; ppat_attributes} , name ) when Variant_coercion. has_res_pat_variant_spread_attribute ppat_attributes ->
1171+ let (_, p, ty) = build_or_pat_for_variant_spread ! env loc lid expected_ty in
1172+ Ctype. subtype ! env ty expected_ty () ;
1173+ assert (constrs = None );
1174+
1175+ let id = enter_variable ~is_as_variable: true loc name ty in
1176+ rp k {
1177+ pat_desc = Tpat_alias (p, id, name);
1178+ pat_loc = loc; pat_extra= [] ;
1179+ pat_type = expected_ty;
1180+ pat_attributes = sp.ppat_attributes;
1181+ pat_env = ! env }
11141182 | Ppat_alias (sq , name ) ->
11151183 assert (constrs = None );
11161184 type_pat sq expected_ty (fun q ->
@@ -1435,6 +1503,12 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env
14351503 | _ -> {p with pat_type = ty;
14361504 pat_extra = extra :: p .pat_extra}
14371505 in k p)
1506+ | Ppat_type lid when Variant_coercion. has_res_pat_variant_spread_attribute sp.ppat_attributes ->
1507+ let (path, p, ty) = build_or_pat_for_variant_spread ! env loc lid expected_ty in
1508+ Ctype. subtype ! env ty expected_ty () ;
1509+ assert (constrs = None );
1510+ k { p with pat_extra =
1511+ (Tpat_type (path, lid), loc, sp.ppat_attributes) :: p.pat_extra }
14381512 | Ppat_type lid ->
14391513 let (path, p,ty) = build_or_pat ! env loc lid in
14401514 unify_pat_types loc ! env ty expected_ty;
0 commit comments