rustc_mir_transform/
check_packed_ref.rs

1use 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        // Make sure we know where in the MIR we are.
29        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        // Make sure we know where in the MIR we are.
35        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                // If we ever reach here it means that the generated derive
47                // code is somehow doing an unaligned reference, which it
48                // shouldn't do.
49                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}