Skip to content

Commit

Permalink
Support UFCS style calls to a method defined in Trait where Self
Browse files Browse the repository at this point in the history
is bound to a trait object. Fixes #20676.
  • Loading branch information
nikomatsakis committed Jan 13, 2015
1 parent a6408fa commit d3cecbf
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 3 deletions.
17 changes: 14 additions & 3 deletions src/librustc_trans/trans/meth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))[]);
Expand Down Expand Up @@ -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(..) |
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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.
Expand Down
20 changes: 20 additions & 0 deletions src/test/run-pass/issue-20676.rs
Original file line number Diff line number Diff line change
@@ -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);
}
25 changes: 25 additions & 0 deletions src/test/run-pass/ufcs-trait-object.rs
Original file line number Diff line number Diff line change
@@ -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);
}

0 comments on commit d3cecbf

Please sign in to comment.