|
| 1 | +(* SPDX-License-Identifier: PMPL-1.0-or-later *) |
| 2 | +(* SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell *) |
| 3 | + |
| 4 | +(** * Soundness gap (L2): preservation_l2 fails for nested-TFunEff |
| 5 | + substituends — the gap Phase 3b Stage 1's [tfuneff_lambda_free] |
| 6 | + precondition correctly EXCLUDES. |
| 7 | +
|
| 8 | + Sibling artifact to [Counterexample_L2.v]. That earlier file |
| 9 | + witnessed the soundness gap for TFunEff substituends crossing |
| 10 | + a fresh-region scope ([ERegion]). This file witnesses a |
| 11 | + DIFFERENT gap class: TFunEff substituends placed inside an |
| 12 | + inner [TFunEff] lambda whose declared [R_in_inner] is too |
| 13 | + small to accommodate the substituent's required formation env. |
| 14 | +
|
| 15 | + The two together justify the **two**-condition statement of |
| 16 | + Phase 3b Stage 1's [preservation_l2_app_eff_beta_tfuneff_l1]: |
| 17 | +
|
| 18 | + (P1) [tfuneff_lambda_free ebody = true] |
| 19 | + — rules out THIS counterexample's class (inner lambda) |
| 20 | + (P2) [regions_introduced_by ebody ⊆ R_in_v] |
| 21 | + — rules out [Counterexample_L2.v]'s class (fresh region) |
| 22 | +
|
| 23 | + Stage 2 (#240) lifts (P1) by carrying [R_in / R_out] on [ELam]. |
| 24 | + Stage 3 (#241) replaces (P1) with a CPS-style proof that closes |
| 25 | + the inner-lambda case via a relaxed [declared_lambda_r_ins ⊆ R_in_v] |
| 26 | + obligation. Stage 4 (#242) reaches an unconditional preservation_l2. |
| 27 | +
|
| 28 | + ===== Configuration ===== |
| 29 | +
|
| 30 | + T_v := TFunEff TUnit TUnit [] [] (* substituent type, R_in_v = [] *) |
| 31 | + v := ELam TUnit EUnit (* value of type T_v *) |
| 32 | + inner_body := ELam TUnit (EVar 1) (* inner lambda; body refs outer var *) |
| 33 | + T_inner := TFunEff TUnit T_v [r2] [r2] (* inner lambda's annotated type *) |
| 34 | + outer := ELam T_v inner_body (* outer lambda; param of type T_v *) |
| 35 | + T_outer := TFunEff T_v T_inner [] [] (* outer type *) |
| 36 | + e_before := EApp outer v (* well-typed via T_App_L2_Eff at R = [] *) |
| 37 | + e_after := ELam TUnit v (* β-result: subst 0 v inner_body *) |
| 38 | +
|
| 39 | + ===== Why this configuration witnesses the gap ===== |
| 40 | +
|
| 41 | + Pre-β [outer] is well-typed because the inner lambda's body |
| 42 | + [EVar 1] references the outer variable (de-Bruijn index 1 |
| 43 | + skipping the inner binder) at type [T_v]. Per [T_Var_Unr_L1] |
| 44 | + on a non-linear type ([is_linear_ty T_v = false]), the reference |
| 45 | + types at any region env; in particular at [R_in_inner = [r2]]. |
| 46 | + Side condition [R_in_outer ⊆ R_in_inner] passes vacuously when |
| 47 | + [R_in_outer = []]. |
| 48 | +
|
| 49 | + Post-β substitutes [v] for the outer variable. The inner lambda |
| 50 | + body becomes [shift 0 1 v = v] (closed value). So |
| 51 | + [e_after = ELam TUnit v]. For [e_after] to type at [T_inner], |
| 52 | + [v] would need to retype at [R = [r2]] via [T_Lam_L1_*_Eff], |
| 53 | + which requires [[r2] ⊆ R_in_v = []]. This fails on [r2 ∈ [r2]] |
| 54 | + vs. [r2 ∉ []]. |
| 55 | +
|
| 56 | + The structural mechanism: [tfuneff_lambda_retype_l1_m] |
| 57 | + (Semantics_L1.v:1257) carries the obligation [R' ⊆ R_in_v]; |
| 58 | + inside a nested [TFunEff] lambda the [R'] is the INNER |
| 59 | + [R_in_inner], not the OUTER formation env — and inner [R_in] |
| 60 | + annotations are invisible to Phase 3b Stage 1's syntactic |
| 61 | + [regions_introduced_by] over-approximation. Stage 1 therefore |
| 62 | + refuses ebody-with-inner-lambdas via [tfuneff_lambda_free]. |
| 63 | +
|
| 64 | + ===== Three theorems ===== |
| 65 | +
|
| 66 | + - [e_before_typed] — outer at [T_outer] via T_Lam_L1_Affine_Eff |
| 67 | + cascaded with inner; full e_before via T_App_L2_Eff. |
| 68 | + - [e_step] — operational [S_App_Fun] β-reduction. |
| 69 | + - [e_after_untypable] — no L1 derivation exists for e_after at |
| 70 | + T_inner. Inversion forces [T_Lam_L1_*_Eff] |
| 71 | + (only formation rule producing TFunEff); |
| 72 | + both modes' side condition |
| 73 | + [forall r, In r [r2] -> In r []] is |
| 74 | + contradicted by [In r2 [r2]]. |
| 75 | +
|
| 76 | + ===== Owner-directive compliance ===== |
| 77 | +
|
| 78 | + - Does not modify [Semantics.v] or [Counterexample.v] (legacy |
| 79 | + soundness-gap artifacts). |
| 80 | + - Does not patch [Typing.v]. |
| 81 | + - Does not close any residual [Semantics_L1.v] admit. |
| 82 | + - Adds NEW infrastructure (a new file in [formal/]) orthogonal |
| 83 | + to legacy admits, mirroring the precedent of [Counterexample.v] |
| 84 | + for the legacy preservation and [Counterexample_L2.v] for the |
| 85 | + fresh-region soundness-gap class. |
| 86 | + - No new [Axiom] or [Admitted] markers. *) |
| 87 | + |
| 88 | +From Ephapax Require Import Syntax Typing TypingL1 Modality Semantics Semantics_L1 TypingL2. |
| 89 | +Require Import Coq.Strings.String. |
| 90 | +Require Import Coq.Lists.List. |
| 91 | +Import ListNotations. |
| 92 | +Open Scope string_scope. |
| 93 | + |
| 94 | +Section CounterexampleL2Nested. |
| 95 | + |
| 96 | + Definition r2 : region_name := "r2". |
| 97 | + |
| 98 | + (** Substituent type — a TFunEff lambda with empty input region env. *) |
| 99 | + Definition T_v : ty := |
| 100 | + TFunEff (TBase TUnit) (TBase TUnit) [] []. |
| 101 | + |
| 102 | + (** Substituent value — a closed [TUnit -> TUnit] lambda. *) |
| 103 | + Definition v : expr := |
| 104 | + ELam (TBase TUnit) EUnit. |
| 105 | + |
| 106 | + (** Inner lambda type — annotated with [R_in = R_out = [r2]]. *) |
| 107 | + Definition T_inner : ty := |
| 108 | + TFunEff (TBase TUnit) T_v [r2] [r2]. |
| 109 | + |
| 110 | + (** Inner lambda body — references the outer-bound variable via |
| 111 | + [EVar 1] (de Bruijn index 1 skips the inner [ELam] binder). *) |
| 112 | + Definition inner_body : expr := |
| 113 | + ELam (TBase TUnit) (EVar 1). |
| 114 | + |
| 115 | + (** Outer lambda — parameter of type [T_v], body is [inner_body]. *) |
| 116 | + Definition outer : expr := |
| 117 | + ELam T_v inner_body. |
| 118 | + |
| 119 | + (** Outer lambda's type. *) |
| 120 | + Definition T_outer : ty := |
| 121 | + TFunEff T_v T_inner [] []. |
| 122 | + |
| 123 | + Definition e_before : expr := EApp outer v. |
| 124 | + |
| 125 | + (** Post-β term: [subst 0 v (ELam TUnit (EVar 1))] |
| 126 | + = [ELam TUnit (subst 1 (shift 0 1 v) (EVar 1))] |
| 127 | + = [ELam TUnit (shift 0 1 v)] (* EVar 1 substitutes to shift 0 1 v *) |
| 128 | + = [ELam TUnit v] (* v is a closed value, shift is identity on its body *) *) |
| 129 | + Definition e_after : expr := ELam (TBase TUnit) v. |
| 130 | + |
| 131 | + (** Helper: [v] types at [T_v] at any sufficiently small R. *) |
| 132 | + |
| 133 | + Lemma v_typed_at_empty : |
| 134 | + has_type_l1 Affine [] [] v T_v [] []. |
| 135 | + Proof. |
| 136 | + unfold v, T_v. |
| 137 | + eapply T_Lam_L1_Affine_Eff with (u := false). |
| 138 | + - intros r Hr; inversion Hr. |
| 139 | + - apply T_Unit_L1. |
| 140 | + Qed. |
| 141 | + |
| 142 | + (** Outer lambda is well-typed at [T_outer]. *) |
| 143 | + |
| 144 | + Lemma outer_typed : |
| 145 | + has_type_l1 Affine [] [] outer T_outer [] []. |
| 146 | + Proof. |
| 147 | + unfold outer, T_outer, T_inner, inner_body. |
| 148 | + eapply T_Lam_L1_Affine_Eff with (u := false). |
| 149 | + - intros r Hr; inversion Hr. |
| 150 | + - (* Inner lambda formation at outer body context. |
| 151 | + Outer body context: [ctx_extend [] T_v = (T_v, false) :: []]. |
| 152 | + Inner lambda forms at TFunEff (TBase TUnit) T_v [r2] [r2]. *) |
| 153 | + eapply T_Lam_L1_Affine_Eff with (u := false). |
| 154 | + + intros r Hr; inversion Hr. |
| 155 | + + (* Body of inner: [EVar 1] at R = [r2], context = |
| 156 | + ctx_extend ((T_v, false) :: []) (TBase TUnit) |
| 157 | + = ((TBase TUnit, false) :: (T_v, false) :: []). |
| 158 | + [EVar 1] looks up [T_v] at index 1; output type [T_v]. *) |
| 159 | + eapply T_Var_Unr_L1. |
| 160 | + * unfold ctx_lookup. simpl. reflexivity. |
| 161 | + * reflexivity. |
| 162 | + Qed. |
| 163 | + |
| 164 | + (** ===== (a) e_before is well-typed via T_App_L2_Eff ===== *) |
| 165 | + |
| 166 | + Lemma e_before_typed : |
| 167 | + has_type_l2 Affine [] [] e_before T_inner [] []. |
| 168 | + Proof. |
| 169 | + unfold e_before. |
| 170 | + eapply T_App_L2_Eff. |
| 171 | + - apply L2_lift_l1. exact outer_typed. |
| 172 | + - apply L2_lift_l1. exact v_typed_at_empty. |
| 173 | + Qed. |
| 174 | + |
| 175 | + (** ===== (b) The β-step from e_before to e_after ===== |
| 176 | +
|
| 177 | + [subst 0 v (ELam TUnit (EVar 1))] |
| 178 | + = [ELam TUnit (subst 1 (shift 0 1 v) (EVar 1))] (* binder descent *) |
| 179 | + = [ELam TUnit (shift 0 1 v)] (* EVar 1 substitutes *) |
| 180 | +
|
| 181 | + We need [shift 0 1 v = v]. Since [v = ELam TUnit EUnit] and |
| 182 | + [shift c d (ELam T0 e0) = ELam T0 (shift (S c) 1 e0)], we get |
| 183 | + [shift 0 1 (ELam TUnit EUnit) = ELam TUnit (shift 1 1 EUnit) = |
| 184 | + ELam TUnit EUnit = v]. *) |
| 185 | + |
| 186 | + Lemma e_step : |
| 187 | + forall mu, step (mu, [], e_before) (mu, [], e_after). |
| 188 | + Proof. |
| 189 | + intros mu. unfold e_before, e_after, outer, inner_body. |
| 190 | + change (ELam (TBase TUnit) v) |
| 191 | + with (subst 0 v (ELam (TBase TUnit) (EVar 1))). |
| 192 | + apply S_App_Fun. unfold v. apply VLam. |
| 193 | + Qed. |
| 194 | + |
| 195 | + (** ===== (c) e_after does NOT type at T_inner ===== |
| 196 | +
|
| 197 | + No L1 derivation exists for [[] ; [] |=L1[Affine] e_after : |
| 198 | + T_inner -| ?R_out; ?G_out]. |
| 199 | +
|
| 200 | + Proof by inversion: e_after = ELam (TBase TUnit) v is an [ELam] |
| 201 | + whose annotated TFunEff type carries [R_in = [r2]]. Only |
| 202 | + [T_Lam_L1_Linear_Eff] and [T_Lam_L1_Affine_Eff] produce |
| 203 | + TFunEff types ([T_Lam_L1_Linear] and [T_Lam_L1_Affine] produce |
| 204 | + [TFun], discriminated). Both _Eff rules form the body of e_after |
| 205 | + ([v]) at [R = R_in = [r2]] and require [v] to type at |
| 206 | + [TFunEff (TBase TUnit) (TBase TUnit) [] []]; the body |
| 207 | + [v = ELam (TBase TUnit) EUnit] re-enters [T_Lam_L1_*_Eff], |
| 208 | + whose side condition [forall r, In r [r2] -> In r []] is |
| 209 | + contradicted by [In r2 [r2]]. *) |
| 210 | + |
| 211 | + Lemma e_after_untypable : |
| 212 | + forall R_out G_out, |
| 213 | + ~ has_type_l1 Affine [] [] e_after T_inner R_out G_out. |
| 214 | + Proof. |
| 215 | + intros R_out G_out Ht. |
| 216 | + unfold e_after, T_inner, v in Ht. |
| 217 | + inversion Ht; subst. |
| 218 | + (* Only T_Lam_L1_Affine_Eff survives (mode matches, output type |
| 219 | + structure matches). The body [ELam (TBase TUnit) EUnit] at |
| 220 | + [R = [r2]] must produce a TFunEff. *) |
| 221 | + match goal with |
| 222 | + | [ Hbody : has_type_l1 _ (r2 :: nil) _ |
| 223 | + (ELam (TBase TUnit) EUnit) _ _ _ |- _ ] => |
| 224 | + rename Hbody into Hv_inner |
| 225 | + end. |
| 226 | + inversion Hv_inner; subst. |
| 227 | + (* Only T_Lam_L1_Affine_Eff survives — T_Lam_L1_Affine produces |
| 228 | + TFun (discriminated against output type |
| 229 | + TFunEff (TBase TUnit) (TBase TUnit) [] []). *) |
| 230 | + match goal with |
| 231 | + | [ Hside : forall r, In r (r2 :: nil) -> In r nil |- _ ] => |
| 232 | + specialize (Hside r2 (or_introl eq_refl)); inversion Hside |
| 233 | + end. |
| 234 | + Qed. |
| 235 | + |
| 236 | + (** ===== Soundness-gap witness ===== |
| 237 | +
|
| 238 | + The three lemmas above ([e_before_typed] + [e_step] + |
| 239 | + [e_after_untypable]) jointly witness preservation_l2's failure |
| 240 | + for the nested-TFunEff substituent class. No top-level |
| 241 | + conjunction theorem is stated for the same Type/Prop-sort reason |
| 242 | + documented in [Counterexample_L2.v]. *) |
| 243 | + |
| 244 | +End CounterexampleL2Nested. |
0 commit comments