From aa1cd61c84199c8a1e44645e4af3f8c15c6dd018 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 9 Dec 2011 16:56:48 -0800 Subject: [PATCH] push changes through to get things compiling, if not running. --- src/comp/front/test.rs | 11 +++++- src/comp/metadata/tydecode.rs | 23 +++++++----- src/comp/metadata/tyencode.rs | 1 + src/comp/middle/freevars.rs | 4 +- src/comp/middle/kind.rs | 37 ++++++++++++------- src/comp/middle/tstate/auxiliary.rs | 5 ++- src/comp/middle/tstate/pre_post_conditions.rs | 2 + src/comp/middle/ty.rs | 28 ++++++-------- src/comp/syntax/ast.rs | 19 ++++++++++ src/comp/syntax/parse/parser.rs | 32 +++++++++------- src/comp/syntax/print/pprust.rs | 1 + 11 files changed, 103 insertions(+), 60 deletions(-) diff --git a/src/comp/front/test.rs b/src/comp/front/test.rs index 4756ee0b83e..c2ca656192e 100644 --- a/src/comp/front/test.rs +++ b/src/comp/front/test.rs @@ -347,9 +347,18 @@ fn mk_test_wrapper(cx: test_ctxt, body: wrapper_body }; + let wrapper_capture: @ast::capture = @{ + node: { + is_send: false, + copies: [], + moves: [] + }, + span: span + }; + let wrapper_expr: ast::expr = { id: cx.sess.next_node_id(), - node: ast::expr_fn(wrapper_fn), + node: ast::expr_fn(wrapper_fn, wrapper_capture), span: span }; diff --git a/src/comp/metadata/tydecode.rs b/src/comp/metadata/tydecode.rs index 0bf44376b63..434564f9c0d 100644 --- a/src/comp/metadata/tydecode.rs +++ b/src/comp/metadata/tydecode.rs @@ -164,6 +164,13 @@ fn parse_constr(st: @pstate, sd: str_def, pser: arg_parser) -> ret @respan(sp, {path: pth, args: args, id: def}); } +fn parse_ty_rust_fn(st: @pstate, sd: str_def, p: ast::proto) -> ty::t { + let func = parse_ty_fn(st, sd); + ret ty::mk_fn(st.tcx, p, + func.args, func.ty, func.cf, + func.cs); +} + fn parse_ty(st: @pstate, sd: str_def) -> ty::t { alt next(st) as char { 'n' { ret ty::mk_nil(st.tcx); } @@ -235,21 +242,17 @@ fn parse_ty(st: @pstate, sd: str_def) -> ty::t { st.pos = st.pos + 1u; ret ty::mk_tup(st.tcx, params); } + 's' { + ret parse_ty_rust_fn(st, sd, ast::proto_send); + } 'F' { - let func = parse_ty_fn(st, sd); - ret ty::mk_fn(st.tcx, ast::proto_shared(ast::sugar_normal), - func.args, func.ty, func.cf, - func.cs); + ret parse_ty_rust_fn(st, sd, ast::proto_shared(ast::sugar_normal)); } 'f' { - let func = parse_ty_fn(st, sd); - ret ty::mk_fn(st.tcx, ast::proto_bare, func.args, func.ty, func.cf, - func.cs); + ret parse_ty_rust_fn(st, sd, ast::proto_bare); } 'B' { - let func = parse_ty_fn(st, sd); - ret ty::mk_fn(st.tcx, ast::proto_block, func.args, func.ty, func.cf, - func.cs); + ret parse_ty_rust_fn(st, sd, ast::proto_block); } 'N' { let func = parse_ty_fn(st, sd); diff --git a/src/comp/metadata/tyencode.rs b/src/comp/metadata/tyencode.rs index 9fb37e4f4bf..18ab46d7ef3 100644 --- a/src/comp/metadata/tyencode.rs +++ b/src/comp/metadata/tyencode.rs @@ -193,6 +193,7 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) { } fn enc_proto(w: io::writer, proto: proto) { alt proto { + proto_send. { w.write_char('s'); } proto_shared(_) { w.write_char('F'); } proto_block. { w.write_char('B'); } proto_bare. { w.write_char('f'); } diff --git a/src/comp/middle/freevars.rs b/src/comp/middle/freevars.rs index bf1530e523f..8055f49f5d8 100644 --- a/src/comp/middle/freevars.rs +++ b/src/comp/middle/freevars.rs @@ -34,9 +34,7 @@ fn collect_freevars(def_map: resolve::def_map, walker: fn@(visit::vt)) -> lambda (expr: @ast::expr, &&depth: int, v: visit::vt) { alt expr.node { ast::expr_fn(f, captures) { - if f.proto == ast::proto_block || - f.proto == ast::proto_shared(ast::sugar_normal) || - f.proto == ast::proto_shared(ast::sugar_sexy) { + if f.proto != ast::proto_bare { visit::visit_expr(expr, depth + 1, v); } } diff --git a/src/comp/middle/kind.rs b/src/comp/middle/kind.rs index 974c6ca5f7f..8e577484303 100644 --- a/src/comp/middle/kind.rs +++ b/src/comp/middle/kind.rs @@ -48,6 +48,17 @@ fn check_crate(tcx: ty::ctxt, last_uses: last_use::last_uses, } fn check_expr(e: @expr, cx: ctx, v: visit::vt) { + + fn check_free_vars(e: @expr, + cx: ctx, + check_fn: fn(ctx, ty::t, sp: span)) { + for free in *freevars::get_freevars(cx.tcx, e.id) { + let id = ast_util::def_id_of_def(free).node; + let ty = ty::node_id_to_type(cx.tcx, id); + check_fn(cx, ty, e.span); + } + } + alt e.node { expr_assign(_, ex) | expr_assign_op(_, _, ex) | expr_block({node: {expr: some(ex), _}, _}) | @@ -65,7 +76,7 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt) { let ty_fields = alt ty::struct(cx.tcx, t) { ty::ty_rec(f) { f } }; for tf in ty_fields { if !vec::any({|f| f.node.ident == tf.ident}, fields) && - ty::type_kind(cx.tcx, tf.mt.ty) == kind_noncopyable { + !kind_can_be_copied(ty::type_kind(cx.tcx, tf.mt.ty)) { cx.tcx.sess.span_err(ex.span, "copying a noncopyable value"); } @@ -107,19 +118,11 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt) { none. {} } } - expr_fn({proto: proto_send, _}, captures) { - for free in *freevars::get_freevars(cx.tcx, e.id) { - let id = ast_util::def_id_of_def(free).node; - let ty = ty::node_id_to_type(cx.tcx, id); - check_copy(cx, ty, e.span); - } + expr_fn({proto: proto_send., _}, captures) { // NDM captures + check_free_vars(e, cx, check_send); } - expr_fn({proto: proto_shared(_), _}, captures) { - for free in *freevars::get_freevars(cx.tcx, e.id) { - let id = ast_util::def_id_of_def(free).node; - let ty = ty::node_id_to_type(cx.tcx, id); - check_copy(cx, ty, e.span); - } + expr_fn({proto: proto_shared(_), _}, captures) { // NDM captures + check_free_vars(e, cx, check_copy); } expr_ternary(_, a, b) { maybe_copy(cx, a); maybe_copy(cx, b); } _ { } @@ -159,11 +162,17 @@ fn check_copy_ex(cx: ctx, ex: @expr, _warn: bool) { } fn check_copy(cx: ctx, ty: ty::t, sp: span) { - if ty::type_kind(cx.tcx, ty) == kind_noncopyable { + if !kind_can_be_copied(ty::type_kind(cx.tcx, ty)) { cx.tcx.sess.span_err(sp, "copying a noncopyable value"); } } +fn check_send(cx: ctx, ty: ty::t, sp: span) { + if !kind_can_be_sent(ty::type_kind(cx.tcx, ty)) { + cx.tcx.sess.span_err(sp, "not a sendable value"); + } +} + // // Local Variables: // mode: rust diff --git a/src/comp/middle/tstate/auxiliary.rs b/src/comp/middle/tstate/auxiliary.rs index ec1c268e775..c9f27e36810 100644 --- a/src/comp/middle/tstate/auxiliary.rs +++ b/src/comp/middle/tstate/auxiliary.rs @@ -49,8 +49,9 @@ fn comma_str(args: [@constr_arg_use]) -> str { fn constraint_to_str(tcx: ty::ctxt, c: sp_constr) -> str { alt c.node { - ninit(_, i) { - ret "init(" + i + " [" + tcx.sess.span_str(c.span) + "])"; + ninit(id, i) { + ret #fmt("init(%s id=%d [%s])", + i, id, tcx.sess.span_str(c.span)); } npred(p, _, args) { ret path_to_str(p) + "(" + comma_str(args) + ")" + "[" + diff --git a/src/comp/middle/tstate/pre_post_conditions.rs b/src/comp/middle/tstate/pre_post_conditions.rs index 929dbce308a..ce759abf74d 100644 --- a/src/comp/middle/tstate/pre_post_conditions.rs +++ b/src/comp/middle/tstate/pre_post_conditions.rs @@ -278,6 +278,7 @@ fn handle_var(fcx: fn_ctxt, rslt: pre_and_post, id: node_id, name: ident) { } fn handle_var_def(fcx: fn_ctxt, rslt: pre_and_post, def: def, name: ident) { + log ("handle_var_def: ", def, name); alt def { def_local(d_id, _) | def_arg(d_id, _) { use_var(fcx, d_id.node); @@ -345,6 +346,7 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) { let rslt = expr_pp(fcx.ccx, e); clear_pp(rslt); for def in *freevars::get_freevars(fcx.ccx.tcx, e.id) { + log ("handle_var_def: def=", def); handle_var_def(fcx, rslt, def, "upvar"); } } diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index d369e818d47..d35d2038190 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -1971,29 +1971,23 @@ mod unify { } fn unify_fn_proto(e_proto: ast::proto, a_proto: ast::proto, variance: variance) -> option::t { + fn rank(proto: ast::proto) -> int { + ret alt proto { + ast::proto_block. { 0 } + ast::proto_shared(_) { 1 } + ast::proto_send. { 2 } + ast::proto_bare. { 3 } + }; + } + fn gt(e_proto: ast::proto, a_proto: ast::proto) -> bool { - alt e_proto { - ast::proto_block. { - // Every function type is a subtype of block - false - } - ast::proto_shared(_) { - a_proto == ast::proto_block - } - ast::proto_bare. { - a_proto != ast::proto_bare - } - } + ret rank(e_proto) > rank(a_proto); } ret if e_proto == a_proto { none } else if variance == invariant { - if e_proto != a_proto { - some(ures_err(terr_mismatch)) - } else { - fail - } + some(ures_err(terr_mismatch)) } else if variance == covariant { if gt(e_proto, a_proto) { some(ures_err(terr_mismatch)) diff --git a/src/comp/syntax/ast.rs b/src/comp/syntax/ast.rs index 62b24e220d8..0034eede2f2 100644 --- a/src/comp/syntax/ast.rs +++ b/src/comp/syntax/ast.rs @@ -106,6 +106,25 @@ tag mutability { mut; imm; maybe_mut; } tag kind { kind_sendable; kind_copyable; kind_noncopyable; } +// Using these query functons is preferable to direct comparison or matching +// against the kind constants, as we may modify the kind hierarchy in the +// future. +pure fn kind_can_be_copied(k: kind) -> bool { + ret alt k { + kind_sendable. { true } + kind_copyable. { true } + kind_noncopyable. { false } + }; +} + +pure fn kind_can_be_sent(k: kind) -> bool { + ret alt k { + kind_sendable. { true } + kind_copyable. { false } + kind_noncopyable. { false } + }; +} + tag proto_sugar { sugar_normal; sugar_sexy; diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs index 063042e3bad..c8b94616ab9 100644 --- a/src/comp/syntax/parse/parser.rs +++ b/src/comp/syntax/parse/parser.rs @@ -16,6 +16,7 @@ tag file_type { CRATE_FILE; SOURCE_FILE; } tag fn_kw { fn_kw_fn; + fn_kw_fn_at; fn_kw_lambda; fn_kw_block; } @@ -542,10 +543,9 @@ fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty { } else if eat_word(p, "block") { t = parse_ty_fn(ast::proto_block, p); } else if eat_word(p, "lambda") { - if p.peek() == token::LBRACE { // lambda[send](...) - expect(p, token::LBRACE); + if eat(p, token::LBRACKET) { // lambda[send](...) expect_word(p, "send"); - expect(p, token::RBRACE); + expect(p, token::RBRACKET); t = parse_ty_fn(ast::proto_send, p); } else { // lambda(...) t = parse_ty_fn(ast::proto_shared(ast::sugar_sexy), p); @@ -843,8 +843,8 @@ fn parse_bottom_expr(p: parser) -> @ast::expr { ret parse_spawn_expr(p); */ } else if eat_word(p, "fn") { - let proto = parse_fn_anon_proto(p); - ret parse_fn_expr(p, fn_kw_fn); + let kw = parse_fn_anon_kw(p); + ret parse_fn_expr(p, kw); } else if eat_word(p, "block") { ret parse_fn_expr(p, fn_kw_block); } else if eat_word(p, "lambda") { @@ -1295,7 +1295,7 @@ fn parse_if_expr(p: parser) -> @ast::expr { fn parse_capture_clause(p: parser) -> @ast::capture { fn expect_opt_trailing_semi(p: parser) { if !eat(p, token::SEMI) { - if p.peek() != token::RBRACE { + if p.peek() != token::RBRACKET { p.fatal("expecting ; or ]"); } } @@ -1306,7 +1306,9 @@ fn parse_capture_clause(p: parser) -> @ast::capture { while true { alt p.peek() { token::IDENT(_, _) { - let i = spanned(p.get_lo_pos(), p.get_hi_pos(), parse_ident(p)); + let i = spanned(p.get_lo_pos(), + p.get_hi_pos(), + parse_ident(p)); res += [i]; if !eat(p, token::COMMA) { ret res; @@ -1316,6 +1318,7 @@ fn parse_capture_clause(p: parser) -> @ast::capture { _ { ret res; } } } + std::util::unreachable(); } let is_send = false; @@ -1323,8 +1326,8 @@ fn parse_capture_clause(p: parser) -> @ast::capture { let moves = []; let lo = p.get_lo_pos(); - if eat(p, token::LBRACE) { - while !eat(p, token::RBRACE) { + if eat(p, token::LBRACKET) { + while !eat(p, token::RBRACKET) { if eat_word(p, "send") { is_send = true; expect_opt_trailing_semi(p); @@ -1352,10 +1355,13 @@ fn parse_fn_expr(p: parser, kw: fn_kw) -> @ast::expr { let body = parse_block(p); let proto = alt (kw, captures.node.is_send) { (fn_kw_fn., true) { ast::proto_bare } + (fn_kw_fn_at., true) { ast::proto_send } (fn_kw_lambda., true) { ast::proto_send } + (fn_kw_block., true) { p.fatal("block cannot be declared sendable"); } + (fn_kw_fn., false) { ast::proto_bare } + (fn_kw_fn_at., false) { ast::proto_shared(ast::sugar_normal) } (fn_kw_lambda., false) { ast::proto_shared(ast::sugar_sexy) } (fn_kw_block., false) { ast::proto_block } - (_, true) { p.fatal("only lambda can be declared sendable"); } }; let _fn = {decl: decl, proto: proto, body: body}; ret mk_expr(p, lo, body.span.hi, ast::expr_fn(_fn, captures)); @@ -2151,12 +2157,12 @@ fn parse_fn_ty_proto(p: parser) -> ast::proto { } } -fn parse_fn_anon_proto(p: parser) -> ast::proto { +fn parse_fn_anon_kw(p: parser) -> fn_kw { if p.peek() == token::AT { p.bump(); - ast::proto_shared(ast::sugar_normal) + fn_kw_fn_at } else { - ast::proto_bare + fn_kw_fn } } diff --git a/src/comp/syntax/print/pprust.rs b/src/comp/syntax/print/pprust.rs index 16b9f89bf63..5899cf95d7e 100644 --- a/src/comp/syntax/print/pprust.rs +++ b/src/comp/syntax/print/pprust.rs @@ -1600,6 +1600,7 @@ fn proto_to_str(p: ast::proto) -> str { ret alt p { ast::proto_bare. { "fn" } ast::proto_block. { "block" } + ast::proto_send. { "lambda[send]" } ast::proto_shared(ast::sugar_normal.) { "fn@" } ast::proto_shared(ast::sugar_sexy.) { "lambda" } };