Line data Source code
1 : // Copyright (C) 2026 Free Software Foundation, Inc.
2 :
3 : // This file is part of GCC.
4 :
5 : // GCC is free software; you can redistribute it and/or modify it under
6 : // the terms of the GNU General Public License as published by the Free
7 : // Software Foundation; either version 3, or (at your option) any later
8 : // version.
9 :
10 : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 : // for more details.
14 :
15 : // You should have received a copy of the GNU General Public License
16 : // along with GCC; see the file COPYING3. If not see
17 : // <http://www.gnu.org/licenses/>.
18 :
19 : #include "rust-attribute-checker.h"
20 : #include "rust-attributes.h"
21 : #include "rust-attribute-values.h"
22 : #include "rust-diagnostics.h"
23 : #include "rust-session-manager.h"
24 :
25 : namespace Rust {
26 : namespace Analysis {
27 :
28 : using Attrs = Values::Attributes;
29 :
30 : static bool
31 7443 : is_proc_macro_type (const AST::Attribute &attribute)
32 : {
33 7443 : auto result_opt = lookup_builtin (attribute);
34 7443 : if (!result_opt.has_value ())
35 : return false;
36 7441 : auto result = result_opt.value ();
37 :
38 7441 : auto name = result.name;
39 7423 : return name == Attrs::PROC_MACRO || name == Attrs::PROC_MACRO_DERIVE
40 14864 : || name == Attrs::PROC_MACRO_ATTRIBUTE;
41 7441 : }
42 :
43 : // Emit an error when one encountered attribute is either #[proc_macro],
44 : // #[proc_macro_attribute] or #[proc_macro_derive]
45 : static void
46 5390 : check_proc_macro_non_function (const AST::Attribute &attr)
47 : {
48 5390 : if (is_proc_macro_type (attr))
49 45 : rust_error_at (attr.get_locus (),
50 : "the %<#[%s]%> attribute may only be used on bare functions",
51 90 : attr.get_path ().get_segments ()[0].as_string ().c_str ());
52 5390 : }
53 :
54 : // Emit an error when one attribute is either proc_macro, proc_macro_attribute
55 : // or proc_macro_derive
56 : static void
57 2053 : check_proc_macro_non_root (const AST::Attribute &attr, location_t loc)
58 : {
59 2053 : if (is_proc_macro_type (attr))
60 : {
61 9 : rust_error_at (
62 : loc,
63 : "functions tagged with %<#[%s]%> must currently "
64 : "reside in the root of the crate",
65 18 : attr.get_path ().get_segments ().at (0).as_string ().c_str ());
66 : }
67 2053 : }
68 :
69 5050 : AttributeChecker::AttributeChecker () {}
70 :
71 : void
72 5050 : AttributeChecker::go (AST::Crate &crate)
73 : {
74 5050 : visit (crate);
75 5050 : }
76 :
77 : void
78 18183 : AttributeChecker::visit (AST::Attribute &attribute)
79 : {
80 18183 : auto &session = Session::get_instance ();
81 18183 : if (attribute.get_path () == Values::Attributes::CFG_ATTR)
82 : {
83 25 : if (!attribute.is_parsed_to_meta_item ())
84 25 : attribute.parse_attr_to_meta_item ();
85 25 : if (!attribute.check_cfg_predicate (session))
86 : return; // Do not emit errors for attribute that'll get stripped.
87 : }
88 :
89 18170 : AST::DefaultASTVisitor::visit (attribute);
90 : }
91 :
92 : void
93 0 : AttributeChecker::visit (AST::Token &)
94 0 : {}
95 :
96 : void
97 9182 : AttributeChecker::visit (AST::DelimTokenTree &ttree)
98 : {
99 : // Checking if the DelimTokenTree contains '('
100 : // or something else. If something else, then error
101 9182 : const auto &token_stream = ttree.to_token_stream ();
102 42579 : for (auto &token : token_stream)
103 : {
104 33397 : switch (token.get ()->get_id ())
105 : {
106 : case TokenId::LEFT_PAREN:
107 : // correct case
108 : break;
109 2 : case TokenId::LEFT_CURLY:
110 2 : case TokenId::LEFT_SQUARE:
111 2 : rust_error_at (token.get ()->get_locus (),
112 : "wrong meta list delimiters");
113 2 : rust_inform (token.get ()->get_locus (),
114 : "the delimiters should be %<(%> and %<)%>");
115 2 : break;
116 : default:
117 : break;
118 : }
119 : }
120 9182 : }
121 :
122 : void
123 618 : AttributeChecker::visit (AST::IdentifierExpr &)
124 618 : {}
125 :
126 : void
127 0 : AttributeChecker::visit (AST::Lifetime &)
128 0 : {}
129 :
130 : void
131 75 : AttributeChecker::visit (AST::LifetimeParam &)
132 75 : {}
133 :
134 : void
135 92 : AttributeChecker::visit (AST::ConstGenericParam &)
136 92 : {}
137 :
138 : // rust-path.h
139 : void
140 167 : AttributeChecker::visit (AST::PathInExpression &)
141 167 : {}
142 :
143 : void
144 0 : AttributeChecker::visit (AST::TypePathSegment &)
145 0 : {}
146 :
147 : void
148 0 : AttributeChecker::visit (AST::TypePathSegmentGeneric &)
149 0 : {}
150 :
151 : void
152 0 : AttributeChecker::visit (AST::TypePathSegmentFunction &)
153 0 : {}
154 :
155 : void
156 6617 : AttributeChecker::visit (AST::TypePath &)
157 6617 : {}
158 :
159 : void
160 0 : AttributeChecker::visit (AST::QualifiedPathInExpression &)
161 0 : {}
162 :
163 : void
164 1 : AttributeChecker::visit (AST::QualifiedPathInType &)
165 1 : {}
166 :
167 : // rust-expr.h
168 : void
169 1667 : AttributeChecker::visit (AST::LiteralExpr &)
170 1667 : {}
171 :
172 : void
173 3866 : AttributeChecker::visit (AST::AttrInputLiteral &)
174 3866 : {}
175 :
176 : void
177 0 : AttributeChecker::visit (AST::MetaItemLitExpr &)
178 0 : {}
179 :
180 : void
181 1 : AttributeChecker::visit (AST::MetaItemPathExpr &attribute)
182 : {
183 1 : if (!attribute.get_expr ().is_literal ())
184 : {
185 1 : rust_error_at (attribute.get_expr ().get_locus (),
186 : "malformed %<path%> attribute input");
187 1 : rust_inform (attribute.get_expr ().get_locus (),
188 : "must be of the form: %<#[path = \"file\"]%>");
189 : }
190 1 : }
191 :
192 : void
193 145 : AttributeChecker::visit (AST::BorrowExpr &)
194 145 : {}
195 :
196 : void
197 242 : AttributeChecker::visit (AST::DereferenceExpr &)
198 242 : {}
199 :
200 : void
201 0 : AttributeChecker::visit (AST::ErrorPropagationExpr &)
202 0 : {}
203 :
204 : void
205 139 : AttributeChecker::visit (AST::NegationExpr &)
206 139 : {}
207 :
208 : void
209 871 : AttributeChecker::visit (AST::ArithmeticOrLogicalExpr &)
210 871 : {}
211 :
212 : void
213 757 : AttributeChecker::visit (AST::ComparisonExpr &)
214 757 : {}
215 :
216 : void
217 28 : AttributeChecker::visit (AST::LazyBooleanExpr &)
218 28 : {}
219 :
220 : void
221 195 : AttributeChecker::visit (AST::TypeCastExpr &)
222 195 : {}
223 :
224 : void
225 71 : AttributeChecker::visit (AST::AssignmentExpr &)
226 71 : {}
227 :
228 : void
229 7 : AttributeChecker::visit (AST::CompoundAssignmentExpr &)
230 7 : {}
231 :
232 : void
233 12 : AttributeChecker::visit (AST::GroupedExpr &)
234 12 : {}
235 :
236 : void
237 0 : AttributeChecker::visit (AST::ArrayElemsValues &)
238 0 : {}
239 :
240 : void
241 0 : AttributeChecker::visit (AST::ArrayElemsCopied &)
242 0 : {}
243 :
244 : void
245 16 : AttributeChecker::visit (AST::ArrayExpr &)
246 16 : {}
247 :
248 : void
249 0 : AttributeChecker::visit (AST::ArrayIndexExpr &)
250 0 : {}
251 :
252 : void
253 61 : AttributeChecker::visit (AST::TupleExpr &)
254 61 : {}
255 :
256 : void
257 190 : AttributeChecker::visit (AST::TupleIndexExpr &)
258 190 : {}
259 :
260 : void
261 7 : AttributeChecker::visit (AST::StructExprStruct &)
262 7 : {}
263 :
264 : void
265 0 : AttributeChecker::visit (AST::StructExprFieldIdentifier &)
266 0 : {}
267 :
268 : void
269 0 : AttributeChecker::visit (AST::StructExprFieldIdentifierValue &)
270 0 : {}
271 :
272 : void
273 0 : AttributeChecker::visit (AST::StructExprFieldIndexValue &)
274 0 : {}
275 :
276 : void
277 166 : AttributeChecker::visit (AST::StructExprStructFields &)
278 166 : {}
279 :
280 : void
281 0 : AttributeChecker::visit (AST::StructExprStructBase &)
282 0 : {}
283 :
284 : void
285 738 : AttributeChecker::visit (AST::CallExpr &)
286 738 : {}
287 :
288 : void
289 303 : AttributeChecker::visit (AST::MethodCallExpr &)
290 303 : {}
291 :
292 : void
293 185 : AttributeChecker::visit (AST::FieldAccessExpr &)
294 185 : {}
295 :
296 : void
297 1 : AttributeChecker::visit (AST::ClosureExprInner &)
298 1 : {}
299 :
300 : void
301 13197 : AttributeChecker::visit (AST::BlockExpr &expr)
302 : {
303 30688 : for (auto &stmt : expr.get_statements ())
304 : {
305 17491 : if (stmt->get_stmt_kind () == AST::Stmt::Kind::Item)
306 : {
307 : // Non owning pointer, let it go out of scope
308 770 : auto item = static_cast<AST::Item *> (stmt.get ());
309 780 : for (auto &attr : item->get_outer_attrs ())
310 10 : check_proc_macro_non_root (attr, item->get_locus ());
311 : }
312 : }
313 13197 : AST::DefaultASTVisitor::visit (expr);
314 13197 : }
315 :
316 : void
317 0 : AttributeChecker::visit (AST::ClosureExprInnerTyped &)
318 0 : {}
319 :
320 : void
321 0 : AttributeChecker::visit (AST::ContinueExpr &)
322 0 : {}
323 :
324 : void
325 0 : AttributeChecker::visit (AST::BreakExpr &)
326 0 : {}
327 :
328 : void
329 0 : AttributeChecker::visit (AST::RangeFromToExpr &)
330 0 : {}
331 :
332 : void
333 0 : AttributeChecker::visit (AST::RangeFromExpr &)
334 0 : {}
335 :
336 : void
337 0 : AttributeChecker::visit (AST::RangeToExpr &)
338 0 : {}
339 :
340 : void
341 0 : AttributeChecker::visit (AST::RangeFullExpr &)
342 0 : {}
343 :
344 : void
345 0 : AttributeChecker::visit (AST::RangeFromToInclExpr &)
346 0 : {}
347 :
348 : void
349 0 : AttributeChecker::visit (AST::RangeToInclExpr &)
350 0 : {}
351 :
352 : void
353 3 : AttributeChecker::visit (AST::ReturnExpr &)
354 3 : {}
355 :
356 : void
357 59 : AttributeChecker::visit (AST::LoopExpr &)
358 59 : {}
359 :
360 : void
361 20 : AttributeChecker::visit (AST::WhileLoopExpr &)
362 20 : {}
363 :
364 : void
365 3 : AttributeChecker::visit (AST::WhileLetLoopExpr &)
366 3 : {}
367 :
368 : void
369 2 : AttributeChecker::visit (AST::ForLoopExpr &)
370 2 : {}
371 :
372 : void
373 85 : AttributeChecker::visit (AST::IfExpr &)
374 85 : {}
375 :
376 : void
377 555 : AttributeChecker::visit (AST::IfExprConseqElse &)
378 555 : {}
379 :
380 : void
381 0 : AttributeChecker::visit (AST::IfLetExpr &)
382 0 : {}
383 :
384 : void
385 9 : AttributeChecker::visit (AST::IfLetExprConseqElse &)
386 9 : {}
387 :
388 : void
389 550 : AttributeChecker::visit (AST::MatchExpr &)
390 550 : {}
391 :
392 : void
393 0 : AttributeChecker::visit (AST::AwaitExpr &)
394 0 : {}
395 :
396 : void
397 0 : AttributeChecker::visit (AST::AsyncBlockExpr &)
398 0 : {}
399 :
400 : // rust-item.h
401 : void
402 6597 : AttributeChecker::visit (AST::TypeParam &)
403 6597 : {}
404 :
405 : void
406 0 : AttributeChecker::visit (AST::LifetimeWhereClauseItem &)
407 0 : {}
408 :
409 : void
410 124 : AttributeChecker::visit (AST::TypeBoundWhereClauseItem &)
411 124 : {}
412 :
413 : void
414 1458 : AttributeChecker::visit (AST::Module &module)
415 : {
416 1664 : for (auto &attr : module.get_outer_attrs ())
417 206 : check_proc_macro_non_function (attr);
418 :
419 4414 : for (auto &item : module.get_items ())
420 4999 : for (auto &attr : item->get_outer_attrs ())
421 2043 : check_proc_macro_non_root (attr, item->get_locus ());
422 :
423 1458 : AST::DefaultASTVisitor::visit (module);
424 1458 : }
425 :
426 : void
427 70 : AttributeChecker::visit (AST::ExternCrate &crate)
428 : {
429 76 : for (auto &attr : crate.get_outer_attrs ())
430 6 : check_proc_macro_non_function (attr);
431 70 : }
432 :
433 : void
434 0 : AttributeChecker::visit (AST::UseTreeGlob &)
435 0 : {}
436 :
437 : void
438 0 : AttributeChecker::visit (AST::UseTreeList &)
439 0 : {}
440 :
441 : void
442 0 : AttributeChecker::visit (AST::UseTreeRebind &)
443 0 : {}
444 :
445 : void
446 748 : AttributeChecker::visit (AST::UseDeclaration &declaration)
447 : {
448 756 : for (auto &attr : declaration.get_outer_attrs ())
449 8 : check_proc_macro_non_function (attr);
450 748 : }
451 :
452 : void
453 13850 : AttributeChecker::visit (AST::Function &fun)
454 : {
455 13850 : if (fun.has_body ())
456 11911 : fun.get_definition ().value ()->accept_vis (*this);
457 13850 : }
458 :
459 : void
460 807 : AttributeChecker::visit (AST::TypeAlias &alias)
461 : {
462 810 : for (auto &attr : alias.get_outer_attrs ())
463 3 : check_proc_macro_non_function (attr);
464 807 : }
465 :
466 : void
467 1747 : AttributeChecker::visit (AST::StructStruct &struct_item)
468 : {
469 2297 : for (auto &attr : struct_item.get_outer_attrs ())
470 : {
471 550 : check_proc_macro_non_function (attr);
472 : }
473 :
474 1747 : AST::DefaultASTVisitor::visit (struct_item);
475 1747 : }
476 :
477 : void
478 1042 : AttributeChecker::visit (AST::TupleStruct &tuplestruct)
479 : {
480 1098 : for (auto &attr : tuplestruct.get_outer_attrs ())
481 56 : check_proc_macro_non_function (attr);
482 1042 : }
483 :
484 : void
485 0 : AttributeChecker::visit (AST::EnumItem &)
486 0 : {}
487 :
488 : void
489 0 : AttributeChecker::visit (AST::EnumItemTuple &)
490 0 : {}
491 :
492 : void
493 0 : AttributeChecker::visit (AST::EnumItemStruct &)
494 0 : {}
495 :
496 : void
497 0 : AttributeChecker::visit (AST::EnumItemDiscriminant &)
498 0 : {}
499 :
500 : void
501 601 : AttributeChecker::visit (AST::Enum &enumeration)
502 : {
503 759 : for (auto &attr : enumeration.get_outer_attrs ())
504 158 : check_proc_macro_non_function (attr);
505 601 : }
506 :
507 : void
508 112 : AttributeChecker::visit (AST::Union &u)
509 : {
510 131 : for (auto &attr : u.get_outer_attrs ())
511 19 : check_proc_macro_non_function (attr);
512 112 : }
513 :
514 : void
515 621 : AttributeChecker::visit (AST::ConstantItem &item)
516 : {
517 626 : for (auto &attr : item.get_outer_attrs ())
518 5 : check_proc_macro_non_function (attr);
519 621 : }
520 :
521 : void
522 97 : AttributeChecker::visit (AST::StaticItem &item)
523 : {
524 119 : for (auto &attr : item.get_outer_attrs ())
525 22 : check_proc_macro_non_function (attr);
526 97 : }
527 :
528 : void
529 837 : AttributeChecker::visit (AST::TraitItemType &)
530 837 : {}
531 :
532 : void
533 4316 : AttributeChecker::visit (AST::Trait &trait)
534 : {
535 8489 : for (auto &attr : trait.get_outer_attrs ())
536 4173 : check_proc_macro_non_function (attr);
537 :
538 4316 : AST::DefaultASTVisitor::visit (trait);
539 4316 : }
540 :
541 : void
542 834 : AttributeChecker::visit (AST::InherentImpl &impl)
543 : {
544 1005 : for (auto &attr : impl.get_outer_attrs ())
545 171 : check_proc_macro_non_function (attr);
546 :
547 834 : AST::DefaultASTVisitor::visit (impl);
548 834 : }
549 :
550 : void
551 2216 : AttributeChecker::visit (AST::TraitImpl &impl)
552 : {
553 2224 : for (auto &attr : impl.get_outer_attrs ())
554 8 : check_proc_macro_non_function (attr);
555 :
556 2216 : AST::DefaultASTVisitor::visit (impl);
557 2216 : }
558 :
559 : void
560 0 : AttributeChecker::visit (AST::ExternalTypeItem &)
561 0 : {}
562 :
563 : void
564 0 : AttributeChecker::visit (AST::ExternalStaticItem &)
565 0 : {}
566 :
567 : void
568 1729 : AttributeChecker::visit (AST::ExternBlock &block)
569 : {
570 1734 : for (auto &attr : block.get_outer_attrs ())
571 5 : check_proc_macro_non_function (attr);
572 1729 : }
573 :
574 : // rust-macro.h
575 : void
576 0 : AttributeChecker::visit (AST::MacroMatchFragment &)
577 0 : {}
578 :
579 : void
580 0 : AttributeChecker::visit (AST::MacroMatchRepetition &)
581 0 : {}
582 :
583 : void
584 0 : AttributeChecker::visit (AST::MacroMatcher &)
585 0 : {}
586 :
587 : void
588 1063 : AttributeChecker::visit (AST::MacroRulesDefinition &)
589 1063 : {}
590 :
591 : void
592 810 : AttributeChecker::visit (AST::MacroInvocation &)
593 810 : {}
594 :
595 : void
596 0 : AttributeChecker::visit (AST::MetaItemPath &)
597 0 : {}
598 :
599 : void
600 22 : AttributeChecker::visit (AST::MetaWord &)
601 22 : {}
602 :
603 : void
604 1 : AttributeChecker::visit (AST::MetaNameValueStr &)
605 1 : {}
606 :
607 : void
608 0 : AttributeChecker::visit (AST::MetaListPaths &)
609 0 : {}
610 :
611 : void
612 0 : AttributeChecker::visit (AST::MetaListNameValueStr &)
613 0 : {}
614 :
615 : // rust-pattern.h
616 : void
617 0 : AttributeChecker::visit (AST::LiteralPattern &)
618 0 : {}
619 :
620 : void
621 0 : AttributeChecker::visit (AST::IdentifierPattern &)
622 0 : {}
623 :
624 : void
625 0 : AttributeChecker::visit (AST::WildcardPattern &)
626 0 : {}
627 :
628 : void
629 0 : AttributeChecker::visit (AST::RestPattern &)
630 0 : {}
631 :
632 : // void AttributeChecker::visit(RangePatternBound& ){}
633 :
634 : void
635 0 : AttributeChecker::visit (AST::RangePatternBoundLiteral &)
636 0 : {}
637 :
638 : void
639 0 : AttributeChecker::visit (AST::RangePatternBoundPath &)
640 0 : {}
641 :
642 : void
643 0 : AttributeChecker::visit (AST::RangePatternBoundQualPath &)
644 0 : {}
645 :
646 : void
647 0 : AttributeChecker::visit (AST::RangePattern &)
648 0 : {}
649 :
650 : void
651 0 : AttributeChecker::visit (AST::ReferencePattern &)
652 0 : {}
653 :
654 : // void AttributeChecker::visit(StructPatternField& ){}
655 :
656 : void
657 0 : AttributeChecker::visit (AST::StructPatternFieldTuplePat &)
658 0 : {}
659 :
660 : void
661 0 : AttributeChecker::visit (AST::StructPatternFieldIdentPat &)
662 0 : {}
663 :
664 : void
665 0 : AttributeChecker::visit (AST::StructPatternFieldIdent &)
666 0 : {}
667 :
668 : void
669 0 : AttributeChecker::visit (AST::StructPattern &)
670 0 : {}
671 :
672 : // void AttributeChecker::visit(TupleStructItems& ){}
673 :
674 : void
675 0 : AttributeChecker::visit (AST::TupleStructItemsNoRest &)
676 0 : {}
677 :
678 : void
679 0 : AttributeChecker::visit (AST::TupleStructItemsHasRest &)
680 0 : {}
681 :
682 : void
683 0 : AttributeChecker::visit (AST::TupleStructPattern &)
684 0 : {}
685 :
686 : // void AttributeChecker::visit(TuplePatternItems& ){}
687 :
688 : void
689 0 : AttributeChecker::visit (AST::TuplePatternItemsNoRest &)
690 0 : {}
691 :
692 : void
693 0 : AttributeChecker::visit (AST::TuplePatternItemsHasRest &)
694 0 : {}
695 :
696 : void
697 0 : AttributeChecker::visit (AST::TuplePattern &)
698 0 : {}
699 :
700 : void
701 0 : AttributeChecker::visit (AST::GroupedPattern &)
702 0 : {}
703 :
704 : void
705 0 : AttributeChecker::visit (AST::SlicePattern &)
706 0 : {}
707 :
708 : void
709 0 : AttributeChecker::visit (AST::AltPattern &)
710 0 : {}
711 :
712 : // rust-stmt.h
713 : void
714 18 : AttributeChecker::visit (AST::EmptyStmt &)
715 18 : {}
716 :
717 : void
718 10364 : AttributeChecker::visit (AST::LetStmt &)
719 10364 : {}
720 :
721 : void
722 6339 : AttributeChecker::visit (AST::ExprStmt &)
723 6339 : {}
724 :
725 : // rust-type.h
726 : void
727 662 : AttributeChecker::visit (AST::TraitBound &)
728 662 : {}
729 :
730 : void
731 0 : AttributeChecker::visit (AST::ImplTraitType &)
732 0 : {}
733 :
734 : void
735 4 : AttributeChecker::visit (AST::TraitObjectType &)
736 4 : {}
737 :
738 : void
739 2 : AttributeChecker::visit (AST::ParenthesisedType &)
740 2 : {}
741 :
742 : void
743 2 : AttributeChecker::visit (AST::ImplTraitTypeOneBound &)
744 2 : {}
745 :
746 : void
747 7 : AttributeChecker::visit (AST::TraitObjectTypeOneBound &)
748 7 : {}
749 :
750 : void
751 8 : AttributeChecker::visit (AST::TupleType &)
752 8 : {}
753 :
754 : void
755 3 : AttributeChecker::visit (AST::NeverType &)
756 3 : {}
757 :
758 : void
759 285 : AttributeChecker::visit (AST::RawPointerType &)
760 285 : {}
761 :
762 : void
763 199 : AttributeChecker::visit (AST::ReferenceType &)
764 199 : {}
765 :
766 : void
767 51 : AttributeChecker::visit (AST::ArrayType &)
768 51 : {}
769 :
770 : void
771 82 : AttributeChecker::visit (AST::SliceType &)
772 82 : {}
773 :
774 : void
775 2 : AttributeChecker::visit (AST::InferredType &)
776 2 : {}
777 :
778 : void
779 12 : AttributeChecker::visit (AST::BareFunctionType &)
780 12 : {}
781 :
782 : void
783 0 : AttributeChecker::visit (AST::SelfParam &)
784 0 : {}
785 :
786 : void
787 0 : AttributeChecker::visit (AST::VariadicParam &)
788 0 : {}
789 :
790 : void
791 0 : AttributeChecker::visit (AST::FunctionParam &)
792 0 : {}
793 :
794 : } // namespace Analysis
795 : } // namespace Rust
|