auto merge of #7725 : msullivan/rust/default-methods, r=pcwalton

r?
This commit is contained in:
bors 2013-07-12 17:28:28 -07:00
commit 1ee54a8617
41 changed files with 185 additions and 121 deletions

View file

@ -791,7 +791,7 @@ fn encode_info_for_method(ecx: &EncodeContext,
if len > 0u || should_inline {
(ecx.encode_inlined_item)(
ecx, ebml_w, impl_path,
ii_method(local_def(parent_id), m));
ii_method(local_def(parent_id), false, m));
} else {
encode_symbol(ecx, ebml_w, m.id);
}
@ -1123,21 +1123,16 @@ fn encode_info_for_item(ecx: &EncodeContext,
}
provided(m) => {
// This is obviously a bogus assert but I don't think this
// ever worked before anyhow...near as I can tell, before
// we would emit two items.
if method_ty.explicit_self == sty_static {
tcx.sess.span_unimpl(
item.span,
fmt!("Method %s is both provided and static",
token::ident_to_str(&method_ty.ident)));
// If this is a static method, we've already encoded
// this.
if method_ty.explicit_self != sty_static {
encode_type_param_bounds(ebml_w, ecx,
&m.generics.ty_params);
}
encode_type_param_bounds(ebml_w, ecx,
&m.generics.ty_params);
encode_method_sort(ebml_w, 'p');
(ecx.encode_inlined_item)(
ecx, ebml_w, path,
ii_method(local_def(item.id), m));
ii_method(local_def(item.id), true, m));
}
}

View file

@ -319,7 +319,8 @@ fn simplify_ast(ii: &ast::inlined_item) -> ast::inlined_item {
match *ii {
//hack: we're not dropping items
ast::ii_item(i) => ast::ii_item(fld.fold_item(i).get()),
ast::ii_method(d, m) => ast::ii_method(d, fld.fold_method(m)),
ast::ii_method(d, is_provided, m) =>
ast::ii_method(d, is_provided, fld.fold_method(m)),
ast::ii_foreign(i) => ast::ii_foreign(fld.fold_foreign_item(i))
}
}
@ -340,7 +341,8 @@ fn renumber_ast(xcx: @ExtendedDecodeContext, ii: ast::inlined_item)
match ii {
ast::ii_item(i) => ast::ii_item(fld.fold_item(i).get()),
ast::ii_method(d, m) => ast::ii_method(xcx.tr_def_id(d), fld.fold_method(m)),
ast::ii_method(d, is_provided, m) =>
ast::ii_method(xcx.tr_def_id(d), is_provided, fld.fold_method(m)),
ast::ii_foreign(i) => ast::ii_foreign(fld.fold_foreign_item(i)),
}
}

View file

@ -244,7 +244,7 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[
LintSpec {
lint: default_methods,
desc: "allow default methods",
default: deny
default: allow
}),
("unused_unsafe",

View file

@ -1185,7 +1185,7 @@ impl cmt_ {
}
}
impl Repr for cmt {
impl Repr for cmt_ {
fn repr(&self, tcx: ty::ctxt) -> ~str {
fmt!("{%s id:%d m:%? ty:%s}",
self.cat.repr(tcx),

View file

@ -520,7 +520,7 @@ pub fn get_res_dtor(ccx: @mut CrateContext,
let _icx = push_ctxt("trans_res_dtor");
if !substs.is_empty() {
let did = if did.crate != ast::local_crate {
inline::maybe_instantiate_inline(ccx, did, true)
inline::maybe_instantiate_inline(ccx, did)
} else {
did
};

View file

@ -250,7 +250,7 @@ pub fn trans_fn_ref_with_vtables(
def_id: ast::def_id, // def id of fn
ref_id: ast::node_id, // node id of use of fn; may be zero if N/A
type_params: &[ty::t], // values for fn's ty params
vtables: Option<typeck::vtable_res>)
vtables: Option<typeck::vtable_res>) // vtables for the call
-> FnData {
//!
//
@ -361,8 +361,7 @@ pub fn trans_fn_ref_with_vtables(
// def_id to the local id of the inlined copy.
let def_id = {
if def_id.crate != ast::local_crate {
let may_translate = opt_impl_did.is_none();
inline::maybe_instantiate_inline(ccx, def_id, may_translate)
inline::maybe_instantiate_inline(ccx, def_id)
} else {
def_id
}

View file

@ -154,12 +154,6 @@ impl Repr for param_substs {
}
}
impl Repr for @param_substs {
fn repr(&self, tcx: ty::ctxt) -> ~str {
param_substs_to_str(*self, tcx)
}
}
// Function context. Every LLVM function we create will have one of
// these.
pub struct fn_ctxt_ {

View file

@ -159,7 +159,7 @@ pub fn get_const_val(cx: @mut CrateContext, mut def_id: ast::def_id) -> ValueRef
let contains_key = cx.const_values.contains_key(&def_id.node);
if !ast_util::is_local(def_id) || !contains_key {
if !ast_util::is_local(def_id) {
def_id = inline::maybe_instantiate_inline(cx, def_id, true);
def_id = inline::maybe_instantiate_inline(cx, def_id);
}
match cx.tcx.items.get_copy(&def_id.node) {
ast_map::node_item(@ast::item {

View file

@ -956,7 +956,7 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
fn get_did(ccx: @mut CrateContext, did: ast::def_id)
-> ast::def_id {
if did.crate != ast::local_crate {
inline::maybe_instantiate_inline(ccx, did, true)
inline::maybe_instantiate_inline(ccx, did)
} else {
did
}

View file

@ -22,11 +22,7 @@ use syntax::ast;
use syntax::ast_map::path_name;
use syntax::ast_util::local_def;
// `translate` will be true if this function is allowed to translate the
// item and false otherwise. Currently, this parameter is set to false when
// translating default methods.
pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::def_id,
translate: bool)
pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::def_id)
-> ast::def_id {
let _icx = push_ctxt("maybe_instantiate_inline");
match ccx.external.find(&fn_id) {
@ -59,7 +55,7 @@ pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::def_id,
csearch::found(ast::ii_item(item)) => {
ccx.external.insert(fn_id, Some(item.id));
ccx.stats.n_inlines += 1;
if translate { trans_item(ccx, item); }
trans_item(ccx, item);
local_def(item.id)
}
csearch::found(ast::ii_foreign(item)) => {
@ -81,19 +77,19 @@ pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::def_id,
_ => ccx.sess.bug("maybe_instantiate_inline: item has a \
non-enum parent")
}
if translate { trans_item(ccx, item); }
trans_item(ccx, item);
local_def(my_id)
}
csearch::found_parent(_, _) => {
ccx.sess.bug("maybe_get_item_ast returned a found_parent \
with a non-item parent");
}
csearch::found(ast::ii_method(impl_did, mth)) => {
csearch::found(ast::ii_method(impl_did, is_provided, mth)) => {
ccx.stats.n_inlines += 1;
ccx.external.insert(fn_id, Some(mth.id));
// If this is a default method, we can't look up the
// impl type. But we aren't going to translate anyways, so don't.
if !translate { return local_def(mth.id); }
if is_provided { return local_def(mth.id); }
let impl_tpt = ty::lookup_item_type(ccx.tcx, impl_did);
let num_type_params =

View file

@ -63,24 +63,26 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
assert!(real_substs.tps.iter().all(|t| !ty::type_needs_infer(*t)));
let _icx = push_ctxt("monomorphic_fn");
let mut must_cast = false;
let substs = real_substs.tps.iter().transform(|t| {
let do_normalize = |t: &ty::t| {
match normalize_for_monomorphization(ccx.tcx, *t) {
Some(t) => { must_cast = true; t }
None => *t
}
}).collect::<~[ty::t]>();
for real_substs.tps.iter().advance |s| { assert!(!ty::type_has_params(*s)); }
for substs.iter().advance |s| { assert!(!ty::type_has_params(*s)); }
let param_uses = type_use::type_uses_for(ccx, fn_id, substs.len());
};
let psubsts = @param_substs {
tys: substs,
tys: real_substs.tps.map(|x| do_normalize(x)),
vtables: vtables,
self_ty: real_substs.self_ty,
self_ty: real_substs.self_ty.map(|x| do_normalize(x)),
self_vtable: self_vtable
};
for real_substs.tps.iter().advance |s| { assert!(!ty::type_has_params(*s)); }
for psubsts.tys.iter().advance |s| { assert!(!ty::type_has_params(*s)); }
let param_uses = type_use::type_uses_for(ccx, fn_id, psubsts.tys.len());
let hash_id = make_mono_id(ccx, fn_id, impl_did_opt,
&*psubsts,
Some(param_uses));
@ -109,6 +111,10 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
let tpt = ty::lookup_item_type(ccx.tcx, fn_id);
let llitem_ty = tpt.ty;
// We need to do special handling of the substitutions if we are
// calling a static provided method. This is sort of unfortunate.
let mut is_static_provided = None;
let map_node = session::expect(
ccx.sess,
ccx.tcx.items.find_copy(&fn_id.node),
@ -127,6 +133,12 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
return (get_item_val(ccx, fn_id.node), true);
}
ast_map::node_trait_method(@ast::provided(m), _, pt) => {
// If this is a static provided method, indicate that
// and stash the number of params on the method.
if m.explicit_self.node == ast::sty_static {
is_static_provided = Some(m.generics.ty_params.len());
}
(pt, m.ident, m.span)
}
ast_map::node_trait_method(@ast::required(_), _, _) => {
@ -151,8 +163,36 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
ast_map::node_struct_ctor(_, i, pt) => (pt, i.ident, i.span)
};
let mono_ty = ty::subst_tps(ccx.tcx, psubsts.tys,
psubsts.self_ty, llitem_ty);
debug!("monomorphic_fn about to subst into %s", llitem_ty.repr(ccx.tcx));
let mono_ty = match is_static_provided {
None => ty::subst_tps(ccx.tcx, psubsts.tys,
psubsts.self_ty, llitem_ty),
Some(num_method_ty_params) => {
// Static default methods are a little unfortunate, in
// that the "internal" and "external" type of them differ.
// Internally, the method body can refer to Self, but the
// externally visable type of the method has a type param
// inserted in between the trait type params and the
// method type params. The substs that we are given are
// the proper substs *internally* to the method body, so
// we have to use those when compiling it.
//
// In order to get the proper substitution to use on the
// type of the method, we pull apart the substitution and
// stick a substitution for the self type in.
// This is a bit unfortunate.
let idx = psubsts.tys.len() - num_method_ty_params;
let substs =
(psubsts.tys.slice(0, idx) +
&[psubsts.self_ty.get()] +
psubsts.tys.tailn(idx));
debug!("static default: changed substitution to %s",
substs.repr(ccx.tcx));
ty::subst_tps(ccx.tcx, substs, None, llitem_ty)
}
};
let llfty = type_of_fn_from_ty(ccx, mono_ty);
ccx.stats.n_monos += 1;

View file

@ -49,6 +49,8 @@ pub type type_uses = uint; // Bitmask
pub static use_repr: uint = 1; /* Dependency on size/alignment/mode and
take/drop glue */
pub static use_tydesc: uint = 2; /* Takes the tydesc, or compares */
pub static use_all: uint = use_repr|use_tydesc;
pub struct Context {
ccx: @mut CrateContext,
@ -57,6 +59,14 @@ pub struct Context {
pub fn type_uses_for(ccx: @mut CrateContext, fn_id: def_id, n_tps: uint)
-> @~[type_uses] {
fn store_type_uses(cx: Context, fn_id: def_id) -> @~[type_uses] {
let Context { uses, ccx } = cx;
let uses = @copy *uses; // freeze
ccx.type_use_cache.insert(fn_id, uses);
uses
}
match ccx.type_use_cache.find(&fn_id) {
Some(uses) => return *uses,
None => ()
@ -65,32 +75,29 @@ pub fn type_uses_for(ccx: @mut CrateContext, fn_id: def_id, n_tps: uint)
let fn_id_loc = if fn_id.crate == local_crate {
fn_id
} else {
inline::maybe_instantiate_inline(ccx, fn_id, true)
inline::maybe_instantiate_inline(ccx, fn_id)
};
// Conservatively assume full use for recursive loops
ccx.type_use_cache.insert(fn_id, @vec::from_elem(n_tps, 3u));
ccx.type_use_cache.insert(fn_id, @vec::from_elem(n_tps, use_all));
let cx = Context {
ccx: ccx,
uses: @mut vec::from_elem(n_tps, 0)
};
match ty::get(ty::lookup_item_type(cx.ccx.tcx, fn_id).ty).sty {
ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, _}) |
ty::ty_closure(ty::ClosureTy {sig: ref sig, _}) => {
for sig.inputs.iter().advance |arg| {
type_needs(&cx, use_repr, *arg);
}
}
_ => ()
// If the method is a default method, we mark all of the types as
// used. This is imprecise, but simple. Getting it right is
// tricky because the substs on the call and the substs on the
// default method differ, because of substs on the trait/impl.
let is_default = ccx.tcx.provided_method_sources.contains_key(&fn_id_loc);
// We also mark all of the params as used if it is an extern thing
// that we haven't been able to inline yet.
if is_default || fn_id_loc.crate != local_crate {
for uint::range(0u, n_tps) |n| { cx.uses[n] |= use_all; }
return store_type_uses(cx, fn_id);
}
if fn_id_loc.crate != local_crate {
let Context { uses, _ } = cx;
let uses = @copy *uses; // freeze
ccx.type_use_cache.insert(fn_id, uses);
return uses;
}
let map_node = match ccx.tcx.items.find(&fn_id_loc.node) {
Some(x) => (/*bad*/copy *x),
None => ccx.sess.bug(fmt!("type_uses_for: unbound item ID %?",
@ -106,7 +113,10 @@ pub fn type_uses_for(ccx: @mut CrateContext, fn_id: def_id, n_tps: uint)
// This will be a static trait method. For now, we just assume
// it fully depends on all of the type information. (Doing
// otherwise would require finding the actual implementation).
for uint::range(0u, n_tps) |n| { cx.uses[n] |= use_repr|use_tydesc;}
for uint::range(0u, n_tps) |n| { cx.uses[n] |= use_all;}
// We need to return early, before the arguments are processed,
// because of difficulties in the handling of Self.
return store_type_uses(cx, fn_id);
}
ast_map::node_variant(_, _, _) => {
for uint::range(0u, n_tps) |n| { cx.uses[n] |= use_repr;}
@ -171,10 +181,19 @@ pub fn type_uses_for(ccx: @mut CrateContext, fn_id: def_id, n_tps: uint)
token::get_ident_interner())));
}
}
let Context { uses, _ } = cx;
let uses = @copy *uses; // freeze
ccx.type_use_cache.insert(fn_id, uses);
uses
// Now handle arguments
match ty::get(ty::lookup_item_type(cx.ccx.tcx, fn_id).ty).sty {
ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, _}) |
ty::ty_closure(ty::ClosureTy {sig: ref sig, _}) => {
for sig.inputs.iter().advance |arg| {
type_needs(&cx, use_repr, *arg);
}
}
_ => ()
}
store_type_uses(cx, fn_id)
}
pub fn type_needs(cx: &Context, use_: uint, ty: ty::t) {

View file

@ -3327,11 +3327,15 @@ pub fn instantiate_path(fcx: @mut FnCtxt,
fcx.infcx().next_ty_vars(ty_param_count)
} else if ty_substs_len > ty_param_count {
fcx.ccx.tcx.sess.span_err
(span, "too many type parameters provided for this item");
(span,
fmt!("too many type parameters provided: expected %u, found %u",
ty_param_count, ty_substs_len));
fcx.infcx().next_ty_vars(ty_param_count)
} else if ty_substs_len < ty_param_count {
fcx.ccx.tcx.sess.span_err
(span, "not enough type parameters provided for this item");
(span,
fmt!("not enough type parameters provided: expected %u, found %u",
ty_param_count, ty_substs_len));
fcx.infcx().next_ty_vars(ty_param_count)
} else {
pth.types.map(|aty| fcx.to_ty(aty))

View file

@ -278,7 +278,7 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
// Represents [A',B',C']
let num_trait_bounds = trait_ty_generics.type_param_defs.len();
let non_shifted_trait_tps = do vec::from_fn(num_trait_bounds) |i| {
ty::mk_param(tcx, i, dummy_defid)
ty::mk_param(tcx, i, trait_ty_generics.type_param_defs[i].def_id)
};
// Represents [D']
@ -288,7 +288,8 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
// Represents [E',F',G']
let num_method_bounds = m.generics.type_param_defs.len();
let shifted_method_tps = do vec::from_fn(num_method_bounds) |i| {
ty::mk_param(tcx, i + 1, dummy_defid)
ty::mk_param(tcx, i + num_trait_bounds + 1,
m.generics.type_param_defs[i].def_id)
};
// build up the substitution from

View file

@ -512,9 +512,6 @@ impl<T:Repr> Repr for Option<T> {
}
}
/*
Annoyingly, these conflict with @ast::expr.
impl<T:Repr> Repr for @T {
fn repr(&self, tcx: ctxt) -> ~str {
(&**self).repr(tcx)
@ -526,7 +523,6 @@ impl<T:Repr> Repr for ~T {
(&**self).repr(tcx)
}
}
*/
fn repr_vec<T:Repr>(tcx: ctxt, v: &[T]) -> ~str {
fmt!("[%s]", v.map(|t| t.repr(tcx)).connect(","))
@ -538,11 +534,11 @@ impl<'self, T:Repr> Repr for &'self [T] {
}
}
// This is necessary to handle types like Option<@~[T]>, for which
// This is necessary to handle types like Option<~[T]>, for which
// autoderef cannot convert the &[T] handler
impl<T:Repr> Repr for @~[T] {
impl<T:Repr> Repr for ~[T] {
fn repr(&self, tcx: ctxt) -> ~str {
repr_vec(tcx, **self)
repr_vec(tcx, *self)
}
}
@ -593,19 +589,19 @@ impl Repr for ty::TraitRef {
}
}
impl Repr for @ast::expr {
impl Repr for ast::expr {
fn repr(&self, tcx: ctxt) -> ~str {
fmt!("expr(%d: %s)",
self.id,
pprust::expr_to_str(*self, tcx.sess.intr()))
pprust::expr_to_str(self, tcx.sess.intr()))
}
}
impl Repr for @ast::pat {
impl Repr for ast::pat {
fn repr(&self, tcx: ctxt) -> ~str {
fmt!("pat(%d: %s)",
self.id,
pprust::pat_to_str(*self, tcx.sess.intr()))
pprust::pat_to_str(self, tcx.sess.intr()))
}
}

View file

@ -17,7 +17,7 @@ implementing the `Iterator` trait.
*/
#[allow(default_methods)]; // solid enough for the use case here
#[allow(default_methods)]; // still off by default in stage0
use cmp;
use iter::Times;

View file

@ -1033,7 +1033,7 @@ pub enum foreign_item_ {
#[deriving(Eq, Encodable, Decodable,IterBytes)]
pub enum inlined_item {
ii_item(@item),
ii_method(def_id /* impl id */, @method),
ii_method(def_id /* impl id */, bool /* is provided */, @method),
ii_foreign(@foreign_item),
}

View file

@ -165,8 +165,8 @@ pub fn map_decoded_item(diag: @span_handler,
i.vis, // Wrong but OK
@path));
}
ii_method(impl_did, m) => {
map_method(impl_did, @path, m, cx);
ii_method(impl_did, is_provided, m) => {
map_method(impl_did, @path, m, is_provided, cx);
}
}
@ -207,8 +207,11 @@ pub fn map_pat(pat: @pat, (cx,v): (@mut Ctx, visit::vt<@mut Ctx>)) {
}
pub fn map_method(impl_did: def_id, impl_path: @path,
m: @method, cx: @mut Ctx) {
cx.map.insert(m.id, node_method(m, impl_did, impl_path));
m: @method, is_provided: bool, cx: @mut Ctx) {
let entry = if is_provided {
node_trait_method(@provided(m), impl_did, impl_path)
} else { node_method(m, impl_did, impl_path) };
cx.map.insert(m.id, entry);
cx.map.insert(m.self_id, node_local(special_idents::self_));
}
@ -219,7 +222,7 @@ pub fn map_item(i: @item, (cx, v): (@mut Ctx, visit::vt<@mut Ctx>)) {
item_impl(_, _, _, ref ms) => {
let impl_did = ast_util::local_def(i.id);
for ms.iter().advance |m| {
map_method(impl_did, extend(cx, i.ident), *m, cx);
map_method(impl_did, extend(cx, i.ident), *m, false, cx);
}
}
item_enum(ref enum_definition, _) => {

View file

@ -298,7 +298,7 @@ impl inlined_item_utils for inlined_item {
match *self {
ii_item(i) => /* FIXME (#2543) */ copy i.ident,
ii_foreign(i) => /* FIXME (#2543) */ copy i.ident,
ii_method(_, m) => /* FIXME (#2543) */ copy m.ident,
ii_method(_, _, m) => /* FIXME (#2543) */ copy m.ident,
}
}
@ -306,7 +306,7 @@ impl inlined_item_utils for inlined_item {
match *self {
ii_item(i) => i.id,
ii_foreign(i) => i.id,
ii_method(_, m) => m.id,
ii_method(_, _, m) => m.id,
}
}
@ -314,7 +314,7 @@ impl inlined_item_utils for inlined_item {
match *self {
ii_item(i) => (v.visit_item)(i, (e, v)),
ii_foreign(i) => (v.visit_foreign_item)(i, (e, v)),
ii_method(_, m) => visit::visit_method_helper(m, (e, v)),
ii_method(_, _, m) => visit::visit_method_helper(m, (e, v)),
}
}
}

View file

@ -18,7 +18,6 @@ trait Positioned {
fn X(&self) -> int;
}
#[allow(default_methods)]
trait Movable: Positioned {
fn translate(&self, dx: int) {
self.SetX(self.X() + dx);

View file

@ -1,11 +1,11 @@
#[allow(default_methods)];
pub struct Something { x: int }
pub trait A {
fn f(&self) -> int;
fn g(&self) -> int { 10 }
fn h(&self) -> int { 10 }
fn h(&self) -> int { 11 }
fn lurr(x: &Self, y: &Self) -> int { x.g() + y.h() }
}
@ -19,6 +19,7 @@ impl A for Something {
trait B<T> {
fn thing<U>(&self, x: T, y: U) -> (T, U) { (x, y) }
fn staticthing<U>(z: &Self, x: T, y: U) -> (T, U) { (x, y) }
}
impl<T> B<T> for int { }

View file

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[allow(default_methods)]
trait Speak {
fn say(&self, s:&str) -> ~str;
fn hi(&self) -> ~str { hello(self) }

View file

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[allow(default_methods)];
pub trait Foo<T> {
pub fn func1<U>(&self, t: U);

View file

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[allow(default_methods)];
trait Foo {
fn f(&self) {

View 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.
trait vec_utils<T> {
fn map_<U:Copy>(x: &Self, f: &fn(&T) -> U) -> ~[U];
}
impl<T> vec_utils<T> for ~[T] {
fn map_<U:Copy>(x: &~[T], f: &fn(&T) -> U) -> ~[U] {
let mut r = ~[];
for x.iter().advance |elt| {
r.push(f(elt));
}
r
}
}
fn main() {
assert_eq!(vec_utils::map_(&~[1,2,3], |&x| x+1), ~[2,3,4]);
}

View file

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[allow(default_methods)]
trait Canvas {
fn add_point(&self, point: &int);
fn add_points(&self, shapes: &[int]) {

View file

@ -113,7 +113,6 @@ impl ToStr for AsciiArt {
// This is similar to an interface in other languages: it defines a protocol which
// developers can implement for arbitrary concrete types.
#[allow(default_methods)]
trait Canvas {
fn add_point(&mut self, shape: Point);
fn add_rect(&mut self, shape: Rect);

View file

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[allow(default_methods)];
trait Foo {
fn a(&self) -> int;

View file

@ -14,7 +14,6 @@ trait Positioned<S> {
fn X(&self) -> S;
}
#[allow(default_methods)]
trait Movable<S, T>: Positioned<T> {
fn translate(&self, dx: T) {
self.SetX(self.X() + dx);

View file

@ -16,7 +16,6 @@ trait Positioned {
fn X(&self) -> int;
}
#[allow(default_methods)]
trait Movable: Positioned {
fn translate(&mut self, dx: int) {
let x = self.X();

View file

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[allow(default_methods)];
trait A<T> {
fn g<U>(&self, x: T, y: U) -> (T, U) { (x, y) }

View file

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[allow(default_methods)];
trait A<T> {
fn g(&self, x: T) -> T { x }

View file

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[allow(default_methods)];
trait A {
fn g<T>(&self, x: T, y: T) -> (T, T) { (x, y) }

View file

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[allow(default_methods)];
trait A<T> {
fn g(&self, x: uint) -> uint { x }

View file

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[allow(default_methods)];
trait A {
fn g(&self) -> int { 10 }

View file

@ -1,16 +1,19 @@
// xfail-fast
// aux-build:trait_default_method_xc_aux.rs
#[allow(default_methods)];
extern mod aux(name = "trait_default_method_xc_aux");
use aux::{A, B, TestEquality, Something};
use aux::{A, TestEquality, Something};
use aux::B;
fn f<T: aux::A>(i: T) {
assert_eq!(i.g(), 10);
}
fn welp<T>(i: int, x: &T) -> int {
i.g()
}
mod stuff {
pub struct thing { x: int }
}
@ -43,23 +46,26 @@ fn main () {
// Some tests of random things
f(0);
assert_eq!(A::lurr(&0, &1), 21);
let a = stuff::thing { x: 0 };
let b = stuff::thing { x: 1 };
let c = Something { x: 1 };
assert_eq!(0i.g(), 10);
assert_eq!(a.g(), 10);
assert_eq!(a.h(), 10);
assert_eq!(c.h(), 10);
assert_eq!(a.h(), 11);
assert_eq!(c.h(), 11);
0i.thing(3.14, 1);
assert_eq!(0i.thing(3.14, 1), (3.14, 1));
assert_eq!(B::staticthing(&0i, 3.14, 1), (3.14, 1));
assert_eq!(B::staticthing::<float, int, int>(&0i, 3.14, 1), (3.14, 1));
assert_eq!(g(0i, 3.14, 1), (3.14, 1));
assert_eq!(g(false, 3.14, 1), (3.14, 1));
let obj = @0i as @A;
assert_eq!(obj.h(), 10);
assert_eq!(obj.h(), 11);
// Trying out a real one

View file

@ -15,7 +15,6 @@ pub trait Clone2 {
fn clone(&self) -> Self;
}
#[allow(default_methods)]
trait Getter<T: Clone> {
fn do_get(&self) -> T;

View file

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[allow(default_methods)];
trait Foo {
fn bar(&self) -> ~str {

View file

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[allow(default_methods)];
trait Foo {
fn foo(&self, mut v: int) { v = 1; }

View file

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[allow(default_methods)];
trait Cat {
fn meow(&self) -> bool;

View file

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[allow(default_methods)];
trait Cat {
fn meow(&self) -> bool;