Skip to content

Commit 174ecfd

Browse files
hyperpolymathclaude
andcommitted
feat(formal/coq): discharge totality — Coq formalization now fully proved
`totality` was the lone Admitted. Discharged as genuine progress-to-a-value: a well-typed closed expression always evaluates (the language has no loops or recursion). Proof is induction on the expression using the now-proved `preservation` + canonical value shapes to pin each operand; the value environment `ρ` is arbitrary because `[] ⊢ e ∈ τ` already forces closedness. The redundant `free_vars` hypothesis (and the previously-unsound free-vars-only statement) is dropped, since well-typedness in the empty context implies the expression is closed. Whole file now: `coqc Phronesis.v` exits 0 with NO Admitted/Abort/sorry, and `Print Assumptions totality` / `type_safety` = "Closed under the global context" (axiom-free). The mechanized safety story is complete: type safety (preservation), totality/progress, determinism, decidable type equality, subtyping transitivity, and by-construction sandbox isolation. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 8afc849 commit 174ecfd

1 file changed

Lines changed: 91 additions & 17 deletions

File tree

academic/formal-verification/coq/Phronesis.v

Lines changed: 91 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -642,27 +642,101 @@ Fixpoint free_vars (e : phr_expr) : list string :=
642642
| EIn e1 e2 => free_vars e1 ++ free_vars e2
643643
end.
644644

645-
(** Totality / progress-to-a-value.
645+
(** Totality / progress-to-a-value: a well-typed closed expression always
646+
evaluates to a value (the language has no loops or recursion).
646647
647-
NOTE (honesty): this is the one safety obligation in this file that is NOT
648-
yet mechanized. It is stated here as an explicit [Admitted] obligation, not
649-
a hidden gap. The ORIGINAL statement (closedness of the value environment
650-
alone implies evaluation) is FALSE — e.g. [EBinOp OpAdd (ELit (VBool true))
648+
NOTE: the ORIGINAL statement required only that the value environment cover
649+
[free_vars e], which is FALSE — e.g. [EBinOp OpAdd (ELit (VBool true))
651650
(ELit (VInt 1))] is closed but has no applicable evaluation rule. The
652-
correct statement requires WELL-TYPEDNESS: a closed, well-typed expression
653-
evaluates to a value (the language has no loops or recursion). The full
654-
proof is an induction on the typing derivation using the canonical-forms
655-
lemmas to pin each operand's value shape; it is left open here.
656-
657-
Nothing below depends on [totality]; the safety core ([preservation],
658-
[eval_deterministic], [type_safety], [phr_type_eq_dec], [subtype_trans],
659-
[no_system_calls]) is fully proved and axiom-free. *)
651+
correct hypothesis is WELL-TYPEDNESS; and since [[] ⊢ e ∈ τ] already forces
652+
[e] to be closed (there is no binding form, so [EVar] is untypable here),
653+
the value-environment hypothesis is redundant and dropped. The proof is an
654+
induction on [e] that uses [preservation] + the canonical value shapes to
655+
pin each operand. [ρ] is arbitrary precisely because [e] is closed. *)
660656
Theorem totality : forall e τ ρ,
661-
[] ⊢ e ∈ τ ->
662-
(forall x, In x (free_vars e) -> exists v, val_lookup x ρ = Some v) ->
663-
exists v, ρ ⊢ e ⇓ v.
657+
[] ⊢ e ∈ τ -> exists v, ρ ⊢ e ⇓ v.
664658
Proof.
665-
Admitted.
659+
intros e; induction e as
660+
[ p | s | b e1 IHe1 e2 IHe2 | u e IHe
661+
| e1 IHe1 e2 IHe2 e3 IHe3 | e IHe f | e1 IHe1 e2 IHe2 ];
662+
intros τ ρ Ht.
663+
- (* ELit *) exists p. constructor.
664+
- (* EVar: untypable in the empty context *)
665+
inversion Ht; subst.
666+
match goal with H : lookup _ [] = Some _ |- _ => simpl in H; discriminate H end.
667+
- (* EBinOp: evaluate the left operand once, up front *)
668+
inversion Ht; subst;
669+
match goal with Ha : has_type [] e1 _ |- _ =>
670+
destruct (IHe1 _ ρ Ha) as [v1 Hv1];
671+
pose proof (preservation _ _ _ _ Ha Hv1) as T1
672+
end.
673+
+ (* Add *) match goal with Hb : has_type [] e2 _ |- _ =>
674+
destruct (IHe2 _ ρ Hb) as [v2 Hv2]; pose proof (preservation _ _ _ _ Hb Hv2) as T2 end;
675+
inversion T1; subst; inversion T2; subst; eexists; apply E_Add; eassumption.
676+
+ (* Sub *) match goal with Hb : has_type [] e2 _ |- _ =>
677+
destruct (IHe2 _ ρ Hb) as [v2 Hv2]; pose proof (preservation _ _ _ _ Hb Hv2) as T2 end;
678+
inversion T1; subst; inversion T2; subst; eexists; apply E_Sub; eassumption.
679+
+ (* Mul *) match goal with Hb : has_type [] e2 _ |- _ =>
680+
destruct (IHe2 _ ρ Hb) as [v2 Hv2]; pose proof (preservation _ _ _ _ Hb Hv2) as T2 end;
681+
inversion T1; subst; inversion T2; subst; eexists; apply E_Mul; eassumption.
682+
+ (* And: short-circuit on the left guard *)
683+
inversion T1; subst;
684+
match goal with Hg : _ ⊢ e1 ⇓ VBool ?bb |- _ => destruct bb end.
685+
* match goal with Hb : has_type [] e2 _ |- _ =>
686+
destruct (IHe2 _ ρ Hb) as [v2 Hv2]; pose proof (preservation _ _ _ _ Hb Hv2) as T2 end;
687+
inversion T2; subst; eexists; apply E_And_True; eassumption.
688+
* eexists; apply E_And_False; eassumption.
689+
+ (* Or: short-circuit on the left guard *)
690+
inversion T1; subst;
691+
match goal with Hg : _ ⊢ e1 ⇓ VBool ?bb |- _ => destruct bb end.
692+
* eexists; apply E_Or_True; eassumption.
693+
* match goal with Hb : has_type [] e2 _ |- _ =>
694+
destruct (IHe2 _ ρ Hb) as [v2 Hv2]; pose proof (preservation _ _ _ _ Hb Hv2) as T2 end;
695+
inversion T2; subst; eexists; apply E_Or_False; eassumption.
696+
+ (* Eq: no value-shape constraint *)
697+
match goal with Hb : has_type [] e2 _ |- _ =>
698+
destruct (IHe2 _ ρ Hb) as [v2 Hv2] end;
699+
eexists; apply E_Eq; eassumption.
700+
+ (* Lt *) match goal with Hb : has_type [] e2 _ |- _ =>
701+
destruct (IHe2 _ ρ Hb) as [v2 Hv2]; pose proof (preservation _ _ _ _ Hb Hv2) as T2 end;
702+
inversion T1; subst; inversion T2; subst; eexists; apply E_Lt; eassumption.
703+
- (* EUnOp *)
704+
inversion Ht; subst;
705+
match goal with Ha : has_type [] e _ |- _ =>
706+
destruct (IHe _ ρ Ha) as [v Hv]; pose proof (preservation _ _ _ _ Ha Hv) as T end;
707+
inversion T; subst.
708+
+ eexists; apply E_Not; eassumption.
709+
+ eexists; apply E_Neg; eassumption.
710+
- (* EIf: branch on the guard value *)
711+
inversion Ht; subst.
712+
match goal with Hc : has_type [] e1 _ |- _ =>
713+
destruct (IHe1 _ ρ Hc) as [v1 Hv1]; pose proof (preservation _ _ _ _ Hc Hv1) as T1 end.
714+
inversion T1; subst.
715+
match goal with Hg : _ ⊢ e1 ⇓ VBool ?bb |- _ => destruct bb end.
716+
+ match goal with Ht2 : has_type [] e2 _ |- _ =>
717+
destruct (IHe2 _ ρ Ht2) as [v2 Hv2] end; exists v2; apply E_If_True; assumption.
718+
+ match goal with Ht3 : has_type [] e3 _ |- _ =>
719+
destruct (IHe3 _ ρ Ht3) as [v3 Hv3] end; exists v3; apply E_If_False; assumption.
720+
- (* EField: the field exists in the (well-typed) record value *)
721+
inversion Ht; subst.
722+
match goal with Hr : has_type [] e (TRecord ?ff), Hin : In (f, τ) ?ff |- _ =>
723+
destruct (IHe _ ρ Hr) as [v Hv]; pose proof (preservation _ _ _ _ Hr Hv) as T;
724+
inversion T; subst;
725+
match goal with Hbody : forall a t, In (a, t) ff -> _ |- _ =>
726+
destruct (Hbody f τ Hin) as [w [Hlk Hwt]]
727+
end
728+
end.
729+
exists w. eapply E_Field; eassumption.
730+
- (* EIn: the right operand is a list value *)
731+
inversion Ht; subst.
732+
match goal with
733+
Ha : has_type [] e1 _, Hb : has_type [] e2 (TList _) |- _ =>
734+
destruct (IHe1 _ ρ Ha) as [v1 Hv1];
735+
destruct (IHe2 _ ρ Hb) as [v2 Hv2];
736+
pose proof (preservation _ _ _ _ Hb Hv2) as T2
737+
end.
738+
inversion T2; subst. eexists. apply E_In; eassumption.
739+
Qed.
666740

667741
(** * 16. Type Safety Corollary *)
668742

0 commit comments

Comments
 (0)