]> 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-2023 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 void
183 UnsafeChecker::visit (Lifetime &lifetime)
184 {}
185
186 void
187 UnsafeChecker::visit (LifetimeParam &lifetime_param)
188 {}
189
190 void
191 UnsafeChecker::visit (PathInExpression &path)
192 {
193 NodeId ast_node_id = path.get_mappings ().get_nodeid ();
194 NodeId ref_node_id;
195 HirId definition_id;
196
197 if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id))
198 return;
199
200 rust_assert (mappings.lookup_node_to_hir (ref_node_id, &definition_id));
201
202 check_use_of_static (definition_id, path.get_locus ());
203 }
204
205 void
206 UnsafeChecker::visit (TypePathSegment &segment)
207 {}
208
209 void
210 UnsafeChecker::visit (TypePathSegmentGeneric &segment)
211 {}
212
213 void
214 UnsafeChecker::visit (TypePathSegmentFunction &segment)
215 {}
216
217 void
218 UnsafeChecker::visit (TypePath &path)
219 {}
220
221 void
222 UnsafeChecker::visit (QualifiedPathInExpression &path)
223 {}
224
225 void
226 UnsafeChecker::visit (QualifiedPathInType &path)
227 {}
228
229 void
230 UnsafeChecker::visit (LiteralExpr &expr)
231 {}
232
233 void
234 UnsafeChecker::visit (BorrowExpr &expr)
235 {
236 expr.get_expr ()->accept_vis (*this);
237 }
238
239 void
240 UnsafeChecker::visit (DereferenceExpr &expr)
241 {
242 TyTy::BaseType *to_deref_type;
243 auto to_deref = expr.get_expr ()->get_mappings ().get_hirid ();
244
245 rust_assert (context.lookup_type (to_deref, &to_deref_type));
246
247 if (to_deref_type->get_kind () == TyTy::TypeKind::POINTER
248 && !unsafe_context.is_in_context ())
249 rust_error_at (expr.get_locus (), "dereference of raw pointer requires "
250 "unsafe function or block");
251 }
252
253 void
254 UnsafeChecker::visit (ErrorPropagationExpr &expr)
255 {
256 expr.get_expr ()->accept_vis (*this);
257 }
258
259 void
260 UnsafeChecker::visit (NegationExpr &expr)
261 {
262 expr.get_expr ()->accept_vis (*this);
263 }
264
265 void
266 UnsafeChecker::visit (ArithmeticOrLogicalExpr &expr)
267 {
268 expr.get_lhs ()->accept_vis (*this);
269 expr.get_rhs ()->accept_vis (*this);
270 }
271
272 void
273 UnsafeChecker::visit (ComparisonExpr &expr)
274 {
275 expr.get_lhs ()->accept_vis (*this);
276 expr.get_rhs ()->accept_vis (*this);
277 }
278
279 void
280 UnsafeChecker::visit (LazyBooleanExpr &expr)
281 {
282 expr.get_lhs ()->accept_vis (*this);
283 expr.get_rhs ()->accept_vis (*this);
284 }
285
286 void
287 UnsafeChecker::visit (TypeCastExpr &expr)
288 {
289 expr.get_expr ()->accept_vis (*this);
290 }
291
292 void
293 UnsafeChecker::visit (AssignmentExpr &expr)
294 {
295 expr.get_lhs ()->accept_vis (*this);
296 expr.get_rhs ()->accept_vis (*this);
297 }
298
299 void
300 UnsafeChecker::visit (CompoundAssignmentExpr &expr)
301 {
302 expr.get_left_expr ()->accept_vis (*this);
303 expr.get_right_expr ()->accept_vis (*this);
304 }
305
306 void
307 UnsafeChecker::visit (GroupedExpr &expr)
308 {
309 expr.get_expr_in_parens ()->accept_vis (*this);
310 }
311
312 void
313 UnsafeChecker::visit (ArrayElemsValues &elems)
314 {
315 for (auto &elem : elems.get_values ())
316 elem->accept_vis (*this);
317 }
318
319 void
320 UnsafeChecker::visit (ArrayElemsCopied &elems)
321 {
322 elems.get_elem_to_copy ()->accept_vis (*this);
323 }
324
325 void
326 UnsafeChecker::visit (ArrayExpr &expr)
327 {
328 expr.get_internal_elements ()->accept_vis (*this);
329 }
330
331 void
332 UnsafeChecker::visit (ArrayIndexExpr &expr)
333 {
334 expr.get_array_expr ()->accept_vis (*this);
335 expr.get_index_expr ()->accept_vis (*this);
336 }
337
338 void
339 UnsafeChecker::visit (TupleExpr &expr)
340 {
341 for (auto &elem : expr.get_tuple_elems ())
342 elem->accept_vis (*this);
343 }
344
345 void
346 UnsafeChecker::visit (TupleIndexExpr &expr)
347 {
348 expr.get_tuple_expr ()->accept_vis (*this);
349 }
350
351 void
352 UnsafeChecker::visit (StructExprStruct &expr)
353 {}
354
355 void
356 UnsafeChecker::visit (StructExprFieldIdentifier &field)
357 {}
358
359 void
360 UnsafeChecker::visit (StructExprFieldIdentifierValue &field)
361 {
362 field.get_value ()->accept_vis (*this);
363 }
364
365 void
366 UnsafeChecker::visit (StructExprFieldIndexValue &field)
367 {
368 field.get_value ()->accept_vis (*this);
369 }
370
371 void
372 UnsafeChecker::visit (StructExprStructFields &expr)
373 {
374 for (auto &field : expr.get_fields ())
375 field->accept_vis (*this);
376 }
377
378 void
379 UnsafeChecker::visit (StructExprStructBase &expr)
380 {}
381
382 void
383 UnsafeChecker::visit (CallExpr &expr)
384 {
385 auto fn = expr.get_fnexpr ();
386 if (!fn)
387 return;
388
389 NodeId ast_node_id = fn->get_mappings ().get_nodeid ();
390 NodeId ref_node_id;
391 HirId definition_id;
392
393 // There are no unsafe types, and functions are defined in the name resolver.
394 // If we can't find the name, then we're dealing with a type and should return
395 // early.
396 if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id))
397 return;
398
399 rust_assert (mappings.lookup_node_to_hir (ref_node_id, &definition_id));
400
401 // At this point we have the function's HIR Id. There are two checks we
402 // must perform:
403 // 1. The function is an unsafe one
404 // 2. The function is an extern one
405 check_function_call (definition_id, expr.get_locus ());
406
407 if (expr.has_params ())
408 for (auto &arg : expr.get_arguments ())
409 arg->accept_vis (*this);
410 }
411
412 void
413 UnsafeChecker::visit (MethodCallExpr &expr)
414 {
415 TyTy::BaseType *method_type;
416 context.lookup_type (expr.get_method_name ().get_mappings ().get_hirid (),
417 &method_type);
418
419 auto fn = *static_cast<TyTy::FnType *> (method_type);
420 auto method = mappings.lookup_hir_implitem (fn.get_ref (), nullptr);
421
422 if (!unsafe_context.is_in_context () && method)
423 check_unsafe_call (static_cast<Function *> (method), expr.get_locus (),
424 "method");
425
426 expr.get_receiver ()->accept_vis (*this);
427
428 for (auto &arg : expr.get_arguments ())
429 arg->accept_vis (*this);
430 }
431
432 void
433 UnsafeChecker::visit (FieldAccessExpr &expr)
434 {
435 expr.get_receiver_expr ()->accept_vis (*this);
436
437 if (unsafe_context.is_in_context ())
438 return;
439
440 TyTy::BaseType *receiver_ty;
441 auto ok = context.lookup_type (
442 expr.get_receiver_expr ()->get_mappings ().get_hirid (), &receiver_ty);
443 rust_assert (ok);
444
445 if (receiver_ty->get_kind () == TyTy::TypeKind::ADT)
446 {
447 auto maybe_union = static_cast<TyTy::ADTType *> (receiver_ty);
448 if (maybe_union->is_union ())
449 rust_error_at (
450 expr.get_locus (),
451 "access to union field requires unsafe function or block");
452 }
453 }
454
455 void
456 UnsafeChecker::visit (ClosureExprInner &expr)
457 {}
458
459 void
460 UnsafeChecker::visit (BlockExpr &expr)
461 {
462 for (auto &stmt : expr.get_statements ())
463 stmt->accept_vis (*this);
464
465 if (expr.has_expr ())
466 expr.get_final_expr ()->accept_vis (*this);
467 }
468
469 void
470 UnsafeChecker::visit (ClosureExprInnerTyped &expr)
471 {}
472
473 void
474 UnsafeChecker::visit (ContinueExpr &expr)
475 {}
476
477 void
478 UnsafeChecker::visit (BreakExpr &expr)
479 {
480 if (expr.has_break_expr ())
481 expr.get_expr ()->accept_vis (*this);
482 }
483
484 void
485 UnsafeChecker::visit (RangeFromToExpr &expr)
486 {
487 expr.get_from_expr ()->accept_vis (*this);
488 expr.get_to_expr ()->accept_vis (*this);
489 }
490
491 void
492 UnsafeChecker::visit (RangeFromExpr &expr)
493 {
494 expr.get_from_expr ()->accept_vis (*this);
495 }
496
497 void
498 UnsafeChecker::visit (RangeToExpr &expr)
499 {
500 expr.get_to_expr ()->accept_vis (*this);
501 }
502
503 void
504 UnsafeChecker::visit (RangeFullExpr &expr)
505 {}
506
507 void
508 UnsafeChecker::visit (RangeFromToInclExpr &expr)
509 {
510 expr.get_from_expr ()->accept_vis (*this);
511 expr.get_to_expr ()->accept_vis (*this);
512 }
513
514 void
515 UnsafeChecker::visit (RangeToInclExpr &expr)
516 {
517 expr.get_to_expr ()->accept_vis (*this);
518 }
519
520 void
521 UnsafeChecker::visit (ReturnExpr &expr)
522 {
523 if (expr.has_return_expr ())
524 expr.get_expr ()->accept_vis (*this);
525 }
526
527 void
528 UnsafeChecker::visit (UnsafeBlockExpr &expr)
529 {
530 unsafe_context.enter (expr.get_mappings ().get_hirid ());
531
532 expr.get_block_expr ()->accept_vis (*this);
533
534 unsafe_context.exit ();
535 }
536
537 void
538 UnsafeChecker::visit (LoopExpr &expr)
539 {
540 expr.get_loop_block ()->accept_vis (*this);
541 }
542
543 void
544 UnsafeChecker::visit (WhileLoopExpr &expr)
545 {
546 expr.get_predicate_expr ()->accept_vis (*this);
547 expr.get_loop_block ()->accept_vis (*this);
548 }
549
550 void
551 UnsafeChecker::visit (WhileLetLoopExpr &expr)
552 {
553 expr.get_cond ()->accept_vis (*this);
554 expr.get_loop_block ()->accept_vis (*this);
555 }
556
557 void
558 UnsafeChecker::visit (ForLoopExpr &expr)
559 {
560 expr.get_iterator_expr ()->accept_vis (*this);
561 expr.get_loop_block ()->accept_vis (*this);
562 }
563
564 void
565 UnsafeChecker::visit (IfExpr &expr)
566 {
567 expr.get_if_condition ()->accept_vis (*this);
568 expr.get_if_block ()->accept_vis (*this);
569 }
570
571 void
572 UnsafeChecker::visit (IfExprConseqElse &expr)
573 {
574 expr.get_if_condition ()->accept_vis (*this);
575 expr.get_if_block ()->accept_vis (*this);
576 expr.get_else_block ()->accept_vis (*this);
577 }
578
579 void
580 UnsafeChecker::visit (IfExprConseqIf &expr)
581 {
582 expr.get_if_condition ()->accept_vis (*this);
583 expr.get_if_block ()->accept_vis (*this);
584 expr.get_conseq_if_expr ()->accept_vis (*this);
585 }
586
587 void
588 UnsafeChecker::visit (IfExprConseqIfLet &expr)
589 {
590 expr.get_if_condition ()->accept_vis (*this);
591 expr.get_if_block ()->accept_vis (*this);
592
593 // TODO: Visit conseq if let expression
594 }
595
596 void
597 UnsafeChecker::visit (IfLetExpr &expr)
598 {
599 expr.get_scrutinee_expr ()->accept_vis (*this);
600 expr.get_if_block ()->accept_vis (*this);
601 }
602
603 void
604 UnsafeChecker::visit (IfLetExprConseqElse &expr)
605 {
606 expr.get_scrutinee_expr ()->accept_vis (*this);
607 expr.get_if_block ()->accept_vis (*this);
608
609 // TODO: Visit else expression
610 }
611
612 void
613 UnsafeChecker::visit (IfLetExprConseqIf &expr)
614 {
615 expr.get_scrutinee_expr ()->accept_vis (*this);
616 expr.get_if_block ()->accept_vis (*this);
617 }
618
619 void
620 UnsafeChecker::visit (IfLetExprConseqIfLet &expr)
621 {
622 expr.get_scrutinee_expr ()->accept_vis (*this);
623 expr.get_if_block ()->accept_vis (*this);
624
625 // TODO: Visit conseq if let expression
626 }
627
628 void
629 UnsafeChecker::visit (MatchExpr &expr)
630 {
631 expr.get_scrutinee_expr ()->accept_vis (*this);
632
633 for (auto &match_arm : expr.get_match_cases ())
634 match_arm.get_expr ()->accept_vis (*this);
635 }
636
637 void
638 UnsafeChecker::visit (AwaitExpr &expr)
639 {
640 // TODO: Visit expression
641 }
642
643 void
644 UnsafeChecker::visit (AsyncBlockExpr &expr)
645 {
646 // TODO: Visit block expression
647 }
648
649 void
650 UnsafeChecker::visit (TypeParam &param)
651 {}
652
653 void
654 UnsafeChecker::visit (ConstGenericParam &param)
655 {}
656
657 void
658 UnsafeChecker::visit (LifetimeWhereClauseItem &item)
659 {}
660
661 void
662 UnsafeChecker::visit (TypeBoundWhereClauseItem &item)
663 {}
664
665 void
666 UnsafeChecker::visit (Module &module)
667 {
668 for (auto &item : module.get_items ())
669 item->accept_vis (*this);
670 }
671
672 void
673 UnsafeChecker::visit (ExternCrate &crate)
674 {}
675
676 void
677 UnsafeChecker::visit (UseTreeGlob &use_tree)
678 {}
679
680 void
681 UnsafeChecker::visit (UseTreeList &use_tree)
682 {}
683
684 void
685 UnsafeChecker::visit (UseTreeRebind &use_tree)
686 {}
687
688 void
689 UnsafeChecker::visit (UseDeclaration &use_decl)
690 {}
691
692 void
693 UnsafeChecker::visit (Function &function)
694 {
695 auto is_unsafe_fn = function.get_qualifiers ().is_unsafe ();
696
697 if (is_unsafe_fn)
698 unsafe_context.enter (function.get_mappings ().get_hirid ());
699
700 function.get_definition ()->accept_vis (*this);
701
702 if (is_unsafe_fn)
703 unsafe_context.exit ();
704 }
705
706 void
707 UnsafeChecker::visit (TypeAlias &type_alias)
708 {
709 // FIXME: What do we need to do to handle type aliasing? Is it possible to
710 // have unsafe types? Type aliases on unsafe functions?
711 }
712
713 void
714 UnsafeChecker::visit (StructStruct &struct_item)
715 {}
716
717 void
718 UnsafeChecker::visit (TupleStruct &tuple_struct)
719 {}
720
721 void
722 UnsafeChecker::visit (EnumItem &item)
723 {}
724
725 void
726 UnsafeChecker::visit (EnumItemTuple &item)
727 {}
728
729 void
730 UnsafeChecker::visit (EnumItemStruct &item)
731 {}
732
733 void
734 UnsafeChecker::visit (EnumItemDiscriminant &item)
735 {}
736
737 void
738 UnsafeChecker::visit (Enum &enum_item)
739 {}
740
741 void
742 UnsafeChecker::visit (Union &union_item)
743 {}
744
745 void
746 UnsafeChecker::visit (ConstantItem &const_item)
747 {
748 const_item.get_expr ()->accept_vis (*this);
749 }
750
751 void
752 UnsafeChecker::visit (StaticItem &static_item)
753 {
754 static_item.get_expr ()->accept_vis (*this);
755 }
756
757 void
758 UnsafeChecker::visit (TraitItemFunc &item)
759 {
760 if (item.has_block_defined ())
761 item.get_block_expr ()->accept_vis (*this);
762 }
763
764 void
765 UnsafeChecker::visit (TraitItemConst &item)
766 {
767 if (item.has_expr ())
768 item.get_expr ()->accept_vis (*this);
769 }
770
771 void
772 UnsafeChecker::visit (TraitItemType &item)
773 {}
774
775 void
776 UnsafeChecker::visit (Trait &trait)
777 {
778 // FIXME: Handle unsafe traits
779 for (auto &item : trait.get_trait_items ())
780 item->accept_vis (*this);
781 }
782
783 void
784 UnsafeChecker::visit (ImplBlock &impl)
785 {
786 // FIXME: Handle unsafe impls
787 for (auto &item : impl.get_impl_items ())
788 item->accept_vis (*this);
789 }
790
791 void
792 UnsafeChecker::visit (ExternalStaticItem &item)
793 {}
794
795 void
796 UnsafeChecker::visit (ExternalFunctionItem &item)
797 {}
798
799 void
800 UnsafeChecker::visit (ExternBlock &block)
801 {
802 // FIXME: Do we need to do this?
803 for (auto &item : block.get_extern_items ())
804 item->accept_vis (*this);
805 }
806
807 void
808 UnsafeChecker::visit (LiteralPattern &pattern)
809 {}
810
811 void
812 UnsafeChecker::visit (IdentifierPattern &pattern)
813 {}
814
815 void
816 UnsafeChecker::visit (WildcardPattern &pattern)
817 {}
818
819 void
820 UnsafeChecker::visit (RangePatternBoundLiteral &bound)
821 {}
822
823 void
824 UnsafeChecker::visit (RangePatternBoundPath &bound)
825 {}
826
827 void
828 UnsafeChecker::visit (RangePatternBoundQualPath &bound)
829 {}
830
831 void
832 UnsafeChecker::visit (RangePattern &pattern)
833 {}
834
835 void
836 UnsafeChecker::visit (ReferencePattern &pattern)
837 {}
838
839 void
840 UnsafeChecker::visit (StructPatternFieldTuplePat &field)
841 {}
842
843 void
844 UnsafeChecker::visit (StructPatternFieldIdentPat &field)
845 {}
846
847 void
848 UnsafeChecker::visit (StructPatternFieldIdent &field)
849 {}
850
851 void
852 UnsafeChecker::visit (StructPattern &pattern)
853 {}
854
855 void
856 UnsafeChecker::visit (TupleStructItemsNoRange &tuple_items)
857 {}
858
859 void
860 UnsafeChecker::visit (TupleStructItemsRange &tuple_items)
861 {}
862
863 void
864 UnsafeChecker::visit (TupleStructPattern &pattern)
865 {}
866
867 void
868 UnsafeChecker::visit (TuplePatternItemsMultiple &tuple_items)
869 {}
870
871 void
872 UnsafeChecker::visit (TuplePatternItemsRanged &tuple_items)
873 {}
874
875 void
876 UnsafeChecker::visit (TuplePattern &pattern)
877 {}
878
879 void
880 UnsafeChecker::visit (GroupedPattern &pattern)
881 {}
882
883 void
884 UnsafeChecker::visit (SlicePattern &pattern)
885 {}
886
887 void
888 UnsafeChecker::visit (EmptyStmt &stmt)
889 {}
890
891 void
892 UnsafeChecker::visit (LetStmt &stmt)
893 {
894 if (stmt.has_init_expr ())
895 stmt.get_init_expr ()->accept_vis (*this);
896 }
897
898 void
899 UnsafeChecker::visit (ExprStmtWithoutBlock &stmt)
900 {
901 stmt.get_expr ()->accept_vis (*this);
902 }
903
904 void
905 UnsafeChecker::visit (ExprStmtWithBlock &stmt)
906 {
907 stmt.get_expr ()->accept_vis (*this);
908 }
909
910 void
911 UnsafeChecker::visit (TraitBound &bound)
912 {}
913
914 void
915 UnsafeChecker::visit (ImplTraitType &type)
916 {}
917
918 void
919 UnsafeChecker::visit (TraitObjectType &type)
920 {}
921
922 void
923 UnsafeChecker::visit (ParenthesisedType &type)
924 {}
925
926 void
927 UnsafeChecker::visit (ImplTraitTypeOneBound &type)
928 {}
929
930 void
931 UnsafeChecker::visit (TupleType &type)
932 {}
933
934 void
935 UnsafeChecker::visit (NeverType &type)
936 {}
937
938 void
939 UnsafeChecker::visit (RawPointerType &type)
940 {}
941
942 void
943 UnsafeChecker::visit (ReferenceType &type)
944 {}
945
946 void
947 UnsafeChecker::visit (ArrayType &type)
948 {}
949
950 void
951 UnsafeChecker::visit (SliceType &type)
952 {}
953
954 void
955 UnsafeChecker::visit (InferredType &type)
956 {}
957
958 void
959 UnsafeChecker::visit (BareFunctionType &type)
960 {}
961
962 } // namespace HIR
963 } // namespace Rust