Auto merge of #108128 - clubby789:builtin-derived-attr, r=jackh726

Properly check for builtin derived code

Fixes #108122
This commit is contained in:
bors 2023-02-19 21:18:07 +00:00
commit 21e5b941e0
8 changed files with 60 additions and 34 deletions

View File

@ -761,8 +761,7 @@ impl<'a> TraitDef<'a> {
let path = cx.path_all(self.span, false, vec![type_ident], self_params);
let self_type = cx.ty_path(path);
let attr = cx.attr_word(sym::automatically_derived, self.span);
let attrs = thin_vec![attr];
let attrs = thin_vec![cx.attr_word(sym::automatically_derived, self.span),];
let opt_trait_ref = Some(trait_ref);
cx.item(

View File

@ -46,7 +46,7 @@ use rustc_serialize::{Decodable, Encodable};
use rustc_session::cstore::Untracked;
use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{ExpnId, Span};
use rustc_span::{ExpnId, ExpnKind, Span};
use rustc_target::abi::{Align, Integer, IntegerType, VariantIdx};
pub use rustc_target::abi::{ReprFlags, ReprOptions};
use rustc_type_ir::WithCachedTypeInfo;
@ -2444,8 +2444,23 @@ impl<'tcx> TyCtxt<'tcx> {
None
}
/// If the given `DefId` belongs to a trait that was automatically derived, returns `true`.
pub fn is_builtin_derive(self, def_id: DefId) -> bool {
/// Check if the given `DefId` is `#\[automatically_derived\], *and*
/// whether it was produced by expanding a builtin derive macro.
pub fn is_builtin_derived(self, def_id: DefId) -> bool {
if self.is_automatically_derived(def_id)
&& let Some(def_id) = def_id.as_local()
&& let outer = self.def_span(def_id).ctxt().outer_expn_data()
&& matches!(outer.kind, ExpnKind::Macro(MacroKind::Derive, _))
&& self.has_attr(outer.macro_def_id.unwrap(), sym::rustc_builtin_macro)
{
true
} else {
false
}
}
/// Check if the given `DefId` is `#\[automatically_derived\]`.
pub fn is_automatically_derived(self, def_id: DefId) -> bool {
self.has_attr(def_id, sym::automatically_derived)
}

View File

@ -42,12 +42,12 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> {
if util::is_disaligned(self.tcx, self.body, self.param_env, *place) {
let def_id = self.body.source.instance.def_id();
if let Some(impl_def_id) = self.tcx.impl_of_method(def_id)
&& self.tcx.is_builtin_derive(impl_def_id)
&& self.tcx.is_builtin_derived(impl_def_id)
{
// If we ever reach here it means that the generated derive
// code is somehow doing an unaligned reference, which it
// shouldn't do.
unreachable!();
span_bug!(self.source_info.span, "builtin derive created an unaligned reference");
} else {
struct_span_err!(
self.tcx.sess,

View File

@ -259,7 +259,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
/// for discussion).
fn should_ignore_item(&mut self, def_id: DefId) -> bool {
if let Some(impl_of) = self.tcx.impl_of_method(def_id) {
if !self.tcx.has_attr(impl_of, sym::automatically_derived) {
if !self.tcx.is_automatically_derived(impl_of) {
return false;
}

View File

@ -537,7 +537,7 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
// then it would be "stable" at least for the impl.
// We gate usages of it using `feature(const_trait_impl)` anyways
// so there is no unstable leakage
if self.tcx.is_builtin_derive(def_id.to_def_id()) {
if self.tcx.is_automatically_derived(def_id.to_def_id()) {
return;
}

View File

@ -2104,7 +2104,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// Ignore automatically derived impls and `!Trait` impls.
.filter(|&def_id| {
self.tcx.impl_polarity(def_id) != ty::ImplPolarity::Negative
|| self.tcx.is_builtin_derive(def_id)
|| self.tcx.is_automatically_derived(def_id)
})
.filter_map(|def_id| self.tcx.impl_trait_ref(def_id))
.map(ty::EarlyBinder::subst_identity)

View File

@ -13,6 +13,20 @@ pub struct Packed2 {
z: u8,
}
trait Foo {
fn evil(&self);
}
// Test for #108122
#[automatically_derived]
impl Foo for Packed2 {
fn evil(&self) {
unsafe {
&self.x; //~ ERROR reference to packed field
}
}
}
fn main() {
unsafe {
let good = Good { data: 0, ptr: &0, data2: [0, 0], aligned: [0; 32] };
@ -37,6 +51,7 @@ fn main() {
let _ = &packed2.x; //~ ERROR reference to packed field
let _ = &packed2.y; // ok, has align 2 in packed(2) struct
let _ = &packed2.z; // ok, has align 1
packed2.evil();
}
unsafe {
@ -71,22 +86,10 @@ fn main() {
#[repr(packed)]
struct Misalign<T>(u8, T);
let m1 = Misalign(
0,
Wrapper {
a: U16(10),
b: HasDrop,
},
);
let m1 = Misalign(0, Wrapper { a: U16(10), b: HasDrop });
let _ref = &m1.1.a; //~ ERROR reference to packed field
let m2 = Misalign(
0,
Wrapper2 {
a: U16(10),
b: HasDrop,
},
);
let m2 = Misalign(0, Wrapper2 { a: U16(10), b: HasDrop });
let _ref = &m2.1.a; //~ ERROR reference to packed field
}
}

View File

@ -1,5 +1,14 @@
error[E0793]: reference to packed field is unaligned
--> $DIR/unaligned_references.rs:20:17
--> $DIR/unaligned_references.rs:25:13
|
LL | &self.x;
| ^^^^^^^
|
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
--> $DIR/unaligned_references.rs:34:17
|
LL | let _ = &good.ptr;
| ^^^^^^^^^
@ -8,7 +17,7 @@ LL | let _ = &good.ptr;
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
--> $DIR/unaligned_references.rs:21:17
--> $DIR/unaligned_references.rs:35:17
|
LL | let _ = &good.data;
| ^^^^^^^^^^
@ -17,7 +26,7 @@ LL | let _ = &good.data;
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
--> $DIR/unaligned_references.rs:23:17
--> $DIR/unaligned_references.rs:37:17
|
LL | let _ = &good.data as *const _;
| ^^^^^^^^^^
@ -26,7 +35,7 @@ LL | let _ = &good.data as *const _;
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
--> $DIR/unaligned_references.rs:24:27
--> $DIR/unaligned_references.rs:38:27
|
LL | let _: *const _ = &good.data;
| ^^^^^^^^^^
@ -35,7 +44,7 @@ LL | let _: *const _ = &good.data;
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
--> $DIR/unaligned_references.rs:26:17
--> $DIR/unaligned_references.rs:40:17
|
LL | let _ = good.data.clone();
| ^^^^^^^^^^^^^^^^^
@ -44,7 +53,7 @@ LL | let _ = good.data.clone();
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
--> $DIR/unaligned_references.rs:28:17
--> $DIR/unaligned_references.rs:42:17
|
LL | let _ = &good.data2[0];
| ^^^^^^^^^^^^^^
@ -53,7 +62,7 @@ LL | let _ = &good.data2[0];
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
--> $DIR/unaligned_references.rs:37:17
--> $DIR/unaligned_references.rs:51:17
|
LL | let _ = &packed2.x;
| ^^^^^^^^^^
@ -62,7 +71,7 @@ LL | let _ = &packed2.x;
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
--> $DIR/unaligned_references.rs:81:20
--> $DIR/unaligned_references.rs:90:20
|
LL | let _ref = &m1.1.a;
| ^^^^^^^
@ -71,7 +80,7 @@ LL | let _ref = &m1.1.a;
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
--> $DIR/unaligned_references.rs:90:20
--> $DIR/unaligned_references.rs:93:20
|
LL | let _ref = &m2.1.a;
| ^^^^^^^
@ -79,6 +88,6 @@ LL | let _ref = &m2.1.a;
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error: aborting due to 9 previous errors
error: aborting due to 10 previous errors
For more information about this error, try `rustc --explain E0793`.