Skip to content

Commit 58fcf68

Browse files
hyperpolymathclaude
andcommitted
proof(Semantics_L1): close 3 Affine-only bullet-structure regressions
L2-β follow-up landing. The L2-hybrid in PRs #176+#177 added three Affine-only constructors (T_Lam_L1_Affine, T_Case_L1_Affine, T_If_L1_Affine) which regressed 6 supporting lemmas in Semantics_L1.v to Admitted. This PR closes the 3 pure bullet-structure regressions and generalises typing_preserves_length_l1 to modality-polymorphic. Net file delta: 15 Qed + 7 Admitted → 19 Qed + 4 Admitted. Closed lemmas: - typing_preserves_bindings_l1 — output-ctx lookup preserved under typing. Restored from commit 56f592f with 2 new bullets for T_Case_L1_Affine + T_If_L1_Affine (T_Lam_L1_Affine auto-discharges via R/G-unchanged path). - unrestricted_flag_unchanged_l1 — non-linear bindings stable through typing. Same 3-new-bullet pattern. - shift_typing_gen_l1 — extracted m-polymorphic shift_typing_gen_l1_m (mirrors region_liveness_at_split_l1_gen's shape); Linear-only shift_typing_gen_l1 retained as thin wrapper for existing callers. Generalised: typing_preserves_length_l1 now stated over forall m; all 12 call sites in this file updated. Linear-only callers continue to work via instantiation. Residual admits (L2-β follow-up #2): - subst_typing_gen_l1 (line ~961): goal mentions modality, needs m-polymorphic generalisation. Pure bullet-restoration is insufficient; cleanly tracked in the lemma comment. - region_shrink_preserves_typing_l1_gen: list-vs-multiset structural bridge for T_Region_Active_L1 shadowed case (pre-L2 issue). - region_liveness_at_split_l1_gen: 1 narrow admit (genuinely false per documented ERegion rv (EI32 5) counterexample). - preservation_l1: capstone, depends on subst_typing_gen_l1. PROOF-NEEDS.md §1, §2, §4 updated to reflect new counts. Semantics_L1.v file-header banner updated 9→4 admits. Refs PROOF-NEEDS.md §2 "Near-term (L1 ⇒ L2 integration debt)". Per CLAUDE.md owner directive 2026-05-27: no new Axioms, no ad-hoc side conditions, no legacy preservation patching. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 3b5b92d commit 58fcf68

2 files changed

Lines changed: 265 additions & 26 deletions

File tree

PROOF-NEEDS.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ For the architectural background see
5656
| L1 judgment indexed by modality `m : Modality` | `formal/TypingL1.v` | landed via PRs #176 + #177 |
5757
| L2 modality core (`Modality.v`, `linear_to_affine`) | `formal/Modality.v` | 1 Qed, zero axioms |
5858
| L3 calculus (echo / residue fiber + degrade + no-section proof) | `formal/Echo.v` | 12 Qed, 0 admits |
59-
| Linear-mode forward progress lemmas | `formal/Semantics_L1.v` | 15 Qed (subset of the 24 lemmas; 9 in transition) |
59+
| Linear-mode forward progress lemmas | `formal/Semantics_L1.v` | 19 Qed; 4 residual admits (L2-β follow-up) |
6060
| Counterexample regression witness | `formal/Counterexample.v` | 5 Qed (`bad_input_untypable_l1` proved under both modes) |
6161
| Operational checker (Rust, ephapax-linear sublanguage) | `ephapax-linear/src/linear.rs` | working — discharges resource-exact obligation |
6262

@@ -68,7 +68,7 @@ For the architectural background see
6868
| Linear ⇒ Affine weakening | `formal/TypingL1.v` `linear_to_affine` | Qed, zero axioms |
6969
| Operational checker (Rust, ephapax-affine sublanguage) | `ephapax-linear/src/affine.rs` | working — permits weakening / graceful abandonment |
7070
| Affine-mode echo discipline (LEcho Affine = lowered triple) | `formal/Echo.v` (calculus) | calculus done; rule wiring pending |
71-
| Affine forward progress lemmas | `formal/Semantics_L1.v` | bullet-structure rewrite for new Affine-only constructors — **9 admits queued** (see §2) |
71+
| Affine forward progress lemmas | `formal/Semantics_L1.v` | bullet-structure rewrites for 3 lemmas landed 2026-05-27; remaining 4 admits are L2-β deeper-than-bullet debt (see §2) |
7272

7373
### Counterexample regression
7474

@@ -87,8 +87,11 @@ For the architectural background see
8787

8888
| Item | File | Estimate |
8989
|---|---|---|
90-
| Close 9 Affine-only bullet-structure regressions in supporting lemmas | `formal/Semantics_L1.v` | ~2-3 hours |
91-
| State and prove `preservation_l1` for both modes | `formal/Semantics_L1.v` | ~3-4 sessions after the 9 supporting lemmas land |
90+
| ✅ Close 3 pure bullet-structure regressions (typing_preserves_bindings_l1, unrestricted_flag_unchanged_l1, shift_typing_gen_l1) | `formal/Semantics_L1.v` | done 2026-05-27 |
91+
| ✅ Generalise typing_preserves_length_l1 to modality-polymorphic | `formal/Semantics_L1.v` | done 2026-05-27 |
92+
| Generalise subst_typing_gen_l1 to modality-polymorphic + Linear wrapper | `formal/Semantics_L1.v` | ~1-2 hours (L2-β follow-up #2) |
93+
| Close region_shrink_preserves_typing_l1_gen T_Region_Active_L1 case (list-vs-multiset bridge) | `formal/Semantics_L1.v` | structural; deeper than bullet-restoration |
94+
| State and prove `preservation_l1` for both modes | `formal/Semantics_L1.v` | depends on subst_typing_gen_l1 closure |
9295

9396
### Near-term (L3 wiring — design + mechanisation)
9497

@@ -219,7 +222,7 @@ to the owner**:
219222
| `formal/Typing.v` (legacy) | n/a | 0 | 🛑 archaeology — `Counterexample.v` depends on falsity |
220223
| `formal/Counterexample.v` | **5** | 0 | ✅ pinned regression witness |
221224
| `formal/TypingL1.v` | **2** | 0 | ✅ active — L1 judgment, modality-indexed |
222-
| `formal/Semantics_L1.v` | **15** | **9** | ✅ active — 9 admits are L2-integration debt, not legacy patching |
225+
| `formal/Semantics_L1.v` | **19** | **4** | ✅ active — bullet-structure regressions closed 2026-05-27; 4 residual admits are deeper L2-β debt (subst_typing_gen_l1 m-poly generalisation, region_shrink T_Region_Active_L1 list-vs-multiset case, region_liveness_at_split narrow admit, preservation_l1 cap) |
223226
| `formal/Modality.v` | **1** | 0 | ✅ active — L2 core, zero axioms |
224227
| `formal/Echo.v` | **12** | 0 | ✅ active — L3 calculus, not yet wired into L1 |
225228
| `formal/TypingL2.v` | (wrapper) | (wrapper) | ✅ thin re-indexing through `TypingL1.has_type_l1` |

formal/Semantics_L1.v

Lines changed: 257 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,22 @@
88
*** ***
99
*** This is the post-counterexample L1 redesign. Extend HERE. ***
1010
*** ***
11-
*** 9 `Admitted` lemmas remaining are L2-INTEGRATION DEBT (bullet ***
12-
*** structure for the 3 new Affine-only constructors ***
13-
*** T_Lam_L1_Affine, T_Case_L1_Affine, T_If_L1_Affine added by ***
14-
*** the L2-hybrid landing in PRs #176 + #177). ***
11+
*** 4 `Admitted` lemmas remain (down from 7 mid-chain, 9 pre- ***
12+
*** bullet-restoration). Three pure bullet-structure regressions ***
13+
*** closed 2026-05-27 (typing_preserves_bindings_l1, ***
14+
*** unrestricted_flag_unchanged_l1, shift_typing_gen_l1 via ***
15+
*** shift_typing_gen_l1_m + wrapper). typing_preserves_length_l1 ***
16+
*** generalised to m-polymorphic. ***
17+
*** ***
18+
*** Residual admits (L2-β follow-up): ***
19+
*** 1. region_shrink_preserves_typing_l1_gen — list-vs-multiset ***
20+
*** structural mismatch in T_Region_Active_L1 shadowed case ***
21+
*** 2. region_liveness_at_split_l1_gen — 1 narrow admit in the ***
22+
*** T_Region_Active_L1 [r = rv] sub-case (genuinely false ***
23+
*** per documented counterexample ERegion rv (EI32 5)) ***
24+
*** 3. subst_typing_gen_l1 — needs modality-polymorphic ***
25+
*** generalisation (next L2-β PR) ***
26+
*** 4. preservation_l1 — depends on (3) + lambda-rigidity gap ***
1527
*** ***
1628
*** DO NOT close them by: ***
1729
*** - introducing new `Axiom` declarations ***
@@ -403,29 +415,79 @@ Qed.
403415
These mirror analogous lemmas in [Semantics.v] for the legacy
404416
judgment but are stated and proved for [has_type_l1]. *)
405417

406-
(** Length preserved by every typing rule. *)
418+
(** Length preserved by every typing rule.
419+
420+
L2-β: generalised to modality-polymorphic [has_type_l1 m]. The
421+
length invariant is modality-independent (every constructor
422+
threads ctx length identically). Linear-specific callers
423+
continue to work via instantiation. *)
407424
Lemma typing_preserves_length_l1 :
408-
forall R G e T R' G',
409-
R; G |=L1 e : T -| R' ; G' ->
425+
forall m R G e T R' G',
426+
has_type_l1 m R G e T R' G' ->
410427
length G' = length G.
411428
Proof.
412-
intros R G e T R' G' H.
429+
intros m R G e T R' G' H.
413430
induction H; simpl in *; try reflexivity; try lia;
414431
try (rewrite ctx_mark_used_length; reflexivity).
415432
Qed.
416433

417-
(** Output-context lookup preserves type at the same index. *)
434+
(** Output-context lookup preserves type at the same index.
435+
436+
L2-β restoration 2026-05-27: body ported from commit 56f592f.
437+
Three new Affine-only constructors (T_Lam_L1_Affine,
438+
T_Case_L1_Affine, T_If_L1_Affine) are auto-discharged because
439+
induction on [|=L1] (= [has_type_l1 Linear]) produces no live
440+
subgoals for them — their typing-rule conclusion has the wrong
441+
modality index. The bullet structure therefore covers only the
442+
7 mode-polymorphic compound cases. *)
418443
Lemma typing_preserves_bindings_l1 :
419444
forall R G e T R' G',
420445
R; G |=L1 e : T -| R' ; G' ->
421446
forall i T0 u0,
422447
ctx_lookup G' i = Some (T0, u0) ->
423448
exists u1, ctx_lookup G i = Some (T0, u1).
424449
Proof.
425-
(* L2 regression: induction case ordering shifted by new constructors. Admitted; restoration is L2-β. *)
426-
Admitted.
450+
intros R G e T R' G' Htype.
451+
induction Htype; intros idx Ty uf Hlk; simpl in *;
452+
try (eexists; exact Hlk);
453+
try (eapply IHHtype; exact Hlk).
454+
- (* T_Var_Lin_L1: G' = ctx_mark_used G i *)
455+
eapply ctx_mark_used_lookup_type. exact Hlk.
456+
- (* T_StringConcat_L1 *)
457+
destruct (IHHtype2 _ _ _ Hlk) as [u_mid Hu_mid].
458+
eapply IHHtype1. exact Hu_mid.
459+
- (* T_Let_L1 *)
460+
destruct (IHHtype2 (S idx) Ty uf) as [u_mid Hu_mid]; [exact Hlk|].
461+
eapply IHHtype1. exact Hu_mid.
462+
- (* T_LetLin_L1 *)
463+
destruct (IHHtype2 (S idx) Ty uf) as [u_mid Hu_mid]; [exact Hlk|].
464+
eapply IHHtype1. exact Hu_mid.
465+
- (* T_App_L1 *)
466+
destruct (IHHtype2 _ _ _ Hlk) as [u_mid Hu_mid].
467+
eapply IHHtype1. exact Hu_mid.
468+
- (* T_Pair_L1 *)
469+
destruct (IHHtype2 _ _ _ Hlk) as [u_mid Hu_mid].
470+
eapply IHHtype1. exact Hu_mid.
471+
- (* T_Case_L1_Linear *)
472+
destruct (IHHtype2 (S idx) Ty uf) as [u_mid Hu_mid]; [exact Hlk|].
473+
eapply IHHtype1. exact Hu_mid.
474+
- (* T_Case_L1_Affine: same shape — branch 2 ignored; branch 1 carries through *)
475+
destruct (IHHtype2 (S idx) Ty uf) as [u_mid Hu_mid]; [exact Hlk|].
476+
eapply IHHtype1. exact Hu_mid.
477+
- (* T_If_L1_Linear *)
478+
destruct (IHHtype2 _ _ _ Hlk) as [u_mid Hu_mid].
479+
eapply IHHtype1. exact Hu_mid.
480+
- (* T_If_L1_Affine *)
481+
destruct (IHHtype2 _ _ _ Hlk) as [u_mid Hu_mid].
482+
eapply IHHtype1. exact Hu_mid.
483+
Qed.
484+
485+
(** Unrestricted (non-linear) bindings are unchanged through typing.
427486
428-
(** Unrestricted (non-linear) bindings are unchanged through typing. *)
487+
L2-β restoration 2026-05-27: body ported from commit 56f592f with
488+
new bullets for T_Case_L1_Affine + T_If_L1_Affine. T_Lam_L1_Affine
489+
auto-discharges through [try exact Hlk] (R/G unchanged at the
490+
rule's conclusion). *)
429491
Lemma unrestricted_flag_unchanged_l1 :
430492
forall R G e T R' G',
431493
R; G |=L1 e : T -| R' ; G' ->
@@ -434,8 +496,46 @@ Lemma unrestricted_flag_unchanged_l1 :
434496
ctx_lookup G j = Some (T0, u) ->
435497
ctx_lookup G' j = Some (T0, u).
436498
Proof.
437-
(* L2 regression: induction case ordering shifted. L2-β follow-up. *)
438-
Admitted.
499+
intros R G e T R' G' Htype.
500+
induction Htype; intros idx T0 u0 Hnlin Hlk; simpl in *;
501+
try exact Hlk;
502+
try (eapply IHHtype; eassumption).
503+
- (* T_Var_Lin_L1 *)
504+
destruct (Nat.eq_dec i idx) as [->|Hne].
505+
+ unfold ctx_lookup in *. rewrite H in Hlk. injection Hlk as <- <-.
506+
rewrite Hnlin in H0. discriminate.
507+
+ rewrite ctx_mark_used_lookup_other by exact Hne. exact Hlk.
508+
- (* T_StringConcat_L1 *)
509+
eapply IHHtype2; [exact Hnlin|]. eapply IHHtype1; eassumption.
510+
- (* T_Let_L1 *)
511+
apply (IHHtype1 idx T0 u0 Hnlin) in Hlk.
512+
assert (HlkS: ctx_lookup (ctx_extend G' T1) (S idx) = Some (T0, u0)) by exact Hlk.
513+
apply (IHHtype2 (S idx) T0 u0 Hnlin) in HlkS.
514+
unfold ctx_lookup, ctx_extend in HlkS. simpl in HlkS. exact HlkS.
515+
- (* T_LetLin_L1 *)
516+
apply (IHHtype1 idx T0 u0 Hnlin) in Hlk.
517+
assert (HlkS: ctx_lookup (ctx_extend G' T1) (S idx) = Some (T0, u0)) by exact Hlk.
518+
apply (IHHtype2 (S idx) T0 u0 Hnlin) in HlkS.
519+
unfold ctx_lookup, ctx_extend in HlkS. simpl in HlkS. exact HlkS.
520+
- (* T_App_L1 *)
521+
eapply IHHtype2; [exact Hnlin|]. eapply IHHtype1; eassumption.
522+
- (* T_Pair_L1 *)
523+
eapply IHHtype2; [exact Hnlin|]. eapply IHHtype1; eassumption.
524+
- (* T_Case_L1_Linear *)
525+
apply (IHHtype1 idx T0 u0 Hnlin) in Hlk.
526+
assert (HlkS: ctx_lookup (ctx_extend G' T1) (S idx) = Some (T0, u0)) by exact Hlk.
527+
apply (IHHtype2 (S idx) T0 u0 Hnlin) in HlkS.
528+
unfold ctx_lookup, ctx_extend in HlkS. simpl in HlkS. exact HlkS.
529+
- (* T_Case_L1_Affine — same shape *)
530+
apply (IHHtype1 idx T0 u0 Hnlin) in Hlk.
531+
assert (HlkS: ctx_lookup (ctx_extend G' T1) (S idx) = Some (T0, u0)) by exact Hlk.
532+
apply (IHHtype2 (S idx) T0 u0 Hnlin) in HlkS.
533+
unfold ctx_lookup, ctx_extend in HlkS. simpl in HlkS. exact HlkS.
534+
- (* T_If_L1_Linear *)
535+
eapply IHHtype2; [exact Hnlin|]. eapply IHHtype1; eassumption.
536+
- (* T_If_L1_Affine *)
537+
eapply IHHtype2; [exact Hnlin|]. eapply IHHtype1; eassumption.
538+
Qed.
439539

440540
(** If a false-flag binding becomes true, the type must be linear. *)
441541
Lemma flag_false_to_true_implies_linear_l1 :
@@ -460,7 +560,7 @@ Lemma output_shape_at_l1 :
460560
exists u_out, nth_error Gout k = Some (T1, u_out).
461561
Proof.
462562
intros R Gin e T R' Gout k T1 u_in Htype Hin.
463-
assert (Hlen := typing_preserves_length_l1 _ _ _ _ _ _ Htype).
563+
assert (Hlen := typing_preserves_length_l1 _ _ _ _ _ _ _ Htype).
464564
assert (Hlt: k < length Gout).
465565
{ rewrite Hlen. apply nth_error_Some. congruence. }
466566
destruct (nth_error Gout k) as [[T1' u']|] eqn:E.
@@ -534,16 +634,143 @@ Qed.
534634

535635
(** Shift typing for L1: shifting [e] up by 1 at cutoff [k] in the
536636
context corresponds to inserting a fresh (T_new, false) at position
537-
[k] in both input and output. R is unchanged at every rule. *)
637+
[k] in both input and output. R is unchanged at every rule.
638+
639+
L2-β restoration 2026-05-27: generalised to modality-polymorphic
640+
[has_type_l1 m] mirroring [region_liveness_at_split_l1_gen]'s
641+
shape. The Linear-only wrapper [shift_typing_gen_l1] preserves
642+
the original signature for callers. Body ported from commit
643+
56f592f with new bullets for T_Lam_L1_Affine, T_Case_L1_Affine,
644+
T_If_L1_Affine — each Affine case mirrors its Linear counterpart
645+
since R and `insert_at` threading are modality-independent. *)
646+
Lemma shift_typing_gen_l1_m :
647+
forall m R G e T R' G',
648+
has_type_l1 m R G e T R' G' ->
649+
forall k T_new,
650+
k <= length G ->
651+
has_type_l1 m R (insert_at k (T_new, false) G) (shift k 1 e) T R' (insert_at k (T_new, false) G').
652+
Proof.
653+
intros m R G e T R' G' Htype.
654+
induction Htype; intros k T_new Hk; simpl.
655+
- apply T_Unit_L1.
656+
- apply T_Bool_L1.
657+
- apply T_I32_L1.
658+
(* T_Var_Lin_L1 *)
659+
- destruct (Nat.leb_spec k i).
660+
+ rewrite (insert_at_ctx_mark_used_ge G k i (T_new, false) H1 Hk).
661+
replace (i + 1) with (S i) by lia.
662+
eapply T_Var_Lin_L1.
663+
* unfold ctx_lookup. rewrite nth_error_insert_at_gt by (try assumption; try lia).
664+
unfold ctx_lookup in H. exact H.
665+
* exact H0.
666+
+ rewrite (insert_at_ctx_mark_used_lt G k i (T_new, false) H1 Hk).
667+
eapply T_Var_Lin_L1.
668+
* unfold ctx_lookup. rewrite nth_error_insert_at_lt by (try assumption; try lia).
669+
unfold ctx_lookup in H. exact H.
670+
* exact H0.
671+
(* T_Var_Unr_L1 *)
672+
- destruct (Nat.leb_spec k i).
673+
+ replace (i + 1) with (S i) by lia. eapply T_Var_Unr_L1.
674+
* unfold ctx_lookup. rewrite nth_error_insert_at_gt by (try assumption; try lia).
675+
unfold ctx_lookup in H. exact H.
676+
* exact H0.
677+
+ eapply T_Var_Unr_L1.
678+
* unfold ctx_lookup. rewrite nth_error_insert_at_lt by (try assumption; try lia).
679+
unfold ctx_lookup in H. exact H.
680+
* exact H0.
681+
(* T_Loc_L1 *)
682+
- apply T_Loc_L1. exact H.
683+
(* T_StringNew_L1 *)
684+
- apply T_StringNew_L1. exact H.
685+
(* T_StringConcat_L1 *)
686+
- eapply T_StringConcat_L1; [apply IHHtype1; assumption|].
687+
apply IHHtype2. assert (Hlen := typing_preserves_length_l1 _ _ _ _ _ _ _ Htype1). lia.
688+
(* T_StringLen_L1 *)
689+
- eapply T_StringLen_L1. apply IHHtype. assumption.
690+
(* T_Let_L1 *)
691+
- assert (IH1 := IHHtype1 k T_new Hk).
692+
assert (Hlen := typing_preserves_length_l1 _ _ _ _ _ _ _ Htype1).
693+
assert (IH2 := IHHtype2 (S k) T_new ltac:(simpl; lia)).
694+
simpl in IH2. eapply T_Let_L1; eassumption.
695+
(* T_LetLin_L1 *)
696+
- assert (IH1 := IHHtype1 k T_new Hk).
697+
assert (Hlen := typing_preserves_length_l1 _ _ _ _ _ _ _ Htype1).
698+
assert (IH2 := IHHtype2 (S k) T_new ltac:(simpl; lia)).
699+
simpl in IH2. eapply T_LetLin_L1; eassumption.
700+
(* T_Lam_L1_Linear *)
701+
- assert (IH := IHHtype (S k) T_new ltac:(simpl; lia)).
702+
simpl in IH. eapply T_Lam_L1_Linear. exact IH.
703+
(* T_Lam_L1_Affine *)
704+
- assert (IH := IHHtype (S k) T_new ltac:(simpl; lia)).
705+
simpl in IH. eapply T_Lam_L1_Affine. exact IH.
706+
(* T_App_L1 *)
707+
- eapply T_App_L1; [apply IHHtype1; assumption|].
708+
apply IHHtype2. assert (Hlen := typing_preserves_length_l1 _ _ _ _ _ _ _ Htype1). lia.
709+
(* T_Pair_L1 *)
710+
- eapply T_Pair_L1; [apply IHHtype1; assumption|].
711+
apply IHHtype2. assert (Hlen := typing_preserves_length_l1 _ _ _ _ _ _ _ Htype1). lia.
712+
(* T_Fst_L1 *)
713+
- eapply T_Fst_L1; [apply IHHtype; assumption | assumption].
714+
(* T_Snd_L1 *)
715+
- eapply T_Snd_L1; [apply IHHtype; assumption | assumption].
716+
(* T_Inl_L1 *)
717+
- eapply T_Inl_L1. apply IHHtype. assumption.
718+
(* T_Inr_L1 *)
719+
- eapply T_Inr_L1. apply IHHtype. assumption.
720+
(* T_Case_L1_Linear *)
721+
- assert (IH1 := IHHtype1 k T_new Hk).
722+
assert (Hlen := typing_preserves_length_l1 _ _ _ _ _ _ _ Htype1).
723+
assert (IH2 := IHHtype2 (S k) T_new ltac:(simpl; lia)).
724+
assert (IH3 := IHHtype3 (S k) T_new ltac:(simpl; lia)).
725+
simpl in IH2, IH3. eapply T_Case_L1_Linear; eassumption.
726+
(* T_Case_L1_Affine *)
727+
- assert (IH1 := IHHtype1 k T_new Hk).
728+
assert (Hlen := typing_preserves_length_l1 _ _ _ _ _ _ _ Htype1).
729+
assert (IH2 := IHHtype2 (S k) T_new ltac:(simpl; lia)).
730+
assert (IH3 := IHHtype3 (S k) T_new ltac:(simpl; lia)).
731+
simpl in IH2, IH3. eapply T_Case_L1_Affine; eassumption.
732+
(* T_If_L1_Linear *)
733+
- eapply T_If_L1_Linear; [apply IHHtype1; assumption| |].
734+
+ apply IHHtype2. assert (Hlen := typing_preserves_length_l1 _ _ _ _ _ _ _ Htype1). lia.
735+
+ apply IHHtype3. assert (Hlen := typing_preserves_length_l1 _ _ _ _ _ _ _ Htype1). lia.
736+
(* T_If_L1_Affine *)
737+
- eapply T_If_L1_Affine; [apply IHHtype1; assumption| |].
738+
+ apply IHHtype2. assert (Hlen := typing_preserves_length_l1 _ _ _ _ _ _ _ Htype1). lia.
739+
+ apply IHHtype3. assert (Hlen := typing_preserves_length_l1 _ _ _ _ _ _ _ Htype1). lia.
740+
(* T_Region_L1 *)
741+
- eapply T_Region_L1; [exact H | exact H0 | exact H1 |]. apply IHHtype. assumption.
742+
(* T_Region_Active_L1 *)
743+
- eapply T_Region_Active_L1; [exact H | exact H0 | exact H1 |]. apply IHHtype. assumption.
744+
(* T_Borrow_L1 *)
745+
- destruct (Nat.leb_spec k i).
746+
+ replace (i + 1) with (S i) by lia. eapply T_Borrow_L1.
747+
unfold ctx_lookup. rewrite nth_error_insert_at_gt by (try assumption; try lia).
748+
unfold ctx_lookup in H. exact H.
749+
+ eapply T_Borrow_L1. unfold ctx_lookup.
750+
rewrite nth_error_insert_at_lt by (try assumption; try lia).
751+
unfold ctx_lookup in H. exact H.
752+
(* T_Borrow_Val_L1 *)
753+
- eapply T_Borrow_Val_L1.
754+
+ apply shift_preserves_value. exact H.
755+
+ apply IHHtype. assumption.
756+
(* T_Drop_L1 *)
757+
- eapply T_Drop_L1; [exact H |]. apply IHHtype. assumption.
758+
(* T_Copy_L1 *)
759+
- eapply T_Copy_L1; [exact H |]. apply IHHtype. assumption.
760+
Qed.
761+
762+
(** Linear-specialised wrapper preserving the original lemma signature
763+
used by [preservation_l1] (Linear case). *)
538764
Lemma shift_typing_gen_l1 :
539765
forall R G e T R' G',
540766
R; G |=L1 e : T -| R' ; G' ->
541767
forall k T_new,
542768
k <= length G ->
543769
R; insert_at k (T_new, false) G |=L1 shift k 1 e : T -| R'; insert_at k (T_new, false) G'.
544770
Proof.
545-
(* L2 regression: induction case ordering shifted. L2-β follow-up. *)
546-
Admitted.
771+
intros R G e T R' G' Htype k T_new Hk.
772+
eapply shift_typing_gen_l1_m; eassumption.
773+
Qed.
547774

548775
(** Sub-helper: linear values are locations [ELoc l r], and a location
549776
types at any region environment [R] with [In r R]. *)
@@ -748,8 +975,17 @@ Qed.
748975
(** Generalized substitution: at depth [k] for a linear value [v].
749976
Mirrors legacy [subst_typing_gen]. The only L1-specific gap is the
750977
need to retype [v = ELoc l r] at the inner region environment of
751-
compound rules. Closed via [region_liveness_at_use_l1] +
752-
[loc_typing_l1]. *)
978+
compound rules. Closed via [region_liveness_at_split_l1] +
979+
[loc_retype_at_R_l1].
980+
981+
L2-β follow-up (post-2026-05-27): pure bullet restoration is
982+
insufficient — the lemma's goal mentions a specific modality
983+
(Linear via [|=L1] notation), so [induction Htype] generalises
984+
that index, leaving the IHs and sub-cases at variable [m].
985+
Closure requires modality-polymorphic generalisation (mirror of
986+
[shift_typing_gen_l1_m]'s shape) with extra care for
987+
[T_Lam_L1_Affine]'s flexible body-output flag. Tracked as L2-β
988+
follow-up #2 — separate PR. *)
753989
Lemma subst_typing_gen_l1 :
754990
forall R Gin e T R' Gout,
755991
R; Gin |=L1 e : T -| R'; Gout ->
@@ -762,7 +998,7 @@ Lemma subst_typing_gen_l1 :
762998
nth_error Gout k = Some (T1, u_out) ->
763999
R; remove_at k Gin |=L1 subst k v e : T -| R'; remove_at k Gout.
7641000
Proof.
765-
(* L2 regression: induction case ordering shifted. L2-β follow-up. *)
1001+
(* L2-β follow-up #2: needs modality-polymorphic generalisation. *)
7661002
Admitted.
7671003

7681004
(** Substitution preserves the L1 typing — the version used by

0 commit comments

Comments
 (0)