Skip to content

Commit 1ece331

Browse files
hyperpolymathclaude
andcommitted
syntax: expr_strictly_free_of_region (closes blocker 5)
Reformulates the region-freedom predicate to drop the shadow short- circuit in [ERegion r' body], which the 2026-05-28 audit (task #29) identified as the cause of blocker 5 (predicate-too-weak in L1 region-shrinkage lemma family). Changes: * formal/Syntax.v - new Fixpoint expr_strictly_free_of_region : same shape as expr_free_of_region except the [ERegion _ body] case recurses UNCONDITIONALLY (no String.eqb shadow short-circuit). - new Lemma expr_strictly_free_implies_free : Qed via structural induction. Trivial implication establishing the strict variant is a conservative strengthening. * formal/Semantics_L1.v - migrate preconditions of region_shrink_preserves_typing_l1_gen_m, region_shrink_preserves_typing_l1_gen, region_shrink_preserves_typing_l1, preservation_l3_region_active_echo, and preservation_l3 from expr_free_of_region to expr_strictly_free_of_region. - update the [T_Region_L1] / [T_Region_L1_Echo] rr<>r descend sub-cases' IH-discharge comments (proof body uses the same simpl + destruct pattern, now with strict Hfree). Audit constraints honored: * Zero new Admitted or Axiom declarations (4 admits / 3 Admitted preserved exactly per main). * The shadowed sub-case admits at Semantics_L1.v:553/621 REMAIN — they are blocked by list-vs-multiset structural mismatch (Phase D work), NOT by predicate weakness. The strict variant does NOT close them. * No patching of legacy Theorem preservation in Semantics.v (false per Counterexample.v) or the legacy Typing.v judgment. Out of scope (follow-up): * The step rules S_Region_Exit / S_Region_Exit_Echo in Semantics.v still emit the weak expr_free_of_region premise. Migrating those to strict is a separate concern (legacy operational semantics) and intentionally NOT done here per task instruction. Build: all 9 .v files compile clean under coqc 8.18.0 from a fresh .vo state. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 8747d89 commit 1ece331

2 files changed

Lines changed: 120 additions & 8 deletions

File tree

formal/Semantics_L1.v

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -428,11 +428,21 @@ Qed.
428428
(analog of [region_env_perm_typing] and [region_add_typing])
429429
is needed to close it; bridging options are listed in the
430430
case's own comment. *)
431+
(** Migrated to [expr_strictly_free_of_region] as the precondition
432+
(blocker 5 reformulation, 2026-05-28). The strict predicate gives
433+
the body strictly MORE information than the weak one — in
434+
particular, the [T_Region_*_L1] cases no longer rely on a
435+
shadow-short-circuited [True] in the [rr = r] subcase. The
436+
residual [admit] at the [T_Region_Active_L1] [rr = r] sub-case
437+
is blocked by a list-vs-multiset structural mismatch (Phase D
438+
work, NOT by predicate weakness — strengthening the predicate
439+
does not close it). The [admit] remains; see the case's own
440+
comment for resolution options. *)
431441
Lemma region_shrink_preserves_typing_l1_gen_m :
432442
forall m R G e T R' G',
433443
R ; G |=L1[m] e : T -| R' ; G' ->
434444
forall r,
435-
expr_free_of_region r e ->
445+
expr_strictly_free_of_region r e ->
436446
remove_first r R ; G |=L1[m] e : T -| remove_first r R' ; G'.
437447
Proof.
438448
intros m R G e T R' G' Ht.
@@ -532,7 +542,11 @@ Proof.
532542
* intro Hin. apply H. eapply remove_first_subset; exact Hin.
533543
* exact H0.
534544
* apply remove_first_preserves_other; [intro Hbad; apply Heq; exact Hbad | exact H1].
535-
* specialize (IHHt rr Hfree).
545+
* (* Strict-predicate migration: [Hfree] is uniformly the body's
546+
strict-freedom (no conditional to discharge). Still need
547+
[simpl in IHHt] to unfold [remove_first rr (r :: R)] into
548+
[r :: remove_first rr R] via the [rr <> r] guard. *)
549+
specialize (IHHt rr Hfree).
536550
simpl in IHHt.
537551
destruct (String.eqb rr r) eqn:Heq2.
538552
-- exfalso. apply String.eqb_eq in Heq2. apply Heq. exact Heq2.
@@ -601,7 +615,9 @@ Proof.
601615
* intro Hin. apply H. eapply remove_first_subset; exact Hin.
602616
* exact H0.
603617
* apply remove_first_preserves_other; [intro Hbad; apply Heq; exact Hbad | exact H1].
604-
* specialize (IHHt rr Hfree).
618+
* (* Strict-predicate migration: same as T_Region_L1 above —
619+
[simpl in IHHt] still needed to unfold [remove_first]. *)
620+
specialize (IHHt rr Hfree).
605621
simpl in IHHt.
606622
destruct (String.eqb rr r) eqn:Heq2.
607623
-- exfalso. apply String.eqb_eq in Heq2. apply Heq. exact Heq2.
@@ -656,7 +672,7 @@ Lemma region_shrink_preserves_typing_l1_gen :
656672
forall R G e T R' G',
657673
has_type_l1_linear R G e T R' G' ->
658674
forall r,
659-
expr_free_of_region r e ->
675+
expr_strictly_free_of_region r e ->
660676
has_type_l1_linear (remove_first r R) G e T (remove_first r R') G'.
661677
Proof.
662678
intros R G e T R' G' Ht r Hfree.
@@ -668,7 +684,7 @@ Lemma region_shrink_preserves_typing_l1 :
668684
is_value v ->
669685
has_type_l1_linear R G v T R' G' ->
670686
~ In r (free_regions T) ->
671-
expr_free_of_region r v ->
687+
expr_strictly_free_of_region r v ->
672688
has_type_l1_linear (remove_first r R) G v T (remove_first r R') G'.
673689
Proof.
674690
intros R G v T R' G' r Hv Ht HnotT Hfree.
@@ -1741,15 +1757,23 @@ Admitted.
17411757
Region shrinkage then provides the post-step witness typing
17421758
at [remove_first r R], and [T_Echo_L1] wraps it. *)
17431759

1760+
(** Strict-predicate migration (blocker 5, 2026-05-28): the
1761+
region-shrinkage helper this lemma calls now requires
1762+
[expr_strictly_free_of_region], so the corresponding premise
1763+
here is also tightened. The legacy step rules
1764+
[S_Region_Exit_Echo] in [Semantics.v] still emit the weak
1765+
[expr_free_of_region]; bridging the step-rule premise to the
1766+
L1 lemma precondition is a follow-up (legacy operational
1767+
semantics — see PR description). *)
17441768
Lemma preservation_l3_region_active_echo :
17451769
forall m R G r v T R_body G',
17461770
(* T_Region_Active_L1_Echo premises *)
17471771
In r R ->
17481772
~ In r (Typing.free_regions T) ->
17491773
has_type_l1 m R G v T R_body G' ->
1750-
(* S_Region_Exit_Echo premises *)
1774+
(* S_Region_Exit_Echo premises (strict variant per blocker 5) *)
17511775
is_value v ->
1752-
expr_free_of_region r v ->
1776+
expr_strictly_free_of_region r v ->
17531777
(* Conclusion: post-step types at [TEcho T] *)
17541778
has_type_l1 m (remove_first r R) G
17551779
(EEcho T v) (TEcho T) (remove_first_L1 r R_body) G'.
@@ -1806,7 +1830,7 @@ Theorem preservation_l3 :
18061830
~ In r (Typing.free_regions T) ->
18071831
has_type_l1 m R G v T R_body G' ->
18081832
is_value v ->
1809-
expr_free_of_region r v ->
1833+
expr_strictly_free_of_region r v ->
18101834
has_type_l1 m (remove_first r R) G
18111835
(EEcho T v) (TEcho T) (remove_first_L1 r R_body) G')
18121836
/\

formal/Syntax.v

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,94 @@ Fixpoint expr_free_of_region (r : region_name) (e : expr) : Prop :=
187187
| EObserve e' => expr_free_of_region r e'
188188
end.
189189

190+
(** ** Strict Region-Freedom (reformulation, closes blocker 5)
191+
192+
[expr_strictly_free_of_region r e] mirrors [expr_free_of_region]
193+
EXCEPT in the [ERegion r' body] case, where it recurses
194+
UNCONDITIONALLY (no shadow short-circuit on [r = r']).
195+
196+
Why a strict variant exists. The weak [expr_free_of_region]
197+
short-circuits to [True] when [ERegion r' body] shadows [r]
198+
(the [String.eqb r r'] guard). That weakness is sound for the
199+
plain capability-list reading of [R], where a nested
200+
[ERegion r ...] statically masks the outer [r] and the body
201+
cannot "reach back." But under the L1 [T_Region_Active_L1]
202+
judgment — and more sharply under L3 re-entry semantics —
203+
a body can witness the outer [r] through count-monotonicity /
204+
multiset accounting that the syntactic shadow does NOT
205+
discharge. The audit (task #29, 2026-05-28, blocker 5) traced
206+
one class of "predicate too weak" failures in the region-
207+
shrinkage lemma family to exactly this short-circuit accepting
208+
expressions whose body legitimately references the outer [r].
209+
210+
The strict variant is the conservative reading: an expression
211+
is strictly free of [r] iff [r] never appears anywhere inside,
212+
even under a same-named [ERegion r ...] shadow. It implies the
213+
weak variant (see [expr_strictly_free_implies_free] below).
214+
215+
Scope. The strict predicate is intended to replace the weak one
216+
in the L1 region-shrinkage lemma family
217+
([region_shrink_preserves_typing_l1_gen_m] and friends in
218+
[Semantics_L1.v]) and downstream consumers
219+
([preservation_l3_region_active_echo]). The legacy step rules
220+
[S_Region_Exit] / [S_Region_Exit_Echo] in [Semantics.v] still
221+
emit the weak [expr_free_of_region] premise; migrating those
222+
is a separate concern (legacy operational semantics) and may
223+
or may not happen in this PR (see PR description for current
224+
scope).
225+
226+
Note. The L1 shadowed-sub-case [admit] at
227+
[Semantics_L1.v:553/621] is blocked by a list-vs-multiset
228+
structural mismatch (Phase D work), NOT by predicate weakness.
229+
Strengthening to [expr_strictly_free_of_region] does NOT close
230+
those admits. *)
231+
232+
Fixpoint expr_strictly_free_of_region (r : region_name) (e : expr) : Prop :=
233+
match e with
234+
| EUnit | EBool _ | EI32 _ | EVar _ => True
235+
| EStringNew r' _ => r <> r'
236+
| EStringConcat e1 e2 | ELet e1 e2 | ELetLin e1 e2
237+
| EApp e1 e2 | EPair e1 e2 =>
238+
expr_strictly_free_of_region r e1 /\ expr_strictly_free_of_region r e2
239+
| EStringLen e' | EFst e' | ESnd e' | EInl _ e' | EInr _ e'
240+
| EBorrow e' | EDeref e' | EDrop e' | ECopy e' | ELam _ e' =>
241+
expr_strictly_free_of_region r e'
242+
| EIf e1 e2 e3 | ECase e1 e2 e3 =>
243+
expr_strictly_free_of_region r e1 /\ expr_strictly_free_of_region r e2
244+
/\ expr_strictly_free_of_region r e3
245+
(** The strictness difference: no [String.eqb] shadow short-circuit.
246+
Always descend into the body. *)
247+
| ERegion _ e' => expr_strictly_free_of_region r e'
248+
| ELoc _ r' => r <> r'
249+
| EEcho _ e' => expr_strictly_free_of_region r e'
250+
| EObserve e' => expr_strictly_free_of_region r e'
251+
end.
252+
253+
(** [expr_strictly_free_of_region] strictly strengthens
254+
[expr_free_of_region]: every strictly-free expression is also
255+
weakly-free. The converse fails on (e.g.)
256+
[ERegion r (EStringNew r _)] where the weak variant accepts
257+
via shadow short-circuit but the strict variant rejects.
258+
259+
Proof. Structural induction. The only non-trivial case is
260+
[ERegion r' body]: the weak version short-circuits to [True]
261+
when [r = r'], which is implied by anything; the strict
262+
version's recursive hypothesis discharges the weak version's
263+
recursive case when [r <> r']. *)
264+
Lemma expr_strictly_free_implies_free :
265+
forall r e, expr_strictly_free_of_region r e -> expr_free_of_region r e.
266+
Proof.
267+
intros r e. induction e; simpl; intros H; try exact I; try assumption;
268+
try (apply IHe; exact H);
269+
try (destruct H as [H1 H2]; split; [apply IHe1 | apply IHe2]; assumption);
270+
try (destruct H as [H1 [H2 H3]]; split;
271+
[apply IHe1; assumption | split; [apply IHe2 | apply IHe3]; assumption]).
272+
- (* ERegion r' e *)
273+
destruct (String.eqb r r0) eqn:Heq.
274+
+ exact I.
275+
+ apply IHe; exact H.
276+
Qed.
277+
190278
(** ** Typing Contexts (De Bruijn) *)
191279

192280
(** A typing context is a list of (type, used?) pairs.

0 commit comments

Comments
 (0)