mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-15 12:39:31 +03:00
Rollup merge of #151831 - clubby789:port-rustc-layout, r=JonathanBrouwer
Port `rustc_layout` to attribute parser Tracking issue: rust-lang/rust#131229 Uses rust-lang/rust#151827 r? jdonszelmann
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
use rustc_ast::{LitIntType, LitKind, MetaItemLit};
|
||||
use rustc_hir::attrs::RustcLayoutType;
|
||||
use rustc_session::errors;
|
||||
|
||||
use super::prelude::*;
|
||||
@@ -329,3 +330,61 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcOffloadKernelParser {
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcOffloadKernel;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcLayoutParser;
|
||||
|
||||
impl<S: Stage> CombineAttributeParser<S> for RustcLayoutParser {
|
||||
const PATH: &[rustc_span::Symbol] = &[sym::rustc_layout];
|
||||
|
||||
type Item = RustcLayoutType;
|
||||
|
||||
const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::RustcLayout(items);
|
||||
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
Allow(Target::Struct),
|
||||
Allow(Target::Enum),
|
||||
Allow(Target::Union),
|
||||
Allow(Target::TyAlias),
|
||||
]);
|
||||
|
||||
const TEMPLATE: AttributeTemplate =
|
||||
template!(List: &["abi", "align", "size", "homogenous_aggregate", "debug"]);
|
||||
|
||||
fn extend(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
args: &ArgParser,
|
||||
) -> impl IntoIterator<Item = Self::Item> {
|
||||
let ArgParser::List(items) = args else {
|
||||
cx.expected_list(cx.attr_span, args);
|
||||
return vec![];
|
||||
};
|
||||
|
||||
let mut result = Vec::new();
|
||||
for item in items.mixed() {
|
||||
let Some(arg) = item.meta_item() else {
|
||||
cx.unexpected_literal(item.span());
|
||||
continue;
|
||||
};
|
||||
let Some(ident) = arg.ident() else {
|
||||
cx.expected_identifier(arg.span());
|
||||
return vec![];
|
||||
};
|
||||
let ty = match ident.name {
|
||||
sym::abi => RustcLayoutType::Abi,
|
||||
sym::align => RustcLayoutType::Align,
|
||||
sym::size => RustcLayoutType::Size,
|
||||
sym::homogeneous_aggregate => RustcLayoutType::HomogenousAggregate,
|
||||
sym::debug => RustcLayoutType::Debug,
|
||||
_ => {
|
||||
cx.expected_specific_argument(
|
||||
ident.span,
|
||||
&[sym::abi, sym::align, sym::size, sym::homogeneous_aggregate, sym::debug],
|
||||
);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
result.push(ty);
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
RustcDumpVtable,
|
||||
};
|
||||
use crate::attributes::rustc_internal::{
|
||||
RustcHasIncoherentInherentImplsParser, RustcLayoutScalarValidRangeEndParser,
|
||||
RustcHasIncoherentInherentImplsParser, RustcLayoutParser, RustcLayoutScalarValidRangeEndParser,
|
||||
RustcLayoutScalarValidRangeStartParser, RustcLegacyConstGenericsParser,
|
||||
RustcLintOptDenyFieldAccessParser, RustcLintOptTyParser, RustcLintQueryInstabilityParser,
|
||||
RustcLintUntrackedQueryInformationParser, RustcMainParser, RustcMustImplementOneOfParser,
|
||||
@@ -198,6 +198,7 @@ mod late {
|
||||
Combine<ForceTargetFeatureParser>,
|
||||
Combine<LinkParser>,
|
||||
Combine<ReprParser>,
|
||||
Combine<RustcLayoutParser>,
|
||||
Combine<TargetFeatureParser>,
|
||||
Combine<UnstableFeatureBoundParser>,
|
||||
// tidy-alphabetical-end
|
||||
|
||||
@@ -690,6 +690,15 @@ fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)]
|
||||
pub enum RustcLayoutType {
|
||||
Abi,
|
||||
Align,
|
||||
Size,
|
||||
HomogenousAggregate,
|
||||
Debug,
|
||||
}
|
||||
|
||||
/// Represents parsed *built-in* inert attributes.
|
||||
///
|
||||
/// ## Overview
|
||||
@@ -1048,6 +1057,9 @@ pub enum AttributeKind {
|
||||
/// Represents `#[rustc_has_incoherent_inherent_impls]`
|
||||
RustcHasIncoherentInherentImpls,
|
||||
|
||||
/// Represents `#[rustc_layout]`
|
||||
RustcLayout(ThinVec<RustcLayoutType>),
|
||||
|
||||
/// Represents `#[rustc_layout_scalar_valid_range_end]`.
|
||||
RustcLayoutScalarValidRangeEnd(Box<u128>, Span),
|
||||
|
||||
|
||||
@@ -111,6 +111,7 @@ pub fn encode_cross_crate(&self) -> EncodeCrossCrate {
|
||||
RustcDumpVtable(..) => No,
|
||||
RustcDynIncompatibleTrait(..) => No,
|
||||
RustcHasIncoherentInherentImpls => Yes,
|
||||
RustcLayout(..) => No,
|
||||
RustcLayoutScalarValidRangeEnd(..) => Yes,
|
||||
RustcLayoutScalarValidRangeStart(..) => Yes,
|
||||
RustcLegacyConstGenerics { .. } => Yes,
|
||||
|
||||
@@ -302,8 +302,6 @@ 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 =
|
||||
|
||||
@@ -299,6 +299,7 @@ fn check_attributes(
|
||||
| AttributeKind::RustcDumpVtable(..)
|
||||
| AttributeKind::RustcDynIncompatibleTrait(..)
|
||||
| AttributeKind::RustcHasIncoherentInherentImpls
|
||||
| AttributeKind::RustcLayout(..)
|
||||
| AttributeKind::RustcLayoutScalarValidRangeEnd(..)
|
||||
| AttributeKind::RustcLayoutScalarValidRangeStart(..)
|
||||
| AttributeKind::RustcLintOptDenyFieldAccess { .. }
|
||||
|
||||
@@ -519,13 +519,6 @@ pub(crate) struct LayoutOf<'tcx> {
|
||||
pub ty_layout: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_layout_invalid_attribute)]
|
||||
pub(crate) struct LayoutInvalidAttribute {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_abi_of)]
|
||||
pub(crate) struct AbiOf {
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
use rustc_abi::{HasDataLayout, TargetDataLayout};
|
||||
use rustc_hir::Attribute;
|
||||
use rustc_hir::attrs::{AttributeKind, RustcLayoutType};
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::find_attr;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::{Span, sym};
|
||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||
use rustc_trait_selection::infer::TyCtxtInferExt;
|
||||
use rustc_trait_selection::traits;
|
||||
|
||||
use crate::errors::{
|
||||
LayoutAbi, LayoutAlign, LayoutHomogeneousAggregate, LayoutInvalidAttribute, LayoutOf,
|
||||
LayoutSize, UnrecognizedArgument,
|
||||
};
|
||||
use crate::errors::{LayoutAbi, LayoutAlign, LayoutHomogeneousAggregate, LayoutOf, LayoutSize};
|
||||
|
||||
pub fn test_layout(tcx: TyCtxt<'_>) {
|
||||
if !tcx.features().rustc_attrs() {
|
||||
@@ -22,14 +20,14 @@ pub fn test_layout(tcx: TyCtxt<'_>) {
|
||||
return;
|
||||
}
|
||||
for id in tcx.hir_crate_items(()).definitions() {
|
||||
for attr in tcx.get_attrs(id, sym::rustc_layout) {
|
||||
match tcx.def_kind(id) {
|
||||
DefKind::TyAlias | DefKind::Enum | DefKind::Struct | DefKind::Union => {
|
||||
dump_layout_of(tcx, id, attr);
|
||||
}
|
||||
_ => {
|
||||
tcx.dcx().emit_err(LayoutInvalidAttribute { span: tcx.def_span(id) });
|
||||
}
|
||||
let attrs = tcx.get_all_attrs(id);
|
||||
if let Some(attrs) = find_attr!(attrs, AttributeKind::RustcLayout(attrs) => attrs) {
|
||||
// Attribute parsing handles error reporting
|
||||
if matches!(
|
||||
tcx.def_kind(id),
|
||||
DefKind::TyAlias | DefKind::Enum | DefKind::Struct | DefKind::Union
|
||||
) {
|
||||
dump_layout_of(tcx, id, attrs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,7 +64,7 @@ pub fn ensure_wf<'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
|
||||
fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attrs: &[RustcLayoutType]) {
|
||||
let typing_env = ty::TypingEnv::post_analysis(tcx, item_def_id);
|
||||
let ty = tcx.type_of(item_def_id).instantiate_identity();
|
||||
let span = tcx.def_span(item_def_id.to_def_id());
|
||||
@@ -75,32 +73,29 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
|
||||
}
|
||||
match tcx.layout_of(typing_env.as_query_input(ty)) {
|
||||
Ok(ty_layout) => {
|
||||
// Check out the `#[rustc_layout(..)]` attribute to tell what to dump.
|
||||
// The `..` are the names of fields to dump.
|
||||
let meta_items = attr.meta_item_list().unwrap_or_default();
|
||||
for meta_item in meta_items {
|
||||
match meta_item.name() {
|
||||
for attr in attrs {
|
||||
match attr {
|
||||
// FIXME: this never was about ABI and now this dump arg is confusing
|
||||
Some(sym::abi) => {
|
||||
RustcLayoutType::Abi => {
|
||||
tcx.dcx().emit_err(LayoutAbi {
|
||||
span,
|
||||
abi: format!("{:?}", ty_layout.backend_repr),
|
||||
});
|
||||
}
|
||||
|
||||
Some(sym::align) => {
|
||||
RustcLayoutType::Align => {
|
||||
tcx.dcx().emit_err(LayoutAlign {
|
||||
span,
|
||||
align: format!("{:?}", ty_layout.align),
|
||||
});
|
||||
}
|
||||
|
||||
Some(sym::size) => {
|
||||
RustcLayoutType::Size => {
|
||||
tcx.dcx()
|
||||
.emit_err(LayoutSize { span, size: format!("{:?}", ty_layout.size) });
|
||||
}
|
||||
|
||||
Some(sym::homogeneous_aggregate) => {
|
||||
RustcLayoutType::HomogenousAggregate => {
|
||||
tcx.dcx().emit_err(LayoutHomogeneousAggregate {
|
||||
span,
|
||||
homogeneous_aggregate: format!(
|
||||
@@ -111,16 +106,12 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
|
||||
});
|
||||
}
|
||||
|
||||
Some(sym::debug) => {
|
||||
RustcLayoutType::Debug => {
|
||||
let normalized_ty = tcx.normalize_erasing_regions(typing_env, ty);
|
||||
// FIXME: using the `Debug` impl here isn't ideal.
|
||||
let ty_layout = format!("{:#?}", *ty_layout);
|
||||
tcx.dcx().emit_err(LayoutOf { span, normalized_ty, ty_layout });
|
||||
}
|
||||
|
||||
_ => {
|
||||
tcx.dcx().emit_err(UnrecognizedArgument { span: meta_item.span() });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,12 +68,12 @@ union P4 { x: E } //~ ERROR: layout_of
|
||||
#[rustc_layout(debug)]
|
||||
type X = std::mem::MaybeUninit<u8>; //~ ERROR: layout_of
|
||||
|
||||
#[rustc_layout(debug)]
|
||||
const C: () = (); //~ ERROR: can only be applied to
|
||||
#[rustc_layout(debug)] //~ ERROR: cannot be used on constants
|
||||
const C: () = ();
|
||||
|
||||
impl S {
|
||||
#[rustc_layout(debug)]
|
||||
const C: () = (); //~ ERROR: can only be applied to
|
||||
#[rustc_layout(debug)] //~ ERROR: cannot be used on associated consts
|
||||
const C: () = ();
|
||||
}
|
||||
|
||||
#[rustc_layout(debug)]
|
||||
|
||||
@@ -4,6 +4,22 @@ error: unions cannot have zero fields
|
||||
LL | union EmptyUnion {}
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: `#[rustc_layout]` attribute cannot be used on constants
|
||||
--> $DIR/debug.rs:71:1
|
||||
|
|
||||
LL | #[rustc_layout(debug)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: `#[rustc_layout]` can be applied to data types and type aliases
|
||||
|
||||
error: `#[rustc_layout]` attribute cannot be used on associated consts
|
||||
--> $DIR/debug.rs:75:5
|
||||
|
|
||||
LL | #[rustc_layout(debug)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: `#[rustc_layout]` can be applied to data types and type aliases
|
||||
|
||||
error: layout_of(E) = Layout {
|
||||
size: Size(12 bytes),
|
||||
align: AbiAlign {
|
||||
@@ -577,12 +593,6 @@ error: layout_of(MaybeUninit<u8>) = Layout {
|
||||
LL | type X = std::mem::MaybeUninit<u8>;
|
||||
| ^^^^^^
|
||||
|
||||
error: `#[rustc_layout]` can only be applied to `struct`/`enum`/`union` declarations and type aliases
|
||||
--> $DIR/debug.rs:72:1
|
||||
|
|
||||
LL | const C: () = ();
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error[E0277]: the size for values of type `str` cannot be known at compilation time
|
||||
--> $DIR/debug.rs:80:19
|
||||
|
|
||||
@@ -604,12 +614,6 @@ error: the type `T` does not have a fixed layout
|
||||
LL | type TooGeneric<T> = T;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: `#[rustc_layout]` can only be applied to `struct`/`enum`/`union` declarations and type aliases
|
||||
--> $DIR/debug.rs:76:5
|
||||
|
|
||||
LL | const C: () = ();
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 20 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
||||
Reference in New Issue
Block a user