Skip to content

Commit 087ec2a

Browse files
committed
Implement cross-crate support for autoderef.
Closes #13044.
1 parent 75d7d52 commit 087ec2a

File tree

3 files changed

+147
-20
lines changed

3 files changed

+147
-20
lines changed

Diff for: src/librustc/middle/astencode.rs

+92-20
Original file line numberDiff line numberDiff line change
@@ -581,41 +581,48 @@ impl tr for moves::CaptureVar {
581581
// Encoding and decoding of MethodCallee
582582

583583
trait read_method_callee_helper {
584-
fn read_method_callee(&mut self, xcx: &ExtendedDecodeContext) -> MethodCallee;
584+
fn read_method_callee(&mut self, xcx: &ExtendedDecodeContext) -> (u32, MethodCallee);
585585
}
586586

587587
fn encode_method_callee(ecx: &e::EncodeContext,
588588
ebml_w: &mut writer::Encoder,
589+
autoderef: u32,
589590
method: &MethodCallee) {
590-
ebml_w.emit_struct("MethodCallee", 3, |ebml_w| {
591-
ebml_w.emit_struct_field("origin", 0u, |ebml_w| {
591+
ebml_w.emit_struct("MethodCallee", 4, |ebml_w| {
592+
ebml_w.emit_struct_field("autoderef", 0u, |ebml_w| {
593+
autoderef.encode(ebml_w);
594+
});
595+
ebml_w.emit_struct_field("origin", 1u, |ebml_w| {
592596
method.origin.encode(ebml_w);
593597
});
594-
ebml_w.emit_struct_field("ty", 1u, |ebml_w| {
598+
ebml_w.emit_struct_field("ty", 2u, |ebml_w| {
595599
ebml_w.emit_ty(ecx, method.ty);
596600
});
597-
ebml_w.emit_struct_field("substs", 2u, |ebml_w| {
601+
ebml_w.emit_struct_field("substs", 3u, |ebml_w| {
598602
ebml_w.emit_substs(ecx, &method.substs);
599603
});
600604
})
601605
}
602606

603607
impl<'a> read_method_callee_helper for reader::Decoder<'a> {
604-
fn read_method_callee(&mut self, xcx: &ExtendedDecodeContext) -> MethodCallee {
605-
self.read_struct("MethodCallee", 3, |this| {
606-
MethodCallee {
607-
origin: this.read_struct_field("origin", 0, |this| {
608+
fn read_method_callee(&mut self, xcx: &ExtendedDecodeContext) -> (u32, MethodCallee) {
609+
self.read_struct("MethodCallee", 4, |this| {
610+
let autoderef = this.read_struct_field("autoderef", 0, |this| {
611+
Decodable::decode(this)
612+
});
613+
(autoderef, MethodCallee {
614+
origin: this.read_struct_field("origin", 1, |this| {
608615
let method_origin: MethodOrigin =
609616
Decodable::decode(this);
610617
method_origin.tr(xcx)
611618
}),
612-
ty: this.read_struct_field("ty", 1, |this| {
619+
ty: this.read_struct_field("ty", 2, |this| {
613620
this.read_ty(xcx)
614621
}),
615-
substs: this.read_struct_field("substs", 2, |this| {
622+
substs: this.read_struct_field("substs", 3, |this| {
616623
this.read_substs(xcx)
617624
})
618-
}
625+
})
619626
})
620627
}
621628
}
@@ -647,6 +654,20 @@ impl tr for MethodOrigin {
647654
// ______________________________________________________________________
648655
// Encoding and decoding vtable_res
649656

657+
fn encode_vtable_res_with_key(ecx: &e::EncodeContext,
658+
ebml_w: &mut writer::Encoder,
659+
autoderef: u32,
660+
dr: typeck::vtable_res) {
661+
ebml_w.emit_struct("VtableWithKey", 2, |ebml_w| {
662+
ebml_w.emit_struct_field("autoderef", 0u, |ebml_w| {
663+
autoderef.encode(ebml_w);
664+
});
665+
ebml_w.emit_struct_field("vtable_res", 1u, |ebml_w| {
666+
encode_vtable_res(ecx, ebml_w, dr);
667+
});
668+
})
669+
}
670+
650671
pub fn encode_vtable_res(ecx: &e::EncodeContext,
651672
ebml_w: &mut writer::Encoder,
652673
dr: typeck::vtable_res) {
@@ -701,6 +722,10 @@ pub fn encode_vtable_origin(ecx: &e::EncodeContext,
701722
}
702723

703724
pub trait vtable_decoder_helpers {
725+
fn read_vtable_res_with_key(&mut self,
726+
tcx: &ty::ctxt,
727+
cdata: @cstore::crate_metadata)
728+
-> (u32, typeck::vtable_res);
704729
fn read_vtable_res(&mut self,
705730
tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
706731
-> typeck::vtable_res;
@@ -713,6 +738,20 @@ pub trait vtable_decoder_helpers {
713738
}
714739

715740
impl<'a> vtable_decoder_helpers for reader::Decoder<'a> {
741+
fn read_vtable_res_with_key(&mut self,
742+
tcx: &ty::ctxt,
743+
cdata: @cstore::crate_metadata)
744+
-> (u32, typeck::vtable_res) {
745+
self.read_struct("VtableWithKey", 2, |this| {
746+
let autoderef = this.read_struct_field("autoderef", 0, |this| {
747+
Decodable::decode(this)
748+
});
749+
(autoderef, this.read_struct_field("vtable_res", 1, |this| {
750+
this.read_vtable_res(tcx, cdata)
751+
}))
752+
})
753+
}
754+
716755
fn read_vtable_res(&mut self,
717756
tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
718757
-> typeck::vtable_res {
@@ -1018,7 +1057,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
10181057
ebml_w.tag(c::tag_table_method_map, |ebml_w| {
10191058
ebml_w.id(id);
10201059
ebml_w.tag(c::tag_table_val, |ebml_w| {
1021-
encode_method_callee(ecx, ebml_w, method)
1060+
encode_method_callee(ecx, ebml_w, method_call.autoderef, method)
10221061
})
10231062
})
10241063
}
@@ -1027,12 +1066,39 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
10271066
ebml_w.tag(c::tag_table_vtable_map, |ebml_w| {
10281067
ebml_w.id(id);
10291068
ebml_w.tag(c::tag_table_val, |ebml_w| {
1030-
encode_vtable_res(ecx, ebml_w, *dr);
1069+
encode_vtable_res_with_key(ecx, ebml_w, method_call.autoderef, *dr);
10311070
})
10321071
})
10331072
}
10341073

10351074
for adj in tcx.adjustments.borrow().find(&id).iter() {
1075+
match ***adj {
1076+
ty::AutoDerefRef(adj) => {
1077+
for autoderef in range(0, adj.autoderefs) {
1078+
let method_call = MethodCall::autoderef(id, autoderef as u32);
1079+
for &method in maps.method_map.borrow().find(&method_call).iter() {
1080+
ebml_w.tag(c::tag_table_method_map, |ebml_w| {
1081+
ebml_w.id(id);
1082+
ebml_w.tag(c::tag_table_val, |ebml_w| {
1083+
encode_method_callee(ecx, ebml_w, method_call.autoderef, method)
1084+
})
1085+
})
1086+
}
1087+
1088+
for &dr in maps.vtable_map.borrow().find(&method_call).iter() {
1089+
ebml_w.tag(c::tag_table_vtable_map, |ebml_w| {
1090+
ebml_w.id(id);
1091+
ebml_w.tag(c::tag_table_val, |ebml_w| {
1092+
encode_vtable_res_with_key(ecx, ebml_w,
1093+
method_call.autoderef, *dr);
1094+
})
1095+
})
1096+
}
1097+
}
1098+
}
1099+
_ => {}
1100+
}
1101+
10361102
ebml_w.tag(c::tag_table_adjustments, |ebml_w| {
10371103
ebml_w.id(id);
10381104
ebml_w.tag(c::tag_table_val, |ebml_w| {
@@ -1336,15 +1402,21 @@ fn decode_side_tables(xcx: &ExtendedDecodeContext,
13361402
dcx.tcx.ty_param_defs.borrow_mut().insert(id, bounds);
13371403
}
13381404
c::tag_table_method_map => {
1339-
let method = val_dsr.read_method_callee(xcx);
1340-
let method_call = MethodCall::expr(id);
1405+
let (autoderef, method) = val_dsr.read_method_callee(xcx);
1406+
let method_call = MethodCall {
1407+
expr_id: id,
1408+
autoderef: autoderef
1409+
};
13411410
dcx.maps.method_map.borrow_mut().insert(method_call, method);
13421411
}
13431412
c::tag_table_vtable_map => {
1344-
let vtable_res =
1345-
val_dsr.read_vtable_res(xcx.dcx.tcx,
1346-
xcx.dcx.cdata);
1347-
let vtable_key = MethodCall::expr(id);
1413+
let (autoderef, vtable_res) =
1414+
val_dsr.read_vtable_res_with_key(xcx.dcx.tcx,
1415+
xcx.dcx.cdata);
1416+
let vtable_key = MethodCall {
1417+
expr_id: id,
1418+
autoderef: autoderef
1419+
};
13481420
dcx.maps.vtable_map.borrow_mut().insert(vtable_key, vtable_res);
13491421
}
13501422
c::tag_table_adjustments => {

Diff for: src/test/auxiliary/overloaded_autoderef_xc.rs

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright 2014 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+
use std::ops::Deref;
12+
13+
struct DerefWithHelper<H, T> {
14+
helper: H
15+
}
16+
17+
trait Helper<T> {
18+
fn helper_borrow<'a>(&'a self) -> &'a T;
19+
}
20+
21+
impl<T> Helper<T> for Option<T> {
22+
fn helper_borrow<'a>(&'a self) -> &'a T {
23+
self.as_ref().unwrap()
24+
}
25+
}
26+
27+
impl<T, H: Helper<T>> Deref<T> for DerefWithHelper<H, T> {
28+
fn deref<'a>(&'a self) -> &'a T {
29+
self.helper.helper_borrow()
30+
}
31+
}
32+
33+
// Test cross-crate autoderef + vtable.
34+
pub fn check<T: Eq>(x: T, y: T) -> bool {
35+
let d: DerefWithHelper<Option<T>, T> = DerefWithHelper { helper: Some(x) };
36+
d.eq(&y)
37+
}

Diff for: src/test/run-pass/overloaded-autoderef-xcrate.rs

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2014 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+
// ignore-fast
12+
// aux-build:overloaded_autoderef_xc.rs
13+
14+
extern crate overloaded_autoderef_xc;
15+
16+
fn main() {
17+
assert!(overloaded_autoderef_xc::check(5, 5));
18+
}

0 commit comments

Comments
 (0)