auto merge of #5435 : nikomatsakis/rust/issue-4846-refactor-self_info, r=nikomatsakis
Refactor the self-info so that the def-id is carried in ty_self()and the fn_ctxt doesn't need any self_info field at all. Pull out explicit self transformation into `check_method`. Step towards fixing `fn(&self)` to have a distinct lifetime. (cc #4846) r? @catamorphism
This commit is contained in:
commit
c202430687
@ -289,7 +289,8 @@ fn parse_ty(st: @mut PState, conv: conv_did) -> ty::t {
|
||||
return ty::mk_param(st.tcx, parse_int(st) as uint, did);
|
||||
}
|
||||
's' => {
|
||||
return ty::mk_self(st.tcx);
|
||||
let did = parse_def(st, TypeParameter, conv);
|
||||
return ty::mk_self(st.tcx, did);
|
||||
}
|
||||
'@' => return ty::mk_box(st.tcx, parse_mt(st, conv)),
|
||||
'~' => return ty::mk_uniq(st.tcx, parse_mt(st, conv)),
|
||||
|
@ -312,8 +312,10 @@ fn enc_sty(w: @io::Writer, cx: @ctxt, +st: ty::sty) {
|
||||
w.write_char('|');
|
||||
w.write_str(uint::to_str(id));
|
||||
}
|
||||
ty::ty_self => {
|
||||
ty::ty_self(did) => {
|
||||
w.write_char('s');
|
||||
w.write_str((cx.ds)(did));
|
||||
w.write_char('|');
|
||||
}
|
||||
ty::ty_type => w.write_char('Y'),
|
||||
ty::ty_opaque_closure_ptr(p) => {
|
||||
|
@ -297,7 +297,7 @@ fn visit_ty(&mut self, t: ty::t) {
|
||||
let extra = ~[self.c_uint(p.idx)];
|
||||
self.visit(~"param", extra)
|
||||
}
|
||||
ty::ty_self => self.leaf(~"self"),
|
||||
ty::ty_self(*) => self.leaf(~"self"),
|
||||
ty::ty_type => self.leaf(~"type"),
|
||||
ty::ty_opaque_box => self.leaf(~"opaque_box"),
|
||||
ty::ty_opaque_closure_ptr(ck) => {
|
||||
|
@ -144,7 +144,7 @@ pub fn sizing_type_of(cx: @CrateContext, t: ty::t) -> TypeRef {
|
||||
T_struct(adt::sizing_fields_of(cx, repr))
|
||||
}
|
||||
|
||||
ty::ty_self | ty::ty_infer(*) | ty::ty_param(*) | ty::ty_err(*) => {
|
||||
ty::ty_self(_) | ty::ty_infer(*) | ty::ty_param(*) | ty::ty_err(*) => {
|
||||
cx.tcx.sess.bug(
|
||||
fmt!("fictitious type %? in sizing_type_of()",
|
||||
ty::get(t).sty))
|
||||
@ -251,7 +251,7 @@ pub fn type_of(cx: @CrateContext, t: ty::t) -> TypeRef {
|
||||
did,
|
||||
/*bad*/ copy substs.tps))
|
||||
}
|
||||
ty::ty_self => cx.tcx.sess.unimpl(~"type_of: ty_self"),
|
||||
ty::ty_self(*) => cx.tcx.sess.unimpl(~"type_of: ty_self"),
|
||||
ty::ty_infer(*) => cx.tcx.sess.bug(~"type_of with ty_infer"),
|
||||
ty::ty_param(*) => cx.tcx.sess.bug(~"type_of with ty_param"),
|
||||
ty::ty_err(*) => cx.tcx.sess.bug(~"type_of with ty_err")
|
||||
|
@ -522,7 +522,8 @@ pub enum sty {
|
||||
ty_tup(~[t]),
|
||||
|
||||
ty_param(param_ty), // type parameter
|
||||
ty_self, // special, implicit `self` type parameter
|
||||
ty_self(def_id), /* special, implicit `self` type parameter;
|
||||
* def_id is the id of the trait */
|
||||
|
||||
ty_infer(InferTy), // something used only during inference/typeck
|
||||
ty_err, // Also only used during inference/typeck, to represent
|
||||
@ -897,7 +898,7 @@ fn sflags(substs: &substs) -> uint {
|
||||
&ty_err => flags |= has_ty_err as uint,
|
||||
&ty_param(_) => flags |= has_params as uint,
|
||||
&ty_infer(_) => flags |= needs_infer as uint,
|
||||
&ty_self => flags |= has_self as uint,
|
||||
&ty_self(_) => flags |= has_self as uint,
|
||||
&ty_enum(_, ref substs) | &ty_struct(_, ref substs) |
|
||||
&ty_trait(_, ref substs, _) => {
|
||||
flags |= sflags(substs);
|
||||
@ -1082,7 +1083,7 @@ pub fn mk_float_var(cx: ctxt, v: FloatVid) -> t { mk_infer(cx, FloatVar(v)) }
|
||||
|
||||
pub fn mk_infer(cx: ctxt, +it: InferTy) -> t { mk_t(cx, ty_infer(it)) }
|
||||
|
||||
pub fn mk_self(cx: ctxt) -> t { mk_t(cx, ty_self) }
|
||||
pub fn mk_self(cx: ctxt, did: ast::def_id) -> t { mk_t(cx, ty_self(did)) }
|
||||
|
||||
pub fn mk_param(cx: ctxt, n: uint, k: def_id) -> t {
|
||||
mk_t(cx, ty_param(param_ty { idx: n, def_id: k }))
|
||||
@ -1163,7 +1164,7 @@ pub fn maybe_walk_ty(ty: t, f: &fn(t) -> bool) {
|
||||
if !f(ty) { return; }
|
||||
match get(ty).sty {
|
||||
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
|
||||
ty_estr(_) | ty_type | ty_opaque_box | ty_self |
|
||||
ty_estr(_) | ty_type | ty_opaque_box | ty_self(_) |
|
||||
ty_opaque_closure_ptr(_) | ty_infer(_) | ty_param(_) | ty_err => {
|
||||
}
|
||||
ty_box(ref tm) | ty_evec(ref tm, _) | ty_unboxed_vec(ref tm) |
|
||||
@ -1250,7 +1251,7 @@ fn fold_substs(substs: &substs, fldop: &fn(t) -> t) -> substs {
|
||||
}
|
||||
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
|
||||
ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) | ty_err |
|
||||
ty_opaque_box | ty_infer(_) | ty_param(*) | ty_self => {
|
||||
ty_opaque_box | ty_infer(_) | ty_param(*) | ty_self(_) => {
|
||||
/*bad*/copy *sty
|
||||
}
|
||||
}
|
||||
@ -1362,7 +1363,7 @@ pub fn subst_tps(cx: ctxt, tps: &[t], self_ty_opt: Option<t>, typ: t) -> t {
|
||||
if self_ty_opt.is_none() && !tbox_has_flag(tb, has_params) { return typ; }
|
||||
match tb.sty {
|
||||
ty_param(p) => tps[p.idx],
|
||||
ty_self => {
|
||||
ty_self(_) => {
|
||||
match self_ty_opt {
|
||||
None => cx.sess.bug(~"ty_self unexpected here"),
|
||||
Some(self_ty) => {
|
||||
@ -1424,7 +1425,7 @@ fn do_subst(cx: ctxt,
|
||||
if !tbox_has_flag(tb, needs_subst) { return typ; }
|
||||
match tb.sty {
|
||||
ty_param(p) => substs.tps[p.idx],
|
||||
ty_self => substs.self_ty.get(),
|
||||
ty_self(_) => substs.self_ty.get(),
|
||||
_ => {
|
||||
fold_regions_and_ty(
|
||||
cx, typ,
|
||||
@ -2002,7 +2003,7 @@ fn tc_ty(cx: ctxt,
|
||||
cx, cx.ty_param_bounds.get(&p.def_id.node))
|
||||
}
|
||||
|
||||
ty_self => {
|
||||
ty_self(_) => {
|
||||
// Currently, self is not bounded, so we must assume the
|
||||
// worst. But in the future we should examine the super
|
||||
// traits.
|
||||
@ -2159,7 +2160,7 @@ fn type_size(cx: ctxt, ty: t) -> uint {
|
||||
v.args.foldl(0, |s, a| *s + type_size(cx, *a))))
|
||||
}
|
||||
|
||||
ty_param(_) | ty_self => {
|
||||
ty_param(_) | ty_self(_) => {
|
||||
1
|
||||
}
|
||||
|
||||
@ -2220,7 +2221,7 @@ fn subtypes_require(cx: ctxt, seen: &mut ~[def_id],
|
||||
ty_infer(_) |
|
||||
ty_err |
|
||||
ty_param(_) |
|
||||
ty_self |
|
||||
ty_self(_) |
|
||||
ty_type |
|
||||
ty_opaque_box |
|
||||
ty_opaque_closure_ptr(_) |
|
||||
@ -2655,7 +2656,7 @@ impl to_bytes::IterBytes for sty {
|
||||
ty_bare_fn(ref ft) =>
|
||||
to_bytes::iter_bytes_2(&12u8, ft, lsb0, f),
|
||||
|
||||
ty_self => 13u8.iter_bytes(lsb0, f),
|
||||
ty_self(ref did) => to_bytes::iter_bytes_2(&13u8, did, lsb0, f),
|
||||
|
||||
ty_infer(ref v) =>
|
||||
to_bytes::iter_bytes_2(&14u8, v, lsb0, f),
|
||||
@ -3341,7 +3342,7 @@ pub fn ty_sort_str(cx: ctxt, t: t) -> ~str {
|
||||
ty_infer(IntVar(_)) => ~"integral variable",
|
||||
ty_infer(FloatVar(_)) => ~"floating-point variable",
|
||||
ty_param(_) => ~"type parameter",
|
||||
ty_self => ~"self",
|
||||
ty_self(_) => ~"self",
|
||||
ty_err => ~"type error"
|
||||
}
|
||||
}
|
||||
|
@ -64,7 +64,7 @@
|
||||
|
||||
use core::result;
|
||||
use core::vec;
|
||||
use syntax::ast;
|
||||
use syntax::{ast, ast_util};
|
||||
use syntax::codemap::span;
|
||||
use syntax::print::pprust::{lifetime_to_str, path_to_str};
|
||||
use syntax::parse::token::special_idents;
|
||||
@ -400,12 +400,13 @@ fn check_path_args(tcx: ty::ctxt,
|
||||
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
|
||||
ty::mk_param(tcx, n, id)
|
||||
}
|
||||
ast::def_self_ty(_) => {
|
||||
ast::def_self_ty(id) => {
|
||||
// n.b.: resolve guarantees that the self type only appears in a
|
||||
// trait, which we rely upon in various places when creating
|
||||
// substs
|
||||
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
|
||||
ty::mk_self(tcx)
|
||||
let did = ast_util::local_def(id);
|
||||
ty::mk_self(tcx, did)
|
||||
}
|
||||
_ => {
|
||||
tcx.sess.span_fatal(ast_ty.span,
|
||||
|
@ -307,12 +307,9 @@ fn push_inherent_candidates(&self, self_ty: ty::t) {
|
||||
self_ty, did, substs, store);
|
||||
self.push_inherent_impl_candidates_for_type(did);
|
||||
}
|
||||
ty_self => {
|
||||
ty_self(self_did) => {
|
||||
// Call is of the form "self.foo()" and appears in one
|
||||
// of a trait's default method implementations.
|
||||
let self_did = self.fcx.self_info.expect(
|
||||
~"self_impl_def_id is undefined (`self` may not \
|
||||
be in scope here").def_id;
|
||||
let substs = substs {
|
||||
self_r: None,
|
||||
self_ty: None,
|
||||
@ -932,7 +929,7 @@ fn search_for_autoptrd_method(
|
||||
ty_bare_fn(*) | ty_box(*) | ty_uniq(*) | ty_rptr(*) |
|
||||
ty_infer(IntVar(_)) |
|
||||
ty_infer(FloatVar(_)) |
|
||||
ty_self | ty_param(*) | ty_nil | ty_bot | ty_bool |
|
||||
ty_self(_) | ty_param(*) | ty_nil | ty_bot | ty_bool |
|
||||
ty_int(*) | ty_uint(*) |
|
||||
ty_float(*) | ty_enum(*) | ty_ptr(*) | ty_struct(*) | ty_tup(*) |
|
||||
ty_estr(*) | ty_evec(*) | ty_trait(*) | ty_closure(*) => {
|
||||
|
@ -144,8 +144,7 @@
|
||||
pub struct SelfInfo {
|
||||
self_ty: ty::t,
|
||||
self_id: ast::node_id,
|
||||
def_id: ast::def_id,
|
||||
explicit_self: ast::self_ty
|
||||
span: span
|
||||
}
|
||||
|
||||
/// Fields that are part of a `FnCtxt` which are inherited by
|
||||
@ -183,9 +182,6 @@ pub struct FnCtxt {
|
||||
// with any nested functions that capture the environment
|
||||
// (and with any functions whose environment is being captured).
|
||||
|
||||
// Refers to whichever `self` is in scope, even this FnCtxt is
|
||||
// for a nested closure that captures `self`
|
||||
self_info: Option<SelfInfo>,
|
||||
ret_ty: ty::t,
|
||||
// Used by loop bodies that return from the outer function
|
||||
indirect_ret_ty: Option<ty::t>,
|
||||
@ -236,7 +232,6 @@ pub fn blank_fn_ctxt(ccx: @mut CrateCtxt,
|
||||
// It's kind of a kludge to manufacture a fake function context
|
||||
// and statement context, but we might as well do write the code only once
|
||||
@mut FnCtxt {
|
||||
self_info: None,
|
||||
ret_ty: rty,
|
||||
indirect_ret_ty: None,
|
||||
purity: ast::pure_fn,
|
||||
@ -332,7 +327,6 @@ pub fn check_fn(ccx: @mut CrateCtxt,
|
||||
};
|
||||
|
||||
@mut FnCtxt {
|
||||
self_info: self_info,
|
||||
ret_ty: ret_ty,
|
||||
indirect_ret_ty: indirect_ret_ty,
|
||||
purity: purity,
|
||||
@ -344,25 +338,6 @@ pub fn check_fn(ccx: @mut CrateCtxt,
|
||||
}
|
||||
};
|
||||
|
||||
// Update the SelfInfo to contain an accurate self type (taking
|
||||
// into account explicit self).
|
||||
let self_info = do self_info.chain_ref |self_info| {
|
||||
// If the self type is sty_static, we don't have a self ty.
|
||||
if self_info.explicit_self.node == ast::sty_static {
|
||||
None
|
||||
} else {
|
||||
let in_scope_regions = fcx.in_scope_regions;
|
||||
let self_region = 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,
|
||||
TransformTypeNormally);
|
||||
Some(SelfInfo { self_ty: ty,.. *self_info })
|
||||
}
|
||||
};
|
||||
|
||||
gather_locals(fcx, decl, body, arg_tys, self_info);
|
||||
check_block(fcx, body);
|
||||
|
||||
@ -500,20 +475,25 @@ fn visit_item(_i: @ast::item, &&_e: (), _v: visit::vt<()>) { }
|
||||
|
||||
pub fn check_method(ccx: @mut CrateCtxt,
|
||||
method: @ast::method,
|
||||
self_ty: ty::t,
|
||||
self_impl_def_id: ast::def_id) {
|
||||
let self_info = SelfInfo {
|
||||
self_ty: self_ty,
|
||||
self_id: method.self_id,
|
||||
def_id: self_impl_def_id,
|
||||
explicit_self: method.self_ty
|
||||
self_ty: ty::t)
|
||||
{
|
||||
let self_info = if method.self_ty.node == ast::sty_static {None} else {
|
||||
let ty = method::transform_self_type_for_method(
|
||||
ccx.tcx,
|
||||
Some(ty::re_bound(ty::br_self)),
|
||||
self_ty,
|
||||
method.self_ty.node,
|
||||
TransformTypeNormally);
|
||||
Some(SelfInfo {self_ty: ty, self_id: method.self_id,
|
||||
span: method.self_ty.span})
|
||||
};
|
||||
|
||||
check_bare_fn(
|
||||
ccx,
|
||||
&method.decl,
|
||||
&method.body,
|
||||
method.id,
|
||||
Some(self_info)
|
||||
self_info
|
||||
);
|
||||
}
|
||||
|
||||
@ -550,11 +530,7 @@ pub fn check_struct(ccx: @mut CrateCtxt,
|
||||
let class_t = SelfInfo {
|
||||
self_ty: self_ty,
|
||||
self_id: dtor.node.self_id,
|
||||
def_id: local_def(id),
|
||||
explicit_self: spanned {
|
||||
node: ast::sty_by_ref,
|
||||
span: codemap::dummy_sp()
|
||||
}
|
||||
span: dtor.span,
|
||||
};
|
||||
// typecheck the dtor
|
||||
let dtor_dec = ast_util::dtor_dec();
|
||||
@ -594,7 +570,7 @@ pub fn check_item(ccx: @mut CrateCtxt, it: @ast::item) {
|
||||
*ccx.tcx.sess.str_of(it.ident), it.id, rp);
|
||||
let self_ty = ccx.to_ty(&rscope::type_rscope(rp), ty);
|
||||
for ms.each |m| {
|
||||
check_method(ccx, *m, self_ty, local_def(it.id));
|
||||
check_method(ccx, *m, self_ty);
|
||||
}
|
||||
}
|
||||
ast::item_trait(_, _, ref trait_methods) => {
|
||||
@ -605,7 +581,8 @@ pub fn check_item(ccx: @mut CrateCtxt, it: @ast::item) {
|
||||
// bodies to check.
|
||||
}
|
||||
provided(m) => {
|
||||
check_method(ccx, m, ty::mk_self(ccx.tcx), local_def(it.id));
|
||||
let self_ty = ty::mk_self(ccx.tcx, local_def(it.id));
|
||||
check_method(ccx, m, self_ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1699,9 +1676,7 @@ fn check_expr_fn(fcx: @mut FnCtxt,
|
||||
ty::determine_inherited_purity(copy fcx.purity, purity,
|
||||
fn_ty.sigil);
|
||||
|
||||
// We inherit the same self info as the enclosing scope,
|
||||
// since the function we're checking might capture `self`
|
||||
check_fn(fcx.ccx, fcx.self_info, inherited_purity,
|
||||
check_fn(fcx.ccx, None, inherited_purity,
|
||||
&fn_ty.sig, decl, body, fn_kind,
|
||||
fcx.in_scope_regions, fcx.inh);
|
||||
}
|
||||
|
@ -40,18 +40,8 @@ pub fn replace_bound_regions_in_fn_sig(
|
||||
|
||||
let mut all_tys = ty::tys_in_fn_sig(fn_sig);
|
||||
|
||||
match self_info {
|
||||
Some(SelfInfo {
|
||||
explicit_self: codemap::spanned {
|
||||
node: ast::sty_region(_, m),
|
||||
// FIXME(#4846) ------^ Use this lifetime instead of self
|
||||
_}, _}) => {
|
||||
let region = ty::re_bound(ty::br_self);
|
||||
let ty = ty::mk_rptr(tcx, region,
|
||||
ty::mt { ty: ty::mk_self(tcx), mutbl: m });
|
||||
all_tys.push(ty);
|
||||
}
|
||||
_ => {}
|
||||
for self_info.each |self_info| {
|
||||
all_tys.push(self_info.self_ty);
|
||||
}
|
||||
|
||||
for self_ty.each |t| { all_tys.push(*t) }
|
||||
|
@ -283,8 +283,8 @@ pub fn resolve_type_vars_in_fn(fcx: @mut FnCtxt,
|
||||
let visit = mk_visitor();
|
||||
(visit.visit_block)(blk, wbcx, visit);
|
||||
for self_info.each |self_info| {
|
||||
if self_info.explicit_self.node == ast::sty_static { break; }
|
||||
resolve_type_vars_for_node(wbcx, self_info.explicit_self.span,
|
||||
resolve_type_vars_for_node(wbcx,
|
||||
self_info.span,
|
||||
self_info.self_id);
|
||||
}
|
||||
for decl.inputs.each |arg| {
|
||||
|
@ -94,7 +94,7 @@ pub fn get_base_type(inference_context: @mut InferCtxt,
|
||||
|
||||
ty_nil | ty_bot | ty_bool | ty_int(*) | ty_uint(*) | ty_float(*) |
|
||||
ty_estr(*) | ty_evec(*) | ty_bare_fn(*) | ty_closure(*) | ty_tup(*) |
|
||||
ty_infer(*) | ty_param(*) | ty_self | ty_type | ty_opaque_box |
|
||||
ty_infer(*) | ty_param(*) | ty_self(*) | ty_type | ty_opaque_box |
|
||||
ty_opaque_closure_ptr(*) | ty_unboxed_vec(*) | ty_err | ty_box(_) |
|
||||
ty_uniq(_) | ty_ptr(_) | ty_rptr(_, _) => {
|
||||
debug!("(getting base type) no base type; found %?",
|
||||
|
@ -443,7 +443,7 @@ fn field_to_str(cx: ctxt, f: field) -> ~str {
|
||||
str::from_bytes(~[('a' as u8) + (id as u8)]))
|
||||
}
|
||||
}
|
||||
ty_self => ~"self",
|
||||
ty_self(*) => ~"self",
|
||||
ty_enum(did, ref substs) | ty_struct(did, ref substs) => {
|
||||
let path = ty::item_path(cx, did);
|
||||
let base = ast_map::path_to_str(path, cx.sess.intr());
|
||||
|
@ -185,7 +185,7 @@ pub enum def {
|
||||
/* trait */ Option<def_id>,
|
||||
purity),
|
||||
def_self(node_id, bool /* is_implicit */),
|
||||
def_self_ty(node_id),
|
||||
def_self_ty(/* trait id */ node_id),
|
||||
def_mod(def_id),
|
||||
def_foreign_mod(def_id),
|
||||
def_const(def_id),
|
||||
|
Loading…
Reference in New Issue
Block a user