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 1e9214e666b..dbed508348d 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1066,6 +1066,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 9b11301a9c4..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,6 +159,18 @@ impl LanguageItems { } } + 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> { self.items[FreezeTraitLangItem as uint] } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 96d12dbc3ac..39ffffa25c7 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, } @@ -2160,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(_) => { @@ -2314,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; - for bound in type_param_def.bounds.builtin_bounds.iter() { + 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), @@ -2334,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: &BuiltinBounds, + traits: &[@TraitRef], f: &fn(BuiltinBound)) { + for bound in bounds.iter() { + f(bound); + } + + 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); + } + true + }; + } } } @@ -3727,6 +3745,25 @@ pub fn impl_trait_ref(cx: ctxt, id: ast::def_id) -> Option<@TraitRef> { return ret; } +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"); + 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> { match get(ty).sty { ty_trait(id, _, _, _, _) | ty_struct(id, _) | ty_enum(id, _) => Some(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 7678a12b78a..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 } /** @@ -869,14 +880,20 @@ 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. + 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"); + } + 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); @@ -1032,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; @@ -1218,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) { 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..dfb0c0310ec --- /dev/null +++ b/src/test/auxiliary/trait_superkinds_in_metadata.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. + +// Test library crate for cross-crate usages of traits inheriting +// from the builtin kinds. Mostly tests metadata correctness. + +#[crate_type="lib"]; + +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 new file mode 100644 index 00000000000..15fa0b66433 --- /dev/null +++ b/src/test/compile-fail/builtin-superkinds-double-superkind.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. + +// 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 + +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..fe35bf47196 --- /dev/null +++ b/src/test/compile-fail/builtin-superkinds-in-metadata.rs @@ -0,0 +1,27 @@ +// 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. + +// xfail-fast + +// 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::{RequiresRequiresFreezeAndSend, RequiresFreeze}; + +struct X<T>(T); + +impl <T:Freeze> RequiresFreeze for X<T> { } + +impl <T:Freeze> RequiresRequiresFreezeAndSend for X<T> { } //~ ERROR cannot implement this trait + +fn main() { } 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..d7ee3aae4d5 --- /dev/null +++ b/src/test/compile-fail/builtin-superkinds-self-type.rs @@ -0,0 +1,28 @@ +// 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. + +use std::comm; + +trait Foo : Freeze { + fn foo(self, chan: comm::Chan<Self>) { + chan.send(self); //~ ERROR does not fulfill `Send` + } +} + +impl <T: Freeze> Foo for T { } + +fn main() { + let (p,c) = comm::stream(); + 1193182.foo(c); + assert!(p.recv() == 1193182); +} 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..c1011f1368a --- /dev/null +++ b/src/test/compile-fail/builtin-superkinds-simple.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. + +// 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 + +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..2a3d3c7df61 --- /dev/null +++ b/src/test/compile-fail/builtin-superkinds-typaram-not-send.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. + +// Basic test for traits inheriting from the builtin kinds. + +trait Foo : Send { } + +impl <T: Freeze> Foo for T { } //~ ERROR cannot implement this trait + +fn main() { } 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() { } 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..74a218ac469 --- /dev/null +++ b/src/test/run-pass/builtin-superkinds-capabilities-transitive.rs @@ -0,0 +1,33 @@ +// 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 "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. + +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: comm::Chan<T>) { + chan.send(val); +} + +fn main() { + 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 new file mode 100644 index 00000000000..ea61b91e3b9 --- /dev/null +++ b/src/test/run-pass/builtin-superkinds-capabilities-xc.rs @@ -0,0 +1,36 @@ +// 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. + +// xfail-fast + +// 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::{RequiresRequiresFreezeAndSend, RequiresFreeze}; +use std::comm; + +#[deriving(Eq)] +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: comm::Chan<T>) { + chan.send(val); +} + +fn main() { + 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 new file mode 100644 index 00000000000..c2d2129b1c1 --- /dev/null +++ b/src/test/run-pass/builtin-superkinds-capabilities.rs @@ -0,0 +1,29 @@ +// 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 "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. + +use std::comm; + +trait Foo : Send { } + +impl <T: Send> Foo for T { } + +fn foo<T: Foo>(val: T, chan: comm::Chan<T>) { + chan.send(val); +} + +fn main() { + let (p,c) = comm::stream(); + foo(31337, c); + assert!(p.recv() == 31337); +} 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..e2fc6cc335f --- /dev/null +++ b/src/test/run-pass/builtin-superkinds-in-metadata.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. + +// xfail-fast + +// 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::{RequiresRequiresFreezeAndSend, RequiresFreeze}; + +struct X<T>(T); + +impl <T:Freeze> RequiresFreeze for X<T> { } + +impl <T:Freeze+Send> RequiresRequiresFreezeAndSend for X<T> { } + +fn main() { } diff --git a/src/test/run-pass/builtin-superkinds-phantom-typaram.rs b/src/test/run-pass/builtin-superkinds-phantom-typaram.rs new file mode 100644 index 00000000000..b6e58bfbf3d --- /dev/null +++ b/src/test/run-pass/builtin-superkinds-phantom-typaram.rs @@ -0,0 +1,21 @@ +// 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 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>(()); + +impl <T> Foo for X<T> { } + +fn main() { } 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..2285c471c91 --- /dev/null +++ b/src/test/run-pass/builtin-superkinds-self-type.rs @@ -0,0 +1,28 @@ +// 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. + +use std::comm; + +trait Foo : Send { + fn foo(self, chan: comm::Chan<Self>) { + chan.send(self); + } +} + +impl <T: Send> Foo for T { } + +fn main() { + let (p,c) = comm::stream(); + 1193182.foo(c); + assert!(p.recv() == 1193182); +} 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..61a22d97498 --- /dev/null +++ b/src/test/run-pass/builtin-superkinds-simple.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. + +// Simple test case of implementing a trait with super-builtin-kinds. + +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..7dfd1e0629f --- /dev/null +++ b/src/test/run-pass/builtin-superkinds-typaram.rs @@ -0,0 +1,18 @@ +// 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 correct implementation of traits with super-builtin-kinds +// using a bounded type parameter. + +trait Foo : Send { } + +impl <T: Send> Foo for T { } + +fn main() { }