]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/rust/ast/rust-ast-full-test.cc
Update copyright years.
[thirdparty/gcc.git] / gcc / rust / ast / rust-ast-full-test.cc
1 /* General AST-related method implementations for Rust frontend.
2 Copyright (C) 2009-2023 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
19
20 #include "rust-system.h"
21 #include "rust-ast-full.h"
22 #include "rust-diagnostics.h"
23 #include "rust-ast-visitor.h"
24 #include "rust-macro.h"
25 #include "rust-session-manager.h"
26 #include "rust-lex.h"
27 #include "rust-parse.h"
28 #include "operator.h"
29
30 /* Compilation unit used for various AST-related functions that would make
31 * the headers too long if they were defined inline and don't receive any
32 * benefits from being defined inline because they are virtual. Also used
33 * for various other stuff. */
34
35 namespace Rust {
36 namespace AST {
37
38 enum indent_mode
39 {
40 enter,
41 out,
42 stay
43 };
44
45 std::string
46 indent_spaces (enum indent_mode mode)
47 {
48 static int indent = 0;
49 std::string str = "";
50 if (out == mode)
51 indent--;
52 for (int i = 0; i < indent; i++)
53 str += " ";
54 if (enter == mode)
55 indent++;
56
57 return str;
58 }
59
60 // Gets a string in a certain delim type.
61 std::string
62 get_string_in_delims (std::string str_input, DelimType delim_type)
63 {
64 switch (delim_type)
65 {
66 case PARENS:
67 return "(" + str_input + ")";
68 case SQUARE:
69 return "[" + str_input + "]";
70 case CURLY:
71 return "{" + str_input + "}";
72 default:
73 return "ERROR-MARK-STRING (delims)";
74 }
75 gcc_unreachable ();
76 }
77
78 enum AttrMode
79 {
80 OUTER,
81 INNER
82 };
83
84 std::string
85 get_mode_dump_desc (AttrMode mode)
86 {
87 switch (mode)
88 {
89 case OUTER:
90 return "outer attributes";
91 case INNER:
92 return "inner attributes";
93 default:
94 gcc_unreachable ();
95 return "";
96 }
97 }
98
99 // Adds lines below adding attributes
100 std::string
101 append_attributes (std::vector<Attribute> attrs, AttrMode mode)
102 {
103 indent_spaces (enter);
104
105 std::string str
106 = "\n" + indent_spaces (stay) + get_mode_dump_desc (mode) + ": ";
107 // str += "\n" + indent_spaces (stay) + "inner attributes: ";
108 if (attrs.empty ())
109 {
110 str += "none";
111 }
112 else
113 {
114 /* note that this does not print them with outer or "inner attribute"
115 * syntax - just prints the body */
116 for (const auto &attr : attrs)
117 str += "\n" + indent_spaces (stay) + attr.as_string ();
118 }
119
120 indent_spaces (out);
121
122 return str;
123 }
124
125 // Removes the beginning and end quotes of a quoted string.
126 std::string
127 unquote_string (std::string input)
128 {
129 rust_assert (input.front () == '"');
130 rust_assert (input.back () == '"');
131 return input.substr (1, input.length () - 2);
132 }
133
134 std::string
135 Crate::as_string () const
136 {
137 rust_debug ("beginning crate recursive as-string");
138
139 std::string str ("Crate: ");
140
141 // inner attributes
142 str += append_attributes (inner_attrs, INNER);
143
144 // items
145 str += "\n items: ";
146 if (items.empty ())
147 {
148 str += "none";
149 }
150 else
151 {
152 for (const auto &item : items)
153 {
154 // DEBUG: null pointer check
155 if (item == nullptr)
156 {
157 rust_debug ("something really terrible has gone wrong - "
158 "null pointer item in crate.");
159 return "NULL_POINTER_MARK";
160 }
161
162 str += "\n " + item->as_string ();
163 }
164 }
165
166 return str + "\n";
167 }
168
169 std::string
170 Attribute::as_string () const
171 {
172 std::string path_str = path.as_string ();
173 if (attr_input == nullptr)
174 return path_str;
175 else
176 return path_str + attr_input->as_string ();
177 }
178
179 // Copy constructor must deep copy attr_input as unique pointer
180 Attribute::Attribute (Attribute const &other)
181 : path (other.path), locus (other.locus)
182 {
183 // guard to protect from null pointer dereference
184 if (other.attr_input != nullptr)
185 attr_input = other.attr_input->clone_attr_input ();
186 }
187
188 // overload assignment operator to use custom clone method
189 Attribute &
190 Attribute::operator= (Attribute const &other)
191 {
192 path = other.path;
193 locus = other.locus;
194 // guard to protect from null pointer dereference
195 if (other.attr_input != nullptr)
196 attr_input = other.attr_input->clone_attr_input ();
197 else
198 attr_input = nullptr;
199
200 return *this;
201 }
202
203 std::string
204 DelimTokenTree::as_string () const
205 {
206 std::string start_delim;
207 std::string end_delim;
208 switch (delim_type)
209 {
210 case PARENS:
211 start_delim = "(";
212 end_delim = ")";
213 break;
214 case SQUARE:
215 start_delim = "[";
216 end_delim = "]";
217 break;
218 case CURLY:
219 start_delim = "{";
220 end_delim = "}";
221 break;
222 default:
223 rust_debug ("Invalid delimiter type, "
224 "Should be PARENS, SQUARE, or CURLY.");
225 return "Invalid delimiter type";
226 }
227 std::string str = start_delim;
228 if (!token_trees.empty ())
229 {
230 for (const auto &tree : token_trees)
231 {
232 // DEBUG: null pointer check
233 if (tree == nullptr)
234 {
235 rust_debug (
236 "something really terrible has gone wrong - null pointer "
237 "token tree in delim token tree.");
238 return "NULL_POINTER_MARK";
239 }
240
241 str += tree->as_string ();
242 }
243 }
244 str += end_delim;
245
246 return str;
247 }
248
249 std::string
250 Token::as_string () const
251 {
252 if (tok_ref->has_str ())
253 {
254 std::string str = tok_ref->get_str ();
255
256 std::string quote = is_string_lit () ? "\"" : "";
257 return quote + str + quote;
258 }
259 else
260 {
261 return tok_ref->get_token_description ();
262 }
263 }
264
265 std::string
266 SimplePathSegment::as_string () const
267 {
268 return segment_name;
269 }
270
271 std::string
272 SimplePath::as_string () const
273 {
274 std::string path;
275 if (has_opening_scope_resolution)
276 path = "::";
277
278 // crappy hack because doing proper for loop would be more code
279 bool first_time = true;
280 for (const auto &segment : segments)
281 {
282 if (first_time)
283 {
284 path += segment.as_string ();
285 first_time = false;
286 }
287 else
288 {
289 path += "::" + segment.as_string ();
290 }
291
292 // DEBUG: remove later. Checks for path error.
293 if (segment.is_error ())
294 {
295 rust_debug ("segment in path is error - this should've been filtered "
296 "out. first segment "
297 "was '%s'",
298 segments.at (0).as_string ().c_str ());
299 }
300 }
301
302 return path;
303 }
304
305 std::string
306 Visibility::as_string () const
307 {
308 switch (vis_type)
309 {
310 case PRIV:
311 return std::string ("");
312 case PUB:
313 return std::string ("pub");
314 case PUB_CRATE:
315 return std::string ("pub(crate)");
316 case PUB_SELF:
317 return std::string ("pub(self)");
318 case PUB_SUPER:
319 return std::string ("pub(super)");
320 case PUB_IN_PATH:
321 return std::string ("pub(in ") + in_path.as_string () + std::string (")");
322 default:
323 gcc_unreachable ();
324 }
325 }
326
327 // Creates a string that reflects the visibility stored.
328 std::string
329 VisItem::as_string () const
330 {
331 // FIXME: can't do formatting on string to make identation occur.
332 std::string str;
333
334 if (!outer_attrs.empty ())
335 {
336 for (const auto &attr : outer_attrs)
337 str += attr.as_string () + "\n";
338 }
339
340 if (has_visibility ())
341 str += visibility.as_string () + " ";
342
343 return str;
344 }
345
346 std::string
347 Module::as_string () const
348 {
349 std::string str = VisItem::as_string () + "mod " + module_name;
350
351 // Return early if we're dealing with an unloaded module as their body resides
352 // in a different file
353 if (kind == ModuleKind::UNLOADED)
354 return str + "\n no body (reference to external file)\n";
355
356 // inner attributes
357 str += append_attributes (inner_attrs, INNER);
358
359 // items
360 str += "\n items: ";
361
362 // This can still happen if the module is loaded but empty, i.e. `mod foo {}`
363 if (items.empty ())
364 {
365 str += "none";
366 }
367 else
368 {
369 for (const auto &item : items)
370 {
371 // DEBUG: null pointer check
372 if (item == nullptr)
373 {
374 rust_debug ("something really terrible has gone wrong - "
375 "null pointer item in crate.");
376 return "NULL_POINTER_MARK";
377 }
378
379 str += "\n " + item->as_string ();
380 }
381 }
382
383 return str + "\n";
384 }
385
386 std::string
387 StaticItem::as_string () const
388 {
389 std::string str = VisItem::as_string ();
390
391 str += indent_spaces (stay) + "static";
392
393 if (has_mut)
394 str += " mut";
395
396 str += " " + name;
397
398 // DEBUG: null pointer check
399 if (type == nullptr)
400 {
401 rust_debug ("something really terrible has gone wrong - null "
402 "pointer type in static item.");
403 return "NULL_POINTER_MARK";
404 }
405 str += "\n" + indent_spaces (stay) + "Type: " + type->as_string ();
406
407 // DEBUG: null pointer check
408 if (expr == nullptr)
409 {
410 rust_debug ("something really terrible has gone wrong - null "
411 "pointer expr in static item.");
412 return "NULL_POINTER_MARK";
413 }
414 str += "\n" + indent_spaces (stay) + "Expression: " + expr->as_string ();
415
416 return str + "\n";
417 }
418
419 std::string
420 ExternCrate::as_string () const
421 {
422 std::string str = VisItem::as_string ();
423
424 str += "extern crate " + referenced_crate;
425
426 if (has_as_clause ())
427 str += " as " + as_clause_name;
428
429 return str;
430 }
431
432 std::string
433 TupleStruct::as_string () const
434 {
435 std::string str = VisItem::as_string ();
436
437 str += "struct " + struct_name;
438
439 // generic params
440 str += "\n Generic params: ";
441 if (generic_params.empty ())
442 {
443 str += "none";
444 }
445 else
446 {
447 for (const auto &param : generic_params)
448 {
449 // DEBUG: null pointer check
450 if (param == nullptr)
451 {
452 rust_debug (
453 "something really terrible has gone wrong - null pointer "
454 "generic param in enum.");
455 return "NULL_POINTER_MARK";
456 }
457
458 str += "\n " + param->as_string ();
459 }
460 }
461
462 // tuple fields
463 str += "\n Tuple fields: ";
464 if (fields.empty ())
465 {
466 str += "none";
467 }
468 else
469 {
470 for (const auto &field : fields)
471 str += "\n " + field.as_string ();
472 }
473
474 str += "\n Where clause: ";
475 if (has_where_clause ())
476 str += where_clause.as_string ();
477 else
478 str += "none";
479
480 return str;
481 }
482
483 std::string
484 ConstantItem::as_string () const
485 {
486 std::string str = VisItem::as_string ();
487
488 str += "const " + identifier;
489
490 // DEBUG: null pointer check
491 if (type == nullptr)
492 {
493 rust_debug ("something really terrible has gone wrong - null "
494 "pointer type in const item.");
495 return "NULL_POINTER_MARK";
496 }
497 str += "\n Type: " + type->as_string ();
498
499 // DEBUG: null pointer check
500 if (const_expr == nullptr)
501 {
502 rust_debug ("something really terrible has gone wrong - null "
503 "pointer expr in const item.");
504 return "NULL_POINTER_MARK";
505 }
506 str += "\n Expression: " + const_expr->as_string ();
507
508 return str + "\n";
509 }
510
511 std::string
512 InherentImpl::as_string () const
513 {
514 std::string str = VisItem::as_string ();
515
516 str += "impl ";
517
518 // generic params
519 str += "\n Generic params: ";
520 if (generic_params.empty ())
521 {
522 str += "none";
523 }
524 else
525 {
526 for (const auto &param : generic_params)
527 {
528 // DEBUG: null pointer check
529 if (param == nullptr)
530 {
531 rust_debug (
532 "something really terrible has gone wrong - null pointer "
533 "generic param in inherent impl.");
534 return "NULL_POINTER_MARK";
535 }
536
537 str += "\n " + param->as_string ();
538 }
539 }
540
541 str += "\n Type: " + trait_type->as_string ();
542
543 str += "\n Where clause: ";
544 if (has_where_clause ())
545 str += where_clause.as_string ();
546 else
547 str += "none";
548
549 // inner attributes
550 str += append_attributes (inner_attrs, INNER);
551
552 // inherent impl items
553 str += "\n Inherent impl items: ";
554 if (!has_impl_items ())
555 {
556 str += "none";
557 }
558 else
559 {
560 for (const auto &item : impl_items)
561 str += "\n " + item->as_string ();
562 }
563
564 return str;
565 }
566
567 std::string
568 Method::as_string () const
569 {
570 std::string str ("Method: \n ");
571
572 str += vis.as_string () + " " + qualifiers.as_string ();
573
574 str += " fn " + method_name;
575
576 // generic params
577 str += "\n Generic params: ";
578 if (generic_params.empty ())
579 {
580 str += "none";
581 }
582 else
583 {
584 for (const auto &param : generic_params)
585 {
586 // DEBUG: null pointer check
587 if (param == nullptr)
588 {
589 rust_debug (
590 "something really terrible has gone wrong - null pointer "
591 "generic param in method.");
592 return "NULL_POINTER_MARK";
593 }
594
595 str += "\n " + param->as_string ();
596 }
597 }
598
599 str += "\n Self param: " + self_param.as_string ();
600
601 str += "\n Function params: ";
602 if (function_params.empty ())
603 {
604 str += "none";
605 }
606 else
607 {
608 for (const auto &param : function_params)
609 str += "\n " + param.as_string ();
610 }
611
612 str += "\n Return type: ";
613 if (has_return_type ())
614 str += return_type->as_string ();
615 else
616 str += "none (void)";
617
618 str += "\n Where clause: ";
619 if (has_where_clause ())
620 str += where_clause.as_string ();
621 else
622 str += "none";
623
624 str += "\n Block expr (body): \n ";
625 str += function_body->as_string ();
626
627 return str;
628 }
629
630 std::string
631 StructStruct::as_string () const
632 {
633 std::string str = VisItem::as_string ();
634
635 str += "struct " + struct_name;
636
637 // generic params
638 str += "\n Generic params: ";
639 if (generic_params.empty ())
640 {
641 str += "none";
642 }
643 else
644 {
645 for (const auto &param : generic_params)
646 {
647 // DEBUG: null pointer check
648 if (param == nullptr)
649 {
650 rust_debug (
651 "something really terrible has gone wrong - null pointer "
652 "generic param in enum.");
653 return "NULL_POINTER_MARK";
654 }
655
656 str += "\n " + param->as_string ();
657 }
658 }
659
660 str += "\n Where clause: ";
661 if (has_where_clause ())
662 str += where_clause.as_string ();
663 else
664 str += "none";
665
666 // struct fields
667 str += "\n Struct fields: ";
668 if (is_unit)
669 {
670 str += "none (unit)";
671 }
672 else if (fields.empty ())
673 {
674 str += "none (non-unit)";
675 }
676 else
677 {
678 for (const auto &field : fields)
679 str += "\n " + field.as_string ();
680 }
681
682 return str;
683 }
684
685 std::string
686 UseDeclaration::as_string () const
687 {
688 std::string str = VisItem::as_string ();
689
690 // DEBUG: null pointer check
691 if (use_tree == nullptr)
692 {
693 rust_debug (
694 "something really terrible has gone wrong - null pointer use tree in "
695 "use declaration.");
696 return "NULL_POINTER_MARK";
697 }
698
699 str += "use " + use_tree->as_string ();
700
701 return str;
702 }
703
704 std::string
705 UseTreeGlob::as_string () const
706 {
707 switch (glob_type)
708 {
709 case NO_PATH:
710 return "*";
711 case GLOBAL:
712 return "::*";
713 case PATH_PREFIXED: {
714 std::string path_str = path.as_string ();
715 return path_str + "::*";
716 }
717 default:
718 // some kind of error
719 return "ERROR-PATH";
720 }
721 gcc_unreachable ();
722 }
723
724 std::string
725 UseTreeList::as_string () const
726 {
727 std::string path_str;
728 switch (path_type)
729 {
730 case NO_PATH:
731 path_str = "{";
732 break;
733 case GLOBAL:
734 path_str = "::{";
735 break;
736 case PATH_PREFIXED: {
737 path_str = path.as_string () + "::{";
738 break;
739 }
740 default:
741 // some kind of error
742 return "ERROR-PATH-LIST";
743 }
744
745 if (has_trees ())
746 {
747 auto i = trees.begin ();
748 auto e = trees.end ();
749
750 // DEBUG: null pointer check
751 if (*i == nullptr)
752 {
753 rust_debug ("something really terrible has gone wrong - null pointer "
754 "tree in use tree list.");
755 return "NULL_POINTER_MARK";
756 }
757
758 for (; i != e; i++)
759 {
760 path_str += (*i)->as_string ();
761 if (e != i + 1)
762 path_str += ", ";
763 }
764 }
765 else
766 {
767 path_str += "none";
768 }
769
770 return path_str + "}";
771 }
772
773 std::string
774 UseTreeRebind::as_string () const
775 {
776 std::string path_str = path.as_string ();
777
778 switch (bind_type)
779 {
780 case NONE:
781 // nothing to add, just path
782 break;
783 case IDENTIFIER:
784 path_str += " as " + identifier;
785 break;
786 case WILDCARD:
787 path_str += " as _";
788 break;
789 default:
790 // error
791 return "ERROR-PATH-REBIND";
792 }
793
794 return path_str;
795 }
796
797 std::string
798 Enum::as_string () const
799 {
800 std::string str = VisItem::as_string ();
801 str += enum_name;
802
803 // generic params
804 str += "\n Generic params: ";
805 if (generic_params.empty ())
806 {
807 str += "none";
808 }
809 else
810 {
811 for (const auto &param : generic_params)
812 {
813 // DEBUG: null pointer check
814 if (param == nullptr)
815 {
816 rust_debug (
817 "something really terrible has gone wrong - null pointer "
818 "generic param in enum.");
819 return "NULL_POINTER_MARK";
820 }
821
822 str += "\n " + param->as_string ();
823 }
824 }
825
826 str += "\n Where clause: ";
827 if (has_where_clause ())
828 str += where_clause.as_string ();
829 else
830 str += "none";
831
832 // items
833 str += "\n Items: ";
834 if (items.empty ())
835 {
836 str += "none";
837 }
838 else
839 {
840 for (const auto &item : items)
841 {
842 // DEBUG: null pointer check
843 if (item == nullptr)
844 {
845 rust_debug (
846 "something really terrible has gone wrong - null pointer "
847 "enum item in enum.");
848 return "NULL_POINTER_MARK";
849 }
850
851 str += "\n " + item->as_string ();
852 }
853 }
854
855 return str;
856 }
857
858 std::string
859 Trait::as_string () const
860 {
861 std::string str = VisItem::as_string ();
862
863 if (has_unsafe)
864 str += "unsafe ";
865
866 str += "trait " + name;
867
868 // generic params
869 str += "\n Generic params: ";
870 if (generic_params.empty ())
871 {
872 str += "none";
873 }
874 else
875 {
876 for (const auto &param : generic_params)
877 {
878 // DEBUG: null pointer check
879 if (param == nullptr)
880 {
881 rust_debug (
882 "something really terrible has gone wrong - null pointer "
883 "generic param in trait.");
884 return "NULL_POINTER_MARK";
885 }
886
887 str += "\n " + param->as_string ();
888 }
889 }
890
891 str += "\n Type param bounds: ";
892 if (!has_type_param_bounds ())
893 {
894 str += "none";
895 }
896 else
897 {
898 for (const auto &bound : type_param_bounds)
899 {
900 // DEBUG: null pointer check
901 if (bound == nullptr)
902 {
903 rust_debug (
904 "something really terrible has gone wrong - null pointer "
905 "type param bound in trait.");
906 return "NULL_POINTER_MARK";
907 }
908
909 str += "\n " + bound->as_string ();
910 }
911 }
912
913 str += "\n Where clause: ";
914 if (!has_where_clause ())
915 str += "none";
916 else
917 str += where_clause.as_string ();
918
919 str += "\n Trait items: ";
920 if (!has_trait_items ())
921 {
922 str += "none";
923 }
924 else
925 {
926 for (const auto &item : trait_items)
927 {
928 // DEBUG: null pointer check
929 if (item == nullptr)
930 {
931 rust_debug (
932 "something really terrible has gone wrong - null pointer "
933 "trait item in trait.");
934 return "NULL_POINTER_MARK";
935 }
936
937 str += "\n " + item->as_string ();
938 }
939 }
940
941 return str;
942 }
943
944 std::string
945 Union::as_string () const
946 {
947 std::string str = VisItem::as_string ();
948
949 str += "union " + union_name;
950
951 // generic params
952 str += "\n Generic params: ";
953 if (generic_params.empty ())
954 {
955 str += "none";
956 }
957 else
958 {
959 for (const auto &param : generic_params)
960 {
961 // DEBUG: null pointer check
962 if (param == nullptr)
963 {
964 rust_debug (
965 "something really terrible has gone wrong - null pointer "
966 "generic param in union.");
967 return "NULL_POINTER_MARK";
968 }
969
970 str += "\n " + param->as_string ();
971 }
972 }
973
974 str += "\n Where clause: ";
975 if (has_where_clause ())
976 str += where_clause.as_string ();
977 else
978 str += "none";
979
980 // struct fields
981 str += "\n Struct fields (variants): ";
982 if (variants.empty ())
983 {
984 str += "none";
985 }
986 else
987 {
988 for (const auto &field : variants)
989 str += "\n " + field.as_string ();
990 }
991
992 return str;
993 }
994
995 std::string
996 Function::as_string () const
997 {
998 std::string str = VisItem::as_string () + "\n";
999 std::string qstr = qualifiers.as_string ();
1000 if ("" != qstr)
1001 str += qstr + " ";
1002
1003 if (has_return_type ())
1004 {
1005 // DEBUG: null pointer check
1006 if (return_type == nullptr)
1007 {
1008 rust_debug (
1009 "something really terrible has gone wrong - null pointer return "
1010 "type in function.");
1011 return "NULL_POINTER_MARK";
1012 }
1013
1014 str += return_type->as_string () + " ";
1015 }
1016 else
1017 {
1018 str += "void ";
1019 }
1020
1021 str += function_name;
1022
1023 if (has_generics ())
1024 {
1025 str += "<";
1026
1027 auto i = generic_params.begin ();
1028 auto e = generic_params.end ();
1029
1030 // DEBUG: null pointer check
1031 if (i == e)
1032 {
1033 rust_debug ("something really terrible has gone wrong - null pointer "
1034 "generic param in function item.");
1035 return "NULL_POINTER_MARK";
1036 }
1037
1038 for (; i != e; i++)
1039 {
1040 str += (*i)->as_string ();
1041 if (e != i + 1)
1042 str += ", ";
1043 }
1044 str += ">";
1045 }
1046
1047 if (has_function_params ())
1048 {
1049 auto i = function_params.begin ();
1050 auto e = function_params.end ();
1051 str += "(";
1052 for (; i != e; i++)
1053 {
1054 str += (*i).as_string ();
1055 if (e != i + 1)
1056 str += ", ";
1057 }
1058 str += ")";
1059 }
1060 else
1061 {
1062 str += "()";
1063 }
1064
1065 if (has_where_clause ())
1066 str += " where " + where_clause.as_string ();
1067
1068 str += "\n";
1069
1070 // DEBUG: null pointer check
1071 if (function_body == nullptr)
1072 {
1073 rust_debug (
1074 "something really terrible has gone wrong - null pointer function "
1075 "body in function.");
1076 return "NULL_POINTER_MARK";
1077 }
1078 str += function_body->as_string () + "\n";
1079
1080 return str;
1081 }
1082
1083 std::string
1084 WhereClause::as_string () const
1085 {
1086 // just print where clause items, don't mention "where" or "where clause"
1087 std::string str;
1088
1089 if (where_clause_items.empty ())
1090 {
1091 str = "none";
1092 }
1093 else
1094 {
1095 for (const auto &item : where_clause_items)
1096 str += "\n " + item->as_string ();
1097 }
1098
1099 return str;
1100 }
1101
1102 std::string
1103 BlockExpr::as_string () const
1104 {
1105 std::string istr = indent_spaces (enter);
1106 std::string str = istr + "BlockExpr:\n" + istr;
1107
1108 // get outer attributes
1109 str += append_attributes (outer_attrs, OUTER);
1110
1111 // inner attributes
1112 str += append_attributes (inner_attrs, INNER);
1113
1114 // statements
1115 str += "\n" + indent_spaces (stay) + "statements: ";
1116 if (statements.empty ())
1117 {
1118 str += "none";
1119 }
1120 else
1121 {
1122 for (const auto &stmt : statements)
1123 {
1124 // DEBUG: null pointer check
1125 if (stmt == nullptr)
1126 {
1127 rust_debug (
1128 "something really terrible has gone wrong - null pointer "
1129 "stmt in block expr.");
1130 return "NULL_POINTER_MARK";
1131 }
1132
1133 str += "\n" + indent_spaces (stay) + stmt->as_string ();
1134 }
1135 }
1136
1137 // final expression
1138 str += "\n" + indent_spaces (stay) + "final expression: ";
1139 if (expr == nullptr)
1140 str += "none";
1141 else
1142 str += "\n" + expr->as_string ();
1143
1144 str += "\n" + indent_spaces (out);
1145 return str;
1146 }
1147
1148 std::string
1149 TraitImpl::as_string () const
1150 {
1151 std::string str = VisItem::as_string ();
1152
1153 if (has_unsafe)
1154 str += "unsafe ";
1155
1156 str += "impl ";
1157
1158 // generic params
1159 str += "\n Generic params: ";
1160 if (!has_generics ())
1161 {
1162 str += "none";
1163 }
1164 else
1165 {
1166 for (const auto &param : generic_params)
1167 str += "\n " + param->as_string ();
1168 }
1169
1170 str += "\n Has exclam: ";
1171 if (has_exclam)
1172 str += "true";
1173 else
1174 str += "false";
1175
1176 str += "\n TypePath (to trait): " + trait_path.as_string ();
1177
1178 str += "\n Type (struct to impl on): " + trait_type->as_string ();
1179
1180 str += "\n Where clause: ";
1181 if (!has_where_clause ())
1182 str += "none";
1183 else
1184 str += where_clause.as_string ();
1185
1186 // inner attributes
1187 str += append_attributes (inner_attrs, INNER);
1188
1189 str += "\n trait impl items: ";
1190 if (!has_impl_items ())
1191 {
1192 str += "none";
1193 }
1194 else
1195 {
1196 for (const auto &item : impl_items)
1197 str += "\n " + item->as_string ();
1198 }
1199
1200 return str;
1201 }
1202
1203 std::string
1204 TypeAlias::as_string () const
1205 {
1206 std::string str = VisItem::as_string ();
1207
1208 str += " " + new_type_name;
1209
1210 // generic params
1211 str += "\n Generic params: ";
1212 if (!has_generics ())
1213 {
1214 str += "none";
1215 }
1216 else
1217 {
1218 auto i = generic_params.begin ();
1219 auto e = generic_params.end ();
1220
1221 for (; i != e; i++)
1222 {
1223 str += (*i)->as_string ();
1224 if (e != i + 1)
1225 str += ", ";
1226 }
1227 }
1228
1229 str += "\n Where clause: ";
1230 if (!has_where_clause ())
1231 str += "none";
1232 else
1233 str += where_clause.as_string ();
1234
1235 str += "\n Type: " + existing_type->as_string ();
1236
1237 return str;
1238 }
1239
1240 std::string
1241 ExternBlock::as_string () const
1242 {
1243 std::string str = VisItem::as_string ();
1244
1245 str += "extern ";
1246 if (has_abi ())
1247 str += "\"" + abi + "\" ";
1248
1249 str += append_attributes (inner_attrs, INNER);
1250
1251 str += "\n external items: ";
1252 if (!has_extern_items ())
1253 {
1254 str += "none";
1255 }
1256 else
1257 {
1258 for (const auto &item : extern_items)
1259 str += "\n " + item->as_string ();
1260 }
1261
1262 return str;
1263 }
1264
1265 std::string
1266 MacroRule::as_string () const
1267 {
1268 std::string str ("Macro rule: ");
1269
1270 str += "\n Matcher: \n ";
1271 str += matcher.as_string ();
1272
1273 str += "\n Transcriber: \n ";
1274 str += transcriber.as_string ();
1275
1276 return str;
1277 }
1278
1279 std::string
1280 MacroRulesDefinition::as_string () const
1281 {
1282 std::string str;
1283
1284 // get outer attrs
1285 str += append_attributes (outer_attrs, OUTER);
1286
1287 str += "macro_rules!";
1288
1289 str += rule_name;
1290
1291 str += "\n Macro rules: ";
1292 if (rules.empty ())
1293 {
1294 str += "none";
1295 }
1296 else
1297 {
1298 for (const auto &rule : rules)
1299 str += "\n " + rule.as_string ();
1300 }
1301
1302 str += "\n Delim type: ";
1303 switch (delim_type)
1304 {
1305 case PARENS:
1306 str += "parentheses";
1307 break;
1308 case SQUARE:
1309 str += "square";
1310 break;
1311 case CURLY:
1312 str += "curly";
1313 break;
1314 default:
1315 return "ERROR_MARK_STRING - delim type in macro invocation";
1316 }
1317
1318 return str;
1319 }
1320
1321 std::string
1322 MacroInvocation::as_string () const
1323 {
1324 std::string str = "MacroInvocation: ";
1325
1326 str += append_attributes (outer_attrs, OUTER);
1327
1328 str += "\n " + invoc_data.as_string ();
1329
1330 str += "\n has semicolon: ";
1331 str += has_semicolon () ? "true" : "false";
1332
1333 return str;
1334 }
1335
1336 std::string
1337 MacroInvocData::as_string () const
1338 {
1339 return path.as_string () + "!" + token_tree.as_string ();
1340 }
1341
1342 std::string
1343 PathInExpression::as_string () const
1344 {
1345 std::string str;
1346
1347 if (has_opening_scope_resolution)
1348 str = "::";
1349
1350 return str + PathPattern::as_string ();
1351 }
1352
1353 std::string
1354 ExprStmtWithBlock::as_string () const
1355 {
1356 std::string str = indent_spaces (enter) + "ExprStmtWithBlock: \n";
1357
1358 if (expr == nullptr)
1359 {
1360 str += "none (this should not happen and is an error)";
1361 }
1362 else
1363 {
1364 indent_spaces (enter);
1365 str += expr->as_string ();
1366 indent_spaces (out);
1367 }
1368
1369 indent_spaces (out);
1370 return str;
1371 }
1372
1373 std::string
1374 ClosureParam::as_string () const
1375 {
1376 std::string str (pattern->as_string ());
1377
1378 if (has_type_given ())
1379 str += " : " + type->as_string ();
1380
1381 return str;
1382 }
1383
1384 std::string
1385 ClosureExpr::as_string () const
1386 {
1387 std::string str = "ClosureExpr:";
1388
1389 str += append_attributes (outer_attrs, OUTER);
1390
1391 str += "\n Has move: ";
1392 if (has_move)
1393 str += "true";
1394 else
1395 str += "false";
1396
1397 str += "\n Params: ";
1398 if (params.empty ())
1399 {
1400 str += "none";
1401 }
1402 else
1403 {
1404 for (const auto &param : params)
1405 str += "\n " + param.as_string ();
1406 }
1407
1408 return str;
1409 }
1410
1411 std::string
1412 ClosureExprInnerTyped::as_string () const
1413 {
1414 std::string str = ClosureExpr::as_string ();
1415
1416 str += "\n Return type: " + return_type->as_string ();
1417
1418 str += "\n Body: " + expr->as_string ();
1419
1420 return str;
1421 }
1422
1423 std::string
1424 PathPattern::as_string () const
1425 {
1426 std::string str;
1427
1428 for (const auto &segment : segments)
1429 str += segment.as_string () + "::";
1430
1431 // basically a hack - remove last two characters of string (remove final ::)
1432 str.erase (str.length () - 2);
1433
1434 return str;
1435 }
1436
1437 std::string
1438 QualifiedPathType::as_string () const
1439 {
1440 std::string str ("<");
1441 str += type_to_invoke_on->as_string ();
1442
1443 if (has_as_clause ())
1444 str += " as " + trait_path.as_string ();
1445
1446 return str + ">";
1447 }
1448
1449 std::string
1450 QualifiedPathInExpression::as_string () const
1451 {
1452 return path_type.as_string () + "::" + PathPattern::as_string ();
1453 }
1454
1455 std::string
1456 BorrowExpr::as_string () const
1457 {
1458 /* TODO: find way to incorporate outer attrs - may have to represent in
1459 * different style (i.e. something more like BorrowExpr: \n outer attrs) */
1460
1461 std::string str ("&");
1462
1463 if (double_borrow)
1464 str += "&";
1465
1466 if (is_mut)
1467 str += "mut ";
1468
1469 str += main_or_left_expr->as_string ();
1470
1471 return str;
1472 }
1473
1474 std::string
1475 ReturnExpr::as_string () const
1476 {
1477 /* TODO: find way to incorporate outer attrs - may have to represent in
1478 * different style (i.e. something more like BorrowExpr: \n outer attrs) */
1479
1480 std::string str ("return ");
1481
1482 if (has_returned_expr ())
1483 str += return_expr->as_string ();
1484
1485 return str;
1486 }
1487
1488 std::string
1489 GroupedExpr::as_string () const
1490 {
1491 std::string str ("Grouped expr:");
1492
1493 // outer attrs
1494 str += append_attributes (outer_attrs, OUTER);
1495
1496 // inner attributes
1497 str += append_attributes (inner_attrs, INNER);
1498
1499 str += "\n Expr in parens: " + expr_in_parens->as_string ();
1500
1501 return str;
1502 }
1503
1504 std::string
1505 RangeToExpr::as_string () const
1506 {
1507 return ".." + to->as_string ();
1508 }
1509
1510 std::string
1511 ContinueExpr::as_string () const
1512 {
1513 // TODO: rewrite format to allow outer attributes
1514 std::string str ("continue ");
1515
1516 if (has_label ())
1517 str += label.as_string ();
1518
1519 return str;
1520 }
1521
1522 std::string
1523 NegationExpr::as_string () const
1524 {
1525 // TODO: rewrite formula to allow outer attributes
1526 std::string str;
1527
1528 switch (expr_type)
1529 {
1530 case NegationOperator::NEGATE:
1531 str = "-";
1532 break;
1533 case NegationOperator::NOT:
1534 str = "!";
1535 break;
1536 default:
1537 return "ERROR_MARK_STRING - negation expr";
1538 }
1539
1540 str += main_or_left_expr->as_string ();
1541
1542 return str;
1543 }
1544
1545 std::string
1546 RangeFromExpr::as_string () const
1547 {
1548 return from->as_string () + "..";
1549 }
1550
1551 std::string
1552 RangeFullExpr::as_string () const
1553 {
1554 return "..";
1555 }
1556
1557 std::string
1558 ArrayIndexExpr::as_string () const
1559 {
1560 // TODO: rewrite formula to allow outer attributes
1561 return array_expr->as_string () + "[" + index_expr->as_string () + "]";
1562 }
1563
1564 std::string
1565 AssignmentExpr::as_string () const
1566 {
1567 std::string str ("AssignmentExpr: ");
1568
1569 if (main_or_left_expr == nullptr || right_expr == nullptr)
1570 {
1571 str += "error (either or both expressions are null)";
1572 }
1573 else
1574 {
1575 // left expr
1576 str += "\n left: " + main_or_left_expr->as_string ();
1577
1578 // right expr
1579 str += "\n right: " + right_expr->as_string ();
1580 }
1581
1582 return str;
1583 }
1584
1585 std::string
1586 AsyncBlockExpr::as_string () const
1587 {
1588 std::string str = "AsyncBlockExpr: ";
1589
1590 // get outer attributes
1591 // str += "\n " + Expr::as_string ();
1592 str += append_attributes (outer_attrs, OUTER);
1593
1594 str += "\n Has move: ";
1595 str += has_move ? "true" : "false";
1596
1597 return str + "\n" + block_expr->as_string ();
1598 }
1599
1600 std::string
1601 ComparisonExpr::as_string () const
1602 {
1603 // TODO: rewrite to better reflect non-literal expressions
1604 std::string str (main_or_left_expr->as_string ());
1605
1606 switch (expr_type)
1607 {
1608 case ComparisonOperator::EQUAL:
1609 str += " == ";
1610 break;
1611 case ComparisonOperator::NOT_EQUAL:
1612 str += " != ";
1613 break;
1614 case ComparisonOperator::GREATER_THAN:
1615 str += " > ";
1616 break;
1617 case ComparisonOperator::LESS_THAN:
1618 str += " < ";
1619 break;
1620 case ComparisonOperator::GREATER_OR_EQUAL:
1621 str += " >= ";
1622 break;
1623 case ComparisonOperator::LESS_OR_EQUAL:
1624 str += " <= ";
1625 break;
1626 default:
1627 return "ERROR_MARK_STRING - comparison expr";
1628 }
1629
1630 str += right_expr->as_string ();
1631
1632 return str;
1633 }
1634
1635 std::string
1636 MethodCallExpr::as_string () const
1637 {
1638 std::string str = "MethodCallExpr: ";
1639
1640 str += append_attributes (outer_attrs, OUTER);
1641
1642 str += "\n Object (receiver) expr: \n";
1643 str += receiver->as_string ();
1644
1645 str += "\n Method path segment: \n";
1646 str += method_name.as_string ();
1647
1648 str += "\n Call params:";
1649 if (params.empty ())
1650 {
1651 str += "none";
1652 }
1653 else
1654 {
1655 for (const auto &param : params)
1656 {
1657 if (param == nullptr)
1658 return "ERROR_MARK_STRING - method call expr param is null";
1659
1660 str += "\n " + param->as_string ();
1661 }
1662 }
1663
1664 return str;
1665 }
1666
1667 std::string
1668 TupleIndexExpr::as_string () const
1669 {
1670 // TODO: rewrite dump to better reflect non-literal exprs
1671 return tuple_expr->as_string () + "." + std::to_string (tuple_index);
1672 }
1673
1674 std::string
1675 DereferenceExpr::as_string () const
1676 {
1677 // TODO: rewrite dump to better reflect non-literal exprs
1678 return "*" + main_or_left_expr->as_string ();
1679 }
1680
1681 std::string
1682 FieldAccessExpr::as_string () const
1683 {
1684 // TODO: rewrite dump to better reflect non-literal exprs
1685 return receiver->as_string () + "." + field;
1686 }
1687
1688 std::string
1689 LazyBooleanExpr::as_string () const
1690 {
1691 // TODO: rewrite dump to better reflect non-literal exprs
1692 std::string str (main_or_left_expr->as_string ());
1693
1694 switch (expr_type)
1695 {
1696 case LazyBooleanOperator::LOGICAL_OR:
1697 str += " || ";
1698 break;
1699 case LazyBooleanOperator::LOGICAL_AND:
1700 str += " && ";
1701 break;
1702 default:
1703 return "ERROR_MARK_STRING - lazy boolean expr out of bounds";
1704 }
1705
1706 str += right_expr->as_string ();
1707
1708 return str;
1709 }
1710
1711 std::string
1712 RangeFromToExpr::as_string () const
1713 {
1714 // TODO: rewrite dump to better reflect non-literal exprs
1715 return from->as_string () + ".." + to->as_string ();
1716 }
1717
1718 std::string
1719 RangeToInclExpr::as_string () const
1720 {
1721 // TODO: rewrite dump to better reflect non-literal exprs
1722 return "..=" + to->as_string ();
1723 }
1724
1725 std::string
1726 UnsafeBlockExpr::as_string () const
1727 {
1728 std::string str = "UnsafeBlockExpr:" + indent_spaces (enter);
1729
1730 // get outer attributes
1731 str += append_attributes (outer_attrs, OUTER);
1732
1733 str += indent_spaces (stay) + expr->as_string () + "\n" + indent_spaces (out);
1734
1735 return str;
1736 }
1737
1738 std::string
1739 ClosureExprInner::as_string () const
1740 {
1741 std::string str = ClosureExpr::as_string ();
1742
1743 str += "\n Expression: " + closure_inner->as_string ();
1744
1745 return str;
1746 }
1747
1748 std::string
1749 IfExpr::as_string () const
1750 {
1751 std::string str = "IfExpr: ";
1752
1753 str += append_attributes (outer_attrs, OUTER);
1754
1755 str += "\n Condition expr: " + condition->as_string ();
1756
1757 str += "\n If block expr: " + if_block->as_string ();
1758
1759 return str;
1760 }
1761
1762 std::string
1763 IfExprConseqElse::as_string () const
1764 {
1765 std::string str = IfExpr::as_string ();
1766
1767 str += "\n Else block expr: " + else_block->as_string ();
1768
1769 return str;
1770 }
1771
1772 std::string
1773 IfExprConseqIf::as_string () const
1774 {
1775 std::string str = IfExpr::as_string ();
1776
1777 str += "\n Else if expr: \n " + conseq_if_expr->as_string ();
1778
1779 return str;
1780 }
1781
1782 std::string
1783 IfExprConseqIfLet::as_string () const
1784 {
1785 std::string str = IfExpr::as_string ();
1786
1787 str += "\n Else if let expr: \n " + if_let_expr->as_string ();
1788
1789 return str;
1790 }
1791
1792 std::string
1793 IfLetExpr::as_string () const
1794 {
1795 std::string str = "IfLetExpr: ";
1796
1797 str += append_attributes (outer_attrs, OUTER);
1798
1799 str += "\n Condition match arm patterns: ";
1800 if (match_arm_patterns.empty ())
1801 {
1802 str += "none";
1803 }
1804 else
1805 {
1806 for (const auto &pattern : match_arm_patterns)
1807 str += "\n " + pattern->as_string ();
1808 }
1809
1810 str += "\n Scrutinee expr: " + value->as_string ();
1811
1812 str += "\n If let block expr: " + if_block->as_string ();
1813
1814 return str;
1815 }
1816
1817 std::string
1818 IfLetExprConseqElse::as_string () const
1819 {
1820 std::string str = IfLetExpr::as_string ();
1821
1822 str += "\n Else block expr: " + else_block->as_string ();
1823
1824 return str;
1825 }
1826
1827 std::string
1828 IfLetExprConseqIf::as_string () const
1829 {
1830 std::string str = IfLetExpr::as_string ();
1831
1832 str += "\n Else if expr: \n " + if_expr->as_string ();
1833
1834 return str;
1835 }
1836
1837 std::string
1838 IfLetExprConseqIfLet::as_string () const
1839 {
1840 std::string str = IfLetExpr::as_string ();
1841
1842 str += "\n Else if let expr: \n " + if_let_expr->as_string ();
1843
1844 return str;
1845 }
1846
1847 std::string
1848 RangeFromToInclExpr::as_string () const
1849 {
1850 // TODO: rewrite to allow dumps with non-literal exprs
1851 return from->as_string () + "..=" + to->as_string ();
1852 }
1853
1854 std::string
1855 ErrorPropagationExpr::as_string () const
1856 {
1857 // TODO: rewrite to allow dumps with non-literal exprs
1858 return main_or_left_expr->as_string () + "?";
1859 }
1860
1861 std::string
1862 CompoundAssignmentExpr::as_string () const
1863 {
1864 std::string operator_str;
1865 operator_str.reserve (1);
1866
1867 // get operator string
1868 switch (expr_type)
1869 {
1870 case CompoundAssignmentOperator::ADD:
1871 operator_str = "+";
1872 break;
1873 case CompoundAssignmentOperator::SUBTRACT:
1874 operator_str = "-";
1875 break;
1876 case CompoundAssignmentOperator::MULTIPLY:
1877 operator_str = "*";
1878 break;
1879 case CompoundAssignmentOperator::DIVIDE:
1880 operator_str = "/";
1881 break;
1882 case CompoundAssignmentOperator::MODULUS:
1883 operator_str = "%";
1884 break;
1885 case CompoundAssignmentOperator::BITWISE_AND:
1886 operator_str = "&";
1887 break;
1888 case CompoundAssignmentOperator::BITWISE_OR:
1889 operator_str = "|";
1890 break;
1891 case CompoundAssignmentOperator::BITWISE_XOR:
1892 operator_str = "^";
1893 break;
1894 case CompoundAssignmentOperator::LEFT_SHIFT:
1895 operator_str = "<<";
1896 break;
1897 case CompoundAssignmentOperator::RIGHT_SHIFT:
1898 operator_str = ">>";
1899 break;
1900 default:
1901 operator_str = "invalid operator. wtf";
1902 break;
1903 }
1904
1905 operator_str += "=";
1906
1907 std::string str ("CompoundAssignmentExpr: ");
1908 if (main_or_left_expr == nullptr || right_expr == nullptr)
1909 {
1910 str += "error. this is probably a parsing failure.";
1911 }
1912 else
1913 {
1914 str += "\n left: " + main_or_left_expr->as_string ();
1915 str += "\n right: " + right_expr->as_string ();
1916 str += "\n operator: " + operator_str;
1917 }
1918
1919 return str;
1920 }
1921
1922 std::string
1923 ArithmeticOrLogicalExpr::as_string () const
1924 {
1925 std::string operator_str;
1926 operator_str.reserve (1);
1927
1928 // get operator string
1929 switch (expr_type)
1930 {
1931 case ArithmeticOrLogicalOperator::ADD:
1932 operator_str = "+";
1933 break;
1934 case ArithmeticOrLogicalOperator::SUBTRACT:
1935 operator_str = "-";
1936 break;
1937 case ArithmeticOrLogicalOperator::MULTIPLY:
1938 operator_str = "*";
1939 break;
1940 case ArithmeticOrLogicalOperator::DIVIDE:
1941 operator_str = "/";
1942 break;
1943 case ArithmeticOrLogicalOperator::MODULUS:
1944 operator_str = "%";
1945 break;
1946 case ArithmeticOrLogicalOperator::BITWISE_AND:
1947 operator_str = "&";
1948 break;
1949 case ArithmeticOrLogicalOperator::BITWISE_OR:
1950 operator_str = "|";
1951 break;
1952 case ArithmeticOrLogicalOperator::BITWISE_XOR:
1953 operator_str = "^";
1954 break;
1955 case ArithmeticOrLogicalOperator::LEFT_SHIFT:
1956 operator_str = "<<";
1957 break;
1958 case ArithmeticOrLogicalOperator::RIGHT_SHIFT:
1959 operator_str = ">>";
1960 break;
1961 default:
1962 operator_str = "invalid operator. wtf";
1963 break;
1964 }
1965
1966 std::string str ("ArithmeticOrLogicalExpr: ");
1967 if (main_or_left_expr == nullptr || right_expr == nullptr)
1968 {
1969 str += "error. this is probably a parsing failure.";
1970 }
1971 else
1972 {
1973 str += main_or_left_expr->as_string () + " ";
1974 str += operator_str + " ";
1975 str += right_expr->as_string ();
1976 }
1977
1978 return str;
1979 }
1980
1981 std::string
1982 CallExpr::as_string () const
1983 {
1984 std::string str = "CallExpr: ";
1985
1986 str += append_attributes (outer_attrs, OUTER);
1987
1988 str += "\n Function expr: ";
1989 str += function->as_string ();
1990
1991 str += "\n Call params:";
1992 if (!has_params ())
1993 {
1994 str += "none";
1995 }
1996 else
1997 {
1998 for (const auto &param : params)
1999 {
2000 if (param == nullptr)
2001 return "ERROR_MARK_STRING - call expr param is null";
2002
2003 str += "\n " + param->as_string ();
2004 }
2005 }
2006
2007 return str;
2008 }
2009
2010 std::string
2011 WhileLoopExpr::as_string () const
2012 {
2013 std::string str = "WhileLoopExpr: ";
2014
2015 str += append_attributes (outer_attrs, OUTER);
2016
2017 str += "\n Label: ";
2018 if (!has_loop_label ())
2019 str += "none";
2020 else
2021 str += loop_label.as_string ();
2022
2023 str += "\n Conditional expr: " + condition->as_string ();
2024
2025 str += "\n Loop block: " + loop_block->as_string ();
2026
2027 return str;
2028 }
2029
2030 std::string
2031 WhileLetLoopExpr::as_string () const
2032 {
2033 std::string str = "WhileLetLoopExpr: ";
2034
2035 str += append_attributes (outer_attrs, OUTER);
2036
2037 str += "\n Label: ";
2038 if (!has_loop_label ())
2039 str += "none";
2040 else
2041 str += loop_label.as_string ();
2042
2043 str += "\n Match arm patterns: ";
2044 if (match_arm_patterns.empty ())
2045 {
2046 str += "none";
2047 }
2048 else
2049 {
2050 for (const auto &pattern : match_arm_patterns)
2051 str += "\n " + pattern->as_string ();
2052 }
2053
2054 str += "\n Scrutinee expr: " + scrutinee->as_string ();
2055
2056 str += "\n Loop block: " + loop_block->as_string ();
2057
2058 return str;
2059 }
2060
2061 std::string
2062 LoopExpr::as_string () const
2063 {
2064 std::string str = "LoopExpr: (infinite loop)";
2065
2066 str += append_attributes (outer_attrs, OUTER);
2067
2068 str += "\n Label: ";
2069 if (!has_loop_label ())
2070 str += "none";
2071 else
2072 str += loop_label.as_string ();
2073
2074 str += "\n Loop block: " + loop_block->as_string ();
2075
2076 return str;
2077 }
2078
2079 std::string
2080 ArrayExpr::as_string () const
2081 {
2082 std::string str = "ArrayExpr:";
2083
2084 str += append_attributes (outer_attrs, OUTER);
2085
2086 // inner attributes
2087 str += append_attributes (inner_attrs, INNER);
2088
2089 str += "\n Array elems: ";
2090 str += internal_elements->as_string ();
2091
2092 return str;
2093 }
2094
2095 std::string
2096 AwaitExpr::as_string () const
2097 {
2098 // TODO: rewrite dump to allow non-literal exprs
2099 return awaited_expr->as_string () + ".await";
2100 }
2101
2102 std::string
2103 BreakExpr::as_string () const
2104 {
2105 // TODO: rewrite dump to allow outer attrs, non-literal exprs
2106 std::string str ("break ");
2107
2108 if (has_label ())
2109 str += label.as_string () + " ";
2110
2111 if (has_break_expr ())
2112 str += break_expr->as_string ();
2113
2114 return str;
2115 }
2116
2117 std::string
2118 LoopLabel::as_string () const
2119 {
2120 return label.as_string () + ": (label) ";
2121 }
2122
2123 std::string
2124 MatchArm::as_string () const
2125 {
2126 // outer attributes
2127 std::string str = append_attributes (outer_attrs, OUTER);
2128
2129 str += "\nPatterns: ";
2130 if (match_arm_patterns.empty ())
2131 {
2132 str += "none";
2133 }
2134 else
2135 {
2136 for (const auto &pattern : match_arm_patterns)
2137 str += "\n " + pattern->as_string ();
2138 }
2139
2140 str += "\nGuard expr: ";
2141 if (!has_match_arm_guard ())
2142 str += "none";
2143 else
2144 str += guard_expr->as_string ();
2145
2146 return str;
2147 }
2148
2149 std::string
2150 MatchCase::as_string () const
2151 {
2152 std::string str ("MatchCase: (match arm) ");
2153
2154 str += "\n Match arm matcher: \n" + arm.as_string ();
2155 str += "\n Expr: " + expr->as_string ();
2156
2157 return str;
2158 }
2159
2160 std::string
2161 MatchExpr::as_string () const
2162 {
2163 std::string str ("MatchExpr:");
2164
2165 str += append_attributes (outer_attrs, OUTER);
2166
2167 str += "\n Scrutinee expr: " + branch_value->as_string ();
2168
2169 // inner attributes
2170 str += append_attributes (inner_attrs, INNER);
2171
2172 // match arms
2173 str += "\n Match arms: ";
2174 if (match_arms.empty ())
2175 {
2176 str += "none";
2177 }
2178 else
2179 {
2180 for (const auto &arm : match_arms)
2181 str += "\n " + arm.as_string ();
2182 }
2183
2184 return str;
2185 }
2186
2187 std::string
2188 TupleExpr::as_string () const
2189 {
2190 std::string str ("TupleExpr:");
2191
2192 str += append_attributes (outer_attrs, OUTER);
2193
2194 // inner attributes
2195 str += append_attributes (inner_attrs, INNER);
2196
2197 str += "\n Tuple elements: ";
2198 if (tuple_elems.empty ())
2199 {
2200 str += "none";
2201 }
2202 else
2203 {
2204 for (const auto &elem : tuple_elems)
2205 str += "\n " + elem->as_string ();
2206 }
2207
2208 return str;
2209 }
2210
2211 std::string
2212 ExprStmtWithoutBlock::as_string () const
2213 {
2214 std::string str ("ExprStmtWithoutBlock:\n");
2215 indent_spaces (enter);
2216 str += indent_spaces (stay);
2217
2218 if (expr == nullptr)
2219 str += "none (this shouldn't happen and is probably an error)";
2220 else
2221 str += expr->as_string ();
2222 indent_spaces (out);
2223
2224 return str;
2225 }
2226
2227 std::string
2228 FunctionParam::as_string () const
2229 {
2230 // TODO: rewrite dump to allow non-literal types
2231 return param_name->as_string () + " : " + type->as_string ();
2232 }
2233
2234 std::string
2235 FunctionQualifiers::as_string () const
2236 {
2237 std::string str;
2238
2239 switch (const_status)
2240 {
2241 case NONE:
2242 // do nothing
2243 break;
2244 case CONST_FN:
2245 str += "const ";
2246 break;
2247 case ASYNC_FN:
2248 str += "async ";
2249 break;
2250 default:
2251 return "ERROR_MARK_STRING: async-const status failure";
2252 }
2253
2254 if (has_unsafe)
2255 str += "unsafe ";
2256
2257 if (has_extern)
2258 {
2259 str += "extern";
2260 if (extern_abi != "")
2261 str += " \"" + extern_abi + "\"";
2262 }
2263
2264 return str;
2265 }
2266
2267 std::string
2268 TraitBound::as_string () const
2269 {
2270 std::string str ("TraitBound:");
2271
2272 str += "\n Has opening question mark: ";
2273 if (opening_question_mark)
2274 str += "true";
2275 else
2276 str += "false";
2277
2278 str += "\n For lifetimes: ";
2279 if (!has_for_lifetimes ())
2280 {
2281 str += "none";
2282 }
2283 else
2284 {
2285 for (const auto &lifetime : for_lifetimes)
2286 str += "\n " + lifetime.as_string ();
2287 }
2288
2289 str += "\n Type path: " + type_path.as_string ();
2290
2291 return str;
2292 }
2293
2294 std::string
2295 MacroMatcher::as_string () const
2296 {
2297 std::string str ("Macro matcher: ");
2298
2299 str += "\n Delim type: ";
2300
2301 switch (delim_type)
2302 {
2303 case PARENS:
2304 str += "parentheses";
2305 break;
2306 case SQUARE:
2307 str += "square";
2308 break;
2309 case CURLY:
2310 str += "curly";
2311 break;
2312 default:
2313 return "ERROR_MARK_STRING - macro matcher delim";
2314 }
2315
2316 str += "\n Matches: ";
2317
2318 if (matches.empty ())
2319 {
2320 str += "none";
2321 }
2322 else
2323 {
2324 for (const auto &match : matches)
2325 str += "\n " + match->as_string ();
2326 }
2327
2328 return str;
2329 }
2330
2331 std::string
2332 LifetimeParam::as_string () const
2333 {
2334 std::string str ("LifetimeParam: ");
2335
2336 str += "\n Outer attribute: ";
2337 if (!has_outer_attribute ())
2338 str += "none";
2339 else
2340 str += outer_attr.as_string ();
2341
2342 str += "\n Lifetime: " + lifetime.as_string ();
2343
2344 str += "\n Lifetime bounds: ";
2345 if (!has_lifetime_bounds ())
2346 {
2347 str += "none";
2348 }
2349 else
2350 {
2351 for (const auto &bound : lifetime_bounds)
2352 str += "\n " + bound.as_string ();
2353 }
2354
2355 return str;
2356 }
2357
2358 std::string
2359 ConstGenericParam::as_string () const
2360 {
2361 std::string str ("ConstGenericParam: ");
2362 str += "const " + name + ": " + type->as_string ();
2363
2364 if (has_default_value ())
2365 str += " = " + get_default_value ().as_string ();
2366
2367 return str;
2368 }
2369
2370 std::string
2371 MacroMatchFragment::as_string () const
2372 {
2373 return "$" + ident + ": " + frag_spec.as_string ();
2374 }
2375
2376 std::string
2377 QualifiedPathInType::as_string () const
2378 {
2379 /* TODO: this may need adjusting if segments (e.g. with functions) can't be
2380 * literalised */
2381 std::string str = path_type.as_string ();
2382
2383 for (const auto &segment : segments)
2384 str += "::" + segment->as_string ();
2385
2386 return str;
2387 }
2388
2389 std::string
2390 MacroMatchRepetition::as_string () const
2391 {
2392 std::string str ("Macro match repetition: ");
2393
2394 str += "\n Matches: ";
2395 if (matches.empty ())
2396 {
2397 str += "none";
2398 }
2399 else
2400 {
2401 for (const auto &match : matches)
2402 str += "\n " + match->as_string ();
2403 }
2404
2405 str += "\n Sep: ";
2406 if (!has_sep ())
2407 str += "none";
2408 else
2409 str += sep->as_string ();
2410
2411 str += "\n Op: ";
2412 switch (op)
2413 {
2414 case ANY:
2415 str += "*";
2416 break;
2417 case ONE_OR_MORE:
2418 str += "+";
2419 break;
2420 case ZERO_OR_ONE:
2421 str += "?";
2422 break;
2423 case NONE:
2424 str += "no op? shouldn't be allowed";
2425 break;
2426 default:
2427 return "ERROR_MARK_STRING - unknown op in macro match repetition";
2428 }
2429
2430 return str;
2431 }
2432
2433 std::string
2434 Lifetime::as_string () const
2435 {
2436 if (is_error ())
2437 return "error lifetime";
2438
2439 switch (lifetime_type)
2440 {
2441 case NAMED:
2442 return "'" + lifetime_name;
2443 case STATIC:
2444 return "'static";
2445 case WILDCARD:
2446 return "'_";
2447 default:
2448 return "ERROR-MARK-STRING: lifetime type failure";
2449 }
2450 }
2451
2452 std::string
2453 TypePath::as_string () const
2454 {
2455 /* TODO: this may need to be rewritten if a segment (e.g. function) can't be
2456 * literalised */
2457 std::string str;
2458
2459 if (has_opening_scope_resolution)
2460 str = "::";
2461
2462 for (const auto &segment : segments)
2463 str += segment->as_string () + "::";
2464
2465 // kinda hack - remove last 2 '::' characters
2466 str.erase (str.length () - 2);
2467
2468 return str;
2469 }
2470
2471 std::string
2472 TypeParam::as_string () const
2473 {
2474 std::string str ("TypeParam: ");
2475
2476 str += "\n Outer attribute: ";
2477 if (!has_outer_attribute ())
2478 str += "none";
2479 else
2480 str += outer_attr.as_string ();
2481
2482 str += "\n Identifier: " + type_representation;
2483
2484 str += "\n Type param bounds: ";
2485 if (!has_type_param_bounds ())
2486 {
2487 str += "none";
2488 }
2489 else
2490 {
2491 for (const auto &bound : type_param_bounds)
2492 str += "\n " + bound->as_string ();
2493 }
2494
2495 str += "\n Type: ";
2496 if (!has_type ())
2497 str += "none";
2498 else
2499 str += type->as_string ();
2500
2501 return str;
2502 }
2503
2504 SimplePath
2505 PathPattern::convert_to_simple_path (bool with_opening_scope_resolution) const
2506 {
2507 if (!has_segments ())
2508 return SimplePath::create_empty ();
2509
2510 // create vector of reserved size (to minimise reallocations)
2511 std::vector<SimplePathSegment> simple_segments;
2512 simple_segments.reserve (segments.size ());
2513
2514 for (const auto &segment : segments)
2515 {
2516 // return empty path if doesn't meet simple path segment requirements
2517 if (segment.is_error () || segment.has_generic_args ()
2518 || segment.as_string () == "Self")
2519 return SimplePath::create_empty ();
2520
2521 // create segment and add to vector
2522 std::string segment_str = segment.as_string ();
2523 simple_segments.push_back (
2524 SimplePathSegment (std::move (segment_str), segment.get_locus ()));
2525 }
2526
2527 // kind of a HACK to get locus depending on opening scope resolution
2528 Location locus = Linemap::unknown_location ();
2529 if (with_opening_scope_resolution)
2530 locus = simple_segments[0].get_locus () - 2; // minus 2 chars for ::
2531 else
2532 locus = simple_segments[0].get_locus ();
2533 // FIXME: this hack probably doesn't actually work
2534
2535 return SimplePath (std::move (simple_segments), with_opening_scope_resolution,
2536 locus);
2537 }
2538
2539 SimplePath
2540 TypePath::as_simple_path () const
2541 {
2542 if (segments.empty ())
2543 return SimplePath::create_empty ();
2544
2545 // create vector of reserved size (to minimise reallocations)
2546 std::vector<SimplePathSegment> simple_segments;
2547 simple_segments.reserve (segments.size ());
2548
2549 for (const auto &segment : segments)
2550 {
2551 // return empty path if doesn't meet simple path segment requirements
2552 if (segment == nullptr || segment->is_error ()
2553 || !segment->is_ident_only () || segment->as_string () == "Self")
2554 return SimplePath::create_empty ();
2555
2556 // create segment and add to vector
2557 std::string segment_str = segment->as_string ();
2558 simple_segments.push_back (
2559 SimplePathSegment (std::move (segment_str), segment->get_locus ()));
2560 }
2561
2562 return SimplePath (std::move (simple_segments), has_opening_scope_resolution,
2563 locus);
2564 }
2565
2566 std::string
2567 PathExprSegment::as_string () const
2568 {
2569 // TODO: rewrite dump to work with non-literalisable types
2570 std::string ident_str = segment_name.as_string ();
2571 if (has_generic_args ())
2572 ident_str += "::<" + generic_args.as_string () + ">";
2573
2574 return ident_str;
2575 }
2576
2577 std::string
2578 GenericArgs::as_string () const
2579 {
2580 std::string args;
2581
2582 // lifetime args
2583 if (!lifetime_args.empty ())
2584 {
2585 auto i = lifetime_args.begin ();
2586 auto e = lifetime_args.end ();
2587
2588 for (; i != e; i++)
2589 {
2590 args += (*i).as_string ();
2591 if (e != i + 1)
2592 args += ", ";
2593 }
2594 }
2595
2596 // type args
2597 if (!generic_args.empty ())
2598 {
2599 auto i = generic_args.begin ();
2600 auto e = generic_args.end ();
2601
2602 for (; i != e; i++)
2603 {
2604 args += (*i).as_string ();
2605 if (e != i + 1)
2606 args += ", ";
2607 }
2608 }
2609
2610 // binding args
2611 if (!binding_args.empty ())
2612 {
2613 auto i = binding_args.begin ();
2614 auto e = binding_args.end ();
2615
2616 for (; i != e; i++)
2617 {
2618 args += (*i).as_string ();
2619 if (e != i + 1)
2620 args += ", ";
2621 }
2622 }
2623
2624 return args;
2625 }
2626
2627 std::string
2628 GenericArgsBinding::as_string () const
2629 {
2630 // TODO: rewrite to work with non-literalisable types
2631 return identifier + " = " + type->as_string ();
2632 }
2633
2634 std::string
2635 ForLoopExpr::as_string () const
2636 {
2637 std::string str = "ForLoopExpr: ";
2638
2639 str += append_attributes (outer_attrs, OUTER);
2640
2641 str += "\n Label: ";
2642 if (!has_loop_label ())
2643 str += "none";
2644 else
2645 str += loop_label.as_string ();
2646
2647 str += "\n Pattern: " + pattern->as_string ();
2648
2649 str += "\n Iterator expr: " + iterator_expr->as_string ();
2650
2651 str += "\n Loop block: " + loop_block->as_string ();
2652
2653 return str;
2654 }
2655
2656 std::string
2657 RangePattern::as_string () const
2658 {
2659 // TODO: maybe rewrite to work with non-linearisable bounds
2660 if (has_ellipsis_syntax)
2661 return lower->as_string () + "..." + upper->as_string ();
2662 else
2663 return lower->as_string () + "..=" + upper->as_string ();
2664 }
2665
2666 std::string
2667 RangePatternBoundLiteral::as_string () const
2668 {
2669 std::string str;
2670
2671 if (has_minus)
2672 str += "-";
2673
2674 str += literal.as_string ();
2675
2676 return str;
2677 }
2678
2679 std::string
2680 SlicePattern::as_string () const
2681 {
2682 std::string str ("SlicePattern: ");
2683
2684 for (const auto &pattern : items)
2685 str += "\n " + pattern->as_string ();
2686
2687 return str;
2688 }
2689
2690 std::string
2691 TuplePatternItemsMultiple::as_string () const
2692 {
2693 std::string str;
2694
2695 for (const auto &pattern : patterns)
2696 str += "\n " + pattern->as_string ();
2697
2698 return str;
2699 }
2700
2701 std::string
2702 TuplePatternItemsRanged::as_string () const
2703 {
2704 std::string str;
2705
2706 str += "\n Lower patterns: ";
2707 if (lower_patterns.empty ())
2708 {
2709 str += "none";
2710 }
2711 else
2712 {
2713 for (const auto &lower : lower_patterns)
2714 str += "\n " + lower->as_string ();
2715 }
2716
2717 str += "\n Upper patterns: ";
2718 if (upper_patterns.empty ())
2719 {
2720 str += "none";
2721 }
2722 else
2723 {
2724 for (const auto &upper : upper_patterns)
2725 str += "\n " + upper->as_string ();
2726 }
2727
2728 return str;
2729 }
2730
2731 std::string
2732 TuplePattern::as_string () const
2733 {
2734 return "TuplePattern: " + items->as_string ();
2735 }
2736
2737 std::string
2738 StructPatternField::as_string () const
2739 {
2740 // outer attributes
2741 std::string str = append_attributes (outer_attrs, OUTER);
2742
2743 return str;
2744 }
2745
2746 std::string
2747 StructPatternFieldIdent::as_string () const
2748 {
2749 std::string str = StructPatternField::as_string ();
2750
2751 str += "\n";
2752
2753 if (has_ref)
2754 str += "ref ";
2755
2756 if (has_mut)
2757 str += "mut ";
2758
2759 str += ident;
2760
2761 return str;
2762 }
2763
2764 std::string
2765 StructPatternFieldTuplePat::as_string () const
2766 {
2767 // TODO: maybe rewrite to work with non-linearisable patterns
2768 std::string str = StructPatternField::as_string ();
2769
2770 str += "\n";
2771
2772 str += std::to_string (index) + " : " + tuple_pattern->as_string ();
2773
2774 return str;
2775 }
2776
2777 std::string
2778 StructPatternFieldIdentPat::as_string () const
2779 {
2780 // TODO: maybe rewrite to work with non-linearisable patterns
2781 std::string str = StructPatternField::as_string ();
2782
2783 str += "\n";
2784
2785 str += ident + " : " + ident_pattern->as_string ();
2786
2787 return str;
2788 }
2789
2790 std::string
2791 StructPatternElements::as_string () const
2792 {
2793 std::string str ("\n Fields: ");
2794
2795 if (!has_struct_pattern_fields ())
2796 {
2797 str += "none";
2798 }
2799 else
2800 {
2801 for (const auto &field : fields)
2802 str += "\n " + field->as_string ();
2803 }
2804
2805 str += "\n Etc: ";
2806 if (has_struct_pattern_etc)
2807 str += "true";
2808 else
2809 str += "false";
2810
2811 return str;
2812 }
2813
2814 std::string
2815 StructPattern::as_string () const
2816 {
2817 std::string str ("StructPattern: \n Path: ");
2818
2819 str += path.as_string ();
2820
2821 str += "\n Struct pattern elems: ";
2822 if (!has_struct_pattern_elems ())
2823 str += "none";
2824 else
2825 str += elems.as_string ();
2826
2827 return str;
2828 }
2829
2830 std::string
2831 LiteralPattern::as_string () const
2832 {
2833 return lit.as_string ();
2834 }
2835
2836 std::string
2837 ReferencePattern::as_string () const
2838 {
2839 // TODO: maybe rewrite to work with non-linearisable patterns
2840 std::string str ("&");
2841
2842 if (has_two_amps)
2843 str += "&";
2844
2845 if (is_mut)
2846 str += "mut ";
2847
2848 str += pattern->as_string ();
2849
2850 return str;
2851 }
2852
2853 std::string
2854 IdentifierPattern::as_string () const
2855 {
2856 // TODO: maybe rewrite to work with non-linearisable patterns
2857 std::string str;
2858
2859 if (is_ref)
2860 str += "ref ";
2861
2862 if (is_mut)
2863 str += "mut ";
2864
2865 str += variable_ident;
2866
2867 if (has_pattern_to_bind ())
2868 str += " @ " + to_bind->as_string ();
2869
2870 return str;
2871 }
2872
2873 std::string
2874 TupleStructItemsNoRange::as_string () const
2875 {
2876 std::string str;
2877
2878 for (const auto &pattern : patterns)
2879 str += "\n " + pattern->as_string ();
2880
2881 return str;
2882 }
2883
2884 std::string
2885 TupleStructItemsRange::as_string () const
2886 {
2887 std::string str ("\n Lower patterns: ");
2888
2889 if (lower_patterns.empty ())
2890 {
2891 str += "none";
2892 }
2893 else
2894 {
2895 for (const auto &lower : lower_patterns)
2896 str += "\n " + lower->as_string ();
2897 }
2898
2899 str += "\n Upper patterns: ";
2900 if (upper_patterns.empty ())
2901 {
2902 str += "none";
2903 }
2904 else
2905 {
2906 for (const auto &upper : upper_patterns)
2907 str += "\n " + upper->as_string ();
2908 }
2909
2910 return str;
2911 }
2912
2913 std::string
2914 TupleStructPattern::as_string () const
2915 {
2916 std::string str ("TupleStructPattern: \n Path: ");
2917
2918 str += path.as_string ();
2919
2920 str += "\n Tuple struct items: " + items->as_string ();
2921
2922 return str;
2923 }
2924
2925 std::string
2926 LetStmt::as_string () const
2927 {
2928 // TODO: rewrite to work with non-linearisable types and exprs
2929 std::string str = append_attributes (outer_attrs, OUTER);
2930
2931 str += "\n" + indent_spaces (stay) + "let " + variables_pattern->as_string ();
2932
2933 if (has_type ())
2934 str += " : " + type->as_string ();
2935
2936 if (has_init_expr ())
2937 str += " = " + init_expr->as_string ();
2938
2939 return str;
2940 }
2941
2942 // hopefully definition here will prevent circular dependency issue
2943 TraitBound *
2944 TypePath::to_trait_bound (bool in_parens) const
2945 {
2946 return new TraitBound (TypePath (*this), get_locus (), in_parens);
2947 }
2948
2949 std::string
2950 InferredType::as_string () const
2951 {
2952 return "_ (inferred)";
2953 }
2954
2955 std::string
2956 TypeCastExpr::as_string () const
2957 {
2958 // TODO: rewrite to work with non-linearisable exprs and types
2959 return main_or_left_expr->as_string () + " as "
2960 + type_to_convert_to->as_string ();
2961 }
2962
2963 std::string
2964 ImplTraitType::as_string () const
2965 {
2966 std::string str ("ImplTraitType: \n TypeParamBounds: ");
2967
2968 if (type_param_bounds.empty ())
2969 {
2970 str += "none";
2971 }
2972 else
2973 {
2974 for (const auto &bound : type_param_bounds)
2975 str += "\n " + bound->as_string ();
2976 }
2977
2978 return str;
2979 }
2980
2981 std::string
2982 ReferenceType::as_string () const
2983 {
2984 // TODO: rewrite to work with non-linearisable types
2985 std::string str ("&");
2986
2987 if (has_lifetime ())
2988 str += lifetime.as_string () + " ";
2989
2990 if (has_mut)
2991 str += "mut ";
2992
2993 str += type->as_string ();
2994
2995 return str;
2996 }
2997
2998 std::string
2999 RawPointerType::as_string () const
3000 {
3001 // TODO: rewrite to work with non-linearisable types
3002 std::string str ("*");
3003
3004 switch (pointer_type)
3005 {
3006 case MUT:
3007 str += "mut ";
3008 break;
3009 case CONST:
3010 str += "const ";
3011 break;
3012 default:
3013 return "ERROR_MARK_STRING - unknown pointer type in raw pointer type";
3014 }
3015
3016 str += type->as_string ();
3017
3018 return str;
3019 }
3020
3021 std::string
3022 TraitObjectType::as_string () const
3023 {
3024 std::string str ("TraitObjectType: \n Has dyn dispatch: ");
3025
3026 if (has_dyn)
3027 str += "true";
3028 else
3029 str += "false";
3030
3031 str += "\n TypeParamBounds: ";
3032 if (type_param_bounds.empty ())
3033 {
3034 str += "none";
3035 }
3036 else
3037 {
3038 for (const auto &bound : type_param_bounds)
3039 str += "\n " + bound->as_string ();
3040 }
3041
3042 return str;
3043 }
3044
3045 std::string
3046 BareFunctionType::as_string () const
3047 {
3048 std::string str ("BareFunctionType: \n For lifetimes: ");
3049
3050 if (!has_for_lifetimes ())
3051 {
3052 str += "none";
3053 }
3054 else
3055 {
3056 for (const auto &for_lifetime : for_lifetimes)
3057 str += "\n " + for_lifetime.as_string ();
3058 }
3059
3060 str += "\n Qualifiers: " + function_qualifiers.as_string ();
3061
3062 str += "\n Params: ";
3063 if (params.empty ())
3064 {
3065 str += "none";
3066 }
3067 else
3068 {
3069 for (const auto &param : params)
3070 str += "\n " + param.as_string ();
3071 }
3072
3073 str += "\n Is variadic: ";
3074 if (is_variadic)
3075 str += "true";
3076 else
3077 str += "false";
3078
3079 str += "\n Return type: ";
3080 if (!has_return_type ())
3081 str += "none (void)";
3082 else
3083 str += return_type->as_string ();
3084
3085 return str;
3086 }
3087
3088 std::string
3089 ImplTraitTypeOneBound::as_string () const
3090 {
3091 std::string str ("ImplTraitTypeOneBound: \n TraitBound: ");
3092
3093 return str + trait_bound.as_string ();
3094 }
3095
3096 std::string
3097 TypePathSegmentGeneric::as_string () const
3098 {
3099 // TODO: rewrite to work with non-linearisable types
3100 return TypePathSegment::as_string () + "<" + generic_args.as_string () + ">";
3101 }
3102
3103 std::string
3104 TraitObjectTypeOneBound::as_string () const
3105 {
3106 std::string str ("TraitObjectTypeOneBound: \n Has dyn dispatch: ");
3107
3108 if (has_dyn)
3109 str += "true";
3110 else
3111 str += "false";
3112
3113 str += "\n TraitBound: " + trait_bound.as_string ();
3114
3115 return str;
3116 }
3117
3118 std::string
3119 TypePathFunction::as_string () const
3120 {
3121 // TODO: rewrite to work with non-linearisable types
3122 std::string str ("(");
3123
3124 if (has_inputs ())
3125 {
3126 auto i = inputs.begin ();
3127 auto e = inputs.end ();
3128
3129 for (; i != e; i++)
3130 {
3131 str += (*i)->as_string ();
3132 if (e != i + 1)
3133 str += ", ";
3134 }
3135 }
3136
3137 str += ")";
3138
3139 if (has_return_type ())
3140 str += " -> " + return_type->as_string ();
3141
3142 return str;
3143 }
3144
3145 std::string
3146 TypePathSegmentFunction::as_string () const
3147 {
3148 // TODO: rewrite to work with non-linearisable types
3149 return TypePathSegment::as_string () + function_path.as_string ();
3150 }
3151
3152 std::string
3153 ArrayType::as_string () const
3154 {
3155 // TODO: rewrite to work with non-linearisable types and exprs
3156 return "[" + elem_type->as_string () + "; " + size->as_string () + "]";
3157 }
3158
3159 std::string
3160 SliceType::as_string () const
3161 {
3162 // TODO: rewrite to work with non-linearisable types
3163 return "[" + elem_type->as_string () + "]";
3164 }
3165
3166 std::string
3167 TupleType::as_string () const
3168 {
3169 // TODO: rewrite to work with non-linearisable types
3170 std::string str ("(");
3171
3172 if (!is_unit_type ())
3173 {
3174 auto i = elems.begin ();
3175 auto e = elems.end ();
3176
3177 for (; i != e; i++)
3178 {
3179 str += (*i)->as_string ();
3180 if (e != i + 1)
3181 str += ", ";
3182 }
3183 }
3184
3185 str += ")";
3186
3187 return str;
3188 }
3189
3190 std::string
3191 StructExpr::as_string () const
3192 {
3193 std::string str = append_attributes (outer_attrs, OUTER);
3194 indent_spaces (enter);
3195 str += "\n" + indent_spaces (stay) + "StructExpr:";
3196 indent_spaces (enter);
3197 str += "\n" + indent_spaces (stay) + "PathInExpr:\n";
3198 str += indent_spaces (stay) + struct_name.as_string ();
3199 indent_spaces (out);
3200 indent_spaces (out);
3201 return str;
3202 }
3203
3204 std::string
3205 StructExprStruct::as_string () const
3206 {
3207 // TODO: doesn't this require data from StructExpr?
3208 std::string str ("StructExprStruct (or subclass): ");
3209
3210 str += "\n Path: " + get_struct_name ().as_string ();
3211
3212 // inner attributes
3213 str += append_attributes (inner_attrs, INNER);
3214
3215 return str;
3216 }
3217
3218 std::string
3219 StructBase::as_string () const
3220 {
3221 if (base_struct != nullptr)
3222 return base_struct->as_string ();
3223 else
3224 return "ERROR_MARK_STRING - invalid struct base had as string applied";
3225 }
3226
3227 std::string
3228 StructExprFieldWithVal::as_string () const
3229 {
3230 // used to get value string
3231 return value->as_string ();
3232 }
3233
3234 std::string
3235 StructExprFieldIdentifierValue::as_string () const
3236 {
3237 // TODO: rewrite to work with non-linearisable exprs
3238 return field_name + " : " + StructExprFieldWithVal::as_string ();
3239 }
3240
3241 std::string
3242 StructExprFieldIndexValue::as_string () const
3243 {
3244 // TODO: rewrite to work with non-linearisable exprs
3245 return std::to_string (index) + " : " + StructExprFieldWithVal::as_string ();
3246 }
3247
3248 std::string
3249 StructExprStructFields::as_string () const
3250 {
3251 std::string str = StructExprStruct::as_string ();
3252
3253 str += "\n Fields: ";
3254 if (fields.empty ())
3255 {
3256 str += "none";
3257 }
3258 else
3259 {
3260 for (const auto &field : fields)
3261 str += "\n " + field->as_string ();
3262 }
3263
3264 str += "\n Struct base: ";
3265 if (!has_struct_base ())
3266 str += "none";
3267 else
3268 str += struct_base.as_string ();
3269
3270 return str;
3271 }
3272
3273 std::string
3274 EnumItem::as_string () const
3275 {
3276 std::string str = VisItem::as_string ();
3277 str += variant_name;
3278
3279 return str;
3280 }
3281
3282 std::string
3283 EnumItemTuple::as_string () const
3284 {
3285 std::string str = EnumItem::as_string ();
3286
3287 // add tuple opening parens
3288 str += "(";
3289
3290 // tuple fields
3291 if (has_tuple_fields ())
3292 {
3293 auto i = tuple_fields.begin ();
3294 auto e = tuple_fields.end ();
3295
3296 for (; i != e; i++)
3297 {
3298 str += (*i).as_string ();
3299 if (e != i + 1)
3300 str += ", ";
3301 }
3302 }
3303
3304 // add tuple closing parens
3305 str += ")";
3306
3307 return str;
3308 }
3309
3310 std::string
3311 TupleField::as_string () const
3312 {
3313 // TODO: rewrite to work with non-linearisable exprs
3314
3315 // outer attributes
3316 std::string str = append_attributes (outer_attrs, OUTER);
3317
3318 if (has_visibility ())
3319 str += "\n" + visibility.as_string ();
3320
3321 str += " " + field_type->as_string ();
3322
3323 return str;
3324 }
3325
3326 std::string
3327 EnumItemStruct::as_string () const
3328 {
3329 std::string str = EnumItem::as_string ();
3330
3331 // add struct opening parens
3332 str += "{";
3333
3334 // tuple fields
3335 if (has_struct_fields ())
3336 {
3337 auto i = struct_fields.begin ();
3338 auto e = struct_fields.end ();
3339
3340 for (; i != e; i++)
3341 {
3342 str += (*i).as_string ();
3343 if (e != i + 1)
3344 str += ", ";
3345 }
3346 }
3347
3348 // add struct closing parens
3349 str += "}";
3350
3351 return str;
3352 }
3353
3354 std::string
3355 StructField::as_string () const
3356 {
3357 // TODO: rewrite to work with non-linearisable exprs
3358 // outer attributes
3359 std::string str = append_attributes (outer_attrs, OUTER);
3360
3361 if (has_visibility ())
3362 str += "\n" + visibility.as_string ();
3363
3364 str += " " + field_name + " : " + field_type->as_string ();
3365
3366 return str;
3367 }
3368
3369 std::string
3370 EnumItemDiscriminant::as_string () const
3371 {
3372 // TODO: rewrite to work with non-linearisable exprs
3373 std::string str = EnumItem::as_string ();
3374
3375 // add equal and expression
3376 str += " = " + expression->as_string ();
3377
3378 return str;
3379 }
3380
3381 std::string
3382 ExternalStaticItem::as_string () const
3383 {
3384 // outer attributes
3385 std::string str = append_attributes (outer_attrs, OUTER);
3386
3387 // start visibility on new line and with a space
3388 str += "\n" + visibility.as_string () + " ";
3389
3390 str += "static ";
3391
3392 if (has_mut)
3393 str += "mut ";
3394
3395 // add name
3396 str += item_name;
3397
3398 // add type on new line
3399 str += "\n Type: " + item_type->as_string ();
3400
3401 return str;
3402 }
3403
3404 std::string
3405 ExternalFunctionItem::as_string () const
3406 {
3407 // outer attributes
3408 std::string str = append_attributes (outer_attrs, OUTER);
3409
3410 // start visibility on new line and with a space
3411 str += "\n" + visibility.as_string () + " ";
3412
3413 str += "fn ";
3414
3415 // add name
3416 str += item_name;
3417
3418 // generic params
3419 str += "\n Generic params: ";
3420 if (generic_params.empty ())
3421 {
3422 str += "none";
3423 }
3424 else
3425 {
3426 for (const auto &param : generic_params)
3427 {
3428 // DEBUG: null pointer check
3429 if (param == nullptr)
3430 {
3431 rust_debug (
3432 "something really terrible has gone wrong - null pointer "
3433 "generic param in external function item.");
3434 return "NULL_POINTER_MARK";
3435 }
3436
3437 str += "\n " + param->as_string ();
3438 }
3439 }
3440
3441 // function params
3442 str += "\n Function params: ";
3443 if (function_params.empty () && !has_variadics)
3444 {
3445 str += "none";
3446 }
3447 else
3448 {
3449 for (const auto &param : function_params)
3450 str += "\n " + param.as_string ();
3451
3452 if (has_variadics)
3453 {
3454 str += "\n variadic outer attrs: ";
3455 if (has_variadic_outer_attrs ())
3456 {
3457 for (const auto &attr : variadic_outer_attrs)
3458 str += "\n " + attr.as_string ();
3459 }
3460 else
3461 {
3462 str += "none";
3463 }
3464 str += "\n ... (variadic)";
3465 }
3466 }
3467
3468 // add type on new line
3469 str += "\n (return) Type: "
3470 + (has_return_type () ? return_type->as_string () : "()");
3471
3472 // where clause
3473 str += "\n Where clause: ";
3474 if (has_where_clause ())
3475 str += where_clause.as_string ();
3476 else
3477 str += "none";
3478
3479 return str;
3480 }
3481
3482 std::string
3483 NamedFunctionParam::as_string () const
3484 {
3485 std::string str = append_attributes (outer_attrs, OUTER);
3486
3487 str += "\n" + name;
3488
3489 str += "\n Type: " + param_type->as_string ();
3490
3491 return str;
3492 }
3493
3494 std::string
3495 TraitItemFunc::as_string () const
3496 {
3497 std::string str = append_attributes (outer_attrs, OUTER);
3498
3499 str += "\n" + decl.as_string ();
3500
3501 str += "\n Definition (block expr): ";
3502 if (has_definition ())
3503 str += block_expr->as_string ();
3504 else
3505 str += "none";
3506
3507 return str;
3508 }
3509
3510 std::string
3511 TraitFunctionDecl::as_string () const
3512 {
3513 std::string str = qualifiers.as_string () + "fn " + function_name;
3514
3515 // generic params
3516 str += "\n Generic params: ";
3517 if (generic_params.empty ())
3518 {
3519 str += "none";
3520 }
3521 else
3522 {
3523 for (const auto &param : generic_params)
3524 {
3525 // DEBUG: null pointer check
3526 if (param == nullptr)
3527 {
3528 rust_debug (
3529 "something really terrible has gone wrong - null pointer "
3530 "generic param in trait function decl.");
3531 return "NULL_POINTER_MARK";
3532 }
3533
3534 str += "\n " + param->as_string ();
3535 }
3536 }
3537
3538 str += "\n Function params: ";
3539 if (has_params ())
3540 {
3541 for (const auto &param : function_params)
3542 str += "\n " + param.as_string ();
3543 }
3544 else
3545 {
3546 str += "none";
3547 }
3548
3549 str += "\n Return type: ";
3550 if (has_return_type ())
3551 str += return_type->as_string ();
3552 else
3553 str += "none (void)";
3554
3555 str += "\n Where clause: ";
3556 if (has_where_clause ())
3557 str += where_clause.as_string ();
3558 else
3559 str += "none";
3560
3561 return str;
3562 }
3563
3564 std::string
3565 TraitItemMethod::as_string () const
3566 {
3567 std::string str = append_attributes (outer_attrs, OUTER);
3568
3569 str += "\n" + decl.as_string ();
3570
3571 str += "\n Definition (block expr): ";
3572 if (has_definition ())
3573 str += block_expr->as_string ();
3574 else
3575 str += "none";
3576
3577 return str;
3578 }
3579
3580 std::string
3581 TraitMethodDecl::as_string () const
3582 {
3583 std::string str = qualifiers.as_string () + "fn " + function_name;
3584
3585 // generic params
3586 str += "\n Generic params: ";
3587 if (generic_params.empty ())
3588 {
3589 str += "none";
3590 }
3591 else
3592 {
3593 for (const auto &param : generic_params)
3594 {
3595 // DEBUG: null pointer check
3596 if (param == nullptr)
3597 {
3598 rust_debug (
3599 "something really terrible has gone wrong - null pointer "
3600 "generic param in trait function decl.");
3601 return "NULL_POINTER_MARK";
3602 }
3603
3604 str += "\n " + param->as_string ();
3605 }
3606 }
3607
3608 str += "\n Self param: " + self_param.as_string ();
3609
3610 str += "\n Function params: ";
3611 if (has_params ())
3612 {
3613 for (const auto &param : function_params)
3614 str += "\n " + param.as_string ();
3615 }
3616 else
3617 {
3618 str += "none";
3619 }
3620
3621 str += "\n Return type: ";
3622 if (has_return_type ())
3623 str += return_type->as_string ();
3624 else
3625 str += "none (void)";
3626
3627 str += "\n Where clause: ";
3628 if (has_where_clause ())
3629 str += where_clause.as_string ();
3630 else
3631 str += "none";
3632
3633 return str;
3634 }
3635
3636 std::string
3637 TraitItemConst::as_string () const
3638 {
3639 // TODO: rewrite to work with non-linearisable exprs
3640 std::string str = append_attributes (outer_attrs, OUTER);
3641
3642 str += "\nconst " + name + " : " + type->as_string ();
3643
3644 if (has_expression ())
3645 str += " = " + expr->as_string ();
3646
3647 return str;
3648 }
3649
3650 std::string
3651 TraitItemType::as_string () const
3652 {
3653 std::string str = append_attributes (outer_attrs, OUTER);
3654
3655 str += "\ntype " + name;
3656
3657 str += "\n Type param bounds: ";
3658 if (!has_type_param_bounds ())
3659 {
3660 str += "none";
3661 }
3662 else
3663 {
3664 for (const auto &bound : type_param_bounds)
3665 {
3666 // DEBUG: null pointer check
3667 if (bound == nullptr)
3668 {
3669 rust_debug (
3670 "something really terrible has gone wrong - null pointer "
3671 "type param bound in trait item type.");
3672 return "NULL_POINTER_MARK";
3673 }
3674
3675 str += "\n " + bound->as_string ();
3676 }
3677 }
3678
3679 return str;
3680 }
3681
3682 std::string
3683 SelfParam::as_string () const
3684 {
3685 // TODO: rewrite to allow non-linearisable types
3686 if (is_error ())
3687 {
3688 return "error";
3689 }
3690 else
3691 {
3692 if (has_type ())
3693 {
3694 // type (i.e. not ref, no lifetime)
3695 std::string str;
3696
3697 if (is_mut)
3698 str += "mut ";
3699
3700 str += "self : ";
3701
3702 str += type->as_string ();
3703
3704 return str;
3705 }
3706 else if (has_lifetime ())
3707 {
3708 // ref and lifetime
3709 std::string str = "&" + lifetime.as_string () + " ";
3710
3711 if (is_mut)
3712 str += "mut ";
3713
3714 str += "self";
3715
3716 return str;
3717 }
3718 else if (has_ref)
3719 {
3720 // ref with no lifetime
3721 std::string str = "&";
3722
3723 if (is_mut)
3724 str += " mut ";
3725
3726 str += "self";
3727
3728 return str;
3729 }
3730 else
3731 {
3732 // no ref, no type
3733 std::string str;
3734
3735 if (is_mut)
3736 str += "mut ";
3737
3738 str += "self";
3739
3740 return str;
3741 }
3742 }
3743 }
3744
3745 std::string
3746 ArrayElemsCopied::as_string () const
3747 {
3748 // TODO: rewrite to allow non-linearisable exprs
3749 return elem_to_copy->as_string () + "; " + num_copies->as_string ();
3750 }
3751
3752 std::string
3753 LifetimeWhereClauseItem::as_string () const
3754 {
3755 std::string str ("Lifetime: ");
3756
3757 str += lifetime.as_string ();
3758
3759 str += "\nLifetime bounds: ";
3760
3761 for (const auto &bound : lifetime_bounds)
3762 str += "\n " + bound.as_string ();
3763
3764 return str;
3765 }
3766
3767 std::string
3768 TypeBoundWhereClauseItem::as_string () const
3769 {
3770 std::string str ("For lifetimes: ");
3771
3772 if (!has_for_lifetimes ())
3773 {
3774 str += "none";
3775 }
3776 else
3777 {
3778 for (const auto &for_lifetime : for_lifetimes)
3779 str += "\n " + for_lifetime.as_string ();
3780 }
3781
3782 str += "\nType: " + bound_type->as_string ();
3783
3784 str += "\nType param bounds bounds: ";
3785
3786 for (const auto &bound : type_param_bounds)
3787 {
3788 // debug null pointer check
3789 if (bound == nullptr)
3790 return "NULL_POINTER_MARK - type param bounds";
3791
3792 str += "\n " + bound->as_string ();
3793 }
3794
3795 return str;
3796 }
3797
3798 std::string
3799 ArrayElemsValues::as_string () const
3800 {
3801 std::string str;
3802
3803 for (const auto &expr : values)
3804 {
3805 // DEBUG: null pointer check
3806 if (expr == nullptr)
3807 {
3808 rust_debug ("something really terrible has gone wrong - null pointer "
3809 "expr in array elems values.");
3810 return "NULL_POINTER_MARK";
3811 }
3812
3813 str += "\n " + expr->as_string ();
3814 }
3815
3816 return str;
3817 }
3818
3819 std::string
3820 MaybeNamedParam::as_string () const
3821 {
3822 // TODO: rewrite to allow using non-linearisable types in dump
3823 std::string str;
3824
3825 switch (param_kind)
3826 {
3827 case UNNAMED:
3828 break;
3829 case IDENTIFIER:
3830 str = name + " : ";
3831 break;
3832 case WILDCARD:
3833 str = "_ : ";
3834 break;
3835 default:
3836 return "ERROR_MARK_STRING - maybe named param unrecognised param kind";
3837 }
3838
3839 str += param_type->as_string ();
3840
3841 return str;
3842 }
3843
3844 MetaItemInner::~MetaItemInner () = default;
3845
3846 std::unique_ptr<MetaNameValueStr>
3847 MetaItemInner::to_meta_name_value_str () const
3848 {
3849 if (is_key_value_pair ())
3850 {
3851 auto converted_item = static_cast<const MetaNameValueStr *> (this);
3852 return converted_item->to_meta_name_value_str ();
3853 }
3854 // TODO actually parse foo = bar
3855 return nullptr;
3856 }
3857
3858 std::string
3859 MetaItemSeq::as_string () const
3860 {
3861 std::string path_str = path.as_string () + "(";
3862
3863 auto i = seq.begin ();
3864 auto e = seq.end ();
3865
3866 for (; i != e; i++)
3867 {
3868 path_str += (*i)->as_string ();
3869 if (e != i + 1)
3870 path_str += ", ";
3871 }
3872
3873 return path_str + ")";
3874 }
3875
3876 std::string
3877 MetaListPaths::as_string () const
3878 {
3879 std::string str = ident + "(";
3880
3881 auto i = paths.begin ();
3882 auto e = paths.end ();
3883
3884 for (; i != e; i++)
3885 {
3886 str += (*i).as_string ();
3887 if (e != i + 1)
3888 str += ", ";
3889 }
3890
3891 return str + ")";
3892 }
3893
3894 std::string
3895 MetaListNameValueStr::as_string () const
3896 {
3897 std::string str = ident + "(";
3898
3899 auto i = strs.begin ();
3900 auto e = strs.end ();
3901
3902 for (; i != e; i++)
3903 {
3904 str += (*i).as_string ();
3905 if (e != i + 1)
3906 str += ", ";
3907 }
3908
3909 return str + ")";
3910 }
3911
3912 std::string
3913 AttrInputMetaItemContainer::as_string () const
3914 {
3915 std::string str = "(";
3916
3917 auto i = items.begin ();
3918 auto e = items.end ();
3919
3920 for (; i != e; i++)
3921 {
3922 str += (*i)->as_string ();
3923 if (e != i + 1)
3924 str += ", ";
3925 }
3926
3927 return str + ")";
3928 }
3929
3930 /* Override that calls the function recursively on all items contained within
3931 * the module. */
3932 void
3933 Module::add_crate_name (std::vector<std::string> &names) const
3934 {
3935 /* TODO: test whether module has been 'cfg'-ed out to determine whether to
3936 * exclude it from search */
3937
3938 for (const auto &item : items)
3939 item->add_crate_name (names);
3940 }
3941
3942 static bool
3943 file_exists (const std::string path)
3944 {
3945 // Simply check if the file exists
3946 // FIXME: This does not work on Windows
3947 return access (path.c_str (), F_OK) != -1;
3948 }
3949
3950 static std::string
3951 filename_from_path_attribute (std::vector<Attribute> &outer_attrs)
3952 {
3953 // An out-of-line module cannot have inner attributes. Additionally, the
3954 // default name is specified as `""` so that the caller can detect the case
3955 // of "no path given" and use the default path logic (`name.rs` or
3956 // `name/mod.rs`).
3957 return extract_module_path ({}, outer_attrs, "");
3958 }
3959
3960 void
3961 Module::process_file_path ()
3962 {
3963 rust_assert (kind == Module::ModuleKind::UNLOADED);
3964 rust_assert (module_file.empty ());
3965
3966 // This corresponds to the path of the file 'including' the module. So the
3967 // file that contains the 'mod <file>;' directive
3968 std::string including_fname (outer_filename);
3969
3970 std::string expected_file_path = module_name + ".rs";
3971 std::string expected_dir_path = "mod.rs";
3972
3973 auto dir_slash_pos = including_fname.rfind (file_separator);
3974 std::string current_directory_name;
3975
3976 // If we haven't found a file_separator, then we have to look for files in the
3977 // current directory ('.')
3978 if (dir_slash_pos == std::string::npos)
3979 current_directory_name = std::string (".") + file_separator;
3980 else
3981 current_directory_name
3982 = including_fname.substr (0, dir_slash_pos) + file_separator;
3983
3984 // Handle inline module declarations adding path components.
3985 for (auto const &name : module_scope)
3986 {
3987 current_directory_name.append (name);
3988 current_directory_name.append (file_separator);
3989 }
3990
3991 auto path_string = filename_from_path_attribute (get_outer_attrs ());
3992 if (!path_string.empty ())
3993 {
3994 module_file = current_directory_name + path_string;
3995 return;
3996 }
3997
3998 // FIXME: We also have to search for
3999 // <directory>/<including_fname>/<module_name>.rs In rustc, this is done via
4000 // the concept of `DirOwnernship`, which is based on whether or not the
4001 // current file is titled `mod.rs`.
4002
4003 // First, we search for <directory>/<module_name>.rs
4004 std::string file_mod_path = current_directory_name + expected_file_path;
4005 bool file_mod_found = file_exists (file_mod_path);
4006
4007 // Then, search for <directory>/<module_name>/mod.rs
4008 std::string dir_mod_path
4009 = current_directory_name + module_name + file_separator + expected_dir_path;
4010 bool dir_mod_found = file_exists (dir_mod_path);
4011
4012 bool multiple_candidates_found = file_mod_found && dir_mod_found;
4013 bool no_candidates_found = !file_mod_found && !dir_mod_found;
4014
4015 if (multiple_candidates_found)
4016 rust_error_at (locus,
4017 "two candidates found for module %s: %s.rs and %s%smod.rs",
4018 module_name.c_str (), module_name.c_str (),
4019 module_name.c_str (), file_separator);
4020
4021 if (no_candidates_found)
4022 rust_error_at (locus, "no candidate found for module %s",
4023 module_name.c_str ());
4024
4025 if (no_candidates_found || multiple_candidates_found)
4026 return;
4027
4028 module_file = std::move (file_mod_found ? file_mod_path : dir_mod_path);
4029 }
4030
4031 void
4032 Module::load_items ()
4033 {
4034 process_file_path ();
4035
4036 // We will already have errored out appropriately in the process_file_path ()
4037 // method
4038 if (module_file.empty ())
4039 return;
4040
4041 RAIIFile file_wrap (module_file.c_str ());
4042 Linemap *linemap = Session::get_instance ().linemap;
4043 if (!file_wrap.ok ())
4044 {
4045 rust_error_at (get_locus (), "cannot open module file %s: %m",
4046 module_file.c_str ());
4047 return;
4048 }
4049
4050 rust_debug ("Attempting to parse file %s", module_file.c_str ());
4051
4052 Lexer lex (module_file.c_str (), std::move (file_wrap), linemap);
4053 Parser<Lexer> parser (lex);
4054
4055 // we need to parse any possible inner attributes for this module
4056 inner_attrs = parser.parse_inner_attributes ();
4057 auto parsed_items = parser.parse_items ();
4058 for (const auto &error : parser.get_errors ())
4059 error.emit_error ();
4060
4061 items = std::move (parsed_items);
4062 kind = ModuleKind::LOADED;
4063 }
4064
4065 void
4066 Attribute::parse_attr_to_meta_item ()
4067 {
4068 // only parse if has attribute input and not already parsed
4069 if (!has_attr_input () || is_parsed_to_meta_item ())
4070 return;
4071
4072 auto res = attr_input->parse_to_meta_item ();
4073 std::unique_ptr<AttrInput> converted_input (res);
4074
4075 if (converted_input != nullptr)
4076 attr_input = std::move (converted_input);
4077 }
4078
4079 AttrInputMetaItemContainer *
4080 DelimTokenTree::parse_to_meta_item () const
4081 {
4082 // must have token trees
4083 if (token_trees.empty ())
4084 return nullptr;
4085
4086 /* assume top-level delim token tree in attribute - convert all nested ones
4087 * to token stream */
4088 std::vector<std::unique_ptr<Token>> token_stream = to_token_stream ();
4089
4090 AttributeParser parser (std::move (token_stream));
4091 std::vector<std::unique_ptr<MetaItemInner>> meta_items (
4092 parser.parse_meta_item_seq ());
4093
4094 return new AttrInputMetaItemContainer (std::move (meta_items));
4095 }
4096
4097 std::unique_ptr<MetaItemInner>
4098 AttributeParser::parse_meta_item_inner ()
4099 {
4100 // if first tok not identifier, not a "special" case one
4101 if (peek_token ()->get_id () != IDENTIFIER)
4102 {
4103 switch (peek_token ()->get_id ())
4104 {
4105 case CHAR_LITERAL:
4106 case STRING_LITERAL:
4107 case BYTE_CHAR_LITERAL:
4108 case BYTE_STRING_LITERAL:
4109 case INT_LITERAL:
4110 case FLOAT_LITERAL:
4111 case TRUE_LITERAL:
4112 case FALSE_LITERAL:
4113 return parse_meta_item_lit ();
4114
4115 case SUPER:
4116 case SELF:
4117 case CRATE:
4118 case DOLLAR_SIGN:
4119 case SCOPE_RESOLUTION:
4120 return parse_path_meta_item ();
4121
4122 default:
4123 rust_error_at (peek_token ()->get_locus (),
4124 "unrecognised token '%s' in meta item",
4125 get_token_description (peek_token ()->get_id ()));
4126 return nullptr;
4127 }
4128 }
4129
4130 // else, check for path
4131 if (peek_token (1)->get_id () == SCOPE_RESOLUTION)
4132 {
4133 // path
4134 return parse_path_meta_item ();
4135 }
4136
4137 auto ident = peek_token ()->as_string ();
4138 auto ident_locus = peek_token ()->get_locus ();
4139
4140 if (is_end_meta_item_tok (peek_token (1)->get_id ()))
4141 {
4142 // meta word syntax
4143 skip_token ();
4144 return std::unique_ptr<MetaWord> (new MetaWord (ident, ident_locus));
4145 }
4146
4147 if (peek_token (1)->get_id () == EQUAL)
4148 {
4149 // maybe meta name value str syntax - check next 2 tokens
4150 if (peek_token (2)->get_id () == STRING_LITERAL
4151 && is_end_meta_item_tok (peek_token (3)->get_id ()))
4152 {
4153 // meta name value str syntax
4154 auto &value_tok = peek_token (2);
4155 auto value = value_tok->as_string ();
4156 auto locus = value_tok->get_locus ();
4157
4158 skip_token (2);
4159
4160 // remove the quotes from the string value
4161 std::string raw_value = unquote_string (std::move (value));
4162
4163 return std::unique_ptr<MetaNameValueStr> (
4164 new MetaNameValueStr (ident, ident_locus, std::move (raw_value),
4165 locus));
4166 }
4167 else
4168 {
4169 // just interpret as path-based meta item
4170 return parse_path_meta_item ();
4171 }
4172 }
4173
4174 if (peek_token (1)->get_id () != LEFT_PAREN)
4175 {
4176 rust_error_at (peek_token (1)->get_locus (),
4177 "unexpected token '%s' after identifier in attribute",
4178 get_token_description (peek_token (1)->get_id ()));
4179 return nullptr;
4180 }
4181
4182 // is it one of those special cases like not?
4183 if (peek_token ()->get_id () == IDENTIFIER)
4184 {
4185 return parse_path_meta_item ();
4186 }
4187
4188 auto meta_items = parse_meta_item_seq ();
4189
4190 // pass for meta name value str
4191 std::vector<MetaNameValueStr> meta_name_value_str_items;
4192 for (const auto &item : meta_items)
4193 {
4194 std::unique_ptr<MetaNameValueStr> converted_item
4195 = item->to_meta_name_value_str ();
4196 if (converted_item == nullptr)
4197 {
4198 meta_name_value_str_items.clear ();
4199 break;
4200 }
4201 meta_name_value_str_items.push_back (std::move (*converted_item));
4202 }
4203 // if valid, return this
4204 if (!meta_name_value_str_items.empty ())
4205 {
4206 return std::unique_ptr<MetaListNameValueStr> (
4207 new MetaListNameValueStr (ident, ident_locus,
4208 std::move (meta_name_value_str_items)));
4209 }
4210
4211 // // pass for meta list idents
4212 // std::vector<Identifier> ident_items;
4213 // for (const auto &item : meta_items)
4214 // {
4215 // std::unique_ptr<Identifier> converted_ident (item->to_ident_item ());
4216 // if (converted_ident == nullptr)
4217 // {
4218 // ident_items.clear ();
4219 // break;
4220 // }
4221 // ident_items.push_back (std::move (*converted_ident));
4222 // }
4223 // // if valid return this
4224 // if (!ident_items.empty ())
4225 // {
4226 // return std::unique_ptr<MetaListIdents> (
4227 // new MetaListIdents (std::move (ident), std::move (ident_items)));
4228 // }
4229 // // as currently no meta list ident, currently no path. may change in future
4230
4231 // pass for meta list paths
4232 std::vector<SimplePath> path_items;
4233 for (const auto &item : meta_items)
4234 {
4235 SimplePath converted_path (item->to_path_item ());
4236 if (converted_path.is_empty ())
4237 {
4238 path_items.clear ();
4239 break;
4240 }
4241 path_items.push_back (std::move (converted_path));
4242 }
4243 if (!path_items.empty ())
4244 {
4245 return std::unique_ptr<MetaListPaths> (
4246 new MetaListPaths (ident, ident_locus, std::move (path_items)));
4247 }
4248
4249 rust_error_at (Linemap::unknown_location (),
4250 "failed to parse any meta item inner");
4251 return nullptr;
4252 }
4253
4254 bool
4255 AttributeParser::is_end_meta_item_tok (TokenId id) const
4256 {
4257 return id == COMMA || id == RIGHT_PAREN;
4258 }
4259
4260 std::unique_ptr<MetaItem>
4261 AttributeParser::parse_path_meta_item ()
4262 {
4263 SimplePath path = parse_simple_path ();
4264 if (path.is_empty ())
4265 {
4266 rust_error_at (peek_token ()->get_locus (),
4267 "failed to parse simple path in attribute");
4268 return nullptr;
4269 }
4270
4271 switch (peek_token ()->get_id ())
4272 {
4273 case LEFT_PAREN: {
4274 std::vector<std::unique_ptr<MetaItemInner>> meta_items
4275 = parse_meta_item_seq ();
4276
4277 return std::unique_ptr<MetaItemSeq> (
4278 new MetaItemSeq (std::move (path), std::move (meta_items)));
4279 }
4280 case EQUAL: {
4281 skip_token ();
4282
4283 Location locus = peek_token ()->get_locus ();
4284 Literal lit = parse_literal ();
4285 if (lit.is_error ())
4286 {
4287 rust_error_at (peek_token ()->get_locus (),
4288 "failed to parse literal in attribute");
4289 return nullptr;
4290 }
4291 LiteralExpr expr (std::move (lit), {}, locus);
4292 // stream_pos++;
4293 /* shouldn't be required anymore due to parsing literal actually
4294 * skipping the token */
4295 return std::unique_ptr<MetaItemPathLit> (
4296 new MetaItemPathLit (std::move (path), std::move (expr)));
4297 }
4298 case COMMA:
4299 // just simple path
4300 return std::unique_ptr<MetaItemPath> (
4301 new MetaItemPath (std::move (path)));
4302 default:
4303 rust_error_at (peek_token ()->get_locus (),
4304 "unrecognised token '%s' in meta item",
4305 get_token_description (peek_token ()->get_id ()));
4306 return nullptr;
4307 }
4308 }
4309
4310 /* Parses a parenthesised sequence of meta item inners. Parentheses are
4311 * required here. */
4312 std::vector<std::unique_ptr<MetaItemInner>>
4313 AttributeParser::parse_meta_item_seq ()
4314 {
4315 int vec_length = token_stream.size ();
4316 std::vector<std::unique_ptr<MetaItemInner>> meta_items;
4317
4318 if (peek_token ()->get_id () != LEFT_PAREN)
4319 {
4320 rust_error_at (peek_token ()->get_locus (),
4321 "missing left paren in delim token tree");
4322 return {};
4323 }
4324 skip_token ();
4325
4326 while (stream_pos < vec_length && peek_token ()->get_id () != RIGHT_PAREN)
4327 {
4328 std::unique_ptr<MetaItemInner> inner = parse_meta_item_inner ();
4329 if (inner == nullptr)
4330 {
4331 rust_error_at (peek_token ()->get_locus (),
4332 "failed to parse inner meta item in attribute");
4333 return {};
4334 }
4335 meta_items.push_back (std::move (inner));
4336
4337 if (peek_token ()->get_id () != COMMA)
4338 break;
4339
4340 skip_token ();
4341 }
4342
4343 if (peek_token ()->get_id () != RIGHT_PAREN)
4344 {
4345 rust_error_at (peek_token ()->get_locus (),
4346 "missing right paren in delim token tree");
4347 return {};
4348 }
4349 skip_token ();
4350
4351 return meta_items;
4352 }
4353
4354 /* Collects any nested token trees into a flat token stream, suitable for
4355 * parsing. */
4356 std::vector<std::unique_ptr<Token>>
4357 DelimTokenTree::to_token_stream () const
4358 {
4359 std::vector<std::unique_ptr<Token>> tokens;
4360 for (const auto &tree : token_trees)
4361 {
4362 std::vector<std::unique_ptr<Token>> stream = tree->to_token_stream ();
4363
4364 tokens.insert (tokens.end (), std::make_move_iterator (stream.begin ()),
4365 std::make_move_iterator (stream.end ()));
4366 }
4367
4368 tokens.shrink_to_fit ();
4369 return tokens;
4370 }
4371
4372 Literal
4373 AttributeParser::parse_literal ()
4374 {
4375 const std::unique_ptr<Token> &tok = peek_token ();
4376 switch (tok->get_id ())
4377 {
4378 case CHAR_LITERAL:
4379 skip_token ();
4380 return Literal (tok->as_string (), Literal::CHAR, tok->get_type_hint ());
4381 case STRING_LITERAL:
4382 skip_token ();
4383 return Literal (tok->as_string (), Literal::STRING,
4384 tok->get_type_hint ());
4385 case BYTE_CHAR_LITERAL:
4386 skip_token ();
4387 return Literal (tok->as_string (), Literal::BYTE, tok->get_type_hint ());
4388 case BYTE_STRING_LITERAL:
4389 skip_token ();
4390 return Literal (tok->as_string (), Literal::BYTE_STRING,
4391 tok->get_type_hint ());
4392 case INT_LITERAL:
4393 skip_token ();
4394 return Literal (tok->as_string (), Literal::INT, tok->get_type_hint ());
4395 case FLOAT_LITERAL:
4396 skip_token ();
4397 return Literal (tok->as_string (), Literal::FLOAT, tok->get_type_hint ());
4398 case TRUE_LITERAL:
4399 skip_token ();
4400 return Literal ("true", Literal::BOOL, tok->get_type_hint ());
4401 case FALSE_LITERAL:
4402 skip_token ();
4403 return Literal ("false", Literal::BOOL, tok->get_type_hint ());
4404 default:
4405 rust_error_at (tok->get_locus (), "expected literal - found '%s'",
4406 get_token_description (tok->get_id ()));
4407 return Literal::create_error ();
4408 }
4409 }
4410
4411 SimplePath
4412 AttributeParser::parse_simple_path ()
4413 {
4414 bool has_opening_scope_res = false;
4415 if (peek_token ()->get_id () == SCOPE_RESOLUTION)
4416 {
4417 has_opening_scope_res = true;
4418 skip_token ();
4419 }
4420
4421 std::vector<SimplePathSegment> segments;
4422
4423 SimplePathSegment segment = parse_simple_path_segment ();
4424 if (segment.is_error ())
4425 {
4426 rust_error_at (
4427 peek_token ()->get_locus (),
4428 "failed to parse simple path segment in attribute simple path");
4429 return SimplePath::create_empty ();
4430 }
4431 segments.push_back (std::move (segment));
4432
4433 while (peek_token ()->get_id () == SCOPE_RESOLUTION)
4434 {
4435 skip_token ();
4436
4437 SimplePathSegment segment = parse_simple_path_segment ();
4438 if (segment.is_error ())
4439 {
4440 rust_error_at (
4441 peek_token ()->get_locus (),
4442 "failed to parse simple path segment in attribute simple path");
4443 return SimplePath::create_empty ();
4444 }
4445 segments.push_back (std::move (segment));
4446 }
4447 segments.shrink_to_fit ();
4448
4449 return SimplePath (std::move (segments), has_opening_scope_res);
4450 }
4451
4452 SimplePathSegment
4453 AttributeParser::parse_simple_path_segment ()
4454 {
4455 const std::unique_ptr<Token> &tok = peek_token ();
4456 switch (tok->get_id ())
4457 {
4458 case IDENTIFIER:
4459 skip_token ();
4460 return SimplePathSegment (tok->as_string (), tok->get_locus ());
4461 case SUPER:
4462 skip_token ();
4463 return SimplePathSegment ("super", tok->get_locus ());
4464 case SELF:
4465 skip_token ();
4466 return SimplePathSegment ("self", tok->get_locus ());
4467 case CRATE:
4468 skip_token ();
4469 return SimplePathSegment ("crate", tok->get_locus ());
4470 case DOLLAR_SIGN:
4471 if (peek_token (1)->get_id () == CRATE)
4472 {
4473 skip_token (1);
4474 return SimplePathSegment ("$crate", tok->get_locus ());
4475 }
4476 gcc_fallthrough ();
4477 default:
4478 rust_error_at (tok->get_locus (),
4479 "unexpected token '%s' in simple path segment",
4480 get_token_description (tok->get_id ()));
4481 return SimplePathSegment::create_error ();
4482 }
4483 }
4484
4485 std::unique_ptr<MetaItemLitExpr>
4486 AttributeParser::parse_meta_item_lit ()
4487 {
4488 Location locus = peek_token ()->get_locus ();
4489 LiteralExpr lit_expr (parse_literal (), {}, locus);
4490 return std::unique_ptr<MetaItemLitExpr> (
4491 new MetaItemLitExpr (std::move (lit_expr)));
4492 }
4493
4494 bool
4495 AttrInputMetaItemContainer::check_cfg_predicate (const Session &session) const
4496 {
4497 if (items.empty ())
4498 return false;
4499
4500 for (const auto &inner_item : items)
4501 {
4502 if (!inner_item->check_cfg_predicate (session))
4503 return false;
4504 }
4505
4506 return true;
4507 }
4508
4509 bool
4510 MetaItemLitExpr::check_cfg_predicate (const Session &) const
4511 {
4512 /* as far as I can tell, a literal expr can never be a valid cfg body, so
4513 * false */
4514 return false;
4515 }
4516
4517 bool
4518 MetaListNameValueStr::check_cfg_predicate (const Session &session) const
4519 {
4520 if (ident == "all")
4521 {
4522 for (const auto &str : strs)
4523 {
4524 if (!str.check_cfg_predicate (session))
4525 return false;
4526 }
4527 return true;
4528 }
4529 else if (ident == "any")
4530 {
4531 for (const auto &str : strs)
4532 {
4533 if (str.check_cfg_predicate (session))
4534 return true;
4535 }
4536 return false;
4537 }
4538 else if (ident == "not")
4539 {
4540 if (strs.size () != 1)
4541 {
4542 /* HACK: convert vector platform-dependent size_type to string to
4543 * use in printf */
4544 rust_error_at (Linemap::unknown_location (),
4545 "cfg predicate could not be checked for "
4546 "MetaListNameValueStr with ident of "
4547 "'not' because there are '%s' elements, not '1'",
4548 std::to_string (strs.size ()).c_str ());
4549 return false;
4550 }
4551
4552 return !strs[0].check_cfg_predicate (session);
4553 }
4554 else
4555 {
4556 rust_error_at (Linemap::unknown_location (),
4557 "cfg predicate could not be checked for "
4558 "MetaListNameValueStr with ident of "
4559 "'%s' - ident must be 'all' or 'any'",
4560 ident.c_str ());
4561 return false;
4562 }
4563 }
4564
4565 bool
4566 MetaListPaths::check_cfg_predicate (const Session &session) const
4567 {
4568 if (ident == "all")
4569 {
4570 for (const auto &path : paths)
4571 {
4572 if (!check_path_exists_in_cfg (session, path))
4573 return false;
4574 }
4575 return true;
4576 }
4577 else if (ident == "any")
4578 {
4579 for (const auto &path : paths)
4580 {
4581 if (check_path_exists_in_cfg (session, path))
4582 return true;
4583 }
4584 return false;
4585 }
4586 else if (ident == "not")
4587 {
4588 if (paths.size () != 1)
4589 {
4590 // HACK: convert vector platform-dependent size_type to string to
4591 // use in printf
4592 rust_error_at (Linemap::unknown_location (),
4593 "cfg predicate could not be checked for MetaListPaths "
4594 "with ident of 'not' "
4595 "because there are '%s' elements, not '1'",
4596 std::to_string (paths.size ()).c_str ());
4597 return false;
4598 }
4599
4600 return !check_path_exists_in_cfg (session, paths[0]);
4601 }
4602 else
4603 {
4604 rust_error_at (Linemap::unknown_location (),
4605 "cfg predicate could not be checked for "
4606 "MetaListNameValueStr with ident of "
4607 "'%s' - ident must be 'all' or 'any'",
4608 ident.c_str ());
4609 return false;
4610 }
4611 }
4612
4613 bool
4614 MetaListPaths::check_path_exists_in_cfg (const Session &session,
4615 const SimplePath &path) const
4616 {
4617 return session.options.target_data.has_key (path.as_string ());
4618 }
4619
4620 bool
4621 MetaItemSeq::check_cfg_predicate (const Session &session) const
4622 {
4623 if (path.as_string () == "all")
4624 {
4625 for (const auto &item : seq)
4626 {
4627 if (!item->check_cfg_predicate (session))
4628 return false;
4629 }
4630 return true;
4631 }
4632 else if (path.as_string () == "any")
4633 {
4634 for (const auto &item : seq)
4635 {
4636 if (item->check_cfg_predicate (session))
4637 return true;
4638 }
4639 return false;
4640 }
4641 else if (path.as_string () == "not")
4642 {
4643 if (seq.size () != 1)
4644 {
4645 /* HACK: convert vector platform-dependent size_type to string to
4646 * use in printf */
4647 rust_error_at (Linemap::unknown_location (),
4648 "cfg predicate could not be checked for MetaItemSeq "
4649 "with ident of 'not' "
4650 "because there are '%s' elements, not '1'",
4651 std::to_string (seq.size ()).c_str ());
4652 return false;
4653 }
4654
4655 return !seq[0]->check_cfg_predicate (session);
4656 }
4657 else
4658 {
4659 rust_error_at (
4660 Linemap::unknown_location (),
4661 "cfg predicate could not be checked for MetaItemSeq with path of "
4662 "'%s' - path must be 'all' or 'any'",
4663 path.as_string ().c_str ());
4664 return false;
4665 }
4666 }
4667
4668 bool
4669 MetaWord::check_cfg_predicate (const Session &session) const
4670 {
4671 return session.options.target_data.has_key (ident);
4672 }
4673
4674 bool
4675 MetaItemPath::check_cfg_predicate (const Session &session) const
4676 {
4677 /* Strictly speaking, this should always be false, but maybe do check
4678 * relating to SimplePath being identifier. Currently, it would return true
4679 * if path as identifier existed, and if the path in string form existed
4680 * (though this shouldn't occur). */
4681 return session.options.target_data.has_key (path.as_string ());
4682 }
4683
4684 bool
4685 MetaNameValueStr::check_cfg_predicate (const Session &session) const
4686 {
4687 // DEBUG
4688 rust_debug (
4689 "checked key-value pair for cfg: '%s', '%s' - is%s in target data",
4690 ident.c_str (), str.c_str (),
4691 session.options.target_data.has_key_value_pair (ident, str) ? "" : " not");
4692
4693 return session.options.target_data.has_key_value_pair (ident, str);
4694 }
4695
4696 bool
4697 MetaItemPathLit::check_cfg_predicate (const Session &session) const
4698 {
4699 return session.options.target_data.has_key_value_pair (path.as_string (),
4700 lit.as_string ());
4701 }
4702
4703 std::vector<std::unique_ptr<Token>>
4704 Token::to_token_stream () const
4705 {
4706 /* initialisation list doesn't work as it needs copy constructor, so have to
4707 * do this */
4708 std::vector<std::unique_ptr<Token>> dummy_vector;
4709 dummy_vector.reserve (1);
4710 dummy_vector.push_back (std::unique_ptr<Token> (clone_token_impl ()));
4711 return dummy_vector;
4712 }
4713
4714 Attribute
4715 MetaNameValueStr::to_attribute () const
4716 {
4717 LiteralExpr lit_expr (str, Literal::LitType::STRING,
4718 PrimitiveCoreType::CORETYPE_UNKNOWN, {}, str_locus);
4719 // FIXME: What location do we put here? Is the literal above supposed to have
4720 // an empty location as well?
4721 // Should MetaNameValueStr keep a location?
4722 return Attribute (SimplePath::from_str (ident, ident_locus),
4723 std::unique_ptr<AttrInputLiteral> (
4724 new AttrInputLiteral (std::move (lit_expr))));
4725 }
4726
4727 Attribute
4728 MetaItemPath::to_attribute () const
4729 {
4730 return Attribute (path, nullptr);
4731 }
4732
4733 Attribute
4734 MetaItemSeq::to_attribute () const
4735 {
4736 std::vector<std::unique_ptr<MetaItemInner>> new_seq;
4737 new_seq.reserve (seq.size ());
4738 for (const auto &e : seq)
4739 new_seq.push_back (e->clone_meta_item_inner ());
4740
4741 std::unique_ptr<AttrInputMetaItemContainer> new_seq_container (
4742 new AttrInputMetaItemContainer (std::move (new_seq)));
4743 return Attribute (path, std::move (new_seq_container));
4744 }
4745
4746 Attribute
4747 MetaWord::to_attribute () const
4748 {
4749 return Attribute (SimplePath::from_str (ident, ident_locus), nullptr);
4750 }
4751
4752 Attribute
4753 MetaListPaths::to_attribute () const
4754 {
4755 /* probably one of the most annoying conversions - have to lose specificity by
4756 * turning it into just AttrInputMetaItemContainer (i.e. paths-only nature is
4757 * no longer known). If conversions back are required, might have to do a
4758 * "check all are paths" pass or something. */
4759
4760 std::vector<std::unique_ptr<MetaItemInner>> new_seq;
4761 new_seq.reserve (paths.size ());
4762 for (const auto &e : paths)
4763 new_seq.push_back (std::unique_ptr<MetaItemPath> (new MetaItemPath (e)));
4764
4765 std::unique_ptr<AttrInputMetaItemContainer> new_seq_container (
4766 new AttrInputMetaItemContainer (std::move (new_seq)));
4767 return Attribute (SimplePath::from_str (ident, ident_locus),
4768 std::move (new_seq_container));
4769 }
4770
4771 Attribute
4772 MetaListNameValueStr::to_attribute () const
4773 {
4774 std::vector<std::unique_ptr<MetaItemInner>> new_seq;
4775 new_seq.reserve (strs.size ());
4776 for (const auto &e : strs)
4777 new_seq.push_back (
4778 std::unique_ptr<MetaNameValueStr> (new MetaNameValueStr (e)));
4779
4780 std::unique_ptr<AttrInputMetaItemContainer> new_seq_container (
4781 new AttrInputMetaItemContainer (std::move (new_seq)));
4782 return Attribute (SimplePath::from_str (ident, ident_locus),
4783 std::move (new_seq_container));
4784 }
4785
4786 Attribute
4787 MetaItemPathLit::to_attribute () const
4788 {
4789 return Attribute (path, std::unique_ptr<AttrInputLiteral> (
4790 new AttrInputLiteral (lit)));
4791 }
4792
4793 std::vector<Attribute>
4794 AttrInputMetaItemContainer::separate_cfg_attrs () const
4795 {
4796 rust_assert (!items.empty ());
4797
4798 if (items.size () == 1)
4799 return {};
4800
4801 std::vector<Attribute> attrs;
4802 attrs.reserve (items.size () - 1);
4803
4804 for (auto it = items.begin () + 1; it != items.end (); ++it)
4805 {
4806 Attribute attr = (*it)->to_attribute ();
4807 if (attr.is_empty ())
4808 {
4809 /* TODO should this be an error that causes us to chuck out
4810 * everything? */
4811 continue;
4812 }
4813 attrs.push_back (std::move (attr));
4814 }
4815
4816 attrs.shrink_to_fit ();
4817 return attrs;
4818 }
4819
4820 bool
4821 Attribute::check_cfg_predicate (const Session &session) const
4822 {
4823 /* assume that cfg predicate actually can exist, i.e. attribute has cfg or
4824 * cfg_attr path */
4825 if (!has_attr_input ()
4826 || (path.as_string () != "cfg" && path.as_string () != "cfg_attr"))
4827 {
4828 // DEBUG message
4829 rust_debug (
4830 "tried to check cfg predicate on attr that either has no input "
4831 "or invalid path. attr: '%s'",
4832 as_string ().c_str ());
4833
4834 return false;
4835 }
4836
4837 // assume that it has already been parsed
4838 if (!is_parsed_to_meta_item ())
4839 return false;
4840
4841 return attr_input->check_cfg_predicate (session);
4842 }
4843
4844 std::vector<Attribute>
4845 Attribute::separate_cfg_attrs () const
4846 {
4847 if (!has_attr_input () || path.as_string () != "cfg_attr")
4848 return {};
4849
4850 // assume that it has already been parsed
4851 if (!is_parsed_to_meta_item ())
4852 return {};
4853
4854 return attr_input->separate_cfg_attrs ();
4855 }
4856
4857 bool
4858 Attribute::is_parsed_to_meta_item () const
4859 {
4860 return has_attr_input () && attr_input->is_meta_item ();
4861 }
4862
4863 /* Visitor implementations - these are short but inlining can't happen anyway
4864 * due to virtual functions and I didn't want to make the ast header includes
4865 * any longer than they already are. */
4866
4867 void
4868 Token::accept_vis (ASTVisitor &vis)
4869 {
4870 vis.visit (*this);
4871 }
4872
4873 void
4874 DelimTokenTree::accept_vis (ASTVisitor &vis)
4875 {
4876 vis.visit (*this);
4877 }
4878
4879 void
4880 IdentifierExpr::accept_vis (ASTVisitor &vis)
4881 {
4882 vis.visit (*this);
4883 }
4884
4885 void
4886 Lifetime::accept_vis (ASTVisitor &vis)
4887 {
4888 vis.visit (*this);
4889 }
4890
4891 void
4892 LifetimeParam::accept_vis (ASTVisitor &vis)
4893 {
4894 vis.visit (*this);
4895 }
4896
4897 void
4898 ConstGenericParam::accept_vis (ASTVisitor &vis)
4899 {
4900 vis.visit (*this);
4901 }
4902
4903 void
4904 PathInExpression::accept_vis (ASTVisitor &vis)
4905 {
4906 vis.visit (*this);
4907 }
4908
4909 void
4910 TypePathSegment::accept_vis (ASTVisitor &vis)
4911 {
4912 vis.visit (*this);
4913 }
4914
4915 void
4916 TypePathSegmentGeneric::accept_vis (ASTVisitor &vis)
4917 {
4918 vis.visit (*this);
4919 }
4920
4921 void
4922 TypePathSegmentFunction::accept_vis (ASTVisitor &vis)
4923 {
4924 vis.visit (*this);
4925 }
4926
4927 void
4928 TypePath::accept_vis (ASTVisitor &vis)
4929 {
4930 vis.visit (*this);
4931 }
4932
4933 void
4934 QualifiedPathInExpression::accept_vis (ASTVisitor &vis)
4935 {
4936 vis.visit (*this);
4937 }
4938
4939 void
4940 QualifiedPathInType::accept_vis (ASTVisitor &vis)
4941 {
4942 vis.visit (*this);
4943 }
4944
4945 void
4946 LiteralExpr::accept_vis (ASTVisitor &vis)
4947 {
4948 vis.visit (*this);
4949 }
4950
4951 void
4952 AttrInputLiteral::accept_vis (ASTVisitor &vis)
4953 {
4954 vis.visit (*this);
4955 }
4956
4957 void
4958 MetaItemLitExpr::accept_vis (ASTVisitor &vis)
4959 {
4960 vis.visit (*this);
4961 }
4962
4963 void
4964 MetaItemPathLit::accept_vis (ASTVisitor &vis)
4965 {
4966 vis.visit (*this);
4967 }
4968
4969 void
4970 BorrowExpr::accept_vis (ASTVisitor &vis)
4971 {
4972 vis.visit (*this);
4973 }
4974
4975 void
4976 DereferenceExpr::accept_vis (ASTVisitor &vis)
4977 {
4978 vis.visit (*this);
4979 }
4980
4981 void
4982 ErrorPropagationExpr::accept_vis (ASTVisitor &vis)
4983 {
4984 vis.visit (*this);
4985 }
4986
4987 void
4988 NegationExpr::accept_vis (ASTVisitor &vis)
4989 {
4990 vis.visit (*this);
4991 }
4992
4993 void
4994 ArithmeticOrLogicalExpr::accept_vis (ASTVisitor &vis)
4995 {
4996 vis.visit (*this);
4997 }
4998
4999 void
5000 ComparisonExpr::accept_vis (ASTVisitor &vis)
5001 {
5002 vis.visit (*this);
5003 }
5004
5005 void
5006 LazyBooleanExpr::accept_vis (ASTVisitor &vis)
5007 {
5008 vis.visit (*this);
5009 }
5010
5011 void
5012 TypeCastExpr::accept_vis (ASTVisitor &vis)
5013 {
5014 vis.visit (*this);
5015 }
5016
5017 void
5018 AssignmentExpr::accept_vis (ASTVisitor &vis)
5019 {
5020 vis.visit (*this);
5021 }
5022
5023 void
5024 CompoundAssignmentExpr::accept_vis (ASTVisitor &vis)
5025 {
5026 vis.visit (*this);
5027 }
5028
5029 void
5030 GroupedExpr::accept_vis (ASTVisitor &vis)
5031 {
5032 vis.visit (*this);
5033 }
5034
5035 void
5036 ArrayElemsValues::accept_vis (ASTVisitor &vis)
5037 {
5038 vis.visit (*this);
5039 }
5040
5041 void
5042 ArrayElemsCopied::accept_vis (ASTVisitor &vis)
5043 {
5044 vis.visit (*this);
5045 }
5046
5047 void
5048 ArrayExpr::accept_vis (ASTVisitor &vis)
5049 {
5050 vis.visit (*this);
5051 }
5052
5053 void
5054 ArrayIndexExpr::accept_vis (ASTVisitor &vis)
5055 {
5056 vis.visit (*this);
5057 }
5058
5059 void
5060 TupleExpr::accept_vis (ASTVisitor &vis)
5061 {
5062 vis.visit (*this);
5063 }
5064
5065 void
5066 TupleIndexExpr::accept_vis (ASTVisitor &vis)
5067 {
5068 vis.visit (*this);
5069 }
5070
5071 void
5072 StructExprStruct::accept_vis (ASTVisitor &vis)
5073 {
5074 vis.visit (*this);
5075 }
5076
5077 void
5078 StructExprFieldIdentifier::accept_vis (ASTVisitor &vis)
5079 {
5080 vis.visit (*this);
5081 }
5082
5083 void
5084 StructExprFieldIdentifierValue::accept_vis (ASTVisitor &vis)
5085 {
5086 vis.visit (*this);
5087 }
5088
5089 void
5090 StructExprFieldIndexValue::accept_vis (ASTVisitor &vis)
5091 {
5092 vis.visit (*this);
5093 }
5094
5095 void
5096 StructExprStructFields::accept_vis (ASTVisitor &vis)
5097 {
5098 vis.visit (*this);
5099 }
5100
5101 void
5102 StructExprStructBase::accept_vis (ASTVisitor &vis)
5103 {
5104 vis.visit (*this);
5105 }
5106
5107 void
5108 CallExpr::accept_vis (ASTVisitor &vis)
5109 {
5110 vis.visit (*this);
5111 }
5112
5113 void
5114 MethodCallExpr::accept_vis (ASTVisitor &vis)
5115 {
5116 vis.visit (*this);
5117 }
5118
5119 void
5120 FieldAccessExpr::accept_vis (ASTVisitor &vis)
5121 {
5122 vis.visit (*this);
5123 }
5124
5125 void
5126 ClosureExprInner::accept_vis (ASTVisitor &vis)
5127 {
5128 vis.visit (*this);
5129 }
5130
5131 void
5132 BlockExpr::accept_vis (ASTVisitor &vis)
5133 {
5134 vis.visit (*this);
5135 }
5136
5137 void
5138 ClosureExprInnerTyped::accept_vis (ASTVisitor &vis)
5139 {
5140 vis.visit (*this);
5141 }
5142
5143 void
5144 ContinueExpr::accept_vis (ASTVisitor &vis)
5145 {
5146 vis.visit (*this);
5147 }
5148
5149 void
5150 BreakExpr::accept_vis (ASTVisitor &vis)
5151 {
5152 vis.visit (*this);
5153 }
5154
5155 void
5156 RangeFromToExpr::accept_vis (ASTVisitor &vis)
5157 {
5158 vis.visit (*this);
5159 }
5160
5161 void
5162 RangeFromExpr::accept_vis (ASTVisitor &vis)
5163 {
5164 vis.visit (*this);
5165 }
5166
5167 void
5168 RangeToExpr::accept_vis (ASTVisitor &vis)
5169 {
5170 vis.visit (*this);
5171 }
5172
5173 void
5174 RangeFullExpr::accept_vis (ASTVisitor &vis)
5175 {
5176 vis.visit (*this);
5177 }
5178
5179 void
5180 RangeFromToInclExpr::accept_vis (ASTVisitor &vis)
5181 {
5182 vis.visit (*this);
5183 }
5184
5185 void
5186 RangeToInclExpr::accept_vis (ASTVisitor &vis)
5187 {
5188 vis.visit (*this);
5189 }
5190
5191 void
5192 ReturnExpr::accept_vis (ASTVisitor &vis)
5193 {
5194 vis.visit (*this);
5195 }
5196
5197 void
5198 UnsafeBlockExpr::accept_vis (ASTVisitor &vis)
5199 {
5200 vis.visit (*this);
5201 }
5202
5203 void
5204 LoopExpr::accept_vis (ASTVisitor &vis)
5205 {
5206 vis.visit (*this);
5207 }
5208
5209 void
5210 WhileLoopExpr::accept_vis (ASTVisitor &vis)
5211 {
5212 vis.visit (*this);
5213 }
5214
5215 void
5216 WhileLetLoopExpr::accept_vis (ASTVisitor &vis)
5217 {
5218 vis.visit (*this);
5219 }
5220
5221 void
5222 ForLoopExpr::accept_vis (ASTVisitor &vis)
5223 {
5224 vis.visit (*this);
5225 }
5226
5227 void
5228 IfExpr::accept_vis (ASTVisitor &vis)
5229 {
5230 vis.visit (*this);
5231 }
5232
5233 void
5234 IfExprConseqElse::accept_vis (ASTVisitor &vis)
5235 {
5236 vis.visit (*this);
5237 }
5238
5239 void
5240 IfExprConseqIf::accept_vis (ASTVisitor &vis)
5241 {
5242 vis.visit (*this);
5243 }
5244
5245 void
5246 IfExprConseqIfLet::accept_vis (ASTVisitor &vis)
5247 {
5248 vis.visit (*this);
5249 }
5250
5251 void
5252 IfLetExpr::accept_vis (ASTVisitor &vis)
5253 {
5254 vis.visit (*this);
5255 }
5256
5257 void
5258 IfLetExprConseqElse::accept_vis (ASTVisitor &vis)
5259 {
5260 vis.visit (*this);
5261 }
5262
5263 void
5264 IfLetExprConseqIf::accept_vis (ASTVisitor &vis)
5265 {
5266 vis.visit (*this);
5267 }
5268
5269 void
5270 IfLetExprConseqIfLet::accept_vis (ASTVisitor &vis)
5271 {
5272 vis.visit (*this);
5273 }
5274
5275 void
5276 MatchExpr::accept_vis (ASTVisitor &vis)
5277 {
5278 vis.visit (*this);
5279 }
5280
5281 void
5282 AwaitExpr::accept_vis (ASTVisitor &vis)
5283 {
5284 vis.visit (*this);
5285 }
5286
5287 void
5288 AsyncBlockExpr::accept_vis (ASTVisitor &vis)
5289 {
5290 vis.visit (*this);
5291 }
5292
5293 void
5294 TypeParam::accept_vis (ASTVisitor &vis)
5295 {
5296 vis.visit (*this);
5297 }
5298
5299 void
5300 LifetimeWhereClauseItem::accept_vis (ASTVisitor &vis)
5301 {
5302 vis.visit (*this);
5303 }
5304
5305 void
5306 TypeBoundWhereClauseItem::accept_vis (ASTVisitor &vis)
5307 {
5308 vis.visit (*this);
5309 }
5310
5311 void
5312 Method::accept_vis (ASTVisitor &vis)
5313 {
5314 vis.visit (*this);
5315 }
5316
5317 void
5318 Module::accept_vis (ASTVisitor &vis)
5319 {
5320 vis.visit (*this);
5321 }
5322
5323 void
5324 ExternCrate::accept_vis (ASTVisitor &vis)
5325 {
5326 vis.visit (*this);
5327 }
5328
5329 void
5330 UseTreeGlob::accept_vis (ASTVisitor &vis)
5331 {
5332 vis.visit (*this);
5333 }
5334
5335 void
5336 UseTreeList::accept_vis (ASTVisitor &vis)
5337 {
5338 vis.visit (*this);
5339 }
5340
5341 void
5342 UseTreeRebind::accept_vis (ASTVisitor &vis)
5343 {
5344 vis.visit (*this);
5345 }
5346
5347 void
5348 UseDeclaration::accept_vis (ASTVisitor &vis)
5349 {
5350 vis.visit (*this);
5351 }
5352
5353 void
5354 Function::accept_vis (ASTVisitor &vis)
5355 {
5356 vis.visit (*this);
5357 }
5358
5359 void
5360 TypeAlias::accept_vis (ASTVisitor &vis)
5361 {
5362 vis.visit (*this);
5363 }
5364
5365 void
5366 StructStruct::accept_vis (ASTVisitor &vis)
5367 {
5368 vis.visit (*this);
5369 }
5370
5371 void
5372 TupleStruct::accept_vis (ASTVisitor &vis)
5373 {
5374 vis.visit (*this);
5375 }
5376
5377 void
5378 EnumItem::accept_vis (ASTVisitor &vis)
5379 {
5380 vis.visit (*this);
5381 }
5382
5383 void
5384 EnumItemTuple::accept_vis (ASTVisitor &vis)
5385 {
5386 vis.visit (*this);
5387 }
5388
5389 void
5390 EnumItemStruct::accept_vis (ASTVisitor &vis)
5391 {
5392 vis.visit (*this);
5393 }
5394
5395 void
5396 EnumItemDiscriminant::accept_vis (ASTVisitor &vis)
5397 {
5398 vis.visit (*this);
5399 }
5400
5401 void
5402 Enum::accept_vis (ASTVisitor &vis)
5403 {
5404 vis.visit (*this);
5405 }
5406
5407 void
5408 Union::accept_vis (ASTVisitor &vis)
5409 {
5410 vis.visit (*this);
5411 }
5412
5413 void
5414 ConstantItem::accept_vis (ASTVisitor &vis)
5415 {
5416 vis.visit (*this);
5417 }
5418
5419 void
5420 StaticItem::accept_vis (ASTVisitor &vis)
5421 {
5422 vis.visit (*this);
5423 }
5424
5425 void
5426 TraitItemFunc::accept_vis (ASTVisitor &vis)
5427 {
5428 vis.visit (*this);
5429 }
5430
5431 void
5432 TraitItemMethod::accept_vis (ASTVisitor &vis)
5433 {
5434 vis.visit (*this);
5435 }
5436
5437 void
5438 TraitItemConst::accept_vis (ASTVisitor &vis)
5439 {
5440 vis.visit (*this);
5441 }
5442
5443 void
5444 TraitItemType::accept_vis (ASTVisitor &vis)
5445 {
5446 vis.visit (*this);
5447 }
5448
5449 void
5450 Trait::accept_vis (ASTVisitor &vis)
5451 {
5452 vis.visit (*this);
5453 }
5454
5455 void
5456 InherentImpl::accept_vis (ASTVisitor &vis)
5457 {
5458 vis.visit (*this);
5459 }
5460
5461 void
5462 TraitImpl::accept_vis (ASTVisitor &vis)
5463 {
5464 vis.visit (*this);
5465 }
5466
5467 void
5468 ExternalStaticItem::accept_vis (ASTVisitor &vis)
5469 {
5470 vis.visit (*this);
5471 }
5472
5473 void
5474 ExternalFunctionItem::accept_vis (ASTVisitor &vis)
5475 {
5476 vis.visit (*this);
5477 }
5478
5479 void
5480 ExternBlock::accept_vis (ASTVisitor &vis)
5481 {
5482 vis.visit (*this);
5483 }
5484
5485 void
5486 MacroMatchFragment::accept_vis (ASTVisitor &vis)
5487 {
5488 vis.visit (*this);
5489 }
5490
5491 void
5492 MacroMatchRepetition::accept_vis (ASTVisitor &vis)
5493 {
5494 vis.visit (*this);
5495 }
5496
5497 void
5498 MacroMatcher::accept_vis (ASTVisitor &vis)
5499 {
5500 vis.visit (*this);
5501 }
5502
5503 void
5504 MacroRulesDefinition::accept_vis (ASTVisitor &vis)
5505 {
5506 vis.visit (*this);
5507 }
5508
5509 void
5510 MacroInvocation::accept_vis (ASTVisitor &vis)
5511 {
5512 vis.visit (*this);
5513 }
5514
5515 void
5516 LiteralPattern::accept_vis (ASTVisitor &vis)
5517 {
5518 vis.visit (*this);
5519 }
5520
5521 void
5522 IdentifierPattern::accept_vis (ASTVisitor &vis)
5523 {
5524 vis.visit (*this);
5525 }
5526
5527 void
5528 WildcardPattern::accept_vis (ASTVisitor &vis)
5529 {
5530 vis.visit (*this);
5531 }
5532
5533 void
5534 RangePatternBoundLiteral::accept_vis (ASTVisitor &vis)
5535 {
5536 vis.visit (*this);
5537 }
5538
5539 void
5540 RangePatternBoundPath::accept_vis (ASTVisitor &vis)
5541 {
5542 vis.visit (*this);
5543 }
5544
5545 void
5546 RangePatternBoundQualPath::accept_vis (ASTVisitor &vis)
5547 {
5548 vis.visit (*this);
5549 }
5550
5551 void
5552 RangePattern::accept_vis (ASTVisitor &vis)
5553 {
5554 vis.visit (*this);
5555 }
5556
5557 void
5558 ReferencePattern::accept_vis (ASTVisitor &vis)
5559 {
5560 vis.visit (*this);
5561 }
5562
5563 void
5564 StructPatternFieldTuplePat::accept_vis (ASTVisitor &vis)
5565 {
5566 vis.visit (*this);
5567 }
5568
5569 void
5570 StructPatternFieldIdentPat::accept_vis (ASTVisitor &vis)
5571 {
5572 vis.visit (*this);
5573 }
5574
5575 void
5576 StructPatternFieldIdent::accept_vis (ASTVisitor &vis)
5577 {
5578 vis.visit (*this);
5579 }
5580
5581 void
5582 StructPattern::accept_vis (ASTVisitor &vis)
5583 {
5584 vis.visit (*this);
5585 }
5586
5587 void
5588 TupleStructItemsNoRange::accept_vis (ASTVisitor &vis)
5589 {
5590 vis.visit (*this);
5591 }
5592
5593 void
5594 TupleStructItemsRange::accept_vis (ASTVisitor &vis)
5595 {
5596 vis.visit (*this);
5597 }
5598
5599 void
5600 TupleStructPattern::accept_vis (ASTVisitor &vis)
5601 {
5602 vis.visit (*this);
5603 }
5604
5605 void
5606 TuplePatternItemsMultiple::accept_vis (ASTVisitor &vis)
5607 {
5608 vis.visit (*this);
5609 }
5610
5611 void
5612 TuplePatternItemsRanged::accept_vis (ASTVisitor &vis)
5613 {
5614 vis.visit (*this);
5615 }
5616
5617 void
5618 TuplePattern::accept_vis (ASTVisitor &vis)
5619 {
5620 vis.visit (*this);
5621 }
5622
5623 void
5624 GroupedPattern::accept_vis (ASTVisitor &vis)
5625 {
5626 vis.visit (*this);
5627 }
5628
5629 void
5630 SlicePattern::accept_vis (ASTVisitor &vis)
5631 {
5632 vis.visit (*this);
5633 }
5634
5635 void
5636 EmptyStmt::accept_vis (ASTVisitor &vis)
5637 {
5638 vis.visit (*this);
5639 }
5640
5641 void
5642 LetStmt::accept_vis (ASTVisitor &vis)
5643 {
5644 vis.visit (*this);
5645 }
5646
5647 void
5648 ExprStmtWithoutBlock::accept_vis (ASTVisitor &vis)
5649 {
5650 vis.visit (*this);
5651 }
5652
5653 void
5654 ExprStmtWithBlock::accept_vis (ASTVisitor &vis)
5655 {
5656 vis.visit (*this);
5657 }
5658
5659 void
5660 TraitBound::accept_vis (ASTVisitor &vis)
5661 {
5662 vis.visit (*this);
5663 }
5664
5665 void
5666 ImplTraitType::accept_vis (ASTVisitor &vis)
5667 {
5668 vis.visit (*this);
5669 }
5670
5671 void
5672 TraitObjectType::accept_vis (ASTVisitor &vis)
5673 {
5674 vis.visit (*this);
5675 }
5676
5677 void
5678 ParenthesisedType::accept_vis (ASTVisitor &vis)
5679 {
5680 vis.visit (*this);
5681 }
5682
5683 void
5684 ImplTraitTypeOneBound::accept_vis (ASTVisitor &vis)
5685 {
5686 vis.visit (*this);
5687 }
5688
5689 void
5690 TraitObjectTypeOneBound::accept_vis (ASTVisitor &vis)
5691 {
5692 vis.visit (*this);
5693 }
5694
5695 void
5696 TupleType::accept_vis (ASTVisitor &vis)
5697 {
5698 vis.visit (*this);
5699 }
5700
5701 void
5702 NeverType::accept_vis (ASTVisitor &vis)
5703 {
5704 vis.visit (*this);
5705 }
5706
5707 void
5708 RawPointerType::accept_vis (ASTVisitor &vis)
5709 {
5710 vis.visit (*this);
5711 }
5712
5713 void
5714 ReferenceType::accept_vis (ASTVisitor &vis)
5715 {
5716 vis.visit (*this);
5717 }
5718
5719 void
5720 ArrayType::accept_vis (ASTVisitor &vis)
5721 {
5722 vis.visit (*this);
5723 }
5724
5725 void
5726 SliceType::accept_vis (ASTVisitor &vis)
5727 {
5728 vis.visit (*this);
5729 }
5730
5731 void
5732 InferredType::accept_vis (ASTVisitor &vis)
5733 {
5734 vis.visit (*this);
5735 }
5736
5737 void
5738 BareFunctionType::accept_vis (ASTVisitor &vis)
5739 {
5740 vis.visit (*this);
5741 }
5742
5743 void
5744 MetaItemSeq::accept_vis (ASTVisitor &vis)
5745 {
5746 vis.visit (*this);
5747 }
5748
5749 void
5750 MetaItemPath::accept_vis (ASTVisitor &vis)
5751 {
5752 vis.visit (*this);
5753 }
5754
5755 void
5756 MetaListPaths::accept_vis (ASTVisitor &vis)
5757 {
5758 vis.visit (*this);
5759 }
5760
5761 void
5762 MetaNameValueStr::accept_vis (ASTVisitor &vis)
5763 {
5764 vis.visit (*this);
5765 }
5766
5767 void
5768 MetaListNameValueStr::accept_vis (ASTVisitor &vis)
5769 {
5770 vis.visit (*this);
5771 }
5772
5773 void
5774 AttrInputMetaItemContainer::accept_vis (ASTVisitor &vis)
5775 {
5776 vis.visit (*this);
5777 }
5778
5779 void
5780 MetaWord::accept_vis (ASTVisitor &vis)
5781 {
5782 vis.visit (*this);
5783 }
5784
5785 GenericArg
5786 GenericArg::disambiguate_to_const () const
5787 {
5788 rust_assert (get_kind () == Kind::Either);
5789
5790 // FIXME: is it fine to have no outer attributes?
5791 return GenericArg::create_const (
5792 std::unique_ptr<Expr> (new IdentifierExpr (path, {}, locus)));
5793 }
5794
5795 GenericArg
5796 GenericArg::disambiguate_to_type () const
5797 {
5798 rust_assert (get_kind () == Kind::Either);
5799
5800 auto segment = std::unique_ptr<TypePathSegment> (
5801 new TypePathSegment (path, false, locus));
5802 auto segments = std::vector<std::unique_ptr<TypePathSegment>> ();
5803 segments.emplace_back (std::move (segment));
5804
5805 return GenericArg::create_type (
5806 std::unique_ptr<Type> (new TypePath (std::move (segments), locus)));
5807 }
5808
5809 } // namespace AST
5810 } // namespace Rust