From 33d793c326a83ed2e71a4d5e612526cf13c890b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 28 Mar 2020 13:48:04 -0700 Subject: [PATCH] Point at all constraints before args --- src/librustc_ast_passes/ast_validation.rs | 42 +++++--- src/test/ui/parser/issue-32214.stderr | 2 +- .../ui/suggestions/suggest-move-types.stderr | 96 +++++++++++-------- 3 files changed, 86 insertions(+), 54 deletions(-) diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index de7ae10723f4..680a58d8b778 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -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; @@ -647,24 +647,38 @@ 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::>(); + let arg_spans = data + .args + .iter() + .filter_map(|arg| match arg { + AngleBracketedArg::Arg(a) => Some(a.span()), + _ => None, + }) + .collect::>(); + 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") .emit(); } } diff --git a/src/test/ui/parser/issue-32214.stderr b/src/test/ui/parser/issue-32214.stderr index 742f4fdc38bb..6bb1425ee133 100644 --- a/src/test/ui/parser/issue-32214.stderr +++ b/src/test/ui/parser/issue-32214.stderr @@ -4,7 +4,7 @@ error: generic arguments must come before the first constraint LL | pub fn test >() {} | ------- ^ generic argument | | - | the first constraint is provided here + | the constraint is provided here error: aborting due to previous error diff --git a/src/test/ui/suggestions/suggest-move-types.stderr b/src/test/ui/suggestions/suggest-move-types.stderr index 4dd0613757a9..b4cf0deacee4 100644 --- a/src/test/ui/suggestions/suggest-move-types.stderr +++ b/src/test/ui/suggestions/suggest-move-types.stderr @@ -4,7 +4,7 @@ error: generic arguments must come before the first constraint LL | struct A> { | ---- ^ generic argument | | - | the first constraint is provided here + | the constraint is provided here error: generic arguments must come before the first constraint --> $DIR/suggest-move-types.rs:33:43 @@ -13,70 +13,88 @@ LL | struct Al<'a, T, M: OneWithLifetime> { | ---- ^ ^^ generic argument | | | | | generic argument - | the first constraint is provided here + | the constraint is provided here error: generic arguments must come before the first constraint --> $DIR/suggest-move-types.rs:40:46 | LL | struct B> { - | ---- ^ ^ ^ 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 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> { - | ---- ^ ^ ^ ^^ ^^ ^^ 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 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> { - | ---- ^ ^ 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 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> { - | ---- ^ ^^ ^ ^^ 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 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> { - | ---- ^ ^ 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 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> { - | ---- ^ ^^ ^ ^^ 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 error[E0747]: type provided when a lifetime was expected --> $DIR/suggest-move-types.rs:33:43