1+ use rustc_ast:: mut_visit:: { self , MutVisitor } ;
12use rustc_ast:: { self as ast, MetaItem , Safety } ;
23use rustc_data_structures:: fx:: FxHashSet ;
34use rustc_expand:: base:: { Annotatable , ExtCtxt } ;
4- use rustc_span:: { Ident , Span , sym} ;
5+ use rustc_span:: { Ident , Span , kw , sym} ;
56use thin_vec:: { ThinVec , thin_vec} ;
67
78use crate :: deriving:: generic:: * ;
89use crate :: deriving:: path_std;
910
11+ struct ReplaceSelfTyVisitor ( Box < ast:: Ty > ) ;
12+ impl MutVisitor for ReplaceSelfTyVisitor {
13+ fn visit_ty ( & mut self , ty : & mut ast:: Ty ) {
14+ if let ast:: TyKind :: Path ( None , path) = & mut ty. kind
15+ && let [ segment] = & path. segments [ ..]
16+ && * segment == kw:: SelfUpper
17+ {
18+ * ty = * self . 0 . clone ( ) ;
19+ } else {
20+ mut_visit:: walk_ty ( self , ty) ;
21+ }
22+ }
23+ }
24+
25+ struct RespanGenericsVisitor ( Span ) ;
26+ impl MutVisitor for RespanGenericsVisitor {
27+ fn visit_generics ( & mut self , generics : & mut ast:: Generics ) {
28+ generics. where_clause . span = self . 0 . with_ctxt ( generics. where_clause . span . ctxt ( ) ) ;
29+ generics. span = self . 0 . with_ctxt ( generics. span . ctxt ( ) ) ;
30+ mut_visit:: walk_generics ( self , generics) ;
31+ }
32+ fn visit_where_predicate ( & mut self , predicate : & mut ast:: WherePredicate ) {
33+ predicate. span = self . 0 . with_ctxt ( predicate. span . ctxt ( ) ) ;
34+ mut_visit:: walk_where_predicate ( self , predicate) ;
35+ }
36+ fn visit_where_predicate_kind ( & mut self , kind : & mut ast:: WherePredicateKind ) {
37+ match kind {
38+ ast:: WherePredicateKind :: BoundPredicate ( bound_predicate) => {
39+ bound_predicate. bounded_ty . span =
40+ self . 0 . with_ctxt ( bound_predicate. bounded_ty . span . ctxt ( ) ) ;
41+ }
42+ ast:: WherePredicateKind :: EqPredicate ( eq_predicate) => {
43+ eq_predicate. lhs_ty . span = self . 0 . with_ctxt ( eq_predicate. lhs_ty . span . ctxt ( ) ) ;
44+ eq_predicate. rhs_ty . span = self . 0 . with_ctxt ( eq_predicate. rhs_ty . span . ctxt ( ) ) ;
45+ }
46+ ast:: WherePredicateKind :: RegionPredicate ( _) => { }
47+ }
48+ mut_visit:: walk_where_predicate_kind ( self , kind) ;
49+ }
50+ fn visit_param_bound (
51+ & mut self ,
52+ bound : & mut rustc_ast:: GenericBound ,
53+ _ctxt : rustc_ast:: visit:: BoundKind ,
54+ ) {
55+ match bound {
56+ ast:: GenericBound :: Trait ( poly_trait_ref) => {
57+ poly_trait_ref. span = self . 0 . with_ctxt ( poly_trait_ref. span . ctxt ( ) ) ;
58+ }
59+ ast:: GenericBound :: Outlives ( _) => { }
60+ ast:: GenericBound :: Use ( _, _) => { }
61+ }
62+ ast:: mut_visit:: walk_param_bound ( self , bound) ;
63+ }
64+ }
65+
66+ struct StripConstTraitBoundsVisitor ;
67+ impl MutVisitor for StripConstTraitBoundsVisitor {
68+ fn visit_param_bound (
69+ & mut self ,
70+ bound : & mut rustc_ast:: GenericBound ,
71+ _ctxt : rustc_ast:: visit:: BoundKind ,
72+ ) {
73+ if let ast:: GenericBound :: Trait ( poly_trait_ref) = bound {
74+ poly_trait_ref. modifiers . constness = ast:: BoundConstness :: Never ;
75+ }
76+ mut_visit:: walk_param_bound ( self , bound) ;
77+ }
78+ }
79+
1080pub ( crate ) fn expand_deriving_eq (
1181 cx : & ExtCtxt < ' _ > ,
1282 span : Span ,
@@ -17,8 +87,8 @@ pub(crate) fn expand_deriving_eq(
1787) {
1888 let span = cx. with_def_site_ctxt ( span) ;
1989
20- let mut impl_generics = ast:: Generics :: default ( ) ;
21- let mut impl_self_ty = None ;
90+ let mut fn_generics = ast:: Generics { span , .. Default :: default ( ) } ;
91+ let mut self_ty = None ;
2292
2393 let trait_def = TraitDef {
2494 span,
@@ -45,150 +115,90 @@ pub(crate) fn expand_deriving_eq(
45115 let ast:: ItemKind :: Impl ( imp) = & mut item. kind else {
46116 unreachable ! ( "should have emitted an Impl in trait_def.expand_ext" ) ;
47117 } ;
48- impl_generics = imp. generics . clone ( ) ;
49- impl_self_ty = Some ( imp. self_ty . clone ( ) ) ;
50- respan_generics_for_derive ( & mut imp. generics , span) ;
118+ use ast:: mut_visit:: MutVisitor ;
119+ RespanGenericsVisitor ( span) . visit_generics ( & mut imp. generics ) ;
120+ fn_generics = imp. generics . clone ( ) ;
121+ self_ty = Some ( imp. self_ty . clone ( ) ) ;
51122 push ( a)
52123 } ,
53124 true ,
54125 ) ;
55126
56- let assert_stmts = eq_assert_stmts_from_item ( cx, span, item) ;
127+ let self_ty =
128+ self_ty. unwrap_or_else ( || cx. dcx ( ) . span_bug ( span, "missing self type in `derive(Eq)`" ) ) ;
129+ let assert_stmts = eq_assert_stmts_from_item ( cx, span, item, ReplaceSelfTyVisitor ( self_ty) ) ;
57130
58131 // Skip generating `assert_fields_are_eq` impl if there are no assertions to make
59132 if assert_stmts. is_empty ( ) {
60133 return ;
61134 }
62135
63- let impl_self_ty = impl_self_ty
64- . unwrap_or_else ( || cx. dcx ( ) . span_bug ( span, "missing self type in `derive(Eq)`" ) ) ;
65- push ( Annotatable :: Item ( assert_fields_are_eq_impl (
66- cx,
67- span,
68- strip_const_trait_bounds_from_generics ( impl_generics) ,
69- impl_self_ty,
70- assert_stmts,
71- ) ) ) ;
72- }
73-
74- fn respan_generics_for_derive ( generics : & mut ast:: Generics , span : Span ) {
75- for predicate in & mut generics. where_clause . predicates {
76- predicate. span = span. with_ctxt ( predicate. span . ctxt ( ) ) ;
77-
78- match & mut predicate. kind {
79- ast:: WherePredicateKind :: BoundPredicate ( bound_predicate) => {
80- bound_predicate. bounded_ty . span =
81- span. with_ctxt ( bound_predicate. bounded_ty . span . ctxt ( ) ) ;
82-
83- for bound in & mut bound_predicate. bounds {
84- match bound {
85- ast:: GenericBound :: Trait ( poly_trait_ref) => {
86- poly_trait_ref. span = span. with_ctxt ( poly_trait_ref. span . ctxt ( ) ) ;
87- }
88- _ => { }
89- }
90- }
91- }
92- ast:: WherePredicateKind :: RegionPredicate ( region_predicate) => {
93- for bound in & mut region_predicate. bounds {
94- match bound {
95- ast:: GenericBound :: Trait ( poly_trait_ref) => {
96- poly_trait_ref. span = span. with_ctxt ( poly_trait_ref. span . ctxt ( ) ) ;
97- }
98- _ => { }
99- }
100- }
101- }
102- ast:: WherePredicateKind :: EqPredicate ( eq_predicate) => {
103- eq_predicate. lhs_ty . span = span. with_ctxt ( eq_predicate. lhs_ty . span . ctxt ( ) ) ;
104- eq_predicate. rhs_ty . span = span. with_ctxt ( eq_predicate. rhs_ty . span . ctxt ( ) ) ;
105- }
106- }
107- }
108- generics. where_clause . span = span. with_ctxt ( generics. where_clause . span . ctxt ( ) ) ;
109- generics. span = span. with_ctxt ( generics. span . ctxt ( ) ) ;
136+ StripConstTraitBoundsVisitor . visit_generics ( & mut fn_generics) ;
137+ push ( Annotatable :: Item ( expand_const_item_block ( cx, span, fn_generics, assert_stmts) ) ) ;
110138}
111139
112- fn assert_fields_are_eq_impl (
140+ fn expand_const_item_block (
113141 cx : & ExtCtxt < ' _ > ,
114142 span : Span ,
115- impl_generics : ast:: Generics ,
116- impl_self_ty : Box < ast:: Ty > ,
143+ fn_generics : ast:: Generics ,
117144 assert_stmts : ThinVec < ast:: Stmt > ,
118145) -> Box < ast:: Item > {
119146 cx. item (
120147 span,
121148 ast:: AttrVec :: new ( ) ,
122- ast:: ItemKind :: Impl ( ast:: Impl {
123- generics : impl_generics,
124- of_trait : None ,
125- constness : ast:: Const :: No ,
126- self_ty : impl_self_ty,
127- items : thin_vec ! [ Box :: new( ast:: AssocItem {
128- id: ast:: DUMMY_NODE_ID ,
129- attrs: thin_vec![
130- cx. attr_nested_word( sym:: doc, sym:: hidden, span) ,
131- cx. attr_nested_word( sym:: coverage, sym:: off, span) ,
132- ] ,
149+ ast:: ItemKind :: ConstBlock ( ast:: ConstBlockItem {
150+ span,
151+ id : ast:: DUMMY_NODE_ID ,
152+ block : cx. block (
133153 span,
134- vis: ast:: Visibility {
135- span: span. shrink_to_lo( ) ,
136- kind: ast:: VisibilityKind :: Inherited ,
137- tokens: None ,
138- } ,
139- kind: ast:: AssocItemKind :: Fn ( Box :: new( ast:: Fn {
140- defaultness: ast:: Defaultness :: Implicit ,
141- ident: Ident :: new( sym:: assert_fields_are_eq, span) ,
142- generics: ast:: Generics { span, ..Default :: default ( ) } ,
143- sig: ast:: FnSig {
144- header: ast:: FnHeader {
145- constness: ast:: Const :: Yes ( span) ,
146- coroutine_kind: None ,
147- safety: ast:: Safety :: Default ,
148- ext: ast:: Extern :: None ,
149- } ,
150- decl: cx. fn_decl( ThinVec :: new( ) , ast:: FnRetTy :: Default ( span) ) ,
154+ thin_vec ! [ ast:: Stmt {
155+ span,
156+ id: ast:: DUMMY_NODE_ID ,
157+ kind: ast:: StmtKind :: Item ( Box :: new( ast:: Item {
151158 span,
152- } ,
153- contract: None ,
154- define_opaque: None ,
155- body: Some ( cx. block( span, assert_stmts) ) ,
156- eii_impls: ThinVec :: new( ) ,
157- } ) ) ,
158- tokens: None ,
159- } ) ] ,
159+ id: ast:: DUMMY_NODE_ID ,
160+ attrs: thin_vec![
161+ cx. attr_nested_word( sym:: doc, sym:: hidden, span) ,
162+ cx. attr_nested_word( sym:: coverage, sym:: off, span) ,
163+ cx. attr_word( sym:: inline, span) ,
164+ ] ,
165+ vis: ast:: Visibility {
166+ kind: ast:: VisibilityKind :: Inherited ,
167+ span,
168+ tokens: None ,
169+ } ,
170+ tokens: None ,
171+ kind: ast:: ItemKind :: Fn ( Box :: new( ast:: Fn {
172+ defaultness: ast:: Defaultness :: Implicit ,
173+ ident: Ident :: new( sym:: assert_fields_are_eq, span) ,
174+ generics: fn_generics,
175+ sig: ast:: FnSig {
176+ header: ast:: FnHeader {
177+ constness: ast:: Const :: Yes ( span) ,
178+ coroutine_kind: None ,
179+ safety: ast:: Safety :: Default ,
180+ ext: ast:: Extern :: None ,
181+ } ,
182+ decl: cx. fn_decl( ThinVec :: new( ) , ast:: FnRetTy :: Default ( span) ) ,
183+ span,
184+ } ,
185+ contract: None ,
186+ define_opaque: None ,
187+ body: Some ( cx. block( span, assert_stmts) ) ,
188+ eii_impls: ThinVec :: new( ) ,
189+ } ) )
190+ } ) )
191+ } , ] ,
192+ ) ,
160193 } ) ,
161194 )
162195}
163196
164- fn strip_const_trait_bounds_from_generics ( mut generics : ast:: Generics ) -> ast:: Generics {
165- for param in & mut generics. params {
166- if let ast:: GenericParamKind :: Type { .. } = & param. kind {
167- strip_constness_from_bounds ( & mut param. bounds ) ;
168- }
169- }
170-
171- for predicate in & mut generics. where_clause . predicates {
172- if let ast:: WherePredicateKind :: BoundPredicate ( bound_predicate) = & mut predicate. kind {
173- strip_constness_from_bounds ( & mut bound_predicate. bounds ) ;
174- }
175- }
176-
177- generics
178- }
179-
180- fn strip_constness_from_bounds ( bounds : & mut [ ast:: GenericBound ] ) {
181- for bound in bounds {
182- if let ast:: GenericBound :: Trait ( poly_trait_ref) = bound {
183- poly_trait_ref. modifiers . constness = ast:: BoundConstness :: Never ;
184- }
185- }
186- }
187-
188197fn eq_assert_stmts_from_item (
189198 cx : & ExtCtxt < ' _ > ,
190199 span : Span ,
191200 item : & Annotatable ,
201+ mut replace_self_ty : ReplaceSelfTyVisitor ,
192202) -> ThinVec < ast:: Stmt > {
193203 let mut stmts = ThinVec :: new ( ) ;
194204 let mut seen_type_names = FxHashSet :: default ( ) ;
@@ -202,11 +212,14 @@ fn eq_assert_stmts_from_item(
202212 {
203213 // Already produced an assertion for this type.
204214 } else {
215+ use ast:: mut_visit:: MutVisitor ;
216+ let mut field_ty = field. ty . clone ( ) ;
217+ replace_self_ty. visit_ty ( & mut field_ty) ;
205218 // let _: AssertParamIsEq<FieldTy>;
206219 super :: assert_ty_bounds (
207220 cx,
208221 & mut stmts,
209- field . ty . clone ( ) ,
222+ field_ty ,
210223 field. span ,
211224 & [ sym:: cmp, sym:: AssertParamIsEq ] ,
212225 ) ;
0 commit comments