diff options
| -rw-r--r-- | src/expr.rs | 46 | ||||
| -rw-r--r-- | tests/source/structs.rs | 11 | ||||
| -rw-r--r-- | tests/target/structs.rs | 14 |
3 files changed, 53 insertions, 18 deletions
diff --git a/src/expr.rs b/src/expr.rs index 1ba879ccc1d..38543b70ae3 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -106,11 +106,11 @@ pub(crate) fn format_expr( }) } ast::ExprKind::Unary(op, ref subexpr) => rewrite_unary_op(context, op, subexpr, shape), - ast::ExprKind::Struct(ref path, ref fields, ref base) => rewrite_struct_lit( + ast::ExprKind::Struct(ref path, ref fields, ref struct_rest) => rewrite_struct_lit( context, path, fields, - base.as_ref().map(|e| &**e), + struct_rest, &expr.attrs, expr.span, shape, @@ -1510,19 +1510,15 @@ fn rewrite_index( } } -fn struct_lit_can_be_aligned(fields: &[ast::Field], base: Option<&ast::Expr>) -> bool { - if base.is_some() { - return false; - } - - fields.iter().all(|field| !field.is_shorthand) +fn struct_lit_can_be_aligned(fields: &[ast::Field], has_base: bool) -> bool { + !has_base && fields.iter().all(|field| !field.is_shorthand) } fn rewrite_struct_lit<'a>( context: &RewriteContext<'_>, path: &ast::Path, fields: &'a [ast::Field], - base: Option<&'a ast::Expr>, + struct_rest: &ast::StructRest, attrs: &[ast::Attribute], span: Span, shape: Shape, @@ -1532,22 +1528,29 @@ fn rewrite_struct_lit<'a>( enum StructLitField<'a> { Regular(&'a ast::Field), Base(&'a ast::Expr), + Rest(&'a Span), } // 2 = " {".len() let path_shape = shape.sub_width(2)?; let path_str = rewrite_path(context, PathContext::Expr, None, path, path_shape)?; - if fields.is_empty() && base.is_none() { - return Some(format!("{} {{}}", path_str)); - } + + let has_base = match struct_rest { + ast::StructRest::None if fields.is_empty() => return Some(format!("{} {{}}", path_str)), + ast::StructRest::Rest(_) if fields.is_empty() => { + return Some(format!("{} {{ .. }}", path_str)); + } + ast::StructRest::Base(_) => true, + _ => false, + }; // Foo { a: Foo } - indent is +3, width is -5. let (h_shape, v_shape) = struct_lit_shape(shape, context, path_str.len() + 3, 2)?; let one_line_width = h_shape.map_or(0, |shape| shape.width); let body_lo = context.snippet_provider.span_after(span, "{"); - let fields_str = if struct_lit_can_be_aligned(fields, base) + let fields_str = if struct_lit_can_be_aligned(fields, has_base) && context.config.struct_field_align_threshold() > 0 { rewrite_with_alignment( @@ -1558,10 +1561,14 @@ fn rewrite_struct_lit<'a>( one_line_width, )? } else { - let field_iter = fields - .iter() - .map(StructLitField::Regular) - .chain(base.into_iter().map(StructLitField::Base)); + let field_iter = fields.iter().map(StructLitField::Regular).chain( + match struct_rest { + ast::StructRest::Base(expr) => Some(StructLitField::Base(&**expr)), + ast::StructRest::Rest(span) => Some(StructLitField::Rest(span)), + ast::StructRest::None => None, + } + .into_iter(), + ); let span_lo = |item: &StructLitField<'_>| match *item { StructLitField::Regular(field) => field.span().lo(), @@ -1571,10 +1578,12 @@ fn rewrite_struct_lit<'a>( let pos = snippet.find_uncommented("..").unwrap(); last_field_hi + BytePos(pos as u32) } + StructLitField::Rest(span) => span.lo(), }; let span_hi = |item: &StructLitField<'_>| match *item { StructLitField::Regular(field) => field.span().hi(), StructLitField::Base(expr) => expr.span.hi(), + StructLitField::Rest(span) => span.hi(), }; let rewrite = |item: &StructLitField<'_>| match *item { StructLitField::Regular(field) => { @@ -1586,6 +1595,7 @@ fn rewrite_struct_lit<'a>( expr.rewrite(context, v_shape.offset_left(2)?) .map(|s| format!("..{}", s)) } + StructLitField::Rest(_) => Some("..".to_owned()), }; let items = itemize_list( @@ -1612,7 +1622,7 @@ fn rewrite_struct_lit<'a>( nested_shape, tactic, context, - force_no_trailing_comma || base.is_some() || !context.use_block_indent(), + force_no_trailing_comma || has_base || !context.use_block_indent(), ); write_list(&item_vec, &fmt)? diff --git a/tests/source/structs.rs b/tests/source/structs.rs index 711264a11d3..537151b276a 100644 --- a/tests/source/structs.rs +++ b/tests/source/structs.rs @@ -15,6 +15,17 @@ pub struct Foo { pub i: TypeForPublicField } +// Destructuring +fn foo() { + S { x: 5, + ..}; + Struct {..} = Struct { a: 1, b: 4 }; + Struct { a, .. } = Struct { a: 1, b: 2, c: 3}; + TupleStruct(a,.., b) = TupleStruct(1, 2); + TupleStruct( ..) = TupleStruct(3, 4); + TupleStruct(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, .., bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) = TupleStruct(1, 2); +} + // #1095 struct S<T: /* comment */> { t: T, diff --git a/tests/target/structs.rs b/tests/target/structs.rs index 0495ab3c81c..4948e37a5a3 100644 --- a/tests/target/structs.rs +++ b/tests/target/structs.rs @@ -15,6 +15,20 @@ pub struct Foo { pub i: TypeForPublicField, } +// Destructuring +fn foo() { + S { x: 5, .. }; + Struct { .. } = Struct { a: 1, b: 4 }; + Struct { a, .. } = Struct { a: 1, b: 2, c: 3 }; + TupleStruct(a, .., b) = TupleStruct(1, 2); + TupleStruct(..) = TupleStruct(3, 4); + TupleStruct( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + .., + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + ) = TupleStruct(1, 2); +} + // #1095 struct S<T /* comment */> { t: T, |
