Skip to content

Commit

Permalink
Format generic associated type bounds
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewjasper authored and calebcartwright committed Feb 15, 2021
1 parent a36bcfa commit 257311c
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 58 deletions.
153 changes: 96 additions & 57 deletions src/formatting/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::iter::ExactSizeIterator;
use std::ops::Deref;

use rustc_ast::ast::{self, FnRetTy, Mutability};
use rustc_span::{symbol::kw, BytePos, Pos, Span};
use rustc_span::{symbol::kw, symbol::Ident, BytePos, Pos, Span};

use crate::config::{lists::*, IndentStyle, TypeDensity};
use crate::formatting::{
Expand Down Expand Up @@ -170,17 +170,32 @@ impl<'a> Rewrite for SegmentParam<'a> {
SegmentParam::LifeTime(lt) => lt.rewrite(context, shape),
SegmentParam::Type(ty) => ty.rewrite(context, shape),
SegmentParam::Binding(assoc_ty_constraint) => {
let ident = rewrite_ident(context, assoc_ty_constraint.ident);
let segment = if let Some(ref gen_args) = assoc_ty_constraint.gen_args {
append_rewrite_args(
PathContext::Type,
assoc_ty_constraint.ident,
gen_args,
&mut assoc_ty_constraint.span.lo(),
assoc_ty_constraint.span.hi(),
context,
shape,
ident.to_string(),
)?
} else {
ident.to_string()
};
let mut result = match assoc_ty_constraint.kind {
ast::AssocTyConstraintKind::Bound { .. } => {
format!("{}: ", rewrite_ident(context, assoc_ty_constraint.ident))
format!("{}: ", segment)
}
ast::AssocTyConstraintKind::Equality { .. } => {
match context.config.type_punctuation_density() {
TypeDensity::Wide => {
format!("{} = ", rewrite_ident(context, assoc_ty_constraint.ident))
format!("{} = ", segment)
}
TypeDensity::Compressed => {
format!("{}=", rewrite_ident(context, assoc_ty_constraint.ident))
format!("{}=", segment)
}
}
}
Expand Down Expand Up @@ -235,63 +250,87 @@ fn rewrite_segment(
};

if let Some(ref args) = segment.args {
match **args {
ast::GenericArgs::AngleBracketed(ref data) if !data.args.is_empty() => {
let param_list = data
.args
.iter()
.map(|x| match x {
ast::AngleBracketedArg::Arg(generic_arg) => {
SegmentParam::from_generic_arg(generic_arg)
}
ast::AngleBracketedArg::Constraint(constraint) => {
SegmentParam::Binding(constraint)
}
})
.collect::<Vec<_>>();

// HACK: squeeze out the span between the identifier and the parameters.
// The hack is requried so that we don't remove the separator inside macro calls.
// This does not work in the presence of comment, hoping that people are
// sane about where to put their comment.
let separator_snippet = context
.snippet(mk_sp(segment.ident.span.hi(), data.span.lo()))
.trim();
let force_separator = context.inside_macro() && separator_snippet.starts_with("::");
let separator = if path_context == PathContext::Expr || force_separator {
"::"
} else {
""
};
result.push_str(separator);
append_rewrite_args(
path_context,
segment.ident,
args,
span_lo,
span_hi,
context,
shape,
result,
)
} else {
Some(result)
}
}

let generics_str = overflow::rewrite_with_angle_brackets(
context,
"",
param_list.iter(),
shape,
mk_sp(*span_lo, span_hi),
)?;
fn append_rewrite_args(
path_context: PathContext,
ident: Ident,
args: &ast::GenericArgs,
span_lo: &mut BytePos,
span_hi: BytePos,
context: &RewriteContext<'_>,
shape: Shape,
mut result: String,
) -> Option<String> {
match args {
ast::GenericArgs::AngleBracketed(ref data) if !data.args.is_empty() => {
let param_list = data
.args
.iter()
.map(|x| match x {
ast::AngleBracketedArg::Arg(generic_arg) => {
SegmentParam::from_generic_arg(generic_arg)
}
ast::AngleBracketedArg::Constraint(constraint) => {
SegmentParam::Binding(constraint)
}
})
.collect::<Vec<_>>();

// HACK: squeeze out the span between the identifier and the parameters.
// The hack is requried so that we don't remove the separator inside macro calls.
// This does not work in the presence of comment, hoping that people are
// sane about where to put their comment.
let separator_snippet = context
.snippet(mk_sp(ident.span.hi(), data.span.lo()))
.trim();
let force_separator = context.inside_macro() && separator_snippet.starts_with("::");
let separator = if path_context == PathContext::Expr || force_separator {
"::"
} else {
""
};
result.push_str(separator);

// Update position of last bracket.
*span_lo = context
.snippet_provider
.span_after(mk_sp(*span_lo, span_hi), "<");
let generics_str = overflow::rewrite_with_angle_brackets(
context,
"",
param_list.iter(),
shape,
mk_sp(*span_lo, span_hi),
)?;

result.push_str(&generics_str)
}
ast::GenericArgs::Parenthesized(ref data) => {
result.push_str(&format_function_type(
data.inputs.iter().map(|x| &**x),
&data.output,
false,
data.span,
context,
shape,
)?);
}
_ => {}
// Update position of last bracket.
*span_lo = context
.snippet_provider
.span_after(mk_sp(*span_lo, span_hi), "<");

result.push_str(&generics_str)
}
ast::GenericArgs::Parenthesized(ref data) => {
result.push_str(&format_function_type(
data.inputs.iter().map(|x| &**x),
&data.output,
false,
data.span,
context,
shape,
)?);
}
_ => {}
}

Some(result)
Expand Down
12 changes: 11 additions & 1 deletion tests/source/type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,14 @@ impl<T: ? const Trait> Foo<T> {
type T = typeof(
1);
impl T for .. {
}
}

fn gat_object(x: &dyn for<'a> StreamingIterator<Item<'a> = &'a i32>)
-> &dyn for< 'a> StreamingIterator
<Item<'a > = & 'a i32> { x }

fn gat_impl_trait(x: &impl for<'a
> StreamingIterator<Item<'a > = &'a i32>) -> &impl for<'a>
StreamingIterator<Item<'a> = &'a i32> {
x
}
4 changes: 4 additions & 0 deletions tests/source/where-clause.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
pub trait AsUnindented {
type Output<'ast> where Self: 'ast;
}

fn f<T: AsUnindented<
Output<'static> = U>, U>() where U: AsUnindented<
Output<'static> = i32> {}
12 changes: 12 additions & 0 deletions tests/target/type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,3 +181,15 @@ impl<T: ?const Trait> Foo<T> {
// #4357
type T = typeof(1);
impl T for .. {}

fn gat_object(
x: &dyn for<'a> StreamingIterator<Item<'a> = &'a i32>,
) -> &dyn for<'a> StreamingIterator<Item<'a> = &'a i32> {
x
}

fn gat_impl_trait(
x: &impl for<'a> StreamingIterator<Item<'a> = &'a i32>,
) -> &impl for<'a> StreamingIterator<Item<'a> = &'a i32> {
x
}
5 changes: 5 additions & 0 deletions tests/target/where-clause.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
pub trait AsUnindented {
type Output<'ast> where Self: 'ast;
}

fn f<T: AsUnindented<Output<'static> = U>, U>()
where U: AsUnindented<Output<'static> = i32>
{
}

0 comments on commit 257311c

Please sign in to comment.