Skip to content

Commit

Permalink
unifying var and polymorphic int is polymorphic, simplify check_cast …
Browse files Browse the repository at this point in the history
…on values, revert commenting out arithmetic_generics test cases, cargo clippy / fmt
  • Loading branch information
michaeljklein committed Oct 9, 2024
1 parent 59bfb4c commit 17b3c7e
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 39 deletions.
38 changes: 12 additions & 26 deletions compiler/noirc_frontend/src/elaborator/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -873,7 +873,7 @@ impl<'context> Elaborator<'context> {
span,
reason: "casting from a non-integral type is unsupported".into(),
});
false
true
}
Type::Error => return Type::Error,
from => {
Expand All @@ -885,32 +885,18 @@ impl<'context> Elaborator<'context> {

// TODO(https://github.com/noir-lang/noir/issues/6247):
// handle negative literals
match (from_is_polymorphic, from_value_opt, to.integral_maximum_size()) {
// allow casting from unsized polymorphic variables
(true, None, _) => (),

// allow casting from sized to unsized types
(_, Some(_), None) => (),

// allow casting specific unsized types to sized types
(false, None, Some(_)) => (),

// when casting a polymorphic value to a specifically sized type,
// check that it fits or throw a warning
(true, Some(from_maximum_size), Some(to_maximum_size)) => {
if from_maximum_size > to_maximum_size {
let from = from.clone();
let reason = format!("casting untyped value ({}) to a type with a maximum size ({}) that's smaller than it", from_maximum_size, to_maximum_size);
// we warn that the 'to' type is too small for the value
self.push_err(TypeCheckError::DownsizingCast { from, span, reason });
}
// when casting a polymorphic value to a specifically sized type,
// check that it fits or throw a warning
if let (Some(from_value), Some(to_maximum_size)) =
(from_value_opt, to.integral_maximum_size())
{
if from_is_polymorphic && from_value > to_maximum_size {
let from = from.clone();
let to = to.clone();
let reason = format!("casting untyped value ({from_value}) to a type with a maximum size ({to_maximum_size}) that's smaller than it");
// we warn that the 'to' type is too small for the value
self.push_err(TypeCheckError::DownsizingCast { from, to, span, reason });
}

// allow casting typed values to other sizes
(false, Some(_), Some(_)) => (),

// allow casting from non-polymorphic unsized types
(false, None, None) => (),
}

match to {
Expand Down
4 changes: 2 additions & 2 deletions compiler/noirc_frontend/src/hir/type_check/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ pub enum TypeCheckError {
PublicReturnType { typ: Type, span: Span },
#[error("Cannot cast type {from}, 'as' is only for primitive field or integer types")]
InvalidCast { from: Type, span: Span, reason: String },
#[error("Casting value with {from} to a smaller type")]
DownsizingCast { from: Type, span: Span, reason: String },
#[error("Casting value with type {from} to a smaller type ({to})")]
DownsizingCast { from: Type, to: Type, span: Span, reason: String },
#[error("Expected a function, but found a(n) {found}")]
ExpectedFunction { found: Type, span: Span },
#[error("Type {lhs_type} has no member named {field_name}")]
Expand Down
2 changes: 1 addition & 1 deletion compiler/noirc_frontend/src/hir_def/types/arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ impl Type {
}

let divides_evenly = !lhs.infix_kind(rhs).is_field_element()
&& l_const.to_i128() % r_const.to_i128() != 0;
&& l_const.to_i128().checked_rem(r_const.to_i128()) == Some(0);

// If op is a division we need to ensure it divides evenly
if op == Division && (r_const == FieldElement::zero() || !divides_evenly) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,16 +114,12 @@ fn test_constant_folding<let N: u32>() {

// N - C1 + C2 = N - (C1 - C2)
let _: W<N - 3 + 2> = W::<N - 1> {};
// TODO see PR
// [Integer division is not the inverse of integer multiplication](https://github.com/noir-lang/noir/pull/6243)
// for more info
// // N * C1 / C2 = N * (C1 / C2)
// let _: W<N * 10 / 2> = W::<N * 5> {};
// TODO see PR
// [Integer division is not the inverse of integer multiplication](https://github.com/noir-lang/noir/pull/6243)
// for more info
// // N / C1 * C2 = N / (C1 / C2)
// let _: W<N / 10 * 2> = W::<N / 5> {};

// N * C1 / C2 = N * (C1 / C2)
let _: W<N * 10 / 2> = W::<N * 5> {};

// N / C1 * C2 = N / (C1 / C2)
let _: W<N / 10 * 2> = W::<N / 5> {};
}

fn test_non_constant_folding<let N: u32, let M: u32>() {
Expand Down

0 comments on commit 17b3c7e

Please sign in to comment.