|
@@ -409,43 +409,45 @@ module Pattern = struct
|
|
|
in
|
|
|
pattern t
|
|
|
| EObjectDecl fl ->
|
|
|
- let rec known_fields t = match follow t with
|
|
|
+ let known_fields = ref [] in
|
|
|
+ let collect_field cf t filter = match filter with
|
|
|
+ | Some sl when not (List.mem cf.cf_name sl) -> ()
|
|
|
+ | _ -> known_fields := (cf,t) :: (List.filter (fun (cf',_) -> cf'.cf_name <> cf.cf_name) !known_fields)
|
|
|
+ in
|
|
|
+ let rec collect_fields t filter = match follow t with
|
|
|
| TAnon an ->
|
|
|
- PMap.fold (fun cf acc -> (cf,cf.cf_type) :: acc) an.a_fields []
|
|
|
+ PMap.iter (fun _ cf -> collect_field cf cf.cf_type filter) an.a_fields
|
|
|
| TInst(c,tl) ->
|
|
|
- let rec loop fields c tl =
|
|
|
- let fields = List.fold_left (fun acc cf ->
|
|
|
- if Typecore.can_access ctx c cf false then (cf,apply_params c.cl_params tl cf.cf_type) :: acc
|
|
|
- else acc
|
|
|
- ) fields c.cl_ordered_fields in
|
|
|
- match c.cl_super with
|
|
|
- | None -> fields
|
|
|
- | Some (csup,tlsup) -> loop fields csup (List.map (apply_params c.cl_params tl) tlsup)
|
|
|
+ let rec loop c tl =
|
|
|
+ (match c.cl_super with
|
|
|
+ | Some (csup,tlsup) -> loop csup (List.map (apply_params c.cl_params tl) tlsup)
|
|
|
+ | _ -> ());
|
|
|
+ List.iter (fun cf ->
|
|
|
+ if Typecore.can_access ctx c cf false then
|
|
|
+ collect_field cf (apply_params c.cl_params tl cf.cf_type) filter
|
|
|
+ ) c.cl_ordered_fields
|
|
|
in
|
|
|
- loop [] c tl
|
|
|
+ loop c tl
|
|
|
| TAbstract({a_impl = Some c} as a,tl) ->
|
|
|
- let fields = try
|
|
|
+ (if Meta.has Meta.Forward a.a_meta then
|
|
|
let _,el,_ = Meta.get Meta.Forward a.a_meta in
|
|
|
let sl = ExtList.List.filter_map (fun e -> match fst e with
|
|
|
| EConst(Ident s) -> Some s
|
|
|
| _ -> None
|
|
|
) el in
|
|
|
- let fields = known_fields (Abstract.get_underlying_type a tl) in
|
|
|
- if sl = [] then fields else List.filter (fun (cf,t) -> List.mem cf.cf_name sl) fields
|
|
|
- with Not_found ->
|
|
|
- []
|
|
|
- in
|
|
|
- let fields = List.fold_left (fun acc cf ->
|
|
|
+ let filter = if sl = [] then filter else Some (match filter with
|
|
|
+ | Some fsl -> List.filter (fun s -> List.mem s fsl) sl
|
|
|
+ | None -> sl
|
|
|
+ ) in
|
|
|
+ collect_fields (Abstract.get_underlying_type a tl) filter);
|
|
|
+ List.iter (fun cf ->
|
|
|
if Meta.has Meta.Impl cf.cf_meta then
|
|
|
- (cf,apply_params a.a_params tl cf.cf_type) :: acc
|
|
|
- else
|
|
|
- acc
|
|
|
- ) fields c.cl_ordered_statics in
|
|
|
- fields
|
|
|
+ collect_field cf (apply_params a.a_params tl cf.cf_type) filter
|
|
|
+ ) c.cl_ordered_statics;
|
|
|
| _ ->
|
|
|
error (Printf.sprintf "Cannot field-match against %s" (s_type t)) (pos e)
|
|
|
in
|
|
|
- let known_fields = known_fields t in
|
|
|
+ collect_fields t None;
|
|
|
let is_matchable cf =
|
|
|
match cf.cf_kind with Method _ -> false | _ -> true
|
|
|
in
|
|
@@ -459,7 +461,7 @@ module Pattern = struct
|
|
|
(PatAny,cf.cf_pos) :: patterns,cf.cf_name :: fields
|
|
|
else
|
|
|
patterns,fields
|
|
|
- ) ([],[]) known_fields in
|
|
|
+ ) ([],[]) !known_fields in
|
|
|
List.iter (fun ((s,_,_),e) -> if not (List.mem s fields) then error (Printf.sprintf "%s has no field %s" (s_type t) s) (pos e)) fl;
|
|
|
PatConstructor(con_fields fields (pos e),patterns)
|
|
|
| EBinop(OpOr,e1,e2) ->
|
|
@@ -1698,4 +1700,4 @@ module Match = struct
|
|
|
type_expr ctx e WithType.value
|
|
|
| _ ->
|
|
|
match_expr ctx e cases def with_type postfix_match p
|
|
|
-end
|
|
|
+end
|