From 369f7fa169d9f97ac8185105201182781076a90d Mon Sep 17 00:00:00 2001 From: Ben Blum <bblum@andrew.cmu.edu> Date: Wed, 14 Aug 2013 18:13:16 -0400 Subject: [PATCH 01/10] Prevent Send, Freeze, and Sized from being manually implemented. Close #8517. --- src/librustc/middle/lang_items.rs | 6 ++++++ src/librustc/middle/ty.rs | 6 ++++++ src/librustc/middle/typeck/collect.rs | 7 +++++++ .../cant-implement-builtin-kinds.rs | 19 +++++++++++++++++++ 4 files changed, 38 insertions(+) create mode 100644 src/test/compile-fail/cant-implement-builtin-kinds.rs diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 9b11301a9c4..8dd5ee20585 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -158,6 +158,12 @@ impl LanguageItems { } } + pub fn is_builtin_kind(&self, id: def_id) -> bool { + Some(id) == self.freeze_trait() || + Some(id) == self.send_trait() || + Some(id) == self.sized_trait() + } + pub fn freeze_trait(&self) -> Option<def_id> { self.items[FreezeTraitLangItem as uint] } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 685699f7819..56c3616d671 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -3725,6 +3725,12 @@ pub fn impl_trait_ref(cx: ctxt, id: ast::def_id) -> Option<@TraitRef> { return ret; } +pub fn trait_ref_is_builtin_kind(tcx: ctxt, tr: &ast::trait_ref) -> bool { + let def = tcx.def_map.find(&tr.ref_id).expect("no def-map entry for trait"); + let def_id = ast_util::def_id_of_def(*def); + tcx.lang_items.is_builtin_kind(def_id) +} + pub fn ty_to_def_id(ty: t) -> Option<ast::def_id> { match get(ty).sty { ty_trait(id, _, _, _, _) | ty_struct(id, _) | ty_enum(id, _) => Some(id), diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 7678a12b78a..2f6728891ff 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -869,6 +869,13 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::item) { &i_ty_generics, generics, parent_visibility); for t in opt_trait_ref.iter() { + // Prevent the builtin kind traits from being manually implemented. + if ty::trait_ref_is_builtin_kind(ccx.tcx, t) { + ccx.tcx.sess.span_err(it.span, + "cannot provide an explicit implementation \ + for a builtin kind"); + } + check_methods_against_trait(ccx, generics, rp, selfty, t, cms); } } diff --git a/src/test/compile-fail/cant-implement-builtin-kinds.rs b/src/test/compile-fail/cant-implement-builtin-kinds.rs new file mode 100644 index 00000000000..c35ca098372 --- /dev/null +++ b/src/test/compile-fail/cant-implement-builtin-kinds.rs @@ -0,0 +1,19 @@ +// Copyright 2013 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. + +// See issue #8517 for why this should be illegal. + +struct X<T>(T); + +impl <T> Send for X<T> { } //~ ERROR cannot provide an explicit implementation for a builtin kind +impl <T> Sized for X<T> { } //~ ERROR cannot provide an explicit implementation for a builtin kind +impl <T> Freeze for X<T> { } //~ ERROR cannot provide an explicit implementation for a builtin kind + +fn main() { } From 69322d941032202b7d5308dbe16e31b62c752cd2 Mon Sep 17 00:00:00 2001 From: Ben Blum <bblum@andrew.cmu.edu> Date: Fri, 16 Aug 2013 16:57:42 -0400 Subject: [PATCH 02/10] Allow traits to use builtin kinds as supertraits for #7083. --- src/librustc/metadata/decoder.rs | 20 +++++++- src/librustc/metadata/encoder.rs | 3 ++ src/librustc/middle/kind.rs | 74 +++++++++++++-------------- src/librustc/middle/lang_items.rs | 15 ++++-- src/librustc/middle/ty.rs | 20 ++++++-- src/librustc/middle/typeck/astconv.rs | 28 +--------- src/librustc/middle/typeck/collect.rs | 49 +++++++++++------- 7 files changed, 118 insertions(+), 91 deletions(-) diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 81a2e863bde..9eb09806bc0 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -375,9 +375,21 @@ pub fn get_trait_def(cdata: cmd, let tp_defs = item_ty_param_defs(item_doc, tcx, cdata, tag_items_data_item_ty_param_bounds); let rp = item_ty_region_param(item_doc); + let mut bounds = ty::EmptyBuiltinBounds(); + // Collect the builtin bounds from the encoded supertraits. + // FIXME(#8559): They should be encoded directly. + do reader::tagged_docs(item_doc, tag_item_super_trait_ref) |trait_doc| { + // NB. Bypasses real supertraits. See get_supertraits() if you wanted them. + let trait_ref = doc_trait_ref(trait_doc, tcx, cdata); + do tcx.lang_items.to_builtin_kind(trait_ref.def_id).map_move |bound| { + bounds.add(bound); + }; + true + }; ty::TraitDef { generics: ty::Generics {type_param_defs: tp_defs, region_param: rp}, + bounds: bounds, trait_ref: @item_trait_ref(item_doc, tcx, cdata) } } @@ -929,7 +941,13 @@ pub fn get_supertraits(cdata: cmd, id: ast::NodeId, tcx: ty::ctxt) let mut results = ~[]; let item_doc = lookup_item(id, cdata.data); do reader::tagged_docs(item_doc, tag_item_super_trait_ref) |trait_doc| { - results.push(@doc_trait_ref(trait_doc, tcx, cdata)); + // NB. Only reads the ones that *aren't* builtin-bounds. See also + // get_trait_def() for collecting the builtin bounds. + // FIXME(#8559): The builtin bounds shouldn't be encoded in the first place. + let trait_ref = doc_trait_ref(trait_doc, tcx, cdata); + if tcx.lang_items.to_builtin_kind(trait_ref.def_id).is_none() { + results.push(@trait_ref); + } true }; return results; diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 4a3704dc3aa..6a999a0c266 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1076,6 +1076,9 @@ fn encode_info_for_item(ecx: &EncodeContext, ebml_w.end_tag(); } encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident)); + // FIXME(#8559): This should use the tcx's supertrait cache instead of + // reading the AST's list, because the former has already filtered out + // the builtin-kinds-as-supertraits. See corresponding fixme in decoder. for ast_trait_ref in super_traits.iter() { let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id); encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_super_trait_ref); diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index 6d7d8112991..edea267d226 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -50,8 +50,6 @@ use syntax::visit::Visitor; // primitives in the stdlib are explicitly annotated to only take sendable // types. -pub static try_adding: &'static str = "Try adding a move"; - #[deriving(Clone)] pub struct Context { tcx: ty::ctxt, @@ -77,9 +75,6 @@ impl Visitor<Context> for KindAnalysisVisitor { fn visit_item(&mut self, i:@item, e:Context) { check_item(self, i, e); } - fn visit_block(&mut self, b:&Block, e:Context) { - check_block(self, b, e); - } } pub fn check_crate(tcx: ty::ctxt, @@ -125,46 +120,47 @@ fn check_struct_safe_for_destructor(cx: Context, } } -fn check_block(visitor: &mut KindAnalysisVisitor, - block: &Block, - cx: Context) { - visit::walk_block(visitor, block, cx); +fn check_impl_of_trait(cx: Context, it: @item, trait_ref: &trait_ref, self_type: &Ty) { + let ast_trait_def = cx.tcx.def_map.find(&trait_ref.ref_id) + .expect("trait ref not in def map!"); + let trait_def_id = ast_util::def_id_of_def(*ast_trait_def); + let trait_def = cx.tcx.trait_defs.find(&trait_def_id) + .expect("trait def not in trait-defs map!"); + + // If this trait has builtin-kind supertraits, meet them. + let self_ty: ty::t = ty::node_id_to_type(cx.tcx, it.id); + error!("checking impl with self type %?", ty::get(self_ty).sty); + do check_builtin_bounds(cx, self_ty, trait_def.bounds) |missing| { + cx.tcx.sess.span_err(self_type.span, + fmt!("the type `%s', which does not fulfill `%s`, cannot implement this \ + trait", ty_to_str(cx.tcx, self_ty), missing.user_string(cx.tcx))); + cx.tcx.sess.span_note(self_type.span, + fmt!("types implementing this trait must fulfill `%s`", + trait_def.bounds.user_string(cx.tcx))); + } + + // If this is a destructor, check kinds. + if cx.tcx.lang_items.drop_trait() == Some(trait_def_id) { + match self_type.node { + ty_path(_, ref bounds, path_node_id) => { + assert!(bounds.is_none()); + let struct_def = cx.tcx.def_map.get_copy(&path_node_id); + let struct_did = ast_util::def_id_of_def(struct_def); + check_struct_safe_for_destructor(cx, self_type.span, struct_did); + } + _ => { + cx.tcx.sess.span_bug(self_type.span, + "the self type for the Drop trait impl is not a path"); + } + } + } } fn check_item(visitor: &mut KindAnalysisVisitor, item: @item, cx: Context) { - // If this is a destructor, check kinds. if !attr::contains_name(item.attrs, "unsafe_destructor") { match item.node { item_impl(_, Some(ref trait_ref), ref self_type, _) => { - match cx.tcx.def_map.find(&trait_ref.ref_id) { - None => cx.tcx.sess.bug("trait ref not in def map!"), - Some(&trait_def) => { - let trait_def_id = ast_util::def_id_of_def(trait_def); - if cx.tcx.lang_items.drop_trait() == Some(trait_def_id) { - // Yes, it's a destructor. - match self_type.node { - ty_path(_, ref bounds, path_node_id) => { - assert!(bounds.is_none()); - let struct_def = cx.tcx.def_map.get_copy( - &path_node_id); - let struct_did = - ast_util::def_id_of_def(struct_def); - check_struct_safe_for_destructor( - cx, - self_type.span, - struct_did); - } - _ => { - cx.tcx.sess.span_bug(self_type.span, - "the self type for \ - the Drop trait \ - impl is not a \ - path"); - } - } - } - } - } + check_impl_of_trait(cx, item, trait_ref, self_type); } _ => {} } diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 8dd5ee20585..47e2937ca8a 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -23,6 +23,7 @@ use driver::session::Session; use metadata::csearch::each_lang_item; use metadata::cstore::iter_crate_data; +use middle::ty::{BuiltinBound, BoundFreeze, BoundSend, BoundSized}; use syntax::ast::{Crate, def_id, MetaItem}; use syntax::ast_util::local_def; use syntax::attr::AttrMetaMethods; @@ -158,10 +159,16 @@ impl LanguageItems { } } - pub fn is_builtin_kind(&self, id: def_id) -> bool { - Some(id) == self.freeze_trait() || - Some(id) == self.send_trait() || - Some(id) == self.sized_trait() + pub fn to_builtin_kind(&self, id: def_id) -> Option<BuiltinBound> { + if Some(id) == self.freeze_trait() { + Some(BoundFreeze) + } else if Some(id) == self.send_trait() { + Some(BoundSend) + } else if Some(id) == self.sized_trait() { + Some(BoundSized) + } else { + None + } } pub fn freeze_trait(&self) -> Option<def_id> { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 56c3616d671..757f05c208b 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -863,6 +863,7 @@ pub struct ty_param_bounds_and_ty { /// As `ty_param_bounds_and_ty` but for a trait ref. pub struct TraitDef { generics: Generics, + bounds: BuiltinBounds, trait_ref: @ty::TraitRef, } @@ -3725,10 +3726,23 @@ pub fn impl_trait_ref(cx: ctxt, id: ast::def_id) -> Option<@TraitRef> { return ret; } -pub fn trait_ref_is_builtin_kind(tcx: ctxt, tr: &ast::trait_ref) -> bool { +pub fn trait_ref_to_def_id(tcx: ctxt, tr: &ast::trait_ref) -> ast::def_id { let def = tcx.def_map.find(&tr.ref_id).expect("no def-map entry for trait"); - let def_id = ast_util::def_id_of_def(*def); - tcx.lang_items.is_builtin_kind(def_id) + ast_util::def_id_of_def(*def) +} + +pub fn try_add_builtin_trait(tcx: ctxt, + trait_def_id: ast::def_id, + builtin_bounds: &mut BuiltinBounds) -> bool { + //! Checks whether `trait_ref` refers to one of the builtin + //! traits, like `Send`, and adds the corresponding + //! bound to the set `builtin_bounds` if so. Returns true if `trait_ref` + //! is a builtin trait. + + match tcx.lang_items.to_builtin_kind(trait_def_id) { + Some(bound) => { builtin_bounds.add(bound); true } + None => false + } } pub fn ty_to_def_id(ty: t) -> Option<ast::def_id> { diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index c666e98c9c1..db76d75a5a5 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -773,9 +773,8 @@ fn conv_builtin_bounds(tcx: ty::ctxt, ast_bounds: &Option<OptVec<ast::TyParamBou ast::TraitTyParamBound(ref b) => { match lookup_def_tcx(tcx, b.path.span, b.ref_id) { ast::def_trait(trait_did) => { - if try_add_builtin_trait(tcx, - trait_did, - &mut builtin_bounds) { + if ty::try_add_builtin_trait(tcx, trait_did, + &mut builtin_bounds) { loop; // success } } @@ -807,26 +806,3 @@ fn conv_builtin_bounds(tcx: ty::ctxt, ast_bounds: &Option<OptVec<ast::TyParamBou (&None, ty::RegionTraitStore(*)) => ty::EmptyBuiltinBounds(), } } - -pub fn try_add_builtin_trait(tcx: ty::ctxt, - trait_def_id: ast::def_id, - builtin_bounds: &mut ty::BuiltinBounds) -> bool { - //! Checks whether `trait_ref` refers to one of the builtin - //! traits, like `Send`, and adds the corresponding - //! bound to the set `builtin_bounds` if so. Returns true if `trait_ref` - //! is a builtin trait. - - let li = &tcx.lang_items; - if Some(trait_def_id) == li.send_trait() { - builtin_bounds.add(ty::BoundSend); - true - } else if Some(trait_def_id) == li.freeze_trait() { - builtin_bounds.add(ty::BoundFreeze); - true - } else if Some(trait_def_id) == li.sized_trait() { - builtin_bounds.add(ty::BoundSized); - true - } else { - false - } -} diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 2f6728891ff..a22879654e8 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -398,28 +398,39 @@ pub fn ensure_supertraits(ccx: &CrateCtxt, sp: codemap::span, rp: Option<ty::region_variance>, ast_trait_refs: &[ast::trait_ref], - generics: &ast::Generics) + generics: &ast::Generics) -> ty::BuiltinBounds { let tcx = ccx.tcx; - if tcx.supertraits.contains_key(&local_def(id)) { return; } + + // Called only the first time trait_def_of_item is called. + // Supertraits are ensured at the same time. + assert!(!tcx.supertraits.contains_key(&local_def(id))); let self_ty = ty::mk_self(ccx.tcx, local_def(id)); let mut ty_trait_refs: ~[@ty::TraitRef] = ~[]; + let mut bounds = ty::EmptyBuiltinBounds(); for ast_trait_ref in ast_trait_refs.iter() { + let trait_def_id = ty::trait_ref_to_def_id(ccx.tcx, ast_trait_ref); + // FIXME(#8559): Need to instantiate the trait_ref whether or not it's a + // builtin trait, so that the trait's node id appears in the tcx trait_ref + // map. This is only needed for metadata; see the similar fixme in encoder.rs. let trait_ref = instantiate_trait_ref(ccx, ast_trait_ref, rp, generics, self_ty); + if !ty::try_add_builtin_trait(ccx.tcx, trait_def_id, &mut bounds) { - // FIXME(#5527) Could have same trait multiple times - if ty_trait_refs.iter().any(|other_trait| other_trait.def_id == trait_ref.def_id) { - // This means a trait inherited from the same supertrait more - // than once. - tcx.sess.span_err(sp, "Duplicate supertrait in trait declaration"); - break; - } else { - ty_trait_refs.push(trait_ref); + // FIXME(#5527) Could have same trait multiple times + if ty_trait_refs.iter().any(|other_trait| other_trait.def_id == trait_ref.def_id) { + // This means a trait inherited from the same supertrait more + // than once. + tcx.sess.span_err(sp, "Duplicate supertrait in trait declaration"); + break; + } else { + ty_trait_refs.push(trait_ref); + } } } tcx.supertraits.insert(local_def(id), @ty_trait_refs); + bounds } /** @@ -870,8 +881,9 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::item) { parent_visibility); for t in opt_trait_ref.iter() { // Prevent the builtin kind traits from being manually implemented. - if ty::trait_ref_is_builtin_kind(ccx.tcx, t) { - ccx.tcx.sess.span_err(it.span, + let trait_def_id = ty::trait_ref_to_def_id(tcx, t); + if tcx.lang_items.to_builtin_kind(trait_def_id).is_some() { + tcx.sess.span_err(it.span, "cannot provide an explicit implementation \ for a builtin kind"); } @@ -879,11 +891,9 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::item) { check_methods_against_trait(ccx, generics, rp, selfty, t, cms); } } - ast::item_trait(ref generics, ref supertraits, ref trait_methods) => { - let trait_def = trait_def_of_item(ccx, it); - tcx.trait_defs.insert(local_def(it.id), trait_def); + ast::item_trait(ref generics, _, ref trait_methods) => { + let _trait_def = trait_def_of_item(ccx, it); ensure_trait_methods(ccx, it.id); - ensure_supertraits(ccx, it.id, it.span, rp, *supertraits, generics); let (_, provided_methods) = split_trait_methods(*trait_methods); @@ -1039,13 +1049,16 @@ pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::item) -> @ty::TraitDef { } let rp = tcx.region_paramd_items.find(&it.id).map_move(|x| *x); match it.node { - ast::item_trait(ref generics, _, _) => { + ast::item_trait(ref generics, ref supertraits, _) => { let self_ty = ty::mk_self(tcx, def_id); let (ty_generics, substs) = mk_item_substs(ccx, generics, rp, Some(self_ty)); + let bounds = ensure_supertraits(ccx, it.id, it.span, rp, + *supertraits, generics); let trait_ref = @ty::TraitRef {def_id: def_id, substs: substs}; let trait_def = @ty::TraitDef {generics: ty_generics, + bounds: bounds, trait_ref: trait_ref}; tcx.trait_defs.insert(def_id, trait_def); return trait_def; @@ -1225,7 +1238,7 @@ pub fn ty_generics(ccx: &CrateCtxt, TraitTyParamBound(ref b) => { let ty = ty::mk_param(ccx.tcx, param_ty.idx, param_ty.def_id); let trait_ref = instantiate_trait_ref(ccx, b, rp, generics, ty); - if !astconv::try_add_builtin_trait( + if !ty::try_add_builtin_trait( ccx.tcx, trait_ref.def_id, &mut param_bounds.builtin_bounds) { From 4ca2e55adbf0cfbc34d8b1e7de773045d36cce2e Mon Sep 17 00:00:00 2001 From: Ben Blum <bblum@andrew.cmu.edu> Date: Fri, 16 Aug 2013 18:21:02 -0400 Subject: [PATCH 03/10] Add tests for #7083. --- .../auxiliary/trait_superkinds_in_metadata.rs | 14 ++++++++++++ .../builtin-superkinds-double-superkind.rs | 19 ++++++++++++++++ .../builtin-superkinds-in-metadata.rs | 22 +++++++++++++++++++ .../compile-fail/builtin-superkinds-simple.rs | 19 ++++++++++++++++ .../builtin-superkinds-typaram-not-send.rs | 15 +++++++++++++ .../builtin-superkinds-in-metadata.rs | 22 +++++++++++++++++++ .../builtin-superkinds-shadow-typaram.rs | 17 ++++++++++++++ .../run-pass/builtin-superkinds-simple.rs | 15 +++++++++++++ .../run-pass/builtin-superkinds-typaram.rs | 15 +++++++++++++ 9 files changed, 158 insertions(+) create mode 100644 src/test/auxiliary/trait_superkinds_in_metadata.rs create mode 100644 src/test/compile-fail/builtin-superkinds-double-superkind.rs create mode 100644 src/test/compile-fail/builtin-superkinds-in-metadata.rs create mode 100644 src/test/compile-fail/builtin-superkinds-simple.rs create mode 100644 src/test/compile-fail/builtin-superkinds-typaram-not-send.rs create mode 100644 src/test/run-pass/builtin-superkinds-in-metadata.rs create mode 100644 src/test/run-pass/builtin-superkinds-shadow-typaram.rs create mode 100644 src/test/run-pass/builtin-superkinds-simple.rs create mode 100644 src/test/run-pass/builtin-superkinds-typaram.rs diff --git a/src/test/auxiliary/trait_superkinds_in_metadata.rs b/src/test/auxiliary/trait_superkinds_in_metadata.rs new file mode 100644 index 00000000000..02d2a6b8af4 --- /dev/null +++ b/src/test/auxiliary/trait_superkinds_in_metadata.rs @@ -0,0 +1,14 @@ +// Copyright 2013 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. + +#[crate_type="lib"]; + +pub trait Bar : Freeze { } +pub trait Foo : Bar + Send { } diff --git a/src/test/compile-fail/builtin-superkinds-double-superkind.rs b/src/test/compile-fail/builtin-superkinds-double-superkind.rs new file mode 100644 index 00000000000..c5dbcd9bb23 --- /dev/null +++ b/src/test/compile-fail/builtin-superkinds-double-superkind.rs @@ -0,0 +1,19 @@ +// Copyright 2013 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. + +trait Foo : Send+Freeze { } + +impl <T: Freeze> Foo for (T,) { } //~ ERROR cannot implement this trait + +impl <T: Send> Foo for (T,T) { } //~ ERROR cannot implement this trait + +impl <T: Send+Freeze> Foo for (T,T,T) { } // (ok) + +fn main() { } diff --git a/src/test/compile-fail/builtin-superkinds-in-metadata.rs b/src/test/compile-fail/builtin-superkinds-in-metadata.rs new file mode 100644 index 00000000000..3fa7c5a28ba --- /dev/null +++ b/src/test/compile-fail/builtin-superkinds-in-metadata.rs @@ -0,0 +1,22 @@ +// Copyright 2013 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. + +// aux-build:trait_superkinds_in_metadata.rs + +extern mod trait_superkinds_in_metadata; +use trait_superkinds_in_metadata::{Foo, Bar}; + +struct X<T>(T); + +impl <T:Freeze> Bar for X<T> { } + +impl <T:Freeze> Foo for X<T> { } //~ ERROR cannot implement this trait + +fn main() { } diff --git a/src/test/compile-fail/builtin-superkinds-simple.rs b/src/test/compile-fail/builtin-superkinds-simple.rs new file mode 100644 index 00000000000..472bef715e9 --- /dev/null +++ b/src/test/compile-fail/builtin-superkinds-simple.rs @@ -0,0 +1,19 @@ +// Copyright 2013 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. + +trait Foo : Send { } + +impl <'self> Foo for &'self mut () { } //~ ERROR cannot implement this trait + +trait Bar : Freeze { } + +impl <'self> Bar for &'self mut () { } //~ ERROR cannot implement this trait + +fn main() { } diff --git a/src/test/compile-fail/builtin-superkinds-typaram-not-send.rs b/src/test/compile-fail/builtin-superkinds-typaram-not-send.rs new file mode 100644 index 00000000000..ec10ba09104 --- /dev/null +++ b/src/test/compile-fail/builtin-superkinds-typaram-not-send.rs @@ -0,0 +1,15 @@ +// Copyright 2013 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. + +trait Foo : Send { } + +impl <T: Freeze> Foo for T { } //~ ERROR cannot implement this trait + +fn main() { } diff --git a/src/test/run-pass/builtin-superkinds-in-metadata.rs b/src/test/run-pass/builtin-superkinds-in-metadata.rs new file mode 100644 index 00000000000..fc445058c04 --- /dev/null +++ b/src/test/run-pass/builtin-superkinds-in-metadata.rs @@ -0,0 +1,22 @@ +// Copyright 2013 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. + +// aux-build:trait_superkinds_in_metadata.rs + +extern mod trait_superkinds_in_metadata; +use trait_superkinds_in_metadata::{Foo, Bar}; + +struct X<T>(T); + +impl <T:Freeze> Bar for X<T> { } + +impl <T:Freeze+Send> Foo for X<T> { } + +fn main() { } diff --git a/src/test/run-pass/builtin-superkinds-shadow-typaram.rs b/src/test/run-pass/builtin-superkinds-shadow-typaram.rs new file mode 100644 index 00000000000..193efb06d39 --- /dev/null +++ b/src/test/run-pass/builtin-superkinds-shadow-typaram.rs @@ -0,0 +1,17 @@ +// Copyright 2013 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. + +trait Foo : Send { } + +struct X<T>(()); + +impl <T> Foo for X<T> { } + +fn main() { } diff --git a/src/test/run-pass/builtin-superkinds-simple.rs b/src/test/run-pass/builtin-superkinds-simple.rs new file mode 100644 index 00000000000..5ecac6a0f7a --- /dev/null +++ b/src/test/run-pass/builtin-superkinds-simple.rs @@ -0,0 +1,15 @@ +// Copyright 2013 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. + +trait Foo : Send { } + +impl Foo for int { } + +fn main() { } diff --git a/src/test/run-pass/builtin-superkinds-typaram.rs b/src/test/run-pass/builtin-superkinds-typaram.rs new file mode 100644 index 00000000000..eda04a780ee --- /dev/null +++ b/src/test/run-pass/builtin-superkinds-typaram.rs @@ -0,0 +1,15 @@ +// Copyright 2013 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. + +trait Foo : Send { } + +impl <T: Send> Foo for T { } + +fn main() { } From 3c3bfb4c3c5f89a6c4f48b7ad8b9f71de792be04 Mon Sep 17 00:00:00 2001 From: Ben Blum <bblum@andrew.cmu.edu> Date: Mon, 19 Aug 2013 16:50:23 -0400 Subject: [PATCH 04/10] Add more capabilities to typarams bounded by traits with super-builtin-kinds. Close #7083. --- src/librustc/middle/ty.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 757f05c208b..3672bfeec86 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -2322,7 +2322,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { let _i = indenter(); let mut tc = TC_ALL; - for bound in type_param_def.bounds.builtin_bounds.iter() { + do each_inherited_builtin_bound(cx, type_param_def.bounds) |bound| { debug!("tc = %s, bound = %?", tc.to_str(), bound); tc = tc - match bound { BoundStatic => TypeContents::nonstatic(cx), @@ -2335,6 +2335,23 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { debug!("result = %s", tc.to_str()); return tc; + + // Iterates over all builtin bounds on the type parameter def, including + // those inherited from traits with builtin-kind-supertraits. + fn each_inherited_builtin_bound(cx: ctxt, bounds: &ParamBounds, + f: &fn(BuiltinBound)) { + for bound in bounds.builtin_bounds.iter() { + f(bound); + } + + do each_bound_trait_and_supertraits(cx, bounds.trait_bounds) |trait_ref| { + let trait_def = lookup_trait_def(cx, trait_ref.def_id); + for bound in trait_def.bounds.iter() { + f(bound); + } + true + }; + } } } From 95089d37930267931c375fea5f10d0322fde771e Mon Sep 17 00:00:00 2001 From: Ben Blum <bblum@andrew.cmu.edu> Date: Mon, 19 Aug 2013 16:54:58 -0400 Subject: [PATCH 05/10] Add tests for super-builtin-kind capabilities (#7083) --- ...ltin-superkinds-capabilities-transitive.rs | 25 ++++++++++++++++ .../builtin-superkinds-capabilities-xc.rs | 30 +++++++++++++++++++ .../builtin-superkinds-capabilities.rs | 23 ++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 src/test/run-pass/builtin-superkinds-capabilities-transitive.rs create mode 100644 src/test/run-pass/builtin-superkinds-capabilities-xc.rs create mode 100644 src/test/run-pass/builtin-superkinds-capabilities.rs diff --git a/src/test/run-pass/builtin-superkinds-capabilities-transitive.rs b/src/test/run-pass/builtin-superkinds-capabilities-transitive.rs new file mode 100644 index 00000000000..8b9cd057457 --- /dev/null +++ b/src/test/run-pass/builtin-superkinds-capabilities-transitive.rs @@ -0,0 +1,25 @@ +// Copyright 2013 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. + +trait Bar : Send { } +trait Foo : Bar { } + +impl <T: Send> Foo for T { } +impl <T: Send> Bar for T { } + +fn foo<T: Foo>(val: T, chan: std::comm::Chan<T>) { + chan.send(val); +} + +fn main() { + let (p,c) = std::comm::stream(); + foo(31337, c); + assert!(p.recv() == 31337); +} diff --git a/src/test/run-pass/builtin-superkinds-capabilities-xc.rs b/src/test/run-pass/builtin-superkinds-capabilities-xc.rs new file mode 100644 index 00000000000..85012896253 --- /dev/null +++ b/src/test/run-pass/builtin-superkinds-capabilities-xc.rs @@ -0,0 +1,30 @@ +// Copyright 2013 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. + +// aux-build:trait_superkinds_in_metadata.rs + +extern mod trait_superkinds_in_metadata; +use trait_superkinds_in_metadata::{Foo, Bar}; + +#[deriving(Eq)] +struct X<T>(T); + +impl <T: Freeze> Bar for X<T> { } +impl <T: Freeze+Send> Foo for X<T> { } + +fn foo<T: Foo>(val: T, chan: std::comm::Chan<T>) { + chan.send(val); +} + +fn main() { + let (p,c) = std::comm::stream(); + foo(X(31337), c); + assert!(p.recv() == X(31337)); +} diff --git a/src/test/run-pass/builtin-superkinds-capabilities.rs b/src/test/run-pass/builtin-superkinds-capabilities.rs new file mode 100644 index 00000000000..639c78bd657 --- /dev/null +++ b/src/test/run-pass/builtin-superkinds-capabilities.rs @@ -0,0 +1,23 @@ +// Copyright 2013 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. + +trait Foo : Send { } + +impl <T: Send> Foo for T { } + +fn foo<T: Foo>(val: T, chan: std::comm::Chan<T>) { + chan.send(val); +} + +fn main() { + let (p,c) = std::comm::stream(); + foo(31337, c); + assert!(p.recv() == 31337); +} From 4fd404f2ca1b3a246872521a606d749ae5a11258 Mon Sep 17 00:00:00 2001 From: Ben Blum <bblum@andrew.cmu.edu> Date: Mon, 19 Aug 2013 17:15:25 -0400 Subject: [PATCH 06/10] Fixup style of test cases for #7083 --- src/test/auxiliary/trait_superkinds_in_metadata.rs | 7 +++++-- .../builtin-superkinds-double-superkind.rs | 3 +++ .../compile-fail/builtin-superkinds-in-metadata.rs | 9 ++++++--- src/test/compile-fail/builtin-superkinds-simple.rs | 3 +++ .../builtin-superkinds-typaram-not-send.rs | 2 ++ .../builtin-superkinds-capabilities-transitive.rs | 6 ++++++ .../run-pass/builtin-superkinds-capabilities-xc.rs | 11 +++++++---- src/test/run-pass/builtin-superkinds-capabilities.rs | 4 ++++ src/test/run-pass/builtin-superkinds-in-metadata.rs | 8 +++++--- ...param.rs => builtin-superkinds-phantom-typaram.rs} | 4 ++++ src/test/run-pass/builtin-superkinds-simple.rs | 2 ++ src/test/run-pass/builtin-superkinds-typaram.rs | 3 +++ 12 files changed, 50 insertions(+), 12 deletions(-) rename src/test/run-pass/{builtin-superkinds-shadow-typaram.rs => builtin-superkinds-phantom-typaram.rs} (74%) diff --git a/src/test/auxiliary/trait_superkinds_in_metadata.rs b/src/test/auxiliary/trait_superkinds_in_metadata.rs index 02d2a6b8af4..dfb0c0310ec 100644 --- a/src/test/auxiliary/trait_superkinds_in_metadata.rs +++ b/src/test/auxiliary/trait_superkinds_in_metadata.rs @@ -8,7 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Test library crate for cross-crate usages of traits inheriting +// from the builtin kinds. Mostly tests metadata correctness. + #[crate_type="lib"]; -pub trait Bar : Freeze { } -pub trait Foo : Bar + Send { } +pub trait RequiresFreeze : Freeze { } +pub trait RequiresRequiresFreezeAndSend : RequiresFreeze + Send { } diff --git a/src/test/compile-fail/builtin-superkinds-double-superkind.rs b/src/test/compile-fail/builtin-superkinds-double-superkind.rs index c5dbcd9bb23..15fa0b66433 100644 --- a/src/test/compile-fail/builtin-superkinds-double-superkind.rs +++ b/src/test/compile-fail/builtin-superkinds-double-superkind.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Test for traits that inherit from multiple builtin kinds at once, +// testing that all such kinds must be present on implementing types. + trait Foo : Send+Freeze { } impl <T: Freeze> Foo for (T,) { } //~ ERROR cannot implement this trait diff --git a/src/test/compile-fail/builtin-superkinds-in-metadata.rs b/src/test/compile-fail/builtin-superkinds-in-metadata.rs index 3fa7c5a28ba..a52a3765889 100644 --- a/src/test/compile-fail/builtin-superkinds-in-metadata.rs +++ b/src/test/compile-fail/builtin-superkinds-in-metadata.rs @@ -10,13 +10,16 @@ // aux-build:trait_superkinds_in_metadata.rs +// Test for traits inheriting from the builtin kinds cross-crate. +// Mostly tests correctness of metadata. + extern mod trait_superkinds_in_metadata; -use trait_superkinds_in_metadata::{Foo, Bar}; +use trait_superkinds_in_metadata::{RequiresRequiresFreezeAndSend, RequiresFreeze}; struct X<T>(T); -impl <T:Freeze> Bar for X<T> { } +impl <T:Freeze> RequiresFreeze for X<T> { } -impl <T:Freeze> Foo for X<T> { } //~ ERROR cannot implement this trait +impl <T:Freeze> RequiresRequiresFreezeAndSend for X<T> { } //~ ERROR cannot implement this trait fn main() { } diff --git a/src/test/compile-fail/builtin-superkinds-simple.rs b/src/test/compile-fail/builtin-superkinds-simple.rs index 472bef715e9..c1011f1368a 100644 --- a/src/test/compile-fail/builtin-superkinds-simple.rs +++ b/src/test/compile-fail/builtin-superkinds-simple.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Basic test for traits inheriting from the builtin kinds, checking +// the type contents of the implementing type (that's not a typaram). + trait Foo : Send { } impl <'self> Foo for &'self mut () { } //~ ERROR cannot implement this trait diff --git a/src/test/compile-fail/builtin-superkinds-typaram-not-send.rs b/src/test/compile-fail/builtin-superkinds-typaram-not-send.rs index ec10ba09104..2a3d3c7df61 100644 --- a/src/test/compile-fail/builtin-superkinds-typaram-not-send.rs +++ b/src/test/compile-fail/builtin-superkinds-typaram-not-send.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Basic test for traits inheriting from the builtin kinds. + trait Foo : Send { } impl <T: Freeze> Foo for T { } //~ ERROR cannot implement this trait diff --git a/src/test/run-pass/builtin-superkinds-capabilities-transitive.rs b/src/test/run-pass/builtin-superkinds-capabilities-transitive.rs index 8b9cd057457..ab5e58285d4 100644 --- a/src/test/run-pass/builtin-superkinds-capabilities-transitive.rs +++ b/src/test/run-pass/builtin-superkinds-capabilities-transitive.rs @@ -8,6 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Tests "transitivity" of super-builtin-kinds on traits. Here, if +// we have a Foo, we know we have a Bar, and if we have a Bar, we +// know we have a Send. So if we have a Foo we should know we have +// a Send. Basically this just makes sure rustc is using +// each_bound_trait_and_supertraits in type_contents correctly. + trait Bar : Send { } trait Foo : Bar { } diff --git a/src/test/run-pass/builtin-superkinds-capabilities-xc.rs b/src/test/run-pass/builtin-superkinds-capabilities-xc.rs index 85012896253..1e24c121f5a 100644 --- a/src/test/run-pass/builtin-superkinds-capabilities-xc.rs +++ b/src/test/run-pass/builtin-superkinds-capabilities-xc.rs @@ -10,16 +10,19 @@ // aux-build:trait_superkinds_in_metadata.rs +// Tests "capabilities" granted by traits with super-builtin-kinds, +// even when using them cross-crate. + extern mod trait_superkinds_in_metadata; -use trait_superkinds_in_metadata::{Foo, Bar}; +use trait_superkinds_in_metadata::{RequiresRequiresFreezeAndSend, RequiresFreeze}; #[deriving(Eq)] struct X<T>(T); -impl <T: Freeze> Bar for X<T> { } -impl <T: Freeze+Send> Foo for X<T> { } +impl <T: Freeze> RequiresFreeze for X<T> { } +impl <T: Freeze+Send> RequiresRequiresFreezeAndSend for X<T> { } -fn foo<T: Foo>(val: T, chan: std::comm::Chan<T>) { +fn foo<T: RequiresRequiresFreezeAndSend>(val: T, chan: std::comm::Chan<T>) { chan.send(val); } diff --git a/src/test/run-pass/builtin-superkinds-capabilities.rs b/src/test/run-pass/builtin-superkinds-capabilities.rs index 639c78bd657..ebbb3d38694 100644 --- a/src/test/run-pass/builtin-superkinds-capabilities.rs +++ b/src/test/run-pass/builtin-superkinds-capabilities.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Tests "capabilities" granted by traits that inherit from super- +// builtin-kinds, e.g., if a trait requires Send to implement, then +// at usage site of that trait, we know we have the Send capability. + trait Foo : Send { } impl <T: Send> Foo for T { } diff --git a/src/test/run-pass/builtin-superkinds-in-metadata.rs b/src/test/run-pass/builtin-superkinds-in-metadata.rs index fc445058c04..9f68976a4a4 100644 --- a/src/test/run-pass/builtin-superkinds-in-metadata.rs +++ b/src/test/run-pass/builtin-superkinds-in-metadata.rs @@ -10,13 +10,15 @@ // aux-build:trait_superkinds_in_metadata.rs +// Tests (correct) usage of trait super-builtin-kinds cross-crate. + extern mod trait_superkinds_in_metadata; -use trait_superkinds_in_metadata::{Foo, Bar}; +use trait_superkinds_in_metadata::{RequiresRequiresFreezeAndSend, RequiresFreeze}; struct X<T>(T); -impl <T:Freeze> Bar for X<T> { } +impl <T:Freeze> RequiresFreeze for X<T> { } -impl <T:Freeze+Send> Foo for X<T> { } +impl <T:Freeze+Send> RequiresRequiresFreezeAndSend for X<T> { } fn main() { } diff --git a/src/test/run-pass/builtin-superkinds-shadow-typaram.rs b/src/test/run-pass/builtin-superkinds-phantom-typaram.rs similarity index 74% rename from src/test/run-pass/builtin-superkinds-shadow-typaram.rs rename to src/test/run-pass/builtin-superkinds-phantom-typaram.rs index 193efb06d39..b6e58bfbf3d 100644 --- a/src/test/run-pass/builtin-superkinds-shadow-typaram.rs +++ b/src/test/run-pass/builtin-superkinds-phantom-typaram.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Tests that even when a type paramenter doesn't implement a required +// super-builtin-kind of a trait, if the type parameter is never used, +// the type can implement the trait anyway. + trait Foo : Send { } struct X<T>(()); diff --git a/src/test/run-pass/builtin-superkinds-simple.rs b/src/test/run-pass/builtin-superkinds-simple.rs index 5ecac6a0f7a..61a22d97498 100644 --- a/src/test/run-pass/builtin-superkinds-simple.rs +++ b/src/test/run-pass/builtin-superkinds-simple.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Simple test case of implementing a trait with super-builtin-kinds. + trait Foo : Send { } impl Foo for int { } diff --git a/src/test/run-pass/builtin-superkinds-typaram.rs b/src/test/run-pass/builtin-superkinds-typaram.rs index eda04a780ee..7dfd1e0629f 100644 --- a/src/test/run-pass/builtin-superkinds-typaram.rs +++ b/src/test/run-pass/builtin-superkinds-typaram.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Tests correct implementation of traits with super-builtin-kinds +// using a bounded type parameter. + trait Foo : Send { } impl <T: Send> Foo for T { } From cdbdfe88a5e95428055f0c630bd3346a78436486 Mon Sep 17 00:00:00 2001 From: Ben Blum <bblum@andrew.cmu.edu> Date: Tue, 20 Aug 2013 15:44:19 -0400 Subject: [PATCH 07/10] Allow the Self type to benefit from builtin-kinds-as-supertraits (#7083). --- src/librustc/middle/ty.rs | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 3672bfeec86..4e0f76fe198 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -2161,17 +2161,19 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { // def-id. assert_eq!(p.def_id.crate, ast::LOCAL_CRATE); - type_param_def_to_contents( - cx, cx.ty_param_defs.get(&p.def_id.node)) + let tp_def = cx.ty_param_defs.get(&p.def_id.node); + kind_bounds_to_contents(cx, &tp_def.bounds.builtin_bounds, + tp_def.bounds.trait_bounds) } - ty_self(_) => { - // Currently, self is not bounded, so we must assume the - // worst. But in the future we should examine the super - // traits. - // + ty_self(def_id) => { // FIXME(#4678)---self should just be a ty param - TC_ALL + + // Self may be bounded if the associated trait has builtin kinds + // for supertraits. If so we can use those bounds. + let trait_def = lookup_trait_def(cx, def_id); + let traits = [trait_def.trait_ref]; + kind_bounds_to_contents(cx, &trait_def.bounds, traits) } ty_infer(_) => { @@ -2315,14 +2317,12 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { st + mt + bt } - fn type_param_def_to_contents(cx: ctxt, - type_param_def: &TypeParameterDef) -> TypeContents - { - debug!("type_param_def_to_contents(%s)", type_param_def.repr(cx)); + fn kind_bounds_to_contents(cx: ctxt, bounds: &BuiltinBounds, traits: &[@TraitRef]) + -> TypeContents { let _i = indenter(); let mut tc = TC_ALL; - do each_inherited_builtin_bound(cx, type_param_def.bounds) |bound| { + do each_inherited_builtin_bound(cx, bounds, traits) |bound| { debug!("tc = %s, bound = %?", tc.to_str(), bound); tc = tc - match bound { BoundStatic => TypeContents::nonstatic(cx), @@ -2338,13 +2338,13 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { // Iterates over all builtin bounds on the type parameter def, including // those inherited from traits with builtin-kind-supertraits. - fn each_inherited_builtin_bound(cx: ctxt, bounds: &ParamBounds, - f: &fn(BuiltinBound)) { - for bound in bounds.builtin_bounds.iter() { + fn each_inherited_builtin_bound(cx: ctxt, bounds: &BuiltinBounds, + traits: &[@TraitRef], f: &fn(BuiltinBound)) { + for bound in bounds.iter() { f(bound); } - do each_bound_trait_and_supertraits(cx, bounds.trait_bounds) |trait_ref| { + do each_bound_trait_and_supertraits(cx, traits) |trait_ref| { let trait_def = lookup_trait_def(cx, trait_ref.def_id); for bound in trait_def.bounds.iter() { f(bound); From 5796e9e49ccf155772b8f829f458c304da1742fb Mon Sep 17 00:00:00 2001 From: Ben Blum <bblum@andrew.cmu.edu> Date: Tue, 20 Aug 2013 15:46:48 -0400 Subject: [PATCH 08/10] Add tests for self type using builtin kinds. (#7083) --- .../builtin-superkinds-self-type.rs | 26 +++++++++++++++++++ .../run-pass/builtin-superkinds-self-type.rs | 26 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 src/test/compile-fail/builtin-superkinds-self-type.rs create mode 100644 src/test/run-pass/builtin-superkinds-self-type.rs diff --git a/src/test/compile-fail/builtin-superkinds-self-type.rs b/src/test/compile-fail/builtin-superkinds-self-type.rs new file mode 100644 index 00000000000..75690edeb01 --- /dev/null +++ b/src/test/compile-fail/builtin-superkinds-self-type.rs @@ -0,0 +1,26 @@ +// Copyright 2013 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. + +// Tests (negatively) the ability for the Self type in default methods +// to use capabilities granted by builtin kinds as supertraits. + +trait Foo : Freeze { + fn foo(self, chan: std::comm::Chan<Self>) { + chan.send(self); //~ ERROR does not fulfill `Send` + } +} + +impl <T: Freeze> Foo for T { } + +fn main() { + let (p,c) = std::comm::stream(); + 1193182.foo(c); + assert!(p.recv() == 1193182); +} diff --git a/src/test/run-pass/builtin-superkinds-self-type.rs b/src/test/run-pass/builtin-superkinds-self-type.rs new file mode 100644 index 00000000000..da7f0fb5de9 --- /dev/null +++ b/src/test/run-pass/builtin-superkinds-self-type.rs @@ -0,0 +1,26 @@ +// Copyright 2013 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. + +// Tests the ability for the Self type in default methods to use +// capabilities granted by builtin kinds as supertraits. + +trait Foo : Send { + fn foo(self, chan: std::comm::Chan<Self>) { + chan.send(self); + } +} + +impl <T: Send> Foo for T { } + +fn main() { + let (p,c) = std::comm::stream(); + 1193182.foo(c); + assert!(p.recv() == 1193182); +} From 22ad36d75b18bb6b37d88fd5559c6873e50dd4c6 Mon Sep 17 00:00:00 2001 From: Ben Blum <bblum@andrew.cmu.edu> Date: Wed, 21 Aug 2013 15:52:31 -0400 Subject: [PATCH 09/10] oops, xfail-fast the cross-crate superkind tests --- src/test/compile-fail/builtin-superkinds-in-metadata.rs | 2 ++ src/test/run-pass/builtin-superkinds-capabilities-xc.rs | 2 ++ src/test/run-pass/builtin-superkinds-in-metadata.rs | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/test/compile-fail/builtin-superkinds-in-metadata.rs b/src/test/compile-fail/builtin-superkinds-in-metadata.rs index a52a3765889..fe35bf47196 100644 --- a/src/test/compile-fail/builtin-superkinds-in-metadata.rs +++ b/src/test/compile-fail/builtin-superkinds-in-metadata.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-fast + // aux-build:trait_superkinds_in_metadata.rs // Test for traits inheriting from the builtin kinds cross-crate. diff --git a/src/test/run-pass/builtin-superkinds-capabilities-xc.rs b/src/test/run-pass/builtin-superkinds-capabilities-xc.rs index 1e24c121f5a..6e722d4d538 100644 --- a/src/test/run-pass/builtin-superkinds-capabilities-xc.rs +++ b/src/test/run-pass/builtin-superkinds-capabilities-xc.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-fast + // aux-build:trait_superkinds_in_metadata.rs // Tests "capabilities" granted by traits with super-builtin-kinds, diff --git a/src/test/run-pass/builtin-superkinds-in-metadata.rs b/src/test/run-pass/builtin-superkinds-in-metadata.rs index 9f68976a4a4..e2fc6cc335f 100644 --- a/src/test/run-pass/builtin-superkinds-in-metadata.rs +++ b/src/test/run-pass/builtin-superkinds-in-metadata.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-fast + // aux-build:trait_superkinds_in_metadata.rs // Tests (correct) usage of trait super-builtin-kinds cross-crate. From b795fab046ca1b218785bee5ec5af7326ef9fc85 Mon Sep 17 00:00:00 2001 From: Ben Blum <bblum@andrew.cmu.edu> Date: Wed, 21 Aug 2013 20:33:56 -0400 Subject: [PATCH 10/10] oops v2, apparently writing std::comm::stream() doesn't work on check-fast; fix this --- src/test/compile-fail/builtin-superkinds-self-type.rs | 6 ++++-- .../run-pass/builtin-superkinds-capabilities-transitive.rs | 6 ++++-- src/test/run-pass/builtin-superkinds-capabilities-xc.rs | 5 +++-- src/test/run-pass/builtin-superkinds-capabilities.rs | 6 ++++-- src/test/run-pass/builtin-superkinds-self-type.rs | 6 ++++-- 5 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/test/compile-fail/builtin-superkinds-self-type.rs b/src/test/compile-fail/builtin-superkinds-self-type.rs index 75690edeb01..d7ee3aae4d5 100644 --- a/src/test/compile-fail/builtin-superkinds-self-type.rs +++ b/src/test/compile-fail/builtin-superkinds-self-type.rs @@ -11,8 +11,10 @@ // Tests (negatively) the ability for the Self type in default methods // to use capabilities granted by builtin kinds as supertraits. +use std::comm; + trait Foo : Freeze { - fn foo(self, chan: std::comm::Chan<Self>) { + fn foo(self, chan: comm::Chan<Self>) { chan.send(self); //~ ERROR does not fulfill `Send` } } @@ -20,7 +22,7 @@ trait Foo : Freeze { impl <T: Freeze> Foo for T { } fn main() { - let (p,c) = std::comm::stream(); + let (p,c) = comm::stream(); 1193182.foo(c); assert!(p.recv() == 1193182); } diff --git a/src/test/run-pass/builtin-superkinds-capabilities-transitive.rs b/src/test/run-pass/builtin-superkinds-capabilities-transitive.rs index ab5e58285d4..74a218ac469 100644 --- a/src/test/run-pass/builtin-superkinds-capabilities-transitive.rs +++ b/src/test/run-pass/builtin-superkinds-capabilities-transitive.rs @@ -14,18 +14,20 @@ // a Send. Basically this just makes sure rustc is using // each_bound_trait_and_supertraits in type_contents correctly. +use std::comm; + trait Bar : Send { } trait Foo : Bar { } impl <T: Send> Foo for T { } impl <T: Send> Bar for T { } -fn foo<T: Foo>(val: T, chan: std::comm::Chan<T>) { +fn foo<T: Foo>(val: T, chan: comm::Chan<T>) { chan.send(val); } fn main() { - let (p,c) = std::comm::stream(); + let (p,c) = comm::stream(); foo(31337, c); assert!(p.recv() == 31337); } diff --git a/src/test/run-pass/builtin-superkinds-capabilities-xc.rs b/src/test/run-pass/builtin-superkinds-capabilities-xc.rs index 6e722d4d538..ea61b91e3b9 100644 --- a/src/test/run-pass/builtin-superkinds-capabilities-xc.rs +++ b/src/test/run-pass/builtin-superkinds-capabilities-xc.rs @@ -17,6 +17,7 @@ extern mod trait_superkinds_in_metadata; use trait_superkinds_in_metadata::{RequiresRequiresFreezeAndSend, RequiresFreeze}; +use std::comm; #[deriving(Eq)] struct X<T>(T); @@ -24,12 +25,12 @@ struct X<T>(T); impl <T: Freeze> RequiresFreeze for X<T> { } impl <T: Freeze+Send> RequiresRequiresFreezeAndSend for X<T> { } -fn foo<T: RequiresRequiresFreezeAndSend>(val: T, chan: std::comm::Chan<T>) { +fn foo<T: RequiresRequiresFreezeAndSend>(val: T, chan: comm::Chan<T>) { chan.send(val); } fn main() { - let (p,c) = std::comm::stream(); + let (p,c) = comm::stream(); foo(X(31337), c); assert!(p.recv() == X(31337)); } diff --git a/src/test/run-pass/builtin-superkinds-capabilities.rs b/src/test/run-pass/builtin-superkinds-capabilities.rs index ebbb3d38694..c2d2129b1c1 100644 --- a/src/test/run-pass/builtin-superkinds-capabilities.rs +++ b/src/test/run-pass/builtin-superkinds-capabilities.rs @@ -12,16 +12,18 @@ // builtin-kinds, e.g., if a trait requires Send to implement, then // at usage site of that trait, we know we have the Send capability. +use std::comm; + trait Foo : Send { } impl <T: Send> Foo for T { } -fn foo<T: Foo>(val: T, chan: std::comm::Chan<T>) { +fn foo<T: Foo>(val: T, chan: comm::Chan<T>) { chan.send(val); } fn main() { - let (p,c) = std::comm::stream(); + let (p,c) = comm::stream(); foo(31337, c); assert!(p.recv() == 31337); } diff --git a/src/test/run-pass/builtin-superkinds-self-type.rs b/src/test/run-pass/builtin-superkinds-self-type.rs index da7f0fb5de9..2285c471c91 100644 --- a/src/test/run-pass/builtin-superkinds-self-type.rs +++ b/src/test/run-pass/builtin-superkinds-self-type.rs @@ -11,8 +11,10 @@ // Tests the ability for the Self type in default methods to use // capabilities granted by builtin kinds as supertraits. +use std::comm; + trait Foo : Send { - fn foo(self, chan: std::comm::Chan<Self>) { + fn foo(self, chan: comm::Chan<Self>) { chan.send(self); } } @@ -20,7 +22,7 @@ trait Foo : Send { impl <T: Send> Foo for T { } fn main() { - let (p,c) = std::comm::stream(); + let (p,c) = comm::stream(); 1193182.foo(c); assert!(p.recv() == 1193182); }