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()
41 && let Some((adt, pack)) =
42 util::place_unalignment(self.tcx, self.body, self.typing_env, *place)
43 {
44 let def_id = self.body.source.instance.def_id();
45 if let Some(impl_def_id) = self.tcx.trait_impl_of_assoc(def_id)
46 && self.tcx.is_builtin_derived(impl_def_id)
47 {
48 span_bug!(self.source_info.span, "builtin derive created an unaligned reference");
52 } else {
53 self.tcx.dcx().emit_err(errors::UnalignedPackedRef {
54 span: self.source_info.span,
55 ty_descr: adt.descr(),
56 align: pack.bytes(),
57 });
58 }
59 }
60 }
61}