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 {
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.

View file

@ -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(

View file

@ -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],
);
}
}
};

View file

@ -95,7 +95,6 @@ struct Point {
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]
@ -773,8 +764,6 @@ enum Mixed {
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]