diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index a9f3200af12..b2fefdd97b8 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -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)); } } diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 7412eba1156..2e0090f7dda 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -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)), } } diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs index 893ef3feb56..1f7b2bd4663 100644 --- a/src/librustc/middle/trans/inline.rs +++ b/src/librustc/middle/trans/inline.rs @@ -88,7 +88,7 @@ pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::def_id, 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 diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 8c37c1510cf..b6275ed186c 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -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), } diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs index 59020e9d183..e7eedcaa62e 100644 --- a/src/libsyntax/ast_map.rs +++ b/src/libsyntax/ast_map.rs @@ -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, _) => { diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 78be8e6f180..d87955a484c 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -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)), } } } diff --git a/src/test/auxiliary/trait_default_method_xc_aux.rs b/src/test/auxiliary/trait_default_method_xc_aux.rs index 7ae648f113a..6bd679f1304 100644 --- a/src/test/auxiliary/trait_default_method_xc_aux.rs +++ b/src/test/auxiliary/trait_default_method_xc_aux.rs @@ -5,7 +5,8 @@ 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 +20,7 @@ impl A for Something { trait B { fn thing(&self, x: T, y: U) -> (T, U) { (x, y) } + fn staticthing(z: &Self, x: T, y: U) -> (T, U) { (x, y) } } impl B for int { } diff --git a/src/test/run-pass/trait-default-method-xc.rs b/src/test/run-pass/trait-default-method-xc.rs index 4eac1a1e730..f31b46c3339 100644 --- a/src/test/run-pass/trait-default-method-xc.rs +++ b/src/test/run-pass/trait-default-method-xc.rs @@ -4,13 +4,17 @@ #[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(i: T) { assert_eq!(i.g(), 10); } +fn welp(i: int, x: &T) -> int { + i.g() +} + mod stuff { pub struct thing { x: int } } @@ -43,23 +47,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::(&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