Get cross crate static default methods working. Closes #7569.
This commit is contained in:
parent
1bbb434880
commit
186f6faf1e
8 changed files with 40 additions and 31 deletions
|
@ -791,7 +791,7 @@ fn encode_info_for_method(ecx: &EncodeContext,
|
||||||
if len > 0u || should_inline {
|
if len > 0u || should_inline {
|
||||||
(ecx.encode_inlined_item)(
|
(ecx.encode_inlined_item)(
|
||||||
ecx, ebml_w, impl_path,
|
ecx, ebml_w, impl_path,
|
||||||
ii_method(local_def(parent_id), m));
|
ii_method(local_def(parent_id), false, m));
|
||||||
} else {
|
} else {
|
||||||
encode_symbol(ecx, ebml_w, m.id);
|
encode_symbol(ecx, ebml_w, m.id);
|
||||||
}
|
}
|
||||||
|
@ -1123,21 +1123,16 @@ fn encode_info_for_item(ecx: &EncodeContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
provided(m) => {
|
provided(m) => {
|
||||||
// This is obviously a bogus assert but I don't think this
|
// If this is a static method, we've already encoded
|
||||||
// ever worked before anyhow...near as I can tell, before
|
// this.
|
||||||
// we would emit two items.
|
if method_ty.explicit_self != sty_static {
|
||||||
if method_ty.explicit_self == sty_static {
|
encode_type_param_bounds(ebml_w, ecx,
|
||||||
tcx.sess.span_unimpl(
|
&m.generics.ty_params);
|
||||||
item.span,
|
|
||||||
fmt!("Method %s is both provided and static",
|
|
||||||
token::ident_to_str(&method_ty.ident)));
|
|
||||||
}
|
}
|
||||||
encode_type_param_bounds(ebml_w, ecx,
|
|
||||||
&m.generics.ty_params);
|
|
||||||
encode_method_sort(ebml_w, 'p');
|
encode_method_sort(ebml_w, 'p');
|
||||||
(ecx.encode_inlined_item)(
|
(ecx.encode_inlined_item)(
|
||||||
ecx, ebml_w, path,
|
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 {
|
match *ii {
|
||||||
//hack: we're not dropping items
|
//hack: we're not dropping items
|
||||||
ast::ii_item(i) => ast::ii_item(fld.fold_item(i).get()),
|
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))
|
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 {
|
match ii {
|
||||||
ast::ii_item(i) => ast::ii_item(fld.fold_item(i).get()),
|
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)),
|
ast::ii_foreign(i) => ast::ii_foreign(fld.fold_foreign_item(i)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 \
|
ccx.sess.bug("maybe_get_item_ast returned a found_parent \
|
||||||
with a non-item 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.stats.n_inlines += 1;
|
||||||
ccx.external.insert(fn_id, Some(mth.id));
|
ccx.external.insert(fn_id, Some(mth.id));
|
||||||
// If this is a default method, we can't look up the
|
// If this is a default method, we can't look up the
|
||||||
|
|
|
@ -1033,7 +1033,7 @@ pub enum foreign_item_ {
|
||||||
#[deriving(Eq, Encodable, Decodable,IterBytes)]
|
#[deriving(Eq, Encodable, Decodable,IterBytes)]
|
||||||
pub enum inlined_item {
|
pub enum inlined_item {
|
||||||
ii_item(@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),
|
ii_foreign(@foreign_item),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -165,8 +165,8 @@ pub fn map_decoded_item(diag: @span_handler,
|
||||||
i.vis, // Wrong but OK
|
i.vis, // Wrong but OK
|
||||||
@path));
|
@path));
|
||||||
}
|
}
|
||||||
ii_method(impl_did, m) => {
|
ii_method(impl_did, is_provided, m) => {
|
||||||
map_method(impl_did, @path, m, cx);
|
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,
|
pub fn map_method(impl_did: def_id, impl_path: @path,
|
||||||
m: @method, cx: @mut Ctx) {
|
m: @method, is_provided: bool, cx: @mut Ctx) {
|
||||||
cx.map.insert(m.id, node_method(m, impl_did, impl_path));
|
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_));
|
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) => {
|
item_impl(_, _, _, ref ms) => {
|
||||||
let impl_did = ast_util::local_def(i.id);
|
let impl_did = ast_util::local_def(i.id);
|
||||||
for ms.iter().advance |m| {
|
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, _) => {
|
item_enum(ref enum_definition, _) => {
|
||||||
|
|
|
@ -298,7 +298,7 @@ impl inlined_item_utils for inlined_item {
|
||||||
match *self {
|
match *self {
|
||||||
ii_item(i) => /* FIXME (#2543) */ copy i.ident,
|
ii_item(i) => /* FIXME (#2543) */ copy i.ident,
|
||||||
ii_foreign(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 {
|
match *self {
|
||||||
ii_item(i) => i.id,
|
ii_item(i) => i.id,
|
||||||
ii_foreign(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 {
|
match *self {
|
||||||
ii_item(i) => (v.visit_item)(i, (e, v)),
|
ii_item(i) => (v.visit_item)(i, (e, v)),
|
||||||
ii_foreign(i) => (v.visit_foreign_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)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,8 @@ pub struct Something { x: int }
|
||||||
pub trait A {
|
pub trait A {
|
||||||
fn f(&self) -> int;
|
fn f(&self) -> int;
|
||||||
fn g(&self) -> int { 10 }
|
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<T> {
|
trait B<T> {
|
||||||
fn thing<U>(&self, x: T, y: U) -> (T, U) { (x, y) }
|
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 { }
|
impl<T> B<T> for int { }
|
||||||
|
|
|
@ -4,13 +4,17 @@
|
||||||
#[allow(default_methods)];
|
#[allow(default_methods)];
|
||||||
|
|
||||||
extern mod aux(name = "trait_default_method_xc_aux");
|
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) {
|
fn f<T: aux::A>(i: T) {
|
||||||
assert_eq!(i.g(), 10);
|
assert_eq!(i.g(), 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn welp<T>(i: int, x: &T) -> int {
|
||||||
|
i.g()
|
||||||
|
}
|
||||||
|
|
||||||
mod stuff {
|
mod stuff {
|
||||||
pub struct thing { x: int }
|
pub struct thing { x: int }
|
||||||
}
|
}
|
||||||
|
@ -43,23 +47,26 @@ fn main () {
|
||||||
// Some tests of random things
|
// Some tests of random things
|
||||||
f(0);
|
f(0);
|
||||||
|
|
||||||
|
assert_eq!(A::lurr(&0, &1), 21);
|
||||||
|
|
||||||
let a = stuff::thing { x: 0 };
|
let a = stuff::thing { x: 0 };
|
||||||
let b = stuff::thing { x: 1 };
|
let b = stuff::thing { x: 1 };
|
||||||
let c = Something { x: 1 };
|
let c = Something { x: 1 };
|
||||||
|
|
||||||
assert_eq!(0i.g(), 10);
|
assert_eq!(0i.g(), 10);
|
||||||
assert_eq!(a.g(), 10);
|
assert_eq!(a.g(), 10);
|
||||||
assert_eq!(a.h(), 10);
|
assert_eq!(a.h(), 11);
|
||||||
assert_eq!(c.h(), 10);
|
assert_eq!(c.h(), 11);
|
||||||
|
|
||||||
0i.thing(3.14, 1);
|
|
||||||
assert_eq!(0i.thing(3.14, 1), (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(0i, 3.14, 1), (3.14, 1));
|
||||||
assert_eq!(g(false, 3.14, 1), (3.14, 1));
|
assert_eq!(g(false, 3.14, 1), (3.14, 1));
|
||||||
|
|
||||||
let obj = @0i as @A;
|
let obj = @0i as @A;
|
||||||
assert_eq!(obj.h(), 10);
|
assert_eq!(obj.h(), 11);
|
||||||
|
|
||||||
|
|
||||||
// Trying out a real one
|
// Trying out a real one
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue