Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 },
Comment thread
jfecher marked this conversation as resolved.
#[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