Skip to content

Commit 257311c

Browse files
matthewjaspercalebcartwright
authored andcommitted
Format generic associated type bounds
1 parent a36bcfa commit 257311c

File tree

5 files changed

+128
-58
lines changed

5 files changed

+128
-58
lines changed

Diff for: src/formatting/types.rs

+96-57
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::iter::ExactSizeIterator;
22
use std::ops::Deref;
33

44
use rustc_ast::ast::{self, FnRetTy, Mutability};
5-
use rustc_span::{symbol::kw, BytePos, Pos, Span};
5+
use rustc_span::{symbol::kw, symbol::Ident, BytePos, Pos, Span};
66

77
use crate::config::{lists::*, IndentStyle, TypeDensity};
88
use crate::formatting::{
@@ -170,17 +170,32 @@ impl<'a> Rewrite for SegmentParam<'a> {
170170
SegmentParam::LifeTime(lt) => lt.rewrite(context, shape),
171171
SegmentParam::Type(ty) => ty.rewrite(context, shape),
172172
SegmentParam::Binding(assoc_ty_constraint) => {
173+
let ident = rewrite_ident(context, assoc_ty_constraint.ident);
174+
let segment = if let Some(ref gen_args) = assoc_ty_constraint.gen_args {
175+
append_rewrite_args(
176+
PathContext::Type,
177+
assoc_ty_constraint.ident,
178+
gen_args,
179+
&mut assoc_ty_constraint.span.lo(),
180+
assoc_ty_constraint.span.hi(),
181+
context,
182+
shape,
183+
ident.to_string(),
184+
)?
185+
} else {
186+
ident.to_string()
187+
};
173188
let mut result = match assoc_ty_constraint.kind {
174189
ast::AssocTyConstraintKind::Bound { .. } => {
175-
format!("{}: ", rewrite_ident(context, assoc_ty_constraint.ident))
190+
format!("{}: ", segment)
176191
}
177192
ast::AssocTyConstraintKind::Equality { .. } => {
178193
match context.config.type_punctuation_density() {
179194
TypeDensity::Wide => {
180-
format!("{} = ", rewrite_ident(context, assoc_ty_constraint.ident))
195+
format!("{} = ", segment)
181196
}
182197
TypeDensity::Compressed => {
183-
format!("{}=", rewrite_ident(context, assoc_ty_constraint.ident))
198+
format!("{}=", segment)
184199
}
185200
}
186201
}
@@ -235,63 +250,87 @@ fn rewrite_segment(
235250
};
236251

237252
if let Some(ref args) = segment.args {
238-
match **args {
239-
ast::GenericArgs::AngleBracketed(ref data) if !data.args.is_empty() => {
240-
let param_list = data
241-
.args
242-
.iter()
243-
.map(|x| match x {
244-
ast::AngleBracketedArg::Arg(generic_arg) => {
245-
SegmentParam::from_generic_arg(generic_arg)
246-
}
247-
ast::AngleBracketedArg::Constraint(constraint) => {
248-
SegmentParam::Binding(constraint)
249-
}
250-
})
251-
.collect::<Vec<_>>();
252-
253-
// HACK: squeeze out the span between the identifier and the parameters.
254-
// The hack is requried so that we don't remove the separator inside macro calls.
255-
// This does not work in the presence of comment, hoping that people are
256-
// sane about where to put their comment.
257-
let separator_snippet = context
258-
.snippet(mk_sp(segment.ident.span.hi(), data.span.lo()))
259-
.trim();
260-
let force_separator = context.inside_macro() && separator_snippet.starts_with("::");
261-
let separator = if path_context == PathContext::Expr || force_separator {
262-
"::"
263-
} else {
264-
""
265-
};
266-
result.push_str(separator);
253+
append_rewrite_args(
254+
path_context,
255+
segment.ident,
256+
args,
257+
span_lo,
258+
span_hi,
259+
context,
260+
shape,
261+
result,
262+
)
263+
} else {
264+
Some(result)
265+
}
266+
}
267267

268-
let generics_str = overflow::rewrite_with_angle_brackets(
269-
context,
270-
"",
271-
param_list.iter(),
272-
shape,
273-
mk_sp(*span_lo, span_hi),
274-
)?;
268+
fn append_rewrite_args(
269+
path_context: PathContext,
270+
ident: Ident,
271+
args: &ast::GenericArgs,
272+
span_lo: &mut BytePos,
273+
span_hi: BytePos,
274+
context: &RewriteContext<'_>,
275+
shape: Shape,
276+
mut result: String,
277+
) -> Option<String> {
278+
match args {
279+
ast::GenericArgs::AngleBracketed(ref data) if !data.args.is_empty() => {
280+
let param_list = data
281+
.args
282+
.iter()
283+
.map(|x| match x {
284+
ast::AngleBracketedArg::Arg(generic_arg) => {
285+
SegmentParam::from_generic_arg(generic_arg)
286+
}
287+
ast::AngleBracketedArg::Constraint(constraint) => {
288+
SegmentParam::Binding(constraint)
289+
}
290+
})
291+
.collect::<Vec<_>>();
292+
293+
// HACK: squeeze out the span between the identifier and the parameters.
294+
// The hack is requried so that we don't remove the separator inside macro calls.
295+
// This does not work in the presence of comment, hoping that people are
296+
// sane about where to put their comment.
297+
let separator_snippet = context
298+
.snippet(mk_sp(ident.span.hi(), data.span.lo()))
299+
.trim();
300+
let force_separator = context.inside_macro() && separator_snippet.starts_with("::");
301+
let separator = if path_context == PathContext::Expr || force_separator {
302+
"::"
303+
} else {
304+
""
305+
};
306+
result.push_str(separator);
275307

276-
// Update position of last bracket.
277-
*span_lo = context
278-
.snippet_provider
279-
.span_after(mk_sp(*span_lo, span_hi), "<");
308+
let generics_str = overflow::rewrite_with_angle_brackets(
309+
context,
310+
"",
311+
param_list.iter(),
312+
shape,
313+
mk_sp(*span_lo, span_hi),
314+
)?;
280315

281-
result.push_str(&generics_str)
282-
}
283-
ast::GenericArgs::Parenthesized(ref data) => {
284-
result.push_str(&format_function_type(
285-
data.inputs.iter().map(|x| &**x),
286-
&data.output,
287-
false,
288-
data.span,
289-
context,
290-
shape,
291-
)?);
292-
}
293-
_ => {}
316+
// Update position of last bracket.
317+
*span_lo = context
318+
.snippet_provider
319+
.span_after(mk_sp(*span_lo, span_hi), "<");
320+
321+
result.push_str(&generics_str)
322+
}
323+
ast::GenericArgs::Parenthesized(ref data) => {
324+
result.push_str(&format_function_type(
325+
data.inputs.iter().map(|x| &**x),
326+
&data.output,
327+
false,
328+
data.span,
329+
context,
330+
shape,
331+
)?);
294332
}
333+
_ => {}
295334
}
296335

297336
Some(result)

Diff for: tests/source/type.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -171,4 +171,14 @@ impl<T: ? const Trait> Foo<T> {
171171
type T = typeof(
172172
1);
173173
impl T for .. {
174-
}
174+
}
175+
176+
fn gat_object(x: &dyn for<'a> StreamingIterator<Item<'a> = &'a i32>)
177+
-> &dyn for< 'a> StreamingIterator
178+
<Item<'a > = & 'a i32> { x }
179+
180+
fn gat_impl_trait(x: &impl for<'a
181+
> StreamingIterator<Item<'a > = &'a i32>) -> &impl for<'a>
182+
StreamingIterator<Item<'a> = &'a i32> {
183+
x
184+
}

Diff for: tests/source/where-clause.rs

+4
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
6161
pub trait AsUnindented {
6262
type Output<'ast> where Self: 'ast;
6363
}
64+
65+
fn f<T: AsUnindented<
66+
Output<'static> = U>, U>() where U: AsUnindented<
67+
Output<'static> = i32> {}

Diff for: tests/target/type.rs

+12
Original file line numberDiff line numberDiff line change
@@ -181,3 +181,15 @@ impl<T: ?const Trait> Foo<T> {
181181
// #4357
182182
type T = typeof(1);
183183
impl T for .. {}
184+
185+
fn gat_object(
186+
x: &dyn for<'a> StreamingIterator<Item<'a> = &'a i32>,
187+
) -> &dyn for<'a> StreamingIterator<Item<'a> = &'a i32> {
188+
x
189+
}
190+
191+
fn gat_impl_trait(
192+
x: &impl for<'a> StreamingIterator<Item<'a> = &'a i32>,
193+
) -> &impl for<'a> StreamingIterator<Item<'a> = &'a i32> {
194+
x
195+
}

Diff for: tests/target/where-clause.rs

+5
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
110110
pub trait AsUnindented {
111111
type Output<'ast> where Self: 'ast;
112112
}
113+
114+
fn f<T: AsUnindented<Output<'static> = U>, U>()
115+
where U: AsUnindented<Output<'static> = i32>
116+
{
117+
}

0 commit comments

Comments
 (0)