summaryrefslogtreecommitdiff
path: root/crates/typst-utils
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2025-06-12 16:11:18 +0200
committerGitHub <noreply@github.com>2025-06-12 14:11:18 +0000
commit64d0a564bf92b6540955d820149e62e7fab394c5 (patch)
treee15c415d0905633c5ae4abfae4f3c7d52a2f5bbe /crates/typst-utils
parent4a638f41cde37312390359a5345073bed5835ae6 (diff)
Better error message for compile time string interning failure (#6439)
Diffstat (limited to 'crates/typst-utils')
-rw-r--r--crates/typst-utils/src/pico.rs45
1 files changed, 36 insertions, 9 deletions
diff --git a/crates/typst-utils/src/pico.rs b/crates/typst-utils/src/pico.rs
index ce43667e..3aa4570f 100644
--- a/crates/typst-utils/src/pico.rs
+++ b/crates/typst-utils/src/pico.rs
@@ -72,7 +72,7 @@ impl PicoStr {
pub const fn constant(string: &'static str) -> PicoStr {
match PicoStr::try_constant(string) {
Ok(value) => value,
- Err(err) => panic!("{}", err.message()),
+ Err(err) => failed_to_compile_time_intern(err, string),
}
}
@@ -190,15 +190,9 @@ mod bitcode {
impl EncodingError {
pub const fn message(&self) -> &'static str {
match self {
- Self::TooLong => {
- "the maximum auto-internible string length is 12. \
- you can add an exception to typst-utils/src/pico.rs \
- to intern longer strings."
- }
+ Self::TooLong => "the maximum auto-internible string length is 12",
Self::BadChar => {
- "can only auto-intern the chars 'a'-'z', '1'-'4', and '-'. \
- you can add an exception to typst-utils/src/pico.rs \
- to intern other strings."
+ "can only auto-intern the chars 'a'-'z', '1'-'4', and '-'"
}
}
}
@@ -356,6 +350,39 @@ impl Hash for ResolvedPicoStr {
}
}
+/// The error when a string could not be interned at compile time. Because the
+/// normal formatting machinery is not available at compile time, just producing
+/// the message is a bit involved ...
+#[track_caller]
+const fn failed_to_compile_time_intern(
+ error: bitcode::EncodingError,
+ string: &'static str,
+) -> ! {
+ const CAPACITY: usize = 512;
+ const fn push((buf, i): &mut ([u8; CAPACITY], usize), s: &str) {
+ let mut k = 0;
+ while k < s.len() && *i < buf.len() {
+ buf[*i] = s.as_bytes()[k];
+ k += 1;
+ *i += 1;
+ }
+ }
+
+ let mut dest = ([0; CAPACITY], 0);
+ push(&mut dest, "failed to compile-time intern string \"");
+ push(&mut dest, string);
+ push(&mut dest, "\". ");
+ push(&mut dest, error.message());
+ push(&mut dest, ". you can add an exception to ");
+ push(&mut dest, file!());
+ push(&mut dest, " to intern longer strings.");
+
+ let (slice, _) = dest.0.split_at(dest.1);
+ let Ok(message) = std::str::from_utf8(slice) else { panic!() };
+
+ panic!("{}", message);
+}
+
#[cfg(test)]
mod tests {
use super::*;