Skip to content

Format existetenial type #2860

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 76 additions & 58 deletions Cargo.lock

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ env_logger = "0.5"
getopts = "0.2"
derive-new = "0.5"
cargo_metadata = "0.6"
rustc-ap-rustc_target = "201.0.0"
rustc-ap-syntax = "201.0.0"
rustc-ap-syntax_pos = "201.0.0"
rustc-ap-rustc_target = "206.0.0"
rustc-ap-syntax = "206.0.0"
rustc-ap-syntax_pos = "206.0.0"
failure = "0.1.1"

[dev-dependencies]
Expand Down
143 changes: 91 additions & 52 deletions src/items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -801,17 +801,12 @@ fn format_impl_ref_and_type(
result.push_str(format_defaultness(defaultness));
result.push_str(format_unsafety(unsafety));

let lo = context.snippet_provider.span_after(item.span, "impl");
let hi = match *trait_ref {
Some(ref tr) => tr.path.span.lo(),
None => self_ty.span.lo(),
};
let shape = generics_shape_from_config(
context.config,
Shape::indented(offset + last_line_width(&result), context.config),
0,
)?;
let generics_str = rewrite_generics(context, "impl", generics, shape, mk_sp(lo, hi))?;
let generics_str = rewrite_generics(context, "impl", generics, shape)?;
result.push_str(&generics_str);

let polarity_str = if polarity == ast::ImplPolarity::Negative {
Expand Down Expand Up @@ -986,13 +981,8 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent)
let body_lo = context.snippet_provider.span_after(item.span, "{");

let shape = Shape::indented(offset, context.config).offset_left(result.len())?;
let generics_str = rewrite_generics(
context,
rewrite_ident(context, item.ident),
generics,
shape,
mk_sp(item.span.lo(), body_lo),
)?;
let generics_str =
rewrite_generics(context, rewrite_ident(context, item.ident), generics, shape)?;
result.push_str(&generics_str);

// FIXME(#2055): rustfmt fails to format when there are comments between trait bounds.
Expand Down Expand Up @@ -1138,7 +1128,7 @@ pub fn format_trait_alias(
let alias = rewrite_ident(context, ident);
// 6 = "trait ", 2 = " ="
let g_shape = shape.offset_left(6)?.sub_width(2)?;
let generics_str = rewrite_generics(context, &alias, generics, g_shape, generics.span)?;
let generics_str = rewrite_generics(context, &alias, generics, g_shape)?;
let lhs = format!("trait {} =", generics_str);
// 1 = ";"
rewrite_assign_rhs(context, lhs, generic_bounds, shape.sub_width(1)?).map(|s| s + ";")
Expand Down Expand Up @@ -1340,8 +1330,7 @@ fn format_tuple_struct(
Some(generics) => {
let budget = context.budget(last_line_width(&header_str));
let shape = Shape::legacy(budget, offset);
let g_span = mk_sp(span.lo(), body_lo);
let generics_str = rewrite_generics(context, "", generics, shape, g_span)?;
let generics_str = rewrite_generics(context, "", generics, shape)?;
result.push_str(&generics_str);

let where_budget = context.budget(last_line_width(&result));
Expand Down Expand Up @@ -1400,36 +1389,27 @@ fn format_tuple_struct(
Some(result)
}

pub fn rewrite_type_alias(
fn rewrite_type_prefix(
context: &RewriteContext,
indent: Indent,
prefix: &str,
ident: ast::Ident,
ty: &ast::Ty,
generics: &ast::Generics,
vis: &ast::Visibility,
span: Span,
) -> Option<String> {
let mut result = String::with_capacity(128);

result.push_str(&format_visibility(context, vis));
result.push_str("type ");
result.push_str(prefix);
let ident_str = rewrite_ident(context, ident);

// 2 = `= `
let g_shape = Shape::indented(indent, context.config)
.offset_left(result.len())?
.sub_width(2)?;
let g_span = mk_sp(
context.snippet_provider.span_after(span, "type"),
ty.span.lo(),
);
let generics_str = rewrite_generics(
context,
rewrite_ident(context, ident),
generics,
g_shape,
g_span,
)?;
result.push_str(&generics_str);
if generics.params.is_empty() {
result.push_str(ident_str)
} else {
let g_shape = Shape::indented(indent, context.config)
.offset_left(result.len())?
.sub_width(2)?;
let generics_str = rewrite_generics(context, ident_str, generics, g_shape)?;
result.push_str(&generics_str);
}

let where_budget = context.budget(last_line_width(&result));
let option = WhereClauseOption::snuggled(&result);
Expand All @@ -1440,24 +1420,76 @@ pub fn rewrite_type_alias(
Shape::legacy(where_budget, indent),
Density::Vertical,
"=",
Some(span.hi()),
None,
generics.span.hi(),
option,
false,
)?;
result.push_str(&where_clause_str);
if where_clause_str.is_empty() {
result.push_str(" =");

Some(result)
}

fn rewrite_type_item<R: Rewrite>(
context: &RewriteContext,
indent: Indent,
prefix: &str,
suffix: &str,
ident: ast::Ident,
rhs: &R,
generics: &ast::Generics,
vis: &ast::Visibility,
) -> Option<String> {
let mut result = String::with_capacity(128);
result.push_str(&rewrite_type_prefix(
context,
indent,
&format!("{}{} ", format_visibility(context, vis), prefix),
ident,
generics,
)?);

if generics.where_clause.predicates.is_empty() {
result.push_str(suffix);
} else {
result.push_str(&format!(
"{}=",
indent.to_string_with_newline(context.config)
));
result.push_str(&indent.to_string_with_newline(context.config));
result.push_str(suffix.trim_left());
}

// 1 = ";"
let ty_shape = Shape::indented(indent, context.config).sub_width(1)?;
rewrite_assign_rhs(context, result, ty, ty_shape).map(|s| s + ";")
let rhs_shape = Shape::indented(indent, context.config).sub_width(1)?;
rewrite_assign_rhs(context, result, rhs, rhs_shape).map(|s| s + ";")
}

pub fn rewrite_type_alias(
context: &RewriteContext,
indent: Indent,
ident: ast::Ident,
ty: &ast::Ty,
generics: &ast::Generics,
vis: &ast::Visibility,
) -> Option<String> {
rewrite_type_item(context, indent, "type", " =", ident, ty, generics, vis)
}

pub fn rewrite_existential_type(
context: &RewriteContext,
indent: Indent,
ident: ast::Ident,
generic_bounds: &ast::GenericBounds,
generics: &ast::Generics,
vis: &ast::Visibility,
) -> Option<String> {
rewrite_type_item(
context,
indent,
"existential type",
":",
ident,
generic_bounds,
generics,
vis,
)
}

fn type_annotation_spacing(config: &Config) -> (&str, &str) {
Expand Down Expand Up @@ -1706,6 +1738,16 @@ pub fn rewrite_associated_type(
}
}

pub fn rewrite_existential_impl_type(
context: &RewriteContext,
ident: ast::Ident,
generic_bounds: &ast::GenericBounds,
indent: Indent,
) -> Option<String> {
rewrite_associated_type(ident, None, Some(generic_bounds), context, indent)
.map(|s| format!("existential {}", s))
}

pub fn rewrite_associated_impl_type(
ident: ast::Ident,
defaultness: ast::Defaultness,
Expand Down Expand Up @@ -1889,13 +1931,11 @@ fn rewrite_fn_base(
offset: used_width,
};
let fd = fn_sig.decl;
let g_span = mk_sp(span.lo(), fd.output.span().lo());
let generics_str = rewrite_generics(
context,
rewrite_ident(context, ident),
fn_sig.generics,
shape,
g_span,
)?;
result.push_str(&generics_str);

Expand Down Expand Up @@ -2413,7 +2453,6 @@ fn rewrite_generics(
ident: &str,
generics: &ast::Generics,
shape: Shape,
span: Span,
) -> Option<String> {
// FIXME: convert bounds to where clauses where they get too big or if
// there is a where clause at all.
Expand All @@ -2423,7 +2462,7 @@ fn rewrite_generics(
}

let params = &generics.params.iter().map(|e| &*e).collect::<Vec<_>>();
overflow::rewrite_with_angle_brackets(context, ident, params, shape, span)
overflow::rewrite_with_angle_brackets(context, ident, params, shape, generics.span)
}

pub fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) -> Option<Shape> {
Expand Down Expand Up @@ -2711,7 +2750,7 @@ fn format_generics(
used_width: usize,
) -> Option<String> {
let shape = Shape::legacy(context.budget(used_width + offset.width()), offset);
let mut result = rewrite_generics(context, "", generics, shape, span)?;
let mut result = rewrite_generics(context, "", generics, shape)?;

let same_line_brace = if !generics.where_clause.predicates.is_empty() || result.contains('\n') {
let budget = context.budget(last_line_used_width(&result, offset.width()));
Expand Down
26 changes: 23 additions & 3 deletions src/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ use comment::{CodeCharKind, CommentCodeSlices, FindUncommented};
use config::{BraceStyle, Config};
use items::{
format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item,
rewrite_associated_impl_type, rewrite_associated_type, rewrite_extern_crate,
rewrite_type_alias, FnSig, StaticParts, StructParts,
rewrite_associated_impl_type, rewrite_associated_type, rewrite_existential_impl_type,
rewrite_existential_type, rewrite_extern_crate, rewrite_type_alias, FnSig, StaticParts,
StructParts,
};
use macros::{rewrite_macro, rewrite_macro_def, MacroPosition};
use rewrite::{Rewrite, RewriteContext};
Expand Down Expand Up @@ -412,7 +413,17 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
ty,
generics,
&item.vis,
item.span,
);
self.push_rewrite(item.span, rewrite);
}
ast::ItemKind::Existential(ref generic_bounds, ref generics) => {
let rewrite = rewrite_existential_type(
&self.get_context(),
self.block_indent,
item.ident,
generic_bounds,
generics,
&item.vis,
);
self.push_rewrite(item.span, rewrite);
}
Expand Down Expand Up @@ -510,6 +521,15 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
);
self.push_rewrite(ii.span, rewrite);
}
ast::ImplItemKind::Existential(ref generic_bounds) => {
let rewrite = rewrite_existential_impl_type(
&self.get_context(),
ii.ident,
generic_bounds,
self.block_indent,
);
self.push_rewrite(ii.span, rewrite);
}
ast::ImplItemKind::Macro(ref mac) => {
self.visit_mac(mac, Some(ii.ident), MacroPosition::Item);
}
Expand Down
15 changes: 15 additions & 0 deletions tests/source/existential_type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Existential type.

#![feature(existential_type)]

pub existential type Adder<F, T>
where
T: Clone,
F: Copy
: Fn(T) -> T;

pub existential type Adderrr<T>: Fn( T ) -> T;

impl Foo for Bar {
existential type E : Trait;
}
15 changes: 15 additions & 0 deletions tests/target/existential_type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Existential type.

#![feature(existential_type)]

pub existential type Adder<F, T>
where
T: Clone,
F: Copy,
: Fn(T) -> T;

pub existential type Adderrr<T>: Fn(T) -> T;

impl Foo for Bar {
existential type E: Trait;
}