diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 7ac062108f3fb..72c5e9f9d093b 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -288,6 +288,17 @@ pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, param_substs, callee_substs) } + traits::VtableObject(ref data) => { + let trait_item_def_ids = + ty::trait_item_def_ids(ccx.tcx(), trait_id); + let method_offset_in_trait = + trait_item_def_ids.iter() + .position(|item| item.def_id() == method_id) + .unwrap(); + let (llfn, ty) = + trans_object_shim(ccx, data.object_ty, trait_id, method_offset_in_trait); + immediate_rvalue(llfn, ty) + } _ => { tcx.sess.bug(&format!("static call to invalid vtable: {}", vtbl.repr(tcx))[]); @@ -371,7 +382,7 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, Callee { bcx: bcx, data: Fn(llfn) } } traits::VtableObject(ref data) => { - let llfn = trans_object_shim(bcx.ccx(), data.object_ty, trait_id, n_method); + let (llfn, _) = trans_object_shim(bcx.ccx(), data.object_ty, trait_id, n_method); Callee { bcx: bcx, data: Fn(llfn) } } traits::VtableBuiltin(..) | @@ -540,7 +551,7 @@ pub fn trans_object_shim<'a, 'tcx>( object_ty: Ty<'tcx>, trait_id: ast::DefId, method_offset_in_trait: uint) - -> ValueRef + -> (ValueRef, Ty<'tcx>) { let _icx = push_ctxt("trans_object_shim"); let tcx = ccx.tcx(); @@ -667,7 +678,7 @@ pub fn trans_object_shim<'a, 'tcx>( finish_fn(&fcx, bcx, sig.output); - llfn + (llfn, method_bare_fn_ty) } /// Creates a returns a dynamic vtable for the given type and vtable origin. diff --git a/src/test/run-pass/issue-20676.rs b/src/test/run-pass/issue-20676.rs new file mode 100644 index 0000000000000..fd99fc01a23d1 --- /dev/null +++ b/src/test/run-pass/issue-20676.rs @@ -0,0 +1,20 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #20676. Error was that we didn't support +// UFCS-style calls to a method in `Trait` where `Self` was bound to a +// trait object of type `Trait`. See also `ufcs-trait-object.rs`. + +use std::fmt; + +fn main() { + let a: &fmt::Show = &1_i32; + format!("{:?}", a); +} diff --git a/src/test/run-pass/ufcs-trait-object.rs b/src/test/run-pass/ufcs-trait-object.rs new file mode 100644 index 0000000000000..2ae63040d1785 --- /dev/null +++ b/src/test/run-pass/ufcs-trait-object.rs @@ -0,0 +1,25 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that when you use ufcs form to invoke a trait method (on a +// trait object) everything works fine. + +trait Foo { + fn test(&self) -> i32; +} + +impl Foo for i32 { + fn test(&self) -> i32 { *self } +} + +fn main() { + let a: &Foo = &22_i32; + assert_eq!(Foo::test(a), 22); +}