1
Fork 0

Combining move lifetime and type suggestions.

This commit combines the move lifetime and move type suggestions so that
when rustfix applies them they don't conflict with each other.
This commit is contained in:
David Wood 2019-01-25 00:36:28 +01:00
parent 463e623ca9
commit 7a0abbff8b
No known key found for this signature in database
GPG key ID: 01760B4F9F53F154
3 changed files with 179 additions and 35 deletions

View file

@ -5611,49 +5611,92 @@ impl<'a> Parser<'a> {
}
}
if !bad_lifetime_pos.is_empty() {
let mut err = self.struct_span_err(
self.maybe_report_incorrect_generic_argument_order(
bad_lifetime_pos, bad_type_pos, lifetime_suggestions, type_suggestions
);
Ok((args, bindings))
}
/// Maybe report an error about incorrect generic argument order - "lifetime parameters
/// must be declared before type parameters", "type parameters must be declared before
/// associated type bindings" or both.
fn maybe_report_incorrect_generic_argument_order(
&self,
bad_lifetime_pos: Vec<Span>,
bad_type_pos: Vec<Span>,
lifetime_suggestions: Vec<(Span, String)>,
type_suggestions: Vec<(Span, String)>,
) {
let mut err = if !bad_lifetime_pos.is_empty() && !bad_type_pos.is_empty() {
let mut positions = bad_lifetime_pos.clone();
positions.extend_from_slice(&bad_type_pos);
self.struct_span_err(
positions,
"generic arguments must declare lifetimes, types and associated type bindings in \
that order",
)
} else if !bad_lifetime_pos.is_empty() {
self.struct_span_err(
bad_lifetime_pos.clone(),
"lifetime parameters must be declared prior to type parameters"
);
)
} else if !bad_type_pos.is_empty() {
self.struct_span_err(
bad_type_pos.clone(),
"type parameters must be declared prior to associated type bindings"
)
} else {
return;
};
if !bad_lifetime_pos.is_empty() {
for sp in &bad_lifetime_pos {
err.span_label(*sp, "must be declared prior to type parameters");
}
if !lifetime_suggestions.is_empty() {
err.multipart_suggestion_with_applicability(
&format!(
"move the lifetime parameter{} prior to the first type parameter",
if bad_lifetime_pos.len() > 1 { "s" } else { "" },
),
lifetime_suggestions,
Applicability::MachineApplicable,
);
}
err.emit();
}
if !bad_type_pos.is_empty() {
let mut err = self.struct_span_err(
bad_type_pos.clone(),
"type parameters must be declared prior to associated type bindings"
);
for sp in &bad_type_pos {
err.span_label(*sp, "must be declared prior to associated type bindings");
}
if !type_suggestions.is_empty() {
err.multipart_suggestion_with_applicability(
&format!(
"move the type parameter{} prior to the first associated type binding",
if bad_type_pos.len() > 1 { "s" } else { "" },
),
type_suggestions,
Applicability::MachineApplicable,
);
}
err.emit();
}
Ok((args, bindings))
if !lifetime_suggestions.is_empty() && !type_suggestions.is_empty() {
let mut suggestions = lifetime_suggestions;
suggestions.extend_from_slice(&type_suggestions);
let plural = bad_lifetime_pos.len() + bad_type_pos.len() > 1;
err.multipart_suggestion_with_applicability(
&format!(
"move the parameter{}",
if plural { "s" } else { "" },
),
suggestions,
Applicability::MachineApplicable,
);
} else if !lifetime_suggestions.is_empty() {
err.multipart_suggestion_with_applicability(
&format!(
"move the lifetime parameter{} prior to the first type parameter",
if bad_lifetime_pos.len() > 1 { "s" } else { "" },
),
lifetime_suggestions,
Applicability::MachineApplicable,
);
} else if !type_suggestions.is_empty() {
err.multipart_suggestion_with_applicability(
&format!(
"move the type parameter{} prior to the first associated type binding",
if bad_type_pos.len() > 1 { "s" } else { "" },
),
type_suggestions,
Applicability::MachineApplicable,
);
}
err.emit();
}
/// Parses an optional `where` clause and places it in `generics`.