|
| 1 | +require import AllCore. |
| 2 | +require Subtype. |
| 3 | + |
| 4 | +(* Generic abstract predicates declared outside any section so they |
| 5 | + stay polymorphic instead of being generalized when the section is |
| 6 | + closed. *) |
| 7 | +op P ['c] : int -> 'c -> bool. |
| 8 | +op Q ['c] : int -> 'c -> bool. |
| 9 | +op R ['o 'i] : 'o -> 'i -> bool. |
| 10 | + |
| 11 | +axiom P_sat ['c] : exists n, P<:'c> n witness. |
| 12 | +axiom Q_sat ['c] : exists n, Q<:'c> n witness. |
| 13 | +axiom R_sat ['o 'i] : R<:'o, 'i> witness witness. |
| 14 | + |
| 15 | + |
| 16 | +(* -------------------------------------------------------------------- *) |
| 17 | +(* Basic case: subtype inside a section with a single section-declared *) |
| 18 | +(* free type. The subtype must be generalized over [c] at section *) |
| 19 | +(* close so that [val]/[insub] (which gain a [c] tparam) and the type *) |
| 20 | +(* itself stay coherent. *) |
| 21 | +(* -------------------------------------------------------------------- *) |
| 22 | +theory T1. |
| 23 | +section. |
| 24 | +declare type c. |
| 25 | + |
| 26 | +subtype carrier = { x : int * c | P x.`1 x.`2 }. |
| 27 | + |
| 28 | +realize inhabited. proof. by have [n hn] := P_sat<:c>; exists (n, witness). qed. |
| 29 | + |
| 30 | +end section. |
| 31 | +end T1. |
| 32 | + |
| 33 | +(* After section close, [carrier] is unary. Using it at two distinct |
| 34 | + carrier types in the same lemma produces two distinct types — would |
| 35 | + fail to type-check if [carrier] had stayed monomorphic. *) |
| 36 | +lemma test_basic_unary (x : bool T1.carrier) (y : int T1.carrier) : |
| 37 | + T1.val x = (0, witness<:bool>) /\ T1.val y = (1, witness<:int>). |
| 38 | +proof. admit. qed. |
| 39 | + |
| 40 | + |
| 41 | +(* -------------------------------------------------------------------- *) |
| 42 | +(* Predicate-only dependency: the carrier mentions no section-declared *) |
| 43 | +(* type, but the predicate does (the polymorphic [Q] is instantiated at *) |
| 44 | +(* the section's [c]). The fv collected from the predicate must trigger *) |
| 45 | +(* the same generalization. *) |
| 46 | +(* -------------------------------------------------------------------- *) |
| 47 | +theory T2. |
| 48 | +section. |
| 49 | +declare type c. |
| 50 | +
|
| 51 | +subtype only_pred = { x : int | Q<:c> x witness }. |
| 52 | +
|
| 53 | +realize inhabited. proof. exact: Q_sat. qed. |
| 54 | +
|
| 55 | +end section. |
| 56 | +end T2. |
| 57 | +
|
| 58 | +lemma test_pred_dep_unary (x : bool T2.only_pred) (y : int T2.only_pred) : |
| 59 | + T2.val x = 0 /\ T2.val y = 1. |
| 60 | +proof. |
| 61 | +(* The subtype-cloned [valP] axiom must itself be polymorphic over the |
| 62 | + carrier — instantiating it at two distinct types here would fail to |
| 63 | + type-check if the generalization had not happened. *) |
| 64 | +have hx : Q<:bool> (T2.val x) witness by exact: T2.valP. |
| 65 | +have hy : Q<:int> (T2.val y) witness by exact: T2.valP. |
| 66 | +admit. |
| 67 | +qed. |
| 68 | +
|
| 69 | +
|
| 70 | +(* -------------------------------------------------------------------- *) |
| 71 | +(* Two nested sections. The subtype is declared in the inner section *) |
| 72 | +(* and depends on free types from BOTH levels. After both closes, it *) |
| 73 | +(* must be generalized over both [outer] and [inner]. *) |
| 74 | +(* -------------------------------------------------------------------- *) |
| 75 | +theory T3. |
| 76 | +section Outer. |
| 77 | +declare type outer. |
| 78 | +
|
| 79 | +section Inner. |
| 80 | +declare type inner. |
| 81 | +
|
| 82 | +subtype pair_carrier = { x : outer * inner | R x.`1 x.`2 }. |
| 83 | +
|
| 84 | +realize inhabited. |
| 85 | +proof. by exists (witness, witness); exact: R_sat. qed. |
| 86 | +
|
| 87 | +end section Inner. |
| 88 | +end section Outer. |
| 89 | +end T3. |
| 90 | +
|
| 91 | +(* Now [pair_carrier] should be binary. *) |
| 92 | +lemma test_nested_binary |
| 93 | + (x : (int, bool) T3.pair_carrier) |
| 94 | + (y : (bool, int) T3.pair_carrier) |
| 95 | +: |
| 96 | + T3.val x = (0, true) /\ T3.val y = (true, 0). |
| 97 | +proof. |
| 98 | +(* As in T2, instantiating [valP] at two distinct carrier pairs would |
| 99 | + fail to type-check if the cloned axiom had not been generalized |
| 100 | + over both [outer] and [inner]. *) |
| 101 | +have hx : R<:int, bool> (T3.val x).`1 (T3.val x).`2 by exact: T3.valP. |
| 102 | +have hy : R<:bool, int> (T3.val y).`1 (T3.val y).`2 by exact: T3.valP. |
| 103 | +admit. |
| 104 | +qed. |
0 commit comments