Skip to content

Commit 67545c1

Browse files
authored
Unrolled build for #146422
Rollup merge of #146422 - fmease:less-greedy-maybe-const-bounds, r=estebank Less greedily parse `[const]` bounds > [!IMPORTANT] > If you're coming here from any beta backport nomination thread on Zulip, only the last commit is truly relevant (the first commit doesn't need to be backported, it only contains test modifications)! Don't consider `[` to start a bound, only consider `[const]` in its entirety to do so. This drastically reduces (but doesn't eliminate!) the chance of *real* breakages. Like `const`, `~const` and `async` before, `[const]` unavoidably brings along theoretical breakages, see preexisting tests: `macro-const-trait-bound-theoretical-regression.rs` and `macro-async-trait-bound-theoretical-regression.rs`. Side note: It's unfortunate that we have to do this but apart from the known fact that MBE hurts forward compatibility, the `[const]` syntax is simply a bit scuffed (also CC'ing #146122, section (3)). Fixes [after beta backport] #146417. * 1st commit: Restore the original test intentions of several preexisting related tests that were unfortunately lost over time * I've added a bunch of SCREAMING comments to make it less likely to be lost again * CC PR #119099 which added most of these tests * CC [#144409 (comment)](#144409 (comment)) for further context (NB: It's not the only PR that negatively affected the test intention) * 2nd commit: Actually address the regression r? `@oli-obk` or anyone
2 parents 5e33838 + f5dad62 commit 67545c1

9 files changed

+156
-105
lines changed

compiler/rustc_parse/src/parser/ty.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,10 @@ fn can_continue_type_after_non_fn_ident(t: &Token) -> bool {
9292
}
9393

9494
fn can_begin_dyn_bound_in_edition_2015(t: &Token) -> bool {
95-
// `Not`, `Tilde` & `Const` are deliberately not part of this list to
95+
// `!`, `const`, `[`, `async` are deliberately not part of this list to
9696
// contain the number of potential regressions esp. in MBE code.
97-
// `Const` would regress `rfc-2632-const-trait-impl/mbe-dyn-const-2015.rs`.
98-
// `Not` would regress `dyn!(...)` macro calls in Rust 2015.
97+
// `const` and `[` would regress UI test `macro-dyn-const-2015.rs`.
98+
// `!` would regress `dyn!(...)` macro calls in Rust 2015.
9999
t.is_path_start()
100100
|| t.is_lifetime()
101101
|| t == &TokenKind::Question
@@ -1015,12 +1015,18 @@ impl<'a> Parser<'a> {
10151015
|| self.check(exp!(Tilde))
10161016
|| self.check_keyword(exp!(For))
10171017
|| self.check(exp!(OpenParen))
1018-
|| self.check(exp!(OpenBracket))
1018+
|| self.can_begin_maybe_const_bound()
10191019
|| self.check_keyword(exp!(Const))
10201020
|| self.check_keyword(exp!(Async))
10211021
|| self.check_keyword(exp!(Use))
10221022
}
10231023

1024+
fn can_begin_maybe_const_bound(&mut self) -> bool {
1025+
self.check(exp!(OpenBracket))
1026+
&& self.look_ahead(1, |t| t.is_keyword(kw::Const))
1027+
&& self.look_ahead(2, |t| *t == token::CloseBracket)
1028+
}
1029+
10241030
/// Parse a bound.
10251031
///
10261032
/// ```ebnf
@@ -1199,10 +1205,7 @@ impl<'a> Parser<'a> {
11991205
let span = tilde.to(self.prev_token.span);
12001206
self.psess.gated_spans.gate(sym::const_trait_impl, span);
12011207
BoundConstness::Maybe(span)
1202-
} else if self.check(exp!(OpenBracket))
1203-
&& self.look_ahead(1, |t| t.is_keyword(kw::Const))
1204-
&& self.look_ahead(2, |t| *t == token::CloseBracket)
1205-
{
1208+
} else if self.can_begin_maybe_const_bound() {
12061209
let start = self.token.span;
12071210
self.bump();
12081211
self.expect_keyword(exp!(Const)).unwrap();
Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
// Demonstrates and records a theoretical regressions / breaking changes caused by the
22
// introduction of async trait bounds.
33

4-
// Setting the edition to 2018 since we don't regress `demo! { dyn async }` in Rust <2018.
4+
// Setting the edition to >2015 since we didn't regress `demo! { dyn async }` in Rust 2015.
55
//@ edition:2018
66

77
macro_rules! demo {
8-
($ty:ty) => { compile_error!("ty"); };
8+
($ty:ty) => { compile_error!("ty"); }; // KEEP THIS RULE FIRST AND AS IS!
99
//~^ ERROR ty
1010
//~| ERROR ty
11-
(impl $c:ident Trait) => {};
12-
(dyn $c:ident Trait) => {};
11+
12+
// DON'T MODIFY THE MATCHERS BELOW UNLESS THE ASYNC TRAIT MODIFIER SYNTAX CHANGES!
13+
14+
(impl $c:ident Trait) => { /* KEEP THIS EMPTY! */ };
15+
(dyn $c:ident Trait) => { /* KEEP THIS EMPTY! */ };
1316
}
1417

15-
demo! { impl async Trait }
16-
//~^ ERROR `async` trait bounds are unstable
18+
demo! { impl async Trait } //~ ERROR `async` trait bounds are unstable
1719

18-
demo! { dyn async Trait }
19-
//~^ ERROR `async` trait bounds are unstable
20+
demo! { dyn async Trait } //~ ERROR `async` trait bounds are unstable
2021

2122
fn main() {}

tests/ui/async-await/async-fn/macro-async-trait-bound-theoretical-regression.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
error: ty
22
--> $DIR/macro-async-trait-bound-theoretical-regression.rs:8:19
33
|
4-
LL | ($ty:ty) => { compile_error!("ty"); };
4+
LL | ($ty:ty) => { compile_error!("ty"); }; // KEEP THIS RULE FIRST AND AS IS!
55
| ^^^^^^^^^^^^^^^^^^^^
66
...
77
LL | demo! { impl async Trait }
@@ -12,7 +12,7 @@ LL | demo! { impl async Trait }
1212
error: ty
1313
--> $DIR/macro-async-trait-bound-theoretical-regression.rs:8:19
1414
|
15-
LL | ($ty:ty) => { compile_error!("ty"); };
15+
LL | ($ty:ty) => { compile_error!("ty"); }; // KEEP THIS RULE FIRST AND AS IS!
1616
| ^^^^^^^^^^^^^^^^^^^^
1717
...
1818
LL | demo! { dyn async Trait }
@@ -21,7 +21,7 @@ LL | demo! { dyn async Trait }
2121
= note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info)
2222

2323
error[E0658]: `async` trait bounds are unstable
24-
--> $DIR/macro-async-trait-bound-theoretical-regression.rs:15:14
24+
--> $DIR/macro-async-trait-bound-theoretical-regression.rs:18:14
2525
|
2626
LL | demo! { impl async Trait }
2727
| ^^^^^
@@ -32,7 +32,7 @@ LL | demo! { impl async Trait }
3232
= help: use the desugared name of the async trait, such as `AsyncFn`
3333

3434
error[E0658]: `async` trait bounds are unstable
35-
--> $DIR/macro-async-trait-bound-theoretical-regression.rs:18:13
35+
--> $DIR/macro-async-trait-bound-theoretical-regression.rs:20:13
3636
|
3737
LL | demo! { dyn async Trait }
3838
| ^^^^^
Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,23 @@
1-
// Ensure that we don't consider `const Trait` to
2-
// match the macro fragment specifier `ty` as that would be a breaking
3-
// change theoretically speaking. Syntactically trait object types can
4-
// be "bare", i.e., lack the prefix `dyn`.
5-
// By contrast, `?Trait` *does* match `ty` and therefore an arm like
6-
// `?$Trait:path` would never be reached.
7-
// See `parser/macro/mbe-bare-trait-object-maybe-trait-bound.rs`.
8-
// `[const] Trait` is already an error for a `ty` fragment,
9-
// so we do not need to prevent that.
1+
// Ensure that we don't consider `const Trait` to match the macro fragment specifier `ty`
2+
// as that would be a breaking change theoretically speaking.
3+
//
4+
// Syntactically trait object types can be "bare", i.e., lack the prefix `dyn`.
5+
// By contrast, `?Trait` *does* match `ty` and therefore an arm like `?$Trait:path`
6+
// would never be reached. See `parser/macro/macro-bare-trait-object-maybe-trait-bound.rs`.
7+
8+
//@ check-pass (KEEP THIS AS A PASSING TEST!)
109

1110
macro_rules! check {
12-
($Type:ty) => {
13-
compile_error!("ty");
14-
};
15-
(const $Trait:path) => {};
16-
([const] $Trait:path) => { [const] Trait };
11+
($ty:ty) => { compile_error!("ty"); }; // KEEP THIS RULE FIRST AND AS IS!
12+
13+
// DON'T MODIFY THE MATCHERS BELOW UNLESS THE CONST TRAIT MODIFIER SYNTAX CHANGES!
14+
15+
(const $Trait:path) => { /* KEEP THIS EMPTY! */ };
16+
// We don't need to check `[const] Trait` here since that matches the `ty` fragment
17+
// already anyway since `[` may begin a slice or array type. However, it'll then
18+
// subsequently fail due to #146122 (section 3).
1719
}
1820

1921
check! { const Trait }
20-
check! { [const] Trait }
21-
//~^ ERROR: expected identifier, found `]`
22-
//~| ERROR: const trait impls are experimental
2322

2423
fn main() {}

tests/ui/traits/const-traits/macro-bare-trait-objects-const-trait-bounds.stderr

Lines changed: 0 additions & 22 deletions
This file was deleted.
Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,32 @@
11
// Demonstrates and records a theoretical regressions / breaking changes caused by the
2-
// introduction of const trait bounds.
2+
// introduction of `const` and `[const]` trait bounds.
33

4-
// Setting the edition to 2018 since we don't regress `demo! { dyn const }` in Rust <2018.
4+
// Setting the edition to >2015 since we didn't regress `demo! { dyn const }` in Rust 2015.
5+
// See also test `traits/const-traits/macro-dyn-const-2015.rs`.
56
//@ edition:2018
67

78
trait Trait {}
89

910
macro_rules! demo {
10-
(impl $c:ident Trait) => { impl $c Trait {} };
11-
//~^ ERROR inherent
12-
//~| WARN trait objects without an explicit `dyn` are deprecated
13-
//~| WARN this is accepted in the current edition
14-
(dyn $c:ident Trait) => { dyn $c Trait {} }; //~ ERROR macro expansion
11+
($ty:ty) => { compile_error!("ty"); }; // KEEP THIS RULE FIRST AND AS IS!
12+
//~^ ERROR ty
13+
//~| ERROR ty
14+
//~| ERROR ty
15+
//~| ERROR ty
16+
17+
// DON'T MODIFY THE MATCHERS BELOW UNLESS THE CONST TRAIT MODIFIER SYNTAX CHANGES!
18+
19+
(impl $c:ident Trait) => { /* KEEP THIS EMPTY! */ };
20+
(dyn $c:ident Trait) => { /* KEEP THIS EMPTY! */ };
21+
22+
(impl [const] Trait) => { /* KEEP THIS EMPTY! */ };
23+
(dyn [const] Trait) => { /* KEEP THIS EMPTY! */ };
1524
}
1625

17-
demo! { impl const Trait }
18-
//~^ ERROR const trait impls are experimental
26+
demo! { impl const Trait } //~ ERROR const trait impls are experimental
27+
demo! { dyn const Trait } //~ ERROR const trait impls are experimental
1928

20-
demo! { dyn const Trait }
29+
demo! { impl [const] Trait } //~ ERROR const trait impls are experimental
30+
demo! { dyn [const] Trait } //~ ERROR const trait impls are experimental
2131

2232
fn main() {}
Lines changed: 61 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,49 @@
1-
error: inherent impls cannot be const
2-
--> $DIR/macro-const-trait-bound-theoretical-regression.rs:10:40
1+
error: ty
2+
--> $DIR/macro-const-trait-bound-theoretical-regression.rs:11:19
33
|
4-
LL | (impl $c:ident Trait) => { impl $c Trait {} };
5-
| ^^^^^ inherent impl for this type
4+
LL | ($ty:ty) => { compile_error!("ty"); }; // KEEP THIS RULE FIRST AND AS IS!
5+
| ^^^^^^^^^^^^^^^^^^^^
66
...
77
LL | demo! { impl const Trait }
8-
| --------------------------
9-
| | |
10-
| | const because of this
11-
| in this macro invocation
8+
| -------------------------- in this macro invocation
129
|
13-
= note: only trait implementations may be annotated with `const`
1410
= note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info)
1511

16-
error: macro expansion ignores keyword `dyn` and any tokens following
17-
--> $DIR/macro-const-trait-bound-theoretical-regression.rs:14:31
12+
error: ty
13+
--> $DIR/macro-const-trait-bound-theoretical-regression.rs:11:19
1814
|
19-
LL | (dyn $c:ident Trait) => { dyn $c Trait {} };
20-
| ^^^
15+
LL | ($ty:ty) => { compile_error!("ty"); }; // KEEP THIS RULE FIRST AND AS IS!
16+
| ^^^^^^^^^^^^^^^^^^^^
2117
...
2218
LL | demo! { dyn const Trait }
23-
| ------------------------- caused by the macro expansion here
19+
| ------------------------- in this macro invocation
2420
|
25-
= note: the usage of `demo!` is likely invalid in item context
21+
= note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info)
22+
23+
error: ty
24+
--> $DIR/macro-const-trait-bound-theoretical-regression.rs:11:19
25+
|
26+
LL | ($ty:ty) => { compile_error!("ty"); }; // KEEP THIS RULE FIRST AND AS IS!
27+
| ^^^^^^^^^^^^^^^^^^^^
28+
...
29+
LL | demo! { impl [const] Trait }
30+
| ---------------------------- in this macro invocation
31+
|
32+
= note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info)
33+
34+
error: ty
35+
--> $DIR/macro-const-trait-bound-theoretical-regression.rs:11:19
36+
|
37+
LL | ($ty:ty) => { compile_error!("ty"); }; // KEEP THIS RULE FIRST AND AS IS!
38+
| ^^^^^^^^^^^^^^^^^^^^
39+
...
40+
LL | demo! { dyn [const] Trait }
41+
| --------------------------- in this macro invocation
42+
|
43+
= note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info)
2644

2745
error[E0658]: const trait impls are experimental
28-
--> $DIR/macro-const-trait-bound-theoretical-regression.rs:17:14
46+
--> $DIR/macro-const-trait-bound-theoretical-regression.rs:26:14
2947
|
3048
LL | demo! { impl const Trait }
3149
| ^^^^^
@@ -34,24 +52,36 @@ LL | demo! { impl const Trait }
3452
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
3553
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
3654

37-
warning: trait objects without an explicit `dyn` are deprecated
38-
--> $DIR/macro-const-trait-bound-theoretical-regression.rs:10:40
55+
error[E0658]: const trait impls are experimental
56+
--> $DIR/macro-const-trait-bound-theoretical-regression.rs:27:13
3957
|
40-
LL | (impl $c:ident Trait) => { impl $c Trait {} };
41-
| ^^^^^
42-
...
43-
LL | demo! { impl const Trait }
44-
| -------------------------- in this macro invocation
58+
LL | demo! { dyn const Trait }
59+
| ^^^^^
4560
|
46-
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
47-
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2021/warnings-promoted-to-error.html>
48-
= note: `#[warn(bare_trait_objects)]` (part of `#[warn(rust_2021_compatibility)]`) on by default
49-
= note: this warning originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info)
50-
help: you might have intended to implement this trait for a given type
61+
= note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
62+
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
63+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
64+
65+
error[E0658]: const trait impls are experimental
66+
--> $DIR/macro-const-trait-bound-theoretical-regression.rs:29:14
67+
|
68+
LL | demo! { impl [const] Trait }
69+
| ^^^^^^^
70+
|
71+
= note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
72+
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
73+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
74+
75+
error[E0658]: const trait impls are experimental
76+
--> $DIR/macro-const-trait-bound-theoretical-regression.rs:30:13
5177
|
52-
LL | (impl $c:ident Trait) => { impl $c Trait for /* Type */ {} };
53-
| ++++++++++++++
78+
LL | demo! { dyn [const] Trait }
79+
| ^^^^^^^
80+
|
81+
= note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
82+
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
83+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
5484

55-
error: aborting due to 3 previous errors; 1 warning emitted
85+
error: aborting due to 8 previous errors
5686

5787
For more information about this error, try `rustc --explain E0658`.
Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
1-
// Ensure that the introduction of const trait bound didn't regress this code in Rust 2015.
2-
// See also `mbe-const-trait-bound-theoretical-regression.rs`.
1+
// Ensure that the introduction of `const` and `[const]` trait bounds didn't regress this
2+
// Rust 2015 code. See also test `macro-const-trait-bound-theoretical-regression.rs`.
33

44
//@ edition: 2015
5-
//@ check-pass
5+
//@ check-pass (KEEP THIS AS A PASSING TEST!)
66

77
macro_rules! check {
8-
($ty:ty) => { compile_error!("ty"); };
9-
(dyn $c:ident) => {};
8+
($ty:ty) => { compile_error!("ty"); }; // KEEP THIS RULE FIRST AND AS IS!
9+
10+
// DON'T MODIFY THE MATCHERS BELOW UNLESS THE CONST TRAIT MODIFIER SYNTAX CHANGES!
11+
12+
(dyn $c:ident) => { /* KEEP THIS EMPTY! */ };
13+
(dyn [$c:ident]) => { /* KEEP THIS EMPTY! */ };
1014
}
1115

1216
check! { dyn const }
17+
check! { dyn [const] }
1318

1419
fn main() {}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Ensure that we don't consider `[` to begin trait bounds to contain breakages.
2+
// Only `[const]` in its entirety begins a trait bound.
3+
// See also test `macro-const-trait-bound-theoretical-regression.rs`.
4+
5+
//@ check-pass (KEEP THIS AS A PASSING TEST!)
6+
// Setting the edition to >2015 since we didn't regress `check! { dyn [const] Trait }` in Rust 2015.
7+
// See also test `traits/const-traits/macro-dyn-const-2015.rs`.
8+
//@ edition:2018
9+
10+
macro_rules! check {
11+
($ty:ty) => { compile_error!("ty"); }; // KEEP THIS RULE FIRST AND AS IS!
12+
13+
// DON'T MODIFY THE MATCHERS BELOW UNLESS THE CONST TRAIT MODIFIER SYNTAX CHANGES!
14+
15+
(dyn [$($any:tt)*] Trait) => { /* KEEP THIS EMPTY! */ };
16+
(impl [$($any:tt)*] Trait) => { /* KEEP THIS EMPTY! */ };
17+
}
18+
19+
check!(dyn [T] Trait);
20+
21+
// issue: <https://github.com/rust-lang/rust/issues/146417>
22+
check!(impl [T] Trait);
23+
check!(impl [T: Bound] Trait);
24+
25+
fn main() {}

0 commit comments

Comments
 (0)