Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/lib/ast/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,10 +293,10 @@ pub struct TraitAliasItem<'src> {

#[derive(Default, Debug)]
pub struct TraitItemModifiers<'src> {
pub impl_restriction: Option<Path<'src, NoGenericArgs>>,
pub const_: Const,
pub safety: Safety,
pub auto: Auto,
pub impl_restriction: Option<Path<'src, NoGenericArgs>>,
}

#[derive(Default, Debug)]
Expand Down
8 changes: 4 additions & 4 deletions src/lib/fmter/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -575,16 +575,16 @@ impl Fmt for (ast::TraitItem<'_>, Vec<ast::Attr<'_, ast::InnerAttrStyle>>) {

impl Fmt for TrailingSpace<ast::TraitItemModifiers<'_>> {
fn fmt(self, cx: &mut Cx<'_>) {
let Self(ast::TraitItemModifiers { const_, safety, auto, impl_restriction }) = self;
let Self(ast::TraitItemModifiers { impl_restriction, const_, safety, auto }) = self;

const_.trailing_space().fmt(cx);
safety.trailing_space().fmt(cx);
auto.trailing_space().fmt(cx);
if let Some(path) = impl_restriction {
fmt!(cx, "impl");
Restriction(path).fmt(cx);
fmt!(cx, " ");
}
const_.trailing_space().fmt(cx);
safety.trailing_space().fmt(cx);
auto.trailing_space().fmt(cx);
}
}

Expand Down
38 changes: 21 additions & 17 deletions src/lib/parser/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,14 @@ impl<'src> Parser<'_, '_, 'src> {
&mut [mut ref mut qualifiers @ .., Qualifier::Trait] => {
let mut modifiers = ast::TraitItemModifiers::default();

(modifiers.impl_restriction, qualifiers) = match qualifiers {
[Qualifier::ImplRestriction(path), qualifiers @ ..] => {
self.feature_no_span_fixme(Feature::impl_restriction);
let Ok(path) = path else { return Err(()) };
(Some(mem::replace(path, ast::Path { segs: Vec::new() })), qualifiers)
}
_ => (None, qualifiers),
};
(modifiers.const_, qualifiers) = Qualifier::strip_const(qualifiers);
if let ast::Const::Yes = modifiers.const_ {
self.feature_no_span_fixme(Feature::const_trait_impl);
Expand All @@ -244,14 +252,6 @@ impl<'src> Parser<'_, '_, 'src> {
}
_ => (ast::Auto::No, qualifiers),
};
(modifiers.impl_restriction, qualifiers) = match qualifiers {
[Qualifier::ImplRestriction(path), qualifiers @ ..] => {
self.feature_no_span_fixme(Feature::impl_restriction);
let Ok(path) = path else { return Err(()) };
(Some(mem::replace(path, ast::Path { segs: Vec::new() })), qualifiers)
}
_ => (None, qualifiers),
};
if !qualifiers.is_empty() {
self.error(Error::InvalidItemPrefix(start.until(self.token.span)));
}
Expand Down Expand Up @@ -352,7 +352,11 @@ impl<'src> Parser<'_, '_, 'src> {
TokenKind::Impl => {
self.advance();

if let Some(path) = self.parse_restriction(Some(TokenKind::Trait)) {
// We disqualify sequences like `impl(crate) {` which should be
// interpreted as impl blocks instead.
if let Some(path) =
self.parse_restriction(|kind| kind != TokenKind::OpenCurlyBracket)
{
yield (Qualifier::ImplRestriction(Box::new(path)), self.token.kind);
continue;
}
Expand Down Expand Up @@ -819,7 +823,11 @@ impl<'src> Parser<'_, '_, 'src> {

self.parse(TokenKind::Semicolon)?;

let ast::TraitItemModifiers { const_, safety, auto, impl_restriction } = modifiers;
let ast::TraitItemModifiers { impl_restriction, const_, safety, auto } = modifiers;

if impl_restriction.is_some() {
self.error(Error::ImplRestrictedTraitAlias);
}

match safety {
ast::Safety::Inherited => {}
Expand All @@ -831,10 +839,6 @@ impl<'src> Parser<'_, '_, 'src> {
ast::Auto::No => {}
}

if impl_restriction.is_some() {
self.error(Error::ImplRestrictedTraitAlias);
}

Ok(ast::ItemKind::TraitAlias(Box::new(ast::TraitAliasItem {
const_,
binder,
Expand Down Expand Up @@ -1103,7 +1107,7 @@ impl<'src> Parser<'_, '_, 'src> {
return Ok(ast::Visibility::Inherited);
}

if let Some(path) = self.parse_restriction(None) {
if let Some(path) = self.parse_restriction(|_| true) {
return Ok(ast::Visibility::Restricted(path?));
}

Expand All @@ -1118,7 +1122,7 @@ impl<'src> Parser<'_, '_, 'src> {

fn parse_restriction(
&mut self,
disambiguator: Option<TokenKind>,
may_follow: fn(TokenKind) -> bool,
) -> Option<Result<ast::Path<'src, ast::NoGenericArgs>>> {
enum Herald {
In,
Expand All @@ -1130,7 +1134,7 @@ impl<'src> Parser<'_, '_, 'src> {
&& let Some(herald) = match token.kind {
TokenKind::Crate | TokenKind::Super | TokenKind::SelfLower
if let TokenKind::CloseRoundBracket = self.peek(2).kind
&& disambiguator.is_none_or(|t| self.peek(3).kind == t) =>
&& may_follow(self.peek(3).kind) =>
{
Some(Herald::CrateSuperSelf(token.span))
}
Expand Down
14 changes: 10 additions & 4 deletions src/lib/parser/test/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,6 @@ async safe extern fn f() {}
async safe fn f() {}
async unsafe extern fn f() {}
async unsafe fn f() {}
auto impl(crate) trait Trait {}
auto impl(in crate) trait Trait {}
auto trait Trait {}
const F: () = ();
const async fn f() {}
Expand Down Expand Up @@ -210,8 +208,13 @@ gen extern fn f() {}
gen fn f() {}
gen unsafe fn f() {}
impl !Trait for () {}
impl (crate) {}
impl Trait for () {}
impl const Trait for () {}
impl(crate) auto trait Trait {}
impl(in crate) auto trait Trait {}
impl(self) trait Trait {}
impl(super) const trait Trait {}
pub const extern "C" fn f() {}
pub const fn f() {}
pub const unsafe extern "C" fn f() {}
Expand Down Expand Up @@ -274,8 +277,6 @@ async safe extern fn f() {}
async safe fn f() {}
async unsafe extern fn f() {}
async unsafe fn f() {}
auto impl(crate) trait Trait {}
auto impl(in crate) trait Trait {}
auto trait Trait {}
const F: () = ();
const async fn f() {}
Expand Down Expand Up @@ -317,8 +318,13 @@ gen extern fn f() {}
gen fn f() {}
gen unsafe fn f() {}
impl !Trait for () {}
impl (crate) {}
impl Trait for () {}
impl const Trait for () {}
impl(crate) auto trait Trait {}
impl(in crate) auto trait Trait {}
impl(self) trait Trait {}
impl(super) const trait Trait {}
pub const extern "C" fn f() {}
pub const fn f() {}
pub const unsafe extern "C" fn f() {}
Expand Down