Implement cross-crate support for autoderef.

Closes #13044.
This commit is contained in:
Eduard Burtescu 2014-03-23 01:11:39 +02:00
parent 75d7d5210a
commit 087ec2aa24
3 changed files with 147 additions and 20 deletions

View File

@ -581,41 +581,48 @@ impl tr for moves::CaptureVar {
// Encoding and decoding of MethodCallee
trait read_method_callee_helper {
fn read_method_callee(&mut self, xcx: &ExtendedDecodeContext) -> MethodCallee;
fn read_method_callee(&mut self, xcx: &ExtendedDecodeContext) -> (u32, MethodCallee);
}
fn encode_method_callee(ecx: &e::EncodeContext,
ebml_w: &mut writer::Encoder,
autoderef: u32,
method: &MethodCallee) {
ebml_w.emit_struct("MethodCallee", 3, |ebml_w| {
ebml_w.emit_struct_field("origin", 0u, |ebml_w| {
ebml_w.emit_struct("MethodCallee", 4, |ebml_w| {
ebml_w.emit_struct_field("autoderef", 0u, |ebml_w| {
autoderef.encode(ebml_w);
});
ebml_w.emit_struct_field("origin", 1u, |ebml_w| {
method.origin.encode(ebml_w);
});
ebml_w.emit_struct_field("ty", 1u, |ebml_w| {
ebml_w.emit_struct_field("ty", 2u, |ebml_w| {
ebml_w.emit_ty(ecx, method.ty);
});
ebml_w.emit_struct_field("substs", 2u, |ebml_w| {
ebml_w.emit_struct_field("substs", 3u, |ebml_w| {
ebml_w.emit_substs(ecx, &method.substs);
});
})
}
impl<'a> read_method_callee_helper for reader::Decoder<'a> {
fn read_method_callee(&mut self, xcx: &ExtendedDecodeContext) -> MethodCallee {
self.read_struct("MethodCallee", 3, |this| {
MethodCallee {
origin: this.read_struct_field("origin", 0, |this| {
fn read_method_callee(&mut self, xcx: &ExtendedDecodeContext) -> (u32, MethodCallee) {
self.read_struct("MethodCallee", 4, |this| {
let autoderef = this.read_struct_field("autoderef", 0, |this| {
Decodable::decode(this)
});
(autoderef, MethodCallee {
origin: this.read_struct_field("origin", 1, |this| {
let method_origin: MethodOrigin =
Decodable::decode(this);
method_origin.tr(xcx)
}),
ty: this.read_struct_field("ty", 1, |this| {
ty: this.read_struct_field("ty", 2, |this| {
this.read_ty(xcx)
}),
substs: this.read_struct_field("substs", 2, |this| {
substs: this.read_struct_field("substs", 3, |this| {
this.read_substs(xcx)
})
}
})
})
}
}
@ -647,6 +654,20 @@ impl tr for MethodOrigin {
// ______________________________________________________________________
// Encoding and decoding vtable_res
fn encode_vtable_res_with_key(ecx: &e::EncodeContext,
ebml_w: &mut writer::Encoder,
autoderef: u32,
dr: typeck::vtable_res) {
ebml_w.emit_struct("VtableWithKey", 2, |ebml_w| {
ebml_w.emit_struct_field("autoderef", 0u, |ebml_w| {
autoderef.encode(ebml_w);
});
ebml_w.emit_struct_field("vtable_res", 1u, |ebml_w| {
encode_vtable_res(ecx, ebml_w, dr);
});
})
}
pub fn encode_vtable_res(ecx: &e::EncodeContext,
ebml_w: &mut writer::Encoder,
dr: typeck::vtable_res) {
@ -701,6 +722,10 @@ pub fn encode_vtable_origin(ecx: &e::EncodeContext,
}
pub trait vtable_decoder_helpers {
fn read_vtable_res_with_key(&mut self,
tcx: &ty::ctxt,
cdata: @cstore::crate_metadata)
-> (u32, typeck::vtable_res);
fn read_vtable_res(&mut self,
tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
-> typeck::vtable_res;
@ -713,6 +738,20 @@ pub trait vtable_decoder_helpers {
}
impl<'a> vtable_decoder_helpers for reader::Decoder<'a> {
fn read_vtable_res_with_key(&mut self,
tcx: &ty::ctxt,
cdata: @cstore::crate_metadata)
-> (u32, typeck::vtable_res) {
self.read_struct("VtableWithKey", 2, |this| {
let autoderef = this.read_struct_field("autoderef", 0, |this| {
Decodable::decode(this)
});
(autoderef, this.read_struct_field("vtable_res", 1, |this| {
this.read_vtable_res(tcx, cdata)
}))
})
}
fn read_vtable_res(&mut self,
tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
-> typeck::vtable_res {
@ -1018,7 +1057,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
ebml_w.tag(c::tag_table_method_map, |ebml_w| {
ebml_w.id(id);
ebml_w.tag(c::tag_table_val, |ebml_w| {
encode_method_callee(ecx, ebml_w, method)
encode_method_callee(ecx, ebml_w, method_call.autoderef, method)
})
})
}
@ -1027,12 +1066,39 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
ebml_w.tag(c::tag_table_vtable_map, |ebml_w| {
ebml_w.id(id);
ebml_w.tag(c::tag_table_val, |ebml_w| {
encode_vtable_res(ecx, ebml_w, *dr);
encode_vtable_res_with_key(ecx, ebml_w, method_call.autoderef, *dr);
})
})
}
for adj in tcx.adjustments.borrow().find(&id).iter() {
match ***adj {
ty::AutoDerefRef(adj) => {
for autoderef in range(0, adj.autoderefs) {
let method_call = MethodCall::autoderef(id, autoderef as u32);
for &method in maps.method_map.borrow().find(&method_call).iter() {
ebml_w.tag(c::tag_table_method_map, |ebml_w| {
ebml_w.id(id);
ebml_w.tag(c::tag_table_val, |ebml_w| {
encode_method_callee(ecx, ebml_w, method_call.autoderef, method)
})
})
}
for &dr in maps.vtable_map.borrow().find(&method_call).iter() {
ebml_w.tag(c::tag_table_vtable_map, |ebml_w| {
ebml_w.id(id);
ebml_w.tag(c::tag_table_val, |ebml_w| {
encode_vtable_res_with_key(ecx, ebml_w,
method_call.autoderef, *dr);
})
})
}
}
}
_ => {}
}
ebml_w.tag(c::tag_table_adjustments, |ebml_w| {
ebml_w.id(id);
ebml_w.tag(c::tag_table_val, |ebml_w| {
@ -1336,15 +1402,21 @@ fn decode_side_tables(xcx: &ExtendedDecodeContext,
dcx.tcx.ty_param_defs.borrow_mut().insert(id, bounds);
}
c::tag_table_method_map => {
let method = val_dsr.read_method_callee(xcx);
let method_call = MethodCall::expr(id);
let (autoderef, method) = val_dsr.read_method_callee(xcx);
let method_call = MethodCall {
expr_id: id,
autoderef: autoderef
};
dcx.maps.method_map.borrow_mut().insert(method_call, method);
}
c::tag_table_vtable_map => {
let vtable_res =
val_dsr.read_vtable_res(xcx.dcx.tcx,
xcx.dcx.cdata);
let vtable_key = MethodCall::expr(id);
let (autoderef, vtable_res) =
val_dsr.read_vtable_res_with_key(xcx.dcx.tcx,
xcx.dcx.cdata);
let vtable_key = MethodCall {
expr_id: id,
autoderef: autoderef
};
dcx.maps.vtable_map.borrow_mut().insert(vtable_key, vtable_res);
}
c::tag_table_adjustments => {

View File

@ -0,0 +1,37 @@
// Copyright 2014 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.
use std::ops::Deref;
struct DerefWithHelper<H, T> {
helper: H
}
trait Helper<T> {
fn helper_borrow<'a>(&'a self) -> &'a T;
}
impl<T> Helper<T> for Option<T> {
fn helper_borrow<'a>(&'a self) -> &'a T {
self.as_ref().unwrap()
}
}
impl<T, H: Helper<T>> Deref<T> for DerefWithHelper<H, T> {
fn deref<'a>(&'a self) -> &'a T {
self.helper.helper_borrow()
}
}
// Test cross-crate autoderef + vtable.
pub fn check<T: Eq>(x: T, y: T) -> bool {
let d: DerefWithHelper<Option<T>, T> = DerefWithHelper { helper: Some(x) };
d.eq(&y)
}

View File

@ -0,0 +1,18 @@
// Copyright 2014 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.
// ignore-fast
// aux-build:overloaded_autoderef_xc.rs
extern crate overloaded_autoderef_xc;
fn main() {
assert!(overloaded_autoderef_xc::check(5, 5));
}