diff --git a/source/compiler/qsc/benches/rca.rs b/source/compiler/qsc/benches/rca.rs index 072acc59856..174f675217e 100644 --- a/source/compiler/qsc/benches/rca.rs +++ b/source/compiler/qsc/benches/rca.rs @@ -156,7 +156,7 @@ fn lower_hir_package_store(hir_package_store: &HirPackageStore) -> PackageStore for (id, unit) in hir_package_store { fir_store.insert( map_hir_package_to_fir(id), - Lowerer::new().lower_package(&unit.package, &fir_store), + Lowerer::new().lower_package(&unit.package, &fir_store, map_hir_package_to_fir(id)), ); } fir_store diff --git a/source/compiler/qsc/src/codegen.rs b/source/compiler/qsc/src/codegen.rs index c1688af4958..0f0cf6fe101 100644 --- a/source/compiler/qsc/src/codegen.rs +++ b/source/compiler/qsc/src/codegen.rs @@ -112,19 +112,23 @@ pub mod qir { &unit.package }; + let fir_id = qsc_lowerer::map_hir_package_to_fir(id); let mut lowerer = qsc_lowerer::Lowerer::new(); let fir_package = if id == package_id { - let mut fir_package = Package::default(); + let mut fir_package = Package { + id: fir_id, + ..Package::default() + }; lowerer.lower_and_update_package(&mut fir_package, hir_package); fir_package.entry_exec_graph = lowerer.take_exec_graph(); fir_package } else { - lowerer.lower_package(hir_package, &fir_store) + lowerer.lower_package(hir_package, &fir_store, fir_id) }; if id == package_id { fir_assigner = lowerer.into_assigner(); } - fir_store.insert(qsc_lowerer::map_hir_package_to_fir(id), fir_package); + fir_store.insert(fir_id, fir_package); } ( @@ -263,13 +267,22 @@ pub mod qir { package_id: qsc_hir::hir::PackageId, errors: Vec, ) -> Vec { - let source_package = package_store - .get(package_id) - .expect("package should be in store"); - errors .into_iter() - .map(|e| Error::Pass(WithSource::from_map(&source_package.sources, e))) + .map(|e| { + // A capability error can point into a dependency, so resolve it + // against the package that actually owns its span. + let owner = match &e { + qsc_passes::Error::CapabilitiesCk(inner) => { + qsc_lowerer::map_fir_package_to_hir(inner.span().package) + } + _ => package_id, + }; + let source_package = package_store + .get(owner) + .expect("package should be in store"); + Error::Pass(WithSource::from_map(&source_package.sources, e)) + }) .collect() } @@ -401,7 +414,7 @@ pub mod qir { fn callable_expr_span_and_ty( fir_store: &qsc_fir::fir::PackageStore, callable_store_id: qsc_fir::fir::StoreItemId, - ) -> (qsc_data_structures::span::Span, qsc_fir::ty::Ty) { + ) -> (qsc_fir::fir::PackageSpan, qsc_fir::ty::Ty) { use qsc_fir::fir::{Global, PackageLookup}; let package = fir_store.get(callable_store_id.package); @@ -421,7 +434,7 @@ pub mod qir { (callable_decl.span, ty) } - fn seed_entry_with_callables( + pub(super) fn seed_entry_with_callables( fir_store: &mut qsc_fir::fir::PackageStore, fir_package_id: qsc_fir::fir::PackageId, callables: &FxHashSet, @@ -938,7 +951,7 @@ pub mod qir { expr_id, qsc_fir::fir::Expr { id: expr_id, - span: qsc_data_structures::span::Span::default(), + span: package.synthetic_span(), ty: qsc_fir::ty::Ty::Tuple(Vec::new()), kind: qsc_fir::fir::ExprKind::Tuple(Vec::new()), exec_graph_range: qsc_fir::fir::ExecGraphIdx::ZERO @@ -978,7 +991,7 @@ pub mod qir { expr_id, qsc_fir::fir::Expr { id: expr_id, - span: qsc_data_structures::span::Span::default(), + span: package.synthetic_span(), ty: input_ty.clone(), kind: qsc_fir::fir::ExprKind::Tuple(elem_ids), exec_graph_range: qsc_fir::fir::ExecGraphIdx::ZERO @@ -1006,7 +1019,7 @@ pub mod qir { expr_id, qsc_fir::fir::Expr { id: expr_id, - span: qsc_data_structures::span::Span::default(), + span: package.synthetic_span(), ty: input_ty.clone(), kind: qsc_fir::fir::ExprKind::Tuple(elem_ids), exec_graph_range: qsc_fir::fir::ExecGraphIdx::ZERO @@ -1120,7 +1133,7 @@ pub mod qir { expr_id, qsc_fir::fir::Expr { id: expr_id, - span: qsc_data_structures::span::Span::default(), + span: package.synthetic_span(), ty: ty.clone(), kind: qsc_fir::fir::ExprKind::Lit(qsc_fir::fir::Lit::Int(0)), exec_graph_range: qsc_fir::fir::ExecGraphIdx::ZERO @@ -1417,11 +1430,12 @@ pub mod qir { -> Option { opt.map(|n| { let id = a.next_expr(); + let span = pkg.synthetic_span(); pkg.exprs.insert( id, qsc_fir::fir::Expr { id, - span: qsc_data_structures::span::Span::default(), + span, ty: qsc_fir::ty::Ty::Prim(qsc_fir::ty::Prim::Int), kind: qsc_fir::fir::ExprKind::Lit(qsc_fir::fir::Lit::Int(n)), exec_graph_range: qsc_fir::fir::ExecGraphIdx::ZERO @@ -1460,7 +1474,7 @@ pub mod qir { expr_id, qsc_fir::fir::Expr { id: expr_id, - span: qsc_data_structures::span::Span::default(), + span: package.synthetic_span(), ty, kind, exec_graph_range: qsc_fir::fir::ExecGraphIdx::ZERO @@ -1497,7 +1511,7 @@ pub mod qir { expr_id, qsc_fir::fir::Expr { id: expr_id, - span: qsc_data_structures::span::Span::default(), + span: package.synthetic_span(), ty: ty.clone(), kind: qsc_fir::fir::ExprKind::Var( qsc_fir::fir::Res::Item(qsc_fir::fir::ItemId { @@ -1668,7 +1682,7 @@ pub mod qir { expr_id, qsc_fir::fir::Expr { id: expr_id, - span: qsc_data_structures::span::Span::default(), + span: package.synthetic_span(), ty: ty.clone(), kind: qsc_fir::fir::ExprKind::UnOp(qsc_fir::fir::UnOp::Functor(functor), inner_id), exec_graph_range: qsc_fir::fir::ExecGraphIdx::ZERO @@ -1716,7 +1730,7 @@ pub mod qir { expr_id, qsc_fir::fir::Expr { id: expr_id, - span: qsc_data_structures::span::Span::default(), + span: package.synthetic_span(), ty: full_ty.clone(), kind, exec_graph_range: qsc_fir::fir::ExecGraphIdx::ZERO @@ -1769,7 +1783,7 @@ pub mod qir { expr_id, qsc_fir::fir::Expr { id: expr_id, - span: qsc_data_structures::span::Span::default(), + span: package.synthetic_span(), ty: closure_ty.clone(), kind: qsc_fir::fir::ExprKind::Closure(capture_locals, closure.id.item), exec_graph_range: qsc_fir::fir::ExecGraphIdx::ZERO @@ -1809,7 +1823,7 @@ pub mod qir { value_expr_id: qsc_fir::fir::ExprId, value_ty: &qsc_fir::ty::Ty, ) -> (qsc_fir::fir::StmtId, qsc_fir::fir::LocalVarId) { - let span = qsc_data_structures::span::Span::default(); + let span = package.synthetic_span(); let local_var_id = assigner.next_local(); let pat_id = assigner.next_pat(); diff --git a/source/compiler/qsc/src/codegen/tests.rs b/source/compiler/qsc/src/codegen/tests.rs index b6644333a11..4a7ff74b384 100644 --- a/source/compiler/qsc/src/codegen/tests.rs +++ b/source/compiler/qsc/src/codegen/tests.rs @@ -20,15 +20,20 @@ use qsc_data_structures::{ }; use qsc_eval::output::CursorReceiver; use qsc_eval::val::Value; +use qsc_fir::fir::{ + ExprKind as FirExprKind, ItemKind as FirItemKind, PackageLookup, Res as FirRes, StoreItemId, +}; use qsc_frontend::compile::parse_all; use qsc_hir::hir::{ItemKind, PackageId}; -use qsc_passes::PackageType; -use rustc_hash::FxHashMap; +use qsc_passes::{PackageType, lower_hir_to_fir}; +use rustc_hash::{FxHashMap, FxHashSet}; use crate::codegen::qir::{ CallableArgsBackend, get_qir, get_qir_from_ast, get_rir, prepare_codegen_fir_from_callable_args, }; +use super::qir::seed_entry_with_callables; + fn format_interpret_errors(errors: Vec) -> String { errors .into_iter() @@ -1717,6 +1722,67 @@ fn two_callable_hof_closure_preserves_array_arg_threading() { .assert_eq(&qir); } +#[test] +fn seed_entry_with_callables_preserves_callable_source_packages() { + let capabilities = TargetCapabilityFlags::all(); + let (std_id, mut store) = crate::compile::package_store_with_stdlib(capabilities); + let dependencies: Vec<(PackageId, Option>)> = vec![(std_id, None)]; + let (unit, errors) = crate::compile::compile( + &store, + &dependencies, + source_map_from_source("namespace Test { operation Destination() : Unit {} }"), + PackageType::Lib, + capabilities, + LanguageFeatures::default(), + ); + assert!(errors.is_empty(), "compilation failed: {errors:?}"); + let destination_hir_package = store.insert(unit); + let (mut fir_store, destination_package, _) = lower_hir_to_fir(&store, destination_hir_package); + let foreign_package = qsc_lowerer::map_hir_package_to_fir(std_id); + + let expected_spans: FxHashMap = fir_store + .get(foreign_package) + .items + .values() + .filter_map(|item| match &item.kind { + FirItemKind::Callable(decl) if decl.span.package == foreign_package => Some(( + StoreItemId { + package: foreign_package, + item: item.id, + }, + decl.span, + )), + FirItemKind::Callable(_) | FirItemKind::Ty(..) => None, + }) + .take(2) + .collect(); + assert_eq!(expected_spans.len(), 2, "expected two foreign callables"); + let callables: FxHashSet<_> = expected_spans.keys().copied().collect(); + + seed_entry_with_callables(&mut fir_store, destination_package, &callables); + + let destination = fir_store.get(destination_package); + let entry = destination + .entry + .expect("plural seed should create an entry expression"); + let FirExprKind::Tuple(entry_exprs) = &destination.get_expr(entry).kind else { + panic!("two callable seeds should create a tuple entry"); + }; + assert_eq!(entry_exprs.len(), expected_spans.len()); + for expr_id in entry_exprs { + let expr = destination.get_expr(*expr_id); + let FirExprKind::Var(FirRes::Item(item), _) = &expr.kind else { + panic!("seeded entry child should be a global callable variable"); + }; + let callable = StoreItemId { + package: item.package, + item: item.item, + }; + assert_eq!(expr.span, expected_spans[&callable]); + assert_ne!(expr.span.package, destination_package); + } +} + #[test] fn callable_args_with_arrow_input_survives_dce() { let source = indoc::indoc! {r#" @@ -6207,3 +6273,49 @@ fn foreign_table_lookup_callable_generates_qir() { ); } } + +#[test] +fn foreign_hof_capability_error_resolves_against_owning_package() { + // `ForEach` lives in the std package; specializing it for this call site + // clones std nodes into the user package, so the capability diagnostic must + // still resolve against std's source map rather than the entry map. + let source = r#" +namespace Test { + import Std.Arrays.ForEach; + @EntryPoint() + operation Main() : Unit { + use q = Qubit(); + ForEach(q => M(q) == One, [q]); + } +} +"#; + let errors = compile_source_to_qir_result(source, TargetCapabilityFlags::from(Profile::Base)) + .expect_err("Base profile must reject a dynamic bool"); + + // The diagnostics must be owned by two different packages: the user's lambda + // and the std `ForEach` body specialized into the user package. + let mut packages: Vec<_> = errors + .iter() + .filter_map(|e| match e { + crate::interpret::Error::Pass(with_source) => match with_source.error() { + qsc_passes::Error::CapabilitiesCk(inner) => Some(inner.span().package), + _ => None, + }, + _ => None, + }) + .collect(); + packages.sort_unstable(); + packages.dedup(); + assert!( + packages.len() >= 2, + "expected capability diagnostics from both the user and std packages, got {packages:?}" + ); + + // Rendering is the regression guard: resolving a std-owned span against the + // entry source map used to panic inside `WithSource::from_map`. + let rendered = format_interpret_errors(errors); + assert!( + rendered.contains("cannot use a dynamic bool"), + "expected a dynamic-bool capability diagnostic, got:\n{rendered}" + ); +} diff --git a/source/compiler/qsc/src/interpret.rs b/source/compiler/qsc/src/interpret.rs index 6a171d52783..42b900d54e9 100644 --- a/source/compiler/qsc/src/interpret.rs +++ b/source/compiler/qsc/src/interpret.rs @@ -353,7 +353,7 @@ impl Interpreter { let mut fir_store = fir::PackageStore::new(); for (id, unit) in compiler.package_store() { let mut lowerer = qsc_lowerer::Lowerer::new(); - let pkg = lowerer.lower_package(&unit.package, &fir_store); + let pkg = lowerer.lower_package(&unit.package, &fir_store, map_hir_package_to_fir(id)); fir_store.insert(map_hir_package_to_fir(id), pkg); } @@ -420,7 +420,18 @@ impl Interpreter { caps_errors .into_iter() .map(|error| { - Error::Pass(WithSource::from_map(&source_package.sources, error)) + let sources = if let qsc_passes::Error::CapabilitiesCk(err) = &error + { + let err_package = err.span().package; + &compiler + .package_store() + .get((Into::::into(err_package)).into()) + .expect("package for error should exist in store") + .sources + } else { + &source_package.sources + }; + Error::Pass(WithSource::from_map(sources, error)) }) .collect::>() })?; @@ -1738,7 +1749,20 @@ impl Interpreter { caps_errors .into_iter() - .map(|error| Error::Pass(WithSource::from_map(&source_package.sources, error))) + .map(|error| { + let sources = if let qsc_passes::Error::CapabilitiesCk(err) = &error { + let err_package = err.span().package; + &self + .compiler + .package_store() + .get((Into::::into(err_package)).into()) + .expect("package for error should exist in store") + .sources + } else { + &source_package.sources + }; + Error::Pass(WithSource::from_map(sources, error)) + }) .collect::>() })?; @@ -2087,7 +2111,7 @@ impl<'a> BreakpointCollector<'a> { fn add_stmt(&mut self, stmt: &fir::Stmt) { let source: &Source = self.get_source(stmt.span.lo); if source.offset == self.offset { - let span = stmt.span - source.offset; + let span = stmt.span.span - source.offset; if span != Span::default() { let range = Range::from_span(self.position_encoding, &source.contents, &span); let bps = BreakpointSpan { diff --git a/source/compiler/qsc/src/lib.rs b/source/compiler/qsc/src/lib.rs index f9baf5af911..45226933f51 100644 --- a/source/compiler/qsc/src/lib.rs +++ b/source/compiler/qsc/src/lib.rs @@ -44,7 +44,7 @@ pub use qsc_data_structures::{ span::Span, target::TargetCapabilityFlags, }; -pub use qsc_passes::{PackageType, PassContext, lower_hir_to_fir}; +pub use qsc_passes::{Error as PassError, PackageType, PassContext, lower_hir_to_fir}; pub mod line_column { pub use qsc_data_structures::line_column::{Encoding, Position, Range}; diff --git a/source/compiler/qsc_circuit/src/builder.rs b/source/compiler/qsc_circuit/src/builder.rs index c5c509e4a8a..5a32f3bdbfa 100644 --- a/source/compiler/qsc_circuit/src/builder.rs +++ b/source/compiler/qsc_circuit/src/builder.rs @@ -721,9 +721,11 @@ impl SourceLookup for (&compile::PackageStore, &fir::PackageStore) { let cond_expr = package.get_expr(cond_expr_id); let expr_contents = self .0 - .get(map_fir_package_to_hir(package_id)) + .get(map_fir_package_to_hir(cond_expr.span.package)) .and_then(|p| p.sources.find_by_offset(cond_expr.span.lo)) - .and_then(|s| source_span_contents(&s.contents, s.offset, cond_expr.span)); + .and_then(|s| { + source_span_contents(&s.contents, s.offset, cond_expr.span.span) + }); LexicalScope { name: format!("loop: {}", expr_contents.unwrap_or_default()).into(), diff --git a/source/compiler/qsc_circuit/src/builder/tests.rs b/source/compiler/qsc_circuit/src/builder/tests.rs index bf11e832974..4446030a092 100644 --- a/source/compiler/qsc_circuit/src/builder/tests.rs +++ b/source/compiler/qsc_circuit/src/builder/tests.rs @@ -170,7 +170,11 @@ fn compile_origin_lookup_stores() -> (PackageStore, fir::PackageStore, PackageId run_core_passes(&mut core); let lowering_store = fir::PackageStore::new(); - let core_fir = fir_lowerer.lower_package(&core.package, &lowering_store); + let core_fir = fir_lowerer.lower_package( + &core.package, + &lowering_store, + qsc_fir::fir::PackageId::CORE, + ); let mut store = PackageStore::new(core); let library_source = indoc! { @@ -193,9 +197,16 @@ fn compile_origin_lookup_stores() -> (PackageStore, fir::PackageStore, PackageId assert!(library_unit.errors.is_empty(), "{:?}", library_unit.errors); let library_pass_errors = run_default_passes(store.core(), &mut library_unit, PackageType::Lib); assert!(library_pass_errors.is_empty(), "{library_pass_errors:?}"); - let library_fir = fir_lowerer.lower_package(&library_unit.package, &lowering_store); let dep_unit_id = store.insert(library_unit); let dep_pkg_id = map_hir_package_to_fir(dep_unit_id); + let library_fir = fir_lowerer.lower_package( + &store + .get(dep_unit_id) + .expect("package should exist") + .package, + &lowering_store, + dep_pkg_id, + ); let user_source = indoc! { r#" @@ -214,9 +225,16 @@ fn compile_origin_lookup_stores() -> (PackageStore, fir::PackageStore, PackageId assert!(user_unit.errors.is_empty(), "{:?}", user_unit.errors); let user_pass_errors = run_default_passes(store.core(), &mut user_unit, PackageType::Lib); assert!(user_pass_errors.is_empty(), "{user_pass_errors:?}"); - let user_fir = fir_lowerer.lower_package(&user_unit.package, &lowering_store); let app_unit_id = store.insert(user_unit); let app_pkg_id = map_hir_package_to_fir(app_unit_id); + let user_fir = fir_lowerer.lower_package( + &store + .get(app_unit_id) + .expect("package should exist") + .package, + &lowering_store, + app_pkg_id, + ); let mut fir_store = fir::PackageStore::new(); fir_store.insert( @@ -713,7 +731,11 @@ fn resolve_scope_for_loop_tolerates_out_of_range_condition_span() { let mut core = compile::core(); run_core_passes(&mut core); let lowering_store = fir::PackageStore::new(); - let core_fir = fir_lowerer.lower_package(&core.package, &lowering_store); + let core_fir = fir_lowerer.lower_package( + &core.package, + &lowering_store, + qsc_fir::fir::PackageId::CORE, + ); let mut store = PackageStore::new(core); let source = indoc! { @@ -741,9 +763,16 @@ fn resolve_scope_for_loop_tolerates_out_of_range_condition_span() { assert!(unit.errors.is_empty(), "{:?}", unit.errors); let pass_errors = run_default_passes(store.core(), &mut unit, PackageType::Lib); assert!(pass_errors.is_empty(), "{pass_errors:?}"); - let unit_fir = fir_lowerer.lower_package(&unit.package, &lowering_store); let hir_package_id = store.insert(unit); let fir_package_id = map_hir_package_to_fir(hir_package_id); + let unit_fir = fir_lowerer.lower_package( + &store + .get(hir_package_id) + .expect("package should exist") + .package, + &lowering_store, + fir_package_id, + ); let mut fir_store = fir::PackageStore::new(); fir_store.insert( @@ -777,7 +806,7 @@ fn resolve_scope_for_loop_tolerates_out_of_range_condition_span() { .exprs .get_mut(cond_expr_id) .expect("condition expr should exist"); - cond_expr.span.hi = source_len + 100; + cond_expr.span.span.hi = source_len + 100; // Resolution should tolerate the bad condition span and still produce a // stable group name and source location from the loop expression itself. @@ -796,6 +825,124 @@ fn resolve_scope_for_loop_tolerates_out_of_range_condition_span() { ); } +fn compile_and_lower_test_package( + store: &mut PackageStore, + source_name: &str, + source: &str, + entry: Option<&str>, +) -> (qsc_fir::fir::PackageId, fir::Package) { + let capabilities = qsc_data_structures::target::TargetCapabilityFlags::all(); + let mut unit = compile( + store, + &[], + qsc_data_structures::source::SourceMap::new( + [(source_name.into(), source.into())], + entry.map(Into::into), + ), + capabilities, + qsc_data_structures::language_features::LanguageFeatures::default(), + ); + assert!(unit.errors.is_empty(), "{:?}", unit.errors); + let pass_errors = run_default_passes(store.core(), &mut unit, PackageType::Lib); + assert!(pass_errors.is_empty(), "{pass_errors:?}"); + let hir_package = store.insert(unit); + let fir_package = map_hir_package_to_fir(hir_package); + let package = qsc_lowerer::Lowerer::new().lower_package( + &store + .get(hir_package) + .expect("package should exist") + .package, + &fir::PackageStore::new(), + fir_package, + ); + (fir_package, package) +} + +#[test] +fn resolve_scope_for_loop_uses_condition_source_package() { + let mut core = compile::core(); + run_core_passes(&mut core); + let mut store = PackageStore::new(core); + + let dependency_source = indoc! { + r#" + namespace Dependency { + operation Foreign() : Unit { + mutable dependency_index = 0; + while dependency_index < 17 { + set dependency_index += 1; + } + } + } + "# + }; + let (dependency_package, dependency_fir) = + compile_and_lower_test_package(&mut store, "Dependency.qs", dependency_source, None); + + let user_source = indoc! { + r#" + namespace Test { + operation Main() : Unit { + mutable i = 0; + while i < 2 { + set i += 1; + } + } + } + "# + }; + let (user_package, user_fir) = + compile_and_lower_test_package(&mut store, "User.qs", user_source, Some("Test.Main()")); + let mut fir_store = fir::PackageStore::new(); + fir_store.insert(dependency_package, dependency_fir); + fir_store.insert(user_package, user_fir); + + let dependency_condition_span = { + let package = fir_store.get(dependency_package); + package + .exprs + .values() + .find_map(|expr| match expr.kind { + ExprKind::While(condition, _) => Some(package.get_expr(condition).span), + _ => None, + }) + .expect("expected dependency while loop") + }; + let (user_loop, user_condition) = { + let package = fir_store.get(user_package); + package + .exprs + .iter() + .find_map(|(expr_id, expr)| match expr.kind { + ExprKind::While(condition, _) => Some((expr_id, condition)), + _ => None, + }) + .expect("expected user while loop") + }; + assert_eq!(dependency_condition_span.package, dependency_package); + assert_ne!(dependency_condition_span.package, user_package); + fir_store + .get_mut(user_package) + .exprs + .get_mut(user_condition) + .expect("user condition should exist") + .span = dependency_condition_span; + + let scope = (&store, &fir_store).resolve_scope( + &Scope::Loop(LoopId::Id(user_package, user_loop)), + &mut Default::default(), + ); + + assert_eq!(scope.name.as_ref(), "loop: dependency_index < 17"); + assert_eq!( + scope.location, + Some(PackageOffset { + package_id: user_package, + offset: fir_store.get(user_package).get_expr(user_loop).span.lo, + }) + ); +} + #[test] fn source_locations_for_groups() { let mut c = FakeCompilation::default(); diff --git a/source/compiler/qsc_circuit/src/builder/tests/logical_stack_trace.rs b/source/compiler/qsc_circuit/src/builder/tests/logical_stack_trace.rs index 1f1f64b920d..0202fa722ca 100644 --- a/source/compiler/qsc_circuit/src/builder/tests/logical_stack_trace.rs +++ b/source/compiler/qsc_circuit/src/builder/tests/logical_stack_trace.rs @@ -109,14 +109,19 @@ fn check_trace(file: &str, expr: &str, exec_graph_config: ExecGraphConfig, expec let mut core = compile::core(); run_core_passes(&mut core); let fir_store = fir::PackageStore::new(); - let core_fir = fir_lowerer.lower_package(&core.package, &fir_store); + let core_fir = + fir_lowerer.lower_package(&core.package, &fir_store, qsc_fir::fir::PackageId::CORE); let mut store = PackageStore::new(core); let mut std = compile::std(&store, TargetCapabilityFlags::all()); assert!(std.errors.is_empty()); assert!(run_default_passes(store.core(), &mut std, PackageType::Lib).is_empty()); - let std_fir = fir_lowerer.lower_package(&std.package, &fir_store); let std_id = store.insert(std); + let std_fir = fir_lowerer.lower_package( + &store.get(std_id).expect("package should exist").package, + &fir_store, + map_hir_package_to_fir(std_id), + ); let sources = SourceMap::new([("A.qs".into(), file.into())], Some(expr.into())); let mut unit = compile( @@ -129,9 +134,13 @@ fn check_trace(file: &str, expr: &str, exec_graph_config: ExecGraphConfig, expec assert!(unit.errors.is_empty(), "{:?}", unit.errors); let pass_errors = run_default_passes(store.core(), &mut unit, PackageType::Lib); assert!(pass_errors.is_empty(), "{pass_errors:?}"); - let unit_fir = fir_lowerer.lower_package(&unit.package, &fir_store); - let entry = unit_fir.entry_exec_graph.clone(); let id = store.insert(unit); + let unit_fir = fir_lowerer.lower_package( + &store.get(id).expect("package should exist").package, + &fir_store, + map_hir_package_to_fir(id), + ); + let entry = unit_fir.entry_exec_graph.clone(); let mut fir_store = fir::PackageStore::new(); fir_store.insert( diff --git a/source/compiler/qsc_circuit/src/rir_to_circuit/tests/logical_stack_trace.rs b/source/compiler/qsc_circuit/src/rir_to_circuit/tests/logical_stack_trace.rs index 1e8dad2b0b1..3b3e8dc5828 100644 --- a/source/compiler/qsc_circuit/src/rir_to_circuit/tests/logical_stack_trace.rs +++ b/source/compiler/qsc_circuit/src/rir_to_circuit/tests/logical_stack_trace.rs @@ -107,14 +107,19 @@ fn check_trace(file: &str, expr: &str, expect: &Expect) { let mut core = compile::core(); run_core_passes(&mut core); let fir_store = fir::PackageStore::new(); - let core_fir = fir_lowerer.lower_package(&core.package, &fir_store); + let core_fir = + fir_lowerer.lower_package(&core.package, &fir_store, qsc_fir::fir::PackageId::CORE); let mut store = PackageStore::new(core); let mut std = compile::std(&store, capabilities); assert!(std.errors.is_empty()); assert!(run_default_passes(store.core(), &mut std, PackageType::Lib).is_empty()); - let std_fir = fir_lowerer.lower_package(&std.package, &fir_store); let std_id = store.insert(std); + let std_fir = fir_lowerer.lower_package( + &store.get(std_id).expect("package should exist").package, + &fir_store, + map_hir_package_to_fir(std_id), + ); let sources = SourceMap::new([("A.qs".into(), file.into())], Some(expr.into())); let mut unit = compile( @@ -127,8 +132,12 @@ fn check_trace(file: &str, expr: &str, expect: &Expect) { assert!(unit.errors.is_empty(), "{:?}", unit.errors); let pass_errors = run_default_passes(store.core(), &mut unit, PackageType::Lib); assert!(pass_errors.is_empty(), "{pass_errors:?}"); - let unit_fir = fir_lowerer.lower_package(&unit.package, &fir_store); let id = store.insert(unit); + let unit_fir = fir_lowerer.lower_package( + &store.get(id).expect("package should exist").package, + &fir_store, + map_hir_package_to_fir(id), + ); let mut fir_store = fir::PackageStore::new(); fir_store.insert( diff --git a/source/compiler/qsc_data_structures/src/span.rs b/source/compiler/qsc_data_structures/src/span.rs index 8ea8d07b44a..60a634eb1ae 100644 --- a/source/compiler/qsc_data_structures/src/span.rs +++ b/source/compiler/qsc_data_structures/src/span.rs @@ -33,6 +33,25 @@ impl

PackageSpan

{ } } +/// Synthetic nodes with no source text default to the first package. +impl Default for PackageSpan

{ + fn default() -> Self { + Self { + package: P::default(), + span: Span::default(), + } + } +} + +/// Lets a package-qualified span be read like the bare `Span` it wraps. +impl

std::ops::Deref for PackageSpan

{ + type Target = Span; + + fn deref(&self) -> &Span { + &self.span + } +} + impl Span { /// Returns true if the position is within the span. Meaning it is in the /// right open interval `[self.lo, self.hi)`. diff --git a/source/compiler/qsc_eval/src/intrinsic/tests.rs b/source/compiler/qsc_eval/src/intrinsic/tests.rs index 56a79bd0f42..6f1077869ca 100644 --- a/source/compiler/qsc_eval/src/intrinsic/tests.rs +++ b/source/compiler/qsc_eval/src/intrinsic/tests.rs @@ -162,14 +162,22 @@ fn check_intrinsic(file: &str, expr: &str, out: &mut impl Receiver) -> Result Result { self.idx += 1; - self.current_span = globals.get_stmt((self.package, *stmt).into()).span; + self.current_span = + globals.get_stmt((self.package, *stmt).into()).span.span; match self.check_for_break(breakpoints, *stmt, step, current_frame) { Some(value) => value, @@ -1015,7 +1016,7 @@ impl State { // of generated code. This also avoids underflowing the `u32` offset in // `block.span.hi - 1` below, which would otherwise surface a bogus // end-of-file location when stepping. - if block.span == Span::default() { + if block.span.span == Span::default() { return None; } let span = Span { @@ -1058,7 +1059,13 @@ impl State { ExprKind::String(components) => self.collect_string(components), ExprKind::ArrayLit(arr) => self.eval_arr_lit(arr, globals), ExprKind::Closure(args, callable) => { - let closure = resolve_closure(env, self.package, span, args, *callable)?; + let closure = resolve_closure( + env, + self.package, + map_fir_package_span_to_hir(expr.span), + args, + *callable, + )?; self.set_val_register(closure); } ExprKind::AssignField(record, field, _) => { @@ -1097,7 +1104,7 @@ impl State { ExecGraphExpr::Assign(lhs) => self.eval_assign(env, globals, *lhs)?, ExecGraphExpr::Tuple(size) => self.eval_tup(*size), ExecGraphExpr::Var(res) => { - self.set_val_register(resolve_binding(env, self.package, *res, span)?); + self.set_val_register(resolve_binding(env, *res, self.to_global_span(span))?); } ExecGraphExpr::Call { callee_span, @@ -1126,7 +1133,11 @@ impl State { else { panic!("lhs of assign op should be a variable"); }; - self.set_val_register(resolve_binding(env, self.package, *res, *lhs_span)?); + self.set_val_register(resolve_binding( + env, + *res, + self.to_global_span(*lhs_span), + )?); self.push_val(); self.set_val_register(rhs_val); } @@ -1155,7 +1166,11 @@ impl State { let ExprKind::Var(res, _) = &lhs_expr.kind else { panic!("lhs of assign op should be a variable"); }; - self.set_val_register(resolve_binding(env, self.package, *res, lhs_expr.span)?); + self.set_val_register(resolve_binding( + env, + *res, + map_fir_package_span_to_hir(lhs_expr.span), + )?); self.eval_update_index(*mid_span)?; self.eval_assign(env, globals, *lhs)?; } @@ -1225,7 +1240,7 @@ impl State { var.value.append_array(rhs); } None => { - return Err(Error::UnboundName(self.to_global_span(lhs.span))); + return Err(Error::UnboundName(map_fir_package_span_to_hir(lhs.span))); } }, _ => unreachable!("unassignable array update pattern should be disallowed by compiler"), @@ -1342,10 +1357,7 @@ impl State { } }; - let callee_span = PackageSpan { - package: map_fir_package_to_hir(callee_id.package), - span: callee.span, - }; + let callee_span = map_fir_package_span_to_hir(callee.span); let spec = spec_from_functor_app(functor); match &callee.implementation { @@ -1792,7 +1804,7 @@ impl State { Variable { name: variable.name.clone(), value: val, - span: variable.span, + span: variable.span.span, }, ); } @@ -1822,7 +1834,7 @@ impl State { var.value = rhs; } None => { - return Err(Error::UnboundName(self.to_global_span(lhs.span))); + return Err(Error::UnboundName(map_fir_package_span_to_hir(lhs.span))); } }, (ExprKind::Tuple(var_tup), Value::Tuple(tup, _)) => { @@ -1850,7 +1862,7 @@ impl State { Some(var) => { var.value.update_array(index, rhs, span)?; } - None => return Err(Error::UnboundName(self.to_global_span(lhs.span))), + None => return Err(Error::UnboundName(map_fir_package_span_to_hir(lhs.span))), }, _ => unreachable!("unassignable array update pattern should be disallowed by compiler"), } @@ -1886,7 +1898,7 @@ impl State { var.value.update_array(idx, rhs.clone(), range_span)?; } } - None => return Err(Error::UnboundName(self.to_global_span(lhs.span))), + None => return Err(Error::UnboundName(map_fir_package_span_to_hir(lhs.span))), }, _ => unreachable!("unassignable array update pattern should be disallowed by compiler"), } @@ -2172,7 +2184,7 @@ fn merge_fixed_args(fixed_args: Option>, arg: Value) -> Value { } } -fn resolve_binding(env: &Env, package: PackageId, res: Res, span: Span) -> Result { +fn resolve_binding(env: &Env, res: Res, span: PackageSpan) -> Result { Ok(match res { Res::Err => panic!("resolution error"), Res::Item(item) => Value::Global( @@ -2182,14 +2194,7 @@ fn resolve_binding(env: &Env, package: PackageId, res: Res, span: Span) -> Resul }, FunctorApp::default(), ), - Res::Local(id) => env - .get(id) - .ok_or(Error::UnboundName(PackageSpan { - package: map_fir_package_to_hir(package), - span, - }))? - .value - .clone(), + Res::Local(id) => env.get(id).ok_or(Error::UnboundName(span))?.value.clone(), }) } @@ -2205,7 +2210,7 @@ fn spec_from_functor_app(functor: FunctorApp) -> Spec { pub fn resolve_closure( env: &Env, package: PackageId, - span: Span, + span: PackageSpan, args: &[LocalVarId], callable: LocalItemId, ) -> Result { @@ -2213,10 +2218,7 @@ pub fn resolve_closure( .iter() .map(|&arg| Some(env.get(arg)?.value.clone())) .collect(); - let args: Vec<_> = args.ok_or(Error::UnboundName(PackageSpan { - package: map_fir_package_to_hir(package), - span, - }))?; + let args: Vec<_> = args.ok_or(Error::UnboundName(span))?; let callable = StoreItemId { package, item: callable, diff --git a/source/compiler/qsc_eval/src/tests.rs b/source/compiler/qsc_eval/src/tests.rs index 4e0b9597510..0b4430b9e15 100644 --- a/source/compiler/qsc_eval/src/tests.rs +++ b/source/compiler/qsc_eval/src/tests.rs @@ -2,15 +2,17 @@ // Licensed under the MIT License. use crate::{ - Env, Error, ErrorBehavior, State, StepAction, StepResult, Value, + Env, Error, ErrorBehavior, PackageSpan, State, StepAction, StepResult, Value, Variable, backend::{Backend, SparseSim, TracingBackend}, debug::Frame, output::{GenericReceiver, Receiver}, + resolve_closure, }; use expect_test::{Expect, expect}; use indoc::indoc; use qsc_data_structures::{ - language_features::LanguageFeatures, source::SourceMap, target::TargetCapabilityFlags, + language_features::LanguageFeatures, source::SourceMap, span::Span, + target::TargetCapabilityFlags, }; use qsc_fir::fir::{self, ExecGraph, ExecGraphConfig, StmtId}; use qsc_fir::fir::{PackageId, PackageStoreLookup}; @@ -52,20 +54,70 @@ pub(super) fn eval_graph( Ok(value) } +#[test] +fn resolve_closure_separates_callable_and_source_packages() { + let callable_package = PackageId::from(1usize); + let callable = fir::LocalItemId::from(2usize); + let capture = fir::LocalVarId::from(3usize); + let source_span = PackageSpan::new( + qsc_hir::hir::PackageId::from(4usize), + Span { lo: 5, hi: 13 }, + ); + + let mut env = Env::default(); + env.bind_variable_in_top_frame( + capture, + Variable { + name: "capture".into(), + value: Value::Int(42), + span: Span::default(), + }, + ); + + let value = resolve_closure(&env, callable_package, source_span, &[capture], callable) + .expect("bound capture should resolve"); + let Value::Closure(closure) = value else { + panic!("expected a closure value"); + }; + assert_eq!( + closure.id, + fir::StoreItemId { + package: callable_package, + item: callable, + } + ); + assert_eq!(closure.fixed_args.as_ref(), &[Value::Int(42)]); + + let error = resolve_closure( + &Env::default(), + callable_package, + source_span, + &[capture], + callable, + ) + .expect_err("unbound capture should fail"); + assert!(matches!(error, Error::UnboundName(span) if span == source_span)); +} + fn check_expr(file: &str, expr: &str, expect: &Expect) { let mut fir_lowerer = qsc_lowerer::Lowerer::new(); let mut core = compile::core(); run_core_passes(&mut core); let fir_store = fir::PackageStore::new(); // store can be empty since core doesn't have any dependencies - let core_fir = fir_lowerer.lower_package(&core.package, &fir_store); + let core_fir = + fir_lowerer.lower_package(&core.package, &fir_store, qsc_fir::fir::PackageId::CORE); let mut store = PackageStore::new(core); let mut std = compile::std(&store, TargetCapabilityFlags::all()); assert!(std.errors.is_empty()); assert!(run_default_passes(store.core(), &mut std, PackageType::Lib).is_empty()); - let std_fir = fir_lowerer.lower_package(&std.package, &fir_store); let std_id = store.insert(std); + let std_fir = fir_lowerer.lower_package( + &store.get(std_id).expect("package should exist").package, + &fir_store, + map_hir_package_to_fir(std_id), + ); let sources = SourceMap::new([("test".into(), file.into())], Some(expr.into())); let mut unit = compile( @@ -78,9 +130,13 @@ fn check_expr(file: &str, expr: &str, expect: &Expect) { assert!(unit.errors.is_empty(), "{:?}", unit.errors); let pass_errors = run_default_passes(store.core(), &mut unit, PackageType::Lib); assert!(pass_errors.is_empty(), "{pass_errors:?}"); - let unit_fir = fir_lowerer.lower_package(&unit.package, &fir_store); - let entry = unit_fir.entry_exec_graph.clone(); let id = store.insert(unit); + let unit_fir = fir_lowerer.lower_package( + &store.get(id).expect("package should exist").package, + &fir_store, + map_hir_package_to_fir(id), + ); + let entry = unit_fir.entry_exec_graph.clone(); let mut fir_store = fir::PackageStore::new(); fir_store.insert( @@ -113,14 +169,19 @@ fn check_expr_with_lib(lib: &str, file: &str, expr: &str, expect: &Expect) { run_core_passes(&mut core); let fir_store = fir::PackageStore::new(); // store can be empty since core doesn't have any dependencies - let core_fir = fir_lowerer.lower_package(&core.package, &fir_store); + let core_fir = + fir_lowerer.lower_package(&core.package, &fir_store, qsc_fir::fir::PackageId::CORE); let mut store = PackageStore::new(core); let mut std = compile::std(&store, TargetCapabilityFlags::all()); assert!(std.errors.is_empty()); assert!(run_default_passes(store.core(), &mut std, PackageType::Lib).is_empty()); - let std_fir = fir_lowerer.lower_package(&std.package, &fir_store); let std_id = store.insert(std); + let std_fir = fir_lowerer.lower_package( + &store.get(std_id).expect("package should exist").package, + &fir_store, + map_hir_package_to_fir(std_id), + ); let lib_sources = SourceMap::new([("lib".into(), lib.into())], None); let mut lib_unit = compile( @@ -133,8 +194,12 @@ fn check_expr_with_lib(lib: &str, file: &str, expr: &str, expect: &Expect) { assert!(lib_unit.errors.is_empty(), "{:?}", lib_unit.errors); let lib_pass_errors = run_default_passes(store.core(), &mut lib_unit, PackageType::Lib); assert!(lib_pass_errors.is_empty(), "{lib_pass_errors:?}"); - let lib_fir = fir_lowerer.lower_package(&lib_unit.package, &fir_store); let lib_id = store.insert(lib_unit); + let lib_fir = fir_lowerer.lower_package( + &store.get(lib_id).expect("package should exist").package, + &fir_store, + map_hir_package_to_fir(lib_id), + ); let sources = SourceMap::new([("test".into(), file.into())], Some(expr.into())); let mut unit = compile( @@ -147,9 +212,13 @@ fn check_expr_with_lib(lib: &str, file: &str, expr: &str, expect: &Expect) { assert!(unit.errors.is_empty(), "{:?}", unit.errors); let pass_errors = run_default_passes(store.core(), &mut unit, PackageType::Lib); assert!(pass_errors.is_empty(), "{pass_errors:?}"); - let unit_fir = fir_lowerer.lower_package(&unit.package, &fir_store); - let entry = unit_fir.entry_exec_graph.clone(); let id = store.insert(unit); + let unit_fir = fir_lowerer.lower_package( + &store.get(id).expect("package should exist").package, + &fir_store, + map_hir_package_to_fir(id), + ); + let entry = unit_fir.entry_exec_graph.clone(); let mut fir_store = fir::PackageStore::new(); fir_store.insert( @@ -180,14 +249,19 @@ fn check_output(file: &str, expr: &str, expect: &Expect) { let mut core = compile::core(); run_core_passes(&mut core); let fir_store = fir::PackageStore::new(); - let core_fir = fir_lowerer.lower_package(&core.package, &fir_store); + let core_fir = + fir_lowerer.lower_package(&core.package, &fir_store, qsc_fir::fir::PackageId::CORE); let mut store = PackageStore::new(core); let mut std = compile::std(&store, TargetCapabilityFlags::all()); assert!(std.errors.is_empty()); assert!(run_default_passes(store.core(), &mut std, PackageType::Lib).is_empty()); - let std_fir = fir_lowerer.lower_package(&std.package, &fir_store); let std_id = store.insert(std); + let std_fir = fir_lowerer.lower_package( + &store.get(std_id).expect("package should exist").package, + &fir_store, + map_hir_package_to_fir(std_id), + ); let sources = SourceMap::new([("test".into(), file.into())], Some(expr.into())); let mut unit = compile( @@ -200,9 +274,13 @@ fn check_output(file: &str, expr: &str, expect: &Expect) { assert!(unit.errors.is_empty(), "{:?}", unit.errors); let pass_errors = run_default_passes(store.core(), &mut unit, PackageType::Lib); assert!(pass_errors.is_empty(), "{pass_errors:?}"); - let unit_fir = fir_lowerer.lower_package(&unit.package, &fir_store); - let entry = unit_fir.entry_exec_graph.clone(); let id = store.insert(unit); + let unit_fir = fir_lowerer.lower_package( + &store.get(id).expect("package should exist").package, + &fir_store, + map_hir_package_to_fir(id), + ); + let entry = unit_fir.entry_exec_graph.clone(); let mut fir_store = fir::PackageStore::new(); fir_store.insert( @@ -241,14 +319,22 @@ fn check_partial_eval_stmt( let mut core = compile::core(); run_core_passes(&mut core); let fir_store = fir::PackageStore::new(); - let core_fir = qsc_lowerer::Lowerer::new().lower_package(&core.package, &fir_store); + let core_fir = qsc_lowerer::Lowerer::new().lower_package( + &core.package, + &fir_store, + qsc_fir::fir::PackageId::CORE, + ); let mut store = PackageStore::new(core); let mut std = compile::std(&store, TargetCapabilityFlags::all()); assert!(std.errors.is_empty()); assert!(run_default_passes(store.core(), &mut std, PackageType::Lib).is_empty()); - let std_fir = qsc_lowerer::Lowerer::new().lower_package(&std.package, &fir_store); let std_id = store.insert(std); + let std_fir = qsc_lowerer::Lowerer::new().lower_package( + &store.get(std_id).expect("package should exist").package, + &fir_store, + map_hir_package_to_fir(std_id), + ); let sources = SourceMap::new([("test".into(), file.into())], Some(expr.into())); let mut unit = compile( @@ -261,11 +347,15 @@ fn check_partial_eval_stmt( assert!(unit.errors.is_empty(), "{:?}", unit.errors); let pass_errors = run_default_passes(store.core(), &mut unit, PackageType::Lib); assert!(pass_errors.is_empty(), "{pass_errors:?}"); - let unit_fir = qsc_lowerer::Lowerer::new().lower_package(&unit.package, &fir_store); + let id = store.insert(unit); + let unit_fir = qsc_lowerer::Lowerer::new().lower_package( + &store.get(id).expect("package should exist").package, + &fir_store, + map_hir_package_to_fir(id), + ); fir_expect.assert_eq(&unit_fir.to_string()); let entry = unit_fir.entry_exec_graph.clone(); - let id = store.insert(unit); let mut fir_store = fir::PackageStore::new(); fir_store.insert( diff --git a/source/compiler/qsc_fir/src/fir.rs b/source/compiler/qsc_fir/src/fir.rs index d3d5d1876a5..3c23cf8a191 100644 --- a/source/compiler/qsc_fir/src/fir.rs +++ b/source/compiler/qsc_fir/src/fir.rs @@ -113,7 +113,7 @@ fir_id!(StmtId); fir_id!(LocalVarId); /// A unique identifier for a package within a package store. -#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct PackageId(usize); /// A span qualified by the FIR package that owns it. @@ -467,6 +467,9 @@ pub trait PackageLookup { /// `PackageId`s and `LocalItemId`s are 1:1 from the HIR and are not remapped. #[derive(Debug, Clone, Default)] pub struct Package { + /// The package this is stored under, used to qualify the spans of nodes + /// synthesized into it. + pub id: PackageId, /// The items in the package. pub items: IndexMap, /// The entry expression for an executable package. @@ -483,6 +486,20 @@ pub struct Package { pub stmts: IndexMap, } +impl Package { + /// Qualifies `span` with this package, for nodes synthesized into it. + #[must_use] + pub fn span(&self, span: Span) -> PackageSpan { + PackageSpan::new(self.id, span) + } + + /// The span for a node synthesized into this package with no source text. + #[must_use] + pub fn synthetic_span(&self) -> PackageSpan { + PackageSpan::new(self.id, Span::default()) + } +} + impl Display for Package { fn fmt(&self, f: &mut Formatter) -> fmt::Result { let mut indent = set_indentation(indented(f), 0); @@ -564,7 +581,7 @@ pub struct Item { /// The ID. pub id: LocalItemId, /// The span. - pub span: Span, + pub span: PackageSpan, /// The parent item. pub parent: Option, /// The documentation. @@ -583,7 +600,7 @@ impl Display for Item { write!( indent, "Item {} {} ({:?}):", - self.id, self.span, self.visibility + self.id, self.span.span, self.visibility )?; indent = set_indentation(indent, 1); @@ -629,7 +646,7 @@ impl Display for ItemKind { #[derive(Clone, Debug, PartialEq)] pub struct CallableDecl { /// The span. - pub span: Span, + pub span: PackageSpan, /// The callable kind. pub kind: CallableKind, /// The name of the callable. @@ -667,7 +684,7 @@ impl CallableDecl { impl Display for CallableDecl { fn fmt(&self, f: &mut Formatter) -> fmt::Result { let mut indent = set_indentation(indented(f), 0); - write!(indent, "Callable {} ({}):", self.span, self.kind)?; + write!(indent, "Callable {} ({}):", self.span.span, self.kind)?; indent = set_indentation(indent, 1); write!(indent, "\nname: {}", self.name)?; if !self.generics.is_empty() { @@ -759,7 +776,7 @@ impl Display for SpecImpl { #[derive(Clone, Debug, PartialEq)] pub struct SpecDecl { /// The span. - pub span: Span, + pub span: PackageSpan, /// The block that implements the specialization. pub block: BlockId, /// The input of the specialization. @@ -770,7 +787,11 @@ pub struct SpecDecl { impl Display for SpecDecl { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "SpecDecl {}: {:?} {}", self.span, self.input, self.block) + write!( + f, + "SpecDecl {}: {:?} {}", + self.span.span, self.input, self.block + ) } } @@ -1019,7 +1040,7 @@ pub struct Block { /// The node ID. pub id: BlockId, /// The span. - pub span: Span, + pub span: PackageSpan, /// The block type. pub ty: Ty, /// The statements in the block. @@ -1029,13 +1050,13 @@ pub struct Block { impl Display for Block { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { if self.stmts.is_empty() { - write!(f, "Block {} {}: ", self.id, self.span)?; + write!(f, "Block {} {}: ", self.id, self.span.span)?; } else { let mut indent = set_indentation(indented(f), 0); write!( indent, "Block {} {} [Type {}]:", - self.id, self.span, self.ty + self.id, self.span.span, self.ty )?; indent = set_indentation(indent, 1); for s in &self.stmts { @@ -1052,7 +1073,7 @@ pub struct Stmt { /// The stmt ID. pub id: StmtId, /// The span. - pub span: Span, + pub span: PackageSpan, /// The statement kind. pub kind: StmtKind, /// The locations within the containing control flow graph for the current statement. @@ -1061,7 +1082,7 @@ pub struct Stmt { impl Display for Stmt { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "Stmt {} {}: {}", self.id, self.span, self.kind) + write!(f, "Stmt {} {}: {}", self.id, self.span.span, self.kind) } } @@ -1102,7 +1123,7 @@ pub struct Expr { /// The expr ID. pub id: ExprId, /// The span. - pub span: Span, + pub span: PackageSpan, /// The expression type. pub ty: Ty, /// The expression kind. @@ -1116,7 +1137,7 @@ impl Display for Expr { write!( f, "Expr {} {} [Type {}]: {}", - self.id, self.span, self.ty, self.kind + self.id, self.span.span, self.ty, self.kind ) } } @@ -1504,7 +1525,7 @@ fn display_while(mut indent: Indented, cond: ExprId, block: BlockId) #[derive(Clone, Debug, PartialEq)] pub struct FieldAssign { /// The span. - pub span: Span, + pub span: PackageSpan, /// The field to assign. pub field: Field, /// The value to assign to the field. @@ -1516,7 +1537,7 @@ impl Display for FieldAssign { write!( f, "FieldsAssign {}: ({}) {}", - self.span, self.field, self.value + self.span.span, self.field, self.value ) } } @@ -1536,7 +1557,7 @@ pub struct Pat { /// The node ID. pub id: PatId, /// The span. - pub span: Span, + pub span: PackageSpan, /// The pattern type. pub ty: Ty, /// The pattern kind. @@ -1548,7 +1569,7 @@ impl Display for Pat { write!( f, "Pat {} {} [Type {}]: {}", - self.id, self.span, self.ty, self.kind + self.id, self.span.span, self.ty, self.kind ) } } @@ -1594,14 +1615,14 @@ pub struct Ident { /// The node ID. pub id: LocalVarId, /// The span. - pub span: Span, + pub span: PackageSpan, /// The identifier name. pub name: Rc, } impl Display for Ident { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "Ident {} {} \"{}\"", self.id, self.span, self.name) + write!(f, "Ident {} {} \"{}\"", self.id, self.span.span, self.name) } } diff --git a/source/compiler/qsc_fir_transforms/src/arg_promote.rs b/source/compiler/qsc_fir_transforms/src/arg_promote.rs index 8ec9c70e8ef..8d89412ab74 100644 --- a/source/compiler/qsc_fir_transforms/src/arg_promote.rs +++ b/source/compiler/qsc_fir_transforms/src/arg_promote.rs @@ -60,7 +60,6 @@ use crate::walk_utils::{ ParamUse, classify_uses_in_block, collect_expr_ids_in_entry_and_local_callables, collect_expr_ids_in_local_callables, for_each_expr, for_each_expr_in_callable_impl, }; -use qsc_data_structures::span::Span; use qsc_fir::assigner::Assigner; use qsc_fir::fir::{ CallableDecl, CallableImpl, Expr, ExprId, ExprKind, Field, Functor, ItemKind, LocalItemId, @@ -1150,7 +1149,7 @@ fn build_leaf_tuple( assigner, *leaf_local, leaf_ty.clone(), - Span::default(), + package.synthetic_span(), ); } @@ -1160,7 +1159,13 @@ fn build_leaf_tuple( // (handled by the early return above), so this fallback is unreachable for // well-formed flattened inputs. Fall back to a unit tuple to keep the // rewrite total. - return alloc_tuple_expr(package, assigner, vec![], sub_ty.clone(), Span::default()); + return alloc_tuple_expr( + package, + assigner, + vec![], + sub_ty.clone(), + package.synthetic_span(), + ); }; let mut child_ids = Vec::with_capacity(elems.len()); @@ -1182,7 +1187,7 @@ fn build_leaf_tuple( assigner, child_ids, sub_ty.clone(), - Span::default(), + package.synthetic_span(), ) } @@ -1444,7 +1449,7 @@ fn project_leaf_through_tuple_literal( current, rest.to_vec(), leaf_ty.clone(), - Span::default(), + package.synthetic_span(), ) } @@ -1504,7 +1509,13 @@ fn try_inline_tuple_literal_projection( .map(|(_, leaf_ty)| leaf_ty.clone()) .collect(), ); - let new_arg_id = alloc_tuple_expr(package, assigner, field_expr_ids, tuple_ty, Span::default()); + let new_arg_id = alloc_tuple_expr( + package, + assigner, + field_expr_ids, + tuple_ty, + package.synthetic_span(), + ); Some(new_arg_id) } @@ -1543,7 +1554,7 @@ fn create_projected_tuple_arg( assigner, temp_local, arg_ty.clone(), - Span::default(), + package.synthetic_span(), ) } else { arg_id @@ -1554,7 +1565,7 @@ fn create_projected_tuple_arg( field_base_id, path.clone(), leaf_ty.clone(), - Span::default(), + package.synthetic_span(), ); field_expr_ids.push(field_expr_id); } @@ -1566,7 +1577,13 @@ fn create_projected_tuple_arg( .map(|(_, leaf_ty)| leaf_ty.clone()) .collect(), ); - alloc_tuple_expr(package, assigner, field_expr_ids, tuple_ty, Span::default()) + alloc_tuple_expr( + package, + assigner, + field_expr_ids, + tuple_ty, + package.synthetic_span(), + ) } /// Wraps a single promoted payload expression in a one-element tuple argument. @@ -1581,7 +1598,7 @@ fn create_single_tuple_arg( assigner, vec![arg_id], Ty::Tuple(elem_types.to_vec()), - Span::default(), + package.synthetic_span(), ) } @@ -1595,17 +1612,24 @@ fn create_payload_block( ) -> ExprId { let result_ty = package.get_expr(result_expr_id).ty.clone(); - let result_stmt_id = alloc_expr_stmt(package, assigner, result_expr_id, Span::default()); + let result_stmt_id = + alloc_expr_stmt(package, assigner, result_expr_id, package.synthetic_span()); let block_id = alloc_block( package, assigner, vec![leading_stmt_id, result_stmt_id], result_ty.clone(), - Span::default(), + package.synthetic_span(), ); - alloc_block_expr(package, assigner, block_id, result_ty, Span::default()) + alloc_block_expr( + package, + assigner, + block_id, + result_ty, + package.synthetic_span(), + ) } /// Returns `true` when `elems` is already the fully-flattened argument list: @@ -1728,17 +1752,17 @@ fn wrap_call_in_block( callee_id, new_arg_id, call_ty.clone(), - Span::default(), + package.synthetic_span(), ); - let call_stmt_id = alloc_expr_stmt(package, assigner, inner_call_id, Span::default()); + let call_stmt_id = alloc_expr_stmt(package, assigner, inner_call_id, package.synthetic_span()); let block_id = alloc_block( package, assigner, vec![leading_stmt_id, call_stmt_id], call_ty.clone(), - Span::default(), + package.synthetic_span(), ); let call_mut = package @@ -1936,7 +1960,7 @@ fn rebuild_controlled_arg_layers( assigner, vec![controls, current], tuple_ty, - Span::default(), + package.synthetic_span(), ); current = tuple_id; } diff --git a/source/compiler/qsc_fir_transforms/src/defunctionalize.rs b/source/compiler/qsc_fir_transforms/src/defunctionalize.rs index 903e962d766..9222aec07a8 100644 --- a/source/compiler/qsc_fir_transforms/src/defunctionalize.rs +++ b/source/compiler/qsc_fir_transforms/src/defunctionalize.rs @@ -358,12 +358,12 @@ fn accumulate_and_check_specialization_budget( let (name, span) = if let ItemKind::Callable(decl) = &item.kind { (decl.name.name.to_string(), decl.name.span) } else { - (format!("Item({hof_id})"), Span::default()) + (format!("Item({hof_id})"), package.synthetic_span()) }; return Some(Error::RecursiveSpecialization( name, count, - PackageSpan::new(hof_id.package, span), + PackageSpan::new(hof_id.package, span.span), )); } } @@ -558,7 +558,7 @@ fn emit_fixpoint_error( for &call_site in unresolved_direct_call_sites { let package = store.get(call_site.package); errors.push(Error::DynamicCallable( - (call_site.package, package.get_expr(call_site.expr).span).into(), + package.get_expr(call_site.expr).span, )); } } @@ -832,7 +832,7 @@ fn remaining_callable_value_info( if let ItemKind::Callable(decl) = &item.kind { let input_pat = package.get_pat(decl.input); if ty_contains_arrow_through_udts(store, &input_pat.ty) { - record_remaining(store_id.package, input_pat.span); + record_remaining(store_id.package, input_pat.span.span); } crate::walk_utils::for_each_expr_in_callable_impl( @@ -840,7 +840,7 @@ fn remaining_callable_value_info( &decl.implementation, &mut |_expr_id, expr| { if matches!(expr.kind, ExprKind::Closure(_, _)) { - record_remaining(store_id.package, expr.span); + record_remaining(store_id.package, expr.span.span); } // Count indirect calls through arrow-typed local variables. // After defunc iteration 1 specializes HOFs and removes callable @@ -857,7 +857,7 @@ fn remaining_callable_value_info( if matches!(base_expr.kind, ExprKind::Var(Res::Local(_), _)) && ty_contains_arrow(&base_expr.ty) { - record_remaining(store_id.package, base_expr.span); + record_remaining(store_id.package, base_expr.span.span); } } }, @@ -869,7 +869,7 @@ fn remaining_callable_value_info( if let Some(entry_id) = package.entry { crate::walk_utils::for_each_expr(package, entry_id, &mut |_expr_id, expr| { if matches!(expr.kind, ExprKind::Closure(_, _)) { - record_remaining(package_id, expr.span); + record_remaining(package_id, expr.span.span); } // Same indirect-call check as callable body walker. if let ExprKind::Call(callee_id, _) = &expr.kind { @@ -878,7 +878,7 @@ fn remaining_callable_value_info( if matches!(base_expr.kind, ExprKind::Var(Res::Local(_), _)) && ty_contains_arrow(&base_expr.ty) { - record_remaining(package_id, base_expr.span); + record_remaining(package_id, base_expr.span.span); } } }); diff --git a/source/compiler/qsc_fir_transforms/src/defunctionalize/prepass.rs b/source/compiler/qsc_fir_transforms/src/defunctionalize/prepass.rs index 5720f576214..efee1af690a 100644 --- a/source/compiler/qsc_fir_transforms/src/defunctionalize/prepass.rs +++ b/source/compiler/qsc_fir_transforms/src/defunctionalize/prepass.rs @@ -958,7 +958,7 @@ fn check_identity_closure( vec![( closure_expr_id, ExprKind::Var(Res::Local(captures[capture_idx]), Vec::new()), - Some(inner_span), + Some(inner_span.span), )] } // Callee is a global item — replace with the global reference. @@ -966,7 +966,7 @@ fn check_identity_closure( vec![( closure_expr_id, ExprKind::Var(Res::Item(*item_id), generic_args.clone()), - Some(inner_span), + Some(inner_span.span), )] } // Callee is a functor-wrapped expression — replace closure with the functor @@ -988,7 +988,7 @@ fn check_identity_closure( ( closure_expr_id, ExprKind::UnOp(UnOp::Functor(*functor), *inner_id), - Some(inner_span), + Some(inner_span.span), ), ] } @@ -998,7 +998,7 @@ fn check_identity_closure( vec![( closure_expr_id, ExprKind::UnOp(UnOp::Functor(*functor), *inner_id), - Some(inner_span), + Some(inner_span.span), )] } _ => Vec::new(), diff --git a/source/compiler/qsc_fir_transforms/src/defunctionalize/rewrite.rs b/source/compiler/qsc_fir_transforms/src/defunctionalize/rewrite.rs index 145490d4ced..71b1803c732 100644 --- a/source/compiler/qsc_fir_transforms/src/defunctionalize/rewrite.rs +++ b/source/compiler/qsc_fir_transforms/src/defunctionalize/rewrite.rs @@ -53,8 +53,8 @@ use crate::walk_utils::{ expr_is_safe_to_discard_with_total_foreign, expr_is_side_effect_free, for_each_direct_child, }; use qsc_data_structures::functors::FunctorApp; -use qsc_data_structures::span::Span; use qsc_fir::assigner::Assigner; +use qsc_fir::fir::PackageSpan; use qsc_fir::fir::{ BinOp, Block, BlockId, CallableImpl, CallableKind, Expr, ExprId, ExprKind, Field, FieldAssign, FieldPath, ItemId, ItemKind, LocalItemId, LocalVarId, Mutability, Package, PackageId, @@ -600,6 +600,7 @@ fn rewrite_direct_call( return; }; if let Some(span) = direct_call_site.def_span { + let span = package.span(span); package .exprs .get_mut(direct_call_site.call_expr_id) @@ -1372,7 +1373,7 @@ fn alloc_index_eq_expr( package: &mut Package, index_expr_id: ExprId, index_value: usize, - span: Span, + span: PackageSpan, assigner: &mut Assigner, ) -> ExprId { let index_value = i64::try_from(index_value).expect("dispatch index should fit in i64"); @@ -2799,7 +2800,7 @@ fn create_direct_branch_call( package_id: PackageId, orig_callee: &Expr, orig_args: &Expr, - span: Span, + span: PackageSpan, result_ty: &Ty, direct_call_site: &DirectCallSite, assigner: &mut Assigner, @@ -4387,7 +4388,7 @@ fn materialize_struct_copy_field( copy_id: ExprId, field_index: usize, field_ty: Ty, - span: Span, + span: PackageSpan, assigner: &mut Assigner, ) -> Option { let copy_expr = package.get_expr(copy_id).clone(); @@ -4671,7 +4672,7 @@ fn remove_element_at_path(package: &mut Package, expr_id: ExprId, path: &[usize] /// expression when possible and otherwise synthesizing `Var(Local(_))` nodes. fn allocate_capture_exprs( package: &mut Package, - span: Span, + span: PackageSpan, captures: &[CapturedVar], assigner: &mut Assigner, ) -> Vec { @@ -5396,7 +5397,7 @@ fn install_branch_split_dispatch<'a>( call_expr_id: ExprId, orig_callee_id: ExprId, orig_args_id: ExprId, - span: Span, + span: PackageSpan, result_ty: &Ty, conditioned: Vec>, default_entry: HofDispatchTarget<'a>, @@ -5481,7 +5482,7 @@ fn create_branch_call( _package_id: PackageId, orig_callee: &Expr, orig_args: &Expr, - span: Span, + span: PackageSpan, result_ty: &Ty, call_site: &CallSite, param: &CallableParam, @@ -5561,7 +5562,7 @@ fn create_combined_branch_call( package: &mut Package, orig_callee: &Expr, orig_args: &Expr, - span: Span, + span: PackageSpan, result_ty: &Ty, candidate: &CallSite, candidate_param: &CallableParam, @@ -5677,7 +5678,7 @@ fn build_combined_branch_args_data( orig_args: &Expr, remove_indices: &[usize], captures: &[CapturedVar], - span: Span, + span: PackageSpan, assigner: &mut Assigner, ) -> (ExprKind, Ty) { let new_ty = remove_tys_at_indices(package, &orig_args.ty, remove_indices, captures); @@ -5714,7 +5715,7 @@ fn build_combined_nested_branch_args_data( orig_args: &Expr, remove_indices: &[usize], captures: &[CapturedVar], - span: Span, + span: PackageSpan, assigner: &mut Assigner, ) -> (ExprKind, Ty) { let remove: FxHashSet = remove_indices.iter().copied().collect(); @@ -5910,7 +5911,7 @@ fn build_branch_args_data( orig_args: &Expr, input_path: &[usize], captures: &[CapturedVar], - span: Span, + span: PackageSpan, assigner: &mut Assigner, ) -> (ExprKind, Ty) { if input_path.is_empty() { @@ -6046,7 +6047,7 @@ fn alloc_specialized_callee_expr( /// `assigner`. fn alloc_item_callee_expr_with_functor( package: &mut Package, - span: Span, + span: PackageSpan, item_id: ItemId, callee_ty: &Ty, functor: FunctorApp, @@ -6066,7 +6067,7 @@ fn alloc_item_callee_expr_with_functor( /// through `assigner`. fn alloc_if_expr( package: &mut Package, - span: Span, + span: PackageSpan, result_ty: &Ty, cond_id: ExprId, true_id: ExprId, @@ -6100,7 +6101,7 @@ fn alloc_if_expr( /// `kind`/`ty` back into the original call expression. fn build_branch_tree( package: &mut Package, - span: Span, + span: PackageSpan, result_ty: &Ty, conditioned: Vec<(E, Vec)>, default_entry: E, diff --git a/source/compiler/qsc_fir_transforms/src/defunctionalize/specialize.rs b/source/compiler/qsc_fir_transforms/src/defunctionalize/specialize.rs index 3fc003f3dff..aaf6dbd5a85 100644 --- a/source/compiler/qsc_fir_transforms/src/defunctionalize/specialize.rs +++ b/source/compiler/qsc_fir_transforms/src/defunctionalize/specialize.rs @@ -40,8 +40,8 @@ use crate::fir_builder::{ use crate::package_assigners::PackageAssigners; use crate::walk_utils::{expr_is_side_effect_free, for_each_expr_in_callable_impl}; use qsc_data_structures::functors::FunctorApp; -use qsc_data_structures::span::Span; use qsc_fir::assigner::Assigner; +use qsc_fir::fir::PackageSpan; use qsc_fir::fir::{ BinOp, Block, BlockId, CallableDecl, CallableImpl, Expr, ExprId, ExprKind, Field, FieldPath, Ident, Item, ItemId, ItemKind, LocalItemId, LocalVarId, Mutability, Package, PackageId, @@ -268,7 +268,7 @@ fn try_decline_multiple_callable_arrays( let package = store.get(group[0].call_pkg_id); if has_multiple_forwarded_callable_arrays(package, group) { let span = package.get_expr(group[0].call_expr_id).span; - let package_span = (group[0].call_pkg_id, span).into(); + let package_span = span; if !errors .iter() .any(|e| matches!(e, Error::UnsupportedMultipleCallableArrays(s) if *s == package_span)) @@ -431,7 +431,7 @@ fn specialize_per_row_group( if matches!(call_site.callable_arg, ConcreteCallable::Dynamic) { let package = store.get(call_site.call_pkg_id); let span = package.get_expr(call_site.call_expr_id).span; - errors.push(Error::DynamicCallable((call_site.call_pkg_id, span).into())); + errors.push(Error::DynamicCallable(span)); continue; } @@ -507,7 +507,7 @@ fn report_excessive_specializations( errors.push(Error::ExcessiveSpecializations( decl.name.name.to_string(), *count, - (hof_id.package, decl.name.span).into(), + decl.name.span, )); } } @@ -844,7 +844,7 @@ fn specialize_many( let new_item = Item { id: new_item_id, - span: Span::default(), + span: target.synthetic_span(), parent: None, doc: Rc::from(""), attrs: Vec::new(), @@ -1357,7 +1357,7 @@ fn specialize_one( // Insert the new item. let new_item = Item { id: new_item_id, - span: Span::default(), + span: target.synthetic_span(), parent: None, doc: Rc::from(""), attrs: Vec::new(), @@ -2766,7 +2766,7 @@ fn replace_callable_value( /// for a dynamic callable, which has no concrete value to emit. fn alloc_callable_value_expr( package: &mut Package, - span: Span, + span: PackageSpan, concrete: &ConcreteCallable, hint_ty: &Ty, assigner: &mut Assigner, @@ -3023,7 +3023,7 @@ fn apply_body_functor_to_concrete( fn alloc_dispatch_branch_call( package: &mut Package, package_id: PackageId, - span: Span, + span: PackageSpan, result_ty: &Ty, callee_ty: &Ty, original_args: &Expr, @@ -3399,7 +3399,7 @@ fn grouped_capture_arg_data( /// fresh `Var(Res::Local)` reference to the captured variable is synthesized. fn allocate_capture_exprs( package: &mut Package, - span: Span, + span: PackageSpan, captures: &[CapturedVar], assigner: &mut Assigner, ) -> Vec { @@ -3445,7 +3445,7 @@ fn alloc_index_eq_expr( package: &mut Package, index_expr_id: ExprId, index_value: usize, - span: Span, + span: PackageSpan, assigner: &mut Assigner, ) -> ExprId { let index_value = i64::try_from(index_value).expect("dispatch index should fit in i64"); @@ -3465,7 +3465,7 @@ fn alloc_index_eq_expr( /// the given result type. fn alloc_if_expr( package: &mut Package, - span: Span, + span: PackageSpan, result_ty: &Ty, condition_id: ExprId, true_id: ExprId, @@ -3965,11 +3965,11 @@ fn thread_closure_captures( let name: Rc = Rc::from(format!("{CAPTURE_NAME_PREFIX}_{}", name_offset + i)); let new_pat = Pat { id: new_pat_id, - span: Span::default(), + span: package.synthetic_span(), ty: capture.ty.clone(), kind: PatKind::Bind(Ident { id: new_local_var, - span: Span::default(), + span: package.synthetic_span(), name, }), }; @@ -4009,7 +4009,7 @@ fn thread_closure_captures( let tuple_pat = Pat { id: tuple_pat_id, - span: Span::default(), + span: package.synthetic_span(), ty: Ty::Tuple(all_tys), kind: PatKind::Tuple(sub_pats), }; diff --git a/source/compiler/qsc_fir_transforms/src/defunctionalize/tests/analysis.rs b/source/compiler/qsc_fir_transforms/src/defunctionalize/tests/analysis.rs index 6f0b0b3940f..539dc2a71f5 100644 --- a/source/compiler/qsc_fir_transforms/src/defunctionalize/tests/analysis.rs +++ b/source/compiler/qsc_fir_transforms/src/defunctionalize/tests/analysis.rs @@ -5337,6 +5337,7 @@ fn analysis_callable_from_tuple_destructured_array_iteration() { #[test] fn resolve_captures_missing_binding_returns_none() { let package = Package { + id: qsc_fir::fir::PackageId::default(), items: IndexMap::new(), entry: None, entry_exec_graph: qsc_fir::fir::ExecGraph::default(), diff --git a/source/compiler/qsc_fir_transforms/src/exec_graph_rebuild.rs b/source/compiler/qsc_fir_transforms/src/exec_graph_rebuild.rs index e960565bf3c..e7bc495bc29 100644 --- a/source/compiler/qsc_fir_transforms/src/exec_graph_rebuild.rs +++ b/source/compiler/qsc_fir_transforms/src/exec_graph_rebuild.rs @@ -412,7 +412,10 @@ fn rebuild_expr( rebuild_expr(package, builder, lhs, ranges); builder.truncate(idx); rebuild_expr(package, builder, rhs, ranges); - builder.push(ExecGraphNode::Expr(ExecGraphExpr::Assign(lhs), expr_span)); + builder.push(ExecGraphNode::Expr( + ExecGraphExpr::Assign(lhs), + expr_span.span, + )); builder.push(ExecGraphNode::Unit); } @@ -454,10 +457,10 @@ fn rebuild_expr( ExecGraphExpr::AssignOp { op, lhs, - lhs_span, - rhs_span, + lhs_span: lhs_span.span, + rhs_span: rhs_span.span, }, - expr_span, + expr_span.span, )); builder.push(ExecGraphNode::Unit); } @@ -466,7 +469,10 @@ fn rebuild_expr( rebuild_expr(package, builder, replace, ranges); builder.push(ExecGraphNode::Store); rebuild_expr(package, builder, container, ranges); - builder.push(ExecGraphNode::Expr(ExecGraphExpr::Expr(expr_id), expr_span)); + builder.push(ExecGraphNode::Expr( + ExecGraphExpr::Expr(expr_id), + expr_span.span, + )); builder.push(ExecGraphNode::Unit); } @@ -482,9 +488,9 @@ fn rebuild_expr( builder.push(ExecGraphNode::Expr( ExecGraphExpr::AssignIndex { lhs: container, - mid_span: index_span, + mid_span: index_span.span, }, - expr_span, + expr_span.span, )); builder.push(ExecGraphNode::Unit); } @@ -506,7 +512,7 @@ fn rebuild_expr( } builder.push(ExecGraphNode::Expr( ExecGraphExpr::Array(items.len()), - expr_span, + expr_span.span, )); } ExprKind::Tuple(items) => { @@ -516,7 +522,7 @@ fn rebuild_expr( } builder.push(ExecGraphNode::Expr( ExecGraphExpr::Tuple(items.len()), - expr_span, + expr_span.span, )); } @@ -525,14 +531,20 @@ fn rebuild_expr( rebuild_expr(package, builder, *item_id, ranges); builder.pop(); } - builder.push(ExecGraphNode::Expr(ExecGraphExpr::Expr(expr_id), expr_span)); + builder.push(ExecGraphNode::Expr( + ExecGraphExpr::Expr(expr_id), + expr_span.span, + )); } ExprKind::ArrayRepeat(val, size) => { rebuild_expr(package, builder, val, ranges); builder.push(ExecGraphNode::Store); rebuild_expr(package, builder, size, ranges); - builder.push(ExecGraphNode::Expr(ExecGraphExpr::ArrayRepeat, expr_span)); + builder.push(ExecGraphNode::Expr( + ExecGraphExpr::ArrayRepeat, + expr_span.span, + )); } ExprKind::BinOp(op, lhs, rhs) => { @@ -547,10 +559,10 @@ fn rebuild_expr( builder.push(ExecGraphNode::Expr( ExecGraphExpr::BinOp { op, - lhs_span, - rhs_span, + lhs_span: lhs_span.span, + rhs_span: rhs_span.span, }, - expr_span, + expr_span.span, )); } @@ -564,10 +576,10 @@ fn rebuild_expr( let args_span = package.get_expr(arg).span; builder.push(ExecGraphNode::Expr( ExecGraphExpr::Call { - callee_span, - args_span, + callee_span: callee_span.span, + args_span: args_span.span, }, - expr_span, + expr_span.span, )); } @@ -577,8 +589,10 @@ fn rebuild_expr( rebuild_expr(package, builder, index, ranges); let index_span = package.get_expr(index).span; builder.push(ExecGraphNode::Expr( - ExecGraphExpr::Index { index_span }, - expr_span, + ExecGraphExpr::Index { + index_span: index_span.span, + }, + expr_span.span, )); } @@ -586,7 +600,10 @@ fn rebuild_expr( rebuild_expr(package, builder, replace, ranges); builder.push(ExecGraphNode::Store); rebuild_expr(package, builder, record, ranges); - builder.push(ExecGraphNode::Expr(ExecGraphExpr::Expr(expr_id), expr_span)); + builder.push(ExecGraphNode::Expr( + ExecGraphExpr::Expr(expr_id), + expr_span.span, + )); } ExprKind::UpdateIndex(lhs, mid, rhs) => { @@ -597,8 +614,10 @@ fn rebuild_expr( rebuild_expr(package, builder, lhs, ranges); let mid_span = package.get_expr(mid).span; builder.push(ExecGraphNode::Expr( - ExecGraphExpr::UpdateIndex { mid_span }, - expr_span, + ExecGraphExpr::UpdateIndex { + mid_span: mid_span.span, + }, + expr_span.span, )); } @@ -620,7 +639,7 @@ fn rebuild_expr( has_step: step.is_some(), has_end: end.is_some(), }, - expr_span, + expr_span.span, )); } @@ -631,29 +650,38 @@ fn rebuild_expr( builder.push(ExecGraphNode::Store); } } - builder.push(ExecGraphNode::Expr(ExecGraphExpr::Expr(expr_id), expr_span)); + builder.push(ExecGraphNode::Expr( + ExecGraphExpr::Expr(expr_id), + expr_span.span, + )); } ExprKind::Lit(..) => { - builder.push(ExecGraphNode::Expr(ExecGraphExpr::Expr(expr_id), expr_span)); + builder.push(ExecGraphNode::Expr( + ExecGraphExpr::Expr(expr_id), + expr_span.span, + )); } ExprKind::Var(res, _) => { - builder.push(ExecGraphNode::Expr(ExecGraphExpr::Var(res), expr_span)); + builder.push(ExecGraphNode::Expr(ExecGraphExpr::Var(res), expr_span.span)); } ExprKind::Fail(msg) => { rebuild_expr(package, builder, msg, ranges); - builder.push(ExecGraphNode::Expr(ExecGraphExpr::Fail, expr_span)); + builder.push(ExecGraphNode::Expr(ExecGraphExpr::Fail, expr_span.span)); } ExprKind::Field(container, _) => { rebuild_expr(package, builder, container, ranges); - builder.push(ExecGraphNode::Expr(ExecGraphExpr::Expr(expr_id), expr_span)); + builder.push(ExecGraphNode::Expr( + ExecGraphExpr::Expr(expr_id), + expr_span.span, + )); } ExprKind::UnOp(op, operand) => { rebuild_expr(package, builder, operand, ranges); - builder.push(ExecGraphNode::Expr(ExecGraphExpr::UnOp(op), expr_span)); + builder.push(ExecGraphNode::Expr(ExecGraphExpr::UnOp(op), expr_span.span)); } ExprKind::Parallel(limit, body) => { diff --git a/source/compiler/qsc_fir_transforms/src/fir_builder.rs b/source/compiler/qsc_fir_transforms/src/fir_builder.rs index cb2447d3b97..c5a5c7e8d24 100644 --- a/source/compiler/qsc_fir_transforms/src/fir_builder.rs +++ b/source/compiler/qsc_fir_transforms/src/fir_builder.rs @@ -30,7 +30,6 @@ mod tests; use crate::EMPTY_EXEC_RANGE; use qsc_data_structures::functors::FunctorApp; -use qsc_data_structures::span::Span; use qsc_fir::assigner::Assigner; use qsc_fir::fir::{ BinOp, Block, BlockId, CallableDecl, Expr, ExprId, ExprKind, Field, FieldPath, Functor, Ident, @@ -39,6 +38,7 @@ use qsc_fir::fir::{ }; use rustc_hash::FxHashSet; +use qsc_fir::fir::PackageSpan; use qsc_fir::ty::{Arrow, Prim, Ty}; use std::rc::Rc; @@ -48,7 +48,7 @@ pub(crate) fn alloc_expr( assigner: &mut Assigner, ty: Ty, kind: ExprKind, - span: Span, + span: PackageSpan, ) -> ExprId { let id = assigner.next_expr(); package.exprs.insert( @@ -70,7 +70,7 @@ pub(crate) fn alloc_local_var_expr( assigner: &mut Assigner, var_id: LocalVarId, ty: Ty, - span: Span, + span: PackageSpan, ) -> ExprId { alloc_expr( package, @@ -88,7 +88,7 @@ pub(crate) fn alloc_field_expr( record_id: ExprId, index: usize, ty: Ty, - span: Span, + span: PackageSpan, ) -> ExprId { alloc_expr( package, @@ -114,7 +114,7 @@ pub(crate) fn alloc_field_path_expr( record_id: ExprId, indices: Vec, ty: Ty, - span: Span, + span: PackageSpan, ) -> ExprId { alloc_expr( package, @@ -131,7 +131,7 @@ pub(crate) fn alloc_item_var_expr( assigner: &mut Assigner, item_id: ItemId, ty: Ty, - span: Span, + span: PackageSpan, ) -> ExprId { alloc_expr( package, @@ -149,7 +149,7 @@ pub(crate) fn alloc_call_expr( callee_id: ExprId, args_id: ExprId, ty: Ty, - span: Span, + span: PackageSpan, ) -> ExprId { alloc_expr( package, @@ -165,7 +165,7 @@ pub(crate) fn alloc_int_lit( package: &mut Package, assigner: &mut Assigner, value: i64, - span: Span, + span: PackageSpan, ) -> ExprId { alloc_expr( package, @@ -248,7 +248,7 @@ pub(crate) fn wrap_in_functors( base_id: ExprId, functor: FunctorApp, ty: &Ty, - span: Span, + span: PackageSpan, ) -> ExprId { // `layer_tys[0]` is the outermost type; `layer_tys[controlled]` is the base. let layer_tys = controlled_layer_types(ty, functor.controlled); @@ -293,7 +293,7 @@ pub(crate) fn alloc_functor_wrapped_expr( base_kind: ExprKind, functor: FunctorApp, ty: &Ty, - span: Span, + span: PackageSpan, ) -> ExprId { let mut base_ty = ty.clone(); for _ in 0..functor.controlled { @@ -311,7 +311,7 @@ pub(crate) fn alloc_bin_op_expr( lhs: ExprId, rhs: ExprId, ty: Ty, - span: Span, + span: PackageSpan, ) -> ExprId { alloc_expr(package, assigner, ty, ExprKind::BinOp(op, lhs, rhs), span) } @@ -321,7 +321,7 @@ pub(crate) fn alloc_not_expr( package: &mut Package, assigner: &mut Assigner, operand: ExprId, - span: Span, + span: PackageSpan, ) -> ExprId { alloc_expr( package, @@ -340,7 +340,7 @@ pub(crate) fn alloc_if_expr( then_expr: ExprId, else_expr: Option, ty: Ty, - span: Span, + span: PackageSpan, ) -> ExprId { alloc_expr( package, @@ -357,7 +357,7 @@ pub(crate) fn alloc_block_expr( assigner: &mut Assigner, block_id: BlockId, ty: Ty, - span: Span, + span: PackageSpan, ) -> ExprId { alloc_expr(package, assigner, ty, ExprKind::Block(block_id), span) } @@ -368,7 +368,7 @@ pub(crate) fn alloc_assign_expr( assigner: &mut Assigner, lhs: ExprId, rhs: ExprId, - span: Span, + span: PackageSpan, ) -> ExprId { alloc_expr( package, @@ -384,7 +384,7 @@ pub(crate) fn alloc_bool_lit( package: &mut Package, assigner: &mut Assigner, value: bool, - span: Span, + span: PackageSpan, ) -> ExprId { alloc_expr( package, @@ -399,7 +399,7 @@ pub(crate) fn alloc_bool_lit( pub(crate) fn alloc_unit_expr( package: &mut Package, assigner: &mut Assigner, - span: Span, + span: PackageSpan, ) -> ExprId { alloc_expr( package, @@ -416,7 +416,7 @@ pub(crate) fn alloc_tuple_expr( assigner: &mut Assigner, exprs: Vec, ty: Ty, - span: Span, + span: PackageSpan, ) -> ExprId { alloc_expr(package, assigner, ty, ExprKind::Tuple(exprs), span) } @@ -426,7 +426,7 @@ pub(crate) fn alloc_stmt( package: &mut Package, assigner: &mut Assigner, kind: StmtKind, - span: Span, + span: PackageSpan, ) -> StmtId { let id = assigner.next_stmt(); package.stmts.insert( @@ -446,7 +446,7 @@ pub(crate) fn alloc_expr_stmt( package: &mut Package, assigner: &mut Assigner, expr_id: ExprId, - span: Span, + span: PackageSpan, ) -> StmtId { alloc_stmt(package, assigner, StmtKind::Expr(expr_id), span) } @@ -456,7 +456,7 @@ pub(crate) fn alloc_semi_stmt( package: &mut Package, assigner: &mut Assigner, expr_id: ExprId, - span: Span, + span: PackageSpan, ) -> StmtId { alloc_stmt(package, assigner, StmtKind::Semi(expr_id), span) } @@ -468,7 +468,7 @@ pub(crate) fn alloc_local_stmt( mutability: Mutability, pat_id: PatId, init_expr: ExprId, - span: Span, + span: PackageSpan, ) -> StmtId { alloc_stmt( package, @@ -484,7 +484,7 @@ pub(crate) fn alloc_block( assigner: &mut Assigner, stmts: Vec, ty: Ty, - span: Span, + span: PackageSpan, ) -> BlockId { let id = assigner.next_block(); package.blocks.insert( @@ -505,7 +505,7 @@ pub(crate) fn alloc_bind_pat( assigner: &mut Assigner, name: &str, ty: Ty, - span: Span, + span: PackageSpan, ) -> (LocalVarId, PatId) { let local_id = assigner.next_local(); let pat_id = assigner.next_pat(); @@ -530,7 +530,7 @@ pub(crate) fn alloc_discard_pat( package: &mut Package, assigner: &mut Assigner, ty: Ty, - span: Span, + span: PackageSpan, ) -> PatId { let pat_id = assigner.next_pat(); package.pats.insert( @@ -556,14 +556,20 @@ pub(crate) fn alloc_local_var( init_expr: ExprId, mutability: Mutability, ) -> (LocalVarId, StmtId) { - let (local_id, pat_id) = alloc_bind_pat(package, assigner, name, ty.clone(), Span::default()); + let (local_id, pat_id) = alloc_bind_pat( + package, + assigner, + name, + ty.clone(), + package.synthetic_span(), + ); let stmt_id = alloc_local_stmt( package, assigner, mutability, pat_id, init_expr, - Span::default(), + package.synthetic_span(), ); (local_id, stmt_id) } @@ -597,11 +603,11 @@ pub(crate) fn decompose_binding( let elem_name: Rc = Rc::from(format!("{name}.{i}")); let new_pat = Pat { id: new_pat_id, - span: Span::default(), + span: package.synthetic_span(), ty: elem_ty.clone(), kind: PatKind::Bind(Ident { id: new_local, - span: Span::default(), + span: package.synthetic_span(), name: elem_name, }), }; @@ -712,8 +718,13 @@ fn collect_leaf_binds( leaf_name.push('.'); leaf_name.push_str(&index.to_string()); } - let (local_id, leaf_pat_id) = - alloc_bind_pat(package, assigner, &leaf_name, ty.clone(), Span::default()); + let (local_id, leaf_pat_id) = alloc_bind_pat( + package, + assigner, + &leaf_name, + ty.clone(), + package.synthetic_span(), + ); leaves.push((path.clone(), local_id, ty.clone())); leaf_pat_ids.push(leaf_pat_id); } diff --git a/source/compiler/qsc_fir_transforms/src/intrinsic_precheck.rs b/source/compiler/qsc_fir_transforms/src/intrinsic_precheck.rs index a47837e020a..8a1817c6860 100644 --- a/source/compiler/qsc_fir_transforms/src/intrinsic_precheck.rs +++ b/source/compiler/qsc_fir_transforms/src/intrinsic_precheck.rs @@ -103,7 +103,7 @@ pub fn validate_intrinsic_types(store: &PackageStore, package_id: PackageId) -> errors.push(Error::UnsupportedParamType( name.clone(), format!("{}", param.ty), - (item_id.package, decl.span).into(), + decl.span, )); } } @@ -116,7 +116,7 @@ pub fn validate_intrinsic_types(store: &PackageStore, package_id: PackageId) -> errors.push(Error::UnsupportedReturnType( name, format!("{}", decl.output), - (item_id.package, decl.span).into(), + decl.span, )); } } diff --git a/source/compiler/qsc_fir_transforms/src/item_dce/tests.rs b/source/compiler/qsc_fir_transforms/src/item_dce/tests.rs index 776bda74228..ebb1caf6a28 100644 --- a/source/compiler/qsc_fir_transforms/src/item_dce/tests.rs +++ b/source/compiler/qsc_fir_transforms/src/item_dce/tests.rs @@ -7,8 +7,8 @@ use crate::test_utils::{ compile_and_run_pipeline_to_with_library, compile_to_fir, compile_to_fir_with_library, }; use indoc::indoc; -use qsc_data_structures::span::Span; use qsc_fir::assigner::Assigner; +use qsc_fir::fir::PackageSpan; use qsc_fir::fir::{ItemKind, PackageLookup}; /// Counts total items in the user package. @@ -428,7 +428,7 @@ mod item_dce_contracts { stmt_id, qsc_fir::fir::Stmt { id: stmt_id, - span: Span::default(), + span: PackageSpan::default(), kind: qsc_fir::fir::StmtKind::Item(item_id), exec_graph_range: crate::EMPTY_EXEC_RANGE, }, diff --git a/source/compiler/qsc_fir_transforms/src/return_unify.rs b/source/compiler/qsc_fir_transforms/src/return_unify.rs index 344b29d5541..ba908769fb4 100644 --- a/source/compiler/qsc_fir_transforms/src/return_unify.rs +++ b/source/compiler/qsc_fir_transforms/src/return_unify.rs @@ -585,7 +585,7 @@ fn process_callable_returns( if has_return { errors.push(Error::UnsupportedEarlyReturnType( format!("{return_ty}"), - PackageSpan::new(owning_pkg, callable.name.span), + PackageSpan::new(owning_pkg, callable.name.span.span), )); skipped.insert(StoreItemId { package: owning_pkg, @@ -704,7 +704,7 @@ fn check_normalize_supportable( { errors.push(Error::UnsupportedHoistContext( format!("{}", expr.ty), - PackageSpan::new(package_id, expr.span), + PackageSpan::new(package_id, expr.span.span), )); } ExprKind::Block(bid) | ExprKind::While(_, bid) => block_ids.push(*bid), @@ -725,7 +725,7 @@ fn check_normalize_supportable( if !is_type_defaultable(package, package_id, pat_ty) { errors.push(Error::UnsupportedHoistContext( format!("{pat_ty}"), - PackageSpan::new(package_id, package.get_expr(*init_id).span), + PackageSpan::new(package_id, package.get_expr(*init_id).span.span), )); } } diff --git a/source/compiler/qsc_fir_transforms/src/return_unify/lower.rs b/source/compiler/qsc_fir_transforms/src/return_unify/lower.rs index 767009e1462..871a13195a8 100644 --- a/source/compiler/qsc_fir_transforms/src/return_unify/lower.rs +++ b/source/compiler/qsc_fir_transforms/src/return_unify/lower.rs @@ -12,7 +12,6 @@ use crate::{ }, walk_utils::{expr_is_safe_to_discard, for_each_expr}, }; -use qsc_data_structures::span::Span; use qsc_fir::{ assigner::Assigner, fir::{ @@ -22,6 +21,8 @@ use qsc_fir::{ ty::{Prim, Ty}, }; +use qsc_fir::fir::PackageSpan; + use super::{ UdtPureTyCache, continuation::continuation_suffix_requires_split, @@ -540,13 +541,19 @@ fn create_lazy_flag_continuation_stmt( match output { // A value-producing block ends in an expression statement (no trailing // semicolon) so the guarded `if` becomes the block's value. - FlagBlockOutput::ReturnValue { .. } => { - alloc_expr_stmt(package, assigner, lazy_continuation, Span::default()) - } + FlagBlockOutput::ReturnValue { .. } => alloc_expr_stmt( + package, + assigner, + lazy_continuation, + package.synthetic_span(), + ), // A unit block ends in a semicolon statement. - FlagBlockOutput::Unit => { - alloc_semi_stmt(package, assigner, lazy_continuation, Span::default()) - } + FlagBlockOutput::Unit => alloc_semi_stmt( + package, + assigner, + lazy_continuation, + package.synthetic_span(), + ), } } @@ -615,7 +622,7 @@ fn create_lazy_flag_continuation_expr( package, assigner, missing_value, - Span::default(), + package.synthetic_span(), )); } @@ -637,14 +644,14 @@ fn create_lazy_flag_continuation_expr( assigner, continuation_stmts, continuation_ty.clone(), - Span::default(), + package.synthetic_span(), ); let continuation_expr = alloc_block_expr( package, assigner, continuation_block, continuation_ty.clone(), - Span::default(), + package.synthetic_span(), ); // Guard on `not __has_returned` so the suffix runs only when no early return // has fired; otherwise control takes the `else` (slot read) path. @@ -657,7 +664,7 @@ fn create_lazy_flag_continuation_expr( continuation_expr, else_expr, continuation_ty, - Span::default(), + package.synthetic_span(), ) } @@ -753,7 +760,7 @@ fn transform_while_in_expr( not_flag, cond_id, Ty::Prim(Prim::Bool), - Span::default(), + package.synthetic_span(), ); if contains_return_in_block(package, body_block_id) { @@ -1006,9 +1013,10 @@ fn replace_returns_in_expr( inner_id, &inner_ty, ); - let assign_val_semi = alloc_semi_stmt(package, assigner, assign_val, Span::default()); + let assign_val_semi = + alloc_semi_stmt(package, assigner, assign_val, package.synthetic_span()); - let true_lit = alloc_bool_lit(package, assigner, true, Span::default()); + let true_lit = alloc_bool_lit(package, assigner, true, package.synthetic_span()); let assign_flag = create_assign_expr( package, assigner, @@ -1016,17 +1024,23 @@ fn replace_returns_in_expr( true_lit, &Ty::Prim(Prim::Bool), ); - let assign_flag_semi = alloc_semi_stmt(package, assigner, assign_flag, Span::default()); + let assign_flag_semi = + alloc_semi_stmt(package, assigner, assign_flag, package.synthetic_span()); let flag_block = alloc_block( package, assigner, vec![assign_val_semi, assign_flag_semi], Ty::UNIT, - Span::default(), + package.synthetic_span(), + ); + let flag_block_expr = alloc_block_expr( + package, + assigner, + flag_block, + Ty::UNIT, + package.synthetic_span(), ); - let flag_block_expr = - alloc_block_expr(package, assigner, flag_block, Ty::UNIT, Span::default()); let replacement = package.get_expr(flag_block_expr).clone(); let e = package.exprs.get_mut(expr_id).expect("expr not found"); @@ -1284,7 +1298,7 @@ fn replace_condition_return_with_flags( package: &mut Package, assigner: &mut Assigner, return_expr_id: ExprId, - span: Span, + span: PackageSpan, inner_id: ExprId, flag_context: &FlagContext<'_>, ) { @@ -1296,9 +1310,9 @@ fn replace_condition_return_with_flags( inner_id, &inner_ty, ); - let assign_val_semi = alloc_semi_stmt(package, assigner, assign_val, Span::default()); + let assign_val_semi = alloc_semi_stmt(package, assigner, assign_val, package.synthetic_span()); - let true_lit = alloc_bool_lit(package, assigner, true, Span::default()); + let true_lit = alloc_bool_lit(package, assigner, true, package.synthetic_span()); let assign_flag = create_assign_expr( package, assigner, @@ -1306,24 +1320,25 @@ fn replace_condition_return_with_flags( true_lit, &Ty::Prim(Prim::Bool), ); - let assign_flag_semi = alloc_semi_stmt(package, assigner, assign_flag, Span::default()); + let assign_flag_semi = + alloc_semi_stmt(package, assigner, assign_flag, package.synthetic_span()); - let false_lit = alloc_bool_lit(package, assigner, false, Span::default()); - let false_stmt = alloc_expr_stmt(package, assigner, false_lit, Span::default()); + let false_lit = alloc_bool_lit(package, assigner, false, package.synthetic_span()); + let false_stmt = alloc_expr_stmt(package, assigner, false_lit, package.synthetic_span()); let flag_block = alloc_block( package, assigner, vec![assign_val_semi, assign_flag_semi, false_stmt], Ty::Prim(Prim::Bool), - Span::default(), + package.synthetic_span(), ); let flag_block_expr = alloc_block_expr( package, assigner, flag_block, Ty::Prim(Prim::Bool), - Span::default(), + package.synthetic_span(), ); let replacement = package.get_expr(flag_block_expr).clone(); @@ -1361,36 +1376,38 @@ pub(super) fn guard_stmt_with_flag( let not_flag = create_not_var_expr(package, assigner, flag_context.has_returned_var_id); - let then_trailing = alloc_expr_stmt(package, assigner, init_expr_id, Span::default()); + let then_trailing = + alloc_expr_stmt(package, assigner, init_expr_id, package.synthetic_span()); let then_block = alloc_block( package, assigner, vec![then_trailing], init_ty.clone(), - Span::default(), + package.synthetic_span(), ); let then_expr = alloc_block_expr( package, assigner, then_block, init_ty.clone(), - Span::default(), + package.synthetic_span(), ); - let else_trailing = alloc_expr_stmt(package, assigner, default_val, Span::default()); + let else_trailing = + alloc_expr_stmt(package, assigner, default_val, package.synthetic_span()); let else_block = alloc_block( package, assigner, vec![else_trailing], init_ty.clone(), - Span::default(), + package.synthetic_span(), ); let else_expr = alloc_block_expr( package, assigner, else_block, init_ty.clone(), - Span::default(), + package.synthetic_span(), ); let if_expr = alloc_if_expr( @@ -1400,7 +1417,7 @@ pub(super) fn guard_stmt_with_flag( then_expr, Some(else_expr), init_ty, - Span::default(), + package.synthetic_span(), ); let stmt = package.stmts.get_mut(stmt_id).expect("stmt not found"); @@ -1417,9 +1434,20 @@ pub(super) fn guard_stmt_with_flag( "guard_stmt_with_flag requires Unit-typed inner stmt" ); let not_flag = create_not_var_expr(package, assigner, flag_context.has_returned_var_id); - let guard_block = alloc_block(package, assigner, vec![stmt_id], Ty::UNIT, Span::default()); - let guard_block_expr = - alloc_block_expr(package, assigner, guard_block, Ty::UNIT, Span::default()); + let guard_block = alloc_block( + package, + assigner, + vec![stmt_id], + Ty::UNIT, + package.synthetic_span(), + ); + let guard_block_expr = alloc_block_expr( + package, + assigner, + guard_block, + Ty::UNIT, + package.synthetic_span(), + ); let if_expr = alloc_if_expr( package, assigner, @@ -1427,9 +1455,9 @@ pub(super) fn guard_stmt_with_flag( guard_block_expr, None, Ty::UNIT, - Span::default(), + package.synthetic_span(), ); - alloc_semi_stmt(package, assigner, if_expr, Span::default()) + alloc_semi_stmt(package, assigner, if_expr, package.synthetic_span()) } #[cfg(test)] @@ -1476,7 +1504,7 @@ fn create_flag_trailing_expr_for_slot( assigner, flag_context.has_returned_var_id, Ty::Prim(Prim::Bool), - Span::default(), + package.synthetic_span(), ); let ret_var = create_return_slot_read_expr( package, @@ -1503,7 +1531,7 @@ fn create_flag_trailing_expr_for_slot( assigner, trailing_var_id, flag_context.return_ty.clone(), - Span::default(), + package.synthetic_span(), ); let if_expr = alloc_if_expr( package, @@ -1512,15 +1540,20 @@ fn create_flag_trailing_expr_for_slot( ret_var, Some(trailing_var_expr), flag_context.return_ty.clone(), - Span::default(), + package.synthetic_span(), ); ( - Some(alloc_expr_stmt(package, assigner, if_expr, Span::default())), + Some(alloc_expr_stmt( + package, + assigner, + if_expr, + package.synthetic_span(), + )), Some(trailing_var_id), ) } else { let fallback_expr = if flag_context.return_ty == &Ty::UNIT { - alloc_unit_expr(package, assigner, Span::default()) + alloc_unit_expr(package, assigner, package.synthetic_span()) } else { create_return_slot_unwritten_fallback_expr( package, @@ -1536,10 +1569,15 @@ fn create_flag_trailing_expr_for_slot( ret_var, Some(fallback_expr), flag_context.return_ty.clone(), - Span::default(), + package.synthetic_span(), ); ( - Some(alloc_expr_stmt(package, assigner, if_expr, Span::default())), + Some(alloc_expr_stmt( + package, + assigner, + if_expr, + package.synthetic_span(), + )), None, ) } @@ -1555,9 +1593,9 @@ fn create_not_var_expr( assigner, var_id, Ty::Prim(Prim::Bool), - Span::default(), + package.synthetic_span(), ); - alloc_not_expr(package, assigner, var, Span::default()) + alloc_not_expr(package, assigner, var, package.synthetic_span()) } fn create_assign_expr( @@ -1567,8 +1605,14 @@ fn create_assign_expr( value: ExprId, ty: &Ty, ) -> ExprId { - let var_expr = alloc_local_var_expr(package, assigner, var_id, ty.clone(), Span::default()); - alloc_assign_expr(package, assigner, var_expr, value, Span::default()) + let var_expr = alloc_local_var_expr( + package, + assigner, + var_id, + ty.clone(), + package.synthetic_span(), + ); + alloc_assign_expr(package, assigner, var_expr, value, package.synthetic_span()) } fn create_mutable_bool_var( @@ -1577,7 +1621,7 @@ fn create_mutable_bool_var( name: &str, value: bool, ) -> (LocalVarId, StmtId) { - let init_expr = alloc_bool_lit(package, assigner, value, Span::default()); + let init_expr = alloc_bool_lit(package, assigner, value, package.synthetic_span()); alloc_local_var( package, assigner, diff --git a/source/compiler/qsc_fir_transforms/src/return_unify/normalize.rs b/source/compiler/qsc_fir_transforms/src/return_unify/normalize.rs index e2e894916c1..c4e3dc3c33b 100644 --- a/source/compiler/qsc_fir_transforms/src/return_unify/normalize.rs +++ b/source/compiler/qsc_fir_transforms/src/return_unify/normalize.rs @@ -63,7 +63,6 @@ use crate::fir_builder::{ alloc_block, alloc_bool_lit, alloc_discard_pat, alloc_expr, alloc_expr_stmt, alloc_local_stmt, alloc_local_var, alloc_local_var_expr, alloc_not_expr, alloc_semi_stmt, }; -use qsc_data_structures::span::Span; use std::rc::Rc; use super::detect::contains_return_in_expr; @@ -522,7 +521,7 @@ fn hoist_in_expr( return Some(inner_stmts); } // Re-use the existing Return expression as a Semi statement. - let stmt = alloc_semi_stmt(package, assigner, expr_id, Span::default()); + let stmt = alloc_semi_stmt(package, assigner, expr_id, package.synthetic_span()); Some(vec![stmt]) } @@ -706,7 +705,7 @@ fn hoist_short_circuit( } let lit_expr = { let value = !is_and; - alloc_bool_lit(package, assigner, value, Span::default()) + alloc_bool_lit(package, assigner, value, package.synthetic_span()) }; let (then_id, else_id) = if is_and { (b, lit_expr) } else { (lit_expr, b) }; let expr = package.exprs.get_mut(expr_id).expect("expr not found"); @@ -742,19 +741,19 @@ fn hoist_short_circuit_assign( assigner, place_expr.ty.clone(), place_expr.kind.clone(), - Span::default(), + package.synthetic_span(), ); let cond = if is_and { place_read } else { - alloc_not_expr(package, assigner, place_read, Span::default()) + alloc_not_expr(package, assigner, place_read, package.synthetic_span()) }; let assign = alloc_expr( package, assigner, Ty::UNIT, ExprKind::Assign(place, rhs), - Span::default(), + package.synthetic_span(), ); let expr = package.exprs.get_mut(expr_id).expect("expr not found"); expr.kind = ExprKind::If(cond, assign, None); @@ -776,14 +775,14 @@ fn create_typed_fail_expr( assigner, Ty::Prim(Prim::String), ExprKind::String(vec![StringComponent::Lit(Rc::from(message))]), - Span::default(), + package.synthetic_span(), ); alloc_expr( package, assigner, output_ty.clone(), ExprKind::Fail(msg_expr_id), - Span::default(), + package.synthetic_span(), ) } @@ -827,12 +826,18 @@ fn hoist_in_cond( package, assigner, dead_tail, - Span::default(), + package.synthetic_span(), )); } let block_id = { let ty: &Ty = &orig_ty; - alloc_block(package, assigner, block_stmts, ty.clone(), Span::default()) + alloc_block( + package, + assigner, + block_stmts, + ty.clone(), + package.synthetic_span(), + ) }; let expr = package.exprs.get_mut(expr_id).expect("expr not found"); expr.kind = ExprKind::Block(block_id); @@ -849,14 +854,14 @@ fn create_discard_let_stmt( expr_id: ExprId, ) -> StmtId { let ty = package.get_expr(expr_id).ty.clone(); - let pat_id = alloc_discard_pat(package, assigner, ty, Span::default()); + let pat_id = alloc_discard_pat(package, assigner, ty, package.synthetic_span()); alloc_local_stmt( package, assigner, Mutability::Immutable, pat_id, expr_id, - Span::default(), + package.synthetic_span(), ) } @@ -895,8 +900,13 @@ fn bind_inner_and_return( Mutability::Immutable, ); - let var_expr_id = - alloc_local_var_expr(package, assigner, local_var_id, inner_ty, Span::default()); + let var_expr_id = alloc_local_var_expr( + package, + assigner, + local_var_id, + inner_ty, + package.synthetic_span(), + ); // Rewrite the existing Return expression in place so it now wraps the // Var, then wrap it in a fresh Semi statement. @@ -905,7 +915,7 @@ fn bind_inner_and_return( .get_mut(return_expr) .expect("return expr not found"); ret.kind = ExprKind::Return(var_expr_id); - let return_stmt_id = alloc_semi_stmt(package, assigner, return_expr, Span::default()); + let return_stmt_id = alloc_semi_stmt(package, assigner, return_expr, package.synthetic_span()); vec![local_stmt_id, return_stmt_id] } diff --git a/source/compiler/qsc_fir_transforms/src/return_unify/normalize/anf.rs b/source/compiler/qsc_fir_transforms/src/return_unify/normalize/anf.rs index 1d5d366a27d..6b89b197a90 100644 --- a/source/compiler/qsc_fir_transforms/src/return_unify/normalize/anf.rs +++ b/source/compiler/qsc_fir_transforms/src/return_unify/normalize/anf.rs @@ -529,7 +529,7 @@ fn check_operand_for_unsupported_lift( let operand = package.get_expr(operand_id); let temp_ty = Ty::Array(Box::new(operand.ty.clone())); if !is_type_defaultable(package, package_id, &temp_ty) { - rejected.push((format!("{}", operand.ty), operand.span)); + rejected.push((format!("{}", operand.ty), operand.span.span)); } } else { scan_operand_tree_for_unsupported_lifts(package, package_id, operand_id, rejected); @@ -887,7 +887,7 @@ fn anf_lift_scalar_assign_op( assigner, place_ty.clone(), place_expr.kind.clone(), - Span::default(), + package.synthetic_span(), ); let temp_name = format!("{}_{}", super::super::symbols::OPERAND_TEMP, old_value_temp); let (old_value_local, old_value_stmt) = alloc_local_var( @@ -903,7 +903,7 @@ fn anf_lift_scalar_assign_op( assigner, old_value_local, place_ty.clone(), - Span::default(), + package.synthetic_span(), ); let value = alloc_bin_op_expr( package, @@ -912,7 +912,7 @@ fn anf_lift_scalar_assign_op( old_value_read, lifted_rhs, place_ty, - Span::default(), + package.synthetic_span(), ); package.exprs.get_mut(expr_id).expect("expr not found").kind = ExprKind::Assign(place, value); prefix.insert(0, old_value_stmt); @@ -1075,8 +1075,13 @@ fn anf_lift_operand( operand_id, Mutability::Immutable, ); - let var_expr_id = - alloc_local_var_expr(package, assigner, local_id, operand_ty, Span::default()); + let var_expr_id = alloc_local_var_expr( + package, + assigner, + local_id, + operand_ty, + package.synthetic_span(), + ); replace_operand_slot(package, parent_id, operand_id, var_expr_id); generated_operand_reads.insert(var_expr_id); (local_stmt_id, var_expr_id) @@ -1100,8 +1105,13 @@ fn anf_lift_operand( init_id, Mutability::Immutable, ); - let array_var_id = - alloc_local_var_expr(package, assigner, local_id, array_ty, Span::default()); + let array_var_id = alloc_local_var_expr( + package, + assigner, + local_id, + array_ty, + package.synthetic_span(), + ); // Reading the element back through `[0]` leaves a compound `Index` in // the operand slot rather than a bare variable. This is a deliberate, // sound relaxation of strict ANF atomicity: the `[0]` read is pure, diff --git a/source/compiler/qsc_fir_transforms/src/return_unify/normalize/anf/tests/convergence.rs b/source/compiler/qsc_fir_transforms/src/return_unify/normalize/anf/tests/convergence.rs index c8d9b9507ff..b819bae3ee9 100644 --- a/source/compiler/qsc_fir_transforms/src/return_unify/normalize/anf/tests/convergence.rs +++ b/source/compiler/qsc_fir_transforms/src/return_unify/normalize/anf/tests/convergence.rs @@ -14,6 +14,7 @@ use qsc_fir::assigner::Assigner; use qsc_fir::fir::{ExprId, ExprKind, PackageLookup, StmtKind}; use crate::return_unify::Error; +use qsc_fir::fir::PackageSpan; #[test] fn anf_fixpoint_is_structurally_idempotent_after_nested_ancestor_lift() { @@ -404,7 +405,7 @@ fn projected_assign_op_place_trips_the_unhandled_shape_assertion() { &mut assigner, projection.ty, projection.kind, - qsc_data_structures::span::Span::default(), + PackageSpan::default(), ); let ExprKind::AssignOp(op, _, rhs) = package.get_expr(assign_op_id).kind.clone() else { diff --git a/source/compiler/qsc_fir_transforms/src/return_unify/normalize/anf/tests/invariant.rs b/source/compiler/qsc_fir_transforms/src/return_unify/normalize/anf/tests/invariant.rs index 9dd5c3ffe64..a036db004bb 100644 --- a/source/compiler/qsc_fir_transforms/src/return_unify/normalize/anf/tests/invariant.rs +++ b/source/compiler/qsc_fir_transforms/src/return_unify/normalize/anf/tests/invariant.rs @@ -18,7 +18,6 @@ //! residual-`Return` callable still receives a well-formed, non-empty rebuilt //! specialization exec graph. -use qsc_data_structures::span::Span; use qsc_fir::assigner::Assigner; use qsc_fir::fir::{ BlockId, CallableImpl, ExecGraphConfig, ExprKind, ItemKind, Mutability, Package, PackageId, @@ -36,6 +35,7 @@ use crate::test_utils::{assert_panics_with, compile_and_run_pipeline_to}; use super::*; use crate::return_unify::symbols; +use qsc_fir::fir::PackageSpan; /// Returns the body specialization block of the callable named `Main`. fn main_body_block(package: &Package) -> BlockId { @@ -99,16 +99,16 @@ fn flag_write_in_operand_position_trips_operand_position_invariant() { &mut assigner, symbols::HAS_RETURNED, Ty::Prim(Prim::Bool), - Span::default(), + PackageSpan::default(), ); - let false_lit = alloc_bool_lit(package, &mut assigner, false, Span::default()); + let false_lit = alloc_bool_lit(package, &mut assigner, false, PackageSpan::default()); let decl_stmt = alloc_local_stmt( package, &mut assigner, Mutability::Mutable, flag_pat, false_lit, - Span::default(), + PackageSpan::default(), ); // Write the flag from an operand position: the assign is the initializer of @@ -119,16 +119,22 @@ fn flag_write_in_operand_position_trips_operand_position_invariant() { &mut assigner, flag_id, Ty::Prim(Prim::Bool), - Span::default(), + PackageSpan::default(), + ); + let true_lit = alloc_bool_lit(package, &mut assigner, true, PackageSpan::default()); + let assign = alloc_assign_expr( + package, + &mut assigner, + flag_ref, + true_lit, + PackageSpan::default(), ); - let true_lit = alloc_bool_lit(package, &mut assigner, true, Span::default()); - let assign = alloc_assign_expr(package, &mut assigner, flag_ref, true_lit, Span::default()); let (_tmp_id, tmp_pat) = alloc_bind_pat( package, &mut assigner, symbols::OPERAND_TEMP, Ty::UNIT, - Span::default(), + PackageSpan::default(), ); let violation_stmt = alloc_local_stmt( package, @@ -136,7 +142,7 @@ fn flag_write_in_operand_position_trips_operand_position_invariant() { Mutability::Immutable, tmp_pat, assign, - Span::default(), + PackageSpan::default(), ); package diff --git a/source/compiler/qsc_fir_transforms/src/return_unify/simplify/bare_return.rs b/source/compiler/qsc_fir_transforms/src/return_unify/simplify/bare_return.rs index 113a788b832..89770034bcf 100644 --- a/source/compiler/qsc_fir_transforms/src/return_unify/simplify/bare_return.rs +++ b/source/compiler/qsc_fir_transforms/src/return_unify/simplify/bare_return.rs @@ -62,7 +62,6 @@ //! through its captures. The walker treats closures as opaque leaves via //! [`super::push_children`]. -use qsc_data_structures::span::Span; use qsc_fir::{ assigner::Assigner, fir::{BlockId, ExprId, ExprKind, LocalVarId, Package, PackageLookup, Res, StmtId, StmtKind}, @@ -154,7 +153,7 @@ fn try_apply_once( return false; } - let new_stmt = alloc_expr_stmt(package, assigner, v_id, Span::default()); + let new_stmt = alloc_expr_stmt(package, assigner, v_id, package.synthetic_span()); let block = package.blocks.get_mut(block_id).expect("block not found"); block.stmts.truncate(terminal_start_idx); block.stmts.push(new_stmt); diff --git a/source/compiler/qsc_fir_transforms/src/return_unify/simplify/both_branches.rs b/source/compiler/qsc_fir_transforms/src/return_unify/simplify/both_branches.rs index 408ea5922be..c0b554ab4b4 100644 --- a/source/compiler/qsc_fir_transforms/src/return_unify/simplify/both_branches.rs +++ b/source/compiler/qsc_fir_transforms/src/return_unify/simplify/both_branches.rs @@ -53,7 +53,6 @@ //! [`super::expr_tree_contains_qubit_type`] walker. Typed Q# cannot //! return qubits, so this almost never fires. -use qsc_data_structures::span::Span; use qsc_fir::{ assigner::Assigner, fir::{BlockId, ExprId, ExprKind, Package, PackageLookup, StmtId, StmtKind}, @@ -124,7 +123,7 @@ fn try_apply_once( } let new_if = build_replacement_if(package, assigner, cond_id, v1_id, v2_id, &block_ty); - let new_stmt = alloc_expr_stmt(package, assigner, new_if, Span::default()); + let new_stmt = alloc_expr_stmt(package, assigner, new_if, package.synthetic_span()); let block = package.blocks.get_mut(block_id).expect("block not found"); block.stmts.truncate(guard_idx); @@ -169,36 +168,36 @@ fn build_replacement_if( v2_id: ExprId, block_ty: &Ty, ) -> ExprId { - let v1_stmt = alloc_expr_stmt(package, assigner, v1_id, Span::default()); + let v1_stmt = alloc_expr_stmt(package, assigner, v1_id, package.synthetic_span()); let then_bid = alloc_block( package, assigner, vec![v1_stmt], block_ty.clone(), - Span::default(), + package.synthetic_span(), ); let then_expr = alloc_block_expr( package, assigner, then_bid, block_ty.clone(), - Span::default(), + package.synthetic_span(), ); - let v2_stmt = alloc_expr_stmt(package, assigner, v2_id, Span::default()); + let v2_stmt = alloc_expr_stmt(package, assigner, v2_id, package.synthetic_span()); let else_bid = alloc_block( package, assigner, vec![v2_stmt], block_ty.clone(), - Span::default(), + package.synthetic_span(), ); let else_expr = alloc_block_expr( package, assigner, else_bid, block_ty.clone(), - Span::default(), + package.synthetic_span(), ); alloc_if_expr( @@ -208,6 +207,6 @@ fn build_replacement_if( then_expr, Some(else_expr), block_ty.clone(), - Span::default(), + package.synthetic_span(), ) } diff --git a/source/compiler/qsc_fir_transforms/src/return_unify/simplify/guard_clause.rs b/source/compiler/qsc_fir_transforms/src/return_unify/simplify/guard_clause.rs index c1c8b8d1ef4..ca60f53212b 100644 --- a/source/compiler/qsc_fir_transforms/src/return_unify/simplify/guard_clause.rs +++ b/source/compiler/qsc_fir_transforms/src/return_unify/simplify/guard_clause.rs @@ -35,7 +35,6 @@ //! The guard-set and lazy continuation must then reference exactly those //! locals, or the rule refuses to fire. -use qsc_data_structures::span::Span; use qsc_fir::{ assigner::Assigner, fir::{BlockId, ExprId, ExprKind, LocalVarId, Package, PackageLookup, StmtId, StmtKind, UnOp}, @@ -104,7 +103,7 @@ fn try_apply_once( return_slot, &block_ty, ) { - let not_cond = alloc_not_expr(package, assigner, cond, Span::default()); + let not_cond = alloc_not_expr(package, assigner, cond, package.synthetic_span()); (not_cond, v) } else { return false; @@ -116,27 +115,27 @@ fn try_apply_once( }; // Build the replacement: `if c { v } else { rest_block }`. - let v_stmt = alloc_expr_stmt(package, assigner, v_id, Span::default()); + let v_stmt = alloc_expr_stmt(package, assigner, v_id, package.synthetic_span()); let then_bid = alloc_block( package, assigner, vec![v_stmt], block_ty.clone(), - Span::default(), + package.synthetic_span(), ); let then_expr = alloc_block_expr( package, assigner, then_bid, block_ty.clone(), - Span::default(), + package.synthetic_span(), ); let else_expr = alloc_block_expr( package, assigner, rest_block_id, block_ty.clone(), - Span::default(), + package.synthetic_span(), ); let new_if = alloc_if_expr( package, @@ -145,9 +144,9 @@ fn try_apply_once( then_expr, Some(else_expr), block_ty.clone(), - Span::default(), + package.synthetic_span(), ); - let new_stmt = alloc_expr_stmt(package, assigner, new_if, Span::default()); + let new_stmt = alloc_expr_stmt(package, assigner, new_if, package.synthetic_span()); let block = package.blocks.get_mut(block_id).expect("block not found"); block.stmts.truncate(guard_idx); diff --git a/source/compiler/qsc_fir_transforms/src/return_unify/simplify/single_branch.rs b/source/compiler/qsc_fir_transforms/src/return_unify/simplify/single_branch.rs index 7009a79955b..5d55d574dc7 100644 --- a/source/compiler/qsc_fir_transforms/src/return_unify/simplify/single_branch.rs +++ b/source/compiler/qsc_fir_transforms/src/return_unify/simplify/single_branch.rs @@ -51,7 +51,6 @@ //! a sub-expression whose type contains [`qsc_fir::ty::Prim::Qubit`], //! matching the conservative policy of [`super::both_branches`]. -use qsc_data_structures::span::Span; use qsc_fir::{ assigner::Assigner, fir::{BlockId, ExprId, ExprKind, LocalVarId, Package, PackageLookup, PatKind, StmtKind}, @@ -151,9 +150,9 @@ fn try_apply_once( then_id, Some(else_arm), block_ty, - Span::default(), + package.synthetic_span(), ); - let new_stmt = alloc_expr_stmt(package, assigner, new_if, Span::default()); + let new_stmt = alloc_expr_stmt(package, assigner, new_if, package.synthetic_span()); let block = package.blocks.get_mut(block_id).expect("block not found"); block.stmts.truncate(let_idx); block.stmts.push(new_stmt); @@ -178,9 +177,9 @@ fn try_apply_once( then_arm, Some(else_id), block_ty, - Span::default(), + package.synthetic_span(), ); - let new_stmt = alloc_expr_stmt(package, assigner, new_if, Span::default()); + let new_stmt = alloc_expr_stmt(package, assigner, new_if, package.synthetic_span()); let block = package.blocks.get_mut(block_id).expect("block not found"); block.stmts.truncate(let_idx); block.stmts.push(new_stmt); @@ -200,15 +199,21 @@ fn wrap_in_block_expr( expr_id: qsc_fir::fir::ExprId, block_ty: &qsc_fir::ty::Ty, ) -> qsc_fir::fir::ExprId { - let stmt = alloc_expr_stmt(package, assigner, expr_id, Span::default()); + let stmt = alloc_expr_stmt(package, assigner, expr_id, package.synthetic_span()); let bid = alloc_block( package, assigner, vec![stmt], block_ty.clone(), - Span::default(), + package.synthetic_span(), ); - alloc_block_expr(package, assigner, bid, block_ty.clone(), Span::default()) + alloc_block_expr( + package, + assigner, + bid, + block_ty.clone(), + package.synthetic_span(), + ) } /// Returns `true` when `arm_expr_id` contains any assignment whose LHS diff --git a/source/compiler/qsc_fir_transforms/src/return_unify/simplify/tests/bare_return.rs b/source/compiler/qsc_fir_transforms/src/return_unify/simplify/tests/bare_return.rs index 807ede70ed7..8e1a53ec4e6 100644 --- a/source/compiler/qsc_fir_transforms/src/return_unify/simplify/tests/bare_return.rs +++ b/source/compiler/qsc_fir_transforms/src/return_unify/simplify/tests/bare_return.rs @@ -41,7 +41,6 @@ use expect_test::expect; use indoc::indoc; -use qsc_data_structures::span::Span; use qsc_fir::{ assigner::Assigner, fir::{ExprId, ExprKind, Lit, LocalVarId, Package, PackageLookup, StmtId, StmtKind}, @@ -54,6 +53,7 @@ use crate::fir_builder::{ }; use crate::return_unify::simplify::bare_return; use crate::return_unify::tests::check_simplify_rule_q; +use qsc_fir::fir::PackageSpan; /// Slot identities shared by every test fixture. struct Slots { @@ -84,29 +84,29 @@ fn build_merge_stmt( assigner, slots.has_returned, Ty::Prim(Prim::Bool), - Span::default(), + PackageSpan::default(), ); let then_var = alloc_local_var_expr( package, assigner, slots.ret_val, return_ty.clone(), - Span::default(), + PackageSpan::default(), ); - let then_stmt = alloc_expr_stmt(package, assigner, then_var, Span::default()); + let then_stmt = alloc_expr_stmt(package, assigner, then_var, PackageSpan::default()); let then_bid = alloc_block( package, assigner, vec![then_stmt], return_ty.clone(), - Span::default(), + PackageSpan::default(), ); let then_expr = alloc_block_expr( package, assigner, then_bid, return_ty.clone(), - Span::default(), + PackageSpan::default(), ); let merge = alloc_if_expr( package, @@ -115,9 +115,9 @@ fn build_merge_stmt( then_expr, Some(fallthrough), return_ty.clone(), - Span::default(), + PackageSpan::default(), ); - alloc_expr_stmt(package, assigner, merge, Span::default()) + alloc_expr_stmt(package, assigner, merge, PackageSpan::default()) } /// Build a `__ret_val = v;` Semi statement. @@ -133,10 +133,10 @@ fn build_slot_assign_stmt( assigner, slots.ret_val, return_ty.clone(), - Span::default(), + PackageSpan::default(), ); - let assign = alloc_assign_expr(package, assigner, lhs, v_id, Span::default()); - alloc_semi_stmt(package, assigner, assign, Span::default()) + let assign = alloc_assign_expr(package, assigner, lhs, v_id, PackageSpan::default()); + alloc_semi_stmt(package, assigner, assign, PackageSpan::default()) } /// Build a `__has_returned = true;` Semi statement. @@ -147,11 +147,11 @@ fn build_flag_set_stmt(package: &mut Package, assigner: &mut Assigner, slots: &S assigner, slots.has_returned, bool_ty.clone(), - Span::default(), + PackageSpan::default(), ); - let rhs = alloc_bool_lit(package, assigner, true, Span::default()); - let assign = alloc_assign_expr(package, assigner, lhs, rhs, Span::default()); - alloc_semi_stmt(package, assigner, assign, Span::default()) + let rhs = alloc_bool_lit(package, assigner, true, PackageSpan::default()); + let assign = alloc_assign_expr(package, assigner, lhs, rhs, PackageSpan::default()); + alloc_semi_stmt(package, assigner, assign, PackageSpan::default()) } /// Build the nested-block terminal pair @@ -170,10 +170,16 @@ fn build_nested_pair_stmt( assigner, vec![slot_stmt, flag_stmt], Ty::UNIT, - Span::default(), + PackageSpan::default(), ); - let inner_expr = alloc_block_expr(package, assigner, inner_bid, Ty::UNIT, Span::default()); - alloc_semi_stmt(package, assigner, inner_expr, Span::default()) + let inner_expr = alloc_block_expr( + package, + assigner, + inner_bid, + Ty::UNIT, + PackageSpan::default(), + ); + alloc_semi_stmt(package, assigner, inner_expr, PackageSpan::default()) } /// Build an arbitrary `__ret_val` fallthrough expression of the given @@ -191,7 +197,7 @@ fn build_fallthrough( assigner, slots.ret_val, return_ty.clone(), - Span::default(), + PackageSpan::default(), ) } @@ -319,7 +325,7 @@ fn flat_two_semi_pair_collapses() { &mut assigner, int_ty.clone(), ExprKind::Lit(Lit::Int(7)), - Span::default(), + PackageSpan::default(), ); let slot_stmt = build_slot_assign_stmt(&mut package, &mut assigner, &slots, v_id, &int_ty); let flag_stmt = build_flag_set_stmt(&mut package, &mut assigner, &slots); @@ -330,7 +336,7 @@ fn flat_two_semi_pair_collapses() { &mut assigner, vec![slot_stmt, flag_stmt, merge_stmt], int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let synth_slots = crate::return_unify::tests::synth_slots_for_block(&package, block_id); @@ -371,16 +377,21 @@ fn pre_stmt_reads_flag_refuses_to_fold() { &mut assigner, slots.has_returned, bool_ty.clone(), - Span::default(), + PackageSpan::default(), + ); + let pre_stmt = alloc_semi_stmt( + &mut package, + &mut assigner, + flag_read, + PackageSpan::default(), ); - let pre_stmt = alloc_semi_stmt(&mut package, &mut assigner, flag_read, Span::default()); let v_id = alloc_expr( &mut package, &mut assigner, int_ty.clone(), ExprKind::Lit(Lit::Int(1)), - Span::default(), + PackageSpan::default(), ); let pair_stmt = build_nested_pair_stmt(&mut package, &mut assigner, &slots, v_id, &int_ty); let fallthrough = build_fallthrough(&mut package, &mut assigner, &slots, &int_ty); @@ -390,7 +401,7 @@ fn pre_stmt_reads_flag_refuses_to_fold() { &mut assigner, vec![pre_stmt, pair_stmt, merge_stmt], int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let before = package.get_block(block_id).stmts.clone(); @@ -426,7 +437,7 @@ fn missing_flag_set_refuses_to_fold() { &mut assigner, int_ty.clone(), ExprKind::Lit(Lit::Int(1)), - Span::default(), + PackageSpan::default(), ); let slot_stmt = build_slot_assign_stmt(&mut package, &mut assigner, &slots, v_id, &int_ty); // Wrap just the slot assign in a Unit block to mimic the @@ -436,17 +447,21 @@ fn missing_flag_set_refuses_to_fold() { &mut assigner, vec![slot_stmt], Ty::UNIT, - Span::default(), + PackageSpan::default(), ); let inner_expr = alloc_block_expr( &mut package, &mut assigner, inner_bid, Ty::UNIT, - Span::default(), + PackageSpan::default(), + ); + let broken_pair_stmt = alloc_semi_stmt( + &mut package, + &mut assigner, + inner_expr, + PackageSpan::default(), ); - let broken_pair_stmt = - alloc_semi_stmt(&mut package, &mut assigner, inner_expr, Span::default()); let fallthrough = build_fallthrough(&mut package, &mut assigner, &slots, &int_ty); let merge_stmt = build_merge_stmt(&mut package, &mut assigner, &slots, fallthrough, &int_ty); let block_id = alloc_block( @@ -454,7 +469,7 @@ fn missing_flag_set_refuses_to_fold() { &mut assigner, vec![broken_pair_stmt, merge_stmt], int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let before = package.get_block(block_id).stmts.clone(); @@ -515,36 +530,36 @@ fn build_single_body_merge_stmt( assigner, slots.has_returned, Ty::Prim(Prim::Bool), - Span::default(), + PackageSpan::default(), ); let then_var = alloc_local_var_expr( package, assigner, slots.ret_val, return_ty.clone(), - Span::default(), + PackageSpan::default(), ); - let then_stmt = alloc_expr_stmt(package, assigner, then_var, Span::default()); + let then_stmt = alloc_expr_stmt(package, assigner, then_var, PackageSpan::default()); let then_bid = alloc_block( package, assigner, vec![then_stmt], return_ty.clone(), - Span::default(), + PackageSpan::default(), ); let then_expr = alloc_block_expr( package, assigner, then_bid, return_ty.clone(), - Span::default(), + PackageSpan::default(), ); let else_default = alloc_expr( package, assigner, return_ty.clone(), ExprKind::Lit(Lit::Int(0)), - Span::default(), + PackageSpan::default(), ); let merge = alloc_if_expr( package, @@ -553,9 +568,9 @@ fn build_single_body_merge_stmt( then_expr, Some(else_default), return_ty.clone(), - Span::default(), + PackageSpan::default(), ); - alloc_expr_stmt(package, assigner, merge, Span::default()) + alloc_expr_stmt(package, assigner, merge, PackageSpan::default()) } #[test] @@ -679,30 +694,35 @@ fn given_else_arm_writes_slot_with_aliased_lhs_bare_return_does_not_collapse() { &mut assigner, int_ty.clone(), ExprKind::Lit(Lit::Int(99)), - Span::default(), + PackageSpan::default(), ); let bad_lhs = alloc_local_var_expr( &mut package, &mut assigner, slots.ret_val, int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let bad_assign = alloc_assign_expr( &mut package, &mut assigner, bad_lhs, bad_rhs, - Span::default(), + PackageSpan::default(), + ); + let bad_stmt = alloc_semi_stmt( + &mut package, + &mut assigner, + bad_assign, + PackageSpan::default(), ); - let bad_stmt = alloc_semi_stmt(&mut package, &mut assigner, bad_assign, Span::default()); let v_id = alloc_expr( &mut package, &mut assigner, int_ty.clone(), ExprKind::Lit(Lit::Int(17)), - Span::default(), + PackageSpan::default(), ); let pair_stmt = build_nested_pair_stmt(&mut package, &mut assigner, &slots, v_id, &int_ty); let merge_stmt = build_single_body_merge_stmt(&mut package, &mut assigner, &slots, &int_ty); @@ -711,7 +731,7 @@ fn given_else_arm_writes_slot_with_aliased_lhs_bare_return_does_not_collapse() { &mut assigner, vec![bad_stmt, pair_stmt, merge_stmt], int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let before = package.get_block(block_id).stmts.clone(); @@ -749,7 +769,7 @@ fn given_else_arm_lacks_set_pair_bare_return_does_not_collapse() { &mut assigner, int_ty.clone(), ExprKind::Lit(Lit::Int(17)), - Span::default(), + PackageSpan::default(), ); // Build the slot/flag set pair, then prepend a stray Semi-Unit // stmt so the inner block is 3 stmts instead of 2. @@ -760,25 +780,34 @@ fn given_else_arm_lacks_set_pair_bare_return_does_not_collapse() { &mut assigner, Ty::UNIT, ExprKind::Tuple(Vec::new()), - Span::default(), + PackageSpan::default(), + ); + let stray_stmt = alloc_semi_stmt( + &mut package, + &mut assigner, + stray_unit, + PackageSpan::default(), ); - let stray_stmt = alloc_semi_stmt(&mut package, &mut assigner, stray_unit, Span::default()); let inner_bid = alloc_block( &mut package, &mut assigner, vec![stray_stmt, slot_stmt, flag_stmt], Ty::UNIT, - Span::default(), + PackageSpan::default(), ); let inner_expr = alloc_block_expr( &mut package, &mut assigner, inner_bid, Ty::UNIT, - Span::default(), + PackageSpan::default(), + ); + let broken_pair_stmt = alloc_semi_stmt( + &mut package, + &mut assigner, + inner_expr, + PackageSpan::default(), ); - let broken_pair_stmt = - alloc_semi_stmt(&mut package, &mut assigner, inner_expr, Span::default()); let merge_stmt = build_single_body_merge_stmt(&mut package, &mut assigner, &slots, &int_ty); let block_id = alloc_block( @@ -786,7 +815,7 @@ fn given_else_arm_lacks_set_pair_bare_return_does_not_collapse() { &mut assigner, vec![broken_pair_stmt, merge_stmt], int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let before = package.get_block(block_id).stmts.clone(); @@ -829,36 +858,41 @@ fn given_then_arm_not_var_ret_val_bare_return_does_not_collapse() { &mut assigner, slots.has_returned, Ty::Prim(Prim::Bool), - Span::default(), + PackageSpan::default(), ); let then_var = alloc_local_var_expr( &mut package, &mut assigner, decoy_local, int_ty.clone(), - Span::default(), + PackageSpan::default(), + ); + let then_stmt = alloc_expr_stmt( + &mut package, + &mut assigner, + then_var, + PackageSpan::default(), ); - let then_stmt = alloc_expr_stmt(&mut package, &mut assigner, then_var, Span::default()); let then_bid = alloc_block( &mut package, &mut assigner, vec![then_stmt], int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let then_expr = alloc_block_expr( &mut package, &mut assigner, then_bid, int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let else_default = alloc_expr( &mut package, &mut assigner, int_ty.clone(), ExprKind::Lit(Lit::Int(0)), - Span::default(), + PackageSpan::default(), ); let merge = alloc_if_expr( &mut package, @@ -867,16 +901,16 @@ fn given_then_arm_not_var_ret_val_bare_return_does_not_collapse() { then_expr, Some(else_default), int_ty.clone(), - Span::default(), + PackageSpan::default(), ); - let merge_stmt = alloc_expr_stmt(&mut package, &mut assigner, merge, Span::default()); + let merge_stmt = alloc_expr_stmt(&mut package, &mut assigner, merge, PackageSpan::default()); let v_id = alloc_expr( &mut package, &mut assigner, int_ty.clone(), ExprKind::Lit(Lit::Int(17)), - Span::default(), + PackageSpan::default(), ); let pair_stmt = build_nested_pair_stmt(&mut package, &mut assigner, &slots, v_id, &int_ty); let block_id = alloc_block( @@ -884,7 +918,7 @@ fn given_then_arm_not_var_ret_val_bare_return_does_not_collapse() { &mut assigner, vec![pair_stmt, merge_stmt], int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let before = package.get_block(block_id).stmts.clone(); diff --git a/source/compiler/qsc_fir_transforms/src/return_unify/simplify/tests/both_branches.rs b/source/compiler/qsc_fir_transforms/src/return_unify/simplify/tests/both_branches.rs index 0a740808b79..e54ec0567eb 100644 --- a/source/compiler/qsc_fir_transforms/src/return_unify/simplify/tests/both_branches.rs +++ b/source/compiler/qsc_fir_transforms/src/return_unify/simplify/tests/both_branches.rs @@ -31,6 +31,7 @@ use indoc::indoc; use crate::return_unify::simplify::both_branches; use crate::return_unify::tests::check_simplify_rule_q; +use qsc_fir::fir::PackageSpan; #[test] fn simple_both_branches_collapses_to_if_else() { @@ -369,7 +370,7 @@ fn qubit_typed_rhs_refuses_to_collapse() { alloc_assign_expr, alloc_block, alloc_block_expr, alloc_bool_lit, alloc_expr, alloc_expr_stmt, alloc_if_expr, alloc_semi_stmt, }; - use qsc_data_structures::span::Span; + use qsc_fir::{ assigner::Assigner, fir::{ExprKind, LocalVarId, Package, Res}, @@ -396,7 +397,7 @@ fn qubit_typed_rhs_refuses_to_collapse() { asn, ty, ExprKind::Var(Res::Local(id), Vec::new()), - Span::default(), + PackageSpan::default(), ) }; @@ -411,43 +412,43 @@ fn qubit_typed_rhs_refuses_to_collapse() { asn, return_ty.clone(), ExprKind::Var(Res::Local(slot_local), Vec::new()), - Span::default(), + PackageSpan::default(), ); let slot_rhs = alloc_expr( pkg, asn, return_ty.clone(), ExprKind::Var(Res::Local(qubit_local), Vec::new()), - Span::default(), + PackageSpan::default(), ); - let slot_assign = alloc_assign_expr(pkg, asn, slot_lhs, slot_rhs, Span::default()); - let slot_stmt = alloc_semi_stmt(pkg, asn, slot_assign, Span::default()); + let slot_assign = alloc_assign_expr(pkg, asn, slot_lhs, slot_rhs, PackageSpan::default()); + let slot_stmt = alloc_semi_stmt(pkg, asn, slot_assign, PackageSpan::default()); let flag_lhs = alloc_expr( pkg, asn, bool_ty.clone(), ExprKind::Var(Res::Local(flag_local), Vec::new()), - Span::default(), + PackageSpan::default(), ); - let flag_rhs = alloc_bool_lit(pkg, asn, true, Span::default()); - let flag_assign = alloc_assign_expr(pkg, asn, flag_lhs, flag_rhs, Span::default()); - let flag_stmt = alloc_semi_stmt(pkg, asn, flag_assign, Span::default()); + let flag_rhs = alloc_bool_lit(pkg, asn, true, PackageSpan::default()); + let flag_assign = alloc_assign_expr(pkg, asn, flag_lhs, flag_rhs, PackageSpan::default()); + let flag_stmt = alloc_semi_stmt(pkg, asn, flag_assign, PackageSpan::default()); let arm_bid = alloc_block( pkg, asn, vec![slot_stmt, flag_stmt], Ty::UNIT, - Span::default(), + PackageSpan::default(), ); - alloc_block_expr(pkg, asn, arm_bid, Ty::UNIT, Span::default()) + alloc_block_expr(pkg, asn, arm_bid, Ty::UNIT, PackageSpan::default()) }; let then_arm = mk_arm(&mut package, &mut assigner); let else_arm = mk_arm(&mut package, &mut assigner); - let cond = alloc_bool_lit(&mut package, &mut assigner, true, Span::default()); + let cond = alloc_bool_lit(&mut package, &mut assigner, true, PackageSpan::default()); let outer_if = alloc_if_expr( &mut package, &mut assigner, @@ -455,45 +456,58 @@ fn qubit_typed_rhs_refuses_to_collapse() { then_arm, Some(else_arm), Ty::UNIT, - Span::default(), + PackageSpan::default(), + ); + let guard_set_stmt = alloc_semi_stmt( + &mut package, + &mut assigner, + outer_if, + PackageSpan::default(), ); - let guard_set_stmt = alloc_semi_stmt(&mut package, &mut assigner, outer_if, Span::default()); // Build the merge `if __has_returned { __ret_val } else { __ret_val }`. let merge_cond = make_var(&mut package, &mut assigner, flag_local, bool_ty.clone()); let then_slot_var = make_var(&mut package, &mut assigner, slot_local, return_ty.clone()); - let then_slot_stmt = - alloc_expr_stmt(&mut package, &mut assigner, then_slot_var, Span::default()); + let then_slot_stmt = alloc_expr_stmt( + &mut package, + &mut assigner, + then_slot_var, + PackageSpan::default(), + ); let then_blk = alloc_block( &mut package, &mut assigner, vec![then_slot_stmt], return_ty.clone(), - Span::default(), + PackageSpan::default(), ); let then_blk_expr = alloc_block_expr( &mut package, &mut assigner, then_blk, return_ty.clone(), - Span::default(), + PackageSpan::default(), ); let else_slot_var = make_var(&mut package, &mut assigner, slot_local, return_ty.clone()); - let else_blk_stmt = - alloc_expr_stmt(&mut package, &mut assigner, else_slot_var, Span::default()); + let else_blk_stmt = alloc_expr_stmt( + &mut package, + &mut assigner, + else_slot_var, + PackageSpan::default(), + ); let else_blk = alloc_block( &mut package, &mut assigner, vec![else_blk_stmt], return_ty.clone(), - Span::default(), + PackageSpan::default(), ); let else_blk_expr = alloc_block_expr( &mut package, &mut assigner, else_blk, return_ty.clone(), - Span::default(), + PackageSpan::default(), ); let merge_if = alloc_if_expr( &mut package, @@ -502,16 +516,21 @@ fn qubit_typed_rhs_refuses_to_collapse() { then_blk_expr, Some(else_blk_expr), return_ty.clone(), - Span::default(), + PackageSpan::default(), + ); + let merge_stmt = alloc_expr_stmt( + &mut package, + &mut assigner, + merge_if, + PackageSpan::default(), ); - let merge_stmt = alloc_expr_stmt(&mut package, &mut assigner, merge_if, Span::default()); let outer_bid = alloc_block( &mut package, &mut assigner, vec![guard_set_stmt, merge_stmt], return_ty.clone(), - Span::default(), + PackageSpan::default(), ); // Snapshot the block contents before applying the rule. diff --git a/source/compiler/qsc_fir_transforms/src/return_unify/simplify/tests/dead_flag.rs b/source/compiler/qsc_fir_transforms/src/return_unify/simplify/tests/dead_flag.rs index da2957c4060..69e4c9cbef4 100644 --- a/source/compiler/qsc_fir_transforms/src/return_unify/simplify/tests/dead_flag.rs +++ b/source/compiler/qsc_fir_transforms/src/return_unify/simplify/tests/dead_flag.rs @@ -57,7 +57,6 @@ //! of captures, leaving setters live whenever the user happened to //! bind a closure later in the block. -use qsc_data_structures::span::Span; use qsc_fir::{ assigner::Assigner, fir::{BlockId, ExprKind, Lit, LocalVarId, Mutability, Package, PackageLookup, Res, StmtKind}, @@ -70,6 +69,7 @@ use crate::fir_builder::{ }; use crate::return_unify::simplify::dead_flag; use crate::return_unify::symbols; +use qsc_fir::fir::PackageSpan; /// Allocate a `mutable __has_returned : Bool = false;` binding and /// return the local id plus its declaration statement. @@ -77,7 +77,7 @@ fn alloc_has_returned_binding( package: &mut Package, assigner: &mut Assigner, ) -> (LocalVarId, qsc_fir::fir::StmtId) { - let init = alloc_bool_lit(package, assigner, false, Span::default()); + let init = alloc_bool_lit(package, assigner, false, PackageSpan::default()); alloc_local_var( package, assigner, @@ -99,11 +99,11 @@ fn build_flag_set_stmt( assigner, flag_id, Ty::Prim(Prim::Bool), - Span::default(), + PackageSpan::default(), ); - let rhs = alloc_bool_lit(package, assigner, true, Span::default()); - let assign = alloc_assign_expr(package, assigner, lhs, rhs, Span::default()); - alloc_semi_stmt(package, assigner, assign, Span::default()) + let rhs = alloc_bool_lit(package, assigner, true, PackageSpan::default()); + let assign = alloc_assign_expr(package, assigner, lhs, rhs, PackageSpan::default()); + alloc_semi_stmt(package, assigner, assign, PackageSpan::default()) } /// Build a trailing `Expr(Int)` literal statement of the given value. @@ -117,9 +117,9 @@ fn build_trailing_int( assigner, Ty::Prim(Prim::Int), ExprKind::Lit(Lit::Int(value)), - Span::default(), + PackageSpan::default(), ); - alloc_expr_stmt(package, assigner, lit, Span::default()) + alloc_expr_stmt(package, assigner, lit, PackageSpan::default()) } /// Count the number of flag-set statements (`Semi(Assign(Var(flag), _))`) @@ -164,7 +164,7 @@ fn single_dead_setter_is_dropped() { &mut assigner, vec![decl_stmt, set_stmt, tail_stmt], Ty::Prim(Prim::Int), - Span::default(), + PackageSpan::default(), ); let synth_slots = crate::return_unify::tests::synth_slots_for_block(&package, block_id); @@ -218,7 +218,7 @@ fn multiple_dead_setters_are_all_dropped() { &mut assigner, vec![decl_stmt, set_a, set_b, set_c, tail_stmt], Ty::Prim(Prim::Int), - Span::default(), + PackageSpan::default(), ); let synth_slots = crate::return_unify::tests::synth_slots_for_block(&package, block_id); @@ -267,7 +267,7 @@ fn dead_setter_with_nested_block_downstream_is_dropped() { &mut assigner, int_ty.clone(), ExprKind::Lit(Lit::Int(1)), - Span::default(), + PackageSpan::default(), ); let (_unrelated_local, unrelated_decl) = alloc_local_var( &mut package, @@ -282,33 +282,33 @@ fn dead_setter_with_nested_block_downstream_is_dropped() { &mut assigner, int_ty.clone(), ExprKind::Lit(Lit::Int(2)), - Span::default(), + PackageSpan::default(), ); let inner_tail_stmt = alloc_expr_stmt( &mut package, &mut assigner, inner_tail_value, - Span::default(), + PackageSpan::default(), ); let inner_bid = alloc_block( &mut package, &mut assigner, vec![unrelated_decl, inner_tail_stmt], int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let inner_block_expr = alloc_block_expr( &mut package, &mut assigner, inner_bid, int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let inner_block_stmt = alloc_semi_stmt( &mut package, &mut assigner, inner_block_expr, - Span::default(), + PackageSpan::default(), ); let tail_stmt = build_trailing_int(&mut package, &mut assigner, 3); @@ -317,7 +317,7 @@ fn dead_setter_with_nested_block_downstream_is_dropped() { &mut assigner, vec![decl_stmt, set_stmt, inner_block_stmt, tail_stmt], int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let synth_slots = crate::return_unify::tests::synth_slots_for_block(&package, block_id); @@ -364,7 +364,7 @@ fn surviving_trailing_merge_blocks_the_drop() { &mut assigner, int_ty.clone(), ExprKind::Lit(Lit::Int(0)), - Span::default(), + PackageSpan::default(), ); let (ret_local, ret_decl) = alloc_local_var( &mut package, @@ -383,36 +383,41 @@ fn surviving_trailing_merge_blocks_the_drop() { &mut assigner, flag_id, bool_ty.clone(), - Span::default(), + PackageSpan::default(), ); let then_var = alloc_local_var_expr( &mut package, &mut assigner, ret_local, int_ty.clone(), - Span::default(), + PackageSpan::default(), + ); + let then_stmt = alloc_expr_stmt( + &mut package, + &mut assigner, + then_var, + PackageSpan::default(), ); - let then_stmt = alloc_expr_stmt(&mut package, &mut assigner, then_var, Span::default()); let then_bid = alloc_block( &mut package, &mut assigner, vec![then_stmt], int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let then_expr = alloc_block_expr( &mut package, &mut assigner, then_bid, int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let else_arm = alloc_expr( &mut package, &mut assigner, int_ty.clone(), ExprKind::Lit(Lit::Int(0)), - Span::default(), + PackageSpan::default(), ); let merge = alloc_if_expr( &mut package, @@ -421,16 +426,16 @@ fn surviving_trailing_merge_blocks_the_drop() { then_expr, Some(else_arm), int_ty.clone(), - Span::default(), + PackageSpan::default(), ); - let merge_stmt = alloc_expr_stmt(&mut package, &mut assigner, merge, Span::default()); + let merge_stmt = alloc_expr_stmt(&mut package, &mut assigner, merge, PackageSpan::default()); let block_id = alloc_block( &mut package, &mut assigner, vec![decl_stmt, ret_decl, set_stmt, merge_stmt], int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let before = package.get_block(block_id).stmts.clone(); @@ -474,7 +479,7 @@ fn downstream_closure_does_not_block_drop() { &mut assigner, Ty::Err, ExprKind::Closure(Vec::new(), item_id), - Span::default(), + PackageSpan::default(), ); let (_f_local, f_decl) = alloc_local_var( &mut package, @@ -489,28 +494,33 @@ fn downstream_closure_does_not_block_drop() { &mut assigner, int_ty.clone(), ExprKind::Lit(Lit::Int(5)), - Span::default(), + PackageSpan::default(), + ); + let inner_tail_stmt = alloc_expr_stmt( + &mut package, + &mut assigner, + inner_tail, + PackageSpan::default(), ); - let inner_tail_stmt = alloc_expr_stmt(&mut package, &mut assigner, inner_tail, Span::default()); let inner_bid = alloc_block( &mut package, &mut assigner, vec![f_decl, inner_tail_stmt], int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let inner_block_expr = alloc_block_expr( &mut package, &mut assigner, inner_bid, int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let inner_block_stmt = alloc_semi_stmt( &mut package, &mut assigner, inner_block_expr, - Span::default(), + PackageSpan::default(), ); let tail_stmt = build_trailing_int(&mut package, &mut assigner, 7); @@ -519,7 +529,7 @@ fn downstream_closure_does_not_block_drop() { &mut assigner, vec![decl_stmt, set_stmt, inner_block_stmt, tail_stmt], int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let synth_slots = crate::return_unify::tests::synth_slots_for_block(&package, block_id); diff --git a/source/compiler/qsc_fir_transforms/src/return_unify/simplify/tests/dead_local.rs b/source/compiler/qsc_fir_transforms/src/return_unify/simplify/tests/dead_local.rs index 8d4ba8037fe..7ef6a1990ba 100644 --- a/source/compiler/qsc_fir_transforms/src/return_unify/simplify/tests/dead_local.rs +++ b/source/compiler/qsc_fir_transforms/src/return_unify/simplify/tests/dead_local.rs @@ -45,7 +45,6 @@ use expect_test::expect; use indoc::indoc; -use qsc_data_structures::span::Span; use qsc_fir::{ assigner::Assigner, fir::{ @@ -60,6 +59,7 @@ use crate::fir_builder::{ }; use crate::return_unify::simplify::dead_local::{self, eligible_local_binding}; use crate::return_unify::tests::check_simplify_rule_q; +use qsc_fir::fir::PackageSpan; /// Allocate an `Int` literal `ExprId`. fn int_lit(package: &mut Package, assigner: &mut Assigner, value: i64) -> qsc_fir::fir::ExprId { @@ -68,14 +68,14 @@ fn int_lit(package: &mut Package, assigner: &mut Assigner, value: i64) -> qsc_fi assigner, Ty::Prim(Prim::Int), ExprKind::Lit(Lit::Int(value)), - Span::default(), + PackageSpan::default(), ) } /// Allocate a trailing `Expr(Int)` literal statement. fn trailing_int(package: &mut Package, assigner: &mut Assigner, value: i64) -> StmtId { let lit = int_lit(package, assigner, value); - alloc_expr_stmt(package, assigner, lit, Span::default()) + alloc_expr_stmt(package, assigner, lit, PackageSpan::default()) } #[test] @@ -184,7 +184,7 @@ fn given_preserved_local_with_default_init_dead_local_drops_binding() { &mut assigner, vec![decl, tail], Ty::Prim(Prim::Int), - Span::default(), + PackageSpan::default(), ); let fired = dead_local::apply(&mut package, &mut assigner, PackageId::CORE, block); @@ -410,9 +410,14 @@ fn given_local_used_in_closure_capture_dead_local_does_not_drop() { &mut assigner, closure_ty, ExprKind::Closure(vec![x_local], LocalItemId::from(0)), - Span::default(), + PackageSpan::default(), + ); + let semi = alloc_semi_stmt( + &mut package, + &mut assigner, + closure_expr, + PackageSpan::default(), ); - let semi = alloc_semi_stmt(&mut package, &mut assigner, closure_expr, Span::default()); let tail = trailing_int(&mut package, &mut assigner, 42); let block = alloc_block( @@ -420,7 +425,7 @@ fn given_local_used_in_closure_capture_dead_local_does_not_drop() { &mut assigner, vec![decl, semi, tail], Ty::Prim(Prim::Int), - Span::default(), + PackageSpan::default(), ); let fired = dead_local::apply(&mut package, &mut assigner, PackageId::CORE, block); diff --git a/source/compiler/qsc_fir_transforms/src/return_unify/simplify/tests/fixpoint.rs b/source/compiler/qsc_fir_transforms/src/return_unify/simplify/tests/fixpoint.rs index aa25c610193..a84e7008362 100644 --- a/source/compiler/qsc_fir_transforms/src/return_unify/simplify/tests/fixpoint.rs +++ b/source/compiler/qsc_fir_transforms/src/return_unify/simplify/tests/fixpoint.rs @@ -34,7 +34,6 @@ use expect_test::expect; use indoc::indoc; -use qsc_data_structures::span::Span; use qsc_fir::{ assigner::Assigner, fir::{ @@ -51,6 +50,7 @@ use crate::fir_builder::{ use crate::return_unify::simplify; use crate::return_unify::symbols; use crate::return_unify::tests::{check_simplify_rule_q, synth_slots_for_block}; +use qsc_fir::fir::PackageSpan; /// Adapt [`simplify::run_to_fixpoint`] (which returns `()`) to the /// `FnOnce(_, _, _, _) -> bool` contract that @@ -82,7 +82,7 @@ fn alloc_slot_decls(package: &mut Package, assigner: &mut Assigner) -> (Slots, S let bool_ty = Ty::Prim(Prim::Bool); let int_ty = Ty::Prim(Prim::Int); - let hr_init = alloc_bool_lit(package, assigner, false, Span::default()); + let hr_init = alloc_bool_lit(package, assigner, false, PackageSpan::default()); let (hr_local, hr_decl) = alloc_local_var( package, assigner, @@ -97,7 +97,7 @@ fn alloc_slot_decls(package: &mut Package, assigner: &mut Assigner) -> (Slots, S assigner, int_ty.clone(), ExprKind::Lit(Lit::Int(0)), - Span::default(), + PackageSpan::default(), ); let (rv_local, rv_decl) = alloc_local_var( package, @@ -126,9 +126,15 @@ fn build_slot_assign_stmt( v_id: ExprId, ) -> StmtId { let int_ty = Ty::Prim(Prim::Int); - let lhs = alloc_local_var_expr(package, assigner, slots.ret_val, int_ty, Span::default()); - let assign = alloc_assign_expr(package, assigner, lhs, v_id, Span::default()); - alloc_semi_stmt(package, assigner, assign, Span::default()) + let lhs = alloc_local_var_expr( + package, + assigner, + slots.ret_val, + int_ty, + PackageSpan::default(), + ); + let assign = alloc_assign_expr(package, assigner, lhs, v_id, PackageSpan::default()); + alloc_semi_stmt(package, assigner, assign, PackageSpan::default()) } /// Build a `__has_returned = true;` Semi statement. @@ -139,11 +145,11 @@ fn build_flag_set_stmt(package: &mut Package, assigner: &mut Assigner, slots: &S assigner, slots.has_returned, bool_ty, - Span::default(), + PackageSpan::default(), ); - let rhs = alloc_bool_lit(package, assigner, true, Span::default()); - let assign = alloc_assign_expr(package, assigner, lhs, rhs, Span::default()); - alloc_semi_stmt(package, assigner, assign, Span::default()) + let rhs = alloc_bool_lit(package, assigner, true, PackageSpan::default()); + let assign = alloc_assign_expr(package, assigner, lhs, rhs, PackageSpan::default()); + alloc_semi_stmt(package, assigner, assign, PackageSpan::default()) } /// Build a Unit-typed block expression carrying the flat slot/flag @@ -161,9 +167,9 @@ fn build_slot_set_arm_expr( assigner, vec![slot_stmt, flag_stmt], Ty::UNIT, - Span::default(), + PackageSpan::default(), ); - alloc_block_expr(package, assigner, arm_bid, Ty::UNIT, Span::default()) + alloc_block_expr(package, assigner, arm_bid, Ty::UNIT, PackageSpan::default()) } /// Build the canonical trailing merge @@ -183,30 +189,36 @@ fn build_merge_stmt(package: &mut Package, assigner: &mut Assigner, slots: &Slot assigner, slots.has_returned, bool_ty, - Span::default(), + PackageSpan::default(), ); let then_var = alloc_local_var_expr( package, assigner, slots.ret_val, int_ty.clone(), - Span::default(), + PackageSpan::default(), ); - let then_stmt = alloc_expr_stmt(package, assigner, then_var, Span::default()); + let then_stmt = alloc_expr_stmt(package, assigner, then_var, PackageSpan::default()); let then_bid = alloc_block( package, assigner, vec![then_stmt], int_ty.clone(), - Span::default(), + PackageSpan::default(), + ); + let then_expr = alloc_block_expr( + package, + assigner, + then_bid, + int_ty.clone(), + PackageSpan::default(), ); - let then_expr = alloc_block_expr(package, assigner, then_bid, int_ty.clone(), Span::default()); let else_arm = alloc_local_var_expr( package, assigner, slots.ret_val, int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let merge = alloc_if_expr( package, @@ -215,9 +227,9 @@ fn build_merge_stmt(package: &mut Package, assigner: &mut Assigner, slots: &Slot then_expr, Some(else_arm), int_ty, - Span::default(), + PackageSpan::default(), ); - alloc_expr_stmt(package, assigner, merge, Span::default()) + alloc_expr_stmt(package, assigner, merge, PackageSpan::default()) } /// Count `Semi(Assign(Var(has_returned), _))` statements in `block_id`. @@ -554,10 +566,10 @@ fn guard_clause_plus_dead_flag_via_run_to_fixpoint() { &mut assigner, int_ty.clone(), ExprKind::Lit(Lit::Int(5)), - Span::default(), + PackageSpan::default(), ); let guard_then = build_slot_set_arm_expr(&mut package, &mut assigner, &slots, v_expr); - let guard_cond = alloc_bool_lit(&mut package, &mut assigner, true, Span::default()); + let guard_cond = alloc_bool_lit(&mut package, &mut assigner, true, PackageSpan::default()); let guard_if = alloc_if_expr( &mut package, &mut assigner, @@ -565,9 +577,14 @@ fn guard_clause_plus_dead_flag_via_run_to_fixpoint() { guard_then, None, Ty::UNIT, - Span::default(), + PackageSpan::default(), + ); + let guard_stmt = alloc_semi_stmt( + &mut package, + &mut assigner, + guard_if, + PackageSpan::default(), ); - let guard_stmt = alloc_semi_stmt(&mut package, &mut assigner, guard_if, Span::default()); // Continuation: `if not __has_returned { 8 }`. let rest_value = alloc_expr( @@ -575,31 +592,41 @@ fn guard_clause_plus_dead_flag_via_run_to_fixpoint() { &mut assigner, int_ty.clone(), ExprKind::Lit(Lit::Int(8)), - Span::default(), + PackageSpan::default(), + ); + let rest_value_stmt = alloc_expr_stmt( + &mut package, + &mut assigner, + rest_value, + PackageSpan::default(), ); - let rest_value_stmt = alloc_expr_stmt(&mut package, &mut assigner, rest_value, Span::default()); let rest_bid = alloc_block( &mut package, &mut assigner, vec![rest_value_stmt], int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let rest_block_expr = alloc_block_expr( &mut package, &mut assigner, rest_bid, int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let flag_read = alloc_local_var_expr( &mut package, &mut assigner, slots.has_returned, bool_ty, - Span::default(), + PackageSpan::default(), + ); + let not_flag = alloc_not_expr( + &mut package, + &mut assigner, + flag_read, + PackageSpan::default(), ); - let not_flag = alloc_not_expr(&mut package, &mut assigner, flag_read, Span::default()); let cont_if = alloc_if_expr( &mut package, &mut assigner, @@ -607,9 +634,9 @@ fn guard_clause_plus_dead_flag_via_run_to_fixpoint() { rest_block_expr, None, int_ty.clone(), - Span::default(), + PackageSpan::default(), ); - let cont_stmt = alloc_semi_stmt(&mut package, &mut assigner, cont_if, Span::default()); + let cont_stmt = alloc_semi_stmt(&mut package, &mut assigner, cont_if, PackageSpan::default()); let merge_stmt = build_merge_stmt(&mut package, &mut assigner, &slots); @@ -625,7 +652,7 @@ fn guard_clause_plus_dead_flag_via_run_to_fixpoint() { merge_stmt, ], int_ty, - Span::default(), + PackageSpan::default(), ); let synth_slots = synth_slots_for_block(&package, block_id); diff --git a/source/compiler/qsc_fir_transforms/src/return_unify/simplify/tests/guard_clause.rs b/source/compiler/qsc_fir_transforms/src/return_unify/simplify/tests/guard_clause.rs index 33354647baa..7c591414d3f 100644 --- a/source/compiler/qsc_fir_transforms/src/return_unify/simplify/tests/guard_clause.rs +++ b/source/compiler/qsc_fir_transforms/src/return_unify/simplify/tests/guard_clause.rs @@ -422,7 +422,8 @@ fn both_branches_return_shape_not_collapsed_by_guard_clause_rule() { mod inverted_orientation { use expect_test::expect; use indoc::indoc; - use qsc_data_structures::span::Span; + + use qsc_fir::fir::PackageSpan; use qsc_fir::{ assigner::Assigner, fir::{ @@ -466,10 +467,10 @@ mod inverted_orientation { assigner, slots.ret_val, return_ty.clone(), - Span::default(), + PackageSpan::default(), ); - let assign = alloc_assign_expr(package, assigner, lhs, v_id, Span::default()); - alloc_semi_stmt(package, assigner, assign, Span::default()) + let assign = alloc_assign_expr(package, assigner, lhs, v_id, PackageSpan::default()); + alloc_semi_stmt(package, assigner, assign, PackageSpan::default()) } /// Build `__has_returned = true;` Semi statement. @@ -484,11 +485,11 @@ mod inverted_orientation { assigner, slots.has_returned, bool_ty.clone(), - Span::default(), + PackageSpan::default(), ); - let rhs = alloc_bool_lit(package, assigner, true, Span::default()); - let assign = alloc_assign_expr(package, assigner, lhs, rhs, Span::default()); - alloc_semi_stmt(package, assigner, assign, Span::default()) + let rhs = alloc_bool_lit(package, assigner, true, PackageSpan::default()); + let assign = alloc_assign_expr(package, assigner, lhs, rhs, PackageSpan::default()); + alloc_semi_stmt(package, assigner, assign, PackageSpan::default()) } /// Build a Unit-typed block expr containing the slot-set sequence @@ -508,16 +509,22 @@ mod inverted_orientation { assigner, vec![slot_stmt, flag_stmt], Ty::UNIT, - Span::default(), + PackageSpan::default(), ); - alloc_block_expr(package, assigner, bid, Ty::UNIT, Span::default()) + alloc_block_expr(package, assigner, bid, Ty::UNIT, PackageSpan::default()) } /// Build an empty Unit-typed block expr — the only then-arm shape /// `identify_guard_else_arm` accepts. fn build_empty_unit_block_expr(package: &mut Package, assigner: &mut Assigner) -> ExprId { - let bid = alloc_block(package, assigner, Vec::new(), Ty::UNIT, Span::default()); - alloc_block_expr(package, assigner, bid, Ty::UNIT, Span::default()) + let bid = alloc_block( + package, + assigner, + Vec::new(), + Ty::UNIT, + PackageSpan::default(), + ); + alloc_block_expr(package, assigner, bid, Ty::UNIT, PackageSpan::default()) } /// Build the inverted guard `Semi(If(cond, empty_unit, Some(slot_sets)))`. @@ -535,9 +542,9 @@ mod inverted_orientation { then_id, Some(else_id), Ty::UNIT, - Span::default(), + PackageSpan::default(), ); - alloc_semi_stmt(package, assigner, if_expr, Span::default()) + alloc_semi_stmt(package, assigner, if_expr, PackageSpan::default()) } /// Build the lazy continuation `Semi(If(not __has_returned, rest_block, None))`. @@ -553,9 +560,9 @@ mod inverted_orientation { assigner, slots.has_returned, bool_ty.clone(), - Span::default(), + PackageSpan::default(), ); - let not_flag = alloc_not_expr(package, assigner, flag_read, Span::default()); + let not_flag = alloc_not_expr(package, assigner, flag_read, PackageSpan::default()); let if_expr = alloc_if_expr( package, assigner, @@ -563,9 +570,9 @@ mod inverted_orientation { rest_block_expr_id, None, Ty::UNIT, - Span::default(), + PackageSpan::default(), ); - alloc_semi_stmt(package, assigner, if_expr, Span::default()) + alloc_semi_stmt(package, assigner, if_expr, PackageSpan::default()) } /// Build the canonical merge `Expr(If(__has_returned, __ret_val, Some(fallthrough)))`. @@ -581,29 +588,29 @@ mod inverted_orientation { assigner, slots.has_returned, Ty::Prim(Prim::Bool), - Span::default(), + PackageSpan::default(), ); let then_var = alloc_local_var_expr( package, assigner, slots.ret_val, return_ty.clone(), - Span::default(), + PackageSpan::default(), ); - let then_stmt = alloc_expr_stmt(package, assigner, then_var, Span::default()); + let then_stmt = alloc_expr_stmt(package, assigner, then_var, PackageSpan::default()); let then_bid = alloc_block( package, assigner, vec![then_stmt], return_ty.clone(), - Span::default(), + PackageSpan::default(), ); let then_expr = alloc_block_expr( package, assigner, then_bid, return_ty.clone(), - Span::default(), + PackageSpan::default(), ); let merge = alloc_if_expr( package, @@ -612,9 +619,9 @@ mod inverted_orientation { then_expr, Some(fallthrough), return_ty.clone(), - Span::default(), + PackageSpan::default(), ); - alloc_expr_stmt(package, assigner, merge, Span::default()) + alloc_expr_stmt(package, assigner, merge, PackageSpan::default()) } /// Build the rest-block expression `{ rest_value }` (single trailing @@ -628,20 +635,20 @@ mod inverted_orientation { rest_value: ExprId, return_ty: &Ty, ) -> (qsc_fir::fir::BlockId, ExprId) { - let rest_stmt = alloc_expr_stmt(package, assigner, rest_value, Span::default()); + let rest_stmt = alloc_expr_stmt(package, assigner, rest_value, PackageSpan::default()); let rest_bid = alloc_block( package, assigner, vec![rest_stmt], return_ty.clone(), - Span::default(), + PackageSpan::default(), ); let expr_id = alloc_block_expr( package, assigner, rest_bid, return_ty.clone(), - Span::default(), + PackageSpan::default(), ); (rest_bid, expr_id) } @@ -655,7 +662,7 @@ mod inverted_orientation { assigner, cond_local, Ty::Prim(Prim::Bool), - Span::default(), + PackageSpan::default(), ); (cond_local, cond_expr) } @@ -737,7 +744,7 @@ mod inverted_orientation { assigner, int_ty.clone(), ExprKind::Lit(Lit::Int(42)), - Span::default(), + PackageSpan::default(), ); let then_id = build_empty_unit_block_expr(package, assigner); let else_id = build_slot_set_arm_expr(package, assigner, slots, v_id, int_ty); @@ -748,7 +755,7 @@ mod inverted_orientation { assigner, int_ty.clone(), ExprKind::Lit(Lit::Int(7)), - Span::default(), + PackageSpan::default(), ); let (rest_bid, rest_block_expr) = build_rest_block_expr(package, assigner, rest_value, int_ty); @@ -759,7 +766,7 @@ mod inverted_orientation { assigner, slots.ret_val, int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let merge_stmt = build_merge_stmt(package, assigner, slots, fallthrough, int_ty); @@ -768,7 +775,7 @@ mod inverted_orientation { assigner, vec![guard_stmt, cont_stmt, merge_stmt], int_ty.clone(), - Span::default(), + PackageSpan::default(), ); (block_id, cond_local, v_id, rest_bid) } @@ -863,14 +870,14 @@ mod inverted_orientation { &mut assigner, inner_block_id, int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let (_outer_local, outer_pat) = alloc_bind_pat( &mut package, &mut assigner, "x", int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let outer_local_stmt = alloc_local_stmt( &mut package, @@ -878,14 +885,14 @@ mod inverted_orientation { Mutability::Immutable, outer_pat, init_expr, - Span::default(), + PackageSpan::default(), ); let _outer_block = alloc_block( &mut package, &mut assigner, vec![outer_local_stmt], int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let synth_slots = @@ -920,20 +927,20 @@ mod inverted_orientation { &mut assigner, inner_block_id, int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let wrapper_stmt = alloc_expr_stmt( &mut package, &mut assigner, inner_block_expr, - Span::default(), + PackageSpan::default(), ); let _outer_block = alloc_block( &mut package, &mut assigner, vec![wrapper_stmt], int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let synth_slots = @@ -966,7 +973,7 @@ mod inverted_orientation { &mut assigner, int_ty.clone(), ExprKind::Lit(Lit::Int(42)), - Span::default(), + PackageSpan::default(), ); let slot_stmt = build_slot_assign_stmt(&mut package, &mut assigner, &slots, v_id, &int_ty); // Else-arm is a Unit block carrying only the slot set — flag set absent. @@ -975,14 +982,14 @@ mod inverted_orientation { &mut assigner, vec![slot_stmt], Ty::UNIT, - Span::default(), + PackageSpan::default(), ); let asymmetric_else = alloc_block_expr( &mut package, &mut assigner, asymmetric_bid, Ty::UNIT, - Span::default(), + PackageSpan::default(), ); let then_id = build_empty_unit_block_expr(&mut package, &mut assigner); let guard_stmt = build_inverted_guard_stmt( @@ -998,7 +1005,7 @@ mod inverted_orientation { &mut assigner, int_ty.clone(), ExprKind::Lit(Lit::Int(7)), - Span::default(), + PackageSpan::default(), ); let (_rest_bid, rest_block_expr) = build_rest_block_expr(&mut package, &mut assigner, rest_value, &int_ty); @@ -1009,7 +1016,7 @@ mod inverted_orientation { &mut assigner, slots.ret_val, int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let merge_stmt = build_merge_stmt(&mut package, &mut assigner, &slots, fallthrough, &int_ty); @@ -1019,7 +1026,7 @@ mod inverted_orientation { &mut assigner, vec![guard_stmt, cont_stmt, merge_stmt], int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let pre_stmts = package.get_block(block_id).stmts.clone(); @@ -1058,7 +1065,7 @@ mod inverted_orientation { &mut assigner, int_ty.clone(), ExprKind::Lit(Lit::Int(42)), - Span::default(), + PackageSpan::default(), ); let slot_stmt = build_slot_assign_stmt(&mut package, &mut assigner, &slots, v_id, &int_ty); // Foreign stmt: a Semi(Unit-literal) — innocuous but breaks the @@ -1068,24 +1075,28 @@ mod inverted_orientation { &mut assigner, Ty::UNIT, ExprKind::Tuple(Vec::new()), - Span::default(), + PackageSpan::default(), + ); + let foreign_stmt = alloc_semi_stmt( + &mut package, + &mut assigner, + foreign_expr, + PackageSpan::default(), ); - let foreign_stmt = - alloc_semi_stmt(&mut package, &mut assigner, foreign_expr, Span::default()); let flag_stmt = build_flag_set_stmt(&mut package, &mut assigner, &slots); let bloated_bid = alloc_block( &mut package, &mut assigner, vec![slot_stmt, foreign_stmt, flag_stmt], Ty::UNIT, - Span::default(), + PackageSpan::default(), ); let bloated_else = alloc_block_expr( &mut package, &mut assigner, bloated_bid, Ty::UNIT, - Span::default(), + PackageSpan::default(), ); let then_id = build_empty_unit_block_expr(&mut package, &mut assigner); let guard_stmt = build_inverted_guard_stmt( @@ -1101,7 +1112,7 @@ mod inverted_orientation { &mut assigner, int_ty.clone(), ExprKind::Lit(Lit::Int(7)), - Span::default(), + PackageSpan::default(), ); let (_rest_bid, rest_block_expr) = build_rest_block_expr(&mut package, &mut assigner, rest_value, &int_ty); @@ -1112,7 +1123,7 @@ mod inverted_orientation { &mut assigner, slots.ret_val, int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let merge_stmt = build_merge_stmt(&mut package, &mut assigner, &slots, fallthrough, &int_ty); @@ -1122,7 +1133,7 @@ mod inverted_orientation { &mut assigner, vec![guard_stmt, cont_stmt, merge_stmt], int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let pre_stmts = package.get_block(block_id).stmts.clone(); diff --git a/source/compiler/qsc_fir_transforms/src/return_unify/simplify/tests/let_folding.rs b/source/compiler/qsc_fir_transforms/src/return_unify/simplify/tests/let_folding.rs index 2c8484c75fd..052d1705ffb 100644 --- a/source/compiler/qsc_fir_transforms/src/return_unify/simplify/tests/let_folding.rs +++ b/source/compiler/qsc_fir_transforms/src/return_unify/simplify/tests/let_folding.rs @@ -39,7 +39,6 @@ //! `__has_returned`). Folding would let the merge read the slot //! before the init's writes commit. -use qsc_data_structures::span::Span; use qsc_fir::{ assigner::Assigner, fir::{ @@ -55,6 +54,7 @@ use crate::fir_builder::{ }; use crate::return_unify::simplify::let_folding; use crate::return_unify::symbols; +use qsc_fir::fir::PackageSpan; /// Slot identities shared by every test fixture. struct Slots { @@ -86,21 +86,21 @@ fn build_merge( assigner, slots.has_returned, Ty::Prim(Prim::Bool), - Span::default(), + PackageSpan::default(), ); let then_arm = alloc_local_var_expr( package, assigner, slots.ret_val, return_ty.clone(), - Span::default(), + PackageSpan::default(), ); let else_arm = alloc_local_var_expr( package, assigner, else_local, return_ty.clone(), - Span::default(), + PackageSpan::default(), ); alloc_if_expr( package, @@ -109,7 +109,7 @@ fn build_merge( then_arm, Some(else_arm), return_ty.clone(), - Span::default(), + PackageSpan::default(), ) } @@ -133,13 +133,13 @@ fn build_let_merge_pattern( Mutability::Immutable, ); let merge_expr_id = build_merge(package, assigner, slots, trailing_local, return_ty); - let merge_stmt = alloc_expr_stmt(package, assigner, merge_expr_id, Span::default()); + let merge_stmt = alloc_expr_stmt(package, assigner, merge_expr_id, PackageSpan::default()); let block_id = alloc_block( package, assigner, vec![let_stmt, merge_stmt], return_ty.clone(), - Span::default(), + PackageSpan::default(), ); (block_id, trailing_local, merge_expr_id) } @@ -156,7 +156,7 @@ fn canonical_literal_init_folds_into_merge_else() { &mut assigner, int_ty.clone(), ExprKind::Lit(Lit::Int(42)), - Span::default(), + PackageSpan::default(), ); let (block_id, _, merge_expr_id) = build_let_merge_pattern( &mut package, @@ -210,47 +210,56 @@ fn block_init_with_side_effect_folds() { &mut assigner, int_ty.clone(), ExprKind::Var(Res::Local(sink_local), Vec::new()), - Span::default(), + PackageSpan::default(), ); let sink_rhs = alloc_expr( &mut package, &mut assigner, int_ty.clone(), ExprKind::Lit(Lit::Int(1)), - Span::default(), + PackageSpan::default(), ); let side_effect = alloc_expr( &mut package, &mut assigner, Ty::UNIT, ExprKind::Assign(sink_lhs, sink_rhs), - Span::default(), + PackageSpan::default(), + ); + let side_effect_stmt = alloc_semi_stmt( + &mut package, + &mut assigner, + side_effect, + PackageSpan::default(), ); - let side_effect_stmt = - alloc_semi_stmt(&mut package, &mut assigner, side_effect, Span::default()); let tail_value = alloc_expr( &mut package, &mut assigner, int_ty.clone(), ExprKind::Lit(Lit::Int(7)), - Span::default(), + PackageSpan::default(), + ); + let tail_stmt = alloc_expr_stmt( + &mut package, + &mut assigner, + tail_value, + PackageSpan::default(), ); - let tail_stmt = alloc_expr_stmt(&mut package, &mut assigner, tail_value, Span::default()); let inner_bid = alloc_block( &mut package, &mut assigner, vec![side_effect_stmt, tail_stmt], int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let init = alloc_expr( &mut package, &mut assigner, int_ty.clone(), ExprKind::Block(inner_bid), - Span::default(), + PackageSpan::default(), ); let (block_id, _, merge_expr_id) = build_let_merge_pattern( @@ -297,21 +306,21 @@ fn call_init_folds() { &mut assigner, Ty::Err, ExprKind::Var(Res::Local(callable_local), Vec::new()), - Span::default(), + PackageSpan::default(), ); let arg_expr = alloc_expr( &mut package, &mut assigner, Ty::UNIT, ExprKind::Tuple(Vec::new()), - Span::default(), + PackageSpan::default(), ); let init = alloc_expr( &mut package, &mut assigner, int_ty.clone(), ExprKind::Call(callable_expr, arg_expr), - Span::default(), + PackageSpan::default(), ); let (block_id, _, merge_expr_id) = build_let_merge_pattern( @@ -354,7 +363,7 @@ fn wrong_name_refuses_to_fold() { &mut assigner, int_ty.clone(), ExprKind::Lit(Lit::Int(42)), - Span::default(), + PackageSpan::default(), ); let (block_id, _, _) = build_let_merge_pattern( &mut package, @@ -397,7 +406,7 @@ fn multiple_uses_in_merge_refuse_to_fold() { &mut assigner, bool_ty.clone(), ExprKind::Lit(Lit::Bool(false)), - Span::default(), + PackageSpan::default(), ); // Build the let first so we know `trailing_local`. @@ -416,21 +425,21 @@ fn multiple_uses_in_merge_refuse_to_fold() { &mut assigner, trailing_local, bool_ty.clone(), - Span::default(), + PackageSpan::default(), ); let then_arm = alloc_local_var_expr( &mut package, &mut assigner, slots.ret_val, bool_ty.clone(), - Span::default(), + PackageSpan::default(), ); let else_arm = alloc_local_var_expr( &mut package, &mut assigner, trailing_local, bool_ty.clone(), - Span::default(), + PackageSpan::default(), ); let merge_expr_id = alloc_if_expr( &mut package, @@ -439,15 +448,20 @@ fn multiple_uses_in_merge_refuse_to_fold() { then_arm, Some(else_arm), bool_ty.clone(), - Span::default(), + PackageSpan::default(), + ); + let merge_stmt = alloc_expr_stmt( + &mut package, + &mut assigner, + merge_expr_id, + PackageSpan::default(), ); - let merge_stmt = alloc_expr_stmt(&mut package, &mut assigner, merge_expr_id, Span::default()); let block_id = alloc_block( &mut package, &mut assigner, vec![let_stmt, merge_stmt], bool_ty.clone(), - Span::default(), + PackageSpan::default(), ); let before = package.get_block(block_id).stmts.clone(); @@ -485,47 +499,56 @@ fn init_that_writes_merge_slot_refuses_to_fold() { &mut assigner, bool_ty.clone(), ExprKind::Var(Res::Local(slots.has_returned), Vec::new()), - Span::default(), + PackageSpan::default(), ); let flag_rhs = alloc_expr( &mut package, &mut assigner, bool_ty.clone(), ExprKind::Lit(Lit::Bool(true)), - Span::default(), + PackageSpan::default(), ); let flag_assign = alloc_expr( &mut package, &mut assigner, Ty::UNIT, ExprKind::Assign(flag_lhs, flag_rhs), - Span::default(), + PackageSpan::default(), + ); + let flag_assign_stmt = alloc_semi_stmt( + &mut package, + &mut assigner, + flag_assign, + PackageSpan::default(), ); - let flag_assign_stmt = - alloc_semi_stmt(&mut package, &mut assigner, flag_assign, Span::default()); let tail_value = alloc_expr( &mut package, &mut assigner, int_ty.clone(), ExprKind::Lit(Lit::Int(7)), - Span::default(), + PackageSpan::default(), + ); + let tail_stmt = alloc_expr_stmt( + &mut package, + &mut assigner, + tail_value, + PackageSpan::default(), ); - let tail_stmt = alloc_expr_stmt(&mut package, &mut assigner, tail_value, Span::default()); let inner_bid = alloc_block( &mut package, &mut assigner, vec![flag_assign_stmt, tail_stmt], int_ty.clone(), - Span::default(), + PackageSpan::default(), ); let init = alloc_expr( &mut package, &mut assigner, int_ty.clone(), ExprKind::Block(inner_bid), - Span::default(), + PackageSpan::default(), ); let (block_id, _, _) = build_let_merge_pattern( diff --git a/source/compiler/qsc_fir_transforms/src/return_unify/slot.rs b/source/compiler/qsc_fir_transforms/src/return_unify/slot.rs index 056cd88abaf..1422c28192a 100644 --- a/source/compiler/qsc_fir_transforms/src/return_unify/slot.rs +++ b/source/compiler/qsc_fir_transforms/src/return_unify/slot.rs @@ -8,7 +8,6 @@ use crate::fir_builder::{ alloc_local_var, alloc_local_var_expr, }; use num_bigint::BigInt; -use qsc_data_structures::span::Span; use qsc_fir::{ assigner::Assigner, fir::{ @@ -255,7 +254,7 @@ pub(super) fn create_return_slot_decl( assigner, slot_ty.clone(), ExprKind::Array(Vec::new()), - Span::default(), + package.synthetic_span(), ); (slot_ty, init_expr) } @@ -313,7 +312,7 @@ pub(super) fn wrap_in_singleton_array( assigner, array_ty, ExprKind::Array(vec![value_expr]), - Span::default(), + package.synthetic_span(), ) } @@ -334,14 +333,14 @@ pub(super) fn singleton_array_index_read( assigner, Ty::Prim(Prim::Int), ExprKind::Lit(Lit::Int(0)), - Span::default(), + package.synthetic_span(), ); alloc_expr( package, assigner, elem_ty.clone(), ExprKind::Index(array_expr, zero), - Span::default(), + package.synthetic_span(), ) } @@ -358,12 +357,17 @@ pub(super) fn create_return_slot_read_expr( assigner, slot.var_id, return_ty.clone(), - Span::default(), + package.synthetic_span(), ), ReturnSlotStrategy::ArrayBacked => { let array_ty = Ty::Array(Box::new(return_ty.clone())); - let array_expr = - alloc_local_var_expr(package, assigner, slot.var_id, array_ty, Span::default()); + let array_expr = alloc_local_var_expr( + package, + assigner, + slot.var_id, + array_ty, + package.synthetic_span(), + ); singleton_array_index_read(package, assigner, array_expr, return_ty) } } @@ -387,7 +391,7 @@ pub(super) fn create_return_slot_read_or_fail_expr( assigner, has_returned_var_id, Ty::Prim(Prim::Bool), - Span::default(), + package.synthetic_span(), ); let read = create_return_slot_read_expr(package, assigner, slot, return_ty); let fail = create_typed_fail_expr( @@ -403,7 +407,7 @@ pub(super) fn create_return_slot_read_or_fail_expr( read, Some(fail), return_ty.clone(), - Span::default(), + package.synthetic_span(), ) } } @@ -440,14 +444,14 @@ fn create_typed_fail_expr( assigner, Ty::Prim(Prim::String), ExprKind::String(vec![StringComponent::Lit(Rc::from(message))]), - Span::default(), + package.synthetic_span(), ); alloc_expr( package, assigner, ty.clone(), ExprKind::Fail(message_expr), - Span::default(), + package.synthetic_span(), ) } @@ -518,7 +522,7 @@ pub(super) fn create_default_value( assigner, ty.clone(), kind, - Span::default(), + package.synthetic_span(), )) } @@ -695,28 +699,33 @@ fn synthesize_fail_callable( assigner, Ty::Prim(Prim::String), ExprKind::String(vec![StringComponent::Lit("callable init expr".into())]), - Span::default(), + package.synthetic_span(), ); let fail_expr_id = alloc_expr( package, assigner, output_ty.clone(), ExprKind::Fail(msg_expr_id), - Span::default(), + package.synthetic_span(), ); - let trailing_stmt = alloc_expr_stmt(package, assigner, fail_expr_id, Span::default()); + let trailing_stmt = alloc_expr_stmt(package, assigner, fail_expr_id, package.synthetic_span()); let body_block = alloc_block( package, assigner, vec![trailing_stmt], output_ty.clone(), - Span::default(), + package.synthetic_span(), ); - let input_pat_id = alloc_discard_pat(package, assigner, input_ty.clone(), Span::default()); + let input_pat_id = alloc_discard_pat( + package, + assigner, + input_ty.clone(), + package.synthetic_span(), + ); let body_spec = qsc_fir::fir::SpecDecl { - span: Span::default(), + span: package.synthetic_span(), block: body_block, input: None, exec_graph: qsc_fir::fir::ExecGraph::default(), @@ -731,11 +740,11 @@ fn synthesize_fail_callable( let new_item_id = assigner.next_item(); let callable_name: Rc = Rc::from(format!("__return_unify_fail_{new_item_id}")); let decl = CallableDecl { - span: Span::default(), + span: package.synthetic_span(), kind, name: Ident { id: LocalVarId::from(0_u32), - span: Span::default(), + span: package.synthetic_span(), name: callable_name, }, generics: Vec::new(), @@ -748,7 +757,7 @@ fn synthesize_fail_callable( let item = qsc_fir::fir::Item { id: new_item_id, - span: Span::default(), + span: package.synthetic_span(), parent: None, doc: Rc::from(""), attrs: Vec::new(), @@ -767,6 +776,12 @@ fn create_assign_expr( value: ExprId, ty: &Ty, ) -> ExprId { - let var_expr = alloc_local_var_expr(package, assigner, var_id, ty.clone(), Span::default()); - alloc_assign_expr(package, assigner, var_expr, value, Span::default()) + let var_expr = alloc_local_var_expr( + package, + assigner, + var_id, + ty.clone(), + package.synthetic_span(), + ); + alloc_assign_expr(package, assigner, var_expr, value, package.synthetic_span()) } diff --git a/source/compiler/qsc_fir_transforms/src/return_unify/tests/contracts_and_errors.rs b/source/compiler/qsc_fir_transforms/src/return_unify/tests/contracts_and_errors.rs index 18721c2cbc0..3ab475ff529 100644 --- a/source/compiler/qsc_fir_transforms/src/return_unify/tests/contracts_and_errors.rs +++ b/source/compiler/qsc_fir_transforms/src/return_unify/tests/contracts_and_errors.rs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -use qsc_data_structures::span::Span; use qsc_fir::{ fir::{CallableKind, ItemId, LocalItemId}, ty::{Arrow, FunctorSet, FunctorSetValue}, @@ -12,6 +11,7 @@ use crate::fir_builder::alloc_expr_stmt; use crate::test_utils::frontend_error_codes; use super::*; +use qsc_fir::fir::PackageSpan; fn operation_arrow_ty(input: Ty, output: Ty) -> Ty { Ty::Arrow(Box::new(Arrow { @@ -87,7 +87,7 @@ fn guard_stmt_with_flag_panics_on_non_unit_expr_stmt() { lit_expr_id, Expr { id: lit_expr_id, - span: qsc_data_structures::span::Span::default(), + span: PackageSpan::default(), ty: Ty::Prim(Prim::Int), kind: ExprKind::Lit(Lit::Int(0)), exec_graph_range: crate::EMPTY_EXEC_RANGE, @@ -96,7 +96,7 @@ fn guard_stmt_with_flag_panics_on_non_unit_expr_stmt() { let stmt_id = { let assigner: &mut Assigner = &mut assigner; - alloc_expr_stmt(package, assigner, lit_expr_id, Span::default()) + alloc_expr_stmt(package, assigner, lit_expr_id, PackageSpan::default()) }; let reachable = FxHashSet::default(); let udt_pure_tys = super::super::build_scoped_udt_pure_ty_cache(&store, &reachable); diff --git a/source/compiler/qsc_fir_transforms/src/test_utils.rs b/source/compiler/qsc_fir_transforms/src/test_utils.rs index 0bd3089ac7c..39c7bf52570 100644 --- a/source/compiler/qsc_fir_transforms/src/test_utils.rs +++ b/source/compiler/qsc_fir_transforms/src/test_utils.rs @@ -215,13 +215,14 @@ fn lower_cached_stdlib_and_user_to_fir( let mut fir_store = fir::PackageStore::new(); for (hir_id, unit) in [(PackageId::CORE, core_unit), (std_id, std_unit)] { let mut lowerer = qsc_lowerer::Lowerer::new(); - let package = lowerer.lower_package(&unit.package, &fir_store); + let package = + lowerer.lower_package(&unit.package, &fir_store, map_hir_package_to_fir(hir_id)); fir_store.insert(map_hir_package_to_fir(hir_id), package); } let mut lowerer = qsc_lowerer::Lowerer::new(); - let user_package = lowerer.lower_package(&user_unit.package, &fir_store); let fir_pkg_id = map_hir_package_to_fir(user_hir_id); + let user_package = lowerer.lower_package(&user_unit.package, &fir_store, fir_pkg_id); fir_store.insert(fir_pkg_id, user_package); (fir_store, fir_pkg_id) diff --git a/source/compiler/qsc_fir_transforms/src/tuple_compare_lower.rs b/source/compiler/qsc_fir_transforms/src/tuple_compare_lower.rs index f6d762d2c59..f81072f08ab 100644 --- a/source/compiler/qsc_fir_transforms/src/tuple_compare_lower.rs +++ b/source/compiler/qsc_fir_transforms/src/tuple_compare_lower.rs @@ -45,6 +45,7 @@ use crate::walk_utils::{ collect_expr_ids_in_entry_and_local_callables, collect_expr_ids_in_local_callables, }; use qsc_fir::assigner::Assigner; +use qsc_fir::fir::PackageSpan; use qsc_fir::fir::{ BinOp, ExprId, ExprKind, Package, PackageId, PackageLookup, PackageStore, StoreItemId, }; @@ -220,7 +221,7 @@ fn extract_or_field( assigner: &mut Assigner, tuple_expr_id: ExprId, elem_tys: &[Ty], - span: qsc_data_structures::span::Span, + span: PackageSpan, ) -> Vec { let expr = package.get_expr(tuple_expr_id); if let ExprKind::Tuple(es) = &expr.kind { @@ -249,7 +250,7 @@ fn fold_left( assigner: &mut Assigner, exprs: &[ExprId], joiner: BinOp, - span: qsc_data_structures::span::Span, + span: PackageSpan, ) -> ExprId { assert!(!exprs.is_empty(), "fold_left requires at least one expr"); let mut acc = exprs[0]; diff --git a/source/compiler/qsc_fir_transforms/src/tuple_decompose.rs b/source/compiler/qsc_fir_transforms/src/tuple_decompose.rs index 1745d412a47..2f6b8ca53c7 100644 --- a/source/compiler/qsc_fir_transforms/src/tuple_decompose.rs +++ b/source/compiler/qsc_fir_transforms/src/tuple_decompose.rs @@ -51,7 +51,6 @@ use crate::reachability::{ }; use crate::tuple_destructuring::{normalize_tuple_copy_assignment, normalize_tuple_destructuring}; use crate::walk_utils::{UseClass, classify_block_use, collect_expr_ids_in_local_callables}; -use qsc_data_structures::span::Span; use qsc_fir::assigner::Assigner; use qsc_fir::fir::{ Block, BlockId, CallableDecl, CallableImpl, Expr, ExprId, ExprKind, Field, ItemKind, @@ -745,7 +744,7 @@ fn rewrite_assign_tuples( assigner, new_locals[0], elem_types[0].clone(), - Span::default(), + package.synthetic_span(), ); let assign = package @@ -764,11 +763,17 @@ fn rewrite_assign_tuples( assigner, new_locals[i], elem_types[i].clone(), - Span::default(), + package.synthetic_span(), ); - let assign_id = - alloc_assign_expr(package, assigner, lhs_id, elements[i], Span::default()); - let new_stmt_id = alloc_semi_stmt(package, assigner, assign_id, Span::default()); + let assign_id = alloc_assign_expr( + package, + assigner, + lhs_id, + elements[i], + package.synthetic_span(), + ); + let new_stmt_id = + alloc_semi_stmt(package, assigner, assign_id, package.synthetic_span()); new_stmt_ids.push(new_stmt_id); } diff --git a/source/compiler/qsc_fir_transforms/src/tuple_destructuring.rs b/source/compiler/qsc_fir_transforms/src/tuple_destructuring.rs index b9378485a9b..a019a22ea89 100644 --- a/source/compiler/qsc_fir_transforms/src/tuple_destructuring.rs +++ b/source/compiler/qsc_fir_transforms/src/tuple_destructuring.rs @@ -25,7 +25,6 @@ use crate::fir_builder::alloc_local_stmt; use crate::fir_builder::alloc_local_var_expr; use crate::fir_builder::reachable_local_callables; use crate::tuple_decompose::collect_all_block_ids_in_callable; -use qsc_data_structures::span::Span; use qsc_fir::assigner::Assigner; use qsc_fir::fir::{ BlockId, ExprId, ExprKind, ItemKind, LocalItemId, LocalVarId, Mutability, Package, PackageId, @@ -363,7 +362,7 @@ fn apply_destructure_rewrite( mutability, pat_id, rhs_id, - Span::default(), + package.synthetic_span(), ); new_stmt_ids.push(stmt_id); } @@ -433,7 +432,7 @@ fn create_local_projection_path( assigner, source_local, tuple_ty.clone(), - Span::default(), + package.synthetic_span(), ); alloc_field_path_expr( package, @@ -441,6 +440,6 @@ fn create_local_projection_path( base_id, indices.to_vec(), leaf_ty.clone(), - Span::default(), + package.synthetic_span(), ) } diff --git a/source/compiler/qsc_fir_transforms/src/udt_erase.rs b/source/compiler/qsc_fir_transforms/src/udt_erase.rs index 13492be6b5f..7df601cc057 100644 --- a/source/compiler/qsc_fir_transforms/src/udt_erase.rs +++ b/source/compiler/qsc_fir_transforms/src/udt_erase.rs @@ -51,13 +51,13 @@ use crate::EMPTY_EXEC_RANGE; use crate::cloner::FirCloner; use crate::package_assigners::PackageAssigners; use crate::reachability::{collect_reachable_from_entry, collect_reachable_package_closure}; -use qsc_data_structures::span::Span; use qsc_fir::fir::{ BlockId, Expr, ExprId, ExprKind, Field, FieldAssign, FieldPath, ItemKind, LocalItemId, Package, PackageId, PackageStore, PatId, Res, StoreItemId, }; use qsc_fir::ty::{Arrow, Ty}; +use qsc_fir::fir::PackageSpan; use rustc_hash::FxHashMap; /// Maps `StoreItemId` → pure `Ty` for every UDT definition @@ -339,7 +339,7 @@ fn lower_copy_update_struct( expr_id: ExprId, copy_id: ExprId, fields: &[FieldAssign], - span: Span, + span: PackageSpan, ) { // Check for a whole-value replacement (single-field UDT where the // field path is empty). @@ -466,7 +466,7 @@ fn lower_field_updates( udt_cache: &UdtCache, expr_id: ExprId, kind: &ExprKind, - span: Span, + span: PackageSpan, ) { // Lower UpdateField(record, Field::Path(path), replace) into a // tuple construction that extracts all non-updated fields from the @@ -603,7 +603,7 @@ fn lower_update_field( indices: &[usize], replace_id: ExprId, record_ty: &Ty, - span: Span, + span: PackageSpan, ) -> ExprKind { match (indices, record_ty) { // Single-level path on a tuple: build a new tuple with the @@ -701,7 +701,7 @@ fn build_updated_tuple( update_idx: usize, replace_id: ExprId, elems: &[Ty], - span: Span, + span: PackageSpan, ) -> ExprKind { debug_assert!( update_idx < elems.len(), @@ -729,7 +729,7 @@ fn alloc_field_expr( record_id: ExprId, index: usize, ty: &Ty, - span: Span, + span: PackageSpan, ) -> ExprId { let field_id = cloner.alloc_expr(); package.exprs.insert( diff --git a/source/compiler/qsc_fir_transforms/src/udt_erase/tests.rs b/source/compiler/qsc_fir_transforms/src/udt_erase/tests.rs index 298ca22f54d..84089910ace 100644 --- a/source/compiler/qsc_fir_transforms/src/udt_erase/tests.rs +++ b/source/compiler/qsc_fir_transforms/src/udt_erase/tests.rs @@ -18,16 +18,17 @@ use rustc_hash::FxHashMap; use std::rc::Rc; use crate::EMPTY_EXEC_RANGE; +use qsc_fir::fir::PackageSpan; -fn default_span() -> Span { - Span::default() +fn default_span() -> PackageSpan { + PackageSpan::default() } /// Creates a minimal UDT type item (like `newtype Pair = (Int, Double)`). fn make_udt_item(item_id: LocalItemId, fields: Vec<(Option>, Ty)>) -> Item { let def = if fields.len() == 1 { UdtDef { - span: default_span(), + span: Span::default(), kind: UdtDefKind::Field(UdtField { name_span: None, name: fields[0].0.clone(), @@ -36,12 +37,12 @@ fn make_udt_item(item_id: LocalItemId, fields: Vec<(Option>, Ty)>) -> It } } else { UdtDef { - span: default_span(), + span: Span::default(), kind: UdtDefKind::Tuple( fields .into_iter() .map(|(name, ty)| UdtDef { - span: default_span(), + span: Span::default(), kind: UdtDefKind::Field(UdtField { name_span: None, name, @@ -53,7 +54,7 @@ fn make_udt_item(item_id: LocalItemId, fields: Vec<(Option>, Ty)>) -> It } }; let udt = Udt { - span: default_span(), + span: Span::default(), name: Rc::from("TestUdt"), definition: def, }; @@ -80,6 +81,7 @@ fn make_store_with_items(items: Vec) -> (PackageStore, PackageId) { let pkg_id = PackageId::from(0usize); let mut store = PackageStore::new(); let mut package = Package { + id: qsc_fir::fir::PackageId::default(), items: IndexMap::new(), entry: None, entry_exec_graph: ExecGraph::default(), @@ -105,6 +107,7 @@ fn make_ident(name: &str) -> Ident { fn make_empty_package() -> Package { Package { + id: qsc_fir::fir::PackageId::default(), items: IndexMap::new(), entry: None, entry_exec_graph: ExecGraph::default(), diff --git a/source/compiler/qsc_fir_transforms/src/walk_utils/tests.rs b/source/compiler/qsc_fir_transforms/src/walk_utils/tests.rs index 8552bc459b4..731b73f04e2 100644 --- a/source/compiler/qsc_fir_transforms/src/walk_utils/tests.rs +++ b/source/compiler/qsc_fir_transforms/src/walk_utils/tests.rs @@ -9,8 +9,8 @@ use crate::fir_builder::{ use crate::test_utils::compile_to_fir; use crate::test_utils::find_callable_body_block as find_callable_block; use expect_test::expect; -use qsc_data_structures::span::Span; use qsc_fir::assigner::Assigner; +use qsc_fir::fir::PackageSpan; use qsc_fir::fir::{CallableDecl, CallableImpl, CallableKind, ItemKind, Lit, PatKind}; use qsc_fir::ty::{Arrow, FunctorSet, FunctorSetValue, Prim, Ty}; use std::rc::Rc; @@ -571,7 +571,7 @@ fn int_lit(package: &mut Package, assigner: &mut Assigner, value: i64) -> ExprId assigner, Ty::Prim(Prim::Int), ExprKind::Lit(Lit::Int(value)), - Span::default(), + PackageSpan::default(), ) } @@ -594,7 +594,7 @@ fn given_var_is_side_effect_free() { &mut assigner, some_local, Ty::Prim(Prim::Int), - Span::default(), + PackageSpan::default(), ); assert!(expr_is_side_effect_free(&package, PackageId::CORE, e)); assert!(expr_is_safe_to_discard(&package, PackageId::CORE, e)); @@ -611,7 +611,7 @@ fn given_tuple_of_lits_is_side_effect_free() { &mut assigner, Ty::Tuple(vec![Ty::Prim(Prim::Int), Ty::Prim(Prim::Int)]), ExprKind::Tuple(vec![a, b]), - Span::default(), + PackageSpan::default(), ); assert!(expr_is_side_effect_free(&package, PackageId::CORE, e)); assert!(expr_is_safe_to_discard(&package, PackageId::CORE, e)); @@ -628,7 +628,7 @@ fn given_array_of_lits_is_side_effect_free() { &mut assigner, Ty::Array(Box::new(Ty::Prim(Prim::Int))), ExprKind::Array(vec![a, b]), - Span::default(), + PackageSpan::default(), ); assert!(expr_is_side_effect_free(&package, PackageId::CORE, e)); assert!(expr_is_safe_to_discard(&package, PackageId::CORE, e)); @@ -639,20 +639,20 @@ fn given_block_with_single_lit_is_side_effect_free() { let mut package = Package::default(); let mut assigner = Assigner::default(); let lit = int_lit(&mut package, &mut assigner, 7); - let stmt = alloc_expr_stmt(&mut package, &mut assigner, lit, Span::default()); + let stmt = alloc_expr_stmt(&mut package, &mut assigner, lit, PackageSpan::default()); let bid = alloc_block( &mut package, &mut assigner, vec![stmt], Ty::Prim(Prim::Int), - Span::default(), + PackageSpan::default(), ); let e = alloc_expr( &mut package, &mut assigner, Ty::Prim(Prim::Int), ExprKind::Block(bid), - Span::default(), + PackageSpan::default(), ); assert!(expr_is_side_effect_free(&package, PackageId::CORE, e)); assert!(expr_is_safe_to_discard(&package, PackageId::CORE, e)); @@ -676,7 +676,7 @@ fn given_closure_is_side_effect_free() { &mut assigner, closure_ty, ExprKind::Closure(vec![some_local], LocalItemId::from(0)), - Span::default(), + PackageSpan::default(), ); assert!(expr_is_side_effect_free(&package, PackageId::CORE, e)); assert!(expr_is_safe_to_discard(&package, PackageId::CORE, e)); @@ -697,7 +697,7 @@ fn given_call_is_not_side_effect_free() { &mut assigner, arrow_ty, ExprKind::Hole, - Span::default(), + PackageSpan::default(), ); let arg = int_lit(&mut package, &mut assigner, 0); let e = alloc_expr( @@ -705,7 +705,7 @@ fn given_call_is_not_side_effect_free() { &mut assigner, Ty::Prim(Prim::Int), ExprKind::Call(callee, arg), - Span::default(), + PackageSpan::default(), ); assert!(!expr_is_side_effect_free(&package, PackageId::CORE, e)); assert!(!expr_is_safe_to_discard(&package, PackageId::CORE, e)); @@ -819,10 +819,16 @@ fn given_assign_is_not_side_effect_free() { &mut assigner, some_local, Ty::Prim(Prim::Bool), - Span::default(), + PackageSpan::default(), + ); + let rhs = alloc_bool_lit(&mut package, &mut assigner, true, PackageSpan::default()); + let e = alloc_assign_expr( + &mut package, + &mut assigner, + lhs, + rhs, + PackageSpan::default(), ); - let rhs = alloc_bool_lit(&mut package, &mut assigner, true, Span::default()); - let e = alloc_assign_expr(&mut package, &mut assigner, lhs, rhs, Span::default()); assert!(!expr_is_side_effect_free(&package, PackageId::CORE, e)); assert!(!expr_is_safe_to_discard(&package, PackageId::CORE, e)); } @@ -837,7 +843,7 @@ fn given_return_is_not_side_effect_free() { &mut assigner, Ty::UNIT, ExprKind::Return(inner), - Span::default(), + PackageSpan::default(), ); assert!(!expr_is_side_effect_free(&package, PackageId::CORE, e)); assert!(!expr_is_safe_to_discard(&package, PackageId::CORE, e)); @@ -853,14 +859,14 @@ fn given_fail_is_not_side_effect_free() { &mut assigner, Ty::Prim(Prim::String), ExprKind::String(vec![StringComponent::Lit(Rc::from("boom"))]), - Span::default(), + PackageSpan::default(), ); let e = alloc_expr( &mut package, &mut assigner, Ty::UNIT, ExprKind::Fail(msg), - Span::default(), + PackageSpan::default(), ); assert!(!expr_is_side_effect_free(&package, PackageId::CORE, e)); assert!(!expr_is_safe_to_discard(&package, PackageId::CORE, e)); @@ -870,20 +876,20 @@ fn given_fail_is_not_side_effect_free() { fn given_while_is_not_side_effect_free() { let mut package = Package::default(); let mut assigner = Assigner::default(); - let cond = alloc_bool_lit(&mut package, &mut assigner, false, Span::default()); + let cond = alloc_bool_lit(&mut package, &mut assigner, false, PackageSpan::default()); let body = alloc_block( &mut package, &mut assigner, Vec::new(), Ty::UNIT, - Span::default(), + PackageSpan::default(), ); let e = alloc_expr( &mut package, &mut assigner, Ty::UNIT, ExprKind::While(cond, body), - Span::default(), + PackageSpan::default(), ); assert!(!expr_is_side_effect_free(&package, PackageId::CORE, e)); assert!(!expr_is_safe_to_discard(&package, PackageId::CORE, e)); @@ -900,7 +906,7 @@ fn given_total_binop_is_side_effect_free_and_safe_to_discard() { &mut assigner, Ty::Prim(Prim::Int), ExprKind::BinOp(BinOp::Add, a, b), - Span::default(), + PackageSpan::default(), ); assert!(expr_is_side_effect_free(&package, PackageId::CORE, e)); assert!(expr_is_safe_to_discard(&package, PackageId::CORE, e)); @@ -917,7 +923,7 @@ fn given_fallible_binop_is_side_effect_free_but_not_safe_to_discard() { &mut assigner, Ty::Prim(Prim::Int), ExprKind::BinOp(BinOp::Div, a, b), - Span::default(), + PackageSpan::default(), ); assert!(expr_is_side_effect_free(&package, PackageId::CORE, e)); assert!(!expr_is_safe_to_discard(&package, PackageId::CORE, e)); @@ -933,7 +939,7 @@ fn given_array_index_is_side_effect_free_but_not_safe_to_discard() { &mut assigner, Ty::Array(Box::new(Ty::Prim(Prim::Int))), ExprKind::Array(vec![value]), - Span::default(), + PackageSpan::default(), ); let index = int_lit(&mut package, &mut assigner, 2); let e = alloc_expr( @@ -941,7 +947,7 @@ fn given_array_index_is_side_effect_free_but_not_safe_to_discard() { &mut assigner, Ty::Prim(Prim::Int), ExprKind::Index(array, index), - Span::default(), + PackageSpan::default(), ); assert!(expr_is_side_effect_free(&package, PackageId::CORE, e)); assert!(!expr_is_safe_to_discard(&package, PackageId::CORE, e)); @@ -958,7 +964,7 @@ fn given_array_repeat_is_side_effect_free_but_not_safe_to_discard() { &mut assigner, Ty::Array(Box::new(Ty::Prim(Prim::Int))), ExprKind::ArrayRepeat(value, count), - Span::default(), + PackageSpan::default(), ); assert!(expr_is_side_effect_free(&package, PackageId::CORE, e)); assert!(!expr_is_safe_to_discard(&package, PackageId::CORE, e)); @@ -974,21 +980,21 @@ fn given_result_equality_is_side_effect_free_but_not_safe_to_discard() { &mut assigner, some_local, Ty::Prim(Prim::Result), - Span::default(), + PackageSpan::default(), ); let rhs = alloc_expr( &mut package, &mut assigner, Ty::Prim(Prim::Result), ExprKind::Lit(Lit::Result(qsc_fir::fir::Result::Zero)), - Span::default(), + PackageSpan::default(), ); let e = alloc_expr( &mut package, &mut assigner, Ty::Prim(Prim::Bool), ExprKind::BinOp(BinOp::Eq, lhs, rhs), - Span::default(), + PackageSpan::default(), ); assert!(expr_is_side_effect_free(&package, PackageId::CORE, e)); assert!(!expr_is_safe_to_discard(&package, PackageId::CORE, e)); @@ -1004,7 +1010,7 @@ fn given_negation_is_side_effect_free_and_safe_to_discard() { &mut assigner, Ty::Prim(Prim::Int), ExprKind::UnOp(UnOp::Neg, operand), - Span::default(), + PackageSpan::default(), ); assert!(expr_is_side_effect_free(&package, PackageId::CORE, e)); assert!(expr_is_safe_to_discard(&package, PackageId::CORE, e)); @@ -1016,7 +1022,7 @@ fn given_if_then_only_is_not_side_effect_free() { // case can run its `then` branch for effect. let mut package = Package::default(); let mut assigner = Assigner::default(); - let cond = alloc_bool_lit(&mut package, &mut assigner, true, Span::default()); + let cond = alloc_bool_lit(&mut package, &mut assigner, true, PackageSpan::default()); let then_expr = int_lit(&mut package, &mut assigner, 1); let e = alloc_if_expr( &mut package, @@ -1025,7 +1031,7 @@ fn given_if_then_only_is_not_side_effect_free() { then_expr, None, Ty::UNIT, - Span::default(), + PackageSpan::default(), ); assert!(!expr_is_side_effect_free(&package, PackageId::CORE, e)); assert!(!expr_is_safe_to_discard(&package, PackageId::CORE, e)); @@ -1259,7 +1265,7 @@ fn given_parallel_of_lit_is_side_effect_free() { &mut assigner, Ty::Prim(Prim::Int), ExprKind::Parallel(None, body), - Span::default(), + PackageSpan::default(), ); assert!(expr_is_side_effect_free(&package, PackageId::CORE, e)); } @@ -1276,7 +1282,7 @@ fn given_parallel_with_limit_of_lits_is_side_effect_free() { &mut assigner, Ty::Prim(Prim::Int), ExprKind::Parallel(Some(limit), body), - Span::default(), + PackageSpan::default(), ); assert!(expr_is_side_effect_free(&package, PackageId::CORE, e)); } @@ -1291,21 +1297,21 @@ fn given_parallel_with_fail_in_body_is_not_side_effect_free() { &mut assigner, Ty::Prim(Prim::String), ExprKind::String(vec![StringComponent::Lit(Rc::from("boom"))]), - Span::default(), + PackageSpan::default(), ); let body = alloc_expr( &mut package, &mut assigner, Ty::UNIT, ExprKind::Fail(fail_expr), - Span::default(), + PackageSpan::default(), ); let e = alloc_expr( &mut package, &mut assigner, Ty::Prim(Prim::Int), ExprKind::Parallel(None, body), - Span::default(), + PackageSpan::default(), ); assert!(!expr_is_side_effect_free(&package, PackageId::CORE, e)); } @@ -1320,14 +1326,14 @@ fn given_parallel_with_fail_in_limit_is_not_side_effect_free() { &mut assigner, Ty::Prim(Prim::String), ExprKind::String(vec![StringComponent::Lit(Rc::from("boom"))]), - Span::default(), + PackageSpan::default(), ); let limit = alloc_expr( &mut package, &mut assigner, Ty::Prim(Prim::Int), ExprKind::Fail(fail_expr), - Span::default(), + PackageSpan::default(), ); let body = int_lit(&mut package, &mut assigner, 42); let e = alloc_expr( @@ -1335,7 +1341,7 @@ fn given_parallel_with_fail_in_limit_is_not_side_effect_free() { &mut assigner, Ty::Prim(Prim::Int), ExprKind::Parallel(Some(limit), body), - Span::default(), + PackageSpan::default(), ); assert!(!expr_is_side_effect_free(&package, PackageId::CORE, e)); } diff --git a/source/compiler/qsc_lowerer/src/lib.rs b/source/compiler/qsc_lowerer/src/lib.rs index 0d6aa177ade..7d90a3d302c 100644 --- a/source/compiler/qsc_lowerer/src/lib.rs +++ b/source/compiler/qsc_lowerer/src/lib.rs @@ -2,6 +2,7 @@ // Licensed under the MIT License. use qsc_data_structures::index_map::IndexMap; +use qsc_data_structures::span::Span; use qsc_fir::assigner::Assigner; use qsc_fir::fir::{ Block, CallableImpl, ExecGraph, ExecGraphDebugNode, ExecGraphExpr, ExecGraphIdx, ExecGraphNode, @@ -25,6 +26,11 @@ pub fn map_fir_package_to_hir(package: fir::PackageId) -> hir::PackageId { hir::PackageId::from(Into::::into(package)) } +#[must_use] +pub fn map_fir_package_span_to_hir(span: fir::PackageSpan) -> hir::PackageSpan { + hir::PackageSpan::new(map_fir_package_to_hir(span.package), span.span) +} + #[must_use] pub fn map_hir_local_item_to_fir(local_item: hir::LocalItemId) -> fir::LocalItemId { fir::LocalItemId::from(Into::::into(local_item)) @@ -154,6 +160,8 @@ pub struct Lowerer { exec_graph: ExecGraphBuilder, fir_increment: FirIncrement, parallel_count: u32, + /// The package every node lowered by this instance belongs to. + package_id: fir::PackageId, } impl Default for Lowerer { @@ -175,9 +183,14 @@ impl Lowerer { exec_graph: ExecGraphBuilder::default(), fir_increment: FirIncrement::default(), parallel_count: 0, + package_id: fir::PackageId::default(), } } + fn pkg_span(&self, span: Span) -> fir::PackageSpan { + fir::PackageSpan::new(self.package_id, span) + } + pub fn take_exec_graph(&mut self) -> ExecGraph { self.exec_graph.take() } @@ -193,7 +206,10 @@ impl Lowerer { &mut self, package: &hir::Package, store: &fir::PackageStore, + package_id: fir::PackageId, ) -> fir::Package { + // Every node lowered below is tagged with this package. + self.package_id = package_id; let entry = package.entry.as_ref().map(|e| self.lower_expr(e)); let entry_exec_graph = self.exec_graph.take(); let items: IndexMap = package @@ -225,6 +241,7 @@ impl Lowerer { let stmts: IndexMap<_, _> = self.stmts.drain().collect(); let package = fir::Package { + id: self.package_id, items, entry, entry_exec_graph, @@ -246,6 +263,9 @@ impl Lowerer { fir_package: &mut fir::Package, hir_package: &hir::Package, ) { + // Nodes added by this increment belong to the package being updated. + self.package_id = fir_package.id; + // Clear the previous increment since we are about to take a new one. self.fir_increment = FirIncrement::default(); @@ -345,7 +365,7 @@ impl Lowerer { let attrs = lower_attrs(&item.attrs); fir::Item { id: lower_local_item_id(item.id), - span: item.span, + span: self.pkg_span(item.span), parent: item.parent.map(lower_local_item_id), doc: Rc::clone(&item.doc), attrs, @@ -399,7 +419,7 @@ impl Lowerer { } fir::CallableDecl { - span: decl.span, + span: self.pkg_span(decl.span), kind, name, generics, @@ -418,7 +438,7 @@ impl Lowerer { let input = pat.as_ref().map(|p| self.lower_spec_decl_pat(p)); let block = self.lower_block(block); fir::SpecDecl { - span: decl.span, + span: self.pkg_span(decl.span), block, input, exec_graph: self.exec_graph.take(), @@ -439,7 +459,12 @@ impl Lowerer { hir::PatKind::Err => unreachable!("error pat should not be present"), }; - let pat = fir::Pat { id, span, ty, kind }; + let pat = fir::Pat { + id, + span: self.pkg_span(span), + ty, + kind, + }; self.pats.insert(id, pat); id } @@ -464,7 +489,7 @@ impl Lowerer { ); let block = fir::Block { id, - span: block.span, + span: self.pkg_span(block.span), ty: self.lower_ty(&block.ty), stmts: block.stmts.iter().map(|s| self.lower_stmt(s)).collect(), }; @@ -501,7 +526,7 @@ impl Lowerer { }; let stmt = fir::Stmt { id, - span: stmt.span, + span: self.pkg_span(stmt.span), kind, exec_graph_range: graph_start_idx..self.exec_graph.len(), }; @@ -947,7 +972,7 @@ impl Lowerer { let expr = fir::Expr { id, - span: expr.span, + span: self.pkg_span(expr.span), ty, kind, exec_graph_range: graph_start_idx..self.exec_graph.len(), @@ -958,7 +983,7 @@ impl Lowerer { fn lower_field_assign(&mut self, field_assign: &hir::FieldAssign) -> fir::FieldAssign { fir::FieldAssign { - span: field_assign.span, + span: self.pkg_span(field_assign.span), field: lower_field(&field_assign.field), value: self.lower_expr(&field_assign.value), } @@ -992,7 +1017,7 @@ impl Lowerer { let pat = fir::Pat { id, - span: pat.span, + span: self.pkg_span(pat.span), ty, kind, }; @@ -1019,7 +1044,7 @@ impl Lowerer { fn lower_ident(&mut self, ident: &hir::Ident) -> fir::Ident { fir::Ident { id: self.lower_local_id(ident.id), - span: ident.span, + span: self.pkg_span(ident.span), name: ident.name.clone(), } } diff --git a/source/compiler/qsc_partial_eval/src/lib.rs b/source/compiler/qsc_partial_eval/src/lib.rs index a97bfde4211..3f63b44c4eb 100644 --- a/source/compiler/qsc_partial_eval/src/lib.rs +++ b/source/compiler/qsc_partial_eval/src/lib.rs @@ -41,7 +41,7 @@ use qsc_fir::{ }; pub use qsc_data_structures::intrinsic_names::is_codegen_noop_intrinsic; -use qsc_lowerer::{map_fir_package_to_hir, map_hir_package_to_fir}; +use qsc_lowerer::{map_fir_package_span_to_hir, map_hir_package_to_fir}; use qsc_rca::{ ComputeKind, ComputePropertiesLookup, ItemComputeProperties, PackageStoreComputeProperties, RuntimeFeatureFlags, ValueKind, @@ -167,10 +167,7 @@ impl Error { #[must_use] pub fn span(&self) -> PackageSpan { match self { - Self::CapabilityError(e) => { - let fir_span = e.span(); - PackageSpan::new(map_fir_package_to_hir(fir_span.package), fir_span.span) - } + Self::CapabilityError(e) => map_fir_package_span_to_hir(e.span()), Self::UnexpectedDynamicValue(span) | Self::UnsupportedCustomIntrinsicType(_, span) | Self::EvaluationFailed(_, span) @@ -406,7 +403,7 @@ impl<'a> PartialEvaluator<'a> { let var = Variable { name: ident.name.clone(), value: value.clone(), - span: ident.span, + span: ident.span.span, }; let scope = self.eval_context.get_current_scope_mut(); scope.env.bind_variable_in_top_frame(ident.id, var); @@ -432,13 +429,11 @@ impl<'a> PartialEvaluator<'a> { input_type.push(map_fir_type_to_rir_type(&input_param.ty).map_err(|msg| { Error::UnsupportedCustomIntrinsicType( msg, - PackageSpan { - package: map_fir_package_to_hir(store_item_id.package), - span: self - .package_store + map_fir_package_span_to_hir( + self.package_store .get_pat((store_item_id.package, input_param.pat).into()) .span, - }, + ), ) })?); } @@ -449,10 +444,7 @@ impl<'a> PartialEvaluator<'a> { map_fir_type_to_rir_type(&callable_decl.output).map_err(|msg| { Error::UnsupportedCustomIntrinsicType( msg, - PackageSpan { - package: map_fir_package_to_hir(self.get_current_package_id()), - span: callable_decl.span, - }, + map_fir_package_span_to_hir(callable_decl.span), ) })?, ) @@ -489,21 +481,12 @@ impl<'a> PartialEvaluator<'a> { let local_span = match &expr.kind { // Special handling for compiler generated entry expressions that come from the `@EntryPoint` // attributed callable. - ExprKind::Call(callee, _) if expr.span == Span::default() => { + ExprKind::Call(callee, _) if expr.span.span == Span::default() => { self.get_expr(*callee).span } _ => expr.span, }; - let hir_package_id = map_fir_package_to_hir( - self.entry - .expect("should have entry when getting entry expr span") - .expr - .package, - ); - PackageSpan { - package: hir_package_id, - span: local_span, - } + map_fir_package_span_to_hir(local_span) } fn extract_program( @@ -581,10 +564,7 @@ impl<'a> PartialEvaluator<'a> { self.extract_program( ret_val, output_ty, - PackageSpan { - package: map_fir_package_to_hir(callable.package), - span: callable_decl.span, - }, + map_fir_package_span_to_hir(callable_decl.span), ) } @@ -1362,7 +1342,7 @@ impl<'a> PartialEvaluator<'a> { let closure = resolve_closure( &self.eval_context.get_current_scope().env, self.get_current_package_id(), - expr.span, + map_fir_package_span_to_hir(expr.span), args, *callable, ) @@ -1800,10 +1780,7 @@ impl<'a> PartialEvaluator<'a> { if !missing_features.is_empty() && let Some(error) = generate_errors_from_runtime_features( missing_features, - fir::PackageSpan::new( - self.get_current_package_id(), - self.get_expr(call_expr_id).span, - ), + self.get_expr(call_expr_id).span, ) .drain(..) .next() @@ -2393,7 +2370,7 @@ impl<'a> PartialEvaluator<'a> { let variable = Variable { name, value: Value::Var(eval_var), - span, + span: span.span, }; body_args.push(Arg::Var(local_var_id, variable)); } else { @@ -3488,11 +3465,7 @@ impl<'a> PartialEvaluator<'a> { fn get_expr_package_span(&self, id: ExprId) -> PackageSpan { let fir_package_id = self.get_current_package_id(); let expr = self.package_store.get_expr((fir_package_id, id).into()); - let hir_package_id = map_fir_package_to_hir(fir_package_id); - PackageSpan { - package: hir_package_id, - span: expr.span, - } + map_fir_package_span_to_hir(expr.span) } fn get_pat(&self, id: PatId) -> &'a Pat { @@ -3873,7 +3846,7 @@ impl<'a> PartialEvaluator<'a> { let variable = Variable { name: ident.name.clone(), value: ctls_value, - span: ident.span, + span: ident.span.span, }; let ctl_arg = Arg::Var(ident.id, variable); Some(ctl_arg) @@ -3907,7 +3880,7 @@ impl<'a> PartialEvaluator<'a> { let variable = Variable { name: ident.name.clone(), value, - span: ident.span, + span: ident.span.span, }; (vec![Arg::Var(ident.id, variable)], arrays) } @@ -3966,14 +3939,9 @@ impl<'a> PartialEvaluator<'a> { if remaining_stmt_count > 0 && current_scope.is_currently_evaluating_branch() { let return_stmt = self.get_stmt(return_stmt_id.expect("a return statement ID must have been set")); - let hir_package_id = map_fir_package_to_hir(self.get_current_package_id()); - let return_stmt_package_span = PackageSpan { - package: hir_package_id, - span: return_stmt.span, - }; Err(Error::Unimplemented( "early return".to_string(), - return_stmt_package_span, + map_fir_package_span_to_hir(return_stmt.span), )) } else { Ok(last_control_flow) diff --git a/source/compiler/qsc_partial_eval/src/tests/misc.rs b/source/compiler/qsc_partial_eval/src/tests/misc.rs index e1fc66ccf86..1910f1ffe3f 100644 --- a/source/compiler/qsc_partial_eval/src/tests/misc.rs +++ b/source/compiler/qsc_partial_eval/src/tests/misc.rs @@ -4,13 +4,17 @@ #![allow(clippy::needless_raw_string_hashes, clippy::similar_names)] use crate::tests::get_rir_program_with_adaptive_profile; +use crate::{Error, PartialEvalConfig, partially_evaluate}; use super::{ - assert_block_instructions, assert_blocks, assert_callable, assert_error, + CompilationContext, assert_block_instructions, assert_blocks, assert_callable, assert_error, get_partial_evaluation_error, get_rir_program, }; use expect_test::expect; use indoc::indoc; +use qsc_data_structures::target::{Profile, TargetCapabilityFlags}; +use qsc_fir::fir::{ExprKind, PackageId}; +use qsc_lowerer::{map_fir_package_to_hir, map_hir_package_to_fir}; use qsc_rir::rir::{BlockId, CallableId}; #[test] @@ -628,6 +632,72 @@ fn evaluation_error_within_stdlib_yield_correct_package_span() { ); } +#[test] +fn partial_evaluation_error_uses_expr_source_package_after_relocation() { + let source = indoc! { + r#" + namespace Test { + import Std.Arrays.*; + @EntryPoint() + operation Main() : Int[] { + use q = Qubit(); + let a = if MResetZ(q) == One { + 1 + } else { + 0 + }; + let b = [(a, a)]; + ForEach(t => Fst(t), b) + } + } + "#, + }; + let capabilities: TargetCapabilityFlags = Profile::AdaptiveRIF.into(); + let mut context = CompilationContext::new(source, capabilities); + let Err(original_error) = partially_evaluate( + &context.fir_store, + &context.compute_properties, + &context.entry, + capabilities, + PartialEvalConfig { + generate_debug_metadata: false, + }, + ) else { + panic!("partial evaluation should fail"); + }; + let original_span = original_error.span(); + let storage_package = map_hir_package_to_fir(original_span.package); + let source_package = PackageId::CORE; + assert_ne!(storage_package, source_package); + + let relocated_expr = context + .fir_store + .get_mut(storage_package) + .exprs + .values_mut() + .find(|expr| { + matches!(&expr.kind, ExprKind::Call(..)) && expr.span.span == original_span.span + }) + .expect("failing call expression should exist"); + relocated_expr.span.package = source_package; + + let Err(error) = partially_evaluate( + &context.fir_store, + &context.compute_properties, + &context.entry, + capabilities, + PartialEvalConfig { + generate_debug_metadata: false, + }, + ) else { + panic!("partial evaluation should still fail after relocation"); + }; + let span = error.span(); + assert!(matches!(error, Error::UnexpectedDynamicValue(_))); + assert_eq!(span.package, map_fir_package_to_hir(source_package)); + assert_eq!(span.span, original_span.span); +} + #[test] fn string_interpolation_with_side_effects_captures_side_effects() { let program = get_rir_program(indoc! { diff --git a/source/compiler/qsc_passes/src/capabilitiesck.rs b/source/compiler/qsc_passes/src/capabilitiesck.rs index f4d0f013981..54574b50e19 100644 --- a/source/compiler/qsc_passes/src/capabilitiesck.rs +++ b/source/compiler/qsc_passes/src/capabilitiesck.rs @@ -47,7 +47,7 @@ pub fn lower_store( let mut last_assigner = qsc_fir::assigner::Assigner::new(); for (id, unit) in package_store { let mut lowerer = qsc_lowerer::Lowerer::new(); - let package = lowerer.lower_package(&unit.package, &fir_store); + let package = lowerer.lower_package(&unit.package, &fir_store, map_hir_package_to_fir(id)); fir_store.insert(map_hir_package_to_fir(id), package); last_assigner = lowerer.into_assigner(); } @@ -66,7 +66,6 @@ pub fn run_rca_pass( let package_compute_properties = compute_properties.get(package_id, false); let mut errors = check_supported_capabilities( fir_package, - package_id, package_compute_properties, capabilities, fir_store, @@ -86,14 +85,12 @@ pub fn run_rca_pass( #[must_use] pub fn check_supported_capabilities( package: &Package, - package_id: PackageId, compute_properties: &PackageComputeProperties, capabilities: TargetCapabilityFlags, store: &qsc_fir::fir::PackageStore, ) -> Vec { let checker = Checker { package, - package_id, compute_properties, target_capabilities: capabilities, current_callable: None, @@ -112,7 +109,6 @@ pub fn check_supported_capabilities( #[must_use] pub fn check_supported_capabilities_for_callable( package: &Package, - package_id: PackageId, compute_properties: &PackageComputeProperties, callable: LocalItemId, capabilities: TargetCapabilityFlags, @@ -120,7 +116,6 @@ pub fn check_supported_capabilities_for_callable( ) -> Vec { let checker = Checker { package, - package_id, compute_properties, target_capabilities: capabilities, current_callable: None, @@ -133,7 +128,6 @@ pub fn check_supported_capabilities_for_callable( struct Checker<'a> { package: &'a Package, - package_id: PackageId, compute_properties: &'a PackageComputeProperties, target_capabilities: TargetCapabilityFlags, current_callable: Option, @@ -275,7 +269,7 @@ impl<'a> Checker<'a> { fn check_entry_expr(&mut self, expr_id: ExprId) { let expr = self.get_expr(expr_id); - if expr.span == Span::default() { + if expr.span.span == Span::default() { // This is an auto-generated entry expression, so we only need to verify the output recording flags. self.check_output_recording(expr); } else { @@ -303,7 +297,7 @@ impl<'a> Checker<'a> { let expr = self.get_expr(expr_id); if !missing_features.is_empty() { self.missing_features_map - .entry(PackageSpan::new(self.package_id, expr.span)) + .entry(expr.span) .and_modify(|f| *f |= missing_features) .or_insert(missing_features); } @@ -370,7 +364,7 @@ impl<'a> Checker<'a> { }; let output_reporting_span = match &expr.kind { - ExprKind::Call(callee_expr, _) if expr.span == Span::default() => { + ExprKind::Call(callee_expr, _) if expr.span.span == Span::default() => { // Since this is auto-generated, use the callee expression span. self.get_expr(*callee_expr).span } @@ -383,7 +377,7 @@ impl<'a> Checker<'a> { & RuntimeFeatureFlags::output_recording_flags(); if !missing_features.is_empty() { self.missing_features_map - .entry(PackageSpan::new(self.package_id, output_reporting_span)) + .entry(output_reporting_span) .and_modify(|f| *f |= missing_features) .or_insert(missing_features); } @@ -396,7 +390,7 @@ impl<'a> Checker<'a> { ) & RuntimeFeatureFlags::output_recording_flags(); if !missing_features.is_empty() { self.missing_features_map - .entry(PackageSpan::new(self.package_id, callable_decl.name.span)) + .entry(callable_decl.name.span) .and_modify(|f| *f |= missing_features) .or_insert(missing_features); } @@ -431,8 +425,10 @@ impl<'a> Checker<'a> { let mut missing_features_map = self.missing_features_map.drain().collect::>(); missing_features_map.sort_unstable(); for (span, missing_features) in missing_features_map { - let mut span_errors = generate_errors_from_runtime_features(missing_features, span); - errors.append(&mut span_errors); + errors.append(&mut generate_errors_from_runtime_features( + missing_features, + span, + )); } errors } diff --git a/source/compiler/qsc_passes/src/capabilitiesck/tests_common.rs b/source/compiler/qsc_passes/src/capabilitiesck/tests_common.rs index 739624b47ce..8bbf67d82a9 100644 --- a/source/compiler/qsc_passes/src/capabilitiesck/tests_common.rs +++ b/source/compiler/qsc_passes/src/capabilitiesck/tests_common.rs @@ -18,7 +18,6 @@ pub fn check(source: &str, expect: &Expect, capabilities: TargetCapabilityFlags) let (package, compute_properties) = compilation_context.get_package_compute_properties_tuple(); let errors = check_supported_capabilities( package, - compilation_context.package_id, compute_properties, capabilities, &compilation_context.fir_store, @@ -31,7 +30,6 @@ pub fn check_for_exe(source: &str, expect: &Expect, capabilities: TargetCapabili let (package, compute_properties) = compilation_context.get_package_compute_properties_tuple(); let errors = check_supported_capabilities( package, - compilation_context.package_id, compute_properties, capabilities, &compilation_context.fir_store, @@ -47,7 +45,6 @@ pub fn capability_error_kinds(source: &str, capabilities: TargetCapabilityFlags) let (package, compute_properties) = compilation_context.get_package_compute_properties_tuple(); let errors = check_supported_capabilities( package, - compilation_context.package_id, compute_properties, capabilities, &compilation_context.fir_store, @@ -73,7 +70,7 @@ fn lower_hir_package_store( ) -> PackageStore { let mut fir_store = PackageStore::new(); for (id, unit) in hir_package_store { - let pkg = lowerer.lower_package(&unit.package, &fir_store); + let pkg = lowerer.lower_package(&unit.package, &fir_store, map_hir_package_to_fir(id)); fir_store.insert(map_hir_package_to_fir(id), pkg); } fir_store diff --git a/source/compiler/qsc_passes/src/lib.rs b/source/compiler/qsc_passes/src/lib.rs index ead431fe49c..036001497c3 100644 --- a/source/compiler/qsc_passes/src/lib.rs +++ b/source/compiler/qsc_passes/src/lib.rs @@ -298,7 +298,6 @@ pub fn run_rca_for_callable( let package_compute_properties = compute_properties.get(callable.package, false); let capabilities_errors = check_supported_capabilities_for_callable( package, - callable.package, package_compute_properties, callable.item, capabilities, diff --git a/source/compiler/qsc_rca/src/tests.rs b/source/compiler/qsc_rca/src/tests.rs index dc2fe23c926..a8c63b6dd59 100644 --- a/source/compiler/qsc_rca/src/tests.rs +++ b/source/compiler/qsc_rca/src/tests.rs @@ -227,7 +227,7 @@ fn lower_hir_package_store(hir_package_store: &HirPackageStore) -> PackageStore let mut lowerer = Lowerer::new(); fir_store.insert( map_hir_package_to_fir(id), - lowerer.lower_package(&unit.package, &fir_store), + lowerer.lower_package(&unit.package, &fir_store, map_hir_package_to_fir(id)), ); } fir_store diff --git a/source/language_service/src/compilation.rs b/source/language_service/src/compilation.rs index d8849bb0fcb..3470368b01e 100644 --- a/source/language_service/src/compilation.rs +++ b/source/language_service/src/compilation.rs @@ -3,8 +3,8 @@ use log::trace; use qsc::{ - CompileUnit, LanguageFeatures, PackageStore, PackageType, PassContext, SourceMap, Span, ast, - compile, + CompileUnit, LanguageFeatures, PackageStore, PackageType, PassContext, PassError, SourceMap, + Span, ast, compile, display::Lookup, error::WithSource, hir::{self, PackageId, Res}, @@ -445,7 +445,16 @@ fn run_fir_passes( PassContext::run_fir_passes_on_fir(&fir_store, fir_package_id, target_profile.into()); if let Err(caps_errors) = caps_results { for err in caps_errors { - let err = WithSource::from_map(&unit.sources, compile::ErrorKind::Pass(err)); + let sources = if let PassError::CapabilitiesCk(err) = &err { + let err_package = err.span().package; + &package_store + .get((Into::::into(err_package)).into()) + .expect("package for error should exist in store") + .sources + } else { + &unit.sources + }; + let err = WithSource::from_map(sources, compile::ErrorKind::Pass(err)); errors.push(err); } } diff --git a/source/qdk_openqasm/src/vendor/span.rs b/source/qdk_openqasm/src/vendor/span.rs index 8ea8d07b44a..60a634eb1ae 100644 --- a/source/qdk_openqasm/src/vendor/span.rs +++ b/source/qdk_openqasm/src/vendor/span.rs @@ -33,6 +33,25 @@ impl

PackageSpan

{ } } +/// Synthetic nodes with no source text default to the first package. +impl Default for PackageSpan

{ + fn default() -> Self { + Self { + package: P::default(), + span: Span::default(), + } + } +} + +/// Lets a package-qualified span be read like the bare `Span` it wraps. +impl

std::ops::Deref for PackageSpan

{ + type Target = Span; + + fn deref(&self) -> &Span { + &self.span + } +} + impl Span { /// Returns true if the position is within the span. Meaning it is in the /// right open interval `[self.lo, self.hi)`.