Skip to content

Tweak output of type params and constraints in the wrong order #70519

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 6 commits into from
Apr 6, 2020
Merged
Show file tree
Hide file tree
Changes from 2 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
65 changes: 51 additions & 14 deletions src/librustc_ast_passes/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
use rustc_ast::walk_list;
use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{error_code, struct_span_err, Applicability};
use rustc_errors::{error_code, pluralize, struct_span_err, Applicability};
use rustc_parse::validate_attr;
use rustc_session::lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY;
use rustc_session::lint::LintBuffer;
Expand Down Expand Up @@ -647,24 +647,61 @@ impl<'a> AstValidator<'a> {
return;
}
// Find all generic argument coming after the first constraint...
let mut misplaced_args = Vec::new();
let mut first = None;
for arg in &data.args {
match (arg, first) {
(AngleBracketedArg::Arg(a), Some(_)) => misplaced_args.push(a.span()),
(AngleBracketedArg::Constraint(c), None) => first = Some(c.span),
(AngleBracketedArg::Arg(_), None) | (AngleBracketedArg::Constraint(_), Some(_)) => {
}
}
}
let constraint_spans = data
.args
.iter()
.filter_map(|arg| match arg {
AngleBracketedArg::Constraint(c) => Some(c.span),
_ => None,
})
.collect::<Vec<_>>();
let arg_spans = data
.args
.iter()
.filter_map(|arg| match arg {
AngleBracketedArg::Arg(a) => Some(a.span()),
_ => None,
})
.collect::<Vec<_>>();
let snippet_span = match &constraint_spans[..] {
[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();
// ...and then error:
self.err_handler()
.struct_span_err(
misplaced_args.clone(),
arg_spans.clone(),
"generic arguments must come before the first constraint",
)
.span_label(first.unwrap(), "the first constraint is provided here")
.span_labels(misplaced_args, "generic argument")
.span_labels(
constraint_spans,
&format!(
"the constraint{} {} provided here",
pluralize!(constraint_len),
if constraint_len == 1 { "is" } else { "are" }
),
)
.span_labels(arg_spans, "generic argument")
.multipart_suggestion(
"move the constraints after the generic arguments",
vec![
(removal_span, String::new()),
(sugg_span.shrink_to_lo(), ", ".to_string()),
(sugg_span, snippet),
],
Applicability::MachineApplicable,
)
.emit();
}
}
Expand Down
7 changes: 6 additions & 1 deletion src/test/ui/parser/issue-32214.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ error: generic arguments must come before the first constraint
LL | pub fn test<W, I: Trait<Item=(), W> >() {}
| ------- ^ generic argument
| |
| the first constraint is provided here
| the constraint is provided here
|
help: move the constraints after the generic arguments
|
LL | pub fn test<W, I: Trait<W, Item=()> >() {}
| --^^^^^^^

error: aborting due to previous error

136 changes: 97 additions & 39 deletions src/test/ui/suggestions/suggest-move-types.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ error: generic arguments must come before the first constraint
LL | struct A<T, M: One<A=(), T>> {
| ---- ^ generic argument
| |
| the first constraint is provided here
| the constraint is provided here
|
help: move the constraints after the generic arguments
|
LL | struct A<T, M: One<T, A=()>> {
| --^^^^

error: generic arguments must come before the first constraint
--> $DIR/suggest-move-types.rs:33:43
Expand All @@ -13,70 +18,123 @@ LL | struct Al<'a, T, M: OneWithLifetime<A=(), T, 'a>> {
| ---- ^ ^^ generic argument
| | |
| | generic argument
| the first constraint is provided here
| the constraint is provided here
|
help: move the constraints after the generic arguments
|
LL | struct Al<'a, T, M: OneWithLifetime<T, 'a, A=()>> {
| -- ^^^^

error: generic arguments must come before the first constraint
--> $DIR/suggest-move-types.rs:40:46
|
LL | struct B<T, U, V, M: Three<A=(), B=(), C=(), T, U, V>> {
| ---- ^ ^ ^ generic argument
| | | |
| | | generic argument
| | generic argument
| the first constraint is provided here
| ---- ---- ---- ^ ^ ^ generic argument
| | | | | |
| | | | | generic argument
| | | | generic argument
| | | the constraints are provided here
| | the constraints are provided here
| the constraints are provided here
|
help: move the constraints after the generic arguments
|
LL | struct B<T, U, V, M: Three<T, U, V, A=(), B=(), C=()>> {
| -- ^^^^^^^^^^^^^^^^

error: generic arguments must come before the first constraint
--> $DIR/suggest-move-types.rs:48:71
|
LL | struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<A=(), B=(), C=(), T, U, V, 'a, 'b, 'c>> {
| ---- ^ ^ ^ ^^ ^^ ^^ generic argument
| | | | | | |
| | | | | | generic argument
| | | | | generic argument
| | | | generic argument
| | | generic argument
| | generic argument
| the first constraint is provided here
| ---- ---- ---- ^ ^ ^ ^^ ^^ ^^ generic argument
| | | | | | | | |
| | | | | | | | generic argument
| | | | | | | generic argument
| | | | | | generic argument
| | | | | generic argument
| | | | generic argument
| | | the constraints are provided here
| | the constraints are provided here
| the constraints are provided here
|
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=()>> {
| -- ^^^^^^^^^^^^^^^^

error: generic arguments must come before the first constraint
--> $DIR/suggest-move-types.rs:57:49
--> $DIR/suggest-move-types.rs:57:28
|
LL | struct C<T, U, V, M: Three<T, A=(), B=(), C=(), U, V>> {
| ---- ^ ^ generic argument
| | |
| | generic argument
| the first constraint is provided here
| ^ ---- ---- ---- ^ ^ generic argument
| | | | | |
| | | | | generic argument
| | | | the constraints are provided here
| | | the constraints are provided here
| | the constraints are provided here
| generic argument
|
help: move the constraints after the generic arguments
|
LL | struct C<T, U, V, M: Three<A=(), B=(), C=(), U, V, A=(), B=(), C=()>> {
| -- ^^^^^^^^^^^^^^^^

error: generic arguments must come before the first constraint
--> $DIR/suggest-move-types.rs:65:78
--> $DIR/suggest-move-types.rs:65:53
|
LL | struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), C=(), U, 'b, V, 'c>> {
| ---- ^ ^^ ^ ^^ generic argument
| | | | |
| | | | generic argument
| | | generic argument
| | generic argument
| the first constraint is provided here
| ^ ^^ ---- ---- ---- ^ ^^ ^ ^^ generic argument
| | | | | | | | |
| | | | | | | | generic argument
| | | | | | | generic argument
| | | | | | generic argument
| | | | | the constraints are provided here
| | | | the constraints are provided here
| | | the constraints are provided here
| | generic argument
| generic argument
|
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=()>> {
| -- ^^^^^^^^^^^^^^^^

error: generic arguments must come before the first constraint
--> $DIR/suggest-move-types.rs:74:43
--> $DIR/suggest-move-types.rs:74:28
|
LL | struct D<T, U, V, M: Three<T, A=(), B=(), U, C=(), V>> {
| ---- ^ ^ generic argument
| | |
| | generic argument
| the first constraint is provided here
| ^ ---- ---- ^ ---- ^ generic argument
| | | | | |
| | | | | the constraints are provided here
| | | | generic argument
| | | the constraints are provided here
| | the constraints are provided here
| generic argument
|
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=()>> {
| -- ^^^^^^^^^^^^^^^^^^^

error: generic arguments must come before the first constraint
--> $DIR/suggest-move-types.rs:82:72
--> $DIR/suggest-move-types.rs:82:53
|
LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), U, 'b, C=(), V, 'c>> {
| ---- ^ ^^ ^ ^^ generic argument
| | | | |
| | | | generic argument
| | | generic argument
| | generic argument
| the first constraint is provided here
| ^ ^^ ---- ---- ^ ^^ ---- ^ ^^ generic argument
| | | | | | | | |
| | | | | | | | generic argument
| | | | | | | the constraints are provided here
| | | | | | generic argument
| | | | | generic argument
| | | | the constraints are provided here
| | | the constraints are provided here
| | generic argument
| generic argument
|
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=()>> {
| -- ^^^^^^^^^^^^^^^^^^^^^^^

error[E0747]: type provided when a lifetime was expected
--> $DIR/suggest-move-types.rs:33:43
Expand Down