diff --git a/compiler/noirc_frontend/src/ast/mod.rs b/compiler/noirc_frontend/src/ast/mod.rs index dfe4258744a..8cdf377528b 100644 --- a/compiler/noirc_frontend/src/ast/mod.rs +++ b/compiler/noirc_frontend/src/ast/mod.rs @@ -323,13 +323,11 @@ impl UnresolvedTypeExpression { fn from_expr_helper(expr: Expression) -> Result { match expr.kind { - ExpressionKind::Literal(Literal::Integer(int, sign)) => { - assert!(!sign, "Negative literal is not allowed here"); - match int.try_to_u32() { - Some(int) => Ok(UnresolvedTypeExpression::Constant(int, expr.span)), - None => Err(expr), - } - } + // TODO(https://github.com/noir-lang/noir/issues/5571): The `sign` bool from `Literal::Integer` should be used to construct the constant type expression. + ExpressionKind::Literal(Literal::Integer(int, _)) => match int.try_to_u32() { + Some(int) => Ok(UnresolvedTypeExpression::Constant(int, expr.span)), + None => Err(expr), + }, ExpressionKind::Variable(path, _) => Ok(UnresolvedTypeExpression::Variable(path)), ExpressionKind::Prefix(prefix) if prefix.operator == UnaryOp::Minus => { let lhs = Box::new(UnresolvedTypeExpression::Constant(0, expr.span)); diff --git a/compiler/noirc_frontend/src/parser/errors.rs b/compiler/noirc_frontend/src/parser/errors.rs index 41ea9f88c19..9df9a8e15dd 100644 --- a/compiler/noirc_frontend/src/parser/errors.rs +++ b/compiler/noirc_frontend/src/parser/errors.rs @@ -44,6 +44,10 @@ pub enum ParserErrorReason { InvalidBitSize(u32), #[error("{0}")] Lexer(LexerErrorKind), + // TODO(https://github.com/noir-lang/noir/issues/5571): This error can be removed once support is expanded for type-level integers. + // This error reason was added to prevent the panic outline in this issue: https://github.com/noir-lang/noir/issues/5552. + #[error("Only unsigned integers allowed for numeric generics")] + SignedNumericGeneric, } /// Represents a parsing error, or a parsing error in the making. diff --git a/compiler/noirc_frontend/src/parser/parser/function.rs b/compiler/noirc_frontend/src/parser/parser/function.rs index 3e686ee4c85..fd1c7d5237f 100644 --- a/compiler/noirc_frontend/src/parser/parser/function.rs +++ b/compiler/noirc_frontend/src/parser/parser/function.rs @@ -4,13 +4,17 @@ use super::{ parameter_name_recovery, parameter_recovery, parenthesized, parse_type, pattern, self_parameter, where_clause, NoirParser, }; -use crate::ast::{ - FunctionDefinition, FunctionReturnType, ItemVisibility, NoirFunction, Param, Visibility, -}; use crate::parser::spanned; use crate::token::{Keyword, Token}; use crate::{ - ast::{UnresolvedGeneric, UnresolvedGenerics}, + ast::{ + FunctionDefinition, FunctionReturnType, ItemVisibility, NoirFunction, Param, Visibility, + }, + macros_api::UnresolvedTypeData, + parser::{ParserError, ParserErrorReason}, +}; +use crate::{ + ast::{Signedness, UnresolvedGeneric, UnresolvedGenerics}, parser::labels::ParsingRuleLabel, }; @@ -85,6 +89,19 @@ pub(super) fn numeric_generic() -> impl NoirParser { .then_ignore(just(Token::Colon)) .then(parse_type()) .map(|(ident, typ)| UnresolvedGeneric::Numeric { ident, typ }) + .validate(|generic, span, emit| { + if let UnresolvedGeneric::Numeric { typ, .. } = &generic { + if let UnresolvedTypeData::Integer(signedness, _) = typ.typ { + if matches!(signedness, Signedness::Signed) { + emit(ParserError::with_reason( + ParserErrorReason::SignedNumericGeneric, + span, + )); + } + } + } + generic + }) } pub(super) fn generic_type() -> impl NoirParser { @@ -233,6 +250,7 @@ mod test { "fn func_name(y: T) {}", "fn func_name(y: T) {}", "fn func_name(y: T) {}", + "fn func_name() {}", ], ); }