From eca101ef0f006fd644a309699aca5a7167942c75 Mon Sep 17 00:00:00 2001 From: Oscar Puente <156957451+orpuente-MS@users.noreply.github.com> Date: Wed, 23 Oct 2024 16:28:12 -0700 Subject: [PATCH] `Measurement` attribute on function issues error --- compiler/qsc_frontend/src/lower.rs | 43 +++++++++++++++++------- compiler/qsc_frontend/src/lower/tests.rs | 24 +++++++++++++ 2 files changed, 54 insertions(+), 13 deletions(-) diff --git a/compiler/qsc_frontend/src/lower.rs b/compiler/qsc_frontend/src/lower.rs index da09044210..42dd0ceae5 100644 --- a/compiler/qsc_frontend/src/lower.rs +++ b/compiler/qsc_frontend/src/lower.rs @@ -30,8 +30,12 @@ pub(super) enum Error { #[error("invalid attribute arguments: expected {0}")] #[diagnostic(code("Qsc.LowerAst.InvalidAttrArgs"))] InvalidAttrArgs(String, #[label] Span), + #[error("invalid use of the Measurement attribute on a function")] + #[diagnostic(code("Qsc.LowerAst.InvalidMeasurementAttrOnFunction"))] + InvalidMeasurementAttrOnFunction(#[label] Span), #[error("missing callable body")] #[diagnostic(code("Qsc.LowerAst.MissingBody"))] + #[diagnostic(help("try declaring the callable as an operation"))] MissingBody(#[label] Span), #[error("duplicate specialization")] #[diagnostic(code("Qsc.LowerAst.DuplicateSpec"))] @@ -380,7 +384,7 @@ impl With<'_> { attrs: &[qsc_hir::hir::Attr], ) -> hir::CallableDecl { let id = self.lower_id(decl.id); - let kind = lower_callable_kind(decl.kind, attrs); + let kind = self.lower_callable_kind(decl.kind, attrs, decl.name.span); let name = self.lower_ident(&decl.name); let mut input = self.lower_pat(&decl.input); let output = convert::ty_from_ast(self.names, &decl.output).0; @@ -428,6 +432,30 @@ impl With<'_> { } } + fn lower_callable_kind( + &mut self, + kind: ast::CallableKind, + attrs: &[qsc_hir::hir::Attr], + span: Span, + ) -> hir::CallableKind { + if attrs.contains(&qsc_hir::hir::Attr::Measurement) { + match kind { + ast::CallableKind::Operation => hir::CallableKind::Measurement, + ast::CallableKind::Function => { + self.lowerer + .errors + .push(Error::InvalidMeasurementAttrOnFunction(span)); + hir::CallableKind::Function + } + } + } else { + match kind { + ast::CallableKind::Operation => hir::CallableKind::Operation, + ast::CallableKind::Function => hir::CallableKind::Function, + } + } + } + fn find_spec( &mut self, specs: &[Box], @@ -623,7 +651,7 @@ impl With<'_> { FunctorSetValue::Empty }; let lambda = Lambda { - kind: lower_callable_kind(*kind, &[]), + kind: self.lower_callable_kind(*kind, &[], expr.span), functors, input: self.lower_pat(input), body: self.lower_expr(body), @@ -934,17 +962,6 @@ impl With<'_> { } } -fn lower_callable_kind(kind: ast::CallableKind, attrs: &[qsc_hir::hir::Attr]) -> hir::CallableKind { - if attrs.contains(&qsc_hir::hir::Attr::Measurement) { - hir::CallableKind::Measurement - } else { - match kind { - ast::CallableKind::Function => hir::CallableKind::Function, - ast::CallableKind::Operation => hir::CallableKind::Operation, - } - } -} - fn lower_mutability(mutability: ast::Mutability) -> hir::Mutability { match mutability { ast::Mutability::Immutable => hir::Mutability::Immutable, diff --git a/compiler/qsc_frontend/src/lower/tests.rs b/compiler/qsc_frontend/src/lower/tests.rs index e2d2a14ea5..f35ba17a66 100644 --- a/compiler/qsc_frontend/src/lower/tests.rs +++ b/compiler/qsc_frontend/src/lower/tests.rs @@ -2208,6 +2208,30 @@ fn invalid_spec_pat() { ); } +#[test] +fn test_measurement_attr_on_function_issues_error() { + check_errors( + indoc! {r#" + namespace Test { + @Measurement() + function Foo(q: Qubit) : Result { + body intrinsic; + } + } + "#}, + &expect![[r#" + [ + InvalidMeasurementAttrOnFunction( + Span { + lo: 49, + hi: 52, + }, + ), + ] + "#]], + ); +} + #[test] fn item_docs() { check_hir(