auto merge of #8659 : msullivan/rust/default-methods, r=alexcrichton
This commit is contained in:
commit
23bfa600a0
8 changed files with 92 additions and 21 deletions
|
@ -1617,7 +1617,7 @@ impl Liveness {
|
|||
|
||||
pub fn should_warn(&self, var: Variable) -> Option<@str> {
|
||||
let name = self.ir.variable_name(var);
|
||||
if name[0] == ('_' as u8) { None } else { Some(name) }
|
||||
if name.len() == 0 || name[0] == ('_' as u8) { None } else { Some(name) }
|
||||
}
|
||||
|
||||
pub fn warn_about_unused_args(&self, decl: &fn_decl, entry_ln: LiveNode) {
|
||||
|
|
|
@ -577,20 +577,23 @@ fn emit_vtable_methods(bcx: @mut Block,
|
|||
|
||||
let trait_method_def_ids = ty::trait_method_def_ids(tcx, trt_id);
|
||||
do trait_method_def_ids.map |method_def_id| {
|
||||
let im = ty::method(tcx, *method_def_id);
|
||||
let ident = ty::method(tcx, *method_def_id).ident;
|
||||
// The substitutions we have are on the impl, so we grab
|
||||
// the method type from the impl to substitute into.
|
||||
let m_id = method_with_name(ccx, impl_id, ident);
|
||||
let m = ty::method(tcx, m_id);
|
||||
debug!("(making impl vtable) emitting method %s at subst %s",
|
||||
m.repr(tcx),
|
||||
substs.repr(tcx));
|
||||
let fty = ty::subst_tps(tcx,
|
||||
substs,
|
||||
None,
|
||||
ty::mk_bare_fn(tcx, im.fty.clone()));
|
||||
if im.generics.has_type_params() || ty::type_has_self(fty) {
|
||||
ty::mk_bare_fn(tcx, m.fty.clone()));
|
||||
if m.generics.has_type_params() || ty::type_has_self(fty) {
|
||||
debug!("(making impl vtable) method has self or type params: %s",
|
||||
tcx.sess.str_of(im.ident));
|
||||
tcx.sess.str_of(ident));
|
||||
C_null(Type::nil().ptr_to())
|
||||
} else {
|
||||
debug!("(making impl vtable) adding method to vtable: %s",
|
||||
tcx.sess.str_of(im.ident));
|
||||
let m_id = method_with_name(ccx, impl_id, im.ident);
|
||||
|
||||
trans_fn_ref_with_vtables(bcx, m_id, 0,
|
||||
substs, Some(vtables)).llfn
|
||||
}
|
||||
|
|
|
@ -938,9 +938,18 @@ impl<'self> LookupContext<'self> {
|
|||
|
||||
// static methods should never have gotten this far:
|
||||
assert!(candidate.method_ty.explicit_self != sty_static);
|
||||
let transformed_self_ty =
|
||||
ty::subst(tcx, &candidate.rcvr_substs,
|
||||
candidate.method_ty.transformed_self_ty.unwrap());
|
||||
|
||||
let transformed_self_ty = match candidate.origin {
|
||||
method_object(*) => {
|
||||
// For annoying reasons, we've already handled the
|
||||
// substitution for object calls.
|
||||
candidate.method_ty.transformed_self_ty.unwrap()
|
||||
}
|
||||
_ => {
|
||||
ty::subst(tcx, &candidate.rcvr_substs,
|
||||
candidate.method_ty.transformed_self_ty.unwrap())
|
||||
}
|
||||
};
|
||||
|
||||
// Determine the values for the type parameters of the method.
|
||||
// If they were not explicitly supplied, just construct fresh
|
||||
|
|
|
@ -3092,7 +3092,6 @@ pub fn ty_param_bounds_and_ty_for_def(fcx: @mut FnCtxt,
|
|||
sp: span,
|
||||
defn: ast::def)
|
||||
-> ty_param_bounds_and_ty {
|
||||
|
||||
match defn {
|
||||
ast::def_arg(nid, _) | ast::def_local(nid, _) | ast::def_self(nid, _) |
|
||||
ast::def_binding(nid, _) => {
|
||||
|
@ -3149,7 +3148,8 @@ pub fn instantiate_path(fcx: @mut FnCtxt,
|
|||
let ty_param_count = tpt.generics.type_param_defs.len();
|
||||
let ty_substs_len = pth.types.len();
|
||||
|
||||
debug!("ty_param_count=%? ty_substs_len=%?",
|
||||
debug!("tpt=%s ty_param_count=%? ty_substs_len=%?",
|
||||
tpt.repr(fcx.tcx()),
|
||||
ty_param_count,
|
||||
ty_substs_len);
|
||||
|
||||
|
|
|
@ -346,9 +346,10 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
|
|||
let substd_type_param_defs = m.generics.type_param_defs.subst(tcx, &substs);
|
||||
new_type_param_defs.push_all(*substd_type_param_defs);
|
||||
|
||||
debug!("static method %s type_param_defs=%s substs=%s",
|
||||
debug!("static method %s type_param_defs=%s ty=%s, substs=%s",
|
||||
m.def_id.repr(tcx),
|
||||
new_type_param_defs.repr(tcx),
|
||||
ty.repr(tcx),
|
||||
substs.repr(tcx));
|
||||
|
||||
tcx.tcache.insert(m.def_id,
|
||||
|
@ -893,8 +894,8 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::item) {
|
|||
}
|
||||
ast::item_trait(ref generics, _, ref trait_methods) => {
|
||||
let _trait_def = trait_def_of_item(ccx, it);
|
||||
ensure_trait_methods(ccx, it.id);
|
||||
|
||||
// Run convert_methods on the provided methods.
|
||||
let (_, provided_methods) =
|
||||
split_trait_methods(*trait_methods);
|
||||
let untransformed_rcvr_ty = ty::mk_self(tcx, local_def(it.id));
|
||||
|
@ -904,6 +905,11 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::item) {
|
|||
untransformed_rcvr_ty,
|
||||
&ty_generics, generics,
|
||||
it.vis);
|
||||
|
||||
// We need to do this *after* converting methods, since
|
||||
// convert_methods produces a tcache entry that is wrong for
|
||||
// static trait methods. This is somewhat unfortunate.
|
||||
ensure_trait_methods(ccx, it.id);
|
||||
}
|
||||
ast::item_struct(struct_def, ref generics) => {
|
||||
ensure_no_ty_param_bounds(ccx, it.span, generics, "structure");
|
||||
|
|
|
@ -678,6 +678,7 @@ fn rustpkg_local_pkg() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[ignore (reason = "test makes bogus assumptions about build directory layout: issue #8690")]
|
||||
fn package_script_with_default_build() {
|
||||
let dir = create_local_package(&PkgId::new("fancy-lib"));
|
||||
debug!("dir = %s", dir.to_str());
|
||||
|
|
|
@ -238,12 +238,18 @@ impl Visitor<()> for Ctx {
|
|||
self.map.insert(p.ref_id, node_item(i, item_path));
|
||||
}
|
||||
for tm in methods.iter() {
|
||||
let id = ast_util::trait_method_to_ty_method(tm).id;
|
||||
let ext = { self.extend(i.ident) };
|
||||
let d_id = ast_util::local_def(i.id);
|
||||
self.map.insert(id,
|
||||
node_trait_method(@(*tm).clone(),
|
||||
d_id,
|
||||
item_path));
|
||||
match *tm {
|
||||
required(ref m) => {
|
||||
let entry =
|
||||
node_trait_method(@(*tm).clone(), d_id, ext);
|
||||
self.map.insert(m.id, entry);
|
||||
}
|
||||
provided(m) => {
|
||||
self.map_method(d_id, ext, m, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
|
46
src/test/run-pass/trait-object-generics.rs
Normal file
46
src/test/run-pass/trait-object-generics.rs
Normal file
|
@ -0,0 +1,46 @@
|
|||
// 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.
|
||||
|
||||
// test for #8664
|
||||
|
||||
pub trait Trait2<A> {
|
||||
fn doit(&self);
|
||||
}
|
||||
|
||||
pub struct Impl<A1, A2, A3> {
|
||||
/*
|
||||
* With A2 we get the ICE:
|
||||
* task <unnamed> failed at 'index out of bounds: the len is 1 but the index is 1', /home/tortue/rust_compiler_newest/src/librustc/middle/subst.rs:58
|
||||
*/
|
||||
t: ~Trait2<A2>
|
||||
}
|
||||
|
||||
impl<A1, A2, A3> Impl<A1, A2, A3> {
|
||||
pub fn step(&self) {
|
||||
self.t.doit()
|
||||
}
|
||||
}
|
||||
|
||||
// test for #8601
|
||||
|
||||
enum Type<T> { Constant }
|
||||
|
||||
trait Trait<K,V> {
|
||||
fn method(&self,Type<(K,V)>) -> int;
|
||||
}
|
||||
|
||||
impl<V> Trait<u8,V> for () {
|
||||
fn method(&self, _x: Type<(u8,V)>) -> int { 0 }
|
||||
}
|
||||
|
||||
fn main () {
|
||||
let a = @() as @Trait<u8, u8>;
|
||||
assert_eq!(a.method(Constant), 0);
|
||||
}
|
Loading…
Add table
Reference in a new issue