Skip to content

Commit 257ef4c

Browse files
committed
Less greedily parse [const] bounds
1 parent 2371802 commit 257ef4c

8 files changed

+117
-87
lines changed

compiler/rustc_parse/src/parser/ty.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -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();

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
//@ edition:2018
66

77
macro_rules! demo {
8-
($ty:ty) => { compile_error!("ty"); };
8+
($ty:ty) => { compile_error!("ty"); }; // KEEP THIS RULE FIRST!
99
//~^ ERROR ty
1010
//~| ERROR ty
11-
(impl $c:ident Trait) => {};
12-
(dyn $c:ident Trait) => {};
11+
(impl $c:ident Trait) => { /* KEEP THIS EMPTY! */ };
12+
(dyn $c:ident Trait) => { /* KEEP THIS EMPTY! */ };
1313
}
1414

1515
demo! { impl async Trait }

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

Lines changed: 2 additions & 2 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!
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!
1616
| ^^^^^^^^^^^^^^^^^^^^
1717
...
1818
LL | demo! { dyn async Trait }
Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,20 @@
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
109

1110
macro_rules! check {
12-
($Type:ty) => {
13-
compile_error!("ty");
14-
};
11+
($ty:ty) => { compile_error!("ty"); };
1512
(const $Trait:path) => {};
16-
([const] $Trait:path) => { [const] Trait };
13+
// We don't need to check `[const] Trait` here since that matches the `ty` fragment
14+
// already anyway since `[` may begin a slice or array type. However, it'll then
15+
// subsequently fail due to #146122 (section 3).
1716
}
1817

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

2420
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.

tests/ui/traits/const-traits/macro-const-trait-bound-theoretical-regression.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,22 @@
77
trait Trait {}
88

99
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
10+
($ty:ty) => { compile_error!("ty"); };
11+
//~^ ERROR ty
12+
//~| ERROR ty
13+
//~| ERROR ty
14+
//~| ERROR ty
15+
(impl $c:ident Trait) => {};
16+
(dyn $c:ident Trait) => {};
17+
18+
(impl [const] Trait) => {};
19+
(dyn [const] Trait) => {};
1520
}
1621

17-
demo! { impl const Trait }
18-
//~^ ERROR const trait impls are experimental
22+
demo! { impl const Trait } //~ ERROR const trait impls are experimental
23+
demo! { dyn const Trait } //~ ERROR const trait impls are experimental
1924

20-
demo! { dyn const Trait }
25+
demo! { impl [const] Trait } //~ ERROR const trait impls are experimental
26+
demo! { dyn [const] Trait } //~ ERROR const trait impls are experimental
2127

2228
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:10:19
33
|
4-
LL | (impl $c:ident Trait) => { impl $c Trait {} };
5-
| ^^^^^ inherent impl for this type
4+
LL | ($ty:ty) => { compile_error!("ty"); };
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:10:19
1814
|
19-
LL | (dyn $c:ident Trait) => { dyn $c Trait {} };
20-
| ^^^
15+
LL | ($ty:ty) => { compile_error!("ty"); };
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:10:19
25+
|
26+
LL | ($ty:ty) => { compile_error!("ty"); };
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:10:19
36+
|
37+
LL | ($ty:ty) => { compile_error!("ty"); };
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:22: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:23: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:25: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:26: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: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// FIXME(fmease): Explainer.
2+
3+
//@ check-pass (KEEP THIS AS A PASSING TEST!)
4+
5+
macro_rules! check {
6+
($ty:ty) => { compile_error!("ty"); }; // KEEP THIS RULE FIRST!
7+
(dyn [$($any:tt)*] Trait) => { /* KEEP THIS EMPTY! */ };
8+
(impl [$($any:tt)*] Trait) => { /* KEEP THIS EMPTY! */ };
9+
}
10+
11+
check!(dyn [T] Trait);
12+
13+
// issue: <https://github.com/rust-lang/rust/issues/146417>
14+
check!(impl [T] Trait);
15+
check!(impl [T: Bound] Trait);
16+
17+
fn main() {}

0 commit comments

Comments
 (0)