Skip to content

Commit efaa1ea

Browse files
committed
Resolve the vtables for method calls to generic Drop impls with trait bounds.
1 parent efef078 commit efaa1ea

File tree

3 files changed

+43
-24
lines changed

3 files changed

+43
-24
lines changed

src/librustc/middle/trans/base.rs

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ use middle::trans::type_of;
6565
use middle::trans::type_of::*;
6666
use middle::trans::value::Value;
6767
use middle::ty;
68+
use middle::typeck;
6869
use util::common::indenter;
6970
use util::ppaux::{Repr, ty_to_str};
7071
use util::sha2::Sha256;
@@ -535,22 +536,14 @@ pub fn get_res_dtor(ccx: @CrateContext,
535536
};
536537
if !substs.is_empty() {
537538
assert_eq!(did.krate, ast::LOCAL_CRATE);
538-
let tsubsts = ty::substs {regions: ty::ErasedRegions,
539-
self_ty: None,
540-
tps: /*bad*/ substs.to_owned() };
541-
542-
// FIXME: #4252: Generic destructors with type bounds are broken.
543-
//
544-
// Since the vtables aren't passed to `monomorphic_fn` here, generic destructors with type
545-
// bounds are broken. Sadly, the `typeck` pass isn't outputting the necessary metadata
546-
// because it does so based on method calls present in the AST. Destructor calls are not yet
547-
// known about at that stage of compilation, since `trans` handles cleanups.
548-
let (val, _) = monomorphize::monomorphic_fn(ccx,
549-
did,
550-
&tsubsts,
551-
None,
552-
None,
553-
None);
539+
let tsubsts = ty::substs {
540+
regions: ty::ErasedRegions,
541+
self_ty: None,
542+
tps: substs.to_owned()
543+
};
544+
545+
let vtables = typeck::check::vtable::trans_resolve_method(ccx.tcx, did.node, &tsubsts);
546+
let (val, _) = monomorphize::monomorphic_fn(ccx, did, &tsubsts, vtables, None, None);
554547

555548
val
556549
} else if did.krate == ast::LOCAL_CRATE {

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -812,6 +812,28 @@ pub fn resolve_impl(tcx: ty::ctxt,
812812
impl_vtables.get().insert(impl_def_id, res);
813813
}
814814

815+
/// Resolve vtables for a method call after typeck has finished.
816+
/// Used by trans to monomorphize artificial method callees (e.g. drop).
817+
pub fn trans_resolve_method(tcx: ty::ctxt, id: ast::NodeId,
818+
substs: &ty::substs) -> Option<vtable_res> {
819+
let generics = ty::lookup_item_type(tcx, ast_util::local_def(id)).generics;
820+
let type_param_defs = generics.type_param_defs.borrow();
821+
if has_trait_bounds(*type_param_defs) {
822+
let vcx = VtableContext {
823+
infcx: &infer::new_infer_ctxt(tcx),
824+
param_env: &ty::construct_parameter_environment(tcx, None, [], [], [], id)
825+
};
826+
let loc_info = LocationInfo {
827+
id: id,
828+
span: tcx.map.span(id)
829+
};
830+
831+
Some(lookup_vtables(&vcx, &loc_info, *type_param_defs, substs, false))
832+
} else {
833+
None
834+
}
835+
}
836+
815837
impl<'a> visit::Visitor<()> for &'a FnCtxt {
816838
fn visit_expr(&mut self, ex: &ast::Expr, _: ()) {
817839
early_resolve_expr(ex, *self, false);

src/test/run-pass/issue-4252.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,30 +8,34 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// ignore-test
12-
1311
trait X {
14-
fn call(&self);
12+
fn call<T>(&self, x: &T);
13+
fn default_method<T>(&self, x: &T) {
14+
println!("X::default_method {:?} {:?}", self, x);
15+
}
1516
}
1617

17-
struct Y;
18+
struct Y(int);
1819

1920
struct Z<T> {
2021
x: T
2122
}
2223

2324
impl X for Y {
24-
fn call(&self) {
25+
fn call<T>(&self, x: &T) {
26+
println!("X::call {:?} {:?}", self, x);
2527
}
2628
}
2729

30+
#[unsafe_destructor]
2831
impl<T: X> Drop for Z<T> {
2932
fn drop(&mut self) {
30-
self.x.call(); // Adding this statement causes an ICE.
33+
// These statements used to cause an ICE.
34+
self.x.call(self);
35+
self.x.default_method(self);
3136
}
3237
}
3338

3439
pub fn main() {
35-
let y = Y;
36-
let _z = Z{x: y};
40+
let _z = Z {x: Y(42)};
3741
}

0 commit comments

Comments
 (0)