Skip to content

Fix two default method bugs #7545

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/librustc/middle/privacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,14 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
method_id: def_id,
name: &ident) =
|span, method_id, name| {
// If the method is a default method, we need to use the def_id of
// the default implementation.
// Having to do this this is really unfortunate.
let method_id = match tcx.provided_method_sources.find(&method_id) {
None => method_id,
Some(source) => source.method_id
};

if method_id.crate == local_crate {
let is_private = method_is_private(span, method_id.node);
let container_id = local_method_container_id(span,
Expand Down
14 changes: 8 additions & 6 deletions src/librustc/middle/trans/meth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -641,16 +641,18 @@ pub fn vtable_id(ccx: @mut CrateContext,
-> mono_id {
match origin {
&typeck::vtable_static(impl_id, ref substs, sub_vtables) => {
let psubsts = param_substs {
tys: copy *substs,
vtables: Some(sub_vtables),
self_ty: None,
self_vtable: None
};

monomorphize::make_mono_id(
ccx,
impl_id,
*substs,
if sub_vtables.is_empty() {
None
} else {
Some(sub_vtables)
},
None,
&psubsts,
None)
}

Expand Down
66 changes: 39 additions & 27 deletions src/librustc/middle/trans/monomorphize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,13 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
fn_id=%s, \
real_substs=%s, \
vtables=%s, \
self_vtable=%s, \
impl_did_opt=%s, \
ref_id=%?)",
fn_id.repr(ccx.tcx),
real_substs.repr(ccx.tcx),
vtables.repr(ccx.tcx),
self_vtable.repr(ccx.tcx),
impl_did_opt.repr(ccx.tcx),
ref_id);

Expand All @@ -71,7 +73,16 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
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 hash_id = make_mono_id(ccx, fn_id, substs, vtables, impl_did_opt,

let psubsts = @param_substs {
tys: substs,
vtables: vtables,
self_ty: real_substs.self_ty,
self_vtable: self_vtable
};

let hash_id = make_mono_id(ccx, fn_id, impl_did_opt,
&*psubsts,
Some(param_uses));
if hash_id.params.iter().any_(
|p| match *p { mono_precise(_, _) => false, _ => true }) {
Expand All @@ -80,12 +91,10 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,

debug!("monomorphic_fn(\
fn_id=%s, \
vtables=%s, \
substs=%s, \
psubsts=%s, \
hash_id=%?)",
fn_id.repr(ccx.tcx),
vtables.repr(ccx.tcx),
substs.repr(ccx.tcx),
psubsts.repr(ccx.tcx),
hash_id);

match ccx.monomorphized.find(&hash_id) {
Expand Down Expand Up @@ -142,8 +151,8 @@ 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, substs,
real_substs.self_ty, llitem_ty);
let mono_ty = ty::subst_tps(ccx.tcx, psubsts.tys,
psubsts.self_ty, llitem_ty);
let llfty = type_of_fn_from_ty(ccx, mono_ty);

ccx.stats.n_monos += 1;
Expand Down Expand Up @@ -172,13 +181,6 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
lldecl
};

let psubsts = Some(@param_substs {
tys: substs,
vtables: vtables,
self_ty: real_substs.self_ty,
self_vtable: self_vtable
});

let lldecl = match map_node {
ast_map::node_item(i@@ast::item {
node: ast::item_fn(ref decl, _, _, _, ref body),
Expand All @@ -192,7 +194,7 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
body,
d,
no_self,
psubsts,
Some(psubsts),
fn_id.node,
[]);
d
Expand All @@ -202,7 +204,7 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
}
ast_map::node_foreign_item(i, _, _, _) => {
let d = mk_lldecl();
foreign::trans_intrinsic(ccx, d, i, pt, psubsts.get(), i.attrs,
foreign::trans_intrinsic(ccx, d, i, pt, psubsts, i.attrs,
ref_id);
d
}
Expand All @@ -214,7 +216,7 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
match v.node.kind {
ast::tuple_variant_kind(ref args) => {
trans_enum_variant(ccx, enum_item.id, v, /*bad*/copy *args,
this_tv.disr_val, psubsts, d);
this_tv.disr_val, Some(psubsts), d);
}
ast::struct_variant_kind(_) =>
ccx.tcx.sess.bug("can't monomorphize struct variants"),
Expand All @@ -225,13 +227,13 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
// XXX: What should the self type be here?
let d = mk_lldecl();
set_inline_hint_if_appr(/*bad*/copy mth.attrs, d);
meth::trans_method(ccx, pt, mth, psubsts, d);
meth::trans_method(ccx, pt, mth, Some(psubsts), d);
d
}
ast_map::node_trait_method(@ast::provided(mth), _, pt) => {
let d = mk_lldecl();
set_inline_hint_if_appr(/*bad*/copy mth.attrs, d);
meth::trans_method(ccx, /*bad*/copy *pt, mth, psubsts, d);
meth::trans_method(ccx, /*bad*/copy *pt, mth, Some(psubsts), d);
d
}
ast_map::node_struct_ctor(struct_def, _, _) => {
Expand All @@ -241,7 +243,7 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
/*bad*/copy struct_def.fields,
struct_def.ctor_id.expect("ast-mapped tuple struct \
didn't have a ctor id"),
psubsts,
Some(psubsts),
d);
d
}
Expand Down Expand Up @@ -320,26 +322,36 @@ pub fn normalize_for_monomorphization(tcx: ty::ctxt,

pub fn make_mono_id(ccx: @mut CrateContext,
item: ast::def_id,
substs: &[ty::t],
vtables: Option<typeck::vtable_res>,
impl_did_opt: Option<ast::def_id>,
substs: &param_substs,
param_uses: Option<@~[type_use::type_uses]>) -> mono_id {
// FIXME (possibly #5801): Need a lot of type hints to get
// .collect() to work.
let precise_param_ids: ~[(ty::t, Option<@~[mono_id]>)] = match vtables {
let substs_iter = substs.self_ty.iter().chain_(substs.tys.iter());
let precise_param_ids: ~[(ty::t, Option<@~[mono_id]>)] = match substs.vtables {
Some(vts) => {
debug!("make_mono_id vtables=%s substs=%s",
vts.repr(ccx.tcx), substs.repr(ccx.tcx));
vts.iter().zip(substs.iter()).transform(|(vtable, subst)| {
vts.repr(ccx.tcx), substs.tys.repr(ccx.tcx));
let self_vtables = substs.self_vtable.map(|vtbl| @~[copy *vtbl]);
let vts_iter = self_vtables.iter().chain_(vts.iter());
vts_iter.zip(substs_iter).transform(|(vtable, subst)| {
let v = vtable.map(|vt| meth::vtable_id(ccx, vt));
(*subst, if !v.is_empty() { Some(@v) } else { None })
}).collect()
}
None => substs.iter().transform(|subst| (*subst, None::<@~[mono_id]>)).collect()
None => substs_iter.transform(|subst| (*subst, None::<@~[mono_id]>)).collect()
};


let param_ids = match param_uses {
Some(ref uses) => {
precise_param_ids.iter().zip(uses.iter()).transform(|(id, uses)| {
// param_uses doesn't include a use for the self type.
// We just say it is fully used.
let self_use =
substs.self_ty.map(|_| type_use::use_repr|type_use::use_tydesc);
let uses_iter = self_use.iter().chain_(uses.iter());

precise_param_ids.iter().zip(uses_iter).transform(|(id, uses)| {
if ccx.sess.no_monomorphic_collapse() {
match copy *id {
(a, b) => mono_precise(a, b)
Expand Down
6 changes: 6 additions & 0 deletions src/test/auxiliary/trait_default_method_xc_aux.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#[allow(default_methods)];

pub struct Something { x: int }

pub trait A {
fn f(&self) -> int;
fn g(&self) -> int { 10 }
Expand All @@ -11,6 +13,10 @@ impl A for int {
fn f(&self) -> int { 10 }
}

impl A for Something {
fn f(&self) -> int { 10 }
}

trait B<T> {
fn thing<U>(&self, x: T, y: U) -> (T, U) { (x, y) }
}
Expand Down
5 changes: 2 additions & 3 deletions src/test/run-pass/bug-7183-generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ fn main() {
assert_eq!(Some(Some(3)).hi(), ~"something!something!hello: 3");
assert_eq!(None::<int>.hi(), ~"hello - none");

// These fail because of a bug in monomorphization's ID generation.
//assert_eq!(Some(None::<int>).hi(), ~"something!hello - none");
//assert_eq!(Some(3).hi(), ~"something!hello: 3");
assert_eq!(Some(None::<int>).hi(), ~"something!hello - none");
assert_eq!(Some(3).hi(), ~"something!hello: 3");
}
28 changes: 16 additions & 12 deletions src/test/run-pass/trait-default-method-xc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,18 @@
#[allow(default_methods)];

extern mod aux(name = "trait_default_method_xc_aux");
use aux::{A, B, TestEquality};
use aux::{A, B, TestEquality, Something};


fn f<T: aux::A>(i: T) {
assert_eq!(i.g(), 10);
}

mod stuff {
pub struct thing { x: int }
}

pub struct thing { x: int }
impl A for thing {
impl A for stuff::thing {
fn f(&self) -> int { 10 }
}

Expand All @@ -29,8 +31,8 @@ fn neq<T: TestEquality>(lhs: &T, rhs: &T) -> bool {
}


impl TestEquality for thing {
fn test_eq(&self, rhs: &thing) -> bool {
impl TestEquality for stuff::thing {
fn test_eq(&self, rhs: &stuff::thing) -> bool {
//self.x.test_eq(&rhs.x)
eq(&self.x, &rhs.x)
}
Expand All @@ -41,15 +43,17 @@ fn main () {
// Some tests of random things
f(0);

let a = thing { x: 0 };
let b = thing { x: 1 };
let a = stuff::thing { x: 0 };
let b = stuff::thing { 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.h(), 10);
assert_eq!(c.h(), 10);


//assert_eq!(0i.thing(3.14, 1), (3.14, 1));
0i.thing(3.14, 1);
assert_eq!(0i.thing(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));
Expand All @@ -59,8 +63,8 @@ fn main () {


// Trying out a real one
//assert!(12.test_neq(&10));
//assert!(!10.test_neq(&10));
assert!(12.test_neq(&10));
assert!(!10.test_neq(&10));
assert!(a.test_neq(&b));
assert!(!a.test_neq(&a));

Expand Down