From dbd70e585916f2599827ab8ce3f810323fd1a5a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Tue, 20 Feb 2024 04:41:01 +0100 Subject: [PATCH] Detect empty leading where-clauses on type aliases --- compiler/rustc_ast_passes/messages.ftl | 3 +- .../rustc_ast_passes/src/ast_validation.rs | 63 ++++++++++--------- compiler/rustc_ast_passes/src/errors.rs | 30 +++++---- .../rustc_lint/src/context/diagnostics.rs | 25 +++++--- compiler/rustc_lint_defs/src/lib.rs | 2 +- .../leading-where-clause.fixed | 18 ++++-- .../lazy-type-alias/leading-where-clause.rs | 21 +++++-- .../leading-where-clause.stderr | 41 +++++++++++- ...-clause-placement-assoc-type-in-impl.fixed | 6 ++ ...ere-clause-placement-assoc-type-in-impl.rs | 6 ++ ...clause-placement-assoc-type-in-impl.stderr | 29 +++++++-- 11 files changed, 177 insertions(+), 67 deletions(-) diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index 6586ca5d36f88..28a13d275a559 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -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 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 diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 8b8478eacacb1..8db0c1002865b 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -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(","); + 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(); + + if !ty_alias.where_clauses.after.has_where_token { + state.space(); + state.word_space("where"); } - first = false; - state.print_where_predicate(p); - } - let span = ty_alias.where_clauses.before.span; - Err(errors::WhereClauseBeforeTypeAlias { - span, - sugg: errors::WhereClauseBeforeTypeAliasSugg { + 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, f: impl FnOnce(&mut Self)) { @@ -1475,15 +1479,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), ); } diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 9662c73ca8532..a4ea0b8be4433 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -509,17 +509,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)] diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index 5af2b6daec185..75552cf144a6a 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -427,15 +427,22 @@ pub(super) fn builtin( db.note("see for more information about checking conditional configuration"); } } - BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(new_span, suggestion) => { - db.multipart_suggestion( - "move it to the end of the type declaration", - vec![(db.span.primary_span().unwrap(), "".to_string()), (new_span, suggestion)], - Applicability::MachineApplicable, - ); - db.note( - "see issue #89122 for more information", - ); + BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(sugg) => { + let left_sp = db.span.primary_span().unwrap(); + match sugg { + Some((right_sp, sugg)) => db.multipart_suggestion( + "move it to the end of the type declaration", + vec![(left_sp, String::new()), (right_sp, sugg)], + Applicability::MachineApplicable, + ), + None => db.span_suggestion( + left_sp, + "remove this `where`", + "", + Applicability::MachineApplicable, + ), + }; + db.note("see issue #89122 for more information"); } BuiltinLintDiagnostics::SingleUseLifetime { param_span, diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 09b1f03f151ed..2e8d3662294d8 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -593,7 +593,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, diff --git a/tests/ui/lazy-type-alias/leading-where-clause.fixed b/tests/ui/lazy-type-alias/leading-where-clause.fixed index 885556c1efe7f..ca0ab7b5c7dd2 100644 --- a/tests/ui/lazy-type-alias/leading-where-clause.fixed +++ b/tests/ui/lazy-type-alias/leading-where-clause.fixed @@ -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 +pub type Leading0 = T where String: From; -//~^^^ ERROR where clauses are not allowed before the type for type aliases -fn main() { - let _: Alias<&str>; -} +pub type Leading1 + += (T, U) +where + U: Copy, String: From; + +pub type EmptyLeading0 = () where; +//~^ ERROR where clauses are not allowed before the type for type aliases + +pub type EmptyLeading1 = T where T: Copy; +//~^ ERROR where clauses are not allowed before the type for type aliases diff --git a/tests/ui/lazy-type-alias/leading-where-clause.rs b/tests/ui/lazy-type-alias/leading-where-clause.rs index a0a09a2a08ee1..460f7e3a9994d 100644 --- a/tests/ui/lazy-type-alias/leading-where-clause.rs +++ b/tests/ui/lazy-type-alias/leading-where-clause.rs @@ -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 -where +pub type Leading0 +where //~ ERROR where clauses are not allowed before the type for type aliases String: From, = T; -//~^^^ ERROR where clauses are not allowed before the type for type aliases -fn main() { - let _: Alias<&str>; -} +pub type Leading1 +where //~ ERROR where clauses are not allowed before the type for type aliases + String: From, += (T, U) +where + U: Copy; + +pub type EmptyLeading0 where = (); +//~^ ERROR where clauses are not allowed before the type for type aliases + +pub type EmptyLeading1 where = T where T: Copy; +//~^ ERROR where clauses are not allowed before the type for type aliases diff --git a/tests/ui/lazy-type-alias/leading-where-clause.stderr b/tests/ui/lazy-type-alias/leading-where-clause.stderr index 6b0613787e8bf..344c318d0ef9d 100644 --- a/tests/ui/lazy-type-alias/leading-where-clause.stderr +++ b/tests/ui/lazy-type-alias/leading-where-clause.stderr @@ -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, @@ -12,5 +12,42 @@ LL + LL ~ = T where String: From; | -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, + | |____________________^ + | + = note: see issue #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; + | + +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 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 where = T where T: Copy; + | ^^^^^ help: remove this `where` + | + = note: see issue #89122 for more information + +error: aborting due to 4 previous errors diff --git a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.fixed b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.fixed index b53d9d61d67f2..9b935b1667878 100644 --- a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.fixed +++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.fixed @@ -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() {} diff --git a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.rs b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.rs index 18955dd8bcc39..b7a8ab3d4f782 100644 --- a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.rs +++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.rs @@ -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() {} diff --git a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.stderr b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.stderr index 6ff9d2dd73b5b..5809ff8f80347 100644 --- a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.stderr +++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.stderr @@ -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 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 for more information + +warning: 5 warnings emitted