Zulip Chat Archive

Stream: lean4

Topic: Failed nested rewrite when eliminating from Prop to Prop


Jakub Nowak (Dec 10 2025 at 00:15):

Is it expected, that this doesn't work, or is it a bug?

namespace WithType

inductive Foo : Type where
| foo (x : Nat) : Foo

inductive Bar : Foo  Type where
| bar (x : Nat) (h : x = 2) : Bar (.foo x)

def Bar.h {x : Nat} (bar : Bar (.foo x)) : x = 2 :=
  match _ : bar with
  | .bar x h => h

end WithType


namespace WithProp

inductive Foo : Prop where
| foo (x : Nat) : Foo

inductive Bar : Foo  Prop where
| bar (x : Nat) (h : x = 2) : Bar (.foo x)

/--
error: Type mismatch
  h
has type
  x = 2
but is expected to have type
  x✝ = 2
-/
#guard_msgs in
def Bar.h {x : Nat} (bar : Bar (.foo x)) : x = 2 :=
  match _ : bar with
  | .bar x h => h

end WithProp

Jakub Nowak (Dec 10 2025 at 00:17):

It's the same with cases instead of match.

Jakub Nowak (Dec 10 2025 at 00:19):

It's worth noting, that in the WithType section, match generates these two equalities in context:

h✝¹ : x = x
h : bar  Bar.bar x h

But in WithProp section, it only generates:

h : bar = Bar.bar x h

Jakub Nowak (Dec 10 2025 at 00:23):

I also have no idea how to workaround this, and how to prove Bar.h. Is it even possible to prove?

Jakub Nowak (Dec 10 2025 at 00:34):

Hm, Lean generates Foo.foo.noConfusion in WithType section, but not in WithProp section.

Eric Wieser (Dec 10 2025 at 02:26):

Does including x in the match help?

Jakub Nowak (Dec 10 2025 at 02:27):

Eric Wieser said:

Does including x in the match help?

Nope.

inductive Foo : Prop where
| foo (x : Nat) : Foo

inductive Bar : Foo  Prop where
| bar (x : Nat) (h : x = 2) : Bar (.foo x)

/--
error: Type mismatch
  h
has type
  x = 2
but is expected to have type
  x' = 2
-/
#guard_msgs in
def Bar.h {x : Nat} (bar : Bar (.foo x)) : x = 2 :=
  match x, _ : bar with
  | x', .bar x h => h

Kyle Miller (Dec 10 2025 at 02:30):

This is expected. Foo is a proposition, so Foo.foo x = Foo.foo y does not imply x = y.

Kyle Miller (Dec 10 2025 at 02:31):

Every proof of Bar (.foo x) is equal to each other as well, so having match generate an equality wouldn't be useful.

Jakub Nowak (Dec 10 2025 at 02:32):

Kyle Miller said:

This is expected. Foo is a proposition, so Foo.foo x = Foo.foo y does not imply x = y.

I see. I've tried to prove exactly this implication. That explains why is there no Foo.foo.noConfusion.

Aaron Liu (Dec 10 2025 at 02:34):

oh

inductive Foo : Prop where
| foo (x : Nat) : Foo

inductive Bar : Foo  Prop where
| bar (x : Nat) (h : x = 2) : Bar (.foo x)

def Bar.h {x : Nat} (bar : Bar (.foo x)) : x = 2 := sorry

example : False := nomatch @Bar.h 1 (.bar 2 rfl)

Aaron Liu (Dec 10 2025 at 02:35):

I guess that explains it

Jakub Nowak (Dec 10 2025 at 02:36):

Yeah, that's because Foo.foo 1 = Foo.foo 2 I think.


Last updated: Dec 20 2025 at 21:32 UTC