Skip to content

Commit 028d3d2

Browse files
committed
Parse negative impls
1 parent 76dfe62 commit 028d3d2

File tree

5 files changed

+40
-3
lines changed

5 files changed

+40
-3
lines changed

syntax/check.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,15 @@ fn check_api_type_alias(cx: &mut Check, alias: &TypeAlias) {
402402
}
403403

404404
fn check_api_impl(cx: &mut Check, imp: &Impl) {
405-
if let Type::UniquePtr(ty) | Type::CxxVector(ty) = &imp.ty {
405+
let ty = &imp.ty;
406+
407+
if let Some(negative) = imp.negative_token {
408+
let span = quote!(#negative #ty);
409+
cx.error(span, "negative impl is not supported yet");
410+
return;
411+
}
412+
413+
if let Type::UniquePtr(ty) | Type::CxxVector(ty) = ty {
406414
if let Type::Ident(inner) = &ty.inner {
407415
if Atom::from(&inner.rust).is_none() {
408416
return;

syntax/impls.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -342,9 +342,14 @@ impl Hash for Impl {
342342
fn hash<H: Hasher>(&self, state: &mut H) {
343343
let Impl {
344344
impl_token: _,
345+
negative,
345346
ty,
346347
brace_token: _,
348+
negative_token: _,
347349
} = self;
350+
if *negative {
351+
negative.hash(state);
352+
}
348353
ty.hash(state);
349354
}
350355
}
@@ -355,15 +360,19 @@ impl PartialEq for Impl {
355360
fn eq(&self, other: &Impl) -> bool {
356361
let Impl {
357362
impl_token: _,
363+
negative,
358364
ty,
359365
brace_token: _,
366+
negative_token: _,
360367
} = self;
361368
let Impl {
362369
impl_token: _,
370+
negative: negative2,
363371
ty: ty2,
364372
brace_token: _,
373+
negative_token: _,
365374
} = other;
366-
ty == ty2
375+
negative == negative2 && ty == ty2
367376
}
368377
}
369378

syntax/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,10 @@ pub struct TypeAlias {
120120

121121
pub struct Impl {
122122
pub impl_token: Token![impl],
123+
pub negative: bool,
123124
pub ty: Type,
124125
pub brace_token: Brace,
126+
pub negative_token: Option<Token![!]>,
125127
}
126128

127129
pub struct Signature {

syntax/parse.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -673,8 +673,8 @@ fn parse_impl(imp: ItemImpl) -> Result<Api> {
673673
return Err(Error::new_spanned(span, "expected an empty impl block"));
674674
}
675675

676-
let self_ty = &imp.self_ty;
677676
if let Some((bang, path, for_token)) = &imp.trait_ {
677+
let self_ty = &imp.self_ty;
678678
let span = quote!(#bang #path #for_token #self_ty);
679679
return Err(Error::new_spanned(
680680
span,
@@ -690,10 +690,27 @@ fn parse_impl(imp: ItemImpl) -> Result<Api> {
690690
));
691691
}
692692

693+
let mut negative_token = None;
694+
let mut self_ty = *imp.self_ty;
695+
if let RustType::Verbatim(ty) = &self_ty {
696+
let mut iter = ty.clone().into_iter();
697+
if let Some(TokenTree::Punct(punct)) = iter.next() {
698+
if punct.as_char() == '!' {
699+
let ty = iter.collect::<TokenStream>();
700+
if !ty.is_empty() {
701+
negative_token = Some(Token![!](punct.span()));
702+
self_ty = syn::parse2(ty)?;
703+
}
704+
}
705+
}
706+
}
707+
693708
Ok(Api::Impl(Impl {
694709
impl_token: imp.impl_token,
710+
negative: negative_token.is_some(),
695711
ty: parse_type(&self_ty)?,
696712
brace_token: imp.brace_token,
713+
negative_token,
697714
}))
698715
}
699716

syntax/tokens.rs

+1
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ impl ToTokens for ExternFn {
148148
impl ToTokens for Impl {
149149
fn to_tokens(&self, tokens: &mut TokenStream) {
150150
self.impl_token.to_tokens(tokens);
151+
self.negative_token.to_tokens(tokens);
151152
self.ty.to_tokens(tokens);
152153
self.brace_token.surround(tokens, |_tokens| {});
153154
}

0 commit comments

Comments
 (0)