Skip to content

Commit

Permalink
fix: Perform occurs check before binding function types (#2027)
Browse files Browse the repository at this point in the history
Fix binding function types without doing an occurs check
  • Loading branch information
jfecher authored Jul 25, 2023
1 parent 8adc57c commit 1544786
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 1 deletion.
4 changes: 3 additions & 1 deletion crates/noirc_frontend/src/hir/type_check/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -775,8 +775,10 @@ impl<'interner> TypeChecker<'interner> {
let ret = self.interner.next_type_variable();
let args = vecmap(args, |(arg, _)| arg);
let expected = Type::Function(args, Box::new(ret.clone()));
*binding.borrow_mut() = TypeBinding::Bound(expected);

if let Err(error) = binding.borrow_mut().bind_to(expected, span) {
self.errors.push(error);
}
ret
}
Type::Function(parameters, ret) => {
Expand Down
14 changes: 14 additions & 0 deletions crates/noirc_frontend/src/hir_def/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,20 @@ impl TypeBinding {
pub fn is_unbound(&self) -> bool {
matches!(self, TypeBinding::Unbound(_))
}

pub fn bind_to(&mut self, binding: Type, span: Span) -> Result<(), TypeCheckError> {
match self {
TypeBinding::Bound(_) => panic!("Tried to bind an already bound type variable!"),
TypeBinding::Unbound(id) => {
if binding.occurs(*id) {
Err(TypeCheckError::TypeAnnotationsNeeded { span })
} else {
*self = TypeBinding::Bound(binding);
Ok(())
}
}
}
}
}

/// A unique ID used to differentiate different type variables
Expand Down

0 comments on commit 1544786

Please sign in to comment.