From fb8786fe522ed96172cf1ae8e205e3f2722e834c Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 7 Sep 2012 07:37:19 -0700 Subject: [PATCH] Refactor fn_ty, working towards #3320 --- src/rustc/metadata/decoder.rs | 2 +- src/rustc/metadata/encoder.rs | 2 +- src/rustc/metadata/tydecode.rs | 15 +- src/rustc/metadata/tyencode.rs | 14 +- src/rustc/middle/borrowck/check_loans.rs | 4 +- src/rustc/middle/lint.rs | 2 +- src/rustc/middle/trans/base.rs | 6 +- src/rustc/middle/trans/closure.rs | 20 +- src/rustc/middle/trans/expr.rs | 13 +- src/rustc/middle/trans/foreign.rs | 40 +-- src/rustc/middle/trans/monomorphize.rs | 52 +-- src/rustc/middle/trans/reflect.rs | 18 +- src/rustc/middle/trans/shape.rs | 295 ++++++++-------- src/rustc/middle/trans/type_use.rs | 4 +- src/rustc/middle/tstate/auxiliary.rs | 16 +- src/rustc/middle/ty.rs | 326 ++++++++++-------- src/rustc/middle/typeck.rs | 62 ++-- src/rustc/middle/typeck/astconv.rs | 13 +- src/rustc/middle/typeck/check.rs | 96 +++--- src/rustc/middle/typeck/check/method.rs | 18 +- src/rustc/middle/typeck/check/regionck.rs | 11 +- src/rustc/middle/typeck/check/regionmanip.rs | 4 +- src/rustc/middle/typeck/collect.rs | 55 +-- src/rustc/middle/typeck/infer.rs | 24 +- src/rustc/middle/typeck/infer/combine.rs | 57 +-- src/rustc/middle/typeck/infer/glb.rs | 10 +- src/rustc/middle/typeck/infer/lattice.rs | 4 +- src/rustc/middle/typeck/infer/lub.rs | 10 +- .../typeck/infer/region_var_bindings.rs | 38 +- src/rustc/middle/typeck/infer/resolve.rs | 10 +- src/rustc/middle/typeck/infer/sub.rs | 10 +- src/rustc/middle/typeck/infer/unify.rs | 16 +- src/rustc/util/ppaux.rs | 11 +- 33 files changed, 704 insertions(+), 574 deletions(-) diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs index 4e2c7b8ee72..b738295d262 100644 --- a/src/rustc/metadata/decoder.rs +++ b/src/rustc/metadata/decoder.rs @@ -585,7 +585,7 @@ fn get_enum_variants(intr: ident_interner, cdata: cmd, id: ast::node_id, let mut arg_tys: ~[ty::t] = ~[]; match ty::get(ctor_ty).struct { ty::ty_fn(f) => { - for f.inputs.each |a| { vec::push(arg_tys, a.ty); } + for f.sig.inputs.each |a| { vec::push(arg_tys, a.ty); } } _ => { /* Nullary enum variant. */ } } diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs index b1b5e081a80..803c9967d0c 100644 --- a/src/rustc/metadata/encoder.rs +++ b/src/rustc/metadata/encoder.rs @@ -750,7 +750,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Writer, item: @item, encode_name(ecx, ebml_w, mty.ident); encode_type_param_bounds(ebml_w, ecx, ty_m.tps); encode_type(ecx, ebml_w, ty::mk_fn(tcx, mty.fty)); - encode_family(ebml_w, purity_fn_family(mty.fty.purity)); + encode_family(ebml_w, purity_fn_family(mty.fty.meta.purity)); encode_self_type(ebml_w, mty.self_ty); ebml_w.end_tag(); } diff --git a/src/rustc/metadata/tydecode.rs b/src/rustc/metadata/tydecode.rs index 24f706eeb46..8fe58a93824 100644 --- a/src/rustc/metadata/tydecode.rs +++ b/src/rustc/metadata/tydecode.rs @@ -9,6 +9,7 @@ use syntax::ast_util; use syntax::ast_util::respan; use middle::ty; use std::map::hashmap; +use ty::{FnTyBase, FnMeta, FnSig}; export parse_ty_data, parse_def_id, parse_ident; export parse_bounds_data; @@ -274,7 +275,7 @@ fn parse_ty(st: @pstate, conv: conv_did) -> ty::t { parse_ty_rust_fn(st, conv) } 'X' => { - return ty::mk_var(st.tcx, ty::ty_vid(parse_int(st) as uint)); + return ty::mk_var(st.tcx, ty::TyVid(parse_int(st) as uint)); } 'Y' => return ty::mk_type(st.tcx), 'C' => { @@ -372,7 +373,7 @@ fn parse_purity(c: char) -> purity { } } -fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::fn_ty { +fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::FnTy { let proto = parse_proto(st); let purity = parse_purity(next(st)); let bounds = parse_bounds(st, conv); @@ -392,8 +393,14 @@ fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::fn_ty { } st.pos += 1u; // eat the ']' let (ret_style, ret_ty) = parse_ret_ty(st, conv); - return {purity: purity, proto: proto, bounds: bounds, inputs: inputs, - output: ret_ty, ret_style: ret_style}; + return FnTyBase { + meta: FnMeta {purity: purity, + proto: proto, + bounds: bounds, + ret_style: ret_style}, + sig: FnSig {inputs: inputs, + output: ret_ty} + }; } diff --git a/src/rustc/metadata/tyencode.rs b/src/rustc/metadata/tyencode.rs index 0ecb9dc3dc0..622ba1a5cce 100644 --- a/src/rustc/metadata/tyencode.rs +++ b/src/rustc/metadata/tyencode.rs @@ -342,19 +342,19 @@ fn enc_purity(w: io::Writer, p: purity) { } } -fn enc_ty_fn(w: io::Writer, cx: @ctxt, ft: ty::fn_ty) { - enc_proto(w, cx, ft.proto); - enc_purity(w, ft.purity); - enc_bounds(w, cx, ft.bounds); +fn enc_ty_fn(w: io::Writer, cx: @ctxt, ft: ty::FnTy) { + enc_proto(w, cx, ft.meta.proto); + enc_purity(w, ft.meta.purity); + enc_bounds(w, cx, ft.meta.bounds); w.write_char('['); - for ft.inputs.each |arg| { + for ft.sig.inputs.each |arg| { enc_mode(w, cx, arg.mode); enc_ty(w, cx, arg.ty); } w.write_char(']'); - match ft.ret_style { + match ft.meta.ret_style { noreturn => w.write_char('!'), - _ => enc_ty(w, cx, ft.output) + _ => enc_ty(w, cx, ft.sig.output) } } diff --git a/src/rustc/middle/borrowck/check_loans.rs b/src/rustc/middle/borrowck/check_loans.rs index 7f2964181d8..a81620b20ba 100644 --- a/src/rustc/middle/borrowck/check_loans.rs +++ b/src/rustc/middle/borrowck/check_loans.rs @@ -218,13 +218,13 @@ impl check_loan_ctxt { let callee_ty = ty::node_id_to_type(tcx, callee_id); match ty::get(callee_ty).struct { ty::ty_fn(fn_ty) => { - match fn_ty.purity { + match fn_ty.meta.purity { ast::pure_fn => return, // case (c) above ast::impure_fn | ast::unsafe_fn | ast::extern_fn => { self.report_purity_error( pc, callee_span, fmt!("access to %s function", - pprust::purity_to_str(fn_ty.purity))); + pprust::purity_to_str(fn_ty.meta.purity))); } } } diff --git a/src/rustc/middle/lint.rs b/src/rustc/middle/lint.rs index e38ba74fecf..8c2776d3ceb 100644 --- a/src/rustc/middle/lint.rs +++ b/src/rustc/middle/lint.rs @@ -659,7 +659,7 @@ fn check_fn(tcx: ty::ctxt, fk: visit::fn_kind, decl: ast::fn_decl, match ty::get(fn_ty).struct { ty::ty_fn(fn_ty) => { let mut counter = 0; - do vec::iter2(fn_ty.inputs, decl.inputs) |arg_ty, arg_ast| { + do vec::iter2(fn_ty.sig.inputs, decl.inputs) |arg_ty, arg_ast| { counter += 1; debug!("arg %d, ty=%s, mode=%s", counter, diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 3eef274e9d6..acf51691a96 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -529,10 +529,10 @@ fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t, let ccx = cx.ccx(); let mut cx = cx; match ty::get(fn_ty).struct { - ty::ty_fn({inputs: args, _}) => { + ty::ty_fn(ref fn_ty) => { let mut j = 0u; let v_id = variant.id; - for vec::each(args) |a| { + for vec::each(fn_ty.sig.inputs) |a| { let llfldp_a = GEP_enum(cx, a_tup, tid, v_id, tps, j); let ty_subst = ty::subst_tps(ccx.tcx, tps, a.ty); cx = f(cx, llfldp_a, ty_subst); @@ -1984,7 +1984,7 @@ fn create_main_wrapper(ccx: @crate_ctxt, sp: span, main_llfn: ValueRef, let main_takes_argv = // invariant! match ty::get(main_node_type).struct { - ty::ty_fn({inputs, _}) => inputs.len() != 0u, + ty::ty_fn(ref fn_ty) => fn_ty.sig.inputs.len() != 0u, _ => ccx.sess.span_fatal(sp, ~"main has a non-function type") }; diff --git a/src/rustc/middle/trans/closure.rs b/src/rustc/middle/trans/closure.rs index 9cf4393346b..57fcf66c701 100644 --- a/src/rustc/middle/trans/closure.rs +++ b/src/rustc/middle/trans/closure.rs @@ -425,17 +425,15 @@ fn make_fn_glue( } }; - return match ty::get(t).struct { - ty::ty_fn({proto: ty::proto_bare, _}) | - ty::ty_fn({proto: ty::proto_vstore(ty::vstore_slice(_)), _}) => - bcx, - ty::ty_fn({proto: ty::proto_vstore(ty::vstore_uniq), _}) => - fn_env(ty::ck_uniq), - ty::ty_fn({proto: ty::proto_vstore(ty::vstore_box), _}) => - fn_env(ty::ck_box), - _ => - fail ~"make_fn_glue invoked on non-function type" - }; + let proto = ty::ty_fn_proto(t); + match proto { + ty::proto_bare | ty::proto_vstore(ty::vstore_slice(_)) => bcx, + ty::proto_vstore(ty::vstore_uniq) => fn_env(ty::ck_uniq), + ty::proto_vstore(ty::vstore_box) => fn_env(ty::ck_box), + ty::proto_vstore(ty::vstore_fixed(_)) => { + cx.sess().bug(~"Closure with fixed vstore"); + } + } } fn make_opaque_cbox_take_glue( diff --git a/src/rustc/middle/trans/expr.rs b/src/rustc/middle/trans/expr.rs index 1e9c36b1e7e..118eff8c53b 100644 --- a/src/rustc/middle/trans/expr.rs +++ b/src/rustc/middle/trans/expr.rs @@ -447,13 +447,14 @@ fn trans_rvalue_dps(bcx: block, expr: @ast::expr, dest: Dest) -> block { ast::expr_fn_block(decl, body, cap_clause) => { let expr_ty = expr_ty(bcx, expr); match ty::get(expr_ty).struct { - ty::ty_fn({proto, _}) => { + ty::ty_fn(ref fn_ty) => { debug!("translating fn_block %s with type %s", expr_to_str(expr, tcx.sess.intr()), ty_to_str(tcx, expr_ty)); - return closure::trans_expr_fn(bcx, proto, decl, body, - expr.id, cap_clause, None, - dest); + return closure::trans_expr_fn( + bcx, fn_ty.meta.proto, decl, body, + expr.id, cap_clause, None, + dest); } _ => { bcx.sess().impossible_case( @@ -463,11 +464,11 @@ fn trans_rvalue_dps(bcx: block, expr: @ast::expr, dest: Dest) -> block { } ast::expr_loop_body(blk) => { match ty::get(expr_ty(bcx, expr)).struct { - ty::ty_fn({proto, _}) => { + ty::ty_fn(ref fn_ty) => { match blk.node { ast::expr_fn_block(decl, body, cap) => { return closure::trans_expr_fn( - bcx, proto, decl, body, blk.id, + bcx, fn_ty.meta.proto, decl, body, blk.id, cap, Some(None), dest); } _ => { diff --git a/src/rustc/middle/trans/foreign.rs b/src/rustc/middle/trans/foreign.rs index cd2be095178..bb5ea98e1b4 100644 --- a/src/rustc/middle/trans/foreign.rs +++ b/src/rustc/middle/trans/foreign.rs @@ -20,6 +20,7 @@ use util::ppaux::ty_to_str; use datum::*; use callee::*; use expr::{Dest, Ignore}; +use ty::{FnTyBase, FnMeta, FnSig}; export link_name, trans_foreign_mod, register_foreign_fn, trans_foreign_fn, trans_intrinsic; @@ -439,12 +440,12 @@ type c_stack_tys = { fn c_arg_and_ret_lltys(ccx: @crate_ctxt, id: ast::node_id) -> (~[TypeRef], TypeRef, ty::t) { match ty::get(ty::node_id_to_type(ccx.tcx, id)).struct { - ty::ty_fn({inputs: arg_tys, output: ret_ty, _}) => { - let llargtys = type_of_explicit_args(ccx, arg_tys); - let llretty = type_of::type_of(ccx, ret_ty); - (llargtys, llretty, ret_ty) - } - _ => ccx.sess.bug(~"c_arg_and_ret_lltys called on non-function type") + ty::ty_fn(ref fn_ty) => { + let llargtys = type_of_explicit_args(ccx, fn_ty.sig.inputs); + let llretty = type_of::type_of(ccx, fn_ty.sig.output); + (llargtys, llretty, fn_ty.sig.output) + } + _ => ccx.sess.bug(~"c_arg_and_ret_lltys called on non-function type") } } @@ -953,20 +954,19 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item, ~"frame_address" => { let frameaddress = ccx.intrinsics.get(~"llvm.frameaddress"); let frameaddress_val = Call(bcx, frameaddress, ~[C_i32(0i32)]); - let fty = ty::mk_fn(bcx.tcx(), { - purity: ast::impure_fn, - proto: - ty::proto_vstore(ty::vstore_slice( - ty::re_bound(ty::br_anon(0)))), - bounds: @~[], - inputs: ~[{ - mode: ast::expl(ast::by_val), - ty: ty::mk_imm_ptr( - bcx.tcx(), - ty::mk_mach_uint(bcx.tcx(), ast::ty_u8)) - }], - output: ty::mk_nil(bcx.tcx()), - ret_style: ast::return_val + let star_u8 = ty::mk_imm_ptr( + bcx.tcx(), + ty::mk_mach_uint(bcx.tcx(), ast::ty_u8)); + let fty = ty::mk_fn(bcx.tcx(), FnTyBase { + meta: FnMeta {purity: ast::impure_fn, + proto: + ty::proto_vstore(ty::vstore_slice( + ty::re_bound(ty::br_anon(0)))), + bounds: @~[], + ret_style: ast::return_val}, + sig: FnSig {inputs: ~[{mode: ast::expl(ast::by_val), + ty: star_u8}], + output: ty::mk_nil(bcx.tcx())} }); let datum = Datum {val: get_param(decl, first_real_arg), mode: ByRef, ty: fty, source: FromLvalue}; diff --git a/src/rustc/middle/trans/monomorphize.rs b/src/rustc/middle/trans/monomorphize.rs index 962aed37ff1..a0df372173d 100644 --- a/src/rustc/middle/trans/monomorphize.rs +++ b/src/rustc/middle/trans/monomorphize.rs @@ -10,6 +10,7 @@ use base::{trans_item, get_item_val, no_self, self_arg, trans_fn, use syntax::parse::token::special_idents; use type_of::type_of_fn_from_ty; use back::link::mangle_exported_name; +use middle::ty::{FnTyBase, FnMeta, FnSig}; fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, @@ -198,27 +199,36 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn normalize_for_monomorphization(tcx: ty::ctxt, ty: ty::t) -> Option { // FIXME[mono] could do this recursively. is that worthwhile? (#2529) match ty::get(ty).struct { - ty::ty_box(*) => { - Some(ty::mk_opaque_box(tcx)) - } - ty::ty_fn(ref fty) => { - Some(ty::mk_fn(tcx, {purity: ast::impure_fn, - proto: fty.proto, - bounds: @~[], - inputs: ~[], - output: ty::mk_nil(tcx), - ret_style: ast::return_val})) - } - ty::ty_trait(_, _, _) => { - Some(ty::mk_fn(tcx, {purity: ast::impure_fn, - proto: ty::proto_vstore(ty::vstore_box), - bounds: @~[], - inputs: ~[], - output: ty::mk_nil(tcx), - ret_style: ast::return_val})) - } - ty::ty_ptr(_) => Some(ty::mk_uint(tcx)), - _ => None + ty::ty_box(*) => { + Some(ty::mk_opaque_box(tcx)) + } + ty::ty_fn(ref fty) => { + Some(ty::mk_fn( + tcx, + FnTyBase {meta: FnMeta {purity: ast::impure_fn, + proto: fty.meta.proto, + bounds: @~[], + ret_style: ast::return_val}, + sig: FnSig {inputs: ~[], + output: ty::mk_nil(tcx)}})) + } + ty::ty_trait(_, _, _) => { + let box_proto = ty::proto_vstore(ty::vstore_box); + Some(ty::mk_fn( + tcx, + FnTyBase {meta: FnMeta {purity: ast::impure_fn, + proto: box_proto, + bounds: @~[], + ret_style: ast::return_val}, + sig: FnSig {inputs: ~[], + output: ty::mk_nil(tcx)}})) + } + ty::ty_ptr(_) => { + Some(ty::mk_uint(tcx)) + } + _ => { + None + } } } diff --git a/src/rustc/middle/trans/reflect.rs b/src/rustc/middle/trans/reflect.rs index 5aeddac8ab3..c78e264a86f 100644 --- a/src/rustc/middle/trans/reflect.rs +++ b/src/rustc/middle/trans/reflect.rs @@ -178,14 +178,14 @@ impl reflector { // FIXME (#2594): fetch constants out of intrinsic:: for the // numbers. - ty::ty_fn(fty) => { - let pureval = match fty.purity { + ty::ty_fn(ref fty) => { + let pureval = match fty.meta.purity { ast::pure_fn => 0u, ast::unsafe_fn => 1u, ast::impure_fn => 2u, ast::extern_fn => 3u }; - let protoval = match fty.proto { + let protoval = match fty.meta.proto { ty::proto_bare => 0u, ty::proto_vstore(ty::vstore_uniq) => 2u, ty::proto_vstore(ty::vstore_box) => 3u, @@ -193,16 +193,16 @@ impl reflector { ty::proto_vstore(ty::vstore_fixed(_)) => fail ~"fixed unexpected" }; - let retval = match fty.ret_style { + let retval = match fty.meta.ret_style { ast::noreturn => 0u, ast::return_val => 1u }; let extra = ~[self.c_uint(pureval), - self.c_uint(protoval), - self.c_uint(vec::len(fty.inputs)), - self.c_uint(retval)]; + self.c_uint(protoval), + self.c_uint(vec::len(fty.sig.inputs)), + self.c_uint(retval)]; self.visit(~"enter_fn", extra); - for fty.inputs.eachi |i, arg| { + for fty.sig.inputs.eachi |i, arg| { let modeval = match arg.mode { ast::infer(_) => 0u, ast::expl(e) => match e { @@ -220,7 +220,7 @@ impl reflector { } self.visit(~"fn_output", ~[self.c_uint(retval), - self.c_tydesc(fty.output)]); + self.c_tydesc(fty.sig.output)]); self.visit(~"leave_fn", extra); } diff --git a/src/rustc/middle/trans/shape.rs b/src/rustc/middle/trans/shape.rs index 92ee4e5dc90..f93d9c0b593 100644 --- a/src/rustc/middle/trans/shape.rs +++ b/src/rustc/middle/trans/shape.rs @@ -213,158 +213,161 @@ fn add_substr(&dest: ~[u8], src: ~[u8]) { fn shape_of(ccx: @crate_ctxt, t: ty::t) -> ~[u8] { match ty::get(t).struct { - ty::ty_nil | ty::ty_bool | ty::ty_uint(ast::ty_u8) | - ty::ty_bot => ~[shape_u8], - ty::ty_int(ast::ty_i) => ~[s_int(ccx.tcx)], - ty::ty_float(ast::ty_f) => ~[s_float(ccx.tcx)], - ty::ty_uint(ast::ty_u) | ty::ty_ptr(_) => ~[s_uint(ccx.tcx)], - ty::ty_type => ~[s_tydesc(ccx.tcx)], - ty::ty_int(ast::ty_i8) => ~[shape_i8], - ty::ty_uint(ast::ty_u16) => ~[shape_u16], - ty::ty_int(ast::ty_i16) => ~[shape_i16], - ty::ty_uint(ast::ty_u32) => ~[shape_u32], - ty::ty_int(ast::ty_i32) | ty::ty_int(ast::ty_char) => ~[shape_i32], - ty::ty_uint(ast::ty_u64) => ~[shape_u64], - ty::ty_int(ast::ty_i64) => ~[shape_i64], - ty::ty_float(ast::ty_f32) => ~[shape_f32], - ty::ty_float(ast::ty_f64) => ~[shape_f64], - ty::ty_estr(ty::vstore_uniq) => { - shape_of(ccx, tvec::expand_boxed_vec_ty(ccx.tcx, t)) - } - ty::ty_enum(did, substs) => { - match enum_kind(ccx, did) { - tk_unit => ~[s_variant_enum_t(ccx.tcx)], - tk_enum => ~[s_variant_enum_t(ccx.tcx)], - tk_newtype | tk_complex => { - let mut s = ~[shape_enum], id; - let nom_id = mk_nominal_id(ccx.tcx, did, None, substs.tps); - match ccx.shape_cx.tag_id_to_index.find(nom_id) { - None => { - id = ccx.shape_cx.next_tag_id; - ccx.shape_cx.tag_id_to_index.insert(nom_id, id); - ccx.shape_cx.tag_order.push({did: did, substs: substs}); - ccx.shape_cx.next_tag_id += 1u16; - } - Some(existing_id) => id = existing_id, + ty::ty_nil | ty::ty_bool | ty::ty_uint(ast::ty_u8) | + ty::ty_bot => ~[shape_u8], + ty::ty_int(ast::ty_i) => ~[s_int(ccx.tcx)], + ty::ty_float(ast::ty_f) => ~[s_float(ccx.tcx)], + ty::ty_uint(ast::ty_u) | ty::ty_ptr(_) => ~[s_uint(ccx.tcx)], + ty::ty_type => ~[s_tydesc(ccx.tcx)], + ty::ty_int(ast::ty_i8) => ~[shape_i8], + ty::ty_uint(ast::ty_u16) => ~[shape_u16], + ty::ty_int(ast::ty_i16) => ~[shape_i16], + ty::ty_uint(ast::ty_u32) => ~[shape_u32], + ty::ty_int(ast::ty_i32) | ty::ty_int(ast::ty_char) => ~[shape_i32], + ty::ty_uint(ast::ty_u64) => ~[shape_u64], + ty::ty_int(ast::ty_i64) => ~[shape_i64], + ty::ty_float(ast::ty_f32) => ~[shape_f32], + ty::ty_float(ast::ty_f64) => ~[shape_f64], + ty::ty_estr(ty::vstore_uniq) => { + shape_of(ccx, tvec::expand_boxed_vec_ty(ccx.tcx, t)) + } + ty::ty_enum(did, substs) => { + match enum_kind(ccx, did) { + tk_unit => ~[s_variant_enum_t(ccx.tcx)], + tk_enum => ~[s_variant_enum_t(ccx.tcx)], + tk_newtype | tk_complex => { + let mut s = ~[shape_enum], id; + let nom_id = mk_nominal_id(ccx.tcx, did, + None, substs.tps); + match ccx.shape_cx.tag_id_to_index.find(nom_id) { + None => { + id = ccx.shape_cx.next_tag_id; + ccx.shape_cx.tag_id_to_index.insert(nom_id, id); + ccx.shape_cx.tag_order.push({did: did, + substs: substs}); + ccx.shape_cx.next_tag_id += 1u16; + } + Some(existing_id) => id = existing_id, + } + add_u16(s, id as u16); + + s + } } - add_u16(s, id as u16); - + } + ty::ty_estr(ty::vstore_box) | + ty::ty_evec(_, ty::vstore_box) | + ty::ty_box(_) | ty::ty_opaque_box => ~[shape_box], + ty::ty_uniq(mt) => { + let mut s = ~[shape_uniq]; + add_substr(s, shape_of(ccx, mt.ty)); s - } } - } - ty::ty_estr(ty::vstore_box) | - ty::ty_evec(_, ty::vstore_box) | - ty::ty_box(_) | ty::ty_opaque_box => ~[shape_box], - ty::ty_uniq(mt) => { - let mut s = ~[shape_uniq]; - add_substr(s, shape_of(ccx, mt.ty)); - s - } - ty::ty_unboxed_vec(mt) => { - let mut s = ~[shape_unboxed_vec]; - add_bool(s, ty::type_is_pod(ccx.tcx, mt.ty)); - add_substr(s, shape_of(ccx, mt.ty)); - s - } - ty::ty_evec(_, ty::vstore_uniq) => { - shape_of(ccx, tvec::expand_boxed_vec_ty(ccx.tcx, t)) - } - - ty::ty_estr(ty::vstore_fixed(n)) => { - let mut s = ~[shape_fixedvec]; - let u8_t = ty::mk_mach_uint(ccx.tcx, ast::ty_u8); - assert (n + 1u) <= 0xffffu; - add_u16(s, (n + 1u) as u16); - add_bool(s, true); - add_substr(s, shape_of(ccx, u8_t)); - s - } - - ty::ty_evec(mt, ty::vstore_fixed(n)) => { - let mut s = ~[shape_fixedvec]; - assert n <= 0xffffu; - add_u16(s, n as u16); - add_bool(s, ty::type_is_pod(ccx.tcx, mt.ty)); - add_substr(s, shape_of(ccx, mt.ty)); - s - } - - ty::ty_estr(ty::vstore_slice(_)) => { - let mut s = ~[shape_slice]; - let u8_t = ty::mk_mach_uint(ccx.tcx, ast::ty_u8); - add_bool(s, true); // is_pod - add_bool(s, true); // is_str - add_substr(s, shape_of(ccx, u8_t)); - s - } - - ty::ty_evec(mt, ty::vstore_slice(_)) => { - let mut s = ~[shape_slice]; - add_bool(s, ty::type_is_pod(ccx.tcx, mt.ty)); - add_bool(s, false); // is_str - add_substr(s, shape_of(ccx, mt.ty)); - s - } - - ty::ty_rec(fields) => { - let mut s = ~[shape_struct], sub = ~[]; - for vec::each(fields) |f| { - sub += shape_of(ccx, f.mt.ty); + ty::ty_unboxed_vec(mt) => { + let mut s = ~[shape_unboxed_vec]; + add_bool(s, ty::type_is_pod(ccx.tcx, mt.ty)); + add_substr(s, shape_of(ccx, mt.ty)); + s } - add_substr(s, sub); - s - } - ty::ty_tup(elts) => { - let mut s = ~[shape_struct], sub = ~[]; - for vec::each(elts) |elt| { - sub += shape_of(ccx, elt); + ty::ty_evec(_, ty::vstore_uniq) => { + shape_of(ccx, tvec::expand_boxed_vec_ty(ccx.tcx, t)) } - add_substr(s, sub); - s - } - ty::ty_trait(_, _, _) => ~[shape_box_fn], - ty::ty_class(did, ref substs) => { - // same as records, unless there's a dtor - let tps = substs.tps; - let m_dtor_did = ty::ty_dtor(ccx.tcx, did); - let mut s = if option::is_some(m_dtor_did) { - ~[shape_res] - } - else { ~[shape_struct] }, sub = ~[]; - do option::iter(m_dtor_did) |dtor_did| { - let ri = @{did: dtor_did, parent_id: Some(did), tps: tps}; - let id = ccx.shape_cx.resources.intern(ri); - add_u16(s, id as u16); - }; - for ty::class_items_as_mutable_fields(ccx.tcx, did, substs).each |f| { - sub += shape_of(ccx, f.mt.ty); + + ty::ty_estr(ty::vstore_fixed(n)) => { + let mut s = ~[shape_fixedvec]; + let u8_t = ty::mk_mach_uint(ccx.tcx, ast::ty_u8); + assert (n + 1u) <= 0xffffu; + add_u16(s, (n + 1u) as u16); + add_bool(s, true); + add_substr(s, shape_of(ccx, u8_t)); + s + } + + ty::ty_evec(mt, ty::vstore_fixed(n)) => { + let mut s = ~[shape_fixedvec]; + assert n <= 0xffffu; + add_u16(s, n as u16); + add_bool(s, ty::type_is_pod(ccx.tcx, mt.ty)); + add_substr(s, shape_of(ccx, mt.ty)); + s + } + + ty::ty_estr(ty::vstore_slice(_)) => { + let mut s = ~[shape_slice]; + let u8_t = ty::mk_mach_uint(ccx.tcx, ast::ty_u8); + add_bool(s, true); // is_pod + add_bool(s, true); // is_str + add_substr(s, shape_of(ccx, u8_t)); + s + } + + ty::ty_evec(mt, ty::vstore_slice(_)) => { + let mut s = ~[shape_slice]; + add_bool(s, ty::type_is_pod(ccx.tcx, mt.ty)); + add_bool(s, false); // is_str + add_substr(s, shape_of(ccx, mt.ty)); + s + } + + ty::ty_rec(fields) => { + let mut s = ~[shape_struct], sub = ~[]; + for vec::each(fields) |f| { + sub += shape_of(ccx, f.mt.ty); + } + add_substr(s, sub); + s + } + ty::ty_tup(elts) => { + let mut s = ~[shape_struct], sub = ~[]; + for vec::each(elts) |elt| { + sub += shape_of(ccx, elt); + } + add_substr(s, sub); + s + } + ty::ty_trait(_, _, _) => ~[shape_box_fn], + ty::ty_class(did, ref substs) => { + // same as records, unless there's a dtor + let tps = substs.tps; + let m_dtor_did = ty::ty_dtor(ccx.tcx, did); + let mut s = if option::is_some(m_dtor_did) { + ~[shape_res] + } + else { ~[shape_struct] }, sub = ~[]; + do option::iter(m_dtor_did) |dtor_did| { + let ri = @{did: dtor_did, parent_id: Some(did), tps: tps}; + let id = ccx.shape_cx.resources.intern(ri); + add_u16(s, id as u16); + }; + for ty::class_items_as_mutable_fields(ccx.tcx, did, + substs).each |f| { + sub += shape_of(ccx, f.mt.ty); + } + add_substr(s, sub); + s + } + ty::ty_rptr(_, mt) => { + let mut s = ~[shape_rptr]; + add_substr(s, shape_of(ccx, mt.ty)); + s + } + ty::ty_param(*) => { + ccx.tcx.sess.bug(~"non-monomorphized type parameter"); + } + ty::ty_fn(ref fn_ty) => { + match fn_ty.meta.proto { + ty::proto_vstore(ty::vstore_box) => ~[shape_box_fn], + ty::proto_vstore(ty::vstore_uniq) => ~[shape_uniq_fn], + ty::proto_vstore(ty::vstore_slice(_)) => ~[shape_stack_fn], + ty::proto_bare => ~[shape_bare_fn], + ty::proto_vstore(ty::vstore_fixed(_)) => + fail ~"fixed vstore is impossible", + } + } + ty::ty_opaque_closure_ptr(_) => ~[shape_opaque_closure_ptr], + ty::ty_infer(_) | ty::ty_self => { + ccx.sess.bug(~"shape_of: unexpected type struct found") } - add_substr(s, sub); - s - } - ty::ty_rptr(_, mt) => { - let mut s = ~[shape_rptr]; - add_substr(s, shape_of(ccx, mt.ty)); - s - } - ty::ty_param(*) => { - ccx.tcx.sess.bug(~"non-monomorphized type parameter"); - } - ty::ty_fn({proto: ty::proto_vstore(ty::vstore_box), _}) => - ~[shape_box_fn], - ty::ty_fn({proto: ty::proto_vstore(ty::vstore_uniq), _}) => - ~[shape_uniq_fn], - ty::ty_fn({proto: ty::proto_vstore(ty::vstore_slice(_)), _}) => - ~[shape_stack_fn], - ty::ty_fn({proto: ty::proto_vstore(ty::vstore_fixed(_)), _}) => - fail ~"fixed vstore is impossible", - ty::ty_fn({proto: ty::proto_bare, _}) => - ~[shape_bare_fn], - ty::ty_opaque_closure_ptr(_) => - ~[shape_opaque_closure_ptr], - ty::ty_infer(_) | ty::ty_self => - ccx.sess.bug(~"shape_of: unexpected type struct found") } } diff --git a/src/rustc/middle/trans/type_use.rs b/src/rustc/middle/trans/type_use.rs index 8048a34c219..4c6b936172f 100644 --- a/src/rustc/middle/trans/type_use.rs +++ b/src/rustc/middle/trans/type_use.rs @@ -46,8 +46,8 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint) let cx = {ccx: ccx, uses: vec::to_mut(vec::from_elem(n_tps, 0u))}; match ty::get(ty::lookup_item_type(cx.ccx.tcx, fn_id).ty).struct { - ty::ty_fn({inputs, _}) => { - for vec::each(inputs) |arg| { + ty::ty_fn(ref fn_ty) => { + for vec::each(fn_ty.sig.inputs) |arg| { if arg.mode == expl(by_val) { type_needs(cx, use_repr, arg.ty); } } } diff --git a/src/rustc/middle/tstate/auxiliary.rs b/src/rustc/middle/tstate/auxiliary.rs index 849d4416692..f612ed40a9c 100644 --- a/src/rustc/middle/tstate/auxiliary.rs +++ b/src/rustc/middle/tstate/auxiliary.rs @@ -946,16 +946,14 @@ fn callee_modes(fcx: fn_ctxt, callee: node_id) -> ~[mode] { let ty = ty::type_autoderef(fcx.ccx.tcx, ty::node_id_to_type(fcx.ccx.tcx, callee)); match ty::get(ty).struct { - ty::ty_fn({inputs: args, _}) { - let mut modes = ~[]; - for args.each |arg| { vec::push(modes, arg.mode); } - return modes; - } - _ { - // Shouldn't happen; callee should be ty_fn. - fcx.ccx.tcx.sess.bug(~"non-fn callee type in callee_modes: " + + ty::ty_fn(ref fn_ty) { + return fn_ty.sig.inputs.map(|input| input.mode); + } + _ { + // Shouldn't happen; callee should be ty_fn. + fcx.ccx.tcx.sess.bug(~"non-fn callee type in callee_modes: " + util::ppaux::ty_to_str(fcx.ccx.tcx, ty)); - } + } } } diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index 2f352efc864..f95997c93e9 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -21,7 +21,7 @@ use util::ppaux::{ty_to_str, proto_ty_to_str, tys_to_str}; use std::serialization::{serialize_Option, deserialize_Option}; -export ty_vid, int_vid, region_vid, vid; +export TyVid, IntVid, FnVid, RegionVid, vid; export br_hashmap; export is_instantiable; export node_id_to_type; @@ -80,7 +80,7 @@ export ty_box, mk_box, mk_imm_box, type_is_box, type_is_boxed; export ty_opaque_closure_ptr, mk_opaque_closure_ptr; export ty_opaque_box, mk_opaque_box; export ty_float, mk_float, mk_mach_float, type_is_fp; -export ty_fn, fn_ty, mk_fn; +export ty_fn, FnTy, FnTyBase, FnMeta, FnSig, mk_fn; export ty_fn_proto, ty_fn_purity, ty_fn_ret, ty_fn_ret_style, tys_in_fn_ty; export ty_int, mk_int, mk_mach_int, mk_char; export mk_i8, mk_u8, mk_i16, mk_u16, mk_i32, mk_u32, mk_i64, mk_u64; @@ -119,7 +119,7 @@ export kind_noncopyable, kind_const; export kind_can_be_copied, kind_can_be_sent, kind_can_be_implicitly_copied; export kind_is_safe_for_default_mode; export kind_is_owned; -export proto_kind, kind_lteq, type_kind; +export meta_kind, kind_lteq, type_kind; export operators; export type_err, terr_vstore_kind; export type_err_to_str, note_and_explain_type_err; @@ -203,7 +203,7 @@ type param_bounds = @~[param_bound]; type method = {ident: ast::ident, tps: @~[param_bounds], - fty: fn_ty, + fty: FnTy, self_ty: ast::self_ty_, vis: ast::visibility}; @@ -392,20 +392,42 @@ impl fn_proto : cmp::Eq { } } -/// Innards of a function type: -/// -/// - `purity` is the function's effect (pure, impure, unsafe). -/// - `proto` is the protocol (fn@, fn~, etc). -/// - `bound` is the parameter bounds on the function's upvars. -/// - `inputs` is the list of arguments and their modes. -/// - `output` is the return type. -/// - `ret_style` indicates whether the function returns a value or fails. -type fn_ty = {purity: ast::purity, - proto: fn_proto, - bounds: @~[param_bound], - inputs: ~[arg], - output: t, - ret_style: ret_style}; +/** + * Meta information about a closure. + * + * - `purity` is the function's effect (pure, impure, unsafe). + * - `proto` is the protocol (fn@, fn~, etc). + * - `bounds` is the parameter bounds on the function's upvars. + * - `ret_style` indicates whether the function returns a value or fails. */ +struct FnMeta { + purity: ast::purity; + proto: fn_proto; + bounds: @~[param_bound]; + ret_style: ret_style; +} + +/** + * Signature of a function type, which I have arbitrarily + * decided to use to refer to the input/output types. + * + * - `inputs` is the list of arguments and their modes. + * - `output` is the return type. */ +struct FnSig { + inputs: ~[arg]; + output: t; +} + +/** + * Function type: combines the meta information and the + * type signature. This particular type is parameterized + * by the meta information because, in some cases, the + * meta information is inferred. */ +struct FnTyBase { + meta: M; + sig: FnSig; +} + +type FnTy = FnTyBase; type param_ty = {idx: uint, def_id: def_id}; @@ -440,7 +462,7 @@ enum region { re_static, /// A region variable. Should not exist after typeck. - re_var(region_vid) + re_var(RegionVid) } enum bound_region { @@ -505,7 +527,7 @@ enum sty { ty_ptr(mt), ty_rptr(region, mt), ty_rec(~[field]), - ty_fn(fn_ty), + ty_fn(FnTy), ty_trait(def_id, substs, vstore), ty_class(def_id, substs), ty_tup(~[t]), @@ -567,13 +589,14 @@ enum param_bound { bound_trait(t), } -enum ty_vid = uint; -enum int_vid = uint; -enum region_vid = uint; +enum TyVid = uint; +enum IntVid = uint; +enum FnVid = uint; +enum RegionVid = uint; enum InferTy { - TyVar(ty_vid), - IntVar(int_vid) + TyVar(TyVid), + IntVar(IntVid) } trait vid { @@ -581,17 +604,22 @@ trait vid { pure fn to_str() -> ~str; } -impl ty_vid: vid { +impl TyVid: vid { pure fn to_uint() -> uint { *self } pure fn to_str() -> ~str { fmt!("", self.to_uint()) } } -impl int_vid: vid { +impl IntVid: vid { pure fn to_uint() -> uint { *self } pure fn to_str() -> ~str { fmt!("", self.to_uint()) } } -impl region_vid: vid { +impl FnVid: vid { + pure fn to_uint() -> uint { *self } + pure fn to_str() -> ~str { fmt!("", self.to_uint()) } +} + +impl RegionVid: vid { pure fn to_uint() -> uint { *self } pure fn to_str() -> ~str { fmt!("%?", self) } } @@ -600,14 +628,14 @@ impl InferTy { pure fn to_hash() -> uint { match self { TyVar(v) => v.to_uint() << 1, - IntVar(v) => (v.to_uint() << 1) + 1 + IntVar(v) => (v.to_uint() << 1) + 1, } } pure fn to_str() -> ~str { match self { TyVar(v) => v.to_str(), - IntVar(v) => v.to_str() + IntVar(v) => v.to_str(), } } } @@ -781,12 +809,12 @@ fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option) -> t { ty_rec(flds) => for flds.each |f| { flags |= get(f.mt.ty).flags; }, ty_tup(ts) => for ts.each |tt| { flags |= get(tt).flags; }, ty_fn(ref f) => { - match f.proto { + match f.meta.proto { ty::proto_vstore(vstore_slice(r)) => flags |= rflags(r), ty::proto_bare | ty::proto_vstore(_) => {} } - for f.inputs.each |a| { flags |= get(a.ty).flags; } - flags |= get(f.output).flags; + for f.sig.inputs.each |a| { flags |= get(a.ty).flags; } + flags |= get(f.sig.output).flags; } } let t = @{struct: st, id: cx.next_id, flags: flags, o_def_id: o_def_id}; @@ -883,13 +911,12 @@ fn mk_mut_unboxed_vec(cx: ctxt, ty: t) -> t { mk_t(cx, ty_unboxed_vec({ty: ty, mutbl: ast::m_imm})) } - fn mk_rec(cx: ctxt, fs: ~[field]) -> t { mk_t(cx, ty_rec(fs)) } fn mk_tup(cx: ctxt, ts: ~[t]) -> t { mk_t(cx, ty_tup(ts)) } // take a copy because we want to own the various vectors inside -fn mk_fn(cx: ctxt, +fty: fn_ty) -> t { mk_t(cx, ty_fn(fty)) } +fn mk_fn(cx: ctxt, +fty: FnTy) -> t { mk_t(cx, ty_fn(fty)) } fn mk_trait(cx: ctxt, did: ast::def_id, +substs: substs, vstore: vstore) -> t { @@ -902,9 +929,9 @@ fn mk_class(cx: ctxt, class_id: ast::def_id, +substs: substs) -> t { mk_t(cx, ty_class(class_id, substs)) } -fn mk_var(cx: ctxt, v: ty_vid) -> t { mk_infer(cx, TyVar(v)) } +fn mk_var(cx: ctxt, v: TyVid) -> t { mk_infer(cx, TyVar(v)) } -fn mk_int_var(cx: ctxt, v: int_vid) -> t { +fn mk_int_var(cx: ctxt, v: IntVid) -> t { mk_infer(cx, IntVar(v)) } @@ -976,8 +1003,8 @@ fn maybe_walk_ty(ty: t, f: fn(t) -> bool) { } ty_tup(ts) => { for ts.each |tt| { maybe_walk_ty(tt, f); } } ty_fn(ref ft) => { - for ft.inputs.each |a| { maybe_walk_ty(a.ty, f); } - maybe_walk_ty(ft.output, f); + for ft.sig.inputs.each |a| { maybe_walk_ty(a.ty, f); } + maybe_walk_ty(ft.sig.output, f); } ty_uniq(tm) => { maybe_walk_ty(tm.ty, f); } } @@ -995,58 +1022,61 @@ fn fold_sty(sty: &sty, fldop: fn(t) -> t) -> sty { } match *sty { - ty_box(tm) => { - ty_box({ty: fldop(tm.ty), mutbl: tm.mutbl}) - } - ty_uniq(tm) => { - ty_uniq({ty: fldop(tm.ty), mutbl: tm.mutbl}) - } - ty_ptr(tm) => { - ty_ptr({ty: fldop(tm.ty), mutbl: tm.mutbl}) - } - ty_unboxed_vec(tm) => { - ty_unboxed_vec({ty: fldop(tm.ty), mutbl: tm.mutbl}) - } - ty_evec(tm, vst) => { - ty_evec({ty: fldop(tm.ty), mutbl: tm.mutbl}, vst) - } - ty_enum(tid, ref substs) => { - ty_enum(tid, fold_substs(substs, fldop)) - } - ty_trait(did, ref substs, vst) => { - ty_trait(did, fold_substs(substs, fldop), vst) - } - ty_rec(fields) => { - let new_fields = do vec::map(fields) |fl| { - let new_ty = fldop(fl.mt.ty); - let new_mt = {ty: new_ty, mutbl: fl.mt.mutbl}; - {ident: fl.ident, mt: new_mt} - }; - ty_rec(new_fields) - } - ty_tup(ts) => { - let new_ts = vec::map(ts, |tt| fldop(tt)); - ty_tup(new_ts) - } - ty_fn(ref f) => { - let new_args = vec::map(f.inputs, |a| { - let new_ty = fldop(a.ty); - {mode: a.mode, ty: new_ty} - }); - let new_output = fldop(f.output); - ty_fn({inputs: new_args, output: new_output,.. *f}) - } - ty_rptr(r, tm) => { - ty_rptr(r, {ty: fldop(tm.ty), mutbl: tm.mutbl}) - } - ty_class(did, ref substs) => { - ty_class(did, fold_substs(substs, fldop)) - } - ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) | - ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) | - ty_opaque_box | ty_infer(_) | ty_param(*) | ty_self => { - *sty - } + ty_box(tm) => { + ty_box({ty: fldop(tm.ty), mutbl: tm.mutbl}) + } + ty_uniq(tm) => { + ty_uniq({ty: fldop(tm.ty), mutbl: tm.mutbl}) + } + ty_ptr(tm) => { + ty_ptr({ty: fldop(tm.ty), mutbl: tm.mutbl}) + } + ty_unboxed_vec(tm) => { + ty_unboxed_vec({ty: fldop(tm.ty), mutbl: tm.mutbl}) + } + ty_evec(tm, vst) => { + ty_evec({ty: fldop(tm.ty), mutbl: tm.mutbl}, vst) + } + ty_enum(tid, ref substs) => { + ty_enum(tid, fold_substs(substs, fldop)) + } + ty_trait(did, ref substs, vst) => { + ty_trait(did, fold_substs(substs, fldop), vst) + } + ty_rec(fields) => { + let new_fields = do vec::map(fields) |fl| { + let new_ty = fldop(fl.mt.ty); + let new_mt = {ty: new_ty, mutbl: fl.mt.mutbl}; + {ident: fl.ident, mt: new_mt} + }; + ty_rec(new_fields) + } + ty_tup(ts) => { + let new_ts = vec::map(ts, |tt| fldop(tt)); + ty_tup(new_ts) + } + ty_fn(ref f) => { + let new_args = f.sig.inputs.map(|a| { + let new_ty = fldop(a.ty); + {mode: a.mode, ty: new_ty} + }); + let new_output = fldop(f.sig.output); + ty_fn(FnTyBase { + meta: f.meta, + sig: FnSig {inputs: new_args, output: new_output} + }) + } + ty_rptr(r, tm) => { + ty_rptr(r, {ty: fldop(tm.ty), mutbl: tm.mutbl}) + } + ty_class(did, ref substs) => { + ty_class(did, fold_substs(substs, fldop)) + } + ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) | + ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) | + ty_opaque_box | ty_infer(_) | ty_param(*) | ty_self => { + *sty + } } } @@ -1113,9 +1143,9 @@ fn fold_regions_and_ty( ty_trait(def_id, ref substs, vst) => { ty::mk_trait(cx, def_id, fold_substs(substs, fldr, fldt), vst) } - ty_fn(f) => { + ty_fn(ref f) => { let new_proto; - match f.proto { + match f.meta.proto { proto_bare => new_proto = proto_bare, proto_vstore(vstore_slice(r)) => @@ -1123,16 +1153,15 @@ fn fold_regions_and_ty( proto_vstore(old_vstore) => new_proto = proto_vstore(old_vstore) } - - let new_args = vec::map(f.inputs, |a| { + let new_args = vec::map(f.sig.inputs, |a| { let new_ty = fldfnt(a.ty); {mode: a.mode, ty: new_ty} }); - let new_output = fldfnt(f.output); - ty::mk_fn(cx, { - inputs: new_args, - output: new_output, - proto: new_proto,.. f + let new_output = fldfnt(f.sig.output); + ty::mk_fn(cx, FnTyBase { + meta: FnMeta {proto: new_proto, ..f.meta}, + sig: FnSig {inputs: new_args, + output: new_output} }) } ref sty => { @@ -1440,7 +1469,7 @@ fn type_needs_drop(cx: ctxt, ty: t) -> bool { accum } ty_fn(ref fty) => { - match fty.proto { + match fty.meta.proto { proto_bare | proto_vstore(vstore_slice(_)) => false, _ => true } @@ -1667,8 +1696,8 @@ pure fn kind_is_owned(k: kind) -> bool { *k & KIND_MASK_OWNED == KIND_MASK_OWNED } -fn proto_kind(p: fn_proto) -> kind { - match p { +fn meta_kind(p: FnMeta) -> kind { + match p.proto { // XXX consider the kind bounds! proto_vstore(vstore_slice(_)) => kind_noncopyable() | kind_(KIND_MASK_DEFAULT_MODE), proto_vstore(vstore_box) => @@ -1753,7 +1782,7 @@ fn type_kind(cx: ctxt, ty: t) -> kind { } // functions depend on the protocol - ty_fn(ref f) => proto_kind(f.proto), + ty_fn(ref f) => meta_kind(f.meta), // Those with refcounts raise noncopyable to copyable, // lower sendable to copyable. Therefore just set result to copyable. @@ -2361,8 +2390,10 @@ pure fn hash_type_structure(st: &sty) -> uint { } ty_fn(ref f) => { let mut h = 27u; - for vec::each(f.inputs) |a| { h = hash_subty(h, a.ty); } - hash_subty(h, f.output) + for vec::each(f.sig.inputs) |a| { + h = hash_subty(h, a.ty); + } + hash_subty(h, f.sig.output) } ty_self => 28u, ty_infer(v) => hash_uint(29u, v.to_hash()), @@ -2415,35 +2446,35 @@ fn node_id_has_type_params(cx: ctxt, id: ast::node_id) -> bool { // Type accessors for substructures of types fn ty_fn_args(fty: t) -> ~[arg] { match get(fty).struct { - ty_fn(ref f) => f.inputs, + ty_fn(ref f) => f.sig.inputs, _ => fail ~"ty_fn_args() called on non-fn type" } } fn ty_fn_proto(fty: t) -> fn_proto { match get(fty).struct { - ty_fn(ref f) => f.proto, + ty_fn(ref f) => f.meta.proto, _ => fail ~"ty_fn_proto() called on non-fn type" } } fn ty_fn_purity(fty: t) -> ast::purity { match get(fty).struct { - ty_fn(ref f) => f.purity, + ty_fn(ref f) => f.meta.purity, _ => fail ~"ty_fn_purity() called on non-fn type" } } pure fn ty_fn_ret(fty: t) -> t { match get(fty).struct { - ty_fn(ref f) => f.output, + ty_fn(ref f) => f.sig.output, _ => fail ~"ty_fn_ret() called on non-fn type" } } fn ty_fn_ret_style(fty: t) -> ast::ret_style { match get(fty).struct { - ty_fn(ref f) => f.ret_style, + ty_fn(ref f) => f.meta.ret_style, _ => fail ~"ty_fn_ret_style() called on non-fn type" } } @@ -2463,8 +2494,8 @@ fn ty_region(ty: t) -> region { } // Returns a vec of all the input and output types of fty. -fn tys_in_fn_ty(fty: &fn_ty) -> ~[t] { - vec::append_one(fty.inputs.map(|a| a.ty), fty.output) +fn tys_in_fn_ty(fty: &FnTy) -> ~[t] { + vec::append_one(fty.sig.inputs.map(|a| a.ty), fty.sig.output) } // Just checks whether it's a fn that returns bool, @@ -2474,14 +2505,14 @@ fn is_pred_ty(fty: t) -> bool { } /* -fn ty_var_id(typ: t) -> ty_vid { +fn ty_var_id(typ: t) -> TyVid { match get(typ).struct { ty_infer(TyVar(vid)) => return vid, _ => { error!("ty_var_id called on non-var ty"); fail; } } } -fn int_var_id(typ: t) -> int_vid { +fn int_var_id(typ: t) -> IntVid { match get(typ).struct { ty_infer(IntVar(vid)) => return vid, _ => { error!("ty_var_integral_id called on ty other than \ @@ -2765,11 +2796,11 @@ fn param_tys_in_type(ty: t) -> ~[param_ty] { rslt } -fn occurs_check(tcx: ctxt, sp: span, vid: ty_vid, rt: t) { +fn occurs_check(tcx: ctxt, sp: span, vid: TyVid, rt: t) { // Returns a vec of all the type variables occurring in `ty`. It may // contain duplicates. (Integral type vars aren't counted.) - fn vars_in_type(ty: t) -> ~[ty_vid] { + fn vars_in_type(ty: t) -> ~[TyVid] { let mut rslt = ~[]; do walk_ty(ty) |ty| { match get(ty).struct { @@ -3561,20 +3592,16 @@ fn normalize_ty(cx: ctxt, t: t) -> t { // This type has a region. Get rid of it mk_rptr(cx, re_static, normalize_mt(cx, mt)), - ty_fn({purity: purity, - proto: proto_vstore(vstore), - bounds: bounds, - inputs: inputs, - output: output, - ret_style: ret_style}) => - mk_fn(cx, { - purity: purity, - proto: proto_vstore(normalize_vstore(vstore)), - bounds: bounds, - inputs: inputs, - output: output, - ret_style: ret_style - }), + ty_fn(ref fn_ty) => { + let proto = match fn_ty.meta.proto { + proto_bare => proto_bare, + proto_vstore(vstore) => proto_vstore(normalize_vstore(vstore)) + }; + mk_fn(cx, FnTyBase { + meta: FnMeta {proto: proto, ..fn_ty.meta}, + sig: fn_ty.sig + }) + } ty_enum(did, r) => match r.self_r { @@ -3708,31 +3735,48 @@ impl vstore : cmp::Eq { } } -impl fn_ty : cmp::Eq { - pure fn eq(&&other: fn_ty) -> bool { +impl FnMeta : cmp::Eq { + pure fn eq(&&other: FnMeta) -> bool { self.purity == other.purity && self.proto == other.proto && self.bounds == other.bounds && - self.inputs == other.inputs && - self.output == other.output && self.ret_style == other.ret_style } } -impl ty_vid: cmp::Eq { - pure fn eq(&&other: ty_vid) -> bool { +impl FnSig : cmp::Eq { + pure fn eq(&&other: FnSig) -> bool { + self.inputs == other.inputs && + self.output == other.output + } +} + +impl FnTyBase : cmp::Eq { + pure fn eq(&&other: FnTyBase) -> bool { + self.meta == other.meta && self.sig == other.sig + } +} + +impl TyVid: cmp::Eq { + pure fn eq(&&other: TyVid) -> bool { *self == *other } } -impl int_vid: cmp::Eq { - pure fn eq(&&other: int_vid) -> bool { +impl IntVid: cmp::Eq { + pure fn eq(&&other: IntVid) -> bool { *self == *other } } -impl region_vid: cmp::Eq { - pure fn eq(&&other: region_vid) -> bool { +impl FnVid: cmp::Eq { + pure fn eq(&&other: FnVid) -> bool { + *self == *other + } +} + +impl RegionVid: cmp::Eq { + pure fn eq(&&other: RegionVid) -> bool { *self == *other } } diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs index 3f4ec261698..39d4a64f19f 100644 --- a/src/rustc/middle/typeck.rs +++ b/src/rustc/middle/typeck.rs @@ -255,38 +255,40 @@ fn check_main_fn_ty(ccx: @crate_ctxt, let tcx = ccx.tcx; let main_t = ty::node_id_to_type(tcx, main_id); match ty::get(main_t).struct { - ty::ty_fn({purity: ast::impure_fn, proto: ty::proto_bare, - inputs, output, ret_style: ast::return_val, _}) => { - match tcx.items.find(main_id) { - Some(ast_map::node_item(it,_)) => { - match it.node { - ast::item_fn(_,_,ps,_) if vec::is_not_empty(ps) => { - tcx.sess.span_err(main_span, - ~"main function is not allowed to have type parameters"); - return; - } - _ => () - } - } - _ => () - } - let mut ok = ty::type_is_nil(output); - let num_args = vec::len(inputs); - ok &= num_args == 0u || num_args == 1u && - arg_is_argv_ty(tcx, inputs[0]); - if !ok { - tcx.sess.span_err(main_span, - fmt!("Wrong type in main function: found `%s`, \ - expected `extern fn(~[str]) -> ()` \ - or `extern fn() -> ()`", + ty::ty_fn(fn_ty) => { + match tcx.items.find(main_id) { + Some(ast_map::node_item(it,_)) => { + match it.node { + ast::item_fn(_,_,ps,_) if vec::is_not_empty(ps) => { + tcx.sess.span_err( + main_span, + ~"main function is not allowed \ + to have type parameters"); + return; + } + _ => () + } + } + _ => () + } + let mut ok = ty::type_is_nil(fn_ty.sig.output); + let num_args = vec::len(fn_ty.sig.inputs); + ok &= num_args == 0u || num_args == 1u && + arg_is_argv_ty(tcx, fn_ty.sig.inputs[0]); + if !ok { + tcx.sess.span_err( + main_span, + fmt!("Wrong type in main function: found `%s`, \ + expected `extern fn(~[str]) -> ()` \ + or `extern fn() -> ()`", ty_to_str(tcx, main_t))); - } - } - _ => { - tcx.sess.span_bug(main_span, - ~"main has a non-function type: found `" + + } + } + _ => { + tcx.sess.span_bug(main_span, + ~"main has a non-function type: found `" + ty_to_str(tcx, main_t) + ~"`"); - } + } } } diff --git a/src/rustc/middle/typeck/astconv.rs b/src/rustc/middle/typeck/astconv.rs index 933629bdf91..85bac78da97 100644 --- a/src/rustc/middle/typeck/astconv.rs +++ b/src/rustc/middle/typeck/astconv.rs @@ -45,6 +45,7 @@ use check::fn_ctxt; use rscope::{anon_rscope, binding_rscope, empty_rscope, in_anon_rscope}; use rscope::{in_binding_rscope, region_scope, type_rscope}; +use ty::{FnTyBase, FnMeta, FnSig}; trait ast_conv { fn tcx() -> ty::ctxt; @@ -471,7 +472,7 @@ fn ty_of_fn_decl( bounds: @~[ty::param_bound], decl: ast::fn_decl, expected_tys: expected_tys, - span: span) -> ty::fn_ty { + span: span) -> ty::FnTy { debug!("ty_of_fn_decl"); do indent { @@ -497,8 +498,14 @@ fn ty_of_fn_decl( let proto = ast_proto_to_proto(self, rscope, span, ast_proto); - {purity: purity, proto: proto, bounds: bounds, inputs: input_tys, - output: output_ty, ret_style: decl.cf} + FnTyBase { + meta: FnMeta {purity: purity, + proto: proto, + bounds: bounds, + ret_style: decl.cf}, + sig: FnSig {inputs: input_tys, + output: output_ty} + } } } diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index 7bdc1dd4adb..4ec13684f7e 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -68,7 +68,7 @@ type parameter). use astconv::{ast_conv, ast_path_to_ty, ast_ty_to_ty}; use astconv::{ast_region_to_region}; -use middle::ty::{ty_vid, vid}; +use middle::ty::{TyVid, vid, FnTyBase, FnMeta, FnSig}; use regionmanip::{replace_bound_regions_in_fn_ty}; use rscope::{anon_rscope, binding_rscope, empty_rscope, in_anon_rscope}; use rscope::{in_binding_rscope, region_scope, type_rscope, @@ -98,7 +98,7 @@ type self_info = { /// share the inherited fields. struct inherited { infcx: infer::infer_ctxt; - locals: hashmap; + locals: hashmap; node_types: hashmap; node_type_substs: hashmap; borrowings: hashmap; @@ -211,7 +211,7 @@ fn check_bare_fn(ccx: @crate_ctxt, fn check_fn(ccx: @crate_ctxt, self_info: Option, - fn_ty: &ty::fn_ty, + fn_ty: &ty::FnTy, decl: ast::fn_decl, body: ast::blk, indirect_ret: bool, @@ -231,8 +231,8 @@ fn check_fn(ccx: @crate_ctxt, |br| ty::re_free(body.node.id, br)) }; - let arg_tys = fn_ty.inputs.map(|a| a.ty); - let ret_ty = fn_ty.output; + let arg_tys = fn_ty.sig.inputs.map(|a| a.ty); + let ret_ty = fn_ty.sig.output; debug!("check_fn(arg_tys=%?, ret_ty=%?, self_info.self_ty=%?)", arg_tys.map(|a| ty_to_str(tcx, a)), @@ -245,12 +245,12 @@ fn check_fn(ccx: @crate_ctxt, let fcx: @fn_ctxt = { let (purity, inherited) = match old_fcx { None => { - (fn_ty.purity, + (fn_ty.meta.purity, blank_inherited(ccx)) } Some(fcx) => { - (ty::determine_inherited_purity(fcx.purity, fn_ty.purity, - fn_ty.proto), + (ty::determine_inherited_purity(fcx.purity, fn_ty.meta.purity, + fn_ty.meta.proto), fcx.inh) } }; @@ -943,9 +943,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, // Grab the argument types, supplying fresh type variables // if the wrong number of arguments were supplied - let expected_arg_count = vec::len(fn_ty.inputs); + let expected_arg_count = vec::len(fn_ty.sig.inputs); let arg_tys = if expected_arg_count == supplied_arg_count { - fn_ty.inputs.map(|a| a.ty) + fn_ty.sig.inputs.map(|a| a.ty) } else { fcx.ccx.tcx.sess.span_err( sp, fmt!("this function takes %u parameter%s but %u \ @@ -1031,9 +1031,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, // Pull the return type out of the type of the function. match structure_of(fcx, sp, fty) { - ty::ty_fn(f) => { - bot |= (f.ret_style == ast::noreturn); - fcx.write_ty(call_expr_id, f.output); + ty::ty_fn(ref f) => { + bot |= (f.meta.ret_style == ast::noreturn); + fcx.write_ty(call_expr_id, f.sig.output); return bot; } _ => fcx.ccx.tcx.sess.span_fatal(sp, ~"calling non-function") @@ -1242,10 +1242,10 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, replace_bound_regions_in_fn_ty( tcx, @Nil, None, fn_ty, |br| ty::re_bound(ty::br_cap_avoid(expr.id, @br))); - (Some({inputs:fn_ty.inputs, - output:fn_ty.output}), - fn_ty.purity, - fn_ty.proto) + (Some({inputs: fn_ty.sig.inputs, + output: fn_ty.sig.output}), + fn_ty.meta.purity, + fn_ty.meta.proto) } _ => { (None, ast::impure_fn, ty::proto_vstore(ty::vstore_box)) @@ -1268,8 +1268,8 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, // Patch up the function declaration, if necessary. match ast_proto_opt { None => { - fn_ty.purity = expected_purity; - fn_ty.proto = expected_proto; + fn_ty.meta.purity = expected_purity; + fn_ty.meta.proto = expected_proto; } Some(_) => { } } @@ -1643,16 +1643,20 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, let inner_ty = match expected_sty { Some(ty::ty_fn(fty)) => { match fcx.mk_subty(false, expr.span, - fty.output, ty::mk_bool(tcx)) { + fty.sig.output, ty::mk_bool(tcx)) { result::Ok(_) => (), result::Err(_) => { tcx.sess.span_fatal( expr.span, fmt!("a `loop` function's last argument \ should return `bool`, not `%s`", - fcx.infcx().ty_to_str(fty.output))); + fcx.infcx().ty_to_str(fty.sig.output))); } } - ty::mk_fn(tcx, {output: ty::mk_nil(tcx),.. fty}) + ty::mk_fn(tcx, FnTyBase { + meta: fty.meta, + sig: FnSig {output: ty::mk_nil(tcx), + ..fty.sig} + }) } _ => { tcx.sess.span_fatal(expr.span, ~"a `loop` function's last \ @@ -1675,8 +1679,11 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, fcx, expr.span, fcx.node_ty(b.id)); match ty::get(block_ty).struct { ty::ty_fn(fty) => { - fcx.write_ty(expr.id, ty::mk_fn(tcx, {output: ty::mk_bool(tcx), - .. fty})); + fcx.write_ty(expr.id, ty::mk_fn(tcx, FnTyBase { + meta: fty.meta, + sig: FnSig {output: ty::mk_bool(tcx), + ..fty.sig} + })) } _ => fail ~"expected fn type" } @@ -2306,7 +2313,7 @@ fn self_ref(fcx: @fn_ctxt, id: ast::node_id) -> bool { ast_util::is_self) } -fn lookup_local(fcx: @fn_ctxt, sp: span, id: ast::node_id) -> ty_vid { +fn lookup_local(fcx: @fn_ctxt, sp: span, id: ast::node_id) -> TyVid { match fcx.inh.locals.find(id) { Some(x) => x, _ => { @@ -2571,20 +2578,18 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) { arg(ast::by_ref, visitor_trait)], ty::mk_nil(tcx)) } ~"frame_address" => { - let fty = ty::mk_fn(ccx.tcx, { - purity: ast::impure_fn, - proto: - ty::proto_vstore(ty::vstore_slice( - ty::re_bound(ty::br_anon(0)))), - bounds: @~[], - inputs: ~[{ - mode: ast::expl(ast::by_val), - ty: ty::mk_imm_ptr( - ccx.tcx, - ty::mk_mach_uint(ccx.tcx, ast::ty_u8)) - }], - output: ty::mk_nil(ccx.tcx), - ret_style: ast::return_val + let fty = ty::mk_fn(ccx.tcx, FnTyBase { + meta: FnMeta {purity: ast::impure_fn, + proto: ty::proto_vstore(ty::vstore_slice( + ty::re_bound(ty::br_anon(0)))), + bounds: @~[], + ret_style: ast::return_val}, + sig: FnSig {inputs: ~[{mode: ast::expl(ast::by_val), + ty: ty::mk_imm_ptr( + ccx.tcx, + ty::mk_mach_uint(ccx.tcx, ast::ty_u8)) + }], + output: ty::mk_nil(ccx.tcx)} }); (0u, ~[arg(ast::by_ref, fty)], ty::mk_nil(tcx)) } @@ -2597,11 +2602,14 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) { return; } }; - let fty = ty::mk_fn(tcx, {purity: ast::impure_fn, - proto: ty::proto_bare, - bounds: @~[], - inputs: inputs, output: output, - ret_style: ast::return_val}); + let fty = ty::mk_fn(tcx, FnTyBase { + meta: FnMeta {purity: ast::impure_fn, + proto: ty::proto_bare, + bounds: @~[], + ret_style: ast::return_val}, + sig: FnSig {inputs: inputs, + output: output} + }); let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id)); let i_n_tps = (*i_ty.bounds).len(); if i_n_tps != n_tps { diff --git a/src/rustc/middle/typeck/check/method.rs b/src/rustc/middle/typeck/check/method.rs index b356a1b7f67..52e8578124d 100644 --- a/src/rustc/middle/typeck/check/method.rs +++ b/src/rustc/middle/typeck/check/method.rs @@ -2,7 +2,7 @@ use coherence::get_base_type_def_id; use middle::resolve::{Impl, MethodInfo}; -use middle::ty::{mk_box, mk_rptr, mk_uniq}; +use middle::ty::{mk_box, mk_rptr, mk_uniq, FnTyBase, FnMeta, FnSig}; use syntax::ast::{def_id, sty_static, sty_box, sty_by_ref, sty_region, sty_uniq}; use syntax::ast::{sty_value, by_ref, by_copy}; @@ -411,9 +411,12 @@ struct lookup { fn ty_from_did(did: ast::def_id) -> ty::t { match ty::get(ty::lookup_item_type(self.tcx(), did).ty).struct { - ty::ty_fn(fty) => { - ty::mk_fn(self.tcx(), - {proto: ty::proto_vstore(ty::vstore_box),.. fty}) + ty::ty_fn(ref fty) => { + ty::mk_fn(self.tcx(), FnTyBase { + meta: FnMeta {proto: ty::proto_vstore(ty::vstore_box), + ..fty.meta}, + sig: fty.sig + }) } _ => fail ~"ty_from_did: not function ty" } @@ -553,8 +556,11 @@ struct lookup { // a bit hokey, but the method unbound has a bare protocol, whereas // a.b has a protocol like fn@() (perhaps eventually fn&()): - let fty = ty::mk_fn(tcx, {proto: ty::proto_vstore(ty::vstore_box), - .. m.fty}); + let fty = ty::mk_fn(tcx, FnTyBase { + meta: FnMeta {proto: ty::proto_vstore(ty::vstore_box), + ..m.fty.meta}, + sig: m.fty.sig + }); self.candidates.push( {self_ty: self.self_ty, diff --git a/src/rustc/middle/typeck/check/regionck.rs b/src/rustc/middle/typeck/check/regionck.rs index 6b7a8b4e402..bdb5cc5749c 100644 --- a/src/rustc/middle/typeck/check/regionck.rs +++ b/src/rustc/middle/typeck/check/regionck.rs @@ -216,10 +216,13 @@ fn visit_expr(e: @ast::expr, &&rcx: @rcx, v: rvt) { result::Err(_) => return, // Typechecking will fail anyhow. result::Ok(function_type) => { match ty::get(function_type).struct { - ty::ty_fn({ - proto: proto_vstore(vstore_slice(region)), _ - }) => { - constrain_free_variables(rcx, region, e); + ty::ty_fn(ref fn_ty) => { + match fn_ty.meta.proto { + proto_vstore(vstore_slice(region)) => { + constrain_free_variables(rcx, region, e); + } + _ => {} + } } _ => () } diff --git a/src/rustc/middle/typeck/check/regionmanip.rs b/src/rustc/middle/typeck/check/regionmanip.rs index 50666b92023..d7cbaa05588 100644 --- a/src/rustc/middle/typeck/check/regionmanip.rs +++ b/src/rustc/middle/typeck/check/regionmanip.rs @@ -9,9 +9,9 @@ fn replace_bound_regions_in_fn_ty( tcx: ty::ctxt, isr: isr_alist, self_info: Option, - fn_ty: &ty::fn_ty, + fn_ty: &ty::FnTy, mapf: fn(ty::bound_region) -> ty::region) -> - {isr: isr_alist, self_info: Option, fn_ty: ty::fn_ty} { + {isr: isr_alist, self_info: Option, fn_ty: ty::FnTy} { // Take self_info apart; the self_ty part is the only one we want // to update here. diff --git a/src/rustc/middle/typeck/collect.rs b/src/rustc/middle/typeck/collect.rs index 7bde062008d..3b25e41d313 100644 --- a/src/rustc/middle/typeck/collect.rs +++ b/src/rustc/middle/typeck/collect.rs @@ -23,6 +23,7 @@ are represented as `ty_param()` instances. use astconv::{ast_conv, ty_of_fn_decl, ty_of_arg, ast_ty_to_ty}; use ast_util::trait_method_to_ty_method; use rscope::*; +use ty::{FnTyBase, FnMeta, FnSig}; fn collect_item_types(ccx: @crate_ctxt, crate: @ast::crate) { @@ -127,14 +128,14 @@ fn get_enum_variant_types(ccx: @crate_ctxt, let arg_ty = ccx.to_ty(rs, va.ty); {mode: ast::expl(ast::by_copy), ty: arg_ty} }); - result_ty = Some(ty::mk_fn(tcx, - {purity: ast::pure_fn, - proto: ty::proto_vstore - (ty::vstore_box), - bounds: @~[], - inputs: args, - output: enum_ty, - ret_style: ast::return_val})); + result_ty = Some(ty::mk_fn(tcx, FnTyBase { + meta: FnMeta {purity: ast::pure_fn, + proto: ty::proto_vstore(ty::vstore_box), + bounds: @~[], + ret_style: ast::return_val}, + sig: FnSig {inputs: args, + output: enum_ty} + })); } ast::tuple_variant_kind(_) | ast::struct_variant_kind(_) => { result_ty = Some(enum_ty); @@ -247,7 +248,7 @@ fn compare_impl_method(tcx: ty::ctxt, sp: span, trait_m: ty::method, trait_substs: ty::substs, self_ty: ty::t) { - if impl_m.fty.purity != trait_m.fty.purity { + if impl_m.fty.meta.purity != trait_m.fty.meta.purity { tcx.sess.span_err( sp, fmt!("method `%s`'s purity does \ not match the trait method's \ @@ -268,12 +269,12 @@ fn compare_impl_method(tcx: ty::ctxt, sp: span, return; } - if vec::len(impl_m.fty.inputs) != vec::len(trait_m.fty.inputs) { + if vec::len(impl_m.fty.sig.inputs) != vec::len(trait_m.fty.sig.inputs) { tcx.sess.span_err(sp,fmt!("method `%s` has %u parameters \ but the trait has %u", tcx.sess.str_of(trait_m.ident), - vec::len(impl_m.fty.inputs), - vec::len(trait_m.fty.inputs))); + vec::len(impl_m.fty.sig.inputs), + vec::len(trait_m.fty.sig.inputs))); return; } @@ -488,13 +489,15 @@ fn convert_struct(ccx: @crate_ctxt, {self_r: rscope::bound_self_region(rp), self_ty: None, tps: ty::ty_params_to_tys(tcx, tps)}); - let t_ctor = ty::mk_fn( - tcx, {purity: ast::impure_fn, - proto: ty::proto_vstore(ty::vstore_slice(ty::re_static)), - bounds: @~[], - inputs: t_args, - output: t_res, - ret_style: ast::return_val}); + let proto = ty::proto_vstore(ty::vstore_slice(ty::re_static)); + let t_ctor = ty::mk_fn(tcx, FnTyBase { + meta: FnMeta {purity: ast::impure_fn, + proto: proto, + bounds: @~[], + ret_style: ast::return_val}, + sig: FnSig {inputs: t_args, + output: t_res} + }); write_ty_to_tcx(tcx, ctor.node.id, t_ctor); tcx.tcache.insert(local_def(ctor.node.id), {bounds: tpt.bounds, @@ -755,12 +758,14 @@ fn ty_of_foreign_fn_decl(ccx: @crate_ctxt, let input_tys = decl.inputs.map(|a| ty_of_arg(ccx, rb, a, None) ); let output_ty = ast_ty_to_ty(ccx, rb, decl.output); - let t_fn = ty::mk_fn(ccx.tcx, {purity: purity, - proto: ty::proto_bare, - bounds: @~[], - inputs: input_tys, - output: output_ty, - ret_style: ast::return_val}); + let t_fn = ty::mk_fn(ccx.tcx, FnTyBase { + meta: FnMeta {purity: purity, + proto: ty::proto_bare, + bounds: @~[], + ret_style: ast::return_val}, + sig: FnSig {inputs: input_tys, + output: output_ty} + }); let tpt = {bounds: bounds, region_param: None, ty: t_fn}; ccx.tcx.tcache.insert(def_id, tpt); return tpt; diff --git a/src/rustc/middle/typeck/infer.rs b/src/rustc/middle/typeck/infer.rs index a658ef044df..07752df7b45 100644 --- a/src/rustc/middle/typeck/infer.rs +++ b/src/rustc/middle/typeck/infer.rs @@ -250,7 +250,7 @@ use std::smallintmap; use std::smallintmap::smallintmap; use std::map::hashmap; use middle::ty; -use middle::ty::{ty_vid, int_vid, region_vid, vid, +use middle::ty::{TyVid, IntVid, RegionVid, vid, ty_int, ty_uint, get, terr_fn, TyVar, IntVar}; use syntax::{ast, ast_util}; use syntax::ast::{ret_style, purity}; @@ -312,11 +312,11 @@ enum infer_ctxt = @{ // We instantiate vals_and_bindings with bounds because the // types that might instantiate a general type variable have an // order, represented by its upper and lower bounds. - ty_var_bindings: vals_and_bindings>, + ty_var_bindings: vals_and_bindings>, // The types that might instantiate an integral type variable are // represented by an int_ty_set. - int_var_bindings: vals_and_bindings, + int_var_bindings: vals_and_bindings, // For region variables. region_vars: RegionVarBindings, @@ -328,11 +328,11 @@ enum infer_ctxt = @{ }; enum fixup_err { - unresolved_int_ty(int_vid), - unresolved_ty(ty_vid), - cyclic_ty(ty_vid), - unresolved_region(region_vid), - region_var_bound_by_region_var(region_vid, region_vid) + unresolved_int_ty(IntVid), + unresolved_ty(TyVid), + cyclic_ty(TyVid), + unresolved_region(RegionVid), + region_var_bound_by_region_var(RegionVid, RegionVid) } fn fixup_err_to_str(f: fixup_err) -> ~str { @@ -596,12 +596,12 @@ impl infer_ctxt { } impl infer_ctxt { - fn next_ty_var_id() -> ty_vid { + fn next_ty_var_id() -> TyVid { let id = *self.ty_var_counter; *self.ty_var_counter += 1u; self.ty_var_bindings.vals.insert(id, root({lb: None, ub: None}, 0u)); - return ty_vid(id); + return TyVid(id); } fn next_ty_var() -> ty::t { @@ -612,13 +612,13 @@ impl infer_ctxt { vec::from_fn(n, |_i| self.next_ty_var()) } - fn next_int_var_id() -> int_vid { + fn next_int_var_id() -> IntVid { let id = *self.int_var_counter; *self.int_var_counter += 1u; self.int_var_bindings.vals.insert(id, root(int_ty_set_all(), 0u)); - return int_vid(id); + return IntVid(id); } fn next_int_var() -> ty::t { diff --git a/src/rustc/middle/typeck/infer/combine.rs b/src/rustc/middle/typeck/infer/combine.rs index 2b194ebdf17..8199d7058ff 100644 --- a/src/rustc/middle/typeck/infer/combine.rs +++ b/src/rustc/middle/typeck/infer/combine.rs @@ -45,6 +45,7 @@ // now. use to_str::to_str; +use ty::{FnTyBase, FnMeta, FnSig}; trait combine { fn infcx() -> infer_ctxt; @@ -62,7 +63,9 @@ trait combine { fn self_tys(a: Option, b: Option) -> cres>; fn substs(did: ast::def_id, as: &ty::substs, bs: &ty::substs) -> cres; - fn fns(a: &ty::fn_ty, b: &ty::fn_ty) -> cres; + fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres; + fn fn_sigs(a: &ty::FnSig, b: &ty::FnSig) -> cres; + fn fn_metas(a: &ty::FnMeta, b: &ty::FnMeta) -> cres; fn flds(a: ty::field, b: ty::field) -> cres; fn modes(a: ast::mode, b: ast::mode) -> cres; fn args(a: ty::arg, b: ty::arg) -> cres; @@ -302,37 +305,47 @@ fn super_vstores( } } -fn super_fns( - self: &C, a_f: &ty::fn_ty, b_f: &ty::fn_ty) -> cres { +fn super_fn_metas( + self: &C, a_f: &ty::FnMeta, b_f: &ty::FnMeta) -> cres +{ + do self.protos(a_f.proto, b_f.proto).chain |p| { + do self.ret_styles(a_f.ret_style, b_f.ret_style).chain |rs| { + do self.purities(a_f.purity, b_f.purity).chain |purity| { + Ok(FnMeta {purity: purity, + proto: p, + bounds: a_f.bounds, // XXX: This is wrong! + ret_style: rs}) + } + } + } +} +fn super_fn_sigs( + self: &C, a_f: &ty::FnSig, b_f: &ty::FnSig) -> cres +{ fn argvecs(self: &C, a_args: ~[ty::arg], b_args: ~[ty::arg]) -> cres<~[ty::arg]> { if vec::same_length(a_args, b_args) { - map_vec2(a_args, b_args, |a, b| self.args(a, b) ) + map_vec2(a_args, b_args, |a, b| self.args(a, b)) } else { Err(ty::terr_arg_count) } } - do self.protos(a_f.proto, b_f.proto).chain |p| { - do self.ret_styles(a_f.ret_style, b_f.ret_style).chain |rs| { - do argvecs(self, a_f.inputs, b_f.inputs).chain |inputs| { - do self.tys(a_f.output, b_f.output).chain |output| { - do self.purities(a_f.purity, b_f.purity).chain |purity| { - // FIXME: uncomment if #2588 doesn't get accepted: - // self.infcx().constrvecs(a_f.constraints, - // b_f.constraints).then {|| - Ok({purity: purity, - proto: p, - bounds: a_f.bounds, // XXX: This is wrong! - inputs: inputs, - output: output, - ret_style: rs}) - // } - } - } - } + do argvecs(self, a_f.inputs, b_f.inputs).chain |inputs| { + do self.tys(a_f.output, b_f.output).chain |output| { + Ok(FnSig {inputs: inputs, output: output}) + } + } +} + +fn super_fns( + self: &C, a_f: &ty::FnTy, b_f: &ty::FnTy) -> cres +{ + do self.fn_metas(&a_f.meta, &b_f.meta).chain |m| { + do self.fn_sigs(&a_f.sig, &b_f.sig).chain |s| { + Ok(FnTyBase {meta: m, sig: s}) } } } diff --git a/src/rustc/middle/typeck/infer/glb.rs b/src/rustc/middle/typeck/infer/glb.rs index 7ef0bf91943..b69d85d9fe4 100644 --- a/src/rustc/middle/typeck/infer/glb.rs +++ b/src/rustc/middle/typeck/infer/glb.rs @@ -147,10 +147,18 @@ impl Glb: combine { super_args(&self, a, b) } - fn fns(a: &ty::fn_ty, b: &ty::fn_ty) -> cres { + fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres { super_fns(&self, a, b) } + fn fn_metas(a: &ty::FnMeta, b: &ty::FnMeta) -> cres { + super_fn_metas(&self, a, b) + } + + fn fn_sigs(a: &ty::FnSig, b: &ty::FnSig) -> cres { + super_fn_sigs(&self, a, b) + } + fn substs(did: ast::def_id, as: &ty::substs, bs: &ty::substs) -> cres { diff --git a/src/rustc/middle/typeck/infer/lattice.rs b/src/rustc/middle/typeck/infer/lattice.rs index 5fc9ee8d1a7..49b2e57e2aa 100644 --- a/src/rustc/middle/typeck/infer/lattice.rs +++ b/src/rustc/middle/typeck/infer/lattice.rs @@ -68,7 +68,7 @@ fn lattice_tys( } fn lattice_vars( - self: &L, +a_t: ty::t, +a_vid: ty::ty_vid, +b_vid: ty::ty_vid, + self: &L, +a_t: ty::t, +a_vid: ty::TyVid, +b_vid: ty::TyVid, c_ts: fn(ty::t, ty::t) -> cres) -> cres { // The comments in this function are written for LUB and types, @@ -112,7 +112,7 @@ fn lattice_vars( } fn lattice_var_and_t( - self: &L, a_id: ty::ty_vid, b: ty::t, + self: &L, a_id: ty::TyVid, b: ty::t, c_ts: fn(ty::t, ty::t) -> cres) -> cres { let vb = &self.infcx().ty_var_bindings; diff --git a/src/rustc/middle/typeck/infer/lub.rs b/src/rustc/middle/typeck/infer/lub.rs index 21e2a9febec..0c2f9ca6b13 100644 --- a/src/rustc/middle/typeck/infer/lub.rs +++ b/src/rustc/middle/typeck/infer/lub.rs @@ -126,10 +126,18 @@ impl Lub: combine { super_args(&self, a, b) } - fn fns(a: &ty::fn_ty, b: &ty::fn_ty) -> cres { + fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres { super_fns(&self, a, b) } + fn fn_metas(a: &ty::FnMeta, b: &ty::FnMeta) -> cres { + super_fn_metas(&self, a, b) + } + + fn fn_sigs(a: &ty::FnSig, b: &ty::FnSig) -> cres { + super_fn_sigs(&self, a, b) + } + fn substs(did: ast::def_id, as: &ty::substs, bs: &ty::substs) -> cres { diff --git a/src/rustc/middle/typeck/infer/region_var_bindings.rs b/src/rustc/middle/typeck/infer/region_var_bindings.rs index 70dd5777e3d..b34ffef811a 100644 --- a/src/rustc/middle/typeck/infer/region_var_bindings.rs +++ b/src/rustc/middle/typeck/infer/region_var_bindings.rs @@ -312,7 +312,7 @@ use std::map::{hashmap, uint_hash}; use std::cell::{Cell, empty_cell}; use std::list::{List, Nil, Cons}; -use ty::{region, region_vid, hash_region}; +use ty::{region, RegionVid, hash_region}; use region::is_subregion_of; use syntax::codemap; use to_str::to_str; @@ -324,9 +324,9 @@ export lub_regions; export glb_regions; enum Constraint { - ConstrainVarSubVar(region_vid, region_vid), - ConstrainRegSubVar(region, region_vid), - ConstrainVarSubReg(region_vid, region) + ConstrainVarSubVar(RegionVid, RegionVid), + ConstrainRegSubVar(region, RegionVid), + ConstrainVarSubReg(RegionVid, region) } impl Constraint: cmp::Eq { @@ -361,12 +361,12 @@ impl TwoRegions: cmp::Eq { enum UndoLogEntry { Snapshot, - AddVar(region_vid), + AddVar(RegionVid), AddConstraint(Constraint), AddCombination(CombineMap, TwoRegions) } -type CombineMap = hashmap; +type CombineMap = hashmap; struct RegionVarBindings { tcx: ty::ctxt; @@ -470,10 +470,10 @@ impl RegionVarBindings { self.var_spans.len() } - fn new_region_var(span: span) -> region_vid { + fn new_region_var(span: span) -> RegionVid { let id = self.num_vars(); self.var_spans.push(span); - let vid = region_vid(id); + let vid = RegionVid(id); if self.in_snapshot() { self.undo_log.push(AddVar(vid)); } @@ -568,7 +568,7 @@ impl RegionVarBindings { } } - fn resolve_var(rid: region_vid) -> ty::region { + fn resolve_var(rid: RegionVid) -> ty::region { debug!("RegionVarBindings: resolve_var(%?)", rid); if self.values.is_empty() { self.tcx.sess.span_bug( @@ -857,7 +857,7 @@ impl RegionVarBindings { return graph; fn insert_edge(graph: &mut Graph, - node_id: region_vid, + node_id: RegionVid, edge_dir: Direction, edge_idx: uint) { let edge_dir = edge_dir as uint; @@ -893,7 +893,7 @@ impl RegionVarBindings { } fn expand_node(a_region: region, - b_vid: region_vid, + b_vid: RegionVid, b_node: &GraphNode) -> bool { debug!("expand_node(%?, %? == %?)", a_region, b_vid, b_node.value); @@ -950,7 +950,7 @@ impl RegionVarBindings { } } - fn contract_node(a_vid: region_vid, + fn contract_node(a_vid: RegionVid, a_node: &GraphNode, b_region: region) -> bool { debug!("contract_node(%? == %?/%?, %?)", @@ -980,7 +980,7 @@ impl RegionVarBindings { }; fn check_node(self: &RegionVarBindings, - a_vid: region_vid, + a_vid: RegionVid, a_node: &GraphNode, a_region: region, b_region: region) -> bool { @@ -993,7 +993,7 @@ impl RegionVarBindings { } fn adjust_node(self: &RegionVarBindings, - a_vid: region_vid, + a_vid: RegionVid, a_node: &GraphNode, a_region: region, b_region: region) -> bool { @@ -1051,7 +1051,7 @@ impl RegionVarBindings { } ErrorValue => { - let node_vid = region_vid(idx); + let node_vid = RegionVid(idx); match node.classification { Expanding => { self.report_error_for_expanding_node( @@ -1078,7 +1078,7 @@ impl RegionVarBindings { fn report_error_for_expanding_node(graph: &Graph, dup_map: TwoRegionsMap, - node_idx: region_vid) { + node_idx: RegionVid) { // Errors in expanding nodes result from a lower-bound that is // not contained by an upper-bound. let lower_bounds = @@ -1130,7 +1130,7 @@ impl RegionVarBindings { fn report_error_for_contracting_node(graph: &Graph, dup_map: TwoRegionsMap, - node_idx: region_vid) { + node_idx: RegionVid) { // Errors in contracting nodes result from two upper-bounds // that have no intersection. let upper_bounds = self.collect_concrete_regions(graph, node_idx, @@ -1182,7 +1182,7 @@ impl RegionVarBindings { } fn collect_concrete_regions(graph: &Graph, - orig_node_idx: region_vid, + orig_node_idx: RegionVid, dir: Direction) -> ~[SpannedRegion] { let set = uint_hash(); let mut stack = ~[orig_node_idx]; @@ -1224,7 +1224,7 @@ impl RegionVarBindings { } fn each_edge(graph: &Graph, - node_idx: region_vid, + node_idx: RegionVid, dir: Direction, op: fn(edge: &GraphEdge) -> bool) { let mut edge_idx = graph.nodes[*node_idx].head_edge[dir as uint]; diff --git a/src/rustc/middle/typeck/infer/resolve.rs b/src/rustc/middle/typeck/infer/resolve.rs index 8d6841357c0..e77b5a52aaf 100644 --- a/src/rustc/middle/typeck/infer/resolve.rs +++ b/src/rustc/middle/typeck/infer/resolve.rs @@ -55,7 +55,7 @@ type resolve_state_ = { infcx: infer_ctxt, modes: uint, mut err: Option, - mut v_seen: ~[ty_vid] + mut v_seen: ~[TyVid] }; enum resolve_state { @@ -153,14 +153,14 @@ impl resolve_state { } } - fn resolve_region_var(rid: region_vid) -> ty::region { + fn resolve_region_var(rid: RegionVid) -> ty::region { if !self.should(resolve_rvar) { return ty::re_var(rid) } self.infcx.region_vars.resolve_var(rid) } - fn assert_not_rvar(rid: region_vid, r: ty::region) { + fn assert_not_rvar(rid: RegionVid, r: ty::region) { match r { ty::re_var(rid2) => { self.err = Some(region_var_bound_by_region_var(rid, rid2)); @@ -169,7 +169,7 @@ impl resolve_state { } } - fn resolve_ty_var(vid: ty_vid) -> ty::t { + fn resolve_ty_var(vid: TyVid) -> ty::t { if vec::contains(self.v_seen, vid) { self.err = Some(cyclic_ty(vid)); return ty::mk_var(self.infcx.tcx, vid); @@ -202,7 +202,7 @@ impl resolve_state { } } - fn resolve_int_var(vid: int_vid) -> ty::t { + fn resolve_int_var(vid: IntVid) -> ty::t { if !self.should(resolve_ivar) { return ty::mk_int_var(self.infcx.tcx, vid); } diff --git a/src/rustc/middle/typeck/infer/sub.rs b/src/rustc/middle/typeck/infer/sub.rs index f3853134a37..8c83f03838a 100644 --- a/src/rustc/middle/typeck/infer/sub.rs +++ b/src/rustc/middle/typeck/infer/sub.rs @@ -124,7 +124,7 @@ impl Sub: combine { } } - fn fns(a: &ty::fn_ty, b: &ty::fn_ty) -> cres { + fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres { // Rather than checking the subtype relationship between `a` and `b` // as-is, we need to do some extra work here in order to make sure // that function subtyping works correctly with respect to regions @@ -171,6 +171,14 @@ impl Sub: combine { super_flds(&self, a, b) } + fn fn_metas(a: &ty::FnMeta, b: &ty::FnMeta) -> cres { + super_fn_metas(&self, a, b) + } + + fn fn_sigs(a: &ty::FnSig, b: &ty::FnSig) -> cres { + super_fn_sigs(&self, a, b) + } + fn vstores(vk: ty::terr_vstore_kind, a: ty::vstore, b: ty::vstore) -> cres { super_vstores(&self, vk, a, b) diff --git a/src/rustc/middle/typeck/infer/unify.rs b/src/rustc/middle/typeck/infer/unify.rs index e8e834cfc57..65cbcdcb40a 100644 --- a/src/rustc/middle/typeck/infer/unify.rs +++ b/src/rustc/middle/typeck/infer/unify.rs @@ -113,7 +113,7 @@ fn merge_bnds( fn set_var_to_merged_bounds( self: &C, - v_id: ty::ty_vid, + v_id: ty::TyVid, a: bounds, b: bounds, rank: uint) -> ures { @@ -175,8 +175,8 @@ fn set_var_to_merged_bounds( /// subtle and tricky process, as described in detail at the top /// of infer.rs fn var_sub_var(self: &C, - a_id: ty::ty_vid, - b_id: ty::ty_vid) -> ures { + a_id: ty::TyVid, + b_id: ty::TyVid) -> ures { let vb = &self.infcx().ty_var_bindings; // Need to make sub_id a subtype of sup_id. @@ -241,7 +241,7 @@ fn var_sub_var(self: &C, } /// make variable a subtype of T -fn var_sub_t(self: &C, a_id: ty::ty_vid, b: ty::t) -> ures { +fn var_sub_t(self: &C, a_id: ty::TyVid, b: ty::t) -> ures { let vb = &self.infcx().ty_var_bindings; let nde_a = self.infcx().get(vb, a_id); @@ -257,7 +257,7 @@ fn var_sub_t(self: &C, a_id: ty::ty_vid, b: ty::t) -> ures { } /// make T a subtype of variable -fn t_sub_var(self: &C, a: ty::t, b_id: ty::ty_vid) -> ures { +fn t_sub_var(self: &C, a: ty::t, b_id: ty::TyVid) -> ures { let vb = &self.infcx().ty_var_bindings; let a_bounds = {lb: Some(a), ub: None}; @@ -294,7 +294,7 @@ fn bnds( // Integral variables impl infer_ctxt { - fn int_vars(a_id: ty::int_vid, b_id: ty::int_vid) -> ures { + fn int_vars(a_id: ty::IntVid, b_id: ty::IntVid) -> ures { let vb = &self.int_var_bindings; let nde_a = self.get(vb, a_id); @@ -340,7 +340,7 @@ impl infer_ctxt { uok() } - fn int_var_sub_t(a_id: ty::int_vid, b: ty::t) -> ures { + fn int_var_sub_t(a_id: ty::IntVid, b: ty::t) -> ures { assert ty::type_is_integral(b); let vb = &self.int_var_bindings; @@ -358,7 +358,7 @@ impl infer_ctxt { uok() } - fn t_sub_int_var(a: ty::t, b_id: ty::int_vid) -> ures { + fn t_sub_int_var(a: ty::t, b_id: ty::IntVid) -> ures { assert ty::type_is_integral(a); let vb = &self.int_var_bindings; diff --git a/src/rustc/util/ppaux.rs b/src/rustc/util/ppaux.rs index bb54e9df19b..f78495ef198 100644 --- a/src/rustc/util/ppaux.rs +++ b/src/rustc/util/ppaux.rs @@ -283,8 +283,9 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str { } fn method_to_str(cx: ctxt, m: method) -> ~str { return fn_to_str( - cx, m.fty.purity, m.fty.proto, Some(m.ident), m.fty.inputs, - m.fty.output, m.fty.ret_style) + ~";"; + cx, m.fty.meta.purity, m.fty.meta.proto, Some(m.ident), + m.fty.sig.inputs, m.fty.sig.output, + m.fty.meta.ret_style) + ~";"; } fn field_to_str(cx: ctxt, f: field) -> ~str { return cx.sess.str_of(f.ident) + ~": " + mt_to_str(cx, f.mt); @@ -331,9 +332,9 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str { for elems.each |elem| { vec::push(strs, ty_to_str(cx, elem)); } ~"(" + str::connect(strs, ~",") + ~")" } - ty_fn(f) => { - fn_to_str(cx, f.purity, f.proto, None, f.inputs, - f.output, f.ret_style) + ty_fn(ref f) => { + fn_to_str(cx, f.meta.purity, f.meta.proto, None, f.sig.inputs, + f.sig.output, f.meta.ret_style) } ty_infer(infer_ty) => infer_ty.to_str(), ty_param({idx: id, _}) => {