diff options
| author | Nicholas Nethercote <n.nethercote@gmail.com> | 2022-07-01 16:32:20 +1000 |
|---|---|---|
| committer | Nicholas Nethercote <n.nethercote@gmail.com> | 2022-07-04 18:36:39 +1000 |
| commit | a7b1d31a9f358747221e8eb9986bb8303d5d6586 (patch) | |
| tree | 800969fe38a3592be6582cc24567496b42a92a85 | |
| parent | 5762d2385ebdd735b110ab82e80eed6efa7d7c55 (diff) | |
| download | rust-a7b1d31a9f358747221e8eb9986bb8303d5d6586.tar.gz rust-a7b1d31a9f358747221e8eb9986bb8303d5d6586.zip | |
Don't repeat `AssertParamIs{Clone,Eq}` assertions.
It's common to see repeated assertions like this in derived `clone` and `eq` methods: ``` let _: ::core::clone::AssertParamIsClone<u32>; let _: ::core::clone::AssertParamIsClone<u32>; ``` This commit avoids them.
| -rw-r--r-- | compiler/rustc_ast/src/ast.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/deriving/clone.rs | 26 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs | 25 | ||||
| -rw-r--r-- | src/test/ui/deriving/deriving-all-codegen.stdout | 13 |
4 files changed, 43 insertions, 29 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index e5b61d7000a..bb0b8121cac 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2036,6 +2036,14 @@ impl TyKind { pub fn is_unit(&self) -> bool { matches!(self, TyKind::Tup(tys) if tys.is_empty()) } + + pub fn is_simple_path(&self) -> Option<Symbol> { + if let TyKind::Path(None, Path { segments, .. }) = &self && segments.len() == 1 { + Some(segments[0].ident.name) + } else { + None + } + } } /// Syntax used to declare a trait object. diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index b37b82dd089..0a55d4e0ce0 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -3,6 +3,7 @@ use crate::deriving::generic::*; use crate::deriving::path_std; use rustc_ast::{self as ast, Generics, ItemKind, MetaItem, VariantData}; +use rustc_data_structures::fx::FxHashSet; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Span; @@ -99,20 +100,29 @@ fn cs_clone_simple( is_union: bool, ) -> BlockOrExpr { let mut stmts = Vec::new(); + let mut seen_type_names = FxHashSet::default(); let mut process_variant = |variant: &VariantData| { for field in variant.fields() { - // let _: AssertParamIsClone<FieldTy>; - super::assert_ty_bounds( - cx, - &mut stmts, - field.ty.clone(), - field.span, - &[sym::clone, sym::AssertParamIsClone], - ); + // This basic redundancy checking only prevents duplication of + // assertions like `AssertParamIsClone<Foo>` where the type is a + // simple name. That's enough to get a lot of cases, though. + if let Some(name) = field.ty.kind.is_simple_path() && !seen_type_names.insert(name) { + // Already produced an assertion for this type. + } else { + // let _: AssertParamIsClone<FieldTy>; + super::assert_ty_bounds( + cx, + &mut stmts, + field.ty.clone(), + field.span, + &[sym::clone, sym::AssertParamIsClone], + ); + } } }; if is_union { + // Just a single assertion for unions, that the union impls `Copy`. // let _: AssertParamIsCopy<Self>; let self_ty = cx.ty_path(cx.path_ident(trait_span, Ident::with_dummy_span(kw::SelfUpper))); super::assert_ty_bounds( diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs index 59f8fbc4a08..c1a2ebcc146 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs @@ -3,6 +3,7 @@ use crate::deriving::generic::*; use crate::deriving::path_std; use rustc_ast::{self as ast, MetaItem}; +use rustc_data_structures::fx::FxHashSet; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; @@ -53,16 +54,24 @@ fn cs_total_eq_assert( substr: &Substructure<'_>, ) -> BlockOrExpr { let mut stmts = Vec::new(); + let mut seen_type_names = FxHashSet::default(); let mut process_variant = |variant: &ast::VariantData| { for field in variant.fields() { - // let _: AssertParamIsEq<FieldTy>; - super::assert_ty_bounds( - cx, - &mut stmts, - field.ty.clone(), - field.span, - &[sym::cmp, sym::AssertParamIsEq], - ); + // This basic redundancy checking only prevents duplication of + // assertions like `AssertParamIsEq<Foo>` where the type is a + // simple name. That's enough to get a lot of cases, though. + if let Some(name) = field.ty.kind.is_simple_path() && !seen_type_names.insert(name) { + // Already produced an assertion for this type. + } else { + // let _: AssertParamIsEq<FieldTy>; + super::assert_ty_bounds( + cx, + &mut stmts, + field.ty.clone(), + field.span, + &[sym::cmp, sym::AssertParamIsEq], + ); + } } }; diff --git a/src/test/ui/deriving/deriving-all-codegen.stdout b/src/test/ui/deriving/deriving-all-codegen.stdout index fb5965858cc..7713627be5e 100644 --- a/src/test/ui/deriving/deriving-all-codegen.stdout +++ b/src/test/ui/deriving/deriving-all-codegen.stdout @@ -96,7 +96,6 @@ impl ::core::clone::Clone for Point { #[inline] fn clone(&self) -> Point { let _: ::core::clone::AssertParamIsClone<u32>; - let _: ::core::clone::AssertParamIsClone<u32>; *self } } @@ -152,7 +151,6 @@ impl ::core::cmp::Eq for Point { #[no_coverage] fn assert_receiver_is_total_eq(&self) -> () { let _: ::core::cmp::AssertParamIsEq<u32>; - let _: ::core::cmp::AssertParamIsEq<u32>; } } #[automatically_derived] @@ -291,13 +289,6 @@ impl ::core::cmp::Eq for Big { #[no_coverage] fn assert_receiver_is_total_eq(&self) -> () { let _: ::core::cmp::AssertParamIsEq<u32>; - let _: ::core::cmp::AssertParamIsEq<u32>; - let _: ::core::cmp::AssertParamIsEq<u32>; - let _: ::core::cmp::AssertParamIsEq<u32>; - let _: ::core::cmp::AssertParamIsEq<u32>; - let _: ::core::cmp::AssertParamIsEq<u32>; - let _: ::core::cmp::AssertParamIsEq<u32>; - let _: ::core::cmp::AssertParamIsEq<u32>; } } #[automatically_derived] @@ -774,8 +765,6 @@ impl ::core::clone::Clone for Mixed { #[inline] fn clone(&self) -> Mixed { let _: ::core::clone::AssertParamIsClone<u32>; - let _: ::core::clone::AssertParamIsClone<u32>; - let _: ::core::clone::AssertParamIsClone<u32>; *self } } @@ -871,8 +860,6 @@ impl ::core::cmp::Eq for Mixed { #[no_coverage] fn assert_receiver_is_total_eq(&self) -> () { let _: ::core::cmp::AssertParamIsEq<u32>; - let _: ::core::cmp::AssertParamIsEq<u32>; - let _: ::core::cmp::AssertParamIsEq<u32>; } } #[automatically_derived] |
