diff options
| author | Michael Sullivan <sully@msully.net> | 2012-08-13 12:17:42 -0500 |
|---|---|---|
| committer | Michael Sullivan <sully@msully.net> | 2012-08-14 17:40:04 -0700 |
| commit | e640a66eb494d991e570f9827e7b00122ea538b0 (patch) | |
| tree | 08f1842c77d3f1219d98340158a36a35bda861e7 | |
| parent | 4c16ff516d97bb4a69ad965b93e6db61343be381 (diff) | |
| download | rust-e640a66eb494d991e570f9827e7b00122ea538b0.tar.gz rust-e640a66eb494d991e570f9827e7b00122ea538b0.zip | |
Make most forms of explicit self work. By-value not implemented. Work on #2585.
| -rw-r--r-- | src/libsyntax/ast.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 24 | ||||
| -rw-r--r-- | src/rustc/metadata/decoder.rs | 17 | ||||
| -rw-r--r-- | src/rustc/metadata/encoder.rs | 18 | ||||
| -rw-r--r-- | src/rustc/middle/trans/impl.rs | 16 | ||||
| -rw-r--r-- | src/rustc/middle/typeck/check.rs | 40 | ||||
| -rw-r--r-- | src/rustc/middle/typeck/check/method.rs | 37 | ||||
| -rw-r--r-- | src/rustc/middle/typeck/check/regionmanip.rs | 13 | ||||
| -rw-r--r-- | src/rustc/middle/typeck/check/vtable.rs | 2 |
9 files changed, 86 insertions, 83 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 57795e5d21c..39e116990dd 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -600,7 +600,7 @@ enum self_ty_ { sty_static, // no self: static method sty_by_ref, // old by-reference self: `` sty_value, // by-value self: `self` - sty_region(@region, mutability), // by-region self: `&self` + sty_region(mutability), // by-region self: `&self` sty_box(mutability), // by-managed-pointer self: `@self` sty_uniq(mutability) // by-unique-pointer self: `~self` } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index dd6e9f85312..feb19d6780c 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2300,29 +2300,7 @@ class parser { self.bump(); let mutability = self.parse_mutability(); self.expect_self_ident(); - - // Parse an explicit region, if possible. - let region_name; - match copy self.token { - token::BINOP(token::SLASH) => { - self.bump(); - match copy self.token { - token::IDENT(sid, false) => { - self.bump(); - region_name = some(self.get_str(sid)); - } - _ => { - region_name = none; - } - } - } - _ => { - region_name = none; - } - } - - let region = self.region_from_name(region_name); - self_ty = sty_region(region, mutability); + self_ty = sty_region(mutability); } else { self_ty = sty_by_ref; } diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs index 7dcbae048dd..379982f4a2d 100644 --- a/src/rustc/metadata/decoder.rs +++ b/src/rustc/metadata/decoder.rs @@ -598,22 +598,7 @@ fn get_self_ty(item: ebml::doc) -> ast::self_ty_ { 'v' => { return ast::sty_value; } '@' => { return ast::sty_box(get_mutability(string[1])); } '~' => { return ast::sty_uniq(get_mutability(string[1])); } - '&' => { - let mutability = get_mutability(string[1]); - - let region; - let region_doc = - ebml::get_doc(self_type_doc, - tag_item_trait_method_self_ty_region); - let region_string = str::from_bytes(ebml::doc_data(region_doc)); - if region_string == ~"" { - region = ast::re_anon; - } else { - region = ast::re_named(@region_string); - } - - return ast::sty_region(@{ id: 0, node: region }, mutability); - } + '&' => { return ast::sty_region(get_mutability(string[1])); } _ => { fail fmt!{"unknown self type code: `%c`", self_ty_kind as char}; } diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs index 161f5d9c09c..47414e48462 100644 --- a/src/rustc/metadata/encoder.rs +++ b/src/rustc/metadata/encoder.rs @@ -500,7 +500,7 @@ fn encode_self_type(ebml_w: ebml::writer, self_type: ast::self_ty_) { sty_static => { ch = 's' as u8; } sty_by_ref => { ch = 'r' as u8; } sty_value => { ch = 'v' as u8; } - sty_region(_, _) => { ch = '&' as u8; } + sty_region(_) => { ch = '&' as u8; } sty_box(_) => { ch = '@' as u8; } sty_uniq(_) => { ch = '~' as u8; } } @@ -509,27 +509,17 @@ fn encode_self_type(ebml_w: ebml::writer, self_type: ast::self_ty_) { // Encode mutability. match self_type { sty_static | sty_by_ref | sty_value => { /* No-op. */ } - sty_region(_, m_imm) | sty_box(m_imm) | sty_uniq(m_imm) => { + sty_region(m_imm) | sty_box(m_imm) | sty_uniq(m_imm) => { ebml_w.writer.write(&[ 'i' as u8 ]); } - sty_region(_, m_mutbl) | sty_box(m_mutbl) | sty_uniq(m_mutbl) => { + sty_region(m_mutbl) | sty_box(m_mutbl) | sty_uniq(m_mutbl) => { ebml_w.writer.write(&[ 'm' as u8 ]); } - sty_region(_, m_const) | sty_box(m_const) | sty_uniq(m_const) => { + sty_region(m_const) | sty_box(m_const) | sty_uniq(m_const) => { ebml_w.writer.write(&[ 'c' as u8 ]); } } - // Encode the region. - match self_type { - sty_region(region, _) => { - encode_region(ebml_w, *region); - } - sty_static | sty_by_ref | sty_value | sty_box(*) | sty_uniq(*) => { - // Nothing to do. - } - } - ebml_w.end_tag(); } diff --git a/src/rustc/middle/trans/impl.rs b/src/rustc/middle/trans/impl.rs index 9aa4f2ba97b..20e005d7c54 100644 --- a/src/rustc/middle/trans/impl.rs +++ b/src/rustc/middle/trans/impl.rs @@ -26,9 +26,23 @@ fn trans_impl(ccx: @crate_ctxt, path: path, name: ast::ident, for vec::each(methods) |m| { if m.tps.len() == 0u { let llfn = get_item_val(ccx, m.id); + let self_ty = ty::node_id_to_type(ccx.tcx, m.self_id); let self_arg = match m.self_ty.node { ast::sty_static => { no_self } - _ => { impl_self(ty::node_id_to_type(ccx.tcx, m.self_id)) } + ast::sty_box(_) => { + impl_self(ty::mk_imm_box(ccx.tcx, self_ty)) + } + ast::sty_uniq(_) => { + impl_self(ty::mk_imm_uniq(ccx.tcx, self_ty)) + } + // XXX: Is this right at all? + ast::sty_region(*) => { + impl_self(ty::mk_imm_ptr(ccx.tcx, self_ty)) + } + ast::sty_value => { + ccx.sess.unimpl(~"by value self type not implemented"); + } + ast::sty_by_ref => { impl_self(self_ty) } }; trans_fn(ccx, diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index ff588a586aa..5cb886a36f0 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -80,6 +80,7 @@ import std::map::str_hash; type self_info = { self_ty: ty::t, node_id: ast::node_id, + explicit_self: ast::self_ty_ }; type fn_ctxt_ = @@ -367,14 +368,20 @@ fn check_fn(ccx: @crate_ctxt, fn check_method(ccx: @crate_ctxt, method: @ast::method, self_info: self_info) { + check_bare_fn(ccx, method.decl, method.body, method.id, some(self_info)); } -fn check_class_member(ccx: @crate_ctxt, class_t: self_info, +fn check_class_member(ccx: @crate_ctxt, self_ty: ty::t, + node_id: ast::node_id, cm: @ast::class_member) { match cm.node { ast::instance_var(_,t,_,_,_) => (), - ast::class_method(m) => check_method(ccx, m, class_t) + ast::class_method(m) => { + let class_t = {self_ty: self_ty, node_id: node_id, + explicit_self: m.self_ty.node}; + check_method(ccx, m, class_t) + } } } @@ -404,9 +411,11 @@ fn check_no_duplicate_fields(tcx: ty::ctxt, fields: fn check_struct(ccx: @crate_ctxt, struct_def: @ast::struct_def, id: ast::node_id, span: span) { let tcx = ccx.tcx; - let class_t = {self_ty: ty::node_id_to_type(tcx, id), node_id: id}; + let self_ty = ty::node_id_to_type(tcx, id); do option::iter(struct_def.ctor) |ctor| { + let class_t = {self_ty: self_ty, node_id: id, + explicit_self: ast::sty_by_ref}; // typecheck the ctor check_bare_fn(ccx, ctor.node.dec, ctor.node.body, ctor.node.id, @@ -416,6 +425,8 @@ fn check_struct(ccx: @crate_ctxt, struct_def: @ast::struct_def, } do option::iter(struct_def.dtor) |dtor| { + let class_t = {self_ty: self_ty, node_id: id, + explicit_self: ast::sty_by_ref}; // typecheck the dtor check_bare_fn(ccx, ast_util::dtor_dec(), dtor.node.body, dtor.node.id, @@ -426,7 +437,7 @@ fn check_struct(ccx: @crate_ctxt, struct_def: @ast::struct_def, // typecheck the members for struct_def.members.each |m| { - check_class_member(ccx, class_t, m); + check_class_member(ccx, self_ty, id, m); } // Check that there's at least one field let (fields,_) = split_class_items(struct_def.members); @@ -450,9 +461,12 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) { let rp = ccx.tcx.region_paramd_items.contains_key(it.id); debug!{"item_impl %s with id %d rp %b", *it.ident, it.id, rp}; - let self_info = {self_ty: ccx.to_ty(rscope::type_rscope(rp), ty), - node_id: it.id }; - for ms.each |m| { check_method(ccx, m, self_info);} + let self_ty = ccx.to_ty(rscope::type_rscope(rp), ty); + for ms.each |m| { + let self_info = {self_ty: self_ty, node_id: it.id, + explicit_self: m.self_ty.node }; + check_method(ccx, m, self_info) + } } ast::item_trait(_, _, trait_methods) => { for trait_methods.each |trait_method| { @@ -463,7 +477,8 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) { } provided(m) => { let self_info = {self_ty: ty::mk_self(ccx.tcx), - node_id: it.id}; + node_id: it.id, + explicit_self: m.self_ty.node}; check_method(ccx, m, self_info); } } @@ -742,7 +757,8 @@ fn check_expr(fcx: @fn_ctxt, expr: @ast::expr, // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]` // would return ($0, $1) where $0 and $1 are freshly instantiated type // variables. -fn impl_self_ty(fcx: @fn_ctxt, did: ast::def_id) -> ty_param_substs_and_ty { +fn impl_self_ty(fcx: @fn_ctxt, did: ast::def_id, require_rp: bool) + -> ty_param_substs_and_ty { let tcx = fcx.ccx.tcx; let {n_tps, rp, raw_ty} = if did.crate == ast::local_crate { @@ -778,6 +794,7 @@ fn impl_self_ty(fcx: @fn_ctxt, did: ast::def_id) -> ty_param_substs_and_ty { raw_ty: ity.ty} }; + let rp = rp || require_rp; let self_r = if rp {some(fcx.infcx.next_region_var_nb())} else {none}; let tps = fcx.infcx.next_ty_vars(n_tps); @@ -2216,7 +2233,10 @@ fn ty_param_bounds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) -> ast::def_self(_) => { match fcx.self_info { some(self_info) => { - return no_params(self_info.self_ty); + let self_region = fcx.in_scope_regions.find(ty::br_self); + return no_params(method::transform_self_type_for_method( + fcx.tcx(), self_region, + self_info.self_ty, self_info.explicit_self)); } none => { fcx.ccx.tcx.sess.span_bug(sp, ~"def_self with no self_info"); diff --git a/src/rustc/middle/typeck/check/method.rs b/src/rustc/middle/typeck/check/method.rs index b069745d543..c5d3dd765ab 100644 --- a/src/rustc/middle/typeck/check/method.rs +++ b/src/rustc/middle/typeck/check/method.rs @@ -20,28 +20,30 @@ type candidate = { entry: method_map_entry }; -fn transform_self_type_for_method(fcx: @fn_ctxt, - impl_ty: ty::t, - method_info: MethodInfo) +fn transform_self_type_for_method + (tcx: ty::ctxt, + self_region: option<ty::region>, + impl_ty: ty::t, + self_type: ast::self_ty_) -> ty::t { - match method_info.self_type { + match self_type { sty_static => { - fcx.tcx().sess.bug(~"calling transform_self_type_for_method on \ - static method"); + tcx.sess.bug(~"calling transform_self_type_for_method on \ + static method"); } sty_by_ref | sty_value => { impl_ty } - sty_region(r, mutability) => { - // XXX: dummy_sp is unfortunate here. - let region = ast_region_to_region(fcx, fcx, dummy_sp(), r); - mk_rptr(fcx.ccx.tcx, region, { ty: impl_ty, mutbl: mutability }) + sty_region(mutability) => { + mk_rptr(tcx, + self_region.expect(~"self region missing for &self param"), + { ty: impl_ty, mutbl: mutability }) } sty_box(mutability) => { - mk_box(fcx.ccx.tcx, { ty: impl_ty, mutbl: mutability }) + mk_box(tcx, { ty: impl_ty, mutbl: mutability }) } sty_uniq(mutability) => { - mk_uniq(fcx.ccx.tcx, { ty: impl_ty, mutbl: mutability }) + mk_uniq(tcx, { ty: impl_ty, mutbl: mutability }) } } } @@ -368,14 +370,17 @@ class lookup { // Check whether this impl has a method with the right name. for im.methods.find(|m| m.ident == self.m_name).each |m| { + let need_rp = match m.self_type { ast::sty_region(_) => true, + _ => false }; + // determine the `self` of the impl with fresh // variables for each parameter: let {substs: impl_substs, ty: impl_ty} = - impl_self_ty(self.fcx, im.did); + impl_self_ty(self.fcx, im.did, need_rp); - let impl_ty = transform_self_type_for_method(self.fcx, - impl_ty, - *m); + let impl_ty = transform_self_type_for_method( + self.tcx(), impl_substs.self_r, + impl_ty, m.self_type); // Depending on our argument, we find potential // matches either by checking subtypability or diff --git a/src/rustc/middle/typeck/check/regionmanip.rs b/src/rustc/middle/typeck/check/regionmanip.rs index 401b07031be..75f5ca3cbd8 100644 --- a/src/rustc/middle/typeck/check/regionmanip.rs +++ b/src/rustc/middle/typeck/check/regionmanip.rs @@ -22,6 +22,17 @@ fn replace_bound_regions_in_fn_ty( let mut all_tys = ty::tys_in_fn_ty(fn_ty); + match self_info { + some({explicit_self: ast::sty_region(m), _}) => { + let region = ty::re_bound(ty::br_self); + let ty = ty::mk_rptr(tcx, region, + { ty: ty::mk_self(tcx), mutbl: m }); + vec::push(all_tys, ty); + } + _ => {} + } + + for self_ty.each |t| { vec::push(all_tys, t) } debug!{"replace_bound_regions_in_fn_ty(self_info.self_ty=%?, fn_ty=%s, \ @@ -50,7 +61,7 @@ fn replace_bound_regions_in_fn_ty( // Glue updated self_ty back together with its original node_id. let new_self_info = match self_info { some(s) => match check t_self { - some(t) => some({self_ty: t, node_id: s.node_id}) + some(t) => some({self_ty: t with s}) // this 'none' case shouldn't happen }, none => none diff --git a/src/rustc/middle/typeck/check/vtable.rs b/src/rustc/middle/typeck/check/vtable.rs index 84a5ec67be8..d509b26b841 100644 --- a/src/rustc/middle/typeck/check/vtable.rs +++ b/src/rustc/middle/typeck/check/vtable.rs @@ -146,7 +146,7 @@ fn lookup_vtable(fcx: @fn_ctxt, sp: span, ty: ty::t, trait_ty: ty::t, // check whether the type unifies with the type // that the impl is for, and continue if not let {substs: substs, ty: for_ty} = - impl_self_ty(fcx, im.did); + impl_self_ty(fcx, im.did, false); let im_bs = ty::lookup_item_type(tcx, im.did).bounds; match fcx.mk_subty(ty, for_ty) { result::err(_) => again, |
