Make most forms of explicit self work. By-value not implemented. Work on #2585.
This commit is contained in:
parent
4c16ff516d
commit
e640a66eb4
@ -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`
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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};
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user