From 46440fdab7c444b7a6f719661a5a964a368e9f04 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 10 Dec 2012 17:53:14 -0800 Subject: [PATCH] librustc: Fix explicit self for objects in more cases --- src/librustc/middle/trans/deriving.rs | 4 +- src/librustc/middle/trans/meth.rs | 10 ++- src/librustc/middle/typeck/check/method.rs | 87 +++++++++---------- src/librustc/middle/typeck/check/mod.rs | 8 +- src/librustc/middle/typeck/deriving.rs | 7 +- .../run-pass/explicit-self-objects-ext-1.rs | 39 +++++++++ .../run-pass/explicit-self-objects-ext-2.rs | 39 +++++++++ .../run-pass/explicit-self-objects-ext-3.rs | 39 +++++++++ .../run-pass/explicit-self-objects-ext-4.rs | 39 +++++++++ 9 files changed, 221 insertions(+), 51 deletions(-) create mode 100644 src/test/run-pass/explicit-self-objects-ext-1.rs create mode 100644 src/test/run-pass/explicit-self-objects-ext-2.rs create mode 100644 src/test/run-pass/explicit-self-objects-ext-3.rs create mode 100644 src/test/run-pass/explicit-self-objects-ext-4.rs diff --git a/src/librustc/middle/trans/deriving.rs b/src/librustc/middle/trans/deriving.rs index 785e3451d7597..3c7f645d2518b 100644 --- a/src/librustc/middle/trans/deriving.rs +++ b/src/librustc/middle/trans/deriving.rs @@ -26,6 +26,7 @@ use middle::trans::common::{fn_ctxt}; use middle::trans::expr::SaveIn; use middle::trans::type_of::type_of; use middle::ty::{DerivedFieldInfo, re_static}; +use middle::typeck::check::method::TransformTypeNormally; use middle::typeck::check::method; use middle::typeck::method_static; use syntax::ast; @@ -99,7 +100,8 @@ pub fn trans_deriving_impl(ccx: @crate_ctxt, ccx.tcx, Some(re_static), self_ty.ty, - derived_method_info.method_info.self_type); + derived_method_info.method_info.self_type, + TransformTypeNormally); match ty::get(self_ty.ty).sty { ty::ty_class(*) => { diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index 1f1af5ff98fa5..115b36b7d3051 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -561,8 +561,16 @@ fn trans_trait_callee(bcx: block, let _icx = bcx.insn_ctxt("impl::trans_trait_callee"); let mut bcx = bcx; - let self_datum = unpack_datum!(bcx, expr::trans_to_datum(bcx, self_expr)); + let self_datum = unpack_datum!(bcx, + expr::trans_to_datum(bcx, self_expr)); let llpair = self_datum.to_ref_llval(bcx); + + let llpair = match explicit_self { + ast::sty_region(_) => Load(bcx, llpair), + ast::sty_static | ast::sty_by_ref | ast::sty_value | + ast::sty_box(_) | ast::sty_uniq(_) => llpair + }; + let callee_ty = node_id_type(bcx, callee_id); trans_trait_callee_from_llval(bcx, callee_ty, diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index 560281765cf64..c2695be8f78c6 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -151,12 +151,12 @@ struct Candidate { } /** - * Whether the self type should be transformed according to the form of - * explicit self provided by the method. + * How the self type should be transformed according to the form of explicit + * self provided by the method. */ enum TransformTypeFlag { - DontTransformType, - TransformType + TransformTypeNormally, + TransformTypeForObject, } impl LookupContext { @@ -325,7 +325,8 @@ impl LookupContext { } } - fn push_inherent_candidates_from_param(&self, rcvr_ty: ty::t, + fn push_inherent_candidates_from_param(&self, + rcvr_ty: ty::t, param_ty: param_ty) { debug!("push_inherent_candidates_from_param(param_ty=%?)", param_ty); @@ -424,7 +425,7 @@ impl LookupContext { method.self_ty, rcvr_ty, move init_substs, - TransformType); + TransformTypeNormally); let cand = Candidate { rcvr_ty: rcvr_ty, @@ -486,7 +487,7 @@ impl LookupContext { self.create_rcvr_ty_and_substs_for_method(method.self_ty, self_ty, move rcvr_substs, - DontTransformType); + TransformTypeForObject); self.inherent_candidates.push(Candidate { rcvr_ty: rcvr_ty, @@ -517,7 +518,7 @@ impl LookupContext { method.self_ty, self_ty, move rcvr_substs, - TransformType); + TransformTypeNormally); self.inherent_candidates.push(Candidate { rcvr_ty: rcvr_ty, @@ -572,7 +573,7 @@ impl LookupContext { method.self_type, impl_ty, move impl_substs, - TransformType); + TransformTypeNormally); candidates.push(Candidate { rcvr_ty: impl_ty, @@ -608,7 +609,7 @@ impl LookupContext { provided_method_info.method_info.self_type, self_ty, dummy_substs, - TransformType); + TransformTypeNormally); candidates.push(Candidate { rcvr_ty: impl_ty, @@ -656,18 +657,11 @@ impl LookupContext { } }; - let rcvr_ty; - match transform_type { - TransformType => { - rcvr_ty = transform_self_type_for_method(self.tcx(), - rcvr_substs.self_r, - self_ty, - self_decl); - } - DontTransformType => { - rcvr_ty = self_ty; - } - } + let rcvr_ty = transform_self_type_for_method(self.tcx(), + rcvr_substs.self_r, + self_ty, + self_decl, + transform_type); (rcvr_ty, rcvr_substs) } @@ -684,6 +678,10 @@ impl LookupContext { match self.search_for_method(self_ty) { None => None, Some(move mme) => { + debug!("(searching for autoderef'd method) writing \ + adjustment (%u) to %d", + autoderefs, + self.self_expr.id); self.fcx.write_autoderef_adjustment( self.self_expr.id, autoderefs); Some(mme) @@ -812,25 +810,12 @@ impl LookupContext { match self.search_for_method(autoref_ty) { None => {} Some(move mme) => { - match mme.origin { - method_trait(*) => { - // Do not write adjustments; they make no sense - // here since the adjustments are to be performed - // on the self element of the object pair/triple, - // not the object itself. - // - // FIXME (#4088): This is wrong in the presence - // of autoderef. - } - _ => { - self.fcx.write_adjustment( - self.self_expr.id, - @{autoderefs: autoderefs, - autoref: Some({kind: kind, - region: region, - mutbl: *mutbl})}); - } - } + self.fcx.write_adjustment( + self.self_expr.id, + @{autoderefs: autoderefs, + autoref: Some({kind: kind, + region: region, + mutbl: *mutbl})}); return Some(mme); } } @@ -1160,9 +1145,9 @@ impl LookupContext { fn transform_self_type_for_method(tcx: ty::ctxt, self_region: Option, impl_ty: ty::t, - self_type: ast::self_ty_) - -> ty::t -{ + self_type: ast::self_ty_, + flag: TransformTypeFlag) + -> ty::t { match self_type { sty_static => { tcx.sess.bug(~"calling transform_self_type_for_method on \ @@ -1177,10 +1162,20 @@ fn transform_self_type_for_method(tcx: ty::ctxt, { ty: impl_ty, mutbl: mutability }) } sty_box(mutability) => { - mk_box(tcx, { ty: impl_ty, mutbl: mutability }) + match flag { + TransformTypeNormally => { + mk_box(tcx, { ty: impl_ty, mutbl: mutability }) + } + TransformTypeForObject => impl_ty + } } sty_uniq(mutability) => { - mk_uniq(tcx, { ty: impl_ty, mutbl: mutability }) + match flag { + TransformTypeNormally => { + mk_uniq(tcx, { ty: impl_ty, mutbl: mutability }) + } + TransformTypeForObject => impl_ty + } } } } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index d513221ba1d08..6fb286e4633c2 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -78,6 +78,7 @@ type parameter). use astconv::{ast_conv, ast_path_to_ty, ast_ty_to_ty}; use astconv::{ast_region_to_region}; +use method::TransformTypeNormally; use middle::ty::{TyVid, vid, FnTyBase, FnMeta, FnSig, VariantInfo_}; use regionmanip::{replace_bound_regions_in_fn_ty}; use rscope::{anon_rscope, binding_rscope, empty_rscope, in_anon_rscope}; @@ -302,8 +303,11 @@ fn check_fn(ccx: @crate_ctxt, } else { let self_region = fcx.in_scope_regions.find(ty::br_self); let ty = method::transform_self_type_for_method( - fcx.tcx(), self_region, - self_info.self_ty, self_info.explicit_self.node); + fcx.tcx(), + self_region, + self_info.self_ty, + self_info.explicit_self.node, + TransformTypeNormally); Some({self_ty: ty,.. *self_info}) } }; diff --git a/src/librustc/middle/typeck/deriving.rs b/src/librustc/middle/typeck/deriving.rs index 9a7f2315760ce..b231179567438 100644 --- a/src/librustc/middle/typeck/deriving.rs +++ b/src/librustc/middle/typeck/deriving.rs @@ -32,6 +32,7 @@ use middle::ty::{ty_class, ty_enum, ty_param_bounds_and_ty}; use /*middle::typeck::*/check::method; use /*middle::typeck::*/check::vtable; use /*middle::typeck::*/infer::infer_ctxt; +use /*middle::typeck::*/method::TransformTypeNormally; use /*middle::typeck::*/vtable::{LocationInfo, VtableContext}; use util::ppaux; @@ -70,7 +71,11 @@ impl DerivingChecker { let inference_context = infer::new_infer_ctxt(self.crate_context.tcx); let region = inference_context.next_region_var_nb(span); let transformed_type = method::transform_self_type_for_method( - tcx, Some(region), impl_self_tpbt.ty, method_info.self_type); + tcx, + Some(region), + impl_self_tpbt.ty, + method_info.self_type, + TransformTypeNormally); let substs = { self_r: None, diff --git a/src/test/run-pass/explicit-self-objects-ext-1.rs b/src/test/run-pass/explicit-self-objects-ext-1.rs new file mode 100644 index 0000000000000..52a880eb103b6 --- /dev/null +++ b/src/test/run-pass/explicit-self-objects-ext-1.rs @@ -0,0 +1,39 @@ +pub trait Reader { + // FIXME (#2004): Seekable really should be orthogonal. + + /// Read up to len bytes (or EOF) and put them into bytes (which + /// must be at least len bytes long). Return number of bytes read. + // FIXME (#2982): This should probably return an error. + fn read(&self, bytes: &[mut u8], len: uint) -> uint; +} + +pub trait ReaderUtil { + + /// Read len bytes into a new vec. + fn read_bytes(&self, len: uint); +} + +impl T : ReaderUtil { + + fn read_bytes(&self, len: uint) { + let count = self.read(&[mut 0], len); + } + +} + +struct S { + x: int, + y: int +} + +impl S: Reader { + fn read(&self, bytes: &[mut u8], len: uint) -> uint { + 0 + } +} + +fn main() { + let x = S { x: 1, y: 2 }; + let x = x as @Reader; + x.read_bytes(0); +} diff --git a/src/test/run-pass/explicit-self-objects-ext-2.rs b/src/test/run-pass/explicit-self-objects-ext-2.rs new file mode 100644 index 0000000000000..52a880eb103b6 --- /dev/null +++ b/src/test/run-pass/explicit-self-objects-ext-2.rs @@ -0,0 +1,39 @@ +pub trait Reader { + // FIXME (#2004): Seekable really should be orthogonal. + + /// Read up to len bytes (or EOF) and put them into bytes (which + /// must be at least len bytes long). Return number of bytes read. + // FIXME (#2982): This should probably return an error. + fn read(&self, bytes: &[mut u8], len: uint) -> uint; +} + +pub trait ReaderUtil { + + /// Read len bytes into a new vec. + fn read_bytes(&self, len: uint); +} + +impl T : ReaderUtil { + + fn read_bytes(&self, len: uint) { + let count = self.read(&[mut 0], len); + } + +} + +struct S { + x: int, + y: int +} + +impl S: Reader { + fn read(&self, bytes: &[mut u8], len: uint) -> uint { + 0 + } +} + +fn main() { + let x = S { x: 1, y: 2 }; + let x = x as @Reader; + x.read_bytes(0); +} diff --git a/src/test/run-pass/explicit-self-objects-ext-3.rs b/src/test/run-pass/explicit-self-objects-ext-3.rs new file mode 100644 index 0000000000000..521d5a7570188 --- /dev/null +++ b/src/test/run-pass/explicit-self-objects-ext-3.rs @@ -0,0 +1,39 @@ +pub trait Reader { + // FIXME (#2004): Seekable really should be orthogonal. + + /// Read up to len bytes (or EOF) and put them into bytes (which + /// must be at least len bytes long). Return number of bytes read. + // FIXME (#2982): This should probably return an error. + fn read(&self, bytes: &[mut u8], len: uint) -> uint; +} + +pub trait ReaderUtil { + + /// Read len bytes into a new vec. + fn read_bytes(len: uint); +} + +impl T : ReaderUtil { + + fn read_bytes(len: uint) { + let count = self.read(&[mut 0], len); + } + +} + +struct S { + x: int, + y: int +} + +impl S: Reader { + fn read(&self, bytes: &[mut u8], len: uint) -> uint { + 0 + } +} + +fn main() { + let x = S { x: 1, y: 2 }; + let x = x as @Reader; + x.read_bytes(0); +} diff --git a/src/test/run-pass/explicit-self-objects-ext-4.rs b/src/test/run-pass/explicit-self-objects-ext-4.rs new file mode 100644 index 0000000000000..759097a771b15 --- /dev/null +++ b/src/test/run-pass/explicit-self-objects-ext-4.rs @@ -0,0 +1,39 @@ +pub trait Reader { + // FIXME (#2004): Seekable really should be orthogonal. + + /// Read up to len bytes (or EOF) and put them into bytes (which + /// must be at least len bytes long). Return number of bytes read. + // FIXME (#2982): This should probably return an error. + fn read(bytes: &[mut u8], len: uint) -> uint; +} + +pub trait ReaderUtil { + + /// Read len bytes into a new vec. + fn read_bytes(len: uint); +} + +impl T : ReaderUtil { + + fn read_bytes(len: uint) { + let count = self.read(&[mut 0], len); + } + +} + +struct S { + x: int, + y: int +} + +impl S: Reader { + fn read(bytes: &[mut u8], len: uint) -> uint { + 0 + } +} + +fn main() { + let x = S { x: 1, y: 2 }; + let x = x as @Reader; + x.read_bytes(0); +}