]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/rust/checks/errors/rust-unsafe-checker.cc
Update copyright years.
[thirdparty/gcc.git] / gcc / rust / checks / errors / rust-unsafe-checker.cc
CommitLineData
83ffe9cd 1// Copyright (C) 2020-2023 Free Software Foundation, Inc.
b1b35204
AC
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
25namespace Rust {
26namespace HIR {
27
28UnsafeChecker::UnsafeChecker ()
29 : context (*Resolver::TypeCheckContext::get ()),
30 resolver (*Resolver::Resolver::get ()),
31 mappings (*Analysis::Mappings::get ())
32{}
33
34void
35UnsafeChecker::go (HIR::Crate &crate)
36{
37 for (auto &item : crate.items)
38 item->accept_vis (*this);
39}
40
41static void
42check_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
57static void
58check_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
65void
66UnsafeChecker::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
85static void
86check_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
93static bool
94is_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
137static void
138check_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
162void
163UnsafeChecker::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
182void
183UnsafeChecker::visit (Lifetime &lifetime)
184{}
185
186void
187UnsafeChecker::visit (LifetimeParam &lifetime_param)
188{}
189
190void
191UnsafeChecker::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
205void
206UnsafeChecker::visit (TypePathSegment &segment)
207{}
208
209void
210UnsafeChecker::visit (TypePathSegmentGeneric &segment)
211{}
212
213void
214UnsafeChecker::visit (TypePathSegmentFunction &segment)
215{}
216
217void
218UnsafeChecker::visit (TypePath &path)
219{}
220
221void
222UnsafeChecker::visit (QualifiedPathInExpression &path)
223{}
224
225void
226UnsafeChecker::visit (QualifiedPathInType &path)
227{}
228
229void
230UnsafeChecker::visit (LiteralExpr &expr)
231{}
232
233void
234UnsafeChecker::visit (BorrowExpr &expr)
235{
236 expr.get_expr ()->accept_vis (*this);
237}
238
239void
240UnsafeChecker::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
253void
254UnsafeChecker::visit (ErrorPropagationExpr &expr)
255{
256 expr.get_expr ()->accept_vis (*this);
257}
258
259void
260UnsafeChecker::visit (NegationExpr &expr)
261{
262 expr.get_expr ()->accept_vis (*this);
263}
264
265void
266UnsafeChecker::visit (ArithmeticOrLogicalExpr &expr)
267{
268 expr.get_lhs ()->accept_vis (*this);
269 expr.get_rhs ()->accept_vis (*this);
270}
271
272void
273UnsafeChecker::visit (ComparisonExpr &expr)
274{
275 expr.get_lhs ()->accept_vis (*this);
276 expr.get_rhs ()->accept_vis (*this);
277}
278
279void
280UnsafeChecker::visit (LazyBooleanExpr &expr)
281{
282 expr.get_lhs ()->accept_vis (*this);
283 expr.get_rhs ()->accept_vis (*this);
284}
285
286void
287UnsafeChecker::visit (TypeCastExpr &expr)
288{
289 expr.get_expr ()->accept_vis (*this);
290}
291
292void
293UnsafeChecker::visit (AssignmentExpr &expr)
294{
295 expr.get_lhs ()->accept_vis (*this);
296 expr.get_rhs ()->accept_vis (*this);
297}
298
299void
300UnsafeChecker::visit (CompoundAssignmentExpr &expr)
301{
302 expr.get_left_expr ()->accept_vis (*this);
303 expr.get_right_expr ()->accept_vis (*this);
304}
305
306void
307UnsafeChecker::visit (GroupedExpr &expr)
308{
309 expr.get_expr_in_parens ()->accept_vis (*this);
310}
311
312void
313UnsafeChecker::visit (ArrayElemsValues &elems)
314{
315 for (auto &elem : elems.get_values ())
316 elem->accept_vis (*this);
317}
318
319void
320UnsafeChecker::visit (ArrayElemsCopied &elems)
321{
322 elems.get_elem_to_copy ()->accept_vis (*this);
323}
324
325void
326UnsafeChecker::visit (ArrayExpr &expr)
327{
328 expr.get_internal_elements ()->accept_vis (*this);
329}
330
331void
332UnsafeChecker::visit (ArrayIndexExpr &expr)
333{
334 expr.get_array_expr ()->accept_vis (*this);
335 expr.get_index_expr ()->accept_vis (*this);
336}
337
338void
339UnsafeChecker::visit (TupleExpr &expr)
340{
341 for (auto &elem : expr.get_tuple_elems ())
342 elem->accept_vis (*this);
343}
344
345void
346UnsafeChecker::visit (TupleIndexExpr &expr)
347{
348 expr.get_tuple_expr ()->accept_vis (*this);
349}
350
351void
352UnsafeChecker::visit (StructExprStruct &expr)
353{}
354
355void
356UnsafeChecker::visit (StructExprFieldIdentifier &field)
357{}
358
359void
360UnsafeChecker::visit (StructExprFieldIdentifierValue &field)
361{
362 field.get_value ()->accept_vis (*this);
363}
364
365void
366UnsafeChecker::visit (StructExprFieldIndexValue &field)
367{
368 field.get_value ()->accept_vis (*this);
369}
370
371void
372UnsafeChecker::visit (StructExprStructFields &expr)
373{
374 for (auto &field : expr.get_fields ())
375 field->accept_vis (*this);
376}
377
378void
379UnsafeChecker::visit (StructExprStructBase &expr)
380{}
381
382void
383UnsafeChecker::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
412void
413UnsafeChecker::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
432void
433UnsafeChecker::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
455void
456UnsafeChecker::visit (ClosureExprInner &expr)
457{}
458
459void
460UnsafeChecker::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
469void
470UnsafeChecker::visit (ClosureExprInnerTyped &expr)
471{}
472
473void
474UnsafeChecker::visit (ContinueExpr &expr)
475{}
476
477void
478UnsafeChecker::visit (BreakExpr &expr)
479{
480 if (expr.has_break_expr ())
481 expr.get_expr ()->accept_vis (*this);
482}
483
484void
485UnsafeChecker::visit (RangeFromToExpr &expr)
486{
487 expr.get_from_expr ()->accept_vis (*this);
488 expr.get_to_expr ()->accept_vis (*this);
489}
490
491void
492UnsafeChecker::visit (RangeFromExpr &expr)
493{
494 expr.get_from_expr ()->accept_vis (*this);
495}
496
497void
498UnsafeChecker::visit (RangeToExpr &expr)
499{
500 expr.get_to_expr ()->accept_vis (*this);
501}
502
503void
504UnsafeChecker::visit (RangeFullExpr &expr)
505{}
506
507void
508UnsafeChecker::visit (RangeFromToInclExpr &expr)
509{
510 expr.get_from_expr ()->accept_vis (*this);
511 expr.get_to_expr ()->accept_vis (*this);
512}
513
514void
515UnsafeChecker::visit (RangeToInclExpr &expr)
516{
517 expr.get_to_expr ()->accept_vis (*this);
518}
519
520void
521UnsafeChecker::visit (ReturnExpr &expr)
522{
523 if (expr.has_return_expr ())
524 expr.get_expr ()->accept_vis (*this);
525}
526
527void
528UnsafeChecker::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
537void
538UnsafeChecker::visit (LoopExpr &expr)
539{
540 expr.get_loop_block ()->accept_vis (*this);
541}
542
543void
544UnsafeChecker::visit (WhileLoopExpr &expr)
545{
546 expr.get_predicate_expr ()->accept_vis (*this);
547 expr.get_loop_block ()->accept_vis (*this);
548}
549
550void
551UnsafeChecker::visit (WhileLetLoopExpr &expr)
552{
553 expr.get_cond ()->accept_vis (*this);
554 expr.get_loop_block ()->accept_vis (*this);
555}
556
557void
558UnsafeChecker::visit (ForLoopExpr &expr)
559{
560 expr.get_iterator_expr ()->accept_vis (*this);
561 expr.get_loop_block ()->accept_vis (*this);
562}
563
564void
565UnsafeChecker::visit (IfExpr &expr)
566{
567 expr.get_if_condition ()->accept_vis (*this);
568 expr.get_if_block ()->accept_vis (*this);
569}
570
571void
572UnsafeChecker::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
579void
580UnsafeChecker::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
587void
588UnsafeChecker::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
596void
597UnsafeChecker::visit (IfLetExpr &expr)
598{
599 expr.get_scrutinee_expr ()->accept_vis (*this);
600 expr.get_if_block ()->accept_vis (*this);
601}
602
603void
604UnsafeChecker::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
612void
613UnsafeChecker::visit (IfLetExprConseqIf &expr)
614{
615 expr.get_scrutinee_expr ()->accept_vis (*this);
616 expr.get_if_block ()->accept_vis (*this);
617}
618
619void
620UnsafeChecker::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
628void
629UnsafeChecker::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
637void
638UnsafeChecker::visit (AwaitExpr &expr)
639{
640 // TODO: Visit expression
641}
642
643void
644UnsafeChecker::visit (AsyncBlockExpr &expr)
645{
646 // TODO: Visit block expression
647}
648
649void
650UnsafeChecker::visit (TypeParam &param)
651{}
652
653void
654UnsafeChecker::visit (ConstGenericParam &param)
655{}
656
657void
658UnsafeChecker::visit (LifetimeWhereClauseItem &item)
659{}
660
661void
662UnsafeChecker::visit (TypeBoundWhereClauseItem &item)
663{}
664
665void
666UnsafeChecker::visit (Module &module)
667{
668 for (auto &item : module.get_items ())
669 item->accept_vis (*this);
670}
671
672void
673UnsafeChecker::visit (ExternCrate &crate)
674{}
675
676void
677UnsafeChecker::visit (UseTreeGlob &use_tree)
678{}
679
680void
681UnsafeChecker::visit (UseTreeList &use_tree)
682{}
683
684void
685UnsafeChecker::visit (UseTreeRebind &use_tree)
686{}
687
688void
689UnsafeChecker::visit (UseDeclaration &use_decl)
690{}
691
692void
693UnsafeChecker::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
706void
707UnsafeChecker::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
713void
714UnsafeChecker::visit (StructStruct &struct_item)
715{}
716
717void
718UnsafeChecker::visit (TupleStruct &tuple_struct)
719{}
720
721void
722UnsafeChecker::visit (EnumItem &item)
723{}
724
725void
726UnsafeChecker::visit (EnumItemTuple &item)
727{}
728
729void
730UnsafeChecker::visit (EnumItemStruct &item)
731{}
732
733void
734UnsafeChecker::visit (EnumItemDiscriminant &item)
735{}
736
737void
738UnsafeChecker::visit (Enum &enum_item)
739{}
740
741void
742UnsafeChecker::visit (Union &union_item)
743{}
744
745void
746UnsafeChecker::visit (ConstantItem &const_item)
747{
748 const_item.get_expr ()->accept_vis (*this);
749}
750
751void
752UnsafeChecker::visit (StaticItem &static_item)
753{
754 static_item.get_expr ()->accept_vis (*this);
755}
756
757void
758UnsafeChecker::visit (TraitItemFunc &item)
759{
760 if (item.has_block_defined ())
761 item.get_block_expr ()->accept_vis (*this);
762}
763
764void
765UnsafeChecker::visit (TraitItemConst &item)
766{
767 if (item.has_expr ())
768 item.get_expr ()->accept_vis (*this);
769}
770
771void
772UnsafeChecker::visit (TraitItemType &item)
773{}
774
775void
776UnsafeChecker::visit (Trait &trait)
777{
778 // FIXME: Handle unsafe traits
779 for (auto &item : trait.get_trait_items ())
780 item->accept_vis (*this);
781}
782
783void
784UnsafeChecker::visit (ImplBlock &impl)
785{
786 // FIXME: Handle unsafe impls
787 for (auto &item : impl.get_impl_items ())
788 item->accept_vis (*this);
789}
790
791void
792UnsafeChecker::visit (ExternalStaticItem &item)
793{}
794
795void
796UnsafeChecker::visit (ExternalFunctionItem &item)
797{}
798
799void
800UnsafeChecker::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
807void
808UnsafeChecker::visit (LiteralPattern &pattern)
809{}
810
811void
812UnsafeChecker::visit (IdentifierPattern &pattern)
813{}
814
815void
816UnsafeChecker::visit (WildcardPattern &pattern)
817{}
818
819void
820UnsafeChecker::visit (RangePatternBoundLiteral &bound)
821{}
822
823void
824UnsafeChecker::visit (RangePatternBoundPath &bound)
825{}
826
827void
828UnsafeChecker::visit (RangePatternBoundQualPath &bound)
829{}
830
831void
832UnsafeChecker::visit (RangePattern &pattern)
833{}
834
835void
836UnsafeChecker::visit (ReferencePattern &pattern)
837{}
838
839void
840UnsafeChecker::visit (StructPatternFieldTuplePat &field)
841{}
842
843void
844UnsafeChecker::visit (StructPatternFieldIdentPat &field)
845{}
846
847void
848UnsafeChecker::visit (StructPatternFieldIdent &field)
849{}
850
851void
852UnsafeChecker::visit (StructPattern &pattern)
853{}
854
855void
856UnsafeChecker::visit (TupleStructItemsNoRange &tuple_items)
857{}
858
859void
860UnsafeChecker::visit (TupleStructItemsRange &tuple_items)
861{}
862
863void
864UnsafeChecker::visit (TupleStructPattern &pattern)
865{}
866
867void
868UnsafeChecker::visit (TuplePatternItemsMultiple &tuple_items)
869{}
870
871void
872UnsafeChecker::visit (TuplePatternItemsRanged &tuple_items)
873{}
874
875void
876UnsafeChecker::visit (TuplePattern &pattern)
877{}
878
879void
880UnsafeChecker::visit (GroupedPattern &pattern)
881{}
882
883void
884UnsafeChecker::visit (SlicePattern &pattern)
885{}
886
887void
888UnsafeChecker::visit (EmptyStmt &stmt)
889{}
890
891void
892UnsafeChecker::visit (LetStmt &stmt)
893{
894 if (stmt.has_init_expr ())
895 stmt.get_init_expr ()->accept_vis (*this);
896}
897
898void
899UnsafeChecker::visit (ExprStmtWithoutBlock &stmt)
900{
901 stmt.get_expr ()->accept_vis (*this);
902}
903
904void
905UnsafeChecker::visit (ExprStmtWithBlock &stmt)
906{
907 stmt.get_expr ()->accept_vis (*this);
908}
909
910void
911UnsafeChecker::visit (TraitBound &bound)
912{}
913
914void
915UnsafeChecker::visit (ImplTraitType &type)
916{}
917
918void
919UnsafeChecker::visit (TraitObjectType &type)
920{}
921
922void
923UnsafeChecker::visit (ParenthesisedType &type)
924{}
925
926void
927UnsafeChecker::visit (ImplTraitTypeOneBound &type)
928{}
929
930void
931UnsafeChecker::visit (TupleType &type)
932{}
933
934void
935UnsafeChecker::visit (NeverType &type)
936{}
937
938void
939UnsafeChecker::visit (RawPointerType &type)
940{}
941
942void
943UnsafeChecker::visit (ReferenceType &type)
944{}
945
946void
947UnsafeChecker::visit (ArrayType &type)
948{}
949
950void
951UnsafeChecker::visit (SliceType &type)
952{}
953
954void
955UnsafeChecker::visit (InferredType &type)
956{}
957
958void
959UnsafeChecker::visit (BareFunctionType &type)
960{}
961
962} // namespace HIR
963} // namespace Rust