Skip to content

Commit

Permalink
feat(experimental): Add invalid pattern syntax error (#7487)
Browse files Browse the repository at this point in the history
  • Loading branch information
jfecher authored Feb 22, 2025
1 parent ffcc6f8 commit 7aa23ec
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 8 deletions.
25 changes: 17 additions & 8 deletions compiler/noirc_frontend/src/elaborator/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,14 @@ impl Elaborator<'_> {
});
};

// We want the actual expression's span here, not the innermost one from `type_location()`
let span = expression.location.span;
let syntax_error = |this: &mut Self| {
let errors = ResolverError::InvalidSyntaxInPattern { span };
this.push_err(errors, this.file);
Pattern::Error
};

match expression.kind {
ExpressionKind::Literal(Literal::Integer(value, negative)) => {
let actual = self.interner.next_type_variable_with_kind(Kind::IntegerOrField);
Expand Down Expand Up @@ -363,10 +371,7 @@ impl Elaborator<'_> {
}
Err(error) => {
self.push_err(error, location.file);
// Default to defining a variable of the same name although this could
// cause further match warnings/errors (e.g. redundant cases).
let id = self.fresh_match_variable(expected_type.clone(), location);
Pattern::Binding(id)
Pattern::Error
}
}
}
Expand Down Expand Up @@ -402,7 +407,7 @@ impl Elaborator<'_> {
if let StatementKind::Expression(expr) = self.interner.get_statement_kind(id) {
self.expression_to_pattern(expr.clone(), expected_type, variables_defined)
} else {
panic!("Invalid expr kind {expression}")
syntax_error(self)
}
}

Expand All @@ -425,9 +430,7 @@ impl Elaborator<'_> {
| ExpressionKind::AsTraitPath(_)
| ExpressionKind::TypePath(_)
| ExpressionKind::Resolved(_)
| ExpressionKind::Error => {
panic!("Invalid expr kind {expression}")
}
| ExpressionKind::Error => syntax_error(self),
}
}

Expand Down Expand Up @@ -703,6 +706,7 @@ impl Elaborator<'_> {
let (key, cons) = match col.pattern {
Pattern::Int(val) => ((val, val), Constructor::Int(val)),
Pattern::Range(start, stop) => ((start, stop), Constructor::Range(start, stop)),
Pattern::Error => continue,
pattern => {
eprintln!("Unexpected pattern for integer type: {pattern:?}");
continue;
Expand Down Expand Up @@ -931,6 +935,11 @@ enum Pattern {
/// 1 <= n < 20.
#[allow(unused)]
Range(SignedField, SignedField),

/// An error occurred while translating this pattern. This Pattern kind always translates
/// to a Fail branch in the decision tree, although the compiler is expected to halt
/// with errors before execution.
Error,
}

#[derive(Clone)]
Expand Down
8 changes: 8 additions & 0 deletions compiler/noirc_frontend/src/hir/resolution/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ pub enum ResolverError {
LoopNotYetSupported { span: Span },
#[error("Expected a trait but found {found}")]
ExpectedTrait { found: String, span: Span },
#[error("Invalid syntax in match pattern")]
InvalidSyntaxInPattern { span: Span },
#[error("Variable '{existing}' was already defined in the same match pattern")]
VariableAlreadyDefinedInPattern { existing: Ident, new_span: Span },
}
Expand Down Expand Up @@ -694,6 +696,12 @@ impl<'a> From<&'a ResolverError> for Diagnostic {
String::new(),
*span)
}
ResolverError::InvalidSyntaxInPattern { span } => {
Diagnostic::simple_error(
"Invalid syntax in match pattern".into(),
"Only literal, constructor, and variable patterns are allowed".into(),
*span)
},
ResolverError::VariableAlreadyDefinedInPattern { existing, new_span } => {
let message = format!("Variable `{existing}` was already defined in the same match pattern");
let secondary = format!("`{existing}` redefined here");
Expand Down

0 comments on commit 7aa23ec

Please sign in to comment.