rustc_mir_transform/
check_packed_ref.rs1use rustc_middle::mir::visit::{PlaceContext, Visitor};
2use rustc_middle::mir::*;
3use rustc_middle::ty::{self, TyCtxt};
4use rustc_span::span_bug;
5
6use crate::{diagnostics, 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 mut checker = PackedRefChecker { body, tcx, typing_env };
14 for (bb, data) in body.basic_blocks.iter_enumerated() {
15 checker.visit_basic_block_data(bb, data);
16 }
17 }
18}
19
20struct PackedRefChecker<'a, 'tcx> {
21 body: &'a Body<'tcx>,
22 tcx: TyCtxt<'tcx>,
23 typing_env: ty::TypingEnv<'tcx>,
24}
25
26impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> {
27 fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
28 if context.is_borrow()
29 && let Some((adt, pack)) =
30 util::place_unalignment(self.tcx, self.body, self.typing_env, *place)
31 {
32 let source_info = self.body.source_info(location);
33 let def_id = self.body.source.instance.def_id();
34 if let Some(impl_def_id) = self.tcx.trait_impl_of_assoc(def_id)
35 && self.tcx.is_builtin_derived(impl_def_id)
36 {
37 span_bug!(source_info.span, "builtin derive created an unaligned reference");
41 } else {
42 self.tcx.dcx().emit_err(diagnostics::UnalignedPackedRef {
43 span: source_info.span,
44 ty_descr: adt.descr(),
45 align: pack.bytes(),
46 });
47 }
48 }
49 }
50}