commit
1ee54a8617
41 changed files with 185 additions and 121 deletions
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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_ {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
|
||||
|
|
|
@ -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, _) => {
|
||||
|
|
|
@ -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)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 { }
|
||||
|
|
|
@ -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) }
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
27
src/test/run-pass/generic-static-methods.rs
Executable file
27
src/test/run-pass/generic-static-methods.rs
Executable 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]);
|
||||
}
|
|
@ -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]) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) }
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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) }
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -15,7 +15,6 @@ pub trait Clone2 {
|
|||
fn clone(&self) -> Self;
|
||||
}
|
||||
|
||||
#[allow(default_methods)]
|
||||
trait Getter<T: Clone> {
|
||||
fn do_get(&self) -> T;
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue