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