Skip to content
Closed
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
3 changes: 2 additions & 1 deletion compiler/noirc_frontend/src/hir/comptime/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use noirc_errors::{CustomDiagnostic, Location};
use super::value::Value;

/// The possible errors that can halt the interpreter.
#[derive(Debug, Clone)]
// TODO: revert PartialEq
#[derive(Debug, Clone, PartialEq)]
pub enum InterpreterError {
ArgumentCountMismatch { expected: usize, actual: usize, location: Location },
TypeMismatch { expected: Type, value: Value, location: Location },
Expand Down
16 changes: 7 additions & 9 deletions compiler/noirc_frontend/src/hir/comptime/hir_to_ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::ast::{
use crate::ast::{ConstrainStatement, Expression, Statement, StatementKind};
use crate::hir_def::expr::{HirArrayLiteral, HirBlockExpression, HirExpression, HirIdent};
use crate::hir_def::stmt::{HirLValue, HirPattern, HirStatement};
use crate::hir_def::types::Type;
use crate::hir_def::types::{GenericArith, Type};
use crate::macros_api::HirLiteral;
use crate::node_interner::{ExprId, NodeInterner, StmtId};

Expand Down Expand Up @@ -270,10 +270,6 @@ impl Type {
let name = Path::from_single(name.as_ref().clone(), Span::default());
UnresolvedTypeData::TraitAsType(name, generics)
}
Type::NamedGeneric(_, name) => {
let name = Path::from_single(name.as_ref().clone(), Span::default());
UnresolvedTypeData::TraitAsType(name, Vec::new())
}
Type::Function(args, ret, env) => {
let args = vecmap(args, |arg| arg.to_ast());
let ret = Box::new(ret.to_ast());
Expand All @@ -289,9 +285,9 @@ impl Type {
// Since there is no UnresolvedTypeData equivalent for Type::Forall, we use
// this to ignore this case since it shouldn't be needed anyway.
Type::Forall(_, typ) => return typ.to_ast(),
Type::Constant(_) => panic!("Type::Constant where a type was expected: {self:?}"),
Type::Code => UnresolvedTypeData::Code,
Type::Error => UnresolvedTypeData::Error,
_ => unimplemented!("TODO: hir_to_ast deprecated"),
};

UnresolvedType { typ, span: None }
Expand All @@ -300,9 +296,10 @@ impl Type {
fn to_type_expression(&self) -> UnresolvedTypeExpression {
let span = Span::default();

// NOTE: hir_to_ast deprecated
match self.follow_bindings() {
Type::Constant(length) => UnresolvedTypeExpression::Constant(length, span),
Type::NamedGeneric(_, name) => {
Type::GenericArith(GenericArith::Constant(length), _) => UnresolvedTypeExpression::Constant(length, span),
Type::GenericArith(GenericArith::NamedGeneric(_, name), _) => {
let path = Path::from_single(name.as_ref().clone(), span);
UnresolvedTypeExpression::Variable(path)
}
Expand Down Expand Up @@ -342,7 +339,8 @@ impl HirArrayLiteral {
HirArrayLiteral::Repeated { repeated_element, length } => {
let repeated_element = Box::new(repeated_element.to_ast(interner));
let length = match length {
Type::Constant(length) => {
// NOTE: hir_to_ast deprecated
Type::GenericArith(GenericArith::Constant(length), _) => {
let literal = Literal::Integer((length as u128).into(), false);
let kind = ExpressionKind::Literal(literal);
Box::new(Expression::new(kind, span))
Expand Down
4 changes: 2 additions & 2 deletions compiler/noirc_frontend/src/hir/comptime/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{
hir_def::expr::{HirArrayLiteral, HirConstructorExpression, HirIdent, HirLambda, ImplKind},
macros_api::{HirExpression, HirLiteral, NodeInterner},
node_interner::{ExprId, FuncId},
Shared, Type,
Shared, Type, GenericArith,
};
use rustc_hash::FxHashMap as HashMap;

Expand Down Expand Up @@ -51,7 +51,7 @@ impl Value {
Value::U32(_) => Type::Integer(Signedness::Unsigned, IntegerBitSize::ThirtyTwo),
Value::U64(_) => Type::Integer(Signedness::Unsigned, IntegerBitSize::SixtyFour),
Value::String(value) => {
let length = Type::Constant(value.len() as u64);
let length = Type::GenericArith(GenericArith::Constant(value.len() as u64), vec![].into());
Type::String(Box::new(length))
}
Value::Function(_, typ) => return Cow::Borrowed(typ),
Expand Down
3 changes: 2 additions & 1 deletion compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ pub struct DefCollector {
pub(crate) type ImplMap =
HashMap<(UnresolvedType, LocalModuleId), Vec<(UnresolvedGenerics, Span, UnresolvedFunctions)>>;

#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq)]
// TODO: revert PartialEq
pub enum CompilationError {
ParseError(ParserError),
DefinitionError(DefCollectorErrorKind),
Expand Down
6 changes: 4 additions & 2 deletions compiler/noirc_frontend/src/hir/def_collector/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ pub enum DuplicateType {
TraitAssociatedFunction,
}

#[derive(Error, Debug, Clone)]
// TODO: revert PartialEq
#[derive(Error, Debug, Clone, PartialEq)]
pub enum DefCollectorErrorKind {
#[error("duplicate {typ} found in namespace")]
Duplicate { typ: DuplicateType, first_def: Ident, second_def: Ident },
Expand Down Expand Up @@ -69,7 +70,8 @@ pub enum DefCollectorErrorKind {
}

/// An error struct that macro processors can return.
#[derive(Debug, Clone)]
// TODO: revert PartialEq
#[derive(Debug, Clone, PartialEq)]
pub struct MacroError {
pub primary_message: String,
pub secondary_message: Option<String>,
Expand Down
7 changes: 7 additions & 0 deletions compiler/noirc_frontend/src/hir/resolution/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ pub enum ResolverError {
MissingRhsExpr { name: String, span: Span },
#[error("Expression invalid in an array length context")]
InvalidArrayLengthExpr { span: Span },
#[error("Expression invalid for generic arithmetic: only '+', '-', and '*' are allowed.")]
InvalidGenericArithOp { span: Span },
#[error("Integer too large to be evaluated in an array length context")]
IntegerTooLarge { span: Span },
#[error("No global or generic type parameter found with the given name")]
Expand Down Expand Up @@ -236,6 +238,11 @@ impl<'a> From<&'a ResolverError> for Diagnostic {
"Array-length expressions can only have simple integer operations and any variables used must be global constants".into(),
*span,
),
ResolverError::InvalidGenericArithOp { span } => Diagnostic::simple_error(
"Expression invalid for generic arithmetic with variables: only '+', '-', and '*' are allowed.".into(),
"Generic expressions can only have constants, variables, and simple integer operations: '+', '-', and '*'".into(),
*span,
),
ResolverError::IntegerTooLarge { span } => Diagnostic::simple_error(
"Integer too large to be evaluated to an array-length".into(),
"Array-lengths may be a maximum size of usize::MAX, including intermediate calculations".into(),
Expand Down
106 changes: 82 additions & 24 deletions compiler/noirc_frontend/src/hir/resolution/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ use crate::node_interner::{
DefinitionId, DefinitionKind, DependencyId, ExprId, FuncId, GlobalId, NodeInterner, StmtId,
StructId, TraitId, TraitImplId, TraitMethodId, TypeAliasId,
};
use crate::{Generics, Shared, StructType, Type, TypeAlias, TypeVariable, TypeVariableKind};
use crate::{BinaryTypeOperator, Generics, GenericArith, GenericArithOpKind, Shared, StructType, Type, TypeAlias, TypeVariable, TypeVariableKind};
use fm::FileId;
use iter_extended::vecmap;
use noirc_errors::{Location, Span, Spanned};
Expand Down Expand Up @@ -586,7 +586,7 @@ impl<'a> Resolver<'a> {
let env = Box::new(self.resolve_type_inner(*env, new_variables));

match *env {
Type::Unit | Type::Tuple(_) | Type::NamedGeneric(_, _) => {
Type::Unit | Type::Tuple(_) | Type::GenericArith(GenericArith::NamedGeneric(..), _) => {
Type::Function(args, ret, env)
}
_ => {
Expand Down Expand Up @@ -753,7 +753,7 @@ impl<'a> Resolver<'a> {
if path.segments.len() == 1 {
let name = &path.last_segment().0.contents;
if let Some((name, var, _)) = self.find_generic(name) {
return Some(Type::NamedGeneric(var.clone(), name.clone()));
return Some(Type::GenericArith(GenericArith::NamedGeneric(var.clone(), name.clone()), Shared::new(vec![])));
}
}

Expand All @@ -767,7 +767,7 @@ impl<'a> Resolver<'a> {
if let Some(error) = error {
self.push_err(error.into());
}
Some(Type::Constant(self.eval_global_as_array_length(id, path)))
Some(Type::GenericArith(GenericArith::Constant(self.eval_global_as_array_length(id, path)), vec![].into()))
}
_ => None,
}
Expand All @@ -787,7 +787,7 @@ impl<'a> Resolver<'a> {
// 'Named'Generic is a bit of a misnomer here, we want a type variable that
// wont be bound over but this one has no name since we do not currently
// require users to explicitly be generic over array lengths.
Type::NamedGeneric(typevar, Rc::new("".into()))
Type::GenericArith(GenericArith::NamedGeneric(typevar, Rc::new("".into())), vec![].into())
}
Some(length) => self.convert_expression_type(length),
}
Expand All @@ -798,25 +798,70 @@ impl<'a> Resolver<'a> {
UnresolvedTypeExpression::Variable(path) => {
self.lookup_generic_or_global_type(&path).unwrap_or_else(|| {
self.push_err(ResolverError::NoSuchNumericTypeVariable { path });
Type::Constant(0)
Type::GenericArith(GenericArith::Constant(0), vec![].into())
})
}
UnresolvedTypeExpression::Constant(int, _) => Type::Constant(int),
UnresolvedTypeExpression::BinaryOperation(lhs, op, rhs, _) => {
UnresolvedTypeExpression::Constant(int, _) => Type::GenericArith(GenericArith::Constant(int), vec![].into()),
UnresolvedTypeExpression::BinaryOperation(lhs, op, rhs, op_span) => {
let (lhs_span, rhs_span) = (lhs.span(), rhs.span());
let lhs = self.convert_expression_type(*lhs);
let rhs = self.convert_expression_type(*rhs);

match (lhs, rhs) {
(Type::Constant(lhs), Type::Constant(rhs)) => {
Type::Constant(op.function()(lhs, rhs))
// (Type::Constant(lhs), Type::Constant(rhs)) => {
// Type::Constant(op.function()(lhs, rhs))
// }

(Type::GenericArith(rhs, _), Type::GenericArith(lhs, _)) => {
match (lhs, rhs) {
(GenericArith::Constant(lhs), GenericArith::Constant(rhs)) => {
Type::GenericArith(GenericArith::Constant(op.function()(lhs, rhs)), vec![].into())
}
(lhs, rhs) => {
match op {
BinaryTypeOperator::Addition => {
Type::GenericArith(GenericArith::Op {
kind: GenericArithOpKind::Add,
lhs: Box::new(lhs),
rhs: Box::new(rhs),
}, vec![].into())
}
BinaryTypeOperator::Multiplication => {
Type::GenericArith(GenericArith::Op {
kind: GenericArithOpKind::Mul,
lhs: Box::new(lhs),
rhs: Box::new(rhs),
}, vec![].into())
}
BinaryTypeOperator::Subtraction => {
Type::GenericArith(GenericArith::Op {
kind: GenericArithOpKind::Sub,
lhs: Box::new(lhs),
rhs: Box::new(rhs),
}, vec![].into())
}
_ => {
self.push_err(ResolverError::InvalidGenericArithOp { span: op_span });
Type::GenericArith(GenericArith::Constant(0), vec![].into())
}
}
}
}


}
(lhs, _) => {
let span =
if !matches!(lhs, Type::Constant(_)) { lhs_span } else { rhs_span };
self.push_err(ResolverError::InvalidArrayLengthExpr { span });
Type::Constant(0)

(lhs, rhs) => {

// TODO cleanup
// let span =
// if !matches!(lhs, Type::Constant(_)) { lhs_span } else { rhs_span };
// // TODO: revert before PR
// dbg!("convert_expression_type", &lhs, &rhs);
self.push_err(ResolverError::InvalidArrayLengthExpr { span: op_span });
Type::GenericArith(GenericArith::Constant(0), vec![].into())
}

}
}
}
Expand Down Expand Up @@ -1195,8 +1240,10 @@ impl<'a> Resolver<'a> {
| Type::Unit
| Type::Error
| Type::TypeVariable(_, _)
| Type::Constant(_)
| Type::NamedGeneric(_, _)
// TODO does GenericArith have relevant cases?
// | Type::Constant(_)
// | Type::NamedGeneric(_, _)
| Type::GenericArith(..)
| Type::Code
| Type::Forall(_, _) => (),

Expand All @@ -1207,7 +1254,7 @@ impl<'a> Resolver<'a> {
}

Type::Array(length, element_type) => {
if let Type::NamedGeneric(type_variable, name) = length.as_ref() {
if let Type::GenericArith(GenericArith::NamedGeneric(type_variable, name), _) = length.as_ref() {
found.insert(name.to_string(), type_variable.clone());
}
Self::find_numeric_generics_in_type(element_type, found);
Expand All @@ -1232,7 +1279,7 @@ impl<'a> Resolver<'a> {

Type::Struct(struct_type, generics) => {
for (i, generic) in generics.iter().enumerate() {
if let Type::NamedGeneric(type_variable, name) = generic {
if let Type::GenericArith(GenericArith::NamedGeneric(type_variable, name), _) = generic {
if struct_type.borrow().generic_is_numeric(i) {
found.insert(name.to_string(), type_variable.clone());
}
Expand All @@ -1243,7 +1290,7 @@ impl<'a> Resolver<'a> {
}
Type::Alias(alias, generics) => {
for (i, generic) in generics.iter().enumerate() {
if let Type::NamedGeneric(type_variable, name) = generic {
if let Type::GenericArith(GenericArith::NamedGeneric(type_variable, name), _) = generic {
if alias.borrow().generic_is_numeric(i) {
found.insert(name.to_string(), type_variable.clone());
}
Expand All @@ -1254,12 +1301,12 @@ impl<'a> Resolver<'a> {
}
Type::MutableReference(element) => Self::find_numeric_generics_in_type(element, found),
Type::String(length) => {
if let Type::NamedGeneric(type_variable, name) = length.as_ref() {
if let Type::GenericArith(GenericArith::NamedGeneric(type_variable, name), _) = length.as_ref() {
found.insert(name.to_string(), type_variable.clone());
}
}
Type::FmtString(length, fields) => {
if let Type::NamedGeneric(type_variable, name) = length.as_ref() {
if let Type::GenericArith(GenericArith::NamedGeneric(type_variable, name), _) = length.as_ref() {
found.insert(name.to_string(), type_variable.clone());
}
Self::find_numeric_generics_in_type(fields, found);
Expand Down Expand Up @@ -2109,10 +2156,16 @@ impl<'a> Resolver<'a> {
let expression = let_statement.expression;
self.try_eval_array_length_id_with_fuel(expression, span, fuel - 1)
} else {
// TODO: revert before PR
dbg!("Global", definition);
Err(Some(ResolverError::InvalidArrayLengthExpr { span }))
}
}
_ => Err(Some(ResolverError::InvalidArrayLengthExpr { span })),
_ => {
// TODO: revert before PR
dbg!("Ident", definition);
Err(Some(ResolverError::InvalidArrayLengthExpr { span }))
}
}
}
HirExpression::Infix(infix) => {
Expand All @@ -2138,7 +2191,12 @@ impl<'a> Resolver<'a> {
BinaryOpKind::Modulo => Ok(lhs % rhs),
}
}
_other => Err(Some(ResolverError::InvalidArrayLengthExpr { span })),
_other => {
// TODO: revert before PR
dbg!("_other", _other);

Err(Some(ResolverError::InvalidArrayLengthExpr { span }))
}
}
}

Expand Down
11 changes: 6 additions & 5 deletions compiler/noirc_frontend/src/hir/type_check/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::{
types::Type,
},
node_interner::{DefinitionKind, ExprId, FuncId, TraitId, TraitImplKind, TraitMethodId},
TypeBinding, TypeBindings, TypeVariableKind,
TypeBinding, TypeBindings, TypeVariableKind, GenericArith,
};

use super::{errors::TypeCheckError, TypeChecker};
Expand Down Expand Up @@ -84,8 +84,9 @@ impl<'interner> TypeChecker<'interner> {
}
HirArrayLiteral::Repeated { repeated_element, length } => {
let elem_type = self.check_expression(&repeated_element);
// TODO: before PR: support other cases here?
let length = match length {
Type::Constant(length) => Ok(length),
Type::GenericArith(GenericArith::Constant(length), _) => Ok(length),
other => Err(Box::new(other)),
};
(length, Box::new(elem_type))
Expand Down Expand Up @@ -130,11 +131,11 @@ impl<'interner> TypeChecker<'interner> {
HirLiteral::Bool(_) => Type::Bool,
HirLiteral::Integer(_, _) => self.polymorphic_integer_or_field(),
HirLiteral::Str(string) => {
let len = Type::Constant(string.len() as u64);
let len = Type::GenericArith(GenericArith::Constant(string.len() as u64), vec![].into());
Type::String(Box::new(len))
}
HirLiteral::FmtStr(string, idents) => {
let len = Type::Constant(string.len() as u64);
let len = Type::GenericArith(GenericArith::Constant(string.len() as u64), vec![].into());
let types = vecmap(&idents, |elem| self.check_expression(elem));
Type::FmtString(Box::new(len), Box::new(Type::Tuple(types)))
}
Expand Down Expand Up @@ -934,7 +935,7 @@ impl<'interner> TypeChecker<'interner> {
});
None
}
Type::NamedGeneric(_, _) => {
Type::GenericArith(GenericArith::NamedGeneric(_, _), _) => {
let func_meta = self.interner.function_meta(
&self.current_function.expect("unexpected method outside a function"),
);
Expand Down
Loading