From ae0b63688eb8082d2bbc6e2fc30f80ac2b985591 Mon Sep 17 00:00:00 2001 From: "coderabbitai[bot]" <136622811+coderabbitai[bot]@users.noreply.github.com> Date: Sun, 13 Sep 2026 13:31:27 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9D=20CodeRabbit=20Chat:=20Add=20VMErr?= =?UTF-8?q?or=20Diagnostic=20Links=20to=20Error=20Output?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- rust/src/modules/vmerror/display.rs | 1 + rust/src/modules/vmerror/error.rs | 99 ++++++++++++++++++++++++++++- 2 files changed, 99 insertions(+), 1 deletion(-) diff --git a/rust/src/modules/vmerror/display.rs b/rust/src/modules/vmerror/display.rs index a1d9db54..b8a6d1d1 100644 --- a/rust/src/modules/vmerror/display.rs +++ b/rust/src/modules/vmerror/display.rs @@ -131,6 +131,7 @@ impl fmt::Display for VMError { } VMError::SystemError(s) => write!(f, "{}", s), }?; + write!(f, "\n{}", self.diagnostic_link())?; if !matches!(self, VMError::SystemError(_)) { if is_hint { write!( diff --git a/rust/src/modules/vmerror/error.rs b/rust/src/modules/vmerror/error.rs index bcbfdcc7..39b1e405 100644 --- a/rust/src/modules/vmerror/error.rs +++ b/rust/src/modules/vmerror/error.rs @@ -8,7 +8,6 @@ * http://www.apache.org/licenses/LICENSE-2.0 */ -// TODO: add here use smol_str::SmolStr; use std::borrow::Cow; #[derive(Debug)] @@ -104,4 +103,102 @@ impl VMError { VMError::SystemError(_) => "LVM500", } } + + /// Returns the documentation URL for this error. + #[cold] + pub fn diagnostic_link(&self) -> String { + format!( + "https://lightvm.vercel.app/api-reference/error-codes/{}-code", + self.error_code().to_ascii_lowercase() + ) + } +} + +#[cfg(test)] +mod tests { + use super::VMError; + use crate::modules::vmerror::config::set_thread_error_config; + use smol_str::SmolStr; + + fn all_errors() -> Vec { + vec![ + VMError::StackOverflow { ip: 1, limit: 2 }, + VMError::StackUnderflow { + ip: 1, + opcode: "POP", + }, + VMError::InvalidOpcode { + ip: 1, + code: SmolStr::new("INVALID"), + }, + VMError::TypeMismatch { + ip: 1, + expected: "number", + found: "string", + }, + VMError::SystemError(SmolStr::new("system failure")), + VMError::OutOfBounds { + ip: 1, + index: 2, + len: 1, + }, + VMError::InvalidJumpTarget { + ip: 1, + target: 2, + len: 1, + }, + VMError::FeatureRestricted { + ip: 1, + feature: "nightly", + }, + VMError::IoFlood { ip: 1 }, + VMError::ImportLimitReached { ip: 1 }, + VMError::UnauthorizedModule { + ip: 1, + module: SmolStr::new("module"), + }, + VMError::MemoryLimitExceeded { ip: 1 }, + VMError::CallLimitExceeded { ip: 1 }, + VMError::JumpLimitExceeded { ip: 1 }, + VMError::ExcessiveNopPadding, + VMError::InvalidMaxTicksConfig, + VMError::TickLimitExceeded, + ] + } + + #[test] + fn every_error_has_a_diagnostic_link_containing_its_code() { + for error in all_errors() { + assert!( + error + .diagnostic_link() + .to_ascii_uppercase() + .contains(error.error_code()), + "diagnostic link missing {}", + error.error_code() + ); + } + } + + #[test] + fn formatted_error_contains_its_diagnostic_link() { + let error = VMError::StackOverflow { ip: 1, limit: 2 }; + + assert!(error.to_string().contains(&error.diagnostic_link())); + } + + #[test] + fn formatted_system_error_contains_its_diagnostic_link() { + let error = VMError::SystemError(SmolStr::new("system failure")); + + assert!(error.to_string().contains(&error.diagnostic_link())); + } + + #[test] + fn diagnostic_link_is_rendered_when_hints_are_disabled() { + set_thread_error_config(false, false, false); + let error = VMError::StackOverflow { ip: 1, limit: 2 }; + + assert!(error.to_string().contains(&error.diagnostic_link())); + } }