Skip to content

Commit 547c7c5

Browse files
committed
feat: manage error messages, some more documentation for the new functions
1 parent 3ca2ce0 commit 547c7c5

File tree

5 files changed

+58
-31
lines changed

5 files changed

+58
-31
lines changed

src/ecHiInductive.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ type dterror =
2323
| DTE_TypeError of TT.tyerror
2424
| DTE_DuplicatedCtor of symbol
2525
| DTE_InvalidCTorType of symbol * TT.tyerror
26-
| DTE_NonPositive of symbol * ty
26+
| DTE_NonPositive of symbol * EI.nonpositive_description
2727
| DTE_Empty
2828

2929
type fxerror =

src/ecHiInductive.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ type dterror =
1616
| DTE_TypeError of EcTyping.tyerror
1717
| DTE_DuplicatedCtor of symbol
1818
| DTE_InvalidCTorType of symbol * EcTyping.tyerror
19-
| DTE_NonPositive of symbol * EcTypes.ty
19+
| DTE_NonPositive of symbol * EcInductive.nonpositive_description
2020
| DTE_Empty
2121

2222
type fxerror =

src/ecInductive.ml

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -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

96103
let 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. *)
101110
let 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]) *)
107118
let 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] *)
136150
let 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

154167
let 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

159171
let indsc_of_datatype ?(normty = identity) (mode : indmode) (dt : datatype) =
160172
let tpath = dt.dt_path in

src/ecInductive.mli

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,13 @@ val datatype_proj_name : symbol -> symbol
4343
val datatype_proj_path : path -> symbol -> path
4444

4545
(* -------------------------------------------------------------------- *)
46-
(** A failure raised during a strict-positivity check. The companion type
47-
is the term responsible for the failure. *)
48-
exception NonPositive of ty
46+
type nonpositive_description =
47+
| NonPositive of ty
48+
| AbstractTypeRestriction of EcPath.path
49+
| TypePositionRestriction of ty
50+
51+
(** A failure raised during a strict-positivity check. *)
52+
exception NonPositive of nonpositive_description
4953

5054
(** Evaluates whether a given datatype protype satisfies the strict
5155
positivity check. The first argument defines how to retrieve the

src/ecUserMessages.ml

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -606,13 +606,24 @@ end = struct
606606
msg "invalid constructor type: `%s`: %a'"
607607
name (pp_tyerror env) ee
608608

609-
| DTE_NonPositive (name, ty) ->
610-
msg "non strictly-positive occurrence of type `%s` in `%a`"
611-
name (EcPrinting.pp_type env1) ty
612-
613609
| DTE_Empty ->
614610
msg "the datatype may be empty"
615611

612+
| DTE_NonPositive (name, desc) -> (
613+
let prefix = Printf.sprintf "while defining type `%s`:" name in
614+
match desc with
615+
| NonPositive ty ->
616+
msg "%s non strictly-positive occurrence in `%a`" prefix
617+
(EcPrinting.pp_type env1) ty
618+
| AbstractTypeRestriction p ->
619+
msg "%s unauthorised use within abstract type `%a`" prefix
620+
EcPrinting.pp_path p
621+
| TypePositionRestriction ty ->
622+
msg
623+
"%s unauthorised use of type `%a`, which changes the position of \
624+
its type parameters"
625+
prefix (EcPrinting.pp_type env1) ty)
626+
616627
let pp_fxerror env fmt error =
617628
match error with
618629
| FXLowError ee ->

0 commit comments

Comments
 (0)