Skip to content

Add proj-of-prop soundness test#36

Merged
nomeata merged 2 commits into
masterfrom
joachim/projOfProp
Apr 22, 2026
Merged

Add proj-of-prop soundness test#36
nomeata merged 2 commits into
masterfrom
joachim/projOfProp

Conversation

@nomeata
Copy link
Copy Markdown
Collaborator

@nomeata nomeata commented Apr 22, 2026

The exported theorem builds a proof of False via a projection from a
Prop-typed structure whose constructor was applied to an ill-typed
argument:

structure Wrapper : Prop where mk :: p : False
theorem badFalse : False := (Wrapper.mk True.intro).p

A checker that types a projection by inferring (rather than checking)
its structure — trusting the structure to be well-typed rather than
verifying the constructor's arguments against its binders — will accept
this and return badFalse : False. A sound checker must reject it.

Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

nomeata and others added 2 commits April 22, 2026 22:50
The exported theorem builds a proof of `False` via a projection from a
`Prop`-typed structure whose constructor was applied to an ill-typed
argument:

    structure Wrapper : Prop where mk :: p : False
    theorem badFalse : False := (Wrapper.mk True.intro).p

A checker that types a projection by inferring (rather than checking)
its structure — trusting the structure to be well-typed rather than
verifying the constructor's arguments against its binders — will accept
this and return `badFalse : False`. A sound checker must reject it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous version used `(Wrapper.mk True.intro).p` with `unchecked` +
`debug.skipKernelTC`, but Lean's elaborator desugars `s.field` syntax
into a call to the generated projection *function* (here `Wrapper.p`),
never a raw `Expr.proj`. The exported declaration was therefore an
`App`, which is caught by `infer_app`'s strict argument-type check --
so sound and unsound checkers all rejected it for the wrong reason.

Construct the declaration programmatically instead, building the value
as a literal `Expr.proj` around the ill-typed `Wrapper.mk True.intro`.

Verified with `lka.py run`: the official Lean kernel rejects,
nanoda and sonanoda both (incorrectly) accept.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@nomeata nomeata merged commit 8f2f715 into master Apr 22, 2026
3 checks passed
@nomeata nomeata deleted the joachim/projOfProp branch April 22, 2026 23:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant