about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Sullivan <sully@msully.net>2012-08-13 12:17:42 -0500
committerMichael Sullivan <sully@msully.net>2012-08-14 17:40:04 -0700
commite640a66eb494d991e570f9827e7b00122ea538b0 (patch)
tree08f1842c77d3f1219d98340158a36a35bda861e7
parent4c16ff516d97bb4a69ad965b93e6db61343be381 (diff)
downloadrust-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.rs2
-rw-r--r--src/libsyntax/parse/parser.rs24
-rw-r--r--src/rustc/metadata/decoder.rs17
-rw-r--r--src/rustc/metadata/encoder.rs18
-rw-r--r--src/rustc/middle/trans/impl.rs16
-rw-r--r--src/rustc/middle/typeck/check.rs40
-rw-r--r--src/rustc/middle/typeck/check/method.rs37
-rw-r--r--src/rustc/middle/typeck/check/regionmanip.rs13
-rw-r--r--src/rustc/middle/typeck/check/vtable.rs2
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,