Skip to content

Commit de88bc5

Browse files
And additionally enforce ? and async/const aren't mixed
1 parent 898ed2f commit de88bc5

File tree

10 files changed

+120
-44
lines changed

10 files changed

+120
-44
lines changed

compiler/rustc_ast_passes/messages.ftl

-2
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,6 @@ ast_passes_impl_trait_path = `impl Trait` is not allowed in path parameters
152152
ast_passes_incompatible_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed
153153
.help = remove one of these features
154154
155-
ast_passes_incompatible_trait_bound_modifiers = `{$left}` and `{$right}` are mutually exclusive
156-
157155
ast_passes_inherent_cannot_be = inherent impls cannot be {$annotation}
158156
.because = {$annotation} because of this
159157
.type = inherent impl for this type

compiler/rustc_ast_passes/src/ast_validation.rs

-11
Original file line numberDiff line numberDiff line change
@@ -1435,17 +1435,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
14351435
};
14361436
self.dcx().emit_err(errors::TildeConstDisallowed { span, reason });
14371437
}
1438-
(
1439-
_,
1440-
BoundConstness::Always(_) | BoundConstness::Maybe(_),
1441-
BoundPolarity::Negative(_) | BoundPolarity::Maybe(_),
1442-
) => {
1443-
self.dcx().emit_err(errors::IncompatibleTraitBoundModifiers {
1444-
span: bound.span(),
1445-
left: modifiers.constness.as_str(),
1446-
right: modifiers.polarity.as_str(),
1447-
});
1448-
}
14491438
_ => {}
14501439
}
14511440

compiler/rustc_ast_passes/src/errors.rs

-9
Original file line numberDiff line numberDiff line change
@@ -657,15 +657,6 @@ pub enum TildeConstReason {
657657
Item,
658658
}
659659

660-
#[derive(Diagnostic)]
661-
#[diag(ast_passes_incompatible_trait_bound_modifiers)]
662-
pub struct IncompatibleTraitBoundModifiers {
663-
#[primary_span]
664-
pub span: Span,
665-
pub left: &'static str,
666-
pub right: &'static str,
667-
}
668-
669660
#[derive(Diagnostic)]
670661
#[diag(ast_passes_const_and_async)]
671662
pub struct ConstAndAsync {

compiler/rustc_parse/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,9 @@ parse_missing_trait_in_trait_impl = missing trait in a trait impl
575575
parse_modifier_lifetime = `{$modifier}` may only modify trait bounds, not lifetime bounds
576576
.suggestion = remove the `{$modifier}`
577577
578+
parse_modifiers_and_polarity = `{$modifiers_concatenated}` trait not allowed with `{$polarity}` trait polarity modifier
579+
.label = there is not a well-defined meaning for a `{$modifiers_concatenated} {$polarity}` trait
580+
578581
parse_more_than_one_char = character literal may only contain one codepoint
579582
.followed_by = this `{$chr}` is followed by the combining {$len ->
580583
[one] mark

compiler/rustc_parse/src/errors.rs

+11
Original file line numberDiff line numberDiff line change
@@ -3060,3 +3060,14 @@ pub struct BinderAndPolarity {
30603060
pub binder_span: Span,
30613061
pub polarity: &'static str,
30623062
}
3063+
3064+
#[derive(Diagnostic)]
3065+
#[diag(parse_modifiers_and_polarity)]
3066+
pub struct PolarityAndModifiers {
3067+
#[primary_span]
3068+
pub polarity_span: Span,
3069+
#[label]
3070+
pub modifiers_span: Span,
3071+
pub polarity: &'static str,
3072+
pub modifiers_concatenated: String,
3073+
}

compiler/rustc_parse/src/parser/ty.rs

+29
Original file line numberDiff line numberDiff line change
@@ -930,6 +930,7 @@ impl<'a> Parser<'a> {
930930
/// TRAIT_BOUND_MODIFIERS = [["~"] "const"] ["async"] ["?" | "!"]
931931
/// ```
932932
fn parse_trait_bound_modifiers(&mut self) -> PResult<'a, TraitBoundModifiers> {
933+
let modifier_lo = self.token.span;
933934
let constness = if self.eat(&token::Tilde) {
934935
let tilde = self.prev_token.span;
935936
self.expect_keyword(kw::Const)?;
@@ -962,6 +963,7 @@ impl<'a> Parser<'a> {
962963
} else {
963964
BoundAsyncness::Normal
964965
};
966+
let modifier_hi = self.prev_token.span;
965967

966968
let polarity = if self.eat(&token::Question) {
967969
BoundPolarity::Maybe(self.prev_token.span)
@@ -972,6 +974,33 @@ impl<'a> Parser<'a> {
972974
BoundPolarity::Positive
973975
};
974976

977+
// Enforce the mutual-exclusivity of `const`/`async` and `?`/`!`.
978+
match polarity {
979+
BoundPolarity::Positive => {
980+
// All trait bound modifiers allowed to combine with positive polarity
981+
}
982+
BoundPolarity::Maybe(polarity_span) | BoundPolarity::Negative(polarity_span) => {
983+
match (asyncness, constness) {
984+
(BoundAsyncness::Normal, BoundConstness::Never) => {
985+
// Ok, no modifiers.
986+
}
987+
(_, _) => {
988+
let constness = constness.as_str();
989+
let asyncness = asyncness.as_str();
990+
let glue =
991+
if !constness.is_empty() && !asyncness.is_empty() { " " } else { "" };
992+
let modifiers_concatenated = format!("{constness}{glue}{asyncness}");
993+
self.dcx().emit_err(errors::PolarityAndModifiers {
994+
polarity_span,
995+
polarity: polarity.as_str(),
996+
modifiers_span: modifier_lo.to(modifier_hi),
997+
modifiers_concatenated,
998+
});
999+
}
1000+
}
1001+
}
1002+
}
1003+
9751004
Ok(TraitBoundModifiers { constness, asyncness, polarity })
9761005
}
9771006

tests/ui/parser/bounds-type.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//@ compile-flags: -Z parse-only
2+
//@ edition: 2021
23

34
struct S<
45
T: 'a + Tr, // OK
@@ -10,10 +11,20 @@ struct S<
1011
T: ?'a, //~ ERROR `?` may only modify trait bounds, not lifetime bounds
1112

1213
T: ~const Tr, // OK
13-
T: ~const ?Tr, // OK
14+
T: ~const ?Tr, //~ ERROR `~const` trait not allowed with `?` trait polarity modifier
1415
T: ~const Tr + 'a, // OK
1516
T: ~const 'a, //~ ERROR `~const` may only modify trait bounds, not lifetime bounds
1617
T: const 'a, //~ ERROR `const` may only modify trait bounds, not lifetime bounds
18+
19+
T: async Tr, // OK
20+
T: async ?Tr, //~ ERROR `async` trait not allowed with `?` trait polarity modifier
21+
T: async Tr + 'a, // OK
22+
T: async 'a, //~ ERROR `async` may only modify trait bounds, not lifetime bounds
23+
24+
T: const async Tr, // OK
25+
T: const async ?Tr, //~ ERROR `const async` trait not allowed with `?` trait polarity modifier
26+
T: const async Tr + 'a, // OK
27+
T: const async 'a, //~ ERROR `const` may only modify trait bounds, not lifetime bounds
1728
>;
1829

1930
fn main() {}

tests/ui/parser/bounds-type.stderr

+41-5
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,64 @@
11
error: `for<...>` binder not allowed with `?` trait polarity modifier
2-
--> $DIR/bounds-type.rs:8:16
2+
--> $DIR/bounds-type.rs:9:16
33
|
44
LL | T: for<'a> ?Trait,
55
| ---- ^
66
| |
77
| there is not a well-defined meaning for a higher-ranked `?` trait
88

99
error: `?` may only modify trait bounds, not lifetime bounds
10-
--> $DIR/bounds-type.rs:10:8
10+
--> $DIR/bounds-type.rs:11:8
1111
|
1212
LL | T: ?'a,
1313
| ^
1414

15+
error: `~const` trait not allowed with `?` trait polarity modifier
16+
--> $DIR/bounds-type.rs:14:15
17+
|
18+
LL | T: ~const ?Tr,
19+
| ------ ^
20+
| |
21+
| there is not a well-defined meaning for a `~const ?` trait
22+
1523
error: `~const` may only modify trait bounds, not lifetime bounds
16-
--> $DIR/bounds-type.rs:15:8
24+
--> $DIR/bounds-type.rs:16:8
1725
|
1826
LL | T: ~const 'a,
1927
| ^^^^^^
2028

2129
error: `const` may only modify trait bounds, not lifetime bounds
22-
--> $DIR/bounds-type.rs:16:8
30+
--> $DIR/bounds-type.rs:17:8
2331
|
2432
LL | T: const 'a,
2533
| ^^^^^
2634

27-
error: aborting due to 4 previous errors
35+
error: `async` trait not allowed with `?` trait polarity modifier
36+
--> $DIR/bounds-type.rs:20:14
37+
|
38+
LL | T: async ?Tr,
39+
| ----- ^
40+
| |
41+
| there is not a well-defined meaning for a `async ?` trait
42+
43+
error: `async` may only modify trait bounds, not lifetime bounds
44+
--> $DIR/bounds-type.rs:22:8
45+
|
46+
LL | T: async 'a,
47+
| ^^^^^
48+
49+
error: `const async` trait not allowed with `?` trait polarity modifier
50+
--> $DIR/bounds-type.rs:25:20
51+
|
52+
LL | T: const async ?Tr,
53+
| ----------- ^
54+
| |
55+
| there is not a well-defined meaning for a `const async ?` trait
56+
57+
error: `const` may only modify trait bounds, not lifetime bounds
58+
--> $DIR/bounds-type.rs:27:8
59+
|
60+
LL | T: const async 'a,
61+
| ^^^^^
62+
63+
error: aborting due to 9 previous errors
2864

tests/ui/rfcs/rfc-2632-const-trait-impl/mutually-exclusive-trait-bound-modifiers.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
#![feature(const_trait_impl)]
22

33
const fn maybe_const_maybe<T: ~const ?Sized>() {}
4-
//~^ ERROR `~const` and `?` are mutually exclusive
4+
//~^ ERROR `~const` trait not allowed with `?` trait polarity modifier
55

66
fn const_maybe<T: const ?Sized>() {}
7-
//~^ ERROR `const` and `?` are mutually exclusive
7+
//~^ ERROR `const` trait not allowed with `?` trait polarity modifier
88

99
const fn maybe_const_negative<T: ~const !Trait>() {}
10-
//~^ ERROR `~const` and `!` are mutually exclusive
10+
//~^ ERROR `~const` trait not allowed with `!` trait polarity modifier
1111
//~| ERROR negative bounds are not supported
1212

1313
fn const_negative<T: const !Trait>() {}
14-
//~^ ERROR `const` and `!` are mutually exclusive
14+
//~^ ERROR `const` trait not allowed with `!` trait polarity modifier
1515
//~| ERROR negative bounds are not supported
1616

1717
#[const_trait]

tests/ui/rfcs/rfc-2632-const-trait-impl/mutually-exclusive-trait-bound-modifiers.stderr

+20-12
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,34 @@
1-
error: `~const` and `?` are mutually exclusive
2-
--> $DIR/mutually-exclusive-trait-bound-modifiers.rs:3:31
1+
error: `~const` trait not allowed with `?` trait polarity modifier
2+
--> $DIR/mutually-exclusive-trait-bound-modifiers.rs:3:38
33
|
44
LL | const fn maybe_const_maybe<T: ~const ?Sized>() {}
5-
| ^^^^^^^^^^^^^
5+
| ------ ^
6+
| |
7+
| there is not a well-defined meaning for a `~const ?` trait
68

7-
error: `const` and `?` are mutually exclusive
8-
--> $DIR/mutually-exclusive-trait-bound-modifiers.rs:6:19
9+
error: `const` trait not allowed with `?` trait polarity modifier
10+
--> $DIR/mutually-exclusive-trait-bound-modifiers.rs:6:25
911
|
1012
LL | fn const_maybe<T: const ?Sized>() {}
11-
| ^^^^^^^^^^^^
13+
| ----- ^
14+
| |
15+
| there is not a well-defined meaning for a `const ?` trait
1216

13-
error: `~const` and `!` are mutually exclusive
14-
--> $DIR/mutually-exclusive-trait-bound-modifiers.rs:9:34
17+
error: `~const` trait not allowed with `!` trait polarity modifier
18+
--> $DIR/mutually-exclusive-trait-bound-modifiers.rs:9:41
1519
|
1620
LL | const fn maybe_const_negative<T: ~const !Trait>() {}
17-
| ^^^^^^^^^^^^^
21+
| ------ ^
22+
| |
23+
| there is not a well-defined meaning for a `~const !` trait
1824

19-
error: `const` and `!` are mutually exclusive
20-
--> $DIR/mutually-exclusive-trait-bound-modifiers.rs:13:22
25+
error: `const` trait not allowed with `!` trait polarity modifier
26+
--> $DIR/mutually-exclusive-trait-bound-modifiers.rs:13:28
2127
|
2228
LL | fn const_negative<T: const !Trait>() {}
23-
| ^^^^^^^^^^^^
29+
| ----- ^
30+
| |
31+
| there is not a well-defined meaning for a `const !` trait
2432

2533
error: negative bounds are not supported
2634
--> $DIR/mutually-exclusive-trait-bound-modifiers.rs:9:41

0 commit comments

Comments
 (0)