Repository: zkat/miette
Pull request #338 (2024-02-07 04:39:51)

feat(derive): enable more boxed types to be #[diagnostic_source]
Hello again! Nice and small change this time :)

The `#[diagnostic_source]` attribute already worked for `Box<dyn Diagnostic>`, but not for the highly-related `Box<dyn Diagnostic + Send>` and `Box<dyn Diagnostic + Send + Sync>` types!

It looks like someone already solved this issue for `std::error:Error` with a `macro_rules!` implementation, so I've done the same here to let those new cases compile! Without those `Borrow<dyn Diagnostic>` impls, you end up with compiler errors coming from inside of the derive macro:

![Screenshot from 2024-02-06 20-26-45](https://github.com/zkat/miette/assets/6251883/10fb0847-dd6d-4e03-957f-f7685ed13afe)

Let me know if you have any questions! I'll separately try to sort out those failing tests (unrelated to this change) in another PR :)


TheLostLambda: With some luck, #339 should fix the tests failing for everyone — I don't think there was a behavior change, I think the reference strings just got mangled somehow in a commit from three days ago.

Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index d5f437e..b1eef7d 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -79,4 +79,4 @@ jobs:
         with:
           toolchain: nightly
       - name: Run minimal version build
-        run: cargo build -Z minimal-versions --features fancy,no-format-args-capture
+        run: cargo build -Z direct-minimal-versions --features fancy,no-format-args-capture
diff --git a/Cargo.toml b/Cargo.toml
index 4ffe9b8..0fa1685 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -36,7 +36,7 @@ futures = { version = "0.3", default-features = false }
 indenter = "0.3.3"
 rustversion = "1.0"
 trybuild = { version = "1.0.89", features = ["diff"] }
-syn = { version = "2.0", features = ["full"] }
+syn = { version = "2.0.48", features = ["full"] }
 regex = "1.10"
 lazy_static = "1.4"
 
diff --git a/miette-derive/Cargo.toml b/miette-derive/Cargo.toml
index 822f754..c1e4eb2 100644
--- a/miette-derive/Cargo.toml
+++ b/miette-derive/Cargo.toml
@@ -12,5 +12,5 @@ proc-macro = true
 
 [dependencies]
 proc-macro2 = "1.0.78"
-quote = "1.0"
+quote = "1.0.35"
 syn = "2.0.48"
diff --git a/src/protocol.rs b/src/protocol.rs
index 6b98a97..310fc86 100644
--- a/src/protocol.rs
+++ b/src/protocol.rs
@@ -69,7 +69,7 @@ pub trait Diagnostic: std::error::Error {
     }
 }
 
-macro_rules! box_impls {
+macro_rules! box_error_impls {
     ($($box_type:ty),*) => {
         $(
             impl std::error::Error for $box_type {
@@ -85,12 +85,29 @@ macro_rules! box_impls {
     }
 }
 
-box_impls! {
+box_error_impls! {
     Box<dyn Diagnostic>,
     Box<dyn Diagnostic + Send>,
     Box<dyn Diagnostic + Send + Sync>
 }
 
+macro_rules! box_borrow_impls {
+    ($($box_type:ty),*) => {
+        $(
+            impl std::borrow::Borrow<dyn Diagnostic> for $box_type {
+                fn borrow(&self) -> &(dyn Diagnostic + 'static) {
+                    self.as_ref()
+                }
+            }
+        )*
+    }
+}
+
+box_borrow_impls! {
+    Box<dyn Diagnostic + Send>,
+    Box<dyn Diagnostic + Send + Sync>
+}
+
 impl<T: Diagnostic + Send + Sync + 'static> From<T>
     for Box<dyn Diagnostic + Send + Sync + 'static>
 {


Test patch:
diff --git a/tests/graphical.rs b/tests/graphical.rs
index 7e5de78..b5fa4d8 100644
--- a/tests/graphical.rs
+++ b/tests/graphical.rs
@@ -1864,11 +1864,11 @@ fn syntax_highlighter_on_real_file() {
     let expected = format!(
         r#"  × This is an error
       ╭─[{filename}:{l2}:{CO}]
- {l1} │
+ {l1} │ 
  {l2} │     let (filename, line) = (file!(), line!() as usize);
       ·                            ─────────────┬─────────────
       ·                                         ╰── this is a label
- {l3} │
+ {l3} │ 
       ╰────
 "#,
         l1 = line - 1,
@@ -1911,13 +1911,13 @@ fn triple_adjacent_highlight() -> Result<(), MietteError> {
  1 │ source
    · ───┬──
    ·    ╰── this bit here
- 2 │
- 3 │
+ 2 │ 
+ 3 │ 
  4 │   text
    ·   ──┬─
    ·     ╰── also this bit
- 5 │
- 6 │
+ 5 │ 
+ 6 │ 
  7 │     here
    ·     ──┬─
    ·       ╰── finally we got
@@ -1957,10 +1957,10 @@ fn non_adjacent_highlight() -> Result<(), MietteError> {
  1 │ source
    · ───┬──
    ·    ╰── this bit here
- 2 │
+ 2 │ 
    ╰────
    ╭─[bad_file.rs:5:3]
- 4 │
+ 4 │ 
  5 │   text    here
    ·   ──┬─
    ·     ╰── also this bit
diff --git a/tests/test_diagnostic_source_macro.rs b/tests/test_diagnostic_source_macro.rs
index e5305ac..939812c 100644
--- a/tests/test_diagnostic_source_macro.rs
+++ b/tests/test_diagnostic_source_macro.rs
@@ -41,6 +41,14 @@ struct TestTupleError(#[diagnostic_source] AnErr);
 #[error("TestError")]
 struct TestBoxedError(#[diagnostic_source] Box<dyn Diagnostic>);
 
+#[derive(Debug, miette::Diagnostic, thiserror::Error)]
+#[error("TestError")]
+struct TestBoxedSendError(#[diagnostic_source] Box<dyn Diagnostic + Send>);
+
+#[derive(Debug, miette::Diagnostic, thiserror::Error)]
+#[error("TestError")]
+struct TestBoxedSendSyncError(#[diagnostic_source] Box<dyn Diagnostic + Send + Sync>);
+
 #[derive(Debug, miette::Diagnostic, thiserror::Error)]
 #[error("TestError")]
 struct TestArcedError(#[diagnostic_source] std::sync::Arc<dyn Diagnostic>);
@@ -71,6 +79,12 @@ fn test_diagnostic_source() {
     let error = TestBoxedError(Box::new(AnErr));
     assert!(error.diagnostic_source().is_some());
 
+    let error = TestBoxedSendError(Box::new(AnErr));
+    assert!(error.diagnostic_source().is_some());
+
+    let error = TestBoxedSendSyncError(Box::new(AnErr));
+    assert!(error.diagnostic_source().is_some());
+
     let error = TestArcedError(std::sync::Arc::new(AnErr));
     assert!(error.diagnostic_source().is_some());
 }