diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2012-11-04 20:41:00 -0800 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2012-11-06 08:56:29 -0800 |
| commit | b0ed151539cddb1c191f67f9f9597942919d44eb (patch) | |
| tree | 976ed7cab726c0cdae81e0a18e28a27cbd5e4664 /src/libsyntax | |
| parent | 53ec6c3f9b495dd930cd061784251534bef58d74 (diff) | |
| download | rust-b0ed151539cddb1c191f67f9f9597942919d44eb.tar.gz rust-b0ed151539cddb1c191f67f9f9597942919d44eb.zip | |
Cleanup how we handle proto in types, remove unsound subtyping
Fixes #1896 which was never truly fixed, just masked. The given tests would have failed had they used `~fn()` and not `@fn()`. They now result in compilation errors. Fixes #2978. Necessary first step for #2202, #2263.
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 45 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 18 | ||||
| -rw-r--r-- | src/libsyntax/parse/obsolete.rs | 66 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 275 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 150 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 12 |
6 files changed, 308 insertions, 258 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 8667f36c749..8fcb9300b52 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<ident>), 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 @@ -1080,19 +1086,30 @@ 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_ { ty_nil, ty_bot, /* bottom type */ 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<uint>), 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 7c8909668f5..3879e70cb28 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 1344c9b11ea..e5f6cf8ee25 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<Option<uint>> { - 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 63545a69608..db3f6abbf7b 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<ast::Proto>, + pre_region_name: Option<ident>) -> 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<Option<uint>> { + fn maybe_parse_fixed_vstore_with_star() -> Option<uint> { 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<Proto> { 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 e0b9958bcb7..ed64d02cea3 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<ast::self_ty_>, 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<ast::proto>, + opt_proto: Option<ast::Proto>, + 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<ast::self_ty_>) { 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<comments::cmnt> { } } -fn fn_header_info_to_str(opt_sty: Option<ast::self_ty_>, - opt_purity: Option<ast::purity>, - opt_p: Option<ast::proto>, - 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<ast::self_ty_>) { + match opt_self_ty { + Some(ast::sty_static) => { word(s.s, ~"static "); } + _ => {} + } +} +fn print_opt_purity(s: ps, opt_purity: Option<ast::purity>) { 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<ast::Proto>) { + 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<ast::self_ty_>, + opt_purity: Option<ast::purity>, + onceness: ast::Onceness, + opt_proto: Option<ast::Proto>, + 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<ast::proto>) -> ~str { +fn opt_proto_to_str(opt_p: Option<ast::Proto>) -> ~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 be6fb4cefa8..97cc52bd35a 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -15,7 +15,7 @@ enum vt<E> { mk_vt(visitor<E>), } 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<E>(t: @Ty, e: E, v: vt<E>) { 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(_) | |
