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
14 changes: 7 additions & 7 deletions compiler/noirc_evaluator/src/ssa/ir/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,19 +62,19 @@ impl NumericType {
match self {
NumericType::Unsigned { bit_size } => {
let max = if bit_size == 128 { u128::MAX } else { 2u128.pow(bit_size) - 1 };
if value.is_negative() {
return Some(format!("0..={max}"));
if value.is_negative() || value > SignedField::positive(max) {
Some(format!("0..={max}"))
} else {
None
}
if value.absolute_value() <= max.into() { None } else { Some(format!("0..={max}")) }
}
NumericType::Signed { bit_size } => {
let min = 2u128.pow(bit_size - 1);
let max = 2u128.pow(bit_size - 1) - 1;
let target_max = if value.is_negative() { min } else { max };
if value.absolute_value() <= target_max.into() {
None
} else {
if value > SignedField::positive(max) || value < SignedField::negative(min) {
Some(format!("-{min}..={max}"))
} else {
None
}
}
NumericType::NativeField => None,
Expand Down
14 changes: 4 additions & 10 deletions compiler/noirc_frontend/src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ pub use function::*;
#[cfg(test)]
use proptest_derive::Arbitrary;

use acvm::FieldElement;
pub use docs::*;
pub use enumeration::*;
use noirc_errors::Span;
Expand All @@ -34,6 +33,7 @@ pub use traits::*;
pub use type_alias::*;

use crate::QuotedType;
use crate::signed_field::SignedField;
use crate::token::IntegerTypeSuffix;
use crate::{
BinaryTypeOperator,
Expand All @@ -42,7 +42,6 @@ use crate::{
shared::Signedness,
};

use acvm::acir::AcirField;
use iter_extended::vecmap;

use strum::IntoEnumIterator;
Expand Down Expand Up @@ -234,7 +233,7 @@ impl From<Vec<GenericTypeArg>> for GenericTypeArgs {
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub enum UnresolvedTypeExpression {
Variable(Path),
Constant(FieldElement, Option<IntegerTypeSuffix>, Location),
Constant(SignedField, Option<IntegerTypeSuffix>, Location),
BinaryOperation(
Box<UnresolvedTypeExpression>,
BinaryTypeOperator,
Expand Down Expand Up @@ -525,17 +524,12 @@ impl UnresolvedTypeExpression {
fn from_expr_helper(expr: Expression) -> Result<UnresolvedTypeExpression, Expression> {
match expr.kind {
ExpressionKind::Literal(Literal::Integer(int, suffix)) => {
match int.try_to_unsigned::<u32>() {
Some(int) => {
Ok(UnresolvedTypeExpression::Constant(int.into(), suffix, expr.location))
}
None => Err(expr),
}
Ok(UnresolvedTypeExpression::Constant(int, suffix, expr.location))
}
ExpressionKind::Variable(path) => Ok(UnresolvedTypeExpression::Variable(path)),
ExpressionKind::Prefix(prefix) if prefix.operator == UnaryOp::Minus => {
let lhs = Box::new(UnresolvedTypeExpression::Constant(
FieldElement::zero(),
SignedField::zero(),
None,
expr.location,
));
Expand Down
7 changes: 3 additions & 4 deletions compiler/noirc_frontend/src/ast/visitor.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use acvm::FieldElement;
use noirc_errors::{Location, Span};

use crate::{
Expand Down Expand Up @@ -469,7 +468,7 @@ pub trait Visitor {

fn visit_constant_type_expression(
&mut self,
_value: FieldElement,
_value: SignedField,
_suffix: Option<IntegerTypeSuffix>,
_span: Span,
) {
Expand Down Expand Up @@ -1551,8 +1550,8 @@ impl UnresolvedTypeExpression {
path.accept(visitor);
}
}
UnresolvedTypeExpression::Constant(field_element, suffix, location) => {
visitor.visit_constant_type_expression(*field_element, *suffix, location.span);
UnresolvedTypeExpression::Constant(value, suffix, location) => {
visitor.visit_constant_type_expression(*value, *suffix, location.span);
}
UnresolvedTypeExpression::BinaryOperation(lhs, op, rhs, location) => {
if visitor.visit_binary_type_expression(lhs, *op, rhs, location.span) {
Expand Down
2 changes: 1 addition & 1 deletion compiler/noirc_frontend/src/elaborator/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -795,7 +795,7 @@ impl Elaborator<'_> {

let value = match constant {
Value::Bool(value) => SignedField::positive(value),
Value::Field(value) => SignedField::positive(value),
Comment thread
jfecher marked this conversation as resolved.
Value::Field(value) => value,
Value::I8(value) => signed_to_signed_field!(value),
Value::I16(value) => signed_to_signed_field!(value),
Value::I32(value) => signed_to_signed_field!(value),
Expand Down
4 changes: 2 additions & 2 deletions compiler/noirc_frontend/src/elaborator/expressions.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use acvm::{AcirField, FieldElement};
use iter_extended::vecmap;
use noirc_errors::{Located, Location};
use rustc_hash::FxHashSet as HashSet;
Expand Down Expand Up @@ -36,6 +35,7 @@ use crate::{
DefinitionId, DefinitionKind, ExprId, FuncId, InternedStatementKind, StmtId, TraitItemId,
},
shared::Signedness,
signed_field::SignedField,
token::{FmtStrFragment, IntegerTypeSuffix, Tokens},
};

Expand Down Expand Up @@ -353,7 +353,7 @@ impl Elaborator<'_> {
let length = UnresolvedTypeExpression::from_expr(*length, location).unwrap_or_else(
|error| {
self.push_err(ResolverError::ParserError(Box::new(error)));
UnresolvedTypeExpression::Constant(FieldElement::zero(), None, location)
UnresolvedTypeExpression::Constant(SignedField::zero(), None, location)
},
);

Expand Down
4 changes: 2 additions & 2 deletions compiler/noirc_frontend/src/elaborator/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,7 @@ impl Elaborator<'_> {
return None;
};

let Some(global_value) = global_value.to_field_element() else {
let Some(global_value) = global_value.to_signed_field() else {
let global_value = global_value.clone();
if global_value.is_integral() {
self.push_err(ResolverError::NegativeGlobalType { location, global_value });
Expand All @@ -682,7 +682,7 @@ impl Elaborator<'_> {
};

let Ok(global_value) = kind.ensure_value_fits(global_value, location) else {
self.push_err(ResolverError::GlobalLargerThanKind {
self.push_err(ResolverError::GlobalDoesNotFitItsType {
location,
global_value,
kind,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ use crate::hir_def::expr::{
use crate::hir_def::stmt::{HirLValue, HirPattern, HirStatement};
use crate::hir_def::types::{Type, TypeBinding};
use crate::node_interner::{DefinitionId, ExprId, NodeInterner, StmtId};
use crate::signed_field::SignedField;

// TODO:
// - Full path for idents & types
Expand Down Expand Up @@ -534,7 +533,7 @@ impl HirArrayLiteral {
let length = match length {
Type::Constant(length, kind) => {
let suffix = kind.as_integer_type_suffix();
let literal = Literal::Integer(SignedField::positive(*length), suffix);
let literal = Literal::Integer(*length, suffix);
let expr_kind = ExpressionKind::Literal(literal);
Box::new(Expression::new(expr_kind, location))
}
Expand Down
9 changes: 4 additions & 5 deletions compiler/noirc_frontend/src/hir/comptime/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -647,9 +647,9 @@ impl<'local, 'interner> Interpreter<'local, 'interner> {
let location = self.elaborator.interner.expr_location(&id);
match associated_type
.typ
.evaluate_to_field_element(&associated_type.typ.kind(), location)
.evaluate_to_signed_field(&associated_type.typ.kind(), location)
{
Ok(value) => self.evaluate_integer(value.into(), id),
Ok(value) => self.evaluate_integer(value, id),
Err(err) => Err(InterpreterError::NonIntegerArrayLength {
typ: associated_type.typ.clone(),
err: Some(Box::new(err)),
Expand All @@ -665,15 +665,15 @@ impl<'local, 'interner> Interpreter<'local, 'interner> {
fn evaluate_numeric_generic(&self, value: Type, expected: &Type, id: ExprId) -> IResult<Value> {
let location = self.elaborator.interner.id_location(id);
let value = value
.evaluate_to_field_element(&Kind::Numeric(Box::new(expected.clone())), location)
.evaluate_to_signed_field(&Kind::Numeric(Box::new(expected.clone())), location)
.map_err(|err| {
let typ = value;
let err = Some(Box::new(err));
let location = self.elaborator.interner.expr_location(&id);
InterpreterError::NonIntegerArrayLength { typ, err, location }
})?;

self.evaluate_integer(value.into(), id)
self.evaluate_integer(value, id)
}

fn evaluate_trait_item(&mut self, item: TraitItem, id: ExprId) -> IResult<Value> {
Expand Down Expand Up @@ -1633,7 +1633,6 @@ fn bounds_check(array: Value, index: Value, location: Location) -> IResult<(Vect
let u64: Option<u64> = value.try_to_unsigned();
u64.and_then(|value| value.try_into().ok()).ok_or_else(|| {
let typ = Type::default_int_type();
let value = SignedField::positive(value);
InterpreterError::IntegerOutOfRangeForType { value, typ, location }
})?
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -962,7 +962,7 @@ fn to_le_radix(
let (limb_count, element_type) = if let Type::Array(length, element_type) = return_type {
if let Type::Constant(limb_count, kind) = *length {
if kind.unifies(&Kind::u32()) {
(limb_count, element_type)
(limb_count.to_field_element(), element_type)
} else {
return Err(InterpreterError::TypeAnnotationsNeededForMethodCall { location });
}
Expand Down
17 changes: 5 additions & 12 deletions compiler/noirc_frontend/src/hir/comptime/value.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::{borrow::Cow, rc::Rc, vec};

use acvm::FieldElement;
use im::Vector;
use iter_extended::{try_vecmap, vecmap};
use noirc_errors::Location;
Expand Down Expand Up @@ -666,23 +665,17 @@ impl Value {
}
}

/// Converts any non-negative `Value` into a `FieldElement`.
/// Returns `None` for negative integers and non-integral `Value`s.
pub(crate) fn to_field_element(&self) -> Option<FieldElement> {
/// Converts any integral `Value` into a `SignedField`.
/// Returns `None` for non-integral `Value`s.
pub(crate) fn to_signed_field(&self) -> Option<SignedField> {
match self {
Self::Field(value) => {
if value.is_negative() {
None
} else {
Some(value.absolute_value())
}
}
Self::Field(value) => Some(*value),

Self::I8(value) => (*value >= 0).then_some((*value as u128).into()),
Self::I16(value) => (*value >= 0).then_some((*value as u128).into()),
Self::I32(value) => (*value >= 0).then_some((*value as u128).into()),
Self::I64(value) => (*value >= 0).then_some((*value as u128).into()),
Self::U1(value) => Some(FieldElement::from(*value)),
Self::U1(value) => Some(if *value { SignedField::one() } else { SignedField::zero() }),
Self::U8(value) => Some((*value as u128).into()),
Self::U16(value) => Some((*value as u128).into()),
Self::U32(value) => Some((*value as u128).into()),
Expand Down
14 changes: 7 additions & 7 deletions compiler/noirc_frontend/src/hir/resolution/errors.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use acvm::FieldElement;
pub use noirc_errors::Span;
use noirc_errors::{CustomDiagnostic as Diagnostic, Location};
use thiserror::Error;
Expand All @@ -9,6 +8,7 @@ use crate::{
elaborator::TypedPath,
hir::{comptime::Value, type_check::TypeCheckError},
parser::ParserError,
signed_field::SignedField,
usage_tracker::UnusedItem,
};

Expand Down Expand Up @@ -100,8 +100,8 @@ pub enum ResolverError {
NegativeGlobalType { location: Location, global_value: Value },
#[error("Globals used in a type position must be integers")]
NonIntegralGlobalType { location: Location, global_value: Value },
#[error("Global value `{global_value}` is larger than its kind's maximum value")]
GlobalLargerThanKind { location: Location, global_value: FieldElement, kind: Kind },
#[error("Global value `{global_value}` does not fit its kind's range")]
GlobalDoesNotFitItsType { location: Location, global_value: SignedField, kind: Kind },
#[error("Self-referential types are not supported")]
SelfReferentialType { location: Location },
#[error("#[no_predicates] attribute is only allowed on constrained functions")]
Expand All @@ -124,9 +124,9 @@ pub enum ResolverError {
AssociatedConstantsMustBeNumeric { location: Location },
#[error("Computing `{lhs} {op} {rhs}` failed with error {err}")]
BinaryOpError {
lhs: FieldElement,
lhs: SignedField,
op: crate::BinaryTypeOperator,
rhs: FieldElement,
rhs: SignedField,
err: Box<TypeCheckError>,
location: Location,
},
Expand Down Expand Up @@ -218,7 +218,7 @@ impl ResolverError {
| ResolverError::UnevaluatedGlobalType { location }
| ResolverError::NegativeGlobalType { location, .. }
| ResolverError::NonIntegralGlobalType { location, .. }
| ResolverError::GlobalLargerThanKind { location, .. }
| ResolverError::GlobalDoesNotFitItsType { location, .. }
| ResolverError::SelfReferentialType { location }
| ResolverError::UnquoteUsedOutsideQuote { location }
| ResolverError::InvalidSyntaxInMacroCall { location }
Expand Down Expand Up @@ -540,7 +540,7 @@ impl<'a> From<&'a ResolverError> for Diagnostic {
*location,
)
}
ResolverError::GlobalLargerThanKind { location, global_value, kind } => {
ResolverError::GlobalDoesNotFitItsType { location, global_value, kind } => {
Diagnostic::simple_error(
format!("Global value `{global_value}` is larger than its kind's maximum value"),
format!("Global's kind inferred to be `{kind}`"),
Expand Down
21 changes: 16 additions & 5 deletions compiler/noirc_frontend/src/hir/type_check/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ pub enum Source {
#[derive(Error, Debug, Clone, PartialEq, Eq)]
pub enum TypeCheckError {
#[error("Division by zero: {lhs} / {rhs}")]
DivisionByZero { lhs: FieldElement, rhs: FieldElement, location: Location },
DivisionByZero { lhs: SignedField, rhs: SignedField, location: Location },
#[error("Modulo on Field elements: {lhs} % {rhs}")]
ModuloOnFields { lhs: FieldElement, rhs: FieldElement, location: Location },
ModuloOnFields { lhs: SignedField, rhs: SignedField, location: Location },
#[error("The value `{expr}` cannot fit into `{ty}` which has range `{range}`")]
IntegerLiteralDoesNotFitItsType {
expr: SignedField,
Expand All @@ -48,11 +48,20 @@ pub enum TypeCheckError {
"The value `{value}` cannot fit into `{kind}` which has a maximum size of `{maximum_size}`"
)]
OverflowingConstant {
value: FieldElement,
value: SignedField,
kind: Kind,
maximum_size: FieldElement,
location: Location,
},
#[error(
"The value `{value}` cannot fit into `{kind}` which has a minimum size of `{minimum_size}`"
)]
UnderflowingConstant {
value: SignedField,
kind: Kind,
minimum_size: SignedField,
location: Location,
},
#[error("Evaluating `{op}` on `{lhs}`, `{rhs}` failed")]
FailingBinaryOp { op: BinaryTypeOperator, lhs: String, rhs: String, location: Location },
#[error("Type {typ:?} cannot be used in a {place:?}")]
Expand All @@ -67,8 +76,8 @@ pub enum TypeCheckError {
TypeCanonicalizationMismatch {
to: Type,
from: Type,
to_value: FieldElement,
from_value: FieldElement,
to_value: SignedField,
from_value: SignedField,
location: Location,
},
#[error("Expected {expected:?} found {found:?}")]
Expand Down Expand Up @@ -270,6 +279,7 @@ impl TypeCheckError {
| TypeCheckError::ModuloOnFields { location, .. }
| TypeCheckError::IntegerLiteralDoesNotFitItsType { location, .. }
| TypeCheckError::OverflowingConstant { location, .. }
| TypeCheckError::UnderflowingConstant { location, .. }
| TypeCheckError::FailingBinaryOp { location, .. }
| TypeCheckError::TypeCannotBeUsed { location, .. }
| TypeCheckError::TypeMismatch { expr_location: location, .. }
Expand Down Expand Up @@ -504,6 +514,7 @@ impl<'a> From<&'a TypeCheckError> for Diagnostic {
| TypeCheckError::FieldComparison { location, .. }
| TypeCheckError::IntegerLiteralDoesNotFitItsType { location, .. }
| TypeCheckError::OverflowingConstant { location, .. }
| TypeCheckError::UnderflowingConstant { location, .. }
| TypeCheckError::FailingBinaryOp { location, .. }
| TypeCheckError::FieldModulo { location }
| TypeCheckError::FieldNot { location }
Expand Down
Loading
Loading