Skip to content

Commit 56d415a

Browse files
author
Branimir
committed
fix for issue #9394
This solves problem of incorrect indexing into vtable when method from super trait was called through pointer to derived trait. Problem was that offset of super trait vtables was not calculated at all. Now it works, correct offset is calculated by traversing all super traits up to super trait where method belongs. That is how it is intended to work.
1 parent af25f58 commit 56d415a

File tree

2 files changed

+66
-6
lines changed

2 files changed

+66
-6
lines changed

src/librustc/middle/typeck/check/method.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ impl<'self> LookupContext<'self> {
372372
// to a trait and its supertraits.
373373
fn get_method_index(&self,
374374
trait_ref: @TraitRef,
375-
subtrait_id: ast::DefId,
375+
subtrait: @TraitRef,
376376
n_method: uint) -> uint {
377377
let tcx = self.tcx();
378378

@@ -382,15 +382,14 @@ impl<'self> LookupContext<'self> {
382382
// we find the trait the method came from, counting up the
383383
// methods from them.
384384
let mut method_count = 0;
385-
do ty::each_bound_trait_and_supertraits(tcx, &[trait_ref])
385+
do ty::each_bound_trait_and_supertraits(tcx, &[subtrait])
386386
|bound_ref| {
387-
if bound_ref.def_id == subtrait_id { false }
387+
if bound_ref.def_id == trait_ref.def_id { false }
388388
else {
389389
method_count += ty::trait_methods(tcx, bound_ref.def_id).len();
390390
true
391391
}
392392
};
393-
394393
return method_count + n_method;
395394
}
396395

@@ -418,9 +417,9 @@ impl<'self> LookupContext<'self> {
418417
let trait_ref = @TraitRef { def_id: did, substs: rcvr_substs.clone() };
419418

420419
do self.push_inherent_candidates_from_bounds_inner(&[trait_ref])
421-
|trait_ref, m, method_num, _bound_num| {
420+
|new_trait_ref, m, method_num, _bound_num| {
422421
let vtable_index =
423-
self.get_method_index(trait_ref, trait_ref.def_id, method_num);
422+
self.get_method_index(new_trait_ref, trait_ref, method_num);
424423
// We need to fix up the transformed self type.
425424
let transformed_self_ty =
426425
self.construct_transformed_self_ty_for_object(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
trait Base: Base2 + Base3{
12+
fn foo(&self) -> ~str;
13+
}
14+
15+
trait Base2: Base3{
16+
fn baz(&self) -> ~str;
17+
}
18+
19+
trait Base3{
20+
fn root(&self) -> ~str;
21+
}
22+
23+
trait Super: Base{
24+
fn bar(&self) -> ~str;
25+
}
26+
27+
struct X;
28+
29+
impl Base for X {
30+
fn foo(&self) -> ~str{
31+
~"base foo"
32+
}
33+
34+
}
35+
36+
impl Base2 for X {
37+
fn baz(&self) -> ~str{
38+
~"base2 baz"
39+
}
40+
}
41+
42+
impl Base3 for X {
43+
fn root(&self) -> ~str{
44+
~"base3 root"
45+
}
46+
}
47+
48+
impl Super for X {
49+
fn bar(&self) -> ~str{
50+
~"super bar"
51+
}
52+
}
53+
54+
pub fn main() {
55+
let n = X;
56+
let s = &n as &Super;
57+
assert_eq!(s.bar(),~"super bar");
58+
assert_eq!(s.foo(),~"base foo");
59+
assert_eq!(s.baz(),~"base2 baz");
60+
assert_eq!(s.root(),~"base3 root");
61+
}

0 commit comments

Comments
 (0)