From 00f97b9fb00160ffce41ea5c27627b4729b43f0f Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 19 Mar 2013 10:36:02 -0400 Subject: [PATCH 1/2] 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. Step towards fixing `fn(&self)` (cc #4846) to have a distinct lifetime. --- src/librustc/metadata/tydecode.rs | 3 ++- src/librustc/metadata/tyencode.rs | 4 ++- src/librustc/middle/trans/reflect.rs | 2 +- src/librustc/middle/trans/type_of.rs | 4 +-- src/librustc/middle/ty.rs | 25 ++++++++++--------- src/librustc/middle/typeck/astconv.rs | 7 +++--- src/librustc/middle/typeck/check/method.rs | 7 ++---- src/librustc/middle/typeck/check/mod.rs | 12 +++------ .../middle/typeck/check/regionmanip.rs | 2 +- src/librustc/middle/typeck/coherence.rs | 2 +- src/librustc/util/ppaux.rs | 2 +- src/libsyntax/ast.rs | 2 +- 12 files changed, 34 insertions(+), 38 deletions(-) diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index c87b09cde0856..f12cc140d8ab9 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -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)), diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 56a9683762343..880d01d1cdb50 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -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) => { diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index c6bf8ff3a3a2b..41e63cc878e13 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -297,7 +297,7 @@ pub impl Reflector { 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) => { diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs index 785a31836767b..a7bec5547c4a3 100644 --- a/src/librustc/middle/trans/type_of.rs +++ b/src/librustc/middle/trans/type_of.rs @@ -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") diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index fc634f91ccf5f..e50fd7b10cc4d 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -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 mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option) -> t { &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_sty(sty: &sty, fldop: &fn(t) -> t) -> sty { } 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, 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 @@ pub fn 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 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { 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 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { v.args.foldl(0, |s, a| *s + type_size(cx, *a)))) } - ty_param(_) | ty_self => { + ty_param(_) | ty_self(_) => { 1 } @@ -2220,7 +2221,7 @@ pub fn is_instantiable(cx: ctxt, r_ty: t) -> bool { 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" } } diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index b49c8c2bff861..e259fdaf400e4 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -64,7 +64,7 @@ use middle::typeck::{CrateCtxt, write_substs_to_tcx, write_ty_to_tcx}; 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 @@ pub fn ast_ty_to_ty( 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, diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index 63a210f84ebc1..cb626dc85e0ae 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -307,12 +307,9 @@ pub impl LookupContext/&self { 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 @@ pub impl LookupContext/&self { 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(*) => { diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 2d35fc17ede84..d79e71a926e3c 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -183,9 +183,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, ret_ty: ty::t, // Used by loop bodies that return from the outer function indirect_ret_ty: Option, @@ -236,7 +233,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 +328,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, @@ -605,7 +600,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, local_def(it.id)); } } } @@ -1699,9 +1695,7 @@ pub fn check_expr_with_unifier(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); } diff --git a/src/librustc/middle/typeck/check/regionmanip.rs b/src/librustc/middle/typeck/check/regionmanip.rs index ffdd40c6cd8ca..a76a7f08f0e31 100644 --- a/src/librustc/middle/typeck/check/regionmanip.rs +++ b/src/librustc/middle/typeck/check/regionmanip.rs @@ -48,7 +48,7 @@ pub fn replace_bound_regions_in_fn_sig( _}, _}) => { let region = ty::re_bound(ty::br_self); let ty = ty::mk_rptr(tcx, region, - ty::mt { ty: ty::mk_self(tcx), mutbl: m }); + ty::mt { ty: ty::mk_nil(tcx), mutbl: m }); all_tys.push(ty); } _ => {} diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 620d64fd58e3d..d4bf95bb8bba0 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -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 %?", diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index d8636470555b3..c332d3ac6744d 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -443,7 +443,7 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~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()); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index a2d82bb8ccd32..22ec88cd45625 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -185,7 +185,7 @@ pub enum def { /* trait */ Option, 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), From ad70c748c35958f8afdc70cf67054dd1968e4b78 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 19 Mar 2013 11:58:59 -0400 Subject: [PATCH 2/2] Apply explicit self transformation before we enter check_fn --- src/librustc/middle/typeck/check/mod.rs | 53 ++++++------------- .../middle/typeck/check/regionmanip.rs | 14 +---- src/librustc/middle/typeck/check/writeback.rs | 4 +- 3 files changed, 21 insertions(+), 50 deletions(-) diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index d79e71a926e3c..472e042d12841 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -144,8 +144,7 @@ pub mod method; 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 @@ -339,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); @@ -495,20 +475,25 @@ pub fn check_fn(ccx: @mut CrateCtxt, 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 ); } @@ -545,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(); @@ -589,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) => { @@ -601,7 +582,7 @@ pub fn check_item(ccx: @mut CrateCtxt, it: @ast::item) { } provided(m) => { let self_ty = ty::mk_self(ccx.tcx, local_def(it.id)); - check_method(ccx, m, self_ty, local_def(it.id)); + check_method(ccx, m, self_ty); } } } diff --git a/src/librustc/middle/typeck/check/regionmanip.rs b/src/librustc/middle/typeck/check/regionmanip.rs index a76a7f08f0e31..c78a91b95e4bb 100644 --- a/src/librustc/middle/typeck/check/regionmanip.rs +++ b/src/librustc/middle/typeck/check/regionmanip.rs @@ -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_nil(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) } diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs index 5cfb7973b96a0..18f232379169f 100644 --- a/src/librustc/middle/typeck/check/writeback.rs +++ b/src/librustc/middle/typeck/check/writeback.rs @@ -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| {