@@ -6,7 +6,7 @@ use itertools::Itertools;
66use rustc_ast:: ast;
77use rustc_span:: { BytePos , Span } ;
88
9- use crate :: comment:: combine_strs_with_missing_comments;
9+ use crate :: comment:: { FindUncommented , combine_strs_with_missing_comments} ;
1010use crate :: config:: lists:: * ;
1111use crate :: expr:: rewrite_field;
1212use crate :: items:: { rewrite_struct_field, rewrite_struct_field_prefix} ;
@@ -108,12 +108,13 @@ impl AlignedItem for ast::ExprField {
108108 }
109109}
110110
111- pub ( crate ) fn rewrite_with_alignment < T : AlignedItem > (
111+ pub ( crate ) fn rewrite_with_alignment < T : AlignedItem + std :: fmt :: Debug > (
112112 fields : & [ T ] ,
113113 context : & RewriteContext < ' _ > ,
114114 shape : Shape ,
115115 span : Span ,
116116 one_line_width : usize ,
117+ struct_rest : Option < & ast:: StructRest > ,
117118) -> Option < String > {
118119 let ( spaces, group_index) = if context. config . struct_field_align_threshold ( ) > 0 {
119120 group_aligned_items ( context, fields)
@@ -170,12 +171,15 @@ pub(crate) fn rewrite_with_alignment<T: AlignedItem>(
170171 shape. indent ,
171172 one_line_width,
172173 force_separator,
174+ struct_rest,
175+ shape,
173176 ) ?;
174177 if rest. is_empty ( ) {
175178 Some ( result + spaces)
176179 } else {
177180 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) ?;
179183 Some ( format ! (
180184 "{}{}\n {}{}" ,
181185 result,
@@ -211,6 +215,8 @@ fn rewrite_aligned_items_inner<T: AlignedItem>(
211215 offset : Indent ,
212216 one_line_width : usize ,
213217 force_trailing_separator : bool ,
218+ struct_rest : Option < & ast:: StructRest > ,
219+ shape : Shape ,
214220) -> Option < String > {
215221 // 1 = ","
216222 let item_shape = Shape :: indented ( offset, context. config ) . sub_width_opt ( 1 ) ?;
@@ -221,14 +227,71 @@ fn rewrite_aligned_items_inner<T: AlignedItem>(
221227 field_prefix_max_width = 0 ;
222228 }
223229
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+
224287 let mut items = itemize_list (
225288 context. snippet_provider ,
226- fields . iter ( ) ,
289+ field_iter ,
227290 "}" ,
228291 "," ,
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 ,
232295 span. lo ( ) ,
233296 span. hi ( ) ,
234297 false ,
@@ -258,6 +321,8 @@ fn rewrite_aligned_items_inner<T: AlignedItem>(
258321
259322 let separator_tactic = if force_trailing_separator {
260323 SeparatorTactic :: Always
324+ } else if has_base_or_rest {
325+ SeparatorTactic :: Never
261326 } else {
262327 context. config . trailing_comma ( )
263328 } ;
@@ -277,7 +342,7 @@ fn group_aligned_items<T: AlignedItem>(
277342 fields : & [ T ] ,
278343) -> ( & ' static str , usize ) {
279344 let mut index = 0 ;
280- for i in 0 ..fields. len ( ) - 1 {
345+ for i in 0 ..fields. len ( ) . saturating_sub ( 1 ) {
281346 if fields[ i] . skip ( ) {
282347 return ( "" , index) ;
283348 }
0 commit comments