()
| 2007 | let res_ty_inner = apps( |
| 2008 | cnst("Eq", &[usucc(uzero())]), |
| 2009 | &[cnst("PUnit", &[usucc(uzero())]), proj3.clone(), proj3], |
| 2010 | ); |
| 2011 | // But this res_ty is inside the pi binder (at depth 1 where x=var(0)) |
| 2012 | // The helper mk_prop_structure_proj_test wraps it in pi(PS, res_ty) |
| 2013 | // so res_ty should reference var(0) for x. But var(0) inside pi body |
| 2014 | // IS x. The .proj expressions use var(0) = x. Good. |
| 2015 | let id = |
| 2016 | mk_prop_structure_proj_test(&mut env, "projProp5", res_ty_inner, 4); |
| 2017 | check_rejects(&mut env, &id); |
| 2018 | } |
| 2019 | |
| 2020 | /// projProp6 (bad): idx=5, aFinalProof : PUnit.{0} — after dependent data |
| 2021 | #[test] |
| 2022 | fn bad_proj_prop6() { |
| 2023 | let mut env = prop_structure_env(); |
| 2024 | let id = mk_prop_structure_proj_test( |
| 2025 | &mut env, |
| 2026 | "projProp6", |
| 2027 | cnst("PUnit", &[uzero()]), |
| 2028 | 5, |
| 2029 | ); |
| 2030 | check_rejects(&mut env, &id); |
| 2031 | } |
| 2032 | |
| 2033 | // ========================================================================== |
| 2034 | // etaRuleK corner case (Tutorial.lean 987–999) |
| 2035 | // |
| 2036 | // Partially applied Eq.rec with rule K should NOT trigger eta expansion. |
| 2037 | // @Eq.rec Bool true (fun _ _ => Bool) (a (Eq.refl true)) _ ≠ a |
| 2038 | // even though Eq.rec could reduce via Rule K if fully applied. |
| 2039 | // ========================================================================== |
| 2040 | |
| 2041 | /// etaRuleK: ∀ (a : true = true → Bool), |
| 2042 | /// @Eq (true = true → Bool) (Eq.rec (fun _ _ => Bool) (a (Eq.refl true)) _) a |
| 2043 | /// BAD: partially applied recursor should not eta-expand to match `a`. |
| 2044 | #[test] |
| 2045 | fn bad_eta_rule_k() { |
| 2046 | let mut env = eq_inductive_env(); |
| 2047 | |
| 2048 | let u1 = usucc(uzero()); |
| 2049 | let bool_ty = cnst("Bool", &[]); |
| 2050 | |
| 2051 | // true = true |
| 2052 | let tt_eq = apps( |
| 2053 | cnst("Eq", std::slice::from_ref(&u1)), |
| 2054 | &[bool_ty.clone(), cnst("Bool.true", &[]), cnst("Bool.true", &[])], |
| 2055 | ); |
| 2056 | |
| 2057 | // (true = true → Bool) — the type of `a` |
| 2058 | let a_ty = pi(tt_eq.clone(), bool_ty.clone()); |
| 2059 | |
| 2060 | // motive for Eq.rec: fun _ _ => Bool |
| 2061 | let motive = nlam( |
| 2062 | "_", |
| 2063 | bool_ty.clone(), |
| 2064 | nlam( |
| 2065 | "_", |
| 2066 | apps( |
nothing calls this directly
no test coverage detected