auto merge of #8562 : bblum/rust/superkinds, r=nikomatsakis
For #7083. The metadata issue with the old version is now fixed. Ready for review. This is also not the full solution to #7083, because this is not supported yet: ``` trait Foo : Send { } impl <T: Send> Foo for T { } fn foo<T: Foo>(val: T, chan: std::comm::Chan<T>) { chan.send(val); } ``` cc @nikomatsakis
This commit is contained in:
commit
3ddfb72512
22 changed files with 518 additions and 95 deletions
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
@ -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]
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
17
src/test/auxiliary/trait_superkinds_in_metadata.rs
Normal file
17
src/test/auxiliary/trait_superkinds_in_metadata.rs
Normal file
|
@ -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 { }
|
22
src/test/compile-fail/builtin-superkinds-double-superkind.rs
Normal file
22
src/test/compile-fail/builtin-superkinds-double-superkind.rs
Normal file
|
@ -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() { }
|
27
src/test/compile-fail/builtin-superkinds-in-metadata.rs
Normal file
27
src/test/compile-fail/builtin-superkinds-in-metadata.rs
Normal file
|
@ -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() { }
|
28
src/test/compile-fail/builtin-superkinds-self-type.rs
Normal file
28
src/test/compile-fail/builtin-superkinds-self-type.rs
Normal file
|
@ -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);
|
||||
}
|
22
src/test/compile-fail/builtin-superkinds-simple.rs
Normal file
22
src/test/compile-fail/builtin-superkinds-simple.rs
Normal file
|
@ -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() { }
|
17
src/test/compile-fail/builtin-superkinds-typaram-not-send.rs
Normal file
17
src/test/compile-fail/builtin-superkinds-typaram-not-send.rs
Normal file
|
@ -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() { }
|
19
src/test/compile-fail/cant-implement-builtin-kinds.rs
Normal file
19
src/test/compile-fail/cant-implement-builtin-kinds.rs
Normal file
|
@ -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() { }
|
|
@ -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);
|
||||
}
|
36
src/test/run-pass/builtin-superkinds-capabilities-xc.rs
Normal file
36
src/test/run-pass/builtin-superkinds-capabilities-xc.rs
Normal file
|
@ -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));
|
||||
}
|
29
src/test/run-pass/builtin-superkinds-capabilities.rs
Normal file
29
src/test/run-pass/builtin-superkinds-capabilities.rs
Normal file
|
@ -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);
|
||||
}
|
26
src/test/run-pass/builtin-superkinds-in-metadata.rs
Normal file
26
src/test/run-pass/builtin-superkinds-in-metadata.rs
Normal file
|
@ -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() { }
|
21
src/test/run-pass/builtin-superkinds-phantom-typaram.rs
Normal file
21
src/test/run-pass/builtin-superkinds-phantom-typaram.rs
Normal file
|
@ -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() { }
|
28
src/test/run-pass/builtin-superkinds-self-type.rs
Normal file
28
src/test/run-pass/builtin-superkinds-self-type.rs
Normal file
|
@ -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);
|
||||
}
|
17
src/test/run-pass/builtin-superkinds-simple.rs
Normal file
17
src/test/run-pass/builtin-superkinds-simple.rs
Normal file
|
@ -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() { }
|
18
src/test/run-pass/builtin-superkinds-typaram.rs
Normal file
18
src/test/run-pass/builtin-superkinds-typaram.rs
Normal file
|
@ -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() { }
|
Loading…
Add table
Reference in a new issue