From 3333b0f1177fd758cfd95d992aed18972ed26dfb Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 29 Mar 2013 16:02:55 -0400 Subject: [PATCH] Add a (currently unused) "transformed self type" pointer into ty::method --- src/librustc/metadata/common.rs | 1 + src/librustc/metadata/decoder.rs | 19 +++++- src/librustc/metadata/encoder.rs | 12 ++++ src/librustc/middle/ty.rs | 1 + src/librustc/middle/typeck/astconv.rs | 87 ++++++++++++++++++++++++-- src/librustc/middle/typeck/collect.rs | 53 +++++++++------- src/test/run-pass/regions-expl-self.rs | 2 +- 7 files changed, 144 insertions(+), 31 deletions(-) diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs index d3b06009d72..5df7b037334 100644 --- a/src/librustc/metadata/common.rs +++ b/src/librustc/metadata/common.rs @@ -162,6 +162,7 @@ pub enum astencode_tag { // Reserves 0x50 -- 0x6f pub static tag_item_method_tps: uint = 0x7b; pub static tag_item_method_fty: uint = 0x7c; +pub static tag_item_method_transformed_self_ty: uint = 0x7d; pub struct LinkMeta { name: @str, diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 598539609e9..32a912d0101 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -236,6 +236,16 @@ fn doc_method_fty(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::BareFnTy { |_, did| translate_def_id(cdata, did)) } +fn doc_transformed_self_ty(doc: ebml::Doc, + tcx: ty::ctxt, + cdata: cmd) -> Option +{ + do reader::maybe_get_doc(doc, tag_item_method_transformed_self_ty).map |tp| { + parse_ty_data(tp.data, cdata.cnum, tp.start, tcx, + |_, did| translate_def_id(cdata, did)) + } +} + pub fn item_type(item_id: ast::def_id, item: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::t { let t = doc_type(item, tcx, cdata); @@ -716,14 +726,17 @@ pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::node_id, let method_doc = lookup_item(id, cdata.data); let def_id = item_def_id(method_doc, cdata); let name = item_name(intr, method_doc); - let bounds = item_ty_param_bounds(method_doc, tcx, cdata, - tag_item_method_tps); + let bounds = + item_ty_param_bounds(method_doc, tcx, cdata, + tag_item_method_tps); + let transformed_self_ty = doc_transformed_self_ty(method_doc, tcx, cdata); let fty = doc_method_fty(method_doc, tcx, cdata); let vis = item_visibility(method_doc); let self_ty = get_self_ty(method_doc); ty::method { ident: name, tps: bounds, + transformed_self_ty: transformed_self_ty, fty: fty, self_ty: self_ty, vis: vis, @@ -767,10 +780,12 @@ pub fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd, } }; + let transformed_self_ty = doc_transformed_self_ty(mth, tcx, cdata); let self_ty = get_self_ty(mth); let ty_method = ty::method { ident: name, tps: bounds, + transformed_self_ty: transformed_self_ty, fty: fty, self_ty: self_ty, vis: ast::public, diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 2e3008a0cdc..e8fc4c44fea 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -230,6 +230,17 @@ fn encode_type(ecx: @EncodeContext, ebml_w: writer::Encoder, typ: ty::t) { ebml_w.end_tag(); } +fn encode_transformed_self_ty(ecx: @EncodeContext, + ebml_w: writer::Encoder, + opt_typ: Option) +{ + for opt_typ.each |&typ| { + ebml_w.start_tag(tag_item_method_transformed_self_ty); + write_type(ecx, ebml_w, typ); + ebml_w.end_tag(); + } +} + fn encode_method_fty(ecx: @EncodeContext, ebml_w: writer::Encoder, typ: &ty::BareFnTy) @@ -570,6 +581,7 @@ fn encode_method_ty_fields(ecx: @EncodeContext, encode_name(ecx, ebml_w, method_ty.ident); encode_ty_type_param_bounds(ebml_w, ecx, method_ty.tps, tag_item_method_tps); + encode_transformed_self_ty(ecx, ebml_w, method_ty.transformed_self_ty); encode_method_fty(ecx, ebml_w, &method_ty.fty); encode_visibility(ebml_w, method_ty.vis); encode_self_type(ebml_w, method_ty.self_ty); diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index fcdd5a650af..eb9eec25c04 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -71,6 +71,7 @@ pub struct field { pub struct method { ident: ast::ident, tps: @~[param_bounds], + transformed_self_ty: Option, fty: BareFnTy, self_ty: ast::self_ty_, vis: ast::visibility, diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index c54e76b9c05..05a5e926f27 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -544,6 +544,29 @@ pub fn bound_lifetimes( bound_lifetime_names } +struct SelfInfo { + untransformed_self_ty: ty::t, + self_transform: ast::self_ty +} + +pub fn ty_of_method( + self: &AC, + rscope: &RS, + purity: ast::purity, + lifetimes: &OptVec, + untransformed_self_ty: ty::t, + self_transform: ast::self_ty, + decl: &ast::fn_decl) -> (Option, ty::BareFnTy) +{ + let self_info = SelfInfo { + untransformed_self_ty: untransformed_self_ty, + self_transform: self_transform + }; + let (a, b) = ty_of_method_or_bare_fn( + self, rscope, purity, AbiSet::Rust(), lifetimes, Some(&self_info), decl); + (a.get(), b) +} + pub fn ty_of_bare_fn( self: &AC, rscope: &RS, @@ -551,6 +574,20 @@ pub fn ty_of_bare_fn( abi: AbiSet, lifetimes: &OptVec, decl: &ast::fn_decl) -> ty::BareFnTy +{ + let (_, b) = ty_of_method_or_bare_fn( + self, rscope, purity, abi, lifetimes, None, decl); + b +} + +fn ty_of_method_or_bare_fn( + self: &AC, + rscope: &RS, + purity: ast::purity, + abi: AbiSet, + lifetimes: &OptVec, + opt_self_info: Option<&SelfInfo>, + decl: &ast::fn_decl) -> (Option>, ty::BareFnTy) { debug!("ty_of_bare_fn"); @@ -559,18 +596,56 @@ pub fn ty_of_bare_fn( let bound_lifetime_names = bound_lifetimes(self, lifetimes); let rb = in_binding_rscope(rscope, RegionParamNames(copy bound_lifetime_names)); + let opt_transformed_self_ty = opt_self_info.map(|&self_info| { + transform_self_ty(self, &rb, self_info) + }); + let input_tys = decl.inputs.map(|a| ty_of_arg(self, &rb, *a, None)); + let output_ty = match decl.output.node { ast::ty_infer => self.ty_infer(decl.output.span), _ => ast_ty_to_ty(self, &rb, decl.output) }; - ty::BareFnTy { - purity: purity, - abis: abi, - sig: ty::FnSig {bound_lifetime_names: bound_lifetime_names, - inputs: input_tys, - output: output_ty} + return (opt_transformed_self_ty, + ty::BareFnTy { + purity: purity, + abis: abi, + sig: ty::FnSig {bound_lifetime_names: bound_lifetime_names, + inputs: input_tys, + output: output_ty} + }); + + fn transform_self_ty( + self: &AC, + rscope: &RS, + self_info: &SelfInfo) -> Option + { + match self_info.self_transform.node { + ast::sty_static => None, + ast::sty_value => { + Some(self_info.untransformed_self_ty) + } + ast::sty_region(lifetime, mutability) => { + let region = + ast_region_to_region(self, rscope, + self_info.self_transform.span, + lifetime); + Some(ty::mk_rptr(self.tcx(), region, + ty::mt {ty: self_info.untransformed_self_ty, + mutbl: mutability})) + } + ast::sty_box(mutability) => { + Some(ty::mk_box(self.tcx(), + ty::mt {ty: self_info.untransformed_self_ty, + mutbl: mutability})) + } + ast::sty_uniq(mutability) => { + Some(ty::mk_uniq(self.tcx(), + ty::mt {ty: self_info.untransformed_self_ty, + mutbl: mutability})) + } + } } } diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 3ac3766e89d..81acae1d3a9 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -237,15 +237,17 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, for ms.each |m| { let ty_method = @match m { &ast::required(ref m) => { - ty_method_of_trait_method(ccx, region_paramd, generics, - &m.id, &m.ident, &m.self_ty, - &m.generics, &m.purity, &m.decl) + ty_method_of_trait_method( + ccx, trait_id, region_paramd, generics, + &m.id, &m.ident, &m.self_ty, + &m.generics, &m.purity, &m.decl) } &ast::provided(ref m) => { - ty_method_of_trait_method(ccx, region_paramd, generics, - &m.id, &m.ident, &m.self_ty, - &m.generics, &m.purity, &m.decl) + ty_method_of_trait_method( + ccx, trait_id, region_paramd, generics, + &m.id, &m.ident, &m.self_ty, + &m.generics, &m.purity, &m.decl) } }; @@ -316,6 +318,7 @@ fn make_static_method_ty(ccx: &CrateCtxt, } fn ty_method_of_trait_method(self: &CrateCtxt, + trait_id: ast::node_id, trait_rp: Option, trait_generics: &ast::Generics, m_id: &ast::node_id, @@ -325,16 +328,16 @@ fn ty_method_of_trait_method(self: &CrateCtxt, m_purity: &ast::purity, m_decl: &ast::fn_decl) -> ty::method { + let trait_self_ty = ty::mk_self(self.tcx, local_def(trait_id)); let rscope = MethodRscope::new(m_self_ty.node, trait_rp, trait_generics); + let (transformed_self_ty, fty) = + astconv::ty_of_method(self, &rscope, *m_purity, &m_generics.lifetimes, + trait_self_ty, *m_self_ty, m_decl); ty::method { ident: *m_ident, tps: ty_param_bounds(self, m_generics), - fty: astconv::ty_of_bare_fn(self, - &rscope, - *m_purity, - AbiSet::Rust(), - &m_generics.lifetimes, - m_decl), + transformed_self_ty: transformed_self_ty, + fty: fty, self_ty: m_self_ty.node, // assume public, because this is only invoked on trait methods vis: ast::public, @@ -607,6 +610,7 @@ pub struct ConvertedMethod { pub fn convert_methods(ccx: &CrateCtxt, ms: &[@ast::method], rp: Option, + untransformed_rcvr_ty: ty::t, rcvr_bounds: @~[ty::param_bounds], rcvr_generics: &ast::Generics, rcvr_visibility: ast::visibility) @@ -615,8 +619,9 @@ pub fn convert_methods(ccx: &CrateCtxt, let tcx = ccx.tcx; return vec::map(ms, |m| { let bounds = ty_param_bounds(ccx, &m.generics); - let mty = @ty_of_method(ccx, *m, rp, rcvr_generics, - rcvr_visibility, &m.generics); + let mty = @ty_of_method( + ccx, *m, rp, untransformed_rcvr_ty, + rcvr_generics, rcvr_visibility, &m.generics); let fty = ty::mk_bare_fn(tcx, copy mty.fty); tcx.tcache.insert( local_def(m.id), @@ -637,6 +642,7 @@ pub fn convert_methods(ccx: &CrateCtxt, fn ty_of_method(ccx: &CrateCtxt, m: @ast::method, rp: Option, + untransformed_rcvr_ty: ty::t, rcvr_generics: &ast::Generics, rcvr_visibility: ast::visibility, method_generics: &ast::Generics) -> ty::method @@ -644,15 +650,16 @@ fn ty_of_method(ccx: &CrateCtxt, let rscope = MethodRscope::new(m.self_ty.node, rp, rcvr_generics); + let (transformed_self_ty, fty) = + astconv::ty_of_method(ccx, &rscope, m.purity, + &method_generics.lifetimes, + untransformed_rcvr_ty, + m.self_ty, &m.decl); ty::method { ident: m.ident, tps: ty_param_bounds(ccx, &m.generics), - fty: astconv::ty_of_bare_fn(ccx, - &rscope, - m.purity, - ast::RustAbi, - &method_generics.lifetimes, - &m.decl), + transformed_self_ty: transformed_self_ty, + fty: fty, self_ty: m.self_ty.node, vis: m.vis.inherit_from(rcvr_visibility), def_id: local_def(m.id) @@ -715,7 +722,7 @@ pub fn convert(ccx: &CrateCtxt, it: @ast::item) { it.vis }; - let cms = convert_methods(ccx, *ms, rp, i_bounds, generics, + let cms = convert_methods(ccx, *ms, rp, selfty, i_bounds, generics, parent_visibility); for opt_trait_ref.each |t| { check_methods_against_trait(ccx, generics, rp, selfty, *t, cms); @@ -732,7 +739,9 @@ pub fn convert(ccx: &CrateCtxt, it: @ast::item) { let (_, provided_methods) = split_trait_methods(*trait_methods); let (bounds, _) = mk_substs(ccx, generics, rp); - let _ = convert_methods(ccx, provided_methods, rp, bounds, generics, + let untransformed_rcvr_ty = ty::mk_self(tcx, local_def(it.id)); + let _ = convert_methods(ccx, provided_methods, rp, + untransformed_rcvr_ty, bounds, generics, it.vis); } ast::item_struct(struct_def, ref generics) => { diff --git a/src/test/run-pass/regions-expl-self.rs b/src/test/run-pass/regions-expl-self.rs index 05f0994c765..174b9a206cc 100644 --- a/src/test/run-pass/regions-expl-self.rs +++ b/src/test/run-pass/regions-expl-self.rs @@ -15,7 +15,7 @@ struct Foo { } pub impl Foo { - fn foo(&'a self) {} + fn foo<'a>(&'a self) {} } pub fn main() {} \ No newline at end of file -- GitLab