Skip to content

Commit 9f7fd41

Browse files
proof(SafeEmail): DISCHARGE combineValidValid via constructor pattern + Refl premise (#142)
## Summary Discharge `Proven.SafeEmail.Proofs.combineValidValid` in one line by case-splitting on the `ValidationResult` constructor and using the `Refl` premise to bind the `isValid` field to `True`. The OWED comment already diagnosed the blocker correctly AND suggested the discharge — this PR just applies it. ## Discharge \`\`\`idris combineValidValid (MkValidationResult True _) (MkValidationResult True _) Refl Refl = Refl \`\`\` The pattern \`MkValidationResult True _\` plus the \`Refl\` premise binds the \`isValid\` field to \`True\`. With both fields True, \`(combineResults r1 r2).isValid\` reduces to \`True && True = True\` definitionally. Proof = \`Refl\`. ## Verification - \`/tmp/charrefl/src/TestEmail.idr\` (isolated): Exit 0 - \`/tmp/SafeEmailMinimal.idr\` (against actual proven ValidationResult / combineResults): Exit 0 - Zero \`believe_me\` / \`postulate\` / \`idris_crash\` ## Local-vs-CI note Pre-existing \`validResultIsValid\` in the same module fails to compile locally (record-field projection through a \`public export\` top-level constant — same blocker family as SafeCSV's \`defaultDelimiterIsComma\` we hit in PR #137). This error does NOT reproduce in CI (PR #100 merged green with that proof). My change is purely additive. Refs proven#90 (Phase 3 OWED triage), proven#107 (overly-cautious OWED meta). ## Test plan - [x] Local isolated discharge proof: Exit 0 - [ ] CI \`idris2 --check proven.ipkg\` green - [ ] CI test suite green 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent d09d822 commit 9f7fd41

1 file changed

Lines changed: 10 additions & 15 deletions

File tree

src/Proven/SafeEmail/Proofs.idr

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -103,22 +103,17 @@ validResultIsValid = Refl
103103
issue.severity = Warning ->
104104
(addIssue issue validResult).isValid = True
105105

106-
||| OWED: combining two valid results yields a valid result. By the
107-
||| definition `combineResults r1 r2 = MkValidationResult
108-
||| (r1.isValid && r2.isValid) (r1.issues ++ r2.issues)`
109-
||| (Validation.idr L78-80), with `r1.isValid = True` and
110-
||| `r2.isValid = True` we get `True && True = True`. Held back by
111-
||| Idris2 0.8.0 not reducing the record-field projection
112-
||| `(MkValidationResult (r1.isValid && r2.isValid) _).isValid` to
113-
||| `r1.isValid && r2.isValid` by Refl when `r1`, `r2` are
114-
||| universally quantified (no constructor in normal form to fire
115-
||| the projector). Discharge by case-split on `r1`, `r2` to expose
116-
||| the `MkValidationResult` constructor, then `Refl` after the
117-
||| `True && True = True` rewrite.
106+
||| DISCHARGED: combining two valid results yields a valid result.
107+
||| The OWED comment suggested the discharge pattern: case-split on
108+
||| `r1`, `r2` to expose the `MkValidationResult` constructor, then
109+
||| pattern-match the `True` field through the premise's `Refl` to
110+
||| collapse `True && True` to `True` directly. Empirically verified
111+
||| at `/tmp/charrefl/src/TestEmail.idr`.
118112
public export
119-
0 combineValidValid : (r1, r2 : ValidationResult) ->
120-
r1.isValid = True -> r2.isValid = True ->
121-
(combineResults r1 r2).isValid = True
113+
combineValidValid : (r1, r2 : ValidationResult) ->
114+
r1.isValid = True -> r2.isValid = True ->
115+
(combineResults r1 r2).isValid = True
116+
combineValidValid (MkValidationResult True _) (MkValidationResult True _) Refl Refl = Refl
122117

123118
--------------------------------------------------------------------------------
124119
-- Email Structure Properties

0 commit comments

Comments
 (0)