Skip to content

Commit

Permalink
Add #[allow(unreachable_code)] to generated impls for ! type (#404,
Browse files Browse the repository at this point in the history
#400)

## Synopsis

For `!` never type used in trait signatures, `rustc` emits
`unreachable_code` warning ignoring the `#[automatically_derived]`
attribute.

## Solution

Add `#[allow(unreachable_code)]` to generated `impl`s to suppress such
warnings for `!` and similar types.
  • Loading branch information
tyranron authored Aug 29, 2024
1 parent d7c4a68 commit 06acaad
Show file tree
Hide file tree
Showing 24 changed files with 363 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Associated types of type parameters not being treated as generics in `Debug`
and `Display` expansions.
([#399](https://github.com/JelteF/derive_more/pull/399))
- `unreachable_code` warnings on generated code when `!` (never type) is used.
([#404](https://github.com/JelteF/derive_more/pull/404))


## 1.0.0 - 2024-08-07
Expand Down
1 change: 1 addition & 0 deletions impl/src/as/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ impl<'a> ToTokens for Expansion<'a> {
};

quote! {
#[allow(unreachable_code)] // omit warnings for `!` and other unreachable types
#[automatically_derived]
impl #impl_gens #trait_ty for #ty_ident #ty_gens #where_clause {
#[inline]
Expand Down
1 change: 1 addition & 0 deletions impl/src/constructor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub fn expand(input: &DeriveInput, _: &str) -> TokenStream {
let original_types = &get_field_types(&fields);
quote! {
#[allow(missing_docs)]
#[allow(unreachable_code)] // omit warnings for `!` and other unreachable types
#[automatically_derived]
impl #impl_generics #input_type #ty_generics #where_clause {
#[inline]
Expand Down
1 change: 1 addition & 0 deletions impl/src/deref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStre
let (impl_generics, _, where_clause) = generics.split_for_impl();

Ok(quote! {
#[allow(unreachable_code)] // omit warnings for `!` and other unreachable types
#[automatically_derived]
impl #impl_generics #trait_path for #input_type #ty_generics #where_clause {
type Target = #target;
Expand Down
1 change: 1 addition & 0 deletions impl/src/deref_mut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStre
let (impl_generics, _, where_clause) = generics.split_for_impl();

Ok(quote! {
#[allow(unreachable_code)] // omit warnings for `!` and other unreachable types
#[automatically_derived]
impl #impl_generics #trait_path for #input_type #ty_generics #where_clause {
#[inline]
Expand Down
1 change: 1 addition & 0 deletions impl/src/fmt/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ pub fn expand(input: &syn::DeriveInput, _: &str) -> syn::Result<TokenStream> {
};

Ok(quote! {
#[allow(unreachable_code)] // omit warnings for `!` and other unreachable types
#[automatically_derived]
impl #impl_gens derive_more::Debug for #ident #ty_gens #where_clause {
#[inline]
Expand Down
1 change: 1 addition & 0 deletions impl/src/fmt/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ pub fn expand(input: &syn::DeriveInput, trait_name: &str) -> syn::Result<TokenSt
};

Ok(quote! {
#[allow(unreachable_code)] // omit warnings for `!` and other unreachable types
#[automatically_derived]
impl #impl_gens derive_more::#trait_ident for #ident #ty_gens #where_clause {
fn fmt(
Expand Down
10 changes: 7 additions & 3 deletions impl/src/from.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ impl<'a> Expansion<'a> {
});

Ok(quote! {
#[allow(unreachable_code)] // omit warnings for `!` and unreachable types
#[automatically_derived]
impl #impl_gens derive_more::From<#ty> for #ident #ty_gens #where_clause {
#[inline]
Expand All @@ -192,6 +193,7 @@ impl<'a> Expansion<'a> {
});

Ok(quote! {
#[allow(unreachable_code)] // omit warnings for `!` and other unreachable types
#[automatically_derived]
impl #impl_gens derive_more::From<(#( #field_tys ),*)> for #ident #ty_gens #where_clause {
#[inline]
Expand Down Expand Up @@ -222,9 +224,10 @@ impl<'a> Expansion<'a> {
let generics = {
let mut generics = self.generics.clone();
for (ty, ident) in field_tys.iter().zip(&gen_idents) {
generics.make_where_clause().predicates.push(
parse_quote! { #ty: derive_more::From<#ident> },
);
generics
.make_where_clause()
.predicates
.push(parse_quote! { #ty: derive_more::From<#ident> });
generics
.params
.push(syn::TypeParam::from(ident.clone()).into());
Expand All @@ -234,6 +237,7 @@ impl<'a> Expansion<'a> {
let (impl_gens, _, where_clause) = generics.split_for_impl();

Ok(quote! {
#[allow(unreachable_code)] // omit warnings for `!` and other unreachable types
#[automatically_derived]
impl #impl_gens derive_more::From<(#( #gen_idents ),*)> for #ident #ty_gens #where_clause {
#[inline]
Expand Down
1 change: 1 addition & 0 deletions impl/src/is_variant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStre
}

let imp = quote! {
#[allow(unreachable_code)] // omit warnings for `!` and other unreachable types
#[automatically_derived]
impl #imp_generics #enum_name #type_generics #where_clause {
#(#funcs)*
Expand Down
1 change: 1 addition & 0 deletions impl/src/not_like.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pub fn expand(input: &DeriveInput, trait_name: &str) -> TokenStream {
};

quote! {
#[allow(unreachable_code)] // omit warnings for `!` and other unreachable types
#[automatically_derived]
impl #impl_generics derive_more::#trait_ident for #input_type #ty_generics #where_clause {
type Output = #output_type;
Expand Down
1 change: 1 addition & 0 deletions impl/src/try_unwrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStre
}

let imp = quote! {
#[allow(unreachable_code)] // omit warnings for `!` and other unreachable types
#[automatically_derived]
impl #imp_generics #enum_name #type_generics #where_clause {
#(#funcs)*
Expand Down
1 change: 1 addition & 0 deletions impl/src/unwrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStre
}

let imp = quote! {
#[allow(unreachable_code)] // omit warnings for `!` and other unreachable types
#[automatically_derived]
impl #imp_generics #enum_name #type_generics #where_clause {
#(#funcs)*
Expand Down
38 changes: 38 additions & 0 deletions tests/as_mut.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(nightly, feature(never_type))]
#![allow(clippy::unnecessary_mut_passed)] // testing correct signatures rather than actual code
#![allow(dead_code)] // some code is tested for type checking only

Expand Down Expand Up @@ -423,6 +424,14 @@ mod single_field {
assert!(ptr::eq(item.as_mut(), item.0.as_mut()));
}
}

#[cfg(nightly)]
mod never {
use super::*;

#[derive(AsMut)]
struct Nothing(!);
}
}

mod named {
Expand Down Expand Up @@ -881,6 +890,16 @@ mod single_field {
assert!(ptr::eq(item.as_mut(), item.first.as_mut()));
}
}

#[cfg(nightly)]
mod never {
use super::*;

#[derive(AsMut)]
struct Nothing {
first: !,
}
}
}
}

Expand Down Expand Up @@ -1071,6 +1090,14 @@ mod multi_field {
assert!(ptr::eq(item.as_mut(), item.0.as_mut()));
}
}

#[cfg(nightly)]
mod never {
use super::*;

#[derive(AsMut)]
struct Nothing(String, !);
}
}

mod named {
Expand Down Expand Up @@ -1346,5 +1373,16 @@ mod multi_field {
assert!(ptr::eq(item.as_mut(), item.first.as_mut()));
}
}

#[cfg(nightly)]
mod never {
use super::*;

#[derive(AsMut)]
struct Nothing {
first: !,
second: i32,
}
}
}
}
38 changes: 38 additions & 0 deletions tests/as_ref.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(nightly, feature(never_type))]
#![allow(dead_code)] // some code is tested for type checking only

#[cfg(not(feature = "std"))]
Expand Down Expand Up @@ -416,6 +417,14 @@ mod single_field {
assert!(ptr::eq(item.as_ref(), item.0.as_ref()));
}
}

#[cfg(nightly)]
mod never {
use super::*;

#[derive(AsRef)]
struct Nothing(!);
}
}

mod named {
Expand Down Expand Up @@ -874,6 +883,16 @@ mod single_field {
assert!(ptr::eq(item.as_ref(), item.first.as_ref()));
}
}

#[cfg(nightly)]
mod never {
use super::*;

#[derive(AsRef)]
struct Nothing {
first: !,
}
}
}
}

Expand Down Expand Up @@ -1064,6 +1083,14 @@ mod multi_field {
assert!(ptr::eq(item.as_ref(), item.0.as_ref()));
}
}

#[cfg(nightly)]
mod never {
use super::*;

#[derive(AsRef)]
struct Nothing(String, !);
}
}

mod named {
Expand Down Expand Up @@ -1339,5 +1366,16 @@ mod multi_field {
assert!(ptr::eq(item.as_ref(), item.first.as_ref()));
}
}

#[cfg(nightly)]
mod never {
use super::*;

#[derive(AsRef)]
struct Nothing {
first: !,
second: i32,
}
}
}
}
23 changes: 23 additions & 0 deletions tests/constructor.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(nightly, feature(never_type))]
#![allow(dead_code)] // some code is tested for type checking only

use derive_more::Constructor;
Expand Down Expand Up @@ -30,3 +31,25 @@ struct Point2D {
}

const POINT_2D: Point2D = Point2D::new(-4, 7);

#[cfg(nightly)]
mod never {
use super::*;

#[derive(Constructor)]
struct Tuple(!);

#[derive(Constructor)]
struct Struct {
field: !,
}

#[derive(Constructor)]
struct TupleMulti(i32, !);

#[derive(Constructor)]
struct StructMulti {
field: !,
other: i32,
}
}
50 changes: 50 additions & 0 deletions tests/debug.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(nightly, feature(never_type))]
#![allow(dead_code)] // some code is tested for type checking only

#[cfg(not(feature = "std"))]
Expand Down Expand Up @@ -417,6 +418,19 @@ mod structs {
}
}
}

#[cfg(nightly)]
mod never {
use derive_more::Debug;

#[derive(Debug)]
struct Tuple(!);

#[derive(Debug)]
struct Struct {
field: !,
}
}
}

mod multi_field {
Expand Down Expand Up @@ -676,6 +690,20 @@ mod structs {
);
}
}

#[cfg(nightly)]
mod never {
use derive_more::Debug;

#[derive(Debug)]
struct Tuple(i32, !);

#[derive(Debug)]
struct Struct {
field: !,
other: i32,
}
}
}
}

Expand Down Expand Up @@ -980,6 +1008,17 @@ mod enums {
}
}
}

#[cfg(nightly)]
mod never {
use derive_more::Debug;

#[derive(Debug)]
enum Enum {
Unnamed(!),
Named { field: ! },
}
}
}

mod multi_field_variant {
Expand Down Expand Up @@ -1155,6 +1194,17 @@ mod enums {
);
}
}

#[cfg(nightly)]
mod never {
use derive_more::Debug;

#[derive(Debug)]
enum Enum {
Unnamed(i32, !),
Named { field: !, other: i32 },
}
}
}
}

Expand Down
Loading

0 comments on commit 06acaad

Please sign in to comment.