@@ -300,15 +300,15 @@ let select_local env (qs,s) =
300
300
else None
301
301
302
302
(* -------------------------------------------------------------------- *)
303
- let select_pv env side name ue tvi psig =
303
+ let select_pv env side name ue tvi ( psig , retty ) =
304
304
if tvi <> None
305
305
then []
306
306
else
307
307
try
308
308
let pvs = EcEnv.Var. lookup_progvar ?side name env in
309
309
let select (pv ,ty ) =
310
310
let subue = UE. copy ue in
311
- let texpected = EcUnify. tfun_expected subue psig in
311
+ let texpected = EcUnify. tfun_expected subue ?retty psig in
312
312
try
313
313
EcUnify. unify env subue ty texpected;
314
314
[(pv, ty, subue)]
@@ -346,7 +346,7 @@ let gen_select_op
346
346
(env : EcEnv.env )
347
347
(name : EcSymbols.qsymbol )
348
348
(ue : EcUnify.unienv )
349
- (psig : EcTypes.dom )
349
+ (psig : EcTypes.dom * EcTypes.ty option )
350
350
351
351
: OpSelect. gopsel list
352
352
=
@@ -432,7 +432,7 @@ let select_form_op env mode ~forcepv opsc name ue tvi psig =
432
432
(* -------------------------------------------------------------------- *)
433
433
let select_proj env opsc name ue tvi recty =
434
434
let filter = (fun _ op -> EcDecl. is_proj op) in
435
- let ops = EcUnify. select_op ~filter tvi env name ue [recty] in
435
+ let ops = EcUnify. select_op ~filter tvi env name ue ( [recty], None ) in
436
436
let ops = List. map (fun (p , ty , ue , _ ) -> (p, ty, ue)) ops in
437
437
438
438
match ops, opsc with
@@ -1060,7 +1060,7 @@ let transpattern1 env ue (p : EcParsetree.plpattern) =
1060
1060
let fields =
1061
1061
let for1 (name , v ) =
1062
1062
let filter = fun _ op -> EcDecl. is_proj op in
1063
- let fds = EcUnify. select_op ~filter None env (unloc name) ue [] in
1063
+ let fds = EcUnify. select_op ~filter None env (unloc name) ue ( [] , None ) in
1064
1064
match List. ohead fds with
1065
1065
| None ->
1066
1066
let exn = UnknownRecFieldName (unloc name) in
@@ -1200,7 +1200,7 @@ let trans_record env ue (subtt, proj) (loc, b, fields) =
1200
1200
let for1 rf =
1201
1201
let filter = fun _ op -> EcDecl. is_proj op in
1202
1202
let tvi = rf.rf_tvi |> omap (transtvi env ue) in
1203
- let fds = EcUnify. select_op ~filter tvi env (unloc rf.rf_name) ue [] in
1203
+ let fds = EcUnify. select_op ~filter tvi env (unloc rf.rf_name) ue ( [] , None ) in
1204
1204
match List. ohead fds with
1205
1205
| None ->
1206
1206
let exn = UnknownRecFieldName (unloc rf.rf_name) in
@@ -1289,7 +1289,7 @@ let trans_branch ~loc env ue gindty ((pb, body) : ppattern * _) =
1289
1289
let filter = fun _ op -> EcDecl. is_ctor op in
1290
1290
let PPApp ((cname, tvi), cargs) = pb in
1291
1291
let tvi = tvi |> omap (transtvi env ue) in
1292
- let cts = EcUnify. select_op ~filter tvi env (unloc cname) ue [] in
1292
+ let cts = EcUnify. select_op ~filter tvi env (unloc cname) ue ( [] , None ) in
1293
1293
1294
1294
match cts with
1295
1295
| [] ->
@@ -2512,7 +2512,7 @@ and translvalue ue (env : EcEnv.env) lvalue =
2512
2512
let e, ety = e_tuple e, ttuple ety in
2513
2513
let name = ([] , EcCoreLib. s_set) in
2514
2514
let esig = [xty; ety; codomty] in
2515
- let ops = select_exp_op env `InProc None name ue tvi esig in
2515
+ let ops = select_exp_op env `InProc None name ue tvi ( esig, None ) in
2516
2516
2517
2517
match ops with
2518
2518
| [] ->
@@ -2581,8 +2581,9 @@ and trans_gbinding env ue decl =
2581
2581
and trans_form_or_pattern env mode ?mv ?ps ue pf tt =
2582
2582
let state = PFS. create () in
2583
2583
2584
- let rec transf_r opsc env f =
2585
- let transf = transf_r opsc in
2584
+ let rec transf_r_tyinfo opsc env ?tt f =
2585
+ let transf env ?tt f =
2586
+ transf_r opsc env ?tt f in
2586
2587
2587
2588
match f.pl_desc with
2588
2589
| PFhole -> begin
@@ -2814,20 +2815,18 @@ and trans_form_or_pattern env mode ?mv ?ps ue pf tt =
2814
2815
| PFdecimal (n , f ) ->
2815
2816
f_decimal (n, f)
2816
2817
2817
- | PFtuple args -> begin
2818
- let args = List. map (transf env) args in
2819
- match args with
2820
- | [] -> f_tt
2821
- | [f] -> f
2822
- | fs -> f_tuple fs
2823
- end
2818
+ | PFtuple pes ->
2819
+ let esig = List. map (fun _ -> EcUnify.UniEnv. fresh ue) pes in
2820
+ tt |> oiter (fun tt -> unify_or_fail env ue f.pl_loc ~expct: tt (ttuple esig));
2821
+ let es = List. map2 (fun tt pe -> transf env ~tt pe) esig pes in
2822
+ f_tuple es
2824
2823
2825
2824
| PFident ({ pl_desc = name ; pl_loc = loc } , tvi ) ->
2826
2825
let tvi = tvi |> omap (transtvi env ue) in
2827
2826
let ops =
2828
2827
select_form_op
2829
2828
~forcepv: (PFS. isforced state)
2830
- env mode opsc name ue tvi [] in
2829
+ env mode opsc name ue tvi ( [] , tt) in
2831
2830
begin match ops with
2832
2831
| [] ->
2833
2832
tyerror loc env (UnknownVarOrOp (name, [] ))
@@ -2962,13 +2961,43 @@ and trans_form_or_pattern env mode ?mv ?ps ue pf tt =
2962
2961
check_mem f.pl_loc EcFol. mright;
2963
2962
EcFol. f_ands (List. map (do1 (EcFol. mleft, EcFol. mright)) fs)
2964
2963
2965
- | PFapp ({pl_desc = PFident ({ pl_desc = name ; pl_loc = loc } , tvi )} , pes ) ->
2964
+ | PFapp ({pl_desc = PFident ({ pl_desc = name ; pl_loc = loc } , tvi )} , pes ) -> begin
2965
+ let try_trans ?tt pe =
2966
+ let ue' = EcUnify.UniEnv. copy ue in
2967
+ let ps' = Option. map (fun ps -> ref ! ps) ps in
2968
+ match transf env ?tt pe with
2969
+ | e -> Some e
2970
+ | exception TyError (_ , _ , MultipleOpMatch _ ) ->
2971
+ Option. iter (fun ps -> ps := ! (Option. get ps')) ps;
2972
+ EcUnify.UniEnv. restore ~dst: ue ~src: ue';
2973
+ None
2974
+ in
2975
+
2976
+ match
2977
+ let ue' = EcUnify.UniEnv. copy ue in
2978
+ let ps' = Option. map (fun ps -> ref ! ps) ps in
2979
+ let es = List. map (fun pe -> try_trans pe) pes in
2980
+ let tvi = tvi |> omap (transtvi env ue) in
2981
+ let esig = List. map (fun e ->
2982
+ match e with Some e -> e.f_ty | None -> EcUnify.UniEnv. fresh ue
2983
+ ) es in
2984
+ match
2985
+ select_form_op ~forcepv: (PFS. isforced state)
2986
+ env mode opsc name ue tvi (esig, tt)
2987
+ with
2988
+ | [sel] -> Some (sel, (es, esig, tvi))
2989
+ | _ ->
2990
+ Option. iter (fun ps -> ps := ! (Option. get ps')) ps;
2991
+ EcUnify.UniEnv. restore ~dst: ue ~src: ue';
2992
+ None
2993
+ with
2994
+ | None -> begin
2966
2995
let tvi = tvi |> omap (transtvi env ue) in
2967
2996
let es = List. map (transf env) pes in
2968
2997
let esig = List. map EcFol. f_ty es in
2969
2998
let ops =
2970
2999
select_form_op ~forcepv: (PFS. isforced state)
2971
- env mode opsc name ue tvi esig in
3000
+ env mode opsc name ue tvi ( esig, tt) in
2972
3001
2973
3002
begin match ops with
2974
3003
| [] ->
@@ -2986,6 +3015,24 @@ and trans_form_or_pattern env mode ?mv ?ps ue pf tt =
2986
3015
let matches = List. map (fun (_ , _ , subue , m ) -> (m, subue)) ops in
2987
3016
tyerror loc env (MultipleOpMatch (name, esig, matches))
2988
3017
end
3018
+ end
3019
+
3020
+ | Some ((_ , _ , subue , _ ) as sel , (es , esig , _tvi )) ->
3021
+ EcUnify.UniEnv. restore ~dst: ue ~src: subue;
3022
+ let es =
3023
+ List. map2 (
3024
+ fun (e , ty ) pe ->
3025
+ match e with None -> try_trans ~tt: ty pe | Some e -> Some e
3026
+ ) (List. combine es esig) pes in
3027
+ let es =
3028
+ List. map2 (
3029
+ fun (e , ty ) pe ->
3030
+ match e with None -> transf env ~tt: ty pe | Some e -> e
3031
+ ) (List. combine es esig) pes in
3032
+ let es = List. map2 (fun e l -> mk_loc l.pl_loc e) es pes in
3033
+ EcUnify.UniEnv. restore ~src: ue ~dst: subue;
3034
+ form_of_opselect (env, ue) loc sel es
3035
+ end
2989
3036
2990
3037
| PFapp (e , pes ) ->
2991
3038
let es = List. map (transf env) pes in
@@ -3041,25 +3088,30 @@ and trans_form_or_pattern env mode ?mv ?ps ue pf tt =
3041
3088
let f1 = transf env pf1 in
3042
3089
unify_or_fail env ue pf1.pl_loc ~expct: pty f1.f_ty;
3043
3090
aty |> oiter (fun aty -> unify_or_fail env ue pf1.pl_loc ~expct: pty aty);
3044
- let f2 = transf penv f2 in
3091
+ let f2 = transf penv ?tt f2 in
3045
3092
f_let p f1 f2
3046
3093
3047
3094
| PFforall (xs , pf ) ->
3048
3095
let env, xs = trans_gbinding env ue xs in
3049
3096
let f = transf env pf in
3050
- unify_or_fail env ue pf.pl_loc ~expct: tbool f.f_ty;
3051
- f_forall xs f
3097
+ unify_or_fail env ue pf.pl_loc ~expct: tbool f.f_ty;
3098
+ f_forall xs f
3052
3099
3053
3100
| PFexists (xs , f1 ) ->
3054
3101
let env, xs = trans_gbinding env ue xs in
3055
3102
let f = transf env f1 in
3056
- unify_or_fail env ue f1.pl_loc ~expct: tbool f.f_ty;
3057
- f_exists xs f
3103
+ unify_or_fail env ue f1.pl_loc ~expct: tbool f.f_ty;
3104
+ f_exists xs f
3058
3105
3059
3106
| PFlambda (xs , f1 ) ->
3060
3107
let env, xs = trans_binding env ue xs in
3061
- let f = transf env f1 in
3062
- f_lambda (List. map (fun (x ,ty ) -> (x,GTty ty)) xs) f
3108
+ let subtt = tt |> Option. map (fun tt ->
3109
+ let codom = EcUnify.UniEnv. fresh ue in
3110
+ unify_or_fail env ue (loc f) ~expct: (toarrow (List. snd xs) codom) tt;
3111
+ codom
3112
+ ) in
3113
+ let f = transf env ?tt:subtt f1 in
3114
+ f_lambda (List. map (fun (x , ty ) -> (x, GTty ty)) xs) f
3063
3115
3064
3116
| PFrecord (b , fields ) ->
3065
3117
let (ctor, fields, (rtvi, reccty)) =
@@ -3190,11 +3242,12 @@ and trans_form_or_pattern env mode ?mv ?ps ue pf tt =
3190
3242
unify_or_fail qenv ue post.pl_loc ~expct: tbool post'.f_ty;
3191
3243
f_eagerF pre' s1 fpath1 fpath2 s2 post'
3192
3244
3193
- in
3245
+ and transf_r opsc env ?tt pf =
3246
+ let f = transf_r_tyinfo opsc env ?tt pf in
3247
+ let () = oiter (fun tt -> unify_or_fail env ue pf.pl_loc ~expct: tt f.f_ty) tt in
3248
+ f
3194
3249
3195
- let f = transf_r None env pf in
3196
- tt |> oiter (fun tt -> unify_or_fail env ue pf.pl_loc ~expct: tt f.f_ty);
3197
- f
3250
+ in transf_r None env ?tt pf
3198
3251
3199
3252
(* Type-check a memtype. *)
3200
3253
and trans_memtype env ue (pmemtype : pmemtype ) : memtype =
0 commit comments