(index<- )        ./libsyntax/ast_util.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Fri May  9 13:02:28 2014
   1  // Copyright 2012-2014 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.
   4  //
   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.
  10  
  11  use ast::*;
  12  use ast;
  13  use ast_util;
  14  use codemap;
  15  use codemap::Span;
  16  use owned_slice::OwnedSlice;
  17  use parse::token;
  18  use print::pprust;
  19  use visit::Visitor;
  20  use visit;
  21  
  22  use std::cell::Cell;
  23  use std::cmp;
  24  use std::strbuf::StrBuf;
  25  use std::u32;
  26  
  27  pub fn path_name_i(idents: &[Ident]) -> StrBuf {
  28      // FIXME: Bad copies (#2543 -- same for everything else that says "bad")
  29      idents.iter().map(|i| {
  30          token::get_ident(*i).get().to_strbuf()
  31      }).collect::<Vec<StrBuf>>().connect("::").to_strbuf()
  32  }
  33  
  34  // totally scary function: ignores all but the last element, should have
  35  // a different name
  36  pub fn path_to_ident(path: &Path) -> Ident {
  37      path.segments.last().unwrap().identifier
  38  }
  39  
  40  pub fn local_def(idNodeId) -> DefId {
  41      ast::DefId { krate: LOCAL_CRATE, node: id }
  42  }
  43  
  44  pub fn is_local(didast::DefId) -> bool { did.krate == LOCAL_CRATE }
  45  
  46  pub fn stmt_id(s: &Stmt) -> NodeId {
  47      match s.node {
  48        StmtDecl(_, id) => id,
  49        StmtExpr(_, id) => id,
  50        StmtSemi(_, id) => id,
  51        StmtMac(..) => fail!("attempted to analyze unexpanded stmt")
  52      }
  53  }
  54  
  55  pub fn variant_def_ids(dDef) -> Option<(DefId, DefId)> {
  56      match d {
  57        DefVariant(enum_id, var_id, _) => {
  58            Some((enum_id, var_id))
  59        }
  60        _ => None
  61      }
  62  }
  63  
  64  pub fn def_id_of_def(dDef) -> DefId {
  65      match d {
  66          DefFn(id, _) | DefStaticMethod(id, _, _) | DefMod(id) |
  67          DefForeignMod(id) | DefStatic(id, _) |
  68          DefVariant(_, id, _) | DefTy(id) | DefTyParam(id, _) |
  69          DefUse(id) | DefStruct(id) | DefTrait(id) | DefMethod(id, _) => {
  70              id
  71          }
  72          DefArg(id, _) | DefLocal(id, _) | DefSelfTy(id)
  73          | DefUpvar(id, _, _, _) | DefBinding(id, _) | DefRegion(id)
  74          | DefTyParamBinder(id) | DefLabel(id) => {
  75              local_def(id)
  76          }
  77  
  78          DefPrimTy(_) => fail!()
  79      }
  80  }
  81  
  82  pub fn binop_to_str(opBinOp) -> &'static str {
  83      match op {
  84          BiAdd => "+",
  85          BiSub => "-",
  86          BiMul => "*",
  87          BiDiv => "/",
  88          BiRem => "%",
  89          BiAnd => "&&",
  90          BiOr => "||",
  91          BiBitXor => "^",
  92          BiBitAnd => "&",
  93          BiBitOr => "|",
  94          BiShl => "<<",
  95          BiShr => ">>",
  96          BiEq => "==",
  97          BiLt => "<",
  98          BiLe => "<=",
  99          BiNe => "!=",
 100          BiGe => ">=",
 101          BiGt => ">"
 102      }
 103  }
 104  
 105  pub fn lazy_binop(bBinOp) -> bool {
 106      match b {
 107        BiAnd => true,
 108        BiOr => true,
 109        _ => false
 110      }
 111  }
 112  
 113  pub fn is_shift_binop(bBinOp) -> bool {
 114      match b {
 115        BiShl => true,
 116        BiShr => true,
 117        _ => false
 118      }
 119  }
 120  
 121  pub fn unop_to_str(opUnOp) -> &'static str {
 122      match op {
 123        UnBox => "@",
 124        UnUniq => "box() ",
 125        UnDeref => "*",
 126        UnNot => "!",
 127        UnNeg => "-",
 128      }
 129  }
 130  
 131  pub fn is_path(e: @Expr) -> bool {
 132      return match e.node { ExprPath(_) => true, _ => false };
 133  }
 134  
 135  // Get a string representation of a signed int type, with its value.
 136  // We want to avoid "45int" and "-3int" in favor of "45" and "-3"
 137  pub fn int_ty_to_str(tIntTy, valOption<i64>) -> StrBuf {
 138      let s = match t {
 139          TyI if val.is_some() => "",
 140          TyI => "int",
 141          TyI8 => "i8",
 142          TyI16 => "i16",
 143          TyI32 => "i32",
 144          TyI64 => "i64"
 145      };
 146  
 147      match val {
 148          Some(n) => format!("{}{}", n, s).to_strbuf(),
 149          None => s.to_strbuf()
 150      }
 151  }
 152  
 153  pub fn int_ty_max(tIntTy) -> u64 {
 154      match t {
 155          TyI8 => 0x80u64,
 156          TyI16 => 0x8000u64,
 157          TyI | TyI32 => 0x80000000u64, // actually ni about TyI
 158          TyI64 => 0x8000000000000000u64
 159      }
 160  }
 161  
 162  // Get a string representation of an unsigned int type, with its value.
 163  // We want to avoid "42uint" in favor of "42u"
 164  pub fn uint_ty_to_str(tUintTy, valOption<u64>) -> StrBuf {
 165      let s = match t {
 166          TyU if val.is_some() => "u",
 167          TyU => "uint",
 168          TyU8 => "u8",
 169          TyU16 => "u16",
 170          TyU32 => "u32",
 171          TyU64 => "u64"
 172      };
 173  
 174      match val {
 175          Some(n) => format!("{}{}", n, s).to_strbuf(),
 176          None => s.to_strbuf()
 177      }
 178  }
 179  
 180  pub fn uint_ty_max(tUintTy) -> u64 {
 181      match t {
 182          TyU8 => 0xffu64,
 183          TyU16 => 0xffffu64,
 184          TyU | TyU32 => 0xffffffffu64, // actually ni about TyU
 185          TyU64 => 0xffffffffffffffffu64
 186      }
 187  }
 188  
 189  pub fn float_ty_to_str(tFloatTy) -> StrBuf {
 190      match t {
 191          TyF32 => "f32".to_strbuf(),
 192          TyF64 => "f64".to_strbuf(),
 193          TyF128 => "f128".to_strbuf(),
 194      }
 195  }
 196  
 197  pub fn is_call_expr(e: @Expr) -> bool {
 198      match e.node { ExprCall(..) => true, _ => false }
 199  }
 200  
 201  pub fn block_from_expr(e: @Expr) -> P<Block> {
 202      P(Block {
 203          view_items: Vec::new(),
 204          stmts: Vec::new(),
 205          expr: Some(e),
 206          id: e.id,
 207          rules: DefaultBlock,
 208          span: e.span
 209      })
 210  }
 211  
 212  pub fn ident_to_path(sSpan, identifierIdent) -> Path {
 213      ast::Path {
 214          span: s,
 215          global: false,
 216          segments: vec!(
 217              ast::PathSegment {
 218                  identifier: identifier,
 219                  lifetimes: Vec::new(),
 220                  types: OwnedSlice::empty(),
 221              }
 222          ),
 223      }
 224  }
 225  
 226  pub fn ident_to_pat(idNodeId, sSpan, iIdent) -> @Pat {
 227      @ast::Pat { id: id,
 228                  node: PatIdent(BindByValue(MutImmutable), ident_to_path(s, i), None),
 229                  span: s }
 230  }
 231  
 232  pub fn name_to_dummy_lifetime(nameName) -> Lifetime {
 233      Lifetime { id: DUMMY_NODE_ID,
 234                 span: codemap::DUMMY_SP,
 235                 name: name }
 236  }
 237  
 238  pub fn is_unguarded(a: &Arm) -> bool {
 239      match a.guard {
 240        None => true,
 241        _    => false
 242      }
 243  }
 244  
 245  pub fn unguarded_pat(a: &Arm) -> Option<Vec<@Pat> > {
 246      if is_unguarded(a) {
 247          Some(/* FIXME (#2543) */ a.pats.clone())
 248      } else {
 249          None
 250      }
 251  }
 252  
 253  /// Generate a "pretty" name for an `impl` from its type and trait.
 254  /// This is designed so that symbols of `impl`'d methods give some
 255  /// hint of where they came from, (previously they would all just be
 256  /// listed as `__extensions__::method_name::hash`, with no indication
 257  /// of the type).
 258  pub fn impl_pretty_name(trait_ref: &Option<TraitRef>, ty: &Ty) -> Ident {
 259      let mut pretty = pprust::ty_to_str(ty);
 260      match *trait_ref {
 261          Some(ref trait_ref) => {
 262              pretty.push_char('.');
 263              pretty.push_str(pprust::path_to_str(&trait_ref.path).as_slice());
 264          }
 265          None => {}
 266      }
 267      token::gensym_ident(pretty.as_slice())
 268  }
 269  
 270  pub fn public_methods(msVec<@Method> ) -> Vec<@Method> {
 271      ms.move_iter().filter(|m| {
 272          match m.vis {
 273              Public => true,
 274              _   => false
 275          }
 276      }).collect()
 277  }
 278  
 279  // extract a TypeMethod from a TraitMethod. if the TraitMethod is
 280  // a default, pull out the useful fields to make a TypeMethod
 281  pub fn trait_method_to_ty_method(method: &TraitMethod) -> TypeMethod {
 282      match *method {
 283          Required(ref m) => (*m).clone(),
 284          Provided(ref m) => {
 285              TypeMethod {
 286                  ident: m.ident,
 287                  attrs: m.attrs.clone(),
 288                  fn_style: m.fn_style,
 289                  decl: m.decl,
 290                  generics: m.generics.clone(),
 291                  explicit_self: m.explicit_self,
 292                  id: m.id,
 293                  span: m.span,
 294              }
 295          }
 296      }
 297  }
 298  
 299  pub fn split_trait_methods(trait_methods: &[TraitMethod])
 300      -> (Vec<TypeMethod> , Vec<@Method> ) {
 301      let mut reqd = Vec::new();
 302      let mut provd = Vec::new();
 303      for trt_method in trait_methods.iter() {
 304          match *trt_method {
 305              Required(ref tm) => reqd.push((*tm).clone()),
 306              Provided(m) => provd.push(m)
 307          }
 308      };
 309      (reqd, provd)
 310  }
 311  
 312  pub fn struct_field_visibility(fieldast::StructField) -> Visibility {
 313      match field.node.kind {
 314          ast::NamedField(_, v) | ast::UnnamedField(v) => v
 315      }
 316  }
 317  
 318  /// Maps a binary operator to its precedence
 319  pub fn operator_prec(opast::BinOp) -> uint {
 320    match op {
 321        // 'as' sits here with 12
 322        BiMul | BiDiv | BiRem     => 11u,
 323        BiAdd | BiSub             => 10u,
 324        BiShl | BiShr             =>  9u,
 325        BiBitAnd                  =>  8u,
 326        BiBitXor                  =>  7u,
 327        BiBitOr                   =>  6u,
 328        BiLt | BiLe | BiGe | BiGt =>  4u,
 329        BiEq | BiNe               =>  3u,
 330        BiAnd                     =>  2u,
 331        BiOr                      =>  1u
 332    }
 333  }
 334  
 335  /// Precedence of the `as` operator, which is a binary operator
 336  /// not appearing in the prior table.
 337  pub static as_prec: uint = 12u;
 338  
 339  pub fn empty_generics() -> Generics {
 340      Generics {lifetimes: Vec::new(),
 341                ty_params: OwnedSlice::empty()}
 342  }
 343  
 344  // ______________________________________________________________________
 345  // Enumerating the IDs which appear in an AST
 346  
 347  #[deriving(Encodable, Decodable)]
 348  pub struct IdRange {
 349      pub min: NodeId,
 350      pub max: NodeId,
 351  }
 352  
 353  impl IdRange {
 354      pub fn max() -> IdRange {
 355          IdRange {
 356              min: u32::MAX,
 357              max: u32::MIN,
 358          }
 359      }
 360  
 361      pub fn empty(&self) -> bool {
 362          self.min >= self.max
 363      }
 364  
 365      pub fn add(&mut self, idNodeId) {
 366          self.min = cmp::min(self.min, id);
 367          self.max = cmp::max(self.max, id + 1);
 368      }
 369  }
 370  
 371  pub trait IdVisitingOperation {
 372      fn visit_id(&self, node_id: NodeId);
 373  }
 374  
 375  pub struct IdVisitor<'a, O> {
 376      pub operation: &'a O,
 377      pub pass_through_items: bool,
 378      pub visited_outermost: bool,
 379  }
 380  
 381  impl<'a, O: IdVisitingOperation> IdVisitor<'a, O> {
 382      fn visit_generics_helper(&self, generics&Generics) {
 383          for type_parameter in generics.ty_params.iter() {
 384              self.operation.visit_id(type_parameter.id)
 385          }
 386          for lifetime in generics.lifetimes.iter() {
 387              self.operation.visit_id(lifetime.id)
 388          }
 389      }
 390  }
 391  
 392  impl<'a, O: IdVisitingOperation> Visitor<()> for IdVisitor<'a, O> {
 393      fn visit_mod(&mut self,
 394                   module&Mod,
 395                   _Span,
 396                   node_idNodeId,
 397                   env()) {
 398          self.operation.visit_id(node_id);
 399          visit::walk_mod(self, module, env)
 400      }
 401  
 402      fn visit_view_item(&mut self, view_item&ViewItem, env()) {
 403          if !self.pass_through_items {
 404              if self.visited_outermost {
 405                  return;
 406              } else {
 407                  self.visited_outermost = true;
 408              }
 409          }
 410          match view_item.node {
 411              ViewItemExternCrate(_, _, node_id) => {
 412                  self.operation.visit_id(node_id)
 413              }
 414              ViewItemUse(ref view_path) => {
 415                  match view_path.node {
 416                      ViewPathSimple(_, _, node_id) |
 417                      ViewPathGlob(_, node_id) => {
 418                          self.operation.visit_id(node_id)
 419                      }
 420                      ViewPathList(_, ref paths, node_id) => {
 421                          self.operation.visit_id(node_id);
 422                          for path in paths.iter() {
 423                              self.operation.visit_id(path.node.id)
 424                          }
 425                      }
 426                  }
 427              }
 428          }
 429          visit::walk_view_item(self, view_item, env);
 430          self.visited_outermost = false;
 431      }
 432  
 433      fn visit_foreign_item(&mut self, foreign_item&ForeignItem, env()) {
 434          self.operation.visit_id(foreign_item.id);
 435          visit::walk_foreign_item(self, foreign_item, env)
 436      }
 437  
 438      fn visit_item(&mut self, item&Item, env()) {
 439          if !self.pass_through_items {
 440              if self.visited_outermost {
 441                  return
 442              } else {
 443                  self.visited_outermost = true
 444              }
 445          }
 446  
 447          self.operation.visit_id(item.id);
 448          match item.node {
 449              ItemEnum(ref enum_definition, _) => {
 450                  for variant in enum_definition.variants.iter() {
 451                      self.operation.visit_id(variant.node.id)
 452                  }
 453              }
 454              _ => {}
 455          }
 456  
 457          visit::walk_item(self, item, env);
 458  
 459          self.visited_outermost = false
 460      }
 461  
 462      fn visit_local(&mut self, local&Local, env()) {
 463          self.operation.visit_id(local.id);
 464          visit::walk_local(self, local, env)
 465      }
 466  
 467      fn visit_block(&mut self, block&Block, env()) {
 468          self.operation.visit_id(block.id);
 469          visit::walk_block(self, block, env)
 470      }
 471  
 472      fn visit_stmt(&mut self, statement&Stmt, env()) {
 473          self.operation.visit_id(ast_util::stmt_id(statement));
 474          visit::walk_stmt(self, statement, env)
 475      }
 476  
 477      fn visit_pat(&mut self, pattern&Pat, env()) {
 478          self.operation.visit_id(pattern.id);
 479          visit::walk_pat(self, pattern, env)
 480      }
 481  
 482      fn visit_expr(&mut self, expression&Expr, env()) {
 483          self.operation.visit_id(expression.id);
 484          visit::walk_expr(self, expression, env)
 485      }
 486  
 487      fn visit_ty(&mut self, typ&Ty, env()) {
 488          self.operation.visit_id(typ.id);
 489          match typ.node {
 490              TyPath(_, _, id) => self.operation.visit_id(id),
 491              _ => {}
 492          }
 493          visit::walk_ty(self, typ, env)
 494      }
 495  
 496      fn visit_generics(&mut self, generics&Generics, env()) {
 497          self.visit_generics_helper(generics);
 498          visit::walk_generics(self, generics, env)
 499      }
 500  
 501      fn visit_fn(&mut self,
 502                  function_kind&visit::FnKind,
 503                  function_declaration&FnDecl,
 504                  block&Block,
 505                  spanSpan,
 506                  node_idNodeId,
 507                  env()) {
 508          if !self.pass_through_items {
 509              match *function_kind {
 510                  visit::FkMethod(..) if self.visited_outermost => return,
 511                  visit::FkMethod(..) => self.visited_outermost = true,
 512                  _ => {}
 513              }
 514          }
 515  
 516          self.operation.visit_id(node_id);
 517  
 518          match *function_kind {
 519              visit::FkItemFn(_, generics, _, _) |
 520              visit::FkMethod(_, generics, _) => {
 521                  self.visit_generics_helper(generics)
 522              }
 523              visit::FkFnBlock => {}
 524          }
 525  
 526          for argument in function_declaration.inputs.iter() {
 527              self.operation.visit_id(argument.id)
 528          }
 529  
 530          visit::walk_fn(self,
 531                          function_kind,
 532                          function_declaration,
 533                          block,
 534                          span,
 535                          node_id,
 536                          env);
 537  
 538          if !self.pass_through_items {
 539              match *function_kind {
 540                  visit::FkMethod(..) => self.visited_outermost = false,
 541                  _ => {}
 542              }
 543          }
 544      }
 545  
 546      fn visit_struct_field(&mut self, struct_field&StructField, env()) {
 547          self.operation.visit_id(struct_field.node.id);
 548          visit::walk_struct_field(self, struct_field, env)
 549      }
 550  
 551      fn visit_struct_def(&mut self,
 552                          struct_def&StructDef,
 553                          identast::Ident,
 554                          generics&ast::Generics,
 555                          idNodeId,
 556                          _()) {
 557          self.operation.visit_id(id);
 558          struct_def.ctor_id.map(|ctor_id| self.operation.visit_id(ctor_id));
 559          visit::walk_struct_def(self, struct_def, ident, generics, id, ());
 560      }
 561  
 562      fn visit_trait_method(&mut self, tm&ast::TraitMethod, _()) {
 563          match *tm {
 564              ast::Required(ref m) => self.operation.visit_id(m.id),
 565              ast::Provided(ref m) => self.operation.visit_id(m.id),
 566          }
 567          visit::walk_trait_method(self, tm, ());
 568      }
 569  }
 570  
 571  pub fn visit_ids_for_inlined_item<O: IdVisitingOperation>(item: &InlinedItem,
 572                                                            operation: &O) {
 573      let mut id_visitor = IdVisitor {
 574          operation: operation,
 575          pass_through_items: true,
 576          visited_outermost: false,
 577      };
 578  
 579      visit::walk_inlined_item(&mut id_visitor, item, ());
 580  }
 581  
 582  struct IdRangeComputingVisitor {
 583      result: Cell<IdRange>,
 584  }
 585  
 586  impl IdVisitingOperation for IdRangeComputingVisitor {
 587      fn visit_id(&self, idNodeId) {
 588          let mut id_range = self.result.get();
 589          id_range.add(id);
 590          self.result.set(id_range)
 591      }
 592  }
 593  
 594  pub fn compute_id_range_for_inlined_item(item: &InlinedItem) -> IdRange {
 595      let visitor = IdRangeComputingVisitor {
 596          result: Cell::new(IdRange::max())
 597      };
 598      visit_ids_for_inlined_item(item, &visitor);
 599      visitor.result.get()
 600  }
 601  
 602  pub fn compute_id_range_for_fn_body(fk: &visit::FnKind,
 603                                      decl: &FnDecl,
 604                                      body: &Block,
 605                                      spSpan,
 606                                      idNodeId)
 607                                      -> IdRange
 608  {
 609      /*!
 610       * Computes the id range for a single fn body,
 611       * ignoring nested items.
 612       */
 613  
 614      let visitor = IdRangeComputingVisitor {
 615          result: Cell::new(IdRange::max())
 616      };
 617      let mut id_visitor = IdVisitor {
 618          operation: &visitor,
 619          pass_through_items: false,
 620          visited_outermost: false,
 621      };
 622      id_visitor.visit_fn(fk, decl, body, sp, id, ());
 623      visitor.result.get()
 624  }
 625  
 626  pub fn is_item_impl(item: @ast::Item) -> bool {
 627      match item.node {
 628          ItemImpl(..) => true,
 629          _            => false
 630      }
 631  }
 632  
 633  pub fn walk_pat(pat: &Pat, it: |&Pat-> bool) -> bool {
 634      if !it(pat) {
 635          return false;
 636      }
 637  
 638      match pat.node {
 639          PatIdent(_, _, Some(p)) => walk_pat(p, it),
 640          PatStruct(_, ref fields, _) => {
 641              fields.iter().advance(|f| walk_pat(f.pat, |p| it(p)))
 642          }
 643          PatEnum(_, Some(ref s)) | PatTup(ref s) => {
 644              s.iter().advance(|&p| walk_pat(p, |p| it(p)))
 645          }
 646          PatUniq(s) | PatRegion(s) => {
 647              walk_pat(s, it)
 648          }
 649          PatVec(ref before, ref slice, ref after) => {
 650              before.iter().advance(|&p| walk_pat(p, |p| it(p))) &&
 651                  slice.iter().advance(|&p| walk_pat(p, |p| it(p))) &&
 652                  after.iter().advance(|&p| walk_pat(p, |p| it(p)))
 653          }
 654          PatWild | PatWildMulti | PatLit(_) | PatRange(_, _) | PatIdent(_, _, _) |
 655          PatEnum(_, _) => {
 656              true
 657          }
 658      }
 659  }
 660  
 661  pub trait EachViewItem {
 662      fn each_view_item(&self, f: |&ast::ViewItem-> bool) -> bool;
 663  }
 664  
 665  struct EachViewItemData<'a> {
 666      callback: |&ast::ViewItem|: 'a -> bool,
 667  }
 668  
 669  impl<'a> Visitor<()> for EachViewItemData<'a> {
 670      fn visit_view_item(&mut self, view_item&ast::ViewItem, _()) {
 671          let _ = (self.callback)(view_item);
 672      }
 673  }
 674  
 675  impl EachViewItem for ast::Crate {
 676      fn each_view_item(&self, f|&ast::ViewItem-> bool) -> bool {
 677          let mut visit = EachViewItemData {
 678              callback: f,
 679          };
 680          visit::walk_crate(&mut visit, self, ());
 681          true
 682      }
 683  }
 684  
 685  pub fn view_path_id(p: &ViewPath) -> NodeId {
 686      match p.node {
 687          ViewPathSimple(_, _, id) | ViewPathGlob(_, id)
 688          | ViewPathList(_, _, id) => id
 689      }
 690  }
 691  
 692  /// Returns true if the given struct def is tuple-like; i.e. that its fields
 693  /// are unnamed.
 694  pub fn struct_def_is_tuple_like(struct_def: &ast::StructDef) -> bool {
 695      struct_def.ctor_id.is_some()
 696  }
 697  
 698  /// Returns true if the given pattern consists solely of an identifier
 699  /// and false otherwise.
 700  pub fn pat_is_ident(pat: @ast::Pat) -> bool {
 701      match pat.node {
 702          ast::PatIdent(..) => true,
 703          _ => false,
 704      }
 705  }
 706  
 707  // are two paths equal when compared unhygienically?
 708  // since I'm using this to replace ==, it seems appropriate
 709  // to compare the span, global, etc. fields as well.
 710  pub fn path_name_eq(a : &ast::Path, b : &ast::Path) -> bool {
 711      (a.span == b.span)
 712      && (a.global == b.global)
 713      && (segments_name_eq(a.segments.as_slice(), b.segments.as_slice()))
 714  }
 715  
 716  // are two arrays of segments equal when compared unhygienically?
 717  pub fn segments_name_eq(a : &[ast::PathSegment], b : &[ast::PathSegment]) -> bool {
 718      if a.len() != b.len() {
 719          false
 720      } else {
 721          for (idx,seg) in a.iter().enumerate() {
 722              if (seg.identifier.name != b[idx].identifier.name)
 723                  // FIXME #7743: ident -> name problems in lifetime comparison?
 724                  || (seg.lifetimes != b[idx].lifetimes)
 725                  // can types contain idents?
 726                  || (seg.types != b[idx].types) {
 727                  return false;
 728              }
 729          }
 730          true
 731      }
 732  }
 733  
 734  // Returns true if this literal is a string and false otherwise.
 735  pub fn lit_is_str(lit: @Lit) -> bool {
 736      match lit.node {
 737          LitStr(..) => true,
 738          _ => false,
 739      }
 740  }
 741  
 742  pub fn get_inner_tys(tyP<Ty>) -> Vec<P<Ty>> {
 743      match ty.node {
 744          ast::TyRptr(_, mut_ty) | ast::TyPtr(mut_ty) => {
 745              vec!(mut_ty.ty)
 746          }
 747          ast::TyBox(ty)
 748          | ast::TyVec(ty)
 749          | ast::TyUniq(ty)
 750          | ast::TyFixedLengthVec(ty, _) => vec!(ty),
 751          ast::TyTup(ref tys) => tys.clone(),
 752          _ => Vec::new()
 753      }
 754  }
 755  
 756  
 757  #[cfg(test)]
 758  mod test {
 759      use ast::*;
 760      use super::*;
 761      use owned_slice::OwnedSlice;
 762  
 763      fn ident_to_segment(id : &Ident) -> PathSegment {
 764          PathSegment {identifier:id.clone(),
 765                       lifetimes: Vec::new(),
 766                       types: OwnedSlice::empty()}
 767      }
 768  
 769      #[test] fn idents_name_eq_test() {
 770          assert!(segments_name_eq(
 771              [Ident{name:3,ctxt:4}, Ident{name:78,ctxt:82}]
 772                  .iter().map(ident_to_segment).collect::<Vec<PathSegment>>().as_slice(),
 773              [Ident{name:3,ctxt:104}, Ident{name:78,ctxt:182}]
 774                  .iter().map(ident_to_segment).collect::<Vec<PathSegment>>().as_slice()));
 775          assert!(!segments_name_eq(
 776              [Ident{name:3,ctxt:4}, Ident{name:78,ctxt:82}]
 777                  .iter().map(ident_to_segment).collect::<Vec<PathSegment>>().as_slice(),
 778              [Ident{name:3,ctxt:104}, Ident{name:77,ctxt:182}]
 779                  .iter().map(ident_to_segment).collect::<Vec<PathSegment>>().as_slice()));
 780      }
 781  }


libsyntax/ast_util.rs:81:1-81:1 -fn- definition:
pub fn binop_to_str(op: BinOp) -> &'static str {
    match op {
        BiAdd => "+",
references:- 2
libsyntax/print/pprust.rs:
1230:                 try!(space(&mut self.s));
1231:                 try!(self.word_space(ast_util::binop_to_str(op)));
1232:                 try!(self.print_expr(rhs));
--
1416:                 try!(space(&mut self.s));
1417:                 try!(word(&mut self.s, ast_util::binop_to_str(op)));
1418:                 try!(self.word_space("="));


libsyntax/ast_util.rs:632:1-632:1 -fn- definition:
pub fn walk_pat(pat: &Pat, it: |&Pat| -> bool) -> bool {
    if !it(pat) {
        return false;
references:- 7
640:         PatStruct(_, ref fields, _) => {
641:             fields.iter().advance(|f| walk_pat(f.pat, |p| it(p)))
642:         }
--
650:             before.iter().advance(|&p| walk_pat(p, |p| it(p))) &&
651:                 slice.iter().advance(|&p| walk_pat(p, |p| it(p))) &&
652:                 after.iter().advance(|&p| walk_pat(p, |p| it(p)))
653:         }


libsyntax/ast_util.rs:581:1-581:1 -struct- definition:
struct IdRangeComputingVisitor {
    result: Cell<IdRange>,
}
references:- 3
594: pub fn compute_id_range_for_inlined_item(item: &InlinedItem) -> IdRange {
595:     let visitor = IdRangeComputingVisitor {
596:         result: Cell::new(IdRange::max())
--
614:     let visitor = IdRangeComputingVisitor {
615:         result: Cell::new(IdRange::max())


libsyntax/ast_util.rs:188:1-188:1 -fn- definition:
pub fn float_ty_to_str(t: FloatTy) -> StrBuf {
    match t {
        TyF32 => "f32".to_strbuf(),
references:- 3
libsyntax/print/pprust.rs:
2224:                 word(&mut self.s,
2225:                      f.get() + ast_util::float_ty_to_str(t).as_slice())
2226:             }
libsyntax/ast.rs:
741:     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
742:         write!(f.buf, "{}", ast_util::float_ty_to_str(*self))
743:     }
libsyntax/parse/token.rs:
213:         }
214:         body.push_str(ast_util::float_ty_to_str(t).as_slice());
215:         body


libsyntax/ast_util.rs:39:1-39:1 -fn- definition:
pub fn local_def(id: NodeId) -> DefId {
    ast::DefId { krate: LOCAL_CRATE, node: id }
}
references:- 2
libsyntax/ast_map.rs:
230:             Some(RootInlinedParent(data)) => data.def_id,
231:             _ => ast_util::local_def(parent)
232:         }
libsyntax/ast_util.rs:
74:         | DefTyParamBinder(id) | DefLabel(id) => {
75:             local_def(id)
76:         }


libsyntax/ast_util.rs:257:18-257:18 -fn- definition:
/// of the type).
pub fn impl_pretty_name(trait_ref: &Option<TraitRef>, ty: &Ty) -> Ident {
    let mut pretty = pprust::ty_to_str(ty);
references:- 3
libsyntax/parse/parser.rs:
3902:         let ident = ast_util::impl_pretty_name(&opt_trait, ty);
libsyntax/ext/deriving/generic.rs:
419:         let opt_trait_ref = Some(trait_ref);
420:         let ident = ast_util::impl_pretty_name(&opt_trait_ref, self_type);
421:         cx.item(
libsyntax/fold.rs:
678:         ItemImpl(_, ref maybe_trait, ty, _) => {
679:             ast_util::impl_pretty_name(maybe_trait, ty)
680:         }


libsyntax/ast_util.rs:338:1-338:1 -fn- definition:
pub fn empty_generics() -> Generics {
    Generics {lifetimes: Vec::new(),
              ty_params: OwnedSlice::empty()}
references:- 6
libsyntax/print/pprust.rs:
884:                 try!(self.head(""));
885:                 let generics = ast_util::empty_generics();
886:                 try!(self.print_struct(struct_def, &generics, v.node.name, v.span));
libsyntax/ext/build.rs:
855:             output,
856:             ast_util::empty_generics(),
857:             body)
--
893:             struct_def,
894:             ast_util::empty_generics()
895:         )
--
924:     fn item_ty(&self, span: Span, name: Ident, ty: P<ast::Ty>) -> @ast::Item {
925:         self.item_ty_poly(span, name, ty, ast_util::empty_generics())
926:     }
libsyntax/parse/parser.rs:
3472:         } else {
3473:             ast_util::empty_generics()
3474:         }


libsyntax/ast_util.rs:664:1-664:1 -struct- definition:
struct EachViewItemData<'a> {
    callback: |&ast::ViewItem|: 'a -> bool,
}
references:- 2
669: impl<'a> Visitor<()> for EachViewItemData<'a> {
670:     fn visit_view_item(&mut self, view_item: &ast::ViewItem, _: ()) {
--
676:     fn each_view_item(&self, f: |&ast::ViewItem| -> bool) -> bool {
677:         let mut visit = EachViewItemData {
678:             callback: f,


libsyntax/ast_util.rs:211:1-211:1 -fn- definition:
pub fn ident_to_path(s: Span, identifier: Ident) -> Path {
    ast::Path {
        span: s,
references:- 4
227:     @ast::Pat { id: id,
228:                 node: PatIdent(BindByValue(MutImmutable), ident_to_path(s, i), None),
229:                 span: s }
libsyntax/parse/parser.rs:
1776:         } else if self.eat_keyword(keywords::Self) {
1777:             let path = ast_util::ident_to_path(mk_sp(lo, hi), special_idents::self_);
1778:             ex = ExprPath(path);
--
2750:             } else {
2751:                 let fieldpath = ast_util::ident_to_path(self.last_span,
2752:                                                         fieldname);
libsyntax/ast.rs:
848:     pub fn new_self(span: Span, mutability: Mutability) -> Arg {
849:         let path = ast_util::ident_to_path(span, special_idents::self_);
850:         Arg {


libsyntax/ast_util.rs:45:1-45:1 -fn- definition:
pub fn stmt_id(s: &Stmt) -> NodeId {
    match s.node {
      StmtDecl(_, id) => id,
references:- 2
libsyntax/ast_map.rs:
531:         let stmt = fold::noop_fold_stmt(stmt, self).expect_one("expected one statement");
532:         self.insert(ast_util::stmt_id(stmt), EntryStmt(self.parent, stmt));
533:         SmallVector::one(stmt)
libsyntax/ast_util.rs:
472:     fn visit_stmt(&mut self, statement: &Stmt, env: ()) {
473:         self.operation.visit_id(ast_util::stmt_id(statement));
474:         visit::walk_stmt(self, statement, env)


libsyntax/ast_util.rs:136:66-136:66 -fn- definition:
// We want to avoid "45int" and "-3int" in favor of "45" and "-3"
pub fn int_ty_to_str(t: IntTy, val: Option<i64>) -> StrBuf {
    let s = match t {
references:- 3
libsyntax/parse/token.rs:
205:       }
206:       LIT_INT(i, t) => ast_util::int_ty_to_str(t, Some(i)),
207:       LIT_UINT(u, t) => ast_util::uint_ty_to_str(t, Some(u)),
libsyntax/print/pprust.rs:
2213:                 word(&mut self.s,
2214:                      ast_util::int_ty_to_str(t, Some(i)).as_slice())
2215:             }
libsyntax/ast.rs:
713:     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
714:         write!(f.buf, "{}", ast_util::int_ty_to_str(*self, None))
715:     }


libsyntax/ast_util.rs:374:1-374:1 -struct- definition:
pub struct IdVisitor<'a, O> {
    pub operation: &'a O,
    pub pass_through_items: bool,
references:- 4
572:                                                           operation: &O) {
573:     let mut id_visitor = IdVisitor {
574:         operation: operation,
--
616:     };
617:     let mut id_visitor = IdVisitor {
618:         operation: &visitor,


libsyntax/ast_util.rs:163:47-163:47 -fn- definition:
// We want to avoid "42uint" in favor of "42u"
pub fn uint_ty_to_str(t: UintTy, val: Option<u64>) -> StrBuf {
    let s = match t {
references:- 3
libsyntax/parse/token.rs:
206:       LIT_INT(i, t) => ast_util::int_ty_to_str(t, Some(i)),
207:       LIT_UINT(u, t) => ast_util::uint_ty_to_str(t, Some(u)),
208:       LIT_INT_UNSUFFIXED(i) => { i.to_str().to_strbuf() }
libsyntax/ast.rs:
728:     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
729:         write!(f.buf, "{}", ast_util::uint_ty_to_str(*self, None))
730:     }
libsyntax/print/pprust.rs:
2217:                 word(&mut self.s,
2218:                      ast_util::uint_ty_to_str(t, Some(u)).as_slice())
2219:             }


libsyntax/ast_util.rs:347:34-347:34 -struct- definition:
pub struct IdRange {
    pub min: NodeId,
    pub max: NodeId,
references:- 11
354:     pub fn max() -> IdRange {
355:         IdRange {
356:             min: u32::MAX,
--
606:                                     id: NodeId)
607:                                     -> IdRange
608: {


libsyntax/ast_util.rs:734:65-734:65 -fn- definition:
// Returns true if this literal is a string and false otherwise.
pub fn lit_is_str(lit: @Lit) -> bool {
    match lit.node {
references:- 4
libsyntax/parse/parser.rs:
2315:                 }
2316:                 ExprLit(lit) if lit_is_str(lit) => {
2317:                     ExprVstore(subexpression, ExprVstoreUniq)


libsyntax/ast_util.rs:370:1-370:1 -trait- definition:
pub trait IdVisitingOperation {
    fn visit_id(&self, node_id: NodeId);
}
references:- 4
381: impl<'a, O: IdVisitingOperation> IdVisitor<'a, O> {
382:     fn visit_generics_helper(&self, generics: &Generics) {
--
571: pub fn visit_ids_for_inlined_item<O: IdVisitingOperation>(item: &InlinedItem,
572:                                                           operation: &O) {
--
586: impl IdVisitingOperation for IdRangeComputingVisitor {
587:     fn visit_id(&self, id: NodeId) {