Skip to content

Commit

Permalink
Test (and comment) re. nested FuncDefns
Browse files Browse the repository at this point in the history
  • Loading branch information
acl-cqc committed Nov 16, 2023
1 parent d9da463 commit 3652d56
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/hugr/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,8 @@ impl<'a, 'b> ValidationContext<'a, 'b> {
}
}

// Compute cumulative TypeParams for nested FuncDefns, i.e. allow inner FuncDefns
// to refer to type parameters from outer FuncDefns.
let mut v: Vec<TypeParam>;
let var_decls = if let OpType::FuncDefn(FuncDefn { signature, .. })
| OpType::FuncDecl(FuncDecl { signature, .. }) = op_type
Expand Down
40 changes: 40 additions & 0 deletions src/hugr/validate/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -840,3 +840,43 @@ fn typevars_declared() -> Result<(), Box<dyn std::error::Error>> {
assert!(f.finish_prelude_hugr_with_outputs([w]).is_err());
Ok(())
}

/// Test that nested FuncDefns can use Type Variables declared by enclosing FuncDefns
#[test]
fn nested_typevars() -> Result<(), Box<dyn std::error::Error>> {
const OUTER_BOUND: TypeBound = TypeBound::Any;
const INNER_BOUND: TypeBound = TypeBound::Copyable;
fn build(t: Type) -> Result<Hugr, BuildError> {
let mut outer = FunctionBuilder::new(
"outer",
PolyFuncType::new(
[OUTER_BOUND.into()],
FunctionType::new_endo(vec![Type::new_var_use(0, TypeBound::Any)]),
),
)?;
let inner = outer.define_function(
"inner",
PolyFuncType::new([INNER_BOUND.into()], FunctionType::new_endo(vec![t])),
)?;
let [w] = inner.input_wires_arr();
inner.finish_with_outputs([w])?;
let [w] = outer.input_wires_arr();
outer.finish_prelude_hugr_with_outputs([w])
}
assert!(build(Type::new_var_use(0, INNER_BOUND)).is_ok());
assert!(build(Type::new_var_use(1, OUTER_BOUND)).is_ok());
assert_matches!(build(Type::new_var_use(0, OUTER_BOUND)).unwrap_err(),
BuildError::InvalidHUGR(ValidationError::SignatureError { cause: SignatureError::TypeVarDoesNotMatchDeclaration { actual, cached }, .. }) =>
actual == INNER_BOUND.into() && cached == OUTER_BOUND.into());
assert_matches!(
build(Type::new_var_use(2, OUTER_BOUND)).unwrap_err(),
BuildError::InvalidHUGR(ValidationError::SignatureError {
cause: SignatureError::FreeTypeVar {
idx: 2,
num_decls: 2
},
..
})
);
Ok(())
}

0 comments on commit 3652d56

Please sign in to comment.