Skip to content

Commit 989b466

Browse files
committed
Modernize rustc_builtin_macros generics helpers
1 parent dd91aba commit 989b466

File tree

1 file changed

+115
-95
lines changed
  • compiler/rustc_builtin_macros/src/deriving/generic

1 file changed

+115
-95
lines changed

compiler/rustc_builtin_macros/src/deriving/generic/mod.rs

+115-95
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,9 @@
3737
//! following snippet
3838
//!
3939
//! ```rust
40-
//! # #![allow(dead_code)]
41-
//! struct A { x : i32 }
40+
//! struct A {
41+
//! x: i32,
42+
//! }
4243
//!
4344
//! struct B(i32);
4445
//!
@@ -74,6 +75,7 @@
7475
//! trait PartialEq {
7576
//! fn eq(&self, other: &Self) -> bool;
7677
//! }
78+
//!
7779
//! impl PartialEq for i32 {
7880
//! fn eq(&self, other: &i32) -> bool {
7981
//! *self == *other
@@ -90,22 +92,22 @@
9092
//!
9193
//! ```text
9294
//! Struct(vec![FieldInfo {
93-
//! span: <span of x>
94-
//! name: Some(<ident of x>),
95-
//! self_: <expr for &self.x>,
96-
//! other: vec![<expr for &other.x]
97-
//! }])
95+
//! span: <span of x>,
96+
//! name: Some(<ident of x>),
97+
//! self_: <expr for &self.x>,
98+
//! other: vec![<expr for &other.x>],
99+
//! }])
98100
//! ```
99101
//!
100102
//! For the `B` impl, called with `B(a)` and `B(b)`,
101103
//!
102104
//! ```text
103105
//! Struct(vec![FieldInfo {
104-
//! span: <span of `i32`>,
105-
//! name: None,
106-
//! self_: <expr for &a>
107-
//! other: vec![<expr for &b>]
108-
//! }])
106+
//! span: <span of i32>,
107+
//! name: None,
108+
//! self_: <expr for &a>,
109+
//! other: vec![<expr for &b>],
110+
//! }])
109111
//! ```
110112
//!
111113
//! ## Enums
@@ -114,33 +116,42 @@
114116
//! == C0(b)`, the SubstructureFields is
115117
//!
116118
//! ```text
117-
//! EnumMatching(0, <ast::Variant for C0>,
118-
//! vec![FieldInfo {
119-
//! span: <span of i32>
120-
//! name: None,
121-
//! self_: <expr for &a>,
122-
//! other: vec![<expr for &b>]
123-
//! }])
119+
//! EnumMatching(
120+
//! 0,
121+
//! <ast::Variant for C0>,
122+
//! vec![FieldInfo {
123+
//! span: <span of i32>,
124+
//! name: None,
125+
//! self_: <expr for &a>,
126+
//! other: vec![<expr for &b>],
127+
//! }],
128+
//! )
124129
//! ```
125130
//!
126131
//! For `C1 {x}` and `C1 {x}`,
127132
//!
128133
//! ```text
129-
//! EnumMatching(1, <ast::Variant for C1>,
130-
//! vec![FieldInfo {
131-
//! span: <span of x>
132-
//! name: Some(<ident of x>),
133-
//! self_: <expr for &self.x>,
134-
//! other: vec![<expr for &other.x>]
135-
//! }])
134+
//! EnumMatching(
135+
//! 1,
136+
//! <ast::Variant for C1>,
137+
//! vec![FieldInfo {
138+
//! span: <span of x>,
139+
//! name: Some(<ident of x>),
140+
//! self_: <expr for &self.x>,
141+
//! other: vec![<expr for &other.x>],
142+
//! }],
143+
//! )
136144
//! ```
137145
//!
138146
//! For the tags,
139147
//!
140148
//! ```text
141149
//! EnumTag(
142-
//! &[<ident of self tag>, <ident of other tag>], <expr to combine with>)
150+
//! &[<ident of self tag>, <ident of other tag>],
151+
//! <expr to combine with>,
152+
//! )
143153
//! ```
154+
//!
144155
//! Note that this setup doesn't allow for the brute-force "match every variant
145156
//! against every other variant" approach, which is bad because it produces a
146157
//! quadratic amount of code (see #15375).
@@ -154,9 +165,13 @@
154165
//!
155166
//! StaticStruct(<ast::VariantData of B>, Unnamed(vec![<span of x>]))
156167
//!
157-
//! StaticEnum(<ast::EnumDef of C>,
158-
//! vec![(<ident of C0>, <span of C0>, Unnamed(vec![<span of i32>])),
159-
//! (<ident of C1>, <span of C1>, Named(vec![(<ident of x>, <span of x>)]))])
168+
//! StaticEnum(
169+
//! <ast::EnumDef of C>,
170+
//! vec![
171+
//! (<ident of C0>, <span of C0>, Unnamed(vec![<span of i32>])),
172+
//! (<ident of C1>, <span of C1>, Named(vec![(<ident of x>, <span of x>)])),
173+
//! ],
174+
//! )
160175
//! ```
161176
162177
pub use StaticFields::*;
@@ -522,7 +537,10 @@ impl<'a> TraitDef<'a> {
522537
/// Given that we are deriving a trait `DerivedTrait` for a type like:
523538
///
524539
/// ```ignore (only-for-syntax-highlight)
525-
/// struct Struct<'a, ..., 'z, A, B: DeclaredTrait, C, ..., Z> where C: WhereTrait {
540+
/// struct Struct<'a, ..., 'z, A, B: DeclaredTrait, C, ..., Z>
541+
/// where
542+
/// C: WhereTrait,
543+
/// {
526544
/// a: A,
527545
/// b: B::Item,
528546
/// b1: <B as DeclaredTrait>::Item,
@@ -535,12 +553,13 @@ impl<'a> TraitDef<'a> {
535553
/// create an impl like:
536554
///
537555
/// ```ignore (only-for-syntax-highlight)
538-
/// impl<'a, ..., 'z, A, B: DeclaredTrait, C, ... Z> where
539-
/// C: WhereTrait,
556+
/// impl<'a, ..., 'z, A, B: DeclaredTrait, C, ..., Z>
557+
/// where
558+
/// C: WhereTrait,
540559
/// A: DerivedTrait + B1 + ... + BN,
541560
/// B: DerivedTrait + B1 + ... + BN,
542561
/// C: DerivedTrait + B1 + ... + BN,
543-
/// B::Item: DerivedTrait + B1 + ... + BN,
562+
/// B::Item: DerivedTrait + B1 + ... + BN,
544563
/// <C as WhereTrait>::Item: DerivedTrait + B1 + ... + BN,
545564
/// ...
546565
/// {
@@ -676,65 +695,61 @@ impl<'a> TraitDef<'a> {
676695
}
677696
}));
678697

679-
{
680-
// Extra scope required here so ty_params goes out of scope before params is moved
681-
682-
let mut ty_params = params
683-
.iter()
684-
.filter(|param| matches!(param.kind, ast::GenericParamKind::Type { .. }))
685-
.peekable();
686-
687-
if ty_params.peek().is_some() {
688-
let ty_param_names: Vec<Symbol> =
689-
ty_params.map(|ty_param| ty_param.ident.name).collect();
690-
691-
for field_ty in field_tys {
692-
let field_ty_params = find_type_parameters(&field_ty, &ty_param_names, cx);
693-
694-
for field_ty_param in field_ty_params {
695-
// if we have already handled this type, skip it
696-
if let ast::TyKind::Path(_, p) = &field_ty_param.ty.kind
697-
&& let [sole_segment] = &*p.segments
698-
&& ty_param_names.contains(&sole_segment.ident.name)
699-
{
700-
continue;
701-
}
702-
let mut bounds: Vec<_> = self
703-
.additional_bounds
704-
.iter()
705-
.map(|p| {
706-
cx.trait_bound(
707-
p.to_path(cx, self.span, type_ident, generics),
708-
self.is_const,
709-
)
710-
})
711-
.collect();
712-
713-
// Require the current trait.
714-
if !self.skip_path_as_bound {
715-
bounds.push(cx.trait_bound(trait_path.clone(), self.is_const));
716-
}
717-
718-
// Add a `Copy` bound if required.
719-
if is_packed && self.needs_copy_as_bound_if_packed {
720-
let p = deriving::path_std!(marker::Copy);
721-
bounds.push(cx.trait_bound(
698+
let mut ty_params = params
699+
.iter()
700+
.filter(|param| matches!(param.kind, ast::GenericParamKind::Type { .. }))
701+
.peekable();
702+
703+
if ty_params.peek().is_some() {
704+
let ty_param_names: Vec<Symbol> =
705+
ty_params.map(|ty_param| ty_param.ident.name).collect();
706+
707+
for field_ty in field_tys {
708+
let field_ty_params = find_type_parameters(&field_ty, &ty_param_names, cx);
709+
710+
for field_ty_param in field_ty_params {
711+
// if we have already handled this type, skip it
712+
if let ast::TyKind::Path(_, p) = &field_ty_param.ty.kind
713+
&& let [sole_segment] = &*p.segments
714+
&& ty_param_names.contains(&sole_segment.ident.name)
715+
{
716+
continue;
717+
}
718+
let mut bounds: Vec<_> = self
719+
.additional_bounds
720+
.iter()
721+
.map(|p| {
722+
cx.trait_bound(
722723
p.to_path(cx, self.span, type_ident, generics),
723724
self.is_const,
724-
));
725-
}
725+
)
726+
})
727+
.collect();
726728

727-
if !bounds.is_empty() {
728-
let predicate = ast::WhereBoundPredicate {
729-
span: self.span,
730-
bound_generic_params: field_ty_param.bound_generic_params,
731-
bounded_ty: field_ty_param.ty,
732-
bounds,
733-
};
729+
// Require the current trait.
730+
if !self.skip_path_as_bound {
731+
bounds.push(cx.trait_bound(trait_path.clone(), self.is_const));
732+
}
734733

735-
let predicate = ast::WherePredicate::BoundPredicate(predicate);
736-
where_clause.predicates.push(predicate);
737-
}
734+
// Add a `Copy` bound if required.
735+
if is_packed && self.needs_copy_as_bound_if_packed {
736+
let p = deriving::path_std!(marker::Copy);
737+
bounds.push(cx.trait_bound(
738+
p.to_path(cx, self.span, type_ident, generics),
739+
self.is_const,
740+
));
741+
}
742+
743+
if !bounds.is_empty() {
744+
let predicate = ast::WhereBoundPredicate {
745+
span: self.span,
746+
bound_generic_params: field_ty_param.bound_generic_params,
747+
bounded_ty: field_ty_param.ty,
748+
bounds,
749+
};
750+
751+
let predicate = ast::WherePredicate::BoundPredicate(predicate);
752+
where_clause.predicates.push(predicate);
738753
}
739754
}
740755
}
@@ -1026,6 +1041,7 @@ impl<'a> MethodDef<'a> {
10261041
}
10271042

10281043
/// The normal case uses field access.
1044+
///
10291045
/// ```
10301046
/// #[derive(PartialEq)]
10311047
/// # struct Dummy;
@@ -1038,10 +1054,12 @@ impl<'a> MethodDef<'a> {
10381054
/// }
10391055
/// }
10401056
/// ```
1057+
///
10411058
/// But if the struct is `repr(packed)`, we can't use something like
10421059
/// `&self.x` because that might cause an unaligned ref. So for any trait
10431060
/// method that takes a reference, we use a local block to force a copy.
10441061
/// This requires that the field impl `Copy`.
1062+
///
10451063
/// ```rust,ignore (example)
10461064
/// # struct A { x: u8, y: u8 }
10471065
/// impl PartialEq for A {
@@ -1053,7 +1071,7 @@ impl<'a> MethodDef<'a> {
10531071
/// impl Hash for A {
10541072
/// fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
10551073
/// ::core::hash::Hash::hash(&{ self.x }, state);
1056-
/// ::core::hash::Hash::hash(&{ self.y }, state)
1074+
/// ::core::hash::Hash::hash(&{ self.y }, state);
10571075
/// }
10581076
/// }
10591077
/// ```
@@ -1107,7 +1125,9 @@ impl<'a> MethodDef<'a> {
11071125
/// A2(i32)
11081126
/// }
11091127
/// ```
1128+
///
11101129
/// is equivalent to:
1130+
///
11111131
/// ```
11121132
/// #![feature(core_intrinsics)]
11131133
/// enum A {
@@ -1119,15 +1139,15 @@ impl<'a> MethodDef<'a> {
11191139
/// fn eq(&self, other: &A) -> bool {
11201140
/// let __self_tag = ::core::intrinsics::discriminant_value(self);
11211141
/// let __arg1_tag = ::core::intrinsics::discriminant_value(other);
1122-
/// __self_tag == __arg1_tag &&
1123-
/// match (self, other) {
1124-
/// (A::A2(__self_0), A::A2(__arg1_0)) =>
1125-
/// *__self_0 == *__arg1_0,
1142+
/// __self_tag == __arg1_tag
1143+
/// && match (self, other) {
1144+
/// (A::A2(__self_0), A::A2(__arg1_0)) => *__self_0 == *__arg1_0,
11261145
/// _ => true,
11271146
/// }
11281147
/// }
11291148
/// }
11301149
/// ```
1150+
///
11311151
/// Creates a tag check combined with a match for a tuple of all
11321152
/// `selflike_args`, with an arm for each variant with fields, possibly an
11331153
/// arm for each fieldless variant (if `unify_fieldless_variants` is not
@@ -1349,7 +1369,7 @@ impl<'a> MethodDef<'a> {
13491369
// (Variant1, Variant1, ...) => Body1
13501370
// (Variant2, Variant2, ...) => Body2,
13511371
// ...
1352-
// _ => ::core::intrinsics::unreachable()
1372+
// _ => ::core::intrinsics::unreachable(),
13531373
// }
13541374
let get_match_expr = |mut selflike_args: ThinVec<P<Expr>>| {
13551375
let match_arg = if selflike_args.len() == 1 {

0 commit comments

Comments
 (0)