about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-01-05 04:20:46 +0000
committerbors <bors@rust-lang.org>2015-01-05 04:20:46 +0000
commited22606c8382822efc555f72f895c560289a5c70 (patch)
tree9ed24b7cb51cc64e178d08f421c35d49f97cdb6f /src/libsyntax
parentad9e759382ad7daed26f86732f41f5f83cd673e2 (diff)
parentc062fac835e64c1ebf71da784714de562eac732c (diff)
downloadrust-ed22606c8382822efc555f72f895c560289a5c70.tar.gz
rust-ed22606c8382822efc555f72f895c560289a5c70.zip
auto merge of #20285 : FlaPer87/rust/oibit-send-and-friends, r=nikomatsakis
This commit introduces the syntax for negative implementations of traits
as shown below:

`impl !Trait for Type {}`

cc #13231
Part of RFC rust-lang/rfcs#127

r? @nikomatsakis 
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs19
-rw-r--r--src/libsyntax/ast_map/mod.rs2
-rw-r--r--src/libsyntax/config.rs4
-rw-r--r--src/libsyntax/ext/deriving/generic/mod.rs1
-rw-r--r--src/libsyntax/ext/expand.rs2
-rw-r--r--src/libsyntax/feature_gate.rs15
-rw-r--r--src/libsyntax/fold.rs5
-rw-r--r--src/libsyntax/parse/parser.rs17
-rw-r--r--src/libsyntax/print/pprust.rs8
-rw-r--r--src/libsyntax/visit.rs2
10 files changed, 66 insertions, 9 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index a33ee44be89..03b9eaf76b9 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1299,6 +1299,24 @@ impl fmt::Show for Unsafety {
     }
 }
 
+#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
+pub enum ImplPolarity {
+    /// impl Trait for Type
+    Positive,
+    /// impl !Trait for Type
+    Negative,
+}
+
+impl fmt::Show for ImplPolarity {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            ImplPolarity::Positive => "positive".fmt(f),
+            ImplPolarity::Negative => "negative".fmt(f),
+        }
+    }
+}
+
+
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
 pub enum FunctionRetTy {
     /// Functions with return type ! that always
@@ -1587,6 +1605,7 @@ pub enum Item_ {
               TyParamBounds,
               Vec<TraitItem>),
     ItemImpl(Unsafety,
+             ImplPolarity,
              Generics,
              Option<TraitRef>, // (optional) trait this impl implements
              P<Ty>, // self
diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs
index c5dbd194e3e..ce7b964959f 100644
--- a/src/libsyntax/ast_map/mod.rs
+++ b/src/libsyntax/ast_map/mod.rs
@@ -755,7 +755,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
         let parent = self.parent;
         self.parent = i.id;
         match i.node {
-            ItemImpl(_, _, _, _, ref impl_items) => {
+            ItemImpl(_, _, _, _, _, ref impl_items) => {
                 for impl_item in impl_items.iter() {
                     match *impl_item {
                         MethodImplItem(ref m) => {
diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs
index 94a3784291d..3f91831a5df 100644
--- a/src/libsyntax/config.rs
+++ b/src/libsyntax/config.rs
@@ -133,11 +133,11 @@ fn fold_item_underscore<F>(cx: &mut Context<F>, item: ast::Item_) -> ast::Item_
     F: FnMut(&[ast::Attribute]) -> bool
 {
     let item = match item {
-        ast::ItemImpl(u, a, b, c, impl_items) => {
+        ast::ItemImpl(u, o, a, b, c, impl_items) => {
             let impl_items = impl_items.into_iter()
                                        .filter(|ii| impl_item_in_cfg(cx, ii))
                                        .collect();
-            ast::ItemImpl(u, a, b, c, impl_items)
+            ast::ItemImpl(u, o, a, b, c, impl_items)
         }
         ast::ItemTrait(u, a, b, methods) => {
             let methods = methods.into_iter()
diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs
index 8863de8757b..459abf15b33 100644
--- a/src/libsyntax/ext/deriving/generic/mod.rs
+++ b/src/libsyntax/ext/deriving/generic/mod.rs
@@ -488,6 +488,7 @@ impl<'a> TraitDef<'a> {
             ident,
             a,
             ast::ItemImpl(ast::Unsafety::Normal,
+                          ast::ImplPolarity::Positive,
                           trait_generics,
                           opt_trait_ref,
                           self_type,
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index e65ecc19ea1..b3f30dd4581 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -1111,7 +1111,7 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
 
     fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
         let prev_type = self.current_impl_type.clone();
-        if let ast::Item_::ItemImpl(_, _, _, ref ty, _) = item.node {
+        if let ast::Item_::ItemImpl(_, _, _, _, ref ty, _) = item.node {
             self.current_impl_type = Some(ty.clone());
         }
 
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index f75873ac1c0..f8ac34cfe29 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -84,6 +84,9 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
     // A way to temporarily opt out of the new orphan rules. This will *never* be accepted.
     ("old_orphan_check", Deprecated),
 
+    // OIBIT specific features
+    ("optin_builtin_traits", Active),
+
     // These are used to test this portion of the compiler, they don't actually
     // mean anything
     ("test_accepted_feature", Accepted),
@@ -291,7 +294,17 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
                 }
             }
 
-            ast::ItemImpl(_, _, _, _, ref items) => {
+            ast::ItemImpl(_, polarity, _, _, _, ref items) => {
+                match polarity {
+                    ast::ImplPolarity::Negative => {
+                        self.gate_feature("optin_builtin_traits",
+                                          i.span,
+                                          "negative trait bounds are not yet fully implemented; \
+                                          use marker types for now");
+                    },
+                    _ => {}
+                }
+
                 if attr::contains_name(i.attrs[],
                                        "unsafe_destructor") {
                     self.gate_feature("unsafe_destructor",
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 3d3068f6868..35b2e5dbc53 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -1014,7 +1014,7 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
             let struct_def = folder.fold_struct_def(struct_def);
             ItemStruct(struct_def, folder.fold_generics(generics))
         }
-        ItemImpl(unsafety, generics, ifce, ty, impl_items) => {
+        ItemImpl(unsafety, polarity, generics, ifce, ty, impl_items) => {
             let mut new_impl_items = Vec::new();
             for impl_item in impl_items.iter() {
                 match *impl_item {
@@ -1037,6 +1037,7 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
                 }
             };
             ItemImpl(unsafety,
+                     polarity,
                      folder.fold_generics(generics),
                      ifce,
                      folder.fold_ty(ty),
@@ -1166,7 +1167,7 @@ pub fn noop_fold_item_simple<T: Folder>(Item {id, ident, attrs, node, vis, span}
     let node = folder.fold_item_underscore(node);
     let ident = match node {
         // The node may have changed, recompute the "pretty" impl name.
-        ItemImpl(_, _, ref maybe_trait, ref ty, _) => {
+        ItemImpl(_, _, _, ref maybe_trait, ref ty, _) => {
             ast_util::impl_pretty_name(maybe_trait, &**ty)
         }
         _ => ident
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 37ac86a3324..cc67079e538 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -4801,6 +4801,13 @@ impl<'a> Parser<'a> {
         // allow this to be parsed as a trait.
         let could_be_trait = self.token != token::OpenDelim(token::Paren);
 
+        let neg_span = self.span;
+        let polarity = if self.eat(&token::Not) {
+            ast::ImplPolarity::Negative
+        } else {
+            ast::ImplPolarity::Positive
+        };
+
         // Parse the trait.
         let mut ty = self.parse_ty_sum();
 
@@ -4823,6 +4830,14 @@ impl<'a> Parser<'a> {
             ty = self.parse_ty_sum();
             opt_trait_ref
         } else {
+            match polarity {
+                ast::ImplPolarity::Negative => {
+                    // This is a negated type implementation
+                    // `impl !MyType {}`, which is not allowed.
+                    self.span_err(neg_span, "inherent implementation can't be negated");
+                },
+                _ => {}
+            }
             None
         };
 
@@ -4832,7 +4847,7 @@ impl<'a> Parser<'a> {
         let ident = ast_util::impl_pretty_name(&opt_trait, &*ty);
 
         (ident,
-         ItemImpl(unsafety, generics, opt_trait, ty, impl_items),
+         ItemImpl(unsafety, polarity, generics, opt_trait, ty, impl_items),
          Some(attrs))
     }
 
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 9702c79719c..61b7aa408a8 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -917,6 +917,7 @@ impl<'a> State<'a> {
             }
 
             ast::ItemImpl(unsafety,
+                          polarity,
                           ref generics,
                           ref opt_trait,
                           ref ty,
@@ -931,6 +932,13 @@ impl<'a> State<'a> {
                     try!(space(&mut self.s));
                 }
 
+                match polarity {
+                    ast::ImplPolarity::Negative => {
+                        try!(word(&mut self.s, "!"));
+                    },
+                    _ => {}
+                }
+
                 match opt_trait {
                     &Some(ref t) => {
                         try!(self.print_trait_ref(t));
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index ec6b2cfa5c3..054a288a69e 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -297,7 +297,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             visitor.visit_generics(type_parameters);
             walk_enum_def(visitor, enum_definition, type_parameters)
         }
-        ItemImpl(_,
+        ItemImpl(_, _,
                  ref type_parameters,
                  ref trait_reference,
                  ref typ,