diff options
| author | bors <bors@rust-lang.org> | 2013-02-07 06:05:10 -0800 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2013-02-07 06:05:10 -0800 |
| commit | 3764cfbf57646becdeefa2996f812cbe40b016e7 (patch) | |
| tree | 62fc02049c4d06ccd64a704f6f9e3af53d2835e3 /src/librustc | |
| parent | 82d73963334f01b818cda767b44cd0c8f3baf4cc (diff) | |
| parent | a32498d8464e0dfa4e2cb31967a66e076da40109 (diff) | |
auto merge of #4810 : nikomatsakis/rust/owned-fn-noncopyable, r=nikomatsakis
Part of #3678. Fixes #2828, #3904. r? @brson
Diffstat (limited to 'src/librustc')
51 files changed, 1398 insertions, 1544 deletions
diff --git a/src/librustc/front/config.rs b/src/librustc/front/config.rs index a7c071919ff..cf75db3a900 100644 --- a/src/librustc/front/config.rs +++ b/src/librustc/front/config.rs @@ -64,12 +64,13 @@ fn filter_view_item(cx: ctxt, &&view_item: @ast::view_item } fn fold_mod(cx: ctxt, m: ast::_mod, fld: fold::ast_fold) -> ast::_mod { - let filtered_items = vec::filter_map(m.items, |a| filter_item(cx, *a)); - let filtered_view_items = vec::filter_map(m.view_items, - |a| filter_view_item(cx, *a)); + let filtered_items = + m.items.filter_mapped(|a| filter_item(cx, *a)); + let filtered_view_items = + m.view_items.filter_mapped(|a| filter_view_item(cx, *a)); ast::_mod { view_items: filtered_view_items.map(|x| fld.fold_view_item(*x)), - items: filtered_items.filter_map(|x| fld.fold_item(*x)), + items: vec::filter_map(filtered_items, |x| fld.fold_item(x)) } } @@ -85,10 +86,10 @@ fn fold_foreign_mod( nm: ast::foreign_mod, fld: fold::ast_fold ) -> ast::foreign_mod { - let filtered_items = vec::filter_map(nm.items, - |a| filter_foreign_item(cx, *a)); - let filtered_view_items = vec::filter_map(nm.view_items, - |a| filter_view_item(cx, *a)); + let filtered_items = + nm.items.filter_mapped(|a| filter_foreign_item(cx, *a)); + let filtered_view_items = + nm.view_items.filter_mapped(|a| filter_view_item(cx, *a)); ast::foreign_mod { sort: nm.sort, abi: nm.abi, @@ -136,7 +137,8 @@ fn fold_block( b: ast::blk_, fld: fold::ast_fold ) -> ast::blk_ { - let filtered_stmts = vec::filter_map(b.stmts, |a| filter_stmt(cx, *a)); + let filtered_stmts = + b.stmts.filter_mapped(|a| filter_stmt(cx, *a)); ast::blk_ { view_items: /*bad*/copy b.view_items, stmts: vec::map(filtered_stmts, |x| fld.fold_stmt(*x)), @@ -183,8 +185,9 @@ pub fn metas_in_cfg(cfg: ast::crate_cfg, // Pull the inner meta_items from the #[cfg(meta_item, ...)] attributes, // so we can match against them. This is the list of configurations for // which the item is valid - let cfg_metas = vec::concat(vec::filter_map(cfg_metas, - |i| attr::get_meta_item_list(*i))); + let cfg_metas = + vec::concat( + vec::filter_map(cfg_metas, |i| attr::get_meta_item_list(i))); let has_cfg_metas = vec::len(cfg_metas) > 0u; if !has_cfg_metas { return true; } diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs index 91eb8148bb7..9fa1cea3e10 100644 --- a/src/librustc/front/test.rs +++ b/src/librustc/front/test.rs @@ -168,9 +168,11 @@ fn is_test_fn(i: @ast::item) -> bool { fn is_ignored(cx: test_ctxt, i: @ast::item) -> bool { let ignoreattrs = attr::find_attrs_by_name(i.attrs, "ignore"); let ignoreitems = attr::attr_metas(ignoreattrs); - let cfg_metas = vec::concat(vec::filter_map(ignoreitems, - |i| attr::get_meta_item_list(*i))); return if !ignoreitems.is_empty() { + let cfg_metas = + vec::concat( + vec::filter_map(ignoreitems, + |i| attr::get_meta_item_list(i))); config::metas_in_cfg(/*bad*/copy cx.crate.node.config, cfg_metas) } else { false @@ -277,7 +279,7 @@ fn mk_std(cx: test_ctxt) -> @ast::view_item { } fn mk_tests(cx: test_ctxt) -> @ast::item { - let ret_ty = mk_test_desc_vec_ty(cx); + let ret_ty = mk_test_desc_and_fn_vec_ty(cx); let decl = ast::fn_decl { inputs: ~[], @@ -286,7 +288,7 @@ fn mk_tests(cx: test_ctxt) -> @ast::item { }; // The vector of test_descs for this crate - let test_descs = mk_test_desc_vec(cx); + let test_descs = mk_test_desc_and_fn_vec(cx); let body_: ast::blk_ = default_block(~[], option::Some(test_descs), cx.sess.next_node_id()); @@ -327,19 +329,21 @@ fn mk_path(cx: test_ctxt, +path: ~[ast::ident]) -> @ast::path { } } -// The ast::Ty of ~[std::test::test_desc] -fn mk_test_desc_vec_ty(cx: test_ctxt) -> @ast::Ty { - let test_desc_ty_path = +// The ast::Ty of ~[std::test::TestDescAndFn] +fn mk_test_desc_and_fn_vec_ty(cx: test_ctxt) -> @ast::Ty { + let test_desc_and_fn_ty_path = mk_path(cx, ~[cx.sess.ident_of(~"test"), - cx.sess.ident_of(~"TestDesc")]); + cx.sess.ident_of(~"TestDescAndFn")]); - let test_desc_ty = ast::Ty { + let test_desc_and_fn_ty = ast::Ty { id: cx.sess.next_node_id(), - node: ast::ty_path(test_desc_ty_path, cx.sess.next_node_id()), + node: ast::ty_path(test_desc_and_fn_ty_path, + cx.sess.next_node_id()), span: dummy_sp(), }; - let vec_mt = ast::mt {ty: @test_desc_ty, mutbl: ast::m_imm}; + let vec_mt = ast::mt {ty: @test_desc_and_fn_ty, + mutbl: ast::m_imm}; let inner_ty = @ast::Ty { id: cx.sess.next_node_id(), @@ -354,11 +358,11 @@ fn mk_test_desc_vec_ty(cx: test_ctxt) -> @ast::Ty { } } -fn mk_test_desc_vec(cx: test_ctxt) -> @ast::expr { +fn mk_test_desc_and_fn_vec(cx: test_ctxt) -> @ast::expr { debug!("building test vector from %u tests", cx.testfns.len()); let mut descs = ~[]; for cx.testfns.each |test| { - descs.push(mk_test_desc_rec(cx, *test)); + descs.push(mk_test_desc_and_fn_rec(cx, *test)); } let inner_expr = @ast::expr { @@ -376,7 +380,7 @@ fn mk_test_desc_vec(cx: test_ctxt) -> @ast::expr { } } -fn mk_test_desc_rec(cx: test_ctxt, test: test) -> @ast::expr { +fn mk_test_desc_and_fn_rec(cx: test_ctxt, test: test) -> @ast::expr { let span = test.span; let path = /*bad*/copy test.path; @@ -407,23 +411,6 @@ fn mk_test_desc_rec(cx: test_ctxt, test: test) -> @ast::expr { expr: @name_expr, }); - let fn_path = path_node_global(path); - - let fn_expr = ast::expr { - id: cx.sess.next_node_id(), - callee_id: cx.sess.next_node_id(), - node: ast::expr_path(fn_path), - span: span, - }; - - let fn_wrapper_expr = mk_test_wrapper(cx, fn_expr, span); - - let fn_field = nospan(ast::field_ { - mutbl: ast::m_imm, - ident: cx.sess.ident_of(~"testfn"), - expr: fn_wrapper_expr, - }); - let ignore_lit: ast::lit = nospan(ast::lit_bool(test.ignore)); let ignore_expr = ast::expr { @@ -460,62 +447,52 @@ fn mk_test_desc_rec(cx: test_ctxt, test: test) -> @ast::expr { let desc_rec_ = ast::expr_struct( test_desc_path, - ~[name_field, fn_field, ignore_field, fail_field], + ~[name_field, ignore_field, fail_field], option::None ); - let desc_rec = ast::expr { + let desc_rec = @ast::expr { id: cx.sess.next_node_id(), callee_id: cx.sess.next_node_id(), node: desc_rec_, span: span, }; - return @desc_rec; -} + let desc_field = nospan(ast::field_ { + mutbl: ast::m_imm, + ident: cx.sess.ident_of(~"desc"), + expr: desc_rec + }); -// Produces a bare function that wraps the test function + let fn_path = path_node_global(path); -// FIXME (#1281): This can go away once fn is the type of bare function. -fn mk_test_wrapper(cx: test_ctxt, - +fn_path_expr: ast::expr, - span: span) -> @ast::expr { - let call_expr = ast::expr { + let fn_expr = @ast::expr { id: cx.sess.next_node_id(), callee_id: cx.sess.next_node_id(), - node: ast::expr_call(@fn_path_expr, ~[], false), + node: ast::expr_path(fn_path), span: span, }; - let call_stmt: ast::stmt = nospan( - ast::stmt_semi(@call_expr, cx.sess.next_node_id())); - - let wrapper_decl = ast::fn_decl { - inputs: ~[], - output: @ast::Ty { - id: cx.sess.next_node_id(), - node: ast::ty_nil, - span: span, - }, - cf: ast::return_val - }; - - let wrapper_body = nospan(ast::blk_ { - view_items: ~[], - stmts: ~[@call_stmt], - expr: option::None, - id: cx.sess.next_node_id(), - rules: ast::default_blk + let fn_field = nospan(ast::field_ { + mutbl: ast::m_imm, + ident: cx.sess.ident_of(~"testfn"), + expr: fn_expr, }); - let wrapper_expr = ast::expr { + let test_desc_and_fn_path = + mk_path(cx, ~[cx.sess.ident_of(~"test"), + cx.sess.ident_of(~"TestDescAndFn")]); + + let desc_and_fn_rec = @ast::expr { id: cx.sess.next_node_id(), callee_id: cx.sess.next_node_id(), - node: ast::expr_fn(ast::ProtoBare, wrapper_decl, wrapper_body, @()), - span: span + node: ast::expr_struct(test_desc_and_fn_path, + ~[fn_field, desc_field], + option::None), + span: span, }; - return @wrapper_expr; + return desc_and_fn_rec; } fn mk_main(cx: test_ctxt) -> @ast::item { @@ -567,7 +544,7 @@ fn mk_test_main_call(cx: test_ctxt) -> @ast::expr { let args_call_expr = ast::expr { id: cx.sess.next_node_id(), callee_id: cx.sess.next_node_id(), - node: ast::expr_call(@args_path_expr, ~[], false), + node: ast::expr_call(@args_path_expr, ~[], ast::NoSugar), span: dummy_sp(), }; @@ -584,7 +561,7 @@ fn mk_test_main_call(cx: test_ctxt) -> @ast::expr { let test_call_expr = ast::expr { id: cx.sess.next_node_id(), callee_id: cx.sess.next_node_id(), - node: ast::expr_call(@test_path_expr, ~[], false), + node: ast::expr_call(@test_path_expr, ~[], ast::NoSugar), span: dummy_sp(), }; @@ -606,7 +583,7 @@ fn mk_test_main_call(cx: test_ctxt) -> @ast::expr { node: ast::expr_call( @test_main_path_expr, ~[@args_call_expr, @test_call_expr], - false + ast::NoSugar ), span: dummy_sp(), }; diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 9a6a2f7e954..67498ad5aaf 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -586,10 +586,8 @@ pub fn get_enum_variants(intr: @ident_interner, cdata: cmd, id: ast::node_id, item, tcx, cdata); let name = item_name(intr, item); let arg_tys = match ty::get(ctor_ty).sty { - ty::ty_fn(ref f) => (*f).sig.inputs.map(|a| a.ty), - - // Nullary enum variant. - _ => ~[], + ty::ty_bare_fn(ref f) => f.sig.inputs.map(|a| a.ty), + _ => ~[], // Nullary enum variant. }; match variant_disr_val(item) { Some(val) => { disr_val = val; } @@ -705,11 +703,12 @@ pub fn get_trait_methods(intr: @ident_interner, cdata: cmd, id: ast::node_id, let ty = doc_type(mth, tcx, cdata); let def_id = item_def_id(mth, cdata); let fty = match ty::get(ty).sty { - ty::ty_fn(ref f) => (/*bad*/copy *f), - _ => { - tcx.diag.handler().bug( - ~"get_trait_methods: id has non-function type"); - } }; + ty::ty_bare_fn(ref f) => copy *f, + _ => { + tcx.diag.handler().bug( + ~"get_trait_methods: id has non-function type"); + } + }; let self_ty = get_self_ty(mth); result.push({ident: name, tps: bounds, fty: fty, self_ty: self_ty, vis: ast::public, def_id: def_id}); @@ -734,14 +733,13 @@ pub fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd, let name = item_name(intr, mth); let ty = doc_type(mth, tcx, cdata); - let fty; - match ty::get(ty).sty { - ty::ty_fn(ref f) => fty = (/*bad*/copy *f), + let fty = match ty::get(ty).sty { + ty::ty_bare_fn(ref f) => copy *f, _ => { tcx.diag.handler().bug(~"get_provided_trait_methods(): id \ has non-function type"); } - } + }; let self_ty = get_self_ty(mth); let ty_method = {ident: name, tps: bounds, fty: fty, self_ty: self_ty, diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 072b974d042..b0a424447b3 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -768,8 +768,9 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: writer::Encoder, 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, /*bad*/copy mty.fty)); - encode_family(ebml_w, purity_fn_family(mty.fty.meta.purity)); + encode_type(ecx, ebml_w, + ty::mk_bare_fn(tcx, copy mty.fty)); + encode_family(ebml_w, purity_fn_family(mty.fty.purity)); encode_self_type(ebml_w, mty.self_ty); encode_method_sort(ebml_w, 'r'); ebml_w.end_tag(); @@ -781,8 +782,9 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: writer::Encoder, encode_def_id(ebml_w, local_def(m.id)); encode_name(ecx, ebml_w, mty.ident); encode_type_param_bounds(ebml_w, ecx, m.tps); - encode_type(ecx, ebml_w, ty::mk_fn(tcx, /*bad*/copy mty.fty)); - encode_family(ebml_w, purity_fn_family(mty.fty.meta.purity)); + encode_type(ecx, ebml_w, + ty::mk_bare_fn(tcx, copy mty.fty)); + encode_family(ebml_w, purity_fn_family(mty.fty.purity)); encode_self_type(ebml_w, mty.self_ty); encode_method_sort(ebml_w, 'p'); ebml_w.end_tag(); diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index ea13325ad49..3f989339e27 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -17,8 +17,6 @@ use core::prelude::*; use middle::ty; -use middle::ty::{FnTyBase, FnMeta, FnSig, arg, creader_cache_key, field}; -use middle::ty::{substs}; use core::io; use core::str; @@ -124,17 +122,12 @@ fn parse_path(st: @pstate) -> @ast::path { }; } -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) -> ast::Proto { +fn parse_sigil(st: @pstate) -> ast::Sigil { match next(st) { - '_' => ast::ProtoBare, - '@' => ast::ProtoBox, - '~' => ast::ProtoUniq, - '&' => ast::ProtoBorrowed, - _ => die!(~"parse_proto(): bad input") + '@' => ast::ManagedSigil, + '~' => ast::OwnedSigil, + '&' => ast::BorrowedSigil, + c => st.tcx.sess.bug(fmt!("parse_sigil(): bad input '%c'", c)) } } @@ -152,7 +145,7 @@ fn parse_vstore(st: @pstate) -> ty::vstore { '~' => ty::vstore_uniq, '@' => ty::vstore_box, '&' => ty::vstore_slice(parse_region(st)), - _ => die!(~"parse_vstore: bad input") + c => st.tcx.sess.bug(fmt!("parse_vstore(): bad input '%c'", c)) } } @@ -166,7 +159,7 @@ fn parse_substs(st: @pstate, conv: conv_did) -> ty::substs { while peek(st) != ']' { params.push(parse_ty(st, conv)); } st.pos = st.pos + 1u; - return substs { + return ty::substs { self_r: self_r, self_ty: self_ty, tps: params @@ -316,19 +309,24 @@ fn parse_ty(st: @pstate, conv: conv_did) -> ty::t { return ty::mk_tup(st.tcx, params); } 'f' => { - parse_ty_rust_fn(st, conv) + return ty::mk_closure(st.tcx, parse_closure_ty(st, conv)); + } + 'F' => { + return ty::mk_bare_fn(st.tcx, parse_bare_fn_ty(st, conv)); } 'Y' => return ty::mk_type(st.tcx), 'C' => { - let proto = parse_proto(st); - return ty::mk_opaque_closure_ptr(st.tcx, proto); + let sigil = parse_sigil(st); + return ty::mk_opaque_closure_ptr(st.tcx, sigil); } '#' => { let pos = parse_hex(st); assert (next(st) == ':'); let len = parse_hex(st); assert (next(st) == '#'); - let key = creader_cache_key { cnum: st.crate, pos: pos, len: len }; + let key = ty::creader_cache_key {cnum: st.crate, + pos: pos, + len: len }; match st.tcx.rcache.find(&key) { Some(tt) => return tt, None => { @@ -408,6 +406,13 @@ fn parse_purity(c: char) -> purity { } } +fn parse_abi(c: char) -> Abi { + match c { + 'r' => ast::RustAbi, + _ => die!(fmt!("parse_abi: bad ABI '%c'", c)) + } +} + fn parse_onceness(c: char) -> ast::Onceness { match c { 'o' => ast::Once, @@ -430,12 +435,33 @@ fn parse_mode(st: @pstate) -> ast::mode { return m; } -fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::FnTy { - let proto = parse_proto(st); +fn parse_closure_ty(st: @pstate, conv: conv_did) -> ty::ClosureTy { + let sigil = parse_sigil(st); let purity = parse_purity(next(st)); let onceness = parse_onceness(next(st)); let region = parse_region(st); - let bounds = parse_bounds(st, conv); + let sig = parse_sig(st, conv); + ty::ClosureTy { + purity: purity, + sigil: sigil, + onceness: onceness, + region: region, + sig: sig + } +} + +fn parse_bare_fn_ty(st: @pstate, conv: conv_did) -> ty::BareFnTy { + let purity = parse_purity(next(st)); + let abi = parse_abi(next(st)); + let sig = parse_sig(st, conv); + ty::BareFnTy { + purity: purity, + abi: abi, + sig: sig + } +} + +fn parse_sig(st: @pstate, conv: conv_did) -> ty::FnSig { assert (next(st) == '['); let mut inputs: ~[ty::arg] = ~[]; while peek(st) != ']' { @@ -444,18 +470,9 @@ fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::FnTy { } st.pos += 1u; // eat the ']' let ret_ty = parse_ty(st, conv); - return FnTyBase { - meta: FnMeta {purity: purity, - proto: proto, - onceness: onceness, - bounds: bounds, - region: region}, - sig: FnSig {inputs: inputs, - output: ret_ty} - }; + ty::FnSig {inputs: inputs, output: ret_ty} } - // Rust metadata parsing pub fn parse_def_id(buf: &[u8]) -> ast::def_id { let mut colon_idx = 0u; diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 0d66862c79f..a87ce02d5a3 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -288,8 +288,13 @@ fn enc_sty(w: io::Writer, cx: @ctxt, +st: ty::sty) { } w.write_char(']'); } - ty::ty_fn(ref f) => { - enc_ty_fn(w, cx, (*f)); + ty::ty_closure(ref f) => { + w.write_char('f'); + enc_closure_ty(w, cx, f); + } + ty::ty_bare_fn(ref f) => { + w.write_char('F'); + enc_bare_fn_ty(w, cx, f); } ty::ty_infer(_) => { cx.diag.handler().bug(~"Cannot encode inference variable types"); @@ -306,7 +311,7 @@ fn enc_sty(w: io::Writer, cx: @ctxt, +st: ty::sty) { ty::ty_type => w.write_char('Y'), ty::ty_opaque_closure_ptr(p) => { w.write_str(&"C&"); - enc_proto(w, p); + enc_sigil(w, p); } ty::ty_opaque_box => w.write_char('B'), ty::ty_struct(def, ref substs) => { @@ -325,13 +330,11 @@ fn enc_sty(w: io::Writer, cx: @ctxt, +st: ty::sty) { } } -fn enc_proto(w: io::Writer, proto: Proto) { - w.write_str(&"f"); - match proto { - ProtoBare => w.write_str(&"_"), - ProtoBox => w.write_str(&"@"), - ProtoUniq => w.write_str(&"~"), - ProtoBorrowed => w.write_str(&"&"), +fn enc_sigil(w: io::Writer, sigil: Sigil) { + match sigil { + ManagedSigil => w.write_str("@"), + OwnedSigil => w.write_str("~"), + BorrowedSigil => w.write_str("&"), } } @@ -357,6 +360,12 @@ fn enc_purity(w: io::Writer, p: purity) { } } +fn enc_abi(w: io::Writer, a: Abi) { + match a { + RustAbi => w.write_char('r'), + } +} + fn enc_onceness(w: io::Writer, o: Onceness) { match o { Once => w.write_char('o'), @@ -364,18 +373,27 @@ fn enc_onceness(w: io::Writer, o: Onceness) { } } -fn enc_ty_fn(w: io::Writer, cx: @ctxt, ft: ty::FnTy) { - 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); +fn enc_bare_fn_ty(w: io::Writer, cx: @ctxt, ft: &ty::BareFnTy) { + enc_purity(w, ft.purity); + enc_abi(w, ft.abi); + enc_fn_sig(w, cx, &ft.sig); +} + +fn enc_closure_ty(w: io::Writer, cx: @ctxt, ft: &ty::ClosureTy) { + enc_sigil(w, ft.sigil); + enc_purity(w, ft.purity); + enc_onceness(w, ft.onceness); + enc_region(w, cx, ft.region); + enc_fn_sig(w, cx, &ft.sig); +} + +fn enc_fn_sig(w: io::Writer, cx: @ctxt, fsig: &ty::FnSig) { w.write_char('['); - for ft.sig.inputs.each |arg| { + for fsig.inputs.each |arg| { enc_arg(w, cx, *arg); } w.write_char(']'); - enc_ty(w, cx, ft.sig.output); + enc_ty(w, cx, fsig.output); } pub fn enc_bounds(w: io::Writer, cx: @ctxt, bs: @~[ty::param_bound]) { diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index 9b2d51289ad..dfc26000116 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -221,18 +221,19 @@ impl check_loan_ctxt { let callee_ty = ty::node_id_to_type(tcx, callee_id); match ty::get(callee_ty).sty { - ty::ty_fn(ref fn_ty) => { - 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", - fn_ty.meta.purity.to_str())); - } + ty::ty_bare_fn(ty::BareFnTy {purity: purity, _}) | + ty::ty_closure(ty::ClosureTy {purity: purity, _}) => { + match 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", + purity.to_str())); + } + } } - } - _ => return, // case (d) above + _ => return, // case (d) above } } @@ -240,8 +241,11 @@ impl check_loan_ctxt { // The expression must be an expr_fn(*) or expr_fn_block(*) 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 proto == ast::ProtoBorrowed; + match ty::get(fn_ty).sty { + ty::ty_closure(ty::ClosureTy {sigil: ast::BorrowedSigil, + _}) => true, + _ => false + } } fn is_allowed_pure_arg(expr: @ast::expr) -> bool { @@ -564,17 +568,27 @@ fn check_loans_in_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk, { let is_stack_closure = self.is_stack_closure(id); let fty = ty::node_id_to_type(self.tcx(), id); - let fty_proto = ty::ty_fn_proto(fty); - check_moves_from_captured_variables(self, id, fty_proto); + let declared_purity; + match fk { + visit::fk_item_fn(*) | visit::fk_method(*) | + visit::fk_dtor(*) => { + declared_purity = ty::ty_fn_purity(fty); + } + + visit::fk_anon(*) | visit::fk_fn_block(*) => { + let fty_sigil = ty::ty_closure_sigil(fty); + check_moves_from_captured_variables(self, id, fty_sigil); + declared_purity = ty::determine_inherited_purity( + copy self.declared_purity, ty::ty_fn_purity(fty), + fty_sigil); + } + } debug!("purity on entry=%?", copy self.declared_purity); do save_and_restore(&mut(self.declared_purity)) { do save_and_restore(&mut(self.fn_args)) { - self.declared_purity = ty::determine_inherited_purity( - copy self.declared_purity, - ty::ty_fn_purity(fty), - fty_proto); + self.declared_purity = declared_purity; match fk { visit::fk_anon(*) | @@ -608,10 +622,10 @@ fn check_loans_in_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk, fn check_moves_from_captured_variables(&&self: check_loan_ctxt, id: ast::node_id, - fty_proto: ast::Proto) + fty_sigil: ast::Sigil) { - match fty_proto { - ast::ProtoBox | ast::ProtoUniq => { + match fty_sigil { + ast::ManagedSigil | ast::OwnedSigil => { let cap_vars = self.bccx.capture_map.get(&id); for cap_vars.each |cap_var| { match cap_var.mode { @@ -646,7 +660,7 @@ fn check_loans_in_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk, } } - ast::ProtoBorrowed | ast::ProtoBare => {} + ast::BorrowedSigil => {} } } } diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index 69ace0d7797..ad46d3b6f4d 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -150,7 +150,7 @@ pub fn check_expr(sess: Session, } } } - expr_call(callee, _, false) => { + expr_call(callee, _, NoSugar) => { match def_map.find(&callee.id) { Some(def_struct(*)) => {} // OK. Some(def_variant(*)) => {} // OK. diff --git a/src/librustc/middle/check_loop.rs b/src/librustc/middle/check_loop.rs index 11c557f0249..38450de6b54 100644 --- a/src/librustc/middle/check_loop.rs +++ b/src/librustc/middle/check_loop.rs @@ -39,8 +39,8 @@ pub fn check_crate(tcx: ty::ctxt, crate: @crate) { (v.visit_block)((*b), {in_loop: false, can_ret: false}, v); } expr_loop_body(@expr {node: expr_fn_block(_, ref b), _}) => { - let proto = ty::ty_fn_proto(ty::expr_ty(tcx, e)); - let blk = (proto == ProtoBorrowed); + let sigil = ty::ty_closure_sigil(ty::expr_ty(tcx, e)); + let blk = (sigil == BorrowedSigil); (v.visit_block)((*b), {in_loop: true, can_ret: blk}, v); } expr_break(_) => { diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index 978aaacb18a..6f9fe1edca5 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -100,7 +100,7 @@ pub fn check_expr(cx: @MatchCheckCtxt, ex: @expr, &&s: (), v: visit::vt<()>) { } _ => { /* We assume only enum types can be uninhabited */ } } - let arms = vec::concat(vec::filter_map((*arms), unguarded_pat)); + let arms = vec::concat(arms.filter_mapped(unguarded_pat)); check_exhaustive(cx, ex.span, arms); } _ => () @@ -255,7 +255,8 @@ pub fn is_useful(cx: @MatchCheckCtxt, +m: matrix, +v: &[@pat]) -> useful { } } Some(ref ctor) => { - match is_useful(cx, vec::filter_map(m, |r| default(cx, copy *r)), + match is_useful(cx, + vec::filter_map(m, |r| default(cx, r)), vec::tail(v)) { useful_ => useful(left_ty, (/*bad*/copy *ctor)), ref u => (/*bad*/copy *u) @@ -277,8 +278,7 @@ pub fn is_useful_specialized(cx: @MatchCheckCtxt, arity: uint, lty: ty::t) -> useful { - let ms = vec::filter_map(m, |r| specialize(cx, *r, - ctor, arity, lty)); + let ms = m.filter_mapped(|r| specialize(cx, *r, ctor, arity, lty)); let could_be_useful = is_useful( cx, ms, specialize(cx, v, ctor, arity, lty).get()); match could_be_useful { @@ -387,9 +387,9 @@ pub fn missing_ctor(cx: @MatchCheckCtxt, ty::ty_unboxed_vec(*) | ty::ty_evec(*) => { // Find the lengths and tails of all vector patterns. - let vec_pat_lens = do m.filter_map |r| { - match /*bad*/copy r[0].node { - pat_vec(elems, tail) => { + let vec_pat_lens = do m.filter_mapped |r| { + match r[0].node { + pat_vec(ref elems, ref tail) => { Some((elems.len(), tail.is_some())) } _ => None diff --git a/src/librustc/middle/freevars.rs b/src/librustc/middle/freevars.rs index 5d65aba2a4d..e6091077210 100644 --- a/src/librustc/middle/freevars.rs +++ b/src/librustc/middle/freevars.rs @@ -48,10 +48,8 @@ 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::ProtoBare { - visit::visit_expr(expr, depth + 1, v); - } + ast::expr_fn(_, _, _, _) => { + visit::visit_expr(expr, depth + 1, v); } ast::expr_fn_block(*) => { visit::visit_expr(expr, depth + 1, v); diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index 8abafe6b079..35d5595fefd 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -150,11 +150,23 @@ 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) { - ProtoUniq => b(check_for_uniq), - ProtoBox => b(check_for_box), - ProtoBare => b(check_for_bare), - ProtoBorrowed => b(check_for_block), + match ty::get(fty).sty { + ty::ty_closure(ty::ClosureTy {sigil: OwnedSigil, _}) => { + b(check_for_uniq) + } + ty::ty_closure(ty::ClosureTy {sigil: ManagedSigil, _}) => { + b(check_for_box) + } + ty::ty_closure(ty::ClosureTy {sigil: BorrowedSigil, _}) => { + b(check_for_block) + } + ty::ty_bare_fn(_) => { + b(check_for_bare) + } + ref s => { + cx.tcx.sess.bug( + fmt!("expect fn type in kind checker, not %?", s)); + } } } @@ -240,42 +252,6 @@ pub fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) { expr.span, "explicit copy requires a copyable argument"); } - expr_rec(ref fields, def) | expr_struct(_, ref fields, def) => { - match def { - Some(ex) => { - // All noncopyable fields must be overridden - let t = ty::expr_ty(cx.tcx, ex); - let ty_fields = match ty::get(t).sty { - ty::ty_rec(ref f) => { - copy *f - } - ty::ty_struct(did, ref substs) => { - ty::struct_fields(cx.tcx, did, substs) - } - _ => { - cx.tcx.sess.span_bug( - ex.span, - ~"bad base expr type in record") - } - }; - for ty_fields.each |tf| { - // If this field would not be copied, ok. - if fields.any(|f| f.node.ident == tf.ident) { loop; } - - // If this field is copyable, ok. - let kind = ty::type_kind(cx.tcx, tf.mt.ty); - if ty::kind_can_be_copied(kind) { loop; } - - cx.tcx.sess.span_err( - e.span, - fmt!("cannot copy field `%s` of base expression, \ - which has a noncopyable type", - *cx.tcx.sess.intr().get(tf.ident))); - } - } - _ => {} - } - } expr_repeat(element, count_expr, _) => { let count = ty::eval_repeat_count(cx.tcx, count_expr, e.span); if count > 1 { diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 4601941f73a..51bbdfdc19c 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -897,9 +897,10 @@ fn check_fn(tcx: ty::ctxt, fk: visit::fn_kind, decl: ast::fn_decl, fn check_fn_deprecated_modes(tcx: ty::ctxt, fn_ty: ty::t, decl: ast::fn_decl, span: span, id: ast::node_id) { match ty::get(fn_ty).sty { - ty::ty_fn(ref fn_ty) => { + ty::ty_closure(ty::ClosureTy {sig: ref sig, _}) | + ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, _}) => { let mut counter = 0; - for vec::each2(fn_ty.sig.inputs, decl.inputs) |arg_ty, arg_ast| { + for vec::each2(sig.inputs, decl.inputs) |arg_ty, arg_ast| { counter += 1; debug!("arg %d, ty=%s, mode=%s", counter, @@ -938,13 +939,14 @@ fn check_fn_deprecated_modes(tcx: ty::ctxt, fn_ty: ty::t, decl: ast::fn_decl, } match ty::get(arg_ty.ty).sty { - ty::ty_fn(*) => { + ty::ty_closure(*) | ty::ty_bare_fn(*) => { let span = arg_ast.ty.span; // Recurse to check fn-type argument match arg_ast.ty.node { - ast::ty_fn(f) => { + ast::ty_closure(@ast::TyClosure{decl: ref d, _}) | + ast::ty_bare_fn(@ast::TyBareFn{decl: ref d, _})=>{ check_fn_deprecated_modes(tcx, arg_ty.ty, - f.decl, span, id); + *d, span, id); } ast::ty_path(*) => { // This is probably a typedef, so we can't @@ -976,10 +978,11 @@ fn check_item_deprecated_modes(tcx: ty::ctxt, it: @ast::item) { match it.node { ast::item_ty(ty, _) => { match ty.node { - ast::ty_fn(f) => { + ast::ty_closure(@ast::TyClosure {decl: ref decl, _}) | + ast::ty_bare_fn(@ast::TyBareFn {decl: ref decl, _}) => { let fn_ty = ty::node_id_to_type(tcx, it.id); check_fn_deprecated_modes( - tcx, fn_ty, f.decl, ty.span, it.id) + tcx, fn_ty, *decl, ty.span, it.id) } _ => () } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index abe8a64fea5..07de9987096 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -146,63 +146,55 @@ pub enum deref_kind {deref_ptr(ptr_kind), deref_comp(comp_kind)} // pointer adjustment). pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> { match ty::get(t).sty { - ty::ty_uniq(*) | - ty::ty_evec(_, ty::vstore_uniq) | - ty::ty_estr(ty::vstore_uniq) => { - Some(deref_ptr(uniq_ptr)) - } - - ty::ty_fn(ref f) if (*f).meta.proto == ast::ProtoUniq => { - Some(deref_ptr(uniq_ptr)) - } - - ty::ty_rptr(r, mt) | - ty::ty_evec(mt, ty::vstore_slice(r)) => { - Some(deref_ptr(region_ptr(mt.mutbl, r))) - } - - ty::ty_estr(ty::vstore_slice(r)) => { - Some(deref_ptr(region_ptr(ast::m_imm, r))) - } + ty::ty_uniq(*) | + ty::ty_evec(_, ty::vstore_uniq) | + ty::ty_estr(ty::vstore_uniq) | + ty::ty_closure(ty::ClosureTy {sigil: ast::OwnedSigil, _}) => { + Some(deref_ptr(uniq_ptr)) + } - ty::ty_fn(ref f) if (*f).meta.proto == ast::ProtoBorrowed => { - Some(deref_ptr(region_ptr(ast::m_imm, (*f).meta.region))) - } + ty::ty_rptr(r, mt) | + ty::ty_evec(mt, ty::vstore_slice(r)) => { + Some(deref_ptr(region_ptr(mt.mutbl, r))) + } - ty::ty_box(mt) | - ty::ty_evec(mt, ty::vstore_box) => { - Some(deref_ptr(gc_ptr(mt.mutbl))) - } + ty::ty_estr(ty::vstore_slice(r)) | + ty::ty_closure(ty::ClosureTy {sigil: ast::BorrowedSigil, + region: r, _}) => { + Some(deref_ptr(region_ptr(ast::m_imm, r))) + } - ty::ty_estr(ty::vstore_box) => { - Some(deref_ptr(gc_ptr(ast::m_imm))) - } + ty::ty_box(mt) | + ty::ty_evec(mt, ty::vstore_box) => { + Some(deref_ptr(gc_ptr(mt.mutbl))) + } - ty::ty_fn(ref f) if (*f).meta.proto == ast::ProtoBox => { - Some(deref_ptr(gc_ptr(ast::m_imm))) - } + ty::ty_estr(ty::vstore_box) | + ty::ty_closure(ty::ClosureTy {sigil: ast::ManagedSigil, _}) => { + Some(deref_ptr(gc_ptr(ast::m_imm))) + } - ty::ty_ptr(*) => { - Some(deref_ptr(unsafe_ptr)) - } + ty::ty_ptr(*) => { + Some(deref_ptr(unsafe_ptr)) + } - ty::ty_enum(did, _) => { - Some(deref_comp(comp_variant(did))) - } + ty::ty_enum(did, _) => { + Some(deref_comp(comp_variant(did))) + } - ty::ty_struct(_, _) => { - Some(deref_comp(comp_anon_field)) - } + ty::ty_struct(_, _) => { + Some(deref_comp(comp_anon_field)) + } - ty::ty_evec(mt, ty::vstore_fixed(_)) => { - Some(deref_comp(comp_index(t, mt.mutbl))) - } + ty::ty_evec(mt, ty::vstore_fixed(_)) => { + Some(deref_comp(comp_index(t, mt.mutbl))) + } - ty::ty_estr(ty::vstore_fixed(_)) => { - Some(deref_comp(comp_index(t, m_imm))) - } + ty::ty_estr(ty::vstore_fixed(_)) => { + Some(deref_comp(comp_index(t, m_imm))) + } - _ => None + _ => None } } @@ -473,9 +465,9 @@ pub impl &mem_categorization_ctxt { ast::def_upvar(_, inner, fn_node_id, _) => { let ty = ty::node_id_to_type(self.tcx, fn_node_id); - let proto = ty::ty_fn_proto(ty); - match proto { - ast::ProtoBorrowed => { + let sigil = ty::ty_closure_sigil(ty); + match sigil { + ast::BorrowedSigil => { let upcmt = self.cat_def(id, span, expr_ty, *inner); @cmt_ { id:id, @@ -486,7 +478,7 @@ pub impl &mem_categorization_ctxt { ty:upcmt.ty } } - ast::ProtoUniq | ast::ProtoBox => { + ast::OwnedSigil | ast::ManagedSigil => { // FIXME #2152 allow mutation of moved upvars @cmt_ { id:id, @@ -497,11 +489,6 @@ pub impl &mem_categorization_ctxt { ty:expr_ty } } - ast::ProtoBare => { - self.tcx.sess.span_bug( - span, - fmt!("Upvar in a bare closure?")); - } } } diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs index f7943d6edc0..aaa3156e27c 100644 --- a/src/librustc/middle/moves.rs +++ b/src/librustc/middle/moves.rs @@ -474,7 +474,35 @@ impl VisitContext { } for opt_with.each |with_expr| { - self.consume_expr(*with_expr, visitor); + // If there are any fields whose type is move-by-default, + // then `with` is consumed, otherwise it is only read + let with_ty = ty::expr_ty(self.tcx, *with_expr); + let with_fields = match ty::get(with_ty).sty { + ty::ty_rec(ref f) => copy *f, + ty::ty_struct(did, ref substs) => { + ty::struct_fields(self.tcx, did, substs) + } + ref r => { + self.tcx.sess.span_bug( + with_expr.span, + fmt!("bad base expr type in record: %?", r)) + } + }; + + // The `with` expr must be consumed if it contains + // any fields which (1) were not explicitly + // specified and (2) have a type that + // moves-by-default: + let consume_with = with_fields.any(|tf| { + !fields.any(|f| f.node.ident == tf.ident) && + ty::type_implicitly_moves(self.tcx, tf.mt.ty) + }); + + if consume_with { + self.consume_expr(*with_expr, visitor); + } else { + self.use_expr(*with_expr, Read, visitor); + } } } @@ -786,9 +814,9 @@ impl VisitContext { let _indenter = indenter(); let fn_ty = ty::node_id_to_type(self.tcx, fn_expr_id); - let proto = ty::ty_fn_proto(fn_ty); + let sigil = ty::ty_closure_sigil(fn_ty); let freevars = freevars::get_freevars(self.tcx, fn_expr_id); - if proto == ProtoBorrowed { + if sigil == BorrowedSigil { // &fn() captures everything by ref at_vec::from_fn(freevars.len(), |i| { let fvar = &freevars[i]; diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 867cc7c686f..68e41b329e3 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -657,7 +657,7 @@ pub fn determine_rp_in_ty(ty: @ast::Ty, } } - ast::ty_fn(f) => { + ast::ty_closure(ref f) => { debug!("referenced fn type: %s", pprust::ty_to_str(ty, cx.sess.intr())); match f.region { @@ -668,7 +668,7 @@ pub fn determine_rp_in_ty(ty: @ast::Ty, } } None => { - if f.proto == ast::ProtoBorrowed && cx.anon_implies_rp { + if f.sigil == ast::BorrowedSigil && cx.anon_implies_rp { cx.add_rp(cx.item_id, cx.add_variance(rv_contravariant)); } @@ -732,18 +732,18 @@ pub fn determine_rp_in_ty(ty: @ast::Ty, } } - ast::ty_fn(f) => { + ast::ty_closure(@ast::TyClosure {decl: ref decl, _}) | + ast::ty_bare_fn(@ast::TyBareFn {decl: ref decl, _}) => { // 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 f.decl.inputs.each |a| { + for decl.inputs.each |a| { (visitor.visit_ty)(a.ty, cx, visitor); } } - visit::visit_ty_param_bounds(f.bounds, cx, visitor); - (visitor.visit_ty)(f.decl.output, cx, visitor); + (visitor.visit_ty)(decl.output, cx, visitor); } } diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index 99b5641ac6a..ebd6d9f9056 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -1652,7 +1652,7 @@ pub fn trans_match_inner(scope_cx: block, // insert bindings into the lllocals map and add cleanups bcx = insert_lllocals(bcx, *arm_data, true); - bcx = controlflow::trans_block(bcx, arm_data.arm.body, dest); + bcx = controlflow::trans_block(bcx, &arm_data.arm.body, dest); bcx = trans_block_cleanups(bcx, block_cleanups(arm_data.bodycx)); arm_cxs.push(bcx); } diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index a1f863332bd..588e2916e47 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -613,7 +613,7 @@ pub fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t, let ccx = cx.ccx(); let mut cx = cx; match ty::get(fn_ty).sty { - ty::ty_fn(ref fn_ty) => { + ty::ty_bare_fn(ref fn_ty) => { let mut j = 0u; let v_id = variant.id; for vec::each(fn_ty.sig.inputs) |a| { @@ -777,10 +777,10 @@ pub fn trans_external_path(ccx: @crate_ctxt, did: ast::def_id, t: ty::t) -> ValueRef { let name = csearch::get_symbol(ccx.sess.cstore, did).to_managed(); // Sad match ty::get(t).sty { - ty::ty_fn(_) => { + ty::ty_bare_fn(_) | ty::ty_closure(_) => { let llty = type_of_fn_from_ty(ccx, t); return get_extern_fn(ccx.externs, ccx.llmod, name, - lib::llvm::CCallConv, llty); + lib::llvm::CCallConv, llty); } _ => { let llty = type_of(ccx, t); @@ -1363,7 +1363,7 @@ pub fn with_scope_datumblock(bcx: block, opt_node_info: Option<node_info>, DatumBlock {bcx: leave_block(bcx, scope_cx), datum: datum} } -pub fn block_locals(b: ast::blk, it: fn(@ast::local)) { +pub fn block_locals(b: &ast::blk, it: fn(@ast::local)) { for vec::each(b.node.stmts) |s| { match s.node { ast::stmt_decl(d, _) => { @@ -1727,8 +1727,8 @@ pub enum self_arg { impl_self(ty::t), impl_owned_self(ty::t), no_self, } // returned. pub fn trans_closure(ccx: @crate_ctxt, +path: path, - decl: ast::fn_decl, - body: ast::blk, + decl: &ast::fn_decl, + body: &ast::blk, llfndecl: ValueRef, ty_self: self_arg, +param_substs: Option<param_substs>, @@ -1791,8 +1791,8 @@ pub fn trans_closure(ccx: @crate_ctxt, // function. pub fn trans_fn(ccx: @crate_ctxt, +path: path, - decl: ast::fn_decl, - body: ast::blk, + decl: &ast::fn_decl, + body: &ast::blk, llfndecl: ValueRef, ty_self: self_arg, +param_substs: Option<param_substs>, @@ -1935,7 +1935,7 @@ pub fn trans_tuple_struct(ccx: @crate_ctxt, pub fn trans_struct_dtor(ccx: @crate_ctxt, +path: path, - body: ast::blk, + body: &ast::blk, dtor_id: ast::node_id, +psubsts: Option<param_substs>, hash_id: Option<mono_id>, @@ -1966,8 +1966,9 @@ pub fn trans_struct_dtor(ccx: @crate_ctxt, ccx.monomorphized.insert(*h_id, lldecl); } /* Translate the dtor body */ - trans_fn(ccx, path, ast_util::dtor_dec(), - body, lldecl, impl_self(class_ty), psubsts, dtor_id, None); + let decl = ast_util::dtor_dec(); + trans_fn(ccx, path, &decl, body, lldecl, + impl_self(class_ty), psubsts, dtor_id, None); lldecl } @@ -2013,20 +2014,19 @@ pub fn trans_item(ccx: @crate_ctxt, item: ast::item) { _ => die!(~"trans_item"), }; match /*bad*/copy item.node { - // XXX: Bad copies. - ast::item_fn(copy decl, purity, copy tps, ref body) => { + ast::item_fn(ref decl, purity, ref tps, ref body) => { if purity == ast::extern_fn { let llfndecl = get_item_val(ccx, item.id); foreign::trans_foreign_fn(ccx, vec::append( /*bad*/copy *path, ~[path_name(item.ident)]), - decl, (*body), llfndecl, item.id); + decl, body, llfndecl, item.id); } else if tps.is_empty() { let llfndecl = get_item_val(ccx, item.id); trans_fn(ccx, vec::append(/*bad*/copy *path, ~[path_name(item.ident)]), - decl, (*body), llfndecl, no_self, None, item.id, None); + decl, body, llfndecl, no_self, None, item.id, None); } else { for vec::each((*body).node.stmts) |stmt| { match stmt.node { @@ -2078,7 +2078,7 @@ pub fn trans_struct_def(ccx: @crate_ctxt, struct_def: @ast::struct_def, id: ast::node_id) { // Translate the destructor. do option::iter(&struct_def.dtor) |dtor| { - trans_struct_dtor(ccx, /*bad*/copy *path, dtor.node.body, + trans_struct_dtor(ccx, /*bad*/copy *path, &dtor.node.body, dtor.node.id, None, None, local_def(id)); }; diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index 4bd5ae969f2..4af74b3623f 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -627,18 +627,17 @@ pub fn trans_arg_expr(bcx: block, Some(_) => { match arg_expr.node { ast::expr_loop_body( - // XXX: Bad copy. - blk@@ast::expr { - node: ast::expr_fn_block(copy decl, ref body), + blk @ @ast::expr { + node: ast::expr_fn_block(ref decl, ref body), _ }) => { let scratch_ty = expr_ty(bcx, arg_expr); let scratch = alloc_ty(bcx, scratch_ty); let arg_ty = expr_ty(bcx, arg_expr); - let proto = ty::ty_fn_proto(arg_ty); + let sigil = ty::ty_closure_sigil(arg_ty); let bcx = closure::trans_expr_fn( - bcx, proto, decl, /*bad*/copy *body, arg_expr.id, + bcx, sigil, decl, body, arg_expr.id, blk.id, Some(ret_flag), expr::SaveIn(scratch)); DatumBlock {bcx: bcx, datum: Datum {val: scratch, diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index 62e00100d6c..c70425da9fa 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -160,7 +160,7 @@ pub fn mk_closure_tys(tcx: ty::ctxt, return cdata_ty; } -pub fn allocate_cbox(bcx: block, proto: ast::Proto, cdata_ty: ty::t) +pub fn allocate_cbox(bcx: block, sigil: ast::Sigil, cdata_ty: ty::t) -> Result { let _icx = bcx.insn_ctxt("closure::allocate_cbox"); let ccx = bcx.ccx(), tcx = ccx.tcx; @@ -176,23 +176,19 @@ pub fn allocate_cbox(bcx: block, proto: ast::Proto, cdata_ty: ty::t) } // Allocate and initialize the box: - match proto { - ast::ProtoBox => { + match sigil { + ast::ManagedSigil => { malloc_raw(bcx, cdata_ty, heap_shared) } - ast::ProtoUniq => { + ast::OwnedSigil => { malloc_raw(bcx, cdata_ty, heap_exchange) } - ast::ProtoBorrowed => { + ast::BorrowedSigil => { 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)) - } } } @@ -208,7 +204,7 @@ pub type closure_result = { // Otherwise, it is stack allocated and copies pointers to the upvars. pub fn store_environment(bcx: block, bound_values: ~[EnvValue], - proto: ast::Proto) -> closure_result { + sigil: ast::Sigil) -> closure_result { let _icx = bcx.insn_ctxt("closure::store_environment"); let ccx = bcx.ccx(), tcx = ccx.tcx; @@ -217,7 +213,7 @@ pub fn store_environment(bcx: block, let cdata_ty = mk_closure_tys(tcx, copy bound_values); // allocate closure in the heap - let Result {bcx: bcx, val: llbox} = allocate_cbox(bcx, proto, cdata_ty); + let Result {bcx: bcx, val: llbox} = allocate_cbox(bcx, sigil, cdata_ty); let mut temp_cleanups = ~[]; // cbox_ty has the form of a tuple: (a, b, c) we want a ptr to a @@ -265,7 +261,7 @@ pub fn store_environment(bcx: block, // collects the upvars and packages them up for store_environment. pub fn build_closure(bcx0: block, cap_vars: &[moves::CaptureVar], - proto: ast::Proto, + sigil: ast::Sigil, 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 @@ -279,7 +275,7 @@ pub fn build_closure(bcx0: block, let datum = expr::trans_local_var(bcx, cap_var.def); match cap_var.mode { moves::CapRef => { - assert proto == ast::ProtoBorrowed; + assert sigil == ast::BorrowedSigil; env_vals.push(EnvValue {action: EnvRef, datum: datum}); } @@ -316,7 +312,7 @@ pub fn build_closure(bcx0: block, datum: ret_datum}); } - return store_environment(bcx, env_vals, proto); + return store_environment(bcx, env_vals, sigil); } // Given an enclosing block context, a new function context, a closure type, @@ -326,7 +322,7 @@ pub fn load_environment(fcx: fn_ctxt, cdata_ty: ty::t, cap_vars: &[moves::CaptureVar], load_ret_handle: bool, - proto: ast::Proto) { + sigil: ast::Sigil) { let _icx = fcx.insn_ctxt("closure::load_environment"); let llloadenv = match fcx.llloadenv { @@ -352,9 +348,9 @@ pub fn load_environment(fcx: fn_ctxt, let mut i = 0u; for cap_vars.each |cap_var| { let mut upvarptr = GEPi(bcx, llcdata, [0u, i]); - match proto { - ast::ProtoBorrowed => { upvarptr = Load(bcx, upvarptr); } - ast::ProtoBox | ast::ProtoUniq | ast::ProtoBare => {} + match sigil { + ast::BorrowedSigil => { upvarptr = Load(bcx, upvarptr); } + ast::ManagedSigil | ast::OwnedSigil => {} } let def_id = ast_util::def_id_of_def(cap_var.def); fcx.llupvars.insert(def_id.node, upvarptr); @@ -369,9 +365,9 @@ pub fn load_environment(fcx: fn_ctxt, } pub fn trans_expr_fn(bcx: block, - proto: ast::Proto, - +decl: ast::fn_decl, - +body: ast::blk, + sigil: ast::Sigil, + decl: &ast::fn_decl, + body: &ast::blk, outer_id: ast::node_id, user_id: ast::node_id, is_loop_body: Option<Option<ValueRef>>, @@ -381,7 +377,7 @@ pub fn trans_expr_fn(bcx: block, * * Translates the body of a closure expression. * - * - `proto` + * - `sigil` * - `decl` * - `body` * - `outer_id`: The id of the closure expression with the correct @@ -417,18 +413,18 @@ pub fn trans_expr_fn(bcx: block, ~"expr_fn"); let llfn = decl_internal_cdecl_fn(ccx.llmod, s, llfnty); - let Result {bcx: bcx, val: closure} = match proto { - ast::ProtoBorrowed | ast::ProtoBox | ast::ProtoUniq => { + let Result {bcx: bcx, val: closure} = match sigil { + ast::BorrowedSigil | ast::ManagedSigil | ast::OwnedSigil => { let cap_vars = ccx.maps.capture_map.get(&user_id); let ret_handle = match is_loop_body {Some(x) => x, None => None}; - let {llbox, cdata_ty, bcx} = build_closure(bcx, cap_vars, proto, + let {llbox, cdata_ty, bcx} = build_closure(bcx, cap_vars, sigil, ret_handle); trans_closure(ccx, sub_path, decl, body, llfn, no_self, /*bad*/ copy bcx.fcx.param_substs, user_id, None, |fcx| load_environment(fcx, cdata_ty, cap_vars, - ret_handle.is_some(), proto), + ret_handle.is_some(), sigil), |bcx| { if is_loop_body.is_some() { Store(bcx, C_bool(true), bcx.fcx.llretptr); @@ -436,34 +432,30 @@ pub fn trans_expr_fn(bcx: block, }); rslt(bcx, llbox) } - ast::ProtoBare => { - trans_closure(ccx, sub_path, decl, body, llfn, no_self, None, - user_id, None, |_fcx| { }, |_bcx| { }); - rslt(bcx, C_null(T_opaque_box_ptr(ccx))) - } }; fill_fn_pair(bcx, dest_addr, llfn, closure); return bcx; } -pub fn make_fn_glue(cx: block, - v: ValueRef, - t: ty::t, - glue_fn: fn@(block, v: ValueRef, t: ty::t) -> block) - -> block { - let _icx = cx.insn_ctxt("closure::make_fn_glue"); +pub fn make_closure_glue( + cx: block, + v: ValueRef, + t: ty::t, + glue_fn: fn@(block, v: ValueRef, t: ty::t) -> block) -> block +{ + let _icx = cx.insn_ctxt("closure::make_closure_glue"); let bcx = cx; let tcx = cx.tcx(); - let proto = ty::ty_fn_proto(t); - match proto { - ast::ProtoBare | ast::ProtoBorrowed => bcx, - ast::ProtoUniq | ast::ProtoBox => { + let sigil = ty::ty_closure_sigil(t); + match sigil { + ast::BorrowedSigil => bcx, + ast::OwnedSigil | ast::ManagedSigil => { 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); + let closure_ty = ty::mk_opaque_closure_ptr(tcx, sigil); glue_fn(bcx, box_cell_v, closure_ty) } } @@ -472,20 +464,20 @@ pub fn make_fn_glue(cx: block, pub fn make_opaque_cbox_take_glue( bcx: block, - proto: ast::Proto, + sigil: ast::Sigil, cboxptr: ValueRef) // ptr to ptr to the opaque closure -> block { // Easy cases: let _icx = bcx.insn_ctxt("closure::make_opaque_cbox_take_glue"); - match proto { - ast::ProtoBare | ast::ProtoBorrowed => { + match sigil { + ast::BorrowedSigil => { return bcx; } - ast::ProtoBox => { + ast::ManagedSigil => { glue::incr_refcnt_of_boxed(bcx, Load(bcx, cboxptr)); return bcx; } - ast::ProtoUniq => { + ast::OwnedSigil => { /* hard case: fallthrough to code below */ } } @@ -531,36 +523,36 @@ pub fn make_opaque_cbox_take_glue( pub fn make_opaque_cbox_drop_glue( bcx: block, - proto: ast::Proto, + sigil: ast::Sigil, cboxptr: ValueRef) // ptr to the opaque closure -> block { let _icx = bcx.insn_ctxt("closure::make_opaque_cbox_drop_glue"); - match proto { - ast::ProtoBare | ast::ProtoBorrowed => bcx, - ast::ProtoBox => { + match sigil { + ast::BorrowedSigil => bcx, + ast::ManagedSigil => { glue::decr_refcnt_maybe_free( bcx, Load(bcx, cboxptr), - ty::mk_opaque_closure_ptr(bcx.tcx(), proto)) + ty::mk_opaque_closure_ptr(bcx.tcx(), sigil)) } - ast::ProtoUniq => { + ast::OwnedSigil => { glue::free_ty( bcx, cboxptr, - ty::mk_opaque_closure_ptr(bcx.tcx(), proto)) + ty::mk_opaque_closure_ptr(bcx.tcx(), sigil)) } } } pub fn make_opaque_cbox_free_glue( bcx: block, - proto: ast::Proto, + sigil: ast::Sigil, cbox: ValueRef) // ptr to ptr to the opaque closure -> block { let _icx = bcx.insn_ctxt("closure::make_opaque_cbox_free_glue"); - match proto { - ast::ProtoBare | ast::ProtoBorrowed => { + match sigil { + ast::BorrowedSigil => { return bcx; } - ast::ProtoBox | ast::ProtoUniq => { + ast::ManagedSigil | ast::OwnedSigil => { /* hard cases: fallthrough to code below */ } } @@ -580,10 +572,10 @@ pub fn make_opaque_cbox_free_glue( abi::tydesc_field_drop_glue, None); // Free the ty descr (if necc) and the box itself - match proto { - ast::ProtoBox => glue::trans_free(bcx, cbox), - ast::ProtoUniq => glue::trans_unique_free(bcx, cbox), - ast::ProtoBare | ast::ProtoBorrowed => { + match sigil { + ast::ManagedSigil => glue::trans_free(bcx, cbox), + ast::OwnedSigil => glue::trans_unique_free(bcx, cbox), + ast::BorrowedSigil => { bcx.sess().bug(~"impossible") } } diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs index a1505dd2f11..0933eedd5e4 100644 --- a/src/librustc/middle/trans/controlflow.rs +++ b/src/librustc/middle/trans/controlflow.rs @@ -23,7 +23,7 @@ pub fn macros() { include!("macros.rs"); } -pub fn trans_block(bcx: block, b: ast::blk, dest: expr::Dest) -> block { +pub fn trans_block(bcx: block, b: &ast::blk, dest: expr::Dest) -> block { let _icx = bcx.insn_ctxt("trans_block"); let mut bcx = bcx; do block_locals(b) |local| { @@ -47,7 +47,7 @@ pub fn trans_block(bcx: block, b: ast::blk, dest: expr::Dest) -> block { pub fn trans_if(bcx: block, cond: @ast::expr, - thn: ast::blk, + thn: &ast::blk, els: Option<@ast::expr>, dest: expr::Dest) -> block { @@ -82,10 +82,10 @@ pub fn trans_if(bcx: block, match elexpr.node { ast::expr_if(_, _, _) => { let elseif_blk = ast_util::block_from_expr(elexpr); - trans_block(else_bcx_in, elseif_blk, dest) + trans_block(else_bcx_in, &elseif_blk, dest) } ast::expr_block(ref blk) => { - trans_block(else_bcx_in, (*blk), dest) + trans_block(else_bcx_in, blk, dest) } // would be nice to have a constraint on ifs _ => bcx.tcx().sess.bug(~"strange alternative in if") @@ -114,7 +114,7 @@ pub fn join_blocks(parent_bcx: block, in_cxs: ~[block]) -> block { return out; } -pub fn trans_while(bcx: block, cond: @ast::expr, body: ast::blk) -> block { +pub fn trans_while(bcx: block, cond: @ast::expr, body: &ast::blk) -> block { let _icx = bcx.insn_ctxt("trans_while"); let next_bcx = sub_block(bcx, ~"while next"); @@ -154,7 +154,7 @@ pub fn trans_while(bcx: block, cond: @ast::expr, body: ast::blk) -> block { } pub fn trans_loop(bcx:block, - body: ast::blk, + body: &ast::blk, opt_label: Option<ident>) -> block { let _icx = bcx.insn_ctxt("trans_loop"); diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 56833d373c5..f2da47eb0ec 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -475,10 +475,10 @@ fn trans_rvalue_stmt_unadjusted(bcx: block, expr: @ast::expr) -> block { return controlflow::trans_check_expr(bcx, expr, a, ~"Assertion"); } ast::expr_while(cond, ref body) => { - return controlflow::trans_while(bcx, cond, (*body)); + return controlflow::trans_while(bcx, cond, body); } ast::expr_loop(ref body, opt_label) => { - return controlflow::trans_loop(bcx, (*body), opt_label); + return controlflow::trans_loop(bcx, body, opt_label); } ast::expr_assign(dst, src) => { let src_datum = unpack_datum!( @@ -530,7 +530,7 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr, bcx.def(expr.id), dest); } ast::expr_if(cond, ref thn, els) => { - return controlflow::trans_if(bcx, cond, *thn, els, dest); + return controlflow::trans_if(bcx, cond, thn, els, dest); } ast::expr_match(discr, ref arms) => { return _match::trans_match(bcx, expr, discr, /*bad*/copy *arms, @@ -539,7 +539,7 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr, ast::expr_block(ref blk) => { return do base::with_scope(bcx, blk.info(), ~"block-expr body") |bcx| { - controlflow::trans_block(bcx, (*blk), dest) + controlflow::trans_block(bcx, blk, dest) }; } ast::expr_rec(ref fields, base) | @@ -562,58 +562,31 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr, ast::expr_vec(*) | ast::expr_repeat(*) => { return tvec::trans_fixed_vstore(bcx, expr, expr, dest); } - // XXX: Bad copy. - ast::expr_fn(proto, copy decl, ref body, _) => { - // Don't use this function for anything real. Use the one in - // astconv instead. - return closure::trans_expr_fn(bcx, proto, decl, - /*bad*/copy *body, - expr.id, expr.id, - None, dest); - } + ast::expr_fn(_, ref decl, ref body, _) | ast::expr_fn_block(ref decl, ref body) => { let expr_ty = expr_ty(bcx, expr); - match ty::get(expr_ty).sty { - 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, fn_ty.meta.proto, /*bad*/copy *decl, - /*bad*/copy *body, expr.id, expr.id, - None, dest); - } - _ => { - bcx.sess().impossible_case( - expr.span, "fn_block has body with a non-fn type"); - } - } + let sigil = ty::ty_closure_sigil(expr_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, sigil, decl, body, + expr.id, expr.id, + None, dest); } ast::expr_loop_body(blk) => { - match ty::get(expr_ty(bcx, expr)).sty { - ty::ty_fn(ref fn_ty) => { - match blk.node { - ast::expr_fn_block(copy decl, ref body) => { - return closure::trans_expr_fn( - bcx, - fn_ty.meta.proto, - decl, - /*bad*/copy *body, - expr.id, - blk.id, - Some(None), - dest); - } - _ => { - bcx.sess().impossible_case( - expr.span, - "loop_body has the wrong kind of contents") - } - } + let expr_ty = expr_ty(bcx, expr); + let sigil = ty::ty_closure_sigil(expr_ty); + match blk.node { + ast::expr_fn_block(ref decl, ref body) => { + return closure::trans_expr_fn(bcx, sigil, + decl, body, + expr.id, blk.id, + Some(None), dest); } _ => { bcx.sess().impossible_case( - expr.span, "loop_body has body with a non-fn type") + expr.span, + "loop_body has the wrong kind of contents") } } } diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index ae05ceb1ec5..bb14fce8053 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -31,7 +31,7 @@ use middle::trans::machine; use middle::trans::shape; use middle::trans::type_of::*; use middle::trans::type_of; -use middle::ty::{FnTyBase, FnMeta, FnSig, arg}; +use middle::ty::{FnSig, arg}; use util::ppaux::ty_to_str; use core::libc::c_uint; @@ -66,10 +66,8 @@ 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)).sty { - ty::ty_fn(ref fn_ty) => { - let llargtys = type_of_explicit_args( - ccx, - fn_ty.sig.inputs); + ty::ty_bare_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) } @@ -541,12 +539,11 @@ pub fn trans_intrinsic(ccx: @crate_ctxt, 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: ast::ProtoBorrowed, - onceness: ast::Many, - region: ty::re_bound(ty::br_anon(0)), - bounds: @~[]}, + let fty = ty::mk_closure(bcx.tcx(), ty::ClosureTy { + purity: ast::impure_fn, + sigil: ast::BorrowedSigil, + onceness: ast::Many, + region: ty::re_bound(ty::br_anon(0)), sig: FnSig {inputs: ~[arg {mode: ast::expl(ast::by_copy), ty: star_u8}], output: ty::mk_nil(bcx.tcx())} @@ -843,14 +840,14 @@ pub fn trans_intrinsic(ccx: @crate_ctxt, pub fn trans_foreign_fn(ccx: @crate_ctxt, +path: ast_map::path, - decl: ast::fn_decl, - body: ast::blk, + decl: &ast::fn_decl, + body: &ast::blk, llwrapfn: ValueRef, id: ast::node_id) { let _icx = ccx.insn_ctxt("foreign::build_foreign_fn"); fn build_rust_fn(ccx: @crate_ctxt, +path: ast_map::path, - decl: ast::fn_decl, body: ast::blk, + decl: &ast::fn_decl, body: &ast::blk, id: ast::node_id) -> ValueRef { let _icx = ccx.insn_ctxt("foreign::foreign::build_rust_fn"); let t = ty::node_id_to_type(ccx.tcx, id); diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index 9909980fb7e..564460fd88e 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -172,7 +172,8 @@ pub fn simplified_glue_type(tcx: ty::ctxt, field: uint, t: ty::t) -> ty::t { if field == abi::tydesc_field_free_glue { match ty::get(t).sty { - ty::ty_fn(*) | + ty::ty_bare_fn(*) | + ty::ty_closure(*) | ty::ty_box(*) | ty::ty_opaque_box | ty::ty_uniq(*) | @@ -419,8 +420,8 @@ pub fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) { tvec::expand_boxed_vec_ty(bcx.tcx(), t)); return; } - ty::ty_fn(_) => { - closure::make_fn_glue(bcx, v, t, free_ty) + ty::ty_closure(_) => { + closure::make_closure_glue(bcx, v, t, free_ty) } ty::ty_opaque_closure_ptr(ck) => { closure::make_opaque_cbox_free_glue(bcx, ck, v) @@ -528,8 +529,8 @@ pub fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) { } } } - ty::ty_fn(_) => { - closure::make_fn_glue(bcx, v0, t, drop_ty) + ty::ty_closure(_) => { + closure::make_closure_glue(bcx, v0, t, drop_ty) } ty::ty_trait(_, _, ty::vstore_box) => { let llbox = Load(bcx, GEPi(bcx, v0, [0u, 1u])); @@ -594,8 +595,8 @@ pub fn make_take_glue(bcx: block, v: ValueRef, t: ty::t) { | ty::ty_estr(ty::vstore_slice(_)) => { bcx } - ty::ty_fn(_) => { - closure::make_fn_glue(bcx, v, t, take_ty) + ty::ty_closure(_) => { + closure::make_closure_glue(bcx, v, t, take_ty) } ty::ty_trait(_, _, ty::vstore_box) => { let llbox = Load(bcx, GEPi(bcx, v, [0u, 1u])); diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs index 4466e4e1b28..c094db4ecca 100644 --- a/src/librustc/middle/trans/inline.rs +++ b/src/librustc/middle/trans/inline.rs @@ -108,8 +108,8 @@ pub fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id, }; trans_fn(ccx, path, - mth.decl, - mth.body, + &mth.decl, + &mth.body, llfn, self_kind, None, diff --git a/src/librustc/middle/trans/machine.rs b/src/librustc/middle/trans/machine.rs index e76176218b7..828b5619390 100644 --- a/src/librustc/middle/trans/machine.rs +++ b/src/librustc/middle/trans/machine.rs @@ -34,8 +34,11 @@ pub fn simplify_type(tcx: ty::ctxt, typ: ty::t) -> ty::t { ty::ty_box(_) | ty::ty_opaque_box | ty::ty_uniq(_) | ty::ty_evec(_, ty::vstore_uniq) | ty::ty_evec(_, ty::vstore_box) | ty::ty_estr(ty::vstore_uniq) | ty::ty_estr(ty::vstore_box) | - ty::ty_ptr(_) | ty::ty_rptr(_,_) => nilptr(tcx), - ty::ty_fn(_) => ty::mk_tup(tcx, ~[nilptr(tcx), nilptr(tcx)]), + ty::ty_ptr(_) | ty::ty_rptr(*) => nilptr(tcx), + + ty::ty_bare_fn(*) | // FIXME(#4804) Bare fn repr + ty::ty_closure(*) => ty::mk_tup(tcx, ~[nilptr(tcx), nilptr(tcx)]), + ty::ty_evec(_, ty::vstore_slice(_)) | ty::ty_estr(ty::vstore_slice(_)) => { ty::mk_tup(tcx, ~[nilptr(tcx), ty::mk_int(tcx)]) diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index d751b8f9208..1d48d2dde6b 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -142,8 +142,8 @@ pub fn trans_method(ccx: @crate_ctxt, // generate the actual code trans_fn(ccx, path, - method.decl, - method.body, + &method.decl, + &method.body, llfn, self_arg, param_substs, @@ -822,7 +822,7 @@ pub fn make_impl_vtable(ccx: @crate_ctxt, let has_tps = (*ty::lookup_item_type(ccx.tcx, impl_id).bounds).len() > 0u; make_vtable(ccx, vec::map(*ty::trait_methods(tcx, trt_id), |im| { let fty = ty::subst_tps(tcx, substs, None, - ty::mk_fn(tcx, copy im.fty)); + ty::mk_bare_fn(tcx, copy im.fty)); if (*im.tps).len() > 0u || ty::type_has_self(fty) { debug!("(making impl vtable) method has self or type params: %s", tcx.sess.str_of(im.ident)); diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index 5873d0a76d9..b09a41f2b7f 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -26,7 +26,7 @@ use middle::trans::shape; use middle::trans::type_of::type_of_fn_from_ty; use middle::trans::type_of; use middle::trans::type_use; -use middle::ty::{FnTyBase, FnMeta, FnSig}; +use middle::ty::{FnSig}; use middle::typeck; use core::option; @@ -166,12 +166,12 @@ pub fn monomorphic_fn(ccx: @crate_ctxt, let lldecl = match map_node { ast_map::node_item(i@@ast::item { // XXX: Bad copy. - node: ast::item_fn(copy decl, _, _, ref body), + node: ast::item_fn(ref decl, _, _, ref body), _ }, _) => { let d = mk_lldecl(); set_inline_hint_if_appr(/*bad*/copy i.attrs, d); - trans_fn(ccx, pt, decl, *body, d, no_self, psubsts, fn_id.node, None); + trans_fn(ccx, pt, decl, body, d, no_self, psubsts, fn_id.node, None); d } ast_map::node_item(*) => { @@ -224,7 +224,7 @@ pub fn monomorphic_fn(ccx: @crate_ctxt, None => ccx.sess.span_bug(dtor.span, ~"Bad self ty in \ dtor") }; - trans_struct_dtor(ccx, /*bad*/copy *pt, dtor.node.body, + trans_struct_dtor(ccx, /*bad*/copy *pt, &dtor.node.body, dtor.node.id, psubsts, Some(hash_id), parent_id) } ast_map::node_trait_method(@ast::provided(mth), _, pt) => { @@ -267,31 +267,34 @@ pub fn monomorphic_fn(ccx: @crate_ctxt, pub fn normalize_for_monomorphization(tcx: ty::ctxt, ty: ty::t) -> Option<ty::t> { // FIXME[mono] could do this recursively. is that worthwhile? (#2529) - match ty::get(ty).sty { + return match ty::get(ty).sty { ty::ty_box(*) => { Some(ty::mk_opaque_box(tcx)) } - ty::ty_fn(ref fty) => { - Some(ty::mk_fn( + ty::ty_bare_fn(_) => { + Some(ty::mk_bare_fn( tcx, - FnTyBase {meta: FnMeta {purity: ast::impure_fn, - proto: fty.meta.proto, - onceness: ast::Many, - region: ty::re_static, - bounds: @~[]}, - sig: FnSig {inputs: ~[], - output: ty::mk_nil(tcx)}})) + ty::BareFnTy { + purity: ast::impure_fn, + abi: ast::RustAbi, + sig: FnSig {inputs: ~[], + output: ty::mk_nil(tcx)}})) } - ty::ty_trait(_, _, _) => { - Some(ty::mk_fn( - tcx, - FnTyBase {meta: FnMeta {purity: ast::impure_fn, - proto: ast::ProtoBox, - onceness: ast::Many, - region: ty::re_static, - bounds: @~[]}, - sig: FnSig {inputs: ~[], - output: ty::mk_nil(tcx)}})) + ty::ty_closure(ref fty) => { + Some(normalized_closure_ty(tcx, fty.sigil)) + } + ty::ty_trait(_, _, ref vstore) => { + let sigil = match *vstore { + ty::vstore_uniq => ast::OwnedSigil, + ty::vstore_box => ast::ManagedSigil, + ty::vstore_slice(_) => ast::BorrowedSigil, + ty::vstore_fixed(*) => { + tcx.sess.bug(fmt!("ty_trait with vstore_fixed")); + } + }; + + // Traits have the same runtime representation as closures. + Some(normalized_closure_ty(tcx, sigil)) } ty::ty_ptr(_) => { Some(ty::mk_uint(tcx)) @@ -299,6 +302,20 @@ pub fn normalize_for_monomorphization(tcx: ty::ctxt, _ => { None } + }; + + fn normalized_closure_ty(tcx: ty::ctxt, + sigil: ast::Sigil) -> ty::t + { + ty::mk_closure( + tcx, + ty::ClosureTy { + purity: ast::impure_fn, + sigil: sigil, + onceness: ast::Many, + region: ty::re_static, + sig: ty::FnSig {inputs: ~[], + output: ty::mk_nil(tcx)}}) } } diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index 7380fa2e562..9466099904c 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -86,9 +86,8 @@ pub impl reflector { tcx.sess.ident_of(~"visit_" + ty_name), *self.visitor_methods).expect(fmt!("Couldn't find visit method \ for %s", ty_name)); - let mth_ty = ty::mk_fn( - tcx, - /*bad*/copy self.visitor_methods[mth_idx].fty); + let mth_ty = + ty::mk_bare_fn(tcx, copy self.visitor_methods[mth_idx].fty); let v = self.visitor_val; debug!("passing %u args:", vec::len(args)); let bcx = self.bcx; @@ -211,39 +210,33 @@ pub impl reflector { } } + // FIXME (#2594): fetch constants out of intrinsic + // FIXME (#4809): visitor should break out bare fns from other fns + ty::ty_closure(ref fty) => { + let pureval = ast_purity_constant(fty.purity); + let sigilval = ast_sigil_constant(fty.sigil); + let retval = if ty::type_is_bot(fty.sig.output) {0u} else {1u}; + let extra = ~[self.c_uint(pureval), + self.c_uint(sigilval), + self.c_uint(vec::len(fty.sig.inputs)), + self.c_uint(retval)]; + self.visit(~"enter_fn", copy extra); // XXX: Bad copy. + self.visit_sig(retval, &fty.sig); + self.visit(~"leave_fn", extra); + } + // FIXME (#2594): fetch constants out of intrinsic:: for the // numbers. - 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 = ast_proto_constant(fty.meta.proto); + ty::ty_bare_fn(ref fty) => { + let pureval = ast_purity_constant(fty.purity); + let sigilval = 0u; let retval = if ty::type_is_bot(fty.sig.output) {0u} else {1u}; let extra = ~[self.c_uint(pureval), - self.c_uint(protoval), + self.c_uint(sigilval), self.c_uint(vec::len(fty.sig.inputs)), self.c_uint(retval)]; self.visit(~"enter_fn", copy extra); // XXX: Bad copy. - for fty.sig.inputs.eachi |i, arg| { - let modeval = match arg.mode { - ast::infer(_) => 0u, - ast::expl(e) => match e { - ast::by_ref => 1u, - ast::by_val => 2u, - ast::by_copy => 5u - } - }; - self.visit(~"fn_input", - ~[self.c_uint(i), - self.c_uint(modeval), - self.c_tydesc(arg.ty)]); - } - self.visit(~"fn_output", - ~[self.c_uint(retval), - self.c_tydesc(fty.sig.output)]); + self.visit_sig(retval, &fty.sig); self.visit(~"leave_fn", extra); } @@ -302,11 +295,31 @@ pub impl reflector { ty::ty_type => self.leaf(~"type"), ty::ty_opaque_box => self.leaf(~"opaque_box"), ty::ty_opaque_closure_ptr(ck) => { - let ckval = ast_proto_constant(ck); + let ckval = ast_sigil_constant(ck); self.visit(~"closure_ptr", ~[self.c_uint(ckval)]) } } } + + fn visit_sig(&self, retval: uint, sig: &ty::FnSig) { + for sig.inputs.eachi |i, arg| { + let modeval = match arg.mode { + ast::infer(_) => 0u, + ast::expl(e) => match e { + ast::by_ref => 1u, + ast::by_val => 2u, + ast::by_copy => 5u + } + }; + self.visit(~"fn_input", + ~[self.c_uint(i), + self.c_uint(modeval), + self.c_tydesc(arg.ty)]); + } + self.visit(~"fn_output", + ~[self.c_uint(retval), + self.c_tydesc(sig.output)]); + } } // Emit a sequence of calls to visit_ty::visit_foo @@ -332,12 +345,20 @@ pub fn emit_calls_to_trait_visit_ty(bcx: block, return final; } -pub fn ast_proto_constant(proto: ast::Proto) -> uint { - match proto { - ast::ProtoBare => 0u, - ast::ProtoUniq => 2u, - ast::ProtoBox => 3u, - ast::ProtoBorrowed => 4u, +pub fn ast_sigil_constant(sigil: ast::Sigil) -> uint { + match sigil { + ast::OwnedSigil => 2u, + ast::ManagedSigil => 3u, + ast::BorrowedSigil => 4u, + } +} + +pub fn ast_purity_constant(purity: ast::purity) -> uint { + match purity { + ast::pure_fn => 0u, + ast::unsafe_fn => 1u, + ast::impure_fn => 2u, + ast::extern_fn => 3u } } diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs index 99c47997df0..f727b5a2de0 100644 --- a/src/librustc/middle/trans/type_of.rs +++ b/src/librustc/middle/trans/type_of.rs @@ -59,7 +59,13 @@ pub fn type_of_fn(cx: @crate_ctxt, inputs: &[ty::arg], // Given a function type and a count of ty params, construct an llvm type pub fn type_of_fn_from_ty(cx: @crate_ctxt, fty: ty::t) -> TypeRef { - type_of_fn(cx, ty::ty_fn_args(fty), ty::ty_fn_ret(fty)) + match ty::get(fty).sty { + ty::ty_closure(ref f) => type_of_fn(cx, f.sig.inputs, f.sig.output), + ty::ty_bare_fn(ref f) => type_of_fn(cx, f.sig.inputs, f.sig.output), + _ => { + cx.sess.bug(~"type_of_fn_from_ty given non-closure, non-bare-fn") + } + } } pub fn type_of_non_gc_box(cx: @crate_ctxt, t: ty::t) -> TypeRef { @@ -170,7 +176,11 @@ pub fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef { // structs T_struct(~[T_struct(tys)]) } - ty::ty_fn(_) => T_fn_pair(cx, type_of_fn_from_ty(cx, t)), + + // FIXME(#4804) Bare fn repr + // ty::ty_bare_fn(_) => T_ptr(type_of_fn_from_ty(cx, t)), + ty::ty_bare_fn(_) => T_fn_pair(cx, type_of_fn_from_ty(cx, t)), + ty::ty_closure(_) => T_fn_pair(cx, type_of_fn_from_ty(cx, t)), ty::ty_trait(_, _, vstore) => T_opaque_trait(cx, vstore), ty::ty_type => T_ptr(cx.tydesc_type), ty::ty_tup(elts) => { diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs index 6b0d4e17c74..3fd334c2d15 100644 --- a/src/librustc/middle/trans/type_use.rs +++ b/src/librustc/middle/trans/type_use.rs @@ -69,8 +69,9 @@ pub fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint) let cx = {ccx: ccx, uses: vec::cast_to_mut(vec::from_elem(n_tps, 0u))}; match ty::get(ty::lookup_item_type(cx.ccx.tcx, fn_id).ty).sty { - ty::ty_fn(ref fn_ty) => { - for vec::each(fn_ty.sig.inputs) |arg| { + ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, _}) | + ty::ty_closure(ty::ClosureTy {sig: ref sig, _}) => { + for vec::each(sig.inputs) |arg| { match ty::resolved_mode(ccx.tcx, arg.mode) { by_val | by_copy => { type_needs(cx, use_repr, arg.ty); @@ -197,8 +198,12 @@ pub fn type_needs_inner(cx: ctx, it, we depend on the drop glue for T (we have to write the right tydesc into the result) */ - ty::ty_fn(_) | ty::ty_ptr(_) | ty::ty_rptr(_, _) - | ty::ty_trait(_, _, _) => false, + ty::ty_closure(*) | + ty::ty_bare_fn(*) | + ty::ty_ptr(_) | + ty::ty_rptr(_, _) | + ty::ty_trait(_, _, _) => false, + ty::ty_enum(did, ref substs) => { if option::is_none(&list::find(enums_seen, |id| *id == did)) { let seen = @Cons(did, enums_seen); @@ -287,15 +292,15 @@ pub 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)) { - 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); - } + match ty::ty_closure_sigil(ty::expr_ty(cx.ccx.tcx, e)) { + ast::OwnedSigil => {} + ast::BorrowedSigil | ast::ManagedSigil => { + for freevars::get_freevars(cx.ccx.tcx, e.id).each |fv| { + let node_id = ast_util::def_id_of_def(fv.def).node; + node_type_needs(cx, use_repr, node_id); + } + } } - } } expr_assign(val, _) | expr_swap(val, _) | expr_assign_op(_, val, _) | expr_ret(Some(val)) => { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 9905701e058..ef62fb3caf1 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[warn(deprecated_pattern)]; - use core::prelude::*; use driver::session; @@ -27,7 +25,7 @@ use middle; use session::Session; use util::ppaux::{note_and_explain_region, bound_region_to_str}; use util::ppaux::{region_to_str, explain_region, vstore_to_str}; -use util::ppaux::{ty_to_str, proto_ty_to_str, tys_to_str}; +use util::ppaux::{ty_to_str, tys_to_str}; use core::cast; use core::cmp; @@ -73,7 +71,7 @@ pub type param_bounds = @~[param_bound]; pub type method = { ident: ast::ident, tps: @~[param_bounds], - fty: FnTy, + fty: BareFnTy, self_ty: ast::self_ty_, vis: ast::visibility, def_id: ast::def_id @@ -344,22 +342,20 @@ pub pure fn type_contains_err(t: t) -> bool { pub pure fn type_def_id(t: t) -> Option<ast::def_id> { get(t).o_def_id } pub pure fn type_id(t: t) -> uint { get(t).id } -/** - * Meta information about a closure. - * - * - `purity` is the function's effect (pure, impure, unsafe). - * - `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. */ #[deriving_eq] -pub struct FnMeta { +pub struct BareFnTy { + purity: ast::purity, + abi: Abi, + sig: FnSig +} + +#[deriving_eq] +pub struct ClosureTy { purity: ast::purity, - proto: ast::Proto, + sigil: ast::Sigil, onceness: ast::Onceness, region: Region, - bounds: @~[param_bound] + sig: FnSig } /** @@ -374,25 +370,19 @@ pub struct FnSig { 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. */ -#[deriving_eq] -pub struct FnTyBase<M> { - meta: M, // Either FnMeta or FnVid - sig: FnSig // Types of arguments/return type +impl BareFnTy : to_bytes::IterBytes { + pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + to_bytes::iter_bytes_3(&self.purity, &self.abi, &self.sig, lsb0, f) + } } -impl<M: to_bytes::IterBytes> FnTyBase<M> : to_bytes::IterBytes { +impl ClosureTy : to_bytes::IterBytes { pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { - to_bytes::iter_bytes_2(&self.meta, &self.sig, lsb0, f) + to_bytes::iter_bytes_5(&self.purity, &self.sigil, &self.onceness, + &self.region, &self.sig, lsb0, f) } } -pub type FnTy = FnTyBase<FnMeta>; - #[deriving_eq] pub struct param_ty { idx: uint, @@ -491,6 +481,7 @@ pub struct substs { // NB: If you change this, you'll probably want to change the corresponding // AST structure in libsyntax/ast.rs as well. +#[deriving_eq] pub enum sty { ty_nil, ty_bot, @@ -506,7 +497,8 @@ pub enum sty { ty_ptr(mt), ty_rptr(Region, mt), ty_rec(~[field]), - ty_fn(FnTy), + ty_bare_fn(BareFnTy), + ty_closure(ClosureTy), ty_trait(def_id, substs, vstore), ty_struct(def_id, substs), ty_tup(~[t]), @@ -522,7 +514,7 @@ pub 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(ast::Proto), // ptr to env for fn, fn@, fn~ + ty_opaque_closure_ptr(Sigil), // ptr to env for fn, fn@, fn~ ty_unboxed_vec(mt), } @@ -546,8 +538,9 @@ pub enum type_err { terr_mismatch, terr_purity_mismatch(expected_found<purity>), terr_onceness_mismatch(expected_found<Onceness>), + terr_abi_mismatch(expected_found<ast::Abi>), terr_mutability, - terr_proto_mismatch(expected_found<ast::Proto>), + terr_sigil_mismatch(expected_found<ast::Sigil>), terr_box_mutability, terr_ptr_mutability, terr_ref_mutability, @@ -744,6 +737,15 @@ pub impl RegionVid : to_bytes::IterBytes { } } +pub fn kind_to_param_bounds(kind: Kind) -> param_bounds { + let mut bounds = ~[]; + if kind_can_be_copied(kind) { bounds.push(bound_copy); } + if kind_can_be_sent(kind) { bounds.push(bound_owned); } + else if kind_is_durable(kind) { bounds.push(bound_durable); } + if kind_is_const(kind) { bounds.push(bound_const); } + return @bounds; +} + pub fn param_bounds_to_kind(bounds: param_bounds) -> Kind { let mut kind = kind_noncopyable(); for vec::each(*bounds) |bound| { @@ -925,8 +927,12 @@ fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option<ast::def_id>) -> t { } &ty_rec(ref flds) => for flds.each |f| { flags |= get(f.mt.ty).flags; }, &ty_tup(ref ts) => for ts.each |tt| { flags |= get(*tt).flags; }, - &ty_fn(ref f) => { - flags |= rflags(f.meta.region); + &ty_bare_fn(ref f) => { + for f.sig.inputs.each |a| { flags |= get(a.ty).flags; } + flags |= get(f.sig.output).flags; + } + &ty_closure(ref f) => { + flags |= rflags(f.region); for f.sig.inputs.each |a| { flags |= get(a.ty).flags; } flags |= get(f.sig.output).flags; } @@ -1044,8 +1050,25 @@ pub fn mk_rec(cx: ctxt, +fs: ~[field]) -> t { mk_t(cx, ty_rec(fs)) } pub 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 -pub fn mk_fn(cx: ctxt, +fty: FnTy) -> t { mk_t(cx, ty_fn(fty)) } +pub fn mk_closure(cx: ctxt, +fty: ClosureTy) -> t { + mk_t(cx, ty_closure(fty)) +} + +pub fn mk_bare_fn(cx: ctxt, +fty: BareFnTy) -> t { + mk_t(cx, ty_bare_fn(fty)) +} + +pub fn mk_ctor_fn(cx: ctxt, input_tys: &[ty::t], output: ty::t) -> t { + let input_args = input_tys.map(|t| arg {mode: ast::expl(ast::by_copy), + ty: *t}); + mk_bare_fn(cx, + BareFnTy { + purity: ast::pure_fn, + abi: ast::RustAbi, + sig: FnSig {inputs: input_args, + output: output}}) +} + pub fn mk_trait(cx: ctxt, did: ast::def_id, +substs: substs, vstore: vstore) -> t { @@ -1074,8 +1097,8 @@ pub fn mk_param(cx: ctxt, n: uint, k: def_id) -> t { pub fn mk_type(cx: ctxt) -> t { mk_t(cx, ty_type) } -pub fn mk_opaque_closure_ptr(cx: ctxt, proto: ast::Proto) -> t { - mk_t(cx, ty_opaque_closure_ptr(proto)) +pub fn mk_opaque_closure_ptr(cx: ctxt, sigil: ast::Sigil) -> t { + mk_t(cx, ty_opaque_closure_ptr(sigil)) } pub fn mk_opaque_box(cx: ctxt) -> t { mk_t(cx, ty_opaque_box) } @@ -1097,13 +1120,11 @@ pub pure fn mach_sty(cfg: @session::config, t: t) -> sty { pub fn default_arg_mode_for_ty(tcx: ctxt, ty: ty::t) -> ast::rmode { // FIXME(#2202) --- We retain by-ref for fn& things to workaround a // memory leak that otherwise results when @fn is upcast to &fn. - if type_is_fn(ty) { - match ty_fn_proto(ty) { - ast::ProtoBorrowed => { - return ast::by_ref; - } - _ => {} + match ty::get(ty).sty { + ty::ty_closure(ClosureTy {sigil: ast::BorrowedSigil, _}) => { + return ast::by_ref; } + _ => {} } return if tcx.legacy_modes { if type_is_borrowed(ty) { @@ -1119,13 +1140,6 @@ pub fn default_arg_mode_for_ty(tcx: ctxt, ty: ty::t) -> ast::rmode { ast::by_copy }; - fn type_is_fn(ty: t) -> bool { - match get(ty).sty { - ty_fn(*) => true, - _ => false - } - } - fn type_is_borrowed(ty: t) -> bool { match ty::get(ty).sty { ty::ty_rptr(*) => true, @@ -1171,7 +1185,11 @@ pub fn maybe_walk_ty(ty: t, f: fn(t) -> bool) { for fields.each |fl| { maybe_walk_ty(fl.mt.ty, f); } } ty_tup(ts) => { for ts.each |tt| { maybe_walk_ty(*tt, f); } } - ty_fn(ref ft) => { + ty_bare_fn(ref ft) => { + for ft.sig.inputs.each |a| { maybe_walk_ty(a.ty, f); } + maybe_walk_ty(ft.sig.output, f); + } + ty_closure(ref ft) => { for ft.sig.inputs.each |a| { maybe_walk_ty(a.ty, f); } maybe_walk_ty(ft.sig.output, f); } @@ -1235,9 +1253,13 @@ fn fold_sty(sty: &sty, fldop: fn(t) -> t) -> sty { let new_ts = vec::map(ts, |tt| fldop(*tt)); ty_tup(new_ts) } - ty_fn(ref f) => { + ty_bare_fn(ref f) => { + let sig = fold_sig(&f.sig, fldop); + ty_bare_fn(BareFnTy {sig: sig, abi: f.abi, purity: f.purity}) + } + ty_closure(ref f) => { let sig = fold_sig(&f.sig, fldop); - ty_fn(FnTyBase {meta: f.meta, sig: sig}) + ty_closure(ClosureTy {sig: sig, ..copy *f}) } ty_rptr(r, tm) => { ty_rptr(r, mt {ty: fldop(tm.ty), mutbl: tm.mutbl}) @@ -1318,10 +1340,14 @@ pub 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(ref f) => { - ty::mk_fn(cx, FnTyBase {meta: FnMeta {region: fldr(f.meta.region), - ..f.meta}, - sig: fold_sig(&f.sig, fldfnt)}) + ty_bare_fn(ref f) => { + ty::mk_bare_fn(cx, BareFnTy {sig: fold_sig(&f.sig, fldfnt), + ..copy *f}) + } + ty_closure(ref f) => { + ty::mk_closure(cx, ClosureTy {region: fldr(f.region), + sig: fold_sig(&f.sig, fldfnt), + ..copy *f}) } ref sty => { fold_sty_to_ty(cx, sty, |t| fldt(t)) @@ -1329,30 +1355,6 @@ pub fn fold_regions_and_ty( } } -/* A little utility: it often happens that I have a `fn_ty`, - * but I want to use some function like `fold_regions_and_ty()` - * that is defined over all types. This utility converts to - * a full type and back. It's not the best way to do this (somewhat - * inefficient to do the conversion), it would be better to refactor - * all this folding business. However, I've been waiting on that - * until trait support is improved. */ -pub fn apply_op_on_t_to_ty_fn( - cx: ctxt, - f: &FnTy, - t_op: fn(t) -> t) -> FnTy -{ - let t0 = ty::mk_fn(cx, /*bad*/copy *f); - let t1 = t_op(t0); - match ty::get(t1).sty { - ty::ty_fn(copy f) => { - move f - } - _ => { - cx.sess.bug(~"`t_op` did not return a function type"); - } - } -} - // n.b. this function is intended to eventually replace fold_region() below, // that is why its name is so similar. pub fn fold_regions( @@ -1372,41 +1374,6 @@ pub fn fold_regions( do_fold(cx, ty, false, fldr) } -pub fn fold_region(cx: ctxt, t0: t, fldop: fn(Region, bool) -> Region) -> t { - fn do_fold(cx: ctxt, t0: t, under_r: bool, - fldop: fn(Region, bool) -> Region) -> t { - let tb = get(t0); - if !tbox_has_flag(tb, has_regions) { return t0; } - match tb.sty { - ty_rptr(r, mt {ty: t1, mutbl: m}) => { - let m_r = fldop(r, under_r); - let m_t1 = do_fold(cx, t1, true, fldop); - ty::mk_rptr(cx, m_r, mt {ty: m_t1, mutbl: m}) - } - ty_estr(vstore_slice(r)) => { - let m_r = fldop(r, under_r); - ty::mk_estr(cx, vstore_slice(m_r)) - } - ty_evec(mt {ty: t1, mutbl: m}, vstore_slice(r)) => { - let m_r = fldop(r, under_r); - let m_t1 = do_fold(cx, t1, true, fldop); - ty::mk_evec(cx, mt {ty: m_t1, mutbl: m}, vstore_slice(m_r)) - } - ty_fn(_) => { - // do not recurse into functions, which introduce fresh bindings - t0 - } - ref sty => { - do fold_sty_to_ty(cx, sty) |t| { - do_fold(cx, t, under_r, fldop) - } - } - } - } - - do_fold(cx, t0, false, fldop) -} - // Substitute *only* type parameters. Used in trans where regions are erased. pub fn subst_tps(cx: ctxt, tps: &[t], self_ty_opt: Option<t>, typ: t) -> t { if tps.len() == 0u && self_ty_opt.is_none() { return typ; } @@ -1529,7 +1496,9 @@ pub fn type_is_bool(ty: t) -> bool { get(ty).sty == ty_bool } pub fn type_is_structural(ty: t) -> bool { match get(ty).sty { - ty_rec(_) | ty_struct(*) | ty_tup(_) | ty_enum(*) | ty_fn(_) | + ty_rec(_) | ty_struct(*) | ty_tup(_) | ty_enum(*) | + ty_closure(_) | + ty_bare_fn(_) | // FIXME(#4804) Bare fn repr ty_trait(*) | ty_evec(_, vstore_fixed(_)) | ty_estr(vstore_fixed(_)) | ty_evec(_, vstore_slice(_)) | ty_estr(vstore_slice(_)) @@ -1715,10 +1684,11 @@ pub fn type_needs_drop(cx: ctxt, ty: t) -> bool { } accum } - ty_fn(ref fty) => { - match fty.meta.proto { - ast::ProtoBare | ast::ProtoBorrowed => false, - ast::ProtoBox | ast::ProtoUniq => true, + ty_bare_fn(*) => false, + ty_closure(ref fty) => { + match fty.sigil { + ast::BorrowedSigil => false, + ast::ManagedSigil | ast::OwnedSigil => true, } } }; @@ -1813,7 +1783,7 @@ pub enum Kind { kind_(u32) } const KIND_MASK_COPY : u32 = 0b000000000000000000000000001_u32; /// no shared box, borrowed ptr (must imply DURABLE) -const KIND_MASK_OWNED : u32 = 0b000000000000000000000000010_u32; +const KIND_MASK_OWNED : u32 = 0b000000000000000000000000010_u32; /// is durable (no borrowed ptrs) const KIND_MASK_DURABLE : u32 = 0b000000000000000000000000100_u32; @@ -1942,20 +1912,25 @@ pub pure fn kind_is_durable(k: Kind) -> bool { *k & KIND_MASK_DURABLE == KIND_MASK_DURABLE } -pub fn meta_kind(p: FnMeta) -> Kind { - match p.proto { // XXX consider the kind bounds! - ast::ProtoBare => { - kind_safe_for_default_mode_send() | kind_const() | kind_durable() - } - ast::ProtoBorrowed => { - kind_noncopyable() | kind_(KIND_MASK_DEFAULT_MODE) - } - ast::ProtoBox => { - kind_safe_for_default_mode() | kind_durable() - } - ast::ProtoUniq => { - kind_owned_copy() | kind_durable() - } +pure fn kind_is_const(k: Kind) -> bool { + *k & KIND_MASK_CONST == KIND_MASK_CONST +} + +fn closure_kind(cty: &ClosureTy) -> Kind { + let kind = match cty.sigil { + ast::BorrowedSigil => kind_implicitly_copyable(), + ast::ManagedSigil => kind_implicitly_copyable(), + ast::OwnedSigil => kind_owned_only() | kind_durable(), + }; + + let kind = match cty.region { + re_static => kind | kind_durable(), + _ => kind - kind_owned_only() - kind_durable() + }; + + match cty.onceness { + ast::Once => kind - kind_implicitly_copyable(), + ast::Many => kind } } @@ -2022,7 +1997,7 @@ pub fn type_kind_ext(cx: ctxt, ty: t, allow_ty_var: bool) -> Kind { let mut result = match /*bad*/copy get(ty).sty { // Scalar and unique types are sendable, constant, and owned ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) | - ty_ptr(_) => { + ty_bare_fn(_) | ty_ptr(_) => { kind_safe_for_default_mode_send() | kind_const() | kind_durable() } @@ -2035,8 +2010,9 @@ pub fn type_kind_ext(cx: ctxt, ty: t, allow_ty_var: bool) -> Kind { } } - // functions depend on the protocol - ty_fn(ref f) => meta_kind(f.meta), + ty_closure(ref c) => { + closure_kind(c) + } // Those with refcounts raise noncopyable to copyable, // lower sendable to copyable. Therefore just set result to copyable. @@ -2215,7 +2191,8 @@ fn type_size(cx: ctxt, ty: t) -> uint { ty_evec(_, vstore_slice(_)) | ty_estr(vstore_slice(_)) | - ty_fn(_) => { + ty_bare_fn(*) | + ty_closure(*) => { 2 } @@ -2297,7 +2274,8 @@ pub fn is_instantiable(cx: ctxt, r_ty: t) -> bool { ty_uint(_) | ty_float(_) | ty_estr(_) | - ty_fn(_) | + ty_bare_fn(_) | + ty_closure(_) | ty_infer(_) | ty_err | ty_param(_) | @@ -2472,9 +2450,9 @@ pub fn type_is_pod(cx: ctxt, ty: t) -> bool { match /*bad*/copy get(ty).sty { // Scalar types ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) | - ty_type | ty_ptr(_) => result = true, + ty_type | ty_ptr(_) | ty_bare_fn(_) => result = true, // Boxed types - ty_box(_) | ty_uniq(_) | ty_fn(_) | + ty_box(_) | ty_uniq(_) | ty_closure(_) | ty_estr(vstore_uniq) | ty_estr(vstore_box) | ty_evec(_, vstore_uniq) | ty_evec(_, vstore_box) | ty_trait(_, _, _) | ty_rptr(_,_) | ty_opaque_box => result = false, @@ -2700,14 +2678,9 @@ impl arg : to_bytes::IterBytes { } } -impl FnMeta : to_bytes::IterBytes { +impl Kind : to_bytes::IterBytes { pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { - to_bytes::iter_bytes_5(&self.purity, - &self.proto, - &self.onceness, - &self.region, - &self.bounds, - lsb0, f); + (**self).iter_bytes(lsb0, f) } } @@ -2755,7 +2728,7 @@ impl sty : to_bytes::IterBytes { ty_rec(ref fs) => to_bytes::iter_bytes_2(&11u8, fs, lsb0, f), - ty_fn(ref ft) => + ty_bare_fn(ref ft) => to_bytes::iter_bytes_2(&12u8, ft, lsb0, f), ty_self => 13u8.iter_bytes(lsb0, f), @@ -2789,7 +2762,10 @@ impl sty : to_bytes::IterBytes { ty_rptr(ref r, ref mt) => to_bytes::iter_bytes_3(&24u8, r, mt, lsb0, f), - ty_err => 25u8.iter_bytes(lsb0, f) + ty_err => 25u8.iter_bytes(lsb0, f), + + ty_closure(ref ct) => + to_bytes::iter_bytes_2(&26u8, ct, lsb0, f), } } } @@ -2823,36 +2799,48 @@ fn node_id_has_type_params(cx: ctxt, id: ast::node_id) -> bool { // Type accessors for substructures of types pub fn ty_fn_args(fty: t) -> ~[arg] { match get(fty).sty { - ty_fn(ref f) => /*bad*/copy f.sig.inputs, - _ => die!(~"ty_fn_args() called on non-fn type") + ty_bare_fn(ref f) => copy f.sig.inputs, + ty_closure(ref f) => copy f.sig.inputs, + ref s => { + die!(fmt!("ty_fn_args() called on non-fn type: %?", s)) + } } } -pub fn ty_fn_proto(fty: t) -> Proto { +pub fn ty_closure_sigil(fty: t) -> Sigil { match get(fty).sty { - ty_fn(ref f) => f.meta.proto, - _ => die!(~"ty_fn_proto() called on non-fn type") + ty_closure(ref f) => f.sigil, + ref s => { + die!(fmt!("ty_closure_sigil() called on non-closure type: %?", s)) + } } } pub fn ty_fn_purity(fty: t) -> ast::purity { match get(fty).sty { - ty_fn(ref f) => f.meta.purity, - _ => die!(~"ty_fn_purity() called on non-fn type") + ty_bare_fn(ref f) => f.purity, + ty_closure(ref f) => f.purity, + ref s => { + die!(fmt!("ty_fn_purity() called on non-fn type: %?", s)) + } } } pub pure fn ty_fn_ret(fty: t) -> t { match get(fty).sty { - ty_fn(ref f) => f.sig.output, - _ => die!(~"ty_fn_ret() called on non-fn type") + ty_bare_fn(ref f) => f.sig.output, + ty_closure(ref f) => f.sig.output, + ref s => { + die!(fmt!("ty_fn_ret() called on non-fn type: %?", s)) + } } } fn is_fn_ty(fty: t) -> bool { match get(fty).sty { - ty_fn(_) => true, - _ => false + ty_bare_fn(_) => true, + ty_closure(_) => true, + _ => false } } @@ -2874,17 +2862,17 @@ pub fn ty_region(ty: t) -> Region { } } -pub fn replace_fn_return_type(tcx: ctxt, fn_type: t, ret_type: t) -> t { +pub fn replace_closure_return_type(tcx: ctxt, fn_type: t, ret_type: t) -> t { /*! * * Returns a new function type based on `fn_type` but returning a value of * type `ret_type` instead. */ match ty::get(fn_type).sty { - ty::ty_fn(ref fty) => { - ty::mk_fn(tcx, FnTyBase { - meta: fty.meta, - sig: FnSig {output: ret_type, ..copy fty.sig} + ty::ty_closure(ref fty) => { + ty::mk_closure(tcx, ClosureTy { + sig: FnSig {output: ret_type, ..copy fty.sig}, + ..copy *fty }) } _ => { @@ -2900,12 +2888,6 @@ pub fn tys_in_fn_sig(sig: &FnSig) -> ~[t] { vec::append_one(sig.inputs.map(|a| a.ty), sig.output) } -// Just checks whether it's a fn that returns bool, -// not its purity. -pub fn is_pred_ty(fty: t) -> bool { - is_fn_ty(fty) && type_is_bool(ty_fn_ret(fty)) -} - // Type accessors for AST nodes pub fn block_ty(cx: ctxt, b: &ast::blk) -> t { return node_id_to_type(cx, b.node.id); @@ -3023,11 +3005,12 @@ pub fn expr_ty_adjusted(cx: ctxt, expr: @ast::expr) -> t { fn borrow_fn(cx: ctxt, expr: @ast::expr, autoref: &AutoRef, ty: ty::t) -> ty::t { match get(ty).sty { - ty_fn(ref fty) => { - ty::mk_fn(cx, FnTyBase {meta: FnMeta {proto: ProtoBorrowed, - region: autoref.region, - ..copy fty.meta}, - sig: copy fty.sig}) + ty_closure(ref fty) => { + ty::mk_closure(cx, ClosureTy { + sigil: BorrowedSigil, + region: autoref.region, + ..copy *fty + }) } ref s => { @@ -3417,7 +3400,8 @@ pub fn ty_sort_str(cx: ctxt, t: t) -> ~str { ty_ptr(_) => ~"*-ptr", ty_rptr(_, _) => ~"&-ptr", ty_rec(_) => ~"record", - ty_fn(_) => ~"fn", + ty_bare_fn(_) => ~"extern fn", + ty_closure(_) => ~"fn", ty_trait(id, _, _) => fmt!("trait %s", item_path_str(cx, id)), ty_struct(id, _) => fmt!("struct %s", item_path_str(cx, id)), ty_tup(_) => ~"tuple", @@ -3455,14 +3439,18 @@ pub fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str { fmt!("expected %s fn but found %s fn", values.expected.to_str(), values.found.to_str()) } + terr_abi_mismatch(values) => { + fmt!("expected %s fn but found %s fn", + values.expected.to_str(), values.found.to_str()) + } terr_onceness_mismatch(values) => { fmt!("expected %s fn but found %s fn", values.expected.to_str(), values.found.to_str()) } - terr_proto_mismatch(values) => { + terr_sigil_mismatch(values) => { fmt!("expected %s closure, found %s closure", - proto_ty_to_str(cx, values.expected, false), - proto_ty_to_str(cx, values.found, false)) + values.expected.to_str(), + values.found.to_str()) } terr_mutability => ~"values differ in mutability", terr_box_mutability => ~"boxed values differ in mutability", @@ -4232,13 +4220,10 @@ pub 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(ref fn_ty) => { - mk_fn(cx, FnTyBase { - meta: FnMeta { - region: ty::re_static, - ..fn_ty.meta - }, - sig: /*bad*/copy fn_ty.sig + ty_closure(ref closure_ty) => { + mk_closure(cx, ClosureTy { + region: ty::re_static, + ..copy *closure_ty }) } @@ -4310,13 +4295,13 @@ pub fn eval_repeat_count(tcx: ctxt, // Determine what purity to check a nested function under pub pure fn determine_inherited_purity(parent_purity: ast::purity, child_purity: ast::purity, - child_proto: ast::Proto) + child_sigil: ast::Sigil) -> 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 - match child_proto { - ast::ProtoBorrowed if child_purity == ast::impure_fn => parent_purity, + match child_sigil { + ast::BorrowedSigil if child_purity == ast::impure_fn => parent_purity, _ => child_purity } } @@ -4526,171 +4511,6 @@ impl bound_region : cmp::Eq { pure fn ne(&self, other: &bound_region) -> bool { !(*self).eq(other) } } -impl sty : cmp::Eq { - pure fn eq(&self, other: &sty) -> bool { - match (/*bad*/copy *self) { - ty_nil => { - match (*other) { - ty_nil => true, - _ => false - } - } - ty_bot => { - match (*other) { - ty_bot => true, - _ => false - } - } - ty_bool => { - match (*other) { - ty_bool => true, - _ => false - } - } - ty_int(e0a) => { - match (*other) { - ty_int(e0b) => e0a == e0b, - _ => false - } - } - ty_uint(e0a) => { - match (*other) { - ty_uint(e0b) => e0a == e0b, - _ => false - } - } - ty_float(e0a) => { - match (*other) { - ty_float(e0b) => e0a == e0b, - _ => false - } - } - ty_estr(e0a) => { - match (*other) { - ty_estr(e0b) => e0a == e0b, - _ => false - } - } - ty_enum(e0a, ref e1a) => { - match (*other) { - ty_enum(e0b, ref e1b) => e0a == e0b && (*e1a) == (*e1b), - _ => false - } - } - ty_box(e0a) => { - match (*other) { - ty_box(e0b) => e0a == e0b, - _ => false - } - } - ty_uniq(e0a) => { - match (*other) { - ty_uniq(e0b) => e0a == e0b, - _ => false - } - } - ty_evec(e0a, e1a) => { - match (*other) { - ty_evec(e0b, e1b) => e0a == e0b && e1a == e1b, - _ => false - } - } - ty_ptr(e0a) => { - match (*other) { - ty_ptr(e0b) => e0a == e0b, - _ => false - } - } - ty_rptr(e0a, e1a) => { - match (*other) { - ty_rptr(e0b, e1b) => e0a == e0b && e1a == e1b, - _ => false - } - } - ty_rec(e0a) => { - match (/*bad*/copy *other) { - ty_rec(e0b) => e0a == e0b, - _ => false - } - } - ty_fn(ref e0a) => { - match (*other) { - ty_fn(ref e0b) => (*e0a) == (*e0b), - _ => false - } - } - ty_trait(e0a, ref e1a, e2a) => { - match (*other) { - ty_trait(e0b, ref e1b, e2b) => - e0a == e0b && (*e1a) == (*e1b) && e2a == e2b, - _ => false - } - } - ty_struct(e0a, ref e1a) => { - match (*other) { - ty_struct(e0b, ref e1b) => e0a == e0b && (*e1a) == (*e1b), - _ => false - } - } - ty_tup(e0a) => { - match (/*bad*/copy *other) { - ty_tup(e0b) => e0a == e0b, - _ => false - } - } - ty_infer(ref e0a) => { - match (*other) { - ty_infer(ref e0b) => *e0a == *e0b, - _ => false - } - } - ty_err => { - match (*other) { - ty_err => true, - _ => false - } - } - ty_param(e0a) => { - match (*other) { - ty_param(e0b) => e0a == e0b, - _ => false - } - } - ty_self => { - match (*other) { - ty_self => true, - _ => false - } - } - ty_type => { - match (*other) { - ty_type => true, - _ => false - } - } - ty_opaque_box => { - match (*other) { - ty_opaque_box => true, - _ => false - } - } - ty_opaque_closure_ptr(e0a) => { - match (*other) { - ty_opaque_closure_ptr(e0b) => e0a == e0b, - _ => false - } - } - ty_unboxed_vec(e0a) => { - match (*other) { - ty_unboxed_vec(e0b) => e0a == e0b, - _ => false - } - } - } - } - pure fn ne(&self, other: &sty) -> bool { !(*self).eq(other) } -} - impl param_bound : cmp::Eq { pure fn eq(&self, other: ¶m_bound) -> bool { match (*self) { diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index 070360ce32f..0aafeac265a 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -55,7 +55,7 @@ use core::prelude::*; use middle::pat_util::pat_id_map; -use middle::ty::{FnTyBase, FnMeta, FnSig, arg, field, substs}; +use middle::ty::{arg, field, substs}; use middle::ty::{ty_param_substs_and_ty}; use middle::ty; use middle::typeck::check::fn_ctxt; @@ -70,7 +70,7 @@ use core::vec; use syntax::ast; use syntax::codemap::span; use syntax::print::pprust::path_to_str; -use util::common::indent; +use util::common::indenter; pub trait ast_conv { fn tcx() -> ty::ctxt; @@ -321,13 +321,16 @@ pub fn ast_ty_to_ty<AC: ast_conv, RS: region_scope Copy Durable>( }; ty::mk_rec(tcx, flds) } - 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) + ast::ty_bare_fn(bf) => { + ty::mk_bare_fn(tcx, ty_of_bare_fn(self, rscope, bf.purity, + bf.abi, bf.decl)) + } + ast::ty_closure(f) => { + let fn_decl = ty_of_closure(self, rscope, f.sigil, + f.purity, f.onceness, + f.region, f.decl, None, + ast_ty.span); + ty::mk_closure(tcx, fn_decl) } ast::ty_path(path, id) => { let a_def = match tcx.def_map.find(&id) { @@ -452,71 +455,92 @@ pub fn ty_of_arg<AC: ast_conv, RS: region_scope Copy Durable>( arg {mode: mode, ty: ty} } -pub type expected_tys = Option<{inputs: ~[ty::arg], - output: ty::t}>; +pub fn ty_of_bare_fn<AC: ast_conv, RS: region_scope Copy Durable>( + self: AC, rscope: RS, + purity: ast::purity, + abi: ast::Abi, + decl: ast::fn_decl) -> ty::BareFnTy +{ + debug!("ty_of_fn_decl"); + + // new region names that appear inside of the fn decl are bound to + // that function type + let rb = in_binding_rscope(rscope); + + let input_tys = decl.inputs.map(|a| ty_of_arg(self, rb, *a, None)); + let output_ty = match decl.output.node { + ast::ty_infer => self.ty_infer(decl.output.span), + _ => ast_ty_to_ty(self, rb, decl.output) + }; + + ty::BareFnTy { + purity: purity, + abi: abi, + sig: ty::FnSig {inputs: input_tys, output: output_ty} + } +} -pub fn ty_of_fn_decl<AC: ast_conv, RS: region_scope Copy Durable>( +pub fn ty_of_closure<AC: ast_conv, RS: region_scope Copy Durable>( self: AC, rscope: RS, - ast_proto: ast::Proto, + sigil: ast::Sigil, 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 { + expected_tys: Option<ty::FnSig>, + span: span) -> ty::ClosureTy +{ 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) - } + let _i = indenter(); + + // 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 sigil { + ast::OwnedSigil | ast::ManagedSigil => { + // @fn(), ~fn() default to static as the bound + // on their upvars: + ty::re_static + } + ast::BorrowedSigil => { + // &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); - - let input_tys = do decl.inputs.mapi |i, a| { - let expected_arg_ty = do expected_tys.chain_ref |e| { - // no guarantee that the correct number of expected args - // were supplied - if i < e.inputs.len() {Some(e.inputs[i])} else {None} - }; - ty_of_arg(self, rb, *a, expected_arg_ty) - }; + // new region names that appear inside of the fn decl are bound to + // that function type + let rb = in_binding_rscope(rscope); - let expected_ret_ty = expected_tys.map(|e| e.output); - let output_ty = match decl.output.node { - ast::ty_infer if expected_ret_ty.is_some() => expected_ret_ty.get(), - ast::ty_infer => self.ty_infer(decl.output.span), - _ => ast_ty_to_ty(self, rb, decl.output) + let input_tys = do decl.inputs.mapi |i, a| { + let expected_arg_ty = do expected_tys.chain_ref |e| { + // no guarantee that the correct number of expected args + // were supplied + if i < e.inputs.len() {Some(e.inputs[i])} else {None} }; + ty_of_arg(self, rb, *a, expected_arg_ty) + }; - FnTyBase { - meta: FnMeta {purity: purity, - proto: ast_proto, - onceness: onceness, - region: bound_region, - bounds: bounds}, - sig: FnSig {inputs: input_tys, + let expected_ret_ty = expected_tys.map(|e| e.output); + let output_ty = match decl.output.node { + ast::ty_infer if expected_ret_ty.is_some() => expected_ret_ty.get(), + ast::ty_infer => self.ty_infer(decl.output.span), + _ => ast_ty_to_ty(self, rb, decl.output) + }; + + ty::ClosureTy { + purity: purity, + sigil: sigil, + onceness: onceness, + region: bound_region, + sig: ty::FnSig {inputs: input_tys, output: output_ty} - } } } diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index b86f8f26c25..f5faa968791 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -883,7 +883,7 @@ pub impl LookupContext { }) } - ty_trait(*) | ty_fn(*) => { + ty_trait(*) | ty_closure(*) => { // NDM---eventually these should be some variant of autoref None } @@ -906,14 +906,14 @@ pub impl LookupContext { let tcx = self.tcx(); match ty::get(self_ty).sty { - ty_box(*) | ty_uniq(*) | ty_rptr(*) | + ty_bare_fn(*) | ty_box(*) | ty_uniq(*) | ty_rptr(*) | ty_infer(IntVar(_)) | ty_infer(FloatVar(_)) | ty_self | ty_param(*) | ty_nil | ty_bot | ty_bool | ty_int(*) | ty_uint(*) | ty_float(*) | ty_enum(*) | ty_ptr(*) | ty_rec(*) | ty_struct(*) | ty_tup(*) | ty_estr(*) | ty_evec(*) | - ty_trait(*) | ty_fn(*) => { + ty_trait(*) | ty_closure(*) => { self.search_for_some_kind_of_autorefd_method( AutoPtr, autoderefs, [m_const, m_imm, m_mutbl], |m,r| ty::mk_rptr(tcx, r, ty::mt {ty:self_ty, mutbl:m})) @@ -1212,7 +1212,7 @@ pub impl LookupContext { trait_did: def_id, method_num: uint) -> ty::t { let trait_methods = ty::trait_methods(tcx, trait_did); - ty::mk_fn(tcx, /*bad*/copy trait_methods[method_num].fty) + ty::mk_bare_fn(tcx, copy trait_methods[method_num].fty) } } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 1c0881b6ed5..074a0a565ae 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -81,7 +81,7 @@ use core::prelude::*; use middle::const_eval; use middle::pat_util::pat_id_map; use middle::pat_util; -use middle::ty::{TyVid, Vid, FnTyBase, FnMeta, FnSig, VariantInfo_, field}; +use middle::ty::{TyVid, Vid, FnSig, VariantInfo_, field}; use middle::ty::{ty_param_bounds_and_ty, ty_param_substs_and_ty}; use middle::ty::{re_bound, br_cap_avoid, substs, arg, param_ty}; use middle::ty; @@ -90,7 +90,6 @@ use middle::typeck::astconv::{ast_region_to_region, ast_ty_to_ty}; use middle::typeck::astconv; use middle::typeck::check::_match::pat_ctxt; use middle::typeck::check::method::TransformTypeNormally; -use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_ty; use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig; use middle::typeck::check::vtable::{LocationInfo, VtableContext}; use middle::typeck::crate_ctxt; @@ -248,8 +247,9 @@ pub fn check_bare_fn(ccx: @crate_ctxt, self_info: Option<self_info>) { let fty = ty::node_id_to_type(ccx.tcx, id); match ty::get(fty).sty { - ty::ty_fn(ref fn_ty) => { - check_fn(ccx, self_info, fn_ty, decl, body, Vanilla, None) + ty::ty_bare_fn(ref fn_ty) => { + check_fn(ccx, self_info, fn_ty.purity, None, + &fn_ty.sig, decl, body, Vanilla, None) } _ => ccx.tcx.sess.impossible_case(body.span, "check_bare_fn: function type expected") @@ -258,12 +258,14 @@ pub fn check_bare_fn(ccx: @crate_ctxt, pub fn check_fn(ccx: @crate_ctxt, self_info: Option<self_info>, - fn_ty: &ty::FnTy, + purity: ast::purity, + sigil: Option<ast::Sigil>, + fn_sig: &ty::FnSig, decl: &ast::fn_decl, body: ast::blk, fn_kind: FnKind, - old_fcx: Option<@fn_ctxt>) { - + old_fcx: Option<@fn_ctxt>) +{ let tcx = ccx.tcx; let indirect_ret = match fn_kind { ForLoop => true, _ => false @@ -277,7 +279,7 @@ pub fn check_fn(ccx: @crate_ctxt, let {isr, self_info, fn_sig} = { let old_isr = option::map_default(&old_fcx, @Nil, |fcx| fcx.in_scope_regions); - replace_bound_regions_in_fn_sig(tcx, old_isr, self_info, &fn_ty.sig, + replace_bound_regions_in_fn_sig(tcx, old_isr, self_info, fn_sig, |br| ty::re_free(body.node.id, br)) }; @@ -294,13 +296,10 @@ pub fn check_fn(ccx: @crate_ctxt, // in the case of function expressions, based on the outer context. let fcx: @fn_ctxt = { let (purity, inherited) = match old_fcx { - None => { - (fn_ty.meta.purity, - blank_inherited(ccx)) - } + None => (purity, blank_inherited(ccx)), Some(fcx) => { - (ty::determine_inherited_purity(fcx.purity, fn_ty.meta.purity, - fn_ty.meta.proto), + (ty::determine_inherited_purity(fcx.purity, purity, + sigil.get()), fcx.inh) } }; @@ -1092,8 +1091,9 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt, in_fty: ty::t, callee_expr: @ast::expr, args: ~[@ast::expr], - deref_args: DerefArgs) -> {fty: ty::t, bot: bool} { - + sugar: ast::CallSugar, + deref_args: DerefArgs) -> (ty::t, bool) + { let tcx = fcx.ccx.tcx; let mut bot = false; @@ -1103,62 +1103,72 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt, debug!("check_call_inner: before universal quant., in_fty=%s", fcx.infcx().ty_to_str(in_fty)); - let mut formal_tys; + let formal_tys; // This is subtle: we expect `fty` to be a function type, which // normally introduce a level of binding. In this case, we want to // process the types bound by the function but not by any nested // functions. Therefore, we match one level of structure. - let fty = - match structure_of(fcx, sp, in_fty) { - ty::ty_fn(ref fn_ty) => { - let fn_ty = - /*bad*/copy replace_bound_regions_in_fn_ty(tcx, @Nil, - None, fn_ty, |_br| fcx.infcx().next_region_var(sp, - call_expr_id)).fn_ty; - - let supplied_arg_count = args.len(); - - bot |= ty::type_is_bot(fn_ty.sig.output); - - // Grab the argument types, supplying fresh type variables - // if the wrong number of arguments were supplied - let expected_arg_count = fn_ty.sig.inputs.len(); - formal_tys = if expected_arg_count == supplied_arg_count { - fn_ty.sig.inputs.map(|a| a.ty) - } else { - tcx.sess.span_err( - sp, fmt!("this function takes %u parameter%s but \ - %u parameter%s supplied", + let ret_ty = match structure_of(fcx, sp, in_fty) { + ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, _}) | + ty::ty_closure(ty::ClosureTy {sig: ref sig, _}) => { + let {fn_sig: sig, _} = + replace_bound_regions_in_fn_sig( + tcx, @Nil, None, sig, + |_br| fcx.infcx().next_region_var( + sp, call_expr_id)); + + let supplied_arg_count = args.len(); + + bot |= ty::type_is_bot(sig.output); + + // Grab the argument types, supplying fresh type variables + // if the wrong number of arguments were supplied + let expected_arg_count = sig.inputs.len(); + formal_tys = if expected_arg_count == supplied_arg_count { + sig.inputs.map(|a| a.ty) + } else { + let suffix = match sugar { + ast::NoSugar => "", + ast::DoSugar => " (including the closure passed by \ + the `do` keyword)", + ast::ForSugar => " (including the closure passed by \ + the `for` keyword)" + }; + let msg = fmt!("this function takes %u parameter%s but \ + %u parameter%s supplied%s", expected_arg_count, - if expected_arg_count == 1 { - ~"" - } else { - ~"s" - }, + if expected_arg_count == 1 {""} + else {"s"}, supplied_arg_count, - if supplied_arg_count == 1 { - ~" was" - } else { - ~"s were" - })); - fcx.infcx().next_ty_vars(supplied_arg_count) - }; - ty::mk_fn(tcx, fn_ty) - } - _ => { - fcx.type_error_message(sp, |actual| { - fmt!("expected function or foreign function but \ - found `%s`", actual) }, in_fty, None); - // check each arg against "error", in order to set up - // all the node type bindings - formal_tys = args.map(|_x| ty::mk_err(tcx)); - ty::mk_err(tcx) - } - }; + if supplied_arg_count == 1 {" was"} + else {"s were"}, + suffix); - debug!("check_call_inner: after universal quant., fty=%s", - fcx.infcx().ty_to_str(fty)); + tcx.sess.span_err(sp, msg); + + vec::from_fn(expected_arg_count, |_| ty::mk_err(tcx)) + }; + + sig.output + } + + _ => { + fcx.type_error_message(sp, |actual| { + fmt!("expected function or foreign function but \ + found `%s`", actual) }, in_fty, None); + + // check each arg against "error", in order to set up + // all the node type bindings + formal_tys = args.map(|_x| ty::mk_err(tcx)); + ty::mk_err(tcx) + } + }; + + debug!("check_call_inner: after universal quant., \ + formal_tys=%? ret_ty=%s", + formal_tys.map(|t| fcx.infcx().ty_to_str(*t)), + fcx.infcx().ty_to_str(ret_ty)); // Check the arguments. // We do this in a pretty awful way: first we typecheck any arguments @@ -1209,7 +1219,7 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt, } } - {fty: fty, bot: bot} + (ret_ty, bot) } // A generic function for checking assignment expressions @@ -1233,36 +1243,26 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt, fn_ty: ty::t, expr: @ast::expr, +args: ~[@ast::expr], - bot: bool) - -> bool { + bot: bool, + sugar: ast::CallSugar) -> bool + { let mut bot = bot; // Call the generic checker. - let fty = { - let r = check_call_inner(fcx, sp, call_expr_id, - fn_ty, expr, args, DontDerefArgs); - bot |= r.bot; - r.fty - }; + let (ret_ty, b) = check_call_inner(fcx, sp, call_expr_id, + fn_ty, expr, args, sugar, + DontDerefArgs); + bot |= b; // Pull the return type out of the type of the function. - match structure_of(fcx, sp, fty) { - ty::ty_fn(ref f) => { - fcx.write_ty(call_expr_id, f.sig.output); - return bot; - } - _ => { - fcx.write_ty(call_expr_id, ty::mk_err(fcx.ccx.tcx)); - fcx.type_error_message(sp, |_actual| { - ~"expected function"}, fty, None); - return bot; - } - } + fcx.write_ty(call_expr_id, ret_ty); + return bot; } // A generic function for doing all of the checking for call expressions fn check_call(fcx: @fn_ctxt, sp: span, call_expr_id: ast::node_id, - f: @ast::expr, +args: ~[@ast::expr]) -> bool { + f: @ast::expr, +args: ~[@ast::expr], + sugar: ast::CallSugar) -> bool { // Index expressions need to be handled separately, to inform them // that they appear in call position. let mut bot = match /*bad*/copy f.node { @@ -1278,7 +1278,8 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt, fcx.expr_ty(f), f, args, - bot) + bot, + sugar) } // Checks a method call. @@ -1287,7 +1288,8 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt, rcvr: @ast::expr, method_name: ast::ident, +args: ~[@ast::expr], - tps: ~[@ast::Ty]) + tps: ~[@ast::Ty], + sugar: ast::CallSugar) -> bool { let bot = check_expr(fcx, rcvr); let expr_t = structurally_resolved_type(fcx, @@ -1329,7 +1331,8 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt, fcx.node_ty(expr.callee_id), expr, args, - bot) + bot, + sugar) } // A generic function for checking for or for-each loops @@ -1378,13 +1381,11 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt, op_ex.callee_id, opname, self_t, ~[], deref_args) { Some(ref origin) => { - let {fty: method_ty, bot: bot} = { - let method_ty = fcx.node_ty(op_ex.callee_id); - check_call_inner(fcx, op_ex.span, op_ex.id, - method_ty, op_ex, args, deref_args) - }; - fcx.ccx.method_map.insert(op_ex.id, (*origin)); - Some((ty::ty_fn_ret(method_ty), bot)) + let method_ty = fcx.node_ty(op_ex.callee_id); + fcx.ccx.method_map.insert(op_ex.id, *origin); + Some(check_call_inner(fcx, op_ex.span, op_ex.id, + method_ty, op_ex, args, + ast::NoSugar, deref_args)) } _ => None } @@ -1472,13 +1473,14 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt, // If the or operator is used it might be that the user forgot to // supply the do keyword. Let's be more helpful in that situation. if op == ast::or { - match ty::get(lhs_resolved_t).sty { - ty::ty_fn(_) => { - tcx.sess.span_note( - ex.span, ~"did you forget the `do` keyword for the call?"); + match ty::get(lhs_resolved_t).sty { + ty::ty_bare_fn(_) | ty::ty_closure(_) => { + tcx.sess.span_note( + ex.span, ~"did you forget the `do` keyword \ + for the call?"); + } + _ => () } - _ => () - } } (lhs_resolved_t, false) @@ -1523,7 +1525,7 @@ pub 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_sigil_opt: Option<ast::Sigil>, decl: &ast::fn_decl, body: ast::blk, fn_kind: FnKind, @@ -1534,50 +1536,44 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt, // avoid capture of bound regions in the expected type. See // def'n of br_cap_avoid() for a more lengthy explanation of // what's going on here. - // Also try to pick up inferred purity and proto, defaulting + // Also try to pick up inferred purity and sigil, defaulting // to impure and block. Note that we only will use those for // block syntax lambdas; that is, lambdas without explicit - // protos. + // sigils. let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x)); let (expected_tys, expected_purity, - expected_proto, + expected_sigil, expected_onceness) = { match expected_sty { - Some(ty::ty_fn(ref fn_ty)) => { + Some(ty::ty_closure(ref cenv)) => { let id = expr.id; - let {fn_ty: fn_ty, _} = - replace_bound_regions_in_fn_ty( - tcx, @Nil, None, fn_ty, + let {fn_sig: sig, _} = + replace_bound_regions_in_fn_sig( + tcx, @Nil, None, &cenv.sig, |br| ty::re_bound(ty::br_cap_avoid(id, @br))); - (Some({inputs: /*bad*/copy fn_ty.sig.inputs, - output: fn_ty.sig.output}), - fn_ty.meta.purity, - fn_ty.meta.proto, - fn_ty.meta.onceness) + (Some(sig), cenv.purity, cenv.sigil, cenv.onceness) } _ => { - (None, ast::impure_fn, ast::ProtoBorrowed, ast::Many) + (None, ast::impure_fn, ast::BorrowedSigil, ast::Many) } } }; // If the proto is specified, use that, otherwise select a // proto based on inference. - let (proto, purity) = match ast_proto_opt { + let (sigil, purity) = match ast_sigil_opt { Some(p) => (p, ast::impure_fn), - None => (expected_proto, expected_purity) + None => (expected_sigil, expected_purity) }; // construct the function type - let mut fn_ty = astconv::ty_of_fn_decl( + let mut fn_ty = astconv::ty_of_closure( fcx, fcx, - proto, purity, expected_onceness, - /*bounds:*/ @~[], /*opt_region:*/ None, - *decl, expected_tys, expr.span); + sigil, purity, expected_onceness, + None, *decl, expected_tys, expr.span); - // XXX: Bad copy. - let fty = ty::mk_fn(tcx, copy fn_ty); + let fty = ty::mk_closure(tcx, copy fn_ty); debug!("check_expr_fn_with_unifier %s fty=%s", fcx.expr_to_str(expr), @@ -1587,8 +1583,8 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt, // We inherit the same self info as the enclosing scope, // since the function we're checking might capture `self` - check_fn(fcx.ccx, fcx.self_info, &fn_ty, decl, body, - fn_kind, Some(fcx)); + check_fn(fcx.ccx, fcx.self_info, fn_ty.purity, Some(fn_ty.sigil), + &fn_ty.sig, decl, body, fn_kind, Some(fcx)); } @@ -1913,6 +1909,119 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt, return bot; } + fn check_loop_body(fcx: @fn_ctxt, + expr: @ast::expr, + expected: Option<ty::t>, + loop_body: @ast::expr) + { + // a loop body is the special argument to a `for` loop. We know that + // there will be an expected type in this context because it can only + // appear in the context of a call, so we get the expected type of the + // parameter. The catch here is that we need to validate two things: + // 1. a closure that returns a bool is expected + // 2. the closure that was given returns unit + let tcx = fcx.tcx(); + let mut err_happened = false; + let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x)); + let inner_ty = match expected_sty { + Some(ty::ty_closure(ref fty)) => { + match fcx.mk_subty(false, expr.span, + fty.sig.output, ty::mk_bool(tcx)) { + result::Ok(_) => { + ty::mk_closure(tcx, ty::ClosureTy { + sig: FnSig {output: ty::mk_nil(tcx), + ..copy fty.sig}, + ..copy *fty + }) + } + result::Err(_) => { + fcx.type_error_message( + expr.span, + |actual| { + let did_you_mean = { + if ty::type_is_nil(fty.sig.output) { + "\nDid you mean to use \ + `do` instead of `for`?" + } else { + "" + } + }; + fmt!("A `for` loop iterator should expect a \ + closure that returns `bool`. This \ + iterator expects a closure that \ + returns `%s`.%s", + actual, did_you_mean) + }, + fty.sig.output, + None); + err_happened = true; + + // Kind of a hack: create a function type with + // the result replaced with ty_err, to + // suppress derived errors. + let t = ty::replace_closure_return_type( + tcx, ty::mk_closure(tcx, copy *fty), + ty::mk_err(tcx)); + fcx.write_ty(expr.id, ty::mk_err(tcx)); + t + } + } + } + _ => { + match expected { + Some(expected_t) => { + fcx.type_error_message( + expr.span, + |actual| { + fmt!("last argument in `for` call \ + has non-closure type: %s", + actual) + }, + expected_t, None); + let err_ty = ty::mk_err(tcx); + fcx.write_ty(expr.id, err_ty); + err_happened = true; + err_ty + } + None => fcx.tcx().sess.impossible_case( + expr.span, + ~"loop body must have an expected type") + } + } + }; + + match loop_body.node { + ast::expr_fn_block(ref decl, ref body) => { + // If an error occurred, we pretend this isn't a for + // loop, so as to assign types to all nodes while also + // propagating ty_err throughout so as to suppress + // derived errors. If we passed in ForLoop in the + // error case, we'd potentially emit a spurious error + // message because of the indirect_ret_ty. + let fn_kind = if err_happened {Vanilla} else {ForLoop}; + check_expr_fn(fcx, loop_body, None, + decl, *body, fn_kind, Some(inner_ty)); + demand::suptype(fcx, loop_body.span, + inner_ty, fcx.expr_ty(loop_body)); + } + ref n => { + die!(fmt!( + "check_loop_body expected expr_fn_block, not %?", n)) + } + } + + let block_ty = structurally_resolved_type( + fcx, expr.span, fcx.node_ty(loop_body.id)); + if err_happened { + fcx.write_ty(expr.id, ty::mk_err(fcx.tcx())); + } else { + let loop_body_ty = + ty::replace_closure_return_type( + tcx, block_ty, ty::mk_bool(tcx)); + fcx.write_ty(expr.id, loop_body_ty); + } + } + let tcx = fcx.ccx.tcx; let id = expr.id; let mut bot = false; @@ -2153,121 +2262,38 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt, ast::expr_match(discrim, ref arms) => { bot = _match::check_match(fcx, expr, discrim, (/*bad*/copy *arms)); } - ast::expr_fn(proto, ref decl, ref body, _) => { - check_expr_fn(fcx, expr, Some(proto), + ast::expr_fn(sigil, ref decl, ref body, _) => { + check_expr_fn(fcx, expr, Some(sigil), decl, (*body), Vanilla, expected); } ast::expr_fn_block(ref decl, ref body) => { check_expr_fn(fcx, expr, None, decl, (*body), Vanilla, expected); } - ast::expr_loop_body(b) => { - // a loop body is the special argument to a `for` loop. We know that - // there will be an expected type in this context because it can only - // appear in the context of a call, so we get the expected type of the - // parameter. The catch here is that we need to validate two things: - // 1. a closure that returns a bool is expected - // 2. the closure that was given returns unit - let mut err_happened = false; - let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x)); - let inner_ty = match expected_sty { - Some(ty::ty_fn(ref fty)) => { - match fcx.mk_subty(false, expr.span, - (*fty).sig.output, ty::mk_bool(tcx)) { - result::Ok(_) => - ty::mk_fn(tcx, FnTyBase { - meta: (*fty).meta, - sig: FnSig {output: ty::mk_nil(tcx), - ../*bad*/copy (*fty).sig} - }), - result::Err(_) => { - fcx.type_error_message(expr.span, - |actual| { - fmt!("A `for` loop iterator should expect a \ - closure that returns `bool`. This iterator \ - expects a closure that returns `%s`. %s", - actual, if ty::type_is_nil((*fty).sig.output) { - "\nDid you mean to use `do` instead of \ - `for`?" } else { "" } ) - }, - (*fty).sig.output, None); - err_happened = true; - // Kind of a hack: create a function type with the result - // replaced with ty_err, to suppress derived errors. - let t = ty::replace_fn_return_type(tcx, ty::mk_fn(tcx, - copy *fty), - ty::mk_err(tcx)); - fcx.write_ty(id, ty::mk_err(tcx)); - t - } - } - } - _ => - match expected { - Some(expected_t) => { - fcx.type_error_message(expr.span, |actual| { - fmt!("a `loop` function's last \ - argument should be of function \ - type, not `%s`", - actual) - }, - expected_t, None); - let err_ty = ty::mk_err(tcx); - fcx.write_ty(id, err_ty); - err_happened = true; - err_ty - } - None => fcx.tcx().sess.impossible_case(expr.span, - ~"loop body must have an expected type") - } - }; - match b.node { - ast::expr_fn_block(ref decl, ref body) => { - // If an error occurred, we pretend this isn't a for - // loop, so as to assign types to all nodes while also - // propagating ty_err throughout so as to suppress - // derived errors. If we passed in ForLoop in the - // error case, we'd potentially emit a spurious error - // message because of the indirect_ret_ty. - let fn_kind = if err_happened { Vanilla } - else { ForLoop }; - check_expr_fn(fcx, b, None, - decl, *body, fn_kind, Some(inner_ty)); - demand::suptype(fcx, b.span, inner_ty, fcx.expr_ty(b)); - } - // argh - _ => die!(~"expr_fn_block") - } - let block_ty = structurally_resolved_type( - fcx, expr.span, fcx.node_ty(b.id)); - if err_happened { - fcx.write_ty(expr.id, ty::mk_err(fcx.tcx())); - } else { - let loop_body_ty = ty::replace_fn_return_type(tcx, block_ty, - ty::mk_bool(tcx)); - fcx.write_ty(expr.id, loop_body_ty); - } + ast::expr_loop_body(loop_body) => { + check_loop_body(fcx, expr, expected, loop_body); } ast::expr_do_body(b) => { let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x)); let inner_ty = match expected_sty { - Some(ty::ty_fn(ref fty)) => { - ty::mk_fn(tcx, (/*bad*/copy *fty)) - } - _ => match expected { - Some(expected_t) => { - fcx.type_error_message(expr.span, |_actual| { - ~"Non-function passed to a `do` \ - function as its last argument, or wrong number \ - of arguments passed to a `do` function" - }, expected_t, None); - let err_ty = ty::mk_err(tcx); - fcx.write_ty(id, err_ty); - err_ty - } - None => fcx.tcx().sess.impossible_case(expr.span, - ~"do body must have expected type") - } + Some(ty::ty_closure(_)) => expected.get(), + _ => match expected { + Some(expected_t) => { + fcx.type_error_message(expr.span, |actual| { + fmt!("last argument in `do` call \ + has non-closure type: %s", + actual) + }, expected_t, None); + let err_ty = ty::mk_err(tcx); + fcx.write_ty(id, err_ty); + err_ty + } + None => { + fcx.tcx().sess.impossible_case( + expr.span, + ~"do body must have expected type") + } + } }; match b.node { ast::expr_fn_block(ref decl, ref body) => { @@ -2290,11 +2316,11 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt, }; fcx.write_ty(id, typ); } - ast::expr_call(f, args, _) => { - bot = check_call(fcx, expr.span, expr.id, f, args); + ast::expr_call(f, args, sugar) => { + bot = check_call(fcx, expr.span, expr.id, f, args, sugar); } - ast::expr_method_call(rcvr, ident, tps, args, _) => { - bot = check_method_call(fcx, expr, rcvr, ident, args, tps); + ast::expr_method_call(rcvr, ident, tps, args, sugar) => { + bot = check_method_call(fcx, expr, rcvr, ident, args, tps, sugar); } ast::expr_cast(e, t) => { bot = check_expr(fcx, e); @@ -3088,20 +3114,18 @@ pub 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, FnTyBase { - meta: FnMeta {purity: ast::impure_fn, - proto: ast::ProtoBorrowed, - onceness: ast::Once, - region: ty::re_bound(ty::br_anon(0)), - bounds: @~[]}, - sig: FnSig { - inputs: ~[arg { - 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)} + let fty = ty::mk_closure(ccx.tcx, ty::ClosureTy { + purity: ast::impure_fn, + sigil: ast::BorrowedSigil, + onceness: ast::Once, + region: ty::re_bound(ty::br_anon(0)), + sig: ty::FnSig { + inputs: ~[arg {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)) } @@ -3324,12 +3348,9 @@ pub fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) { return; } }; - let fty = ty::mk_fn(tcx, FnTyBase { - meta: FnMeta {purity: ast::unsafe_fn, - proto: ast::ProtoBare, - onceness: ast::Many, - region: ty::re_static, - bounds: @~[]}, + let fty = ty::mk_bare_fn(tcx, ty::BareFnTy { + purity: ast::unsafe_fn, + abi: ast::RustAbi, sig: FnSig {inputs: inputs, output: output} }); diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index 952c1a9fcd8..9dfaaeebc8f 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -32,7 +32,7 @@ use core::prelude::*; use middle::freevars::get_freevars; use middle::pat_util::{pat_bindings, pat_is_binding}; use middle::ty::{encl_region, re_scope}; -use middle::ty::{ty_fn_proto, vstore_box, vstore_fixed, vstore_slice}; +use middle::ty::{vstore_box, vstore_fixed, vstore_slice}; use middle::ty::{vstore_uniq}; use middle::ty; use middle::typeck::check::fn_ctxt; @@ -42,7 +42,7 @@ use middle::typeck::infer::{resolve_type}; use util::ppaux::{note_and_explain_region, ty_to_str}; use core::result; -use syntax::ast::{ProtoBare, ProtoBox, ProtoUniq, ProtoBorrowed}; +use syntax::ast::{ManagedSigil, OwnedSigil, BorrowedSigil}; use syntax::ast::{def_arg, def_binding, def_local, def_self, def_upvar}; use syntax::ast; use syntax::codemap::span; @@ -59,10 +59,9 @@ pub fn encl_region_of_def(fcx: @fn_ctxt, def: ast::def) -> ty::Region { def_self(node_id, _) | def_binding(node_id, _) => return encl_region(tcx, node_id), def_upvar(_, subdef, closure_id, body_id) => { - match ty_fn_proto(fcx.node_ty(closure_id)) { - ProtoBare => tcx.sess.bug(~"ProtoBare with upvars?!"), - ProtoBorrowed => encl_region_of_def(fcx, *subdef), - ProtoBox | ProtoUniq => re_scope(body_id) + match ty::ty_closure_sigil(fcx.node_ty(closure_id)) { + BorrowedSigil => encl_region_of_def(fcx, *subdef), + ManagedSigil | OwnedSigil => re_scope(body_id) } } _ => { @@ -278,11 +277,9 @@ pub fn visit_expr(expr: @ast::expr, &&rcx: @rcx, v: rvt) { ast::expr_fn(*) | ast::expr_fn_block(*) => { let function_type = rcx.resolve_node_type(expr.id); match ty::get(function_type).sty { - ty::ty_fn(ref fn_ty) => { - if fn_ty.meta.proto == ast::ProtoBorrowed { - constrain_free_variables( - rcx, fn_ty.meta.region, expr); - } + ty::ty_closure(ty::ClosureTy {sigil: ast::BorrowedSigil, + region: region, _}) => { + constrain_free_variables(rcx, region, expr); } _ => () } diff --git a/src/librustc/middle/typeck/check/regionmanip.rs b/src/librustc/middle/typeck/check/regionmanip.rs index 8ea35824e32..f0956df545c 100644 --- a/src/librustc/middle/typeck/check/regionmanip.rs +++ b/src/librustc/middle/typeck/check/regionmanip.rs @@ -12,7 +12,6 @@ use core::prelude::*; -use middle::ty::{FnTyBase}; use middle::ty; use middle::typeck::check::self_info; use middle::typeck::isr_alist; @@ -27,22 +26,6 @@ use syntax::print::pprust::{expr_to_str}; // Helper functions related to manipulating region types. -pub fn replace_bound_regions_in_fn_ty( - tcx: ty::ctxt, - isr: isr_alist, - self_info: Option<self_info>, - fn_ty: &ty::FnTy, - mapf: fn(ty::bound_region) -> ty::Region) -> - {isr: isr_alist, self_info: Option<self_info>, fn_ty: ty::FnTy} { - let {isr, self_info, fn_sig} = - replace_bound_regions_in_fn_sig( - tcx, isr, self_info, &fn_ty.sig, mapf); - {isr: isr, - self_info: self_info, - fn_ty: FnTyBase {meta: fn_ty.meta, - sig: fn_sig}} -} - pub fn replace_bound_regions_in_fn_sig( tcx: ty::ctxt, isr: isr_alist, diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 9f2af3ec003..abd4697eb31 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -233,7 +233,7 @@ pub fn lookup_vtable(vcx: &VtableContext, relate_trait_tys(vcx, location_info, trait_ty, ty); if !allow_unsafe && !is_early { for vec::each(*ty::trait_methods(tcx, did)) |m| { - if ty::type_has_self(ty::mk_fn(tcx, /*bad*/copy m.fty)) { + if ty::type_has_self(ty::mk_bare_fn(tcx, copy m.fty)) { tcx.sess.span_err( location_info.span, ~"a boxed trait with self types may not be \ diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 324cdcc261f..8fc8c4f6cbb 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -26,10 +26,10 @@ use middle::resolve::{Impl, MethodInfo}; use middle::ty::{ProvidedMethodSource, ProvidedMethodInfo, bound_copy, get}; use middle::ty::{kind_can_be_copied, lookup_item_type, param_bounds, subst}; use middle::ty::{substs, t, ty_bool, ty_bot, ty_box, ty_enum, ty_err}; -use middle::ty::{ty_estr, ty_evec, ty_float, ty_fn, ty_infer, ty_int, ty_nil}; +use middle::ty::{ty_estr, ty_evec, ty_float, ty_infer, ty_int, ty_nil}; use middle::ty::{ty_opaque_box, ty_param, ty_param_bounds_and_ty, ty_ptr}; use middle::ty::{ty_rec, ty_rptr, ty_self, ty_struct, ty_trait, ty_tup}; -use middle::ty::{ty_type, ty_uint, ty_uniq}; +use middle::ty::{ty_type, ty_uint, ty_uniq, ty_bare_fn, ty_closure}; use middle::ty::{ty_opaque_closure_ptr, ty_unboxed_vec, type_kind_ext}; use middle::ty::{type_is_ty_var}; use middle::ty; @@ -108,7 +108,7 @@ pub fn get_base_type(inference_context: @InferCtxt, ty_nil | ty_bot | ty_bool | ty_int(*) | ty_uint(*) | ty_float(*) | ty_estr(*) | ty_evec(*) | ty_rec(*) | - ty_fn(*) | ty_tup(*) | ty_infer(*) | + ty_bare_fn(*) | ty_closure(*) | ty_tup(*) | ty_infer(*) | ty_param(*) | ty_self | ty_type | ty_opaque_box | ty_opaque_closure_ptr(*) | ty_unboxed_vec(*) | ty_err => { debug!("(getting base type) no base type; found %?", diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index b7b7899883b..120fd89e5eb 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -33,10 +33,10 @@ are represented as `ty_param()` instances. use core::prelude::*; use metadata::csearch; -use middle::ty::{FnMeta, FnSig, FnTyBase, InstantiatedTraitRef, arg}; +use middle::ty::{InstantiatedTraitRef, arg}; use middle::ty::{substs, ty_param_substs_and_ty}; use middle::ty; -use middle::typeck::astconv::{ast_conv, ty_of_fn_decl, ty_of_arg}; +use middle::typeck::astconv::{ast_conv, ty_of_arg}; use middle::typeck::astconv::{ast_ty_to_ty}; use middle::typeck::astconv; use middle::typeck::infer; @@ -153,9 +153,10 @@ pub impl @crate_ctxt: ast_conv { pub fn get_enum_variant_types(ccx: @crate_ctxt, enum_ty: ty::t, - variants: ~[ast::variant], - ty_params: ~[ast::ty_param], - rp: Option<ty::region_variance>) { + variants: &[ast::variant], + ty_params: &[ast::ty_param], + rp: Option<ty::region_variance>) +{ let tcx = ccx.tcx; // Create a set of parameter types shared among all the variants. @@ -166,58 +167,35 @@ pub fn get_enum_variant_types(ccx: @crate_ctxt, match variant.node.kind { ast::tuple_variant_kind(ref args) if args.len() > 0 => { let rs = type_rscope(rp); - let args = args.map(|va| { - let arg_ty = ccx.to_ty(rs, va.ty); - arg { mode: ast::expl(ast::by_copy), ty: arg_ty } - }); - result_ty = Some(ty::mk_fn(tcx, FnTyBase { - meta: FnMeta {purity: ast::pure_fn, - proto: ast::ProtoBare, - onceness: ast::Many, - bounds: @~[], - region: ty::re_static}, - sig: FnSig {inputs: args, - output: enum_ty} - })); + let input_tys = args.map(|va| ccx.to_ty(rs, va.ty)); + result_ty = Some(ty::mk_ctor_fn(tcx, input_tys, enum_ty)); } + ast::tuple_variant_kind(_) => { result_ty = Some(enum_ty); } + ast::struct_variant_kind(struct_def) => { - // XXX: Merge with computation of the the same value below? - let tpt = { - bounds: ty_param_bounds(ccx, /*bad*/copy ty_params), - region_param: rp, - ty: enum_ty - }; - convert_struct( - ccx, - rp, - struct_def, - /*bad*/copy ty_params, - tpt, - variant.node.id); - // Compute the ctor arg types from the struct fields - let struct_fields = do struct_def.fields.map |struct_field| { - arg { - mode: ast::expl(ast::by_val), - ty: ty::node_id_to_type(ccx.tcx, struct_field.node.id) - } - }; - result_ty = Some(ty::mk_fn(tcx, FnTyBase { - meta: FnMeta {purity: ast::pure_fn, - proto: ast::ProtoBare, - onceness: ast::Many, - bounds: @~[], - region: ty::re_static}, - sig: FnSig {inputs: struct_fields, output: enum_ty }})); + let tpt = {bounds: ty_param_bounds(ccx, ty_params), + region_param: rp, + ty: enum_ty}; + + convert_struct(ccx, + rp, + struct_def, + ty_params.to_vec(), + tpt, + variant.node.id); + + let input_tys = struct_def.fields.map( + |f| ty::node_id_to_type(ccx.tcx, f.node.id)); + result_ty = Some(ty::mk_ctor_fn(tcx, input_tys, enum_ty)); } + ast::enum_variant_kind(ref enum_definition) => { - get_enum_variant_types(ccx, - enum_ty, - /*bad*/copy enum_definition.variants, - /*bad*/copy ty_params, - rp); + get_enum_variant_types(ccx, enum_ty, + enum_definition.variants, + ty_params, rp); result_ty = None; } }; @@ -225,11 +203,9 @@ pub fn get_enum_variant_types(ccx: @crate_ctxt, match result_ty { None => {} Some(result_ty) => { - let tpt = { - bounds: ty_param_bounds(ccx, /*bad*/copy ty_params), - region_param: rp, - ty: result_ty - }; + let tpt = {bounds: ty_param_bounds(ccx, ty_params), + region_param: rp, + ty: result_ty}; tcx.tcache.insert(local_def(variant.node.id), tpt); write_ty_to_tcx(tcx, variant.node.id, result_ty); } @@ -279,7 +255,7 @@ pub fn ensure_trait_methods(ccx: @crate_ctxt, }; let ty = ty::subst(ccx.tcx, &substs, - ty::mk_fn(ccx.tcx, /*bad*/copy m.fty)); + ty::mk_bare_fn(ccx.tcx, copy m.fty)); let bounds = @(*trait_bounds + ~[@~[ty::bound_trait(trait_ty)]] + *m.tps); ccx.tcx.tcache.insert(local_def(am.id), @@ -305,7 +281,7 @@ pub fn ensure_trait_methods(ccx: @crate_ctxt, ast::provided(method) => def_id = local_def(method.id) } - let trait_bounds = ty_param_bounds(ccx, copy *params); + let trait_bounds = ty_param_bounds(ccx, *params); let ty_m = trait_method_to_ty_method(*m); let method_ty = ty_of_ty_method(ccx, ty_m, region_paramd, def_id); if ty_m.self_ty.node == ast::sty_static { @@ -458,7 +434,7 @@ pub fn compare_impl_method(tcx: ty::ctxt, // that correspond to the parameters we will find on the impl // - replace self region with a fresh, dummy region let impl_fty = { - let impl_fty = ty::mk_fn(tcx, /*bad*/copy impl_m.fty); + let impl_fty = ty::mk_bare_fn(tcx, copy impl_m.fty); debug!("impl_fty (pre-subst): %s", ppaux::ty_to_str(tcx, impl_fty)); replace_bound_self(tcx, impl_fty, dummy_self_r) }; @@ -476,7 +452,7 @@ pub fn compare_impl_method(tcx: ty::ctxt, self_ty: Some(self_ty), tps: vec::append(trait_tps, dummy_tps) }; - let trait_fty = ty::mk_fn(tcx, /*bad*/copy trait_m.fty); + let trait_fty = ty::mk_bare_fn(tcx, copy trait_m.fty); debug!("trait_fty (pre-subst): %s", ppaux::ty_to_str(tcx, trait_fty)); ty::subst(tcx, &substs, trait_fty) }; @@ -583,9 +559,9 @@ pub fn convert_methods(ccx: @crate_ctxt, let tcx = ccx.tcx; do vec::map(ms) |m| { - let bounds = ty_param_bounds(ccx, /*bad*/copy m.tps); + let bounds = ty_param_bounds(ccx, m.tps); let mty = ty_of_method(ccx, *m, rp); - let fty = ty::mk_fn(tcx, /*bad*/copy mty.fty); + let fty = ty::mk_bare_fn(tcx, copy mty.fty); tcx.tcache.insert( local_def(m.id), @@ -626,13 +602,11 @@ pub fn convert(ccx: @crate_ctxt, it: @ast::item) { ensure_no_ty_param_bounds(ccx, it.span, *ty_params, "enumeration"); let tpt = ty_of_item(ccx, it); write_ty_to_tcx(tcx, it.id, tpt.ty); - get_enum_variant_types(ccx, - tpt.ty, - /*bad*/copy (*enum_definition).variants, - /*bad*/copy *ty_params, rp); + get_enum_variant_types(ccx, tpt.ty, enum_definition.variants, + *ty_params, rp); } ast::item_impl(ref tps, trait_ref, selfty, ref ms) => { - let i_bounds = ty_param_bounds(ccx, /*bad*/copy *tps); + let i_bounds = ty_param_bounds(ccx, *tps); let selfty = ccx.to_ty(type_rscope(rp), selfty); write_ty_to_tcx(tcx, it.id, selfty); tcx.tcache.insert(local_def(it.id), @@ -695,13 +669,12 @@ pub fn convert_struct(ccx: @crate_ctxt, do option::iter(&struct_def.dtor) |dtor| { // Write the dtor type - let t_dtor = ty::mk_fn( + let t_dtor = ty::mk_bare_fn( tcx, - 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)); + astconv::ty_of_bare_fn( + ccx, type_rscope(rp), + ast::impure_fn, ast::RustAbi, + ast_util::dtor_dec())); write_ty_to_tcx(tcx, dtor.node.id, t_dtor); tcx.tcache.insert(local_def(dtor.node.id), {bounds: tpt.bounds, @@ -727,25 +700,11 @@ pub fn convert_struct(ccx: @crate_ctxt, tcx.tcache.insert(local_def(ctor_id), tpt); } else if struct_def.fields[0].node.kind == ast::unnamed_field { // Tuple-like. - let ctor_fn_ty = ty::mk_fn(tcx, FnTyBase { - meta: FnMeta { - purity: ast::pure_fn, - proto: ast::ProtoBare, - onceness: ast::Many, - bounds: @~[], - region: ty::re_static - }, - sig: FnSig { - inputs: do struct_def.fields.map |field| { - arg { - mode: ast::expl(ast::by_copy), - ty: ccx.tcx.tcache.get - (&local_def(field.node.id)).ty - } - }, - output: selfty - } - }); + let inputs = + struct_def.fields.map( + |field| ccx.tcx.tcache.get( + &local_def(field.node.id)).ty); + let ctor_fn_ty = ty::mk_ctor_fn(tcx, inputs, selfty); write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty); tcx.tcache.insert(local_def(ctor_id), { bounds: tpt.bounds, @@ -770,11 +729,9 @@ pub fn ty_of_method(ccx: @crate_ctxt, m: @ast::method, rp: Option<ty::region_variance>) -> ty::method { {ident: m.ident, - tps: ty_param_bounds(ccx, /*bad*/copy m.tps), - fty: ty_of_fn_decl(ccx, type_rscope(rp), ast::ProtoBare, - m.purity, ast::Many, - /*bounds:*/ @~[], /*opt_region:*/ None, - m.decl, None, m.span), + tps: ty_param_bounds(ccx, m.tps), + fty: astconv::ty_of_bare_fn(ccx, type_rscope(rp), m.purity, + ast::RustAbi, m.decl), self_ty: m.self_ty.node, vis: m.vis, def_id: local_def(m.id)} @@ -785,11 +742,9 @@ pub fn ty_of_ty_method(self: @crate_ctxt, rp: Option<ty::region_variance>, id: ast::def_id) -> ty::method { {ident: m.ident, - tps: ty_param_bounds(self, /*bad*/copy m.tps), - fty: ty_of_fn_decl(self, type_rscope(rp), ast::ProtoBare, - m.purity, ast::Many, - /*bounds:*/ @~[], /*opt_region:*/ None, - m.decl, None, m.span), + tps: ty_param_bounds(self, m.tps), + fty: astconv::ty_of_bare_fn(self, type_rscope(rp), m.purity, + ast::RustAbi, m.decl), // assume public, because this is only invoked on trait methods self_ty: m.self_ty.node, vis: ast::public, @@ -844,13 +799,11 @@ pub 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::ProtoBare, purity, ast::Many, - /*bounds:*/ @~[], /*opt_region:*/ None, - decl, None, it.span); + let tofd = astconv::ty_of_bare_fn(ccx, empty_rscope, purity, + ast::RustAbi, decl); let tpt = {bounds: bounds, region_param: None, - ty: ty::mk_fn(ccx.tcx, tofd)}; + ty: ty::mk_bare_fn(ccx.tcx, tofd)}; debug!("type of %s (id %d) is %s", tcx.sess.str_of(it.ident), it.id, @@ -976,7 +929,7 @@ pub fn compute_bounds(ccx: @crate_ctxt, } pub fn ty_param_bounds(ccx: @crate_ctxt, - params: ~[ast::ty_param]) -> @~[ty::param_bounds] { + params: &[ast::ty_param]) -> @~[ty::param_bounds] { @do params.map |param| { match ccx.tcx.ty_param_bounds.find(¶m.id) { Some(bs) => bs, @@ -999,15 +952,13 @@ pub 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, FnTyBase { - meta: FnMeta {purity: ast::unsafe_fn, - onceness: ast::Many, - proto: ast::ProtoBare, - bounds: @~[], - region: ty::re_static}, - sig: FnSig {inputs: input_tys, - output: output_ty} - }); + let t_fn = ty::mk_bare_fn( + ccx.tcx, + ty::BareFnTy { + abi: ast::RustAbi, + purity: ast::unsafe_fn, + sig: ty::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; @@ -1017,8 +968,7 @@ pub fn mk_ty_params(ccx: @crate_ctxt, atps: ~[ast::ty_param]) -> {bounds: @~[ty::param_bounds], params: ~[ty::t]} { let mut i = 0u; - // XXX: Bad copy. - let bounds = ty_param_bounds(ccx, copy atps); + let bounds = ty_param_bounds(ccx, atps); {bounds: bounds, params: vec::map(atps, |atp| { let t = ty::mk_param(ccx.tcx, i, local_def(atp.id)); diff --git a/src/librustc/middle/typeck/infer/coercion.rs b/src/librustc/middle/typeck/infer/coercion.rs index f0fe2deffdf..5d291fdde77 100644 --- a/src/librustc/middle/typeck/infer/coercion.rs +++ b/src/librustc/middle/typeck/infer/coercion.rs @@ -69,7 +69,7 @@ use core::prelude::*; use middle::ty::{TyVar, AutoPtr, AutoBorrowVec, AutoBorrowFn}; use middle::ty::{AutoAdjustment, AutoRef}; use middle::ty::{vstore_slice, vstore_box, vstore_uniq, vstore_fixed}; -use middle::ty::{FnMeta, FnTyBase, mt}; +use middle::ty::{mt}; use middle::ty; use middle::typeck::infer::{CoerceResult, resolve_type}; use middle::typeck::infer::combine::CombineFields; @@ -117,7 +117,7 @@ impl Coerce { }; } - ty::ty_fn(ref b_f) if b_f.meta.proto == ast::ProtoBorrowed => { + ty::ty_closure(ty::ClosureTy {sigil: ast::BorrowedSigil, _}) => { return do self.unpack_actual_value(a) |sty_a| { self.coerce_borrowed_fn(a, sty_a, b) }; @@ -134,7 +134,7 @@ impl Coerce { do self.unpack_actual_value(a) |sty_a| { match *sty_a { - ty::ty_fn(ref a_f) if a_f.meta.proto == ast::ProtoBare => { + ty::ty_bare_fn(ref a_f) => { // Bare functions are coercable to any closure type. // // FIXME(#3320) this should go away and be @@ -289,9 +289,9 @@ impl Coerce { b.inf_str(self.infcx)); let fn_ty = match *sty_a { - ty::ty_fn(ref f) if f.meta.proto == ast::ProtoBox => {f} - ty::ty_fn(ref f) if f.meta.proto == ast::ProtoUniq => {f} - ty::ty_fn(ref f) if f.meta.proto == ast::ProtoBare => { + ty::ty_closure(ref f) if f.sigil == ast::ManagedSigil => copy *f, + ty::ty_closure(ref f) if f.sigil == ast::OwnedSigil => copy *f, + ty::ty_bare_fn(ref f) => { return self.coerce_from_bare_fn(a, f, b); } _ => { @@ -300,12 +300,13 @@ impl Coerce { }; let r_borrow = self.infcx.next_region_var_nb(self.span); - let meta = FnMeta {proto: ast::ProtoBorrowed, - region: r_borrow, - ..fn_ty.meta}; - let a_borrowed = ty::mk_fn(self.infcx.tcx, - FnTyBase {meta: meta, - sig: copy fn_ty.sig}); + let a_borrowed = ty::mk_closure( + self.infcx.tcx, + ty::ClosureTy { + sigil: ast::BorrowedSigil, + region: r_borrow, + ..fn_ty + }); if_ok!(self.subtype(a_borrowed, b)); Ok(Some(@AutoAdjustment { @@ -320,7 +321,7 @@ impl Coerce { fn coerce_from_bare_fn(&self, a: ty::t, - fn_ty_a: &ty::FnTy, + fn_ty_a: &ty::BareFnTy, b: ty::t) -> CoerceResult { do self.unpack_actual_value(b) |sty_b| { @@ -330,7 +331,7 @@ impl Coerce { fn coerce_from_bare_fn_post_unpack(&self, a: ty::t, - fn_ty_a: &ty::FnTy, + fn_ty_a: &ty::BareFnTy, b: ty::t, sty_b: &ty::sty) -> CoerceResult { @@ -338,18 +339,18 @@ impl Coerce { a.inf_str(self.infcx), b.inf_str(self.infcx)); let fn_ty_b = match *sty_b { - ty::ty_fn(ref f) if f.meta.proto != ast::ProtoBare => {f} + ty::ty_closure(ref f) => {copy *f} _ => { return self.subtype(a, b); } }; - // for now, bare fn and closures have the same - // representation - let a_adapted = ty::mk_fn(self.infcx.tcx, - FnTyBase {meta: copy fn_ty_b.meta, - sig: copy fn_ty_a.sig}); - self.subtype(a_adapted, b) + // for now, bare fn and closures have the same + // representation + let a_closure = ty::mk_closure( + self.infcx.tcx, + ty::ClosureTy {sig: copy fn_ty_a.sig, ..fn_ty_b}); + self.subtype(a_closure, b) } fn coerce_unsafe_ptr(&self, diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs index 819348e744e..7737327bc0c 100644 --- a/src/librustc/middle/typeck/infer/combine.rs +++ b/src/librustc/middle/typeck/infer/combine.rs @@ -56,7 +56,7 @@ use core::prelude::*; -use middle::ty::{FloatVar, FnTyBase, FnMeta, FnSig, IntVar, TyVar}; +use middle::ty::{FloatVar, FnSig, IntVar, TyVar}; use middle::ty::{IntType, UintType, arg, substs}; use middle::ty; use middle::typeck::infer::glb::Glb; @@ -94,14 +94,17 @@ pub trait Combine { fn self_tys(a: Option<ty::t>, b: Option<ty::t>) -> cres<Option<ty::t>>; fn substs(did: ast::def_id, as_: &ty::substs, bs: &ty::substs) -> cres<ty::substs>; - fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres<ty::FnTy>; + fn bare_fn_tys(a: &ty::BareFnTy, + b: &ty::BareFnTy) -> cres<ty::BareFnTy>; + fn closure_tys(a: &ty::ClosureTy, + b: &ty::ClosureTy) -> cres<ty::ClosureTy>; fn fn_sigs(a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig>; - fn fn_metas(a: &ty::FnMeta, b: &ty::FnMeta) -> cres<ty::FnMeta>; 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: ast::Proto, p2: ast::Proto) -> cres<ast::Proto>; + fn sigils(p1: ast::Sigil, p2: ast::Sigil) -> cres<ast::Sigil>; fn purities(a: purity, b: purity) -> cres<purity>; + fn abis(a: ast::Abi, b: ast::Abi) -> cres<ast::Abi>; fn oncenesses(a: Onceness, b: Onceness) -> cres<Onceness>; fn contraregions(a: ty::Region, b: ty::Region) -> cres<ty::Region>; fn regions(a: ty::Region, b: ty::Region) -> cres<ty::Region>; @@ -287,12 +290,12 @@ pub fn super_self_tys<C:Combine>( } } -pub fn super_protos<C: Combine>( - self: &C, p1: ast::Proto, p2: ast::Proto) -> cres<ast::Proto> { +pub fn super_sigils<C: Combine>( + self: &C, p1: ast::Sigil, p2: ast::Sigil) -> cres<ast::Sigil> { if p1 == p2 { Ok(p1) } else { - Err(ty::terr_proto_mismatch(expected_found(self, p1, p2))) + Err(ty::terr_sigil_mismatch(expected_found(self, p1, p2))) } } @@ -350,21 +353,45 @@ pub fn super_vstores<C:Combine>( } } -pub fn super_fn_metas<C:Combine>( - self: &C, a_f: &ty::FnMeta, b_f: &ty::FnMeta) -> cres<ty::FnMeta> { - let p = if_ok!(self.protos(a_f.proto, b_f.proto)); +pub fn super_closure_tys<C:Combine>( + self: &C, a_f: &ty::ClosureTy, b_f: &ty::ClosureTy) -> cres<ty::ClosureTy> +{ + let p = if_ok!(self.sigils(a_f.sigil, b_f.sigil)); let r = if_ok!(self.contraregions(a_f.region, b_f.region)); 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, - onceness: onceness, - region: r, - bounds: a_f.bounds}) // XXX: This is wrong! + let sig = if_ok!(self.fn_sigs(&a_f.sig, &b_f.sig)); + Ok(ty::ClosureTy {purity: purity, + sigil: p, + onceness: onceness, + region: r, + sig: sig}) +} + +pub fn super_abis<C:Combine>( + self: &C, a: ast::Abi, b: ast::Abi) -> cres<ast::Abi> +{ + if a == b { + Ok(a) + } else { + Err(ty::terr_abi_mismatch(expected_found(self, a, b))) + } +} + +pub fn super_bare_fn_tys<C:Combine>( + self: &C, a_f: &ty::BareFnTy, b_f: &ty::BareFnTy) -> cres<ty::BareFnTy> +{ + let purity = if_ok!(self.purities(a_f.purity, b_f.purity)); + let abi = if_ok!(self.abis(a_f.abi, b_f.abi)); + let sig = if_ok!(self.fn_sigs(&a_f.sig, &b_f.sig)); + Ok(ty::BareFnTy {purity: purity, + abi: abi, + sig: sig}) } pub fn super_fn_sigs<C:Combine>( - self: &C, a_f: &ty::FnSig, b_f: &ty::FnSig) -> cres<ty::FnSig> { + self: &C, a_f: &ty::FnSig, b_f: &ty::FnSig) -> cres<ty::FnSig> +{ fn argvecs<C:Combine>(self: &C, +a_args: ~[ty::arg], +b_args: ~[ty::arg]) -> cres<~[ty::arg]> @@ -384,13 +411,6 @@ pub fn super_fn_sigs<C:Combine>( } } -pub fn super_fns<C:Combine>( - self: &C, a_f: &ty::FnTy, b_f: &ty::FnTy) -> cres<ty::FnTy> { - let m = if_ok!(self.fn_metas(&a_f.meta, &b_f.meta)); - let s = if_ok!(self.fn_sigs(&a_f.sig, &b_f.sig)); - Ok(FnTyBase {meta: m, sig: s}) -} - pub fn super_tys<C:Combine>( self: &C, a: ty::t, b: ty::t) -> cres<ty::t> { let tcx = self.infcx().tcx; @@ -551,9 +571,15 @@ pub fn super_tys<C:Combine>( } } - (ty::ty_fn(ref a_fty), ty::ty_fn(ref b_fty)) => { - do self.fns(a_fty, b_fty).chain |fty| { - Ok(ty::mk_fn(tcx, fty)) + (ty::ty_bare_fn(ref a_fty), ty::ty_bare_fn(ref b_fty)) => { + do self.bare_fn_tys(a_fty, b_fty).chain |fty| { + Ok(ty::mk_bare_fn(tcx, fty)) + } + } + + (ty::ty_closure(ref a_fty), ty::ty_closure(ref b_fty)) => { + do self.closure_tys(a_fty, b_fty).chain |fty| { + Ok(ty::mk_closure(tcx, fty)) } } diff --git a/src/librustc/middle/typeck/infer/glb.rs b/src/librustc/middle/typeck/infer/glb.rs index 58d9f1019ae..382d5f24cc7 100644 --- a/src/librustc/middle/typeck/infer/glb.rs +++ b/src/librustc/middle/typeck/infer/glb.rs @@ -267,16 +267,22 @@ pub impl Glb: Combine { } } - fn protos(p1: ast::Proto, p2: ast::Proto) -> cres<ast::Proto> { - super_protos(&self, p1, p2) + fn sigils(p1: ast::Sigil, p2: ast::Sigil) -> cres<ast::Sigil> { + super_sigils(&self, p1, p2) } - fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres<ty::FnTy> { - super_fns(&self, a, b) + fn abis(p1: ast::Abi, p2: ast::Abi) -> cres<ast::Abi> { + super_abis(&self, p1, p2) } - fn fn_metas(a: &ty::FnMeta, b: &ty::FnMeta) -> cres<ty::FnMeta> { - super_fn_metas(&self, a, b) + fn bare_fn_tys(a: &ty::BareFnTy, + b: &ty::BareFnTy) -> cres<ty::BareFnTy> { + super_bare_fn_tys(&self, a, b) + } + + fn closure_tys(a: &ty::ClosureTy, + b: &ty::ClosureTy) -> cres<ty::ClosureTy> { + super_closure_tys(&self, a, b) } fn substs(did: ast::def_id, diff --git a/src/librustc/middle/typeck/infer/lattice.rs b/src/librustc/middle/typeck/infer/lattice.rs index 4f7bedd8149..4bf8a0bae86 100644 --- a/src/librustc/middle/typeck/infer/lattice.rs +++ b/src/librustc/middle/typeck/infer/lattice.rs @@ -71,23 +71,6 @@ pub impl ty::t: LatticeValue { } } -pub impl FnMeta: LatticeValue { - static fn sub(cf: &CombineFields, - a: &FnMeta, b: &FnMeta) -> ures { - Sub(*cf).fn_metas(a, b).to_ures() - } - - static fn lub(cf: &CombineFields, - a: &FnMeta, b: &FnMeta) -> cres<FnMeta> { - Lub(*cf).fn_metas(a, b) - } - - static fn glb(cf: &CombineFields, - a: &FnMeta, b: &FnMeta) -> cres<FnMeta> { - Glb(*cf).fn_metas(a, b) - } -} - pub impl CombineFields { fn var_sub_var<T:Copy InferStr LatticeValue, V:Copy Eq ToStr Vid UnifyVid<Bounds<T>>>( diff --git a/src/librustc/middle/typeck/infer/lub.rs b/src/librustc/middle/typeck/infer/lub.rs index f24d245db58..44ad367c9dc 100644 --- a/src/librustc/middle/typeck/infer/lub.rs +++ b/src/librustc/middle/typeck/infer/lub.rs @@ -191,18 +191,24 @@ pub impl Lub: Combine { } } - fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres<ty::FnTy> { - super_fns(&self, a, b) + fn bare_fn_tys(a: &ty::BareFnTy, + b: &ty::BareFnTy) -> cres<ty::BareFnTy> { + super_bare_fn_tys(&self, a, b) } - fn fn_metas(a: &ty::FnMeta, b: &ty::FnMeta) -> cres<ty::FnMeta> { - super_fn_metas(&self, a, b) + fn closure_tys(a: &ty::ClosureTy, + b: &ty::ClosureTy) -> cres<ty::ClosureTy> { + super_closure_tys(&self, a, b) } // Traits please (FIXME: #2794): - fn protos(p1: ast::Proto, p2: ast::Proto) -> cres<ast::Proto> { - super_protos(&self, p1, p2) + fn sigils(p1: ast::Sigil, p2: ast::Sigil) -> cres<ast::Sigil> { + super_sigils(&self, p1, p2) + } + + fn abis(p1: ast::Abi, p2: ast::Abi) -> cres<ast::Abi> { + super_abis(&self, p1, p2) } fn tys(a: ty::t, b: ty::t) -> cres<ty::t> { diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs index 6140390a24e..d6ecf11ef26 100644 --- a/src/librustc/middle/typeck/infer/mod.rs +++ b/src/librustc/middle/typeck/infer/mod.rs @@ -242,9 +242,6 @@ section on "Type Combining" below for details. */ -#[warn(deprecated_mode)]; -#[warn(deprecated_pattern)]; - use core::prelude::*; pub use middle::ty::IntVarValue; @@ -257,7 +254,6 @@ pub use middle::typeck::infer::resolve::{resolve_nested_tvar}; pub use middle::typeck::infer::resolve::{resolve_rvar}; use middle::ty::{TyVid, IntVid, FloatVid, RegionVid, Vid}; -use middle::ty::{mk_fn, type_is_bot}; use middle::ty::{ty_int, ty_uint, get, terr_fn, TyVar, IntVar, FloatVar}; use middle::ty; use middle::typeck::check::regionmanip::{replace_bound_regions_in_fn_sig}; diff --git a/src/librustc/middle/typeck/infer/region_inference.rs b/src/librustc/middle/typeck/infer/region_inference.rs index 0d4e520122f..afb18888cd9 100644 --- a/src/librustc/middle/typeck/infer/region_inference.rs +++ b/src/librustc/middle/typeck/infer/region_inference.rs @@ -536,9 +536,6 @@ more convincing in the future. */ -#[warn(deprecated_mode)]; -#[warn(deprecated_pattern)]; - use core::prelude::*; use middle::region::is_subregion_of; diff --git a/src/librustc/middle/typeck/infer/sub.rs b/src/librustc/middle/typeck/infer/sub.rs index 2e30bdc5888..bc834ef0289 100644 --- a/src/librustc/middle/typeck/infer/sub.rs +++ b/src/librustc/middle/typeck/infer/sub.rs @@ -212,20 +212,26 @@ pub impl Sub: Combine { // Traits please (FIXME: #2794): - fn protos(p1: ast::Proto, p2: ast::Proto) -> cres<ast::Proto> { - super_protos(&self, p1, p2) + fn sigils(p1: ast::Sigil, p2: ast::Sigil) -> cres<ast::Sigil> { + super_sigils(&self, p1, p2) + } + + fn abis(p1: ast::Abi, p2: ast::Abi) -> cres<ast::Abi> { + super_abis(&self, p1, p2) } fn flds(a: ty::field, b: ty::field) -> cres<ty::field> { super_flds(&self, a, b) } - fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres<ty::FnTy> { - super_fns(&self, a, b) + fn bare_fn_tys(a: &ty::BareFnTy, + b: &ty::BareFnTy) -> cres<ty::BareFnTy> { + super_bare_fn_tys(&self, a, b) } - fn fn_metas(a: &ty::FnMeta, b: &ty::FnMeta) -> cres<ty::FnMeta> { - super_fn_metas(&self, a, b) + fn closure_tys(a: &ty::ClosureTy, + b: &ty::ClosureTy) -> cres<ty::ClosureTy> { + super_closure_tys(&self, a, b) } fn vstores(vk: ty::terr_vstore_kind, diff --git a/src/librustc/middle/typeck/infer/to_str.rs b/src/librustc/middle/typeck/infer/to_str.rs index 57e05926173..bade7639e4b 100644 --- a/src/librustc/middle/typeck/infer/to_str.rs +++ b/src/librustc/middle/typeck/infer/to_str.rs @@ -10,7 +10,7 @@ use core::prelude::*; -use middle::ty::{FnMeta, FnTyBase, FnSig, Vid}; +use middle::ty::{FnSig, Vid}; use middle::ty::{IntVarValue, IntType, UintType}; use middle::ty; use middle::typeck::infer::{Bound, Bounds}; @@ -34,12 +34,6 @@ pub impl ty::t : InferStr { } } -pub impl FnMeta : InferStr { - fn inf_str(&self, _cx: &InferCtxt) -> ~str { - fmt!("%?", *self) - } -} - pub impl FnSig : InferStr { fn inf_str(&self, cx: &InferCtxt) -> ~str { fmt!("(%s) -> %s", @@ -48,12 +42,6 @@ pub impl FnSig : InferStr { } } -pub impl<M:InferStr> FnTyBase<M> : InferStr { - fn inf_str(&self, cx: &InferCtxt) -> ~str { - fmt!("%s%s", self.meta.inf_str(cx), self.sig.inf_str(cx)) - } -} - pub impl ty::mt : InferStr { fn inf_str(&self, cx: &InferCtxt) -> ~str { mt_to_str(cx.tcx, *self) diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index 742646618bd..3d9e2e7b86a 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -324,7 +324,7 @@ 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).sty { - ty::ty_fn(ref fn_ty) => { + ty::ty_bare_fn(ref fn_ty) => { match tcx.items.find(&main_id) { Some(ast_map::node_item(it,_)) => { match it.node { @@ -341,8 +341,8 @@ fn check_main_fn_ty(ccx: @crate_ctxt, } _ => () } - let mut ok = ty::type_is_nil((*fn_ty).sig.output); - let num_args = vec::len((*fn_ty).sig.inputs); + let mut ok = ty::type_is_nil(fn_ty.sig.output); + let num_args = vec::len(fn_ty.sig.inputs); ok &= num_args == 0u; if !ok { tcx.sess.span_err( diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 9e70a6ab130..43d12c95c4d 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -21,7 +21,8 @@ use middle::ty::{mt, t, param_bound, param_ty}; use middle::ty::{re_bound, re_free, re_scope, re_infer, re_static, Region}; use middle::ty::{ReSkolemized, ReVar}; use middle::ty::{ty_bool, ty_bot, ty_box, ty_struct, ty_enum}; -use middle::ty::{ty_err, ty_estr, ty_evec, ty_float, ty_fn, ty_trait, ty_int}; +use middle::ty::{ty_err, ty_estr, ty_evec, ty_float, ty_bare_fn, ty_closure}; +use middle::ty::{ty_trait, ty_int}; use middle::ty::{ty_nil, ty_opaque_box, ty_opaque_closure_ptr, ty_param}; use middle::ty::{ty_ptr, ty_rec, ty_rptr, ty_self, ty_tup}; use middle::ty::{ty_type, ty_uniq, ty_uint, ty_infer}; @@ -30,7 +31,7 @@ use metadata::encoder; use syntax::codemap; use syntax::codemap::span; use syntax::print::pprust; -use syntax::print::pprust::{path_to_str, proto_to_str, mode_to_str}; +use syntax::print::pprust::{path_to_str, mode_to_str}; use syntax::{ast, ast_util}; use syntax::ast_map; @@ -252,17 +253,6 @@ pub fn vstore_ty_to_str(cx: ctxt, ty: ~str, vs: ty::vstore) -> ~str { } } -pub fn proto_ty_to_str(_cx: ctxt, proto: ast::Proto, - followed_by_word: bool) -> &static/str { - match proto { - ast::ProtoBare if followed_by_word => "extern ", - ast::ProtoBare => "extern", - ast::ProtoBox => "@", - ast::ProtoBorrowed => "&", - ast::ProtoUniq => "~", - } -} - pub fn expr_repr(cx: ctxt, expr: @ast::expr) -> ~str { fmt!("expr(%d: %s)", expr.id, @@ -306,69 +296,95 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str { }; fmt!("%s%s", modestr, ty_to_str(cx, ty)) } - fn fn_to_str(cx: ctxt, - proto: ast::Proto, - region: ty::Region, - purity: ast::purity, - onceness: ast::Onceness, - ident: Option<ast::ident>, - inputs: &[arg], - output: t) -> ~str { - let mut s; - - s = match purity { - ast::impure_fn => ~"", - _ => purity.to_str() + ~" " - }; + fn bare_fn_to_str(cx: ctxt, + purity: ast::purity, + abi: ast::Abi, + ident: Option<ast::ident>, + sig: &ty::FnSig) -> ~str + { + let mut s = ~"extern "; - s += match onceness { - ast::Many => ~"", - ast::Once => onceness.to_str() + ~" " + match abi { + ast::RustAbi => {} + } + + match purity { + ast::impure_fn => {} + _ => { + s.push_str(purity.to_str()); + s.push_char(' '); + } }; - s += proto_ty_to_str(cx, proto, true); + s.push_str("fn"); - match (proto, region) { - (ast::ProtoBox, ty::re_static) | - (ast::ProtoUniq, ty::re_static) | - (ast::ProtoBare, ty::re_static) => { - } + match ident { + Some(i) => { + s.push_char(' '); + s.push_str(cx.sess.str_of(i)); + } + _ => { } + } + + push_sig_to_str(cx, &mut s, sig); + + return s; + } + fn closure_to_str(cx: ctxt, cty: &ty::ClosureTy) -> ~str + { + let mut s = cty.sigil.to_str(); + + match (cty.sigil, cty.region) { + (ast::ManagedSigil, ty::re_static) | + (ast::OwnedSigil, ty::re_static) => {} (_, region) => { - s += region_to_str_adorned(cx, ~"", region, ~"/"); + s.push_str(region_to_str_adorned(cx, "", region, "/")); } } - s += ~"fn"; + match cty.purity { + ast::impure_fn => {} + _ => { + s.push_str(cty.purity.to_str()); + s.push_char(' '); + } + }; - match ident { - Some(i) => { s += ~" "; s += cx.sess.str_of(i); } - _ => { } - } - s += ~"("; - let strs = inputs.map(|a| fn_input_to_str(cx, *a)); - s += str::connect(strs, ~", "); - s += ~")"; - if ty::get(output).sty != ty_nil { - s += ~" -> "; - if ty::type_is_bot(output) { - s += ~"!"; + match cty.onceness { + ast::Many => {} + ast::Once => { + s.push_str(cty.onceness.to_str()); + s.push_char(' '); + } + }; + + s.push_str("fn"); + + push_sig_to_str(cx, &mut s, &cty.sig); + + return s; + } + fn push_sig_to_str(cx: ctxt, s: &mut ~str, sig: &ty::FnSig) { + s.push_char('('); + let strs = sig.inputs.map(|a| fn_input_to_str(cx, *a)); + s.push_str(str::connect(strs, ", ")); + s.push_char(')'); + if ty::get(sig.output).sty != ty_nil { + s.push_str(" -> "); + if ty::type_is_bot(sig.output) { + s.push_char('!'); } else { - s += ty_to_str(cx, output); + s.push_str(ty_to_str(cx, sig.output)); } } - return s; } fn method_to_str(cx: ctxt, m: method) -> ~str { - return fn_to_str( - cx, - m.fty.meta.proto, - m.fty.meta.region, - m.fty.meta.purity, - m.fty.meta.onceness, - Some(m.ident), - m.fty.sig.inputs, - m.fty.sig.output) + ~";"; + bare_fn_to_str(cx, + m.fty.purity, + m.fty.abi, + Some(m.ident), + &m.fty.sig) + ~";" } fn field_to_str(cx: ctxt, f: field) -> ~str { return cx.sess.str_of(f.ident) + ~": " + mt_to_str(cx, f.mt); @@ -409,15 +425,11 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str { let strs = elems.map(|elem| ty_to_str(cx, *elem)); ~"(" + str::connect(strs, ~",") + ~")" } - ty_fn(ref f) => { - fn_to_str(cx, - f.meta.proto, - f.meta.region, - f.meta.purity, - f.meta.onceness, - None, - f.sig.inputs, - f.sig.output) + ty_closure(ref f) => { + closure_to_str(cx, f) + } + ty_bare_fn(ref f) => { + bare_fn_to_str(cx, f.purity, f.abi, None, &f.sig) } ty_infer(infer_ty) => infer_ty.to_str(), ty_err => ~"[type error]", @@ -448,10 +460,9 @@ pub 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(ast::ProtoBorrowed) => ~"closure&", - ty_opaque_closure_ptr(ast::ProtoBox) => ~"closure@", - ty_opaque_closure_ptr(ast::ProtoUniq) => ~"closure~", - ty_opaque_closure_ptr(ast::ProtoBare) => ~"closure" + ty_opaque_closure_ptr(ast::BorrowedSigil) => ~"closure&", + ty_opaque_closure_ptr(ast::ManagedSigil) => ~"closure@", + ty_opaque_closure_ptr(ast::OwnedSigil) => ~"closure~", } } |
