From cce81289e6baea01c3cd67a6b85fffb3504d0a0b 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 | 65 ++++++++++--------- 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, 178 insertions(+), 68 deletions(-) diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index 6586ca5d36f..28a13d275a5 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 a53f83bbcdc..b56d695c671 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(","); - } - 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, 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), ); } diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 0f37093f057..19eed070911 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -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)] diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index 71aef50391d..14e4c79563b 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -428,15 +428,22 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiagnostics, diag: diag.note("see 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 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 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 fc590001c0d..198008d4d0d 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -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, diff --git a/tests/ui/lazy-type-alias/leading-where-clause.fixed b/tests/ui/lazy-type-alias/leading-where-clause.fixed index 885556c1efe..ca0ab7b5c7d 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 a0a09a2a08e..460f7e3a999 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 6b0613787e8..344c318d0ef 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 b53d9d61d67..9b935b16678 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 18955dd8bcc..b7a8ab3d4f7 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 6ff9d2dd73b..5809ff8f803 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