diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2012-11-04 20:41:00 -0800 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2012-11-06 08:56:29 -0800 |
| commit | b0ed151539cddb1c191f67f9f9597942919d44eb (patch) | |
| tree | 976ed7cab726c0cdae81e0a18e28a27cbd5e4664 /src/rustc | |
| parent | 53ec6c3f9b495dd930cd061784251534bef58d74 (diff) | |
| download | rust-b0ed151539cddb1c191f67f9f9597942919d44eb.tar.gz rust-b0ed151539cddb1c191f67f9f9597942919d44eb.zip | |
Cleanup how we handle proto in types, remove unsound subtyping
Fixes #1896 which was never truly fixed, just masked. The given tests would have failed had they used `~fn()` and not `@fn()`. They now result in compilation errors. Fixes #2978. Necessary first step for #2202, #2263.
Diffstat (limited to 'src/rustc')
30 files changed, 576 insertions, 693 deletions
diff --git a/src/rustc/front/test.rs b/src/rustc/front/test.rs index f0c9de4f2a2..c839be0739f 100644 --- a/src/rustc/front/test.rs +++ b/src/rustc/front/test.rs @@ -406,7 +406,7 @@ fn mk_test_wrapper(cx: test_ctxt, let wrapper_expr: ast::expr = { id: cx.sess.next_node_id(), callee_id: cx.sess.next_node_id(), - node: ast::expr_fn(ast::proto_bare, wrapper_decl, + node: ast::expr_fn(ast::ProtoBare, wrapper_decl, wrapper_body, @~[]), span: span }; diff --git a/src/rustc/metadata/tydecode.rs b/src/rustc/metadata/tydecode.rs index f15c254e71c..51c56cb8a64 100644 --- a/src/rustc/metadata/tydecode.rs +++ b/src/rustc/metadata/tydecode.rs @@ -103,11 +103,13 @@ fn parse_ty_rust_fn(st: @pstate, conv: conv_did) -> ty::t { return ty::mk_fn(st.tcx, parse_ty_fn(st, conv)); } -fn parse_proto(st: @pstate) -> ty::fn_proto { +fn parse_proto(st: @pstate) -> ast::Proto { match next(st) { - 'n' => ty::proto_bare, - 'v' => ty::proto_vstore(parse_vstore(st)), - c => fail ~"illegal proto type kind " + str::from_char(c) + '_' => ast::ProtoBare, + '@' => ast::ProtoBox, + '~' => ast::ProtoUniq, + '&' => ast::ProtoBorrowed, + _ => fail ~"parse_proto(): bad input" } } @@ -293,13 +295,8 @@ fn parse_ty(st: @pstate, conv: conv_did) -> ty::t { } 'Y' => return ty::mk_type(st.tcx), 'C' => { - let ck = match next(st) { - '&' => ty::ck_block, - '@' => ty::ck_box, - '~' => ty::ck_uniq, - _ => fail ~"parse_ty: bad closure kind" - }; - return ty::mk_opaque_closure_ptr(st.tcx, ck); + let proto = parse_proto(st); + return ty::mk_opaque_closure_ptr(st.tcx, proto); } '#' => { let pos = parse_hex(st); @@ -415,6 +412,7 @@ fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::FnTy { let proto = parse_proto(st); let purity = parse_purity(next(st)); let onceness = parse_onceness(next(st)); + let region = parse_region(st); let bounds = parse_bounds(st, conv); assert (next(st) == '['); let mut inputs: ~[ty::arg] = ~[]; @@ -429,6 +427,7 @@ fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::FnTy { proto: proto, onceness: onceness, bounds: bounds, + region: region, 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 725b8c41f5c..4129066ff28 100644 --- a/src/rustc/metadata/tyencode.rs +++ b/src/rustc/metadata/tyencode.rs @@ -296,9 +296,10 @@ fn enc_sty(w: io::Writer, cx: @ctxt, st: ty::sty) { w.write_char('s'); } ty::ty_type => w.write_char('Y'), - ty::ty_opaque_closure_ptr(ty::ck_block) => w.write_str(&"C&"), - ty::ty_opaque_closure_ptr(ty::ck_box) => w.write_str(&"C@"), - ty::ty_opaque_closure_ptr(ty::ck_uniq) => w.write_str(&"C~"), + ty::ty_opaque_closure_ptr(p) => { + w.write_str(&"C&"); + enc_proto(w, p); + } ty::ty_opaque_box => w.write_char('B'), ty::ty_class(def, substs) => { debug!("~~~~ %s", ~"a["); @@ -315,14 +316,13 @@ fn enc_sty(w: io::Writer, cx: @ctxt, st: ty::sty) { } } -fn enc_proto(w: io::Writer, cx: @ctxt, proto: ty::fn_proto) { +fn enc_proto(w: io::Writer, proto: Proto) { w.write_str(&"f"); match proto { - ty::proto_bare => w.write_str(&"n"), - ty::proto_vstore(vstore) => { - w.write_str(&"v"); - enc_vstore(w, cx, vstore); - } + ProtoBare => w.write_str(&"_"), + ProtoBox => w.write_str(&"@"), + ProtoUniq => w.write_str(&"~"), + ProtoBorrowed => w.write_str(&"&"), } } @@ -357,9 +357,10 @@ fn enc_onceness(w: io::Writer, o: Onceness) { } fn enc_ty_fn(w: io::Writer, cx: @ctxt, ft: ty::FnTy) { - enc_proto(w, cx, ft.meta.proto); + enc_proto(w, ft.meta.proto); enc_purity(w, ft.meta.purity); enc_onceness(w, ft.meta.onceness); + enc_region(w, cx, ft.meta.region); enc_bounds(w, cx, ft.meta.bounds); w.write_char('['); for ft.sig.inputs.each |arg| { diff --git a/src/rustc/middle/borrowck/check_loans.rs b/src/rustc/middle/borrowck/check_loans.rs index efde1985677..d63f52a4a58 100644 --- a/src/rustc/middle/borrowck/check_loans.rs +++ b/src/rustc/middle/borrowck/check_loans.rs @@ -234,7 +234,7 @@ impl check_loan_ctxt { fn is_stack_closure(id: ast::node_id) -> bool { let fn_ty = ty::node_id_to_type(self.tcx(), id); let proto = ty::ty_fn_proto(fn_ty); - return ty::is_blockish(proto); + return proto == ast::ProtoBorrowed; } fn is_allowed_pure_arg(expr: @ast::expr) -> bool { diff --git a/src/rustc/middle/borrowck/gather_loans.rs b/src/rustc/middle/borrowck/gather_loans.rs index 23f0d9edbfa..9875e8600ea 100644 --- a/src/rustc/middle/borrowck/gather_loans.rs +++ b/src/rustc/middle/borrowck/gather_loans.rs @@ -241,12 +241,18 @@ impl gather_loan_ctxt { autoref.mutbl, autoref.region) } - ty::AutoSlice => { + ty::AutoBorrowVec => { let cmt_index = mcx.cat_index(expr, cmt); self.guarantee_valid(cmt_index, autoref.mutbl, autoref.region) } + ty::AutoBorrowFn => { + let cmt_deref = mcx.cat_deref_fn(expr, cmt, 0); + self.guarantee_valid(cmt_deref, + autoref.mutbl, + autoref.region) + } } } } diff --git a/src/rustc/middle/capture.rs b/src/rustc/middle/capture.rs index 563ea8f84be..dae17f66d15 100644 --- a/src/rustc/middle/capture.rs +++ b/src/rustc/middle/capture.rs @@ -58,7 +58,7 @@ fn check_capture_clause(tcx: ty::ctxt, fn compute_capture_vars(tcx: ty::ctxt, fn_expr_id: ast::node_id, - fn_proto: ty::fn_proto, + fn_proto: ast::Proto, cap_clause: ast::capture_clause) -> ~[capture_var] { let freevars = freevars::get_freevars(tcx, fn_expr_id); let cap_map = map::HashMap(); @@ -101,7 +101,7 @@ fn compute_capture_vars(tcx: ty::ctxt, // named and add that let implicit_mode; - if ty::is_blockish(fn_proto) { + if fn_proto == ast::ProtoBorrowed { implicit_mode = cap_ref; } else { implicit_mode = cap_copy; diff --git a/src/rustc/middle/check_loop.rs b/src/rustc/middle/check_loop.rs index 3fa7f34fb33..de275fdcfc4 100644 --- a/src/rustc/middle/check_loop.rs +++ b/src/rustc/middle/check_loop.rs @@ -24,8 +24,8 @@ fn check_crate(tcx: ty::ctxt, crate: @crate) { v.visit_block(b, {in_loop: false, can_ret: false}, v); } expr_loop_body(@{node: expr_fn_block(_, b, _), _}) => { - let blk = ty::is_blockish(ty::ty_fn_proto(ty::expr_ty(tcx, - e))); + let proto = ty::ty_fn_proto(ty::expr_ty(tcx, e)); + let blk = (proto == ProtoBorrowed); v.visit_block(b, {in_loop: true, can_ret: blk}, v); } expr_break(_) => { diff --git a/src/rustc/middle/freevars.rs b/src/rustc/middle/freevars.rs index 1b42c9bb4b6..16f4a66ff0b 100644 --- a/src/rustc/middle/freevars.rs +++ b/src/rustc/middle/freevars.rs @@ -40,7 +40,7 @@ fn collect_freevars(def_map: resolve::DefMap, blk: ast::blk) let walk_expr = fn@(expr: @ast::expr, &&depth: int, v: visit::vt<int>) { match expr.node { ast::expr_fn(proto, _, _, _) => { - if proto != ast::proto_bare { + if proto != ast::ProtoBare { visit::visit_expr(expr, depth + 1, v); } } diff --git a/src/rustc/middle/kind.rs b/src/rustc/middle/kind.rs index 8eace4f5cf1..c0887150f24 100644 --- a/src/rustc/middle/kind.rs +++ b/src/rustc/middle/kind.rs @@ -159,12 +159,10 @@ fn with_appropriate_checker(cx: ctx, id: node_id, b: fn(check_fn)) { let fty = ty::node_id_to_type(cx.tcx, id); match ty::ty_fn_proto(fty) { - ty::proto_vstore(ty::vstore_uniq) => b(check_for_uniq), - ty::proto_vstore(ty::vstore_box) => b(check_for_box), - ty::proto_bare => b(check_for_bare), - ty::proto_vstore(ty::vstore_slice(_)) => b(check_for_block), - ty::proto_vstore(ty::vstore_fixed(_)) => - fail ~"fixed vstore not allowed here" + ProtoUniq => b(check_for_uniq), + ProtoBox => b(check_for_box), + ProtoBare => b(check_for_bare), + ProtoBorrowed => b(check_for_block), } } diff --git a/src/rustc/middle/lint.rs b/src/rustc/middle/lint.rs index 9d28e35acb0..3be1e6d1a61 100644 --- a/src/rustc/middle/lint.rs +++ b/src/rustc/middle/lint.rs @@ -841,29 +841,15 @@ fn check_fn_deprecated_modes(tcx: ty::ctxt, fn_ty: ty::t, decl: ast::fn_decl, let span = arg_ast.ty.span; // Recurse to check fn-type argument match arg_ast.ty.node { - ast::ty_fn(_, _, _, _, decl) => { + ast::ty_fn(f) => { check_fn_deprecated_modes(tcx, arg_ty.ty, - decl, span, id); + f.decl, span, id); } ast::ty_path(*) => { // This is probably a typedef, so we can't // see the actual fn decl // e.g. fn foo(f: InitOp<T>) } - ast::ty_rptr(_, mt) - | ast::ty_box(mt) - | ast::ty_uniq(mt) => { - // Functions with preceding sigil are parsed - // as pointers of functions - match mt.ty.node { - ast::ty_fn(_, _, _, _, decl) => { - check_fn_deprecated_modes( - tcx, arg_ty.ty, - decl, span, id); - } - _ => fail - } - } _ => { tcx.sess.span_warn(span, ~"what"); error!("arg %d, ty=%s, mode=%s", @@ -889,10 +875,10 @@ fn check_item_deprecated_modes(tcx: ty::ctxt, it: @ast::item) { match it.node { ast::item_ty(ty, _) => { match ty.node { - ast::ty_fn(_, _, _, _, decl) => { + ast::ty_fn(f) => { let fn_ty = ty::node_id_to_type(tcx, it.id); check_fn_deprecated_modes( - tcx, fn_ty, decl, ty.span, it.id) + tcx, fn_ty, f.decl, ty.span, it.id) } _ => () } diff --git a/src/rustc/middle/mem_categorization.rs b/src/rustc/middle/mem_categorization.rs index 55bf41b573e..a43dc0747de 100644 --- a/src/rustc/middle/mem_categorization.rs +++ b/src/rustc/middle/mem_categorization.rs @@ -305,18 +305,30 @@ fn opt_deref_kind(t: ty::t) -> Option<deref_kind> { Some(deref_ptr(uniq_ptr)) } + ty::ty_fn(f) if f.meta.proto == ast::ProtoUniq => { + Some(deref_ptr(uniq_ptr)) + } + ty::ty_rptr(r, _) | ty::ty_evec(_, ty::vstore_slice(r)) | ty::ty_estr(ty::vstore_slice(r)) => { Some(deref_ptr(region_ptr(r))) } + ty::ty_fn(f) if f.meta.proto == ast::ProtoBorrowed => { + Some(deref_ptr(region_ptr(f.meta.region))) + } + ty::ty_box(*) | ty::ty_evec(_, ty::vstore_box) | ty::ty_estr(ty::vstore_box) => { Some(deref_ptr(gc_ptr)) } + ty::ty_fn(f) if f.meta.proto == ast::ProtoBox => { + Some(deref_ptr(gc_ptr)) + } + ty::ty_ptr(*) => { Some(deref_ptr(unsafe_ptr)) } @@ -563,22 +575,23 @@ impl &mem_categorization_ctxt { let ty = ty::node_id_to_type(self.tcx, fn_node_id); let proto = ty::ty_fn_proto(ty); match proto { - ty::proto_vstore(ty::vstore_slice(_)) => { - let upcmt = self.cat_def(id, span, expr_ty, *inner); - @{id:id, span:span, - cat:cat_stack_upvar(upcmt), lp:upcmt.lp, - mutbl:upcmt.mutbl, ty:upcmt.ty} - } - ty::proto_bare | - ty::proto_vstore(ty::vstore_uniq) | - ty::proto_vstore(ty::vstore_box) => { - // FIXME #2152 allow mutation of moved upvars - @{id:id, span:span, - cat:cat_special(sk_heap_upvar), lp:None, - mutbl:m_imm, ty:expr_ty} - } - ty::proto_vstore(ty::vstore_fixed(_)) => - fail ~"fixed vstore not allowed here" + ast::ProtoBorrowed => { + let upcmt = self.cat_def(id, span, expr_ty, *inner); + @{id:id, span:span, + cat:cat_stack_upvar(upcmt), lp:upcmt.lp, + mutbl:upcmt.mutbl, ty:upcmt.ty} + } + ast::ProtoUniq | ast::ProtoBox => { + // FIXME #2152 allow mutation of moved upvars + @{id:id, span:span, + cat:cat_special(sk_heap_upvar), lp:None, + mutbl:m_imm, ty:expr_ty} + } + ast::ProtoBare => { + self.tcx.sess.span_bug( + span, + fmt!("Upvar in a bare closure?")); + } } } @@ -648,16 +661,16 @@ impl &mem_categorization_ctxt { base_cmt: cmt, f_name: ast::ident, field_id: ast::node_id) -> cmt { - let f_mutbl = match field_mutbl(self.tcx, base_cmt.ty, f_name, - field_id) { - Some(f_mutbl) => f_mutbl, - None => { - self.tcx.sess.span_bug( - node.span(), - fmt!("Cannot find field `%s` in type `%s`", - self.tcx.sess.str_of(f_name), - ty_to_str(self.tcx, base_cmt.ty))); - } + let f_mutbl = match field_mutbl(self.tcx, base_cmt.ty, + f_name, field_id) { + Some(f_mutbl) => f_mutbl, + None => { + self.tcx.sess.span_bug( + node.span(), + fmt!("Cannot find field `%s` in type `%s`", + self.tcx.sess.str_of(f_name), + ty_to_str(self.tcx, base_cmt.ty))); + } }; let m = self.inherited_mutability(base_cmt.mutbl, f_mutbl); let f_comp = comp_field(f_name, f_mutbl); @@ -667,9 +680,24 @@ impl &mem_categorization_ctxt { mutbl: m, ty: self.tcx.ty(node)} } + fn cat_deref_fn<N:ast_node>(node: N, + base_cmt: cmt, + deref_cnt: uint) -> cmt + { + // Bit of a hack: the "dereference" of a function pointer like + // `@fn()` is a mere logical concept. We interpret it as + // dereferencing the environment pointer; of course, we don't + // know what type lies at the other end, so we just call it + // `()` (the empty tuple). + + let mt = {ty: ty::mk_tup(self.tcx, ~[]), mutbl: m_imm}; + return self.cat_deref_common(node, base_cmt, deref_cnt, mt); + } + fn cat_deref<N:ast_node>(node: N, base_cmt: cmt, - deref_cnt: uint) -> cmt { + deref_cnt: uint) -> cmt + { let mt = match ty::deref(self.tcx, base_cmt.ty, true) { Some(mt) => mt, None => { @@ -680,6 +708,14 @@ impl &mem_categorization_ctxt { } }; + return self.cat_deref_common(node, base_cmt, deref_cnt, mt); + } + + fn cat_deref_common<N:ast_node>(node: N, + base_cmt: cmt, + deref_cnt: uint, + mt: ty::mt) -> cmt + { match deref_kind(self.tcx, base_cmt.ty) { deref_ptr(ptr) => { let lp = do base_cmt.lp.chain_ref |l| { diff --git a/src/rustc/middle/region.rs b/src/rustc/middle/region.rs index a98ec2181d9..0be27483a10 100644 --- a/src/rustc/middle/region.rs +++ b/src/rustc/middle/region.rs @@ -615,23 +615,35 @@ fn determine_rp_in_ty(ty: @ast::Ty, // region is expected (and hence is a supertype of those // locations) match ty.node { - ast::ty_rptr(r, _) => { - debug!("referenced rptr type %s", - pprust::ty_to_str(ty, cx.sess.intr())); + ast::ty_rptr(r, _) => { + debug!("referenced rptr type %s", + pprust::ty_to_str(ty, cx.sess.intr())); - if cx.region_is_relevant(r) { - cx.add_rp(cx.item_id, cx.add_variance(rv_contravariant)) + if cx.region_is_relevant(r) { + cx.add_rp(cx.item_id, cx.add_variance(rv_contravariant)) + } } - } - ast::ty_fn(ast::proto_bare, _, _, _, _) | - ast::ty_fn(ast::proto_block, _, _, _, _) if cx.anon_implies_rp => { - debug!("referenced bare fn type with regions %s", - pprust::ty_to_str(ty, cx.sess.intr())); - cx.add_rp(cx.item_id, cx.add_variance(rv_contravariant)); - } + ast::ty_fn(f) => { + debug!("referenced fn type: %s", + pprust::ty_to_str(ty, cx.sess.intr())); + match f.region { + Some(r) => { + if cx.region_is_relevant(r) { + cx.add_rp(cx.item_id, + cx.add_variance(rv_contravariant)) + } + } + None => { + if f.proto == ast::ProtoBorrowed && cx.anon_implies_rp { + cx.add_rp(cx.item_id, + cx.add_variance(rv_contravariant)); + } + } + } + } - _ => {} + _ => {} } // if this references another named type, add the dependency @@ -666,25 +678,6 @@ fn determine_rp_in_ty(ty: @ast::Ty, _ => {} } - // temporary hack: right now, fn() is short for &fn(), but @(fn()) - // is `@fn()`, so catch this and set anon_implies_rp to none in - // that case - match ty.node { - ast::ty_box(mt) | ast::ty_uniq(mt) => { - match mt.ty.node { - ast::ty_fn(ast::proto_bare, _, _, _, _) | - ast::ty_fn(ast::proto_block, _, _, _, _) => { - do cx.with(cx.item_id, false) { - visit_mt(mt, cx, visitor); - } - return; - } - _ => {} - } - } - _ => {} - } - match ty.node { ast::ty_box(mt) | ast::ty_uniq(mt) | ast::ty_vec(mt) | ast::ty_rptr(_, mt) | ast::ty_ptr(mt) => { @@ -706,18 +699,18 @@ fn determine_rp_in_ty(ty: @ast::Ty, } } - ast::ty_fn(_, _, _, bounds, decl) => { + ast::ty_fn(f) => { // fn() binds the & region, so do not consider &T types that // appear *inside* a fn() type to affect the enclosing item: do cx.with(cx.item_id, false) { // parameters are contravariant do cx.with_ambient_variance(rv_contravariant) { - for decl.inputs.each |a| { + for f.decl.inputs.each |a| { visitor.visit_ty(a.ty, cx, visitor); } } - visit::visit_ty_param_bounds(bounds, cx, visitor); - visitor.visit_ty(decl.output, cx, visitor); + visit::visit_ty_param_bounds(f.bounds, cx, visitor); + visitor.visit_ty(f.decl.output, cx, visitor); } } diff --git a/src/rustc/middle/trans/closure.rs b/src/rustc/middle/trans/closure.rs index 3997076f987..b42d823f0c6 100644 --- a/src/rustc/middle/trans/closure.rs +++ b/src/rustc/middle/trans/closure.rs @@ -144,9 +144,7 @@ fn mk_closure_tys(tcx: ty::ctxt, return cdata_ty; } -fn allocate_cbox(bcx: block, - ck: ty::closure_kind, - cdata_ty: ty::t) +fn allocate_cbox(bcx: block, proto: ast::Proto, cdata_ty: ty::t) -> Result { let _icx = bcx.insn_ctxt("closure::allocate_cbox"); @@ -163,15 +161,23 @@ fn allocate_cbox(bcx: block, } // Allocate and initialize the box: - match ck { - ty::ck_box => malloc_raw(bcx, cdata_ty, heap_shared), - ty::ck_uniq => malloc_raw(bcx, cdata_ty, heap_exchange), - ty::ck_block => { - let cbox_ty = tuplify_box_ty(tcx, cdata_ty); - let llbox = base::alloc_ty(bcx, cbox_ty); - nuke_ref_count(bcx, llbox); - rslt(bcx, llbox) - } + match proto { + ast::ProtoBox => { + malloc_raw(bcx, cdata_ty, heap_shared) + } + ast::ProtoUniq => { + malloc_raw(bcx, cdata_ty, heap_exchange) + } + ast::ProtoBorrowed => { + let cbox_ty = tuplify_box_ty(tcx, cdata_ty); + let llbox = base::alloc_ty(bcx, cbox_ty); + nuke_ref_count(bcx, llbox); + rslt(bcx, llbox) + } + ast::ProtoBare => { + let cdata_llty = type_of(bcx.ccx(), cdata_ty); + rslt(bcx, C_null(cdata_llty)) + } } } @@ -187,7 +193,7 @@ type closure_result = { // Otherwise, it is stack allocated and copies pointers to the upvars. fn store_environment(bcx: block, bound_values: ~[EnvValue], - ck: ty::closure_kind) -> closure_result { + proto: ast::Proto) -> closure_result { let _icx = bcx.insn_ctxt("closure::store_environment"); let ccx = bcx.ccx(), tcx = ccx.tcx; @@ -195,7 +201,7 @@ fn store_environment(bcx: block, let cdata_ty = mk_closure_tys(tcx, bound_values); // allocate closure in the heap - let Result {bcx: bcx, val: llbox} = allocate_cbox(bcx, ck, cdata_ty); + let Result {bcx: bcx, val: llbox} = allocate_cbox(bcx, proto, cdata_ty); let mut temp_cleanups = ~[]; // cbox_ty has the form of a tuple: (a, b, c) we want a ptr to a @@ -243,7 +249,7 @@ fn store_environment(bcx: block, // collects the upvars and packages them up for store_environment. fn build_closure(bcx0: block, cap_vars: ~[capture::capture_var], - ck: ty::closure_kind, + proto: ast::Proto, include_ret_handle: Option<ValueRef>) -> closure_result { let _icx = bcx0.insn_ctxt("closure::build_closure"); // If we need to, package up the iterator body to call @@ -257,7 +263,7 @@ fn build_closure(bcx0: block, let datum = expr::trans_local_var(bcx, cap_var.def); match cap_var.mode { capture::cap_ref => { - assert ck == ty::ck_block; + assert proto == ast::ProtoBorrowed; env_vals.push(EnvValue {action: EnvRef, datum: datum}); } @@ -298,7 +304,7 @@ fn build_closure(bcx0: block, datum: ret_datum}); } - return store_environment(bcx, env_vals, ck); + return store_environment(bcx, env_vals, proto); } // Given an enclosing block context, a new function context, a closure type, @@ -308,7 +314,7 @@ fn load_environment(fcx: fn_ctxt, cdata_ty: ty::t, cap_vars: ~[capture::capture_var], load_ret_handle: bool, - ck: ty::closure_kind) { + proto: ast::Proto) { let _icx = fcx.insn_ctxt("closure::load_environment"); let bcx = raw_block(fcx, false, fcx.llloadenv); @@ -322,9 +328,9 @@ fn load_environment(fcx: fn_ctxt, capture::cap_drop => { /* ignore */ } _ => { let mut upvarptr = GEPi(bcx, llcdata, [0u, i]); - match ck { - ty::ck_block => { upvarptr = Load(bcx, upvarptr); } - ty::ck_uniq | ty::ck_box => () + match proto { + ast::ProtoBorrowed => { upvarptr = Load(bcx, upvarptr); } + ast::ProtoBox | ast::ProtoUniq | ast::ProtoBare => {} } let def_id = ast_util::def_id_of_def(cap_var.def); fcx.llupvars.insert(def_id.node, upvarptr); @@ -341,7 +347,7 @@ fn load_environment(fcx: fn_ctxt, } fn trans_expr_fn(bcx: block, - proto: ty::fn_proto, + proto: ast::Proto, decl: ast::fn_decl, body: ast::blk, id: ast::node_id, @@ -365,16 +371,16 @@ fn trans_expr_fn(bcx: block, let s = mangle_internal_name_by_path_and_seq(ccx, sub_path, ~"expr_fn"); let llfn = decl_internal_cdecl_fn(ccx.llmod, s, llfnty); - let trans_closure_env = fn@(ck: ty::closure_kind) -> Result { + let trans_closure_env = fn@(proto: ast::Proto) -> Result { let cap_vars = capture::compute_capture_vars(ccx.tcx, id, proto, cap_clause); let ret_handle = match is_loop_body { Some(x) => x, None => None }; - let {llbox, cdata_ty, bcx} = build_closure(bcx, cap_vars, ck, + let {llbox, cdata_ty, bcx} = build_closure(bcx, cap_vars, proto, ret_handle); trans_closure(ccx, sub_path, decl, body, llfn, no_self, bcx.fcx.param_substs, id, None, |fcx| { load_environment(fcx, cdata_ty, cap_vars, - ret_handle.is_some(), ck); + ret_handle.is_some(), proto); }, |bcx| { if is_loop_body.is_some() { Store(bcx, C_bool(true), bcx.fcx.llretptr); @@ -384,23 +390,14 @@ fn trans_expr_fn(bcx: block, }; let Result {bcx: bcx, val: closure} = match proto { - ty::proto_vstore(ty::vstore_slice(_)) => { - trans_closure_env(ty::ck_block) - } - ty::proto_vstore(ty::vstore_box) => { - trans_closure_env(ty::ck_box) - } - ty::proto_vstore(ty::vstore_uniq) => { - trans_closure_env(ty::ck_uniq) + ast::ProtoBorrowed | ast::ProtoBox | ast::ProtoUniq => { + trans_closure_env(proto) } - ty::proto_bare => { + ast::ProtoBare => { trans_closure(ccx, sub_path, decl, body, llfn, no_self, None, id, None, |_fcx| { }, |_bcx| { }); rslt(bcx, C_null(T_opaque_box_ptr(ccx))) } - ty::proto_vstore(ty::vstore_fixed(_)) => { - fail ~"vstore_fixed unexpected" - } }; fill_fn_pair(bcx, dest_addr, llfn, closure); @@ -412,48 +409,48 @@ fn make_fn_glue( v: ValueRef, t: ty::t, glue_fn: fn@(block, v: ValueRef, t: ty::t) -> block) - -> block { + -> block +{ let _icx = cx.insn_ctxt("closure::make_fn_glue"); let bcx = cx; let tcx = cx.tcx(); - let fn_env = fn@(ck: ty::closure_kind) -> block { - let box_cell_v = GEPi(cx, v, [0u, abi::fn_field_box]); - let box_ptr_v = Load(cx, box_cell_v); - do with_cond(cx, IsNotNull(cx, box_ptr_v)) |bcx| { - let closure_ty = ty::mk_opaque_closure_ptr(tcx, ck); - glue_fn(bcx, box_cell_v, closure_ty) - } - }; - 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"); + ast::ProtoBare | ast::ProtoBorrowed => bcx, + ast::ProtoUniq | ast::ProtoBox => { + let box_cell_v = GEPi(cx, v, [0u, abi::fn_field_box]); + let box_ptr_v = Load(cx, box_cell_v); + do with_cond(cx, IsNotNull(cx, box_ptr_v)) |bcx| { + let closure_ty = ty::mk_opaque_closure_ptr(tcx, proto); + glue_fn(bcx, box_cell_v, closure_ty) + } } } } fn make_opaque_cbox_take_glue( bcx: block, - ck: ty::closure_kind, + proto: ast::Proto, cboxptr: ValueRef) // ptr to ptr to the opaque closure - -> block { + -> block +{ // Easy cases: let _icx = bcx.insn_ctxt("closure::make_opaque_cbox_take_glue"); - match ck { - ty::ck_block => return bcx, - ty::ck_box => { + match proto { + ast::ProtoBare | ast::ProtoBorrowed => { + return bcx; + } + ast::ProtoBox => { glue::incr_refcnt_of_boxed(bcx, Load(bcx, cboxptr)); return bcx; } - ty::ck_uniq => { /* hard case: */ } + ast::ProtoUniq => { + /* hard case: fallthrough to code below */ + } } - // Hard case, a deep copy: + // fn~ requires a deep copy. let ccx = bcx.ccx(), tcx = ccx.tcx; let llopaquecboxty = T_opaque_box_ptr(ccx); let cbox_in = Load(bcx, cboxptr); @@ -492,34 +489,38 @@ fn make_opaque_cbox_take_glue( fn make_opaque_cbox_drop_glue( bcx: block, - ck: ty::closure_kind, + proto: ast::Proto, cboxptr: ValueRef) // ptr to the opaque closure -> block { let _icx = bcx.insn_ctxt("closure::make_opaque_cbox_drop_glue"); - match ck { - ty::ck_block => bcx, - ty::ck_box => { + match proto { + ast::ProtoBare | ast::ProtoBorrowed => bcx, + ast::ProtoBox => { glue::decr_refcnt_maybe_free( bcx, Load(bcx, cboxptr), - ty::mk_opaque_closure_ptr(bcx.tcx(), ck)) + ty::mk_opaque_closure_ptr(bcx.tcx(), proto)) } - ty::ck_uniq => { + ast::ProtoUniq => { glue::free_ty( bcx, cboxptr, - ty::mk_opaque_closure_ptr(bcx.tcx(), ck)) + ty::mk_opaque_closure_ptr(bcx.tcx(), proto)) } } } fn make_opaque_cbox_free_glue( bcx: block, - ck: ty::closure_kind, + proto: ast::Proto, cbox: ValueRef) // ptr to ptr to the opaque closure -> block { let _icx = bcx.insn_ctxt("closure::make_opaque_cbox_free_glue"); - match ck { - ty::ck_block => return bcx, - ty::ck_box | ty::ck_uniq => { /* hard cases: */ } + match proto { + ast::ProtoBare | ast::ProtoBorrowed => { + return bcx; + } + ast::ProtoBox | ast::ProtoUniq => { + /* hard cases: fallthrough to code below */ + } } let ccx = bcx.ccx(); @@ -537,10 +538,12 @@ fn make_opaque_cbox_free_glue( abi::tydesc_field_drop_glue, None); // Free the ty descr (if necc) and the box itself - match ck { - ty::ck_block => fail ~"Impossible", - ty::ck_box => glue::trans_free(bcx, cbox), - ty::ck_uniq => glue::trans_unique_free(bcx, cbox) + match proto { + ast::ProtoBox => glue::trans_free(bcx, cbox), + ast::ProtoUniq => glue::trans_unique_free(bcx, cbox), + ast::ProtoBare | ast::ProtoBorrowed => { + bcx.sess().bug(~"impossible") + } } } } diff --git a/src/rustc/middle/trans/expr.rs b/src/rustc/middle/trans/expr.rs index 1bd44ee4bda..06d56f4542f 100644 --- a/src/rustc/middle/trans/expr.rs +++ b/src/rustc/middle/trans/expr.rs @@ -109,7 +109,7 @@ use base::*; use syntax::print::pprust::{expr_to_str}; use util::ppaux::ty_to_str; use util::common::indenter; -use ty::{AutoPtr, AutoSlice}; +use ty::{AutoPtr, AutoBorrowVec, AutoBorrowFn}; use callee::{AutorefArg, DoAutorefArg, DontAutorefArg}; // The primary two functions for translating expressions: @@ -188,9 +188,15 @@ fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock { AutoPtr => { unpack_datum!(bcx, auto_ref(bcx, datum)) } - AutoSlice => { + AutoBorrowVec => { unpack_datum!(bcx, auto_slice(bcx, datum)) } + AutoBorrowFn => { + // currently, all closure types are + // represented precisely the same, so no + // runtime adjustment is required: + datum + } } } }; @@ -520,20 +526,7 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr, ast::expr_fn(proto, decl, body, cap_clause) => { // Don't use this function for anything real. Use the one in // astconv instead. - fn ast_proto_to_proto_simple(ast_proto: ast::proto) - -> ty::fn_proto { - match ast_proto { - ast::proto_bare => ty::proto_bare, - ast::proto_uniq => ty::proto_vstore(ty::vstore_uniq), - ast::proto_box => ty::proto_vstore(ty::vstore_box), - ast::proto_block => { - ty::proto_vstore(ty::vstore_slice(ty::re_static)) - } - } - } - - return closure::trans_expr_fn(bcx, - ast_proto_to_proto_simple(proto), + return closure::trans_expr_fn(bcx, proto, decl, body, expr.id, cap_clause, None, dest); } diff --git a/src/rustc/middle/trans/foreign.rs b/src/rustc/middle/trans/foreign.rs index 933fb7eedfb..b4aeface943 100644 --- a/src/rustc/middle/trans/foreign.rs +++ b/src/rustc/middle/trans/foreign.rs @@ -997,10 +997,9 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item, 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)))), + proto: ast::ProtoBorrowed, onceness: ast::Many, + region: ty::re_bound(ty::br_anon(0)), bounds: @~[], ret_style: ast::return_val}, sig: FnSig {inputs: ~[{mode: ast::expl(ast::by_val), diff --git a/src/rustc/middle/trans/monomorphize.rs b/src/rustc/middle/trans/monomorphize.rs index 0c93c610b68..2e18fb2a2e9 100644 --- a/src/rustc/middle/trans/monomorphize.rs +++ b/src/rustc/middle/trans/monomorphize.rs @@ -251,18 +251,19 @@ fn normalize_for_monomorphization(tcx: ty::ctxt, ty: ty::t) -> Option<ty::t> { FnTyBase {meta: FnMeta {purity: ast::impure_fn, proto: fty.meta.proto, onceness: ast::Many, + region: ty::re_static, 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, + proto: ast::ProtoBox, onceness: ast::Many, + region: ty::re_static, bounds: @~[], ret_style: ast::return_val}, sig: FnSig {inputs: ~[], diff --git a/src/rustc/middle/trans/reflect.rs b/src/rustc/middle/trans/reflect.rs index c52b653d536..5724c5ada22 100644 --- a/src/rustc/middle/trans/reflect.rs +++ b/src/rustc/middle/trans/reflect.rs @@ -186,14 +186,7 @@ impl reflector { ast::impure_fn => 2u, ast::extern_fn => 3u }; - let protoval = match fty.meta.proto { - ty::proto_bare => 0u, - ty::proto_vstore(ty::vstore_uniq) => 2u, - ty::proto_vstore(ty::vstore_box) => 3u, - ty::proto_vstore(ty::vstore_slice(_)) => 4u, - ty::proto_vstore(ty::vstore_fixed(_)) => - fail ~"fixed unexpected" - }; + let protoval = ast_proto_constant(fty.meta.proto); let retval = match fty.meta.ret_style { ast::noreturn => 0u, ast::return_val => 1u @@ -278,11 +271,7 @@ impl reflector { ty::ty_type => self.leaf(~"type"), ty::ty_opaque_box => self.leaf(~"opaque_box"), ty::ty_opaque_closure_ptr(ck) => { - let ckval = match ck { - ty::ck_block => 0u, - ty::ck_box => 1u, - ty::ck_uniq => 2u - }; + let ckval = ast_proto_constant(ck); self.visit(~"closure_ptr", ~[self.c_uint(ckval)]) } } @@ -309,3 +298,12 @@ fn emit_calls_to_trait_visit_ty(bcx: block, t: ty::t, Br(r.bcx, final.llbb); return final; } + +fn ast_proto_constant(proto: ast::Proto) -> uint { + match proto { + ast::ProtoBare => 0u, + ast::ProtoUniq => 2u, + ast::ProtoBox => 3u, + ast::ProtoBorrowed => 4u, + } +} \ No newline at end of file diff --git a/src/rustc/middle/trans/type_use.rs b/src/rustc/middle/trans/type_use.rs index b8a7580e03c..53889369361 100644 --- a/src/rustc/middle/trans/type_use.rs +++ b/src/rustc/middle/trans/type_use.rs @@ -213,16 +213,13 @@ fn mark_for_expr(cx: ctx, e: @expr) { } expr_fn(*) | expr_fn_block(*) => { match ty::ty_fn_proto(ty::expr_ty(cx.ccx.tcx, e)) { - ty::proto_bare | ty::proto_vstore(ty::vstore_uniq) => {} - ty::proto_vstore(ty::vstore_box) | - ty::proto_vstore(ty::vstore_slice(_)) => { + ast::ProtoBare | ast::ProtoUniq => {} + ast::ProtoBox | ast::ProtoBorrowed => { for vec::each(*freevars::get_freevars(cx.ccx.tcx, e.id)) |fv| { let node_id = ast_util::def_id_of_def(fv.def).node; node_type_needs(cx, use_repr, node_id); } } - ty::proto_vstore(ty::vstore_fixed(_)) => - fail ~"vstore_fixed not allowed here" } } expr_assign(val, _) | expr_swap(val, _) | expr_assign_op(_, val, _) | diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index 69b4d985f6f..14c5ed5e71e 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -157,10 +157,6 @@ export set_default_mode; export variant_info; export walk_ty, maybe_walk_ty; export occurs_check; -export closure_kind; -export ck_block; -export ck_box; -export ck_uniq; export param_ty; export param_bound, param_bounds, bound_copy, bound_owned; export param_bounds_to_str, param_bound_to_str; @@ -190,9 +186,7 @@ export purity_to_str; export onceness_to_str; export param_tys_in_type; export eval_repeat_count; -export fn_proto, proto_bare, proto_vstore; export ast_proto_to_proto; -export is_blockish; export method_call_bounds; export hash_region; export region_variance, rv_covariant, rv_invariant, rv_contravariant; @@ -200,10 +194,11 @@ export opt_region_variance; export determine_inherited_purity; export provided_trait_methods; export trait_supertraits; -export AutoAdjustment; -export AutoRef, AutoRefKind, AutoSlice, AutoPtr; export DerivedMethodInfo; export DerivedFieldInfo; +export AutoAdjustment; +export AutoRef; +export AutoRefKind, AutoPtr, AutoBorrowVec, AutoBorrowFn; // Data types @@ -304,14 +299,14 @@ impl region_variance : cmp::Eq { #[auto_serialize] #[auto_deserialize] -type AutoAdjustment = { +pub type AutoAdjustment = { autoderefs: uint, autoref: Option<AutoRef> }; #[auto_serialize] #[auto_deserialize] -type AutoRef = { +pub type AutoRef = { kind: AutoRefKind, region: Region, mutbl: ast::mutability @@ -320,11 +315,14 @@ type AutoRef = { #[auto_serialize] #[auto_deserialize] enum AutoRefKind { + /// Convert from T to &T + AutoPtr, + /// Convert from @[]/~[] to &[] (or str) - AutoSlice, + AutoBorrowVec, - /// Convert from T to &T - AutoPtr + /// Convert from @fn()/~fn() to &fn() + AutoBorrowFn, } struct ProvidedMethodSource { @@ -450,62 +448,6 @@ pure fn type_has_regions(t: t) -> bool { tbox_has_flag(get(t), has_regions) } pure fn type_def_id(t: t) -> Option<ast::def_id> { get(t).o_def_id } pure fn type_id(t: t) -> uint { get(t).id } -enum closure_kind { - ck_block, - ck_box, - ck_uniq, -} - -impl closure_kind : to_bytes::IterBytes { - pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) { - (self as u8).iter_bytes(lsb0, f) - } -} - -impl closure_kind : cmp::Eq { - pure fn eq(other: &closure_kind) -> bool { - (self as uint) == ((*other) as uint) - } - pure fn ne(other: &closure_kind) -> bool { !self.eq(other) } -} - -enum fn_proto { - proto_bare, // supertype of all other protocols - proto_vstore(vstore) -} - -impl fn_proto : to_bytes::IterBytes { - pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) { - match self { - proto_bare => - 0u8.iter_bytes(lsb0, f), - - proto_vstore(ref v) => - to_bytes::iter_bytes_2(&1u8, v, lsb0, f) - } - } -} - -impl fn_proto : cmp::Eq { - pure fn eq(other: &fn_proto) -> bool { - match self { - proto_bare => { - match (*other) { - proto_bare => true, - _ => false - } - } - proto_vstore(e0a) => { - match (*other) { - proto_vstore(e0b) => e0a == e0b, - _ => false - } - } - } - } - pure fn ne(other: &fn_proto) -> bool { !self.eq(other) } -} - /** * Meta information about a closure. * @@ -513,12 +455,14 @@ impl fn_proto : cmp::Eq { * - `proto` is the protocol (fn@, fn~, etc). * - `onceness` indicates whether the function can be called one time or many * times. + * - `region` is the region bound on the function's upvars (often &static). * - `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, + proto: ast::Proto, onceness: ast::Onceness, + region: Region, bounds: @~[param_bound], ret_style: ret_style } @@ -671,7 +615,7 @@ enum sty { // "Fake" types, used for trans purposes ty_type, // type_desc* ty_opaque_box, // used by monomorphizer to represent any @ box - ty_opaque_closure_ptr(closure_kind), // ptr to env for fn, fn@, fn~ + ty_opaque_closure_ptr(ast::Proto), // ptr to env for fn, fn@, fn~ ty_unboxed_vec(mt), } @@ -691,7 +635,7 @@ enum type_err { terr_purity_mismatch(expected_found<purity>), terr_onceness_mismatch(expected_found<Onceness>), terr_mutability, - terr_proto_mismatch(expected_found<ty::fn_proto>), + terr_proto_mismatch(expected_found<ast::Proto>), terr_box_mutability, terr_ptr_mutability, terr_ref_mutability, @@ -1036,10 +980,7 @@ fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option<ast::def_id>) -> 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.meta.proto { - ty::proto_vstore(vstore_slice(r)) => flags |= rflags(r), - ty::proto_bare | ty::proto_vstore(_) => {} - } + flags |= rflags(f.meta.region); for f.sig.inputs.each |a| { flags |= get(a.ty).flags; } flags |= get(f.sig.output).flags; } @@ -1172,8 +1113,8 @@ fn mk_param(cx: ctxt, n: uint, k: def_id) -> t { fn mk_type(cx: ctxt) -> t { mk_t(cx, ty_type) } -fn mk_opaque_closure_ptr(cx: ctxt, ck: closure_kind) -> t { - mk_t(cx, ty_opaque_closure_ptr(ck)) +fn mk_opaque_closure_ptr(cx: ctxt, proto: ast::Proto) -> t { + mk_t(cx, ty_opaque_closure_ptr(proto)) } fn mk_opaque_box(cx: ctxt) -> t { mk_t(cx, ty_opaque_box) } @@ -1197,8 +1138,10 @@ fn default_arg_mode_for_ty(tcx: ctxt, ty: ty::t) -> ast::rmode { // memory leak that otherwise results when @fn is upcast to &fn. if type_is_fn(ty) { match ty_fn_proto(ty) { - proto_vstore(vstore_slice(_)) => return ast::by_ref, - _ => () + ast::ProtoBorrowed => { + return ast::by_ref; + } + _ => {} } } return if tcx.legacy_modes { @@ -1409,25 +1352,18 @@ fn fold_regions_and_ty( ty::mk_trait(cx, def_id, fold_substs(substs, fldr, fldt), vst) } ty_fn(ref f) => { - let new_proto; - match f.meta.proto { - proto_bare => - new_proto = proto_bare, - proto_vstore(vstore_slice(r)) => - new_proto = proto_vstore(vstore_slice(fldr(r))), - proto_vstore(old_vstore) => - new_proto = proto_vstore(old_vstore) - } - 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.sig.output); - ty::mk_fn(cx, FnTyBase { - meta: FnMeta {proto: new_proto, ..f.meta}, - sig: FnSig {inputs: new_args, - output: new_output} - }) + let new_region = fldr(f.meta.region); + 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.sig.output); + ty::mk_fn(cx, FnTyBase { + meta: FnMeta {region: new_region, + ..f.meta}, + sig: FnSig {inputs: new_args, + output: new_output} + }) } ref sty => { fold_sty_to_ty(cx, sty, |t| fldt(t)) @@ -1789,8 +1725,8 @@ fn type_needs_drop(cx: ctxt, ty: t) -> bool { } ty_fn(ref fty) => { match fty.meta.proto { - proto_bare | proto_vstore(vstore_slice(_)) => false, - _ => true + ast::ProtoBare | ast::ProtoBorrowed => false, + ast::ProtoBox | ast::ProtoUniq => true, } } }; @@ -2016,16 +1952,18 @@ pure fn kind_is_owned(k: Kind) -> bool { 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) => - kind_safe_for_default_mode() | kind_owned(), - proto_vstore(vstore_uniq) => - kind_send_copy() | kind_owned(), - proto_vstore(vstore_fixed(_)) => - fail ~"fixed vstore protos are not allowed", - proto_bare => - kind_safe_for_default_mode_send() | kind_const() | kind_owned() + ast::ProtoBare => { + kind_safe_for_default_mode_send() | kind_const() | kind_owned() + } + ast::ProtoBorrowed => { + kind_noncopyable() | kind_(KIND_MASK_DEFAULT_MODE) + } + ast::ProtoBox => { + kind_safe_for_default_mode() | kind_owned() + } + ast::ProtoUniq => { + kind_send_copy() | kind_owned() + } } } @@ -2721,8 +2659,27 @@ impl field : to_bytes::IterBytes { impl arg : to_bytes::IterBytes { pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) { - to_bytes::iter_bytes_2(&self.mode, - &self.ty, lsb0, f) + to_bytes::iter_bytes_2(&self.mode, + &self.ty, lsb0, f) + } +} + +impl FnMeta : to_bytes::IterBytes { + pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) { + to_bytes::iter_bytes_5(&self.purity, + &self.proto, + &self.region, + &self.bounds, + &self.ret_style, + lsb0, f); + } +} + +impl FnSig : to_bytes::IterBytes { + pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) { + to_bytes::iter_bytes_2(&self.inputs, + &self.output, + lsb0, f); } } @@ -2763,13 +2720,9 @@ impl sty : to_bytes::IterBytes { to_bytes::iter_bytes_2(&11u8, fs, lsb0, f), ty_fn(ref ft) => - to_bytes::iter_bytes_7(&12u8, - &ft.meta.purity, - &ft.meta.proto, - &ft.meta.bounds, - &ft.sig.inputs, - &ft.sig.output, - &ft.meta.ret_style, + to_bytes::iter_bytes_3(&12u8, + &ft.meta, + &ft.sig, lsb0, f), ty_self => 13u8.iter_bytes(lsb0, f), @@ -2840,7 +2793,7 @@ fn ty_fn_args(fty: t) -> ~[arg] { } } -fn ty_fn_proto(fty: t) -> fn_proto { +fn ty_fn_proto(fty: t) -> Proto { match get(fty).sty { ty_fn(ref f) => f.meta.proto, _ => fail ~"ty_fn_proto() called on non-fn type" @@ -4091,12 +4044,11 @@ fn normalize_ty(cx: ctxt, t: t) -> t { mk_rptr(cx, re_static, normalize_mt(cx, mt)), 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}, + meta: FnMeta { + region: ty::re_static, + ..fn_ty.meta + }, sig: fn_ty.sig }) } @@ -4160,27 +4112,17 @@ fn eval_repeat_count(tcx: ctxt, count_expr: @ast::expr, span: span) -> uint { } } -pure fn is_blockish(proto: fn_proto) -> bool { - match proto { - proto_vstore(vstore_slice(_)) => - true, - proto_vstore(vstore_box) | proto_vstore(vstore_uniq) | proto_bare => - false, - proto_vstore(vstore_fixed(_)) => - fail ~"fixed vstore not allowed here" - } -} - // Determine what purity to check a nested function under pure fn determine_inherited_purity(parent_purity: ast::purity, child_purity: ast::purity, - child_proto: ty::fn_proto) -> ast::purity { + child_proto: ast::Proto) -> ast::purity { // If the closure is a stack closure and hasn't had some non-standard // purity inferred for it, then check it under its parent's purity. // Otherwise, use its own - if ty::is_blockish(child_proto) && child_purity == ast::impure_fn { - parent_purity - } else { child_purity } + match child_proto { + ast::ProtoBorrowed if child_purity == ast::impure_fn => parent_purity, + _ => child_purity + } } impl mt : cmp::Eq { diff --git a/src/rustc/middle/typeck/astconv.rs b/src/rustc/middle/typeck/astconv.rs index b18b032e0a6..f80b655a860 100644 --- a/src/rustc/middle/typeck/astconv.rs +++ b/src/rustc/middle/typeck/astconv.rs @@ -166,76 +166,57 @@ fn ast_ty_to_ty<AC: ast_conv, RS: region_scope Copy Owned>( // Handle @, ~, and & being able to mean estrs and evecs. // If a_seq_ty is a str or a vec, make it an estr/evec. // Also handle function sigils and first-class trait types. - fn mk_maybe_vstore<AC: ast_conv, RS: region_scope Copy Owned>( - self: AC, rscope: RS, a_seq_ty: ast::mt, vst: ty::vstore, - span: span, constr: fn(ty::mt) -> ty::t) -> ty::t { - + fn mk_pointer<AC: ast_conv, RS: region_scope Copy Owned>( + self: AC, + rscope: RS, + a_seq_ty: ast::mt, + vst: ty::vstore, + constr: fn(ty::mt) -> ty::t) -> ty::t + { let tcx = self.tcx(); match a_seq_ty.ty.node { - // to convert to an e{vec,str}, there can't be a mutability argument - _ if a_seq_ty.mutbl != ast::m_imm => (), - ast::ty_vec(mt) => { - return ty::mk_evec(tcx, ast_mt_to_mt(self, rscope, mt), vst); - } - ast::ty_path(path, id) => { - match tcx.def_map.find(id) { - Some(ast::def_prim_ty(ast::ty_str)) => { - check_path_args(tcx, path, NO_TPS | NO_REGIONS); - return ty::mk_estr(tcx, vst); - } - Some(ast::def_ty(type_def_id)) => { - let result = ast_path_to_substs_and_ty(self, rscope, - type_def_id, path); - match ty::get(result.ty).sty { - ty::ty_trait(trait_def_id, substs, _) => { - match vst { - ty::vstore_box | ty::vstore_slice(*) | - ty::vstore_uniq => {} - _ => { - tcx.sess.span_err(path.span, - ~"@trait, ~trait or &trait \ - are the only supported \ - forms of casting-to-\ - trait"); + // to convert to an e{vec,str}, there can't be a + // mutability argument + _ if a_seq_ty.mutbl != ast::m_imm => (), + ast::ty_vec(mt) => { + return ty::mk_evec(tcx, ast_mt_to_mt(self, rscope, mt), vst); + } + ast::ty_path(path, id) => { + match tcx.def_map.find(id) { + Some(ast::def_prim_ty(ast::ty_str)) => { + check_path_args(tcx, path, NO_TPS | NO_REGIONS); + return ty::mk_estr(tcx, vst); + } + Some(ast::def_ty(type_def_id)) => { + let result = ast_path_to_substs_and_ty( + self, rscope, + type_def_id, path); + match ty::get(result.ty).sty { + ty::ty_trait(trait_def_id, substs, _) => { + match vst { + ty::vstore_box | ty::vstore_slice(*) | + ty::vstore_uniq => {} + _ => { + tcx.sess.span_err( + path.span, + ~"@trait, ~trait or &trait \ + are the only supported \ + forms of casting-to-\ + trait"); + } + } + return ty::mk_trait(tcx, trait_def_id, + substs, vst); + } + _ => {} } - return ty::mk_trait(tcx, trait_def_id, substs, vst); } _ => {} } - } - _ => () } - } - ast::ty_fn(ast::proto_block, purity, onceness, ast_bounds, - ast_fn_decl) => { - let new_proto; - match vst { - ty::vstore_fixed(_) => { - tcx.sess.span_err(span, ~"fixed-length functions are not \ - allowed"); - new_proto = ast::proto_block; - } - ty::vstore_uniq => new_proto = ast::proto_uniq, - ty::vstore_box => new_proto = ast::proto_box, - ty::vstore_slice(_) => new_proto = ast::proto_block - } - - // Run through the normal function type conversion process. - let bounds = collect::compute_bounds(self.ccx(), ast_bounds); - let fn_decl = ty_of_fn_decl(self, - rscope, - new_proto, - purity, - onceness, - bounds, - ast_fn_decl, - None, - span); - return ty::mk_fn(tcx, fn_decl); - } - _ => () + _ => {} } let seq_ty = ast_mt_to_mt(self, rscope, a_seq_ty); @@ -279,12 +260,12 @@ fn ast_ty_to_ty<AC: ast_conv, RS: region_scope Copy Owned>( ast::ty_nil => ty::mk_nil(tcx), ast::ty_bot => ty::mk_bot(tcx), ast::ty_box(mt) => { - mk_maybe_vstore(self, rscope, mt, ty::vstore_box, ast_ty.span, - |tmt| ty::mk_box(tcx, tmt)) + mk_pointer(self, rscope, mt, ty::vstore_box, + |tmt| ty::mk_box(tcx, tmt)) } ast::ty_uniq(mt) => { - mk_maybe_vstore(self, rscope, mt, ty::vstore_uniq, ast_ty.span, - |tmt| ty::mk_uniq(tcx, tmt)) + mk_pointer(self, rscope, mt, ty::vstore_uniq, + |tmt| ty::mk_uniq(tcx, tmt)) } ast::ty_vec(mt) => { tcx.sess.span_err(ast_ty.span, @@ -298,12 +279,8 @@ fn ast_ty_to_ty<AC: ast_conv, RS: region_scope Copy Owned>( } ast::ty_rptr(region, mt) => { let r = ast_region_to_region(self, rscope, ast_ty.span, region); - mk_maybe_vstore(self, - in_anon_rscope(rscope, r), - mt, - ty::vstore_slice(r), - ast_ty.span, - |tmt| ty::mk_rptr(tcx, r, tmt)) + mk_pointer(self, in_anon_rscope(rscope, r), mt, ty::vstore_slice(r), + |tmt| ty::mk_rptr(tcx, r, tmt)) } ast::ty_tup(fields) => { let flds = vec::map(fields, |t| ast_ty_to_ty(self, rscope, *t)); @@ -316,10 +293,11 @@ fn ast_ty_to_ty<AC: ast_conv, RS: region_scope Copy Owned>( }; ty::mk_rec(tcx, flds) } - ast::ty_fn(proto, purity, onceness, ast_bounds, decl) => { - let bounds = collect::compute_bounds(self.ccx(), ast_bounds); - let fn_decl = ty_of_fn_decl(self, rscope, proto, purity, - onceness, bounds, decl, None, + ast::ty_fn(f) => { + let bounds = collect::compute_bounds(self.ccx(), f.bounds); + let fn_decl = ty_of_fn_decl(self, rscope, f.proto, + f.purity, f.onceness, + bounds, f.region, f.decl, None, ast_ty.span); ty::mk_fn(tcx, fn_decl) } @@ -377,22 +355,9 @@ fn ast_ty_to_ty<AC: ast_conv, RS: region_scope Copy Owned>( } } } - ast::ty_fixed_length(a_t, Some(u)) => { - mk_maybe_vstore(self, rscope, {ty: a_t, mutbl: ast::m_imm}, - ty::vstore_fixed(u), - ast_ty.span, - |ty| { - tcx.sess.span_err( - a_t.span, - fmt!("bound not allowed on a %s", - ty::ty_sort_str(tcx, ty.ty))); - ty.ty - }) - } - ast::ty_fixed_length(_, None) => { - tcx.sess.span_bug( - ast_ty.span, - ~"implied fixed length for bound"); + ast::ty_fixed_length_vec(a_mt, u) => { + ty::mk_evec(tcx, ast_mt_to_mt(self, rscope, a_mt), + ty::vstore_fixed(u)) } ast::ty_infer => { // ty_infer should only appear as the type of arguments or return @@ -459,38 +424,44 @@ fn ty_of_arg<AC: ast_conv, RS: region_scope Copy Owned>( {mode: mode, ty: ty} } -fn ast_proto_to_proto<AC: ast_conv, RS: region_scope Copy Owned>( - self: AC, rscope: RS, span: span, ast_proto: ast::proto) -> ty::fn_proto { - match ast_proto { - ast::proto_bare => - ty::proto_bare, - ast::proto_uniq => - ty::proto_vstore(ty::vstore_uniq), - ast::proto_box => - ty::proto_vstore(ty::vstore_box), - ast::proto_block => { - let result = rscope.anon_region(span); - let region = get_region_reporting_err(self.tcx(), span, result); - ty::proto_vstore(ty::vstore_slice(region)) - } - } -} - type expected_tys = Option<{inputs: ~[ty::arg], output: ty::t}>; fn ty_of_fn_decl<AC: ast_conv, RS: region_scope Copy Owned>( self: AC, rscope: RS, - ast_proto: ast::proto, + ast_proto: ast::Proto, purity: ast::purity, onceness: ast::Onceness, bounds: @~[ty::param_bound], + opt_region: Option<@ast::region>, decl: ast::fn_decl, expected_tys: expected_tys, - span: span) -> ty::FnTy { - + span: span) -> ty::FnTy +{ debug!("ty_of_fn_decl"); do indent { + // resolve the function bound region in the original region + // scope `rscope`, not the scope of the function parameters + let bound_region = match opt_region { + Some(region) => { + ast_region_to_region(self, rscope, span, region) + } + None => { + match ast_proto { + ast::ProtoBare | ast::ProtoUniq | ast::ProtoBox => { + // @fn(), ~fn() default to static as the bound + // on their upvars: + ty::re_static + } + ast::ProtoBorrowed => { + // &fn() defaults to an anonymous region: + let r_result = rscope.anon_region(span); + get_region_reporting_err(self.tcx(), span, r_result) + } + } + } + }; + // new region names that appear inside of the fn decl are bound to // that function type let rb = in_binding_rscope(rscope); @@ -511,12 +482,11 @@ fn ty_of_fn_decl<AC: ast_conv, RS: region_scope Copy Owned>( _ => ast_ty_to_ty(self, rb, decl.output) }; - let proto = ast_proto_to_proto(self, rscope, span, ast_proto); - FnTyBase { meta: FnMeta {purity: purity, - proto: proto, + proto: ast_proto, onceness: onceness, + region: bound_region, bounds: bounds, ret_style: decl.cf}, sig: FnSig {inputs: input_tys, @@ -524,5 +494,3 @@ fn ty_of_fn_decl<AC: ast_conv, RS: region_scope Copy Owned>( } } } - - diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index 09225b4fef8..3de99554554 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -1294,7 +1294,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, fn check_expr_fn(fcx: @fn_ctxt, expr: @ast::expr, - ast_proto_opt: Option<ast::proto>, + ast_proto_opt: Option<ast::Proto>, decl: ast::fn_decl, body: ast::blk, is_loop_body: bool, @@ -1313,56 +1313,39 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, let (expected_tys, expected_purity, expected_proto, - expected_onceness) = + expected_onceness) = { match expected_sty { - Some(ty::ty_fn(ref fn_ty)) => { - let {fn_ty, _} = - 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.sig.inputs, - output: fn_ty.sig.output}), - fn_ty.meta.purity, - fn_ty.meta.proto, - fn_ty.meta.onceness) - } - _ => { - (None, - ast::impure_fn, - ty::proto_vstore(ty::vstore_box), - ast::Many) - } - }; - + Some(ty::ty_fn(ref fn_ty)) => { + let id = expr.id; + let {fn_ty, _} = + replace_bound_regions_in_fn_ty( + tcx, @Nil, None, fn_ty, + |br| ty::re_bound(ty::br_cap_avoid(id, @br))); + (Some({inputs: fn_ty.sig.inputs, + output: fn_ty.sig.output}), + fn_ty.meta.purity, + fn_ty.meta.proto, + fn_ty.meta.onceness) + } + _ => { + (None, ast::impure_fn, ast::ProtoBox, ast::Many) + } + } + }; - // Generate AST prototypes and purity. - // If this is a block lambda (ast_proto == none), these values - // are bogus. We'll fill in the type with the real one later. - // XXX: This is a hack. - let ast_proto = ast_proto_opt.get_default(ast::proto_box); - let ast_purity = ast::impure_fn; - let ast_onceness = ast::Many; + // If the proto is specified, use that, otherwise select a + // proto based on inference. + let (proto, purity) = match ast_proto_opt { + Some(p) => (p, ast::impure_fn), + None => (expected_proto, expected_purity) + }; // construct the function type - let mut fn_ty = astconv::ty_of_fn_decl(fcx, - fcx, - ast_proto, - ast_purity, - ast_onceness, - @~[], - decl, - expected_tys, - expr.span); - - // Patch up the function declaration, if necessary. - match ast_proto_opt { - None => { - fn_ty.meta.purity = expected_purity; - fn_ty.meta.proto = expected_proto; - fn_ty.meta.onceness = expected_onceness; - } - Some(_) => { } - } + let mut fn_ty = astconv::ty_of_fn_decl( + fcx, fcx, + proto, purity, expected_onceness, + /*bounds:*/ @~[], /*opt_region:*/ None, + decl, expected_tys, expr.span); let fty = ty::mk_fn(tcx, fn_ty); @@ -2815,9 +2798,9 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) { ~"frame_address" => { 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)))), - onceness: ast::Many, + proto: ast::ProtoBorrowed, + onceness: ast::Once, + region: ty::re_bound(ty::br_anon(0)), bounds: @~[], ret_style: ast::return_val}, sig: FnSig {inputs: ~[{mode: ast::expl(ast::by_val), @@ -2840,8 +2823,9 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) { }; let fty = ty::mk_fn(tcx, FnTyBase { meta: FnMeta {purity: ast::impure_fn, - proto: ty::proto_bare, + proto: ast::ProtoBare, onceness: ast::Many, + region: ty::re_static, bounds: @~[], ret_style: ast::return_val}, sig: FnSig {inputs: inputs, diff --git a/src/rustc/middle/typeck/check/method.rs b/src/rustc/middle/typeck/check/method.rs index f1185181f55..dd3f4069a9c 100644 --- a/src/rustc/middle/typeck/check/method.rs +++ b/src/rustc/middle/typeck/check/method.rs @@ -625,7 +625,7 @@ impl LookupContext { ty_evec(mt, vstore_uniq) | ty_evec(mt, vstore_fixed(_)) => { self.search_for_some_kind_of_autorefd_method( - AutoSlice, autoderefs, [m_const, m_imm, m_mutbl], + AutoBorrowVec, autoderefs, [m_const, m_imm, m_mutbl], |m,r| ty::mk_evec(tcx, {ty:mt.ty, mutbl:m}, vstore_slice(r))) @@ -635,7 +635,7 @@ impl LookupContext { ty_estr(vstore_uniq) | ty_estr(vstore_fixed(_)) => { self.search_for_some_kind_of_autorefd_method( - AutoSlice, autoderefs, [m_imm], + AutoBorrowVec, autoderefs, [m_imm], |_m,r| ty::mk_estr(tcx, vstore_slice(r))) } diff --git a/src/rustc/middle/typeck/check/regionck.rs b/src/rustc/middle/typeck/check/regionck.rs index a38b805c7b4..970e86d00de 100644 --- a/src/rustc/middle/typeck/check/regionck.rs +++ b/src/rustc/middle/typeck/check/regionck.rs @@ -22,10 +22,11 @@ use ppaux::{note_and_explain_region, ty_to_str}; use syntax::print::pprust; use infer::{resolve_and_force_all_but_regions, fres}; use syntax::ast::{def_arg, def_binding, def_local, def_self, def_upvar}; +use syntax::ast::{ProtoBare, ProtoBox, ProtoUniq, ProtoBorrowed}; use middle::freevars::get_freevars; use middle::kind::check_owned; use middle::pat_util::pat_bindings; -use middle::ty::{encl_region, proto_bare, proto_vstore, re_scope}; +use middle::ty::{encl_region, re_scope}; use middle::ty::{ty_fn_proto, vstore_box, vstore_fixed, vstore_slice}; use middle::ty::{vstore_uniq}; @@ -40,14 +41,9 @@ fn encl_region_of_def(fcx: @fn_ctxt, def: ast::def) -> ty::Region { return encl_region(tcx, node_id), def_upvar(_, subdef, closure_id, body_id) => { match ty_fn_proto(fcx.node_ty(closure_id)) { - proto_bare => - tcx.sess.bug(~"proto_bare in encl_region_of_def?!"), - proto_vstore(vstore_fixed(_)) => - tcx.sess.bug(~"vstore_fixed in encl_region_of_def?!"), - proto_vstore(vstore_slice(_)) => - encl_region_of_def(fcx, *subdef), - proto_vstore(vstore_uniq) | proto_vstore(vstore_box) => - re_scope(body_id) + ProtoBare => tcx.sess.bug(~"ProtoBare with upvars?!"), + ProtoBorrowed => encl_region_of_def(fcx, *subdef), + ProtoBox | ProtoUniq => re_scope(body_id) } } _ => { @@ -244,12 +240,9 @@ fn visit_expr(expr: @ast::expr, &&rcx: @rcx, v: rvt) { result::Ok(function_type) => { match ty::get(function_type).sty { ty::ty_fn(ref fn_ty) => { - match fn_ty.meta.proto { - proto_vstore(vstore_slice(region)) => { - constrain_free_variables(rcx, region, - expr); - } - _ => {} + if fn_ty.meta.proto == ast::ProtoBorrowed { + constrain_free_variables( + rcx, fn_ty.meta.region, expr); } } _ => () diff --git a/src/rustc/middle/typeck/collect.rs b/src/rustc/middle/typeck/collect.rs index 04f7aae0bf2..ebc26d4b4df 100644 --- a/src/rustc/middle/typeck/collect.rs +++ b/src/rustc/middle/typeck/collect.rs @@ -133,9 +133,10 @@ fn get_enum_variant_types(ccx: @crate_ctxt, }); result_ty = Some(ty::mk_fn(tcx, FnTyBase { meta: FnMeta {purity: ast::pure_fn, - proto: ty::proto_vstore(ty::vstore_box), + proto: ast::ProtoBare, onceness: ast::Many, bounds: @~[], + region: ty::re_static, ret_style: ast::return_val}, sig: FnSig {inputs: args, output: enum_ty} @@ -604,9 +605,11 @@ fn convert_struct(ccx: @crate_ctxt, // Write the dtor type let t_dtor = ty::mk_fn( tcx, - ty_of_fn_decl(ccx, type_rscope(rp), ast::proto_bare, - ast::impure_fn, ast::Many, @~[], - ast_util::dtor_dec(), None, dtor.span)); + ty_of_fn_decl( + ccx, type_rscope(rp), ast::ProtoBare, + ast::impure_fn, ast::Many, + /*bounds:*/ @~[], /*opt_region:*/ None, + ast_util::dtor_dec(), None, dtor.span)); write_ty_to_tcx(tcx, dtor.node.id, t_dtor); tcx.tcache.insert(local_def(dtor.node.id), {bounds: tpt.bounds, @@ -643,9 +646,10 @@ fn convert_struct(ccx: @crate_ctxt, let ctor_fn_ty = ty::mk_fn(tcx, FnTyBase { meta: FnMeta { purity: ast::pure_fn, - proto: ty::proto_bare, + proto: ast::ProtoBare, onceness: ast::Many, bounds: @~[], + region: ty::re_static, ret_style: ast::return_val, }, sig: FnSig { @@ -684,15 +688,10 @@ fn ty_of_method(ccx: @crate_ctxt, rp: Option<ty::region_variance>) -> ty::method { {ident: m.ident, tps: ty_param_bounds(ccx, m.tps), - fty: ty_of_fn_decl(ccx, - type_rscope(rp), - ast::proto_bare, - m.purity, - ast::Many, - @~[], - m.decl, - None, - m.span), + fty: ty_of_fn_decl(ccx, type_rscope(rp), ast::ProtoBare, + m.purity, ast::Many, + /*bounds:*/ @~[], /*opt_region:*/ None, + m.decl, None, m.span), self_ty: m.self_ty.node, vis: m.vis, def_id: local_def(m.id)} @@ -704,15 +703,10 @@ fn ty_of_ty_method(self: @crate_ctxt, id: ast::def_id) -> ty::method { {ident: m.ident, tps: ty_param_bounds(self, m.tps), - fty: ty_of_fn_decl(self, - type_rscope(rp), - ast::proto_bare, - m.purity, - ast::Many, - @~[], - m.decl, - None, - m.span), + fty: ty_of_fn_decl(self, type_rscope(rp), ast::ProtoBare, + m.purity, ast::Many, + /*bounds:*/ @~[], /*opt_region:*/ None, + m.decl, None, m.span), // assume public, because this is only invoked on trait methods self_ty: m.self_ty.node, vis: ast::public, @@ -767,15 +761,10 @@ fn ty_of_item(ccx: @crate_ctxt, it: @ast::item) } ast::item_fn(decl, purity, tps, _) => { let bounds = ty_param_bounds(ccx, tps); - let tofd = ty_of_fn_decl(ccx, - empty_rscope, - ast::proto_bare, - purity, - ast::Many, - @~[], - decl, - None, - it.span); + let tofd = ty_of_fn_decl(ccx, empty_rscope, + ast::ProtoBare, purity, ast::Many, + /*bounds:*/ @~[], /*opt_region:*/ None, + decl, None, it.span); let tpt = {bounds: bounds, region_param: None, ty: ty::mk_fn(ccx.tcx, tofd)}; @@ -930,9 +919,10 @@ fn ty_of_foreign_fn_decl(ccx: @crate_ctxt, let t_fn = ty::mk_fn(ccx.tcx, FnTyBase { meta: FnMeta {purity: purity, - proto: ty::proto_bare, onceness: ast::Many, + proto: ast::ProtoBare, bounds: @~[], + region: ty::re_static, ret_style: ast::return_val}, sig: FnSig {inputs: input_tys, output: output_ty} diff --git a/src/rustc/middle/typeck/infer/assignment.rs b/src/rustc/middle/typeck/infer/assignment.rs index a5af58904dd..e5be4c7a19d 100644 --- a/src/rustc/middle/typeck/infer/assignment.rs +++ b/src/rustc/middle/typeck/infer/assignment.rs @@ -126,6 +126,14 @@ priv impl Assign { } } + fn borrowable_protos(a_p: ast::Proto, b_p: ast::Proto) -> bool { + match (a_p, b_p) { + (ast::ProtoBox, ast::ProtoBorrowed) => true, + (ast::ProtoUniq, ast::ProtoBorrowed) => true, + _ => false + } + } + match (a_bnd, b_bnd) { (Some(a_bnd), Some(b_bnd)) => { // check for a case where a non-region pointer (@, ~) is @@ -149,7 +157,7 @@ priv impl Assign { ty::ty_estr(ty::vstore_slice(r_b))) if is_borrowable(vs_a) => { let nr_b = ty::mk_estr(self.infcx.tcx, vs_a); - self.try_assign(0, ty::AutoSlice, + self.try_assign(0, ty::AutoBorrowVec, a, nr_b, m_imm, r_b) } @@ -160,11 +168,22 @@ priv impl Assign { let nr_b = ty::mk_evec(self.infcx.tcx, {ty: mt_b.ty, mutbl: m_const}, vs_a); - self.try_assign(0, ty::AutoSlice, + self.try_assign(0, ty::AutoBorrowVec, a, nr_b, mt_b.mutbl, r_b) } + (ty::ty_fn(ref a_f), ty::ty_fn(ref b_f)) + if borrowable_protos(a_f.meta.proto, b_f.meta.proto) => { + let nr_b = ty::mk_fn(self.infcx.tcx, ty::FnTyBase { + meta: ty::FnMeta {proto: a_f.meta.proto, + ..b_f.meta}, + sig: b_f.sig + }); + self.try_assign(0, ty::AutoBorrowFn, + a, nr_b, m_imm, b_f.meta.region) + } + _ => { // otherwise, assignment follows normal subtype rules: to_ares(Sub(*self).tys(a, b)) diff --git a/src/rustc/middle/typeck/infer/combine.rs b/src/rustc/middle/typeck/infer/combine.rs index 87f313f68bd..c43f1e9c386 100644 --- a/src/rustc/middle/typeck/infer/combine.rs +++ b/src/rustc/middle/typeck/infer/combine.rs @@ -48,6 +48,8 @@ use to_str::ToStr; use ty::{FnTyBase, FnMeta, FnSig}; use syntax::ast::Onceness; +fn macros() { include!("macros.rs"); } // FIXME(#3114): Macro import/export. + trait combine { fn infcx() -> infer_ctxt; fn tag() -> ~str; @@ -70,7 +72,7 @@ trait combine { fn flds(a: ty::field, b: ty::field) -> cres<ty::field>; fn modes(a: ast::mode, b: ast::mode) -> cres<ast::mode>; fn args(a: ty::arg, b: ty::arg) -> cres<ty::arg>; - fn protos(p1: ty::fn_proto, p2: ty::fn_proto) -> cres<ty::fn_proto>; + fn protos(p1: ast::Proto, p2: ast::Proto) -> cres<ast::Proto>; fn ret_styles(r1: ret_style, r2: ret_style) -> cres<ret_style>; fn purities(a: purity, b: purity) -> cres<purity>; fn oncenesses(a: Onceness, b: Onceness) -> cres<Onceness>; @@ -310,20 +312,17 @@ fn super_vstores<C:combine>( fn super_fn_metas<C:combine>( self: &C, a_f: &ty::FnMeta, b_f: &ty::FnMeta) -> cres<ty::FnMeta> { - 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| { - do self.oncenesses(a_f.onceness, b_f.onceness).chain - |onceness| { - Ok(FnMeta {purity: purity, - proto: p, - onceness: onceness, - bounds: a_f.bounds, // XXX: This is wrong! - ret_style: rs}) - } - } - } - } + let p = if_ok!(self.protos(a_f.proto, b_f.proto)); + let r = if_ok!(self.contraregions(a_f.region, b_f.region)); + let rs = if_ok!(self.ret_styles(a_f.ret_style, b_f.ret_style)); + let purity = if_ok!(self.purities(a_f.purity, b_f.purity)); + let onceness = if_ok!(self.oncenesses(a_f.onceness, b_f.onceness)); + Ok(FnMeta {purity: purity, + proto: p, + region: r, + onceness: onceness, + bounds: a_f.bounds, // XXX: This is wrong! + ret_style: rs}) } fn super_fn_sigs<C:combine>( diff --git a/src/rustc/middle/typeck/infer/glb.rs b/src/rustc/middle/typeck/infer/glb.rs index 0e81d97426f..fb4bd1af199 100644 --- a/src/rustc/middle/typeck/infer/glb.rs +++ b/src/rustc/middle/typeck/infer/glb.rs @@ -71,22 +71,8 @@ impl Glb: combine { Lub(*self).tys(a, b) } - fn protos(p1: ty::fn_proto, p2: ty::fn_proto) -> cres<ty::fn_proto> { - match (p1, p2) { - (ty::proto_vstore(ty::vstore_slice(_)), _) => Ok(p2), - (_, ty::proto_vstore(ty::vstore_slice(_))) => Ok(p1), - (ty::proto_vstore(v1), ty::proto_vstore(v2)) => { - self.infcx.try(|| { - do self.vstores(terr_fn, v1, v2).chain |vs| { - Ok(ty::proto_vstore(vs)) - } - }).chain_err(|_err| { - // XXX: Totally unsound, but fixed up later. - Ok(ty::proto_bare) - }) - } - _ => Ok(ty::proto_bare) - } + fn protos(p1: ast::Proto, p2: ast::Proto) -> cres<ast::Proto> { + if p1 == p2 {Ok(p1)} else {Ok(ast::ProtoBare)} } fn purities(a: purity, b: purity) -> cres<purity> { diff --git a/src/rustc/middle/typeck/infer/lub.rs b/src/rustc/middle/typeck/infer/lub.rs index 285b05736c6..a323ae720b2 100644 --- a/src/rustc/middle/typeck/infer/lub.rs +++ b/src/rustc/middle/typeck/infer/lub.rs @@ -54,21 +54,12 @@ impl Lub: combine { Glb(*self).tys(a, b) } - // XXX: Wrong. - fn protos(p1: ty::fn_proto, p2: ty::fn_proto) -> cres<ty::fn_proto> { + fn protos(p1: ast::Proto, p2: ast::Proto) -> cres<ast::Proto> { match (p1, p2) { - (ty::proto_bare, _) => Ok(p2), - (_, ty::proto_bare) => Ok(p1), - (ty::proto_vstore(v1), ty::proto_vstore(v2)) => { - self.infcx.try(|| { - do self.vstores(terr_fn, v1, v2).chain |vs| { - Ok(ty::proto_vstore(vs)) - } - }).chain_err(|_err| { - // XXX: Totally unsound, but fixed up later. - Ok(ty::proto_vstore(ty::vstore_slice(ty::re_static))) - }) - } + (ast::ProtoBare, _) => Ok(p2), + (_, ast::ProtoBare) => Ok(p1), + _ if p1 == p2 => Ok(p1), + _ => Err(ty::terr_proto_mismatch(expected_found(&self, p1, p2))) } } diff --git a/src/rustc/middle/typeck/infer/sub.rs b/src/rustc/middle/typeck/infer/sub.rs index 9e27235b30d..80f9eb85aab 100644 --- a/src/rustc/middle/typeck/infer/sub.rs +++ b/src/rustc/middle/typeck/infer/sub.rs @@ -63,27 +63,11 @@ impl Sub: combine { } } - fn protos(a: ty::fn_proto, b: ty::fn_proto) -> cres<ty::fn_proto> { - match (a, b) { - (ty::proto_bare, _) => - Ok(ty::proto_bare), - - (ty::proto_vstore(ty::vstore_box), - ty::proto_vstore(ty::vstore_slice(_))) => - Ok(ty::proto_vstore(ty::vstore_box)), - - (ty::proto_vstore(ty::vstore_uniq), - ty::proto_vstore(ty::vstore_slice(_))) => - Ok(ty::proto_vstore(ty::vstore_uniq)), - - (_, ty::proto_bare) => - Err(ty::terr_proto_mismatch(expected_found(&self, a, b))), - - (ty::proto_vstore(vs_a), ty::proto_vstore(vs_b)) => { - do self.vstores(ty::terr_fn, vs_a, vs_b).chain |vs_c| { - Ok(ty::proto_vstore(vs_c)) - } - } + fn protos(p1: ast::Proto, p2: ast::Proto) -> cres<ast::Proto> { + match (p1, p2) { + (ast::ProtoBare, _) => Ok(p1), + _ if p1 == p2 => Ok(p1), + _ => Err(ty::terr_proto_mismatch(expected_found(&self, p1, p2))) } } diff --git a/src/rustc/util/ppaux.rs b/src/rustc/util/ppaux.rs index c7062baaea5..a9b67a7ff29 100644 --- a/src/rustc/util/ppaux.rs +++ b/src/rustc/util/ppaux.rs @@ -4,7 +4,7 @@ use middle::ty::{arg, canon_mode}; use middle::ty::{bound_copy, bound_const, bound_owned, bound_send, bound_trait}; use middle::ty::{bound_region, br_anon, br_named, br_self, br_cap_avoid}; -use middle::ty::{ck_block, ck_box, ck_uniq, ctxt, field, method}; +use middle::ty::{ctxt, field, method}; use middle::ty::{mt, t, param_bound}; use middle::ty::{re_bound, re_free, re_scope, re_infer, re_static, Region}; use middle::ty::{ReSkolemized, ReVar}; @@ -111,22 +111,19 @@ fn explain_region_and_span(cx: ctxt, region: ty::Region) } fn bound_region_to_str(cx: ctxt, br: bound_region) -> ~str { - match br { - br_named(id) => fmt!("&%s", cx.sess.str_of(id)), - br_self if cx.sess.verbose() => ~"&<self>", - br_self => ~"&self", + bound_region_to_str_adorned(cx, ~"&", br, ~"") +} - br_anon(idx) => { - if cx.sess.verbose() {fmt!("&%u", idx)} else {~"&"} - } +fn bound_region_to_str_adorned(cx: ctxt, prefix: ~str, + br: bound_region, sep: ~str) -> ~str { + if cx.sess.verbose() { return fmt!("%s%?%s", prefix, br, sep); } - br_cap_avoid(id, br) => { - if cx.sess.verbose() { - fmt!("br_cap_avoid(%?, %s)", id, bound_region_to_str(cx, *br)) - } else { - bound_region_to_str(cx, *br) - } - } + match br { + br_named(id) => fmt!("%s%s%s", prefix, cx.sess.str_of(id), sep), + br_self => fmt!("%sself%s", prefix, sep), + br_anon(_) => prefix, + br_cap_avoid(_, br) => bound_region_to_str_adorned(cx, prefix, + *br, sep) } } @@ -174,8 +171,13 @@ fn re_scope_id_to_str(cx: ctxt, node_id: ast::node_id) -> ~str { // you should use `explain_region()` or, better yet, // `note_and_explain_region()` fn region_to_str(cx: ctxt, region: Region) -> ~str { + region_to_str_adorned(cx, ~"&", region, ~"") +} + +fn region_to_str_adorned(cx: ctxt, prefix: ~str, + region: Region, sep: ~str) -> ~str { if cx.sess.verbose() { - return fmt!("&%?", region); + return fmt!("%s%?%s", prefix, region, sep); } // These printouts are concise. They do not contain all the information @@ -183,12 +185,14 @@ fn region_to_str(cx: ctxt, region: Region) -> ~str { // to fit that into a short string. Hence the recommendation to use // `explain_region()` or `note_and_explain_region()`. match region { - re_scope(_) => ~"&", - re_bound(br) => bound_region_to_str(cx, br), - re_free(_, br) => bound_region_to_str(cx, br), - re_infer(ReSkolemized(_, br)) => bound_region_to_str(cx, br), - re_infer(ReVar(_)) => ~"&", - re_static => ~"&static" + re_scope(_) => prefix, + re_bound(br) => bound_region_to_str_adorned(cx, prefix, br, sep), + re_free(_, br) => bound_region_to_str_adorned(cx, prefix, br, sep), + re_infer(ReSkolemized(_, br)) => { + bound_region_to_str_adorned(cx, prefix, br, sep) + } + re_infer(ReVar(_)) => prefix, + re_static => fmt!("%sstatic%s", prefix, sep) } } @@ -222,10 +226,12 @@ fn vstore_ty_to_str(cx: ctxt, ty: ~str, vs: ty::vstore) -> ~str { } } -fn proto_ty_to_str(cx: ctxt, proto: ty::fn_proto) -> ~str { +fn proto_ty_to_str(_cx: ctxt, proto: ast::Proto) -> ~str { match proto { - ty::proto_bare => ~"", - ty::proto_vstore(vstore) => vstore_to_str(cx, vstore) + ast::ProtoBare => ~"", + ast::ProtoBox => ~"@", + ast::ProtoBorrowed => ~"&", + ast::ProtoUniq => ~"~", } } @@ -268,8 +274,9 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str { modestr + ty_to_str(cx, ty) } fn fn_to_str(cx: ctxt, + proto: ast::Proto, + region: ty::Region, purity: ast::purity, - proto: ty::fn_proto, onceness: ast::Onceness, ident: Option<ast::ident>, inputs: ~[arg], @@ -287,9 +294,21 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str { ast::Once => onceness_to_str(onceness) + ~" " }; + s += proto_ty_to_str(cx, proto); + + match (proto, region) { + (ast::ProtoBox, ty::re_static) | + (ast::ProtoUniq, ty::re_static) | + (ast::ProtoBare, ty::re_static) => { + } + + (_, region) => { + s += region_to_str_adorned(cx, ~"", region, ~"/"); + } + } + s += ~"fn"; - s += proto_ty_to_str(cx, proto); match ident { Some(i) => { s += ~" "; s += cx.sess.str_of(i); } _ => { } @@ -310,8 +329,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.meta.purity, m.fty.meta.proto, + m.fty.meta.region, + m.fty.meta.purity, m.fty.meta.onceness, Some(m.ident), m.fty.sig.inputs, @@ -345,12 +365,7 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str { ty_uniq(tm) => ~"~" + mt_to_str(cx, tm), ty_ptr(tm) => ~"*" + mt_to_str(cx, tm), ty_rptr(r, tm) => { - let rs = region_to_str(cx, r); - if rs == ~"&" { - rs + mt_to_str(cx, tm) - } else { - rs + ~"/" + mt_to_str(cx, tm) - } + region_to_str_adorned(cx, ~"&", r, ~"/") + mt_to_str(cx, tm) } ty_unboxed_vec(tm) => { ~"unboxed_vec<" + mt_to_str(cx, tm) + ~">" } ty_type => ~"type", @@ -364,8 +379,9 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str { } ty_fn(ref f) => { fn_to_str(cx, - f.meta.purity, f.meta.proto, + f.meta.region, + f.meta.purity, f.meta.onceness, None, f.sig.inputs, @@ -393,9 +409,10 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str { } ty_estr(vs) => vstore_ty_to_str(cx, ~"str", vs), ty_opaque_box => ~"@?", - ty_opaque_closure_ptr(ck_block) => ~"closure&", - ty_opaque_closure_ptr(ck_box) => ~"closure@", - ty_opaque_closure_ptr(ck_uniq) => ~"closure~" + ty_opaque_closure_ptr(ast::ProtoBorrowed) => ~"closure&", + ty_opaque_closure_ptr(ast::ProtoBox) => ~"closure@", + ty_opaque_closure_ptr(ast::ProtoUniq) => ~"closure~", + ty_opaque_closure_ptr(ast::ProtoBare) => ~"closure" } } |
