Skip to content

Commit

Permalink
Enforce globally unique names for callables declared as `SimulatableI…
Browse files Browse the repository at this point in the history
…ntrinsic`

Fixes #1817
  • Loading branch information
swernli committed Aug 12, 2024
1 parent 7df2d20 commit 60b065b
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 4 deletions.
15 changes: 11 additions & 4 deletions compiler/qsc_frontend/src/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ pub(super) enum Error {

#[error("duplicate intrinsic `{0}`")]
#[diagnostic(help(
"each callable declared as `body intrinsic` must have a globally unique name"
"each callable declared as `body intrinsic` or `@SimulatableIntrinsic` must have a globally unique name"
))]
#[diagnostic(code("Qsc.Resolve.DuplicateIntrinsic"))]
DuplicateIntrinsic(String, #[label] Span),
Expand Down Expand Up @@ -1733,7 +1733,8 @@ fn bind_callable(
scope: &mut GlobalScope,
) -> Result<(), Vec<Error>> {
let item_id = next_id();
let status = ItemStatus::from_attrs(&ast_attrs_as_hir_attrs(item.attrs.as_ref()));
let attrs = ast_attrs_as_hir_attrs(item.attrs.as_ref());
let status = ItemStatus::from_attrs(&attrs);
let res = Res::Item(item_id, status);
names.insert(decl.name.id, res.clone());
let mut errors = Vec::new();
Expand All @@ -1759,7 +1760,7 @@ fn bind_callable(
}
}

if decl_is_intrinsic(decl) && !scope.intrinsics.insert(Rc::clone(&decl.name.name)) {
if decl_is_intrinsic(decl, &attrs) && !scope.intrinsics.insert(Rc::clone(&decl.name.name)) {
errors.push(Error::DuplicateIntrinsic(
decl.name.name.to_string(),
decl.name.span,
Expand Down Expand Up @@ -1816,7 +1817,13 @@ fn bind_ty(
}
}

fn decl_is_intrinsic(decl: &CallableDecl) -> bool {
fn decl_is_intrinsic(decl: &CallableDecl, attrs: &[hir::Attr]) -> bool {
if attrs
.iter()
.any(|attr| matches!(attr, hir::Attr::SimulatableIntrinsic))
{
return true;
}
if let CallableBody::Specs(specs) = decl.body.as_ref() {
specs
.iter()
Expand Down
30 changes: 30 additions & 0 deletions compiler/qsc_frontend/src/resolve/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2910,6 +2910,36 @@ fn disallow_duplicate_intrinsic_and_non_intrinsic_collision() {
);
}

#[test]
fn disallow_duplicate_intrinsic_and_simulatableintrinsic() {
check(
indoc! {"
namespace A {
operation C() : Unit {
body intrinsic;
}
}
namespace B {
@SimulatableIntrinsic()
operation C() : Unit {}
}
"},
&expect![[r#"
namespace namespace7 {
operation item1() : Unit {
body intrinsic;
}
}
namespace namespace8 {
@SimulatableIntrinsic()
operation item3() : Unit {}
}
// DuplicateIntrinsic("C", Span { lo: 129, hi: 130 })
"#]],
);
}

#[allow(clippy::cast_possible_truncation)]
fn check_locals(input: &str, expect: &Expect) {
let parts = input.split('↘').collect::<Vec<_>>();
Expand Down

0 comments on commit 60b065b

Please sign in to comment.