Better parser recovery for macro calls in type bound position

This commit is contained in:
Lukas Wirth 2025-06-05 16:11:30 +02:00
parent 634596e2d7
commit 5d3001795a
6 changed files with 134 additions and 10 deletions

View file

@ -201,6 +201,17 @@ fn type_bound(p: &mut Parser<'_>) -> bool {
}
if paths::is_use_path_start(p) {
types::path_type_bounds(p, false);
// test_err type_bounds_macro_call_recovery
// fn foo<T: T![], T: T!, T: T!{}>() -> Box<T! + T!{}> {}
if p.at(T![!]) {
let m = p.start();
p.bump(T![!]);
p.error("unexpected `!` in type path, macro calls are not allowed here");
if p.at_ts(TokenSet::new(&[T!['{'], T!['['], T!['(']])) {
items::token_tree(p);
}
m.complete(p, ERROR);
}
} else {
m.abandon(p);
return false;

View file

@ -98,7 +98,7 @@ fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) -> Option<Completed
types::type_(p);
if p.eat(T![as]) {
if is_use_path_start(p) {
types::path_type(p);
types::path_type_bounds(p, true);
} else {
p.error("expected a trait");
}

View file

@ -330,15 +330,6 @@ fn bare_dyn_trait_type(p: &mut Parser<'_>) {
m.complete(p, DYN_TRAIT_TYPE);
}
// test path_type
// type A = Foo;
// type B = ::Foo;
// type C = self::Foo;
// type D = super::Foo;
pub(super) fn path_type(p: &mut Parser<'_>) {
path_type_bounds(p, true);
}
// test macro_call_type
// type A = foo!();
// type B = crate::foo!();
@ -365,6 +356,11 @@ fn path_or_macro_type(p: &mut Parser<'_>, allow_bounds: bool) {
}
}
// test path_type
// type A = Foo;
// type B = ::Foo;
// type C = self::Foo;
// type D = super::Foo;
pub(super) fn path_type_bounds(p: &mut Parser<'_>, allow_bounds: bool) {
assert!(paths::is_path_start(p));
let m = p.start();