mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-29 02:03:53 +00:00
Detect empty leading where-clauses on type aliases
This commit is contained in:
parent
2b8060578a
commit
cce81289e6
@ -280,4 +280,5 @@ ast_passes_where_clause_after_type_alias = where clauses are not allowed after t
|
||||
|
||||
ast_passes_where_clause_before_type_alias = where clauses are not allowed before the type for type aliases
|
||||
.note = see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
|
||||
.suggestion = move it to the end of the type declaration
|
||||
.remove_suggestion = remove this `where`
|
||||
.move_suggestion = move it to the end of the type declaration
|
||||
|
@ -138,38 +138,42 @@ impl<'a> AstValidator<'a> {
|
||||
&mut self,
|
||||
ty_alias: &TyAlias,
|
||||
) -> Result<(), errors::WhereClauseBeforeTypeAlias> {
|
||||
let before_predicates =
|
||||
ty_alias.generics.where_clause.predicates.split_at(ty_alias.where_clauses.split).0;
|
||||
|
||||
if ty_alias.ty.is_none() || before_predicates.is_empty() {
|
||||
if ty_alias.ty.is_none() || !ty_alias.where_clauses.before.has_where_token {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut state = State::new();
|
||||
if !ty_alias.where_clauses.after.has_where_token {
|
||||
state.space();
|
||||
state.word_space("where");
|
||||
} else {
|
||||
state.word_space(",");
|
||||
}
|
||||
let mut first = true;
|
||||
for p in before_predicates {
|
||||
if !first {
|
||||
state.word_space(",");
|
||||
}
|
||||
first = false;
|
||||
state.print_where_predicate(p);
|
||||
}
|
||||
|
||||
let (before_predicates, after_predicates) =
|
||||
ty_alias.generics.where_clause.predicates.split_at(ty_alias.where_clauses.split);
|
||||
let span = ty_alias.where_clauses.before.span;
|
||||
Err(errors::WhereClauseBeforeTypeAlias {
|
||||
span,
|
||||
sugg: errors::WhereClauseBeforeTypeAliasSugg {
|
||||
|
||||
let sugg = if !before_predicates.is_empty() || !ty_alias.where_clauses.after.has_where_token
|
||||
{
|
||||
let mut state = State::new();
|
||||
|
||||
if !ty_alias.where_clauses.after.has_where_token {
|
||||
state.space();
|
||||
state.word_space("where");
|
||||
}
|
||||
|
||||
let mut first = after_predicates.is_empty();
|
||||
for p in before_predicates {
|
||||
if !first {
|
||||
state.word_space(",");
|
||||
}
|
||||
first = false;
|
||||
state.print_where_predicate(p);
|
||||
}
|
||||
|
||||
errors::WhereClauseBeforeTypeAliasSugg::Move {
|
||||
left: span,
|
||||
snippet: state.s.eof(),
|
||||
right: ty_alias.where_clauses.after.span.shrink_to_hi(),
|
||||
},
|
||||
})
|
||||
}
|
||||
} else {
|
||||
errors::WhereClauseBeforeTypeAliasSugg::Remove { span }
|
||||
};
|
||||
|
||||
Err(errors::WhereClauseBeforeTypeAlias { span, sugg })
|
||||
}
|
||||
|
||||
fn with_impl_trait(&mut self, outer: Option<Span>, f: impl FnOnce(&mut Self)) {
|
||||
@ -1476,15 +1480,18 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
if let AssocItemKind::Type(ty_alias) = &item.kind
|
||||
&& let Err(err) = self.check_type_alias_where_clause_location(ty_alias)
|
||||
{
|
||||
let sugg = match err.sugg {
|
||||
errors::WhereClauseBeforeTypeAliasSugg::Remove { .. } => None,
|
||||
errors::WhereClauseBeforeTypeAliasSugg::Move { snippet, right, .. } => {
|
||||
Some((right, snippet))
|
||||
}
|
||||
};
|
||||
self.lint_buffer.buffer_lint_with_diagnostic(
|
||||
DEPRECATED_WHERE_CLAUSE_LOCATION,
|
||||
item.id,
|
||||
err.span,
|
||||
fluent::ast_passes_deprecated_where_clause_location,
|
||||
BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(
|
||||
err.sugg.right,
|
||||
err.sugg.snippet,
|
||||
),
|
||||
BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(sugg),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -515,17 +515,25 @@ pub struct WhereClauseBeforeTypeAlias {
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(
|
||||
ast_passes_suggestion,
|
||||
applicability = "machine-applicable",
|
||||
style = "verbose"
|
||||
)]
|
||||
pub struct WhereClauseBeforeTypeAliasSugg {
|
||||
#[suggestion_part(code = "")]
|
||||
pub left: Span,
|
||||
pub snippet: String,
|
||||
#[suggestion_part(code = "{snippet}")]
|
||||
pub right: Span,
|
||||
|
||||
pub enum WhereClauseBeforeTypeAliasSugg {
|
||||
#[suggestion(ast_passes_remove_suggestion, applicability = "machine-applicable", code = "")]
|
||||
Remove {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
#[multipart_suggestion(
|
||||
ast_passes_move_suggestion,
|
||||
applicability = "machine-applicable",
|
||||
style = "verbose"
|
||||
)]
|
||||
Move {
|
||||
#[suggestion_part(code = "")]
|
||||
left: Span,
|
||||
snippet: String,
|
||||
#[suggestion_part(code = "{snippet}")]
|
||||
right: Span,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
@ -428,15 +428,22 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag:
|
||||
diag.note("see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration");
|
||||
}
|
||||
}
|
||||
BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(new_span, suggestion) => {
|
||||
diag.multipart_suggestion(
|
||||
"move it to the end of the type declaration",
|
||||
vec![(diag.span.primary_span().unwrap(), "".to_string()), (new_span, suggestion)],
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
diag.note(
|
||||
"see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information",
|
||||
);
|
||||
BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(sugg) => {
|
||||
let left_sp = diag.span.primary_span().unwrap();
|
||||
match sugg {
|
||||
Some((right_sp, sugg)) => diag.multipart_suggestion(
|
||||
"move it to the end of the type declaration",
|
||||
vec![(left_sp, String::new()), (right_sp, sugg)],
|
||||
Applicability::MachineApplicable,
|
||||
),
|
||||
None => diag.span_suggestion(
|
||||
left_sp,
|
||||
"remove this `where`",
|
||||
"",
|
||||
Applicability::MachineApplicable,
|
||||
),
|
||||
};
|
||||
diag.note("see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information");
|
||||
}
|
||||
BuiltinLintDiagnostics::SingleUseLifetime {
|
||||
param_span,
|
||||
|
@ -597,7 +597,7 @@ pub enum BuiltinLintDiagnostics {
|
||||
UnicodeTextFlow(Span, String),
|
||||
UnexpectedCfgName((Symbol, Span), Option<(Symbol, Span)>),
|
||||
UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>),
|
||||
DeprecatedWhereclauseLocation(Span, String),
|
||||
DeprecatedWhereclauseLocation(Option<(Span, String)>),
|
||||
SingleUseLifetime {
|
||||
/// Span of the parameter which declares this lifetime.
|
||||
param_span: Span,
|
||||
|
@ -2,14 +2,22 @@
|
||||
|
||||
#![feature(lazy_type_alias)]
|
||||
#![allow(incomplete_features)]
|
||||
#![crate_type = "lib"]
|
||||
|
||||
// Check that we *reject* leading where-clauses on lazy type aliases.
|
||||
|
||||
type Alias<T>
|
||||
pub type Leading0<T>
|
||||
|
||||
= T where String: From<T>;
|
||||
//~^^^ ERROR where clauses are not allowed before the type for type aliases
|
||||
|
||||
fn main() {
|
||||
let _: Alias<&str>;
|
||||
}
|
||||
pub type Leading1<T, U>
|
||||
|
||||
= (T, U)
|
||||
where
|
||||
U: Copy, String: From<T>;
|
||||
|
||||
pub type EmptyLeading0 = () where;
|
||||
//~^ ERROR where clauses are not allowed before the type for type aliases
|
||||
|
||||
pub type EmptyLeading1<T> = T where T: Copy;
|
||||
//~^ ERROR where clauses are not allowed before the type for type aliases
|
||||
|
@ -2,15 +2,24 @@
|
||||
|
||||
#![feature(lazy_type_alias)]
|
||||
#![allow(incomplete_features)]
|
||||
#![crate_type = "lib"]
|
||||
|
||||
// Check that we *reject* leading where-clauses on lazy type aliases.
|
||||
|
||||
type Alias<T>
|
||||
where
|
||||
pub type Leading0<T>
|
||||
where //~ ERROR where clauses are not allowed before the type for type aliases
|
||||
String: From<T>,
|
||||
= T;
|
||||
//~^^^ ERROR where clauses are not allowed before the type for type aliases
|
||||
|
||||
fn main() {
|
||||
let _: Alias<&str>;
|
||||
}
|
||||
pub type Leading1<T, U>
|
||||
where //~ ERROR where clauses are not allowed before the type for type aliases
|
||||
String: From<T>,
|
||||
= (T, U)
|
||||
where
|
||||
U: Copy;
|
||||
|
||||
pub type EmptyLeading0 where = ();
|
||||
//~^ ERROR where clauses are not allowed before the type for type aliases
|
||||
|
||||
pub type EmptyLeading1<T> where = T where T: Copy;
|
||||
//~^ ERROR where clauses are not allowed before the type for type aliases
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: where clauses are not allowed before the type for type aliases
|
||||
--> $DIR/leading-where-clause.rs:9:1
|
||||
--> $DIR/leading-where-clause.rs:10:1
|
||||
|
|
||||
LL | / where
|
||||
LL | | String: From<T>,
|
||||
@ -12,5 +12,42 @@ LL +
|
||||
LL ~ = T where String: From<T>;
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
error: where clauses are not allowed before the type for type aliases
|
||||
--> $DIR/leading-where-clause.rs:15:1
|
||||
|
|
||||
LL | / where
|
||||
LL | | String: From<T>,
|
||||
| |____________________^
|
||||
|
|
||||
= note: see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
|
||||
help: move it to the end of the type declaration
|
||||
|
|
||||
LL +
|
||||
LL | = (T, U)
|
||||
LL | where
|
||||
LL ~ U: Copy, String: From<T>;
|
||||
|
|
||||
|
||||
error: where clauses are not allowed before the type for type aliases
|
||||
--> $DIR/leading-where-clause.rs:21:24
|
||||
|
|
||||
LL | pub type EmptyLeading0 where = ();
|
||||
| ^^^^^
|
||||
|
|
||||
= note: see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
|
||||
help: move it to the end of the type declaration
|
||||
|
|
||||
LL - pub type EmptyLeading0 where = ();
|
||||
LL + pub type EmptyLeading0 = () where;
|
||||
|
|
||||
|
||||
error: where clauses are not allowed before the type for type aliases
|
||||
--> $DIR/leading-where-clause.rs:24:27
|
||||
|
|
||||
LL | pub type EmptyLeading1<T> where = T where T: Copy;
|
||||
| ^^^^^ help: remove this `where`
|
||||
|
|
||||
= note: see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
@ -8,6 +8,8 @@ trait Trait {
|
||||
type Assoc where u32: Copy;
|
||||
// Fine.
|
||||
type Assoc2 where u32: Copy, i32: Copy;
|
||||
//
|
||||
type Assoc3;
|
||||
}
|
||||
|
||||
impl Trait for u32 {
|
||||
@ -17,6 +19,8 @@ impl Trait for u32 {
|
||||
// Not fine, suggests moving `u32: Copy`
|
||||
type Assoc2 = () where i32: Copy, u32: Copy;
|
||||
//~^ WARNING where clause not allowed here
|
||||
type Assoc3 = () where;
|
||||
//~^ WARNING where clause not allowed here
|
||||
}
|
||||
|
||||
impl Trait for i32 {
|
||||
@ -25,6 +29,8 @@ impl Trait for i32 {
|
||||
// Not fine, suggests moving both.
|
||||
type Assoc2 = () where u32: Copy, i32: Copy;
|
||||
//~^ WARNING where clause not allowed here
|
||||
type Assoc3 = () where;
|
||||
//~^ WARNING where clause not allowed here
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -8,6 +8,8 @@ trait Trait {
|
||||
type Assoc where u32: Copy;
|
||||
// Fine.
|
||||
type Assoc2 where u32: Copy, i32: Copy;
|
||||
//
|
||||
type Assoc3;
|
||||
}
|
||||
|
||||
impl Trait for u32 {
|
||||
@ -17,6 +19,8 @@ impl Trait for u32 {
|
||||
// Not fine, suggests moving `u32: Copy`
|
||||
type Assoc2 where u32: Copy = () where i32: Copy;
|
||||
//~^ WARNING where clause not allowed here
|
||||
type Assoc3 where = ();
|
||||
//~^ WARNING where clause not allowed here
|
||||
}
|
||||
|
||||
impl Trait for i32 {
|
||||
@ -25,6 +29,8 @@ impl Trait for i32 {
|
||||
// Not fine, suggests moving both.
|
||||
type Assoc2 where u32: Copy, i32: Copy = ();
|
||||
//~^ WARNING where clause not allowed here
|
||||
type Assoc3 where = () where;
|
||||
//~^ WARNING where clause not allowed here
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,5 +1,5 @@
|
||||
warning: where clause not allowed here
|
||||
--> $DIR/where-clause-placement-assoc-type-in-impl.rs:15:16
|
||||
--> $DIR/where-clause-placement-assoc-type-in-impl.rs:17:16
|
||||
|
|
||||
LL | type Assoc where u32: Copy = ();
|
||||
| ^^^^^^^^^^^^^^^
|
||||
@ -13,7 +13,7 @@ LL + type Assoc = () where u32: Copy;
|
||||
|
|
||||
|
||||
warning: where clause not allowed here
|
||||
--> $DIR/where-clause-placement-assoc-type-in-impl.rs:18:17
|
||||
--> $DIR/where-clause-placement-assoc-type-in-impl.rs:20:17
|
||||
|
|
||||
LL | type Assoc2 where u32: Copy = () where i32: Copy;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
@ -26,7 +26,20 @@ LL + type Assoc2 = () where i32: Copy, u32: Copy;
|
||||
|
|
||||
|
||||
warning: where clause not allowed here
|
||||
--> $DIR/where-clause-placement-assoc-type-in-impl.rs:26:17
|
||||
--> $DIR/where-clause-placement-assoc-type-in-impl.rs:22:17
|
||||
|
|
||||
LL | type Assoc3 where = ();
|
||||
| ^^^^^
|
||||
|
|
||||
= note: see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
|
||||
help: move it to the end of the type declaration
|
||||
|
|
||||
LL - type Assoc3 where = ();
|
||||
LL + type Assoc3 = () where;
|
||||
|
|
||||
|
||||
warning: where clause not allowed here
|
||||
--> $DIR/where-clause-placement-assoc-type-in-impl.rs:30:17
|
||||
|
|
||||
LL | type Assoc2 where u32: Copy, i32: Copy = ();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -38,5 +51,13 @@ LL - type Assoc2 where u32: Copy, i32: Copy = ();
|
||||
LL + type Assoc2 = () where u32: Copy, i32: Copy;
|
||||
|
|
||||
|
||||
warning: 3 warnings emitted
|
||||
warning: where clause not allowed here
|
||||
--> $DIR/where-clause-placement-assoc-type-in-impl.rs:32:17
|
||||
|
|
||||
LL | type Assoc3 where = () where;
|
||||
| ^^^^^ help: remove this `where`
|
||||
|
|
||||
= note: see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
|
||||
|
||||
warning: 5 warnings emitted
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user