Skip to content

Commit 47c9fba

Browse files
committed
Cloning: support inlining a type via clone-inline (clinline)
Adds a 'tyd_clinline' flag to 'tydecl', the type-level analogue of the existing 'op_clinline'. A type cloned with an inline override ('<-' or '<=') is tagged clinline and retains its body; when it is later used as the target of a 'theory ... <=' override, the consumer receives that body rather than a reference to the type (the two remain convertible — the difference shows only when printing). The replay 'ByPath' branch now consults 'reftyd.tyd_clinline' to choose body-vs-reference, mirroring the operator side. All three type override paths (BySyntax / ByPath / Direct) set tyd_clinline = (mode <> `Alias), matching the operator side exactly. Threads the field through ecDecl, ecHiInductive, ecScope, ecSection, ecSubst. Adds tests/clone-type-inline.ec (expect-based).
1 parent e2bb4eb commit 47c9fba

8 files changed

Lines changed: 94 additions & 38 deletions

File tree

src/ecDecl.ml

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,11 @@ type ty_body =
3535

3636

3737
type tydecl = {
38-
tyd_params : ty_params;
39-
tyd_type : ty_body;
40-
tyd_loca : locality;
41-
tyd_subtype : (EcTypes.ty * EcCoreFol.form) option;
38+
tyd_params : ty_params;
39+
tyd_type : ty_body;
40+
tyd_loca : locality;
41+
tyd_clinline : bool;
42+
tyd_subtype : (EcTypes.ty * EcCoreFol.form) option;
4243
}
4344

4445
let tydecl_as_concrete (td : tydecl) =
@@ -66,10 +67,11 @@ let abs_tydecl ?(params = `Int 0) lc =
6667
(EcUid.NameGen.bulk ~fmt n)
6768
in
6869

69-
{ tyd_params = params;
70-
tyd_type = Abstract;
71-
tyd_loca = lc;
72-
tyd_subtype = None; }
70+
{ tyd_params = params;
71+
tyd_type = Abstract;
72+
tyd_loca = lc;
73+
tyd_clinline = false;
74+
tyd_subtype = None; }
7375

7476
(* -------------------------------------------------------------------- *)
7577
let ty_instantiate (params : ty_params) (args : ty list) (ty : ty) =

src/ecDecl.mli

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@ type ty_body =
3030

3131

3232
type tydecl = {
33-
tyd_params : ty_params;
34-
tyd_type : ty_body;
35-
tyd_loca : locality;
33+
tyd_params : ty_params;
34+
tyd_type : ty_body;
35+
tyd_loca : locality;
36+
tyd_clinline : bool;
3637
(* For [subtype]-declared types: the carrier and the predicate. The
3738
declared type itself stays [tyd_type = Abstract], because a
3839
subtype is semantically a fresh abstract type — but its dependency
@@ -41,7 +42,7 @@ type tydecl = {
4142
carrier+predicate fv into the type's fv when this field is set,
4243
so a subtype declared inside [section. declare type c.] gets the
4344
section's tparams added at close, just like type aliases do. *)
44-
tyd_subtype : (EcTypes.ty * EcCoreFol.form) option;
45+
tyd_subtype : (EcTypes.ty * EcCoreFol.form) option;
4546
}
4647

4748
val tydecl_as_concrete : tydecl -> EcTypes.ty option

src/ecHiInductive.ml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,11 @@ let trans_datatype (env : EcEnv.env) (name : ptydname) (dt : pdatatype) =
8383
let tpath = EcPath.pqname (EcEnv.root env) (unloc name) in
8484
let env0 =
8585
let myself = {
86-
tyd_params = EcUnify.UniEnv.tparams ue;
87-
tyd_type = Abstract;
88-
tyd_loca = lc;
89-
tyd_subtype = None;
86+
tyd_params = EcUnify.UniEnv.tparams ue;
87+
tyd_type = Abstract;
88+
tyd_loca = lc;
89+
tyd_clinline = false;
90+
tyd_subtype = None;
9091
} in
9192
EcEnv.Ty.bind (unloc name) myself env
9293
in

src/ecScope.ml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2297,7 +2297,7 @@ module Ty = struct
22972297
in
22982298

22992299
bind scope (unloc name,
2300-
{ tyd_params; tyd_type; tyd_loca; tyd_subtype = None; })
2300+
{ tyd_params; tyd_type; tyd_loca; tyd_clinline = false; tyd_subtype = None; })
23012301

23022302
(* ------------------------------------------------------------------ *)
23032303
let add_subtype (scope : scope) ({ pl_desc = subtype } : psubtype located) =
@@ -2326,10 +2326,11 @@ module Ty = struct
23262326

23272327
let scope =
23282328
let decl = EcDecl.{
2329-
tyd_params = [];
2330-
tyd_type = Abstract;
2331-
tyd_loca = `Global;
2332-
tyd_subtype = Some (carrier, pred);
2329+
tyd_params = [];
2330+
tyd_type = Abstract;
2331+
tyd_loca = `Global;
2332+
tyd_clinline = false;
2333+
tyd_subtype = Some (carrier, pred);
23332334
} in bind scope (unloc subtype.pst_name, decl) in
23342335

23352336
let evclone =

src/ecSection.ml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -870,8 +870,9 @@ let generalize_tydecl to_gen prefix (name, tydecl) =
870870
let to_gen = { to_gen with tg_subst} in
871871
let tydecl = {
872872
tyd_params; tyd_type;
873-
tyd_loca = `Global;
874-
tyd_subtype = tydecl.tyd_subtype; } in
873+
tyd_loca = `Global;
874+
tyd_clinline = tydecl.tyd_clinline;
875+
tyd_subtype = tydecl.tyd_subtype; } in
875876
to_gen, Some (Th_type (name, tydecl))
876877

877878
| `Declare ->

src/ecSubst.ml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -873,10 +873,11 @@ let subst_tydecl (s : subst) (tyd : tydecl) =
873873
(fun (carrier, pred) -> (subst_ty s carrier, subst_form s pred))
874874
tyd.tyd_subtype in
875875

876-
{ tyd_params = tparams;
877-
tyd_type = body;
878-
tyd_loca = tyd.tyd_loca;
879-
tyd_subtype = subtype; }
876+
{ tyd_params = tparams;
877+
tyd_type = body;
878+
tyd_loca = tyd.tyd_loca;
879+
tyd_clinline = tyd.tyd_clinline;
880+
tyd_subtype = subtype; }
880881

881882
(* -------------------------------------------------------------------- *)
882883
let rec subst_op_kind (s : subst) (kind : operator_kind) =

src/ecTheoryReplay.ml

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -429,19 +429,29 @@ let rec replay_tyd (ove : _ ovrenv) (subst, ops, proofs, scope) (import, x, otyd
429429
let ue = EcUnify.UniEnv.create (Some nargs) in
430430
let ntyd = EcTyping.transty EcTyping.tp_tydecl env ue ntyd in
431431
let decl =
432-
{ tyd_params = nargs;
433-
tyd_type = Concrete ntyd;
434-
tyd_loca = otyd.tyd_loca;
435-
tyd_subtype = None; }
432+
{ tyd_params = nargs;
433+
tyd_type = Concrete ntyd;
434+
tyd_loca = otyd.tyd_loca;
435+
tyd_clinline = (mode <> `Alias);
436+
tyd_subtype = None; }
436437

437438
in (decl, ntyd)
438439

439440
| `ByPath p -> begin
440441
match EcEnv.Ty.by_path_opt p env with
441442
| Some reftyd ->
442-
let tyargs = List.map tvar reftyd.tyd_params in
443-
let body = tconstr p tyargs in
444-
let decl = { reftyd with tyd_type = Concrete body; } in
443+
let body =
444+
if reftyd.tyd_clinline then
445+
(match reftyd.tyd_type with
446+
| Concrete body -> body
447+
| _ -> assert false)
448+
else
449+
let tyargs = List.map tvar reftyd.tyd_params in
450+
tconstr p tyargs in
451+
let decl =
452+
{ reftyd with
453+
tyd_type = Concrete body;
454+
tyd_clinline = (mode <> `Alias); } in
445455
(decl, body)
446456

447457
| _ -> assert false
@@ -450,10 +460,11 @@ let rec replay_tyd (ove : _ ovrenv) (subst, ops, proofs, scope) (import, x, otyd
450460
| `Direct ty -> begin
451461
assert (List.is_empty otyd.tyd_params);
452462
let decl =
453-
{ tyd_params = [];
454-
tyd_type = Concrete ty;
455-
tyd_loca = otyd.tyd_loca;
456-
tyd_subtype = None; }
463+
{ tyd_params = [];
464+
tyd_type = Concrete ty;
465+
tyd_loca = otyd.tyd_loca;
466+
tyd_clinline = (mode <> `Alias);
467+
tyd_subtype = None; }
457468

458469
in (decl, ty)
459470
end

tests/clone-type-inline.ec

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
(* clinline (clone-inline) for types.
2+
3+
A type cloned with the inline-keep override `<=` carries its body and
4+
is tagged [tyd_clinline]. When such a type is later used as the target
5+
of a `theory ... <=` override, the consumer receives the *body* of the
6+
type rather than a reference to it. The two stay convertible; the
7+
difference is only visible when printing.
8+
9+
Contrast (checked below with `expect ... by print`):
10+
- K.t cloned with `type t <= int` (clinline) -> consumer prints `int`
11+
- L.t cloned with `type t = int` (plain alias) -> consumer prints `L.t`
12+
*)
13+
14+
require import AllCore.
15+
16+
abstract theory BV.
17+
type t.
18+
end BV.
19+
20+
(* A theory with an abstract subtheory [P] and a use of [P.t]. *)
21+
abstract theory Use.
22+
clone import BV as P.
23+
op probe : P.t.
24+
end Use.
25+
26+
(* Two instances of BV: one clinline (<=), one a plain alias (=). *)
27+
clone BV as K with type t <= int. (* K.t is clinline, body = int *)
28+
clone BV as L with type t = int. (* L.t is a plain alias *)
29+
30+
(* Override Use's subtheory P, once by each, via a `theory <=` override. *)
31+
clone import Use as UK with theory P <= K.
32+
clone import Use as UL with theory P <= L.
33+
34+
(* UK.P.t receives K.t's *body* (K.t is clinline): prints `int`. *)
35+
expect "type t = int." by print type UK.P.t.
36+
37+
(* UL.P.t keeps the reference to L.t (L.t is a plain alias): prints `L.t`. *)
38+
expect "type t = L.t." by print type UL.P.t.

0 commit comments

Comments
 (0)