diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 8667f36c749e5..8fcb9300b52e9 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -410,18 +410,24 @@ impl mutability : cmp::Eq { #[auto_serialize] #[auto_deserialize] -enum proto { - proto_bare, // foreign fn - proto_uniq, // fn~ - proto_box, // fn@ - proto_block, // fn& +pub enum Proto { + ProtoBare, // bare functions (deprecated) + ProtoUniq, // ~fn + ProtoBox, // @fn + ProtoBorrowed, // &fn } -impl proto : cmp::Eq { - pure fn eq(other: &proto) -> bool { +impl Proto : cmp::Eq { + pure fn eq(other: &Proto) -> bool { (self as uint) == ((*other) as uint) } - pure fn ne(other: &proto) -> bool { !self.eq(other) } + pure fn ne(other: &Proto) -> bool { !self.eq(other) } +} + +impl Proto : to_bytes::IterBytes { + pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) { + (self as uint).iter_bytes(lsb0, f); + } } #[auto_serialize] @@ -444,10 +450,10 @@ enum expr_vstore { expr_vstore_slice // &[1,2,3,4] } -pure fn is_blockish(p: ast::proto) -> bool { +pure fn is_blockish(p: ast::Proto) -> bool { match p { - proto_block => true, - proto_bare | proto_uniq | proto_box => false + ProtoBorrowed => true, + ProtoBare | ProtoUniq | ProtoBox => false } } @@ -678,7 +684,7 @@ enum expr_ { (implicit) condition is always true. */ expr_loop(blk, Option), expr_match(@expr, ~[arm]), - expr_fn(proto, fn_decl, blk, capture_clause), + expr_fn(Proto, fn_decl, blk, capture_clause), expr_fn_block(fn_decl, blk, capture_clause), // Inner expr is always an expr_fn_block. We need the wrapping node to // easily type this (a function returning nil on the inside but bool on @@ -1078,6 +1084,17 @@ impl Onceness : cmp::Eq { } } +#[auto_serialize] +#[auto_deserialize] +struct TyFn { + proto: Proto, + region: Option<@region>, + purity: purity, + onceness: Onceness, + bounds: @~[ty_param_bound], + decl: fn_decl +} + #[auto_serialize] #[auto_deserialize] enum ty_ { @@ -1086,13 +1103,13 @@ enum ty_ { ty_box(mt), ty_uniq(mt), ty_vec(mt), + ty_fixed_length_vec(mt, uint), ty_ptr(mt), ty_rptr(@region, mt), ty_rec(~[ty_field]), - ty_fn(proto, purity, Onceness, @~[ty_param_bound], fn_decl), + ty_fn(@TyFn), ty_tup(~[@Ty]), ty_path(@path, node_id), - ty_fixed_length(@Ty, Option), ty_mac(mac), // ty_infer means the type should be inferred instead of it having been // specified. This should only appear at the "top level" of a type and not diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 7c8909668f535..3879e70cb2888 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -524,15 +524,19 @@ fn noop_fold_ty(t: ty_, fld: ast_fold) -> ty_ { ty_ptr(mt) => ty_ptr(fold_mt(mt, fld)), ty_rptr(region, mt) => ty_rptr(region, fold_mt(mt, fld)), ty_rec(fields) => ty_rec(vec::map(fields, |f| fold_field(*f, fld))), - ty_fn(proto, purity, onceness, bounds, decl) => - ty_fn(proto, - purity, - onceness, - @vec::map(*bounds, |x| fold_ty_param_bound(*x, fld)), - fold_fn_decl(decl, fld)), + ty_fn(f) => + ty_fn(@TyFn { + proto: f.proto, + purity: f.purity, + region: f.region, + onceness: f.onceness, + bounds: @vec::map(*f.bounds, |x| fold_ty_param_bound(*x, fld)), + decl: fold_fn_decl(f.decl, fld) + }), ty_tup(tys) => ty_tup(vec::map(tys, |ty| fld.fold_ty(*ty))), ty_path(path, id) => ty_path(fld.fold_path(path), fld.new_id(id)), - ty_fixed_length(t, vs) => ty_fixed_length(fld.fold_ty(t), vs), + ty_fixed_length_vec(mt, vs) => + ty_fixed_length_vec(fold_mt(mt, fld), vs), ty_mac(mac) => ty_mac(fold_mac(mac)) } } diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index 1344c9b11ea52..e5f6cf8ee2537 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -24,7 +24,6 @@ pub enum ObsoleteSyntax { ObsoletePrivSection, ObsoleteModeInFnType, ObsoleteByMutRefMode, - ObsoleteFixedLengthVec, ObsoleteMoveInit, ObsoleteBinaryMove } @@ -102,11 +101,6 @@ impl Parser : ObsoleteReporter { "by-mutable-reference mode", "Declare an argument of type &mut T instead" ), - ObsoleteFixedLengthVec => ( - "fixed-length vector", - "Fixed-length types are now written `[T * N]`, and instances \ - are type-inferred" - ), ObsoleteMoveInit => ( "initializer-by-move", "Write `let foo = move bar` instead" @@ -200,65 +194,5 @@ impl Parser : ObsoleteReporter { } } - fn try_parse_obsolete_fixed_vstore() -> Option> { - if self.token == token::BINOP(token::SLASH) { - self.bump(); - match copy self.token { - token::UNDERSCORE => { - self.obsolete(copy self.last_span, - ObsoleteFixedLengthVec); - self.bump(); Some(None) - } - token::LIT_INT_UNSUFFIXED(i) if i >= 0i64 => { - self.obsolete(copy self.last_span, - ObsoleteFixedLengthVec); - self.bump(); Some(Some(i as uint)) - } - _ => None - } - } else { - None - } - } - - fn try_convert_ty_to_obsolete_fixed_length_vstore(sp: span, t: ast::ty_) - -> ast::ty_ { - match self.try_parse_obsolete_fixed_vstore() { - // Consider a fixed length vstore suffix (/N or /_) - None => t, - Some(v) => { - ast::ty_fixed_length( - @{id: self.get_id(), node: t, span: sp}, v) - } - } - } - - fn try_convert_expr_to_obsolete_fixed_length_vstore( - lo: uint, hi: uint, ex: ast::expr_ - ) -> (uint, ast::expr_) { - - let mut hi = hi; - let mut ex = ex; - - // Vstore is legal following expr_lit(lit_str(...)) and expr_vec(...) - // only. - match ex { - ast::expr_lit(@{node: ast::lit_str(_), span: _}) | - ast::expr_vec(_, _) => { - match self.try_parse_obsolete_fixed_vstore() { - None => (), - Some(v) => { - hi = self.span.hi; - ex = ast::expr_vstore(self.mk_expr(lo, hi, ex), - ast::expr_vstore_fixed(v)); - } - } - } - _ => () - } - - return (hi, ex); - } - } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 63545a6960872..5d07f666af6a7 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -50,8 +50,8 @@ use ast::{_mod, add, arg, arm, attribute, match_tok, method, mode, module_ns, mt, mul, mutability, named_field, neg, noreturn, not, pat, pat_box, pat_enum, pat_ident, pat_lit, pat_range, pat_rec, pat_region, pat_struct, - pat_tup, pat_uniq, pat_wild, path, private, proto, proto_bare, - proto_block, proto_box, proto_uniq, provided, public, pure_fn, + pat_tup, pat_uniq, pat_wild, path, private, Proto, ProtoBare, + ProtoBorrowed, ProtoBox, ProtoUniq, provided, public, pure_fn, purity, re_static, re_self, re_anon, re_named, region, rem, required, ret_style, return_val, self_ty, shl, shr, stmt, stmt_decl, stmt_expr, @@ -61,14 +61,14 @@ use ast::{_mod, add, arg, arm, attribute, tt_tok, tt_nonterminal, tuple_variant_kind, Ty, ty_, ty_bot, ty_box, ty_field, ty_fn, ty_infer, ty_mac, ty_method, ty_nil, ty_param, ty_param_bound, ty_path, ty_ptr, ty_rec, ty_rptr, - ty_tup, ty_u32, ty_uniq, ty_vec, ty_fixed_length, type_value_ns, - uniq, unnamed_field, unsafe_blk, unsafe_fn, + ty_tup, ty_u32, ty_uniq, ty_vec, ty_fixed_length_vec, + type_value_ns, uniq, unnamed_field, unsafe_blk, unsafe_fn, variant, view_item, view_item_, view_item_export, view_item_import, view_item_use, view_path, view_path_glob, view_path_list, view_path_simple, visibility, vstore, vstore_box, vstore_fixed, vstore_slice, vstore_uniq, expr_vstore_fixed, expr_vstore_slice, expr_vstore_box, - expr_vstore_uniq}; + expr_vstore_uniq, TyFn, Onceness, Once, Many}; export file_type; export Parser; @@ -287,30 +287,90 @@ impl Parser { pure fn id_to_str(id: ident) -> @~str { self.sess.interner.get(id) } - fn parse_ty_fn(purity: ast::purity, onceness: ast::Onceness) -> ty_ { - let proto, bounds; + fn token_is_fn_keyword(+tok: token::Token) -> bool { + self.token_is_keyword(~"pure", tok) || + self.token_is_keyword(~"unsafe", tok) || + self.token_is_keyword(~"once", tok) || + self.token_is_keyword(~"fn", tok) || + self.token_is_keyword(~"extern", tok) + } + + fn parse_ty_fn(pre_proto: Option, + pre_region_name: Option) -> ty_ + { + /* + + (&|~|@) [r/] [pure|unsafe] [once] fn [:K] (S) -> T + ^~~~~~^ ^~~^ ^~~~~~~~~~~~^ ^~~~~^ ^~~^ ^~^ ^ + | | | | | | | + | | | | | | Return type + | | | | | Argument types + | | | | Environment bounds + | | | Once-ness (a.k.a., affine) + | | Purity + | Lifetime bound + Allocation type + + */ + + // At this point, the allocation type and lifetime bound have been + // parsed. + + let purity = parse_purity(&self); + let onceness = parse_onceness(&self); + + let bounds, post_proto; if self.eat_keyword(~"extern") { self.expect_keyword(~"fn"); - proto = ast::proto_bare; + post_proto = Some(ast::ProtoBare); bounds = @~[]; } else { self.expect_keyword(~"fn"); - proto = self.parse_fn_ty_proto(); + post_proto = self.parse_fn_ty_proto(); bounds = self.parse_optional_ty_param_bounds(); }; - ty_fn(proto, purity, onceness, bounds, self.parse_ty_fn_decl()) - } - fn parse_ty_fn_with_onceness(purity: ast::purity) -> ty_ { - let onceness = self.parse_optional_onceness(); - self.parse_ty_fn(purity, onceness) - } + let proto = match (pre_proto, post_proto) { + (None, None) => ast::ProtoBorrowed, + (Some(p), None) | (None, Some(p)) => p, + (Some(_), Some(_)) => { + self.fatal(~"Cannot combine prefix and postfix \ + syntax for closure kind; note that \ + postfix syntax is obsolete"); + } + }; + + let region = if pre_region_name.is_some() { + Some(self.region_from_name(pre_region_name)) + } else { + None + }; + + return ty_fn(@TyFn { + proto: proto, + region: region, + purity: purity, + onceness: onceness, + bounds: bounds, + decl: self.parse_ty_fn_decl() + }); + + fn parse_purity(self: &Parser) -> purity { + if self.eat_keyword(~"pure") { + return pure_fn; + } else if self.eat_keyword(~"unsafe") { + return unsafe_fn; + } else { + return impure_fn; + } + } - fn parse_ty_fn_with_purity_and_onceness() -> ty_ { - let purity = self.parse_optional_purity(); - self.parse_ty_fn_with_onceness(purity) + fn parse_onceness(self: &Parser) -> Onceness { + if self.eat_keyword(~"once") {Once} else {Many} + } } + fn parse_ty_fn_decl() -> fn_decl { let inputs = do self.parse_unspanned_seq( token::LPAREN, token::RPAREN, @@ -449,23 +509,6 @@ impl Parser { } } - // Parses something like "&x/" (note the trailing slash) - fn parse_region_with_sep() -> @region { - let name = - match copy self.token { - token::IDENT(sid, _) => { - if self.look_ahead(1u) == token::BINOP(token::SLASH) { - self.bump(); self.bump(); - Some(sid) - } else { - None - } - } - _ => { None } - }; - self.region_from_name(name) - } - fn parse_ty(colons_before_params: bool) -> @Ty { maybe_whole!(self, nt_ty); @@ -498,10 +541,10 @@ impl Parser { } } else if self.token == token::AT { self.bump(); - ty_box(self.parse_mt()) + self.parse_box_or_uniq_pointee(ast::ProtoBox, ty_box) } else if self.token == token::TILDE { self.bump(); - ty_uniq(self.parse_mt()) + self.parse_box_or_uniq_pointee(ast::ProtoUniq, ty_uniq) } else if self.token == token::BINOP(token::STAR) { self.bump(); ty_ptr(self.parse_mt()) @@ -516,51 +559,77 @@ impl Parser { ty_rec(elems) } else if self.token == token::LBRACKET { self.expect(token::LBRACKET); - let mut t = ty_vec(self.parse_mt()); + let mt = self.parse_mt(); // Parse the `* 3` in `[ int * 3 ]` - match self.maybe_parse_fixed_vstore_with_star() { - None => {} - Some(suffix) => { - t = ty_fixed_length(@{ - id: self.get_id(), - node: t, - span: mk_sp(lo, self.last_span.hi) - }, suffix) - } - } + let t = match self.maybe_parse_fixed_vstore_with_star() { + None => ty_vec(mt), + Some(suffix) => ty_fixed_length_vec(mt, suffix) + }; self.expect(token::RBRACKET); t } else if self.token == token::BINOP(token::AND) { self.bump(); - let region = self.parse_region_with_sep(); - let mt = self.parse_mt(); - ty_rptr(region, mt) - } else if self.eat_keyword(~"once") { - self.parse_ty_fn(ast::impure_fn, ast::Once) - } else if self.eat_keyword(~"pure") { - self.parse_ty_fn_with_onceness(ast::pure_fn) - } else if self.eat_keyword(~"unsafe") { - self.parse_ty_fn_with_onceness(ast::unsafe_fn) - } else if self.is_keyword(~"fn") { - self.parse_ty_fn_with_onceness(ast::impure_fn) - } else if self.eat_keyword(~"extern") { - self.expect_keyword(~"fn"); - ty_fn(proto_bare, ast::impure_fn, ast::Many, @~[], - self.parse_ty_fn_decl()) + self.parse_borrowed_pointee() + } else if self.token_is_fn_keyword(self.token) { + self.parse_ty_fn(None, None) } else if self.token == token::MOD_SEP || is_ident(self.token) { let path = self.parse_path_with_tps(colons_before_params); ty_path(path, self.get_id()) } else { self.fatal(~"expected type"); }; let sp = mk_sp(lo, self.last_span.hi); - return { - let node = - self.try_convert_ty_to_obsolete_fixed_length_vstore(sp, t); - @{id: self.get_id(), - node: node, - span: sp} + return @{id: self.get_id(), node: t, span: sp}; + } + + fn parse_box_or_uniq_pointee( + proto: ast::Proto, + ctor: &fn(+v: mt) -> ty_) -> ty_ + { + // @foo/fn() or @fn() are parsed directly as fn types: + match copy self.token { + token::IDENT(rname, _) => { + if self.look_ahead(1u) == token::BINOP(token::SLASH) && + self.token_is_fn_keyword(self.look_ahead(2u)) + { + self.bump(); self.bump(); + return self.parse_ty_fn(Some(proto), Some(rname)); + } else if self.token_is_fn_keyword(self.token) { + return self.parse_ty_fn(Some(proto), None); + } + } + _ => {} + } + + // other things are parsed as @ + a type. Note that constructs like + // @[] and @str will be resolved during typeck to slices and so forth, + // rather than boxed ptrs. But the special casing of str/vec is not + // reflected in the AST type. + let mt = self.parse_mt(); + ctor(mt) + } + + fn parse_borrowed_pointee() -> ty_ { + // look for `&foo/` and interpret `foo` as the region name: + let rname = match copy self.token { + token::IDENT(sid, _) => { + if self.look_ahead(1u) == token::BINOP(token::SLASH) { + self.bump(); self.bump(); + Some(sid) + } else { + None + } + } + _ => { None } }; + + if self.token_is_fn_keyword(self.token) { + return self.parse_ty_fn(Some(ProtoBorrowed), rname); + } + + let r = self.region_from_name(rname); + let mt = self.parse_mt(); + return ty_rptr(r, mt); } fn parse_arg_mode() -> mode { @@ -691,16 +760,19 @@ impl Parser { } } - fn maybe_parse_fixed_vstore_with_star() -> Option> { + fn maybe_parse_fixed_vstore_with_star() -> Option { if self.eat(token::BINOP(token::STAR)) { match copy self.token { - token::UNDERSCORE => { - self.bump(); Some(None) - } - token::LIT_INT_UNSUFFIXED(i) if i >= 0i64 => { - self.bump(); Some(Some(i as uint)) - } - _ => None + token::LIT_INT_UNSUFFIXED(i) if i >= 0i64 => { + self.bump(); + Some(i as uint) + } + _ => { + self.fatal( + fmt!("expected integral vector length \ + but found `%s`", + token_to_str(self.reader, self.token))); + } } } else { None @@ -909,11 +981,13 @@ impl Parser { } else if self.eat_keyword(~"match") { return self.parse_alt_expr(); } else if self.eat_keyword(~"fn") { - let proto = self.parse_fn_ty_proto(); - match proto { - proto_bare => self.fatal(~"fn expr are deprecated, use fn@"), - _ => { /* fallthrough */ } - } + let opt_proto = self.parse_fn_ty_proto(); + let proto = match opt_proto { + None | Some(ast::ProtoBare) => { + self.fatal(~"fn expr are deprecated, use fn@") + } + Some(p) => { p } + }; return self.parse_fn_expr(proto); } else if self.eat_keyword(~"unsafe") { return self.parse_block_expr(lo, unsafe_blk); @@ -1055,9 +1129,6 @@ impl Parser { ex = expr_lit(@lit); } - let (hi, ex) = - self.try_convert_expr_to_obsolete_fixed_length_vstore(lo, hi, ex); - return self.mk_expr(lo, hi, ex); } @@ -1495,7 +1566,7 @@ impl Parser { return self.mk_expr(q.lo, q.hi, expr_if(q.cond, q.then, q.els)); } - fn parse_fn_expr(proto: proto) -> @expr { + fn parse_fn_expr(proto: Proto) -> @expr { let lo = self.last_span.lo; // if we want to allow fn expression argument types to be inferred in @@ -3188,23 +3259,23 @@ impl Parser { (id, item_enum(enum_definition, ty_params), None) } - fn parse_fn_ty_proto() -> proto { + fn parse_fn_ty_proto() -> Option { match self.token { - token::AT => { - self.bump(); - proto_box - } - token::TILDE => { - self.bump(); - proto_uniq - } - token::BINOP(token::AND) => { - self.bump(); - proto_block - } - _ => { - proto_block - } + token::AT => { + self.bump(); + Some(ProtoBox) + } + token::TILDE => { + self.bump(); + Some(ProtoUniq) + } + token::BINOP(token::AND) => { + self.bump(); + Some(ProtoBorrowed) + } + _ => { + None + } } } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index e0b9958bcb748..ed64d02cea36e 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -7,6 +7,7 @@ use ast_util::{operator_prec}; use dvec::DVec; use parse::classify::*; use parse::token::ident_interner; +use str::{push_str, push_char}; // The ps is stored here to prevent recursive type. enum ann_node { @@ -211,7 +212,9 @@ fn head(s: ps, w: ~str) { // head-box is inconsistent ibox(s, str::len(w) + 1); // keyword that starts the head - word_nbsp(s, w); + if !w.is_empty() { + word_nbsp(s, w); + } } fn bopen(s: ps) { @@ -328,20 +331,19 @@ fn print_foreign_mod(s: ps, nmod: ast::foreign_mod, for nmod.items.each |item| { print_foreign_item(s, *item); } } -fn print_region(s: ps, region: @ast::region, sep: ~str) { +fn print_region(s: ps, prefix: ~str, region: @ast::region, sep: ~str) { + word(s.s, prefix); match region.node { ast::re_anon => { - word_space(s, ~"&"); return; } ast::re_static => { - word_space(s, ~"&static") + word_space(s, ~"static") } ast::re_self => { - word_space(s, ~"&self") + word_space(s, ~"self") } ast::re_named(name) => { - word(s.s, ~"&"); print_ident(s, name); } } @@ -372,7 +374,7 @@ fn print_type_ex(s: ps, &&ty: @ast::Ty, print_colons: bool) { } ast::ty_ptr(mt) => { word(s.s, ~"*"); print_mt(s, mt); } ast::ty_rptr(region, mt) => { - print_region(s, region, ~"/"); + print_region(s, ~"&", region, ~"/"); print_mt(s, mt); } ast::ty_rec(fields) => { @@ -394,26 +396,21 @@ fn print_type_ex(s: ps, &&ty: @ast::Ty, print_colons: bool) { commasep(s, inconsistent, elts, print_type); pclose(s); } - ast::ty_fn(proto, purity, onceness, bounds, d) => { - print_ty_fn(s, Some(proto), purity, onceness, bounds, d, None, None, - None); + ast::ty_fn(f) => { + print_ty_fn(s, Some(f.proto), f.region, f.purity, + f.onceness, f.bounds, f.decl, None, None, None); } ast::ty_path(path, _) => print_path(s, path, print_colons), - ast::ty_fixed_length(t, v) => { + ast::ty_fixed_length_vec(mt, v) => { word(s.s, ~"["); - match t.node { - ast::ty_vec(mt) => { - match mt.mutbl { - ast::m_mutbl => word_space(s, ~"mut"), - ast::m_const => word_space(s, ~"const"), - ast::m_imm => () - } - print_type(s, mt.ty); - } - _ => fail ~"ty_fixed_length can only contain ty_vec as type" + match mt.mutbl { + ast::m_mutbl => word_space(s, ~"mut"), + ast::m_const => word_space(s, ~"const"), + ast::m_imm => () } + print_type(s, mt.ty); word(s.s, ~" * "); - print_vstore(s, ast::vstore_fixed(v)); + word(s.s, fmt!("%u", v)); word(s.s, ~"]"); } ast::ty_mac(_) => { @@ -805,7 +802,7 @@ fn print_ty_method(s: ps, m: ast::ty_method) { hardbreak_if_not_bol(s); maybe_print_comment(s, m.span.lo); print_outer_attributes(s, m.attrs); - print_ty_fn(s, None, m.purity, ast::Many, + print_ty_fn(s, None, None, m.purity, ast::Many, @~[], m.decl, Some(m.ident), Some(m.tps), Some(m.self_ty.node)); word(s.s, ~";"); @@ -1023,7 +1020,7 @@ fn print_vstore(s: ps, t: ast::vstore) { ast::vstore_fixed(None) => word(s.s, ~"_"), ast::vstore_uniq => word(s.s, ~"~"), ast::vstore_box => word(s.s, ~"@"), - ast::vstore_slice(r) => print_region(s, r, ~"/") + ast::vstore_slice(r) => print_region(s, ~"&", r, ~"/") } } @@ -1274,8 +1271,8 @@ fn print_expr(s: ps, &&expr: @ast::expr) { cbox(s, indent_unit); // head-box, will be closed by print-block at start ibox(s, 0u); - word(s.s, fn_header_info_to_str(None, None, Some(proto), ast::Many, - ast::inherited)); + print_fn_header_info(s, None, None, ast::Many, + Some(proto), ast::inherited); print_fn_args_and_ret(s, decl, *cap_clause, None); space(s.s); print_block(s, body); @@ -1481,7 +1478,7 @@ fn print_path(s: ps, &&path: @ast::path, colons_before_params: bool) { None => { /* ok */ } Some(r) => { word(s.s, ~"/"); - print_region(s, r, ~""); + print_region(s, ~"&", r, ~""); } } @@ -1614,8 +1611,9 @@ fn print_fn(s: ps, typarams: ~[ast::ty_param], opt_self_ty: Option, vis: ast::visibility) { - head(s, fn_header_info_to_str(opt_self_ty, purity, None, ast::Many, - vis)); + head(s, ~""); + print_fn_header_info(s, opt_self_ty, purity, ast::Many, None, vis); + nbsp(s); print_ident(s, name); print_type_params(s, typarams); print_fn_args_and_ret(s, decl, ~[], opt_self_ty); @@ -1836,7 +1834,8 @@ fn print_arg(s: ps, input: ast::arg) { } fn print_ty_fn(s: ps, - opt_proto: Option, + opt_proto: Option, + opt_region: Option<@ast::region>, purity: ast::purity, onceness: ast::Onceness, bounds: @~[ast::ty_param_bound], @@ -1844,8 +1843,15 @@ fn print_ty_fn(s: ps, tps: Option<~[ast::ty_param]>, opt_self_ty: Option) { ibox(s, indent_unit); - word(s.s, fn_header_info_to_str(opt_self_ty, Some(purity), opt_proto, - onceness, ast::inherited)); + + // Duplicates the logic in `print_fn_header_info()`. This is because that + // function prints the proto in the wrong place. That should be fixed. + print_self_ty_if_static(s, opt_self_ty); + print_opt_proto(s, opt_proto); + for opt_region.each |r| { print_region(s, ~"", *r, ~"/"); } + print_purity(s, purity); + print_onceness(s, onceness); + word(s.s, ~"fn"); print_bounds(s, bounds); match id { Some(id) => { word(s.s, ~" "); print_ident(s, id); } _ => () } match tps { Some(tps) => print_type_params(s, tps), _ => () } @@ -2066,39 +2072,50 @@ fn next_comment(s: ps) -> Option { } } -fn fn_header_info_to_str(opt_sty: Option, - opt_purity: Option, - opt_p: Option, - onceness: ast::Onceness, - vis: ast::visibility) -> ~str { - - let mut s = visibility_qualified(vis, ~""); - - match opt_sty { - Some(ast::sty_static) => str::push_str(&mut s, ~"static "), - _ => () - }; +fn print_self_ty_if_static(s: ps, + opt_self_ty: Option) { + match opt_self_ty { + Some(ast::sty_static) => { word(s.s, ~"static "); } + _ => {} + } +} +fn print_opt_purity(s: ps, opt_purity: Option) { match opt_purity { - Some(ast::impure_fn) => { } - Some(purity) => { - str::push_str(&mut s, purity_to_str(purity)); - str::push_char(&mut s, ' '); - } - None => {} + Some(ast::impure_fn) => { } + Some(purity) => { + word_nbsp(s, purity_to_str(purity)); + } + None => {} } +} - str::push_str(&mut s, opt_proto_to_str(opt_p)); - - match onceness { - ast::Once => str::push_str(&mut s, ~"once "), - ast::Many => {} - } +fn print_opt_proto(s: ps, opt_proto: Option) { + match opt_proto { + Some(ast::ProtoBare) => { word(s.s, ~"extern "); } + Some(ast::ProtoBorrowed) => { word(s.s, ~"&"); } + Some(ast::ProtoUniq) => { word(s.s, ~"~"); } + Some(ast::ProtoBox) => { word(s.s, ~"@"); } + None => {} + }; +} - return s; +fn print_fn_header_info(s: ps, + opt_sty: Option, + opt_purity: Option, + onceness: ast::Onceness, + opt_proto: Option, + vis: ast::visibility) +{ + word(s.s, visibility_qualified(vis, ~"")); + print_self_ty_if_static(s, opt_sty); + print_opt_purity(s, opt_purity); + print_onceness(s, onceness); + word(s.s, ~"fn"); + print_opt_proto(s, opt_proto); } -fn opt_proto_to_str(opt_p: Option) -> ~str { +fn opt_proto_to_str(opt_p: Option) -> ~str { match opt_p { None => ~"fn", Some(p) => proto_to_str(p) @@ -2128,12 +2145,19 @@ fn print_purity(s: ps, p: ast::purity) { } } -fn proto_to_str(p: ast::proto) -> ~str { +fn print_onceness(s: ps, o: ast::Onceness) { + match o { + ast::Once => { word_nbsp(s, ~"once"); } + ast::Many => {} + } +} + +fn proto_to_str(p: ast::Proto) -> ~str { return match p { - ast::proto_bare => ~"extern fn", - ast::proto_block => ~"fn&", - ast::proto_uniq => ~"fn~", - ast::proto_box => ~"fn@" + ast::ProtoBare => ~"extern fn", + ast::ProtoBorrowed => ~"fn&", + ast::ProtoUniq => ~"fn~", + ast::ProtoBox => ~"fn@" }; } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index be6fb4cefa83e..97cc52bd35a16 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -15,7 +15,7 @@ enum vt { mk_vt(visitor), } enum fn_kind { fk_item_fn(ident, ~[ty_param], purity), //< an item declared with fn() fk_method(ident, ~[ty_param], @method), - fk_anon(proto, capture_clause), //< an anonymous function like fn@(...) + fk_anon(Proto, capture_clause), //< an anonymous function like fn@(...) fk_fn_block(capture_clause), //< a block {||...} fk_dtor(~[ty_param], ~[attribute], node_id /* self id */, def_id /* parent class id */) // class destructor @@ -203,13 +203,13 @@ fn visit_ty(t: @Ty, e: E, v: vt) { ty_tup(ts) => for ts.each |tt| { v.visit_ty(*tt, e, v); }, - ty_fn(_, _, _, bounds, decl) => { - for decl.inputs.each |a| { v.visit_ty(a.ty, e, v); } - visit_ty_param_bounds(bounds, e, v); - v.visit_ty(decl.output, e, v); + ty_fn(f) => { + for f.decl.inputs.each |a| { v.visit_ty(a.ty, e, v); } + visit_ty_param_bounds(f.bounds, e, v); + v.visit_ty(f.decl.output, e, v); } ty_path(p, _) => visit_path(p, e, v), - ty_fixed_length(t, _) => v.visit_ty(t, e, v), + ty_fixed_length_vec(mt, _) => v.visit_ty(mt.ty, e, v), ty_nil | ty_bot | ty_mac(_) | diff --git a/src/rustc/front/test.rs b/src/rustc/front/test.rs index f0c9de4f2a245..c839be0739f9c 100644 --- a/src/rustc/front/test.rs +++ b/src/rustc/front/test.rs @@ -406,7 +406,7 @@ fn mk_test_wrapper(cx: test_ctxt, let wrapper_expr: ast::expr = { id: cx.sess.next_node_id(), callee_id: cx.sess.next_node_id(), - node: ast::expr_fn(ast::proto_bare, wrapper_decl, + node: ast::expr_fn(ast::ProtoBare, wrapper_decl, wrapper_body, @~[]), span: span }; diff --git a/src/rustc/metadata/tydecode.rs b/src/rustc/metadata/tydecode.rs index f15c254e71c00..51c56cb8a649c 100644 --- a/src/rustc/metadata/tydecode.rs +++ b/src/rustc/metadata/tydecode.rs @@ -103,11 +103,13 @@ fn parse_ty_rust_fn(st: @pstate, conv: conv_did) -> ty::t { return ty::mk_fn(st.tcx, parse_ty_fn(st, conv)); } -fn parse_proto(st: @pstate) -> ty::fn_proto { +fn parse_proto(st: @pstate) -> ast::Proto { match next(st) { - 'n' => ty::proto_bare, - 'v' => ty::proto_vstore(parse_vstore(st)), - c => fail ~"illegal proto type kind " + str::from_char(c) + '_' => ast::ProtoBare, + '@' => ast::ProtoBox, + '~' => ast::ProtoUniq, + '&' => ast::ProtoBorrowed, + _ => fail ~"parse_proto(): bad input" } } @@ -293,13 +295,8 @@ fn parse_ty(st: @pstate, conv: conv_did) -> ty::t { } 'Y' => return ty::mk_type(st.tcx), 'C' => { - let ck = match next(st) { - '&' => ty::ck_block, - '@' => ty::ck_box, - '~' => ty::ck_uniq, - _ => fail ~"parse_ty: bad closure kind" - }; - return ty::mk_opaque_closure_ptr(st.tcx, ck); + let proto = parse_proto(st); + return ty::mk_opaque_closure_ptr(st.tcx, proto); } '#' => { let pos = parse_hex(st); @@ -415,6 +412,7 @@ fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::FnTy { let proto = parse_proto(st); let purity = parse_purity(next(st)); let onceness = parse_onceness(next(st)); + let region = parse_region(st); let bounds = parse_bounds(st, conv); assert (next(st) == '['); let mut inputs: ~[ty::arg] = ~[]; @@ -429,6 +427,7 @@ fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::FnTy { proto: proto, onceness: onceness, bounds: bounds, + region: region, ret_style: ret_style}, sig: FnSig {inputs: inputs, output: ret_ty} diff --git a/src/rustc/metadata/tyencode.rs b/src/rustc/metadata/tyencode.rs index 725b8c41f5cbb..4129066ff2863 100644 --- a/src/rustc/metadata/tyencode.rs +++ b/src/rustc/metadata/tyencode.rs @@ -296,9 +296,10 @@ fn enc_sty(w: io::Writer, cx: @ctxt, st: ty::sty) { w.write_char('s'); } ty::ty_type => w.write_char('Y'), - ty::ty_opaque_closure_ptr(ty::ck_block) => w.write_str(&"C&"), - ty::ty_opaque_closure_ptr(ty::ck_box) => w.write_str(&"C@"), - ty::ty_opaque_closure_ptr(ty::ck_uniq) => w.write_str(&"C~"), + ty::ty_opaque_closure_ptr(p) => { + w.write_str(&"C&"); + enc_proto(w, p); + } ty::ty_opaque_box => w.write_char('B'), ty::ty_class(def, substs) => { debug!("~~~~ %s", ~"a["); @@ -315,14 +316,13 @@ fn enc_sty(w: io::Writer, cx: @ctxt, st: ty::sty) { } } -fn enc_proto(w: io::Writer, cx: @ctxt, proto: ty::fn_proto) { +fn enc_proto(w: io::Writer, proto: Proto) { w.write_str(&"f"); match proto { - ty::proto_bare => w.write_str(&"n"), - ty::proto_vstore(vstore) => { - w.write_str(&"v"); - enc_vstore(w, cx, vstore); - } + ProtoBare => w.write_str(&"_"), + ProtoBox => w.write_str(&"@"), + ProtoUniq => w.write_str(&"~"), + ProtoBorrowed => w.write_str(&"&"), } } @@ -357,9 +357,10 @@ fn enc_onceness(w: io::Writer, o: Onceness) { } fn enc_ty_fn(w: io::Writer, cx: @ctxt, ft: ty::FnTy) { - enc_proto(w, cx, ft.meta.proto); + enc_proto(w, ft.meta.proto); enc_purity(w, ft.meta.purity); enc_onceness(w, ft.meta.onceness); + enc_region(w, cx, ft.meta.region); enc_bounds(w, cx, ft.meta.bounds); w.write_char('['); for ft.sig.inputs.each |arg| { diff --git a/src/rustc/middle/borrowck/check_loans.rs b/src/rustc/middle/borrowck/check_loans.rs index efde19856771b..d63f52a4a5838 100644 --- a/src/rustc/middle/borrowck/check_loans.rs +++ b/src/rustc/middle/borrowck/check_loans.rs @@ -234,7 +234,7 @@ impl check_loan_ctxt { fn is_stack_closure(id: ast::node_id) -> bool { let fn_ty = ty::node_id_to_type(self.tcx(), id); let proto = ty::ty_fn_proto(fn_ty); - return ty::is_blockish(proto); + return proto == ast::ProtoBorrowed; } fn is_allowed_pure_arg(expr: @ast::expr) -> bool { diff --git a/src/rustc/middle/borrowck/gather_loans.rs b/src/rustc/middle/borrowck/gather_loans.rs index 23f0d9edbfae2..9875e8600ea02 100644 --- a/src/rustc/middle/borrowck/gather_loans.rs +++ b/src/rustc/middle/borrowck/gather_loans.rs @@ -241,12 +241,18 @@ impl gather_loan_ctxt { autoref.mutbl, autoref.region) } - ty::AutoSlice => { + ty::AutoBorrowVec => { let cmt_index = mcx.cat_index(expr, cmt); self.guarantee_valid(cmt_index, autoref.mutbl, autoref.region) } + ty::AutoBorrowFn => { + let cmt_deref = mcx.cat_deref_fn(expr, cmt, 0); + self.guarantee_valid(cmt_deref, + autoref.mutbl, + autoref.region) + } } } } diff --git a/src/rustc/middle/capture.rs b/src/rustc/middle/capture.rs index 563ea8f84be76..dae17f66d15fd 100644 --- a/src/rustc/middle/capture.rs +++ b/src/rustc/middle/capture.rs @@ -58,7 +58,7 @@ fn check_capture_clause(tcx: ty::ctxt, fn compute_capture_vars(tcx: ty::ctxt, fn_expr_id: ast::node_id, - fn_proto: ty::fn_proto, + fn_proto: ast::Proto, cap_clause: ast::capture_clause) -> ~[capture_var] { let freevars = freevars::get_freevars(tcx, fn_expr_id); let cap_map = map::HashMap(); @@ -101,7 +101,7 @@ fn compute_capture_vars(tcx: ty::ctxt, // named and add that let implicit_mode; - if ty::is_blockish(fn_proto) { + if fn_proto == ast::ProtoBorrowed { implicit_mode = cap_ref; } else { implicit_mode = cap_copy; diff --git a/src/rustc/middle/check_loop.rs b/src/rustc/middle/check_loop.rs index 3fa7f34fb33e2..de275fdcfc484 100644 --- a/src/rustc/middle/check_loop.rs +++ b/src/rustc/middle/check_loop.rs @@ -24,8 +24,8 @@ fn check_crate(tcx: ty::ctxt, crate: @crate) { v.visit_block(b, {in_loop: false, can_ret: false}, v); } expr_loop_body(@{node: expr_fn_block(_, b, _), _}) => { - let blk = ty::is_blockish(ty::ty_fn_proto(ty::expr_ty(tcx, - e))); + let proto = ty::ty_fn_proto(ty::expr_ty(tcx, e)); + let blk = (proto == ProtoBorrowed); v.visit_block(b, {in_loop: true, can_ret: blk}, v); } expr_break(_) => { diff --git a/src/rustc/middle/freevars.rs b/src/rustc/middle/freevars.rs index 1b42c9bb4b67d..16f4a66ff0b43 100644 --- a/src/rustc/middle/freevars.rs +++ b/src/rustc/middle/freevars.rs @@ -40,7 +40,7 @@ fn collect_freevars(def_map: resolve::DefMap, blk: ast::blk) let walk_expr = fn@(expr: @ast::expr, &&depth: int, v: visit::vt) { match expr.node { ast::expr_fn(proto, _, _, _) => { - if proto != ast::proto_bare { + if proto != ast::ProtoBare { visit::visit_expr(expr, depth + 1, v); } } diff --git a/src/rustc/middle/kind.rs b/src/rustc/middle/kind.rs index 8eace4f5cf114..c0887150f24f2 100644 --- a/src/rustc/middle/kind.rs +++ b/src/rustc/middle/kind.rs @@ -159,12 +159,10 @@ fn with_appropriate_checker(cx: ctx, id: node_id, b: fn(check_fn)) { let fty = ty::node_id_to_type(cx.tcx, id); match ty::ty_fn_proto(fty) { - ty::proto_vstore(ty::vstore_uniq) => b(check_for_uniq), - ty::proto_vstore(ty::vstore_box) => b(check_for_box), - ty::proto_bare => b(check_for_bare), - ty::proto_vstore(ty::vstore_slice(_)) => b(check_for_block), - ty::proto_vstore(ty::vstore_fixed(_)) => - fail ~"fixed vstore not allowed here" + ProtoUniq => b(check_for_uniq), + ProtoBox => b(check_for_box), + ProtoBare => b(check_for_bare), + ProtoBorrowed => b(check_for_block), } } diff --git a/src/rustc/middle/lint.rs b/src/rustc/middle/lint.rs index 9d28e35acb0de..3be1e6d1a6189 100644 --- a/src/rustc/middle/lint.rs +++ b/src/rustc/middle/lint.rs @@ -841,29 +841,15 @@ fn check_fn_deprecated_modes(tcx: ty::ctxt, fn_ty: ty::t, decl: ast::fn_decl, let span = arg_ast.ty.span; // Recurse to check fn-type argument match arg_ast.ty.node { - ast::ty_fn(_, _, _, _, decl) => { + ast::ty_fn(f) => { check_fn_deprecated_modes(tcx, arg_ty.ty, - decl, span, id); + f.decl, span, id); } ast::ty_path(*) => { // This is probably a typedef, so we can't // see the actual fn decl // e.g. fn foo(f: InitOp) } - ast::ty_rptr(_, mt) - | ast::ty_box(mt) - | ast::ty_uniq(mt) => { - // Functions with preceding sigil are parsed - // as pointers of functions - match mt.ty.node { - ast::ty_fn(_, _, _, _, decl) => { - check_fn_deprecated_modes( - tcx, arg_ty.ty, - decl, span, id); - } - _ => fail - } - } _ => { tcx.sess.span_warn(span, ~"what"); error!("arg %d, ty=%s, mode=%s", @@ -889,10 +875,10 @@ fn check_item_deprecated_modes(tcx: ty::ctxt, it: @ast::item) { match it.node { ast::item_ty(ty, _) => { match ty.node { - ast::ty_fn(_, _, _, _, decl) => { + ast::ty_fn(f) => { let fn_ty = ty::node_id_to_type(tcx, it.id); check_fn_deprecated_modes( - tcx, fn_ty, decl, ty.span, it.id) + tcx, fn_ty, f.decl, ty.span, it.id) } _ => () } diff --git a/src/rustc/middle/mem_categorization.rs b/src/rustc/middle/mem_categorization.rs index 55bf41b573eb5..16dc82cbbf352 100644 --- a/src/rustc/middle/mem_categorization.rs +++ b/src/rustc/middle/mem_categorization.rs @@ -305,18 +305,30 @@ fn opt_deref_kind(t: ty::t) -> Option { Some(deref_ptr(uniq_ptr)) } + ty::ty_fn(f) if f.meta.proto == ast::ProtoUniq => { + Some(deref_ptr(uniq_ptr)) + } + ty::ty_rptr(r, _) | ty::ty_evec(_, ty::vstore_slice(r)) | ty::ty_estr(ty::vstore_slice(r)) => { Some(deref_ptr(region_ptr(r))) } + ty::ty_fn(f) if f.meta.proto == ast::ProtoBorrowed => { + Some(deref_ptr(region_ptr(f.meta.region))) + } + ty::ty_box(*) | ty::ty_evec(_, ty::vstore_box) | ty::ty_estr(ty::vstore_box) => { Some(deref_ptr(gc_ptr)) } + ty::ty_fn(f) if f.meta.proto == ast::ProtoBox => { + Some(deref_ptr(gc_ptr)) + } + ty::ty_ptr(*) => { Some(deref_ptr(unsafe_ptr)) } @@ -563,22 +575,23 @@ impl &mem_categorization_ctxt { let ty = ty::node_id_to_type(self.tcx, fn_node_id); let proto = ty::ty_fn_proto(ty); match proto { - ty::proto_vstore(ty::vstore_slice(_)) => { - let upcmt = self.cat_def(id, span, expr_ty, *inner); - @{id:id, span:span, - cat:cat_stack_upvar(upcmt), lp:upcmt.lp, - mutbl:upcmt.mutbl, ty:upcmt.ty} - } - ty::proto_bare | - ty::proto_vstore(ty::vstore_uniq) | - ty::proto_vstore(ty::vstore_box) => { - // FIXME #2152 allow mutation of moved upvars - @{id:id, span:span, - cat:cat_special(sk_heap_upvar), lp:None, - mutbl:m_imm, ty:expr_ty} - } - ty::proto_vstore(ty::vstore_fixed(_)) => - fail ~"fixed vstore not allowed here" + ast::ProtoBorrowed => { + let upcmt = self.cat_def(id, span, expr_ty, *inner); + @{id:id, span:span, + cat:cat_stack_upvar(upcmt), lp:upcmt.lp, + mutbl:upcmt.mutbl, ty:upcmt.ty} + } + ast::ProtoUniq | ast::ProtoBox => { + // FIXME #2152 allow mutation of moved upvars + @{id:id, span:span, + cat:cat_special(sk_heap_upvar), lp:None, + mutbl:m_imm, ty:expr_ty} + } + ast::ProtoBare => { + self.tcx.sess.span_bug( + span, + fmt!("Upvar in a bare closure?")); + } } } @@ -648,16 +661,16 @@ impl &mem_categorization_ctxt { base_cmt: cmt, f_name: ast::ident, field_id: ast::node_id) -> cmt { - let f_mutbl = match field_mutbl(self.tcx, base_cmt.ty, f_name, - field_id) { - Some(f_mutbl) => f_mutbl, - None => { - self.tcx.sess.span_bug( - node.span(), - fmt!("Cannot find field `%s` in type `%s`", - self.tcx.sess.str_of(f_name), - ty_to_str(self.tcx, base_cmt.ty))); - } + let f_mutbl = match field_mutbl(self.tcx, base_cmt.ty, + f_name, field_id) { + Some(f_mutbl) => f_mutbl, + None => { + self.tcx.sess.span_bug( + node.span(), + fmt!("Cannot find field `%s` in type `%s`", + self.tcx.sess.str_of(f_name), + ty_to_str(self.tcx, base_cmt.ty))); + } }; let m = self.inherited_mutability(base_cmt.mutbl, f_mutbl); let f_comp = comp_field(f_name, f_mutbl); @@ -667,9 +680,24 @@ impl &mem_categorization_ctxt { mutbl: m, ty: self.tcx.ty(node)} } + fn cat_deref_fn(node: N, + base_cmt: cmt, + deref_cnt: uint) -> cmt + { + // Bit of a hack: the "dereference" of a function pointer like + // `@fn()` is a mere logical concept. We interpret it as + // dereferencing the environment pointer; of course, we don't + // know what type lies at the other end, so we just call it + // `()`. + + let mt = {ty: ty::mk_tup(self.tcx, ~[]), mutbl: m_imm}; + return self.cat_deref_common(node, base_cmt, deref_cnt, mt); + } + fn cat_deref(node: N, base_cmt: cmt, - deref_cnt: uint) -> cmt { + deref_cnt: uint) -> cmt + { let mt = match ty::deref(self.tcx, base_cmt.ty, true) { Some(mt) => mt, None => { @@ -680,6 +708,14 @@ impl &mem_categorization_ctxt { } }; + return self.cat_deref_common(node, base_cmt, deref_cnt, mt); + } + + fn cat_deref_common(node: N, + base_cmt: cmt, + deref_cnt: uint, + mt: ty::mt) -> cmt + { match deref_kind(self.tcx, base_cmt.ty) { deref_ptr(ptr) => { let lp = do base_cmt.lp.chain_ref |l| { diff --git a/src/rustc/middle/region.rs b/src/rustc/middle/region.rs index a98ec2181d923..0be27483a107e 100644 --- a/src/rustc/middle/region.rs +++ b/src/rustc/middle/region.rs @@ -615,23 +615,35 @@ fn determine_rp_in_ty(ty: @ast::Ty, // region is expected (and hence is a supertype of those // locations) match ty.node { - ast::ty_rptr(r, _) => { - debug!("referenced rptr type %s", - pprust::ty_to_str(ty, cx.sess.intr())); + ast::ty_rptr(r, _) => { + debug!("referenced rptr type %s", + pprust::ty_to_str(ty, cx.sess.intr())); - if cx.region_is_relevant(r) { - cx.add_rp(cx.item_id, cx.add_variance(rv_contravariant)) + if cx.region_is_relevant(r) { + cx.add_rp(cx.item_id, cx.add_variance(rv_contravariant)) + } } - } - ast::ty_fn(ast::proto_bare, _, _, _, _) | - ast::ty_fn(ast::proto_block, _, _, _, _) if cx.anon_implies_rp => { - debug!("referenced bare fn type with regions %s", - pprust::ty_to_str(ty, cx.sess.intr())); - cx.add_rp(cx.item_id, cx.add_variance(rv_contravariant)); - } + ast::ty_fn(f) => { + debug!("referenced fn type: %s", + pprust::ty_to_str(ty, cx.sess.intr())); + match f.region { + Some(r) => { + if cx.region_is_relevant(r) { + cx.add_rp(cx.item_id, + cx.add_variance(rv_contravariant)) + } + } + None => { + if f.proto == ast::ProtoBorrowed && cx.anon_implies_rp { + cx.add_rp(cx.item_id, + cx.add_variance(rv_contravariant)); + } + } + } + } - _ => {} + _ => {} } // if this references another named type, add the dependency @@ -666,25 +678,6 @@ fn determine_rp_in_ty(ty: @ast::Ty, _ => {} } - // temporary hack: right now, fn() is short for &fn(), but @(fn()) - // is `@fn()`, so catch this and set anon_implies_rp to none in - // that case - match ty.node { - ast::ty_box(mt) | ast::ty_uniq(mt) => { - match mt.ty.node { - ast::ty_fn(ast::proto_bare, _, _, _, _) | - ast::ty_fn(ast::proto_block, _, _, _, _) => { - do cx.with(cx.item_id, false) { - visit_mt(mt, cx, visitor); - } - return; - } - _ => {} - } - } - _ => {} - } - match ty.node { ast::ty_box(mt) | ast::ty_uniq(mt) | ast::ty_vec(mt) | ast::ty_rptr(_, mt) | ast::ty_ptr(mt) => { @@ -706,18 +699,18 @@ fn determine_rp_in_ty(ty: @ast::Ty, } } - ast::ty_fn(_, _, _, bounds, decl) => { + ast::ty_fn(f) => { // fn() binds the & region, so do not consider &T types that // appear *inside* a fn() type to affect the enclosing item: do cx.with(cx.item_id, false) { // parameters are contravariant do cx.with_ambient_variance(rv_contravariant) { - for decl.inputs.each |a| { + for f.decl.inputs.each |a| { visitor.visit_ty(a.ty, cx, visitor); } } - visit::visit_ty_param_bounds(bounds, cx, visitor); - visitor.visit_ty(decl.output, cx, visitor); + visit::visit_ty_param_bounds(f.bounds, cx, visitor); + visitor.visit_ty(f.decl.output, cx, visitor); } } diff --git a/src/rustc/middle/trans/closure.rs b/src/rustc/middle/trans/closure.rs index 3997076f98713..d15795e9c09bb 100644 --- a/src/rustc/middle/trans/closure.rs +++ b/src/rustc/middle/trans/closure.rs @@ -144,9 +144,7 @@ fn mk_closure_tys(tcx: ty::ctxt, return cdata_ty; } -fn allocate_cbox(bcx: block, - ck: ty::closure_kind, - cdata_ty: ty::t) +fn allocate_cbox(bcx: block, proto: ast::Proto, cdata_ty: ty::t) -> Result { let _icx = bcx.insn_ctxt("closure::allocate_cbox"); @@ -163,15 +161,23 @@ fn allocate_cbox(bcx: block, } // Allocate and initialize the box: - match ck { - ty::ck_box => malloc_raw(bcx, cdata_ty, heap_shared), - ty::ck_uniq => malloc_raw(bcx, cdata_ty, heap_exchange), - ty::ck_block => { - let cbox_ty = tuplify_box_ty(tcx, cdata_ty); - let llbox = base::alloc_ty(bcx, cbox_ty); - nuke_ref_count(bcx, llbox); - rslt(bcx, llbox) - } + match proto { + ast::ProtoBox => { + malloc_raw(bcx, cdata_ty, heap_shared) + } + ast::ProtoUniq => { + malloc_raw(bcx, cdata_ty, heap_exchange) + } + ast::ProtoBorrowed => { + let cbox_ty = tuplify_box_ty(tcx, cdata_ty); + let llbox = base::alloc_ty(bcx, cbox_ty); + nuke_ref_count(bcx, llbox); + rslt(bcx, llbox) + } + ast::ProtoBare => { + let cdata_llty = type_of(bcx.ccx(), cdata_ty); + rslt(bcx, C_null(cdata_llty)) + } } } @@ -187,7 +193,7 @@ type closure_result = { // Otherwise, it is stack allocated and copies pointers to the upvars. fn store_environment(bcx: block, bound_values: ~[EnvValue], - ck: ty::closure_kind) -> closure_result { + proto: ast::Proto) -> closure_result { let _icx = bcx.insn_ctxt("closure::store_environment"); let ccx = bcx.ccx(), tcx = ccx.tcx; @@ -195,7 +201,7 @@ fn store_environment(bcx: block, let cdata_ty = mk_closure_tys(tcx, bound_values); // allocate closure in the heap - let Result {bcx: bcx, val: llbox} = allocate_cbox(bcx, ck, cdata_ty); + let Result {bcx: bcx, val: llbox} = allocate_cbox(bcx, proto, cdata_ty); let mut temp_cleanups = ~[]; // cbox_ty has the form of a tuple: (a, b, c) we want a ptr to a @@ -243,7 +249,7 @@ fn store_environment(bcx: block, // collects the upvars and packages them up for store_environment. fn build_closure(bcx0: block, cap_vars: ~[capture::capture_var], - ck: ty::closure_kind, + proto: ast::Proto, include_ret_handle: Option) -> closure_result { let _icx = bcx0.insn_ctxt("closure::build_closure"); // If we need to, package up the iterator body to call @@ -257,7 +263,7 @@ fn build_closure(bcx0: block, let datum = expr::trans_local_var(bcx, cap_var.def); match cap_var.mode { capture::cap_ref => { - assert ck == ty::ck_block; + assert proto == ast::ProtoBorrowed; env_vals.push(EnvValue {action: EnvRef, datum: datum}); } @@ -298,7 +304,7 @@ fn build_closure(bcx0: block, datum: ret_datum}); } - return store_environment(bcx, env_vals, ck); + return store_environment(bcx, env_vals, proto); } // Given an enclosing block context, a new function context, a closure type, @@ -308,7 +314,7 @@ fn load_environment(fcx: fn_ctxt, cdata_ty: ty::t, cap_vars: ~[capture::capture_var], load_ret_handle: bool, - ck: ty::closure_kind) { + proto: ast::Proto) { let _icx = fcx.insn_ctxt("closure::load_environment"); let bcx = raw_block(fcx, false, fcx.llloadenv); @@ -322,9 +328,9 @@ fn load_environment(fcx: fn_ctxt, capture::cap_drop => { /* ignore */ } _ => { let mut upvarptr = GEPi(bcx, llcdata, [0u, i]); - match ck { - ty::ck_block => { upvarptr = Load(bcx, upvarptr); } - ty::ck_uniq | ty::ck_box => () + match proto { + ast::ProtoBorrowed => { upvarptr = Load(bcx, upvarptr); } + ast::ProtoBox | ast::ProtoUniq | ast::ProtoBare => {} } let def_id = ast_util::def_id_of_def(cap_var.def); fcx.llupvars.insert(def_id.node, upvarptr); @@ -341,7 +347,7 @@ fn load_environment(fcx: fn_ctxt, } fn trans_expr_fn(bcx: block, - proto: ty::fn_proto, + proto: ast::Proto, decl: ast::fn_decl, body: ast::blk, id: ast::node_id, @@ -365,16 +371,16 @@ fn trans_expr_fn(bcx: block, let s = mangle_internal_name_by_path_and_seq(ccx, sub_path, ~"expr_fn"); let llfn = decl_internal_cdecl_fn(ccx.llmod, s, llfnty); - let trans_closure_env = fn@(ck: ty::closure_kind) -> Result { + let trans_closure_env = fn@(proto: ast::Proto) -> Result { let cap_vars = capture::compute_capture_vars(ccx.tcx, id, proto, cap_clause); let ret_handle = match is_loop_body { Some(x) => x, None => None }; - let {llbox, cdata_ty, bcx} = build_closure(bcx, cap_vars, ck, + let {llbox, cdata_ty, bcx} = build_closure(bcx, cap_vars, proto, ret_handle); trans_closure(ccx, sub_path, decl, body, llfn, no_self, bcx.fcx.param_substs, id, None, |fcx| { load_environment(fcx, cdata_ty, cap_vars, - ret_handle.is_some(), ck); + ret_handle.is_some(), proto); }, |bcx| { if is_loop_body.is_some() { Store(bcx, C_bool(true), bcx.fcx.llretptr); @@ -384,23 +390,14 @@ fn trans_expr_fn(bcx: block, }; let Result {bcx: bcx, val: closure} = match proto { - ty::proto_vstore(ty::vstore_slice(_)) => { - trans_closure_env(ty::ck_block) - } - ty::proto_vstore(ty::vstore_box) => { - trans_closure_env(ty::ck_box) - } - ty::proto_vstore(ty::vstore_uniq) => { - trans_closure_env(ty::ck_uniq) + ast::ProtoBorrowed | ast::ProtoBox | ast::ProtoUniq => { + trans_closure_env(proto) } - ty::proto_bare => { + ast::ProtoBare => { trans_closure(ccx, sub_path, decl, body, llfn, no_self, None, id, None, |_fcx| { }, |_bcx| { }); rslt(bcx, C_null(T_opaque_box_ptr(ccx))) } - ty::proto_vstore(ty::vstore_fixed(_)) => { - fail ~"vstore_fixed unexpected" - } }; fill_fn_pair(bcx, dest_addr, llfn, closure); @@ -412,45 +409,45 @@ fn make_fn_glue( v: ValueRef, t: ty::t, glue_fn: fn@(block, v: ValueRef, t: ty::t) -> block) - -> block { + -> block +{ let _icx = cx.insn_ctxt("closure::make_fn_glue"); let bcx = cx; let tcx = cx.tcx(); - let fn_env = fn@(ck: ty::closure_kind) -> block { - let box_cell_v = GEPi(cx, v, [0u, abi::fn_field_box]); - let box_ptr_v = Load(cx, box_cell_v); - do with_cond(cx, IsNotNull(cx, box_ptr_v)) |bcx| { - let closure_ty = ty::mk_opaque_closure_ptr(tcx, ck); - glue_fn(bcx, box_cell_v, closure_ty) - } - }; - let proto = ty::ty_fn_proto(t); match proto { - ty::proto_bare | ty::proto_vstore(ty::vstore_slice(_)) => bcx, - ty::proto_vstore(ty::vstore_uniq) => fn_env(ty::ck_uniq), - ty::proto_vstore(ty::vstore_box) => fn_env(ty::ck_box), - ty::proto_vstore(ty::vstore_fixed(_)) => { - cx.sess().bug(~"Closure with fixed vstore"); + ast::ProtoBare | ast::ProtoBorrowed => bcx, + ast::ProtoUniq | ast::ProtoBox => { + let box_cell_v = GEPi(cx, v, [0u, abi::fn_field_box]); + let box_ptr_v = Load(cx, box_cell_v); + do with_cond(cx, IsNotNull(cx, box_ptr_v)) |bcx| { + let closure_ty = ty::mk_opaque_closure_ptr(tcx, proto); + glue_fn(bcx, box_cell_v, closure_ty) + } } } } fn make_opaque_cbox_take_glue( bcx: block, - ck: ty::closure_kind, + proto: ast::Proto, cboxptr: ValueRef) // ptr to ptr to the opaque closure - -> block { + -> block +{ // Easy cases: let _icx = bcx.insn_ctxt("closure::make_opaque_cbox_take_glue"); - match ck { - ty::ck_block => return bcx, - ty::ck_box => { + match proto { + ast::ProtoBare | ast::ProtoBorrowed => { + return bcx; + } + ast::ProtoBox => { glue::incr_refcnt_of_boxed(bcx, Load(bcx, cboxptr)); return bcx; } - ty::ck_uniq => { /* hard case: */ } + ast::ProtoUniq => { + /* hard case */ + } } // Hard case, a deep copy: @@ -492,34 +489,38 @@ fn make_opaque_cbox_take_glue( fn make_opaque_cbox_drop_glue( bcx: block, - ck: ty::closure_kind, + proto: ast::Proto, cboxptr: ValueRef) // ptr to the opaque closure -> block { let _icx = bcx.insn_ctxt("closure::make_opaque_cbox_drop_glue"); - match ck { - ty::ck_block => bcx, - ty::ck_box => { + match proto { + ast::ProtoBare | ast::ProtoBorrowed => bcx, + ast::ProtoBox => { glue::decr_refcnt_maybe_free( bcx, Load(bcx, cboxptr), - ty::mk_opaque_closure_ptr(bcx.tcx(), ck)) + ty::mk_opaque_closure_ptr(bcx.tcx(), proto)) } - ty::ck_uniq => { + ast::ProtoUniq => { glue::free_ty( bcx, cboxptr, - ty::mk_opaque_closure_ptr(bcx.tcx(), ck)) + ty::mk_opaque_closure_ptr(bcx.tcx(), proto)) } } } fn make_opaque_cbox_free_glue( bcx: block, - ck: ty::closure_kind, + proto: ast::Proto, cbox: ValueRef) // ptr to ptr to the opaque closure -> block { let _icx = bcx.insn_ctxt("closure::make_opaque_cbox_free_glue"); - match ck { - ty::ck_block => return bcx, - ty::ck_box | ty::ck_uniq => { /* hard cases: */ } + match proto { + ast::ProtoBare | ast::ProtoBorrowed => { + return bcx; + } + ast::ProtoBox | ast::ProtoUniq => { + /* hard cases */ + } } let ccx = bcx.ccx(); @@ -537,10 +538,12 @@ fn make_opaque_cbox_free_glue( abi::tydesc_field_drop_glue, None); // Free the ty descr (if necc) and the box itself - match ck { - ty::ck_block => fail ~"Impossible", - ty::ck_box => glue::trans_free(bcx, cbox), - ty::ck_uniq => glue::trans_unique_free(bcx, cbox) + match proto { + ast::ProtoBox => glue::trans_free(bcx, cbox), + ast::ProtoUniq => glue::trans_unique_free(bcx, cbox), + ast::ProtoBare | ast::ProtoBorrowed => { + bcx.sess().bug(~"impossible") + } } } } diff --git a/src/rustc/middle/trans/expr.rs b/src/rustc/middle/trans/expr.rs index 1bd44ee4bda63..06d56f4542fd9 100644 --- a/src/rustc/middle/trans/expr.rs +++ b/src/rustc/middle/trans/expr.rs @@ -109,7 +109,7 @@ use base::*; use syntax::print::pprust::{expr_to_str}; use util::ppaux::ty_to_str; use util::common::indenter; -use ty::{AutoPtr, AutoSlice}; +use ty::{AutoPtr, AutoBorrowVec, AutoBorrowFn}; use callee::{AutorefArg, DoAutorefArg, DontAutorefArg}; // The primary two functions for translating expressions: @@ -188,9 +188,15 @@ fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock { AutoPtr => { unpack_datum!(bcx, auto_ref(bcx, datum)) } - AutoSlice => { + AutoBorrowVec => { unpack_datum!(bcx, auto_slice(bcx, datum)) } + AutoBorrowFn => { + // currently, all closure types are + // represented precisely the same, so no + // runtime adjustment is required: + datum + } } } }; @@ -520,20 +526,7 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr, ast::expr_fn(proto, decl, body, cap_clause) => { // Don't use this function for anything real. Use the one in // astconv instead. - fn ast_proto_to_proto_simple(ast_proto: ast::proto) - -> ty::fn_proto { - match ast_proto { - ast::proto_bare => ty::proto_bare, - ast::proto_uniq => ty::proto_vstore(ty::vstore_uniq), - ast::proto_box => ty::proto_vstore(ty::vstore_box), - ast::proto_block => { - ty::proto_vstore(ty::vstore_slice(ty::re_static)) - } - } - } - - return closure::trans_expr_fn(bcx, - ast_proto_to_proto_simple(proto), + return closure::trans_expr_fn(bcx, proto, decl, body, expr.id, cap_clause, None, dest); } diff --git a/src/rustc/middle/trans/foreign.rs b/src/rustc/middle/trans/foreign.rs index 933fb7eedfba1..b4aeface943bd 100644 --- a/src/rustc/middle/trans/foreign.rs +++ b/src/rustc/middle/trans/foreign.rs @@ -997,10 +997,9 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item, ty::mk_mach_uint(bcx.tcx(), ast::ty_u8)); let fty = ty::mk_fn(bcx.tcx(), FnTyBase { meta: FnMeta {purity: ast::impure_fn, - proto: - ty::proto_vstore(ty::vstore_slice( - ty::re_bound(ty::br_anon(0)))), + proto: ast::ProtoBorrowed, onceness: ast::Many, + region: ty::re_bound(ty::br_anon(0)), bounds: @~[], ret_style: ast::return_val}, sig: FnSig {inputs: ~[{mode: ast::expl(ast::by_val), diff --git a/src/rustc/middle/trans/monomorphize.rs b/src/rustc/middle/trans/monomorphize.rs index 0c93c610b681d..2e18fb2a2e9e2 100644 --- a/src/rustc/middle/trans/monomorphize.rs +++ b/src/rustc/middle/trans/monomorphize.rs @@ -251,18 +251,19 @@ fn normalize_for_monomorphization(tcx: ty::ctxt, ty: ty::t) -> Option { FnTyBase {meta: FnMeta {purity: ast::impure_fn, proto: fty.meta.proto, onceness: ast::Many, + region: ty::re_static, bounds: @~[], ret_style: ast::return_val}, sig: FnSig {inputs: ~[], output: ty::mk_nil(tcx)}})) } ty::ty_trait(_, _, _) => { - let box_proto = ty::proto_vstore(ty::vstore_box); Some(ty::mk_fn( tcx, FnTyBase {meta: FnMeta {purity: ast::impure_fn, - proto: box_proto, + proto: ast::ProtoBox, onceness: ast::Many, + region: ty::re_static, bounds: @~[], ret_style: ast::return_val}, sig: FnSig {inputs: ~[], diff --git a/src/rustc/middle/trans/reflect.rs b/src/rustc/middle/trans/reflect.rs index c52b653d536c1..5724c5ada22f3 100644 --- a/src/rustc/middle/trans/reflect.rs +++ b/src/rustc/middle/trans/reflect.rs @@ -186,14 +186,7 @@ impl reflector { ast::impure_fn => 2u, ast::extern_fn => 3u }; - let protoval = match fty.meta.proto { - ty::proto_bare => 0u, - ty::proto_vstore(ty::vstore_uniq) => 2u, - ty::proto_vstore(ty::vstore_box) => 3u, - ty::proto_vstore(ty::vstore_slice(_)) => 4u, - ty::proto_vstore(ty::vstore_fixed(_)) => - fail ~"fixed unexpected" - }; + let protoval = ast_proto_constant(fty.meta.proto); let retval = match fty.meta.ret_style { ast::noreturn => 0u, ast::return_val => 1u @@ -278,11 +271,7 @@ impl reflector { ty::ty_type => self.leaf(~"type"), ty::ty_opaque_box => self.leaf(~"opaque_box"), ty::ty_opaque_closure_ptr(ck) => { - let ckval = match ck { - ty::ck_block => 0u, - ty::ck_box => 1u, - ty::ck_uniq => 2u - }; + let ckval = ast_proto_constant(ck); self.visit(~"closure_ptr", ~[self.c_uint(ckval)]) } } @@ -309,3 +298,12 @@ fn emit_calls_to_trait_visit_ty(bcx: block, t: ty::t, Br(r.bcx, final.llbb); return final; } + +fn ast_proto_constant(proto: ast::Proto) -> uint { + match proto { + ast::ProtoBare => 0u, + ast::ProtoUniq => 2u, + ast::ProtoBox => 3u, + ast::ProtoBorrowed => 4u, + } +} \ No newline at end of file diff --git a/src/rustc/middle/trans/type_use.rs b/src/rustc/middle/trans/type_use.rs index b8a7580e03cc9..53889369361fd 100644 --- a/src/rustc/middle/trans/type_use.rs +++ b/src/rustc/middle/trans/type_use.rs @@ -213,16 +213,13 @@ fn mark_for_expr(cx: ctx, e: @expr) { } expr_fn(*) | expr_fn_block(*) => { match ty::ty_fn_proto(ty::expr_ty(cx.ccx.tcx, e)) { - ty::proto_bare | ty::proto_vstore(ty::vstore_uniq) => {} - ty::proto_vstore(ty::vstore_box) | - ty::proto_vstore(ty::vstore_slice(_)) => { + ast::ProtoBare | ast::ProtoUniq => {} + ast::ProtoBox | ast::ProtoBorrowed => { for vec::each(*freevars::get_freevars(cx.ccx.tcx, e.id)) |fv| { let node_id = ast_util::def_id_of_def(fv.def).node; node_type_needs(cx, use_repr, node_id); } } - ty::proto_vstore(ty::vstore_fixed(_)) => - fail ~"vstore_fixed not allowed here" } } expr_assign(val, _) | expr_swap(val, _) | expr_assign_op(_, val, _) | diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index 69b4d985f6f6a..14c5ed5e71e01 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -157,10 +157,6 @@ export set_default_mode; export variant_info; export walk_ty, maybe_walk_ty; export occurs_check; -export closure_kind; -export ck_block; -export ck_box; -export ck_uniq; export param_ty; export param_bound, param_bounds, bound_copy, bound_owned; export param_bounds_to_str, param_bound_to_str; @@ -190,9 +186,7 @@ export purity_to_str; export onceness_to_str; export param_tys_in_type; export eval_repeat_count; -export fn_proto, proto_bare, proto_vstore; export ast_proto_to_proto; -export is_blockish; export method_call_bounds; export hash_region; export region_variance, rv_covariant, rv_invariant, rv_contravariant; @@ -200,10 +194,11 @@ export opt_region_variance; export determine_inherited_purity; export provided_trait_methods; export trait_supertraits; -export AutoAdjustment; -export AutoRef, AutoRefKind, AutoSlice, AutoPtr; export DerivedMethodInfo; export DerivedFieldInfo; +export AutoAdjustment; +export AutoRef; +export AutoRefKind, AutoPtr, AutoBorrowVec, AutoBorrowFn; // Data types @@ -304,14 +299,14 @@ impl region_variance : cmp::Eq { #[auto_serialize] #[auto_deserialize] -type AutoAdjustment = { +pub type AutoAdjustment = { autoderefs: uint, autoref: Option }; #[auto_serialize] #[auto_deserialize] -type AutoRef = { +pub type AutoRef = { kind: AutoRefKind, region: Region, mutbl: ast::mutability @@ -320,11 +315,14 @@ type AutoRef = { #[auto_serialize] #[auto_deserialize] enum AutoRefKind { + /// Convert from T to &T + AutoPtr, + /// Convert from @[]/~[] to &[] (or str) - AutoSlice, + AutoBorrowVec, - /// Convert from T to &T - AutoPtr + /// Convert from @fn()/~fn() to &fn() + AutoBorrowFn, } struct ProvidedMethodSource { @@ -450,62 +448,6 @@ pure fn type_has_regions(t: t) -> bool { tbox_has_flag(get(t), has_regions) } pure fn type_def_id(t: t) -> Option { get(t).o_def_id } pure fn type_id(t: t) -> uint { get(t).id } -enum closure_kind { - ck_block, - ck_box, - ck_uniq, -} - -impl closure_kind : to_bytes::IterBytes { - pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) { - (self as u8).iter_bytes(lsb0, f) - } -} - -impl closure_kind : cmp::Eq { - pure fn eq(other: &closure_kind) -> bool { - (self as uint) == ((*other) as uint) - } - pure fn ne(other: &closure_kind) -> bool { !self.eq(other) } -} - -enum fn_proto { - proto_bare, // supertype of all other protocols - proto_vstore(vstore) -} - -impl fn_proto : to_bytes::IterBytes { - pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) { - match self { - proto_bare => - 0u8.iter_bytes(lsb0, f), - - proto_vstore(ref v) => - to_bytes::iter_bytes_2(&1u8, v, lsb0, f) - } - } -} - -impl fn_proto : cmp::Eq { - pure fn eq(other: &fn_proto) -> bool { - match self { - proto_bare => { - match (*other) { - proto_bare => true, - _ => false - } - } - proto_vstore(e0a) => { - match (*other) { - proto_vstore(e0b) => e0a == e0b, - _ => false - } - } - } - } - pure fn ne(other: &fn_proto) -> bool { !self.eq(other) } -} - /** * Meta information about a closure. * @@ -513,12 +455,14 @@ impl fn_proto : cmp::Eq { * - `proto` is the protocol (fn@, fn~, etc). * - `onceness` indicates whether the function can be called one time or many * times. + * - `region` is the region bound on the function's upvars (often &static). * - `bounds` is the parameter bounds on the function's upvars. * - `ret_style` indicates whether the function returns a value or fails. */ struct FnMeta { purity: ast::purity, - proto: fn_proto, + proto: ast::Proto, onceness: ast::Onceness, + region: Region, bounds: @~[param_bound], ret_style: ret_style } @@ -671,7 +615,7 @@ enum sty { // "Fake" types, used for trans purposes ty_type, // type_desc* ty_opaque_box, // used by monomorphizer to represent any @ box - ty_opaque_closure_ptr(closure_kind), // ptr to env for fn, fn@, fn~ + ty_opaque_closure_ptr(ast::Proto), // ptr to env for fn, fn@, fn~ ty_unboxed_vec(mt), } @@ -691,7 +635,7 @@ enum type_err { terr_purity_mismatch(expected_found), terr_onceness_mismatch(expected_found), terr_mutability, - terr_proto_mismatch(expected_found), + terr_proto_mismatch(expected_found), terr_box_mutability, terr_ptr_mutability, terr_ref_mutability, @@ -1036,10 +980,7 @@ fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option) -> t { ty_rec(flds) => for flds.each |f| { flags |= get(f.mt.ty).flags; }, ty_tup(ts) => for ts.each |tt| { flags |= get(*tt).flags; }, ty_fn(ref f) => { - match f.meta.proto { - ty::proto_vstore(vstore_slice(r)) => flags |= rflags(r), - ty::proto_bare | ty::proto_vstore(_) => {} - } + flags |= rflags(f.meta.region); for f.sig.inputs.each |a| { flags |= get(a.ty).flags; } flags |= get(f.sig.output).flags; } @@ -1172,8 +1113,8 @@ fn mk_param(cx: ctxt, n: uint, k: def_id) -> t { fn mk_type(cx: ctxt) -> t { mk_t(cx, ty_type) } -fn mk_opaque_closure_ptr(cx: ctxt, ck: closure_kind) -> t { - mk_t(cx, ty_opaque_closure_ptr(ck)) +fn mk_opaque_closure_ptr(cx: ctxt, proto: ast::Proto) -> t { + mk_t(cx, ty_opaque_closure_ptr(proto)) } fn mk_opaque_box(cx: ctxt) -> t { mk_t(cx, ty_opaque_box) } @@ -1197,8 +1138,10 @@ fn default_arg_mode_for_ty(tcx: ctxt, ty: ty::t) -> ast::rmode { // memory leak that otherwise results when @fn is upcast to &fn. if type_is_fn(ty) { match ty_fn_proto(ty) { - proto_vstore(vstore_slice(_)) => return ast::by_ref, - _ => () + ast::ProtoBorrowed => { + return ast::by_ref; + } + _ => {} } } return if tcx.legacy_modes { @@ -1409,25 +1352,18 @@ fn fold_regions_and_ty( ty::mk_trait(cx, def_id, fold_substs(substs, fldr, fldt), vst) } ty_fn(ref f) => { - let new_proto; - match f.meta.proto { - proto_bare => - new_proto = proto_bare, - proto_vstore(vstore_slice(r)) => - new_proto = proto_vstore(vstore_slice(fldr(r))), - proto_vstore(old_vstore) => - new_proto = proto_vstore(old_vstore) - } - let new_args = vec::map(f.sig.inputs, |a| { - let new_ty = fldfnt(a.ty); - {mode: a.mode, ty: new_ty} - }); - let new_output = fldfnt(f.sig.output); - ty::mk_fn(cx, FnTyBase { - meta: FnMeta {proto: new_proto, ..f.meta}, - sig: FnSig {inputs: new_args, - output: new_output} - }) + let new_region = fldr(f.meta.region); + let new_args = vec::map(f.sig.inputs, |a| { + let new_ty = fldfnt(a.ty); + {mode: a.mode, ty: new_ty} + }); + let new_output = fldfnt(f.sig.output); + ty::mk_fn(cx, FnTyBase { + meta: FnMeta {region: new_region, + ..f.meta}, + sig: FnSig {inputs: new_args, + output: new_output} + }) } ref sty => { fold_sty_to_ty(cx, sty, |t| fldt(t)) @@ -1789,8 +1725,8 @@ fn type_needs_drop(cx: ctxt, ty: t) -> bool { } ty_fn(ref fty) => { match fty.meta.proto { - proto_bare | proto_vstore(vstore_slice(_)) => false, - _ => true + ast::ProtoBare | ast::ProtoBorrowed => false, + ast::ProtoBox | ast::ProtoUniq => true, } } }; @@ -2016,16 +1952,18 @@ pure fn kind_is_owned(k: Kind) -> bool { fn meta_kind(p: FnMeta) -> Kind { match p.proto { // XXX consider the kind bounds! - proto_vstore(vstore_slice(_)) => - kind_noncopyable() | kind_(KIND_MASK_DEFAULT_MODE), - proto_vstore(vstore_box) => - kind_safe_for_default_mode() | kind_owned(), - proto_vstore(vstore_uniq) => - kind_send_copy() | kind_owned(), - proto_vstore(vstore_fixed(_)) => - fail ~"fixed vstore protos are not allowed", - proto_bare => - kind_safe_for_default_mode_send() | kind_const() | kind_owned() + ast::ProtoBare => { + kind_safe_for_default_mode_send() | kind_const() | kind_owned() + } + ast::ProtoBorrowed => { + kind_noncopyable() | kind_(KIND_MASK_DEFAULT_MODE) + } + ast::ProtoBox => { + kind_safe_for_default_mode() | kind_owned() + } + ast::ProtoUniq => { + kind_send_copy() | kind_owned() + } } } @@ -2721,8 +2659,27 @@ impl field : to_bytes::IterBytes { impl arg : to_bytes::IterBytes { pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) { - to_bytes::iter_bytes_2(&self.mode, - &self.ty, lsb0, f) + to_bytes::iter_bytes_2(&self.mode, + &self.ty, lsb0, f) + } +} + +impl FnMeta : to_bytes::IterBytes { + pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) { + to_bytes::iter_bytes_5(&self.purity, + &self.proto, + &self.region, + &self.bounds, + &self.ret_style, + lsb0, f); + } +} + +impl FnSig : to_bytes::IterBytes { + pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) { + to_bytes::iter_bytes_2(&self.inputs, + &self.output, + lsb0, f); } } @@ -2763,13 +2720,9 @@ impl sty : to_bytes::IterBytes { to_bytes::iter_bytes_2(&11u8, fs, lsb0, f), ty_fn(ref ft) => - to_bytes::iter_bytes_7(&12u8, - &ft.meta.purity, - &ft.meta.proto, - &ft.meta.bounds, - &ft.sig.inputs, - &ft.sig.output, - &ft.meta.ret_style, + to_bytes::iter_bytes_3(&12u8, + &ft.meta, + &ft.sig, lsb0, f), ty_self => 13u8.iter_bytes(lsb0, f), @@ -2840,7 +2793,7 @@ fn ty_fn_args(fty: t) -> ~[arg] { } } -fn ty_fn_proto(fty: t) -> fn_proto { +fn ty_fn_proto(fty: t) -> Proto { match get(fty).sty { ty_fn(ref f) => f.meta.proto, _ => fail ~"ty_fn_proto() called on non-fn type" @@ -4091,12 +4044,11 @@ fn normalize_ty(cx: ctxt, t: t) -> t { mk_rptr(cx, re_static, normalize_mt(cx, mt)), ty_fn(ref fn_ty) => { - let proto = match fn_ty.meta.proto { - proto_bare => proto_bare, - proto_vstore(vstore) => proto_vstore(normalize_vstore(vstore)) - }; mk_fn(cx, FnTyBase { - meta: FnMeta {proto: proto, ..fn_ty.meta}, + meta: FnMeta { + region: ty::re_static, + ..fn_ty.meta + }, sig: fn_ty.sig }) } @@ -4160,27 +4112,17 @@ fn eval_repeat_count(tcx: ctxt, count_expr: @ast::expr, span: span) -> uint { } } -pure fn is_blockish(proto: fn_proto) -> bool { - match proto { - proto_vstore(vstore_slice(_)) => - true, - proto_vstore(vstore_box) | proto_vstore(vstore_uniq) | proto_bare => - false, - proto_vstore(vstore_fixed(_)) => - fail ~"fixed vstore not allowed here" - } -} - // Determine what purity to check a nested function under pure fn determine_inherited_purity(parent_purity: ast::purity, child_purity: ast::purity, - child_proto: ty::fn_proto) -> ast::purity { + child_proto: ast::Proto) -> ast::purity { // If the closure is a stack closure and hasn't had some non-standard // purity inferred for it, then check it under its parent's purity. // Otherwise, use its own - if ty::is_blockish(child_proto) && child_purity == ast::impure_fn { - parent_purity - } else { child_purity } + match child_proto { + ast::ProtoBorrowed if child_purity == ast::impure_fn => parent_purity, + _ => child_purity + } } impl mt : cmp::Eq { diff --git a/src/rustc/middle/typeck/astconv.rs b/src/rustc/middle/typeck/astconv.rs index b18b032e0a616..f80b655a860b7 100644 --- a/src/rustc/middle/typeck/astconv.rs +++ b/src/rustc/middle/typeck/astconv.rs @@ -166,76 +166,57 @@ fn ast_ty_to_ty( // Handle @, ~, and & being able to mean estrs and evecs. // If a_seq_ty is a str or a vec, make it an estr/evec. // Also handle function sigils and first-class trait types. - fn mk_maybe_vstore( - self: AC, rscope: RS, a_seq_ty: ast::mt, vst: ty::vstore, - span: span, constr: fn(ty::mt) -> ty::t) -> ty::t { - + fn mk_pointer( + self: AC, + rscope: RS, + a_seq_ty: ast::mt, + vst: ty::vstore, + constr: fn(ty::mt) -> ty::t) -> ty::t + { let tcx = self.tcx(); match a_seq_ty.ty.node { - // to convert to an e{vec,str}, there can't be a mutability argument - _ if a_seq_ty.mutbl != ast::m_imm => (), - ast::ty_vec(mt) => { - return ty::mk_evec(tcx, ast_mt_to_mt(self, rscope, mt), vst); - } - ast::ty_path(path, id) => { - match tcx.def_map.find(id) { - Some(ast::def_prim_ty(ast::ty_str)) => { - check_path_args(tcx, path, NO_TPS | NO_REGIONS); - return ty::mk_estr(tcx, vst); - } - Some(ast::def_ty(type_def_id)) => { - let result = ast_path_to_substs_and_ty(self, rscope, - type_def_id, path); - match ty::get(result.ty).sty { - ty::ty_trait(trait_def_id, substs, _) => { - match vst { - ty::vstore_box | ty::vstore_slice(*) | - ty::vstore_uniq => {} - _ => { - tcx.sess.span_err(path.span, - ~"@trait, ~trait or &trait \ - are the only supported \ - forms of casting-to-\ - trait"); + // to convert to an e{vec,str}, there can't be a + // mutability argument + _ if a_seq_ty.mutbl != ast::m_imm => (), + ast::ty_vec(mt) => { + return ty::mk_evec(tcx, ast_mt_to_mt(self, rscope, mt), vst); + } + ast::ty_path(path, id) => { + match tcx.def_map.find(id) { + Some(ast::def_prim_ty(ast::ty_str)) => { + check_path_args(tcx, path, NO_TPS | NO_REGIONS); + return ty::mk_estr(tcx, vst); + } + Some(ast::def_ty(type_def_id)) => { + let result = ast_path_to_substs_and_ty( + self, rscope, + type_def_id, path); + match ty::get(result.ty).sty { + ty::ty_trait(trait_def_id, substs, _) => { + match vst { + ty::vstore_box | ty::vstore_slice(*) | + ty::vstore_uniq => {} + _ => { + tcx.sess.span_err( + path.span, + ~"@trait, ~trait or &trait \ + are the only supported \ + forms of casting-to-\ + trait"); + } + } + return ty::mk_trait(tcx, trait_def_id, + substs, vst); + } + _ => {} } - return ty::mk_trait(tcx, trait_def_id, substs, vst); } _ => {} } - } - _ => () } - } - ast::ty_fn(ast::proto_block, purity, onceness, ast_bounds, - ast_fn_decl) => { - let new_proto; - match vst { - ty::vstore_fixed(_) => { - tcx.sess.span_err(span, ~"fixed-length functions are not \ - allowed"); - new_proto = ast::proto_block; - } - ty::vstore_uniq => new_proto = ast::proto_uniq, - ty::vstore_box => new_proto = ast::proto_box, - ty::vstore_slice(_) => new_proto = ast::proto_block - } - - // Run through the normal function type conversion process. - let bounds = collect::compute_bounds(self.ccx(), ast_bounds); - let fn_decl = ty_of_fn_decl(self, - rscope, - new_proto, - purity, - onceness, - bounds, - ast_fn_decl, - None, - span); - return ty::mk_fn(tcx, fn_decl); - } - _ => () + _ => {} } let seq_ty = ast_mt_to_mt(self, rscope, a_seq_ty); @@ -279,12 +260,12 @@ fn ast_ty_to_ty( ast::ty_nil => ty::mk_nil(tcx), ast::ty_bot => ty::mk_bot(tcx), ast::ty_box(mt) => { - mk_maybe_vstore(self, rscope, mt, ty::vstore_box, ast_ty.span, - |tmt| ty::mk_box(tcx, tmt)) + mk_pointer(self, rscope, mt, ty::vstore_box, + |tmt| ty::mk_box(tcx, tmt)) } ast::ty_uniq(mt) => { - mk_maybe_vstore(self, rscope, mt, ty::vstore_uniq, ast_ty.span, - |tmt| ty::mk_uniq(tcx, tmt)) + mk_pointer(self, rscope, mt, ty::vstore_uniq, + |tmt| ty::mk_uniq(tcx, tmt)) } ast::ty_vec(mt) => { tcx.sess.span_err(ast_ty.span, @@ -298,12 +279,8 @@ fn ast_ty_to_ty( } ast::ty_rptr(region, mt) => { let r = ast_region_to_region(self, rscope, ast_ty.span, region); - mk_maybe_vstore(self, - in_anon_rscope(rscope, r), - mt, - ty::vstore_slice(r), - ast_ty.span, - |tmt| ty::mk_rptr(tcx, r, tmt)) + mk_pointer(self, in_anon_rscope(rscope, r), mt, ty::vstore_slice(r), + |tmt| ty::mk_rptr(tcx, r, tmt)) } ast::ty_tup(fields) => { let flds = vec::map(fields, |t| ast_ty_to_ty(self, rscope, *t)); @@ -316,10 +293,11 @@ fn ast_ty_to_ty( }; ty::mk_rec(tcx, flds) } - ast::ty_fn(proto, purity, onceness, ast_bounds, decl) => { - let bounds = collect::compute_bounds(self.ccx(), ast_bounds); - let fn_decl = ty_of_fn_decl(self, rscope, proto, purity, - onceness, bounds, decl, None, + ast::ty_fn(f) => { + let bounds = collect::compute_bounds(self.ccx(), f.bounds); + let fn_decl = ty_of_fn_decl(self, rscope, f.proto, + f.purity, f.onceness, + bounds, f.region, f.decl, None, ast_ty.span); ty::mk_fn(tcx, fn_decl) } @@ -377,22 +355,9 @@ fn ast_ty_to_ty( } } } - ast::ty_fixed_length(a_t, Some(u)) => { - mk_maybe_vstore(self, rscope, {ty: a_t, mutbl: ast::m_imm}, - ty::vstore_fixed(u), - ast_ty.span, - |ty| { - tcx.sess.span_err( - a_t.span, - fmt!("bound not allowed on a %s", - ty::ty_sort_str(tcx, ty.ty))); - ty.ty - }) - } - ast::ty_fixed_length(_, None) => { - tcx.sess.span_bug( - ast_ty.span, - ~"implied fixed length for bound"); + ast::ty_fixed_length_vec(a_mt, u) => { + ty::mk_evec(tcx, ast_mt_to_mt(self, rscope, a_mt), + ty::vstore_fixed(u)) } ast::ty_infer => { // ty_infer should only appear as the type of arguments or return @@ -459,38 +424,44 @@ fn ty_of_arg( {mode: mode, ty: ty} } -fn ast_proto_to_proto( - self: AC, rscope: RS, span: span, ast_proto: ast::proto) -> ty::fn_proto { - match ast_proto { - ast::proto_bare => - ty::proto_bare, - ast::proto_uniq => - ty::proto_vstore(ty::vstore_uniq), - ast::proto_box => - ty::proto_vstore(ty::vstore_box), - ast::proto_block => { - let result = rscope.anon_region(span); - let region = get_region_reporting_err(self.tcx(), span, result); - ty::proto_vstore(ty::vstore_slice(region)) - } - } -} - type expected_tys = Option<{inputs: ~[ty::arg], output: ty::t}>; fn ty_of_fn_decl( self: AC, rscope: RS, - ast_proto: ast::proto, + ast_proto: ast::Proto, purity: ast::purity, onceness: ast::Onceness, bounds: @~[ty::param_bound], + opt_region: Option<@ast::region>, decl: ast::fn_decl, expected_tys: expected_tys, - span: span) -> ty::FnTy { - + span: span) -> ty::FnTy +{ debug!("ty_of_fn_decl"); do indent { + // resolve the function bound region in the original region + // scope `rscope`, not the scope of the function parameters + let bound_region = match opt_region { + Some(region) => { + ast_region_to_region(self, rscope, span, region) + } + None => { + match ast_proto { + ast::ProtoBare | ast::ProtoUniq | ast::ProtoBox => { + // @fn(), ~fn() default to static as the bound + // on their upvars: + ty::re_static + } + ast::ProtoBorrowed => { + // &fn() defaults to an anonymous region: + let r_result = rscope.anon_region(span); + get_region_reporting_err(self.tcx(), span, r_result) + } + } + } + }; + // new region names that appear inside of the fn decl are bound to // that function type let rb = in_binding_rscope(rscope); @@ -511,12 +482,11 @@ fn ty_of_fn_decl( _ => ast_ty_to_ty(self, rb, decl.output) }; - let proto = ast_proto_to_proto(self, rscope, span, ast_proto); - FnTyBase { meta: FnMeta {purity: purity, - proto: proto, + proto: ast_proto, onceness: onceness, + region: bound_region, bounds: bounds, ret_style: decl.cf}, sig: FnSig {inputs: input_tys, @@ -524,5 +494,3 @@ fn ty_of_fn_decl( } } } - - diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index 09225b4fef8a9..3de9955455411 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -1294,7 +1294,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, fn check_expr_fn(fcx: @fn_ctxt, expr: @ast::expr, - ast_proto_opt: Option, + ast_proto_opt: Option, decl: ast::fn_decl, body: ast::blk, is_loop_body: bool, @@ -1313,56 +1313,39 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, let (expected_tys, expected_purity, expected_proto, - expected_onceness) = + expected_onceness) = { match expected_sty { - Some(ty::ty_fn(ref fn_ty)) => { - let {fn_ty, _} = - replace_bound_regions_in_fn_ty( - tcx, @Nil, None, fn_ty, - |br| ty::re_bound(ty::br_cap_avoid(expr.id, @br))); - (Some({inputs: fn_ty.sig.inputs, - output: fn_ty.sig.output}), - fn_ty.meta.purity, - fn_ty.meta.proto, - fn_ty.meta.onceness) - } - _ => { - (None, - ast::impure_fn, - ty::proto_vstore(ty::vstore_box), - ast::Many) - } - }; - + Some(ty::ty_fn(ref fn_ty)) => { + let id = expr.id; + let {fn_ty, _} = + replace_bound_regions_in_fn_ty( + tcx, @Nil, None, fn_ty, + |br| ty::re_bound(ty::br_cap_avoid(id, @br))); + (Some({inputs: fn_ty.sig.inputs, + output: fn_ty.sig.output}), + fn_ty.meta.purity, + fn_ty.meta.proto, + fn_ty.meta.onceness) + } + _ => { + (None, ast::impure_fn, ast::ProtoBox, ast::Many) + } + } + }; - // Generate AST prototypes and purity. - // If this is a block lambda (ast_proto == none), these values - // are bogus. We'll fill in the type with the real one later. - // XXX: This is a hack. - let ast_proto = ast_proto_opt.get_default(ast::proto_box); - let ast_purity = ast::impure_fn; - let ast_onceness = ast::Many; + // If the proto is specified, use that, otherwise select a + // proto based on inference. + let (proto, purity) = match ast_proto_opt { + Some(p) => (p, ast::impure_fn), + None => (expected_proto, expected_purity) + }; // construct the function type - let mut fn_ty = astconv::ty_of_fn_decl(fcx, - fcx, - ast_proto, - ast_purity, - ast_onceness, - @~[], - decl, - expected_tys, - expr.span); - - // Patch up the function declaration, if necessary. - match ast_proto_opt { - None => { - fn_ty.meta.purity = expected_purity; - fn_ty.meta.proto = expected_proto; - fn_ty.meta.onceness = expected_onceness; - } - Some(_) => { } - } + let mut fn_ty = astconv::ty_of_fn_decl( + fcx, fcx, + proto, purity, expected_onceness, + /*bounds:*/ @~[], /*opt_region:*/ None, + decl, expected_tys, expr.span); let fty = ty::mk_fn(tcx, fn_ty); @@ -2815,9 +2798,9 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) { ~"frame_address" => { let fty = ty::mk_fn(ccx.tcx, FnTyBase { meta: FnMeta {purity: ast::impure_fn, - proto: ty::proto_vstore(ty::vstore_slice( - ty::re_bound(ty::br_anon(0)))), - onceness: ast::Many, + proto: ast::ProtoBorrowed, + onceness: ast::Once, + region: ty::re_bound(ty::br_anon(0)), bounds: @~[], ret_style: ast::return_val}, sig: FnSig {inputs: ~[{mode: ast::expl(ast::by_val), @@ -2840,8 +2823,9 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) { }; let fty = ty::mk_fn(tcx, FnTyBase { meta: FnMeta {purity: ast::impure_fn, - proto: ty::proto_bare, + proto: ast::ProtoBare, onceness: ast::Many, + region: ty::re_static, bounds: @~[], ret_style: ast::return_val}, sig: FnSig {inputs: inputs, diff --git a/src/rustc/middle/typeck/check/method.rs b/src/rustc/middle/typeck/check/method.rs index f1185181f554a..dd3f4069a9c35 100644 --- a/src/rustc/middle/typeck/check/method.rs +++ b/src/rustc/middle/typeck/check/method.rs @@ -625,7 +625,7 @@ impl LookupContext { ty_evec(mt, vstore_uniq) | ty_evec(mt, vstore_fixed(_)) => { self.search_for_some_kind_of_autorefd_method( - AutoSlice, autoderefs, [m_const, m_imm, m_mutbl], + AutoBorrowVec, autoderefs, [m_const, m_imm, m_mutbl], |m,r| ty::mk_evec(tcx, {ty:mt.ty, mutbl:m}, vstore_slice(r))) @@ -635,7 +635,7 @@ impl LookupContext { ty_estr(vstore_uniq) | ty_estr(vstore_fixed(_)) => { self.search_for_some_kind_of_autorefd_method( - AutoSlice, autoderefs, [m_imm], + AutoBorrowVec, autoderefs, [m_imm], |_m,r| ty::mk_estr(tcx, vstore_slice(r))) } diff --git a/src/rustc/middle/typeck/check/regionck.rs b/src/rustc/middle/typeck/check/regionck.rs index a38b805c7b4f1..970e86d00de91 100644 --- a/src/rustc/middle/typeck/check/regionck.rs +++ b/src/rustc/middle/typeck/check/regionck.rs @@ -22,10 +22,11 @@ use ppaux::{note_and_explain_region, ty_to_str}; use syntax::print::pprust; use infer::{resolve_and_force_all_but_regions, fres}; use syntax::ast::{def_arg, def_binding, def_local, def_self, def_upvar}; +use syntax::ast::{ProtoBare, ProtoBox, ProtoUniq, ProtoBorrowed}; use middle::freevars::get_freevars; use middle::kind::check_owned; use middle::pat_util::pat_bindings; -use middle::ty::{encl_region, proto_bare, proto_vstore, re_scope}; +use middle::ty::{encl_region, re_scope}; use middle::ty::{ty_fn_proto, vstore_box, vstore_fixed, vstore_slice}; use middle::ty::{vstore_uniq}; @@ -40,14 +41,9 @@ fn encl_region_of_def(fcx: @fn_ctxt, def: ast::def) -> ty::Region { return encl_region(tcx, node_id), def_upvar(_, subdef, closure_id, body_id) => { match ty_fn_proto(fcx.node_ty(closure_id)) { - proto_bare => - tcx.sess.bug(~"proto_bare in encl_region_of_def?!"), - proto_vstore(vstore_fixed(_)) => - tcx.sess.bug(~"vstore_fixed in encl_region_of_def?!"), - proto_vstore(vstore_slice(_)) => - encl_region_of_def(fcx, *subdef), - proto_vstore(vstore_uniq) | proto_vstore(vstore_box) => - re_scope(body_id) + ProtoBare => tcx.sess.bug(~"ProtoBare with upvars?!"), + ProtoBorrowed => encl_region_of_def(fcx, *subdef), + ProtoBox | ProtoUniq => re_scope(body_id) } } _ => { @@ -244,12 +240,9 @@ fn visit_expr(expr: @ast::expr, &&rcx: @rcx, v: rvt) { result::Ok(function_type) => { match ty::get(function_type).sty { ty::ty_fn(ref fn_ty) => { - match fn_ty.meta.proto { - proto_vstore(vstore_slice(region)) => { - constrain_free_variables(rcx, region, - expr); - } - _ => {} + if fn_ty.meta.proto == ast::ProtoBorrowed { + constrain_free_variables( + rcx, fn_ty.meta.region, expr); } } _ => () diff --git a/src/rustc/middle/typeck/collect.rs b/src/rustc/middle/typeck/collect.rs index 04f7aae0bf2a0..bb72c310a4b81 100644 --- a/src/rustc/middle/typeck/collect.rs +++ b/src/rustc/middle/typeck/collect.rs @@ -133,9 +133,10 @@ fn get_enum_variant_types(ccx: @crate_ctxt, }); result_ty = Some(ty::mk_fn(tcx, FnTyBase { meta: FnMeta {purity: ast::pure_fn, - proto: ty::proto_vstore(ty::vstore_box), + proto: ast::ProtoBare, onceness: ast::Many, bounds: @~[], + region: ty::re_static, ret_style: ast::return_val}, sig: FnSig {inputs: args, output: enum_ty} @@ -604,9 +605,10 @@ fn convert_struct(ccx: @crate_ctxt, // Write the dtor type let t_dtor = ty::mk_fn( tcx, - ty_of_fn_decl(ccx, type_rscope(rp), ast::proto_bare, - ast::impure_fn, ast::Many, @~[], - ast_util::dtor_dec(), None, dtor.span)); + ty_of_fn_decl( + ccx, type_rscope(rp), ast::ProtoBare, + ast::impure_fn, ast::Many, /*bounds:*/ @~[], /*opt_region:*/ None, + ast_util::dtor_dec(), None, dtor.span)); write_ty_to_tcx(tcx, dtor.node.id, t_dtor); tcx.tcache.insert(local_def(dtor.node.id), {bounds: tpt.bounds, @@ -643,9 +645,10 @@ fn convert_struct(ccx: @crate_ctxt, let ctor_fn_ty = ty::mk_fn(tcx, FnTyBase { meta: FnMeta { purity: ast::pure_fn, - proto: ty::proto_bare, + proto: ast::ProtoBare, onceness: ast::Many, bounds: @~[], + region: ty::re_static, ret_style: ast::return_val, }, sig: FnSig { @@ -684,15 +687,10 @@ fn ty_of_method(ccx: @crate_ctxt, rp: Option) -> ty::method { {ident: m.ident, tps: ty_param_bounds(ccx, m.tps), - fty: ty_of_fn_decl(ccx, - type_rscope(rp), - ast::proto_bare, - m.purity, - ast::Many, - @~[], - m.decl, - None, - m.span), + fty: ty_of_fn_decl(ccx, type_rscope(rp), ast::ProtoBare, + m.purity, ast::Many, + /*bounds:*/ @~[], /*opt_region:*/ None, + m.decl, None, m.span), self_ty: m.self_ty.node, vis: m.vis, def_id: local_def(m.id)} @@ -704,15 +702,10 @@ fn ty_of_ty_method(self: @crate_ctxt, id: ast::def_id) -> ty::method { {ident: m.ident, tps: ty_param_bounds(self, m.tps), - fty: ty_of_fn_decl(self, - type_rscope(rp), - ast::proto_bare, - m.purity, - ast::Many, - @~[], - m.decl, - None, - m.span), + fty: ty_of_fn_decl(self, type_rscope(rp), ast::ProtoBare, + m.purity, ast::Many, + /*bounds:*/ @~[], /*opt_region:*/ None, + m.decl, None, m.span), // assume public, because this is only invoked on trait methods self_ty: m.self_ty.node, vis: ast::public, @@ -767,15 +760,10 @@ fn ty_of_item(ccx: @crate_ctxt, it: @ast::item) } ast::item_fn(decl, purity, tps, _) => { let bounds = ty_param_bounds(ccx, tps); - let tofd = ty_of_fn_decl(ccx, - empty_rscope, - ast::proto_bare, - purity, - ast::Many, - @~[], - decl, - None, - it.span); + let tofd = ty_of_fn_decl(ccx, empty_rscope, + ast::ProtoBare, purity, ast::Many, + /*bounds:*/ @~[], /*opt_region:*/ None, + decl, None, it.span); let tpt = {bounds: bounds, region_param: None, ty: ty::mk_fn(ccx.tcx, tofd)}; @@ -930,9 +918,10 @@ fn ty_of_foreign_fn_decl(ccx: @crate_ctxt, let t_fn = ty::mk_fn(ccx.tcx, FnTyBase { meta: FnMeta {purity: purity, - proto: ty::proto_bare, onceness: ast::Many, + proto: ast::ProtoBare, bounds: @~[], + region: ty::re_static, ret_style: ast::return_val}, sig: FnSig {inputs: input_tys, output: output_ty} diff --git a/src/rustc/middle/typeck/infer/assignment.rs b/src/rustc/middle/typeck/infer/assignment.rs index a5af58904dd77..e5be4c7a19df6 100644 --- a/src/rustc/middle/typeck/infer/assignment.rs +++ b/src/rustc/middle/typeck/infer/assignment.rs @@ -126,6 +126,14 @@ priv impl Assign { } } + fn borrowable_protos(a_p: ast::Proto, b_p: ast::Proto) -> bool { + match (a_p, b_p) { + (ast::ProtoBox, ast::ProtoBorrowed) => true, + (ast::ProtoUniq, ast::ProtoBorrowed) => true, + _ => false + } + } + match (a_bnd, b_bnd) { (Some(a_bnd), Some(b_bnd)) => { // check for a case where a non-region pointer (@, ~) is @@ -149,7 +157,7 @@ priv impl Assign { ty::ty_estr(ty::vstore_slice(r_b))) if is_borrowable(vs_a) => { let nr_b = ty::mk_estr(self.infcx.tcx, vs_a); - self.try_assign(0, ty::AutoSlice, + self.try_assign(0, ty::AutoBorrowVec, a, nr_b, m_imm, r_b) } @@ -160,11 +168,22 @@ priv impl Assign { let nr_b = ty::mk_evec(self.infcx.tcx, {ty: mt_b.ty, mutbl: m_const}, vs_a); - self.try_assign(0, ty::AutoSlice, + self.try_assign(0, ty::AutoBorrowVec, a, nr_b, mt_b.mutbl, r_b) } + (ty::ty_fn(ref a_f), ty::ty_fn(ref b_f)) + if borrowable_protos(a_f.meta.proto, b_f.meta.proto) => { + let nr_b = ty::mk_fn(self.infcx.tcx, ty::FnTyBase { + meta: ty::FnMeta {proto: a_f.meta.proto, + ..b_f.meta}, + sig: b_f.sig + }); + self.try_assign(0, ty::AutoBorrowFn, + a, nr_b, m_imm, b_f.meta.region) + } + _ => { // otherwise, assignment follows normal subtype rules: to_ares(Sub(*self).tys(a, b)) diff --git a/src/rustc/middle/typeck/infer/combine.rs b/src/rustc/middle/typeck/infer/combine.rs index 87f313f68bd9b..c43f1e9c3865c 100644 --- a/src/rustc/middle/typeck/infer/combine.rs +++ b/src/rustc/middle/typeck/infer/combine.rs @@ -48,6 +48,8 @@ use to_str::ToStr; use ty::{FnTyBase, FnMeta, FnSig}; use syntax::ast::Onceness; +fn macros() { include!("macros.rs"); } // FIXME(#3114): Macro import/export. + trait combine { fn infcx() -> infer_ctxt; fn tag() -> ~str; @@ -70,7 +72,7 @@ trait combine { fn flds(a: ty::field, b: ty::field) -> cres; fn modes(a: ast::mode, b: ast::mode) -> cres; fn args(a: ty::arg, b: ty::arg) -> cres; - fn protos(p1: ty::fn_proto, p2: ty::fn_proto) -> cres; + fn protos(p1: ast::Proto, p2: ast::Proto) -> cres; fn ret_styles(r1: ret_style, r2: ret_style) -> cres; fn purities(a: purity, b: purity) -> cres; fn oncenesses(a: Onceness, b: Onceness) -> cres; @@ -310,20 +312,17 @@ fn super_vstores( fn super_fn_metas( self: &C, a_f: &ty::FnMeta, b_f: &ty::FnMeta) -> cres { - do self.protos(a_f.proto, b_f.proto).chain |p| { - do self.ret_styles(a_f.ret_style, b_f.ret_style).chain |rs| { - do self.purities(a_f.purity, b_f.purity).chain |purity| { - do self.oncenesses(a_f.onceness, b_f.onceness).chain - |onceness| { - Ok(FnMeta {purity: purity, - proto: p, - onceness: onceness, - bounds: a_f.bounds, // XXX: This is wrong! - ret_style: rs}) - } - } - } - } + let p = if_ok!(self.protos(a_f.proto, b_f.proto)); + let r = if_ok!(self.contraregions(a_f.region, b_f.region)); + let rs = if_ok!(self.ret_styles(a_f.ret_style, b_f.ret_style)); + let purity = if_ok!(self.purities(a_f.purity, b_f.purity)); + let onceness = if_ok!(self.oncenesses(a_f.onceness, b_f.onceness)); + Ok(FnMeta {purity: purity, + proto: p, + region: r, + onceness: onceness, + bounds: a_f.bounds, // XXX: This is wrong! + ret_style: rs}) } fn super_fn_sigs( diff --git a/src/rustc/middle/typeck/infer/glb.rs b/src/rustc/middle/typeck/infer/glb.rs index 0e81d97426f36..fb4bd1af199d0 100644 --- a/src/rustc/middle/typeck/infer/glb.rs +++ b/src/rustc/middle/typeck/infer/glb.rs @@ -71,22 +71,8 @@ impl Glb: combine { Lub(*self).tys(a, b) } - fn protos(p1: ty::fn_proto, p2: ty::fn_proto) -> cres { - match (p1, p2) { - (ty::proto_vstore(ty::vstore_slice(_)), _) => Ok(p2), - (_, ty::proto_vstore(ty::vstore_slice(_))) => Ok(p1), - (ty::proto_vstore(v1), ty::proto_vstore(v2)) => { - self.infcx.try(|| { - do self.vstores(terr_fn, v1, v2).chain |vs| { - Ok(ty::proto_vstore(vs)) - } - }).chain_err(|_err| { - // XXX: Totally unsound, but fixed up later. - Ok(ty::proto_bare) - }) - } - _ => Ok(ty::proto_bare) - } + fn protos(p1: ast::Proto, p2: ast::Proto) -> cres { + if p1 == p2 {Ok(p1)} else {Ok(ast::ProtoBare)} } fn purities(a: purity, b: purity) -> cres { diff --git a/src/rustc/middle/typeck/infer/lub.rs b/src/rustc/middle/typeck/infer/lub.rs index 285b05736c63e..a323ae720b282 100644 --- a/src/rustc/middle/typeck/infer/lub.rs +++ b/src/rustc/middle/typeck/infer/lub.rs @@ -54,21 +54,12 @@ impl Lub: combine { Glb(*self).tys(a, b) } - // XXX: Wrong. - fn protos(p1: ty::fn_proto, p2: ty::fn_proto) -> cres { + fn protos(p1: ast::Proto, p2: ast::Proto) -> cres { match (p1, p2) { - (ty::proto_bare, _) => Ok(p2), - (_, ty::proto_bare) => Ok(p1), - (ty::proto_vstore(v1), ty::proto_vstore(v2)) => { - self.infcx.try(|| { - do self.vstores(terr_fn, v1, v2).chain |vs| { - Ok(ty::proto_vstore(vs)) - } - }).chain_err(|_err| { - // XXX: Totally unsound, but fixed up later. - Ok(ty::proto_vstore(ty::vstore_slice(ty::re_static))) - }) - } + (ast::ProtoBare, _) => Ok(p2), + (_, ast::ProtoBare) => Ok(p1), + _ if p1 == p2 => Ok(p1), + _ => Err(ty::terr_proto_mismatch(expected_found(&self, p1, p2))) } } diff --git a/src/rustc/middle/typeck/infer/sub.rs b/src/rustc/middle/typeck/infer/sub.rs index 9e27235b30d1a..80f9eb85aab20 100644 --- a/src/rustc/middle/typeck/infer/sub.rs +++ b/src/rustc/middle/typeck/infer/sub.rs @@ -63,27 +63,11 @@ impl Sub: combine { } } - fn protos(a: ty::fn_proto, b: ty::fn_proto) -> cres { - match (a, b) { - (ty::proto_bare, _) => - Ok(ty::proto_bare), - - (ty::proto_vstore(ty::vstore_box), - ty::proto_vstore(ty::vstore_slice(_))) => - Ok(ty::proto_vstore(ty::vstore_box)), - - (ty::proto_vstore(ty::vstore_uniq), - ty::proto_vstore(ty::vstore_slice(_))) => - Ok(ty::proto_vstore(ty::vstore_uniq)), - - (_, ty::proto_bare) => - Err(ty::terr_proto_mismatch(expected_found(&self, a, b))), - - (ty::proto_vstore(vs_a), ty::proto_vstore(vs_b)) => { - do self.vstores(ty::terr_fn, vs_a, vs_b).chain |vs_c| { - Ok(ty::proto_vstore(vs_c)) - } - } + fn protos(p1: ast::Proto, p2: ast::Proto) -> cres { + match (p1, p2) { + (ast::ProtoBare, _) => Ok(p1), + _ if p1 == p2 => Ok(p1), + _ => Err(ty::terr_proto_mismatch(expected_found(&self, p1, p2))) } } diff --git a/src/rustc/util/ppaux.rs b/src/rustc/util/ppaux.rs index c7062baaea5ec..5f7a890f2c422 100644 --- a/src/rustc/util/ppaux.rs +++ b/src/rustc/util/ppaux.rs @@ -4,7 +4,7 @@ use middle::ty::{arg, canon_mode}; use middle::ty::{bound_copy, bound_const, bound_owned, bound_send, bound_trait}; use middle::ty::{bound_region, br_anon, br_named, br_self, br_cap_avoid}; -use middle::ty::{ck_block, ck_box, ck_uniq, ctxt, field, method}; +use middle::ty::{ctxt, field, method}; use middle::ty::{mt, t, param_bound}; use middle::ty::{re_bound, re_free, re_scope, re_infer, re_static, Region}; use middle::ty::{ReSkolemized, ReVar}; @@ -222,10 +222,12 @@ fn vstore_ty_to_str(cx: ctxt, ty: ~str, vs: ty::vstore) -> ~str { } } -fn proto_ty_to_str(cx: ctxt, proto: ty::fn_proto) -> ~str { +fn proto_ty_to_str(_cx: ctxt, proto: ast::Proto) -> ~str { match proto { - ty::proto_bare => ~"", - ty::proto_vstore(vstore) => vstore_to_str(cx, vstore) + ast::ProtoBare => ~"", + ast::ProtoBox => ~"@", + ast::ProtoBorrowed => ~"&", + ast::ProtoUniq => ~"~", } } @@ -268,8 +270,8 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str { modestr + ty_to_str(cx, ty) } fn fn_to_str(cx: ctxt, + proto: ast::Proto, purity: ast::purity, - proto: ty::fn_proto, onceness: ast::Onceness, ident: Option, inputs: ~[arg], @@ -287,9 +289,9 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str { ast::Once => onceness_to_str(onceness) + ~" " }; + s += proto_ty_to_str(cx, proto); s += ~"fn"; - s += proto_ty_to_str(cx, proto); match ident { Some(i) => { s += ~" "; s += cx.sess.str_of(i); } _ => { } @@ -310,8 +312,8 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str { fn method_to_str(cx: ctxt, m: method) -> ~str { return fn_to_str( cx, - m.fty.meta.purity, m.fty.meta.proto, + m.fty.meta.purity, m.fty.meta.onceness, Some(m.ident), m.fty.sig.inputs, @@ -364,8 +366,8 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str { } ty_fn(ref f) => { fn_to_str(cx, - f.meta.purity, f.meta.proto, + f.meta.purity, f.meta.onceness, None, f.sig.inputs, @@ -393,9 +395,10 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str { } ty_estr(vs) => vstore_ty_to_str(cx, ~"str", vs), ty_opaque_box => ~"@?", - ty_opaque_closure_ptr(ck_block) => ~"closure&", - ty_opaque_closure_ptr(ck_box) => ~"closure@", - ty_opaque_closure_ptr(ck_uniq) => ~"closure~" + ty_opaque_closure_ptr(ast::ProtoBorrowed) => ~"closure&", + ty_opaque_closure_ptr(ast::ProtoBox) => ~"closure@", + ty_opaque_closure_ptr(ast::ProtoUniq) => ~"closure~", + ty_opaque_closure_ptr(ast::ProtoBare) => ~"closure" } } diff --git a/src/test/compile-fail/block-coerce-no.rs b/src/test/compile-fail/block-coerce-no.rs index f444568566540..94375d4ffcbf0 100644 --- a/src/test/compile-fail/block-coerce-no.rs +++ b/src/test/compile-fail/block-coerce-no.rs @@ -2,11 +2,11 @@ // other tycons. fn coerce(b: fn()) -> extern fn() { - fn lol(f: extern fn(fn()) -> extern fn(), - g: fn()) -> extern fn() { return f(g); } - fn fn_id(f: extern fn()) -> extern fn() { return f } + fn lol(+f: extern fn(+v: fn()) -> extern fn(), + +g: fn()) -> extern fn() { return f(g); } + fn fn_id(+f: extern fn()) -> extern fn() { return f } return lol(fn_id, b); - //~^ ERROR mismatched types: expected `fn(fn&()) -> fn()` + //~^ ERROR mismatched types } fn main() { diff --git a/src/test/compile-fail/extern-wrong-value-type.rs b/src/test/compile-fail/extern-wrong-value-type.rs index dccd127987139..c9bcfc4111902 100644 --- a/src/test/compile-fail/extern-wrong-value-type.rs +++ b/src/test/compile-fail/extern-wrong-value-type.rs @@ -1,8 +1,7 @@ -// error-pattern:expected `fn&()` but found `*u8` extern fn f() { } fn main() { // extern functions are *u8 types - let _x: fn() = f; + let _x: fn() = f; //~ ERROR mismatched types: expected `&fn()` but found `*u8` } diff --git a/src/test/run-pass/issue-1896-1.rs b/src/test/compile-fail/issue-1896-1.rs similarity index 74% rename from src/test/run-pass/issue-1896-1.rs rename to src/test/compile-fail/issue-1896-1.rs index bee92bc9c9abb..d95611cbeb77c 100644 --- a/src/test/run-pass/issue-1896-1.rs +++ b/src/test/compile-fail/issue-1896-1.rs @@ -1,7 +1,7 @@ type boxedFn = { theFn: fn () -> uint }; fn createClosure (closedUint: uint) -> boxedFn { - { theFn: fn@ () -> uint { closedUint } } + { theFn: fn@ () -> uint { closedUint } } //~ ERROR mismatched types } fn main () { diff --git a/src/test/run-pass/issue-1896-2.rs b/src/test/compile-fail/issue-1896-2.rs similarity index 55% rename from src/test/run-pass/issue-1896-2.rs rename to src/test/compile-fail/issue-1896-2.rs index 671d80a122702..af245dbeae8a0 100644 --- a/src/test/run-pass/issue-1896-2.rs +++ b/src/test/compile-fail/issue-1896-2.rs @@ -5,6 +5,6 @@ fn add(n: int) -> fn@(int) -> int { fn main() { assert add(3)(4) == 7; - let add3 : fn(int)->int = add(3); - assert add3(4) == 7; + let add3 : fn(int)->int = add(3); //~ ERROR mismatched types + assert add3(4) == 7; } \ No newline at end of file diff --git a/src/test/run-pass/issue-1896-3.rs b/src/test/compile-fail/issue-1896-3.rs similarity index 80% rename from src/test/run-pass/issue-1896-3.rs rename to src/test/compile-fail/issue-1896-3.rs index 7cc254d7c19a9..05aea8f0fca54 100644 --- a/src/test/run-pass/issue-1896-3.rs +++ b/src/test/compile-fail/issue-1896-3.rs @@ -12,6 +12,6 @@ fn main() let add2 : &(fn@(int)->int) = &add(2); assert (*add2)(5) == 7; - let add3 : fn(int)->int = add(3); + let add3 : fn(int)->int = add(3); //~ ERROR mismatched types assert add3(4) == 7; } diff --git a/src/test/compile-fail/issue-1896.rs b/src/test/compile-fail/issue-1896.rs index 91b2ec490df99..cd00b0088a732 100644 --- a/src/test/compile-fail/issue-1896.rs +++ b/src/test/compile-fail/issue-1896.rs @@ -3,6 +3,7 @@ type t = { f: fn() -> T }; fn f(_x: t) {} fn main() { - let x: t<()> = { f: { || () } }; - f(x); //~ ERROR copying a noncopyable value + let x: t<()> = { f: { || () } }; //~ ERROR expected & closure, found @ closure + //~^ ERROR in field `f`, expected & closure, found @ closure + f(x); } \ No newline at end of file diff --git a/src/test/compile-fail/missing-do.rs b/src/test/compile-fail/missing-do.rs index c9fe0faab8a6d..1726a527d146d 100644 --- a/src/test/compile-fail/missing-do.rs +++ b/src/test/compile-fail/missing-do.rs @@ -4,6 +4,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 `fn(&fn())` //~^ NOTE did you forget the 'do' keyword for the call? } diff --git a/src/test/compile-fail/obsolete-syntax.rs b/src/test/compile-fail/obsolete-syntax.rs index 4be5470842878..96fb676e42525 100644 --- a/src/test/compile-fail/obsolete-syntax.rs +++ b/src/test/compile-fail/obsolete-syntax.rs @@ -56,22 +56,11 @@ fn obsolete_with() { //~^ ERROR obsolete syntax: with } -fn obsolete_fixed_length_vec() { - let foo: [int]/1; - //~^ ERROR obsolete syntax: fixed-length vector - foo = [1]/_; - //~^ ERROR obsolete syntax: fixed-length vector - let foo: [int]/1; - //~^ ERROR obsolete syntax: fixed-length vector - foo = [1]/1; - //~^ ERROR obsolete syntax: fixed-length vector -} - fn obsolete_moves() { let mut x = 0; let y <- x; //~^ ERROR obsolete syntax: initializer-by-move - y <- x; + y <- x; //~^ ERROR obsolete syntax: binary move } diff --git a/src/test/compile-fail/pure-subtyping.rs b/src/test/compile-fail/pure-subtyping.rs index c6f3568087c95..efc4a720ab19c 100644 --- a/src/test/compile-fail/pure-subtyping.rs +++ b/src/test/compile-fail/pure-subtyping.rs @@ -1,35 +1,37 @@ // Test rules governing higher-order pure fns. +fn take(_v: T) {} + fn assign_to_pure(x: pure fn(), y: fn(), z: unsafe fn()) { - let a: pure fn() = x; - let b: pure fn() = y; //~ ERROR expected pure fn but found impure fn - let c: pure fn() = z; //~ ERROR expected pure fn but found unsafe fn + take::(x); + take::(y); //~ ERROR expected pure fn but found impure fn + take::(z); //~ ERROR expected pure fn but found unsafe fn } fn assign_to_impure(x: pure fn(), y: fn(), z: unsafe fn()) { - let h: fn() = x; - let i: fn() = y; - let j: fn() = z; //~ ERROR expected impure fn but found unsafe fn + take::(x); + take::(y); + take::(z); //~ ERROR expected impure fn but found unsafe fn } fn assign_to_unsafe(x: pure fn(), y: fn(), z: unsafe fn()) { - let m: unsafe fn() = x; - let n: unsafe fn() = y; - let o: unsafe fn() = z; + take::(x); + take::(y); + take::(z); } fn assign_to_pure2(x: pure fn@(), y: fn@(), z: unsafe fn@()) { - let a: pure fn() = x; - let b: pure fn() = y; //~ ERROR expected pure fn but found impure fn - let c: pure fn() = z; //~ ERROR expected pure fn but found unsafe fn + take::(x); + take::(y); //~ ERROR expected pure fn but found impure fn + take::(z); //~ ERROR expected pure fn but found unsafe fn - let a: pure fn~() = x; //~ ERROR fn storage differs: expected ~ but found @ - let b: pure fn~() = y; //~ ERROR fn storage differs: expected ~ but found @ - let c: pure fn~() = z; //~ ERROR fn storage differs: expected ~ but found @ + take::(x); //~ ERROR expected ~ closure, found @ closure + take::(y); //~ ERROR expected ~ closure, found @ closure + take::(z); //~ ERROR expected ~ closure, found @ closure - let a: unsafe fn~() = x; //~ ERROR fn storage differs: expected ~ but found @ - let b: unsafe fn~() = y; //~ ERROR fn storage differs: expected ~ but found @ - let c: unsafe fn~() = z; //~ ERROR fn storage differs: expected ~ but found @ + take::(x); //~ ERROR expected ~ closure, found @ closure + take::(y); //~ ERROR expected ~ closure, found @ closure + take::(z); //~ ERROR expected ~ closure, found @ closure } fn main() { diff --git a/src/test/compile-fail/regions-freevar.rs b/src/test/compile-fail/regions-freevar.rs index b163006c50a68..e5b33d725c7c0 100644 --- a/src/test/compile-fail/regions-freevar.rs +++ b/src/test/compile-fail/regions-freevar.rs @@ -2,8 +2,7 @@ fn wants_static_fn(_x: &static/fn()) {} fn main() { let i = 3; - do wants_static_fn { + do wants_static_fn { //~ ERROR cannot infer an appropriate lifetime due to conflicting requirements debug!("i=%d", i); - //~^ ERROR captured variable does not outlive the enclosing closure } } diff --git a/src/test/compile-fail/sendfn-is-not-a-lambda.rs b/src/test/compile-fail/sendfn-is-not-a-lambda.rs index 081c400d71d18..f47cf51b4be24 100644 --- a/src/test/compile-fail/sendfn-is-not-a-lambda.rs +++ b/src/test/compile-fail/sendfn-is-not-a-lambda.rs @@ -4,5 +4,5 @@ fn test(f: fn@(uint) -> uint) -> uint { fn main() { let f = fn~(x: uint) -> uint { return 4u; }; - log(debug, test(f)); //~ ERROR expected `fn@(uint) -> uint` + log(debug, test(f)); //~ ERROR expected @ closure, found ~ closure } diff --git a/src/test/pretty/disamb-stmt-expr.rs b/src/test/pretty/disamb-stmt-expr.rs index 3ad709d991dd9..9fb898991e8ab 100644 --- a/src/test/pretty/disamb-stmt-expr.rs +++ b/src/test/pretty/disamb-stmt-expr.rs @@ -4,7 +4,7 @@ // preserved. They are needed to disambiguate `{return n+1}; - 0` from // `({return n+1}-0)`. -fn id(f: fn&() -> int) -> int { f() } +fn id(f: &fn() -> int) -> int { f() } fn wsucc(n: int) -> int { (do id || { 1 }) - 0 } fn main() { } diff --git a/src/test/pretty/fn-types.rs b/src/test/pretty/fn-types.rs index 9132c5475ffde..a1fdf5094c12c 100644 --- a/src/test/pretty/fn-types.rs +++ b/src/test/pretty/fn-types.rs @@ -1,7 +1,7 @@ // pp-exact fn from_foreign_fn(x: extern fn()) { } -fn from_stack_closure(x: fn&()) { } -fn from_box_closure(x: fn@()) { } -fn from_unique_closure(x: fn~()) { } +fn from_stack_closure(x: &fn()) { } +fn from_box_closure(x: @fn()) { } +fn from_unique_closure(x: ~fn()) { } fn main() { } diff --git a/src/test/run-pass/issue-2185.rs b/src/test/run-pass/issue-2185.rs index 8913ac3d30493..c95e84179545f 100644 --- a/src/test/run-pass/issue-2185.rs +++ b/src/test/run-pass/issue-2185.rs @@ -1,3 +1,4 @@ +// xfail-test FIXME #2263 // xfail-fast // This test had to do with an outdated version of the iterable trait. // However, the condition it was testing seemed complex enough to diff --git a/src/test/run-pass/task-killjoin-rsrc.rs b/src/test/run-pass/task-killjoin-rsrc.rs index 1cea7d61f8c4b..1e8da40b5b309 100644 --- a/src/test/run-pass/task-killjoin-rsrc.rs +++ b/src/test/run-pass/task-killjoin-rsrc.rs @@ -37,7 +37,7 @@ fn joinable(+f: fn~()) -> comm::Port { } let p = comm::Port(); let c = comm::Chan(&p); - do task::spawn_unlinked { wrapper(c, copy f) }; + do task::spawn_unlinked { wrapper(c, f) }; p }