Skip to content

Commit a15800a

Browse files
ayazhafizcalebcartwright
authored andcommitted
Preserve and format type aliases in extern blocks
Previously, non-trivial type aliases in extern blocks were dropped by rustfmt because only the type alias name would be passed to a rewritter. This commit fixes that by passing all type information (generics, bounds, and assignments) to a type alias rewritter, and consolidates `rewrite_type_alias` and `rewrite_associated_type` as one function.
1 parent 8eedd82 commit a15800a

File tree

3 files changed

+81
-48
lines changed

3 files changed

+81
-48
lines changed

src/items.rs

Lines changed: 54 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1510,6 +1510,7 @@ fn rewrite_type_prefix(
15101510
prefix: &str,
15111511
ident: symbol::Ident,
15121512
generics: &ast::Generics,
1513+
generic_bounds_opt: Option<&ast::GenericBounds>,
15131514
) -> Option<String> {
15141515
let mut result = String::with_capacity(128);
15151516
result.push_str(prefix);
@@ -1526,6 +1527,19 @@ fn rewrite_type_prefix(
15261527
result.push_str(&generics_str);
15271528
}
15281529

1530+
let type_bounds_str = if let Some(bounds) = generic_bounds_opt {
1531+
if bounds.is_empty() {
1532+
String::new()
1533+
} else {
1534+
// 2 = `: `
1535+
let shape = Shape::indented(indent, context.config).offset_left(result.len() + 2)?;
1536+
bounds.rewrite(context, shape).map(|s| format!(": {}", s))?
1537+
}
1538+
} else {
1539+
String::new()
1540+
};
1541+
result.push_str(&type_bounds_str);
1542+
15291543
let where_budget = context.budget(last_line_width(&result));
15301544
let option = WhereClauseOption::snuggled(&result);
15311545
let where_clause_str = rewrite_where_clause(
@@ -1552,6 +1566,7 @@ fn rewrite_type_item<R: Rewrite>(
15521566
ident: symbol::Ident,
15531567
rhs: &R,
15541568
generics: &ast::Generics,
1569+
generic_bounds_opt: Option<&ast::GenericBounds>,
15551570
vis: &ast::Visibility,
15561571
) -> Option<String> {
15571572
let mut result = String::with_capacity(128);
@@ -1561,6 +1576,7 @@ fn rewrite_type_item<R: Rewrite>(
15611576
&format!("{}{} ", format_visibility(context, vis), prefix),
15621577
ident,
15631578
generics,
1579+
generic_bounds_opt,
15641580
)?);
15651581

15661582
if generics.where_clause.predicates.is_empty() {
@@ -1575,17 +1591,6 @@ fn rewrite_type_item<R: Rewrite>(
15751591
rewrite_assign_rhs(context, result, rhs, rhs_shape).map(|s| s + ";")
15761592
}
15771593

1578-
pub(crate) fn rewrite_type_alias(
1579-
context: &RewriteContext<'_>,
1580-
indent: Indent,
1581-
ident: symbol::Ident,
1582-
ty: &ast::Ty,
1583-
generics: &ast::Generics,
1584-
vis: &ast::Visibility,
1585-
) -> Option<String> {
1586-
rewrite_type_item(context, indent, "type", " =", ident, ty, generics, vis)
1587-
}
1588-
15891594
pub(crate) fn rewrite_opaque_type(
15901595
context: &RewriteContext<'_>,
15911596
indent: Indent,
@@ -1603,6 +1608,7 @@ pub(crate) fn rewrite_opaque_type(
16031608
ident,
16041609
&opaque_type_bounds,
16051610
generics,
1611+
Some(generic_bounds),
16061612
vis,
16071613
)
16081614
}
@@ -1824,39 +1830,39 @@ fn rewrite_static(
18241830
}
18251831
}
18261832

1827-
pub(crate) fn rewrite_associated_type(
1833+
pub(crate) fn rewrite_type_alias(
18281834
ident: symbol::Ident,
18291835
ty_opt: Option<&ptr::P<ast::Ty>>,
18301836
generics: &ast::Generics,
18311837
generic_bounds_opt: Option<&ast::GenericBounds>,
18321838
context: &RewriteContext<'_>,
18331839
indent: Indent,
1840+
vis: &ast::Visibility,
18341841
) -> Option<String> {
1835-
let ident_str = rewrite_ident(context, ident);
1836-
// 5 = "type "
1837-
let generics_shape = Shape::indented(indent, context.config).offset_left(5)?;
1838-
let generics_str = rewrite_generics(context, ident_str, generics, generics_shape)?;
1839-
let prefix = format!("type {}", generics_str);
1840-
1841-
let type_bounds_str = if let Some(bounds) = generic_bounds_opt {
1842-
if bounds.is_empty() {
1843-
String::new()
1844-
} else {
1845-
// 2 = ": ".len()
1846-
let shape = Shape::indented(indent, context.config).offset_left(prefix.len() + 2)?;
1847-
bounds.rewrite(context, shape).map(|s| format!(": {}", s))?
1848-
}
1849-
} else {
1850-
String::new()
1851-
};
1842+
let mut prefix = rewrite_type_prefix(
1843+
context,
1844+
indent,
1845+
&format!("{}type ", format_visibility(context, vis)),
1846+
ident,
1847+
generics,
1848+
generic_bounds_opt,
1849+
)?;
18521850

18531851
if let Some(ty) = ty_opt {
18541852
// 1 = `;`
18551853
let shape = Shape::indented(indent, context.config).sub_width(1)?;
1856-
let lhs = format!("{}{} =", prefix, type_bounds_str);
1854+
1855+
// If there's a where clause, add a newline before the assignment. Otherwise just add a
1856+
// space.
1857+
if !generics.where_clause.predicates.is_empty() {
1858+
prefix.push_str(&indent.to_string_with_newline(context.config));
1859+
} else {
1860+
prefix.push(' ');
1861+
}
1862+
let lhs = format!("{}=", prefix);
18571863
rewrite_assign_rhs(context, lhs, &**ty, shape).map(|s| s + ";")
18581864
} else {
1859-
Some(format!("{}{};", prefix, type_bounds_str))
1865+
Some(format!("{};", prefix))
18601866
}
18611867
}
18621868

@@ -1900,13 +1906,14 @@ pub(crate) fn rewrite_opaque_impl_type(
19001906

19011907
pub(crate) fn rewrite_associated_impl_type(
19021908
ident: symbol::Ident,
1909+
vis: &ast::Visibility,
19031910
defaultness: ast::Defaultness,
19041911
ty_opt: Option<&ptr::P<ast::Ty>>,
19051912
generics: &ast::Generics,
19061913
context: &RewriteContext<'_>,
19071914
indent: Indent,
19081915
) -> Option<String> {
1909-
let result = rewrite_associated_type(ident, ty_opt, generics, None, context, indent)?;
1916+
let result = rewrite_type_alias(ident, ty_opt, generics, None, context, indent, vis)?;
19101917

19111918
match defaultness {
19121919
ast::Defaultness::Default(..) => Some(format!("default {}", result)),
@@ -3088,7 +3095,7 @@ impl Rewrite for ast::ForeignItem {
30883095
// FIXME: this may be a faulty span from libsyntax.
30893096
let span = mk_sp(self.span.lo(), self.span.hi() - BytePos(1));
30903097

3091-
let item_str = match self.kind {
3098+
let item_str: String = match self.kind {
30923099
ast::ForeignItemKind::Fn(_, ref fn_sig, ref generics, _) => rewrite_fn_base(
30933100
context,
30943101
shape.indent,
@@ -3112,14 +3119,20 @@ impl Rewrite for ast::ForeignItem {
31123119
// 1 = ;
31133120
rewrite_assign_rhs(context, prefix, &**ty, shape.sub_width(1)?).map(|s| s + ";")
31143121
}
3115-
ast::ForeignItemKind::TyAlias(..) => {
3116-
let vis = format_visibility(context, &self.vis);
3117-
Some(format!(
3118-
"{}type {};",
3119-
vis,
3120-
rewrite_ident(context, self.ident)
3121-
))
3122-
}
3122+
ast::ForeignItemKind::TyAlias(
3123+
_,
3124+
ref generics,
3125+
ref generic_bounds,
3126+
ref type_default,
3127+
) => rewrite_type_alias(
3128+
self.ident,
3129+
type_default.as_ref(),
3130+
generics,
3131+
Some(generic_bounds),
3132+
&context,
3133+
shape.indent,
3134+
&self.vis,
3135+
),
31233136
ast::ForeignItemKind::MacCall(ref mac) => {
31243137
rewrite_macro(mac, None, context, shape, MacroPosition::Item)
31253138
}

src/visitor.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,8 @@ use crate::config::{BraceStyle, Config};
1111
use crate::coverage::transform_missing_snippet;
1212
use crate::items::{
1313
format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item,
14-
rewrite_associated_impl_type, rewrite_associated_type, rewrite_extern_crate,
15-
rewrite_opaque_impl_type, rewrite_opaque_type, rewrite_type_alias, FnBraceStyle, FnSig,
16-
StaticParts, StructParts,
14+
rewrite_associated_impl_type, rewrite_extern_crate, rewrite_opaque_impl_type,
15+
rewrite_opaque_type, rewrite_type_alias, FnBraceStyle, FnSig, StaticParts, StructParts,
1716
};
1817
use crate::macros::{macro_style, rewrite_macro, rewrite_macro_def, MacroPosition};
1918
use crate::modules::Module;
@@ -544,11 +543,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
544543
ast::ItemKind::TyAlias(_, ref generics, ref generic_bounds, ref ty) => match ty {
545544
Some(ty) => {
546545
let rewrite = rewrite_type_alias(
547-
&self.get_context(),
548-
self.block_indent,
549546
item.ident,
550-
&*ty,
547+
Some(&*ty),
551548
generics,
549+
Some(generic_bounds),
550+
&self.get_context(),
551+
self.block_indent,
552552
&item.vis,
553553
);
554554
self.push_rewrite(item.span, rewrite);
@@ -619,13 +619,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
619619
);
620620
}
621621
ast::AssocItemKind::TyAlias(_, ref generics, ref generic_bounds, ref type_default) => {
622-
let rewrite = rewrite_associated_type(
622+
let rewrite = rewrite_type_alias(
623623
ti.ident,
624624
type_default.as_ref(),
625625
generics,
626626
Some(generic_bounds),
627627
&self.get_context(),
628628
self.block_indent,
629+
&ti.vis,
629630
);
630631
self.push_rewrite(ti.span, rewrite);
631632
}
@@ -666,6 +667,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
666667
let rewrite_associated = || {
667668
rewrite_associated_impl_type(
668669
ii.ident,
670+
&ii.vis,
669671
defaultness,
670672
ty.as_ref(),
671673
&generics,

tests/target/issue-4159.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
extern "C" {
2+
type A: Ord;
3+
4+
type A<'a>
5+
where
6+
'a: 'static,;
7+
8+
type A<T: Ord>
9+
where
10+
T: 'static,;
11+
12+
type A = u8;
13+
14+
type A<'a: 'static, T: Ord + 'static>: Eq + PartialEq
15+
where
16+
T: 'static + Copy,
17+
= Vec<u8>;
18+
}

0 commit comments

Comments
 (0)