1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 // The Rust abstract syntax tree.
13 use codemap::{span, spanned};
18 use core::option::{None, Option, Some};
21 use core::to_str::ToStr;
22 use std::serialize::{Encodable, Decodable, Encoder, Decoder};
25 // an identifier contains an index into the interner
26 // table and a SyntaxContext to track renaming and
27 // macro expansion per Flatt et al., "Macros
28 // That Work Together"
30 pub struct ident { repr: Name, ctxt: SyntaxContext }
32 // a SyntaxContext represents a chain of macro-expandings
33 // and renamings. Each macro expansion corresponds to
36 // I'm representing this syntax context as an index into
37 // a table, in order to work around a compiler bug
38 // that's causing unreleased memory to cause core dumps
39 // and also perhaps to save some work in destructor checks.
40 // the special uint '0' will be used to indicate an empty
43 // this uint is a reference to a table stored in thread-local
45 pub type SyntaxContext = uint;
47 pub type SCTable = ~[SyntaxContext_];
48 pub static empty_ctxt : uint = 0;
53 pub enum SyntaxContext_ {
55 Mark (Mrk,SyntaxContext),
56 // flattening the name and syntaxcontext into the rename...
58 // 1) the first name in a Rename node
59 // can only be a programmer-supplied name.
60 // 2) Every Rename node with a given Name in the
61 // "to" slot must have the same name and context
62 // in the "from" slot. In essence, they're all
63 // pointers to a single "rename" event node.
64 Rename (ident,Name,SyntaxContext)
67 // a name represents an identifier
69 // a mark represents a unique id associated
70 // with a macro expansion
74 impl<S:Encoder> Encodable<S> for ident {
75 fn encode(&self, s: &S) {
78 match task::local_data::local_data_get(interner_key!()) {
79 None => fail!(~"encode: TLS interner not set up"),
83 s.emit_str(*(*intr).get(*self));
89 impl<S:Encoder> Encodable<S> for ident {
90 fn encode(&self, s: &mut S) {
93 match task::local_data::local_data_get(interner_key!()) {
94 None => fail!(~"encode: TLS interner not set up"),
98 s.emit_str(*(*intr).get(*self));
104 impl<D:Decoder> Decodable<D> for ident {
105 fn decode(d: &D) -> ident {
106 let intr = match unsafe {
107 task::local_data::local_data_get(interner_key!())
109 None => fail!(~"decode: TLS interner not set up"),
113 (*intr).intern(@d.read_str())
118 impl<D:Decoder> Decodable<D> for ident {
119 fn decode(d: &mut D) -> ident {
120 let intr = match unsafe {
121 task::local_data::local_data_get(interner_key!())
123 None => fail!(~"decode: TLS interner not set up"),
127 (*intr).intern(@d.read_str())
131 impl to_bytes::IterBytes for ident {
132 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
133 self.repr.iter_bytes(lsb0, f)
137 // Functions may or may not have names.
138 pub type fn_ident = Option<ident>;
143 pub struct Lifetime {
149 // a "Path" is essentially Rust's notion of a name;
150 // for instance: core::cmp::Eq . It's represented
151 // as a sequence of identifiers, along with a bunch
152 // of supporting information.
160 rp: Option<@Lifetime>,
164 pub type crate_num = int;
166 pub type node_id = int;
176 pub static local_crate: crate_num = 0;
177 pub static crate_node_id: node_id = 0;
182 // The AST represents all type param bounds as types.
183 // typeck::collect::compute_bounds matches these against
184 // the "special" built-in traits (see middle::lang_items) and
185 // detects Copy, Send, Owned, and Const.
186 pub enum TyParamBound {
187 TraitTyParamBound(@trait_ref),
197 bounds: @OptVec<TyParamBound>
203 pub struct Generics {
204 lifetimes: OptVec<Lifetime>,
205 ty_params: OptVec<TyParam>
209 fn is_parameterized(&self) -> bool {
210 self.lifetimes.len() + self.ty_params.len() > 0
212 fn is_lt_parameterized(&self) -> bool {
213 self.lifetimes.len() > 0
215 fn is_type_parameterized(&self) -> bool {
216 self.ty_params.len() > 0
224 def_fn(def_id, purity),
225 def_static_method(/* method */ def_id,
226 /* trait */ Option<def_id>,
228 def_self(node_id, bool /* is_implicit */),
229 def_self_ty(/* trait id */ node_id),
231 def_foreign_mod(def_id),
233 def_arg(node_id, bool /* is_mutbl */),
234 def_local(node_id, bool /* is_mutbl */),
235 def_variant(def_id /* enum */, def_id /* variant */),
238 def_prim_ty(prim_ty),
239 def_ty_param(def_id, uint),
240 def_binding(node_id, binding_mode),
242 def_upvar(node_id, // id of closed over var
243 @def, // closed over def
244 node_id, // expr node that creates the closure
245 node_id), // id for the block/body of the closure expr
247 def_typaram_binder(node_id), /* struct, impl or trait with ty params */
253 // The set of meta_items that define the compilation environment of the crate,
254 // used to drive conditional compilation
255 pub type crate_cfg = ~[@meta_item];
257 pub type crate = spanned<crate_>;
268 pub type meta_item = spanned<meta_item_>;
273 pub enum meta_item_ {
275 meta_list(@~str, ~[@meta_item]),
276 meta_name_value(@~str, lit),
279 pub type blk = spanned<blk_>;
285 view_items: ~[@view_item],
289 rules: blk_check_mode,
304 pub struct field_pat {
312 pub enum binding_mode {
314 bind_by_ref(mutability),
318 impl to_bytes::IterBytes for binding_mode {
319 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
321 bind_by_copy => 0u8.iter_bytes(lsb0, f),
323 bind_by_ref(ref m) =>
324 to_bytes::iter_bytes_2(&1u8, m, lsb0, f),
327 2u8.iter_bytes(lsb0, f),
337 // A pat_ident may either be a new bound variable,
338 // or a nullary enum (in which case the second field
340 // In the nullary enum case, the parser can't determine
341 // which it is. The resolver determines this, and
342 // records this pattern's node_id in an auxiliary
343 // set (of "pat_idents that refer to nullary enums")
344 pat_ident(binding_mode, @Path, Option<@pat>),
345 pat_enum(@Path, Option<~[@pat]>), /* "none" means a * pattern where
346 * we don't bind the fields to names */
347 pat_struct(@Path, ~[field_pat], bool),
351 pat_region(@pat), // borrowed pointer pattern
353 pat_range(@expr, @expr),
354 // [a, b, ..i, y, z] is represented as
355 // pat_vec(~[a, b], Some(i), ~[y, z])
356 pat_vec(~[@pat], Option<@pat>, ~[@pat])
362 pub enum mutability { m_mutbl, m_imm, m_const, }
364 impl to_bytes::IterBytes for mutability {
365 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
366 (*self as u8).iter_bytes(lsb0, f)
379 impl to_bytes::IterBytes for Sigil {
380 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
381 (*self as uint).iter_bytes(lsb0, f)
385 impl ToStr for Sigil {
386 fn to_str(&self) -> ~str {
388 BorrowedSigil => ~"&",
399 // FIXME (#3469): Change uint to @expr (actually only constant exprs)
400 vstore_fixed(Option<uint>), // [1,2,3,4]
401 vstore_uniq, // ~[1,2,3,4]
402 vstore_box, // @[1,2,3,4]
403 vstore_slice(Option<@Lifetime>) // &'foo? [1,2,3,4]
409 pub enum expr_vstore {
410 expr_vstore_uniq, // ~[1,2,3,4]
411 expr_vstore_box, // @[1,2,3,4]
412 expr_vstore_mut_box, // @mut [1,2,3,4]
413 expr_vstore_slice, // &[1,2,3,4]
414 expr_vstore_mut_slice, // &mut [1,2,3,4]
452 pub type stmt = spanned<stmt_>;
458 stmt_decl(@decl, node_id),
460 // expr without trailing semi-colon (must have unit type):
461 stmt_expr(@expr, node_id),
463 // expr with trailing semi-colon (may have any type):
464 stmt_semi(@expr, node_id),
466 // bool: is there a trailing sem-colon?
470 // FIXME (pending discussion of #1697, #2178...): local should really be
471 // a refinement on pat.
483 pub type local = spanned<local_>;
485 pub type decl = spanned<decl_>;
490 pub enum decl_ { decl_local(~[@local]), decl_item(@item), }
497 guard: Option<@expr>,
510 pub type field = spanned<field_>;
515 pub enum blk_check_mode { default_blk, unsafe_blk, }
522 // Extra node ID is only used for index, assign_op, unary, binary, method
542 expr_vstore(@expr, expr_vstore),
543 expr_vec(~[@expr], mutability),
544 expr_call(@expr, ~[@expr], CallSugar),
545 expr_method_call(@expr, ident, ~[@Ty], ~[@expr], CallSugar),
547 expr_binary(binop, @expr, @expr),
548 expr_unary(unop, @expr),
550 expr_cast(@expr, @Ty),
551 expr_if(@expr, blk, Option<@expr>),
552 expr_while(@expr, blk),
553 /* Conditionless loop (can be exited with break, cont, or ret)
554 Same semantics as while(true) { body }, but typestate knows that the
555 (implicit) condition is always true. */
556 expr_loop(blk, Option<ident>),
557 expr_match(@expr, ~[arm]),
558 expr_fn_block(fn_decl, blk),
559 // Inner expr is always an expr_fn_block. We need the wrapping node to
560 // easily type this (a function returning nil on the inside but bool on
562 expr_loop_body(@expr),
563 // Like expr_loop_body but for 'do' blocks
568 expr_assign(@expr, @expr),
569 expr_swap(@expr, @expr),
570 expr_assign_op(binop, @expr, @expr),
571 expr_field(@expr, ident, ~[@Ty]),
572 expr_index(@expr, @expr),
574 expr_addr_of(mutability, @expr),
575 expr_break(Option<ident>),
576 expr_again(Option<ident>),
577 expr_ret(Option<@expr>),
578 expr_log(@expr, @expr),
580 expr_inline_asm(inline_asm),
584 // A struct literal expression.
585 expr_struct(@Path, ~[field], Option<@expr>),
587 // A vector literal constructed from one repeated element.
588 expr_repeat(@expr /* element */, @expr /* count */, mutability),
590 // No-op: used solely so we can pretty-print faithfully
594 // When the main rust parser encounters a syntax-extension invocation, it
595 // parses the arguments to the invocation as a token-tree. This is a very
596 // loose structure, such that all sorts of different AST-fragments can
597 // be passed to syntax extensions using a uniform type.
599 // If the syntax extension is an MBE macro, it will attempt to match its
600 // LHS "matchers" against the provided token tree, and if it finds a
601 // match, will transcribe the RHS token tree, splicing in any captured
602 // macro_parser::matched_nonterminals into the tt_nonterminals it finds.
604 // The RHS of an MBE macro is the only place a tt_nonterminal or tt_seq
605 // makes any real sense. You could write them elsewhere but nothing
606 // else knows what to do with them, so you'll probably get a syntax
612 #[doc="For macro invocations; parsing is delegated to the macro"]
613 pub enum token_tree {
615 tt_tok(span, ::parse::token::Token),
616 // a delimited sequence (the delimiters appear as the first
617 // and last elements of the vector)
618 tt_delim(~[token_tree]),
619 // These only make sense for right-hand-sides of MBE macros:
621 // a kleene-style repetition sequence with a span, a tt_forest,
622 // an optional separator (?), and a boolean where true indicates
623 // zero or more (*), and false indicates one or more (+).
624 tt_seq(span, ~[token_tree], Option<::parse::token::Token>, bool),
626 // a syntactic variable that will be filled in by macro expansion.
627 tt_nonterminal(span, ident)
631 // Matchers are nodes defined-by and recognized-by the main rust parser and
632 // language, but they're only ever found inside syntax-extension invocations;
633 // indeed, the only thing that ever _activates_ the rules in the rust parser
634 // for parsing a matcher is a matcher looking for the 'matchers' nonterminal
635 // itself. Matchers represent a small sub-language for pattern-matching
636 // token-trees, and are thus primarily used by the macro-defining extension
642 // A matcher that matches a single token, denoted by the token itself. So
643 // long as there's no $ involved.
649 // A matcher that matches a sequence of sub-matchers, denoted various
652 // $(M)* zero or more Ms
653 // $(M)+ one or more Ms
654 // $(M),+ one or more comma-separated Ms
655 // $(A B C);* zero or more semi-separated 'A B C' seqs
661 // A matcher that matches one of a few interesting named rust
662 // nonterminals, such as types, expressions, items, or raw token-trees. A
663 // black-box matcher on expr, for example, binds an expr to a given ident,
664 // and that ident can re-occur as an interpolation in the RHS of a
665 // macro-by-example rule. For example:
667 // $foo:expr => 1 + $foo // interpolate an expr
668 // $foo:tt => $foo // interpolate a token-tree
669 // $foo:tt => bar! $foo // only other valid interpolation
670 // // is in arg position for another
673 // As a final, horrifying aside, note that macro-by-example's input is
674 // also matched by one of these matchers. Holy self-referential! It is matched
675 // by an match_seq, specifically this one:
677 // $( $lhs:matchers => $rhs:tt );+
679 // If you understand that, you have closed to loop and understand the whole
680 // macro system. Congratulations.
682 pub type matcher = spanned<matcher_>;
689 match_tok(::parse::token::Token),
690 // match repetitions of a sequence: body, separator, zero ok?,
691 // lo, hi position-in-match-array used:
692 match_seq(~[matcher], Option<::parse::token::Token>, bool, uint, uint),
693 // parse a Rust NT: name to bind, name of NT, position in match array:
694 match_nonterminal(ident, ident, uint)
697 pub type mac = spanned<mac_>;
703 mac_invoc_tt(@Path,~[token_tree]), // new macro-invocation
706 pub type lit = spanned<lit_>;
713 lit_int(i64, int_ty),
714 lit_uint(u64, uint_ty),
715 lit_int_unsuffixed(i64),
716 lit_float(@~str, float_ty),
717 lit_float_unsuffixed(@~str),
722 // NB: If you change this, you'll probably want to change the corresponding
723 // type structure in middle/ty.rs as well.
735 pub struct ty_field_ {
740 pub type ty_field = spanned<ty_field_>;
745 pub struct ty_method {
759 // A trait method is either required (meaning it doesn't have an
760 // implementation, just a signature) or provided (meaning it has a default
762 pub enum trait_method {
770 pub enum int_ty { ty_i, ty_char, ty_i8, ty_i16, ty_i32, ty_i64, }
772 impl ToStr for int_ty {
773 fn to_str(&self) -> ~str {
774 ::ast_util::int_ty_to_str(*self)
778 impl to_bytes::IterBytes for int_ty {
779 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
780 (*self as u8).iter_bytes(lsb0, f)
787 pub enum uint_ty { ty_u, ty_u8, ty_u16, ty_u32, ty_u64, }
789 impl ToStr for uint_ty {
790 fn to_str(&self) -> ~str {
791 ::ast_util::uint_ty_to_str(*self)
795 impl to_bytes::IterBytes for uint_ty {
796 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
797 (*self as u8).iter_bytes(lsb0, f)
804 pub enum float_ty { ty_f, ty_f32, ty_f64, }
806 impl ToStr for float_ty {
807 fn to_str(&self) -> ~str {
808 ::ast_util::float_ty_to_str(*self)
812 impl to_bytes::IterBytes for float_ty {
813 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
814 (*self as u8).iter_bytes(lsb0, f)
818 // NB Eq method appears below.
828 // Not represented directly in the AST, referred to by name through a ty_path.
848 impl ToStr for Onceness {
849 fn to_str(&self) -> ~str {
857 impl to_bytes::IterBytes for Onceness {
858 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
859 (*self as uint).iter_bytes(lsb0, f);
866 pub struct TyClosure {
868 region: Option<@Lifetime>,
869 lifetimes: OptVec<Lifetime>,
878 pub struct TyBareFn {
881 lifetimes: OptVec<Lifetime>,
890 ty_bot, /* bottom type */
894 ty_fixed_length_vec(mt, @expr),
896 ty_rptr(Option<@Lifetime>, mt),
897 ty_closure(@TyClosure),
898 ty_bare_fn(@TyBareFn),
900 ty_path(@Path, node_id),
902 // ty_infer means the type should be inferred instead of it having been
903 // specified. This should only appear at the "top level" of a type and not
908 impl to_bytes::IterBytes for Ty {
909 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
910 to_bytes::iter_bytes_2(&self.span.lo, &self.span.hi, lsb0, f);
917 pub enum asm_dialect {
925 pub struct inline_asm {
928 inputs: ~[(@~str, @expr)],
929 outputs: ~[(@~str, @expr)],
958 pure_fn, // declared with "pure fn"
959 unsafe_fn, // declared with "unsafe fn"
960 impure_fn, // declared with "fn"
961 extern_fn, // declared with "extern fn"
964 impl ToStr for purity {
965 fn to_str(&self) -> ~str {
967 impure_fn => ~"impure",
968 unsafe_fn => ~"unsafe",
970 extern_fn => ~"extern"
975 impl to_bytes::IterBytes for purity {
976 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
977 (*self as u8).iter_bytes(lsb0, f)
985 noreturn, // functions with return type _|_ that always
986 // raise an error or exit (i.e. never return to the caller)
987 return_val, // everything else
990 impl to_bytes::IterBytes for ret_style {
991 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
992 (*self as u8).iter_bytes(lsb0, f)
1000 sty_static, // no self
1001 sty_value, // `self`
1002 sty_region(Option<@Lifetime>, mutability), // `&'lt self`
1003 sty_box(mutability), // `@self`
1004 sty_uniq(mutability) // `~self`
1007 pub type self_ty = spanned<self_ty_>;
1014 attrs: ~[attribute],
1030 view_items: ~[@view_item],
1034 // Foreign mods can be named or anonymous
1038 pub enum foreign_mod_sort { named, anonymous }
1043 pub struct foreign_mod {
1044 sort: foreign_mod_sort,
1046 view_items: ~[@view_item],
1047 items: ~[@foreign_item],
1053 pub struct variant_arg {
1061 pub enum variant_kind {
1062 tuple_variant_kind(~[variant_arg]),
1063 struct_variant_kind(@struct_def),
1069 pub struct enum_def {
1070 variants: ~[variant],
1076 pub struct variant_ {
1078 attrs: ~[attribute],
1081 disr_expr: Option<@expr>,
1085 pub type variant = spanned<variant_>;
1090 pub struct path_list_ident_ {
1095 pub type path_list_ident = spanned<path_list_ident_>;
1097 pub type view_path = spanned<view_path_>;
1102 pub enum view_path_ {
1104 // quux = foo::bar::baz
1108 // foo::bar::baz (with 'baz =' implicitly on the left)
1109 view_path_simple(ident, @Path, node_id),
1112 view_path_glob(@Path, node_id),
1114 // foo::bar::{a,b,c}
1115 view_path_list(@Path, ~[path_list_ident], node_id)
1121 pub struct view_item {
1123 attrs: ~[attribute],
1131 pub enum view_item_ {
1132 view_item_extern_mod(ident, ~[@meta_item], node_id),
1133 view_item_use(~[@view_path]),
1136 // Meta-data associated with an item
1137 pub type attribute = spanned<attribute_>;
1139 // Distinguishes between attributes that decorate items and attributes that
1140 // are contained as statements within items. These two cases need to be
1141 // distinguished for pretty-printing.
1145 pub enum attr_style { attr_outer, attr_inner, }
1147 // doc-comments are promoted to attributes that have is_sugared_doc = true
1151 pub struct attribute_ {
1154 is_sugared_doc: bool,
1158 trait_refs appear in impls.
1159 resolve maps each trait_ref's ref_id to its defining trait; that's all
1160 that the ref_id is for. The impl_id maps to the "self type" of this impl.
1161 If this impl is an item_impl, the impl_id is redundant (it could be the
1162 same as the impl's node id).
1167 pub struct trait_ref {
1175 pub enum visibility { public, private, inherited }
1178 fn inherit_from(&self, parent_visibility: visibility) -> visibility {
1180 &inherited => parent_visibility,
1181 &public | &private => *self
1189 pub struct struct_field_ {
1190 kind: struct_field_kind,
1193 attrs: ~[attribute],
1196 pub type struct_field = spanned<struct_field_>;
1201 pub enum struct_field_kind {
1202 named_field(ident, struct_mutability, visibility),
1203 unnamed_field // element of a tuple-like struct
1209 pub struct struct_def {
1210 fields: ~[@struct_field], /* fields, not including ctor */
1211 /* ID of the constructor. This is only used for tuple- or enum-like
1213 ctor_id: Option<node_id>
1217 FIXME (#3300): Should allow items to be anonymous. Right now
1218 we just use dummy names for anon items.
1225 attrs: ~[attribute],
1236 item_const(@Ty, @expr),
1237 item_fn(fn_decl, purity, AbiSet, Generics, blk),
1239 item_foreign_mod(foreign_mod),
1240 item_ty(@Ty, Generics),
1241 item_enum(enum_def, Generics),
1242 item_struct(@struct_def, Generics),
1243 item_trait(Generics, ~[@trait_ref], ~[trait_method]),
1245 Option<@trait_ref>, // (optional) trait this impl implements
1248 // a macro invocation (which includes macro definition)
1255 pub enum struct_mutability { struct_mutable, struct_immutable }
1257 impl to_bytes::IterBytes for struct_mutability {
1258 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
1259 (*self as u8).iter_bytes(lsb0, f)
1266 pub struct foreign_item {
1268 attrs: ~[attribute],
1269 node: foreign_item_,
1278 pub enum foreign_item_ {
1279 foreign_item_fn(fn_decl, purity, Generics),
1280 foreign_item_const(@Ty)
1283 // The data we save and restore about an inlined item or method. This is not
1284 // part of the AST that we parse from a file, but it becomes part of the tree
1289 pub enum inlined_item {
1291 ii_method(def_id /* impl id */, @method),
1292 ii_foreign(@foreign_item),
1295 /* hold off on tests ... they appear in a later merge.
1298 use core::option::{None, Option, Some};
1305 #[test] fn xorpush_test () {
1308 assert_eq!(s,~[14]);
1312 assert_eq!(s,~[14]);
1314 assert_eq!(s,~[14,15]);
1315 xorPush (&mut s,16);
1316 assert_eq! (s,~[14,15,16]);
1317 xorPush (&mut s,16);
1318 assert_eq! (s,~[14,15]);
1319 xorPush (&mut s,15);
1320 assert_eq! (s,~[14]);
1323 #[test] fn test_marksof () {
1324 let stopname = uints_to_name(&~[12,14,78]);
1325 let name1 = uints_to_name(&~[4,9,7]);
1326 assert_eq!(marksof (MT,stopname),~[]);
1327 assert_eq! (marksof (Mark (4,@Mark(98,@MT)),stopname),~[4,98]);
1328 // does xoring work?
1329 assert_eq! (marksof (Mark (5, @Mark (5, @Mark (16,@MT))),stopname),
1331 // does nested xoring work?
1332 assert_eq! (marksof (Mark (5,
1339 // stop has no effect on marks
1340 assert_eq! (marksof (Mark (9, @Mark (14, @Mark (12, @MT))),stopname),
1342 // rename where stop doesn't match:
1343 assert_eq! (marksof (Mark (9, @Rename
1346 uints_to_name(&~[100,101,102]),
1350 // rename where stop does match
1352 assert_eq! (marksof (Mark(9, @Rename (name1,
1360 // are ASTs encodable?
1361 #[test] fn check_asts_encodable() {
1362 let bogus_span = span {lo:BytePos(10),
1368 module: _mod {view_items: ~[], items: ~[]},
1373 // doesn't matter which encoder we use....
1374 let _f = (@e as @std::serialize::Encodable<std::json::Encoder>);