()
| 944 | // Quot: 1 (u), Quot.mk: 1 (u), Quot.lift: 2 (u,v), Quot.ind: 1 (u) |
| 945 | let expected_lvls = match kind { |
| 946 | QuotKind::Lift => 2, |
| 947 | QuotKind::Type | QuotKind::Ctor | QuotKind::Ind => 1, |
| 948 | }; |
| 949 | if lvls != expected_lvls { |
| 950 | return Err(TcError::Other(format!( |
| 951 | "check_quot: {:?} expects {} universe params, got {}", |
| 952 | kind, expected_lvls, lvls |
| 953 | ))); |
| 954 | } |
| 955 | |
| 956 | let expected_ty = canonical_quot_type(&self.prims, kind); |
| 957 | if ty != &expected_ty { |
| 958 | return Err(TcError::Other(format!( |
| 959 | "check_quot: {:?} type is not canonical", |
| 960 | kind |
| 961 | ))); |
| 962 | } |
| 963 | |
| 964 | // For Quot.lift (the main eliminator), verify Eq is properly formed. |
| 965 | // This is a prerequisite for the quot reduction rule to be sound. |
| 966 | if kind == QuotKind::Lift { |
| 967 | self.check_eq_type()?; |
| 968 | } |
| 969 | |
| 970 | Ok(()) |
| 971 | } |
| 972 | |
| 973 | /// Verify the exact Eq/Eq.refl prerequisite checked by Lean before it |
| 974 | /// installs the quotient primitives. |
| 975 | fn check_eq_type(&self) -> Result<(), TcError<M>> { |
| 976 | // Find Eq inductive in the environment by address. |
| 977 | // Search all constants for one matching the Eq address. |
| 978 | let eq_const = self |
| 979 | .env |
| 980 | .iter() |
| 981 | .find(|(id, _)| id.addr == self.prims.eq.addr) |
| 982 | .map(|(id, c)| (id.clone(), c.clone())); |
| 983 | let (_eq_id, eq_c) = eq_const.ok_or_else(|| { |
| 984 | TcError::Other("check_eq_type: Eq not found in environment".into()) |
| 985 | })?; |
| 986 | match &eq_c { |
| 987 | KConst::Indc { lvls, params, indices, is_unsafe, ty, ctors, .. } => { |
| 988 | if *lvls != 1 { |
| 989 | return Err(TcError::Other(format!( |
| 990 | "check_eq_type: Eq expects 1 universe param, got {}", |
| 991 | lvls |
| 992 | ))); |
| 993 | } |
| 994 | // Eq : {α : Sort u} → α → α → Prop |
| 995 | // numParams = 2 (α, a are uniform across Eq.refl), numIndices = 1 (b) |
| 996 | if *params != 2 { |
| 997 | return Err(TcError::Other(format!( |
| 998 | "check_eq_type: Eq expects 2 params (α, a), got {}", |
| 999 | params |
no test coverage detected