Skip to content

Commit a7b1d31

Browse files
committed
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.
1 parent 5762d23 commit a7b1d31

File tree

4 files changed

+43
-29
lines changed

4 files changed

+43
-29
lines changed

compiler/rustc_ast/src/ast.rs

+8
Original file line numberDiff line numberDiff line change
@@ -2036,6 +2036,14 @@ impl TyKind {
20362036
pub fn is_unit(&self) -> bool {
20372037
matches!(self, TyKind::Tup(tys) if tys.is_empty())
20382038
}
2039+
2040+
pub fn is_simple_path(&self) -> Option<Symbol> {
2041+
if let TyKind::Path(None, Path { segments, .. }) = &self && segments.len() == 1 {
2042+
Some(segments[0].ident.name)
2043+
} else {
2044+
None
2045+
}
2046+
}
20392047
}
20402048

20412049
/// Syntax used to declare a trait object.

compiler/rustc_builtin_macros/src/deriving/clone.rs

+18-8
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::deriving::generic::*;
33
use crate::deriving::path_std;
44

55
use rustc_ast::{self as ast, Generics, ItemKind, MetaItem, VariantData};
6+
use rustc_data_structures::fx::FxHashSet;
67
use rustc_expand::base::{Annotatable, ExtCtxt};
78
use rustc_span::symbol::{kw, sym, Ident};
89
use rustc_span::Span;
@@ -99,20 +100,29 @@ fn cs_clone_simple(
99100
is_union: bool,
100101
) -> BlockOrExpr {
101102
let mut stmts = Vec::new();
103+
let mut seen_type_names = FxHashSet::default();
102104
let mut process_variant = |variant: &VariantData| {
103105
for field in variant.fields() {
104-
// let _: AssertParamIsClone<FieldTy>;
105-
super::assert_ty_bounds(
106-
cx,
107-
&mut stmts,
108-
field.ty.clone(),
109-
field.span,
110-
&[sym::clone, sym::AssertParamIsClone],
111-
);
106+
// This basic redundancy checking only prevents duplication of
107+
// assertions like `AssertParamIsClone<Foo>` where the type is a
108+
// simple name. That's enough to get a lot of cases, though.
109+
if let Some(name) = field.ty.kind.is_simple_path() && !seen_type_names.insert(name) {
110+
// Already produced an assertion for this type.
111+
} else {
112+
// let _: AssertParamIsClone<FieldTy>;
113+
super::assert_ty_bounds(
114+
cx,
115+
&mut stmts,
116+
field.ty.clone(),
117+
field.span,
118+
&[sym::clone, sym::AssertParamIsClone],
119+
);
120+
}
112121
}
113122
};
114123

115124
if is_union {
125+
// Just a single assertion for unions, that the union impls `Copy`.
116126
// let _: AssertParamIsCopy<Self>;
117127
let self_ty = cx.ty_path(cx.path_ident(trait_span, Ident::with_dummy_span(kw::SelfUpper)));
118128
super::assert_ty_bounds(

compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs

+17-8
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::deriving::generic::*;
33
use crate::deriving::path_std;
44

55
use rustc_ast::{self as ast, MetaItem};
6+
use rustc_data_structures::fx::FxHashSet;
67
use rustc_expand::base::{Annotatable, ExtCtxt};
78
use rustc_span::symbol::{sym, Ident};
89
use rustc_span::Span;
@@ -53,16 +54,24 @@ fn cs_total_eq_assert(
5354
substr: &Substructure<'_>,
5455
) -> BlockOrExpr {
5556
let mut stmts = Vec::new();
57+
let mut seen_type_names = FxHashSet::default();
5658
let mut process_variant = |variant: &ast::VariantData| {
5759
for field in variant.fields() {
58-
// let _: AssertParamIsEq<FieldTy>;
59-
super::assert_ty_bounds(
60-
cx,
61-
&mut stmts,
62-
field.ty.clone(),
63-
field.span,
64-
&[sym::cmp, sym::AssertParamIsEq],
65-
);
60+
// This basic redundancy checking only prevents duplication of
61+
// assertions like `AssertParamIsEq<Foo>` where the type is a
62+
// simple name. That's enough to get a lot of cases, though.
63+
if let Some(name) = field.ty.kind.is_simple_path() && !seen_type_names.insert(name) {
64+
// Already produced an assertion for this type.
65+
} else {
66+
// let _: AssertParamIsEq<FieldTy>;
67+
super::assert_ty_bounds(
68+
cx,
69+
&mut stmts,
70+
field.ty.clone(),
71+
field.span,
72+
&[sym::cmp, sym::AssertParamIsEq],
73+
);
74+
}
6675
}
6776
};
6877

src/test/ui/deriving/deriving-all-codegen.stdout

-13
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,6 @@ struct Point {
9595
impl ::core::clone::Clone for Point {
9696
#[inline]
9797
fn clone(&self) -> Point {
98-
let _: ::core::clone::AssertParamIsClone<u32>;
9998
let _: ::core::clone::AssertParamIsClone<u32>;
10099
*self
101100
}
@@ -152,7 +151,6 @@ impl ::core::cmp::Eq for Point {
152151
#[no_coverage]
153152
fn assert_receiver_is_total_eq(&self) -> () {
154153
let _: ::core::cmp::AssertParamIsEq<u32>;
155-
let _: ::core::cmp::AssertParamIsEq<u32>;
156154
}
157155
}
158156
#[automatically_derived]
@@ -291,13 +289,6 @@ impl ::core::cmp::Eq for Big {
291289
#[no_coverage]
292290
fn assert_receiver_is_total_eq(&self) -> () {
293291
let _: ::core::cmp::AssertParamIsEq<u32>;
294-
let _: ::core::cmp::AssertParamIsEq<u32>;
295-
let _: ::core::cmp::AssertParamIsEq<u32>;
296-
let _: ::core::cmp::AssertParamIsEq<u32>;
297-
let _: ::core::cmp::AssertParamIsEq<u32>;
298-
let _: ::core::cmp::AssertParamIsEq<u32>;
299-
let _: ::core::cmp::AssertParamIsEq<u32>;
300-
let _: ::core::cmp::AssertParamIsEq<u32>;
301292
}
302293
}
303294
#[automatically_derived]
@@ -773,8 +764,6 @@ enum Mixed {
773764
impl ::core::clone::Clone for Mixed {
774765
#[inline]
775766
fn clone(&self) -> Mixed {
776-
let _: ::core::clone::AssertParamIsClone<u32>;
777-
let _: ::core::clone::AssertParamIsClone<u32>;
778767
let _: ::core::clone::AssertParamIsClone<u32>;
779768
*self
780769
}
@@ -871,8 +860,6 @@ impl ::core::cmp::Eq for Mixed {
871860
#[no_coverage]
872861
fn assert_receiver_is_total_eq(&self) -> () {
873862
let _: ::core::cmp::AssertParamIsEq<u32>;
874-
let _: ::core::cmp::AssertParamIsEq<u32>;
875-
let _: ::core::cmp::AssertParamIsEq<u32>;
876863
}
877864
}
878865
#[automatically_derived]

0 commit comments

Comments
 (0)