diff --git a/asg/src/error/mod.rs b/asg/src/error/mod.rs index ae488fb942..e459e52b02 100644 --- a/asg/src/error/mod.rs +++ b/asg/src/error/mod.rs @@ -203,6 +203,10 @@ impl AsgConvertError { ) } + pub fn unexpected_nonconst(span: &Span) -> Self { + Self::new_from_span("expected const, found non-const value".to_string(), span) + } + pub fn unresolved_reference(name: &str, span: &Span) -> Self { Self::new_from_span(format!("failed to resolve variable reference '{}'", name), span) } diff --git a/asg/src/expression/array_range_access.rs b/asg/src/expression/array_range_access.rs index 648bd18eaf..8bd5c80f2d 100644 --- a/asg/src/expression/array_range_access.rs +++ b/asg/src/expression/array_range_access.rs @@ -133,24 +133,41 @@ impl FromAst for ArrayRangeAccessExpression )); } } + let left = value + .left + .as_deref() + .map(|left| { + Arc::::from_ast(scope, left, Some(PartialType::Integer(None, Some(IntegerType::U32)))) + }) + .transpose()?; + let right = value + .right + .as_deref() + .map(|right| { + Arc::::from_ast(scope, right, Some(PartialType::Integer(None, Some(IntegerType::U32)))) + }) + .transpose()?; + + if let Some(left) = left.as_ref() { + if left.const_value().is_none() { + return Err(AsgConvertError::unexpected_nonconst( + &left.span().cloned().unwrap_or_default(), + )); + } + } + if let Some(right) = right.as_ref() { + if right.const_value().is_none() { + return Err(AsgConvertError::unexpected_nonconst( + &right.span().cloned().unwrap_or_default(), + )); + } + } Ok(ArrayRangeAccessExpression { parent: RefCell::new(None), span: Some(value.span.clone()), array, - left: value - .left - .as_deref() - .map(|left| { - Arc::::from_ast(scope, left, Some(PartialType::Integer(None, Some(IntegerType::U32)))) - }) - .transpose()?, - right: value - .right - .as_deref() - .map(|right| { - Arc::::from_ast(scope, right, Some(PartialType::Integer(None, Some(IntegerType::U32)))) - }) - .transpose()?, + left, + right, }) } } diff --git a/asg/src/type_.rs b/asg/src/type_.rs index 3f136386d6..fa86c6cfaf 100644 --- a/asg/src/type_.rs +++ b/asg/src/type_.rs @@ -102,11 +102,9 @@ impl PartialType { pub fn matches(&self, other: &Type) -> bool { match (self, other) { (PartialType::Type(t), other) => t.is_assignable_from(other), - (PartialType::Integer(self_sub_type, self_contextual_type), Type::Integer(sub_type)) => self_sub_type - .as_ref() - .or_else(|| self_contextual_type.as_ref()) - .map(|x| x == sub_type) - .unwrap_or(true), + (PartialType::Integer(self_sub_type, _), Type::Integer(sub_type)) => { + self_sub_type.as_ref().map(|x| x == sub_type).unwrap_or(true) + } (PartialType::Array(element, len), Type::Array(other_element, other_len)) => { if let Some(element) = element { if !element.matches(&*other_element) { diff --git a/asg/tests/pass/array/index_u8.leo b/asg/tests/pass/array/index_u8.leo new file mode 100644 index 0000000000..7ad1c6a9ea --- /dev/null +++ b/asg/tests/pass/array/index_u8.leo @@ -0,0 +1,5 @@ +function main() { + let x = 0u8; + let a = [0u8; 4]; + console.assert(a[x] == 0); +} diff --git a/asg/tests/pass/array/mod.rs b/asg/tests/pass/array/mod.rs index d8778641aa..563d4bad61 100644 --- a/asg/tests/pass/array/mod.rs +++ b/asg/tests/pass/array/mod.rs @@ -102,6 +102,12 @@ fn test_slice() { load_asg(program_string).unwrap(); } +#[test] +fn test_index_u8() { + let program_string = include_str!("index_u8.leo"); + load_asg(program_string).unwrap(); +} + #[test] fn test_slice_i8() { let program_string = include_str!("slice_i8.leo");