diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index db62e6bedf0..94947b95cd3 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -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,21 +1057,48 @@ 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) }) }) } - for &dr in maps.vtable_map.borrow().find(&id).iter() { + 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(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,22 @@ 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); - dcx.maps.vtable_map.borrow_mut().insert(id, vtable_res); + 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 => { let adj: @ty::AutoAdjustment = @val_dsr.read_auto_adjustment(xcx); diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index e1b34198777..8d7cff98f42 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -129,7 +129,7 @@ pub fn lookup_variant_by_id(tcx: &ty::ctxt, let maps = astencode::Maps { root_map: @RefCell::new(HashMap::new()), method_map: @RefCell::new(FnvHashMap::new()), - vtable_map: @RefCell::new(NodeMap::new()), + vtable_map: @RefCell::new(FnvHashMap::new()), capture_map: RefCell::new(NodeMap::new()) }; let e = match csearch::maybe_get_item_ast(tcx, enum_def, @@ -170,7 +170,7 @@ pub fn lookup_const_by_id(tcx: &ty::ctxt, def_id: ast::DefId) let maps = astencode::Maps { root_map: @RefCell::new(HashMap::new()), method_map: @RefCell::new(FnvHashMap::new()), - vtable_map: @RefCell::new(NodeMap::new()), + vtable_map: @RefCell::new(FnvHashMap::new()), capture_map: RefCell::new(NodeMap::new()) }; let e = match csearch::maybe_get_item_ast(tcx, def_id, diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index 5ab94240357..92b97cdfc9f 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -170,16 +170,11 @@ pub fn trans_fn_ref(bcx: &Block, def_id: ast::DefId, node: ExprOrMethodCall) -> let _icx = push_ctxt("trans_fn_ref"); let type_params = node_id_type_params(bcx, node); - let vtables = match node { - ExprId(id) => node_vtables(bcx, id), - MethodCall(ref method_call) => { - if method_call.autoderef == 0 { - node_vtables(bcx, method_call.expr_id) - } else { - None - } - } + let vtable_key = match node { + ExprId(id) => MethodCall::expr(id), + MethodCall(method_call) => method_call }; + let vtables = node_vtables(bcx, vtable_key); debug!("trans_fn_ref(def_id={}, node={:?}, type_params={}, vtables={})", def_id.repr(bcx.tcx()), node, type_params.repr(bcx.tcx()), vtables.repr(bcx.tcx())); diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index b5b68a521a8..9787e9228bf 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -829,7 +829,7 @@ pub fn node_id_type_params(bcx: &Block, node: ExprOrMethodCall) -> Vec { } } -pub fn node_vtables(bcx: &Block, id: ast::NodeId) +pub fn node_vtables(bcx: &Block, id: typeck::MethodCall) -> Option { let vtable_map = bcx.ccx().maps.vtable_map.borrow(); let raw_vtables = vtable_map.find(&id); diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index c5e4fa49f64..4701f38c09a 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -208,7 +208,8 @@ pub fn trans_static_method_callee(bcx: &Block, debug!("trans_static_method_callee: method_id={:?}, expr_id={:?}, \ name={}", method_id, expr_id, token::get_name(mname)); - let vtbls = ccx.maps.vtable_map.borrow().get_copy(&expr_id); + let vtable_key = MethodCall::expr(expr_id); + let vtbls = ccx.maps.vtable_map.borrow().get_copy(&vtable_key); let vtbls = resolve_vtables_in_fn_ctxt(bcx.fcx, vtbls); match vtbls.get(bound_index).get(0) { @@ -327,16 +328,11 @@ fn combine_impl_and_methods_tps(bcx: &Block, // Now, do the same work for the vtables. The vtables might not // exist, in which case we need to make them. - let vtables = match node { - ExprId(id) => node_vtables(bcx, id), - MethodCall(method_call) => { - if method_call.autoderef == 0 { - node_vtables(bcx, method_call.expr_id) - } else { - None - } - } + let vtable_key = match node { + ExprId(id) => MethodCall::expr(id), + MethodCall(method_call) => method_call }; + let vtables = node_vtables(bcx, vtable_key); let r_m_origins = match vtables { Some(vt) => vt, None => @Vec::from_elem(node_substs.len(), @Vec::new()) @@ -597,10 +593,8 @@ pub fn trans_trait_cast<'a>(bcx: &'a Block<'a>, bcx = datum.store_to(bcx, llboxdest); // Store the vtable into the second half of pair. - // This is structured a bit funny because of dynamic borrow failures. - let res = *ccx.maps.vtable_map.borrow().get(&id); - let res = resolve_vtables_in_fn_ctxt(bcx.fcx, res); - let origins = *res.get(0); + let res = *ccx.maps.vtable_map.borrow().get(&MethodCall::expr(id)); + let origins = *resolve_vtables_in_fn_ctxt(bcx.fcx, res).get(0); let vtable = get_vtable(bcx, v_ty, origins); let llvtabledest = GEPi(bcx, lldest, [0u, abi::trt_field_vtable]); let llvtabledest = PointerCast(bcx, llvtabledest, val_ty(vtable).ptr_to()); diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index d4fd8d43927..2410390b5e7 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -267,7 +267,7 @@ impl<'a> Inherited<'a> { node_type_substs: RefCell::new(NodeMap::new()), adjustments: RefCell::new(NodeMap::new()), method_map: @RefCell::new(FnvHashMap::new()), - vtable_map: @RefCell::new(NodeMap::new()), + vtable_map: @RefCell::new(FnvHashMap::new()), upvar_borrow_map: RefCell::new(HashMap::new()), } } diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 29f481f9c04..15de3bf2b5f 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -516,10 +516,10 @@ fn connect_trait_tps(vcx: &VtableContext, relate_trait_refs(vcx, span, impl_trait_ref, trait_ref); } -fn insert_vtables(fcx: &FnCtxt, expr_id: ast::NodeId, vtables: vtable_res) { - debug!("insert_vtables(expr_id={}, vtables={:?})", - expr_id, vtables.repr(fcx.tcx())); - fcx.inh.vtable_map.borrow_mut().insert(expr_id, vtables); +fn insert_vtables(fcx: &FnCtxt, vtable_key: MethodCall, vtables: vtable_res) { + debug!("insert_vtables(vtable_key={}, vtables={:?})", + vtable_key, vtables.repr(fcx.tcx())); + fcx.inh.vtable_map.borrow_mut().insert(vtable_key, vtables); } pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) { @@ -591,7 +591,7 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) { is_early); if !is_early { - insert_vtables(fcx, ex.id, @vec!(vtables)); + insert_vtables(fcx, MethodCall::expr(ex.id), @vec!(vtables)); } // Now, if this is &trait, we need to link the @@ -648,7 +648,7 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) { item_ty.generics.type_param_defs(), substs, is_early); if !is_early { - insert_vtables(fcx, ex.id, vtbls); + insert_vtables(fcx, MethodCall::expr(ex.id), vtbls); } } true @@ -673,7 +673,7 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) { type_param_defs.as_slice(), &substs, is_early); if !is_early { - insert_vtables(fcx, ex.id, vtbls); + insert_vtables(fcx, MethodCall::expr(ex.id), vtbls); } } } @@ -692,6 +692,30 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) { match fcx.inh.adjustments.borrow().find(&ex.id) { Some(adjustment) => { match **adjustment { + AutoDerefRef(adj) => { + for autoderef in range(0, adj.autoderefs) { + let method_call = MethodCall::autoderef(ex.id, autoderef as u32); + match fcx.inh.method_map.borrow().find(&method_call) { + Some(method) => { + debug!("vtable resolution on parameter bounds for autoderef {}", + ex.repr(fcx.tcx())); + let type_param_defs = + ty::method_call_type_param_defs(cx.tcx, method.origin); + if has_trait_bounds(type_param_defs.deref().as_slice()) { + let vcx = fcx.vtable_context(); + let vtbls = lookup_vtables(&vcx, ex.span, + type_param_defs.deref() + .as_slice(), + &method.substs, is_early); + if !is_early { + insert_vtables(fcx, method_call, vtbls); + } + } + } + None => {} + } + } + } AutoObject(ref sigil, ref region, m, @@ -713,7 +737,7 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) { b); resolve_object_cast(ex, object_ty); } - AutoAddEnv(..) | AutoDerefRef(..) => {} + AutoAddEnv(..) => {} } } None => {} diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs index 688baa18c95..31d74a1e938 100644 --- a/src/librustc/middle/typeck/check/writeback.rs +++ b/src/librustc/middle/typeck/check/writeback.rs @@ -21,8 +21,7 @@ use middle::typeck::infer::{force_all, resolve_all, resolve_region}; use middle::typeck::infer::resolve_type; use middle::typeck::infer; use middle::typeck::{MethodCall, MethodCallee}; -use middle::typeck::{vtable_res, vtable_origin}; -use middle::typeck::{vtable_static, vtable_param}; +use middle::typeck::{vtable_res, vtable_static, vtable_param}; use middle::typeck::write_substs_to_tcx; use middle::typeck::write_ty_to_tcx; use util::ppaux; @@ -100,38 +99,34 @@ fn resolve_method_map_entry(wbcx: &mut WbCtxt, sp: Span, method_call: MethodCall } } -fn resolve_vtable_map_entry(fcx: &FnCtxt, sp: Span, id: ast::NodeId) { +fn resolve_vtable_map_entry(fcx: &FnCtxt, sp: Span, vtable_key: MethodCall) { // Resolve any vtable map entry - match fcx.inh.vtable_map.borrow().find_copy(&id) { + match fcx.inh.vtable_map.borrow().find_copy(&vtable_key) { Some(origins) => { let r_origins = resolve_origins(fcx, sp, origins); - fcx.ccx.vtable_map.borrow_mut().insert(id, r_origins); - debug!("writeback::resolve_vtable_map_entry(id={}, vtables={:?})", - id, r_origins.repr(fcx.tcx())); + fcx.ccx.vtable_map.borrow_mut().insert(vtable_key, r_origins); + debug!("writeback::resolve_vtable_map_entry(vtable_key={}, vtables={:?})", + vtable_key, r_origins.repr(fcx.tcx())); } None => {} } fn resolve_origins(fcx: &FnCtxt, sp: Span, vtbls: vtable_res) -> vtable_res { - @vtbls.map(|os| @os.map(|o| resolve_origin(fcx, sp, o))) - } - - fn resolve_origin(fcx: &FnCtxt, - sp: Span, - origin: &vtable_origin) -> vtable_origin { - match origin { - &vtable_static(def_id, ref tys, origins) => { - let r_tys = resolve_type_vars_in_types(fcx, - sp, - tys.as_slice()); - let r_origins = resolve_origins(fcx, sp, origins); - vtable_static(def_id, r_tys, r_origins) + @vtbls.map(|os| @os.map(|origin| { + match origin { + &vtable_static(def_id, ref tys, origins) => { + let r_tys = resolve_type_vars_in_types(fcx, + sp, + tys.as_slice()); + let r_origins = resolve_origins(fcx, sp, origins); + vtable_static(def_id, r_tys, r_origins) + } + &vtable_param(n, b) => { + vtable_param(n, b) + } } - &vtable_param(n, b) => { - vtable_param(n, b) - } - } + })) } } @@ -183,6 +178,7 @@ fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId) for autoderef in range(0, adj.autoderefs) { let method_call = MethodCall::autoderef(id, autoderef as u32); resolve_method_map_entry(wbcx, sp, method_call); + resolve_vtable_map_entry(wbcx.fcx, sp, method_call); } let fixup_region = |r| { @@ -273,7 +269,7 @@ fn visit_expr(e: &ast::Expr, wbcx: &mut WbCtxt) { resolve_type_vars_for_node(wbcx, e.span, e.id); resolve_method_map_entry(wbcx, e.span, MethodCall::expr(e.id)); - resolve_vtable_map_entry(wbcx.fcx, e.span, e.id); + resolve_vtable_map_entry(wbcx.fcx, e.span, MethodCall::expr(e.id)); match e.node { ast::ExprFnBlock(ref decl, _) | ast::ExprProc(ref decl, _) => { diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index 22881b26f63..b33819ff7f4 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -68,7 +68,7 @@ use middle::ty; use util::common::time; use util::ppaux::Repr; use util::ppaux; -use util::nodemap::{DefIdMap, FnvHashMap, NodeMap}; +use util::nodemap::{DefIdMap, FnvHashMap}; use std::cell::RefCell; use std::rc::Rc; @@ -148,7 +148,7 @@ pub struct MethodCallee { substs: ty::substs } -#[deriving(Clone, Eq, Hash)] +#[deriving(Clone, Eq, Hash, Show)] pub struct MethodCall { expr_id: ast::NodeId, autoderef: u32 @@ -216,7 +216,7 @@ impl Repr for vtable_origin { } } -pub type vtable_map = @RefCell>; +pub type vtable_map = @RefCell>; // Information about the vtable resolutions for a trait impl. @@ -461,7 +461,7 @@ pub fn check_crate(tcx: &ty::ctxt, let ccx = CrateCtxt { trait_map: trait_map, method_map: @RefCell::new(FnvHashMap::new()), - vtable_map: @RefCell::new(NodeMap::new()), + vtable_map: @RefCell::new(FnvHashMap::new()), tcx: tcx }; diff --git a/src/test/auxiliary/overloaded_autoderef_xc.rs b/src/test/auxiliary/overloaded_autoderef_xc.rs new file mode 100644 index 00000000000..65a404d1ff3 --- /dev/null +++ b/src/test/auxiliary/overloaded_autoderef_xc.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::ops::Deref; + +struct DerefWithHelper { + helper: H +} + +trait Helper { + fn helper_borrow<'a>(&'a self) -> &'a T; +} + +impl Helper for Option { + fn helper_borrow<'a>(&'a self) -> &'a T { + self.as_ref().unwrap() + } +} + +impl> Deref for DerefWithHelper { + fn deref<'a>(&'a self) -> &'a T { + self.helper.helper_borrow() + } +} + +// Test cross-crate autoderef + vtable. +pub fn check(x: T, y: T) -> bool { + let d: DerefWithHelper, T> = DerefWithHelper { helper: Some(x) }; + d.eq(&y) +} diff --git a/src/test/run-pass/overloaded-autoderef-vtable.rs b/src/test/run-pass/overloaded-autoderef-vtable.rs new file mode 100644 index 00000000000..15b5cca9cf8 --- /dev/null +++ b/src/test/run-pass/overloaded-autoderef-vtable.rs @@ -0,0 +1,42 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::ops::Deref; + +struct DerefWithHelper { + helper: H +} + +trait Helper { + fn helper_borrow<'a>(&'a self) -> &'a T; +} + +impl Helper for Option { + fn helper_borrow<'a>(&'a self) -> &'a T { + self.as_ref().unwrap() + } +} + +impl> Deref for DerefWithHelper { + fn deref<'a>(&'a self) -> &'a T { + self.helper.helper_borrow() + } +} + +struct Foo {x: int} + +impl Foo { + fn foo(&self) -> int {self.x} +} + +pub fn main() { + let x: DerefWithHelper, Foo> = DerefWithHelper { helper: Some(Foo {x: 5}) }; + assert!(x.foo() == 5); +} diff --git a/src/test/run-pass/overloaded-autoderef-xcrate.rs b/src/test/run-pass/overloaded-autoderef-xcrate.rs new file mode 100644 index 00000000000..fc969093d23 --- /dev/null +++ b/src/test/run-pass/overloaded-autoderef-xcrate.rs @@ -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 or the MIT license +// , 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)); +}