about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-07-10 17:49:50 -0400
committerMichael Goulet <michael@errs.io>2024-07-10 17:49:50 -0400
commit898ed2ffa6c485530af1fbe6117c0deb4290715f (patch)
tree4813396f722c85139d412395a3a9a9c05858de40
parent32c8bfdb11e519c6608ead730b6dfafc6cafb9c5 (diff)
downloadrust-898ed2ffa6c485530af1fbe6117c0deb4290715f.tar.gz
rust-898ed2ffa6c485530af1fbe6117c0deb4290715f.zip
Enforce that ? and for<...> are not combined
-rw-r--r--compiler/rustc_parse/messages.ftl3
-rw-r--r--compiler/rustc_parse/src/errors.rs10
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs13
-rw-r--r--tests/ui/parser/bounds-type.rs2
-rw-r--r--tests/ui/parser/bounds-type.stderr10
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-syntax.rs4
6 files changed, 38 insertions, 4 deletions
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 5fb59eeb4f3..5b4a5f4dd38 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -53,6 +53,9 @@ parse_bare_cr = {$double_quotes ->
 
 parse_bare_cr_in_raw_string = bare CR not allowed in raw string
 
+parse_binder_and_polarity = `for<...>` binder not allowed with `{$polarity}` trait polarity modifier
+    .label = there is not a well-defined meaning for a higher-ranked `{$polarity}` trait
+
 parse_binder_before_modifiers = `for<...>` binder should be placed before trait bound modifiers
     .label = place the `for<...>` binder before any modifiers
 
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 6738cc4a120..9b18a771fde 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -3050,3 +3050,13 @@ pub struct BinderBeforeModifiers {
     #[label]
     pub modifiers_span: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag(parse_binder_and_polarity)]
+pub struct BinderAndPolarity {
+    #[primary_span]
+    pub polarity_span: Span,
+    #[label]
+    pub binder_span: Span,
+    pub polarity: &'static str,
+}
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 306029ca94c..6de778fa9f2 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -994,6 +994,19 @@ impl<'a> Parser<'a> {
         let modifiers = self.parse_trait_bound_modifiers()?;
         let modifiers_span = modifiers_lo.to(self.prev_token.span);
 
+        if let Some(binder_span) = binder_span {
+            match modifiers.polarity {
+                BoundPolarity::Negative(polarity_span) | BoundPolarity::Maybe(polarity_span) => {
+                    self.dcx().emit_err(errors::BinderAndPolarity {
+                        binder_span,
+                        polarity_span,
+                        polarity: modifiers.polarity.as_str(),
+                    });
+                }
+                BoundPolarity::Positive => {}
+            }
+        }
+
         // Recover erroneous lifetime bound with modifiers or binder.
         // e.g. `T: for<'a> 'a` or `T: ~const 'a`.
         if self.token.is_lifetime() {
diff --git a/tests/ui/parser/bounds-type.rs b/tests/ui/parser/bounds-type.rs
index 2b2a44b7062..47fec7b1e77 100644
--- a/tests/ui/parser/bounds-type.rs
+++ b/tests/ui/parser/bounds-type.rs
@@ -5,7 +5,7 @@ struct S<
     T: Tr + 'a, // OK
     T: 'a, // OK
     T:, // OK
-    T: for<'a> ?Trait, // OK
+    T: for<'a> ?Trait, //~ ERROR `for<...>` binder not allowed with `?` trait polarity modifier
     T: Tr +, // OK
     T: ?'a, //~ ERROR `?` may only modify trait bounds, not lifetime bounds
 
diff --git a/tests/ui/parser/bounds-type.stderr b/tests/ui/parser/bounds-type.stderr
index d1210e88d66..fa8ab6812b1 100644
--- a/tests/ui/parser/bounds-type.stderr
+++ b/tests/ui/parser/bounds-type.stderr
@@ -1,3 +1,11 @@
+error: `for<...>` binder not allowed with `?` trait polarity modifier
+  --> $DIR/bounds-type.rs:8:16
+   |
+LL |     T: for<'a> ?Trait,
+   |           ---- ^
+   |           |
+   |           there is not a well-defined meaning for a higher-ranked `?` trait
+
 error: `?` may only modify trait bounds, not lifetime bounds
   --> $DIR/bounds-type.rs:10:8
    |
@@ -16,5 +24,5 @@ error: `const` may only modify trait bounds, not lifetime bounds
 LL |     T: const 'a,
    |        ^^^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-syntax.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-syntax.rs
index 4dd0e69598d..d65ecae3d06 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-syntax.rs
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-syntax.rs
@@ -4,6 +4,6 @@
 #![feature(const_trait_impl)]
 
 struct S<
-    T: for<'a> ~const ?Tr<'a> + 'static + ~const std::ops::Add,
-    T: for<'a: 'b> ~const ?m::Trait<'a>,
+    T: for<'a> ~const Tr<'a> + 'static + ~const std::ops::Add,
+    T: for<'a: 'b> ~const m::Trait<'a>,
 >;