1
Fork 0

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
This commit is contained in:
bors 2015-01-05 04:20:46 +00:00
commit ed22606c83
35 changed files with 215 additions and 39 deletions

View file

@ -1762,7 +1762,7 @@ impl LintPass for Stability {
} }
} }
} }
ast::ItemImpl(_, _, Some(ref t), _, _) => { ast::ItemImpl(_, _, _, Some(ref t), _, _) => {
let id = ty::trait_ref_to_def_id(cx.tcx, t); let id = ty::trait_ref_to_def_id(cx.tcx, t);
self.lint(cx, id, t.path.span); self.lint(cx, id, t.path.span);
} }

View file

@ -259,3 +259,5 @@ pub const tag_unsafety: uint = 0xb1;
pub const tag_associated_type_names: uint = 0xb2; pub const tag_associated_type_names: uint = 0xb2;
pub const tag_associated_type_name: uint = 0xb3; pub const tag_associated_type_name: uint = 0xb3;
pub const tag_polarity: uint = 0xb4;

View file

@ -1207,7 +1207,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
None => {} None => {}
} }
} }
ast::ItemImpl(unsafety, _, ref opt_trait, ref ty, ref ast_items) => { ast::ItemImpl(unsafety, polarity, _, ref opt_trait, ref ty, ref ast_items) => {
// We need to encode information about the default methods we // We need to encode information about the default methods we
// have inherited, so we drive this based on the impl structure. // have inherited, so we drive this based on the impl structure.
let impl_items = tcx.impl_items.borrow(); let impl_items = tcx.impl_items.borrow();
@ -1221,6 +1221,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
encode_name(rbml_w, item.ident.name); encode_name(rbml_w, item.ident.name);
encode_attributes(rbml_w, item.attrs[]); encode_attributes(rbml_w, item.attrs[]);
encode_unsafety(rbml_w, unsafety); encode_unsafety(rbml_w, unsafety);
encode_polarity(rbml_w, polarity);
match ty.node { match ty.node {
ast::TyPath(ref path, _) if path.segments.len() == 1 => { ast::TyPath(ref path, _) if path.segments.len() == 1 => {
let ident = path.segments.last().unwrap().identifier; let ident = path.segments.last().unwrap().identifier;
@ -1704,6 +1705,14 @@ fn encode_associated_type_names(rbml_w: &mut Encoder, names: &[ast::Name]) {
rbml_w.end_tag(); rbml_w.end_tag();
} }
fn encode_polarity(rbml_w: &mut Encoder, polarity: ast::ImplPolarity) {
let byte: u8 = match polarity {
ast::ImplPolarity::Positive => 0,
ast::ImplPolarity::Negative => 1,
};
rbml_w.wr_tagged_u8(tag_polarity, byte);
}
fn encode_crate_deps(rbml_w: &mut Encoder, cstore: &cstore::CStore) { fn encode_crate_deps(rbml_w: &mut Encoder, cstore: &cstore::CStore) {
fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> { fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
// Pull the cnums and name,vers,hash out of cstore // Pull the cnums and name,vers,hash out of cstore
@ -1885,7 +1894,7 @@ struct ImplVisitor<'a, 'b:'a, 'c:'a, 'tcx:'b> {
impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> { impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> {
fn visit_item(&mut self, item: &ast::Item) { fn visit_item(&mut self, item: &ast::Item) {
if let ast::ItemImpl(_, _, Some(ref trait_ref), _, _) = item.node { if let ast::ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node {
let def_map = &self.ecx.tcx.def_map; let def_map = &self.ecx.tcx.def_map;
let trait_def = def_map.borrow()[trait_ref.ref_id].clone(); let trait_def = def_map.borrow()[trait_ref.ref_id].clone();
let def_id = trait_def.def_id(); let def_id = trait_def.def_id();

View file

@ -355,7 +355,7 @@ impl<'v> Visitor<'v> for LifeSeeder {
ast::ItemEnum(ref enum_def, _) if allow_dead_code => { ast::ItemEnum(ref enum_def, _) if allow_dead_code => {
self.worklist.extend(enum_def.variants.iter().map(|variant| variant.node.id)); self.worklist.extend(enum_def.variants.iter().map(|variant| variant.node.id));
} }
ast::ItemImpl(_, _, Some(ref _trait_ref), _, ref impl_items) => { ast::ItemImpl(_, _, _, Some(ref _trait_ref), _, ref impl_items) => {
for impl_item in impl_items.iter() { for impl_item in impl_items.iter() {
match *impl_item { match *impl_item {
ast::MethodImplItem(ref method) => { ast::MethodImplItem(ref method) => {

View file

@ -1712,7 +1712,7 @@ fn lifetimes_in_scope(tcx: &ty::ctxt,
match tcx.map.find(parent) { match tcx.map.find(parent) {
Some(node) => match node { Some(node) => match node {
ast_map::NodeItem(item) => match item.node { ast_map::NodeItem(item) => match item.node {
ast::ItemImpl(_, ref gen, _, _, _) => { ast::ItemImpl(_, _, ref gen, _, _, _) => {
taken.push_all(gen.lifetimes.as_slice()); taken.push_all(gen.lifetimes.as_slice());
} }
_ => () _ => ()

View file

@ -287,7 +287,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
// undefined symbols at linkage time if this case is not handled. // undefined symbols at linkage time if this case is not handled.
// //
// * Private trait impls for private types can be completely ignored // * Private trait impls for private types can be completely ignored
ast::ItemImpl(_, _, _, ref ty, ref impl_items) => { ast::ItemImpl(_, _, _, _, ref ty, ref impl_items) => {
let public_ty = match ty.node { let public_ty = match ty.node {
ast::TyPath(_, id) => { ast::TyPath(_, id) => {
match self.tcx.def_map.borrow()[id].clone() { match self.tcx.def_map.borrow()[id].clone() {
@ -657,7 +657,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
// invoked, and the struct/enum itself is private. Crawl // invoked, and the struct/enum itself is private. Crawl
// back up the chains to find the relevant struct/enum that // back up the chains to find the relevant struct/enum that
// was private. // was private.
ast::ItemImpl(_, _, _, ref ty, _) => { ast::ItemImpl(_, _, _, _, ref ty, _) => {
let id = match ty.node { let id = match ty.node {
ast::TyPath(_, id) => id, ast::TyPath(_, id) => id,
_ => return Some((err_span, err_msg, None)), _ => return Some((err_span, err_msg, None)),
@ -1137,7 +1137,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
match item.node { match item.node {
// implementations of traits don't need visibility qualifiers because // implementations of traits don't need visibility qualifiers because
// that's controlled by having the trait in scope. // that's controlled by having the trait in scope.
ast::ItemImpl(_, _, Some(..), _, ref impl_items) => { ast::ItemImpl(_, _, _, Some(..), _, ref impl_items) => {
check_inherited(item.span, item.vis, check_inherited(item.span, item.vis,
"visibility qualifiers have no effect on trait \ "visibility qualifiers have no effect on trait \
impls"); impls");
@ -1216,7 +1216,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
}; };
check_inherited(tcx, item.span, item.vis); check_inherited(tcx, item.span, item.vis);
match item.node { match item.node {
ast::ItemImpl(_, _, _, _, ref impl_items) => { ast::ItemImpl(_, _, _, _, _, ref impl_items) => {
for impl_item in impl_items.iter() { for impl_item in impl_items.iter() {
match *impl_item { match *impl_item {
ast::MethodImplItem(ref m) => { ast::MethodImplItem(ref m) => {
@ -1361,7 +1361,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
// (i.e. we could just return here to not check them at // (i.e. we could just return here to not check them at
// all, or some worse estimation of whether an impl is // all, or some worse estimation of whether an impl is
// publicly visible. // publicly visible.
ast::ItemImpl(_, ref g, ref trait_ref, ref self_, ref impl_items) => { ast::ItemImpl(_, _, ref g, ref trait_ref, ref self_, ref impl_items) => {
// `impl [... for] Private` is never visible. // `impl [... for] Private` is never visible.
let self_contains_private; let self_contains_private;
// impl [... for] Public<...>, but not `impl [... for] // impl [... for] Public<...>, but not `impl [... for]

View file

@ -55,7 +55,7 @@ fn item_might_be_inlined(item: &ast::Item) -> bool {
} }
match item.node { match item.node {
ast::ItemImpl(_, ref generics, _, _, _) | ast::ItemImpl(_, _, ref generics, _, _, _) |
ast::ItemFn(_, _, _, ref generics, _) => { ast::ItemFn(_, _, _, ref generics, _) => {
generics_require_inlining(generics) generics_require_inlining(generics)
} }
@ -216,7 +216,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
.map .map
.expect_item(impl_did.node) .expect_item(impl_did.node)
.node { .node {
ast::ItemImpl(_, ref generics, _, _, _) => { ast::ItemImpl(_, _, ref generics, _, _, _) => {
generics_require_inlining(generics) generics_require_inlining(generics)
} }
_ => false _ => false

View file

@ -106,7 +106,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
ast::ItemEnum(_, ref generics) | ast::ItemEnum(_, ref generics) |
ast::ItemStruct(_, ref generics) | ast::ItemStruct(_, ref generics) |
ast::ItemTrait(_, ref generics, _, _) | ast::ItemTrait(_, ref generics, _, _) |
ast::ItemImpl(_, ref generics, _, _, _) => { ast::ItemImpl(_, _, ref generics, _, _, _) => {
// These kinds of items have only early bound lifetime parameters. // These kinds of items have only early bound lifetime parameters.
let lifetimes = &generics.lifetimes; let lifetimes = &generics.lifetimes;
let early_scope = EarlyScope(subst::TypeSpace, lifetimes, &ROOT_SCOPE); let early_scope = EarlyScope(subst::TypeSpace, lifetimes, &ROOT_SCOPE);

View file

@ -82,7 +82,7 @@ impl<'v> Visitor<'v> for Annotator {
// stability of the trait. This is WRONG, but expedient to get // stability of the trait. This is WRONG, but expedient to get
// libstd stabilized for the 1.0 release. // libstd stabilized for the 1.0 release.
let use_parent = match i.node { let use_parent = match i.node {
ast::ItemImpl(_, _, Some(_), _, _) => false, ast::ItemImpl(_, _, _, Some(_), _, _) => false,
_ => true, _ => true,
}; };

View file

@ -5127,7 +5127,7 @@ pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
match cx.map.find(id.node) { match cx.map.find(id.node) {
Some(ast_map::NodeItem(item)) => { Some(ast_map::NodeItem(item)) => {
match item.node { match item.node {
ast::ItemImpl(_, _, ref opt_trait, _, _) => { ast::ItemImpl(_, _, _, ref opt_trait, _, _) => {
match opt_trait { match opt_trait {
&Some(ref t) => { &Some(ref t) => {
let trait_ref = ty::node_id_to_trait_ref(cx, t.ref_id); let trait_ref = ty::node_id_to_trait_ref(cx, t.ref_id);

View file

@ -386,7 +386,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
parent.clone() parent.clone()
} }
ItemImpl(_, _, None, ref ty, ref impl_items) => { ItemImpl(_, _, _, None, ref ty, ref impl_items) => {
// If this implements an anonymous trait, then add all the // If this implements an anonymous trait, then add all the
// methods within to a new module, if the type was defined // methods within to a new module, if the type was defined
// within this module. // within this module.
@ -527,7 +527,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
parent.clone() parent.clone()
} }
ItemImpl(_, _, Some(_), _, _) => parent.clone(), ItemImpl(_, _, _, Some(_), _, _) => parent.clone(),
ItemTrait(_, _, _, ref items) => { ItemTrait(_, _, _, ref items) => {
let name_bindings = let name_bindings =

View file

@ -972,7 +972,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
} }
} }
// Import resolution // Import resolution
// //
// This is a fixed-point algorithm. We resolve imports until our efforts // This is a fixed-point algorithm. We resolve imports until our efforts
@ -2837,7 +2836,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}); });
} }
ItemImpl(_, ItemImpl(_, _,
ref generics, ref generics,
ref implemented_traits, ref implemented_traits,
ref self_type, ref self_type,

View file

@ -283,7 +283,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
NodeItem(item) => { NodeItem(item) => {
scope_id = item.id; scope_id = item.id;
match item.node { match item.node {
ast::ItemImpl(_, _, _, ref ty, _) => { ast::ItemImpl(_, _, _, _, ref ty, _) => {
let mut result = String::from_str("<"); let mut result = String::from_str("<");
result.push_str(ty_to_string(&**ty)[]); result.push_str(ty_to_string(&**ty)[]);
@ -1040,7 +1040,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
self.process_const(item, &**typ, &**expr), self.process_const(item, &**typ, &**expr),
ast::ItemStruct(ref def, ref ty_params) => self.process_struct(item, &**def, ty_params), ast::ItemStruct(ref def, ref ty_params) => self.process_struct(item, &**def, ty_params),
ast::ItemEnum(ref def, ref ty_params) => self.process_enum(item, def, ty_params), ast::ItemEnum(ref def, ref ty_params) => self.process_enum(item, def, ty_params),
ast::ItemImpl(_, ast::ItemImpl(_, _,
ref ty_params, ref ty_params,
ref trait_ref, ref trait_ref,
ref typ, ref typ,

View file

@ -2317,7 +2317,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
let mut v = TransItemVisitor{ ccx: ccx }; let mut v = TransItemVisitor{ ccx: ccx };
v.visit_block(&**body); v.visit_block(&**body);
} }
ast::ItemImpl(_, ref generics, _, _, ref impl_items) => { ast::ItemImpl(_, _, ref generics, _, _, ref impl_items) => {
meth::trans_impl(ccx, meth::trans_impl(ccx,
item.ident, item.ident,
impl_items[], impl_items[],

View file

@ -699,7 +699,7 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id); let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id);
check_bare_fn(ccx, &**decl, &**body, it.id, fn_pty.ty, param_env); check_bare_fn(ccx, &**decl, &**body, it.id, fn_pty.ty, param_env);
} }
ast::ItemImpl(_, _, _, _, ref impl_items) => { ast::ItemImpl(_, _, _, _, _, ref impl_items) => {
debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id); debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id)); let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));

View file

@ -102,7 +102,7 @@ impl<'a, 'tcx, 'v> visit::Visitor<'v> for CoherenceCheckVisitor<'a, 'tcx> {
//debug!("(checking coherence) item '{}'", token::get_ident(item.ident)); //debug!("(checking coherence) item '{}'", token::get_ident(item.ident));
match item.node { match item.node {
ItemImpl(_, _, ref opt_trait, _, _) => { ItemImpl(_, _, _, ref opt_trait, _, _) => {
match opt_trait.clone() { match opt_trait.clone() {
Some(opt_trait) => { Some(opt_trait) => {
self.cc.check_implementation(item, &[opt_trait]); self.cc.check_implementation(item, &[opt_trait]);
@ -283,7 +283,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
// Converts an implementation in the AST to a vector of items. // Converts an implementation in the AST to a vector of items.
fn create_impl_from_item(&self, item: &Item) -> Vec<ImplOrTraitItemId> { fn create_impl_from_item(&self, item: &Item) -> Vec<ImplOrTraitItemId> {
match item.node { match item.node {
ItemImpl(_, _, ref trait_refs, _, ref ast_items) => { ItemImpl(_, _, _, ref trait_refs, _, ref ast_items) => {
let mut items: Vec<ImplOrTraitItemId> = let mut items: Vec<ImplOrTraitItemId> =
ast_items.iter() ast_items.iter()
.map(|ast_item| { .map(|ast_item| {

View file

@ -44,7 +44,7 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
fn visit_item(&mut self, item: &'v ast::Item) { fn visit_item(&mut self, item: &'v ast::Item) {
let def_id = ast_util::local_def(item.id); let def_id = ast_util::local_def(item.id);
match item.node { match item.node {
ast::ItemImpl(_, _, None, _, _) => { ast::ItemImpl(_, _, _, None, _, _) => {
// For inherent impls, self type must be a nominal type // For inherent impls, self type must be a nominal type
// defined in this crate. // defined in this crate.
debug!("coherence2::orphan check: inherent impl {}", item.repr(self.tcx)); debug!("coherence2::orphan check: inherent impl {}", item.repr(self.tcx));
@ -69,7 +69,7 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
} }
} }
} }
ast::ItemImpl(_, _, Some(_), _, _) => { ast::ItemImpl(_, _, _, Some(_), _, _) => {
// "Trait" impl // "Trait" impl
debug!("coherence2::orphan check: trait impl {}", item.repr(self.tcx)); debug!("coherence2::orphan check: trait impl {}", item.repr(self.tcx));
match traits::orphan_check(self.tcx, def_id) { match traits::orphan_check(self.tcx, def_id) {

View file

@ -30,7 +30,7 @@ struct UnsafetyChecker<'cx, 'tcx:'cx> {
impl<'cx, 'tcx,'v> visit::Visitor<'v> for UnsafetyChecker<'cx, 'tcx> { impl<'cx, 'tcx,'v> visit::Visitor<'v> for UnsafetyChecker<'cx, 'tcx> {
fn visit_item(&mut self, item: &'v ast::Item) { fn visit_item(&mut self, item: &'v ast::Item) {
match item.node { match item.node {
ast::ItemImpl(unsafety, _, _, _, _) => { ast::ItemImpl(unsafety, _, _, _, _, _) => {
match ty::impl_trait_ref(self.tcx, ast_util::local_def(item.id)) { match ty::impl_trait_ref(self.tcx, ast_util::local_def(item.id)) {
None => { None => {
// Inherent impl. // Inherent impl.

View file

@ -549,7 +549,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
enum_definition.variants.as_slice(), enum_definition.variants.as_slice(),
generics); generics);
}, },
ast::ItemImpl(_, ast::ItemImpl(_, _,
ref generics, ref generics,
ref opt_trait_ref, ref opt_trait_ref,
ref selfty, ref selfty,

View file

@ -182,6 +182,7 @@ pub struct Trait {
pub struct Impl { pub struct Impl {
pub unsafety: ast::Unsafety, pub unsafety: ast::Unsafety,
pub polarity: ast::ImplPolarity,
pub generics: ast::Generics, pub generics: ast::Generics,
pub trait_: Option<ast::TraitRef>, pub trait_: Option<ast::TraitRef>,
pub for_: P<ast::Ty>, pub for_: P<ast::Ty>,

View file

@ -337,9 +337,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
}; };
om.traits.push(t); om.traits.push(t);
}, },
ast::ItemImpl(unsafety, ref gen, ref tr, ref ty, ref items) => { ast::ItemImpl(unsafety, polarity, ref gen, ref tr, ref ty, ref items) => {
let i = Impl { let i = Impl {
unsafety: unsafety, unsafety: unsafety,
polarity: polarity,
generics: gen.clone(), generics: gen.clone(),
trait_: tr.clone(), trait_: tr.clone(),
for_: ty.clone(), for_: ty.clone(),

View file

@ -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)] #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
pub enum FunctionRetTy { pub enum FunctionRetTy {
/// Functions with return type ! that always /// Functions with return type ! that always
@ -1587,6 +1605,7 @@ pub enum Item_ {
TyParamBounds, TyParamBounds,
Vec<TraitItem>), Vec<TraitItem>),
ItemImpl(Unsafety, ItemImpl(Unsafety,
ImplPolarity,
Generics, Generics,
Option<TraitRef>, // (optional) trait this impl implements Option<TraitRef>, // (optional) trait this impl implements
P<Ty>, // self P<Ty>, // self

View file

@ -755,7 +755,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
let parent = self.parent; let parent = self.parent;
self.parent = i.id; self.parent = i.id;
match i.node { match i.node {
ItemImpl(_, _, _, _, ref impl_items) => { ItemImpl(_, _, _, _, _, ref impl_items) => {
for impl_item in impl_items.iter() { for impl_item in impl_items.iter() {
match *impl_item { match *impl_item {
MethodImplItem(ref m) => { MethodImplItem(ref m) => {

View file

@ -133,11 +133,11 @@ fn fold_item_underscore<F>(cx: &mut Context<F>, item: ast::Item_) -> ast::Item_
F: FnMut(&[ast::Attribute]) -> bool F: FnMut(&[ast::Attribute]) -> bool
{ {
let item = match item { 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() let impl_items = impl_items.into_iter()
.filter(|ii| impl_item_in_cfg(cx, ii)) .filter(|ii| impl_item_in_cfg(cx, ii))
.collect(); .collect();
ast::ItemImpl(u, a, b, c, impl_items) ast::ItemImpl(u, o, a, b, c, impl_items)
} }
ast::ItemTrait(u, a, b, methods) => { ast::ItemTrait(u, a, b, methods) => {
let methods = methods.into_iter() let methods = methods.into_iter()

View file

@ -488,6 +488,7 @@ impl<'a> TraitDef<'a> {
ident, ident,
a, a,
ast::ItemImpl(ast::Unsafety::Normal, ast::ItemImpl(ast::Unsafety::Normal,
ast::ImplPolarity::Positive,
trait_generics, trait_generics,
opt_trait_ref, opt_trait_ref,
self_type, self_type,

View file

@ -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>> { fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
let prev_type = self.current_impl_type.clone(); 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()); self.current_impl_type = Some(ty.clone());
} }

View file

@ -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. // A way to temporarily opt out of the new orphan rules. This will *never* be accepted.
("old_orphan_check", Deprecated), ("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 // These are used to test this portion of the compiler, they don't actually
// mean anything // mean anything
("test_accepted_feature", Accepted), ("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[], if attr::contains_name(i.attrs[],
"unsafe_destructor") { "unsafe_destructor") {
self.gate_feature("unsafe_destructor", self.gate_feature("unsafe_destructor",

View file

@ -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); let struct_def = folder.fold_struct_def(struct_def);
ItemStruct(struct_def, folder.fold_generics(generics)) 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(); let mut new_impl_items = Vec::new();
for impl_item in impl_items.iter() { for impl_item in impl_items.iter() {
match *impl_item { match *impl_item {
@ -1037,6 +1037,7 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
} }
}; };
ItemImpl(unsafety, ItemImpl(unsafety,
polarity,
folder.fold_generics(generics), folder.fold_generics(generics),
ifce, ifce,
folder.fold_ty(ty), 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 node = folder.fold_item_underscore(node);
let ident = match node { let ident = match node {
// The node may have changed, recompute the "pretty" impl name. // 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) ast_util::impl_pretty_name(maybe_trait, &**ty)
} }
_ => ident _ => ident

View file

@ -4801,6 +4801,13 @@ impl<'a> Parser<'a> {
// allow this to be parsed as a trait. // allow this to be parsed as a trait.
let could_be_trait = self.token != token::OpenDelim(token::Paren); 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. // Parse the trait.
let mut ty = self.parse_ty_sum(); let mut ty = self.parse_ty_sum();
@ -4823,6 +4830,14 @@ impl<'a> Parser<'a> {
ty = self.parse_ty_sum(); ty = self.parse_ty_sum();
opt_trait_ref opt_trait_ref
} else { } 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 None
}; };
@ -4832,7 +4847,7 @@ impl<'a> Parser<'a> {
let ident = ast_util::impl_pretty_name(&opt_trait, &*ty); let ident = ast_util::impl_pretty_name(&opt_trait, &*ty);
(ident, (ident,
ItemImpl(unsafety, generics, opt_trait, ty, impl_items), ItemImpl(unsafety, polarity, generics, opt_trait, ty, impl_items),
Some(attrs)) Some(attrs))
} }

View file

@ -917,6 +917,7 @@ impl<'a> State<'a> {
} }
ast::ItemImpl(unsafety, ast::ItemImpl(unsafety,
polarity,
ref generics, ref generics,
ref opt_trait, ref opt_trait,
ref ty, ref ty,
@ -931,6 +932,13 @@ impl<'a> State<'a> {
try!(space(&mut self.s)); try!(space(&mut self.s));
} }
match polarity {
ast::ImplPolarity::Negative => {
try!(word(&mut self.s, "!"));
},
_ => {}
}
match opt_trait { match opt_trait {
&Some(ref t) => { &Some(ref t) => {
try!(self.print_trait_ref(t)); try!(self.print_trait_ref(t));

View file

@ -297,7 +297,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
visitor.visit_generics(type_parameters); visitor.visit_generics(type_parameters);
walk_enum_def(visitor, enum_definition, type_parameters) walk_enum_def(visitor, enum_definition, type_parameters)
} }
ItemImpl(_, ItemImpl(_, _,
ref type_parameters, ref type_parameters,
ref trait_reference, ref trait_reference,
ref typ, ref typ,

View file

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}

View file

@ -0,0 +1,33 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// 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;
impl !TestType {}
//~^ ERROR inherent implementation can't be negated
trait TestTrait {}
unsafe impl !Send for TestType {}
impl !TestTrait for TestType {}
struct TestType2<T>;
impl<T> !TestType2<T> {}
//~^ ERROR inherent implementation can't be negated
unsafe impl<T> !Send for TestType2<T> {}
impl<T> !TestTrait for TestType2<T> {}
fn main() {}

View file

@ -0,0 +1,23 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(optin_builtin_traits)]
// pp-exact
trait UnsafeTrait {
fn foo(&self);
}
impl !UnsafeTrait for int {
fn foo(&self) { }
}
pub fn main() { }

View file

@ -0,0 +1,31 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// 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;
impl TestType {}
trait TestTrait {}
unsafe impl !Send for TestType {}
impl !TestTrait for TestType {}
struct TestType2<T>;
impl<T> TestType2<T> {}
unsafe impl<T> !Send for TestType2<T> {}
impl<T> !TestTrait for TestType2<T> {}
fn main() {}