Skip to content

Commit c747660

Browse files
committed
simplify inject_impl_of_structural_trait
1 parent 790309b commit c747660

File tree

5 files changed

+35
-90
lines changed

5 files changed

+35
-90
lines changed

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

+8-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,14 @@ pub fn expand_deriving_eq(
4545
is_const,
4646
};
4747

48-
super::inject_impl_of_structural_trait(cx, span, item, path_std!(marker::StructuralEq), push);
48+
super::inject_impl_of_structural_trait(
49+
cx,
50+
span,
51+
mitem,
52+
item,
53+
path_std!(marker::StructuralEq),
54+
push,
55+
);
4956

5057
trait_def.expand_ext(cx, mitem, item, push, true)
5158
}

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

+1
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ pub fn expand_deriving_partial_eq(
7575
super::inject_impl_of_structural_trait(
7676
cx,
7777
span,
78+
mitem,
7879
item,
7980
path_std!(marker::StructuralPartialEq),
8081
push,

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

+3-1
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,9 @@ impl<'a> TraitDef<'a> {
711711
.collect();
712712

713713
// Require the current trait.
714-
bounds.push(cx.trait_bound(trait_path.clone(), self.is_const));
714+
if !self.skip_path_as_bound {
715+
bounds.push(cx.trait_bound(trait_path.clone(), self.is_const));
716+
}
715717

716718
// Add a `Copy` bound if required.
717719
if is_packed && self.needs_copy_as_bound_if_packed {

compiler/rustc_builtin_macros/src/deriving/mod.rs

+14-84
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
33
use rustc_ast as ast;
44
use rustc_ast::ptr::P;
5-
use rustc_ast::{GenericArg, Impl, ItemKind, MetaItem};
5+
use rustc_ast::{GenericArg, MetaItem};
66
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, MultiItemModifier};
7-
use rustc_span::symbol::{sym, Ident, Symbol};
7+
use rustc_span::symbol::{sym, Symbol};
88
use rustc_span::Span;
99
use thin_vec::{thin_vec, ThinVec};
1010

@@ -118,96 +118,26 @@ fn call_unreachable(cx: &ExtCtxt<'_>, span: Span) -> P<ast::Expr> {
118118

119119
// Injects `impl<...> Structural for ItemType<...> { }`. In particular,
120120
// does *not* add `where T: Structural` for parameters `T` in `...`.
121-
// (That's the main reason we cannot use TraitDef here.)
122121
fn inject_impl_of_structural_trait(
123122
cx: &mut ExtCtxt<'_>,
124123
span: Span,
124+
mitem: &MetaItem,
125125
item: &Annotatable,
126126
structural_path: generic::ty::Path,
127127
push: &mut dyn FnMut(Annotatable),
128128
) {
129-
let Annotatable::Item(item) = item else {
130-
unreachable!();
131-
};
132-
133-
let generics = match &item.kind {
134-
ItemKind::Struct(_, generics) | ItemKind::Enum(_, generics) => generics,
135-
// Do not inject `impl Structural for Union`. (`PartialEq` does not
136-
// support unions, so we will see error downstream.)
137-
ItemKind::Union(..) => return,
138-
_ => unreachable!(),
139-
};
140-
141-
// Create generics param list for where clauses and impl headers
142-
let mut generics = generics.clone();
143-
144-
let ctxt = span.ctxt();
145-
146-
// Create the type of `self`.
147-
//
148-
// in addition, remove defaults from generic params (impls cannot have them).
149-
let self_params: Vec<_> = generics
150-
.params
151-
.iter_mut()
152-
.map(|param| match &mut param.kind {
153-
ast::GenericParamKind::Lifetime => ast::GenericArg::Lifetime(
154-
cx.lifetime(param.ident.span.with_ctxt(ctxt), param.ident),
155-
),
156-
ast::GenericParamKind::Type { default } => {
157-
*default = None;
158-
ast::GenericArg::Type(cx.ty_ident(param.ident.span.with_ctxt(ctxt), param.ident))
159-
}
160-
ast::GenericParamKind::Const { ty: _, kw_span: _, default } => {
161-
*default = None;
162-
ast::GenericArg::Const(
163-
cx.const_ident(param.ident.span.with_ctxt(ctxt), param.ident),
164-
)
165-
}
166-
})
167-
.collect();
168-
169-
let type_ident = item.ident;
170-
171-
let trait_ref = cx.trait_ref(structural_path.to_path(cx, span, type_ident, &generics));
172-
let self_type = cx.ty_path(cx.path_all(span, false, vec![type_ident], self_params));
173-
174-
// It would be nice to also encode constraint `where Self: Eq` (by adding it
175-
// onto `generics` cloned above). Unfortunately, that strategy runs afoul of
176-
// rust-lang/rust#48214. So we perform that additional check in the compiler
177-
// itself, instead of encoding it here.
178-
179-
// Keep the lint and stability attributes of the original item, to control
180-
// how the generated implementation is linted.
181-
let mut attrs = ast::AttrVec::new();
182-
attrs.extend(
183-
item.attrs
184-
.iter()
185-
.filter(|a| {
186-
[sym::allow, sym::warn, sym::deny, sym::forbid, sym::stable, sym::unstable]
187-
.contains(&a.name_or_empty())
188-
})
189-
.cloned(),
190-
);
191-
// Mark as `automatically_derived` to avoid some silly lints.
192-
attrs.push(cx.attr_word(sym::automatically_derived, span));
193-
194-
let newitem = cx.item(
129+
let trait_def = generic::TraitDef {
195130
span,
196-
Ident::empty(),
197-
attrs,
198-
ItemKind::Impl(Box::new(Impl {
199-
unsafety: ast::Unsafe::No,
200-
polarity: ast::ImplPolarity::Positive,
201-
defaultness: ast::Defaultness::Final,
202-
constness: ast::Const::No,
203-
generics,
204-
of_trait: Some(trait_ref),
205-
self_ty: self_type,
206-
items: ThinVec::new(),
207-
})),
208-
);
209-
210-
push(Annotatable::Item(newitem));
131+
path: structural_path,
132+
skip_path_as_bound: true, // crucial!
133+
needs_copy_as_bound_if_packed: false,
134+
additional_bounds: Vec::new(),
135+
supports_unions: true,
136+
methods: Vec::new(),
137+
associated_types: Vec::new(),
138+
is_const: false,
139+
};
140+
trait_def.expand(cx, mitem, item, push);
211141
}
212142

213143
fn assert_ty_bounds(

tests/ui/deriving/deriving-all-codegen.stdout

+9-4
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,9 @@ impl<T: ::core::hash::Hash + Trait, U: ::core::hash::Hash> ::core::hash::Hash
598598
}
599599
}
600600
#[automatically_derived]
601-
impl<T: Trait, U> ::core::marker::StructuralPartialEq for Generic<T, U> { }
601+
impl<T: Trait, U> ::core::marker::StructuralPartialEq for Generic<T, U> where
602+
T::A: {
603+
}
602604
#[automatically_derived]
603605
impl<T: ::core::cmp::PartialEq + Trait, U: ::core::cmp::PartialEq>
604606
::core::cmp::PartialEq for Generic<T, U> where
@@ -609,7 +611,8 @@ impl<T: ::core::cmp::PartialEq + Trait, U: ::core::cmp::PartialEq>
609611
}
610612
}
611613
#[automatically_derived]
612-
impl<T: Trait, U> ::core::marker::StructuralEq for Generic<T, U> { }
614+
impl<T: Trait, U> ::core::marker::StructuralEq for Generic<T, U> where T::A: {
615+
}
613616
#[automatically_derived]
614617
impl<T: ::core::cmp::Eq + Trait, U: ::core::cmp::Eq> ::core::cmp::Eq for
615618
Generic<T, U> where T::A: ::core::cmp::Eq {
@@ -717,7 +720,7 @@ impl<T: ::core::hash::Hash + ::core::marker::Copy + Trait,
717720
}
718721
#[automatically_derived]
719722
impl<T: Trait, U> ::core::marker::StructuralPartialEq for PackedGeneric<T, U>
720-
{
723+
where T::A: {
721724
}
722725
#[automatically_derived]
723726
impl<T: ::core::cmp::PartialEq + ::core::marker::Copy + Trait,
@@ -731,7 +734,9 @@ impl<T: ::core::cmp::PartialEq + ::core::marker::Copy + Trait,
731734
}
732735
}
733736
#[automatically_derived]
734-
impl<T: Trait, U> ::core::marker::StructuralEq for PackedGeneric<T, U> { }
737+
impl<T: Trait, U> ::core::marker::StructuralEq for PackedGeneric<T, U> where
738+
T::A: {
739+
}
735740
#[automatically_derived]
736741
impl<T: ::core::cmp::Eq + ::core::marker::Copy + Trait, U: ::core::cmp::Eq +
737742
::core::marker::Copy> ::core::cmp::Eq for PackedGeneric<T, U> where

0 commit comments

Comments
 (0)