]> git.lizzy.rs Git - rust.git/commitdiff
Implement cross-crate support for autoderef.
authorEduard Burtescu <edy.burt@gmail.com>
Sat, 22 Mar 2014 23:11:39 +0000 (01:11 +0200)
committerEduard Burtescu <edy.burt@gmail.com>
Sat, 22 Mar 2014 23:11:39 +0000 (01:11 +0200)
Closes #13044.

src/librustc/middle/astencode.rs
src/test/auxiliary/overloaded_autoderef_xc.rs [new file with mode: 0644]
src/test/run-pass/overloaded-autoderef-xcrate.rs [new file with mode: 0644]

index 96a3203e56c0ab69a158bea557454071ab11536c..94947b95cd38f9833e280b4e5d07a1d91e2dfc94 100644 (file)
@@ -581,41 +581,48 @@ fn tr(&self, xcx: &ExtendedDecodeContext) -> 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 @@ fn tr(&self, xcx: &ExtendedDecodeContext) -> 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 @@ fn read_vtable_origin(&mut self,
 }
 
 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 => {
diff --git a/src/test/auxiliary/overloaded_autoderef_xc.rs b/src/test/auxiliary/overloaded_autoderef_xc.rs
new file mode 100644 (file)
index 0000000..65a404d
--- /dev/null
@@ -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)
+}
diff --git a/src/test/run-pass/overloaded-autoderef-xcrate.rs b/src/test/run-pass/overloaded-autoderef-xcrate.rs
new file mode 100644 (file)
index 0000000..fc96909
--- /dev/null
@@ -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));
+}