add tests, fail gracefully on generic inference attempt and eq generic mismatch
This commit is contained in:
parent
d0622d849c
commit
f92df0fa1a
7 changed files with 73 additions and 25 deletions
|
@ -0,0 +1,7 @@
|
|||
struct A<N> {
|
||||
field[N] a
|
||||
}
|
||||
|
||||
def main():
|
||||
A<_> a = A { a: [1] }
|
||||
return
|
|
@ -0,0 +1,6 @@
|
|||
struct A<N> {
|
||||
field[N] a
|
||||
}
|
||||
|
||||
def main(A<1> a, A<2> b) -> bool:
|
||||
return a == b
|
|
@ -0,0 +1,4 @@
|
|||
struct A<N> {}
|
||||
|
||||
def main():
|
||||
return
|
|
@ -1216,18 +1216,26 @@ impl<'ast, T: Field> Checker<'ast, T> {
|
|||
let assignment = GGenericsAssignment(generics
|
||||
.into_iter()
|
||||
.zip(generic_identifiers)
|
||||
.filter_map(|(e, g)| e.map(|e| {
|
||||
self
|
||||
.check_expression(e, module_id, types)
|
||||
.and_then(|e| {
|
||||
UExpression::try_from_typed(e, &UBitwidth::B32)
|
||||
.map(|e| (g, e))
|
||||
.map_err(|e| ErrorInner {
|
||||
pos: Some(pos),
|
||||
message: format!("Expected u32 expression, but got expression of type {}", e.get_type()),
|
||||
})
|
||||
})
|
||||
}))
|
||||
.map(|(e, g)| match e {
|
||||
Some(e) => {
|
||||
self
|
||||
.check_expression(e, module_id, types)
|
||||
.and_then(|e| {
|
||||
UExpression::try_from_typed(e, &UBitwidth::B32)
|
||||
.map(|e| (g, e))
|
||||
.map_err(|e| ErrorInner {
|
||||
pos: Some(pos),
|
||||
message: format!("Expected u32 expression, but got expression of type {}", e.get_type()),
|
||||
})
|
||||
})
|
||||
},
|
||||
None => Err(ErrorInner {
|
||||
pos: Some(pos),
|
||||
message:
|
||||
"Expected u32 constant or identifier, but found `_`. Generic inference is not supported yet."
|
||||
.into(),
|
||||
})
|
||||
})
|
||||
.collect::<Result<_, _>>()?);
|
||||
|
||||
// specialize the declared type using the generic assignment
|
||||
|
|
|
@ -1279,6 +1279,24 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> {
|
|||
|
||||
Ok(BooleanExpression::ArrayEq(box e1, box e2))
|
||||
}
|
||||
BooleanExpression::StructEq(box e1, box e2) => {
|
||||
let e1 = self.fold_struct_expression(e1)?;
|
||||
let e2 = self.fold_struct_expression(e2)?;
|
||||
|
||||
if let (Ok(t1), Ok(t2)) = (
|
||||
ConcreteType::try_from(e1.get_type()),
|
||||
ConcreteType::try_from(e2.get_type()),
|
||||
) {
|
||||
if t1 != t2 {
|
||||
return Err(Error::Type(format!(
|
||||
"Cannot compare {} of type {} to {} of type {}",
|
||||
e1, t1, e2, t2
|
||||
)));
|
||||
}
|
||||
};
|
||||
|
||||
Ok(BooleanExpression::StructEq(box e1, box e2))
|
||||
}
|
||||
BooleanExpression::FieldLt(box e1, box e2) => {
|
||||
let e1 = self.fold_field_expression(e1)?;
|
||||
let e2 = self.fold_field_expression(e2)?;
|
||||
|
|
|
@ -230,12 +230,15 @@ mod tests {
|
|||
public: true,
|
||||
ty: ConcreteType::Struct(ConcreteStructType::new(
|
||||
"".into(),
|
||||
"Foo".into(),
|
||||
vec![],
|
||||
vec![
|
||||
ConcreteStructMember::new(String::from("a"), ConcreteType::FieldElement),
|
||||
ConcreteStructMember::new(String::from("b"), ConcreteType::Boolean),
|
||||
],
|
||||
"Bar".into(),
|
||||
vec![Some(1usize)],
|
||||
vec![ConcreteStructMember::new(
|
||||
String::from("a"),
|
||||
ConcreteType::Array(ConcreteArrayType::new(
|
||||
ConcreteType::FieldElement,
|
||||
1usize,
|
||||
)),
|
||||
)],
|
||||
)),
|
||||
}],
|
||||
outputs: vec![ConcreteType::Struct(ConcreteStructType::new(
|
||||
|
@ -259,16 +262,18 @@ mod tests {
|
|||
"public": true,
|
||||
"type": "struct",
|
||||
"components": {
|
||||
"name": "Foo",
|
||||
"generics": [],
|
||||
"name": "Bar",
|
||||
"generics": [
|
||||
1
|
||||
],
|
||||
"members": [
|
||||
{
|
||||
"name": "a",
|
||||
"type": "field"
|
||||
},
|
||||
{
|
||||
"name": "b",
|
||||
"type": "bool"
|
||||
"type": "array",
|
||||
"components": {
|
||||
"size": 1,
|
||||
"type": "field"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue