Skip to content

Commit 9b9f3fe

Browse files
proof(L1.B): region_shrink_preserves_typing_l1 Qed via _gen helper (#159)
## Summary Second of three swarm-dispatched helper lemmas for \`preservation_l1\` (task #22 / L1.B). \`region_shrink_preserves_typing_l1\` — value v free of region r, with r not in free_regions T, can be re-typed at \`(remove_first r R)\`. Target closes to **Qed** via routing through a new general helper. ## Structure \`region_shrink_preserves_typing_l1_gen\` (new Admitted): drops the \`is_value\` + \`~ In r (free_regions T)\` premises, mirroring legacy \`Semantics.region_shrink_preserves_typing\`. Structural induction on the typing derivation. **22 of 24 typing-rule cases close to Qed**. Two residual admits: 1. **T_Region_L1** "multiple rr's in R_body" — needs L1 weakening to bump body typing from R to (rr :: R). 2. **T_Region_Active_L1 "rr=r shadowed"** — needs L1 region-perm to fold rr appearance. Both close once L1 analogs of legacy \`region_env_perm_typing\` + \`region_add_typing\` exist. Tasks #25 / #26. Also adds \`remove_first_comm\` (Qed). ## Net admit count Was 4 Admitted. Still 4 — target converted to Qed but the \`_gen\` helper is the new Admitted. Residual debt is **more bounded** (specific T_Region sub-cases vs the whole region-shrink question). ## Test plan - [x] coqc 8.18.0 builds Semantics_L1.vo cleanly - [x] Target lemma Qed - [x] L1.A's proof still Qed (no regression) - [ ] CI green Base: \`proof/l1-region-threading-design\` (rebased onto L1.A's merge). Refs ephapax#157, ephapax#158, tasks #22 / #25 / #26. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent c6b1cda commit 9b9f3fe

1 file changed

Lines changed: 164 additions & 4 deletions

File tree

formal/Semantics_L1.v

Lines changed: 164 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@
2424
- [value_R_G_preserving_l1] — Admitted; needs induction on
2525
[is_value] with nested IH for EInl, EInr, EPair, EBorrow-of-
2626
value.
27-
- [region_shrink_preserves_typing_l1] — Admitted; mirrors
28-
[Semantics.region_shrink_preserves_typing] under the L1
29-
judgment.
27+
- [region_shrink_preserves_typing_l1] — Qed via auxiliary
28+
[region_shrink_preserves_typing_l1_gen]; that aux has 2 admits
29+
(T_Region_L1 multiple-rr branch + T_Region_Active_L1 shadowed
30+
branch), both blocked on building L1 analogs of
31+
[Semantics.region_env_perm_typing] / [region_add_typing].
3032
- [subst_preserves_typing_l1] — Admitted; mirrors
3133
[Semantics.subst_preserves_typing] under the L1 judgment.
3234
- [preservation_l1] — Admitted; depends on the three helpers.
@@ -138,14 +140,172 @@ Qed.
138140
judgment. Used by the [S_Region_Exit] case of [preservation_l1].
139141
Detailed proof deferred to L1 follow-up PR. *)
140142

143+
(** Small commutation/idempotence facts about [remove_first]. *)
144+
145+
Lemma remove_first_comm :
146+
forall r1 r2 R,
147+
remove_first r1 (remove_first r2 R) = remove_first r2 (remove_first r1 R).
148+
Proof.
149+
intros r1 r2. induction R as [| r' R' IH]; [reflexivity|].
150+
simpl.
151+
destruct (String.eqb r2 r') eqn:Heq2; destruct (String.eqb r1 r') eqn:Heq1.
152+
- (* r2 = r' = r1; both pop r' *)
153+
simpl. apply String.eqb_eq in Heq1, Heq2. subst.
154+
reflexivity.
155+
- simpl. rewrite Heq2. reflexivity.
156+
- simpl. rewrite Heq1. reflexivity.
157+
- simpl. rewrite Heq1, Heq2. f_equal. apply IH.
158+
Qed.
159+
160+
(** Auxiliary general L1 region-shrinkage lemma — no [is_value] or
161+
[~ In r (free_regions T)] premises, mirroring the legacy
162+
[Semantics.region_shrink_preserves_typing]. The L1
163+
region-permutation infrastructure (analog of [region_env_perm_typing]
164+
and [region_add_typing]) is not yet built; the [T_Region_L1] and
165+
[T_Region_Active_L1] sub-cases need them. The two [admit]s inside
166+
this helper are the genuine residual blocking the [T_Lam_L1] case
167+
of the targeted lemma below.
168+
169+
Once the L1 permutation infrastructure lands, this helper closes to
170+
Qed and the targeted lemma follows in one line. *)
171+
172+
Lemma region_shrink_preserves_typing_l1_gen :
173+
forall R G e T R' G',
174+
has_type_l1 R G e T R' G' ->
175+
forall r,
176+
expr_free_of_region r e ->
177+
has_type_l1 (remove_first r R) G e T (remove_first r R') G'.
178+
Proof.
179+
intros R G e T R' G' Ht.
180+
induction Ht; intros rr Hfree; simpl in Hfree.
181+
- (* T_Unit_L1 *) apply T_Unit_L1.
182+
- (* T_Bool_L1 *) apply T_Bool_L1.
183+
- (* T_I32_L1 *) apply T_I32_L1.
184+
- (* T_Var_Lin_L1 *) eapply T_Var_Lin_L1; eauto.
185+
- (* T_Var_Unr_L1 *) eapply T_Var_Unr_L1; eauto.
186+
- (* T_Loc_L1 *)
187+
apply T_Loc_L1.
188+
apply remove_first_preserves_other; [exact Hfree | exact H].
189+
- (* T_StringNew_L1 *)
190+
apply T_StringNew_L1.
191+
apply remove_first_preserves_other; [exact Hfree | exact H].
192+
- (* T_StringConcat_L1 *)
193+
destruct Hfree as [Hf1 Hf2].
194+
eapply T_StringConcat_L1; [eapply IHHt1; auto | eapply IHHt2; auto].
195+
- (* T_StringLen_L1 *)
196+
eapply T_StringLen_L1. eapply IHHt; auto.
197+
- (* T_Let_L1 *)
198+
destruct Hfree as [Hf1 Hf2].
199+
eapply T_Let_L1; [eapply IHHt1; auto | eapply IHHt2; auto].
200+
- (* T_LetLin_L1 *)
201+
destruct Hfree as [Hf1 Hf2].
202+
eapply T_LetLin_L1; [exact H | eapply IHHt1; auto | eapply IHHt2; auto].
203+
- (* T_Lam_L1: body is R-preserving; IH gives shrinkage. *)
204+
apply T_Lam_L1. eapply IHHt; auto.
205+
- (* T_App_L1 *)
206+
destruct Hfree as [Hf1 Hf2].
207+
eapply T_App_L1; [eapply IHHt1; auto | eapply IHHt2; auto].
208+
- (* T_Pair_L1 *)
209+
destruct Hfree as [Hf1 Hf2].
210+
eapply T_Pair_L1; [eapply IHHt1; auto | eapply IHHt2; auto].
211+
- (* T_Fst_L1 *)
212+
eapply T_Fst_L1; [eapply IHHt; auto | exact H].
213+
- (* T_Snd_L1 *)
214+
eapply T_Snd_L1; [eapply IHHt; auto | exact H].
215+
- (* T_Inl_L1 *)
216+
eapply T_Inl_L1. eapply IHHt; auto.
217+
- (* T_Inr_L1 *)
218+
eapply T_Inr_L1. eapply IHHt; auto.
219+
- (* T_Case_L1 *)
220+
destruct Hfree as [Hf1 [Hf2 Hf3]].
221+
eapply T_Case_L1;
222+
[eapply IHHt1; auto | eapply IHHt2; auto | eapply IHHt3; auto].
223+
- (* T_If_L1 *)
224+
destruct Hfree as [Hf1 [Hf2 Hf3]].
225+
eapply T_If_L1;
226+
[eapply IHHt1; auto | eapply IHHt2; auto | eapply IHHt3; auto].
227+
- (* T_Region_L1: ERegion r e.
228+
Both sub-cases (rr = r shadowed, rr <> r descend) require either
229+
a "remove_first idempotent on absent" argument or a region-perm
230+
L1 helper. Documented as residual. *)
231+
destruct (String.eqb rr r) eqn:Heq.
232+
+ (* rr = r: shadowed. Hfree is True (irrelevant). *)
233+
apply String.eqb_eq in Heq. subst r.
234+
rewrite (remove_first_not_in_id _ _ H).
235+
(* Goal: R; G |=L1 ERegion rr e : T
236+
-| remove_first rr (remove_first_L1 rr R_body); G' *)
237+
(* Case-split on whether [In rr (remove_first_L1 rr R_body)]:
238+
- If NO: outer [remove_first rr] is identity, and the original
239+
T_Region_L1 derivation suffices.
240+
- If YES: more r's exist; would need T_Region_L1 with the
241+
shrunken R_body and a body-weakening lemma. Residual. *)
242+
destruct (in_dec string_dec rr (remove_first_L1 rr R_body)) as [Hin | Hnotin].
243+
* (* Multiple rr's in R_body — needs L1 weakening to bump body
244+
typing from R to (rr :: R). Residual. *)
245+
admit.
246+
* (* Only one (or zero, but H1 says at least one) rr in R_body.
247+
Then [remove_first rr (remove_first_L1 rr R_body) =
248+
remove_first_L1 rr R_body]. *)
249+
rewrite (remove_first_not_in_id _ _ Hnotin).
250+
eapply T_Region_L1; eauto.
251+
+ (* rr <> r: descend. *)
252+
apply String.eqb_neq in Heq.
253+
assert (Hgoal_eq : remove_first rr (remove_first_L1 r R_body) =
254+
remove_first_L1 r (remove_first rr R_body)).
255+
{ rewrite (remove_first_eq_l1 r R_body).
256+
rewrite (remove_first_eq_l1 r (remove_first rr R_body)).
257+
apply remove_first_comm. }
258+
rewrite Hgoal_eq.
259+
apply (T_Region_L1 (remove_first rr R) (remove_first rr R_body) G G' r e T).
260+
* intro Hin. apply H. eapply remove_first_subset; exact Hin.
261+
* exact H0.
262+
* apply remove_first_preserves_other; [intro Hbad; apply Heq; exact Hbad | exact H1].
263+
* (* Body: IH at rr gives remove_first rr (r::R) ; ... |=L1 e ...
264+
-| remove_first rr R_body ; ... *)
265+
specialize (IHHt rr Hfree).
266+
simpl in IHHt.
267+
destruct (String.eqb rr r) eqn:Heq2.
268+
-- exfalso. apply String.eqb_eq in Heq2. apply Heq. exact Heq2.
269+
-- exact IHHt.
270+
- (* T_Region_Active_L1: ERegion r e (r currently active). *)
271+
destruct (String.eqb rr r) eqn:Heq.
272+
+ (* rr = r: shadowed; Hfree True. Need L1 region-perm to fold the
273+
resulting [r ∈ remove_first r R] cases. Residual. *)
274+
admit.
275+
+ (* rr <> r: descend. *)
276+
apply String.eqb_neq in Heq.
277+
assert (Hgoal_eq : remove_first rr (remove_first_L1 r R_body) =
278+
remove_first_L1 r (remove_first rr R_body)).
279+
{ rewrite (remove_first_eq_l1 r R_body).
280+
rewrite (remove_first_eq_l1 r (remove_first rr R_body)).
281+
apply remove_first_comm. }
282+
rewrite Hgoal_eq.
283+
apply (T_Region_Active_L1 (remove_first rr R) (remove_first rr R_body) G G' r e T).
284+
* apply remove_first_preserves_other; [intro Hbad; apply Heq; exact Hbad | exact H].
285+
* exact H0.
286+
* apply remove_first_preserves_other; [intro Hbad; apply Heq; exact Hbad | exact H1].
287+
* eapply IHHt. exact Hfree.
288+
- (* T_Borrow_L1 *)
289+
eapply T_Borrow_L1. exact H.
290+
- (* T_Borrow_Val_L1 *)
291+
eapply T_Borrow_Val_L1; [exact H | eapply IHHt; auto].
292+
- (* T_Drop_L1 *)
293+
eapply T_Drop_L1; [exact H | eapply IHHt; auto].
294+
- (* T_Copy_L1 *)
295+
eapply T_Copy_L1; [exact H | eapply IHHt; auto].
296+
Admitted.
297+
141298
Lemma region_shrink_preserves_typing_l1 :
142299
forall R G v T R' G' r,
143300
is_value v ->
144301
has_type_l1 R G v T R' G' ->
145302
~ In r (free_regions T) ->
146303
expr_free_of_region r v ->
147304
has_type_l1 (remove_first r R) G v T (remove_first r R') G'.
148-
Admitted.
305+
Proof.
306+
intros R G v T R' G' r Hv Ht HnotT Hfree.
307+
eapply region_shrink_preserves_typing_l1_gen; eauto.
308+
Qed.
149309

150310
(** ** Helper: substitution preserves the L1 typing.
151311

0 commit comments

Comments
 (0)