Same-head constant: if both are `C us args`, compare spines without unfolding.
(
&mut self,
a: &KExpr<M>,
b: &KExpr<M>,
)
| 604 | | ( |
| 605 | ExprData::All(name, bi, ty1, body1, _), |
| 606 | ExprData::All(_, _, ty2, body2, _), |
| 607 | ) => { |
| 608 | if !self.is_def_eq(ty1, ty2)? { |
| 609 | return Ok(false); |
| 610 | } |
| 611 | // Open both bodies with the SAME fresh fvar — the common-fvar |
| 612 | // trick that makes alpha-renamed bodies hash-equal under |
| 613 | // `instantiate_rev` and lets def-eq compare them structurally. |
| 614 | // Mirrors lean4lean `isDefEqBinding` |
| 615 | // (refs/lean4lean/Lean4Lean/TypeChecker.lean:546). |
| 616 | self.with_lctx_scope(|tc| { |
| 617 | let fv_id = tc.fresh_fvar_id(); |
| 618 | let fv = tc.intern(KExpr::fvar(fv_id, name.clone())); |
| 619 | tc.lctx.push( |
| 620 | fv_id, |
| 621 | LocalDecl::CDecl { |
| 622 | name: name.clone(), |
| 623 | bi: bi.clone(), |
| 624 | ty: ty1.clone(), |
| 625 | }, |
| 626 | ); |
| 627 | let b1_open = instantiate_rev( |
| 628 | &mut tc.env.intern, |
| 629 | body1, |
| 630 | std::slice::from_ref(&fv), |
| 631 | ); |
| 632 | let b2_open = instantiate_rev(&mut tc.env.intern, body2, &[fv]); |
| 633 | tc.is_def_eq(&b1_open, &b2_open) |
| 634 | }) |
| 635 | }, |
| 636 | _ => Ok(false), |
| 637 | } |
| 638 | } |