about summary refs log tree commit diff
path: root/compiler/rustc_borrowck/src/diagnostics
diff options
context:
space:
mode:
authorGurinder Singh <frederick.the.fool@gmail.com>2023-11-03 07:32:10 +0530
committerGurinder Singh <frederick.the.fool@gmail.com>2023-11-03 07:32:10 +0530
commit4b3ece475d6e77465a30c8b53d7e1e9e861e4b79 (patch)
tree27e4c496d6eeae63e1797d63c50662f78a663125 /compiler/rustc_borrowck/src/diagnostics
parenta395214a3a88be976eec9256987d5eb6b3584bdc (diff)
downloadrust-4b3ece475d6e77465a30c8b53d7e1e9e861e4b79.tar.gz
rust-4b3ece475d6e77465a30c8b53d7e1e9e861e4b79.zip
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.
Diffstat (limited to 'compiler/rustc_borrowck/src/diagnostics')
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/move_errors.rs20
1 files changed, 19 insertions, 1 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index 695ac6980cd..41d6b98d7cf 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -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"));
+        }
+    }
 }