Detect empty leading where-clauses on type aliases

This commit is contained in:
León Orell Valerian Liehr 2024-02-20 04:41:01 +01:00
parent 2b8060578a
commit cce81289e6
No known key found for this signature in database
GPG Key ID: D17A07215F68E713
11 changed files with 178 additions and 68 deletions

View File

@ -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 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 .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

View File

@ -138,21 +138,24 @@ impl<'a> AstValidator<'a> {
&mut self, &mut self,
ty_alias: &TyAlias, ty_alias: &TyAlias,
) -> Result<(), errors::WhereClauseBeforeTypeAlias> { ) -> Result<(), errors::WhereClauseBeforeTypeAlias> {
let before_predicates = if ty_alias.ty.is_none() || !ty_alias.where_clauses.before.has_where_token {
ty_alias.generics.where_clause.predicates.split_at(ty_alias.where_clauses.split).0;
if ty_alias.ty.is_none() || before_predicates.is_empty() {
return Ok(()); return Ok(());
} }
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;
let sugg = if !before_predicates.is_empty() || !ty_alias.where_clauses.after.has_where_token
{
let mut state = State::new(); let mut state = State::new();
if !ty_alias.where_clauses.after.has_where_token { if !ty_alias.where_clauses.after.has_where_token {
state.space(); state.space();
state.word_space("where"); state.word_space("where");
} else {
state.word_space(",");
} }
let mut first = true;
let mut first = after_predicates.is_empty();
for p in before_predicates { for p in before_predicates {
if !first { if !first {
state.word_space(","); state.word_space(",");
@ -161,15 +164,16 @@ impl<'a> AstValidator<'a> {
state.print_where_predicate(p); state.print_where_predicate(p);
} }
let span = ty_alias.where_clauses.before.span; errors::WhereClauseBeforeTypeAliasSugg::Move {
Err(errors::WhereClauseBeforeTypeAlias {
span,
sugg: errors::WhereClauseBeforeTypeAliasSugg {
left: span, left: span,
snippet: state.s.eof(), snippet: state.s.eof(),
right: ty_alias.where_clauses.after.span.shrink_to_hi(), 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)) { 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 if let AssocItemKind::Type(ty_alias) = &item.kind
&& let Err(err) = self.check_type_alias_where_clause_location(ty_alias) && 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( self.lint_buffer.buffer_lint_with_diagnostic(
DEPRECATED_WHERE_CLAUSE_LOCATION, DEPRECATED_WHERE_CLAUSE_LOCATION,
item.id, item.id,
err.span, err.span,
fluent::ast_passes_deprecated_where_clause_location, fluent::ast_passes_deprecated_where_clause_location,
BuiltinLintDiagnostics::DeprecatedWhereclauseLocation( BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(sugg),
err.sugg.right,
err.sugg.snippet,
),
); );
} }

View File

@ -515,17 +515,25 @@ pub struct WhereClauseBeforeTypeAlias {
} }
#[derive(Subdiagnostic)] #[derive(Subdiagnostic)]
#[multipart_suggestion(
ast_passes_suggestion, 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", applicability = "machine-applicable",
style = "verbose" style = "verbose"
)] )]
pub struct WhereClauseBeforeTypeAliasSugg { Move {
#[suggestion_part(code = "")] #[suggestion_part(code = "")]
pub left: Span, left: Span,
pub snippet: String, snippet: String,
#[suggestion_part(code = "{snippet}")] #[suggestion_part(code = "{snippet}")]
pub right: Span, right: Span,
},
} }
#[derive(Diagnostic)] #[derive(Diagnostic)]

View File

@ -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"); 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) => { BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(sugg) => {
diag.multipart_suggestion( 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", "move it to the end of the type declaration",
vec![(diag.span.primary_span().unwrap(), "".to_string()), (new_span, suggestion)], vec![(left_sp, String::new()), (right_sp, sugg)],
Applicability::MachineApplicable, Applicability::MachineApplicable,
); ),
diag.note( None => diag.span_suggestion(
"see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information", 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 { BuiltinLintDiagnostics::SingleUseLifetime {
param_span, param_span,

View File

@ -597,7 +597,7 @@ pub enum BuiltinLintDiagnostics {
UnicodeTextFlow(Span, String), UnicodeTextFlow(Span, String),
UnexpectedCfgName((Symbol, Span), Option<(Symbol, Span)>), UnexpectedCfgName((Symbol, Span), Option<(Symbol, Span)>),
UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>), UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>),
DeprecatedWhereclauseLocation(Span, String), DeprecatedWhereclauseLocation(Option<(Span, String)>),
SingleUseLifetime { SingleUseLifetime {
/// Span of the parameter which declares this lifetime. /// Span of the parameter which declares this lifetime.
param_span: Span, param_span: Span,

View File

@ -2,14 +2,22 @@
#![feature(lazy_type_alias)] #![feature(lazy_type_alias)]
#![allow(incomplete_features)] #![allow(incomplete_features)]
#![crate_type = "lib"]
// Check that we *reject* leading where-clauses on lazy type aliases. // Check that we *reject* leading where-clauses on lazy type aliases.
type Alias<T> pub type Leading0<T>
= T where String: From<T>; = T where String: From<T>;
//~^^^ ERROR where clauses are not allowed before the type for type aliases
fn main() { pub type Leading1<T, U>
let _: Alias<&str>;
} = (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

View File

@ -2,15 +2,24 @@
#![feature(lazy_type_alias)] #![feature(lazy_type_alias)]
#![allow(incomplete_features)] #![allow(incomplete_features)]
#![crate_type = "lib"]
// Check that we *reject* leading where-clauses on lazy type aliases. // Check that we *reject* leading where-clauses on lazy type aliases.
type Alias<T> pub type Leading0<T>
where where //~ ERROR where clauses are not allowed before the type for type aliases
String: From<T>, String: From<T>,
= T; = T;
//~^^^ ERROR where clauses are not allowed before the type for type aliases
fn main() { pub type Leading1<T, U>
let _: Alias<&str>; 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

View File

@ -1,5 +1,5 @@
error: where clauses are not allowed before the type for type aliases 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 | / where
LL | | String: From<T>, LL | | String: From<T>,
@ -12,5 +12,42 @@ LL +
LL ~ = T where String: From<T>; 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

View File

@ -8,6 +8,8 @@ trait Trait {
type Assoc where u32: Copy; type Assoc where u32: Copy;
// Fine. // Fine.
type Assoc2 where u32: Copy, i32: Copy; type Assoc2 where u32: Copy, i32: Copy;
//
type Assoc3;
} }
impl Trait for u32 { impl Trait for u32 {
@ -17,6 +19,8 @@ impl Trait for u32 {
// Not fine, suggests moving `u32: Copy` // Not fine, suggests moving `u32: Copy`
type Assoc2 = () where i32: Copy, u32: Copy; type Assoc2 = () where i32: Copy, u32: Copy;
//~^ WARNING where clause not allowed here //~^ WARNING where clause not allowed here
type Assoc3 = () where;
//~^ WARNING where clause not allowed here
} }
impl Trait for i32 { impl Trait for i32 {
@ -25,6 +29,8 @@ impl Trait for i32 {
// Not fine, suggests moving both. // Not fine, suggests moving both.
type Assoc2 = () where u32: Copy, i32: Copy; type Assoc2 = () where u32: Copy, i32: Copy;
//~^ WARNING where clause not allowed here //~^ WARNING where clause not allowed here
type Assoc3 = () where;
//~^ WARNING where clause not allowed here
} }
fn main() {} fn main() {}

View File

@ -8,6 +8,8 @@ trait Trait {
type Assoc where u32: Copy; type Assoc where u32: Copy;
// Fine. // Fine.
type Assoc2 where u32: Copy, i32: Copy; type Assoc2 where u32: Copy, i32: Copy;
//
type Assoc3;
} }
impl Trait for u32 { impl Trait for u32 {
@ -17,6 +19,8 @@ impl Trait for u32 {
// Not fine, suggests moving `u32: Copy` // Not fine, suggests moving `u32: Copy`
type Assoc2 where u32: Copy = () where i32: Copy; type Assoc2 where u32: Copy = () where i32: Copy;
//~^ WARNING where clause not allowed here //~^ WARNING where clause not allowed here
type Assoc3 where = ();
//~^ WARNING where clause not allowed here
} }
impl Trait for i32 { impl Trait for i32 {
@ -25,6 +29,8 @@ impl Trait for i32 {
// Not fine, suggests moving both. // Not fine, suggests moving both.
type Assoc2 where u32: Copy, i32: Copy = (); type Assoc2 where u32: Copy, i32: Copy = ();
//~^ WARNING where clause not allowed here //~^ WARNING where clause not allowed here
type Assoc3 where = () where;
//~^ WARNING where clause not allowed here
} }
fn main() {} fn main() {}

View File

@ -1,5 +1,5 @@
warning: where clause not allowed here 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 = (); LL | type Assoc where u32: Copy = ();
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
@ -13,7 +13,7 @@ LL + type Assoc = () where u32: Copy;
| |
warning: where clause not allowed here 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; 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 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 = (); 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; 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