about summary refs log tree commit diff
path: root/compiler/rustc_builtin_macros
diff options
context:
space:
mode:
authorNicholas Nethercote <n.nethercote@gmail.com>2022-07-01 16:32:20 +1000
committerNicholas Nethercote <n.nethercote@gmail.com>2022-07-04 18:36:39 +1000
commita7b1d31a9f358747221e8eb9986bb8303d5d6586 (patch)
tree800969fe38a3592be6582cc24567496b42a92a85 /compiler/rustc_builtin_macros
parent5762d2385ebdd735b110ab82e80eed6efa7d7c55 (diff)
downloadrust-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.
Diffstat (limited to 'compiler/rustc_builtin_macros')
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/clone.rs26
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs25
2 files changed, 35 insertions, 16 deletions
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],
+                );
+            }
         }
     };