]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/rust/checks/errors/rust-unsafe-checker.cc
Update copyright years.
[thirdparty/gcc.git] / gcc / rust / checks / errors / rust-unsafe-checker.cc
1 // Copyright (C) 2020-2024 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-unsafe-checker.h"
20 #include "rust-hir.h"
21 #include "rust-hir-expr.h"
22 #include "rust-hir-stmt.h"
23 #include "rust-hir-item.h"
24
25 namespace Rust {
26 namespace HIR {
27
28 UnsafeChecker::UnsafeChecker ()
29 : context (*Resolver::TypeCheckContext::get ()),
30 resolver (*Resolver::Resolver::get ()),
31 mappings (*Analysis::Mappings::get ())
32 {}
33
34 void
35 UnsafeChecker::go (HIR::Crate &crate)
36 {
37 for (auto &item : crate.items)
38 item->accept_vis (*this);
39 }
40
41 static void
42 check_static_mut (HIR::Item *maybe_static, Location locus)
43 {
44 if (maybe_static->get_hir_kind () == Node::BaseKind::VIS_ITEM)
45 {
46 auto item = static_cast<Item *> (maybe_static);
47 if (item->get_item_kind () == Item::ItemKind::Static)
48 {
49 auto static_item = static_cast<StaticItem *> (item);
50 if (static_item->is_mut ())
51 rust_error_at (
52 locus, "use of mutable static requires unsafe function or block");
53 }
54 }
55 }
56
57 static void
58 check_extern_static (HIR::ExternalItem *maybe_static, Location locus)
59 {
60 if (maybe_static->get_extern_kind () == ExternalItem::ExternKind::Static)
61 rust_error_at (locus,
62 "use of extern static requires unsafe function or block");
63 }
64
65 void
66 UnsafeChecker::check_use_of_static (HirId node_id, Location locus)
67 {
68 if (unsafe_context.is_in_context ())
69 return;
70
71 auto maybe_static_mut = mappings.lookup_hir_item (node_id);
72
73 HirId extern_block;
74 auto maybe_extern_static
75 = mappings.lookup_hir_extern_item (node_id, &extern_block);
76
77 if (maybe_static_mut)
78 check_static_mut (maybe_static_mut, locus);
79
80 if (maybe_extern_static)
81 check_extern_static (static_cast<ExternalItem *> (maybe_extern_static),
82 locus);
83 }
84
85 static void
86 check_unsafe_call (HIR::Function *fn, Location locus, const std::string &kind)
87 {
88 if (fn->get_qualifiers ().is_unsafe ())
89 rust_error_at (locus, "call to unsafe %s requires unsafe function or block",
90 kind.c_str ());
91 }
92
93 static bool
94 is_safe_intrinsic (const std::string &fn_name)
95 {
96 static const std::unordered_set<std::string> safe_intrinsics = {
97 "abort",
98 "size_of",
99 "min_align_of",
100 "needs_drop",
101 "caller_location",
102 "add_with_overflow",
103 "sub_with_overflow",
104 "mul_with_overflow",
105 "wrapping_add",
106 "wrapping_sub",
107 "wrapping_mul",
108 "saturating_add",
109 "saturating_sub",
110 "rotate_left",
111 "rotate_right",
112 "ctpop",
113 "ctlz",
114 "cttz",
115 "bswap",
116 "bitreverse",
117 "discriminant_value",
118 "type_id",
119 "likely",
120 "unlikely",
121 "ptr_guaranteed_eq",
122 "ptr_guaranteed_ne",
123 "minnumf32",
124 "minnumf64",
125 "maxnumf32",
126 "rustc_peek",
127 "maxnumf64",
128 "type_name",
129 "forget",
130 "black_box",
131 "variant_count",
132 };
133
134 return safe_intrinsics.find (fn_name) != safe_intrinsics.end ();
135 }
136
137 static void
138 check_extern_call (HIR::ExternalItem *maybe_fn, HIR::ExternBlock *parent_block,
139 Location locus)
140 {
141 // We have multiple operations to perform here
142 // 1. Is the item an actual function we're calling
143 // 2. Is the block it's defined in an FFI block or an `extern crate` block
144 //
145 // It is not unsafe to call into other crates, so items defined in an `extern
146 // crate` must be callable without being in an unsafe context. On the other
147 // hand, any function defined in a block with a specific ABI (even `extern
148 // "Rust"` blocks) is unsafe to call
149
150 if (maybe_fn->get_extern_kind () != ExternalItem::ExternKind::Function)
151 return;
152
153 // Some intrinsics are safe to call
154 if (parent_block->get_abi () == Rust::ABI::INTRINSIC
155 && is_safe_intrinsic (maybe_fn->get_item_name ()))
156 return;
157
158 rust_error_at (locus,
159 "call to extern function requires unsafe function or block");
160 }
161
162 void
163 UnsafeChecker::check_function_call (HirId node_id, Location locus)
164 {
165 if (unsafe_context.is_in_context ())
166 return;
167
168 HirId parent_extern_block;
169 auto maybe_fn = mappings.lookup_hir_item (node_id);
170 auto maybe_extern
171 = mappings.lookup_hir_extern_item (node_id, &parent_extern_block);
172
173 if (maybe_fn && maybe_fn->get_item_kind () == Item::ItemKind::Function)
174 check_unsafe_call (static_cast<Function *> (maybe_fn), locus, "function");
175
176 if (maybe_extern)
177 check_extern_call (static_cast<ExternalItem *> (maybe_extern),
178 mappings.lookup_hir_extern_block (parent_extern_block),
179 locus);
180 }
181
182 static void
183 check_target_attr (HIR::Function *fn, Location locus)
184 {
185 if (std::any_of (fn->get_outer_attrs ().begin (),
186 fn->get_outer_attrs ().end (),
187 [] (const AST::Attribute &attr) {
188 return attr.get_path ().as_string () == "target_feature";
189 }))
190 rust_error_at (locus,
191 "call to function with %<#[target_feature]%> requires "
192 "unsafe function or block");
193 }
194
195 void
196 UnsafeChecker::check_function_attr (HirId node_id, Location locus)
197 {
198 if (unsafe_context.is_in_context ())
199 return;
200
201 auto maybe_fn = mappings.lookup_hir_item (node_id);
202
203 if (maybe_fn && maybe_fn->get_item_kind () == Item::ItemKind::Function)
204 check_target_attr (static_cast<Function *> (maybe_fn), locus);
205 }
206
207 void
208 UnsafeChecker::visit (Lifetime &)
209 {}
210
211 void
212 UnsafeChecker::visit (LifetimeParam &)
213 {}
214
215 void
216 UnsafeChecker::visit (PathInExpression &path)
217 {
218 NodeId ast_node_id = path.get_mappings ().get_nodeid ();
219 NodeId ref_node_id;
220 HirId definition_id;
221
222 if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id))
223 return;
224
225 rust_assert (mappings.lookup_node_to_hir (ref_node_id, &definition_id));
226
227 check_use_of_static (definition_id, path.get_locus ());
228 }
229
230 void
231 UnsafeChecker::visit (TypePathSegment &)
232 {}
233
234 void
235 UnsafeChecker::visit (TypePathSegmentGeneric &)
236 {}
237
238 void
239 UnsafeChecker::visit (TypePathSegmentFunction &)
240 {}
241
242 void
243 UnsafeChecker::visit (TypePath &)
244 {}
245
246 void
247 UnsafeChecker::visit (QualifiedPathInExpression &)
248 {}
249
250 void
251 UnsafeChecker::visit (QualifiedPathInType &)
252 {}
253
254 void
255 UnsafeChecker::visit (LiteralExpr &)
256 {}
257
258 void
259 UnsafeChecker::visit (BorrowExpr &expr)
260 {
261 expr.get_expr ()->accept_vis (*this);
262 }
263
264 void
265 UnsafeChecker::visit (DereferenceExpr &expr)
266 {
267 TyTy::BaseType *to_deref_type;
268 auto to_deref = expr.get_expr ()->get_mappings ().get_hirid ();
269
270 rust_assert (context.lookup_type (to_deref, &to_deref_type));
271
272 if (to_deref_type->get_kind () == TyTy::TypeKind::POINTER
273 && !unsafe_context.is_in_context ())
274 rust_error_at (expr.get_locus (), "dereference of raw pointer requires "
275 "unsafe function or block");
276 }
277
278 void
279 UnsafeChecker::visit (ErrorPropagationExpr &expr)
280 {
281 expr.get_expr ()->accept_vis (*this);
282 }
283
284 void
285 UnsafeChecker::visit (NegationExpr &expr)
286 {
287 expr.get_expr ()->accept_vis (*this);
288 }
289
290 void
291 UnsafeChecker::visit (ArithmeticOrLogicalExpr &expr)
292 {
293 expr.get_lhs ()->accept_vis (*this);
294 expr.get_rhs ()->accept_vis (*this);
295 }
296
297 void
298 UnsafeChecker::visit (ComparisonExpr &expr)
299 {
300 expr.get_lhs ()->accept_vis (*this);
301 expr.get_rhs ()->accept_vis (*this);
302 }
303
304 void
305 UnsafeChecker::visit (LazyBooleanExpr &expr)
306 {
307 expr.get_lhs ()->accept_vis (*this);
308 expr.get_rhs ()->accept_vis (*this);
309 }
310
311 void
312 UnsafeChecker::visit (TypeCastExpr &expr)
313 {
314 expr.get_expr ()->accept_vis (*this);
315 }
316
317 void
318 UnsafeChecker::visit (AssignmentExpr &expr)
319 {
320 expr.get_lhs ()->accept_vis (*this);
321 expr.get_rhs ()->accept_vis (*this);
322 }
323
324 void
325 UnsafeChecker::visit (CompoundAssignmentExpr &expr)
326 {
327 expr.get_left_expr ()->accept_vis (*this);
328 expr.get_right_expr ()->accept_vis (*this);
329 }
330
331 void
332 UnsafeChecker::visit (GroupedExpr &expr)
333 {
334 expr.get_expr_in_parens ()->accept_vis (*this);
335 }
336
337 void
338 UnsafeChecker::visit (ArrayElemsValues &elems)
339 {
340 for (auto &elem : elems.get_values ())
341 elem->accept_vis (*this);
342 }
343
344 void
345 UnsafeChecker::visit (ArrayElemsCopied &elems)
346 {
347 elems.get_elem_to_copy ()->accept_vis (*this);
348 }
349
350 void
351 UnsafeChecker::visit (ArrayExpr &expr)
352 {
353 expr.get_internal_elements ()->accept_vis (*this);
354 }
355
356 void
357 UnsafeChecker::visit (ArrayIndexExpr &expr)
358 {
359 expr.get_array_expr ()->accept_vis (*this);
360 expr.get_index_expr ()->accept_vis (*this);
361 }
362
363 void
364 UnsafeChecker::visit (TupleExpr &expr)
365 {
366 for (auto &elem : expr.get_tuple_elems ())
367 elem->accept_vis (*this);
368 }
369
370 void
371 UnsafeChecker::visit (TupleIndexExpr &expr)
372 {
373 expr.get_tuple_expr ()->accept_vis (*this);
374 }
375
376 void
377 UnsafeChecker::visit (StructExprStruct &)
378 {}
379
380 void
381 UnsafeChecker::visit (StructExprFieldIdentifier &)
382 {}
383
384 void
385 UnsafeChecker::visit (StructExprFieldIdentifierValue &field)
386 {
387 field.get_value ()->accept_vis (*this);
388 }
389
390 void
391 UnsafeChecker::visit (StructExprFieldIndexValue &field)
392 {
393 field.get_value ()->accept_vis (*this);
394 }
395
396 void
397 UnsafeChecker::visit (StructExprStructFields &expr)
398 {
399 for (auto &field : expr.get_fields ())
400 field->accept_vis (*this);
401 }
402
403 void
404 UnsafeChecker::visit (StructExprStructBase &)
405 {}
406
407 void
408 UnsafeChecker::visit (CallExpr &expr)
409 {
410 auto fn = expr.get_fnexpr ();
411 if (!fn)
412 return;
413
414 NodeId ast_node_id = fn->get_mappings ().get_nodeid ();
415 NodeId ref_node_id;
416 HirId definition_id;
417
418 // There are no unsafe types, and functions are defined in the name resolver.
419 // If we can't find the name, then we're dealing with a type and should return
420 // early.
421 if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id))
422 return;
423
424 rust_assert (mappings.lookup_node_to_hir (ref_node_id, &definition_id));
425
426 // At this point we have the function's HIR Id. There are three checks we
427 // must perform:
428 // 1. The function is an unsafe one
429 // 2. The function is an extern one
430 // 3. The function is marked with a target_feature attribute
431 check_function_call (definition_id, expr.get_locus ());
432 check_function_attr (definition_id, expr.get_locus ());
433
434 if (expr.has_params ())
435 for (auto &arg : expr.get_arguments ())
436 arg->accept_vis (*this);
437 }
438
439 void
440 UnsafeChecker::visit (MethodCallExpr &expr)
441 {
442 TyTy::BaseType *method_type;
443 context.lookup_type (expr.get_method_name ().get_mappings ().get_hirid (),
444 &method_type);
445
446 auto fn = *static_cast<TyTy::FnType *> (method_type);
447 auto method = mappings.lookup_hir_implitem (fn.get_ref (), nullptr);
448
449 if (!unsafe_context.is_in_context () && method)
450 check_unsafe_call (static_cast<Function *> (method), expr.get_locus (),
451 "method");
452
453 expr.get_receiver ()->accept_vis (*this);
454
455 for (auto &arg : expr.get_arguments ())
456 arg->accept_vis (*this);
457 }
458
459 void
460 UnsafeChecker::visit (FieldAccessExpr &expr)
461 {
462 expr.get_receiver_expr ()->accept_vis (*this);
463
464 if (unsafe_context.is_in_context ())
465 return;
466
467 TyTy::BaseType *receiver_ty;
468 auto ok = context.lookup_type (
469 expr.get_receiver_expr ()->get_mappings ().get_hirid (), &receiver_ty);
470 rust_assert (ok);
471
472 if (receiver_ty->get_kind () == TyTy::TypeKind::ADT)
473 {
474 auto maybe_union = static_cast<TyTy::ADTType *> (receiver_ty);
475 if (maybe_union->is_union ())
476 rust_error_at (
477 expr.get_locus (),
478 "access to union field requires unsafe function or block");
479 }
480 }
481
482 void
483 UnsafeChecker::visit (ClosureExpr &expr)
484 {
485 expr.get_expr ()->accept_vis (*this);
486 }
487
488 void
489 UnsafeChecker::visit (BlockExpr &expr)
490 {
491 for (auto &stmt : expr.get_statements ())
492 stmt->accept_vis (*this);
493
494 if (expr.has_expr ())
495 expr.get_final_expr ()->accept_vis (*this);
496 }
497
498 void
499 UnsafeChecker::visit (ContinueExpr &)
500 {}
501
502 void
503 UnsafeChecker::visit (BreakExpr &expr)
504 {
505 if (expr.has_break_expr ())
506 expr.get_expr ()->accept_vis (*this);
507 }
508
509 void
510 UnsafeChecker::visit (RangeFromToExpr &expr)
511 {
512 expr.get_from_expr ()->accept_vis (*this);
513 expr.get_to_expr ()->accept_vis (*this);
514 }
515
516 void
517 UnsafeChecker::visit (RangeFromExpr &expr)
518 {
519 expr.get_from_expr ()->accept_vis (*this);
520 }
521
522 void
523 UnsafeChecker::visit (RangeToExpr &expr)
524 {
525 expr.get_to_expr ()->accept_vis (*this);
526 }
527
528 void
529 UnsafeChecker::visit (RangeFullExpr &)
530 {}
531
532 void
533 UnsafeChecker::visit (RangeFromToInclExpr &expr)
534 {
535 expr.get_from_expr ()->accept_vis (*this);
536 expr.get_to_expr ()->accept_vis (*this);
537 }
538
539 void
540 UnsafeChecker::visit (RangeToInclExpr &expr)
541 {
542 expr.get_to_expr ()->accept_vis (*this);
543 }
544
545 void
546 UnsafeChecker::visit (ReturnExpr &expr)
547 {
548 if (expr.has_return_expr ())
549 expr.get_expr ()->accept_vis (*this);
550 }
551
552 void
553 UnsafeChecker::visit (UnsafeBlockExpr &expr)
554 {
555 unsafe_context.enter (expr.get_mappings ().get_hirid ());
556
557 expr.get_block_expr ()->accept_vis (*this);
558
559 unsafe_context.exit ();
560 }
561
562 void
563 UnsafeChecker::visit (LoopExpr &expr)
564 {
565 expr.get_loop_block ()->accept_vis (*this);
566 }
567
568 void
569 UnsafeChecker::visit (WhileLoopExpr &expr)
570 {
571 expr.get_predicate_expr ()->accept_vis (*this);
572 expr.get_loop_block ()->accept_vis (*this);
573 }
574
575 void
576 UnsafeChecker::visit (WhileLetLoopExpr &expr)
577 {
578 expr.get_cond ()->accept_vis (*this);
579 expr.get_loop_block ()->accept_vis (*this);
580 }
581
582 void
583 UnsafeChecker::visit (ForLoopExpr &expr)
584 {
585 expr.get_iterator_expr ()->accept_vis (*this);
586 expr.get_loop_block ()->accept_vis (*this);
587 }
588
589 void
590 UnsafeChecker::visit (IfExpr &expr)
591 {
592 expr.get_if_condition ()->accept_vis (*this);
593 expr.get_if_block ()->accept_vis (*this);
594 }
595
596 void
597 UnsafeChecker::visit (IfExprConseqElse &expr)
598 {
599 expr.get_if_condition ()->accept_vis (*this);
600 expr.get_if_block ()->accept_vis (*this);
601 expr.get_else_block ()->accept_vis (*this);
602 }
603
604 void
605 UnsafeChecker::visit (IfExprConseqIf &expr)
606 {
607 expr.get_if_condition ()->accept_vis (*this);
608 expr.get_if_block ()->accept_vis (*this);
609 expr.get_conseq_if_expr ()->accept_vis (*this);
610 }
611
612 void
613 UnsafeChecker::visit (IfExprConseqIfLet &expr)
614 {
615 expr.get_if_condition ()->accept_vis (*this);
616 expr.get_if_block ()->accept_vis (*this);
617
618 // TODO: Visit conseq if let expression
619 }
620
621 void
622 UnsafeChecker::visit (IfLetExpr &expr)
623 {
624 expr.get_scrutinee_expr ()->accept_vis (*this);
625 expr.get_if_block ()->accept_vis (*this);
626 }
627
628 void
629 UnsafeChecker::visit (IfLetExprConseqElse &expr)
630 {
631 expr.get_scrutinee_expr ()->accept_vis (*this);
632 expr.get_if_block ()->accept_vis (*this);
633
634 // TODO: Visit else expression
635 }
636
637 void
638 UnsafeChecker::visit (IfLetExprConseqIf &expr)
639 {
640 expr.get_scrutinee_expr ()->accept_vis (*this);
641 expr.get_if_block ()->accept_vis (*this);
642 }
643
644 void
645 UnsafeChecker::visit (IfLetExprConseqIfLet &expr)
646 {
647 expr.get_scrutinee_expr ()->accept_vis (*this);
648 expr.get_if_block ()->accept_vis (*this);
649
650 // TODO: Visit conseq if let expression
651 }
652
653 void
654 UnsafeChecker::visit (MatchExpr &expr)
655 {
656 expr.get_scrutinee_expr ()->accept_vis (*this);
657
658 for (auto &match_arm : expr.get_match_cases ())
659 match_arm.get_expr ()->accept_vis (*this);
660 }
661
662 void
663 UnsafeChecker::visit (AwaitExpr &)
664 {
665 // TODO: Visit expression
666 }
667
668 void
669 UnsafeChecker::visit (AsyncBlockExpr &)
670 {
671 // TODO: Visit block expression
672 }
673
674 void
675 UnsafeChecker::visit (TypeParam &)
676 {}
677
678 void
679 UnsafeChecker::visit (ConstGenericParam &)
680 {}
681
682 void
683 UnsafeChecker::visit (LifetimeWhereClauseItem &)
684 {}
685
686 void
687 UnsafeChecker::visit (TypeBoundWhereClauseItem &)
688 {}
689
690 void
691 UnsafeChecker::visit (Module &module)
692 {
693 for (auto &item : module.get_items ())
694 item->accept_vis (*this);
695 }
696
697 void
698 UnsafeChecker::visit (ExternCrate &)
699 {}
700
701 void
702 UnsafeChecker::visit (UseTreeGlob &)
703 {}
704
705 void
706 UnsafeChecker::visit (UseTreeList &)
707 {}
708
709 void
710 UnsafeChecker::visit (UseTreeRebind &)
711 {}
712
713 void
714 UnsafeChecker::visit (UseDeclaration &)
715 {}
716
717 void
718 UnsafeChecker::visit (Function &function)
719 {
720 auto is_unsafe_fn = function.get_qualifiers ().is_unsafe ();
721
722 if (is_unsafe_fn)
723 unsafe_context.enter (function.get_mappings ().get_hirid ());
724
725 function.get_definition ()->accept_vis (*this);
726
727 if (is_unsafe_fn)
728 unsafe_context.exit ();
729 }
730
731 void
732 UnsafeChecker::visit (TypeAlias &)
733 {
734 // FIXME: What do we need to do to handle type aliasing? Is it possible to
735 // have unsafe types? Type aliases on unsafe functions?
736 }
737
738 void
739 UnsafeChecker::visit (StructStruct &)
740 {}
741
742 void
743 UnsafeChecker::visit (TupleStruct &)
744 {}
745
746 void
747 UnsafeChecker::visit (EnumItem &)
748 {}
749
750 void
751 UnsafeChecker::visit (EnumItemTuple &)
752 {}
753
754 void
755 UnsafeChecker::visit (EnumItemStruct &)
756 {}
757
758 void
759 UnsafeChecker::visit (EnumItemDiscriminant &)
760 {}
761
762 void
763 UnsafeChecker::visit (Enum &)
764 {}
765
766 void
767 UnsafeChecker::visit (Union &)
768 {}
769
770 void
771 UnsafeChecker::visit (ConstantItem &const_item)
772 {
773 const_item.get_expr ()->accept_vis (*this);
774 }
775
776 void
777 UnsafeChecker::visit (StaticItem &static_item)
778 {
779 static_item.get_expr ()->accept_vis (*this);
780 }
781
782 void
783 UnsafeChecker::visit (TraitItemFunc &item)
784 {
785 if (item.has_block_defined ())
786 item.get_block_expr ()->accept_vis (*this);
787 }
788
789 void
790 UnsafeChecker::visit (TraitItemConst &item)
791 {
792 if (item.has_expr ())
793 item.get_expr ()->accept_vis (*this);
794 }
795
796 void
797 UnsafeChecker::visit (TraitItemType &)
798 {}
799
800 void
801 UnsafeChecker::visit (Trait &trait)
802 {
803 // FIXME: Handle unsafe traits
804 for (auto &item : trait.get_trait_items ())
805 item->accept_vis (*this);
806 }
807
808 void
809 UnsafeChecker::visit (ImplBlock &impl)
810 {
811 // FIXME: Handle unsafe impls
812 for (auto &item : impl.get_impl_items ())
813 item->accept_vis (*this);
814 }
815
816 void
817 UnsafeChecker::visit (ExternalStaticItem &)
818 {}
819
820 void
821 UnsafeChecker::visit (ExternalFunctionItem &)
822 {}
823
824 void
825 UnsafeChecker::visit (ExternBlock &block)
826 {
827 // FIXME: Do we need to do this?
828 for (auto &item : block.get_extern_items ())
829 item->accept_vis (*this);
830 }
831
832 void
833 UnsafeChecker::visit (LiteralPattern &)
834 {}
835
836 void
837 UnsafeChecker::visit (IdentifierPattern &)
838 {}
839
840 void
841 UnsafeChecker::visit (WildcardPattern &)
842 {}
843
844 void
845 UnsafeChecker::visit (RangePatternBoundLiteral &)
846 {}
847
848 void
849 UnsafeChecker::visit (RangePatternBoundPath &)
850 {}
851
852 void
853 UnsafeChecker::visit (RangePatternBoundQualPath &)
854 {}
855
856 void
857 UnsafeChecker::visit (RangePattern &)
858 {}
859
860 void
861 UnsafeChecker::visit (ReferencePattern &)
862 {}
863
864 void
865 UnsafeChecker::visit (StructPatternFieldTuplePat &)
866 {}
867
868 void
869 UnsafeChecker::visit (StructPatternFieldIdentPat &)
870 {}
871
872 void
873 UnsafeChecker::visit (StructPatternFieldIdent &)
874 {}
875
876 void
877 UnsafeChecker::visit (StructPattern &)
878 {}
879
880 void
881 UnsafeChecker::visit (TupleStructItemsNoRange &)
882 {}
883
884 void
885 UnsafeChecker::visit (TupleStructItemsRange &)
886 {}
887
888 void
889 UnsafeChecker::visit (TupleStructPattern &)
890 {}
891
892 void
893 UnsafeChecker::visit (TuplePatternItemsMultiple &)
894 {}
895
896 void
897 UnsafeChecker::visit (TuplePatternItemsRanged &)
898 {}
899
900 void
901 UnsafeChecker::visit (TuplePattern &)
902 {}
903
904 void
905 UnsafeChecker::visit (SlicePattern &)
906 {}
907
908 void
909 UnsafeChecker::visit (EmptyStmt &)
910 {}
911
912 void
913 UnsafeChecker::visit (LetStmt &stmt)
914 {
915 if (stmt.has_init_expr ())
916 stmt.get_init_expr ()->accept_vis (*this);
917 }
918
919 void
920 UnsafeChecker::visit (ExprStmtWithoutBlock &stmt)
921 {
922 stmt.get_expr ()->accept_vis (*this);
923 }
924
925 void
926 UnsafeChecker::visit (ExprStmtWithBlock &stmt)
927 {
928 stmt.get_expr ()->accept_vis (*this);
929 }
930
931 void
932 UnsafeChecker::visit (TraitBound &)
933 {}
934
935 void
936 UnsafeChecker::visit (ImplTraitType &)
937 {}
938
939 void
940 UnsafeChecker::visit (TraitObjectType &)
941 {}
942
943 void
944 UnsafeChecker::visit (ParenthesisedType &)
945 {}
946
947 void
948 UnsafeChecker::visit (ImplTraitTypeOneBound &)
949 {}
950
951 void
952 UnsafeChecker::visit (TupleType &)
953 {}
954
955 void
956 UnsafeChecker::visit (NeverType &)
957 {}
958
959 void
960 UnsafeChecker::visit (RawPointerType &)
961 {}
962
963 void
964 UnsafeChecker::visit (ReferenceType &)
965 {}
966
967 void
968 UnsafeChecker::visit (ArrayType &)
969 {}
970
971 void
972 UnsafeChecker::visit (SliceType &)
973 {}
974
975 void
976 UnsafeChecker::visit (InferredType &)
977 {}
978
979 void
980 UnsafeChecker::visit (BareFunctionType &)
981 {}
982
983 } // namespace HIR
984 } // namespace Rust