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