rustc_layout/abi: error when attribute is applied to the wrong thing

This commit is contained in:
Ralf Jung 2023-09-02 14:03:25 +02:00
parent 9570cac019
commit e66913f8fe
8 changed files with 134 additions and 63 deletions

View file

@ -4,15 +4,11 @@
-passes_see_issue =
see issue #{$issue} <https://github.com/rust-lang/rust/issues/{$issue}> for more information
passes_abi =
abi: {$abi}
passes_abi_invalid_attribute =
`#[rustc_abi]` can only be applied to function items, type aliases, and associated functions
passes_abi_of =
fn_abi_of({$fn_name}) = {$fn_abi}
passes_align =
align: {$align}
passes_allow_incoherent_impl =
`rustc_allow_incoherent_impl` attribute should be applied to impl items.
.label = the only currently supported targets are inherent methods
@ -318,9 +314,6 @@ passes_has_incoherent_inherent_impl =
`rustc_has_incoherent_inherent_impls` attribute should be applied to types or traits.
.label = only adts, extern types and traits are supported
passes_homogeneous_aggregate =
homogeneous_aggregate: {$homogeneous_aggregate}
passes_ignored_attr =
`#[{$sym}]` is ignored on struct fields and match arms
.warn = {-passes_previously_accepted}
@ -404,9 +397,18 @@ passes_lang_item_on_incorrect_target =
passes_layout =
layout error: {$layout_error}
passes_layout_abi =
abi: {$abi}
passes_layout_align =
align: {$align}
passes_layout_homogeneous_aggregate =
homogeneous_aggregate: {$homogeneous_aggregate}
passes_layout_invalid_attribute =
`#[rustc_layout]` can only be applied to `struct`/`enum`/`union` declarations and type aliases
passes_layout_of =
layout_of({$normalized_ty}) = {$ty_layout}
passes_layout_size =
size: {$size}
passes_link =
attribute should be applied to an `extern` block with non-Rust ABI
@ -662,9 +664,6 @@ passes_should_be_applied_to_trait =
attribute should be applied to a trait
.label = not a trait
passes_size =
size: {$size}
passes_skipping_const_checks = skipping const checks
passes_stability_promotable =

View file

@ -7,7 +7,7 @@
use rustc_span::symbol::sym;
use rustc_target::abi::call::FnAbi;
use crate::errors::{AbiOf, UnrecognizedField};
use crate::errors::{AbiInvalidAttribute, AbiOf, UnrecognizedField};
pub fn test_abi(tcx: TyCtxt<'_>) {
if !tcx.features().rustc_attrs {
@ -15,28 +15,33 @@ pub fn test_abi(tcx: TyCtxt<'_>) {
return;
}
for id in tcx.hir().items() {
match tcx.def_kind(id.owner_id) {
DefKind::Fn => {
for attr in tcx.get_attrs(id.owner_id, sym::rustc_abi) {
for attr in tcx.get_attrs(id.owner_id, sym::rustc_abi) {
match tcx.def_kind(id.owner_id) {
DefKind::Fn => {
dump_abi_of_fn_item(tcx, id.owner_id.def_id.into(), attr);
}
}
DefKind::TyAlias { .. } => {
for attr in tcx.get_attrs(id.owner_id, sym::rustc_abi) {
DefKind::TyAlias { .. } => {
dump_abi_of_fn_type(tcx, id.owner_id.def_id.into(), attr);
}
_ => {
tcx.sess.emit_err(AbiInvalidAttribute { span: tcx.def_span(id.owner_id) });
}
}
DefKind::Impl { .. } => {
// To find associated functions we need to go into the child items here.
for &id in tcx.associated_item_def_ids(id.owner_id) {
if matches!(tcx.def_kind(id), DefKind::AssocFn) {
for attr in tcx.get_attrs(id, sym::rustc_abi) {
}
if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. }) {
// To find associated functions we need to go into the child items here.
for &id in tcx.associated_item_def_ids(id.owner_id) {
for attr in tcx.get_attrs(id, sym::rustc_abi) {
match tcx.def_kind(id) {
DefKind::AssocFn => {
dump_abi_of_fn_item(tcx, id, attr);
}
_ => {
tcx.sess.emit_err(AbiInvalidAttribute { span: tcx.def_span(id) });
}
}
}
}
_ => {}
}
}
}

View file

@ -873,32 +873,32 @@ pub struct DuplicateDiagnosticItemInCrate {
}
#[derive(Diagnostic)]
#[diag(passes_abi)]
pub struct Abi {
#[diag(passes_layout_abi)]
pub struct LayoutAbi {
#[primary_span]
pub span: Span,
pub abi: String,
}
#[derive(Diagnostic)]
#[diag(passes_align)]
pub struct Align {
#[diag(passes_layout_align)]
pub struct LayoutAlign {
#[primary_span]
pub span: Span,
pub align: String,
}
#[derive(Diagnostic)]
#[diag(passes_size)]
pub struct Size {
#[diag(passes_layout_size)]
pub struct LayoutSize {
#[primary_span]
pub span: Span,
pub size: String,
}
#[derive(Diagnostic)]
#[diag(passes_homogeneous_aggregate)]
pub struct HomogeneousAggregate {
#[diag(passes_layout_homogeneous_aggregate)]
pub struct LayoutHomogeneousAggregate {
#[primary_span]
pub span: Span,
pub homogeneous_aggregate: String,
@ -913,6 +913,13 @@ pub struct LayoutOf {
pub ty_layout: String,
}
#[derive(Diagnostic)]
#[diag(passes_layout_invalid_attribute)]
pub struct LayoutInvalidAttribute {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(passes_abi_of)]
pub struct AbiOf {
@ -922,6 +929,13 @@ pub struct AbiOf {
pub fn_abi: String,
}
#[derive(Diagnostic)]
#[diag(passes_abi_invalid_attribute)]
pub struct AbiInvalidAttribute {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(passes_unrecognized_field)]
pub struct UnrecognizedField {

View file

@ -8,7 +8,10 @@
use rustc_span::Span;
use rustc_target::abi::{HasDataLayout, TargetDataLayout};
use crate::errors::{Abi, Align, HomogeneousAggregate, LayoutOf, Size, UnrecognizedField};
use crate::errors::{
LayoutAbi, LayoutAlign, LayoutHomogeneousAggregate, LayoutInvalidAttribute, LayoutOf,
LayoutSize, UnrecognizedField,
};
pub fn test_layout(tcx: TyCtxt<'_>) {
if !tcx.features().rustc_attrs {
@ -16,12 +19,22 @@ pub fn test_layout(tcx: TyCtxt<'_>) {
return;
}
for id in tcx.hir().items() {
if matches!(
tcx.def_kind(id.owner_id),
DefKind::TyAlias { .. } | DefKind::Enum | DefKind::Struct | DefKind::Union
) {
for attr in tcx.get_attrs(id.owner_id, sym::rustc_layout) {
dump_layout_of(tcx, id.owner_id.def_id, attr);
for attr in tcx.get_attrs(id.owner_id, sym::rustc_layout) {
match tcx.def_kind(id.owner_id) {
DefKind::TyAlias { .. } | DefKind::Enum | DefKind::Struct | DefKind::Union => {
dump_layout_of(tcx, id.owner_id.def_id, attr);
}
_ => {
tcx.sess.emit_err(LayoutInvalidAttribute { span: tcx.def_span(id.owner_id) });
}
}
}
if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. }) {
// To find associated functions we need to go into the child items here.
for &id in tcx.associated_item_def_ids(id.owner_id) {
for _attr in tcx.get_attrs(id, sym::rustc_layout) {
tcx.sess.emit_err(LayoutInvalidAttribute { span: tcx.def_span(id) });
}
}
}
}
@ -38,28 +51,28 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
for meta_item in meta_items {
match meta_item.name_or_empty() {
sym::abi => {
tcx.sess.emit_err(Abi {
tcx.sess.emit_err(LayoutAbi {
span: tcx.def_span(item_def_id.to_def_id()),
abi: format!("{:?}", ty_layout.abi),
});
}
sym::align => {
tcx.sess.emit_err(Align {
tcx.sess.emit_err(LayoutAlign {
span: tcx.def_span(item_def_id.to_def_id()),
align: format!("{:?}", ty_layout.align),
});
}
sym::size => {
tcx.sess.emit_err(Size {
tcx.sess.emit_err(LayoutSize {
span: tcx.def_span(item_def_id.to_def_id()),
size: format!("{:?}", ty_layout.size),
});
}
sym::homogeneous_aggregate => {
tcx.sess.emit_err(HomogeneousAggregate {
tcx.sess.emit_err(LayoutHomogeneousAggregate {
span: tcx.def_span(item_def_id.to_def_id()),
homogeneous_aggregate: format!(
"{:?}",

View file

@ -9,6 +9,8 @@
#![feature(rustc_attrs)]
#![crate_type = "lib"]
struct S(u16);
#[rustc_abi(debug)]
fn test(_x: u8) -> bool { true } //~ ERROR: fn_abi
@ -18,7 +20,14 @@ fn test(_x: u8) -> bool { true } //~ ERROR: fn_abi
#[rustc_abi(debug)]
fn test_generic<T>(_x: *const T) { } //~ ERROR: fn_abi
struct S(u16);
#[rustc_abi(debug)]
const C: () = (); //~ ERROR: can only be applied to
impl S {
#[rustc_abi(debug)]
const C: () = (); //~ ERROR: can only be applied to
}
impl S {
#[rustc_abi(debug)]
fn assoc_test(&self) { } //~ ERROR: fn_abi

View file

@ -87,7 +87,7 @@ error: fn_abi_of(test) = FnAbi {
conv: Rust,
can_unwind: $SOME_BOOL,
}
--> $DIR/debug.rs:13:1
--> $DIR/debug.rs:15:1
|
LL | fn test(_x: u8) -> bool { true }
| ^^^^^^^^^^^^^^^^^^^^^^^
@ -181,7 +181,7 @@ error: fn_abi_of(TestFnPtr) = FnAbi {
conv: Rust,
can_unwind: $SOME_BOOL,
}
--> $DIR/debug.rs:16:1
--> $DIR/debug.rs:18:1
|
LL | type TestFnPtr = fn(bool) -> u8;
| ^^^^^^^^^^^^^^
@ -257,11 +257,23 @@ error: fn_abi_of(test_generic) = FnAbi {
conv: Rust,
can_unwind: $SOME_BOOL,
}
--> $DIR/debug.rs:19:1
--> $DIR/debug.rs:21:1
|
LL | fn test_generic<T>(_x: *const T) { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `#[rustc_abi]` can only be applied to function items, type aliases, and associated functions
--> $DIR/debug.rs:24:1
|
LL | const C: () = ();
| ^^^^^^^^^^^
error: `#[rustc_abi]` can only be applied to function items, type aliases, and associated functions
--> $DIR/debug.rs:28:5
|
LL | const C: () = ();
| ^^^^^^^^^^^
error: fn_abi_of(assoc_test) = FnAbi {
args: [
ArgAbi {
@ -345,10 +357,10 @@ error: fn_abi_of(assoc_test) = FnAbi {
conv: Rust,
can_unwind: $SOME_BOOL,
}
--> $DIR/debug.rs:24:5
--> $DIR/debug.rs:33:5
|
LL | fn assoc_test(&self) { }
| ^^^^^^^^^^^^^^^^^^^^
error: aborting due to 4 previous errors
error: aborting due to 6 previous errors

View file

@ -17,6 +17,9 @@ union U { f1: (i32, i32), f3: i32 } //~ ERROR: layout_of
#[rustc_layout(debug)]
type T = impl std::fmt::Debug; //~ ERROR: layout_of
fn f() -> T {
0i32
}
#[rustc_layout(debug)]
pub union V { //~ ERROR: layout_of
@ -63,6 +66,10 @@ union P4 { x: E } //~ ERROR: layout_of
#[rustc_layout(debug)]
type X = std::mem::MaybeUninit<u8>; //~ ERROR: layout_of
fn f() -> T {
0i32
#[rustc_layout(debug)]
const C: () = (); //~ ERROR: can only be applied to
impl S {
#[rustc_layout(debug)]
const C: () = (); //~ ERROR: can only be applied to
}

View file

@ -344,7 +344,7 @@ error: layout_of(V) = Layout {
max_repr_align: None,
unadjusted_abi_align: Align(2 bytes),
}
--> $DIR/debug.rs:22:1
--> $DIR/debug.rs:25:1
|
LL | pub union V {
| ^^^^^^^^^^^
@ -368,7 +368,7 @@ error: layout_of(W) = Layout {
max_repr_align: None,
unadjusted_abi_align: Align(2 bytes),
}
--> $DIR/debug.rs:28:1
--> $DIR/debug.rs:31:1
|
LL | pub union W {
| ^^^^^^^^^^^
@ -392,7 +392,7 @@ error: layout_of(Y) = Layout {
max_repr_align: None,
unadjusted_abi_align: Align(2 bytes),
}
--> $DIR/debug.rs:34:1
--> $DIR/debug.rs:37:1
|
LL | pub union Y {
| ^^^^^^^^^^^
@ -416,7 +416,7 @@ error: layout_of(P1) = Layout {
max_repr_align: None,
unadjusted_abi_align: Align(1 bytes),
}
--> $DIR/debug.rs:41:1
--> $DIR/debug.rs:44:1
|
LL | union P1 { x: u32 }
| ^^^^^^^^
@ -440,7 +440,7 @@ error: layout_of(P2) = Layout {
max_repr_align: None,
unadjusted_abi_align: Align(1 bytes),
}
--> $DIR/debug.rs:45:1
--> $DIR/debug.rs:48:1
|
LL | union P2 { x: (u32, u32) }
| ^^^^^^^^
@ -464,7 +464,7 @@ error: layout_of(P3) = Layout {
max_repr_align: None,
unadjusted_abi_align: Align(1 bytes),
}
--> $DIR/debug.rs:53:1
--> $DIR/debug.rs:56:1
|
LL | union P3 { x: F32x4 }
| ^^^^^^^^
@ -488,7 +488,7 @@ error: layout_of(P4) = Layout {
max_repr_align: None,
unadjusted_abi_align: Align(1 bytes),
}
--> $DIR/debug.rs:57:1
--> $DIR/debug.rs:60:1
|
LL | union P4 { x: E }
| ^^^^^^^^
@ -517,7 +517,7 @@ error: layout_of(P5) = Layout {
max_repr_align: None,
unadjusted_abi_align: Align(1 bytes),
}
--> $DIR/debug.rs:61:1
--> $DIR/debug.rs:64:1
|
LL | union P5 { zst: [u16; 0], byte: u8 }
| ^^^^^^^^
@ -546,10 +546,22 @@ error: layout_of(std::mem::MaybeUninit<u8>) = Layout {
max_repr_align: None,
unadjusted_abi_align: Align(1 bytes),
}
--> $DIR/debug.rs:64:1
--> $DIR/debug.rs:67:1
|
LL | type X = std::mem::MaybeUninit<u8>;
| ^^^^^^
error: aborting due to 14 previous errors
error: `#[rustc_layout]` can only be applied to `struct`/`enum`/`union` declarations and type aliases
--> $DIR/debug.rs:70:1
|
LL | const C: () = ();
| ^^^^^^^^^^^
error: `#[rustc_layout]` can only be applied to `struct`/`enum`/`union` declarations and type aliases
--> $DIR/debug.rs:74:5
|
LL | const C: () = ();
| ^^^^^^^^^^^
error: aborting due to 16 previous errors