From 8b883ab2681e34ef94575f45c6c0e6c2bca23ab7 Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Sun, 28 Dec 2014 23:33:18 +0100 Subject: Add syntax for negative implementations of traits This commit introduces the syntax for negative implmenetations of traits as shown below: `impl !Trait for Type {}` cc #13231 Part of RFC #3 --- src/libsyntax/ast.rs | 19 +++++++++++++++++++ src/libsyntax/ast_map/mod.rs | 2 +- src/libsyntax/config.rs | 4 ++-- src/libsyntax/ext/deriving/generic/mod.rs | 1 + src/libsyntax/ext/expand.rs | 2 +- src/libsyntax/feature_gate.rs | 2 +- src/libsyntax/fold.rs | 5 +++-- src/libsyntax/parse/parser.rs | 17 ++++++++++++++++- src/libsyntax/print/pprust.rs | 8 ++++++++ src/libsyntax/visit.rs | 2 +- 10 files changed, 53 insertions(+), 9 deletions(-) (limited to 'src/libsyntax') diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 01f66f3bbd0..c9c3ce45f20 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), ItemImpl(Unsafety, + ImplPolarity, Generics, Option, // (optional) trait this impl implements P, // 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(cx: &mut Context, 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) -> SmallVector> { 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..29f8ff9e812 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -291,7 +291,7 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { } } - ast::ItemImpl(_, _, _, _, ref items) => { + ast::ItemImpl(_, _, _, _, _, ref items) => { 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(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(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(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 c0444363d4e..b4223a989ba 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4802,6 +4802,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(); @@ -4824,6 +4831,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 }; @@ -4833,7 +4848,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, -- cgit 1.4.1-3-g733a5 From c062fac835e64c1ebf71da784714de562eac732c Mon Sep 17 00:00:00 2001 From: Flavio Percoco Date: Mon, 29 Dec 2014 13:52:43 +0100 Subject: Put negative trait implemtations behind a feature gate --- src/libsyntax/feature_gate.rs | 15 ++++++++++++++- .../syntax-trait-polarity-feature-gate.rs | 20 ++++++++++++++++++++ src/test/compile-fail/syntax-trait-polarity.rs | 2 ++ src/test/pretty/trait-polarity.rs | 2 ++ src/test/run-pass/syntax-trait-polarity.rs | 2 ++ 5 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 src/test/compile-fail/syntax-trait-polarity-feature-gate.rs (limited to 'src/libsyntax') diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 29f8ff9e812..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/test/compile-fail/syntax-trait-polarity-feature-gate.rs b/src/test/compile-fail/syntax-trait-polarity-feature-gate.rs new file mode 100644 index 00000000000..e6dc712137f --- /dev/null +++ b/src/test/compile-fail/syntax-trait-polarity-feature-gate.rs @@ -0,0 +1,20 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::kinds::Send; + +struct TestType; + +trait TestTrait {} + +unsafe impl !Send for TestType {} +//~^ ERROR negative trait bounds + +fn main() {} diff --git a/src/test/compile-fail/syntax-trait-polarity.rs b/src/test/compile-fail/syntax-trait-polarity.rs index dc01fbaefbd..3c84bc26298 100644 --- a/src/test/compile-fail/syntax-trait-polarity.rs +++ b/src/test/compile-fail/syntax-trait-polarity.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(optin_builtin_traits)] + use std::kinds::Send; struct TestType; diff --git a/src/test/pretty/trait-polarity.rs b/src/test/pretty/trait-polarity.rs index dbc4c263571..47c36ac7a40 100644 --- a/src/test/pretty/trait-polarity.rs +++ b/src/test/pretty/trait-polarity.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(optin_builtin_traits)] + // pp-exact trait UnsafeTrait { diff --git a/src/test/run-pass/syntax-trait-polarity.rs b/src/test/run-pass/syntax-trait-polarity.rs index 263fc4c0231..021cfedf06f 100644 --- a/src/test/run-pass/syntax-trait-polarity.rs +++ b/src/test/run-pass/syntax-trait-polarity.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(optin_builtin_traits)] + use std::kinds::Send; struct TestType; -- cgit 1.4.1-3-g733a5