mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-29 10:58:02 +00:00
parser: fix parsing of trait bound polarity and for-binders
The rustc AST allows both `for<>` binders and `?` polarity
modifiers in trait bounds, but they are parsed in a specific
order and validated for correctness:
1. `for<>` binder is parsed first.
2. Polarity modifiers (`?`, `!`) are parsed second.
3. The parser validates that binders and polarity modifiers
do not conflict:
```rust
if let Some(binder_span) = binder_span {
match modifiers.polarity {
BoundPolarity::Maybe(polarity_span) => {
// Error: "for<...> binder not allowed with ? polarity"
}
}
}
```
This implies:
- `for<> ?Sized` → Valid syntax. Invalid semantics.
- `?for<> Sized` → Invalid syntax.
However, rust-analyzer incorrectly had special-case logic that
allowed `?for<>` as valid syntax. This fix removes that incorrect
special case, making rust-analyzer reject `?for<> Sized` as a
syntax error, matching rustc behavior.
This has caused confusion in other crates (such as syn) which
rely on these files to implement correct syntax evaluation.
This commit is contained in:
parent
31db5b5be9
commit
943b42f743
6 changed files with 73 additions and 19 deletions
|
|
@ -182,12 +182,6 @@ fn type_bound(p: &mut Parser<'_>) -> bool {
|
|||
);
|
||||
m.complete(p, USE_BOUND_GENERIC_ARGS);
|
||||
}
|
||||
T![?] if p.nth_at(1, T![for]) => {
|
||||
// test question_for_type_trait_bound
|
||||
// fn f<T>() where T: ?for<> Sized {}
|
||||
p.bump_any();
|
||||
types::for_type(p, false)
|
||||
}
|
||||
_ => {
|
||||
if path_type_bound(p).is_err() {
|
||||
m.abandon(p);
|
||||
|
|
@ -219,8 +213,13 @@ fn path_type_bound(p: &mut Parser<'_>) -> Result<(), ()> {
|
|||
// test async_trait_bound
|
||||
// fn async_foo(_: impl async Fn(&i32)) {}
|
||||
p.eat(T![async]);
|
||||
// test question_for_type_trait_bound
|
||||
// fn f<T>() where T: for<> ?Sized {}
|
||||
p.eat(T![?]);
|
||||
|
||||
// test_err invalid_question_for_type_trait_bound
|
||||
// fn f<T>() where T: ?for<> Sized {}
|
||||
|
||||
if paths::is_use_path_start(p) {
|
||||
types::path_type_bounds(p, false);
|
||||
// test_err type_bounds_macro_call_recovery
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue