Skip to content

Commit

Permalink
Enforce that ? and for<...> are not combined
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Jul 10, 2024
1 parent 32c8bfd commit 898ed2f
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 4 deletions.
3 changes: 3 additions & 0 deletions compiler/rustc_parse/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_parse/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
13 changes: 13 additions & 0 deletions compiler/rustc_parse/src/parser/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/parser/bounds-type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
10 changes: 9 additions & 1 deletion tests/ui/parser/bounds-type.stderr
Original file line number Diff line number Diff line change
@@ -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
|
Expand All @@ -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

4 changes: 2 additions & 2 deletions tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
>;

0 comments on commit 898ed2f

Please sign in to comment.