about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLeón Orell Valerian Liehr <me@fmease.dev>2024-02-20 04:41:01 +0100
committerLeón Orell Valerian Liehr <me@fmease.dev>2024-02-29 17:20:04 +0100
commitcce81289e6baea01c3cd67a6b85fffb3504d0a0b (patch)
tree2dcffc47b3689758e028be94f252589edb586e83
parent2b8060578a4a7dafc74f782850c86762ec05857a (diff)
Detect empty leading where-clauses on type aliases
-rw-r--r--compiler/rustc_ast_passes/messages.ftl3
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs63
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs30
-rw-r--r--compiler/rustc_lint/src/context/diagnostics.rs25
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs2
-rw-r--r--tests/ui/lazy-type-alias/leading-where-clause.fixed18
-rw-r--r--tests/ui/lazy-type-alias/leading-where-clause.rs21
-rw-r--r--tests/ui/lazy-type-alias/leading-where-clause.stderr41
-rw-r--r--tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.fixed6
-rw-r--r--tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.rs6
-rw-r--r--tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.stderr29
11 files changed, 177 insertions, 67 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 <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
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(",");
+        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<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),
             );
         }
 
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 <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,
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<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
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<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
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<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
 
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 <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