diff --git a/derive/src/expand.rs b/derive/src/expand.rs index df5a54d..e352190 100644 --- a/derive/src/expand.rs +++ b/derive/src/expand.rs @@ -135,6 +135,7 @@ struct DeriveMeta { nt_report_debug: bool, macro_mangle: bool, macro_path: Option, + macro_vis: Option, } fn resolve_meta(input: &DeriveInput) -> Result { @@ -143,6 +144,7 @@ fn resolve_meta(input: &DeriveInput) -> Result { let mut nt_report_debug = false; let mut macro_mangle = false; let mut macro_path = None; + let mut macro_vis = None; for attr in &input.attrs { if attr.path().is_ident("thiserror_ext") { @@ -182,6 +184,13 @@ fn resolve_meta(input: &DeriveInput) -> Result { "macro path should start with `crate`", )); } + } else if meta.path.is_ident("vis") { + let value = meta.value()?; + macro_vis = Some(if let Ok(lit_str) = value.parse::() { + lit_str.parse()? + } else { + value.parse()? + }) } else { return Err(Error::new_spanned(meta.path, "unknown attribute")); } @@ -202,6 +211,7 @@ fn resolve_meta(input: &DeriveInput) -> Result { nt_report_debug, macro_mangle, macro_path, + macro_vis, }) } @@ -519,16 +529,16 @@ pub fn derive_ctor(input: &DeriveInput, t: DeriveCtorType) -> Result Result { - let input_type = input.ident.clone(); - let vis = &input.vis; - let DeriveMeta { impl_type, macro_mangle, macro_path, + macro_vis, .. } = resolve_meta(input)?; + let input_type = input.ident.clone(); + let vis = macro_vis.unwrap_or_else(|| input.vis.clone()); let input = Input::from_syn(input)?; let variants = match input { diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 4065f20..da210f2 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -168,12 +168,13 @@ pub fn derive_context_into(input: TokenStream) -> TokenStream { /// /// There's a different rule set for the visibility of the macros. The macros /// generated by this proc-macro are marked with `#[macro_export]` only if the -/// visibility of the error type is `pub`, or they're just re-exported with -/// the same visibility as the error type and only work in the same crate. +/// visibility of the error type is `pub`, otherwise they're just re-exported +/// with the same visibility as the error type and only work in the same crate. /// /// There're some extra configurations to help to better handle the visibility, /// specified in `#[thiserror_ext(macro(..))]`: /// +/// - `vis = ..`: use a different visibility for the macro re-export. /// - `mangle`: mangle the macro names so that they don't conflict with other /// macros with the same name in the crate root. /// - `path = "crate::.."`: the path to the current module. When specified, diff --git a/tests/macro.rs b/tests/macro.rs index af6afab..3eac6a6 100644 --- a/tests/macro.rs +++ b/tests/macro.rs @@ -33,7 +33,7 @@ pub mod inner { } #[derive(Error, Debug, Macro)] #[error("not implemented: {message}, issue: {issue:?}")] - #[thiserror_ext(macro(mangle, path = "crate::inner"))] + #[thiserror_ext(macro(mangle, path = "crate::inner", vis = pub(super)))] pub struct NotImplemented { pub issue: Option, pub message: String,