aboutsummaryrefslogtreecommitdiff
path: root/src/checker_signature.rs
diff options
context:
space:
mode:
authortslil <tslil@posteo.de>2026-05-04 17:52:04 +0100
committertslil <tslil@posteo.de>2026-05-04 18:26:43 +0100
commit90e451893671ceebaa37fcb634b5d7a3f153ba70 (patch)
treeb7d21bc968fed9141c74b6cb00ec3a3ae1e577ed /src/checker_signature.rs
parent3ce914fdc62923c92812037297aee64747a9867e (diff)
almost done
Diffstat (limited to 'src/checker_signature.rs')
-rw-r--r--src/checker_signature.rs37
1 files changed, 24 insertions, 13 deletions
diff --git a/src/checker_signature.rs b/src/checker_signature.rs
index 42a581f..30598d3 100644
--- a/src/checker_signature.rs
+++ b/src/checker_signature.rs
@@ -420,18 +420,9 @@ impl CheckerState {
other => (other, args.clone()),
};
- let subject_sig: Option<Signature> = match &subject {
- Instance::Var(v) => Some(self.lookup_instance(v)?.container.clone()),
- Instance::Project { field, .. } => {
- Some(self.lookup_signature_field(field)?.field.clone())
- }
- // TODO: i think we need to handle case here
- Instance::App { .. }
- | Instance::Record(_)
- | Instance::SetCoerce(_)
- | Instance::For { .. }
- | Instance::Case { .. } => None,
- };
+ // nevertheless we need the tiniest amount of bidirectionality
+ // here to deal with case, project, and var recursively
+ let subject_sig: Option<Signature> = self.stuck_subject_signature(&subject)?;
if let Some(subject_sig) = subject_sig {
let Signature::Ext { params, codomain } = subject_sig else {
@@ -497,7 +488,7 @@ impl CheckerState {
})
}
Instance::Case { .. } => {
- todo!("App applied to a Case instance?");
+ unreachable!("_stuck_subject_signature should have dealt with this")
}
Instance::Var(_) | Instance::Project { .. } => {
unreachable!("handled in the stuck-head branch above")
@@ -533,4 +524,24 @@ impl CheckerState {
.collect::<Result<Vec<_>, _>>()?;
Ok((ctx, checked))
}
+
+ fn stuck_subject_signature(&self, inst: &Instance) -> Result<Option<Signature>, CheckerError> {
+ match inst {
+ Instance::Var(v) => Ok(Some(self.lookup_instance(v)?.container.clone())),
+ Instance::Project { field, .. } => {
+ Ok(Some(self.lookup_signature_field(field)?.field.clone()))
+ }
+ // All arms of a stuck Case share a signature by the case
+ // elimination typing rule, and we've already expanded the body, so
+ // we can pick any arm.
+ Instance::Case { arms, .. } => self
+ .stuck_subject_signature(&arms.first().expect("we don't allow bottom type").body),
+
+ Instance::For { .. } | Instance::Record(_) | Instance::SetCoerce(_) => Ok(None),
+
+ Instance::App { .. } => unreachable!(
+ "invariant violation: _stuck_head_signature called on a left-nested App"
+ ),
+ }
+ }
}