diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2015-01-13 09:17:07 -0500 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2015-01-13 09:17:07 -0500 |
| commit | d3cecbf6f6aaeb7defdfb2e5d9e2b82d02fa7528 (patch) | |
| tree | 956775208a0ab58a4378bc5d218e4bd00c6de2a9 /src | |
| parent | a6408fa1d80191032bebfa0047bc597b746886a5 (diff) | |
| download | rust-d3cecbf6f6aaeb7defdfb2e5d9e2b82d02fa7528.tar.gz rust-d3cecbf6f6aaeb7defdfb2e5d9e2b82d02fa7528.zip | |
Support UFCS style calls to a method defined in `Trait` where `Self`
is bound to a trait object. Fixes #20676.
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc_trans/trans/meth.rs | 17 | ||||
| -rw-r--r-- | src/test/run-pass/issue-20676.rs | 20 | ||||
| -rw-r--r-- | src/test/run-pass/ufcs-trait-object.rs | 25 |
3 files changed, 59 insertions, 3 deletions
diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 7ac062108f3..72c5e9f9d09 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 00000000000..fd99fc01a23 --- /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 <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. + +// 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 00000000000..2ae63040d17 --- /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 <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 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); +} |
