Skip to content

Commit 2d81c38

Browse files
authored
refactor: enforce lifetime naming convention (#212)
1 parent d78b3b0 commit 2d81c38

8 files changed

Lines changed: 40 additions & 30 deletions

File tree

AGENTS.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,16 @@ cargo run -p plotnik-cli -- langs
259259
- Comments for seniors, not juniors
260260
- Rust 2024 `let` chains: `if let Some(x) = a && let Some(y) = b { ... }`
261261

262+
## Lifetime Conventions
263+
264+
| Lifetime | Meaning |
265+
| -------- | ------------------------------------------------ |
266+
| `'q` | Query source string (`.ptk` file content) |
267+
| `'d` | Diagnostics reference |
268+
| `'s` | Source code string (tree-sitter input) |
269+
| `'t` | Parsed tree-sitter tree |
270+
| `'a` | Any other (generic borrows, bytecode views) |
271+
262272
# Testing Rules
263273

264274
Code: `foo.rs` → tests: `foo_tests.rs` (include via `#[cfg(test)] mod foo_tests;`)

crates/plotnik-lib/src/diagnostics/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ pub struct Diagnostics {
3333
}
3434

3535
#[must_use = "diagnostic not emitted, call .emit()"]
36-
pub struct DiagnosticBuilder<'a> {
37-
diagnostics: &'a mut Diagnostics,
36+
pub struct DiagnosticBuilder<'d> {
37+
diagnostics: &'d mut Diagnostics,
3838
message: DiagnosticMessage,
3939
}
4040

@@ -169,12 +169,12 @@ impl Diagnostics {
169169
}
170170

171171
/// Create a printer with a source map (multi-file support).
172-
pub fn printer<'a>(&self, sources: &'a SourceMap) -> DiagnosticsPrinter<'a> {
172+
pub fn printer<'q>(&self, sources: &'q SourceMap) -> DiagnosticsPrinter<'q> {
173173
DiagnosticsPrinter::new(self.messages.clone(), sources)
174174
}
175175

176176
/// Filtered printer with source map (cascading errors suppressed).
177-
pub fn filtered_printer<'a>(&self, sources: &'a SourceMap) -> DiagnosticsPrinter<'a> {
177+
pub fn filtered_printer<'q>(&self, sources: &'q SourceMap) -> DiagnosticsPrinter<'q> {
178178
DiagnosticsPrinter::new(self.filtered(), sources)
179179
}
180180

@@ -203,7 +203,7 @@ impl Diagnostics {
203203
}
204204
}
205205

206-
impl<'a> DiagnosticBuilder<'a> {
206+
impl<'d> DiagnosticBuilder<'d> {
207207
/// Provide custom detail for this diagnostic, rendered using the kind's template.
208208
pub fn message(mut self, msg: impl Into<String>) -> Self {
209209
let detail = msg.into();

crates/plotnik-lib/src/diagnostics/printer.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ use rowan::TextRange;
88
use super::SourceMap;
99
use super::message::{DiagnosticMessage, Severity};
1010

11-
pub struct DiagnosticsPrinter<'a> {
11+
pub struct DiagnosticsPrinter<'q> {
1212
diagnostics: Vec<DiagnosticMessage>,
13-
sources: &'a SourceMap,
13+
sources: &'q SourceMap,
1414
colored: bool,
1515
}
1616

17-
impl<'a> DiagnosticsPrinter<'a> {
18-
pub(crate) fn new(diagnostics: Vec<DiagnosticMessage>, sources: &'a SourceMap) -> Self {
17+
impl<'q> DiagnosticsPrinter<'q> {
18+
pub(crate) fn new(diagnostics: Vec<DiagnosticMessage>, sources: &'q SourceMap) -> Self {
1919
Self {
2020
diagnostics,
2121
sources,
@@ -112,7 +112,7 @@ impl<'a> DiagnosticsPrinter<'a> {
112112
Ok(())
113113
}
114114

115-
fn source_path(&self, source: crate::query::SourceId) -> Option<&'a str> {
115+
fn source_path(&self, source: crate::query::SourceId) -> Option<&'q str> {
116116
self.sources.path(source)
117117
}
118118
}

crates/plotnik-lib/src/parser/ast.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,19 @@
66
//! ## String Lifetime Limitation
77
//!
88
//! `SyntaxToken::text()` returns `&str` tied to the token's lifetime, not to the
9-
//! source `&'src str`. This is a rowan design: tokens store interned strings, not
9+
//! source `&'q str`. This is a rowan design: tokens store interned strings, not
1010
//! spans into the original source.
1111
//!
1212
//! When building data structures that need source-lifetime strings (e.g.,
13-
//! `SymbolTable<'src>`), use [`token_src`] instead of `token.text()`.
13+
//! `SymbolTable<'q>`), use [`token_src`] instead of `token.text()`.
1414
1515
use super::cst::{SyntaxKind, SyntaxNode, SyntaxToken};
1616
use rowan::TextRange;
1717

1818
/// Extracts token text with source lifetime.
1919
///
20-
/// Use this instead of `token.text()` when you need `&'src str`.
21-
pub fn token_src<'src>(token: &SyntaxToken, source: &'src str) -> &'src str {
20+
/// Use this instead of `token.text()` when you need `&'q str`.
21+
pub fn token_src<'q>(token: &SyntaxToken, source: &'q str) -> &'q str {
2222
let range = token.text_range();
2323
&source[range.start().into()..range.end().into()]
2424
}

crates/plotnik-lib/src/parser/core.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@ pub(super) struct OpenDelimiter {
2222
}
2323

2424
/// Trivia tokens are buffered and flushed when starting a new node.
25-
pub struct Parser<'src, 'diag> {
26-
pub(super) source: &'src str,
25+
pub struct Parser<'q, 'd> {
26+
pub(super) source: &'q str,
2727
pub(super) source_id: SourceId,
2828
pub(super) tokens: Vec<Token>,
2929
pub(super) pos: usize,
3030
pub(super) trivia_buffer: Vec<Token>,
3131
pub(super) builder: GreenNodeBuilder<'static>,
32-
pub(super) diagnostics: &'diag mut Diagnostics,
32+
pub(super) diagnostics: &'d mut Diagnostics,
3333
pub(super) depth: u32,
3434
pub(super) last_diagnostic_pos: Option<TextSize>,
3535
pub(super) delimiter_stack: Vec<OpenDelimiter>,
@@ -40,12 +40,12 @@ pub struct Parser<'src, 'diag> {
4040
fatal_error: Option<Error>,
4141
}
4242

43-
impl<'src, 'diag> Parser<'src, 'diag> {
43+
impl<'q, 'd> Parser<'q, 'd> {
4444
pub fn new(
45-
source: &'src str,
45+
source: &'q str,
4646
source_id: SourceId,
4747
tokens: Vec<Token>,
48-
diagnostics: &'diag mut Diagnostics,
48+
diagnostics: &'d mut Diagnostics,
4949
fuel: u32,
5050
max_depth: u32,
5151
) -> Self {

crates/plotnik-lib/src/parser/lexer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,6 @@ fn split_string_literal(source: &str, span: Range<usize>, tokens: &mut Vec<Token
109109

110110
/// Retrieves the text slice for a token. O(1) slice into source.
111111
#[inline]
112-
pub fn token_text<'src>(source: &'src str, token: &Token) -> &'src str {
112+
pub fn token_text<'q>(source: &'q str, token: &Token) -> &'q str {
113113
&source[std::ops::Range::<usize>::from(token.span)]
114114
}

crates/plotnik-lib/src/query/query.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,10 @@ pub type Query = QueryAnalyzed;
154154
/// Bundles references to the three main analysis artifacts that downstream
155155
/// modules (compile, emit) commonly need together.
156156
#[derive(Clone, Copy)]
157-
pub struct QueryContext<'a> {
158-
pub interner: &'a Interner,
159-
pub type_ctx: &'a TypeContext,
160-
pub symbol_table: &'a SymbolTable,
157+
pub struct QueryContext<'q> {
158+
pub interner: &'q Interner,
159+
pub type_ctx: &'q TypeContext,
160+
pub symbol_table: &'q SymbolTable,
161161
}
162162

163163
pub struct QueryAnalyzed {

crates/plotnik-lib/src/query/source_map.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,15 @@ impl SourceKind {
3131

3232
/// A borrowed view of a source: id, kind, and content.
3333
#[derive(Clone, Debug)]
34-
pub struct Source<'a> {
34+
pub struct Source<'q> {
3535
pub id: SourceId,
36-
pub kind: &'a SourceKind,
37-
pub content: &'a str,
36+
pub kind: &'q SourceKind,
37+
pub content: &'q str,
3838
}
3939

40-
impl<'a> Source<'a> {
40+
impl<'q> Source<'q> {
4141
/// Returns the content string.
42-
pub fn as_str(&self) -> &'a str {
42+
pub fn as_str(&self) -> &'q str {
4343
self.content
4444
}
4545
}

0 commit comments

Comments
 (0)