Repository: dtolnay/thiserror (Rust)

Issue:
Macro triggers unused_qualifications lint
```rust
#![warn(unused_qualifications)]
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
    Ok(())
}
#[derive(Debug, thiserror::Error)]
#[error("err")]
pub struct MyError;
```
triggers this warning:
```console
warning: unnecessary qualification
 --> src\main.rs:8:1
  |
8 | pub struct MyError;
  | ^^^^^^^^^^^^^^^^^^
  |
note: the lint level is defined here
 --> src\main.rs:1:9
  |
1 | #![warn(unused_qualifications)]
  |         ^^^^^^^^^^^^^^^^^^^^^

warning: 1 warning emitted
```



Discussion:
Thanks, fixed in 1.0.20.



Patch:
diff --git a/impl/src/expand.rs b/impl/src/expand.rs
index 40ed2473..9235e8f6 100644
--- a/impl/src/expand.rs
+++ b/impl/src/expand.rs
@@ -113,6 +113,7 @@ fn impl_struct(input: Struct) -> TokenStream {
     };
     let display_impl = display_body.map(|body| {
         quote! {
+            #[allow(unused_qualifications)]
             impl #impl_generics std::fmt::Display for #ty #ty_generics #where_clause {
                 #[allow(clippy::used_underscore_binding)]
                 fn fmt(&self, __formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
@@ -127,6 +128,7 @@ fn impl_struct(input: Struct) -> TokenStream {
         let from = from_field.ty;
         let body = from_initializer(from_field, backtrace_field);
         quote! {
+            #[allow(unused_qualifications)]
             impl #impl_generics std::convert::From<#from> for #ty #ty_generics #where_clause {
                 #[allow(deprecated)]
                 fn from(source: #from) -> Self {
@@ -139,6 +141,7 @@ fn impl_struct(input: Struct) -> TokenStream {
     let error_trait = spanned_error_trait(input.original);
 
     quote! {
+        #[allow(unused_qualifications)]
         impl #impl_generics #error_trait for #ty #ty_generics #where_clause {
             #source_method
             #backtrace_method
@@ -294,6 +297,7 @@ fn impl_enum(input: Enum) -> TokenStream {
             }
         });
         Some(quote! {
+            #[allow(unused_qualifications)]
             impl #impl_generics std::fmt::Display for #ty #ty_generics #where_clause {
                 fn fmt(&self, __formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
                     #use_as_display
@@ -315,6 +319,7 @@ fn impl_enum(input: Enum) -> TokenStream {
         let from = from_field.ty;
         let body = from_initializer(from_field, backtrace_field);
         Some(quote! {
+            #[allow(unused_qualifications)]
             impl #impl_generics std::convert::From<#from> for #ty #ty_generics #where_clause {
                 #[allow(deprecated)]
                 fn from(source: #from) -> Self {
@@ -327,6 +332,7 @@ fn impl_enum(input: Enum) -> TokenStream {
     let error_trait = spanned_error_trait(input.original);
 
     quote! {
+        #[allow(unused_qualifications)]
         impl #impl_generics #error_trait for #ty #ty_generics #where_clause {
             #source_method
             #backtrace_method


Test patch:
diff --git a/tests/test_lints.rs b/tests/test_lints.rs
new file mode 100644
index 00000000..b3b44b2a
--- /dev/null
+++ b/tests/test_lints.rs
@@ -0,0 +1,16 @@
+use thiserror::Error;
+
+pub use std::error::Error;
+
+#[test]
+fn test_unused_qualifications() {
+    #![deny(unused_qualifications)]
+
+    // Expansion of derive(Error) macro can't know whether something like
+    // std::error::Error is already imported in the caller's scope so it must
+    // suppress unused_qualifications.
+
+    #[derive(Debug, Error)]
+    #[error("...")]
+    pub struct MyError;
+}