From 49dd6c321dbf1b8c41479f9eb275e5bd3d890aae Mon Sep 17 00:00:00 2001 From: tyranron Date: Wed, 28 Aug 2024 15:59:31 +0300 Subject: [PATCH 1/9] Add `#[allow(unreachable_code)]` to `Display` and `Debug` derives --- impl/src/fmt/debug.rs | 1 + impl/src/fmt/display.rs | 1 + tests/debug.rs | 50 ++++++++++++++++++++++++++++++++++++++ tests/display.rs | 54 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 106 insertions(+) diff --git a/impl/src/fmt/debug.rs b/impl/src/fmt/debug.rs index a3cee6f2..199b9b0f 100644 --- a/impl/src/fmt/debug.rs +++ b/impl/src/fmt/debug.rs @@ -60,6 +60,7 @@ pub fn expand(input: &syn::DeriveInput, _: &str) -> syn::Result { }; 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] diff --git a/impl/src/fmt/display.rs b/impl/src/fmt/display.rs index b217a779..41320df5 100644 --- a/impl/src/fmt/display.rs +++ b/impl/src/fmt/display.rs @@ -62,6 +62,7 @@ pub fn expand(input: &syn::DeriveInput, trait_name: &str) -> syn::Result Date: Wed, 28 Aug 2024 16:43:49 +0300 Subject: [PATCH 2/9] Consider for `AsRef` and `AsMut` --- impl/src/as/mod.rs | 1 + tests/as_mut.rs | 38 ++++++++++++++++++++++++++++++++++++++ tests/as_ref.rs | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+) diff --git a/impl/src/as/mod.rs b/impl/src/as/mod.rs index fd631aa3..5157fe86 100644 --- a/impl/src/as/mod.rs +++ b/impl/src/as/mod.rs @@ -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] diff --git a/tests/as_mut.rs b/tests/as_mut.rs index 969fc82c..37cc8991 100644 --- a/tests/as_mut.rs +++ b/tests/as_mut.rs @@ -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 @@ -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 { @@ -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: !, + } + } } } @@ -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 { @@ -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, + } + } } } diff --git a/tests/as_ref.rs b/tests/as_ref.rs index 14465c4c..b1daf016 100644 --- a/tests/as_ref.rs +++ b/tests/as_ref.rs @@ -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"))] @@ -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 { @@ -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: !, + } + } } } @@ -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 { @@ -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, + } + } } } From 19c2975d0b0442ac3acda1cde96541839107b5bd Mon Sep 17 00:00:00 2001 From: tyranron Date: Wed, 28 Aug 2024 16:50:48 +0300 Subject: [PATCH 3/9] Consider for `Deref` and `DerefMut` --- impl/src/deref.rs | 1 + impl/src/deref_mut.rs | 1 + tests/deref.rs | 12 ++++++++++++ tests/deref_mut.rs | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 46 insertions(+) diff --git a/impl/src/deref.rs b/impl/src/deref.rs index f87c64cc..cbfc5bdc 100644 --- a/impl/src/deref.rs +++ b/impl/src/deref.rs @@ -42,6 +42,7 @@ pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result Result &Self::Target { + self.0 + } + } + + #[derive(DerefMut)] + struct Struct { + field: !, + } + + // `Deref` implementation is required for `DerefMut`. + impl ::core::ops::Deref for Struct { + type Target = !; + #[inline] + fn deref(&self) -> &Self::Target { + self.field + } + } +} From bc4932c19084a2cc585d7731a0b0cbbfe072ab17 Mon Sep 17 00:00:00 2001 From: tyranron Date: Wed, 28 Aug 2024 17:01:54 +0300 Subject: [PATCH 4/9] Consider for `Constructor` --- impl/src/constructor.rs | 1 + tests/constructor.rs | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/impl/src/constructor.rs b/impl/src/constructor.rs index 284b0643..c1c77cb3 100644 --- a/impl/src/constructor.rs +++ b/impl/src/constructor.rs @@ -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] diff --git a/tests/constructor.rs b/tests/constructor.rs index 8777692b..0bda4116 100644 --- a/tests/constructor.rs +++ b/tests/constructor.rs @@ -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; @@ -30,3 +31,21 @@ 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 } +} + From 680b036de5b7a587343f697f5f443cbc36e48d3b Mon Sep 17 00:00:00 2001 From: tyranron Date: Wed, 28 Aug 2024 17:18:41 +0300 Subject: [PATCH 5/9] Consider for `From` --- impl/src/from.rs | 3 +++ tests/constructor.rs | 10 +++++++--- tests/deref.rs | 4 +++- tests/from.rs | 26 ++++++++++++++++++++++++++ 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/impl/src/from.rs b/impl/src/from.rs index c784d972..6c6e0fee 100644 --- a/impl/src/from.rs +++ b/impl/src/from.rs @@ -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] @@ -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] @@ -234,6 +236,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] diff --git a/tests/constructor.rs b/tests/constructor.rs index 0bda4116..1fc2834e 100644 --- a/tests/constructor.rs +++ b/tests/constructor.rs @@ -40,12 +40,16 @@ mod never { struct Tuple(!); #[derive(Constructor)] - struct Struct { field: ! } + struct Struct { + field: !, + } #[derive(Constructor)] struct TupleMulti(i32, !); #[derive(Constructor)] - struct StructMulti { field: !, other: i32 } + struct StructMulti { + field: !, + other: i32, + } } - diff --git a/tests/deref.rs b/tests/deref.rs index 0b345541..9feab5f3 100644 --- a/tests/deref.rs +++ b/tests/deref.rs @@ -83,5 +83,7 @@ mod never { struct Tuple(!); #[derive(Deref)] - struct Struct { field: ! } + struct Struct { + field: !, + } } diff --git a/tests/from.rs b/tests/from.rs index 48f745fb..51cc6374 100644 --- a/tests/from.rs +++ b/tests/from.rs @@ -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"))] @@ -455,6 +456,20 @@ mod structs { } } } + + #[cfg(nightly)] + mod never { + use super::*; + + #[derive(From)] + struct Tuple(i32, !); + + #[derive(From)] + struct Struct { + field1: !, + field2: i16, + } + } } } @@ -1787,5 +1802,16 @@ mod enums { ); } } + + #[cfg(nightly)] + mod never { + use super::*; + + #[derive(From)] + enum Enum { + Tuple(i8, !), + Struct { field1: !, field2: i16 }, + } + } } } From b300a0c440a73ab5f505a977f3b41d7a711753f4 Mon Sep 17 00:00:00 2001 From: tyranron Date: Wed, 28 Aug 2024 17:22:37 +0300 Subject: [PATCH 6/9] Consider for `IsVariant` --- impl/src/is_variant.rs | 1 + tests/is_variant.rs | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/impl/src/is_variant.rs b/impl/src/is_variant.rs index 12f7db1e..86d1de49 100644 --- a/impl/src/is_variant.rs +++ b/impl/src/is_variant.rs @@ -53,6 +53,7 @@ pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result Date: Wed, 28 Aug 2024 17:27:10 +0300 Subject: [PATCH 7/9] Consider for `Not` --- impl/src/from.rs | 7 ++++--- impl/src/not_like.rs | 1 + tests/not.rs | 31 +++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/impl/src/from.rs b/impl/src/from.rs index 6c6e0fee..10539ee3 100644 --- a/impl/src/from.rs +++ b/impl/src/from.rs @@ -224,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()); diff --git a/impl/src/not_like.rs b/impl/src/not_like.rs index da8a3457..40fae23f 100644 --- a/impl/src/not_like.rs +++ b/impl/src/not_like.rs @@ -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; diff --git a/tests/not.rs b/tests/not.rs index 96b4bb3a..31453bde 100644 --- a/tests/not.rs +++ b/tests/not.rs @@ -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::Not; @@ -27,3 +28,33 @@ enum EnumWithUnit { SmallInt(i32), Unit, } + +#[cfg(nightly)] +mod never { + use super::*; + + #[derive(Not)] + struct Tuple(!); + + #[derive(Not)] + struct Struct { + field: !, + } + + #[derive(Not)] + struct TupleMulti(i32, !); + + #[derive(Not)] + struct StructMulti { + field: !, + other: i32, + } + + #[derive(Not)] + enum Enum { + Tuple(!), + Struct { field: ! }, + TupleMulti(i32, !), + StructMulti { field: !, other: i32 }, + } +} From a22d946321b091c4548ce7a005d371546de31cdf Mon Sep 17 00:00:00 2001 From: tyranron Date: Wed, 28 Aug 2024 17:33:08 +0300 Subject: [PATCH 8/9] Consider for `Unwrap` and `TryUnwrap` --- impl/src/try_unwrap.rs | 1 + impl/src/unwrap.rs | 1 + tests/try_unwrap.rs | 12 ++++++++++++ tests/unwrap.rs | 12 ++++++++++++ 4 files changed, 26 insertions(+) diff --git a/impl/src/try_unwrap.rs b/impl/src/try_unwrap.rs index b90ba714..28187962 100644 --- a/impl/src/try_unwrap.rs +++ b/impl/src/try_unwrap.rs @@ -123,6 +123,7 @@ pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result Result Date: Wed, 28 Aug 2024 17:34:30 +0300 Subject: [PATCH 9/9] Mention in CHANGELOG --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49e08e00..5029725c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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