1
Fork 0

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.
This commit is contained in:
Nicholas Nethercote 2022-07-01 16:32:20 +10:00
parent 5762d2385e
commit a7b1d31a9f
4 changed files with 43 additions and 29 deletions

View file

@ -2036,6 +2036,14 @@ impl TyKind {
pub fn is_unit(&self) -> bool { pub fn is_unit(&self) -> bool {
matches!(self, TyKind::Tup(tys) if tys.is_empty()) 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. /// Syntax used to declare a trait object.

View file

@ -3,6 +3,7 @@ use crate::deriving::generic::*;
use crate::deriving::path_std; use crate::deriving::path_std;
use rustc_ast::{self as ast, Generics, ItemKind, MetaItem, VariantData}; use rustc_ast::{self as ast, Generics, ItemKind, MetaItem, VariantData};
use rustc_data_structures::fx::FxHashSet;
use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Span; use rustc_span::Span;
@ -99,8 +100,15 @@ fn cs_clone_simple(
is_union: bool, is_union: bool,
) -> BlockOrExpr { ) -> BlockOrExpr {
let mut stmts = Vec::new(); let mut stmts = Vec::new();
let mut seen_type_names = FxHashSet::default();
let mut process_variant = |variant: &VariantData| { let mut process_variant = |variant: &VariantData| {
for field in variant.fields() { for field in variant.fields() {
// 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>; // let _: AssertParamIsClone<FieldTy>;
super::assert_ty_bounds( super::assert_ty_bounds(
cx, cx,
@ -110,9 +118,11 @@ fn cs_clone_simple(
&[sym::clone, sym::AssertParamIsClone], &[sym::clone, sym::AssertParamIsClone],
); );
} }
}
}; };
if is_union { if is_union {
// Just a single assertion for unions, that the union impls `Copy`.
// let _: AssertParamIsCopy<Self>; // let _: AssertParamIsCopy<Self>;
let self_ty = cx.ty_path(cx.path_ident(trait_span, Ident::with_dummy_span(kw::SelfUpper))); let self_ty = cx.ty_path(cx.path_ident(trait_span, Ident::with_dummy_span(kw::SelfUpper)));
super::assert_ty_bounds( super::assert_ty_bounds(

View file

@ -3,6 +3,7 @@ use crate::deriving::generic::*;
use crate::deriving::path_std; use crate::deriving::path_std;
use rustc_ast::{self as ast, MetaItem}; use rustc_ast::{self as ast, MetaItem};
use rustc_data_structures::fx::FxHashSet;
use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{sym, Ident}; use rustc_span::symbol::{sym, Ident};
use rustc_span::Span; use rustc_span::Span;
@ -53,8 +54,15 @@ fn cs_total_eq_assert(
substr: &Substructure<'_>, substr: &Substructure<'_>,
) -> BlockOrExpr { ) -> BlockOrExpr {
let mut stmts = Vec::new(); let mut stmts = Vec::new();
let mut seen_type_names = FxHashSet::default();
let mut process_variant = |variant: &ast::VariantData| { let mut process_variant = |variant: &ast::VariantData| {
for field in variant.fields() { for field in variant.fields() {
// 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>; // let _: AssertParamIsEq<FieldTy>;
super::assert_ty_bounds( super::assert_ty_bounds(
cx, cx,
@ -64,6 +72,7 @@ fn cs_total_eq_assert(
&[sym::cmp, sym::AssertParamIsEq], &[sym::cmp, sym::AssertParamIsEq],
); );
} }
}
}; };
match *substr.fields { match *substr.fields {

View file

@ -95,7 +95,6 @@ struct Point {
impl ::core::clone::Clone for Point { impl ::core::clone::Clone for Point {
#[inline] #[inline]
fn clone(&self) -> Point { fn clone(&self) -> Point {
let _: ::core::clone::AssertParamIsClone<u32>;
let _: ::core::clone::AssertParamIsClone<u32>; let _: ::core::clone::AssertParamIsClone<u32>;
*self *self
} }
@ -152,7 +151,6 @@ impl ::core::cmp::Eq for Point {
#[no_coverage] #[no_coverage]
fn assert_receiver_is_total_eq(&self) -> () { fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<u32>; let _: ::core::cmp::AssertParamIsEq<u32>;
let _: ::core::cmp::AssertParamIsEq<u32>;
} }
} }
#[automatically_derived] #[automatically_derived]
@ -291,13 +289,6 @@ impl ::core::cmp::Eq for Big {
#[no_coverage] #[no_coverage]
fn assert_receiver_is_total_eq(&self) -> () { 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>;
let _: ::core::cmp::AssertParamIsEq<u32>;
} }
} }
#[automatically_derived] #[automatically_derived]
@ -773,8 +764,6 @@ enum Mixed {
impl ::core::clone::Clone for Mixed { impl ::core::clone::Clone for Mixed {
#[inline] #[inline]
fn clone(&self) -> Mixed { fn clone(&self) -> Mixed {
let _: ::core::clone::AssertParamIsClone<u32>;
let _: ::core::clone::AssertParamIsClone<u32>;
let _: ::core::clone::AssertParamIsClone<u32>; let _: ::core::clone::AssertParamIsClone<u32>;
*self *self
} }
@ -871,8 +860,6 @@ impl ::core::cmp::Eq for Mixed {
#[no_coverage] #[no_coverage]
fn assert_receiver_is_total_eq(&self) -> () { 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>;
} }
} }
#[automatically_derived] #[automatically_derived]