@@ -66,7 +66,7 @@ type ctors = ctor list
6666
6767type datatype = {
6868 dt_path : EcPath .path ;
69- dt_tparams : ( ty_param * bool ) list ;
69+ dt_tparams : ty_params ;
7070 dt_ctors : ctors
7171}
7272
@@ -84,48 +84,76 @@ let datatype_ind_path (mode : indmode) (p : EcPath.path) =
8484
8585(* -------------------------------------------------------------------- *)
8686exception NonPositive of ty
87+ exception NonPositiveAbstract of EcPath. path
88+ exception NonPositiveParams of ty
89+
90+ (* * below, [fct] designates the function that takes a path to a type constructor
91+ and returns the corresponding type declaration *)
92+ (* * Strict positivity enforces the following, for every variant of the datatype p:
93+ - for each subterm (a → b), p ∉ fv(a);
94+ - inductive occurences a₁ a₂ .. aₙ p are such that ∀i. p ∉ fv(aᵢ) *)
8795
8896let rec occurs ?(normty = identity) p t =
8997 match (normty t).ty_node with
9098 | Tconstr (p' , _ ) when EcPath. p_equal p p' -> true
9199 | _ -> EcTypes. ty_sub_exists (occurs p) t
92100
93- (* * below, [fct] designates the function that takes a path to a type constructor
94- and returns the corresponding type declaration *)
101+ let ty_params_compat =
102+ List. for_all2 (fun ty (param_id , _ ) ->
103+ match ty.ty_node with
104+ | Tvar id -> EcIdent. id_equal id param_id
105+ | _ -> false )
106+
107+ let rec check_positivity_in_decl fct p decl ident =
108+ let tys_to_inspect =
109+ match decl.tyd_type with
110+ | Concrete ty -> [ ty ]
111+ | Abstract _ -> raise @@ NonPositiveAbstract p
112+ | Datatype { tydt_ctors } -> List. flatten (List. map snd tydt_ctors)
113+ | Record (_ , tys ) -> List. map snd tys
114+ in
115+ List. iter (check_positivity_ident fct p decl.tyd_params ident) tys_to_inspect
95116
96- (* * Strict positivity enforces the following, for every variant of the datatype p:
97- - for each subterm (a → b), p ∉ fv(a);
98- - recursive occurences a₁ a₂ .. aₙ p are such that ∀i. p ∉ fv(aᵢ) *)
99-
100- let rec check_positivity_dt fct p ty (q , args ) =
101- let tydecl = fct q in
102- let inst = EcDecl. ty_instanciate tydecl.tyd_params args in
103- match tydecl.tyd_type with
104- | Abstract _ -> ()
105- | Concrete ty' -> check_positivity_ty fct p ty ty'
106- | Record (_ , fields ) ->
107- List. iter (check_positivity_ty fct p ty) (List. map (inst |- snd) fields)
108- | Datatype dt -> check_positivity_ctors fct p inst ty dt.tydt_ctors
109-
110- and check_positivity_ctors fct p inst ty =
111- List. iter (fun (_variant , parameters ) ->
112- List. iter (check_positivity_ty fct p ty) (List. map inst parameters))
113-
114- and check_positivity_ty fct p ty traversed_ty =
115- match traversed_ty.ty_node with
117+ (* * Ensures all occurrences of type variable [ident] are positive in type [ty] *)
118+ and check_positivity_ident fct p params ident ty = match ty.ty_node with
119+ | Tglob _ | Tunivar _ -> assert false
120+ | Tvar _ -> ()
121+ | Ttuple tys -> List. iter (check_positivity_ident fct p params ident) tys
122+ | Tconstr (q , args ) when EcPath. p_equal q p ->
123+ if not (ty_params_compat args params) then raise @@ NonPositiveParams ty
124+ | Tconstr (q , args ) ->
125+ let decl = fct q in
126+ List. combine args decl.tyd_params
127+ |> List. filter_map
128+ (fun (arg , (ident , _ )) -> if EcTypes. var_mem ident arg then Some ident else None )
129+ |> List. iter (check_positivity_in_decl fct q decl)
130+ | Tfun (from , to_ ) ->
131+ if EcTypes. var_mem ident from then raise @@ NonPositive ty;
132+ check_positivity_ident fct p params ident to_
133+
134+
135+ (* * Ensures all occurrences of path [p] are positive in type [ty] *)
136+ let rec check_positivity_path fct p ty =
137+ match ty.ty_node with
116138 | Tglob _ | Tunivar _ -> assert false
117139 | Tvar _ -> ()
118- | Ttuple tys -> List. iter (check_positivity_ty fct p ty ) tys
140+ | Ttuple tys -> List. iter (check_positivity_path fct p) tys
119141 | Tconstr (q , args ) when EcPath. p_equal q p ->
120- if List. exists (fun ty -> occurs p ty) args then
121- raise (NonPositive traversed_ty)
122- | Tconstr (q , args ) -> check_positivity_dt fct p ty (q, args)
142+ if List. exists (occurs p) args then raise (NonPositive ty)
143+ | Tconstr (q , args ) ->
144+ let decl = fct q in
145+ List. combine args decl.tyd_params
146+ |> List. filter_map
147+ (fun (arg , (ident , _ )) -> if occurs p arg then Some ident else None )
148+ |> List. iter (check_positivity_in_decl fct q decl)
149+
123150 | Tfun (from , to_ ) ->
124- if occurs ty from then raise (NonPositive traversed_ty );
125- check_positivity_ty fct p ty to_
151+ if occurs p from then raise (NonPositive ty );
152+ check_positivity_path fct p to_
126153
127154let check_positivity fct dt =
128- check_positivity_ctors fct dt.dt_path identity dt.dt_path dt.dt_ctors
155+ let tys = List. flatten (List. map snd dt.dt_ctors) in
156+ List. iter (check_positivity_path fct dt.dt_path) tys
129157
130158
131159let indsc_of_datatype ?(normty = identity) (mode : indmode ) (dt : datatype ) =
@@ -192,7 +220,7 @@ let indsc_of_datatype ?(normty = identity) (mode : indmode) (dt : datatype) =
192220 let form = FL. f_forall [predx, GTty predty] form in
193221 form
194222
195- in scheme mode (List. map ( fst |- fst) dt.dt_tparams, tpath) dt.dt_ctors
223+ in scheme mode (List. map fst dt.dt_tparams, tpath) dt.dt_ctors
196224
197225(* -------------------------------------------------------------------- *)
198226let datatype_projectors (tpath , tparams , { tydt_ctors = ctors } ) =
@@ -229,7 +257,7 @@ let datatype_projectors (tpath, tparams, { tydt_ctors = ctors }) =
229257let datatype_as_ty_dtype datatype =
230258 let indsc = indsc_of_datatype `Elim datatype in
231259 let casesc = indsc_of_datatype `Case datatype in
232- List. map fst datatype.dt_tparams,
260+ datatype.dt_tparams,
233261 { tydt_ctors = datatype.dt_ctors ;
234262 tydt_schcase = casesc;
235263 tydt_schelim = indsc ; }
0 commit comments