Rollup merge of #70519 - estebank:constraints-before-args-spans, r=Centril
Tweak output of type params and constraints in the wrong order r? @Centril @varkor
This commit is contained in:
commit
eea91c308f
8 changed files with 146 additions and 61 deletions
|
@ -3564,6 +3564,7 @@ dependencies = [
|
||||||
name = "rustc_ast_passes"
|
name = "rustc_ast_passes"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"itertools 0.8.0",
|
||||||
"log",
|
"log",
|
||||||
"rustc_ast",
|
"rustc_ast",
|
||||||
"rustc_ast_pretty",
|
"rustc_ast_pretty",
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ name = "rustc_ast_passes"
|
||||||
path = "lib.rs"
|
path = "lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
itertools = "0.8"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
rustc_ast_pretty = { path = "../librustc_ast_pretty" }
|
rustc_ast_pretty = { path = "../librustc_ast_pretty" }
|
||||||
rustc_attr = { path = "../librustc_attr" }
|
rustc_attr = { path = "../librustc_attr" }
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
// This pass is supposed to perform only simple checks not requiring name resolution
|
// This pass is supposed to perform only simple checks not requiring name resolution
|
||||||
// or type checking or some other kind of complex analysis.
|
// or type checking or some other kind of complex analysis.
|
||||||
|
|
||||||
|
use itertools::{Either, Itertools};
|
||||||
use rustc_ast::ast::*;
|
use rustc_ast::ast::*;
|
||||||
use rustc_ast::attr;
|
use rustc_ast::attr;
|
||||||
use rustc_ast::expand::is_proc_macro_attr;
|
use rustc_ast::expand::is_proc_macro_attr;
|
||||||
|
@ -14,7 +15,7 @@ use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
|
||||||
use rustc_ast::walk_list;
|
use rustc_ast::walk_list;
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
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_parse::validate_attr;
|
||||||
use rustc_session::lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY;
|
use rustc_session::lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY;
|
||||||
use rustc_session::lint::LintBuffer;
|
use rustc_session::lint::LintBuffer;
|
||||||
|
@ -640,6 +641,33 @@ impl<'a> AstValidator<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn correct_generic_order_suggestion(&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(_)) | AngleBracketedArg::Constraint(_) => {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
AngleBracketedArg::Arg(arg) => Some(pprust::to_string(|s| s.print_generic_arg(arg))),
|
||||||
|
});
|
||||||
|
// Constraints 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.
|
||||||
|
@ -647,24 +675,36 @@ impl<'a> AstValidator<'a> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Find all generic argument coming after the first constraint...
|
// Find all generic argument coming after the first constraint...
|
||||||
let mut misplaced_args = Vec::new();
|
let (constraint_spans, arg_spans): (Vec<Span>, Vec<Span>) =
|
||||||
let mut first = None;
|
data.args.iter().partition_map(|arg| match arg {
|
||||||
for arg in &data.args {
|
AngleBracketedArg::Constraint(c) => Either::Left(c.span),
|
||||||
match (arg, first) {
|
AngleBracketedArg::Arg(a) => Either::Right(a.span()),
|
||||||
(AngleBracketedArg::Arg(a), Some(_)) => misplaced_args.push(a.span()),
|
});
|
||||||
(AngleBracketedArg::Constraint(c), None) => first = Some(c.span),
|
let args_len = arg_spans.len();
|
||||||
(AngleBracketedArg::Arg(_), None) | (AngleBracketedArg::Constraint(_), Some(_)) => {
|
let constraint_len = constraint_spans.len();
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// ...and then error:
|
// ...and then error:
|
||||||
self.err_handler()
|
self.err_handler()
|
||||||
.struct_span_err(
|
.struct_span_err(
|
||||||
misplaced_args.clone(),
|
arg_spans.clone(),
|
||||||
"generic arguments must come before the first constraint",
|
"generic arguments must come before the first constraint",
|
||||||
)
|
)
|
||||||
.span_label(first.unwrap(), "the first constraint is provided here")
|
.span_label(constraint_spans[0], &format!("constraint{}", pluralize!(constraint_len)))
|
||||||
.span_labels(misplaced_args, "generic argument")
|
.span_label(
|
||||||
|
*arg_spans.iter().last().unwrap(),
|
||||||
|
&format!("generic argument{}", pluralize!(args_len)),
|
||||||
|
)
|
||||||
|
.span_labels(constraint_spans, "")
|
||||||
|
.span_labels(arg_spans, "")
|
||||||
|
.span_suggestion_verbose(
|
||||||
|
data.span,
|
||||||
|
&format!(
|
||||||
|
"move the constraint{} after the generic argument{}",
|
||||||
|
pluralize!(constraint_len),
|
||||||
|
pluralize!(args_len)
|
||||||
|
),
|
||||||
|
self.correct_generic_order_suggestion(&data),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
)
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -869,7 +869,7 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
||||||
|
@ -883,7 +883,7 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 @@ impl<'a> DiagnosticBuilder<'a> {
|
||||||
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,
|
||||||
|
|
|
@ -4,7 +4,12 @@ error: generic arguments must come before the first constraint
|
||||||
LL | pub fn test<W, I: Trait<Item=(), W> >() {}
|
LL | pub fn test<W, I: Trait<Item=(), W> >() {}
|
||||||
| ------- ^ generic argument
|
| ------- ^ generic argument
|
||||||
| |
|
| |
|
||||||
| the first constraint is provided here
|
| constraint
|
||||||
|
|
|
||||||
|
help: move the constraint after the generic argument
|
||||||
|
|
|
||||||
|
LL | pub fn test<W, I: Trait<W, Item = ()> >() {}
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -4,79 +4,103 @@ error: generic arguments must come before the first constraint
|
||||||
LL | struct A<T, M: One<A=(), T>> {
|
LL | struct A<T, M: One<A=(), T>> {
|
||||||
| ---- ^ generic argument
|
| ---- ^ generic argument
|
||||||
| |
|
| |
|
||||||
| the first constraint is provided here
|
| constraint
|
||||||
|
|
|
||||||
|
help: move the constraint after the generic argument
|
||||||
|
|
|
||||||
|
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
|
||||||
|
|
|
|
||||||
LL | struct Al<'a, T, M: OneWithLifetime<A=(), T, 'a>> {
|
LL | struct Al<'a, T, M: OneWithLifetime<A=(), T, 'a>> {
|
||||||
| ---- ^ ^^ generic argument
|
| ---- ^ ^^ generic arguments
|
||||||
| | |
|
| |
|
||||||
| | generic argument
|
| constraint
|
||||||
| the first constraint is provided here
|
|
|
||||||
|
help: move the constraint after the generic arguments
|
||||||
|
|
|
||||||
|
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
|
||||||
|
|
|
|
||||||
LL | struct B<T, U, V, M: Three<A=(), B=(), C=(), T, U, V>> {
|
LL | struct B<T, U, V, M: Three<A=(), B=(), C=(), T, U, V>> {
|
||||||
| ---- ^ ^ ^ generic argument
|
| ---- ---- ---- ^ ^ ^ generic arguments
|
||||||
| | | |
|
| |
|
||||||
| | | generic argument
|
| constraints
|
||||||
| | generic argument
|
|
|
||||||
| the first constraint is 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
|
error: generic arguments must come before the first constraint
|
||||||
--> $DIR/suggest-move-types.rs:48:71
|
--> $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>> {
|
LL | struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<A=(), B=(), C=(), T, U, V, 'a, 'b, 'c>> {
|
||||||
| ---- ^ ^ ^ ^^ ^^ ^^ generic argument
|
| ---- ---- ---- ^ ^ ^ ^^ ^^ ^^ generic arguments
|
||||||
| | | | | | |
|
| |
|
||||||
| | | | | | generic argument
|
| constraints
|
||||||
| | | | | generic argument
|
|
|
||||||
| | | | generic argument
|
help: move the constraints after the generic arguments
|
||||||
| | | generic argument
|
|
|
||||||
| | generic argument
|
LL | struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<'a, 'b, 'c, T, U, V, A = (), B = (), C = ()>> {
|
||||||
| the first constraint is provided here
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: generic arguments must come before the first constraint
|
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>> {
|
LL | struct C<T, U, V, M: Three<T, A=(), B=(), C=(), U, V>> {
|
||||||
| ---- ^ ^ generic argument
|
| ^ ---- ---- ---- ^ ^ generic arguments
|
||||||
| | |
|
| |
|
||||||
| | generic argument
|
| constraints
|
||||||
| the first constraint is provided here
|
|
|
||||||
|
help: move the constraints after the generic arguments
|
||||||
|
|
|
||||||
|
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: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>> {
|
LL | struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), C=(), U, 'b, V, 'c>> {
|
||||||
| ---- ^ ^^ ^ ^^ generic argument
|
| ^ ^^ ---- ---- ---- ^ ^^ ^ ^^ generic arguments
|
||||||
| | | | |
|
| |
|
||||||
| | | | generic argument
|
| constraints
|
||||||
| | | generic argument
|
|
|
||||||
| | generic argument
|
help: move the constraints after the generic arguments
|
||||||
| the first constraint is provided here
|
|
|
||||||
|
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:43
|
--> $DIR/suggest-move-types.rs:74:28
|
||||||
|
|
|
|
||||||
LL | struct D<T, U, V, M: Three<T, A=(), B=(), U, C=(), V>> {
|
LL | struct D<T, U, V, M: Three<T, A=(), B=(), U, C=(), V>> {
|
||||||
| ---- ^ ^ generic argument
|
| ^ ---- ---- ^ ---- ^ generic arguments
|
||||||
| | |
|
| |
|
||||||
| | generic argument
|
| constraints
|
||||||
| the first constraint is provided here
|
|
|
||||||
|
help: move the constraints after the generic arguments
|
||||||
|
|
|
||||||
|
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: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>> {
|
LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime<T, 'a, A=(), B=(), U, 'b, C=(), V, 'c>> {
|
||||||
| ---- ^ ^^ ^ ^^ generic argument
|
| ^ ^^ ---- ---- ^ ^^ ---- ^ ^^ generic arguments
|
||||||
| | | | |
|
| |
|
||||||
| | | | generic argument
|
| constraints
|
||||||
| | | generic argument
|
|
|
||||||
| | generic argument
|
help: move the constraints after the generic arguments
|
||||||
| the first constraint is provided here
|
|
|
||||||
|
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…
Add table
Add a link
Reference in a new issue