Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
87bae02
wip: add Type::Txm(typ, from, to) as type-level checked_transmute(fro…
michaeljklein Oct 22, 2024
bf06178
wip debugging stack overflow, remove 'x' parameter from Txm since it …
michaeljklein Oct 23, 2024
24c9f1d
fixed type-level checked_transmute stack overflow, only run simplific…
michaeljklein Oct 24, 2024
bca5a85
ensure simplifications are only run on the 'to' side of Txm, cleanup,…
michaeljklein Oct 24, 2024
202e43b
rename Txm -> CheckedCast, address several TODO's
michaeljklein Oct 25, 2024
4bbb827
Merge branch 'master' into michaeljklein/arith-generics-transmute-type
michaeljklein Oct 25, 2024
fb325ec
.
michaeljklein Oct 25, 2024
cf88a9e
Merge branch 'master' into michaeljklein/arith-generics-transmute-type
michaeljklein Oct 28, 2024
ffba14a
Merge branch 'master' into michaeljklein/arith-generics-transmute-type
michaeljklein Oct 29, 2024
1922206
Update compiler/noirc_frontend/src/hir_def/types.rs
michaeljklein Oct 29, 2024
9158d7b
adding errors to evaluate_to_field_element, added more detail to seve…
michaeljklein Oct 29, 2024
8e897aa
CheckedCast(to, from) -> CheckedCast { from, to }
michaeljklein Oct 31, 2024
6491c4a
propagate error instead of unwrapping evaluate_to_field_element, add …
michaeljklein Oct 31, 2024
478c850
wip TODO's
michaeljklein Oct 31, 2024
9a75192
debugging failing arithmetic generics test, adding span to field_coun…
michaeljklein Nov 1, 2024
b81d4ae
Merge branch 'master' into michaeljklein/arith-generics-transmute-type
michaeljklein Nov 1, 2024
36198d3
rename ResolverError::OverflowInType -> BinaryOpError, checking remai…
michaeljklein Nov 1, 2024
aa4c4bc
Merge branch 'master' into michaeljklein/arith-generics-transmute-type
TomAFrench Nov 5, 2024
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
20 changes: 17 additions & 3 deletions compiler/noirc_driver/src/abi_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use iter_extended::vecmap;
use noirc_abi::{
Abi, AbiErrorType, AbiParameter, AbiReturnType, AbiType, AbiValue, AbiVisibility, Sign,
};
use noirc_errors::Span;
use noirc_frontend::ast::{Signedness, Visibility};
use noirc_frontend::TypeBinding;
use noirc_frontend::{
Expand Down Expand Up @@ -39,10 +40,20 @@ pub(super) fn gen_abi(
Abi { parameters, return_type, error_types }
}

// Get the Span of the root crate's main function, or else a dummy span if that fails
fn get_main_function_span(context: &Context) -> Span {
if let Some(func_id) = context.get_main_function(context.root_crate_id()) {
context.function_meta(&func_id).location.span
} else {
Span::default()
}
}

fn build_abi_error_type(context: &Context, typ: &Type) -> AbiErrorType {
match typ {
Type::FmtString(len, item_types) => {
let length = len.evaluate_to_u32().expect("Cannot evaluate fmt length");
let span = get_main_function_span(context);
let length = len.evaluate_to_u32(span).expect("Cannot evaluate fmt length");
let Type::Tuple(item_types) = item_types.as_ref() else {
unreachable!("FmtString items must be a tuple")
};
Expand All @@ -58,8 +69,9 @@ pub(super) fn abi_type_from_hir_type(context: &Context, typ: &Type) -> AbiType {
match typ {
Type::FieldElement => AbiType::Field,
Type::Array(size, typ) => {
let span = get_main_function_span(context);
let length = size
.evaluate_to_u32()
.evaluate_to_u32(span)
.expect("Cannot have variable sized arrays as a parameter to main");
let typ = typ.as_ref();
AbiType::Array { length, typ: Box::new(abi_type_from_hir_type(context, typ)) }
Expand All @@ -86,8 +98,9 @@ pub(super) fn abi_type_from_hir_type(context: &Context, typ: &Type) -> AbiType {
}
Type::Bool => AbiType::Boolean,
Type::String(size) => {
let span = get_main_function_span(context);
let size = size
.evaluate_to_u32()
.evaluate_to_u32(span)
.expect("Cannot have variable sized strings as a parameter to main");
AbiType::String { length: size }
}
Expand All @@ -102,6 +115,7 @@ pub(super) fn abi_type_from_hir_type(context: &Context, typ: &Type) -> AbiType {
AbiType::Struct { fields, path }
}
Type::Alias(def, args) => abi_type_from_hir_type(context, &def.borrow().get_type(args)),
Type::CheckedCast { to, .. } => abi_type_from_hir_type(context, to),
Type::Tuple(fields) => {
let fields = vecmap(fields, |typ| abi_type_from_hir_type(context, typ));
AbiType::Tuple { fields }
Expand Down
4 changes: 2 additions & 2 deletions compiler/noirc_evaluator/src/ssa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,8 +365,8 @@ fn split_public_and_private_inputs(
func_sig
.0
.iter()
.map(|(_, typ, visibility)| {
let num_field_elements_needed = typ.field_count() as usize;
.map(|(pattern, typ, visibility)| {
let num_field_elements_needed = typ.field_count(&pattern.location()) as usize;
let witnesses = input_witnesses[idx..idx + num_field_elements_needed].to_vec();
idx += num_field_elements_needed;
(visibility, witnesses)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl DataBusBuilder {
ast::Visibility::CallData(id) => DatabusVisibility::CallData(id),
ast::Visibility::ReturnData => DatabusVisibility::ReturnData,
};
let len = param.1.field_count() as usize;
let len = param.1.field_count(&param.0.location()) as usize;
params_is_databus.extend(vec![is_databus; len]);
}
params_is_databus
Expand Down
8 changes: 8 additions & 0 deletions compiler/noirc_frontend/src/elaborator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -896,6 +896,10 @@ impl<'context> Elaborator<'context> {
Type::Alias(alias_type, generics) => {
self.mark_type_as_used(&alias_type.borrow().get_type(generics));
}
Type::CheckedCast { from, to } => {
self.mark_type_as_used(from);
self.mark_type_as_used(to);
}
Type::MutableReference(typ) => {
self.mark_type_as_used(typ);
}
Expand Down Expand Up @@ -1501,6 +1505,10 @@ impl<'context> Elaborator<'context> {
span,
);
}
Type::CheckedCast { from, to } => {
self.check_type_is_not_more_private_then_item(name, visibility, from, span);
self.check_type_is_not_more_private_then_item(name, visibility, to, span);
}
Type::Function(args, return_type, env, _) => {
for arg in args {
self.check_type_is_not_more_private_then_item(name, visibility, arg, span);
Expand Down
29 changes: 23 additions & 6 deletions compiler/noirc_frontend/src/elaborator/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -462,14 +462,26 @@ impl<'context> Elaborator<'context> {
});
return Type::Error;
}
if let Some(result) = op.function(lhs, rhs, &lhs_kind) {
Type::Constant(result, lhs_kind)
} else {
self.push_err(ResolverError::OverflowInType { lhs, op, rhs, span });
Type::Error
match op.function(lhs, rhs, &lhs_kind, span) {
Ok(result) => Type::Constant(result, lhs_kind),
Err(err) => {
let err = Box::new(err);
self.push_err(ResolverError::BinaryOpError {
lhs,
op,
rhs,
err,
span,
});
Type::Error
}
}
}
(lhs, rhs) => Type::InfixExpr(Box::new(lhs), op, Box::new(rhs)).canonicalize(),
(lhs, rhs) => {
let infix = Type::InfixExpr(Box::new(lhs), op, Box::new(rhs));
Type::CheckedCast { from: Box::new(infix.clone()), to: Box::new(infix) }
.canonicalize()
}
}
}
UnresolvedTypeExpression::AsTraitPath(path) => {
Expand Down Expand Up @@ -1738,6 +1750,11 @@ impl<'context> Elaborator<'context> {
| Type::Quoted(_)
| Type::Forall(_, _) => (),

Type::CheckedCast { from, to } => {
Self::find_numeric_generics_in_type(from, found);
Self::find_numeric_generics_in_type(to, found);
}

Type::TraitAsType(_, _, args) => {
for arg in &args.ordered {
Self::find_numeric_generics_in_type(arg, found);
Expand Down
20 changes: 15 additions & 5 deletions compiler/noirc_frontend/src/hir/comptime/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use std::rc::Rc;

use crate::{
ast::TraitBound,
hir::{def_collector::dc_crate::CompilationError, type_check::NoMatchingImplFoundError},
hir::{
def_collector::dc_crate::CompilationError,
type_check::{NoMatchingImplFoundError, TypeCheckError},
},
parser::ParserError,
Type,
};
Expand Down Expand Up @@ -87,6 +90,7 @@ pub enum InterpreterError {
},
NonIntegerArrayLength {
typ: Type,
err: Option<Box<TypeCheckError>>,
location: Location,
},
NonNumericCasted {
Expand Down Expand Up @@ -228,6 +232,7 @@ pub enum InterpreterError {
},
UnknownArrayLength {
length: Type,
err: Box<TypeCheckError>,
location: Location,
},

Expand Down Expand Up @@ -435,9 +440,13 @@ impl<'a> From<&'a InterpreterError> for CustomDiagnostic {
let secondary = "This is likely a bug".into();
CustomDiagnostic::simple_error(msg, secondary, location.span)
}
InterpreterError::NonIntegerArrayLength { typ, location } => {
InterpreterError::NonIntegerArrayLength { typ, err, location } => {
let msg = format!("Non-integer array length: `{typ}`");
let secondary = "Array lengths must be integers".into();
let secondary = if let Some(err) = err {
format!("Array lengths must be integers, but evaluating `{typ}` resulted in `{err}`")
} else {
"Array lengths must be integers".to_string()
};
CustomDiagnostic::simple_error(msg, secondary, location.span)
}
InterpreterError::NonNumericCasted { typ, location } => {
Expand Down Expand Up @@ -640,9 +649,10 @@ impl<'a> From<&'a InterpreterError> for CustomDiagnostic {
let msg = format!("`{expression}` is not a valid function body");
CustomDiagnostic::simple_error(msg, String::new(), location.span)
}
InterpreterError::UnknownArrayLength { length, location } => {
InterpreterError::UnknownArrayLength { length, err, location } => {
let msg = format!("Could not determine array length `{length}`");
CustomDiagnostic::simple_error(msg, String::new(), location.span)
let secondary = format!("Evaluating the length failed with: `{err}`");
CustomDiagnostic::simple_error(msg, secondary, location.span)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@ impl Type {
let name = Path::from_single(name.as_ref().clone(), Span::default());
UnresolvedTypeData::Named(name, GenericTypeArgs::default(), true)
}
Type::CheckedCast { to, .. } => to.to_display_ast().typ,
Type::Function(args, ret, env, unconstrained) => {
let args = vecmap(args, |arg| arg.to_display_ast());
let ret = Box::new(ret.to_display_ast());
Expand Down
44 changes: 27 additions & 17 deletions compiler/noirc_frontend/src/hir/comptime/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -585,20 +585,25 @@ impl<'local, 'interner> Interpreter<'local, 'interner> {
}
DefinitionKind::NumericGeneric(type_variable, numeric_typ) => {
let value = match &*type_variable.borrow() {
TypeBinding::Unbound(_, _) => None,
TypeBinding::Unbound(_, _) => {
let typ = self.elaborator.interner.id_type(id);
let location = self.elaborator.interner.expr_location(&id);
Err(InterpreterError::NonIntegerArrayLength { typ, err: None, location })
}
TypeBinding::Bound(binding) => {
binding.evaluate_to_field_element(&Kind::Numeric(numeric_typ.clone()))
let span = self.elaborator.interner.id_location(id).span;
binding
.evaluate_to_field_element(&Kind::Numeric(numeric_typ.clone()), span)
.map_err(|err| {
let typ = Type::TypeVariable(type_variable.clone());
let err = Some(Box::new(err));
let location = self.elaborator.interner.expr_location(&id);
InterpreterError::NonIntegerArrayLength { typ, err, location }
})
}
};
}?;

if let Some(value) = value {
let typ = self.elaborator.interner.id_type(id);
self.evaluate_integer(value, false, id)
} else {
let location = self.elaborator.interner.expr_location(&id);
let typ = Type::TypeVariable(type_variable.clone());
Err(InterpreterError::NonIntegerArrayLength { typ, location })
}
self.evaluate_integer(value, false, id)
}
}
}
Expand Down Expand Up @@ -805,12 +810,17 @@ impl<'local, 'interner> Interpreter<'local, 'interner> {
HirArrayLiteral::Repeated { repeated_element, length } => {
let element = self.evaluate(repeated_element)?;

if let Some(length) = length.evaluate_to_u32() {
let elements = (0..length).map(|_| element.clone()).collect();
Ok(Value::Array(elements, typ))
} else {
let location = self.elaborator.interner.expr_location(&id);
Err(InterpreterError::NonIntegerArrayLength { typ: length, location })
let span = self.elaborator.interner.id_location(id).span;
match length.evaluate_to_u32(span) {
Ok(length) => {
let elements = (0..length).map(|_| element.clone()).collect();
Ok(Value::Array(elements, typ))
}
Err(err) => {
let err = Some(Box::new(err));
let location = self.elaborator.interner.expr_location(&id);
Err(InterpreterError::NonIntegerArrayLength { typ: length, err, location })
}
}
}
}
Expand Down
Loading