Emit explanatory note for move errors in packed struct derives
Derive expansions for packed structs cause move errors because they prefer copying over borrowing since borrowing the fields of a packed struct can result in unaligned access and therefore undefined behaviour. This underlying cause of the errors, however, is not apparent to the user. We add a diagnostic note here to remedy that.
This commit is contained in:
parent
a395214a3a
commit
4b3ece475d
4 changed files with 290 additions and 1 deletions
|
@ -2,7 +2,7 @@ use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed
|
|||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_mir_dataflow::move_paths::{LookupResult, MovePathIndex};
|
||||
use rustc_span::{BytePos, Span};
|
||||
use rustc_span::{BytePos, ExpnKind, MacroKind, Span};
|
||||
|
||||
use crate::diagnostics::CapturedMessageOpt;
|
||||
use crate::diagnostics::{DescribePlaceOpt, UseSpans};
|
||||
|
@ -488,6 +488,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
args_span,
|
||||
}
|
||||
});
|
||||
|
||||
self.add_note_for_packed_struct_derive(err, original_path.local);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -594,4 +596,20 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds an explanatory note if the move error occurs in a derive macro
|
||||
/// expansion of a packed struct.
|
||||
/// Such errors happen because derive macro expansions shy away from taking
|
||||
/// references to the struct's fields since doing so would be undefined behaviour
|
||||
fn add_note_for_packed_struct_derive(&self, err: &mut Diagnostic, local: Local) {
|
||||
let local_place: PlaceRef<'tcx> = local.into();
|
||||
let local_ty = local_place.ty(self.body.local_decls(), self.infcx.tcx).ty.peel_refs();
|
||||
|
||||
if let Some(adt) = local_ty.ty_adt_def()
|
||||
&& adt.repr().packed()
|
||||
&& let ExpnKind::Macro(MacroKind::Derive, name) = self.body.span.ctxt().outer_expn_data().kind
|
||||
{
|
||||
err.note(format!("`#[derive({name})]` triggers a move because taking references to the fields of a packed struct is undefined behaviour"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue