Suggest correct order for arguments when encountering early constraints
When encountering constraints before type arguments or lifetimes, suggest the correct order.
This commit is contained in:
parent
dcb4e817bc
commit
c2e0e71a09
@ -300,8 +300,8 @@ pub enum GenericBound {
|
|||||||
impl GenericBound {
|
impl GenericBound {
|
||||||
pub fn span(&self) -> Span {
|
pub fn span(&self) -> Span {
|
||||||
match self {
|
match self {
|
||||||
&GenericBound::Trait(ref t, ..) => t.span,
|
GenericBound::Trait(ref t, ..) => t.span,
|
||||||
&GenericBound::Outlives(ref l) => l.ident.span,
|
GenericBound::Outlives(ref l) => l.ident.span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -640,6 +640,32 @@ fn deny_items(&self, trait_items: &[P<AssocItem>], ident_span: Span) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn suggest_correct_generic_order(&self, data: &AngleBracketedArgs) -> String {
|
||||||
|
// Lifetimes always come first.
|
||||||
|
let lt_sugg = data.args.iter().filter_map(|arg| match arg {
|
||||||
|
AngleBracketedArg::Arg(lt @ GenericArg::Lifetime(_)) => {
|
||||||
|
Some(pprust::to_string(|s| s.print_generic_arg(lt)))
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
});
|
||||||
|
let args_sugg = data.args.iter().filter_map(|a| match a {
|
||||||
|
AngleBracketedArg::Arg(GenericArg::Lifetime(_)) => None,
|
||||||
|
AngleBracketedArg::Arg(arg) => Some(pprust::to_string(|s| s.print_generic_arg(arg))),
|
||||||
|
AngleBracketedArg::Constraint(_) => None,
|
||||||
|
});
|
||||||
|
// Cosntraints always come last.
|
||||||
|
let constraint_sugg = data.args.iter().filter_map(|a| match a {
|
||||||
|
AngleBracketedArg::Arg(_) => None,
|
||||||
|
AngleBracketedArg::Constraint(c) => {
|
||||||
|
Some(pprust::to_string(|s| s.print_assoc_constraint(c)))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
format!(
|
||||||
|
"<{}>",
|
||||||
|
lt_sugg.chain(args_sugg).chain(constraint_sugg).collect::<Vec<String>>().join(", ")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// Enforce generic args coming before constraints in `<...>` of a path segment.
|
/// Enforce generic args coming before constraints in `<...>` of a path segment.
|
||||||
fn check_generic_args_before_constraints(&self, data: &AngleBracketedArgs) {
|
fn check_generic_args_before_constraints(&self, data: &AngleBracketedArgs) {
|
||||||
// Early exit in case it's partitioned as it should be.
|
// Early exit in case it's partitioned as it should be.
|
||||||
@ -663,20 +689,7 @@ fn check_generic_args_before_constraints(&self, data: &AngleBracketedArgs) {
|
|||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let snippet_span = match &constraint_spans[..] {
|
let args_len = arg_spans.len();
|
||||||
[single] => *single,
|
|
||||||
[first, .., last] => first.to(*last),
|
|
||||||
[] => unreachable!(),
|
|
||||||
};
|
|
||||||
let removal_span = match &arg_spans[..] {
|
|
||||||
[first, ..] => snippet_span.until(*first),
|
|
||||||
[] => unreachable!(),
|
|
||||||
};
|
|
||||||
let sugg_span = match &arg_spans[..] {
|
|
||||||
[.., last] => last.shrink_to_hi(),
|
|
||||||
[] => unreachable!(),
|
|
||||||
};
|
|
||||||
let snippet = self.session.source_map().span_to_snippet(snippet_span).unwrap();
|
|
||||||
let constraint_len = constraint_spans.len();
|
let constraint_len = constraint_spans.len();
|
||||||
// ...and then error:
|
// ...and then error:
|
||||||
self.err_handler()
|
self.err_handler()
|
||||||
@ -693,13 +706,14 @@ fn check_generic_args_before_constraints(&self, data: &AngleBracketedArgs) {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
.span_labels(arg_spans, "generic argument")
|
.span_labels(arg_spans, "generic argument")
|
||||||
.multipart_suggestion(
|
.span_suggestion_verbose(
|
||||||
"move the constraints after the generic arguments",
|
data.span,
|
||||||
vec![
|
&format!(
|
||||||
(removal_span, String::new()),
|
"move the constraint{} after the generic argument{}",
|
||||||
(sugg_span.shrink_to_lo(), ", ".to_string()),
|
pluralize!(constraint_len),
|
||||||
(sugg_span, snippet),
|
pluralize!(args_len)
|
||||||
],
|
),
|
||||||
|
self.suggest_correct_generic_order(&data),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
)
|
)
|
||||||
.emit();
|
.emit();
|
||||||
|
@ -870,7 +870,7 @@ pub fn print_opt_lifetime(&mut self, lifetime: &Option<ast::Lifetime>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_assoc_constraint(&mut self, constraint: &ast::AssocTyConstraint) {
|
pub fn print_assoc_constraint(&mut self, constraint: &ast::AssocTyConstraint) {
|
||||||
self.print_ident(constraint.ident);
|
self.print_ident(constraint.ident);
|
||||||
self.s.space();
|
self.s.space();
|
||||||
match &constraint.kind {
|
match &constraint.kind {
|
||||||
@ -884,7 +884,7 @@ fn print_assoc_constraint(&mut self, constraint: &ast::AssocTyConstraint) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn print_generic_arg(&mut self, generic_arg: &GenericArg) {
|
pub fn print_generic_arg(&mut self, generic_arg: &GenericArg) {
|
||||||
match generic_arg {
|
match generic_arg {
|
||||||
GenericArg::Lifetime(lt) => self.print_lifetime(*lt),
|
GenericArg::Lifetime(lt) => self.print_lifetime(*lt),
|
||||||
GenericArg::Type(ty) => self.print_type(ty),
|
GenericArg::Type(ty) => self.print_type(ty),
|
||||||
|
@ -315,6 +315,20 @@ pub fn span_suggestion_short(
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn span_suggestion_verbose(
|
||||||
|
&mut self,
|
||||||
|
sp: Span,
|
||||||
|
msg: &str,
|
||||||
|
suggestion: String,
|
||||||
|
applicability: Applicability,
|
||||||
|
) -> &mut Self {
|
||||||
|
if !self.0.allow_suggestions {
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
self.0.diagnostic.span_suggestion_verbose(sp, msg, suggestion, applicability);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn span_suggestion_hidden(
|
pub fn span_suggestion_hidden(
|
||||||
&mut self,
|
&mut self,
|
||||||
sp: Span,
|
sp: Span,
|
||||||
|
@ -6,10 +6,10 @@ LL | pub fn test<W, I: Trait<Item=(), W> >() {}
|
|||||||
| |
|
| |
|
||||||
| the constraint is provided here
|
| the constraint is provided here
|
||||||
|
|
|
|
||||||
help: move the constraints after the generic arguments
|
help: move the constraint after the generic argument
|
||||||
|
|
|
|
||||||
LL | pub fn test<W, I: Trait<W, Item=()> >() {}
|
LL | pub fn test<W, I: Trait<W, Item = ()> >() {}
|
||||||
| --^^^^^^^
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -6,10 +6,10 @@ LL | struct A<T, M: One<A=(), T>> {
|
|||||||
| |
|
| |
|
||||||
| the constraint is provided here
|
| the constraint is provided here
|
||||||
|
|
|
|
||||||
help: move the constraints after the generic arguments
|
help: move the constraint after the generic argument
|
||||||
|
|
|
|
||||||
LL | struct A<T, M: One<T, A=()>> {
|
LL | struct A<T, M: One<T, A = ()>> {
|
||||||
| --^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
error: generic arguments must come before the first constraint
|
error: generic arguments must come before the first constraint
|
||||||
--> $DIR/suggest-move-types.rs:33:43
|
--> $DIR/suggest-move-types.rs:33:43
|
||||||
@ -20,10 +20,10 @@ LL | struct Al<'a, T, M: OneWithLifetime<A=(), T, 'a>> {
|
|||||||
| | generic argument
|
| | generic argument
|
||||||
| the constraint is provided here
|
| the constraint is provided here
|
||||||
|
|
|
|
||||||
help: move the constraints after the generic arguments
|
help: move the constraint after the generic arguments
|
||||||
|
|
|
|
||||||
LL | struct Al<'a, T, M: OneWithLifetime<T, 'a, A=()>> {
|
LL | struct Al<'a, T, M: OneWithLifetime<'a, T, A = ()>> {
|
||||||
| -- ^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: generic arguments must come before the first constraint
|
error: generic arguments must come before the first constraint
|
||||||
--> $DIR/suggest-move-types.rs:40:46
|
--> $DIR/suggest-move-types.rs:40:46
|
||||||
@ -39,8 +39,8 @@ LL | struct B<T, U, V, M: Three<A=(), B=(), C=(), T, U, V>> {
|
|||||||
|
|
|
|
||||||
help: move the constraints after the generic arguments
|
help: move the constraints after the generic arguments
|
||||||
|
|
|
|
||||||
LL | struct B<T, U, V, M: Three<T, U, V, A=(), B=(), C=()>> {
|
LL | struct B<T, U, V, M: Three<T, U, V, A = (), B = (), C = ()>> {
|
||||||
| -- ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: generic arguments must come before the first constraint
|
error: generic arguments must come before the first constraint
|
||||||
--> $DIR/suggest-move-types.rs:48:71
|
--> $DIR/suggest-move-types.rs:48:71
|
||||||
@ -59,8 +59,8 @@ LL | struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<A=(), B=(), C=(), T, U,
|
|||||||
|
|
|
|
||||||
help: move the constraints after the generic arguments
|
help: move the constraints after the generic arguments
|
||||||
|
|
|
|
||||||
LL | struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, U, V, 'a, 'b, 'c, A=(), B=(), C=()>> {
|
LL | struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<'a, 'b, 'c, T, U, V, A = (), B = (), C = ()>> {
|
||||||
| -- ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: generic arguments must come before the first constraint
|
error: generic arguments must come before the first constraint
|
||||||
--> $DIR/suggest-move-types.rs:57:28
|
--> $DIR/suggest-move-types.rs:57:28
|
||||||
@ -76,8 +76,8 @@ LL | struct C<T, U, V, M: Three<T, A=(), B=(), C=(), U, V>> {
|
|||||||
|
|
|
|
||||||
help: move the constraints after the generic arguments
|
help: move the constraints after the generic arguments
|
||||||
|
|
|
|
||||||
LL | struct C<T, U, V, M: Three<A=(), B=(), C=(), U, V, A=(), B=(), C=()>> {
|
LL | struct C<T, U, V, M: Three<T, U, V, A = (), B = (), C = ()>> {
|
||||||
| -- ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: generic arguments must come before the first constraint
|
error: generic arguments must come before the first constraint
|
||||||
--> $DIR/suggest-move-types.rs:65:53
|
--> $DIR/suggest-move-types.rs:65:53
|
||||||
@ -96,8 +96,8 @@ LL | struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), C=()
|
|||||||
|
|
|
|
||||||
help: move the constraints after the generic arguments
|
help: move the constraints after the generic arguments
|
||||||
|
|
|
|
||||||
LL | struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<A=(), B=(), C=(), U, 'b, V, 'c, A=(), B=(), C=()>> {
|
LL | struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<'a, 'b, 'c, T, U, V, A = (), B = (), C = ()>> {
|
||||||
| -- ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: generic arguments must come before the first constraint
|
error: generic arguments must come before the first constraint
|
||||||
--> $DIR/suggest-move-types.rs:74:28
|
--> $DIR/suggest-move-types.rs:74:28
|
||||||
@ -113,8 +113,8 @@ LL | struct D<T, U, V, M: Three<T, A=(), B=(), U, C=(), V>> {
|
|||||||
|
|
|
|
||||||
help: move the constraints after the generic arguments
|
help: move the constraints after the generic arguments
|
||||||
|
|
|
|
||||||
LL | struct D<T, U, V, M: Three<A=(), B=(), U, C=(), V, A=(), B=(), U, C=()>> {
|
LL | struct D<T, U, V, M: Three<T, U, V, A = (), B = (), C = ()>> {
|
||||||
| -- ^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: generic arguments must come before the first constraint
|
error: generic arguments must come before the first constraint
|
||||||
--> $DIR/suggest-move-types.rs:82:53
|
--> $DIR/suggest-move-types.rs:82:53
|
||||||
@ -133,8 +133,8 @@ LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), U, '
|
|||||||
|
|
|
|
||||||
help: move the constraints after the generic arguments
|
help: move the constraints after the generic arguments
|
||||||
|
|
|
|
||||||
LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<A=(), B=(), U, 'b, C=(), V, 'c, A=(), B=(), U, 'b, C=()>> {
|
LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<'a, 'b, 'c, T, U, V, A = (), B = (), C = ()>> {
|
||||||
| -- ^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0747]: type provided when a lifetime was expected
|
error[E0747]: type provided when a lifetime was expected
|
||||||
--> $DIR/suggest-move-types.rs:33:43
|
--> $DIR/suggest-move-types.rs:33:43
|
||||||
|
Loading…
Reference in New Issue
Block a user