diff --git a/src/compiletest/compiletest.rc b/src/compiletest/compiletest.rc index 8505e48163869..ba6862039d44d 100644 --- a/src/compiletest/compiletest.rc +++ b/src/compiletest/compiletest.rc @@ -211,7 +211,7 @@ fn is_test(config: config, testfile: &Path) -> bool { fn make_test(config: config, testfile: &Path) -> test::TestDesc { - { + test::TestDesc { name: make_test_name(config, testfile), testfn: make_test_closure(config, testfile), ignore: header::is_test_ignored(config, testfile), diff --git a/src/libcargo/cargo.rc b/src/libcargo/cargo.rc index 8d81f75e0da79..f089c9e04c40d 100644 --- a/src/libcargo/cargo.rc +++ b/src/libcargo/cargo.rc @@ -401,7 +401,7 @@ fn load_crate(filename: &Path) -> Option { let e = @{ mut deps: ~[] }; - let v = visit::mk_simple_visitor(@{ + let v = visit::mk_simple_visitor(@visit::SimpleVisitor { visit_view_item: |a| goto_view_item(sess, e, a), visit_item: |a| goto_item(e, a), .. *visit::default_simple_visitor() diff --git a/src/libcore/stackwalk.rs b/src/libcore/stackwalk.rs index 1beb1a56efa1b..f45f71104f424 100644 --- a/src/libcore/stackwalk.rs +++ b/src/libcore/stackwalk.rs @@ -99,5 +99,5 @@ extern mod rustrt { #[abi = "rust-intrinsic"] extern mod rusti { #[legacy_exports]; - fn frame_address(f: fn(++x: *u8)); + fn frame_address(f: &once fn(++x: *u8)); } diff --git a/src/libfuzzer/fuzzer.rc b/src/libfuzzer/fuzzer.rc index cf242ddd8e219..7d1d112e76f10 100644 --- a/src/libfuzzer/fuzzer.rc +++ b/src/libfuzzer/fuzzer.rc @@ -167,7 +167,7 @@ type stolen_stuff = {exprs: ~[ast::expr], tys: ~[ast::Ty]}; fn steal(crate: ast::crate, tm: test_mode) -> stolen_stuff { let exprs = @mut ~[]; let tys = @mut ~[]; - let v = visit::mk_simple_visitor(@{ + let v = visit::mk_simple_visitor(@visit::SimpleVisitor { visit_expr: |a| stash_expr_if(safe_to_steal_expr, exprs, a, tm), visit_ty: |a| stash_ty_if(safe_to_steal_ty, tys, a, tm), .. *visit::default_simple_visitor() @@ -216,7 +216,7 @@ fn replace_expr_in_crate(crate: ast::crate, i: uint, fold::noop_fold_expr(original, fld) } } - let afp = @{ + let afp = @fold::AstFoldFns { fold_expr: fold::wrap(|a,b| { fold_expr_rep(j, i, newexpr.node, a, b, tm) }), @@ -241,7 +241,7 @@ fn replace_ty_in_crate(crate: ast::crate, i: uint, newty: ast::Ty, newty_ } else { fold::noop_fold_ty(original, fld) } } - let afp = @{ + let afp = @fold::AstFoldFns { fold_ty: fold::wrap(|a,b| fold_ty_rep(j, i, newty.node, a, b, tm) ), .. *fold::default_ast_fold() }; @@ -485,8 +485,9 @@ fn has_raw_pointers(c: ast::crate) -> bool { } } let v = - visit::mk_simple_visitor(@{visit_ty: |a| visit_ty(has_rp, a), - .. *visit::default_simple_visitor()}); + visit::mk_simple_visitor(@visit::SimpleVisitor { + visit_ty: |a| visit_ty(has_rp, a), + .. *visit::default_simple_visitor()}); visit::visit_crate(c, (), v); return *has_rp; } diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 3212adf29ac34..7eba77ad14327 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -394,13 +394,16 @@ fn pretty_print_input(sess: Session, +cfg: ast::crate_cfg, input: input, let ann = match ppm { ppm_typed => { - {pre: ann_paren_for_expr, - post: |a| ann_typed_post(tcx.get(), a) } + pprust::pp_ann {pre: ann_paren_for_expr, + post: |a| ann_typed_post(tcx.get(), a) } } ppm_identified | ppm_expanded_identified => { - {pre: ann_paren_for_expr, post: ann_identified_post} + pprust::pp_ann {pre: ann_paren_for_expr, + post: ann_identified_post} + } + ppm_expanded | ppm_normal => { + pprust::no_ann() } - ppm_expanded | ppm_normal => pprust::no_ann() }; let is_expanded = upto != cu_parse; let src = sess.codemap.get_filemap(source_name(input)).src; diff --git a/src/librustc/front/config.rs b/src/librustc/front/config.rs index 7a073057f0d59..c8b980218c1ed 100644 --- a/src/librustc/front/config.rs +++ b/src/librustc/front/config.rs @@ -37,8 +37,8 @@ fn strip_items(crate: @ast::crate, in_cfg: in_cfg_pred) let ctxt = @{in_cfg: in_cfg}; - let precursor = - @{fold_mod: |a,b| fold_mod(ctxt, a, b), + let precursor = @fold::AstFoldFns { + fold_mod: |a,b| fold_mod(ctxt, a, b), fold_block: fold::wrap(|a,b| fold_block(ctxt, a, b) ), fold_foreign_mod: |a,b| fold_foreign_mod(ctxt, a, b), fold_item_underscore: |a,b| { diff --git a/src/librustc/front/core_inject.rs b/src/librustc/front/core_inject.rs index 6df5e367ad1c3..e0b63314e3e22 100644 --- a/src/librustc/front/core_inject.rs +++ b/src/librustc/front/core_inject.rs @@ -41,7 +41,7 @@ fn inject_libcore_ref(sess: Session, return {node: x, span: dummy_sp()}; } - let precursor = @{ + let precursor = @fold::AstFoldFns { fold_crate: |crate, span, fld| { let n1 = sess.next_node_id(); let vi1 = @{node: ast::view_item_use(sess.ident_of(~"core"), diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs index 09db770512f7f..d675c6f078a77 100644 --- a/src/librustc/front/test.rs +++ b/src/librustc/front/test.rs @@ -64,10 +64,10 @@ fn generate_test_harness(sess: session::Session, mut path: ~[], testfns: DVec()}; - let precursor = - @{fold_crate: fold::wrap(|a,b| fold_crate(cx, a, b) ), - fold_item: |a,b| fold_item(cx, a, b), - fold_mod: |a,b| fold_mod(cx, a, b),.. *fold::default_ast_fold()}; + let precursor = @fold::AstFoldFns { + fold_crate: fold::wrap(|a,b| fold_crate(cx, a, b) ), + fold_item: |a,b| fold_item(cx, a, b), + fold_mod: |a,b| fold_mod(cx, a, b),.. *fold::default_ast_fold()}; let fold = fold::make_fold(precursor); let res = @fold.fold_crate(*crate); @@ -423,8 +423,14 @@ fn mk_test_desc_rec(cx: test_ctxt, test: test) -> @ast::expr { ident: cx.sess.ident_of(~"should_fail"), expr: @fail_expr}); + let test_desc_path = + mk_path(cx, ~[cx.sess.ident_of(~"test"), + cx.sess.ident_of(~"TestDesc")]); + let desc_rec_: ast::expr_ = - ast::expr_rec(~[name_field, fn_field, ignore_field, fail_field], + ast::expr_struct( + test_desc_path, + ~[name_field, fn_field, ignore_field, fail_field], option::None); let desc_rec: ast::expr = {id: cx.sess.next_node_id(), callee_id: cx.sess.next_node_id(), diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index da33aaa460baf..5ba1f4e86b7c9 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -50,10 +50,10 @@ fn read_crates(diag: span_handler, mut next_crate_num: 1, intr: intr}; let v = - visit::mk_simple_visitor(@{visit_view_item: - |a| visit_view_item(e, a), - visit_item: |a| visit_item(e, a) - ,.. *visit::default_simple_visitor()}); + visit::mk_simple_visitor(@visit::SimpleVisitor { + visit_view_item: |a| visit_view_item(e, a), + visit_item: |a| visit_item(e, a), + .. *visit::default_simple_visitor()}); visit::visit_crate(crate, (), v); dump_crates(e.crate_cache); warn_if_multiple_versions(e, diag, e.crate_cache.get()); diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 5a936e113eed0..541913be2616d 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -178,11 +178,12 @@ fn def_to_str(did: def_id) -> ~str { fmt!("%d:%d", did.crate, did.node) } fn encode_ty_type_param_bounds(ebml_w: writer::Encoder, ecx: @encode_ctxt, params: @~[ty::param_bounds]) { - let ty_str_ctxt = @{diag: ecx.diag, - ds: def_to_str, - tcx: ecx.tcx, - reachable: |a| reachable(ecx, a), - abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)}; + let ty_str_ctxt = @tyencode::ctxt { + diag: ecx.diag, + ds: def_to_str, + tcx: ecx.tcx, + reachable: |a| reachable(ecx, a), + abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)}; for params.each |param| { ebml_w.start_tag(tag_items_data_item_ty_param_bounds); tyencode::enc_bounds(ebml_w.writer, ty_str_ctxt, *param); @@ -205,23 +206,23 @@ fn encode_variant_id(ebml_w: writer::Encoder, vid: def_id) { } fn write_type(ecx: @encode_ctxt, ebml_w: writer::Encoder, typ: ty::t) { - let ty_str_ctxt = - @{diag: ecx.diag, - ds: def_to_str, - tcx: ecx.tcx, - reachable: |a| reachable(ecx, a), - abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)}; + let ty_str_ctxt = @tyencode::ctxt { + diag: ecx.diag, + ds: def_to_str, + tcx: ecx.tcx, + reachable: |a| reachable(ecx, a), + abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)}; tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ); } fn write_vstore(ecx: @encode_ctxt, ebml_w: writer::Encoder, vstore: ty::vstore) { - let ty_str_ctxt = - @{diag: ecx.diag, - ds: def_to_str, - tcx: ecx.tcx, - reachable: |a| reachable(ecx, a), - abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)}; + let ty_str_ctxt = @tyencode::ctxt { + diag: ecx.diag, + ds: def_to_str, + tcx: ecx.tcx, + reachable: |a| reachable(ecx, a), + abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)}; tyencode::enc_vstore(ebml_w.writer, ty_str_ctxt, vstore); } @@ -885,7 +886,7 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: writer::Encoder, encode_info_for_mod(ecx, ebml_w, crate.node.module, crate_node_id, ~[], syntax::parse::token::special_idents::invalid); - visit::visit_crate(*crate, (), visit::mk_vt(@{ + visit::visit_crate(*crate, (), visit::mk_vt(@visit::Visitor { visit_expr: |_e, _cx, _v| { }, visit_item: |i, cx, v, copy ebml_w| { visit::visit_item(i, cx, v); @@ -1265,11 +1266,12 @@ fn encode_metadata(parms: encode_parms, crate: @crate) -> ~[u8] { // Get the encoded string for a type fn encoded_ty(tcx: ty::ctxt, t: ty::t) -> ~str { - let cx = @{diag: tcx.diag, - ds: def_to_str, - tcx: tcx, - reachable: |_id| false, - abbrevs: tyencode::ac_no_abbrevs}; + let cx = @tyencode::ctxt { + diag: tcx.diag, + ds: def_to_str, + tcx: tcx, + reachable: |_id| false, + abbrevs: tyencode::ac_no_abbrevs}; do io::with_str_writer |wr| { tyencode::enc_ty(wr, cx, t); } diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 24095ebfe003a..9ae47425fa78a 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -12,7 +12,7 @@ // Type encoding use middle::ty; -use middle::ty::vid; +use middle::ty::Vid; use core::io::WriterUtil; use core::io; @@ -22,6 +22,7 @@ use std::map::HashMap; use syntax::ast::*; use syntax::diagnostic::span_handler; use syntax::print::pprust::*; +use middle::ty::Vid; export ctxt; export ty_abbrev; @@ -33,7 +34,7 @@ export enc_mode; export enc_arg; export enc_vstore; -type ctxt = { +struct ctxt { diag: span_handler, // Def -> str Callback: ds: fn@(def_id) -> ~str, @@ -41,7 +42,7 @@ type ctxt = { tcx: ty::ctxt, reachable: fn@(node_id) -> bool, abbrevs: abbrev_ctxt -}; +} // Compact string representation for ty.t values. API ty_str & parse_from_str. // Extra parameters are for converting to/from def_ids in the string rep. diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index c97553ce1c073..3ab8d39d49dae 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -268,7 +268,7 @@ fn simplify_ast(ii: ast::inlined_item) -> ast::inlined_item { fold::noop_fold_block(blk_sans_items, fld) } - let fld = fold::make_fold(@{ + let fld = fold::make_fold(@fold::AstFoldFns { fold_block: fold::wrap(drop_nested_items), .. *fold::default_ast_fold() }); @@ -300,7 +300,7 @@ fn decode_ast(par_doc: ebml::Doc) -> ast::inlined_item { fn renumber_ast(xcx: extended_decode_ctxt, ii: ast::inlined_item) -> ast::inlined_item { - let fld = fold::make_fold(@{ + let fld = fold::make_fold(@fold::AstFoldFns{ new_id: |a| xcx.tr_id(a), new_span: |a| xcx.tr_span(a), .. *fold::default_ast_fold() @@ -637,11 +637,11 @@ trait get_ty_str_ctxt { impl @e::encode_ctxt: get_ty_str_ctxt { fn ty_str_ctxt() -> @tyencode::ctxt { - @{diag: self.tcx.sess.diagnostic(), - ds: e::def_to_str, - tcx: self.tcx, - reachable: |a| encoder::reachable(self, a), - abbrevs: tyencode::ac_use_abbrevs(self.type_abbrevs)} + @tyencode::ctxt {diag: self.tcx.sess.diagnostic(), + ds: e::def_to_str, + tcx: self.tcx, + reachable: |a| encoder::reachable(self, a), + abbrevs: tyencode::ac_use_abbrevs(self.type_abbrevs)} } } diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index 4370707e66554..9f3ca5a6cfff1 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -81,11 +81,11 @@ fn check_loans(bccx: borrowck_ctxt, reported: HashMap(), mut declared_purity: ast::impure_fn, mut fn_args: @~[]}); - let vt = visit::mk_vt(@{visit_expr: check_loans_in_expr, - visit_local: check_loans_in_local, - visit_block: check_loans_in_block, - visit_fn: check_loans_in_fn, - .. *visit::default_visitor()}); + let vt = visit::mk_vt(@visit::Visitor {visit_expr: check_loans_in_expr, + visit_local: check_loans_in_local, + visit_block: check_loans_in_block, + visit_fn: check_loans_in_fn, + .. *visit::default_visitor()}); visit::visit_crate(*crate, clcx, vt); } @@ -236,13 +236,13 @@ 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 { + match fn_ty.meta.purity { ast::pure_fn => return, // case (c) above ast::impure_fn | ast::unsafe_fn | ast::extern_fn => { self.report_purity_error( pc, callee_span, fmt!("access to %s function", - pprust::purity_to_str((*fn_ty).meta.purity))); + fn_ty.meta.purity.to_str())); } } } diff --git a/src/librustc/middle/borrowck/gather_loans.rs b/src/librustc/middle/borrowck/gather_loans.rs index d5652ae78d6ee..8cb40f3c3f581 100644 --- a/src/librustc/middle/borrowck/gather_loans.rs +++ b/src/librustc/middle/borrowck/gather_loans.rs @@ -73,9 +73,9 @@ fn gather_loans(bccx: borrowck_ctxt, crate: @ast::crate) -> req_maps { mut item_ub: 0, mut root_ub: 0, mut ignore_adjustments: LinearMap()}); - let v = visit::mk_vt(@{visit_expr: req_loans_in_expr, - visit_fn: req_loans_in_fn, - .. *visit::default_visitor()}); + let v = visit::mk_vt(@visit::Visitor {visit_expr: req_loans_in_expr, + visit_fn: req_loans_in_fn, + .. *visit::default_visitor()}); visit::visit_crate(*crate, glcx, v); return glcx.req_maps; } diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index fa7dfd1b77f31..7994ef314cc67 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -229,7 +229,6 @@ Borrowck results in two maps. use middle::liveness; use middle::mem_categorization::*; use middle::region; -use middle::ty::to_str; use middle::ty; use util::common::indenter; use util::ppaux::{expr_repr, note_and_explain_region}; diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index 13df0b73db0c3..df175a83a31bf 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -24,7 +24,7 @@ use syntax::{visit, ast_util, ast_map}; fn check_crate(sess: Session, crate: @crate, ast_map: ast_map::map, def_map: resolve::DefMap, method_map: typeck::method_map, tcx: ty::ctxt) { - visit::visit_crate(*crate, false, visit::mk_vt(@{ + visit::visit_crate(*crate, false, visit::mk_vt(@visit::Visitor { visit_item: |a,b,c| check_item(sess, ast_map, def_map, a, b, c), visit_pat: check_pat, visit_expr: |a,b,c| @@ -209,7 +209,7 @@ fn check_item_recursion(sess: Session, ast_map: ast_map::map, idstack: @DVec() }; - let visitor = visit::mk_vt(@{ + let visitor = visit::mk_vt(@visit::Visitor { visit_item: visit_item, visit_expr: visit_expr, .. *visit::default_visitor() diff --git a/src/librustc/middle/check_loop.rs b/src/librustc/middle/check_loop.rs index 8844384327045..0e260c54fe26b 100644 --- a/src/librustc/middle/check_loop.rs +++ b/src/librustc/middle/check_loop.rs @@ -19,7 +19,7 @@ type ctx = {in_loop: bool, can_ret: bool}; fn check_crate(tcx: ty::ctxt, crate: @crate) { visit::visit_crate(*crate, {in_loop: false, can_ret: true}, - visit::mk_vt(@{ + visit::mk_vt(@visit::Visitor { visit_item: |i, _cx, v| { visit::visit_item(i, {in_loop: false, can_ret: true}, v); }, diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index dc66df9362498..aaf4656cae892 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -37,7 +37,7 @@ struct MatchCheckCtxt { fn check_crate(tcx: ty::ctxt, method_map: method_map, crate: @crate) { let cx = @MatchCheckCtxt { tcx: tcx, method_map: method_map }; - visit::visit_crate(*crate, (), visit::mk_vt(@{ + visit::visit_crate(*crate, (), visit::mk_vt(@visit::Visitor { visit_expr: |a,b,c| check_expr(cx, a, b, c), visit_local: |a,b,c| check_local(cx, a, b, c), visit_fn: |kind, decl, body, sp, id, e, v| @@ -793,7 +793,7 @@ fn check_legality_of_move_bindings(cx: @MatchCheckCtxt, // Now check to ensure that any move binding is not behind an @ or &. // This is always illegal. - let vt = visit::mk_vt(@{ + let vt = visit::mk_vt(@visit::Visitor { visit_pat: |pat, behind_bad_pointer, v| { let error_out = || { cx.tcx.sess.span_err(pat.span, ~"by-move pattern \ diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index e2de186ca2ffb..3781239ad22a9 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -206,7 +206,7 @@ fn lookup_constness(tcx: ty::ctxt, e: @expr) -> constness { fn process_crate(crate: @ast::crate, def_map: resolve::DefMap, tcx: ty::ctxt) { - let v = visit::mk_simple_visitor(@{ + let v = visit::mk_simple_visitor(@visit::SimpleVisitor { visit_expr_post: |e| { classify(e, def_map, tcx); }, .. *visit::default_simple_visitor() }); diff --git a/src/librustc/middle/freevars.rs b/src/librustc/middle/freevars.rs index 9b718ec3beecd..3c1f261c1f8af 100644 --- a/src/librustc/middle/freevars.rs +++ b/src/librustc/middle/freevars.rs @@ -90,8 +90,9 @@ fn collect_freevars(def_map: resolve::DefMap, blk: ast::blk) } }; - let v = visit::mk_vt(@{visit_item: ignore_item, visit_expr: walk_expr, - .. *visit::default_visitor()}); + let v = visit::mk_vt(@visit::Visitor {visit_item: ignore_item, + visit_expr: walk_expr, + .. *visit::default_visitor()}); (v.visit_block)(blk, 1, v); return @/*bad*/copy *refs; } @@ -112,8 +113,9 @@ fn annotate_freevars(def_map: resolve::DefMap, crate: @ast::crate) -> }; let visitor = - visit::mk_simple_visitor(@{visit_fn: walk_fn, - .. *visit::default_simple_visitor()}); + visit::mk_simple_visitor(@visit::SimpleVisitor { + visit_fn: walk_fn, + .. *visit::default_simple_visitor()}); visit::visit_crate(*crate, (), visitor); return freevars; diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index 671a0a2dc8136..90b067d2d588b 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -96,7 +96,7 @@ fn check_crate(tcx: ty::ctxt, method_map: method_map, last_use_map: last_use_map, current_item: -1}; - let visit = visit::mk_vt(@{ + let visit = visit::mk_vt(@visit::Visitor { visit_arm: check_arm, visit_expr: check_expr, visit_stmt: check_stmt, diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 8c887139b70f1..b57dbffc2d360 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -27,7 +27,7 @@ use metadata::decoder::{dl_def, dl_field, dl_impl}; use syntax::ast::{crate, def_fn, def_id, def_ty, lit_str, meta_item}; use syntax::ast::{meta_list, meta_name_value, meta_word}; use syntax::ast_util::{local_def}; -use syntax::visit::{default_simple_visitor, mk_simple_visitor}; +use syntax::visit::{default_simple_visitor, mk_simple_visitor, SimpleVisitor}; use syntax::visit::{visit_crate, visit_item}; use core::ptr; @@ -331,7 +331,7 @@ impl LanguageItemCollector { fn collect_local_language_items() { let this = unsafe { ptr::addr_of(&self) }; - visit_crate(*self.crate, (), mk_simple_visitor(@{ + visit_crate(*self.crate, (), mk_simple_visitor(@SimpleVisitor { visit_item: |item| { for item.attrs.each |attribute| { unsafe { diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 635e2d18d6c26..fa31201ac49eb 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -429,7 +429,7 @@ fn build_settings_crate(sess: session::Session, crate: @ast::crate) { let cx = ctxt_({is_default: true,.. *cx}); - let visit = visit::mk_vt(@{ + let visit = visit::mk_vt(@visit::Visitor { visit_item: build_settings_item, .. *visit::default_visitor() }); @@ -457,29 +457,31 @@ fn check_item(i: @ast::item, cx: ty::ctxt) { // not traverse into subitems, since that is handled by the outer // lint visitor. fn item_stopping_visitor(v: visit::vt) -> visit::vt { - visit::mk_vt(@{visit_item: |_i, _e, _v| { },.. **v}) + visit::mk_vt(@visit::Visitor {visit_item: |_i, _e, _v| { },.. **v}) } fn check_item_while_true(cx: ty::ctxt, it: @ast::item) { - let visit = item_stopping_visitor(visit::mk_simple_visitor(@{ - visit_expr: fn@(e: @ast::expr) { - match e.node { - ast::expr_while(cond, _) => { - match cond.node { - ast::expr_lit(@{node: ast::lit_bool(true),_}) => { - cx.sess.span_lint( - while_true, e.id, it.id, - e.span, - ~"denote infinite loops with loop { ... }"); + let visit = item_stopping_visitor( + visit::mk_simple_visitor(@visit::SimpleVisitor { + visit_expr: |e: @ast::expr| { + match e.node { + ast::expr_while(cond, _) => { + match cond.node { + ast::expr_lit(@{node: ast::lit_bool(true),_}) => { + cx.sess.span_lint( + while_true, e.id, it.id, + e.span, + ~"denote infinite loops \ + with loop { ... }"); + } + _ => () + } } _ => () } - } - _ => () - } - }, - .. *visit::default_simple_visitor() - })); + }, + .. *visit::default_simple_visitor() + })); visit::visit_item(it, (), visit); } @@ -594,10 +596,11 @@ fn check_item_type_limits(cx: ty::ctxt, it: @ast::item) { } }; - let visit = item_stopping_visitor(visit::mk_simple_visitor(@{ - visit_expr: visit_expr, - .. *visit::default_simple_visitor() - })); + let visit = item_stopping_visitor( + visit::mk_simple_visitor(@visit::SimpleVisitor { + visit_expr: visit_expr, + .. *visit::default_simple_visitor() + })); visit::visit_item(it, (), visit); } @@ -658,19 +661,20 @@ fn check_item_deprecated_self(cx: ty::ctxt, item: @ast::item) { } fn check_item_structural_records(cx: ty::ctxt, it: @ast::item) { - let visit = item_stopping_visitor(visit::mk_simple_visitor(@{ - visit_expr: fn@(e: @ast::expr) { - match e.node { - ast::expr_rec(*) => - cx.sess.span_lint( - structural_records, e.id, it.id, - e.span, - ~"structural records are deprecated"), - _ => () - } - }, - .. *visit::default_simple_visitor() - })); + let visit = item_stopping_visitor( + visit::mk_simple_visitor(@visit::SimpleVisitor { + visit_expr: |e: @ast::expr| { + match e.node { + ast::expr_rec(*) => + cx.sess.span_lint( + structural_records, e.id, it.id, + e.span, + ~"structural records are deprecated"), + _ => () + } + }, + .. *visit::default_simple_visitor() + })); visit::visit_item(it, (), visit); } @@ -777,34 +781,36 @@ fn check_item_heap(cx: ty::ctxt, it: @ast::item) { _ => () } - let visit = item_stopping_visitor(visit::mk_simple_visitor(@{ - visit_expr: fn@(e: @ast::expr) { - let ty = ty::expr_ty(cx, e); - check_type(cx, e.id, it.id, e.span, ty); - }, - .. *visit::default_simple_visitor() - })); + let visit = item_stopping_visitor( + visit::mk_simple_visitor(@visit::SimpleVisitor { + visit_expr: |e: @ast::expr| { + let ty = ty::expr_ty(cx, e); + check_type(cx, e.id, it.id, e.span, ty); + }, + .. *visit::default_simple_visitor() + })); visit::visit_item(it, (), visit); } fn check_item_path_statement(cx: ty::ctxt, it: @ast::item) { - let visit = item_stopping_visitor(visit::mk_simple_visitor(@{ - visit_stmt: fn@(s: @ast::stmt) { - match s.node { - ast::stmt_semi(@{id: id, - callee_id: _, - node: ast::expr_path(_), - span: _}, _) => { - cx.sess.span_lint( - path_statement, id, it.id, - s.span, - ~"path statement with no effect"); - } - _ => () - } - }, - .. *visit::default_simple_visitor() - })); + let visit = item_stopping_visitor( + visit::mk_simple_visitor(@visit::SimpleVisitor { + visit_stmt: |s: @ast::stmt| { + match s.node { + ast::stmt_semi(@{id: id, + callee_id: _, + node: ast::expr_path(_), + span: _}, _) => { + cx.sess.span_lint( + path_statement, id, it.id, + s.span, + ~"path statement with no effect"); + } + _ => () + } + }, + .. *visit::default_simple_visitor() + })); visit::visit_item(it, (), visit); } @@ -973,7 +979,7 @@ fn check_item_deprecated_modes(tcx: ty::ctxt, it: @ast::item) { fn check_crate(tcx: ty::ctxt, crate: @ast::crate) { - let v = visit::mk_simple_visitor(@{ + let v = visit::mk_simple_visitor(@visit::SimpleVisitor { visit_item: |it| check_item(it, tcx), visit_fn: |fk, decl, body, span, id| diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 91e6ed289bd14..2cfda6d74b387 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -205,7 +205,7 @@ fn live_node_kind_to_str(lnk: LiveNodeKind, cx: ty::ctxt) -> ~str { fn check_crate(tcx: ty::ctxt, method_map: typeck::method_map, crate: @crate) -> last_use_map { - let visitor = visit::mk_vt(@{ + let visitor = visit::mk_vt(@visit::Visitor { visit_fn: visit_fn, visit_local: visit_local, visit_expr: visit_expr, @@ -487,7 +487,7 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, let entry_ln = (*lsets).compute(decl, body); // check for various error conditions - let check_vt = visit::mk_vt(@{ + let check_vt = visit::mk_vt(@visit::Visitor { visit_fn: check_fn, visit_local: check_local, visit_expr: check_expr, diff --git a/src/librustc/middle/mode.rs b/src/librustc/middle/mode.rs index a736b3d2fa6a4..397c0e20a6e7e 100644 --- a/src/librustc/middle/mode.rs +++ b/src/librustc/middle/mode.rs @@ -233,7 +233,7 @@ fn compute_modes_for_pat(pat: @pat, } pub fn compute_modes(tcx: ctxt, method_map: method_map, crate: @crate) { - let visitor = visit::mk_vt(@{ + let visitor = visit::mk_vt(@visit::Visitor { visit_expr: compute_modes_for_expr, visit_pat: compute_modes_for_pat, .. *visit::default_visitor() diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 1aa3017083c84..acc5e6410c6a7 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -188,7 +188,7 @@ fn check_crate(tcx: ty::ctxt, method_map: &method_map, crate: @ast::crate) { } }; - let visitor = visit::mk_vt(@{ + let visitor = visit::mk_vt(@visit::Visitor { visit_mod: |the_module, span, node_id, method_map, visitor| { let n_added = add_privileged_items(the_module.items); diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 6f9c3070a0e8e..1d9396ee2c37a 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -351,7 +351,7 @@ fn resolve_crate(sess: Session, def_map: resolve::DefMap, region_map: HashMap(), root_exprs: HashMap(), parent: None}; - let visitor = visit::mk_vt(@{ + let visitor = visit::mk_vt(@visit::Visitor { visit_block: resolve_block, visit_item: resolve_item, visit_fn: resolve_fn, @@ -781,7 +781,7 @@ fn determine_rp_in_crate(sess: Session, mut ambient_variance: rv_covariant}); // Gather up the base set, worklist and dep_map - let visitor = visit::mk_vt(@{ + let visitor = visit::mk_vt(@visit::Visitor { visit_fn: determine_rp_in_fn, visit_item: determine_rp_in_item, visit_ty: determine_rp_in_ty, diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 625ed9076e718..9fa524a3fcd35 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -63,7 +63,7 @@ use syntax::parse::token::ident_interner; use syntax::parse::token::special_idents; use syntax::print::pprust::{pat_to_str, path_to_str}; use syntax::codemap::span; -use syntax::visit::{default_visitor, fk_method, mk_vt, visit_block}; +use syntax::visit::{default_visitor, fk_method, mk_vt, Visitor, visit_block}; use syntax::visit::{visit_crate, visit_expr, visit_expr_opt, visit_fn}; use syntax::visit::{visit_foreign_item, visit_item, visit_method_helper}; use syntax::visit::{visit_mod, visit_ty, vt}; @@ -946,7 +946,7 @@ impl Resolver { fn build_reduced_graph(this: @Resolver) { let initial_parent = ModuleReducedGraphParent((*self.graph_root).get_module()); - visit_crate(*self.crate, initial_parent, mk_vt(@{ + visit_crate(*self.crate, initial_parent, mk_vt(@Visitor { visit_item: |item, context, visitor| (*this).build_reduced_graph_for_item(item, context, visitor), @@ -3790,7 +3790,7 @@ impl Resolver { fn resolve_crate(@self) { debug!("(resolving crate) starting"); - visit_crate(*self.crate, (), mk_vt(@{ + visit_crate(*self.crate, (), mk_vt(@Visitor { visit_item: |item, _context, visitor| self.resolve_item(item, visitor), visit_arm: |arm, _context, visitor| diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 317d0fbfd0386..38c461d595d44 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2370,10 +2370,12 @@ fn trans_constant(ccx: @crate_ctxt, it: @ast::item) { } fn trans_constants(ccx: @crate_ctxt, crate: @ast::crate) { - visit::visit_crate(*crate, (), visit::mk_simple_visitor(@{ - visit_item: |a| trans_constant(ccx, a), - ..*visit::default_simple_visitor() - })); + visit::visit_crate( + *crate, (), + visit::mk_simple_visitor(@visit::SimpleVisitor { + visit_item: |a| trans_constant(ccx, a), + ..*visit::default_simple_visitor() + })); } fn vp2i(cx: block, v: ValueRef) -> ValueRef { diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index 88f908c4c2632..c34b8fd151caa 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -389,7 +389,7 @@ fn trans_rtcall_or_lang_call_with_type_params(bcx: block, fn body_contains_ret(body: ast::blk) -> bool { let cx = {mut found: false}; - visit::visit_block(body, cx, visit::mk_vt(@{ + visit::visit_block(body, cx, visit::mk_vt(@visit::Visitor { visit_item: |_i, _cx, _v| { }, visit_expr: |e: @ast::expr, cx: {mut found: bool}, v| { if !cx.found { diff --git a/src/librustc/middle/trans/reachable.rs b/src/librustc/middle/trans/reachable.rs index 832f4f8294eac..5de7ebadb2b31 100644 --- a/src/librustc/middle/trans/reachable.rs +++ b/src/librustc/middle/trans/reachable.rs @@ -142,7 +142,8 @@ fn traverse_public_item(cx: ctx, item: @item) { } fn mk_ty_visitor() -> visit::vt { - visit::mk_vt(@{visit_ty: traverse_ty, ..*visit::default_visitor()}) + visit::mk_vt(@visit::Visitor {visit_ty: traverse_ty, + ..*visit::default_visitor()}) } fn traverse_ty(ty: @Ty, cx: ctx, v: visit::vt) { @@ -209,7 +210,7 @@ fn traverse_inline_body(cx: ctx, body: blk) { fn traverse_item(i: @item, cx: ctx, _v: visit::vt) { traverse_public_item(cx, i); } - visit::visit_block(body, cx, visit::mk_vt(@{ + visit::visit_block(body, cx, visit::mk_vt(@visit::Visitor { visit_expr: traverse_expr, visit_item: traverse_item, ..*visit::default_visitor() @@ -217,21 +218,23 @@ fn traverse_inline_body(cx: ctx, body: blk) { } fn traverse_all_resources_and_impls(cx: ctx, crate_mod: _mod) { - visit::visit_mod(crate_mod, ast_util::dummy_sp(), 0, cx, visit::mk_vt(@{ - visit_expr: |_e, _cx, _v| { }, - visit_item: |i, cx, v| { - visit::visit_item(i, cx, v); - match i.node { - item_struct(struct_def, _) if struct_def.dtor.is_some() => { - traverse_public_item(cx, i); - } - item_impl(*) => { - traverse_public_item(cx, i); - } - _ => () - } - }, - ..*visit::default_visitor() - })); + visit::visit_mod( + crate_mod, ast_util::dummy_sp(), 0, cx, + visit::mk_vt(@visit::Visitor { + visit_expr: |_e, _cx, _v| { }, + visit_item: |i, cx, v| { + visit::visit_item(i, cx, v); + match i.node { + item_struct(sdef, _) if sdef.dtor.is_some() => { + traverse_public_item(cx, i); + } + item_impl(*) => { + traverse_public_item(cx, i); + } + _ => () + } + }, + ..*visit::default_visitor() + })); } diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs index 1b2fc4e387ad8..e17a9c8c0ede7 100644 --- a/src/librustc/middle/trans/type_use.rs +++ b/src/librustc/middle/trans/type_use.rs @@ -340,7 +340,7 @@ fn mark_for_expr(cx: ctx, e: @expr) { } fn handle_body(cx: ctx, body: blk) { - let v = visit::mk_vt(@{ + let v = visit::mk_vt(@visit::Visitor { visit_expr: |e, cx, v| { visit::visit_expr(e, cx, v); mark_for_expr(cx, e); diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 2880e4b770e16..7c6df9eadf934 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -45,7 +45,7 @@ use syntax::ast::*; use syntax::ast_util::{is_local, local_def}; use syntax::ast_util; use syntax::codemap::span; -use syntax::print::pprust::*; +use syntax::print::pprust; use syntax::{ast, ast_map}; use syntax; @@ -53,7 +53,7 @@ export ProvidedMethodSource; export ProvidedMethodInfo; export ProvidedMethodsMap; export InstantiatedTraitRef; -export TyVid, IntVid, FloatVid, FnVid, RegionVid, vid; +export TyVid, IntVid, FloatVid, FnVid, RegionVid, Vid; export br_hashmap; export is_instantiable; export node_id_to_type; @@ -116,7 +116,8 @@ export ty_opaque_closure_ptr, mk_opaque_closure_ptr; export ty_opaque_box, mk_opaque_box; export ty_float, mk_float, mk_mach_float, type_is_fp; export ty_fn, FnTy, FnTyBase, FnMeta, FnSig, mk_fn; -export ty_fn_proto, ty_fn_purity, ty_fn_ret, tys_in_fn_ty; +export ty_fn_proto, ty_fn_purity, ty_fn_ret, tys_in_fn_sig; +export replace_fn_return_type; export ty_int, mk_int, mk_mach_int, mk_char; export mk_i8, mk_u8, mk_i16, mk_u16, mk_i32, mk_u32, mk_i64, mk_u64; export mk_f32, mk_f64; @@ -137,7 +138,8 @@ export ty_tup, mk_tup; export ty_type, mk_type; export ty_uint, mk_uint, mk_mach_uint; export ty_uniq, mk_uniq, mk_imm_uniq, type_is_unique_box; -export ty_infer, mk_infer, type_is_ty_var, mk_var, mk_int_var, mk_float_var; +export ty_infer, mk_infer, type_is_ty_var, mk_var, mk_int_var; +export mk_float_var; export InferTy, TyVar, IntVar, FloatVar; export ValueMode, ReadValue, CopyValue, MoveValue; export ty_self, mk_self, type_has_self; @@ -220,7 +222,6 @@ export terr_regions_insufficiently_polymorphic; export terr_regions_overly_polymorphic; export terr_proto_mismatch; export terr_fn, terr_trait; -export purity_to_str; export onceness_to_str; export param_tys_in_type; export eval_repeat_count; @@ -517,6 +518,7 @@ pure fn type_id(t: t) -> uint { get(t).id } * 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] struct FnMeta { purity: ast::purity, proto: ast::Proto, @@ -531,6 +533,7 @@ struct FnMeta { * * - `inputs` is the list of arguments and their modes. * - `output` is the return type. */ +#[deriving_eq] struct FnSig { inputs: ~[arg], output: t @@ -541,9 +544,16 @@ struct FnSig { * type signature. This particular type is parameterized * by the meta information because, in some cases, the * meta information is inferred. */ +#[deriving_eq] struct FnTyBase { - meta: M, - sig: FnSig + meta: M, // Either FnMeta or FnVid + sig: FnSig // Types of arguments/return type +} + +impl FnTyBase : 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) + } } type FnTy = FnTyBase; @@ -671,7 +681,7 @@ enum sty { ty_param(param_ty), // type parameter ty_self, // special, implicit `self` type parameter - ty_infer(InferTy), // soething used only during inference/typeck + ty_infer(InferTy), // something used only during inference/typeck ty_err, // Also only used during inference/typeck, to represent // the type of an erroneous expression (helps cut down // on non-useful type error messages) @@ -740,6 +750,7 @@ enum FnVid = uint; #[auto_decode] enum RegionVid = uint; +#[deriving_eq] enum InferTy { TyVar(TyVid), IntVar(IntVid), @@ -751,7 +762,7 @@ impl InferTy : to_bytes::IterBytes { match *self { TyVar(ref tv) => to_bytes::iter_bytes_2(&0u8, tv, lsb0, f), IntVar(ref iv) => to_bytes::iter_bytes_2(&1u8, iv, lsb0, f), - FloatVar(ref fv) => to_bytes::iter_bytes_2(&2u8, fv, lsb0, f) + FloatVar(ref fv) => to_bytes::iter_bytes_2(&2u8, fv, lsb0, f), } } } @@ -802,61 +813,64 @@ impl param_bound : to_bytes::IterBytes { } } -trait vid { +trait Vid { pure fn to_uint() -> uint; - pure fn to_str() -> ~str; } -impl TyVid: vid { +impl TyVid: Vid { pure fn to_uint() -> uint { *self } +} + +impl TyVid: ToStr { pure fn to_str() -> ~str { fmt!("", self.to_uint()) } } -impl IntVid: vid { +impl IntVid: Vid { pure fn to_uint() -> uint { *self } +} + +impl IntVid: ToStr { pure fn to_str() -> ~str { fmt!("", self.to_uint()) } } -impl FloatVid: vid { +impl FloatVid: Vid { pure fn to_uint() -> uint { *self } +} + +impl FloatVid: ToStr { pure fn to_str() -> ~str { fmt!("", self.to_uint()) } } -impl FnVid: vid { +impl FnVid: Vid { pure fn to_uint() -> uint { *self } +} + +impl FnVid: ToStr { pure fn to_str() -> ~str { fmt!("", self.to_uint()) } } -impl RegionVid: vid { +impl RegionVid: Vid { pure fn to_uint() -> uint { *self } - pure fn to_str() -> ~str { fmt!("%?", self) } } -impl InferTy { - pure fn to_hash() -> uint { - match self { - TyVar(v) => v.to_uint() << 1, - IntVar(v) => (v.to_uint() << 1) + 1, - FloatVar(v) => (v.to_uint() << 1) + 2 - } - } +impl RegionVid: ToStr { + pure fn to_str() -> ~str { fmt!("%?", self) } +} +impl FnSig : ToStr { pure fn to_str() -> ~str { - match self { - TyVar(v) => v.to_str(), - IntVar(v) => v.to_str(), - FloatVar(v) => v.to_str() - } + // grr, without tcx not much we can do. + return ~"(...)"; } } -trait purity_to_str { - pure fn to_str() -> ~str; -} - -impl purity: purity_to_str { +impl InferTy: ToStr { pure fn to_str() -> ~str { - purity_to_str(self) + match self { + TyVar(ref v) => v.to_str(), + IntVar(ref v) => v.to_str(), + FloatVar(ref v) => v.to_str() + } } } @@ -1195,7 +1209,7 @@ fn mk_int_var(cx: ctxt, v: IntVid) -> t { mk_infer(cx, IntVar(v)) } fn mk_float_var(cx: ctxt, v: FloatVid) -> t { mk_infer(cx, FloatVar(v)) } -fn mk_infer(cx: ctxt, it: InferTy) -> t { mk_t(cx, ty_infer(it)) } +fn mk_infer(cx: ctxt, +it: InferTy) -> t { mk_t(cx, ty_infer(it)) } fn mk_self(cx: ctxt) -> t { mk_t(cx, ty_self) } @@ -1367,15 +1381,8 @@ fn fold_sty(sty: &sty, fldop: fn(t) -> t) -> sty { ty_tup(new_ts) } ty_fn(ref f) => { - let new_args = f.sig.inputs.map(|a| { - let new_ty = fldop(a.ty); - {mode: a.mode, ty: new_ty} - }); - let new_output = fldop(f.sig.output); - ty_fn(FnTyBase { - meta: f.meta, - sig: FnSig {inputs: new_args, output: new_output} - }) + let sig = fold_sig(&f.sig, fldop); + ty_fn(FnTyBase {meta: f.meta, sig: sig}) } ty_rptr(r, tm) => { ty_rptr(r, {ty: fldop(tm.ty), mutbl: tm.mutbl}) @@ -1422,8 +1429,8 @@ fn fold_regions_and_ty( fn fold_substs( substs: &substs, fldr: fn(r: Region) -> Region, - fldt: fn(t: t) -> t) -> substs { - + fldt: fn(t: t) -> t) -> substs + { {self_r: substs.self_r.map(|r| fldr(*r)), self_ty: substs.self_ty.map(|t| fldt(*t)), tps: substs.tps.map(|t| fldt(*t))} @@ -1455,18 +1462,9 @@ fn fold_regions_and_ty( ty::mk_trait(cx, def_id, fold_substs(substs, fldr, fldt), vst) } ty_fn(ref f) => { - let new_region = fldr(f.meta.region); - let new_args = vec::map(f.sig.inputs, |a| { - let new_ty = fldfnt(a.ty); - {mode: a.mode, ty: new_ty} - }); - let new_output = fldfnt(f.sig.output); - ty::mk_fn(cx, FnTyBase { - meta: FnMeta {region: new_region, - ..f.meta}, - sig: FnSig {inputs: new_args, - output: new_output} - }) + ty::mk_fn(cx, FnTyBase {meta: FnMeta {region: fldr(f.meta.region), + ..f.meta}, + sig: fold_sig(&f.sig, fldfnt)}) } ref sty => { fold_sty_to_ty(cx, sty, |t| fldt(t)) @@ -1507,6 +1505,7 @@ fn fold_regions( { fn do_fold(cx: ctxt, ty: t, in_fn: bool, fldr: fn(Region, bool) -> Region) -> t { + debug!("do_fold(ty=%s, in_fn=%b)", ty_to_str(cx, ty), in_fn); if !type_has_regions(ty) { return ty; } fold_regions_and_ty( cx, ty, @@ -2832,8 +2831,9 @@ impl arg : to_bytes::IterBytes { impl FnMeta : to_bytes::IterBytes { pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { - to_bytes::iter_bytes_4(&self.purity, + to_bytes::iter_bytes_5(&self.purity, &self.proto, + &self.onceness, &self.region, &self.bounds, lsb0, f); @@ -2885,10 +2885,7 @@ impl sty : to_bytes::IterBytes { to_bytes::iter_bytes_2(&11u8, fs, lsb0, f), ty_fn(ref ft) => - to_bytes::iter_bytes_3(&12u8, - &ft.meta, - &ft.sig, - lsb0, f), + to_bytes::iter_bytes_2(&12u8, ft, lsb0, f), ty_self => 13u8.iter_bytes(lsb0, f), @@ -2976,8 +2973,8 @@ fn ty_fn_purity(fty: t) -> ast::purity { pure fn ty_fn_ret(fty: t) -> t { match get(fty).sty { - ty_fn(ref f) => f.sig.output, - _ => fail ~"ty_fn_ret() called on non-fn type" + ty_fn(ref f) => f.sig.output, + _ => fail ~"ty_fn_ret() called on non-fn type" } } @@ -2995,9 +2992,30 @@ fn ty_region(ty: t) -> Region { } } +fn replace_fn_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} + }) + } + _ => { + tcx.sess.bug(fmt!( + "replace_fn_ret() invoked with non-fn-type: %s", + ty_to_str(tcx, fn_type))); + } + } +} + // Returns a vec of all the input and output types of fty. -fn tys_in_fn_ty(fty: &FnTy) -> ~[t] { - vec::append_one(fty.sig.inputs.map(|a| a.ty), fty.sig.output) +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, @@ -3442,18 +3460,16 @@ fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str { terr_mismatch => ~"types differ", terr_purity_mismatch(values) => { fmt!("expected %s fn but found %s fn", - purity_to_str(values.expected), - purity_to_str(values.found)) + values.expected.to_str(), values.found.to_str()) } terr_onceness_mismatch(values) => { fmt!("expected %s fn but found %s fn", - onceness_to_str(values.expected), - onceness_to_str(values.found)) + values.expected.to_str(), values.found.to_str()) } terr_proto_mismatch(values) => { fmt!("expected %s closure, found %s closure", - proto_ty_to_str(cx, values.expected), - proto_ty_to_str(cx, values.found)) + proto_ty_to_str(cx, values.expected, false), + proto_ty_to_str(cx, values.found, false)) } terr_mutability => ~"values differ in mutability", terr_box_mutability => ~"boxed values differ in mutability", @@ -3487,7 +3503,8 @@ fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str { terr_arg_count => ~"incorrect number of function parameters", terr_mode_mismatch(values) => { fmt!("expected argument mode %s, but found %s", - mode_to_str(values.expected), mode_to_str(values.found)) + pprust::mode_to_str(values.expected), + pprust::mode_to_str(values.found)) } terr_regions_does_not_outlive(*) => { fmt!("lifetime mismatch") @@ -4396,30 +4413,6 @@ impl vstore : cmp::Eq { pure fn ne(&self, other: &vstore) -> bool { !(*self).eq(other) } } -impl FnMeta : cmp::Eq { - pure fn eq(&self, other: &FnMeta) -> bool { - (*self).purity == (*other).purity && - (*self).proto == (*other).proto && - (*self).bounds == (*other).bounds - } - pure fn ne(&self, other: &FnMeta) -> bool { !(*self).eq(other) } -} - -impl FnSig : cmp::Eq { - pure fn eq(&self, other: &FnSig) -> bool { - (*self).inputs == (*other).inputs && - (*self).output == (*other).output - } - pure fn ne(&self, other: &FnSig) -> bool { !(*self).eq(other) } -} - -impl FnTyBase : cmp::Eq { - pure fn eq(&self, other: &FnTyBase) -> bool { - (*self).meta == (*other).meta && (*self).sig == (*other).sig - } - pure fn ne(&self, other: &FnTyBase) -> bool { !(*self).eq(other) } -} - impl TyVid : cmp::Eq { pure fn eq(&self, other: &TyVid) -> bool { *(*self) == *(*other) } pure fn ne(&self, other: &TyVid) -> bool { *(*self) != *(*other) } @@ -4530,13 +4523,6 @@ impl substs : cmp::Eq { pure fn ne(&self, other: &substs) -> bool { !(*self).eq(other) } } -impl InferTy : cmp::Eq { - pure fn eq(&self, other: &InferTy) -> bool { - (*self).to_hash() == (*other).to_hash() - } - pure fn ne(&self, other: &InferTy) -> bool { !(*self).eq(other) } -} - impl sty : cmp::Eq { pure fn eq(&self, other: &sty) -> bool { match (/*bad*/copy *self) { @@ -4649,9 +4635,9 @@ impl sty : cmp::Eq { _ => false } } - ty_infer(e0a) => { + ty_infer(ref e0a) => { match (*other) { - ty_infer(e0b) => e0a == e0b, + ty_infer(ref e0b) => *e0a == *e0b, _ => false } } diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index f903270e15cba..b683770822dd9 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -1127,7 +1127,7 @@ impl LookupContext { ty::item_path_str(self.tcx(), did))); } - fn infcx(&self) -> infer::infer_ctxt { + fn infcx(&self) -> @infer::InferCtxt { self.fcx.inh.infcx } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index bd8b6934e0db4..9bbfc5dd7d2b8 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -80,7 +80,8 @@ type parameter). use middle::capture; use middle::const_eval; use middle::pat_util; -use middle::ty::{TyVid, vid, FnTyBase, FnMeta, FnSig, VariantInfo_}; +use middle::ty::{TyVid, Vid, FnTyBase, FnMeta, FnSig, VariantInfo_}; +use middle::ty::{re_bound, br_cap_avoid}; use middle::ty; use middle::typeck::astconv::{ast_conv, ast_path_to_ty}; use middle::typeck::astconv::{ast_region_to_region, ast_ty_to_ty}; @@ -88,6 +89,7 @@ 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::infer::{resolve_type, force_tvar}; use middle::typeck::infer; @@ -165,7 +167,7 @@ type self_info = { /// `bar()` will each have their own `fn_ctxt`, but they will /// share the inherited fields. struct inherited { - infcx: infer::infer_ctxt, + infcx: @infer::InferCtxt, locals: HashMap, node_types: HashMap, node_type_substs: HashMap, @@ -243,7 +245,7 @@ fn blank_fn_ctxt(ccx: @crate_ctxt, rty: ty::t, } fn check_item_types(ccx: @crate_ctxt, crate: @ast::crate) { - let visit = visit::mk_simple_visitor(@{ + let visit = visit::mk_simple_visitor(@visit::SimpleVisitor { visit_item: |a| check_item(ccx, a), .. *visit::default_simple_visitor() }); @@ -251,7 +253,7 @@ fn check_item_types(ccx: @crate_ctxt, crate: @ast::crate) { } fn check_bare_fn(ccx: @crate_ctxt, - decl: ast::fn_decl, + decl: &ast::fn_decl, body: ast::blk, id: ast::node_id, self_info: Option) { @@ -268,7 +270,7 @@ fn check_bare_fn(ccx: @crate_ctxt, fn check_fn(ccx: @crate_ctxt, self_info: Option, fn_ty: &ty::FnTy, - decl: ast::fn_decl, + decl: &ast::fn_decl, body: ast::blk, fn_kind: FnKind, old_fcx: Option<@fn_ctxt>) { @@ -283,15 +285,15 @@ fn check_fn(ccx: @crate_ctxt, // types with free ones. The free region references will be bound // the node_id of the body block. - let {isr: isr, self_info: self_info, fn_ty: fn_ty} = { + 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_ty(tcx, old_isr, self_info, fn_ty, - |br| ty::re_free(body.node.id, br)) + |fcx| fcx.in_scope_regions); + replace_bound_regions_in_fn_sig(tcx, old_isr, self_info, &fn_ty.sig, + |br| ty::re_free(body.node.id, br)) }; - let arg_tys = fn_ty.sig.inputs.map(|a| a.ty); - let ret_ty = fn_ty.sig.output; + let arg_tys = fn_sig.inputs.map(|a| a.ty); + let ret_ty = fn_sig.output; debug!("check_fn(arg_tys=%?, ret_ty=%?, self_info.self_ty=%?)", arg_tys.map(|a| ppaux::ty_to_str(tcx, *a)), @@ -384,12 +386,12 @@ fn check_fn(ccx: @crate_ctxt, // resolved when the enclosing scope finishes up. if old_fcx.is_none() { vtable::resolve_in_block(fcx, body); - regionck::regionck_fn(fcx, decl, body); + regionck::regionck_fn(fcx, body); writeback::resolve_type_vars_in_fn(fcx, decl, body, self_info); } fn gather_locals(fcx: @fn_ctxt, - decl: ast::fn_decl, + decl: &ast::fn_decl, body: ast::blk, arg_tys: ~[ty::t], self_info: Option) { @@ -481,12 +483,13 @@ fn check_fn(ccx: @crate_ctxt, } fn visit_item(_i: @ast::item, &&_e: (), _v: visit::vt<()>) { } - let visit = visit::mk_vt(@{visit_local: visit_local, - visit_pat: visit_pat, - visit_fn: visit_fn, - visit_item: visit_item, - visit_block: visit_block, - .. *visit::default_visitor()}); + let visit = visit::mk_vt( + @visit::Visitor {visit_local: visit_local, + visit_pat: visit_pat, + visit_fn: visit_fn, + visit_item: visit_item, + visit_block: visit_block, + ..*visit::default_visitor()}); (visit.visit_block)(body, (), visit); } @@ -498,7 +501,7 @@ fn check_method(ccx: @crate_ctxt, method: @ast::method, self_id: method.self_id, def_id: self_impl_def_id, explicit_self: method.self_ty }; - check_bare_fn(ccx, method.decl, method.body, method.id, Some(self_info)); + check_bare_fn(ccx, &method.decl, method.body, method.id, Some(self_info)); } fn check_no_duplicate_fields(tcx: ty::ctxt, fields: @@ -536,7 +539,8 @@ fn check_struct(ccx: @crate_ctxt, struct_def: @ast::struct_def, explicit_self: {node: ast::sty_by_ref, span: ast_util::dummy_sp()}}; // typecheck the dtor - check_bare_fn(ccx, ast_util::dtor_dec(), + let dtor_dec = ast_util::dtor_dec(); + check_bare_fn(ccx, &dtor_dec, dtor.node.body, dtor.node.id, Some(class_t)); }; @@ -560,7 +564,7 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) { it.id); } ast::item_fn(ref decl, _, _, ref body) => { - check_bare_fn(ccx, *decl, (*body), it.id, None); + check_bare_fn(ccx, decl, (*body), it.id, None); } ast::item_impl(_, _, ty, ms) => { let rp = ccx.tcx.region_paramd_items.find(it.id); @@ -634,7 +638,7 @@ impl @fn_ctxt: ast_conv { } impl @fn_ctxt { - fn infcx() -> infer::infer_ctxt { self.inh.infcx } + fn infcx() -> @infer::InferCtxt { self.inh.infcx } fn search_in_scope_regions(br: ty::bound_region) -> Result { @@ -1496,7 +1500,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, fn check_expr_fn(fcx: @fn_ctxt, expr: @ast::expr, ast_proto_opt: Option, - decl: ast::fn_decl, + decl: &ast::fn_decl, body: ast::blk, fn_kind: FnKind, expected: Option) { @@ -1546,7 +1550,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, fcx, fcx, proto, purity, expected_onceness, /*bounds:*/ @~[], /*opt_region:*/ None, - decl, expected_tys, expr.span); + *decl, expected_tys, expr.span); // XXX: Bad copy. let fty = ty::mk_fn(tcx, copy fn_ty); @@ -2134,12 +2138,12 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, } ast::expr_fn(proto, ref decl, ref body, cap_clause) => { check_expr_fn(fcx, expr, Some(proto), - *decl, (*body), Vanilla, expected); + decl, (*body), Vanilla, expected); capture::check_capture_clause(tcx, expr.id, cap_clause); } ast::expr_fn_block(ref decl, ref body, cap_clause) => { check_expr_fn(fcx, expr, None, - *decl, (*body), Vanilla, expected); + decl, (*body), Vanilla, expected); capture::check_capture_clause(tcx, expr.id, cap_clause); } ast::expr_loop_body(b) => { @@ -2195,7 +2199,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, match b.node { ast::expr_fn_block(ref decl, ref body, cap_clause) => { check_expr_fn(fcx, b, None, - *decl, (*body), ForLoop, Some(inner_ty)); + decl, *body, ForLoop, Some(inner_ty)); demand::suptype(fcx, b.span, inner_ty, fcx.expr_ty(b)); capture::check_capture_clause(tcx, b.id, cap_clause); } @@ -2204,20 +2208,12 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, } let block_ty = structurally_resolved_type( fcx, expr.span, fcx.node_ty(b.id)); - match ty::get(block_ty).sty { - ty::ty_fn(ref fty) => { - if !err_happened { - fcx.write_ty(expr.id, ty::mk_fn(tcx, FnTyBase { - meta: (*fty).meta, - sig: FnSig {output: ty::mk_bool(tcx), - ../*bad*/copy (*fty).sig} - })); - } - else { - fcx.write_ty(expr.id, ty::mk_err(fcx.tcx())); - } - } - _ => fail ~"expected fn type" + 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_do_body(b) => { @@ -2244,21 +2240,14 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, match b.node { ast::expr_fn_block(ref decl, ref body, cap_clause) => { check_expr_fn(fcx, b, None, - *decl, (*body), DoBlock, Some(inner_ty)); + decl, *body, DoBlock, Some(inner_ty)); demand::suptype(fcx, b.span, inner_ty, fcx.expr_ty(b)); capture::check_capture_clause(tcx, b.id, cap_clause); } // argh _ => fail ~"expected fn ty" } - let block_ty = structurally_resolved_type( - fcx, expr.span, fcx.node_ty(b.id)); - match ty::get(block_ty).sty { - ty::ty_fn(ref fty) => { - fcx.write_ty(expr.id, ty::mk_fn(tcx, (/*bad*/copy *fty))); - } - _ => fail ~"expected fn ty" - } + fcx.write_ty(expr.id, fcx.node_ty(b.id)); } ast::expr_block(ref b) => { // If this is an unchecked block, turn off purity-checking diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index c74b5789075e8..b9619d4f91a44 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -109,7 +109,6 @@ fn regionck_expr(fcx: @fn_ctxt, e: @ast::expr) { } fn regionck_fn(fcx: @fn_ctxt, - _decl: ast::fn_decl, blk: ast::blk) { let rcx = rcx_({fcx:fcx, mut errors_reported: 0}); let v = regionck_visitor(); @@ -118,12 +117,12 @@ fn regionck_fn(fcx: @fn_ctxt, } fn regionck_visitor() -> rvt { - visit::mk_vt(@{visit_item: visit_item, - visit_stmt: visit_stmt, - visit_expr: visit_expr, - visit_block: visit_block, - visit_local: visit_local, - .. *visit::default_visitor()}) + visit::mk_vt(@visit::Visitor {visit_item: visit_item, + visit_stmt: visit_stmt, + visit_expr: visit_expr, + visit_block: visit_block, + visit_local: visit_local, + .. *visit::default_visitor()}) } fn visit_item(_item: @ast::item, &&_rcx: @rcx, _v: rvt) { diff --git a/src/librustc/middle/typeck/check/regionmanip.rs b/src/librustc/middle/typeck/check/regionmanip.rs index c7000bb7e70ba..33a9976f74c9b 100644 --- a/src/librustc/middle/typeck/check/regionmanip.rs +++ b/src/librustc/middle/typeck/check/regionmanip.rs @@ -18,22 +18,37 @@ use syntax::print::pprust::{expr_to_str}; // Helper functions related to manipulating region types. -fn replace_bound_regions_in_fn_ty( +pub fn replace_bound_regions_in_fn_ty( tcx: ty::ctxt, isr: isr_alist, self_info: Option, fn_ty: &ty::FnTy, mapf: fn(ty::bound_region) -> ty::Region) -> - {isr: isr_alist, self_info: Option, fn_ty: ty::FnTy} { + {isr: isr_alist, self_info: Option, 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, + self_info: Option, + fn_sig: &ty::FnSig, + mapf: fn(ty::bound_region) -> ty::Region) -> + {isr: isr_alist, self_info: Option, fn_sig: ty::FnSig} +{ // Take self_info apart; the self_ty part is the only one we want // to update here. - let (self_ty, rebuild_self_info) = match self_info { - Some(copy s) => (Some(s.self_ty), |t| Some({self_ty: t,.. s})), - None => (None, |_t| None) - }; + let self_ty = self_info.map(|s| s.self_ty); + let rebuild_self_info = |t| self_info.map(|s| {self_ty: t, ..*s}); - let mut all_tys = ty::tys_in_fn_ty(fn_ty); + let mut all_tys = ty::tys_in_fn_sig(fn_sig); match self_info { Some({explicit_self: {node: ast::sty_region(m), _}, _}) => { @@ -48,10 +63,10 @@ fn replace_bound_regions_in_fn_ty( for self_ty.each |t| { all_tys.push(*t) } - debug!("replace_bound_regions_in_fn_ty(self_info.self_ty=%?, fn_ty=%s, \ - all_tys=%?)", + debug!("replace_bound_regions_in_fn_sig(self_info.self_ty=%?, fn_sig=%s, \ + all_tys=%?)", self_ty.map(|t| ppaux::ty_to_str(tcx, *t)), - ppaux::ty_to_str(tcx, ty::mk_fn(tcx, *fn_ty)), + ppaux::fn_sig_to_str(tcx, fn_sig), all_tys.map(|t| ppaux::ty_to_str(tcx, *t))); let _i = indenter(); @@ -59,17 +74,15 @@ fn replace_bound_regions_in_fn_ty( debug!("br=%?", br); mapf(br) }; - let ty_fn = ty::ty_fn(/*bad*/copy *fn_ty); - let t_fn = ty::fold_sty_to_ty(tcx, &ty_fn, |t| { + let new_fn_sig = ty::fold_sig(fn_sig, |t| { replace_bound_regions(tcx, isr, t) }); let t_self = self_ty.map(|t| replace_bound_regions(tcx, isr, *t)); - debug!("result of replace_bound_regions_in_fn_ty: self_info.self_ty=%?, \ - fn_ty=%s", + debug!("result of replace_bound_regions_in_fn_sig: self_info.self_ty=%?, \ + fn_sig=%s", t_self.map(|t| ppaux::ty_to_str(tcx, *t)), - ppaux::ty_to_str(tcx, t_fn)); - + ppaux::fn_sig_to_str(tcx, &new_fn_sig)); // Glue updated self_ty back together with its original def_id. let new_self_info: Option = match t_self { @@ -78,10 +91,8 @@ fn replace_bound_regions_in_fn_ty( }; return {isr: isr, - self_info: new_self_info, - fn_ty: match ty::get(t_fn).sty { ty::ty_fn(ref o) => /*bad*/copy *o, - _ => tcx.sess.bug(~"replace_bound_regions_in_fn_ty: impossible")}}; - + self_info: new_self_info, + fn_sig: new_fn_sig}; // Takes `isr`, a (possibly empty) mapping from in-scope region // names ("isr"s) to their corresponding regions; `tys`, a list of @@ -150,7 +161,7 @@ fn replace_bound_regions_in_fn_ty( ty: ty::t) -> ty::t { do ty::fold_regions(tcx, ty) |r, in_fn| { - match r { + let r1 = match r { // As long as we are not within a fn() type, `&T` is // mapped to the free region anon_r. But within a fn // type, it remains bound. @@ -179,7 +190,8 @@ fn replace_bound_regions_in_fn_ty( ty::re_scope(_) | ty::re_free(_, _) | ty::re_infer(_) => r - } + }; + r1 } } } diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 0872b1445c3e9..4f1efed09af95 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -12,7 +12,7 @@ use middle::resolve; use middle::ty; use middle::typeck::check::{fn_ctxt, impl_self_ty}; -use middle::typeck::infer::{fixup_err_to_str, infer_ctxt}; +use middle::typeck::infer::{fixup_err_to_str, InferCtxt}; use middle::typeck::infer::{resolve_and_force_all_but_regions, resolve_type}; use middle::typeck::infer; use util::common::indenter; @@ -56,7 +56,7 @@ struct LocationInfo { /// callback function to call in case of type error. struct VtableContext { ccx: @crate_ctxt, - infcx: infer::infer_ctxt + infcx: @infer::InferCtxt } impl VtableContext { @@ -678,8 +678,8 @@ fn early_resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, is_early: bool) { ex.span, fmt!("failed to find an implementation of trait \ %s for %s", - ppaux::ty_to_str(fcx.tcx(), target_ty), - ppaux::ty_to_str(fcx.tcx(), ty))); + fcx.infcx().ty_to_str(target_ty), + fcx.infcx().ty_to_str(ty))); } } Some(vtable) => { @@ -707,7 +707,7 @@ fn resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, v: visit::vt<@fn_ctxt>) { // Detect points where a trait-bounded type parameter is // instantiated, resolve the impls for the parameters. fn resolve_in_block(fcx: @fn_ctxt, bl: ast::blk) { - visit::visit_block(bl, fcx, visit::mk_vt(@{ + visit::visit_block(bl, fcx, visit::mk_vt(@visit::Visitor { visit_expr: resolve_expr, visit_item: fn@(_i: @ast::item, &&_e: @fn_ctxt, _v: visit::vt<@fn_ctxt>) {}, diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs index 623c280ac226b..128fd37d4003e 100644 --- a/src/librustc/middle/typeck/check/writeback.rs +++ b/src/librustc/middle/typeck/check/writeback.rs @@ -155,9 +155,8 @@ fn visit_expr(e: @ast::expr, wbcx: wb_ctxt, v: wb_vt) { resolve_type_vars_for_node(wbcx, e.span, e.id); resolve_method_map_entry(wbcx.fcx, e.span, e.id); resolve_method_map_entry(wbcx.fcx, e.span, e.callee_id); - match /*bad*/copy e.node { - ast::expr_fn(_, decl, _, _) | - ast::expr_fn_block(decl, _, _) => { + match e.node { + ast::expr_fn_block(ref decl, _, _) => { for vec::each(decl.inputs) |input| { let r_ty = resolve_type_vars_for_node(wbcx, e.span, input.id); @@ -231,13 +230,13 @@ fn visit_item(_item: @ast::item, _wbcx: wb_ctxt, _v: wb_vt) { } fn mk_visitor() -> visit::vt { - visit::mk_vt(@{visit_item: visit_item, - visit_stmt: visit_stmt, - visit_expr: visit_expr, - visit_block: visit_block, - visit_pat: visit_pat, - visit_local: visit_local, - .. *visit::default_visitor()}) + visit::mk_vt(@visit::Visitor {visit_item: visit_item, + visit_stmt: visit_stmt, + visit_expr: visit_expr, + visit_block: visit_block, + visit_pat: visit_pat, + visit_local: visit_local, + .. *visit::default_visitor()}) } fn resolve_type_vars_in_expr(fcx: @fn_ctxt, e: @ast::expr) -> bool { @@ -248,7 +247,7 @@ fn resolve_type_vars_in_expr(fcx: @fn_ctxt, e: @ast::expr) -> bool { } fn resolve_type_vars_in_fn(fcx: @fn_ctxt, - decl: ast::fn_decl, + decl: &ast::fn_decl, blk: ast::blk, self_info: Option) -> bool { let wbcx = {fcx: fcx, mut success: true}; diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 0116214b5f9e6..dab47bd25b857 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -31,7 +31,7 @@ use middle::ty::{ty_param, ty_self, ty_type, ty_opaque_box, ty_uniq}; use middle::ty::{ty_opaque_closure_ptr, ty_unboxed_vec, type_kind_ext}; use middle::ty::{type_is_ty_var}; use middle::ty; -use middle::typeck::infer::{infer_ctxt, can_mk_subty}; +use middle::typeck::infer::{InferCtxt, can_mk_subty}; use middle::typeck::infer::{new_infer_ctxt, resolve_ivar}; use middle::typeck::infer::{resolve_nested_tvar, resolve_type}; use syntax::ast::{crate, def_id, def_mod, def_ty}; @@ -48,6 +48,7 @@ use syntax::codemap::span; use syntax::parse; use syntax::visit::{default_simple_visitor, default_visitor}; use syntax::visit::{mk_simple_visitor, mk_vt, visit_crate, visit_item}; +use syntax::visit::{Visitor, SimpleVisitor}; use syntax::visit::{visit_mod}; use util::ppaux::ty_to_str; @@ -66,7 +67,7 @@ struct UniversalQuantificationResult { bounds: @~[param_bounds] } -fn get_base_type(inference_context: infer_ctxt, span: span, original_type: t) +fn get_base_type(inference_context: @InferCtxt, span: span, original_type: t) -> Option { let resolved_type; @@ -113,7 +114,7 @@ fn get_base_type(inference_context: infer_ctxt, span: span, original_type: t) } // Returns the def ID of the base type, if there is one. -fn get_base_type_def_id(inference_context: infer_ctxt, +fn get_base_type_def_id(inference_context: @InferCtxt, span: span, original_type: t) -> Option { @@ -178,7 +179,7 @@ fn CoherenceChecker(crate_context: @crate_ctxt) -> CoherenceChecker { struct CoherenceChecker { crate_context: @crate_ctxt, - inference_context: infer_ctxt, + inference_context: @InferCtxt, // A mapping from implementations to the corresponding base type // definition ID. @@ -196,7 +197,7 @@ impl CoherenceChecker { // Check implementations and traits. This populates the tables // containing the inherent methods and extension methods. It also // builds up the trait inheritance table. - visit_crate(*crate, (), mk_simple_visitor(@{ + visit_crate(*crate, (), mk_simple_visitor(@SimpleVisitor { visit_item: |item| { debug!("(checking coherence) item '%s'", self.crate_context.tcx.sess.str_of(item.ident)); @@ -585,7 +586,7 @@ impl CoherenceChecker { // Privileged scope checking fn check_privileged_scopes(crate: @crate) { - visit_crate(*crate, (), mk_vt(@{ + visit_crate(*crate, (), mk_vt(@Visitor { visit_item: |item, _context, visitor| { match /*bad*/copy item.node { item_mod(module_) => { diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index e8d424b899fe3..e17eafa7cfae7 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -93,11 +93,13 @@ fn collect_item_types(ccx: @crate_ctxt, crate: @ast::crate) { } } - visit::visit_crate(*crate, (), visit::mk_simple_visitor(@{ - visit_item: |a|convert(ccx, a), - visit_foreign_item: |a|convert_foreign(ccx, a), - .. *visit::default_simple_visitor() - })); + visit::visit_crate( + *crate, (), + visit::mk_simple_visitor(@visit::SimpleVisitor { + visit_item: |a|convert(ccx, a), + visit_foreign_item: |a|convert_foreign(ccx, a), + .. *visit::default_simple_visitor() + })); } impl @crate_ctxt { diff --git a/src/librustc/middle/typeck/infer/assignment.rs b/src/librustc/middle/typeck/infer/assignment.rs index 8eb3e0336dfb2..a26079c6f959a 100644 --- a/src/librustc/middle/typeck/infer/assignment.rs +++ b/src/librustc/middle/typeck/infer/assignment.rs @@ -60,13 +60,13 @@ use middle::ty; -use middle::typeck::infer::combine::combine_fields; -use middle::typeck::infer::to_str::ToStr; +use middle::typeck::infer::combine::CombineFields; +use middle::typeck::infer::to_str::InferStr; use core::option; use syntax::ast; -fn to_ares(+c: cres) -> ares { +fn to_ares(+c: cres) -> ares { match c { Ok(_) => Ok(None), Err(ref e) => Err((*e)) @@ -76,13 +76,13 @@ fn to_ares(+c: cres) -> ares { // Note: Assign is not actually a combiner, in that it does not // conform to the same interface, though it performs a similar // function. -enum Assign = combine_fields; +enum Assign = CombineFields; impl Assign { fn tys(a: ty::t, b: ty::t) -> ares { debug!("Assign.tys(%s => %s)", - a.to_str(self.infcx), - b.to_str(self.infcx)); + a.inf_str(self.infcx), + b.inf_str(self.infcx)); let _r = indenter(); debug!("Assign.tys: copying first type"); @@ -140,8 +140,8 @@ priv impl Assign { +a_bnd: Option, +b_bnd: Option) -> ares { debug!("Assign.assign_tys_or_sub(%s => %s, %s => %s)", - a.to_str(self.infcx), b.to_str(self.infcx), - a_bnd.to_str(self.infcx), b_bnd.to_str(self.infcx)); + a.inf_str(self.infcx), b.inf_str(self.infcx), + a_bnd.inf_str(self.infcx), b_bnd.inf_str(self.infcx)); let _r = indenter(); fn is_borrowable(v: ty::vstore) -> bool { @@ -204,18 +204,28 @@ priv impl Assign { let nr_b = ty::mk_fn(self.infcx.tcx, ty::FnTyBase { meta: ty::FnMeta {proto: a_f.meta.proto, ..b_f.meta}, - sig: /*bad*/copy b_f.sig + sig: copy b_f.sig }); self.try_assign(0, ty::AutoBorrowFn, a, nr_b, m_imm, b_f.meta.region) } + (ty::ty_fn(ref a_f), ty::ty_fn(ref b_f)) + if a_f.meta.proto == ast::ProtoBare => { + let b1_f = ty::FnTyBase { + meta: ty::FnMeta {proto: ast::ProtoBare, + ..b_f.meta}, + sig: copy b_f.sig + }; + // Eventually we will need to add some sort of + // adjustment here so that trans can add an + // extra NULL env pointer: + to_ares(Sub(*self).fns(a_f, &b1_f)) + } + // check for &T being assigned to *T: (ty::ty_rptr(_, ref a_t), ty::ty_ptr(ref b_t)) => { - match Sub(*self).mts(*a_t, *b_t) { - Ok(_) => Ok(None), - Err(ref e) => Err((*e)) - } + to_ares(Sub(*self).mts(*a_t, *b_t)) } // otherwise, assignment follows normal subtype rules: @@ -246,10 +256,10 @@ priv impl Assign { r_b: ty::Region) -> ares { debug!("try_assign(a=%s, nr_b=%s, m=%?, r_b=%s)", - a.to_str(self.infcx), - nr_b.to_str(self.infcx), + a.inf_str(self.infcx), + nr_b.inf_str(self.infcx), m, - r_b.to_str(self.infcx)); + r_b.inf_str(self.infcx)); do indent { let sub = Sub(*self); diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs index f790939f4e7d2..ec6205c9d680c 100644 --- a/src/librustc/middle/typeck/infer/combine.rs +++ b/src/librustc/middle/typeck/infer/combine.rs @@ -57,7 +57,7 @@ use middle::ty; use middle::ty::{FnTyBase, FnMeta, FnSig}; use middle::typeck::infer::sub::Sub; -use middle::typeck::infer::to_str::ToStr; +use middle::typeck::infer::to_str::InferStr; use core::vec; use syntax::ast::Onceness; @@ -65,8 +65,8 @@ use syntax::ast; fn macros() { include!("macros.rs"); } // FIXME(#3114): Macro import/export. -trait combine { - fn infcx() -> infer_ctxt; +trait Combine { + fn infcx() -> @InferCtxt; fn tag() -> ~str; fn a_is_expected() -> bool; fn span() -> span; @@ -97,13 +97,13 @@ trait combine { a: ty::vstore, b: ty::vstore) -> cres; } -pub struct combine_fields { - infcx: infer_ctxt, +pub struct CombineFields { + infcx: @InferCtxt, a_is_expected: bool, span: span, } -fn expected_found( +fn expected_found( self: &C, +a: T, +b: T) -> ty::expected_found { if self.a_is_expected() { @@ -113,7 +113,7 @@ fn expected_found( } } -pub fn eq_tys(self: &C, a: ty::t, b: ty::t) -> ures { +pub fn eq_tys(self: &C, a: ty::t, b: ty::t) -> ures { let suber = self.sub(); do self.infcx().try { do suber.tys(a, b).chain |_ok| { @@ -122,10 +122,10 @@ pub fn eq_tys(self: &C, a: ty::t, b: ty::t) -> ures { } } -fn eq_regions(self: &C, a: ty::Region, b: ty::Region) -> ures { +fn eq_regions(self: &C, a: ty::Region, b: ty::Region) -> ures { debug!("eq_regions(%s, %s)", - a.to_str(self.infcx()), - b.to_str(self.infcx())); + a.inf_str(self.infcx()), + b.inf_str(self.infcx())); let sub = self.sub(); do indent { self.infcx().try(|| { @@ -144,7 +144,7 @@ fn eq_regions(self: &C, a: ty::Region, b: ty::Region) -> ures { } } -fn eq_opt_regions( +fn eq_opt_regions( self: &C, a: Option, b: Option) -> cres> { @@ -166,17 +166,17 @@ fn eq_opt_regions( self.infcx().tcx.sess.bug( fmt!("substitution a had opt_region %s and \ b had opt_region %s", - a.to_str(self.infcx()), - b.to_str(self.infcx()))); + a.inf_str(self.infcx()), + b.inf_str(self.infcx()))); } } } -fn super_substs( +fn super_substs( self: &C, did: ast::def_id, a: &ty::substs, b: &ty::substs) -> cres { - fn relate_region_param( + fn relate_region_param( self: &C, did: ast::def_id, a: Option, @@ -212,8 +212,8 @@ fn super_substs( self.infcx().tcx.sess.bug( fmt!("substitution a had opt_region %s and \ b had opt_region %s with variance %?", - a.to_str(self.infcx()), - b.to_str(self.infcx()), + a.inf_str(self.infcx()), + b.inf_str(self.infcx()), polyty.region_param)); } } @@ -230,7 +230,7 @@ fn super_substs( } } -fn super_tps( +fn super_tps( self: &C, as_: &[ty::t], bs: &[ty::t]) -> cres<~[ty::t]> { // Note: type parameters are always treated as *invariant* @@ -248,7 +248,7 @@ fn super_tps( } } -fn super_self_tys( +fn super_self_tys( self: &C, a: Option, b: Option) -> cres> { // Note: the self type parameter is (currently) always treated as @@ -271,7 +271,17 @@ fn super_self_tys( } } -fn super_flds( +fn super_protos( + self: &C, p1: ast::Proto, p2: ast::Proto) -> cres +{ + if p1 == p2 { + Ok(p1) + } else { + Err(ty::terr_proto_mismatch(expected_found(self, p1, p2))) + } +} + +fn super_flds( self: &C, a: ty::field, b: ty::field) -> cres { if a.ident == b.ident { @@ -284,7 +294,7 @@ fn super_flds( } } -fn super_modes( +fn super_modes( self: &C, a: ast::mode, b: ast::mode) -> cres { @@ -292,7 +302,7 @@ fn super_modes( ty::unify_mode(tcx, expected_found(self, a, b)) } -fn super_args( +fn super_args( self: &C, a: ty::arg, b: ty::arg) -> cres { @@ -303,7 +313,7 @@ fn super_args( } } -fn super_vstores( +fn super_vstores( self: &C, vk: ty::terr_vstore_kind, a: ty::vstore, b: ty::vstore) -> cres { @@ -326,7 +336,7 @@ fn super_vstores( } } -fn super_fn_metas( +fn super_fn_metas( self: &C, a_f: &ty::FnMeta, b_f: &ty::FnMeta) -> cres { let p = if_ok!(self.protos(a_f.proto, b_f.proto)); @@ -335,17 +345,18 @@ fn super_fn_metas( let onceness = if_ok!(self.oncenesses(a_f.onceness, b_f.onceness)); Ok(FnMeta {purity: purity, proto: p, - region: r, onceness: onceness, + region: r, bounds: a_f.bounds}) // XXX: This is wrong! } -fn super_fn_sigs( - self: &C, a_f: &ty::FnSig, b_f: &ty::FnSig) -> cres { - fn argvecs(self: &C, +fn super_fn_sigs( + self: &C, a_f: &ty::FnSig, b_f: &ty::FnSig) -> cres +{ + fn argvecs(self: &C, +a_args: ~[ty::arg], - +b_args: ~[ty::arg]) -> cres<~[ty::arg]> { - + +b_args: ~[ty::arg]) -> cres<~[ty::arg]> + { if vec::same_length(a_args, b_args) { map_vec2(a_args, b_args, |a, b| self.args(*a, *b)) } else { @@ -361,19 +372,17 @@ fn super_fn_sigs( } } -fn super_fns( +fn super_fns( self: &C, a_f: &ty::FnTy, b_f: &ty::FnTy) -> cres { - do self.fn_metas(&a_f.meta, &b_f.meta).chain |m| { - do self.fn_sigs(&a_f.sig, &b_f.sig).chain |s| { - Ok(FnTyBase {meta: m, sig: s}) - } - } + 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}) } -fn super_tys( - self: &C, a: ty::t, b: ty::t) -> cres { - +fn super_tys( + self: &C, a: ty::t, b: ty::t) -> cres +{ let tcx = self.infcx().tcx; match (/*bad*/copy ty::get(a).sty, /*bad*/copy ty::get(b).sty) { // The "subtype" ought to be handling cases involving bot or var: @@ -384,32 +393,49 @@ fn super_tys( tcx.sess.bug( fmt!("%s: bot and var types should have been handled (%s,%s)", self.tag(), - a.to_str(self.infcx()), - b.to_str(self.infcx()))); + a.inf_str(self.infcx()), + b.inf_str(self.infcx()))); } // Relate integral variables to other types (ty::ty_infer(IntVar(a_id)), ty::ty_infer(IntVar(b_id))) => { - self.infcx().int_vars(a_id, b_id).then(|| Ok(a) ) + if_ok!(self.infcx().simple_vars(&self.infcx().int_var_bindings, + ty::terr_no_integral_type, + a_id, b_id)); + Ok(a) } - (ty::ty_infer(IntVar(a_id)), ty::ty_int(_)) | - (ty::ty_infer(IntVar(a_id)), ty::ty_uint(_)) => { - self.infcx().int_var_sub_t(a_id, b).then(|| Ok(a) ) + (ty::ty_infer(IntVar(v_id)), ty::ty_int(v)) | + (ty::ty_int(v), ty::ty_infer(IntVar(v_id))) => { + if v == ast::ty_char { + Err(ty::terr_integer_as_char) + } else { + if_ok!(self.infcx().simple_var_t(&self.infcx().int_var_bindings, + ty::terr_no_integral_type, + v_id, IntType(v))); + Ok(ty::mk_mach_int(tcx, v)) + } } - (ty::ty_int(_), ty::ty_infer(IntVar(b_id))) | - (ty::ty_uint(_), ty::ty_infer(IntVar(b_id))) => { - self.infcx().t_sub_int_var(a, b_id).then(|| Ok(a) ) + (ty::ty_infer(IntVar(v_id)), ty::ty_uint(v)) | + (ty::ty_uint(v), ty::ty_infer(IntVar(v_id))) => { + if_ok!(self.infcx().simple_var_t(&self.infcx().int_var_bindings, + ty::terr_no_integral_type, + v_id, UintType(v))); + Ok(ty::mk_mach_uint(tcx, v)) } // Relate floating-point variables to other types (ty::ty_infer(FloatVar(a_id)), ty::ty_infer(FloatVar(b_id))) => { - self.infcx().float_vars(a_id, b_id).then(|| Ok(a) ) - } - (ty::ty_infer(FloatVar(a_id)), ty::ty_float(_)) => { - self.infcx().float_var_sub_t(a_id, b).then(|| Ok(a) ) + if_ok!(self.infcx().simple_vars(&self.infcx().float_var_bindings, + ty::terr_no_floating_point_type, + a_id, b_id)); + Ok(a) } - (ty::ty_float(_), ty::ty_infer(FloatVar(b_id))) => { - self.infcx().t_sub_float_var(a, b_id).then(|| Ok(a) ) + (ty::ty_infer(FloatVar(v_id)), ty::ty_float(v)) | + (ty::ty_float(v), ty::ty_infer(FloatVar(v_id))) => { + if_ok!(self.infcx().simple_var_t(&self.infcx().float_var_bindings, + ty::terr_no_floating_point_type, + v_id, v)); + Ok(ty::mk_mach_float(tcx, v)) } (ty::ty_int(_), _) | diff --git a/src/librustc/middle/typeck/infer/floating.rs b/src/librustc/middle/typeck/infer/floating.rs deleted file mode 100644 index 85a11a598e908..0000000000000 --- a/src/librustc/middle/typeck/infer/floating.rs +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/*! - -Code related to floating-point type inference. - -*/ - - -use middle::ty; -use middle::ty::ty_float; -use middle::typeck::infer::to_str::ToStr; - -use core::uint; -use syntax::ast; - -// Bitvector to represent sets of floating-point types. -pub enum float_ty_set = uint; - -// Constants representing singleton sets containing each of the floating-point -// types. -pub const FLOAT_TY_SET_EMPTY: uint = 0b000u; -pub const FLOAT_TY_SET_FLOAT: uint = 0b001u; -pub const FLOAT_TY_SET_F32: uint = 0b010u; -pub const FLOAT_TY_SET_F64: uint = 0b100u; - -pub fn float_ty_set_all() -> float_ty_set { - float_ty_set(FLOAT_TY_SET_FLOAT | FLOAT_TY_SET_F32 | FLOAT_TY_SET_F64) -} - -pub fn intersection(a: float_ty_set, b: float_ty_set) -> float_ty_set { - float_ty_set(*a & *b) -} - -pub fn single_type_contained_in(tcx: ty::ctxt, a: float_ty_set) - -> Option { - debug!("single_type_contained_in(a=%s)", uint::to_str(*a, 10)); - - if *a == FLOAT_TY_SET_FLOAT { return Some(ty::mk_float(tcx)); } - if *a == FLOAT_TY_SET_F32 { return Some(ty::mk_f32(tcx)); } - if *a == FLOAT_TY_SET_F64 { return Some(ty::mk_f64(tcx)); } - return None; -} - -pub fn convert_floating_point_ty_to_float_ty_set(tcx: ty::ctxt, t: ty::t) - -> float_ty_set { - match get(t).sty { - ty::ty_float(ast::ty_f) => float_ty_set(FLOAT_TY_SET_FLOAT), - ty::ty_float(ast::ty_f32) => float_ty_set(FLOAT_TY_SET_F32), - ty::ty_float(ast::ty_f64) => float_ty_set(FLOAT_TY_SET_F64), - _ => tcx.sess.bug(~"non-floating-point type passed to \ - convert_floating_point_ty_to_float_ty_set()") - } -} - diff --git a/src/librustc/middle/typeck/infer/glb.rs b/src/librustc/middle/typeck/infer/glb.rs index 920b058770acb..f53d9c3a4093c 100644 --- a/src/librustc/middle/typeck/infer/glb.rs +++ b/src/librustc/middle/typeck/infer/glb.rs @@ -13,16 +13,16 @@ use middle::ty; use middle::typeck::infer::combine::*; use middle::typeck::infer::lattice::*; use middle::typeck::infer::sub::Sub; -use middle::typeck::infer::to_str::ToStr; +use middle::typeck::infer::to_str::InferStr; use std::list; use syntax::ast::{Many, Once}; -enum Glb = combine_fields; // "greatest lower bound" (common subtype) +enum Glb = CombineFields; // "greatest lower bound" (common subtype) -impl Glb: combine { - fn infcx() -> infer_ctxt { self.infcx } +impl Glb: Combine { + fn infcx() -> @InferCtxt { self.infcx } fn tag() -> ~str { ~"glb" } fn a_is_expected() -> bool { self.a_is_expected } fn span() -> span { self.span } @@ -88,10 +88,6 @@ impl Glb: combine { Lub(*self).tys(a, b) } - fn protos(p1: ast::Proto, p2: ast::Proto) -> cres { - if p1 == p2 {Ok(p1)} else {Ok(ast::ProtoBare)} - } - fn purities(a: purity, b: purity) -> cres { match (a, b) { (pure_fn, _) | (_, pure_fn) => Ok(pure_fn), @@ -111,8 +107,8 @@ impl Glb: combine { fn regions(a: ty::Region, b: ty::Region) -> cres { debug!("%s.regions(%?, %?)", self.tag(), - a.to_str(self.infcx), - b.to_str(self.infcx)); + a.inf_str(self.infcx), + b.inf_str(self.infcx)); do indent { self.infcx.region_vars.glb_regions(self.span, a, b) @@ -124,7 +120,7 @@ impl Glb: combine { } fn tys(a: ty::t, b: ty::t) -> cres { - lattice_tys(&self, a, b) + super_lattice_tys(&self, a, b) } // Traits please (FIXME: #2794): @@ -146,12 +142,12 @@ impl Glb: combine { super_args(&self, a, b) } - fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres { + fn fn_sigs(a: &ty::FnSig, b: &ty::FnSig) -> cres { // Note: this is a subtle algorithm. For a full explanation, // please see the large comment in `region_inference.rs`. - debug!("%s.fns(%?, %?)", - self.tag(), a.to_str(self.infcx), b.to_str(self.infcx)); + debug!("%s.fn_sigs(%?, %?)", + self.tag(), a.inf_str(self.infcx), b.inf_str(self.infcx)); let _indenter = indenter(); // Take a snapshot. We'll never roll this back, but in later @@ -171,20 +167,20 @@ impl Glb: combine { let b_vars = var_ids(&self, b_isr); // Collect constraints. - let fn_ty0 = if_ok!(super_fns(&self, &a_with_fresh, &b_with_fresh)); - debug!("fn_ty0 = %s", fn_ty0.to_str(self.infcx)); + let sig0 = if_ok!(super_fn_sigs(&self, &a_with_fresh, &b_with_fresh)); + debug!("sig0 = %s", sig0.inf_str(self.infcx)); // Generalize the regions appearing in fn_ty0 if possible let new_vars = self.infcx.region_vars.vars_created_since_snapshot(snapshot); - let fn_ty1 = + let sig1 = self.infcx.fold_regions_in_sig( - &fn_ty0, + &sig0, |r, _in_fn| generalize_region(&self, snapshot, new_vars, a_isr, a_vars, b_vars, r)); - debug!("fn_ty1 = %s", fn_ty1.to_str(self.infcx)); - return Ok(move fn_ty1); + debug!("sig1 = %s", sig1.inf_str(self.infcx)); + return Ok(move sig1); fn generalize_region(self: &Glb, snapshot: uint, @@ -265,12 +261,16 @@ impl Glb: combine { } } - fn fn_metas(a: &ty::FnMeta, b: &ty::FnMeta) -> cres { - super_fn_metas(&self, a, b) + fn protos(p1: ast::Proto, p2: ast::Proto) -> cres { + super_protos(&self, p1, p2) } - fn fn_sigs(a: &ty::FnSig, b: &ty::FnSig) -> cres { - super_fn_sigs(&self, a, b) + fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres { + super_fns(&self, a, b) + } + + fn fn_metas(a: &ty::FnMeta, b: &ty::FnMeta) -> cres { + super_fn_metas(&self, a, b) } fn substs(did: ast::def_id, diff --git a/src/librustc/middle/typeck/infer/integral.rs b/src/librustc/middle/typeck/infer/integral.rs deleted file mode 100644 index e6701182342f5..0000000000000 --- a/src/librustc/middle/typeck/infer/integral.rs +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/*! - -Code related to integral type inference. - -*/ - -use middle::ty; -use middle::typeck::infer::to_str::ToStr; - -use core::uint; -use syntax::ast; - -// Bitvector to represent sets of integral types -enum int_ty_set = uint; - -// Constants representing singleton sets containing each of the -// integral types -const INT_TY_SET_EMPTY : uint = 0b00_0000_0000u; -const INT_TY_SET_i8 : uint = 0b00_0000_0001u; -const INT_TY_SET_u8 : uint = 0b00_0000_0010u; -const INT_TY_SET_i16 : uint = 0b00_0000_0100u; -const INT_TY_SET_u16 : uint = 0b00_0000_1000u; -const INT_TY_SET_i32 : uint = 0b00_0001_0000u; -const INT_TY_SET_u32 : uint = 0b00_0010_0000u; -const INT_TY_SET_i64 : uint = 0b00_0100_0000u; -const INT_TY_SET_u64 : uint = 0b00_1000_0000u; -const INT_TY_SET_i : uint = 0b01_0000_0000u; -const INT_TY_SET_u : uint = 0b10_0000_0000u; - -fn int_ty_set_all() -> int_ty_set { - int_ty_set(INT_TY_SET_i8 | INT_TY_SET_u8 | - INT_TY_SET_i16 | INT_TY_SET_u16 | - INT_TY_SET_i32 | INT_TY_SET_u32 | - INT_TY_SET_i64 | INT_TY_SET_u64 | - INT_TY_SET_i | INT_TY_SET_u) -} - -fn intersection(a: int_ty_set, b: int_ty_set) -> int_ty_set { - int_ty_set(*a & *b) -} - -fn single_type_contained_in(tcx: ty::ctxt, a: int_ty_set) -> - Option { - debug!("single_type_contained_in(a=%s)", uint::to_str(*a, 10u)); - - if *a == INT_TY_SET_i8 { return Some(ty::mk_i8(tcx)); } - if *a == INT_TY_SET_u8 { return Some(ty::mk_u8(tcx)); } - if *a == INT_TY_SET_i16 { return Some(ty::mk_i16(tcx)); } - if *a == INT_TY_SET_u16 { return Some(ty::mk_u16(tcx)); } - if *a == INT_TY_SET_i32 { return Some(ty::mk_i32(tcx)); } - if *a == INT_TY_SET_u32 { return Some(ty::mk_u32(tcx)); } - if *a == INT_TY_SET_i64 { return Some(ty::mk_i64(tcx)); } - if *a == INT_TY_SET_u64 { return Some(ty::mk_u64(tcx)); } - if *a == INT_TY_SET_i { return Some(ty::mk_int(tcx)); } - if *a == INT_TY_SET_u { return Some(ty::mk_uint(tcx)); } - return None; -} - -fn convert_integral_ty_to_int_ty_set(tcx: ty::ctxt, t: ty::t) - -> int_ty_set { - - match get(t).sty { - ty_int(int_ty) => match int_ty { - ast::ty_i8 => int_ty_set(INT_TY_SET_i8), - ast::ty_i16 => int_ty_set(INT_TY_SET_i16), - ast::ty_i32 => int_ty_set(INT_TY_SET_i32), - ast::ty_i64 => int_ty_set(INT_TY_SET_i64), - ast::ty_i => int_ty_set(INT_TY_SET_i), - ast::ty_char => tcx.sess.bug( - ~"char type passed to convert_integral_ty_to_int_ty_set()") - }, - ty_uint(uint_ty) => match uint_ty { - ast::ty_u8 => int_ty_set(INT_TY_SET_u8), - ast::ty_u16 => int_ty_set(INT_TY_SET_u16), - ast::ty_u32 => int_ty_set(INT_TY_SET_u32), - ast::ty_u64 => int_ty_set(INT_TY_SET_u64), - ast::ty_u => int_ty_set(INT_TY_SET_u) - }, - _ => tcx.sess.bug(~"non-integral type passed to \ - convert_integral_ty_to_int_ty_set()") - } -} diff --git a/src/librustc/middle/typeck/infer/lattice.rs b/src/librustc/middle/typeck/infer/lattice.rs index ea994c238c61d..f02e3328afaf9 100644 --- a/src/librustc/middle/typeck/infer/lattice.rs +++ b/src/librustc/middle/typeck/infer/lattice.rs @@ -8,156 +8,481 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +/*! + * + * # Lattice Variables + * + * This file contains generic code for operating on inference variables + * that are characterized by an upper- and lower-bound. The logic and + * reasoning is explained in detail in the large comment in `infer.rs`. + * + * The code in here is defined quite generically so that it can be + * applied both to type variables, which represent types being inferred, + * and fn variables, which represent function types being inferred. + * It may eventually be applied to ther types as well, who knows. + * In some cases, the functions are also generic with respect to the + * operation on the lattice (GLB vs LUB). + * + * Although all the functions are generic, we generally write the + * comments in a way that is specific to type variables and the LUB + * operation. It's just easier that way. + * + * In general all of the functions are defined parametrically + * over a `LatticeValue`, which is a value defined with respect to + * a lattice. + */ use middle::ty; use middle::typeck::infer::combine::*; use middle::typeck::infer::unify::*; -use middle::typeck::infer::to_str::ToStr; +use middle::typeck::infer::sub::Sub; +use middle::typeck::infer::lub::Lub; +use middle::typeck::infer::glb::Glb; +use middle::typeck::infer::to_str::InferStr; +use core::either::{Either, Left, Right}; use std::list; +trait LatticeValue { + static fn sub(cf: &CombineFields, a: &self, b: &self) -> ures; + static fn lub(cf: &CombineFields, a: &self, b: &self) -> cres; + static fn glb(cf: &CombineFields, a: &self, b: &self) -> cres; +} + +type LatticeOp = &fn(cf: &CombineFields, a: &T, b: &T) -> cres; + +impl ty::t: LatticeValue { + static fn sub(cf: &CombineFields, a: &ty::t, b: &ty::t) -> ures { + Sub(*cf).tys(*a, *b).to_ures() + } + + static fn lub(cf: &CombineFields, a: &ty::t, b: &ty::t) -> cres { + Lub(*cf).tys(*a, *b) + } + + static fn glb(cf: &CombineFields, a: &ty::t, b: &ty::t) -> cres { + Glb(*cf).tys(*a, *b) + } +} + +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 { + Lub(*cf).fn_metas(a, b) + } + + static fn glb(cf: &CombineFields, + a: &FnMeta, b: &FnMeta) -> cres { + Glb(*cf).fn_metas(a, b) + } +} + +impl CombineFields { + fn var_sub_var( + &self, + vb: &ValsAndBindings>, + +a_id: V, + +b_id: V) -> ures + { + /*! + * + * Make one variable a subtype of another variable. This is a + * subtle and tricky process, as described in detail at the + * top of infer.rs*/ + + // Need to make sub_id a subtype of sup_id. + let node_a = self.infcx.get(vb, a_id); + let node_b = self.infcx.get(vb, b_id); + let a_id = node_a.root; + let b_id = node_b.root; + let a_bounds = node_a.possible_types; + let b_bounds = node_b.possible_types; + + debug!("vars(%s=%s <: %s=%s)", + a_id.to_str(), a_bounds.inf_str(self.infcx), + b_id.to_str(), b_bounds.inf_str(self.infcx)); + + if a_id == b_id { return uok(); } + + // If both A's UB and B's LB have already been bound to types, + // see if we can make those types subtypes. + match (a_bounds.ub, b_bounds.lb) { + (Some(ref a_ub), Some(ref b_lb)) => { + let r = self.infcx.try( + || LatticeValue::sub(self, a_ub, b_lb)); + match r { + Ok(()) => { + return Ok(()); + } + Err(_) => { /*fallthrough */ } + } + } + _ => { /*fallthrough*/ } + } + + // Otherwise, we need to merge A and B so as to guarantee that + // A remains a subtype of B. Actually, there are other options, + // but that's the route we choose to take. + + self.infcx.unify(vb, &node_a, &node_b, |new_root, new_rank| { + self.set_var_to_merged_bounds(vb, new_root, + &a_bounds, &b_bounds, + new_rank) + }) + } + + /// make variable a subtype of T + fn var_sub_t( + &self, + vb: &ValsAndBindings>, + +a_id: V, + +b: T) -> ures + { + /*! + * + * Make a variable (`a_id`) a subtype of the concrete type `b` */ + + let node_a = self.infcx.get(vb, a_id); + let a_id = node_a.root; + let a_bounds = &node_a.possible_types; + let b_bounds = &{lb: None, ub: Some(b)}; + + debug!("var_sub_t(%s=%s <: %s)", + a_id.to_str(), + a_bounds.inf_str(self.infcx), + b.inf_str(self.infcx)); + + self.set_var_to_merged_bounds( + vb, a_id, a_bounds, b_bounds, node_a.rank) + } + + fn t_sub_var( + &self, + vb: &ValsAndBindings>, + +a: T, + +b_id: V) -> ures + { + /*! + * + * Make a concrete type (`a`) a subtype of the variable `b_id` */ + + let a_bounds = &{lb: Some(a), ub: None}; + let node_b = self.infcx.get(vb, b_id); + let b_id = node_b.root; + let b_bounds = &node_b.possible_types; + + debug!("t_sub_var(%s <: %s=%s)", + a.inf_str(self.infcx), + b_id.to_str(), + b_bounds.inf_str(self.infcx)); + + self.set_var_to_merged_bounds( + vb, b_id, a_bounds, b_bounds, node_b.rank) + } + + fn merge_bnd( + &self, + a: &Bound, + b: &Bound, + lattice_op: LatticeOp) + -> cres> + { + /*! + * + * Combines two bounds into a more general bound. */ + + debug!("merge_bnd(%s,%s)", + a.inf_str(self.infcx), + b.inf_str(self.infcx)); + let _r = indenter(); + + match (*a, *b) { + (None, None) => Ok(None), + (Some(_), None) => Ok(*a), + (None, Some(_)) => Ok(*b), + (Some(ref v_a), Some(ref v_b)) => { + do lattice_op(self, v_a, v_b).chain |v| { + Ok(Some(v)) + } + } + } + } + + fn set_var_to_merged_bounds( + &self, + vb: &ValsAndBindings>, + +v_id: V, + a: &Bounds, + b: &Bounds, + rank: uint) -> ures + { + /*! + * + * Updates the bounds for the variable `v_id` to be the intersection + * of `a` and `b`. That is, the new bounds for `v_id` will be + * a bounds c such that: + * c.ub <: a.ub + * c.ub <: b.ub + * a.lb <: c.lb + * b.lb <: c.lb + * If this cannot be achieved, the result is failure. */ + + // Think of the two diamonds, we want to find the + // intersection. There are basically four possibilities (you + // can swap A/B in these pictures): + // + // A A + // / \ / \ + // / B \ / B \ + // / / \ \ / / \ \ + // * * * * * / * * + // \ \ / / \ / / + // \ B / / \ / / + // \ / * \ / + // A \ / A + // B + + debug!("merge(%s,%s,%s)", + v_id.to_str(), + a.inf_str(self.infcx), + b.inf_str(self.infcx)); + let _indent = indenter(); + + // First, relate the lower/upper bounds of A and B. + // Note that these relations *must* hold for us to + // to be able to merge A and B at all, and relating + // them explicitly gives the type inferencer more + // information and helps to produce tighter bounds + // when necessary. + let () = if_ok!(self.bnds(&a.lb, &b.ub)); + let () = if_ok!(self.bnds(&b.lb, &a.ub)); + let ub = if_ok!(self.merge_bnd(&a.ub, &b.ub, LatticeValue::glb)); + let lb = if_ok!(self.merge_bnd(&a.lb, &b.lb, LatticeValue::lub)); + let bounds = {lb: lb, ub: ub}; + debug!("merge(%s): bounds=%s", + v_id.to_str(), + bounds.inf_str(self.infcx)); + + // the new bounds must themselves + // be relatable: + let () = if_ok!(self.bnds(&bounds.lb, &bounds.ub)); + self.infcx.set(vb, v_id, Root(bounds, rank)); + uok() + } + + fn bnds( + &self, + a: &Bound, + b: &Bound) -> ures + { + debug!("bnds(%s <: %s)", a.inf_str(self.infcx), + b.inf_str(self.infcx)); + let _r = indenter(); + + match (*a, *b) { + (None, None) | + (Some(_), None) | + (None, Some(_)) => { + uok() + } + (Some(ref t_a), Some(ref t_b)) => { + LatticeValue::sub(self, t_a, t_b) + } + } + } +} + // ______________________________________________________________________ // Lattice operations on variables // // This is common code used by both LUB and GLB to compute the LUB/GLB // for pairs of variables or for variables and values. -trait lattice_ops { - fn bnd(b: bounds) -> Option; - fn with_bnd(b: bounds, t: ty::t) -> bounds; +trait LatticeDir { + fn combine_fields() -> CombineFields; + fn bnd(b: &Bounds) -> Option; + fn with_bnd(b: &Bounds, +t: T) -> Bounds; +} + +trait TyLatticeDir { fn ty_bot(t: ty::t) -> cres; } -impl Lub: lattice_ops { - fn bnd(b: bounds) -> Option { b.ub } - fn with_bnd(b: bounds, t: ty::t) -> bounds { - {ub: Some(t),.. b} +impl Lub: LatticeDir { + fn combine_fields() -> CombineFields { *self } + fn bnd(b: &Bounds) -> Option { b.ub } + fn with_bnd(b: &Bounds, +t: T) -> Bounds { + {ub: Some(t), ..*b} } +} + +impl Lub: TyLatticeDir { fn ty_bot(t: ty::t) -> cres { Ok(t) } } -impl Glb: lattice_ops { - fn bnd(b: bounds) -> Option { b.lb } - fn with_bnd(b: bounds, t: ty::t) -> bounds { - {lb: Some(t),.. b} +impl Glb: LatticeDir { + fn combine_fields() -> CombineFields { *self } + fn bnd(b: &Bounds) -> Option { b.lb } + fn with_bnd(b: &Bounds, +t: T) -> Bounds { + {lb: Some(t), ..*b} } +} + +impl Glb: TyLatticeDir { fn ty_bot(_t: ty::t) -> cres { Ok(ty::mk_bot(self.infcx.tcx)) } } -fn lattice_tys( - self: &L, a: ty::t, b: ty::t) -> cres { - +fn super_lattice_tys( + self: &L, + a: ty::t, + b: ty::t) -> cres +{ debug!("%s.lattice_tys(%s, %s)", self.tag(), - a.to_str(self.infcx()), - b.to_str(self.infcx())); - if a == b { return Ok(a); } - do indent { - match (ty::get(a).sty, ty::get(b).sty) { - (ty::ty_bot, _) => self.ty_bot(b), - (_, ty::ty_bot) => self.ty_bot(a), - - (ty::ty_infer(TyVar(a_id)), ty::ty_infer(TyVar(b_id))) => { - lattice_vars(self, a, a_id, b_id, - |x, y| self.tys(x, y) ) - } - - (ty::ty_infer(TyVar(a_id)), _) => { - lattice_var_and_t(self, a_id, b, - |x, y| self.tys(x, y) ) - } - - (_, ty::ty_infer(TyVar(b_id))) => { - lattice_var_and_t(self, b_id, a, - |x, y| self.tys(x, y) ) - } - _ => { - super_tys(self, a, b) - } + a.inf_str(self.infcx()), + b.inf_str(self.infcx())); + let _r = indenter(); + + if a == b { + return Ok(a); + } + + let tcx = self.infcx().tcx; + + match (ty::get(a).sty, ty::get(b).sty) { + (ty::ty_bot, _) => { return self.ty_bot(b); } + (_, ty::ty_bot) => { return self.ty_bot(a); } + + (ty::ty_infer(TyVar(a_id)), ty::ty_infer(TyVar(b_id))) => { + let r = if_ok!(lattice_vars(self, &self.infcx().ty_var_bindings, + a_id, b_id, + |x, y| self.tys(*x, *y))); + return match r { + Left(v) => Ok(ty::mk_var(tcx, v)), + Right(t) => Ok(t) + }; + } + + (ty::ty_infer(TyVar(a_id)), _) => { + return lattice_var_and_t(self, &self.infcx().ty_var_bindings, + a_id, &b, + |x, y| self.tys(*x, *y)); + } + + (_, ty::ty_infer(TyVar(b_id))) => { + return lattice_var_and_t(self, &self.infcx().ty_var_bindings, + b_id, &a, + |x, y| self.tys(*x, *y)); + } + + _ => { + return super_tys(self, a, b); } } } -fn lattice_vars( - self: &L, +a_t: ty::t, +a_vid: ty::TyVid, +b_vid: ty::TyVid, - c_ts: fn(ty::t, ty::t) -> cres) -> cres { +type LatticeDirOp = &fn(a: &T, b: &T) -> cres; +fn lattice_vars( + self: &L, + vb: &ValsAndBindings>, + +a_vid: V, + +b_vid: V, + lattice_dir_op: LatticeDirOp) + -> cres> +{ // The comments in this function are written for LUB and types, // but they apply equally well to GLB and regions if you inverse // upper/lower/sub/super/etc. // Need to find a type that is a supertype of both a and b: - let vb = &self.infcx().ty_var_bindings; let nde_a = self.infcx().get(vb, a_vid); let nde_b = self.infcx().get(vb, b_vid); let a_vid = nde_a.root; let b_vid = nde_b.root; - let a_bounds = nde_a.possible_types; - let b_bounds = nde_b.possible_types; + let a_bounds = &nde_a.possible_types; + let b_bounds = &nde_b.possible_types; debug!("%s.lattice_vars(%s=%s <: %s=%s)", self.tag(), - a_vid.to_str(), a_bounds.to_str(self.infcx()), - b_vid.to_str(), b_bounds.to_str(self.infcx())); + a_vid.to_str(), a_bounds.inf_str(self.infcx()), + b_vid.to_str(), b_bounds.inf_str(self.infcx())); if a_vid == b_vid { - return Ok(a_t); + return Ok(Left(a_vid)); } // If both A and B have an UB type, then we can just compute the // LUB of those types: let a_bnd = self.bnd(a_bounds), b_bnd = self.bnd(b_bounds); match (a_bnd, b_bnd) { - (Some(a_ty), Some(b_ty)) => { - match self.infcx().try(|| c_ts(a_ty, b_ty) ) { - Ok(t) => return Ok(t), - Err(_) => { /*fallthrough */ } + (Some(ref a_ty), Some(ref b_ty)) => { + match self.infcx().try(|| lattice_dir_op(a_ty, b_ty) ) { + Ok(t) => return Ok(Right(t)), + Err(_) => { /*fallthrough */ } + } } - } - _ => {/*fallthrough*/} + _ => {/*fallthrough*/} } // Otherwise, we need to merge A and B into one variable. We can // then use either variable as an upper bound: - var_sub_var(self, a_vid, b_vid).then(|| Ok(a_t) ) + let cf = self.combine_fields(); + do cf.var_sub_var(vb, a_vid, b_vid).then { + Ok(Left(a_vid)) + } } -fn lattice_var_and_t( - self: &L, a_id: ty::TyVid, b: ty::t, - c_ts: fn(ty::t, ty::t) -> cres) -> cres { - - let vb = &self.infcx().ty_var_bindings; +fn lattice_var_and_t( + self: &L, + vb: &ValsAndBindings>, + +a_id: V, + b: &T, + lattice_dir_op: LatticeDirOp) + -> cres +{ let nde_a = self.infcx().get(vb, a_id); let a_id = nde_a.root; - let a_bounds = nde_a.possible_types; + let a_bounds = &nde_a.possible_types; // The comments in this function are written for LUB, but they // apply equally well to GLB if you inverse upper/lower/sub/super/etc. debug!("%s.lattice_var_and_t(%s=%s <: %s)", self.tag(), - a_id.to_str(), a_bounds.to_str(self.infcx()), - b.to_str(self.infcx())); + a_id.to_str(), + a_bounds.inf_str(self.infcx()), + b.inf_str(self.infcx())); match self.bnd(a_bounds) { - Some(a_bnd) => { - // If a has an upper bound, return the LUB(a.ub, b) - debug!("bnd=some(%s)", a_bnd.to_str(self.infcx())); - return c_ts(a_bnd, b); - } - None => { - // If a does not have an upper bound, make b the upper bound of a - // and then return b. - debug!("bnd=none"); - let a_bounds = self.with_bnd(a_bounds, b); - do bnds(self, a_bounds.lb, a_bounds.ub).then { - self.infcx().set(vb, a_id, root(a_bounds, nde_a.rank)); - Ok(b) + Some(ref a_bnd) => { + // If a has an upper bound, return the LUB(a.ub, b) + debug!("bnd=some(%s)", a_bnd.inf_str(self.infcx())); + lattice_dir_op(a_bnd, b) + } + None => { + // If a does not have an upper bound, make b the upper bound of a + // and then return b. + debug!("bnd=none"); + let a_bounds = self.with_bnd(a_bounds, *b); + do self.combine_fields().bnds(&a_bounds.lb, &a_bounds.ub).then { + self.infcx().set(vb, a_id, Root(a_bounds, nde_a.rank)); + Ok(*b) + } } - } } } @@ -165,7 +490,7 @@ fn lattice_var_and_t( // Random utility functions used by LUB/GLB when computing LUB/GLB of // fn types -fn var_ids(self: &T, isr: isr_alist) -> ~[RegionVid] { +fn var_ids(self: &T, isr: isr_alist) -> ~[RegionVid] { let mut result = ~[]; for list::each(isr) |pair| { match pair.second() { diff --git a/src/librustc/middle/typeck/infer/lub.rs b/src/librustc/middle/typeck/infer/lub.rs index 10ac6a3add9ac..f9e8c9d370c4f 100644 --- a/src/librustc/middle/typeck/infer/lub.rs +++ b/src/librustc/middle/typeck/infer/lub.rs @@ -13,22 +13,22 @@ use middle::ty; use middle::typeck::infer::combine::*; use middle::typeck::infer::lattice::*; use middle::typeck::infer::sub::Sub; -use middle::typeck::infer::to_str::ToStr; +use middle::typeck::infer::to_str::InferStr; use std::list; use syntax::ast::{Many, Once}; fn macros() { include!("macros.rs"); } // FIXME(#3114): Macro import/export. -enum Lub = combine_fields; // "subtype", "subregion" etc +enum Lub = CombineFields; // least-upper-bound: common supertype impl Lub { fn bot_ty(b: ty::t) -> cres { Ok(b) } fn ty_bot(b: ty::t) -> cres { self.bot_ty(b) } // commutative } -impl Lub: combine { - fn infcx() -> infer_ctxt { self.infcx } +impl Lub: Combine { + fn infcx() -> @InferCtxt { self.infcx } fn tag() -> ~str { ~"lub" } fn a_is_expected() -> bool { self.a_is_expected } fn span() -> span { self.span } @@ -74,15 +74,6 @@ impl Lub: combine { Glb(*self).tys(a, b) } - fn protos(p1: ast::Proto, p2: ast::Proto) -> cres { - match (p1, p2) { - (ast::ProtoBare, _) => Ok(p2), - (_, ast::ProtoBare) => Ok(p1), - _ if p1 == p2 => Ok(p1), - _ => Err(ty::terr_proto_mismatch(expected_found(&self, p1, p2))) - } - } - fn purities(a: purity, b: purity) -> cres { match (a, b) { (unsafe_fn, _) | (_, unsafe_fn) => Ok(unsafe_fn), @@ -106,15 +97,15 @@ impl Lub: combine { fn regions(a: ty::Region, b: ty::Region) -> cres { debug!("%s.regions(%?, %?)", self.tag(), - a.to_str(self.infcx), - b.to_str(self.infcx)); + a.inf_str(self.infcx), + b.inf_str(self.infcx)); do indent { self.infcx.region_vars.lub_regions(self.span, a, b) } } - fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres { + fn fn_sigs(a: &ty::FnSig, b: &ty::FnSig) -> cres { // Note: this is a subtle algorithm. For a full explanation, // please see the large comment in `region_inference.rs`. @@ -133,18 +124,18 @@ impl Lub: combine { self.span, b); // Collect constraints. - let fn_ty0 = if_ok!(super_fns(&self, &a_with_fresh, &b_with_fresh)); - debug!("fn_ty0 = %s", fn_ty0.to_str(self.infcx)); + let sig0 = if_ok!(super_fn_sigs(&self, &a_with_fresh, &b_with_fresh)); + debug!("sig0 = %s", sig0.inf_str(self.infcx)); - // Generalize the regions appearing in fn_ty0 if possible + // Generalize the regions appearing in sig0 if possible let new_vars = self.infcx.region_vars.vars_created_since_snapshot(snapshot); - let fn_ty1 = + let sig1 = self.infcx.fold_regions_in_sig( - &fn_ty0, + &sig0, |r, _in_fn| generalize_region(&self, snapshot, new_vars, a_isr, r)); - return Ok(move fn_ty1); + return Ok(move sig1); fn generalize_region(self: &Lub, snapshot: uint, @@ -191,18 +182,22 @@ impl Lub: combine { } } - fn fn_metas(a: &ty::FnMeta, b: &ty::FnMeta) -> cres { - super_fn_metas(&self, a, b) + fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres { + super_fns(&self, a, b) } - fn fn_sigs(a: &ty::FnSig, b: &ty::FnSig) -> cres { - super_fn_sigs(&self, a, b) + fn fn_metas(a: &ty::FnMeta, b: &ty::FnMeta) -> cres { + super_fn_metas(&self, a, b) } // Traits please (FIXME: #2794): + fn protos(p1: ast::Proto, p2: ast::Proto) -> cres { + super_protos(&self, p1, p2) + } + fn tys(a: ty::t, b: ty::t) -> cres { - lattice_tys(&self, a, b) + super_lattice_tys(&self, a, b) } fn flds(a: ty::field, b: ty::field) -> cres { diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs index 7d6a2c4366e22..fd31b6aff39bf 100644 --- a/src/librustc/middle/typeck/infer/mod.rs +++ b/src/librustc/middle/typeck/infer/mod.rs @@ -197,29 +197,16 @@ is valid. This basically corresponds to the block nesting structure: the regions for outer block scopes are superregions of those for inner block scopes. -## Integral type variables +## Integral and floating-point type variables There is a third variety of type variable that we use only for inferring the types of unsuffixed integer literals. Integral type variables differ from general-purpose type variables in that there's no subtyping relationship among the various integral types, so instead -of associating each variable with an upper and lower bound, we -represent the set of possible integral types it can take on with an -`int_ty_set`, which is a bitvector with one bit for each integral -type. Because intersecting these sets with each other is simpler than -merging bounds, we don't need to do so transactionally as we do for -general-purpose type variables. - -We could conceivably define a subtyping relationship among integral -types based on their ranges, but we choose not to open that particular -can of worms. Our strategy is to treat integral type variables as -unknown until the typing context constrains them to a unique integral -type, at which point they take on that type. If the typing context -overconstrains the type, it's a type error; if we reach the point at -which type variables must be resolved and an integral type variable is -still underconstrained, it defaults to `int` as a last resort. - -Floating point types are handled similarly to integral types. +of associating each variable with an upper and lower bound, we just +use simple unification. Each integer variable is associated with at +most one integer type. Floating point types are handled similarly to +integral types. ## GLB/LUB @@ -259,16 +246,14 @@ section on "Type Combining" below for details. #[warn(deprecated_mode)]; #[warn(deprecated_pattern)]; -use middle::ty::{TyVid, IntVid, FloatVid, RegionVid, vid}; +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_ty}; +use middle::typeck::check::regionmanip::{replace_bound_regions_in_fn_sig}; use middle::typeck::infer::assignment::Assign; -use middle::typeck::infer::combine::{combine_fields, eq_tys}; -use middle::typeck::infer::floating::{float_ty_set, float_ty_set_all}; +use middle::typeck::infer::combine::{CombineFields, eq_tys}; use middle::typeck::infer::glb::Glb; -use middle::typeck::infer::integral::{int_ty_set, int_ty_set_all}; use middle::typeck::infer::lub::Lub; use middle::typeck::infer::region_inference::{RegionVarBindings}; use middle::typeck::infer::resolve::{force_all, not_regions}; @@ -278,8 +263,8 @@ use middle::typeck::infer::resolve::{resolve_ivar, resolve_all}; use middle::typeck::infer::resolve::{resolve_nested_tvar, resolve_rvar}; use middle::typeck::infer::resolve::{resolver}; use middle::typeck::infer::sub::Sub; -use middle::typeck::infer::to_str::ToStr; -use middle::typeck::infer::unify::{vals_and_bindings, root}; +use middle::typeck::infer::to_str::InferStr; +use middle::typeck::infer::unify::{ValsAndBindings, Root}; use util::common::{indent, indenter}; use util::ppaux::{ty_to_str, mt_to_str}; @@ -296,7 +281,7 @@ use syntax::ast::{unsafe_fn, impure_fn, pure_fn, extern_fn}; use syntax::ast_util::dummy_sp; use syntax::{ast, ast_util}; -export infer_ctxt; +export InferCtxt; export new_infer_ctxt; export mk_subty, can_mk_subty; export mk_subr; @@ -307,15 +292,12 @@ export force_tvar, force_rvar, force_ivar, force_all; export resolve_and_force_all_but_regions, not_regions; export resolve_type, resolve_region; export resolve_borrowings; -export methods; // for infer_ctxt -export unify_methods; // for infer_ctxt export cres, fres, fixup_err, fixup_err_to_str; export assignment; export root, to_str; export int_ty_set_all; export assignment; export combine; -export floating; export glb; export integral; export lattice; @@ -333,9 +315,6 @@ mod combine; #[legacy_exports] mod glb; #[legacy_exports] -mod integral; -mod floating; -#[legacy_exports] mod lattice; #[legacy_exports] mod lub; @@ -350,39 +329,48 @@ mod to_str; #[legacy_exports] mod unify; -type bound = Option; -type bounds = {lb: bound, ub: bound}; +type Bound = Option; +type Bounds = {lb: Bound, ub: Bound}; type cres = Result; // "combine result" type ures = cres<()>; // "unify result" type fres = Result; // "fixup result" type ares = cres>; // "assignment result" -enum infer_ctxt = @{ +#[deriving_eq] +enum IntVarValue { + IntType(ast::int_ty), + UintType(ast::uint_ty), +} + +struct InferCtxt { tcx: ty::ctxt, - // We instantiate vals_and_bindings with bounds because the + // We instantiate ValsAndBindings with bounds because the // types that might instantiate a general type variable have an // order, represented by its upper and lower bounds. - ty_var_bindings: vals_and_bindings>, + ty_var_bindings: ValsAndBindings>, + + // Number of type variables created thus far. + mut ty_var_counter: uint, // The types that might instantiate an integral type variable are // represented by an int_ty_set. - int_var_bindings: vals_and_bindings, + int_var_bindings: ValsAndBindings>, + + // Number of integral variables created thus far. + mut int_var_counter: uint, // The types that might instantiate a floating-point type variable are // represented by an float_ty_set. - float_var_bindings: vals_and_bindings, + float_var_bindings: ValsAndBindings>, + + // Number of floating-point variables created thus far. + mut float_var_counter: uint, // For region variables. region_vars: RegionVarBindings, - - // For keeping track of existing type and region variables. - ty_var_counter: @mut uint, - int_var_counter: @mut uint, - float_var_counter: @mut uint, - region_var_counter: @mut uint -}; +} enum fixup_err { unresolved_int_ty(IntVid), @@ -405,27 +393,33 @@ fn fixup_err_to_str(f: fixup_err) -> ~str { } } -fn new_vals_and_bindings() -> vals_and_bindings { - vals_and_bindings { +fn new_ValsAndBindings() -> ValsAndBindings { + ValsAndBindings { vals: smallintmap::mk(), mut bindings: ~[] } } -fn new_infer_ctxt(tcx: ty::ctxt) -> infer_ctxt { - infer_ctxt(@{tcx: tcx, - ty_var_bindings: new_vals_and_bindings(), - int_var_bindings: new_vals_and_bindings(), - float_var_bindings: new_vals_and_bindings(), - region_vars: RegionVarBindings(tcx), - ty_var_counter: @mut 0u, - int_var_counter: @mut 0u, - float_var_counter: @mut 0u, - region_var_counter: @mut 0u})} - -fn mk_subty(cx: infer_ctxt, a_is_expected: bool, span: span, +fn new_infer_ctxt(tcx: ty::ctxt) -> @InferCtxt { + @InferCtxt { + tcx: tcx, + + ty_var_bindings: new_ValsAndBindings(), + ty_var_counter: 0, + + int_var_bindings: new_ValsAndBindings(), + int_var_counter: 0, + + float_var_bindings: new_ValsAndBindings(), + float_var_counter: 0, + + region_vars: RegionVarBindings(tcx), + } +} + +fn mk_subty(cx: @InferCtxt, a_is_expected: bool, span: span, a: ty::t, b: ty::t) -> ures { - debug!("mk_subty(%s <: %s)", a.to_str(cx), b.to_str(cx)); + debug!("mk_subty(%s <: %s)", a.inf_str(cx), b.inf_str(cx)); do indent { do cx.commit { cx.sub(a_is_expected, span).tys(a, b) @@ -433,8 +427,8 @@ fn mk_subty(cx: infer_ctxt, a_is_expected: bool, span: span, }.to_ures() } -fn can_mk_subty(cx: infer_ctxt, a: ty::t, b: ty::t) -> ures { - debug!("can_mk_subty(%s <: %s)", a.to_str(cx), b.to_str(cx)); +fn can_mk_subty(cx: @InferCtxt, a: ty::t, b: ty::t) -> ures { + debug!("can_mk_subty(%s <: %s)", a.inf_str(cx), b.inf_str(cx)); do indent { do cx.probe { cx.sub(true, ast_util::dummy_sp()).tys(a, b) @@ -442,9 +436,9 @@ fn can_mk_subty(cx: infer_ctxt, a: ty::t, b: ty::t) -> ures { }.to_ures() } -fn mk_subr(cx: infer_ctxt, a_is_expected: bool, span: span, +fn mk_subr(cx: @InferCtxt, a_is_expected: bool, span: span, a: ty::Region, b: ty::Region) -> ures { - debug!("mk_subr(%s <: %s)", a.to_str(cx), b.to_str(cx)); + debug!("mk_subr(%s <: %s)", a.inf_str(cx), b.inf_str(cx)); do indent { do cx.commit { cx.sub(a_is_expected, span).regions(a, b) @@ -452,9 +446,9 @@ fn mk_subr(cx: infer_ctxt, a_is_expected: bool, span: span, }.to_ures() } -fn mk_eqty(cx: infer_ctxt, a_is_expected: bool, span: span, +fn mk_eqty(cx: @InferCtxt, a_is_expected: bool, span: span, a: ty::t, b: ty::t) -> ures { - debug!("mk_eqty(%s <: %s)", a.to_str(cx), b.to_str(cx)); + debug!("mk_eqty(%s <: %s)", a.inf_str(cx), b.inf_str(cx)); do indent { do cx.commit { let suber = cx.sub(a_is_expected, span); @@ -463,9 +457,9 @@ fn mk_eqty(cx: infer_ctxt, a_is_expected: bool, span: span, }.to_ures() } -fn mk_assignty(cx: infer_ctxt, a_is_expected: bool, span: span, +fn mk_assignty(cx: @InferCtxt, a_is_expected: bool, span: span, a: ty::t, b: ty::t) -> ares { - debug!("mk_assignty(%s -> %s)", a.to_str(cx), b.to_str(cx)); + debug!("mk_assignty(%s -> %s)", a.inf_str(cx), b.inf_str(cx)); do indent { do cx.commit { Assign(cx.combine_fields(a_is_expected, span)).tys(a, b) @@ -473,8 +467,8 @@ fn mk_assignty(cx: infer_ctxt, a_is_expected: bool, span: span, } } -fn can_mk_assignty(cx: infer_ctxt, a: ty::t, b: ty::t) -> ures { - debug!("can_mk_assignty(%s -> %s)", a.to_str(cx), b.to_str(cx)); +fn can_mk_assignty(cx: @InferCtxt, a: ty::t, b: ty::t) -> ures { + debug!("can_mk_assignty(%s -> %s)", a.inf_str(cx), b.inf_str(cx)); do indent { do cx.probe { let span = ast_util::dummy_sp(); @@ -484,18 +478,18 @@ fn can_mk_assignty(cx: infer_ctxt, a: ty::t, b: ty::t) -> ures { } // See comment on the type `resolve_state` below -fn resolve_type(cx: infer_ctxt, a: ty::t, modes: uint) +fn resolve_type(cx: @InferCtxt, a: ty::t, modes: uint) -> fres { resolver(cx, modes).resolve_type_chk(a) } -fn resolve_region(cx: infer_ctxt, r: ty::Region, modes: uint) +fn resolve_region(cx: @InferCtxt, r: ty::Region, modes: uint) -> fres { resolver(cx, modes).resolve_region_chk(r) } /* -fn resolve_borrowings(cx: infer_ctxt) { +fn resolve_borrowings(cx: @InferCtxt) { for cx.borrowings.each |item| { match resolve_region(cx, item.scope, resolve_all|force_all) { Ok(region) => { @@ -561,9 +555,10 @@ fn uok() -> ures { Ok(()) } -fn rollback_to( - vb: &vals_and_bindings, len: uint) { - +fn rollback_to( + vb: &ValsAndBindings, + len: uint) +{ while vb.bindings.len() != len { let (vid, old_v) = vb.bindings.pop(); vb.vals.insert(vid.to_uint(), old_v); @@ -576,12 +571,12 @@ struct Snapshot { region_vars_snapshot: uint, } -impl infer_ctxt { +impl @InferCtxt { fn combine_fields(a_is_expected: bool, - span: span) -> combine_fields { - combine_fields {infcx: self, - a_is_expected: a_is_expected, - span: span} + span: span) -> CombineFields { + CombineFields {infcx: self, + a_is_expected: a_is_expected, + span: span} } fn sub(a_is_expected: bool, span: span) -> Sub { @@ -611,8 +606,7 @@ impl infer_ctxt { //rollback_to(&self.int_var_bindings, // snapshot.int_var_bindings_len); - self.region_vars.rollback_to( - snapshot.region_vars_snapshot); + self.region_vars.rollback_to(snapshot.region_vars_snapshot); } /// Execute `f` and commit the bindings if successful @@ -656,12 +650,12 @@ impl infer_ctxt { } } -impl infer_ctxt { +impl @InferCtxt { fn next_ty_var_id() -> TyVid { - let id = *self.ty_var_counter; - *self.ty_var_counter += 1u; + let id = self.ty_var_counter; + self.ty_var_counter += 1; self.ty_var_bindings.vals.insert(id, - root({lb: None, ub: None}, 0u)); + Root({lb: None, ub: None}, 0u)); return TyVid(id); } @@ -674,11 +668,10 @@ impl infer_ctxt { } fn next_int_var_id() -> IntVid { - let id = *self.int_var_counter; - *self.int_var_counter += 1u; + let id = self.int_var_counter; + self.int_var_counter += 1; - self.int_var_bindings.vals.insert(id, - root(int_ty_set_all(), 0u)); + self.int_var_bindings.vals.insert(id, Root(None, 0)); return IntVid(id); } @@ -687,10 +680,10 @@ impl infer_ctxt { } fn next_float_var_id() -> FloatVid { - let id = *self.float_var_counter; - *self.float_var_counter += 1; + let id = self.float_var_counter; + self.float_var_counter += 1; - self.float_var_bindings.vals.insert(id, root(float_ty_set_all(), 0)); + self.float_var_bindings.vals.insert(id, Root(None, 0)); return FloatVid(id); } @@ -782,10 +775,10 @@ impl infer_ctxt { fn replace_bound_regions_with_fresh_regions( &self, span: span, - fty: &ty::FnTy) -> (ty::FnTy, isr_alist) + fsig: &ty::FnSig) -> (ty::FnSig, isr_alist) { - let {fn_ty: fn_ty, isr: isr, _} = - replace_bound_regions_in_fn_ty(self.tcx, @Nil, None, fty, |br| { + let {fn_sig: fn_sig, isr: isr, _} = + replace_bound_regions_in_fn_sig(self.tcx, @Nil, None, fsig, |br| { // N.B.: The name of the bound region doesn't have anything to // do with the region variable that's created for it. The // only thing we're doing with `br` here is using it in the @@ -796,18 +789,17 @@ impl infer_ctxt { rvar); rvar }); - (fn_ty, isr) + (fn_sig, isr) } fn fold_regions_in_sig( &self, - fn_ty: &ty::FnTy, - fldr: &fn(r: ty::Region, in_fn: bool) -> ty::Region) -> ty::FnTy + fn_sig: &ty::FnSig, + fldr: &fn(r: ty::Region, in_fn: bool) -> ty::Region) -> ty::FnSig { - let sig = do ty::fold_sig(&fn_ty.sig) |t| { + do ty::fold_sig(fn_sig) |t| { ty::fold_regions(self.tcx, t, fldr) - }; - ty::FnTyBase {meta: fn_ty.meta, sig: sig} + } } } diff --git a/src/librustc/middle/typeck/infer/region_inference.rs b/src/librustc/middle/typeck/infer/region_inference.rs index e5ca30a3e2ce3..d45fd31ebae4b 100644 --- a/src/librustc/middle/typeck/infer/region_inference.rs +++ b/src/librustc/middle/typeck/infer/region_inference.rs @@ -544,7 +544,7 @@ use middle::region; use middle::ty; use middle::ty::{Region, RegionVid, re_static, re_infer, re_free, re_bound}; use middle::ty::{re_scope, ReVar, ReSkolemized, br_fresh}; -use middle::typeck::infer::to_str::ToStr; +use middle::typeck::infer::to_str::InferStr; use syntax::codemap; use util::ppaux::note_and_explain_region; diff --git a/src/librustc/middle/typeck/infer/resolve.rs b/src/librustc/middle/typeck/infer/resolve.rs index da4c02b9e3507..c02ee0055e641 100644 --- a/src/librustc/middle/typeck/infer/resolve.rs +++ b/src/librustc/middle/typeck/infer/resolve.rs @@ -46,57 +46,56 @@ // future). If you want to resolve everything but one type, you are // probably better off writing `resolve_all - resolve_ivar`. - use middle::ty; -use middle::typeck::infer::floating::*; -use middle::typeck::infer::floating; -use middle::typeck::infer::integral::*; -use middle::typeck::infer::integral; -use middle::typeck::infer::to_str::ToStr; +use middle::typeck::infer::to_str::InferStr; + +use syntax::ast; use core::uint; use core::vec; -const resolve_nested_tvar: uint = 0b00000001; -const resolve_rvar: uint = 0b00000010; -const resolve_ivar: uint = 0b00000100; -const resolve_fvar: uint = 0b00001000; -const resolve_all: uint = 0b00001111; -const force_tvar: uint = 0b00010000; -const force_rvar: uint = 0b00100000; -const force_ivar: uint = 0b01000000; -const force_fvar: uint = 0b11000000; -const force_all: uint = 0b11110000; +const resolve_nested_tvar: uint = 0b0000000001; +const resolve_rvar: uint = 0b0000000010; +const resolve_ivar: uint = 0b0000000100; +const resolve_fvar: uint = 0b0000001000; +const resolve_fnvar: uint = 0b0000010000; +const resolve_all: uint = 0b0000011111; +const force_tvar: uint = 0b0000100000; +const force_rvar: uint = 0b0001000000; +const force_ivar: uint = 0b0010000000; +const force_fvar: uint = 0b0100000000; +const force_fnvar: uint = 0b1000000000; +const force_all: uint = 0b1111100000; const not_regions: uint = !(force_rvar | resolve_rvar); const resolve_and_force_all_but_regions: uint = (resolve_all | force_all) & not_regions; -type resolve_state_ = { - infcx: infer_ctxt, +struct ResolveState { + infcx: @InferCtxt, modes: uint, mut err: Option, - mut v_seen: ~[TyVid] -}; - -enum resolve_state { - resolve_state_(@resolve_state_) + mut v_seen: ~[TyVid], + mut type_depth: uint } -fn resolver(infcx: infer_ctxt, modes: uint) -> resolve_state { - resolve_state_(@{infcx: infcx, - modes: modes, - mut err: None, - mut v_seen: ~[]}) +fn resolver(infcx: @InferCtxt, modes: uint) -> ResolveState { + ResolveState { + infcx: infcx, + modes: modes, + err: None, + v_seen: ~[], + type_depth: 0 + } } -impl resolve_state { - fn should(mode: uint) -> bool { +impl ResolveState { + fn should(&self, mode: uint) -> bool { (self.modes & mode) == mode } - fn resolve_type_chk(typ: ty::t) -> fres { + fn resolve_type_chk(&self, typ: ty::t) -> fres { self.err = None; debug!("Resolving %s (modes=%x)", @@ -121,7 +120,7 @@ impl resolve_state { } } - fn resolve_region_chk(orig: ty::Region) -> fres { + fn resolve_region_chk(&self, orig: ty::Region) -> fres { self.err = None; let resolved = indent(|| self.resolve_region(orig) ); match self.err { @@ -130,63 +129,64 @@ impl resolve_state { } } - fn resolve_type(typ: ty::t) -> ty::t { - debug!("resolve_type(%s)", typ.to_str(self.infcx)); - indent(fn&() -> ty::t { - if !ty::type_needs_infer(typ) { return typ; } + fn resolve_type(&self, typ: ty::t) -> ty::t { + debug!("resolve_type(%s)", typ.inf_str(self.infcx)); + let _i = indenter(); + + if !ty::type_needs_infer(typ) { + return typ; + } + + if self.type_depth > 0 && !self.should(resolve_nested_tvar) { + return typ; + } - match copy ty::get(typ).sty { - ty::ty_infer(TyVar(vid)) => { + match /*bad*/ copy ty::get(typ).sty { + ty::ty_infer(TyVar(vid)) => { self.resolve_ty_var(vid) - } - ty::ty_infer(IntVar(vid)) => { + } + ty::ty_infer(IntVar(vid)) => { self.resolve_int_var(vid) - } - ty::ty_infer(FloatVar(vid)) => { + } + ty::ty_infer(FloatVar(vid)) => { self.resolve_float_var(vid) - } - _ => { - if !self.should(resolve_rvar) && - !self.should(resolve_nested_tvar) { - // shortcircuit for efficiency + } + _ => { + if self.modes & resolve_all == 0 { + // if we are only resolving top-level type + // variables, and this is not a top-level type + // variable, then shortcircuit for efficiency typ } else { - ty::fold_regions_and_ty( + self.type_depth += 1; + let result = ty::fold_regions_and_ty( self.infcx.tcx, typ, |r| self.resolve_region(r), - |t| self.resolve_nested_tvar(t), - |t| self.resolve_nested_tvar(t)) + |t| self.resolve_type(t), + |t| self.resolve_type(t)); + self.type_depth -= 1; + result } - } } - }) - } - - fn resolve_nested_tvar(typ: ty::t) -> ty::t { - debug!("Resolve_if_deep(%s)", typ.to_str(self.infcx)); - if !self.should(resolve_nested_tvar) { - typ - } else { - self.resolve_type(typ) } } - fn resolve_region(orig: ty::Region) -> ty::Region { - debug!("Resolve_region(%s)", orig.to_str(self.infcx)); + fn resolve_region(&self, orig: ty::Region) -> ty::Region { + debug!("Resolve_region(%s)", orig.inf_str(self.infcx)); match orig { ty::re_infer(ty::ReVar(rid)) => self.resolve_region_var(rid), _ => orig } } - fn resolve_region_var(rid: RegionVid) -> ty::Region { + fn resolve_region_var(&self, rid: RegionVid) -> ty::Region { if !self.should(resolve_rvar) { return ty::re_infer(ty::ReVar(rid)); } self.infcx.region_vars.resolve_var(rid) } - fn assert_not_rvar(rid: RegionVid, r: ty::Region) { + fn assert_not_rvar(&self, rid: RegionVid, r: ty::Region) { match r { ty::re_infer(ty::ReVar(rid2)) => { self.err = Some(region_var_bound_by_region_var(rid, rid2)); @@ -195,7 +195,7 @@ impl resolve_state { } } - fn resolve_ty_var(vid: TyVid) -> ty::t { + fn resolve_ty_var(&self, vid: TyVid) -> ty::t { if vec::contains(self.v_seen, &vid) { self.err = Some(cyclic_ty(vid)); return ty::mk_var(self.infcx.tcx, vid); @@ -228,27 +228,22 @@ impl resolve_state { } } - fn resolve_int_var(vid: IntVid) -> ty::t { + fn resolve_int_var(&self, vid: IntVid) -> ty::t { if !self.should(resolve_ivar) { return ty::mk_int_var(self.infcx.tcx, vid); } - let nde = self.infcx.get(&self.infcx.int_var_bindings, vid); - let pt = nde.possible_types; - - // If there's only one type in the set of possible types, then - // that's the answer. - match integral::single_type_contained_in(self.infcx.tcx, pt) { - Some(t) => t, + let node = self.infcx.get(&self.infcx.int_var_bindings, vid); + match node.possible_types { + Some(IntType(t)) => ty::mk_mach_int(self.infcx.tcx, t), + Some(UintType(t)) => ty::mk_mach_uint(self.infcx.tcx, t), None => { if self.should(force_ivar) { // As a last resort, default to int. let ty = ty::mk_int(self.infcx.tcx); self.infcx.set( &self.infcx.int_var_bindings, vid, - root(convert_integral_ty_to_int_ty_set(self.infcx.tcx, - ty), - nde.rank)); + Root(Some(IntType(ast::ty_i)), node.rank)); ty } else { ty::mk_int_var(self.infcx.tcx, vid) @@ -257,18 +252,14 @@ impl resolve_state { } } - fn resolve_float_var(vid: FloatVid) -> ty::t { + fn resolve_float_var(&self, vid: FloatVid) -> ty::t { if !self.should(resolve_fvar) { return ty::mk_float_var(self.infcx.tcx, vid); } - let nde = self.infcx.get(&self.infcx.float_var_bindings, vid); - let pt = nde.possible_types; - - // If there's only one type in the set of possible types, then - // that's the answer. - match floating::single_type_contained_in(self.infcx.tcx, pt) { - Some(t) => t, + let node = self.infcx.get(&self.infcx.float_var_bindings, vid); + match node.possible_types { + Some(t) => ty::mk_mach_float(self.infcx.tcx, t), None => { if self.should(force_fvar) { // As a last resort, default to float. @@ -276,10 +267,7 @@ impl resolve_state { self.infcx.set( &self.infcx.float_var_bindings, vid, - root( - convert_floating_point_ty_to_float_ty_set( - self.infcx.tcx, ty), - nde.rank)); + Root(Some(ast::ty_f), node.rank)); ty } else { ty::mk_float_var(self.infcx.tcx, vid) diff --git a/src/librustc/middle/typeck/infer/sub.rs b/src/librustc/middle/typeck/infer/sub.rs index c96724bd6525f..2f43fd616205b 100644 --- a/src/librustc/middle/typeck/infer/sub.rs +++ b/src/librustc/middle/typeck/infer/sub.rs @@ -8,20 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use middle::ty; use middle::typeck::infer::combine::*; -use middle::typeck::infer::to_str::ToStr; +use middle::typeck::infer::to_str::InferStr; use middle::typeck::infer::unify::*; use std::list; +use middle::typeck::check::regionmanip::{replace_bound_regions_in_fn_sig}; fn macros() { include!("macros.rs"); } // FIXME(#3114): Macro import/export. -enum Sub = combine_fields; // "subtype", "subregion" etc +enum Sub = CombineFields; // "subtype", "subregion" etc -impl Sub: combine { - fn infcx() -> infer_ctxt { self.infcx } +impl Sub: Combine { + fn infcx() -> @InferCtxt { self.infcx } fn tag() -> ~str { ~"sub" } fn a_is_expected() -> bool { self.a_is_expected } fn span() -> span { self.span } @@ -31,14 +31,14 @@ impl Sub: combine { fn glb() -> Glb { Glb(*self) } fn contratys(a: ty::t, b: ty::t) -> cres { - let opp = combine_fields { + let opp = CombineFields { a_is_expected: !self.a_is_expected,.. *self }; Sub(opp).tys(b, a) } fn contraregions(a: ty::Region, b: ty::Region) -> cres { - let opp = combine_fields { + let opp = CombineFields { a_is_expected: !self.a_is_expected,.. *self }; Sub(opp).regions(b, a) @@ -47,8 +47,8 @@ impl Sub: combine { fn regions(a: ty::Region, b: ty::Region) -> cres { debug!("%s.regions(%s, %s)", self.tag(), - a.to_str(self.infcx), - b.to_str(self.infcx)); + a.inf_str(self.infcx), + b.inf_str(self.infcx)); do indent { match self.infcx.region_vars.make_subregion(self.span, a, b) { Ok(()) => Ok(a), @@ -58,7 +58,7 @@ impl Sub: combine { } fn mts(a: ty::mt, b: ty::mt) -> cres { - debug!("mts(%s <: %s)", a.to_str(self.infcx), b.to_str(self.infcx)); + debug!("mts(%s <: %s)", a.inf_str(self.infcx), b.inf_str(self.infcx)); if a.mutbl != b.mutbl && b.mutbl != m_const { return Err(ty::terr_mutability); @@ -77,14 +77,6 @@ impl Sub: combine { } } - fn protos(p1: ast::Proto, p2: ast::Proto) -> cres { - match (p1, p2) { - (ast::ProtoBare, _) => Ok(p1), - _ if p1 == p2 => Ok(p1), - _ => Err(ty::terr_proto_mismatch(expected_found(&self, p1, p2))) - } - } - fn purities(a: purity, b: purity) -> cres { self.lub().purities(a, b).compare(b, || { ty::terr_purity_mismatch(expected_found(&self, a, b)) @@ -99,34 +91,47 @@ impl Sub: combine { fn tys(a: ty::t, b: ty::t) -> cres { debug!("%s.tys(%s, %s)", self.tag(), - a.to_str(self.infcx), b.to_str(self.infcx)); + a.inf_str(self.infcx), b.inf_str(self.infcx)); if a == b { return Ok(a); } do indent { match (ty::get(a).sty, ty::get(b).sty) { - (ty::ty_bot, _) => { - Ok(a) - } - (ty::ty_infer(TyVar(a_id)), ty::ty_infer(TyVar(b_id))) => { - var_sub_var(&self, a_id, b_id).then(|| Ok(a) ) - } - (ty::ty_infer(TyVar(a_id)), _) => { - var_sub_t(&self, a_id, b).then(|| Ok(a) ) - } - (_, ty::ty_infer(TyVar(b_id))) => { - t_sub_var(&self, a, b_id).then(|| Ok(a) ) - } - (_, ty::ty_bot) => { - Err(ty::terr_sorts(expected_found(&self, a, b))) - } - _ => { - super_tys(&self, a, b) - } + (ty::ty_bot, _) => { + Ok(a) + } + + (ty::ty_infer(TyVar(a_id)), ty::ty_infer(TyVar(b_id))) => { + do self.var_sub_var(&self.infcx.ty_var_bindings, + a_id, b_id).then { + Ok(a) + } + } + (ty::ty_infer(TyVar(a_id)), _) => { + do self.var_sub_t(&self.infcx.ty_var_bindings, + a_id, b).then { + Ok(a) + } + } + (_, ty::ty_infer(TyVar(b_id))) => { + do self.t_sub_var(&self.infcx.ty_var_bindings, + a, b_id).then { + Ok(a) + } + } + + (_, ty::ty_bot) => { + Err(ty::terr_sorts(expected_found(&self, a, b))) + } + + _ => { + super_tys(&self, a, b) + } } } } - fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres { - debug!("fns(a=%s, b=%s)", a.to_str(self.infcx), b.to_str(self.infcx)); + fn fn_sigs(a: &ty::FnSig, b: &ty::FnSig) -> cres { + debug!("fn_sigs(a=%s, b=%s)", + a.inf_str(self.infcx), b.inf_str(self.infcx)); let _indenter = indenter(); // Rather than checking the subtype relationship between `a` and `b` @@ -144,14 +149,14 @@ impl Sub: combine { // First, we instantiate each bound region in the subtype with a fresh // region variable. - let (a_fn_ty, _) = + let (a_sig, _) = self.infcx.replace_bound_regions_with_fresh_regions( self.span, a); // Second, we instantiate each bound region in the supertype with a // fresh concrete region. - let {fn_ty: b_fn_ty, isr: skol_isr, _} = { - do replace_bound_regions_in_fn_ty(self.infcx.tcx, @Nil, + let {fn_sig: b_sig, isr: skol_isr, _} = { + do replace_bound_regions_in_fn_sig(self.infcx.tcx, @Nil, None, b) |br| { let skol = self.infcx.region_vars.new_skolemized(br); debug!("Bound region %s skolemized to %?", @@ -161,11 +166,11 @@ impl Sub: combine { } }; - debug!("a_fn_ty=%s", a_fn_ty.to_str(self.infcx)); - debug!("b_fn_ty=%s", b_fn_ty.to_str(self.infcx)); + debug!("a_sig=%s", a_sig.inf_str(self.infcx)); + debug!("b_sig=%s", b_sig.inf_str(self.infcx)); // Compare types now that bound regions have been replaced. - let fn_ty = if_ok!(super_fns(&self, &a_fn_ty, &b_fn_ty)); + let sig = if_ok!(super_fn_sigs(&self, &a_sig, &b_sig)); // Presuming type comparison succeeds, we need to check // that the skolemized regions do not "leak". @@ -197,21 +202,25 @@ impl Sub: combine { } } - return Ok(fn_ty) + return Ok(sig); } // Traits please (FIXME: #2794): + fn protos(p1: ast::Proto, p2: ast::Proto) -> cres { + super_protos(&self, p1, p2) + } + fn flds(a: ty::field, b: ty::field) -> cres { super_flds(&self, a, b) } - fn fn_metas(a: &ty::FnMeta, b: &ty::FnMeta) -> cres { - super_fn_metas(&self, a, b) + fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres { + super_fns(&self, a, b) } - fn fn_sigs(a: &ty::FnSig, b: &ty::FnSig) -> cres { - super_fn_sigs(&self, a, b) + fn fn_metas(a: &ty::FnMeta, b: &ty::FnMeta) -> cres { + super_fn_metas(&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 73352b802d64e..2ef772e24deb8 100644 --- a/src/librustc/middle/typeck/infer/to_str.rs +++ b/src/librustc/middle/typeck/infer/to_str.rs @@ -8,83 +8,97 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use middle::ty::{FnMeta, FnTyBase, FnSig, FnVid}; use middle::ty; -use middle::typeck::infer::integral::int_ty_set; -use middle::typeck::infer::floating::float_ty_set; -use middle::typeck::infer::unify::{redirect, root, var_value}; +use middle::typeck::infer::unify::{Redirect, Root, VarValue}; use util::ppaux; +use syntax::{ast, ast_util}; + use core::uint; +use core::str; -trait ToStr { - fn to_str(cx: infer_ctxt) -> ~str; +pub trait InferStr { + fn inf_str(cx: @InferCtxt) -> ~str; } -impl ty::t: ToStr { - fn to_str(cx: infer_ctxt) -> ~str { +impl ty::t : InferStr { + fn inf_str(cx: @InferCtxt) -> ~str { ty_to_str(cx.tcx, self) } } -impl ty::mt: ToStr { - fn to_str(cx: infer_ctxt) -> ~str { - mt_to_str(cx.tcx, self) +impl FnMeta : InferStr { + fn inf_str(_cx: @InferCtxt) -> ~str { + fmt!("%?", self) + } +} + +impl FnSig : InferStr { + fn inf_str(cx: @InferCtxt) -> ~str { + fmt!("(%s) -> %s", + str::connect(self.inputs.map(|a| a.ty.inf_str(cx)), ", "), + self.output.inf_str(cx)) + } +} + +impl FnTyBase : InferStr { + fn inf_str(cx: @InferCtxt) -> ~str { + fmt!("%s%s", self.meta.inf_str(cx), self.sig.inf_str(cx)) } } -impl ty::Region: ToStr { - fn to_str(cx: infer_ctxt) -> ~str { - ppaux::region_to_str(cx.tcx, self) +impl ty::mt : InferStr { + fn inf_str(cx: @InferCtxt) -> ~str { + mt_to_str(cx.tcx, self) } } -impl ty::FnTy: ToStr { - fn to_str(cx: infer_ctxt) -> ~str { - ty::mk_fn(cx.tcx, self).to_str(cx) +impl ty::Region : InferStr { + fn inf_str(_cx: @InferCtxt) -> ~str { + fmt!("%?", self) } } -impl bound: ToStr { - fn to_str(cx: infer_ctxt) -> ~str { +impl Bound : InferStr { + fn inf_str(cx: @InferCtxt) -> ~str { match self { - Some(ref v) => (*v).to_str(cx), + Some(ref v) => v.inf_str(cx), None => ~"none" } } } -impl bounds: ToStr { - fn to_str(cx: infer_ctxt) -> ~str { +impl Bounds : InferStr { + fn inf_str(cx: @InferCtxt) -> ~str { fmt!("{%s <: %s}", - self.lb.to_str(cx), - self.ub.to_str(cx)) + self.lb.inf_str(cx), + self.ub.inf_str(cx)) } } -impl int_ty_set: ToStr { - fn to_str(_cx: infer_ctxt) -> ~str { +impl VarValue : InferStr { + fn inf_str(cx: @InferCtxt) -> ~str { match self { - int_ty_set(v) => uint::to_str(v, 10u) + Redirect(ref vid) => fmt!("Redirect(%s)", vid.to_str()), + Root(ref pt, rk) => fmt!("Root(%s, %s)", pt.inf_str(cx), + uint::to_str(rk, 10u)) } } } -impl float_ty_set: ToStr { - fn to_str(_cx: infer_ctxt) -> ~str { +impl IntVarValue : InferStr { + fn inf_str(_cx: @InferCtxt) -> ~str { match self { - float_ty_set(v) => uint::to_str(v, 10u) + IntType(t) => ast_util::int_ty_to_str(t), + UintType(t) => ast_util::uint_ty_to_str(t) } } } -impl var_value: ToStr { - fn to_str(cx: infer_ctxt) -> ~str { - match self { - redirect(ref vid) => fmt!("redirect(%s)", (*vid).to_str()), - root(ref pt, rk) => fmt!("root(%s, %s)", (*pt).to_str(cx), - uint::to_str(rk, 10u)) - } +impl ast::float_ty : InferStr { + fn inf_str(_cx: @InferCtxt) -> ~str { + ast_util::float_ty_to_str(self) } } diff --git a/src/librustc/middle/typeck/infer/unify.rs b/src/librustc/middle/typeck/infer/unify.rs index 8056c2c6bb31e..9500d89bf2263 100644 --- a/src/librustc/middle/typeck/infer/unify.rs +++ b/src/librustc/middle/typeck/infer/unify.rs @@ -10,35 +10,40 @@ use middle::ty; -use middle::typeck::infer::combine::combine; -use middle::typeck::infer::floating::*; -use middle::typeck::infer::floating; -use middle::typeck::infer::integral::*; -use middle::typeck::infer::integral; -use middle::typeck::infer::to_str::ToStr; +use middle::typeck::infer::combine::Combine; +use middle::typeck::infer::to_str::InferStr; use core::result; use std::smallintmap::SmallIntMap; -enum var_value { - redirect(V), - root(T, uint), +enum VarValue { + Redirect(V), + Root(T, uint), } -struct vals_and_bindings { - vals: SmallIntMap>, - mut bindings: ~[(V, var_value)], +struct ValsAndBindings { + vals: SmallIntMap>, + mut bindings: ~[(V, VarValue)], } -struct node { +struct Node { root: V, possible_types: T, rank: uint, } -impl infer_ctxt { - fn get( - vb: &vals_and_bindings, vid: V) -> node { +impl @InferCtxt { + fn get( + vb: &ValsAndBindings, + vid: V) + -> Node + { + /*! + * + * Find the root node for `vid`. This uses the standard + * union-find algorithm with path compression: + * http://en.wikipedia.org/wiki/Disjoint-set_data_structure + */ let vid_u = vid.to_uint(); match vb.vals.find(vid_u) { @@ -47,435 +52,141 @@ impl infer_ctxt { } Some(ref var_val) => { match (*var_val) { - redirect(ref vid) => { + Redirect(ref vid) => { let node = self.get(vb, (*vid)); if node.root.ne(vid) { // Path compression - vb.vals.insert((*vid).to_uint(), redirect(node.root)); + vb.vals.insert(vid.to_uint(), Redirect(node.root)); } node } - root(ref pt, rk) => { - node {root: vid, possible_types: (*pt), rank: rk} + Root(ref pt, rk) => { + Node {root: vid, possible_types: *pt, rank: rk} } } } } } - fn set( - vb: &vals_and_bindings, vid: V, - +new_v: var_value) { + fn set( + vb: &ValsAndBindings, + vid: V, + +new_v: VarValue) + { + /*! + * + * Sets the value for `vid` to `new_v`. `vid` MUST be a root node! + */ let old_v = vb.vals.get(vid.to_uint()); vb.bindings.push((vid, old_v)); vb.vals.insert(vid.to_uint(), new_v); debug!("Updating variable %s from %s to %s", - vid.to_str(), old_v.to_str(self), new_v.to_str(self)); + vid.to_str(), old_v.inf_str(self), new_v.inf_str(self)); } -} - -// Combines the two bounds into a more general bound. -fn merge_bnd( - self: &C, a: bound, b: bound, - merge_op: fn(ty::t,ty::t) -> cres) -> cres> { - - debug!("merge_bnd(%s,%s)", - a.to_str(self.infcx()), - b.to_str(self.infcx())); - let _r = indenter(); - - match (a, b) { - (None, None) => Ok(None), - (Some(_), None) => Ok(a), - (None, Some(_)) => Ok(b), - (Some(v_a), Some(v_b)) => { - do merge_op(v_a, v_b).chain |v| { - Ok(Some(v)) - } - } - } -} - -fn merge_bnds( - self: &C, a: bounds, b: bounds, - lub: fn(ty::t,ty::t) -> cres, - glb: fn(ty::t,ty::t) -> cres) -> cres> { - - let _r = indenter(); - do merge_bnd(self, a.ub, b.ub, glb).chain |ub| { - debug!("glb of ubs %s and %s is %s", - a.ub.to_str(self.infcx()), - b.ub.to_str(self.infcx()), - ub.to_str(self.infcx())); - do merge_bnd(self, a.lb, b.lb, lub).chain |lb| { - debug!("lub of lbs %s and %s is %s", - a.lb.to_str(self.infcx()), - b.lb.to_str(self.infcx()), - lb.to_str(self.infcx())); - Ok({lb: lb, ub: ub}) - } - } -} - -// Updates the bounds for the variable `v_id` to be the intersection -// of `a` and `b`. That is, the new bounds for `v_id` will be -// a bounds c such that: -// c.ub <: a.ub -// c.ub <: b.ub -// a.lb <: c.lb -// b.lb <: c.lb -// If this cannot be achieved, the result is failure. - -fn set_var_to_merged_bounds( - self: &C, - v_id: ty::TyVid, - a: bounds, - b: bounds, - rank: uint) -> ures { - - let vb = &self.infcx().ty_var_bindings; - - // Think of the two diamonds, we want to find the - // intersection. There are basically four possibilities (you - // can swap A/B in these pictures): - // - // A A - // / \ / \ - // / B \ / B \ - // / / \ \ / / \ \ - // * * * * * / * * - // \ \ / / \ / / - // \ B / / \ / / - // \ / * \ / - // A \ / A - // B - - debug!("merge(%s,%s,%s)", - v_id.to_str(), - a.to_str(self.infcx()), - b.to_str(self.infcx())); - - // First, relate the lower/upper bounds of A and B. - // Note that these relations *must* hold for us to - // to be able to merge A and B at all, and relating - // them explicitly gives the type inferencer more - // information and helps to produce tighter bounds - // when necessary. - do indent { - do bnds(self, a.lb, b.ub).then { - do bnds(self, b.lb, a.ub).then { - do merge_bnd(self, a.ub, b.ub, - |x, y| self.glb().tys(x, y)).chain |ub| { - do merge_bnd(self, a.lb, b.lb, - |x, y| self.lub().tys(x, y)).chain |lb| { - let bounds = {lb: lb, ub: ub}; - debug!("merge(%s): bounds=%s", - v_id.to_str(), - bounds.to_str(self.infcx())); - - // the new bounds must themselves - // be relatable: - do bnds(self, bounds.lb, bounds.ub).then { - self.infcx().set(vb, v_id, root(bounds, rank)); - uok() - } - } - } - } - } - } -} - -/// Ensure that variable A is a subtype of variable B. This is a -/// subtle and tricky process, as described in detail at the top -/// of infer.rs -fn var_sub_var(self: &C, - a_id: ty::TyVid, - b_id: ty::TyVid) -> ures { - let vb = &self.infcx().ty_var_bindings; - - // Need to make sub_id a subtype of sup_id. - let nde_a = self.infcx().get(vb, a_id); - let nde_b = self.infcx().get(vb, b_id); - let a_id = nde_a.root; - let b_id = nde_b.root; - let a_bounds = nde_a.possible_types; - let b_bounds = nde_b.possible_types; - - debug!("vars(%s=%s <: %s=%s)", - a_id.to_str(), a_bounds.to_str(self.infcx()), - b_id.to_str(), b_bounds.to_str(self.infcx())); - - if a_id == b_id { return uok(); } - - // If both A's UB and B's LB have already been bound to types, - // see if we can make those types subtypes. - match (a_bounds.ub, b_bounds.lb) { - (Some(a_ub), Some(b_lb)) => { - let r = self.infcx().try(|| self.sub().tys(a_ub, b_lb)); - match r { - Ok(_ty) => return result::Ok(()), - Err(_) => { /*fallthrough */ } - } - } - _ => { /*fallthrough*/ } - } - - // Otherwise, we need to merge A and B so as to guarantee that - // A remains a subtype of B. Actually, there are other options, - // but that's the route we choose to take. - - // Rank optimization - - // Make the node with greater rank the parent of the node with - // smaller rank. - if nde_a.rank > nde_b.rank { - debug!("vars(): a has smaller rank"); - // a has greater rank, so a should become b's parent, - // i.e., b should redirect to a. - self.infcx().set(vb, b_id, redirect(a_id)); - set_var_to_merged_bounds( - self, a_id, a_bounds, b_bounds, nde_a.rank) - } else if nde_a.rank < nde_b.rank { - debug!("vars(): b has smaller rank"); - // b has greater rank, so a should redirect to b. - self.infcx().set(vb, a_id, redirect(b_id)); - set_var_to_merged_bounds( - self, b_id, a_bounds, b_bounds, nde_b.rank) - } else { - debug!("vars(): a and b have equal rank"); - assert nde_a.rank == nde_b.rank; - // If equal, just redirect one to the other and increment - // the other's rank. We choose arbitrarily to redirect b - // to a and increment a's rank. - self.infcx().set(vb, b_id, redirect(a_id)); - set_var_to_merged_bounds( - self, a_id, a_bounds, b_bounds, nde_a.rank + 1u - ) - } -} - -/// make variable a subtype of T -fn var_sub_t(self: &C, a_id: ty::TyVid, b: ty::t) -> ures { - - let vb = &self.infcx().ty_var_bindings; - let nde_a = self.infcx().get(vb, a_id); - let a_id = nde_a.root; - let a_bounds = nde_a.possible_types; - - debug!("var_sub_t(%s=%s <: %s)", - a_id.to_str(), - a_bounds.to_str(self.infcx()), - b.to_str(self.infcx())); - let b_bounds = {lb: None, ub: Some(b)}; - set_var_to_merged_bounds(self, a_id, a_bounds, b_bounds, nde_a.rank) -} - -/// make T a subtype of variable -fn t_sub_var(self: &C, a: ty::t, b_id: ty::TyVid) -> ures { - - let vb = &self.infcx().ty_var_bindings; - let a_bounds = {lb: Some(a), ub: None}; - let nde_b = self.infcx().get(vb, b_id); - let b_id = nde_b.root; - let b_bounds = nde_b.possible_types; - - debug!("t_sub_var(%s <: %s=%s)", - a.to_str(self.infcx()), - b_id.to_str(), - b_bounds.to_str(self.infcx())); - set_var_to_merged_bounds(self, b_id, a_bounds, b_bounds, nde_b.rank) -} -fn bnds( - self: &C, a: bound, b: bound) -> ures { - - debug!("bnds(%s <: %s)", a.to_str(self.infcx()), b.to_str(self.infcx())); - do indent { - match (a, b) { - (None, None) | - (Some(_), None) | - (None, Some(_)) => { - uok() - } - (Some(t_a), Some(t_b)) => { - self.sub().tys(t_a, t_b).to_ures() - } - } - } -} - -// ______________________________________________________________________ -// Integral variables - -impl infer_ctxt { - fn optimize_ranks(vb: &vals_and_bindings, - nde_a: node, - nde_b: node, - a_id: V, - b_id: V, - intersection: T) { - if nde_a.rank > nde_b.rank { - debug!("int_vars(): a has smaller rank"); + fn unify( + vb: &ValsAndBindings, + node_a: &Node, + node_b: &Node, + op: &fn(new_root: V, new_rank: uint) -> R + ) -> R { + // Rank optimization: if you don't know what it is, check + // out + + debug!("unify(node_a(id=%?, rank=%?), \ + node_b(id=%?, rank=%?))", + node_a.root, node_a.rank, + node_b.root, node_b.rank); + + if node_a.rank > node_b.rank { // a has greater rank, so a should become b's parent, // i.e., b should redirect to a. - self.set(vb, a_id, root(intersection, nde_a.rank)); - self.set(vb, b_id, redirect(a_id)); - } else if nde_a.rank < nde_b.rank { - debug!("int_vars(): b has smaller rank"); + self.set(vb, node_b.root, Redirect(node_a.root)); + op(node_a.root, node_a.rank) + } else if node_a.rank < node_b.rank { // b has greater rank, so a should redirect to b. - self.set(vb, b_id, root(intersection, nde_b.rank)); - self.set(vb, a_id, redirect(b_id)); + self.set(vb, node_a.root, Redirect(node_b.root)); + op(node_b.root, node_b.rank) } else { - debug!("int_vars(): a and b have equal rank"); - assert nde_a.rank == nde_b.rank; - // If equal, just redirect one to the other and increment - // the other's rank. We choose arbitrarily to redirect b - // to a and increment a's rank. - self.set(vb, a_id, root(intersection, nde_a.rank + 1u)); - self.set(vb, b_id, redirect(a_id)); - }; - } - - fn int_vars(a_id: ty::IntVid, b_id: ty::IntVid) -> ures { - let vb = &self.int_var_bindings; - - let nde_a = self.get(vb, a_id); - let nde_b = self.get(vb, b_id); - let a_id = nde_a.root; - let b_id = nde_b.root; - let a_pt = nde_a.possible_types; - let b_pt = nde_b.possible_types; - - // If we're already dealing with the same two variables, - // there's nothing to do. - if a_id == b_id { return uok(); } - - // Otherwise, take the intersection of the two sets of - // possible types. - let intersection = integral::intersection(a_pt, b_pt); - if *intersection == INT_TY_SET_EMPTY { - return Err(ty::terr_no_integral_type); + // If equal, redirect one to the other and increment the + // other's rank. + assert node_a.rank == node_b.rank; + self.set(vb, node_b.root, Redirect(node_a.root)); + op(node_a.root, node_a.rank + 1) } - - // Rank optimization - self.optimize_ranks(vb, nde_a, nde_b, a_id, b_id, intersection); - - uok() } - fn int_var_sub_t(a_id: ty::IntVid, b: ty::t) -> ures { - if ty::type_is_char(b) { - return Err(ty::terr_integer_as_char); - } - - assert ty::type_is_integral(b); - - let vb = &self.int_var_bindings; - let nde_a = self.get(vb, a_id); - let a_id = nde_a.root; - let a_pt = nde_a.possible_types; - - let intersection = - integral::intersection(a_pt, - convert_integral_ty_to_int_ty_set(self.tcx, b)); - if *intersection == INT_TY_SET_EMPTY { - return Err(ty::terr_no_integral_type); - } - self.set(vb, a_id, root(intersection, nde_a.rank)); - uok() - } - - fn t_sub_int_var(a: ty::t, b_id: ty::IntVid) -> ures { - assert ty::type_is_integral(a); - let vb = &self.int_var_bindings; - - let nde_b = self.get(vb, b_id); - let b_id = nde_b.root; - let b_pt = nde_b.possible_types; - - let intersection = - integral::intersection(b_pt, - convert_integral_ty_to_int_ty_set(self.tcx, a)); - if *intersection == INT_TY_SET_EMPTY { - return Err(ty::terr_no_integral_type); - } - self.set(vb, b_id, root(intersection, nde_b.rank)); - uok() - } - - } // ______________________________________________________________________ -// Floating point variables - -impl infer_ctxt { - fn float_vars(a_id: ty::FloatVid, b_id: ty::FloatVid) -> ures { - let vb = &self.float_var_bindings; - - let nde_a = self.get(vb, a_id); - let nde_b = self.get(vb, b_id); - let a_id = nde_a.root; - let b_id = nde_b.root; - let a_pt = nde_a.possible_types; - let b_pt = nde_b.possible_types; +// Code to handle simple variables like ints, floats---anything that +// doesn't have a subtyping relationship we need to worry about. + +impl @InferCtxt { + fn simple_vars( + vb: &ValsAndBindings>, + err: ty::type_err, + a_id: V, + b_id: V) -> ures + { + /*! + * + * Unifies two simple variables. Because simple variables do + * not have any subtyping relationships, if both variables + * have already been associated with a value, then those two + * values must be the same. */ + + let node_a = self.get(vb, a_id); + let node_b = self.get(vb, b_id); + let a_id = node_a.root; + let b_id = node_b.root; - // If we're already dealing with the same two variables, - // there's nothing to do. if a_id == b_id { return uok(); } - // Otherwise, take the intersection of the two sets of - // possible types. - let intersection = floating::intersection(a_pt, b_pt); - if *intersection == FLOAT_TY_SET_EMPTY { - return Err(ty::terr_no_floating_point_type); - } - - // Rank optimization - self.optimize_ranks(vb, nde_a, nde_b, a_id, b_id, intersection); + let combined = match (&node_a.possible_types, &node_b.possible_types) + { + (&None, &None) => None, + (&Some(ref v), &None) | (&None, &Some(ref v)) => Some(*v), + (&Some(ref v1), &Some(ref v2)) => { + if *v1 != *v2 { return Err(err); } + Some(*v1) + } + }; - uok() + self.unify(vb, &node_a, &node_b, |new_root, new_rank| { + self.set(vb, new_root, Root(combined, new_rank)); + }); + return uok(); } - fn float_var_sub_t(a_id: ty::FloatVid, b: ty::t) -> ures { - assert ty::type_is_fp(b); - - let vb = &self.float_var_bindings; - let nde_a = self.get(vb, a_id); - let a_id = nde_a.root; - let a_pt = nde_a.possible_types; - - let intersection = - floating::intersection( - a_pt, - convert_floating_point_ty_to_float_ty_set(self.tcx, b)); - if *intersection == FLOAT_TY_SET_EMPTY { - return Err(ty::terr_no_floating_point_type); + fn simple_var_t( + vb: &ValsAndBindings>, + err: ty::type_err, + a_id: V, + b: T) -> ures + { + /*! + * + * Sets the value of the variable `a_id` to `b`. Because + * simple variables do not have any subtyping relationships, + * if `a_id` already has a value, it must be the same as + * `b`. */ + + let node_a = self.get(vb, a_id); + let a_id = node_a.root; + + if node_a.possible_types.is_none() { + self.set(vb, a_id, Root(Some(b), node_a.rank)); + return uok(); } - self.set(vb, a_id, root(intersection, nde_a.rank)); - uok() - } - - fn t_sub_float_var(a: ty::t, b_id: ty::FloatVid) -> ures { - assert ty::type_is_fp(a); - let vb = &self.float_var_bindings; - let nde_b = self.get(vb, b_id); - let b_id = nde_b.root; - let b_pt = nde_b.possible_types; - - let intersection = - floating::intersection( - b_pt, - convert_floating_point_ty_to_float_ty_set(self.tcx, a)); - if *intersection == FLOAT_TY_SET_EMPTY { - return Err(ty::terr_no_floating_point_type); + if node_a.possible_types == Some(b) { + return uok(); } - self.set(vb, b_id, root(intersection, nde_b.rank)); - uok() + + return Err(err); } } diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index adb6fc8baf79a..ac9d8eb8e386a 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -263,7 +263,7 @@ fn no_params(t: ty::t) -> ty::ty_param_bounds_and_ty { fn require_same_types( tcx: ty::ctxt, - maybe_infcx: Option, + maybe_infcx: Option<@infer::InferCtxt>, t1_is_expected: bool, span: span, t1: ty::t, diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index cd71bb099fe65..e801721ffc84f 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -68,8 +68,9 @@ fn loop_query(b: ast::blk, p: fn@(ast::expr_) -> bool) -> bool { _ => visit::visit_expr(e, flag, v) } }; - let v = visit::mk_vt(@{visit_expr: visit_expr - ,.. *visit::default_visitor()}); + let v = visit::mk_vt(@visit::Visitor { + visit_expr: visit_expr, + .. *visit::default_visitor()}); visit::visit_block(b, rs, v); return *rs; } @@ -83,8 +84,9 @@ fn block_query(b: ast::blk, p: fn@(@ast::expr) -> bool) -> bool { *flag |= p(e); visit::visit_expr(e, flag, v) }; - let v = visit::mk_vt(@{visit_expr: visit_expr - ,.. *visit::default_visitor()}); + let v = visit::mk_vt(@visit::Visitor{ + visit_expr: visit_expr, + .. *visit::default_visitor()}); visit::visit_block(b, rs, v); return *rs; } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 071f12a92d4fe..16eb9a2cbd0a3 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -24,14 +24,12 @@ use middle::ty::{ty_err, ty_estr, ty_evec, ty_float, ty_fn, 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}; -use middle::ty::{ty_unboxed_vec, vid}; +use middle::ty::{ty_unboxed_vec}; 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, purity_to_str, - onceness_to_str}; +use syntax::print::pprust::{path_to_str, proto_to_str, mode_to_str}; use syntax::{ast, ast_util}; use syntax::ast_map; @@ -247,9 +245,11 @@ fn vstore_ty_to_str(cx: ctxt, ty: ~str, vs: ty::vstore) -> ~str { } } -fn proto_ty_to_str(_cx: ctxt, proto: ast::Proto) -> &static/str { +fn proto_ty_to_str(_cx: ctxt, proto: ast::Proto, + followed_by_word: bool) -> &static/str { match proto { - ast::ProtoBare => "", + ast::ProtoBare if followed_by_word => "extern ", + ast::ProtoBare => "extern", ast::ProtoBox => "@", ast::ProtoBorrowed => "&", ast::ProtoUniq => "~", @@ -264,13 +264,19 @@ fn expr_repr(cx: ctxt, expr: @ast::expr) -> ~str { fn tys_to_str(cx: ctxt, ts: &[t]) -> ~str { let tstrs = ts.map(|t| ty_to_str(cx, *t)); - fmt!("[%s]", str::connect(tstrs, ", ")) + fmt!("(%s)", str::connect(tstrs, ", ")) } fn bound_to_str(cx: ctxt, b: param_bound) -> ~str { ty::param_bound_to_str(cx, &b) } +fn fn_sig_to_str(cx: ctxt, typ: &ty::FnSig) -> ~str { + fmt!("fn%s -> %s", + tys_to_str(cx, typ.inputs.map(|a| a.ty)), + ty_to_str(cx, typ.output)) +} + fn ty_to_str(cx: ctxt, typ: t) -> ~str { fn fn_input_to_str(cx: ctxt, input: {mode: ast::mode, ty: t}) -> ~str { @@ -300,15 +306,15 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str { s = match purity { ast::impure_fn => ~"", - _ => purity_to_str(purity) + ~" " + _ => purity.to_str() + ~" " }; s += match onceness { ast::Many => ~"", - ast::Once => onceness_to_str(onceness) + ~" " + ast::Once => onceness.to_str() + ~" " }; - s += proto_ty_to_str(cx, proto); + s += proto_ty_to_str(cx, proto, true); match (proto, region) { (ast::ProtoBox, ty::re_static) | diff --git a/src/librustdoc/attr_pass.rs b/src/librustdoc/attr_pass.rs index 8e52fb25a9465..bc6d1f5ad9de0 100644 --- a/src/librustdoc/attr_pass.rs +++ b/src/librustdoc/attr_pass.rs @@ -32,7 +32,7 @@ use std::map::HashMap; use std::par; pub fn mk_pass() -> Pass { - { + Pass { name: ~"attr", f: run } diff --git a/src/librustdoc/desc_to_brief_pass.rs b/src/librustdoc/desc_to_brief_pass.rs index 2c3998cecee2c..001f958c2e583 100644 --- a/src/librustdoc/desc_to_brief_pass.rs +++ b/src/librustdoc/desc_to_brief_pass.rs @@ -26,7 +26,7 @@ use core::vec; use std::par; pub fn mk_pass() -> Pass { - { + Pass { name: ~"desc_to_brief", f: run } diff --git a/src/librustdoc/markdown_index_pass.rs b/src/librustdoc/markdown_index_pass.rs index 1408ae874168e..a84f4d66ab288 100644 --- a/src/librustdoc/markdown_index_pass.rs +++ b/src/librustdoc/markdown_index_pass.rs @@ -23,7 +23,7 @@ use core::str; use std::par; pub fn mk_pass(+config: config::Config) -> Pass { - { + Pass { name: ~"markdown_index", f: fn~(srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc { run(srv, doc, config) diff --git a/src/librustdoc/markdown_pass.rs b/src/librustdoc/markdown_pass.rs index fd3cf86df2792..87cdefd90df89 100644 --- a/src/librustdoc/markdown_pass.rs +++ b/src/librustdoc/markdown_pass.rs @@ -44,7 +44,7 @@ pub fn mk_pass(+writer_factory: WriterFactory) -> Pass { run(srv, doc, copy writer_factory) }; - { + Pass { name: ~"markdown", f: move f } diff --git a/src/librustdoc/page_pass.rs b/src/librustdoc/page_pass.rs index 0709cc5dc55eb..d495654e67db4 100644 --- a/src/librustdoc/page_pass.rs +++ b/src/librustdoc/page_pass.rs @@ -31,7 +31,7 @@ use core::vec; use syntax::ast; pub fn mk_pass(output_style: config::OutputStyle) -> Pass { - { + Pass { name: ~"page", f: fn~(srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc { run(srv, doc, output_style) diff --git a/src/librustdoc/pass.rs b/src/librustdoc/pass.rs index 967dcd8f49f8e..a893ba23d32ad 100644 --- a/src/librustdoc/pass.rs +++ b/src/librustdoc/pass.rs @@ -15,10 +15,10 @@ use extract; use core::vec; /// A single operation on the document model -pub type Pass = { +pub struct Pass { name: ~str, f: fn~(srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc -}; +} pub fn run_passes( srv: astsrv::Srv, @@ -79,11 +79,11 @@ fn test_run_passes() { let source = ~""; do astsrv::from_str(source) |srv| { let passes = ~[ - { + Pass { name: ~"", f: pass1 }, - { + Pass { name: ~"", f: pass2 } diff --git a/src/librustdoc/path_pass.rs b/src/librustdoc/path_pass.rs index 4227ce230963b..b2729d7155049 100644 --- a/src/librustdoc/path_pass.rs +++ b/src/librustdoc/path_pass.rs @@ -20,7 +20,7 @@ use fold; use syntax::ast; pub fn mk_pass() -> Pass { - { + Pass { name: ~"path", f: run } diff --git a/src/librustdoc/prune_hidden_pass.rs b/src/librustdoc/prune_hidden_pass.rs index da3c6bd7f2b55..162d0d446f56e 100644 --- a/src/librustdoc/prune_hidden_pass.rs +++ b/src/librustdoc/prune_hidden_pass.rs @@ -21,7 +21,7 @@ use core::vec; use std::map::HashMap; pub fn mk_pass() -> Pass { - { + Pass { name: ~"prune_hidden", f: run } diff --git a/src/librustdoc/prune_private_pass.rs b/src/librustdoc/prune_private_pass.rs index 5017f889d5a6d..10f5b42a4f274 100644 --- a/src/librustdoc/prune_private_pass.rs +++ b/src/librustdoc/prune_private_pass.rs @@ -24,7 +24,7 @@ use syntax::ast; export mk_pass; fn mk_pass() -> Pass { - { + Pass { name: ~"prune_private", f: run } diff --git a/src/librustdoc/sectionalize_pass.rs b/src/librustdoc/sectionalize_pass.rs index a2b6687522022..186fddc528dce 100644 --- a/src/librustdoc/sectionalize_pass.rs +++ b/src/librustdoc/sectionalize_pass.rs @@ -23,7 +23,7 @@ use core::vec; use std::par; pub fn mk_pass() -> Pass { - { + Pass { name: ~"sectionalize", f: run } diff --git a/src/librustdoc/sort_pass.rs b/src/librustdoc/sort_pass.rs index fcf878dbf8d81..4b3c3730a0378 100644 --- a/src/librustdoc/sort_pass.rs +++ b/src/librustdoc/sort_pass.rs @@ -25,7 +25,7 @@ pub type ItemLtEqOp = pure fn~(v1: &doc::ItemTag, v2: &doc::ItemTag) -> bool; type ItemLtEq = NominalOp; pub fn mk_pass(name: ~str, +lteq: ItemLtEqOp) -> Pass { - { + Pass { name: name, f: fn~(move lteq, srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc { run(srv, doc, NominalOp { op: copy lteq }) diff --git a/src/librustdoc/text_pass.rs b/src/librustdoc/text_pass.rs index ae205883902ad..c3b1a4fb67ee2 100644 --- a/src/librustdoc/text_pass.rs +++ b/src/librustdoc/text_pass.rs @@ -20,7 +20,7 @@ use util::NominalOp; use std::par; pub fn mk_pass(name: ~str, +op: fn~(~str) -> ~str) -> Pass { - { + Pass { name: name, f: fn~(move op, srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc { run(srv, doc, copy op) diff --git a/src/librustdoc/tystr_pass.rs b/src/librustdoc/tystr_pass.rs index 92f2e0a5e8b0d..0a3fd75f288f3 100644 --- a/src/librustdoc/tystr_pass.rs +++ b/src/librustdoc/tystr_pass.rs @@ -26,7 +26,7 @@ use syntax::print::pprust; use syntax::ast_map; pub fn mk_pass() -> Pass { - { + Pass { name: ~"tystr", f: run } diff --git a/src/libstd/test.rs b/src/libstd/test.rs index 176953663ebfb..98416a88f10bc 100644 --- a/src/libstd/test.rs +++ b/src/libstd/test.rs @@ -55,12 +55,12 @@ pub type TestFn = fn~(); // The definition of a single test. A test runner will run a list of // these. -pub type TestDesc = { +pub struct TestDesc { name: TestName, testfn: TestFn, ignore: bool, should_fail: bool -}; +} // The default console test runner. It accepts the command line // arguments and a vector of test_descs (generated at compile time). @@ -241,14 +241,14 @@ fn print_failures(st: ConsoleTestState) { #[test] fn should_sort_failures_before_printing_them() { let s = do io::with_str_writer |wr| { - let test_a = { + let test_a = TestDesc { name: ~"a", testfn: fn~() { }, ignore: false, should_fail: false }; - let test_b = { + let test_b = TestDesc { name: ~"b", testfn: fn~() { }, ignore: false, @@ -370,10 +370,11 @@ fn filter_tests(opts: &TestOpts, } else { fn filter(test: &TestDesc) -> Option { if test.ignore { - return option::Some({name: test.name, - testfn: copy test.testfn, - ignore: false, - should_fail: test.should_fail}); + return option::Some(TestDesc { + name: test.name, + testfn: copy test.testfn, + ignore: false, + should_fail: test.should_fail}); } else { return option::None; } }; @@ -433,7 +434,7 @@ mod tests { #[test] fn do_not_run_ignored_tests() { fn f() { fail; } - let desc = { + let desc = TestDesc { name: ~"whatever", testfn: f, ignore: true, @@ -449,7 +450,7 @@ mod tests { #[test] fn ignored_tests_result_in_ignored() { fn f() { } - let desc = { + let desc = TestDesc { name: ~"whatever", testfn: f, ignore: true, @@ -466,7 +467,7 @@ mod tests { #[ignore(cfg(windows))] fn test_should_fail() { fn f() { fail; } - let desc = { + let desc = TestDesc { name: ~"whatever", testfn: f, ignore: false, @@ -482,7 +483,7 @@ mod tests { #[test] fn test_should_fail_but_succeeds() { fn f() { } - let desc = { + let desc = TestDesc { name: ~"whatever", testfn: f, ignore: false, @@ -523,10 +524,10 @@ mod tests { let opts = {filter: option::None, run_ignored: true, logfile: option::None}; let tests = - ~[{name: ~"1", testfn: fn~() { }, - ignore: true, should_fail: false}, - {name: ~"2", testfn: fn~() { }, - ignore: false, should_fail: false}]; + ~[TestDesc {name: ~"1", testfn: fn~() { }, + ignore: true, should_fail: false}, + TestDesc {name: ~"2", testfn: fn~() { }, + ignore: false, should_fail: false}]; let filtered = filter_tests(&opts, tests); assert (vec::len(filtered) == 1u); @@ -551,8 +552,9 @@ mod tests { let testfn = fn~() { }; let mut tests = ~[]; for vec::each(names) |name| { - let test = {name: *name, testfn: copy testfn, ignore: false, - should_fail: false}; + let test = TestDesc { + name: *name, testfn: copy testfn, ignore: false, + should_fail: false}; tests.push(move test); } move tests diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index c7c8c77c70fa3..0431b8243127c 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -415,6 +415,7 @@ impl mutability : cmp::Eq { #[auto_encode] #[auto_decode] +#[deriving_eq] pub enum Proto { ProtoBare, // bare functions (deprecated) ProtoUniq, // ~fn @@ -422,13 +423,6 @@ pub enum Proto { ProtoBorrowed, // &fn } -impl Proto : cmp::Eq { - pure fn eq(&self, other: &Proto) -> bool { - ((*self) as uint) == ((*other) as uint) - } - pure fn ne(&self, other: &Proto) -> bool { !(*self).eq(other) } -} - impl Proto : to_bytes::IterBytes { pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { (*self as uint).iter_bytes(lsb0, f); @@ -1068,20 +1062,24 @@ enum region_ { #[auto_encode] #[auto_decode] +#[deriving_eq] enum Onceness { Once, Many } -impl Onceness : cmp::Eq { - pure fn eq(&self, other: &Onceness) -> bool { - match ((*self), *other) { - (Once, Once) | (Many, Many) => true, - _ => false +impl Onceness : ToStr { + pure fn to_str() -> ~str { + match self { + ast::Once => ~"once", + ast::Many => ~"many" } } - pure fn ne(&self, other: &Onceness) -> bool { - !(*self).eq(other) +} + +impl Onceness : to_bytes::IterBytes { + pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + (*self as uint).iter_bytes(lsb0, f); } } @@ -1156,6 +1154,17 @@ enum purity { extern_fn, // declared with "extern fn" } +impl purity : ToStr { + pure fn to_str() -> ~str { + match self { + impure_fn => ~"impure", + unsafe_fn => ~"unsafe", + pure_fn => ~"pure", + extern_fn => ~"extern" + } + } +} + impl purity : to_bytes::IterBytes { pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { (*self as u8).iter_bytes(lsb0, f) diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs index f35d8c4e1c485..9872410a8079d 100644 --- a/src/libsyntax/ast_map.rs +++ b/src/libsyntax/ast_map.rs @@ -108,7 +108,7 @@ fn extend(cx: ctx, +elt: ident) -> @path { } fn mk_ast_map_visitor() -> vt { - return visit::mk_vt(@{ + return visit::mk_vt(@visit::Visitor { visit_item: map_item, visit_expr: map_expr, visit_stmt: map_stmt, diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index eaa61b304cd16..77953e783ba07 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -436,10 +436,8 @@ fn empty(range: id_range) -> bool { } fn id_visitor(vfn: fn@(node_id)) -> visit::vt<()> { - visit::mk_simple_visitor(@{ - visit_mod: fn@(_m: _mod, _sp: span, id: node_id) { - vfn(id) - }, + visit::mk_simple_visitor(@visit::SimpleVisitor { + visit_mod: |_m, _sp, id| vfn(id), visit_view_item: fn@(vi: @view_item) { match vi.node { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 27565b44c6db2..6666254e307b6 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -317,13 +317,13 @@ fn expand_crate(parse_sess: parse::parse_sess, let exts = syntax_expander_table(); let afp = default_ast_fold(); let cx: ext_ctxt = mk_ctxt(parse_sess, cfg); - let f_pre = - @{fold_expr: |a,b,c| expand_expr(exts, cx, a, b, c, afp.fold_expr), - fold_mod: |a,b| expand_mod_items(exts, cx, a, b, afp.fold_mod), - fold_item: |a,b| expand_item(exts, cx, a, b, afp.fold_item), - fold_stmt: |a,b,c| expand_stmt(exts, cx, a, b, c, afp.fold_stmt), - new_span: |a| new_span(cx, a), - .. *afp}; + let f_pre = @AstFoldFns { + fold_expr: |a,b,c| expand_expr(exts, cx, a, b, c, afp.fold_expr), + fold_mod: |a,b| expand_mod_items(exts, cx, a, b, afp.fold_mod), + fold_item: |a,b| expand_item(exts, cx, a, b, afp.fold_item), + fold_stmt: |a,b,c| expand_stmt(exts, cx, a, b, c, afp.fold_stmt), + new_span: |a| new_span(cx, a), + .. *afp}; let f = make_fold(f_pre); let cm = parse_expr_from_source_str(~"", @core_macros(), diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 6d32c73e1f703..c6b4920920aa2 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -15,7 +15,7 @@ use codemap::span; use core::option; use core::vec; -export ast_fold_precursor; +export ast_fold_fns; export ast_fold; export default_ast_fold; export make_fold; @@ -32,6 +32,7 @@ export fold_ty_param; export fold_ty_params; export fold_fn_decl; export extensions; +export AstFoldFns; trait ast_fold { fn fold_crate(crate) -> crate; @@ -61,7 +62,7 @@ trait ast_fold { // We may eventually want to be able to fold over type parameters, too -type ast_fold_precursor = @{ +struct AstFoldFns { //unlike the others, item_ is non-trivial fold_crate: fn@(crate_, span, ast_fold) -> (crate_, span), fold_view_item: fn@(view_item_, ast_fold) -> view_item_, @@ -85,7 +86,10 @@ type ast_fold_precursor = @{ fold_local: fn@(local_, span, ast_fold) -> (local_, span), map_exprs: fn@(fn@(&&v: @expr) -> @expr, ~[@expr]) -> ~[@expr], new_id: fn@(node_id) -> node_id, - new_span: fn@(span) -> span}; + new_span: fn@(span) -> span +} + +type ast_fold_fns = @AstFoldFns; /* some little folds that probably aren't useful to have in ast_fold itself*/ @@ -629,8 +633,8 @@ fn noop_id(i: node_id) -> node_id { return i; } fn noop_span(sp: span) -> span { return sp; } -fn default_ast_fold() -> ast_fold_precursor { - return @{fold_crate: wrap(noop_fold_crate), +fn default_ast_fold() -> ast_fold_fns { + return @AstFoldFns {fold_crate: wrap(noop_fold_crate), fold_view_item: noop_fold_view_item, fold_foreign_item: noop_fold_foreign_item, fold_item: noop_fold_item, @@ -655,7 +659,7 @@ fn default_ast_fold() -> ast_fold_precursor { new_span: noop_span}; } -impl ast_fold_precursor: ast_fold { +impl ast_fold_fns: ast_fold { /* naturally, a macro to write these would be nice */ fn fold_crate(c: crate) -> crate { let (n, s) = (self.fold_crate)(c.node, c.span, self as ast_fold); @@ -761,7 +765,7 @@ impl ast_fold { } } -fn make_fold(afp: ast_fold_precursor) -> ast_fold { +fn make_fold(afp: ast_fold_fns) -> ast_fold { afp as ast_fold } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 239cff22cc0c2..f392dd66f0ba1 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -42,11 +42,14 @@ enum ann_node { node_expr(ps, @ast::expr), node_pat(ps, @ast::pat), } -type pp_ann = {pre: fn@(ann_node), post: fn@(ann_node)}; +struct pp_ann { + pre: fn@(ann_node), + post: fn@(ann_node) +} fn no_ann() -> pp_ann { fn ignore(_node: ann_node) { } - return {pre: ignore, post: ignore}; + return pp_ann {pre: ignore, post: ignore}; } type ps = diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index b7d894a7e9f82..d668e6c274fce 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -57,51 +57,56 @@ fn tps_of_fn(fk: fn_kind) -> ~[ty_param] { } } -type visitor = - @{visit_mod: fn@(_mod, span, node_id, E, vt), - visit_view_item: fn@(@view_item, E, vt), - visit_foreign_item: fn@(@foreign_item, E, vt), - visit_item: fn@(@item, E, vt), - visit_local: fn@(@local, E, vt), - visit_block: fn@(ast::blk, E, vt), - visit_stmt: fn@(@stmt, E, vt), - visit_arm: fn@(arm, E, vt), - visit_pat: fn@(@pat, E, vt), - visit_decl: fn@(@decl, E, vt), - visit_expr: fn@(@expr, E, vt), - visit_expr_post: fn@(@expr, E, vt), - visit_ty: fn@(@Ty, E, vt), - visit_ty_params: fn@(~[ty_param], E, vt), - visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id, E, vt), - visit_ty_method: fn@(ty_method, E, vt), - visit_trait_method: fn@(trait_method, E, vt), - visit_struct_def: fn@(@struct_def, ident, ~[ty_param], node_id, E, - vt), - visit_struct_field: fn@(@struct_field, E, vt), - visit_struct_method: fn@(@method, E, vt)}; +struct Visitor { + visit_mod: fn@(_mod, span, node_id, E, vt), + visit_view_item: fn@(@view_item, E, vt), + visit_foreign_item: fn@(@foreign_item, E, vt), + visit_item: fn@(@item, E, vt), + visit_local: fn@(@local, E, vt), + visit_block: fn@(ast::blk, E, vt), + visit_stmt: fn@(@stmt, E, vt), + visit_arm: fn@(arm, E, vt), + visit_pat: fn@(@pat, E, vt), + visit_decl: fn@(@decl, E, vt), + visit_expr: fn@(@expr, E, vt), + visit_expr_post: fn@(@expr, E, vt), + visit_ty: fn@(@Ty, E, vt), + visit_ty_params: fn@(~[ty_param], E, vt), + visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id, E, vt), + visit_ty_method: fn@(ty_method, E, vt), + visit_trait_method: fn@(trait_method, E, vt), + visit_struct_def: fn@(@struct_def, ident, ~[ty_param], node_id, E, + vt), + visit_struct_field: fn@(@struct_field, E, vt), + visit_struct_method: fn@(@method, E, vt) +} + +type visitor = @Visitor; fn default_visitor() -> visitor { - return @{visit_mod: |a,b,c,d,e|visit_mod::(a, b, c, d, e), - visit_view_item: |a,b,c|visit_view_item::(a, b, c), - visit_foreign_item: |a,b,c|visit_foreign_item::(a, b, c), - visit_item: |a,b,c|visit_item::(a, b, c), - visit_local: |a,b,c|visit_local::(a, b, c), - visit_block: |a,b,c|visit_block::(a, b, c), - visit_stmt: |a,b,c|visit_stmt::(a, b, c), - visit_arm: |a,b,c|visit_arm::(a, b, c), - visit_pat: |a,b,c|visit_pat::(a, b, c), - visit_decl: |a,b,c|visit_decl::(a, b, c), - visit_expr: |a,b,c|visit_expr::(a, b, c), - visit_expr_post: |_a,_b,_c| (), - visit_ty: |a,b,c|skip_ty::(a, b, c), - visit_ty_params: |a,b,c|visit_ty_params::(a, b, c), - visit_fn: |a,b,c,d,e,f,g|visit_fn::(a, b, c, d, e, f, g), - visit_ty_method: |a,b,c|visit_ty_method::(a, b, c), - visit_trait_method: |a,b,c|visit_trait_method::(a, b, c), - visit_struct_def: |a,b,c,d,e,f|visit_struct_def::(a, b, c, - d, e, f), - visit_struct_field: |a,b,c|visit_struct_field::(a, b, c), - visit_struct_method: |a,b,c|visit_struct_method::(a, b, c)}; + return @Visitor { + visit_mod: |a,b,c,d,e|visit_mod::(a, b, c, d, e), + visit_view_item: |a,b,c|visit_view_item::(a, b, c), + visit_foreign_item: |a,b,c|visit_foreign_item::(a, b, c), + visit_item: |a,b,c|visit_item::(a, b, c), + visit_local: |a,b,c|visit_local::(a, b, c), + visit_block: |a,b,c|visit_block::(a, b, c), + visit_stmt: |a,b,c|visit_stmt::(a, b, c), + visit_arm: |a,b,c|visit_arm::(a, b, c), + visit_pat: |a,b,c|visit_pat::(a, b, c), + visit_decl: |a,b,c|visit_decl::(a, b, c), + visit_expr: |a,b,c|visit_expr::(a, b, c), + visit_expr_post: |_a,_b,_c| (), + visit_ty: |a,b,c|skip_ty::(a, b, c), + visit_ty_params: |a,b,c|visit_ty_params::(a, b, c), + visit_fn: |a,b,c,d,e,f,g|visit_fn::(a, b, c, d, e, f, g), + visit_ty_method: |a,b,c|visit_ty_method::(a, b, c), + visit_trait_method: |a,b,c|visit_trait_method::(a, b, c), + visit_struct_def: |a,b,c,d,e,f|visit_struct_def::(a, b, c, + d, e, f), + visit_struct_field: |a,b,c|visit_struct_field::(a, b, c), + visit_struct_method: |a,b,c|visit_struct_method::(a, b, c) + }; } fn visit_crate(c: crate, e: E, v: vt) { @@ -497,43 +502,46 @@ fn visit_arm(a: arm, e: E, v: vt) { // Simpler, non-context passing interface. Always walks the whole tree, simply // calls the given functions on the nodes. -type simple_visitor = - @{visit_mod: fn@(_mod, span, node_id), - visit_view_item: fn@(@view_item), - visit_foreign_item: fn@(@foreign_item), - visit_item: fn@(@item), - visit_local: fn@(@local), - visit_block: fn@(ast::blk), - visit_stmt: fn@(@stmt), - visit_arm: fn@(arm), - visit_pat: fn@(@pat), - visit_decl: fn@(@decl), - visit_expr: fn@(@expr), - visit_expr_post: fn@(@expr), - visit_ty: fn@(@Ty), - visit_ty_params: fn@(~[ty_param]), - visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id), - visit_ty_method: fn@(ty_method), - visit_trait_method: fn@(trait_method), - visit_struct_def: fn@(@struct_def, ident, ~[ty_param], node_id), - visit_struct_field: fn@(@struct_field), - visit_struct_method: fn@(@method)}; +struct SimpleVisitor { + visit_mod: fn@(_mod, span, node_id), + visit_view_item: fn@(@view_item), + visit_foreign_item: fn@(@foreign_item), + visit_item: fn@(@item), + visit_local: fn@(@local), + visit_block: fn@(ast::blk), + visit_stmt: fn@(@stmt), + visit_arm: fn@(arm), + visit_pat: fn@(@pat), + visit_decl: fn@(@decl), + visit_expr: fn@(@expr), + visit_expr_post: fn@(@expr), + visit_ty: fn@(@Ty), + visit_ty_params: fn@(~[ty_param]), + visit_fn: fn@(fn_kind, fn_decl, blk, span, node_id), + visit_ty_method: fn@(ty_method), + visit_trait_method: fn@(trait_method), + visit_struct_def: fn@(@struct_def, ident, ~[ty_param], node_id), + visit_struct_field: fn@(@struct_field), + visit_struct_method: fn@(@method) +} + +type simple_visitor = @SimpleVisitor; fn simple_ignore_ty(_t: @Ty) {} -fn default_simple_visitor() -> simple_visitor { - return @{visit_mod: fn@(_m: _mod, _sp: span, _id: node_id) { }, - visit_view_item: fn@(_vi: @view_item) { }, - visit_foreign_item: fn@(_ni: @foreign_item) { }, - visit_item: fn@(_i: @item) { }, - visit_local: fn@(_l: @local) { }, - visit_block: fn@(_b: ast::blk) { }, - visit_stmt: fn@(_s: @stmt) { }, - visit_arm: fn@(_a: arm) { }, - visit_pat: fn@(_p: @pat) { }, - visit_decl: fn@(_d: @decl) { }, - visit_expr: fn@(_e: @expr) { }, - visit_expr_post: fn@(_e: @expr) { }, +fn default_simple_visitor() -> @SimpleVisitor { + return @SimpleVisitor {visit_mod: |_m: _mod, _sp: span, _id: node_id| { }, + visit_view_item: |_vi: @view_item| { }, + visit_foreign_item: |_ni: @foreign_item| { }, + visit_item: |_i: @item| { }, + visit_local: |_l: @local| { }, + visit_block: |_b: ast::blk| { }, + visit_stmt: |_s: @stmt| { }, + visit_arm: |_a: arm| { }, + visit_pat: |_p: @pat| { }, + visit_decl: |_d: @decl| { }, + visit_expr: |_e: @expr| { }, + visit_expr_post: |_e: @expr| { }, visit_ty: simple_ignore_ty, visit_ty_params: fn@(_ps: ~[ty_param]) {}, visit_fn: fn@(_fk: fn_kind, _d: fn_decl, _b: blk, _sp: span, @@ -638,37 +646,37 @@ fn mk_simple_visitor(v: simple_visitor) -> vt<()> { f(m); visit_struct_method(m, e, v); } - return mk_vt(@{visit_mod: |a,b,c,d,e|v_mod(v.visit_mod, a, b, c, d, e), - visit_view_item: |a,b,c| - v_view_item(v.visit_view_item, a, b, c), - visit_foreign_item: - |a,b,c|v_foreign_item(v.visit_foreign_item, a, b, c), - visit_item: |a,b,c|v_item(v.visit_item, a, b, c), - visit_local: |a,b,c|v_local(v.visit_local, a, b, c), - visit_block: |a,b,c|v_block(v.visit_block, a, b, c), - visit_stmt: |a,b,c|v_stmt(v.visit_stmt, a, b, c), - visit_arm: |a,b,c|v_arm(v.visit_arm, a, b, c), - visit_pat: |a,b,c|v_pat(v.visit_pat, a, b, c), - visit_decl: |a,b,c|v_decl(v.visit_decl, a, b, c), - visit_expr: |a,b,c|v_expr(v.visit_expr, a, b, c), - visit_expr_post: |a,b,c| v_expr_post(v.visit_expr_post, - a, b, c), - visit_ty: visit_ty, - visit_ty_params: |a,b,c| - v_ty_params(v.visit_ty_params, a, b, c), - visit_fn: |a,b,c,d,e,f,g| - v_fn(v.visit_fn, a, b, c, d, e, f, g), - visit_ty_method: |a,b,c| - v_ty_method(v.visit_ty_method, a, b, c), - visit_trait_method: |a,b,c| - v_trait_method(v.visit_trait_method, a, b, c), - visit_struct_def: |a,b,c,d,e,f| - v_struct_def(v.visit_struct_def, a, b, c, d, e, f), - visit_struct_field: |a,b,c| - v_struct_field(v.visit_struct_field, a, b, c), - visit_struct_method: |a,b,c| - v_struct_method(v.visit_struct_method, a, b, c) - }); + return mk_vt(@Visitor { + visit_mod: |a,b,c,d,e|v_mod(v.visit_mod, a, b, c, d, e), + visit_view_item: |a,b,c| v_view_item(v.visit_view_item, a, b, c), + visit_foreign_item: + |a,b,c|v_foreign_item(v.visit_foreign_item, a, b, c), + visit_item: |a,b,c|v_item(v.visit_item, a, b, c), + visit_local: |a,b,c|v_local(v.visit_local, a, b, c), + visit_block: |a,b,c|v_block(v.visit_block, a, b, c), + visit_stmt: |a,b,c|v_stmt(v.visit_stmt, a, b, c), + visit_arm: |a,b,c|v_arm(v.visit_arm, a, b, c), + visit_pat: |a,b,c|v_pat(v.visit_pat, a, b, c), + visit_decl: |a,b,c|v_decl(v.visit_decl, a, b, c), + visit_expr: |a,b,c|v_expr(v.visit_expr, a, b, c), + visit_expr_post: |a,b,c| v_expr_post(v.visit_expr_post, + a, b, c), + visit_ty: visit_ty, + visit_ty_params: |a,b,c| + v_ty_params(v.visit_ty_params, a, b, c), + visit_fn: |a,b,c,d,e,f,g| + v_fn(v.visit_fn, a, b, c, d, e, f, g), + visit_ty_method: |a,b,c| + v_ty_method(v.visit_ty_method, a, b, c), + visit_trait_method: |a,b,c| + v_trait_method(v.visit_trait_method, a, b, c), + visit_struct_def: |a,b,c,d,e,f| + v_struct_def(v.visit_struct_def, a, b, c, d, e, f), + visit_struct_field: |a,b,c| + v_struct_field(v.visit_struct_field, a, b, c), + visit_struct_method: |a,b,c| + v_struct_method(v.visit_struct_method, a, b, c) + }); } // Local Variables: diff --git a/src/test/auxiliary/cci_nested_lib.rs b/src/test/auxiliary/cci_nested_lib.rs index d55302481a9ca..291a506c4ebb0 100644 --- a/src/test/auxiliary/cci_nested_lib.rs +++ b/src/test/auxiliary/cci_nested_lib.rs @@ -14,7 +14,7 @@ use dvec::DVec; type entry = {key: A, value: B}; -type alist = { eq_fn: fn@(A,A) -> bool, data: DVec> }; +struct alist { eq_fn: fn@(A,A) -> bool, data: DVec> } fn alist_add(lst: alist, k: A, v: B) { lst.data.push({key:k, value:v}); @@ -31,12 +31,12 @@ fn alist_get(lst: alist, k: A) -> B { #[inline] fn new_int_alist() -> alist { fn eq_int(&&a: int, &&b: int) -> bool { a == b } - return {eq_fn: eq_int, data: DVec()}; + return alist {eq_fn: eq_int, data: DVec()}; } #[inline] fn new_int_alist_2() -> alist { #[inline] fn eq_int(&&a: int, &&b: int) -> bool { a == b } - return {eq_fn: eq_int, data: DVec()}; + return alist {eq_fn: eq_int, data: DVec()}; } diff --git a/src/test/compile-fail/block-coerce-no-2.rs b/src/test/compile-fail/block-coerce-no-2.rs index 1e539dc4f36f6..b2265f5e959a0 100644 --- a/src/test/compile-fail/block-coerce-no-2.rs +++ b/src/test/compile-fail/block-coerce-no-2.rs @@ -19,5 +19,5 @@ fn main() { } f(g); - //~^ ERROR mismatched types: expected `fn(fn(fn()))` + //~^ ERROR mismatched types: expected `extern fn(extern fn(extern fn()))` } diff --git a/src/test/compile-fail/borrowck-autoref-3261.rs b/src/test/compile-fail/borrowck-autoref-3261.rs index b21114d9222c3..457cdd2344737 100644 --- a/src/test/compile-fail/borrowck-autoref-3261.rs +++ b/src/test/compile-fail/borrowck-autoref-3261.rs @@ -9,9 +9,9 @@ // except according to those terms. use core::either::*; -enum X = Either<(uint,uint),fn()>; +enum X = Either<(uint,uint),extern fn()>; impl &X { - fn with(blk: fn(x: &Either<(uint,uint),fn()>)) { + fn with(blk: fn(x: &Either<(uint,uint),extern fn()>)) { blk(&**self) } } diff --git a/src/test/compile-fail/main-wrong-type-2.rs b/src/test/compile-fail/main-wrong-type-2.rs index 4e1989eb25c5e..bb6633ecdc1fd 100644 --- a/src/test/compile-fail/main-wrong-type-2.rs +++ b/src/test/compile-fail/main-wrong-type-2.rs @@ -9,5 +9,5 @@ // except according to those terms. fn main() -> char { -//~^ ERROR Wrong type in main function: found `fn() -> char` +//~^ ERROR Wrong type in main function: found `extern fn() -> char` } diff --git a/src/test/compile-fail/main-wrong-type.rs b/src/test/compile-fail/main-wrong-type.rs index 7f8a4053c43ee..33d7b913dafb5 100644 --- a/src/test/compile-fail/main-wrong-type.rs +++ b/src/test/compile-fail/main-wrong-type.rs @@ -9,5 +9,5 @@ // except according to those terms. fn main(foo: {x: int, y: int}) { -//~^ ERROR Wrong type in main function: found `fn({x: int,y: int})` +//~^ ERROR Wrong type in main function: found `extern fn({x: int,y: int})` } diff --git a/src/test/compile-fail/missing-do.rs b/src/test/compile-fail/missing-do.rs index 3a0e8ffb9c48d..916008373c875 100644 --- a/src/test/compile-fail/missing-do.rs +++ b/src/test/compile-fail/missing-do.rs @@ -14,6 +14,6 @@ fn foo(f: fn()) { f() } fn main() { ~"" || 42; //~ ERROR binary operation || cannot be applied to type `~str` - foo || {}; //~ ERROR binary operation || cannot be applied to type `fn(&fn())` + foo || {}; //~ ERROR binary operation || cannot be applied to type `extern fn(&fn())` //~^ NOTE did you forget the 'do' keyword for the call? } diff --git a/src/test/run-pass/fn-coerce-field.rs b/src/test/run-pass/fn-coerce-field.rs index 47f4f122f93f6..0e7d90e2fd81f 100644 --- a/src/test/run-pass/fn-coerce-field.rs +++ b/src/test/run-pass/fn-coerce-field.rs @@ -8,11 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -type r = { +struct r { field: fn@() -}; +} fn main() { fn f() {} - let i: r = {field: f}; + let i: r = r {field: f}; } \ No newline at end of file diff --git a/src/test/run-pass/intrinsic-frame-address.rs b/src/test/run-pass/intrinsic-frame-address.rs index 653e84ea347cf..4b48e9a49c2ac 100644 --- a/src/test/run-pass/intrinsic-frame-address.rs +++ b/src/test/run-pass/intrinsic-frame-address.rs @@ -13,7 +13,7 @@ #[abi = "rust-intrinsic"] extern mod rusti { #[legacy_exports]; - fn frame_address(f: fn(*u8)); + fn frame_address(f: &once fn(*u8)); } fn main() { diff --git a/src/test/run-pass/issue-1458.rs b/src/test/run-pass/issue-1458.rs index b87b3d3aa0d0f..15d809e8208b3 100644 --- a/src/test/run-pass/issue-1458.rs +++ b/src/test/run-pass/issue-1458.rs @@ -12,7 +12,7 @@ fn plus_one(f: fn() -> int) -> int { return f() + 1; } -fn ret_plus_one() -> fn(fn() -> int) -> int { +fn ret_plus_one() -> extern fn(fn() -> int) -> int { return plus_one; }