Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use rustc_ast::{LitIntType, LitKind, MetaItemLit};
use rustc_hir::attrs::RustcLayoutType;
use rustc_session::errors;

use super::prelude::*;
Expand Down Expand Up @@ -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
}
}
3 changes: 2 additions & 1 deletion compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ use crate::attributes::rustc_dump::{
RustcDumpVtable,
};
use crate::attributes::rustc_internal::{
RustcHasIncoherentInherentImplsParser, RustcLayoutScalarValidRangeEndParser,
RustcHasIncoherentInherentImplsParser, RustcLayoutParser, RustcLayoutScalarValidRangeEndParser,
RustcLayoutScalarValidRangeStartParser, RustcLegacyConstGenericsParser,
RustcLintOptDenyFieldAccessParser, RustcLintOptTyParser, RustcLintQueryInstabilityParser,
RustcLintUntrackedQueryInformationParser, RustcMainParser, RustcMustImplementOneOfParser,
Expand Down Expand Up @@ -198,6 +198,7 @@ attribute_parsers!(
Combine<ForceTargetFeatureParser>,
Combine<LinkParser>,
Combine<ReprParser>,
Combine<RustcLayoutParser>,
Combine<TargetFeatureParser>,
Combine<UnstableFeatureBoundParser>,
// tidy-alphabetical-end
Expand Down
12 changes: 12 additions & 0 deletions compiler/rustc_hir/src/attrs/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,15 @@ impl IntoDiagArg for CrateType {
}
}

#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)]
pub enum RustcLayoutType {
Abi,
Align,
Size,
HomogenousAggregate,
Debug,
}

/// Represents parsed *built-in* inert attributes.
///
/// ## Overview
Expand Down Expand Up @@ -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),

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir/src/attrs/encode_cross_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ impl AttributeKind {
RustcDumpVtable(..) => No,
RustcDynIncompatibleTrait(..) => No,
RustcHasIncoherentInherentImpls => Yes,
RustcLayout(..) => No,
RustcLayoutScalarValidRangeEnd(..) => Yes,
RustcLayoutScalarValidRangeStart(..) => Yes,
RustcLegacyConstGenerics { .. } => Yes,
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| AttributeKind::RustcDumpVtable(..)
| AttributeKind::RustcDynIncompatibleTrait(..)
| AttributeKind::RustcHasIncoherentInherentImpls
| AttributeKind::RustcLayout(..)
| AttributeKind::RustcLayoutScalarValidRangeEnd(..)
| AttributeKind::RustcLayoutScalarValidRangeStart(..)
| AttributeKind::RustcLintOptDenyFieldAccess { .. }
Expand Down
7 changes: 0 additions & 7 deletions compiler/rustc_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
49 changes: 20 additions & 29 deletions compiler/rustc_passes/src/layout_test.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,33 @@
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() {
// if the `rustc_attrs` feature is not enabled, don't bother testing layout
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);
}
}
}
Expand Down Expand Up @@ -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());
Expand All @@ -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!(
Expand All @@ -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() });
}
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions tests/rustdoc-gui/globals.goml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
include: "utils.goml"

// URL query
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=sa'%3Bda'%3Bds"
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=sa"
wait-for: "#search-tabs"
assert-window-property-false: {"searchIndex": null}

// Form input
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
call-function: ("perform-search", {"query": "Foo"})
assert-window-property-false: {"searchIndex": null}
wait-for-window-property-false: {"searchIndex": null}

// source sidebar
go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
Expand Down
8 changes: 4 additions & 4 deletions tests/ui/layout/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,12 @@ union P5 { zst: [u16; 0], byte: u8 } //~ 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)]
Expand Down
28 changes: 16 additions & 12 deletions tests/ui/layout/debug.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
|
Expand All @@ -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`.
Loading