Parse negative impls
diff --git a/syntax/check.rs b/syntax/check.rs
index 15e19b8..2ebbf05 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -402,7 +402,15 @@
 }
 
 fn check_api_impl(cx: &mut Check, imp: &Impl) {
-    if let Type::UniquePtr(ty) | Type::CxxVector(ty) = &imp.ty {
+    let ty = &imp.ty;
+
+    if let Some(negative) = imp.negative_token {
+        let span = quote!(#negative #ty);
+        cx.error(span, "negative impl is not supported yet");
+        return;
+    }
+
+    if let Type::UniquePtr(ty) | Type::CxxVector(ty) = ty {
         if let Type::Ident(inner) = &ty.inner {
             if Atom::from(&inner.rust).is_none() {
                 return;
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 4de3c29..73cb1d9 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -342,9 +342,14 @@
     fn hash<H: Hasher>(&self, state: &mut H) {
         let Impl {
             impl_token: _,
+            negative,
             ty,
             brace_token: _,
+            negative_token: _,
         } = self;
+        if *negative {
+            negative.hash(state);
+        }
         ty.hash(state);
     }
 }
@@ -355,15 +360,19 @@
     fn eq(&self, other: &Impl) -> bool {
         let Impl {
             impl_token: _,
+            negative,
             ty,
             brace_token: _,
+            negative_token: _,
         } = self;
         let Impl {
             impl_token: _,
+            negative: negative2,
             ty: ty2,
             brace_token: _,
+            negative_token: _,
         } = other;
-        ty == ty2
+        negative == negative2 && ty == ty2
     }
 }
 
diff --git a/syntax/mod.rs b/syntax/mod.rs
index c688f55..e8bd290 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -120,8 +120,10 @@
 
 pub struct Impl {
     pub impl_token: Token![impl],
+    pub negative: bool,
     pub ty: Type,
     pub brace_token: Brace,
+    pub negative_token: Option<Token![!]>,
 }
 
 pub struct Signature {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index aa86a9f..a3f50ec 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -673,8 +673,8 @@
         return Err(Error::new_spanned(span, "expected an empty impl block"));
     }
 
-    let self_ty = &imp.self_ty;
     if let Some((bang, path, for_token)) = &imp.trait_ {
+        let self_ty = &imp.self_ty;
         let span = quote!(#bang #path #for_token #self_ty);
         return Err(Error::new_spanned(
             span,
@@ -690,10 +690,27 @@
         ));
     }
 
+    let mut negative_token = None;
+    let mut self_ty = *imp.self_ty;
+    if let RustType::Verbatim(ty) = &self_ty {
+        let mut iter = ty.clone().into_iter();
+        if let Some(TokenTree::Punct(punct)) = iter.next() {
+            if punct.as_char() == '!' {
+                let ty = iter.collect::<TokenStream>();
+                if !ty.is_empty() {
+                    negative_token = Some(Token![!](punct.span()));
+                    self_ty = syn::parse2(ty)?;
+                }
+            }
+        }
+    }
+
     Ok(Api::Impl(Impl {
         impl_token: imp.impl_token,
+        negative: negative_token.is_some(),
         ty: parse_type(&self_ty)?,
         brace_token: imp.brace_token,
+        negative_token,
     }))
 }
 
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 377fd4c..edbf818 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -148,6 +148,7 @@
 impl ToTokens for Impl {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         self.impl_token.to_tokens(tokens);
+        self.negative_token.to_tokens(tokens);
         self.ty.to_tokens(tokens);
         self.brace_token.surround(tokens, |_tokens| {});
     }