@@ -83,54 +83,68 @@ let datatype_ind_path (mode : indmode) (p : EcPath.path) =
8383 EcPath. pqoname (EcPath. prefix p) name
8484
8585(* -------------------------------------------------------------------- *)
86- exception NonPositive of ty
87- exception NonPositiveAbstract of EcPath. path
88- exception NonPositiveParams of ty
86+ type nonpositive_description =
87+ | NonPositive of ty
88+ | AbstractTypeRestriction of EcPath .path
89+ | TypePositionRestriction of ty
90+
91+ exception NonPositive of nonpositive_description
8992
9093(* * below, [fct] designates the function that takes a path to a type constructor
9194 and returns the corresponding type declaration *)
95+
9296(* * Strict positivity enforces the following, for every variant of the datatype p:
9397 - for each subterm (a → b), p ∉ fv(a);
94- - inductive occurences a₁ a₂ .. aₙ p are such that ∀i. p ∉ fv(aᵢ) *)
98+ - inductive occurences a₁ a₂ .. aₙ p are such that ∀i. p ∉ fv(aᵢ)
99+
100+ Crucially, this has to be checked whenever p occurs in an instance of
101+ another type constructor. *)
95102
96103let rec occurs ?(normty = identity) p t =
97104 match (normty t).ty_node with
98105 | Tconstr (p' , _ ) when EcPath. p_equal p p' -> true
99106 | _ -> EcTypes. ty_sub_exists (occurs p) t
100107
108+ (* * Tests whether the first list is a list of type variables, matching the
109+ identifiers of the second list. *)
101110let ty_params_compat =
102111 List. for_all2 (fun ty (param_id , _ ) ->
103112 match ty.ty_node with
104113 | Tvar id -> EcIdent. id_equal id param_id
105114 | _ -> false )
106115
116+ (* * Ensures all occurrences of type variable [ident] are positive in type
117+ declaration [decl] (with name [p]) *)
107118let rec check_positivity_in_decl fct p decl ident =
108119 let tys_to_inspect =
109120 match decl.tyd_type with
110121 | Concrete ty -> [ ty ]
111- | Abstract _ -> raise @@ NonPositiveAbstract p
112- | Datatype { tydt_ctors } -> List. flatten (List. map snd tydt_ctors)
122+ | Abstract _ ->
123+ (* Abstract types cannot be polymorphic so this is unreachable for now *)
124+ raise (NonPositive (AbstractTypeRestriction p))
125+ | Datatype { tydt_ctors } -> List. flatten @@ List. map snd tydt_ctors
113126 | Record (_ , tys ) -> List. map snd tys
114127 in
115128 List. iter (check_positivity_ident fct p decl.tyd_params ident) tys_to_inspect
116129
117130(* * 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
131+ and check_positivity_ident fct p params ident ty =
132+ match ty.ty_node with
119133 | Tglob _ | Tunivar _ -> assert false
120134 | Tvar _ -> ()
121135 | Ttuple tys -> List. iter (check_positivity_ident fct p params ident) tys
122136 | 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 ) ->
137+ if not (ty_params_compat args params) then
138+ raise (NonPositive (TypePositionRestriction ty))
139+ | Tconstr (q , args ) ->
125140 let decl = fct q in
126141 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 )
142+ |> List. filter_map ( fun ( arg , ( ident , _ )) ->
143+ if EcTypes. var_mem ident arg then Some ident else None )
129144 |> List. iter (check_positivity_in_decl fct q decl)
130145 | Tfun (from , to_ ) ->
131- if EcTypes. var_mem ident from then raise @@ NonPositive ty;
132- check_positivity_ident fct p params ident to_
133-
146+ if EcTypes. var_mem ident from then raise (NonPositive (NonPositive ty));
147+ check_positivity_ident fct p params ident to_
134148
135149(* * Ensures all occurrences of path [p] are positive in type [ty] *)
136150let rec check_positivity_path fct p ty =
@@ -139,22 +153,20 @@ let rec check_positivity_path fct p ty =
139153 | Tvar _ -> ()
140154 | Ttuple tys -> List. iter (check_positivity_path fct p) tys
141155 | Tconstr (q , args ) when EcPath. p_equal q p ->
142- if List. exists (occurs p) args then raise (NonPositive ty )
156+ if List. exists (occurs p) args then raise (NonPositive ( NonPositive ty) )
143157 | Tconstr (q , args ) ->
144158 let decl = fct q in
145159 List. combine args decl.tyd_params
146- |> List. filter_map
147- ( fun ( arg , ( ident , _ )) -> if occurs p arg then Some ident else None )
160+ |> List. filter_map ( fun ( arg , ( ident , _ )) ->
161+ if occurs p arg then Some ident else None )
148162 |> List. iter (check_positivity_in_decl fct q decl)
149-
150163 | Tfun (from , to_ ) ->
151- if occurs p from then raise (NonPositive ty );
164+ if occurs p from then raise (NonPositive ( NonPositive ty) );
152165 check_positivity_path fct p to_
153166
154167let check_positivity fct dt =
155- let tys = List. flatten (List. map snd dt.dt_ctors) in
156- List. iter (check_positivity_path fct dt.dt_path) tys
157-
168+ let tys = List. flatten (List. map snd dt.dt_ctors) in
169+ List. iter (check_positivity_path fct dt.dt_path) tys
158170
159171let indsc_of_datatype ?(normty = identity) (mode : indmode ) (dt : datatype ) =
160172 let tpath = dt.dt_path in
0 commit comments