rustc_mir_transform/
check_packed_ref.rs1use rustc_middle::mir::visit::{PlaceContext, Visitor};
2use rustc_middle::mir::*;
3use rustc_middle::span_bug;
4use rustc_middle::ty::{self, TyCtxt};
5
6use crate::{errors, util};
7
8pub(super) struct CheckPackedRef;
9
10impl<'tcx> crate::MirLint<'tcx> for CheckPackedRef {
11 fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
12 let typing_env = body.typing_env(tcx);
13 let source_info = SourceInfo::outermost(body.span);
14 let mut checker = PackedRefChecker { body, tcx, typing_env, source_info };
15 checker.visit_body(body);
16 }
17}
18
19struct PackedRefChecker<'a, 'tcx> {
20 body: &'a Body<'tcx>,
21 tcx: TyCtxt<'tcx>,
22 typing_env: ty::TypingEnv<'tcx>,
23 source_info: SourceInfo,
24}
25
26impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> {
27 fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
28 self.source_info = terminator.source_info;
30 self.super_terminator(terminator, location);
31 }
32
33 fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
34 self.source_info = statement.source_info;
36 self.super_statement(statement, location);
37 }
38
39 fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
40 if context.is_borrow() && util::is_disaligned(self.tcx, self.body, self.typing_env, *place)
41 {
42 let def_id = self.body.source.instance.def_id();
43 if let Some(impl_def_id) = self.tcx.impl_of_method(def_id)
44 && self.tcx.is_builtin_derived(impl_def_id)
45 {
46 span_bug!(self.source_info.span, "builtin derive created an unaligned reference");
50 } else {
51 self.tcx.dcx().emit_err(errors::UnalignedPackedRef { span: self.source_info.span });
52 }
53 }
54 }
55}