diff --git a/src/compiletest/compiletest.rc b/src/compiletest/compiletest.rc index 8505e481638..ba6862039d4 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 f588f3643ce..ea67d0ea858 100644 --- a/src/libcargo/cargo.rc +++ b/src/libcargo/cargo.rc @@ -403,7 +403,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 1beb1a56efa..f45f71104f4 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 5f954558668..fd36c1d7701 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() }; @@ -486,8 +486,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 cbc598228a4..b4a9a83992d 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -395,13 +395,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 10c2f2e65f1..307698af037 100644 --- a/src/librustc/front/config.rs +++ b/src/librustc/front/config.rs @@ -38,8 +38,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 772bd39e07b..045e60052a4 100644 --- a/src/librustc/front/core_inject.rs +++ b/src/librustc/front/core_inject.rs @@ -42,7 +42,7 @@ fn inject_libcore_ref(sess: Session, ast::spanned { 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 497a6878bc1..970f1a065a7 100644 --- a/src/librustc/front/test.rs +++ b/src/librustc/front/test.rs @@ -65,10 +65,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); @@ -424,8 +424,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 078b5ea9a4b..a731aa8db97 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -52,10 +52,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 f52c2e448fe..6d131a074eb 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -180,11 +180,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); @@ -207,23 +208,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); } @@ -887,7 +888,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); @@ -1267,11 +1268,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 67f168cc5b6..154fb8d2de8 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -14,7 +14,7 @@ use core::prelude::*; use middle::ty; -use middle::ty::vid; +use middle::ty::Vid; use core::io::WriterUtil; use core::io; @@ -24,6 +24,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; @@ -35,7 +36,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, @@ -43,7 +44,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 9b024f87f41..eb9d4ae6a30 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -271,7 +271,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() }); @@ -304,7 +304,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() @@ -643,11 +643,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 534098d96dc..3d5bdac596b 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -92,11 +92,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); } @@ -247,13 +247,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 215256a8e95..52cbd1da10c 100644 --- a/src/librustc/middle/borrowck/gather_loans.rs +++ b/src/librustc/middle/borrowck/gather_loans.rs @@ -82,9 +82,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 a6fbe5bd6dd..19fc9eb175d 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -231,7 +231,6 @@ use core::prelude::*; 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 0166c8da410..7986352cac2 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -25,7 +25,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| @@ -211,7 +211,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 88443843270..0e260c54fe2 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 441e800f36f..c99b5757baa 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -38,7 +38,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| @@ -797,7 +797,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 5821bf4fbe5..530e63acf57 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -207,7 +207,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 9b718ec3bee..3c1f261c1f8 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 5e7002af2a5..3af1d7ea35b 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -97,7 +97,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 cca71153a7d..6870082ffac 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -29,7 +29,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; @@ -333,7 +333,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 1db7e666ffb..b2881abf53b 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -430,7 +430,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() }); @@ -458,30 +458,33 @@ 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(@ast::spanned { 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(@ast::spanned { + 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); } @@ -596,10 +599,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); } @@ -660,19 +664,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); } @@ -779,34 +784,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); } @@ -975,7 +982,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 6c78c270139..bfcd809594b 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -207,7 +207,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, @@ -489,7 +489,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 00be40cbf49..1e24ff9f5e4 100644 --- a/src/librustc/middle/mode.rs +++ b/src/librustc/middle/mode.rs @@ -234,7 +234,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 56dee0843dd..745e3f6086f 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -190,7 +190,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 21ccfd3b5f2..ae6a6d67c1d 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -352,7 +352,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, @@ -782,7 +782,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 4e5e9b97957..2fb922c3e52 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -64,7 +64,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}; @@ -947,7 +947,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), @@ -3719,7 +3719,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 668457a6a46..12a073e678b 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2372,10 +2372,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 8f02cee5b2a..d90673b31bc 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -390,7 +390,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 832f4f8294e..5de7ebadb2b 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 1b2fc4e387a..e17a9c8c0ed 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 65533571f9a..d29858e1fa4 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -47,7 +47,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; @@ -55,7 +55,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; @@ -118,7 +118,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; @@ -139,7 +140,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; @@ -222,7 +224,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; @@ -519,6 +520,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, @@ -533,6 +535,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 @@ -543,9 +546,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; @@ -673,7 +683,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) @@ -742,6 +752,7 @@ enum FnVid = uint; #[auto_decode] enum RegionVid = uint; +#[deriving_eq] enum InferTy { TyVar(TyVid), IntVar(IntVid), @@ -753,7 +764,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), } } } @@ -804,61 +815,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 } +} + +impl RegionVid: ToStr { 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 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() + } } } @@ -1197,7 +1211,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) } @@ -1369,15 +1383,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}) @@ -1424,8 +1431,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))} @@ -1457,18 +1464,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)) @@ -1509,6 +1507,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, @@ -2834,8 +2833,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); @@ -2887,10 +2887,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), @@ -2978,8 +2975,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" } } @@ -2997,9 +2994,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, @@ -3444,18 +3462,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", @@ -3489,7 +3505,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") @@ -4398,30 +4415,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) } @@ -4532,13 +4525,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) { @@ -4651,9 +4637,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 a8c1b0aaa90..05061ccfa13 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -1137,7 +1137,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 69b2724c054..ff99ee8590a 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -82,8 +82,9 @@ use middle::capture; use middle::const_eval; use middle::pat_util::pat_id_map; use middle::pat_util; -use middle::ty::{TyVid, vid, FnTyBase, FnMeta, FnSig, VariantInfo_, field}; +use middle::ty::{TyVid, Vid, FnTyBase, FnMeta, FnSig, VariantInfo_, field}; use middle::ty::{ty_param_bounds_and_ty, ty_param_substs_and_ty}; +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}; @@ -91,6 +92,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::crate_ctxt; use middle::typeck::infer::{resolve_type, force_tvar}; @@ -187,7 +189,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, @@ -265,7 +267,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() }); @@ -273,7 +275,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) { @@ -290,7 +292,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>) { @@ -305,15 +307,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)), @@ -406,12 +408,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) { @@ -503,12 +505,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); } @@ -520,7 +523,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: @@ -559,7 +562,8 @@ fn check_struct(ccx: @crate_ctxt, struct_def: @ast::struct_def, spanned { 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)); }; @@ -583,7 +587,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); @@ -657,7 +661,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 { @@ -1519,7 +1523,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) { @@ -1569,7 +1573,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); @@ -2157,12 +2161,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) => { @@ -2218,7 +2222,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); } @@ -2227,20 +2231,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) => { @@ -2267,21 +2263,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 029a61c8ca6..3901752ac68 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -114,7 +114,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(); @@ -123,12 +122,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 1e4082fc961..8097b0eca84 100644 --- a/src/librustc/middle/typeck/check/regionmanip.rs +++ b/src/librustc/middle/typeck/check/regionmanip.rs @@ -12,6 +12,7 @@ use core::prelude::*; +use middle::ty::{FnTyBase}; use middle::ty; use middle::typeck::check::self_info; use middle::typeck::isr_alist; @@ -25,22 +26,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: ast::spanned { node: ast::sty_region(m), @@ -56,10 +72,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(); @@ -67,17 +83,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 { @@ -86,10 +100,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 @@ -158,7 +170,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. @@ -187,7 +199,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 593d32c644e..9d309d4996b 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -14,7 +14,7 @@ use middle::resolve; use middle::ty; use middle::typeck::check::{fn_ctxt, impl_self_ty}; use middle::typeck::check::{structurally_resolved_type}; -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 middle::typeck::{crate_ctxt, vtable_origin, vtable_param, vtable_res}; @@ -63,7 +63,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 { @@ -685,8 +685,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) => { @@ -714,7 +714,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 a00fe073c54..b00a3306ceb 100644 --- a/src/librustc/middle/typeck/check/writeback.rs +++ b/src/librustc/middle/typeck/check/writeback.rs @@ -161,9 +161,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); @@ -237,13 +236,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 { @@ -254,7 +253,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 d25c91dfe47..9fa78f01265 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -34,7 +34,7 @@ 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::crate_ctxt; -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}; @@ -51,6 +51,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; @@ -69,7 +70,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; @@ -116,7 +117,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 { @@ -181,7 +182,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. @@ -199,7 +200,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)); @@ -588,7 +589,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 11a932db287..db99689f0ad 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -100,11 +100,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 8e524bb8019..62080f4db35 100644 --- a/src/librustc/middle/typeck/infer/assignment.rs +++ b/src/librustc/middle/typeck/infer/assignment.rs @@ -63,16 +63,16 @@ use core::prelude::*; use middle::ty::TyVar; use middle::ty; use middle::typeck::infer::{ares, cres}; -use middle::typeck::infer::combine::combine_fields; +use middle::typeck::infer::combine::CombineFields; use middle::typeck::infer::sub::Sub; -use middle::typeck::infer::to_str::ToStr; +use middle::typeck::infer::to_str::InferStr; use util::common::{indent, indenter}; use core::option; use syntax::ast::{m_const, m_imm, m_mutbl}; 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)) @@ -82,13 +82,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"); @@ -146,8 +146,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 { @@ -210,18 +210,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: @@ -252,10 +262,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 d0b17d2ddc3..c5e99bc5c03 100644 --- a/src/librustc/middle/typeck/infer/combine.rs +++ b/src/librustc/middle/typeck/infer/combine.rs @@ -61,8 +61,8 @@ use middle::ty; use middle::typeck::infer::glb::Glb; use middle::typeck::infer::lub::Lub; use middle::typeck::infer::sub::Sub; -use middle::typeck::infer::to_str::ToStr; -use middle::typeck::infer::{cres, infer_ctxt, ures}; +use middle::typeck::infer::to_str::InferStr; +use middle::typeck::infer::{cres, InferCtxt, ures, IntType, UintType}; use util::common::indent; use core::result::{iter_vec2, map_vec2}; @@ -73,8 +73,8 @@ use syntax::codemap::span; 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; @@ -105,13 +105,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() { @@ -121,7 +121,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| { @@ -130,10 +130,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(|| { @@ -152,7 +152,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> { @@ -174,17 +174,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, @@ -220,8 +220,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)); } } @@ -238,7 +238,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* @@ -256,7 +256,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 @@ -279,7 +279,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 { @@ -292,7 +302,7 @@ fn super_flds( } } -fn super_modes( +fn super_modes( self: &C, a: ast::mode, b: ast::mode) -> cres { @@ -300,7 +310,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 { @@ -311,7 +321,7 @@ fn super_args( } } -fn super_vstores( +fn super_vstores( self: &C, vk: ty::terr_vstore_kind, a: ty::vstore, b: ty::vstore) -> cres { @@ -334,7 +344,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)); @@ -343,17 +353,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 { @@ -369,19 +380,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: @@ -392,32 +401,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) ) + 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_infer(FloatVar(a_id)), ty::ty_float(_)) => { - self.infcx().float_var_sub_t(a_id, b).then(|| 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 68adeeb82db..00000000000 --- a/src/librustc/middle/typeck/infer/floating.rs +++ /dev/null @@ -1,64 +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 core::prelude::*; - -use middle::ty::{get, ty_float}; -use middle::ty; -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 bfe81245ecb..4d697ad3433 100644 --- a/src/librustc/middle/typeck/infer/glb.rs +++ b/src/librustc/middle/typeck/infer/glb.rs @@ -17,7 +17,7 @@ use middle::typeck::infer::glb::Glb; use middle::typeck::infer::lattice::*; use middle::typeck::infer::lub::Lub; use middle::typeck::infer::sub::Sub; -use middle::typeck::infer::to_str::ToStr; +use middle::typeck::infer::to_str::InferStr; use middle::typeck::isr_alist; use syntax::ast::{Many, Once, extern_fn, impure_fn, m_const, m_imm, m_mutbl}; use syntax::ast::{noreturn, pure_fn, ret_style, return_val, unsafe_fn}; @@ -25,10 +25,10 @@ use util::ppaux::mt_to_str; use std::list; -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 } @@ -94,10 +94,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), @@ -117,8 +113,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) @@ -130,7 +126,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): @@ -152,12 +148,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 @@ -177,20 +173,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, @@ -271,12 +267,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 aa67c1371f9..00000000000 --- a/src/librustc/middle/typeck/infer/integral.rs +++ /dev/null @@ -1,95 +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 core::prelude::*; - -use middle::ty::{get, ty_int, ty_uint}; -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 4437a1e780d..9783aee0848 100644 --- a/src/librustc/middle/typeck/infer/lattice.rs +++ b/src/librustc/middle/typeck/infer/lattice.rs @@ -8,162 +8,503 @@ // 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 core::prelude::*; use middle::ty::{RegionVid, TyVar}; use middle::ty; +use middle::typeck::isr_alist; use middle::typeck::infer::*; use middle::typeck::infer::combine::*; use middle::typeck::infer::glb::Glb; use middle::typeck::infer::lub::Lub; use middle::typeck::infer::unify::*; -use middle::typeck::infer::to_str::ToStr; -use middle::typeck::isr_alist; +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 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), + a.inf_str(self.infcx()), + b.inf_str(self.infcx())); + let _r = indenter(); - (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) ) - } + if a == b { + return Ok(a); + } - (ty::ty_infer(TyVar(a_id)), _) => { - lattice_var_and_t(self, a_id, b, - |x, y| self.tys(x, y) ) - } + let tcx = self.infcx().tcx; - (_, 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) - } + 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 { + VarResult(v) => Ok(ty::mk_var(tcx, v)), + ValueResult(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; - // 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. +enum LatticeVarResult { + VarResult(V), + ValueResult(T) +} - // Need to find a type that is a supertype of both a and b: - let vb = &self.infcx().ty_var_bindings; +/** + * Computes the LUB or GLB of two bounded variables. These could be any + * sort of variables, but in the comments on this function I'll assume + * we are doing an LUB on two type variables. + * + * This computation can be done in one of two ways: + * + * - If both variables have an upper bound, we may just compute the + * LUB of those bounds and return that, in which case we are + * returning a type. This is indicated with a `ValueResult` return. + * + * - If the variables do not both have an upper bound, we will unify + * the variables and return the unified variable, in which case the + * result is a variable. This is indicated with a `VarResult` + * return. */ +fn lattice_vars( + self: &L, // defines whether we want LUB or GLB + vb: &ValsAndBindings>, // relevant variable bindings + +a_vid: V, // first variable + +b_vid: V, // second variable + lattice_dir_op: LatticeDirOp) // LUB or GLB operation on types + -> cres> +{ 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())); + // Same variable: the easy case. if a_vid == b_vid { - return Ok(a_t); + return Ok(VarResult(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(ValueResult(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(VarResult(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) + } } - } } } @@ -171,7 +512,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 d478e8d9b92..ac6c4473999 100644 --- a/src/librustc/middle/typeck/infer/lub.rs +++ b/src/librustc/middle/typeck/infer/lub.rs @@ -16,7 +16,7 @@ use middle::typeck::infer::combine::*; use middle::typeck::infer::glb::Glb; 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 middle::typeck::isr_alist; use util::ppaux::mt_to_str; @@ -26,15 +26,15 @@ use syntax::ast::{pure_fn, ret_style, return_val, unsafe_fn}; 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 } @@ -80,15 +80,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), @@ -112,15 +103,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`. @@ -139,18 +130,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, @@ -197,18 +188,22 @@ impl Lub: combine { } } + fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres { + super_fns(&self, a, b) + } + fn fn_metas(a: &ty::FnMeta, b: &ty::FnMeta) -> cres { super_fn_metas(&self, a, b) } - fn fn_sigs(a: &ty::FnSig, b: &ty::FnSig) -> cres { - super_fn_sigs(&self, a, b) - } - // 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 51e0a5186e8..40134c76dbd 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 @@ -261,16 +248,14 @@ section on "Type Combining" below for details. use core::prelude::*; -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}; @@ -280,8 +265,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 middle::typeck::isr_alist; use util::common::{indent, indenter}; use util::ppaux::{bound_region_to_str, ty_to_str, mt_to_str}; @@ -302,7 +287,7 @@ use syntax::ast_util::dummy_sp; use syntax::ast_util; use syntax::codemap::span; -export infer_ctxt; +export InferCtxt; export new_infer_ctxt; export mk_subty, can_mk_subty; export mk_subr; @@ -313,15 +298,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,11 +315,12 @@ export to_str; export unify; export uok; export cyclic_ty, unresolved_ty, region_var_bound_by_region_var; -export bound, bounds; +export Bound, Bounds; export ures; export ares; export infer_ctxt; export fixup_err; +export IntVarValue, IntType, UintType; #[legacy_exports] mod assignment; @@ -346,9 +329,6 @@ mod combine; #[legacy_exports] mod glb; #[legacy_exports] -mod integral; -mod floating; -#[legacy_exports] mod lattice; #[legacy_exports] mod lub; @@ -363,39 +343,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), @@ -418,27 +407,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 new_infer_ctxt(tcx: ty::ctxt) -> @InferCtxt { + @InferCtxt { + tcx: tcx, -fn mk_subty(cx: infer_ctxt, a_is_expected: bool, span: span, + 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) @@ -446,8 +441,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) @@ -455,9 +450,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) @@ -465,9 +460,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); @@ -476,9 +471,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) @@ -486,8 +481,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(); @@ -497,18 +492,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) => { @@ -574,9 +569,10 @@ pub 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); @@ -589,12 +585,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 { @@ -624,8 +620,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 @@ -669,12 +664,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); } @@ -687,11 +682,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); } @@ -700,10 +694,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); } @@ -795,10 +789,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 @@ -809,18 +803,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 0d9c90e454c..54854bed65e 100644 --- a/src/librustc/middle/typeck/infer/region_inference.rs +++ b/src/librustc/middle/typeck/infer/region_inference.rs @@ -544,10 +544,11 @@ use core::prelude::*; use middle::region::is_subregion_of; use middle::region; use middle::ty; -use middle::ty::{Region, RegionVid, br_fresh, re_bound, re_free, re_infer}; -use middle::ty::{re_scope, re_static, ReVar, ReSkolemized}; +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::InferStr; use middle::typeck::infer::cres; -use middle::typeck::infer::to_str::ToStr; +use syntax::codemap; use util::common::indenter; 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 68e589cab27..23be3b20827 100644 --- a/src/librustc/middle/typeck/infer/resolve.rs +++ b/src/librustc/middle/typeck/infer/resolve.rs @@ -51,60 +51,61 @@ use core::prelude::*; use middle::ty::{FloatVar, FloatVid, IntVar, IntVid, RegionVid, TyVar, TyVid}; use middle::ty::{type_is_bot}; use middle::ty; -use middle::typeck::infer::{cyclic_ty, fixup_err, fres, infer_ctxt}; +use middle::typeck::infer::{cyclic_ty, fixup_err, fres, InferCtxt}; use middle::typeck::infer::{region_var_bound_by_region_var, unresolved_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::unify::root; -use util::common::indent; +use middle::typeck::infer::{IntType, UintType}; +use middle::typeck::infer::to_str::InferStr; +use middle::typeck::infer::unify::Root; +use util::common::{indent, indenter}; use util::ppaux::ty_to_str; +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)", @@ -129,7 +130,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 { @@ -138,63 +139,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(); - match copy ty::get(typ).sty { - ty::ty_infer(TyVar(vid)) => { + if !ty::type_needs_infer(typ) { + return typ; + } + + if self.type_depth > 0 && !self.should(resolve_nested_tvar) { + return typ; + } + + 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)); @@ -203,7 +205,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); @@ -236,27 +238,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) @@ -265,18 +262,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. @@ -284,10 +277,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 79405e955f5..aa6721fb229 100644 --- a/src/librustc/middle/typeck/infer/sub.rs +++ b/src/librustc/middle/typeck/infer/sub.rs @@ -11,13 +11,13 @@ use core::prelude::*; 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::combine::*; use middle::typeck::infer::cres; use middle::typeck::infer::glb::Glb; -use middle::typeck::infer::infer_ctxt; +use middle::typeck::infer::InferCtxt; use middle::typeck::infer::lub::Lub; -use middle::typeck::infer::to_str::ToStr; +use middle::typeck::infer::to_str::InferStr; use middle::typeck::infer::unify::*; use util::ppaux::bound_region_to_str; @@ -27,10 +27,10 @@ use syntax::ast::{m_const, purity, ret_style}; 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 } @@ -40,14 +40,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) @@ -56,8 +56,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), @@ -67,7 +67,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); @@ -86,14 +86,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)) @@ -108,34 +100,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` @@ -153,14 +158,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 %?", @@ -170,11 +175,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". @@ -206,21 +211,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 0a1647eb09a..42f516fe6d8 100644 --- a/src/librustc/middle/typeck/infer/to_str.rs +++ b/src/librustc/middle/typeck/infer/to_str.rs @@ -10,86 +10,101 @@ use core::prelude::*; -use middle::ty::vid; +use middle::ty::{FnMeta, FnTyBase, FnSig, FnVid, Vid}; use middle::ty; -use middle::typeck::infer::{bound, bounds}; -use middle::typeck::infer::floating::float_ty_set; -use middle::typeck::infer::infer_ctxt; -use middle::typeck::infer::integral::int_ty_set; -use middle::typeck::infer::unify::{redirect, root, var_value}; +use middle::typeck::infer::{Bound, Bounds}; +use middle::typeck::infer::{IntVarValue, IntType, UintType}; +use middle::typeck::infer::InferCtxt; +use middle::typeck::infer::unify::{Redirect, Root, VarValue}; use util::ppaux::{mt_to_str, ty_to_str}; use util::ppaux; -use core::uint; +use syntax::{ast, ast_util}; -trait ToStr { - fn to_str(cx: infer_ctxt) -> ~str; +use core::uint; +use core::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 { +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::mt : InferStr { + fn inf_str(cx: @InferCtxt) -> ~str { mt_to_str(cx.tcx, self) } } -impl ty::Region: ToStr { - fn to_str(cx: infer_ctxt) -> ~str { - ppaux::region_to_str(cx.tcx, self) +impl ty::Region : InferStr { + fn inf_str(_cx: @InferCtxt) -> ~str { + fmt!("%?", self) } } -impl ty::FnTy: ToStr { - fn to_str(cx: infer_ctxt) -> ~str { - ty::mk_fn(cx.tcx, self).to_str(cx) - } -} - -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) - } - } -} - -impl float_ty_set: ToStr { - fn to_str(_cx: infer_ctxt) -> ~str { - match self { - float_ty_set(v) => uint::to_str(v, 10u) - } - } -} - -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), + 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 IntVarValue : InferStr { + fn inf_str(_cx: @InferCtxt) -> ~str { + match self { + IntType(t) => ast_util::int_ty_to_str(t), + UintType(t) => ast_util::uint_ty_to_str(t) + } + } +} + +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 633ff706a26..77bd46eea2d 100644 --- a/src/librustc/middle/typeck/infer/unify.rs +++ b/src/librustc/middle/typeck/infer/unify.rs @@ -10,40 +10,45 @@ use core::prelude::*; -use middle::ty::vid; +use middle::ty::Vid; use middle::ty; -use middle::typeck::infer::{bound, bounds, cres, uok, ures}; -use middle::typeck::infer::combine::combine; -use middle::typeck::infer::floating::*; -use middle::typeck::infer::floating; -use middle::typeck::infer::infer_ctxt; -use middle::typeck::infer::integral::*; -use middle::typeck::infer::integral; -use middle::typeck::infer::to_str::ToStr; +use middle::typeck::infer::{Bound, Bounds, cres, uok, ures}; +use middle::typeck::infer::combine::Combine; +use middle::typeck::infer::InferCtxt; +use middle::typeck::infer::to_str::InferStr; use util::common::{indent, indenter}; 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) { @@ -52,435 +57,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)); - } -} - -// 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*/ } + vid.to_str(), old_v.inf_str(self), new_v.inf_str(self)); } - // 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. + 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 - // Rank optimization + debug!("unify(node_a(id=%?, rank=%?), \ + node_b(id=%?, rank=%?))", + node_a.root, node_a.rank, + node_b.root, node_b.rank); - // 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"); + 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 +// Code to handle simple variables like ints, floats---anything that +// doesn't have a subtyping relationship we need to worry about. -impl infer_ctxt { - fn float_vars(a_id: ty::FloatVid, b_id: ty::FloatVid) -> ures { - let vb = &self.float_var_bindings; +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 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; + 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); - } + 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) + } + }; - // Rank optimization - self.optimize_ranks(vb, nde_a, nde_b, a_id, b_id, intersection); - - 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); + 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 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 node_a = self.get(vb, a_id); + let a_id = node_a.root; - 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); + 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 f922e83a164..509fe96508b 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -271,7 +271,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 1a556c32bf3..528b997c8e6 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -69,8 +69,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; } @@ -84,8 +85,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 ebb75de8626..3cd38d67a29 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -25,14 +25,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; @@ -248,9 +246,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 => "~", @@ -265,13 +265,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 { @@ -301,15 +307,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 530f9f22666..165b5e257b2 100644 --- a/src/librustdoc/attr_pass.rs +++ b/src/librustdoc/attr_pass.rs @@ -35,7 +35,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 97caa71d692..4074d9aa691 100644 --- a/src/librustdoc/desc_to_brief_pass.rs +++ b/src/librustdoc/desc_to_brief_pass.rs @@ -29,7 +29,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 881352c9c77..1f4e1be62fc 100644 --- a/src/librustdoc/markdown_index_pass.rs +++ b/src/librustdoc/markdown_index_pass.rs @@ -26,7 +26,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 ad100b9b4e8..1ec30bc74ab 100644 --- a/src/librustdoc/markdown_pass.rs +++ b/src/librustdoc/markdown_pass.rs @@ -47,7 +47,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 c8e2865e986..2629d45635e 100644 --- a/src/librustdoc/page_pass.rs +++ b/src/librustdoc/page_pass.rs @@ -34,7 +34,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 e6b85ca9d64..1e5d5542963 100644 --- a/src/librustdoc/pass.rs +++ b/src/librustdoc/pass.rs @@ -18,10 +18,10 @@ use time; 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, @@ -82,11 +82,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 01ea26e1ad0..48ed1878771 100644 --- a/src/librustdoc/path_pass.rs +++ b/src/librustdoc/path_pass.rs @@ -23,7 +23,7 @@ use pass::Pass; 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 74c4b881eb3..3a924e3bddf 100644 --- a/src/librustdoc/prune_hidden_pass.rs +++ b/src/librustdoc/prune_hidden_pass.rs @@ -22,7 +22,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 f3db152696e..615bd07ca85 100644 --- a/src/librustdoc/prune_private_pass.rs +++ b/src/librustdoc/prune_private_pass.rs @@ -28,7 +28,7 @@ export mk_pass; export run; 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 a9cb8aa1e5d..eeadd82371f 100644 --- a/src/librustdoc/sectionalize_pass.rs +++ b/src/librustdoc/sectionalize_pass.rs @@ -26,7 +26,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 c6d2ab0e9ad..b3ecb8173fe 100644 --- a/src/librustdoc/sort_pass.rs +++ b/src/librustdoc/sort_pass.rs @@ -28,7 +28,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 975767727c5..5627bfead9f 100644 --- a/src/librustdoc/text_pass.rs +++ b/src/librustdoc/text_pass.rs @@ -23,7 +23,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 97d57569c73..ae1b7577ad8 100644 --- a/src/librustdoc/tystr_pass.rs +++ b/src/librustdoc/tystr_pass.rs @@ -29,7 +29,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 8b4c53604bc..12064e56bed 100644 --- a/src/libstd/test.rs +++ b/src/libstd/test.rs @@ -56,12 +56,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). @@ -242,14 +242,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, @@ -372,10 +372,11 @@ pub 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; } }; @@ -427,7 +428,8 @@ fn calc_result(test: &TestDesc, task_succeeded: bool) -> TestResult { mod tests { #[legacy_exports]; - use test::{TrFailed, TrIgnored, TrOk, filter_tests, parse_opts, run_test}; + use test::{TrFailed, TrIgnored, TrOk, filter_tests, parse_opts, TestDesc}; + use test::{run_test}; use core::either; use core::oldcomm; @@ -437,7 +439,7 @@ mod tests { #[test] fn do_not_run_ignored_tests() { fn f() { fail; } - let desc = { + let desc = TestDesc { name: ~"whatever", testfn: f, ignore: true, @@ -453,7 +455,7 @@ mod tests { #[test] fn ignored_tests_result_in_ignored() { fn f() { } - let desc = { + let desc = TestDesc { name: ~"whatever", testfn: f, ignore: true, @@ -470,7 +472,7 @@ mod tests { #[ignore(cfg(windows))] fn test_should_fail() { fn f() { fail; } - let desc = { + let desc = TestDesc { name: ~"whatever", testfn: f, ignore: false, @@ -486,7 +488,7 @@ mod tests { #[test] fn test_should_fail_but_succeeds() { fn f() { } - let desc = { + let desc = TestDesc { name: ~"whatever", testfn: f, ignore: false, @@ -527,10 +529,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); @@ -555,8 +557,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 b71f62c6db2..072a7e94fe9 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -19,6 +19,7 @@ use core::option::{None, Option, Some}; use core::ptr; use core::task; use core::to_bytes; +use core::to_str::ToStr; use std::serialize::{Encodable, Decodable, Encoder, Decoder}; #[auto_encode] @@ -415,6 +416,7 @@ impl mutability : cmp::Eq { #[auto_encode] #[auto_decode] +#[deriving_eq] pub enum Proto { ProtoBare, // bare functions (deprecated) ProtoUniq, // ~fn @@ -422,13 +424,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 +1063,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 +1155,17 @@ pub 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 81c7bb2abc9..9ddf1b24040 100644 --- a/src/libsyntax/ast_map.rs +++ b/src/libsyntax/ast_map.rs @@ -110,7 +110,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 55ac2ae0964..1a34fe29a71 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -440,10 +440,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 82dae3e26b3..e3fb7a289c1 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -322,13 +322,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 2c4efa82499..272ad3456e5 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -17,7 +17,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; @@ -34,6 +34,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; @@ -63,7 +64,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_, @@ -87,7 +88,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*/ @@ -631,8 +635,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, @@ -657,7 +661,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); @@ -763,7 +767,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 dda83aa2d0e..272c35152bb 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -44,11 +44,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 3f7ba2dc37b..0da6396253e 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -59,51 +59,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) { @@ -499,43 +504,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, @@ -640,37 +648,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 d55302481a9..291a506c4eb 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 1e539dc4f36..b2265f5e959 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 b21114d9222..457cdd23447 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 4e1989eb25c..bb6633ecdc1 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 7f8a4053c43..33d7b913daf 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 3a0e8ffb9c4..916008373c8 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 47f4f122f93..0e7d90e2fd8 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 653e84ea347..4b48e9a49c2 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 b87b3d3aa0d..15d809e8208 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; }