on master help sign in
Trace the full-read warning back to the source declaration

The warning pointed at the read site only. Now it also labels the *name declaration, so the user sees both where the relation is read in full and where it is declared. source_decl_spans maps each source to its SourceDecl span. Suite 291/0.

commita7f2c1aac27d1b87b2469b260da890f3b9ea7649 authoriko <mail@iko.soy> dateSun 30 Aug 2026, 10:16 (1 month ago) parent0d8dada
1 file changed+16
crates/knot-compiler/src/codegen.rs+16
crates/knot-compiler/src/codegen.rs+16
@@ -248,6 +248,10 @@ pub struct Codegen<M: cranelift_module::Module = ObjectModule> {
248248 // Surfaced as a build-time INFO diagnostic naming each such table.
249249 in_memory_source_reads: HashMap<String, ast::Span>,
250250
251+ /// Source name → its `*name` declaration span (for the full-read warning's
252+ /// trace back to where the relation is declared).
253+ source_decl_spans: HashMap<String, ast::Span>,
254+
251255 // Resolved monad types for desugared do-blocks (from type inference)
252256 monad_info: MonadInfo,
253257
@@ -1110,6 +1114,10 @@ fn compile_inner<M: cranelift_module::Module>(
11101114 ));
11111115 for (name, span) in &entries {
11121116 diag = diag.label(**span, format!("`*{name}` is read in full here"));
1117+ // Trace back to the source's declaration.
1118+ if let Some(decl_span) = cg.source_decl_spans.get(*name) {
1119+ diag = diag.label(*decl_span, format!("`*{name}` is declared here"));
1120+ }
11131121 }
11141122 diag = diag
11151123 .note("to read only part of it, filter or narrow the query (a `where` clause, `base.take`) so only the matching rows are loaded")
@@ -1462,6 +1470,7 @@ impl<M: cranelift_module::Module> Codegen<M> {
14621470 capture_env_in_progress: std::collections::HashSet::new(),
14631471 relational_do_spans: HashSet::new(),
14641472 in_memory_source_reads: HashMap::new(),
1473+ source_decl_spans: HashMap::new(),
14651474 monad_info: HashMap::new(),
14661475 nullable_ctors: HashMap::new(),
14671476 io_functions: HashSet::new(),
@@ -2514,6 +2523,13 @@ impl<M: cranelift_module::Module> Codegen<M> {
25142523 }
25152524 }
25162525 }
2526+ // Map each source to its `*name` declaration span, for the full-read
2527+ // warning's trace back to where the relation is declared.
2528+ for decl in decl_views(program) {
2529+ if matches!(decl.kind, DeclViewKind::Source { .. }) {
2530+ self.source_decl_spans.insert(decl.name.to_string(), decl.span);
2531+ }
2532+ }
25172533 // Register built-in ADT constructors so trait dispatchers can find their
25182534 // ctor lists. Inference treats these as built-in types (see
25192535 // `register_builtins` in infer.rs), so they don't appear as user-source