@@ -6,7 +6,7 @@ use itertools::Itertools;
6
6
use rustc_ast:: ast;
7
7
use rustc_span:: { BytePos , Span } ;
8
8
9
- use crate :: comment:: combine_strs_with_missing_comments;
9
+ use crate :: comment:: { FindUncommented , combine_strs_with_missing_comments} ;
10
10
use crate :: config:: lists:: * ;
11
11
use crate :: expr:: rewrite_field;
12
12
use crate :: items:: { rewrite_struct_field, rewrite_struct_field_prefix} ;
@@ -108,12 +108,13 @@ impl AlignedItem for ast::ExprField {
108
108
}
109
109
}
110
110
111
- pub ( crate ) fn rewrite_with_alignment < T : AlignedItem > (
111
+ pub ( crate ) fn rewrite_with_alignment < T : AlignedItem + std :: fmt :: Debug > (
112
112
fields : & [ T ] ,
113
113
context : & RewriteContext < ' _ > ,
114
114
shape : Shape ,
115
115
span : Span ,
116
116
one_line_width : usize ,
117
+ struct_rest : Option < & ast:: StructRest > ,
117
118
) -> Option < String > {
118
119
let ( spaces, group_index) = if context. config . struct_field_align_threshold ( ) > 0 {
119
120
group_aligned_items ( context, fields)
@@ -170,12 +171,15 @@ pub(crate) fn rewrite_with_alignment<T: AlignedItem>(
170
171
shape. indent ,
171
172
one_line_width,
172
173
force_separator,
174
+ struct_rest,
175
+ shape,
173
176
) ?;
174
177
if rest. is_empty ( ) {
175
178
Some ( result + spaces)
176
179
} else {
177
180
let rest_span = mk_sp ( init_last_pos, span. hi ( ) ) ;
178
- let rest_str = rewrite_with_alignment ( rest, context, shape, rest_span, one_line_width) ?;
181
+ let rest_str =
182
+ rewrite_with_alignment ( rest, context, shape, rest_span, one_line_width, struct_rest) ?;
179
183
Some ( format ! (
180
184
"{}{}\n {}{}" ,
181
185
result,
@@ -211,6 +215,8 @@ fn rewrite_aligned_items_inner<T: AlignedItem>(
211
215
offset : Indent ,
212
216
one_line_width : usize ,
213
217
force_trailing_separator : bool ,
218
+ struct_rest : Option < & ast:: StructRest > ,
219
+ shape : Shape ,
214
220
) -> Option < String > {
215
221
// 1 = ","
216
222
let item_shape = Shape :: indented ( offset, context. config ) . sub_width_opt ( 1 ) ?;
@@ -221,14 +227,71 @@ fn rewrite_aligned_items_inner<T: AlignedItem>(
221
227
field_prefix_max_width = 0 ;
222
228
}
223
229
230
+ enum StructLitField < ' a , T > {
231
+ Regular ( & ' a T ) ,
232
+ Base ( & ' a ast:: Expr ) ,
233
+ Rest ( Span ) ,
234
+ }
235
+
236
+ let has_base_or_rest = match struct_rest {
237
+ Some ( rest) => match rest {
238
+ // ast::StructRest::None if fields.is_empty() => return format!("{path_str} {{}}"),
239
+ // ast::StructRest::Rest(_) if fields.is_empty() => {
240
+ // return Ok(format!("{path_str} {{ .. }}"));
241
+ // }
242
+ ast:: StructRest :: Rest ( _) | ast:: StructRest :: Base ( _) => true ,
243
+ _ => false ,
244
+ } ,
245
+ None => false ,
246
+ } ;
247
+
248
+ let field_iter = fields. iter ( ) . map ( StructLitField :: Regular ) . chain (
249
+ struct_rest
250
+ . and_then ( |rest| match rest {
251
+ ast:: StructRest :: Base ( expr) => Some ( StructLitField :: Base ( & * * expr) ) ,
252
+ ast:: StructRest :: Rest ( span) => Some ( StructLitField :: Rest ( * span) ) ,
253
+ ast:: StructRest :: None => None ,
254
+ } )
255
+ . into_iter ( ) ,
256
+ ) ;
257
+
258
+ let span_lo = |item : & StructLitField < ' _ , T > | match * item {
259
+ StructLitField :: Regular ( field) => field. get_span ( ) . lo ( ) ,
260
+ StructLitField :: Base ( expr) => {
261
+ let last_field_hi = fields
262
+ . last ( )
263
+ . map_or ( span. lo ( ) , |field| field. get_span ( ) . hi ( ) ) ;
264
+ let snippet = context. snippet ( mk_sp ( last_field_hi, expr. span . lo ( ) ) ) ;
265
+ let pos = snippet. find_uncommented ( ".." ) . unwrap ( ) ;
266
+ last_field_hi + BytePos ( pos as u32 )
267
+ }
268
+ StructLitField :: Rest ( span) => span. lo ( ) ,
269
+ } ;
270
+ let span_hi = |item : & StructLitField < ' _ , T > | match * item {
271
+ StructLitField :: Regular ( field) => field. get_span ( ) . hi ( ) ,
272
+ StructLitField :: Base ( expr) => expr. span . hi ( ) ,
273
+ StructLitField :: Rest ( span) => span. hi ( ) ,
274
+ } ;
275
+ let rewrite = |item : & StructLitField < ' _ , T > | match * item {
276
+ StructLitField :: Regular ( field) => {
277
+ field. rewrite_aligned_item ( context, item_shape, field_prefix_max_width)
278
+ }
279
+ StructLitField :: Base ( expr) => {
280
+ // 2 = ..
281
+ expr. rewrite_result ( context, shape. offset_left ( 2 , span) ?)
282
+ . map ( |s| format ! ( "..{}" , s) )
283
+ }
284
+ StructLitField :: Rest ( _) => Ok ( ".." . to_owned ( ) ) ,
285
+ } ;
286
+
224
287
let mut items = itemize_list (
225
288
context. snippet_provider ,
226
- fields . iter ( ) ,
289
+ field_iter ,
227
290
"}" ,
228
291
"," ,
229
- |field| field . get_span ( ) . lo ( ) ,
230
- |field| field . get_span ( ) . hi ( ) ,
231
- |field| field . rewrite_aligned_item ( context , item_shape , field_prefix_max_width ) ,
292
+ span_lo ,
293
+ span_hi ,
294
+ rewrite ,
232
295
span. lo ( ) ,
233
296
span. hi ( ) ,
234
297
false ,
@@ -258,6 +321,8 @@ fn rewrite_aligned_items_inner<T: AlignedItem>(
258
321
259
322
let separator_tactic = if force_trailing_separator {
260
323
SeparatorTactic :: Always
324
+ } else if has_base_or_rest {
325
+ SeparatorTactic :: Never
261
326
} else {
262
327
context. config . trailing_comma ( )
263
328
} ;
@@ -277,7 +342,7 @@ fn group_aligned_items<T: AlignedItem>(
277
342
fields : & [ T ] ,
278
343
) -> ( & ' static str , usize ) {
279
344
let mut index = 0 ;
280
- for i in 0 ..fields. len ( ) - 1 {
345
+ for i in 0 ..fields. len ( ) . saturating_sub ( 1 ) {
281
346
if fields[ i] . skip ( ) {
282
347
return ( "" , index) ;
283
348
}
0 commit comments