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
26 changes: 18 additions & 8 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1213,7 +1213,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
let mut is_explicit_rust = false;
let mut is_c = false;
let mut is_simd = false;
let mut is_transparent = false;
let mut transparents = 0;
let mut last_int_repr = None;
let mut int_reprs_different = false;

for (repr, repr_span) in reprs {
match repr {
Expand Down Expand Up @@ -1284,7 +1286,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}
ReprAttr::ReprTransparent => {
is_transparent = true;
transparents += 1;
match target {
Target::Struct | Target::Union | Target::Enum => continue,
_ => {
Expand All @@ -1295,8 +1297,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}
}
ReprAttr::ReprInt(_) => {
ReprAttr::ReprInt(int_type) => {
int_reprs += 1;
if let Some(previous_int) = last_int_repr
&& previous_int != int_type
{
int_reprs_different = true;
}
last_int_repr = Some(int_type);
if target != Target::Enum {
self.dcx().emit_err(errors::AttrApplication::Enum {
hint_span: *repr_span,
Expand Down Expand Up @@ -1336,8 +1344,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
// This is not ideal, but tracking precisely which ones are at fault is a huge hassle.
let hint_spans = reprs.iter().map(|(_, span)| *span);

// Error on repr(transparent, <anything else>).
if is_transparent && reprs.len() > 1 {
// Error if repr(transparent) is combined with any other repr apart from additional
// repr(transparent)s.
if transparents > 0 && reprs.len() != transparents {
let hint_spans = hint_spans.clone().collect();
self.dcx().emit_err(errors::TransparentIncompatible {
hint_spans,
Expand All @@ -1346,7 +1355,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
// Error on `#[repr(transparent)]` in combination with
// `#[rustc_pass_indirectly_in_non_rustic_abis]`
if is_transparent
if transparents > 0
&& let Some(&pass_indirectly_span) =
find_attr!(attrs, RustcPassIndirectlyInNonRusticAbis(span) => span)
{
Expand All @@ -1358,11 +1367,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
if is_explicit_rust && (int_reprs > 0 || is_c || is_simd) {
let hint_spans = hint_spans.clone().collect();
self.dcx().emit_err(errors::ReprConflicting { hint_spans });
return;
}
// Warn on repr(u8, u16), repr(C, simd), and c-like-enum-repr(C, u8)
if (int_reprs > 1)
if (int_reprs > 1 && int_reprs_different)
|| (is_simd && is_c)
|| (int_reprs == 1
|| (int_reprs >= 1
&& is_c
&& item.is_some_and(|item| {
if let ItemLike::Item(item) = item { is_c_like_enum(item) } else { false }
Expand Down
59 changes: 59 additions & 0 deletions tests/ui/repr/repr-repeated-attrs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Tests that repeated attributes are allowed.

#[repr(transparent, transparent)]
#[repr(transparent)]
struct SeveralTransparentReprs(*mut u8);

#[repr(transparent)]
#[repr(transparent)]
struct MultilineOnly(*mut u8);

#[repr(Rust, Rust)]
struct SeveralRustReprs(u8);

#[repr(C, C)]
#[repr(C, C, C)]
struct SeveralC(u8);

#[repr(u8, u8)]
enum SeveralPrimitiveRerprs {
Variant,
}

#[repr(C, C, u8)]
#[repr(C, u8, u8)]
enum SeveralCAndPrims {
Variant(u8),
}

#[repr(Rust, u8, u8)]
//~^ ERROR conflicting representation hints [E0566]
enum RustAndPrimDisallowed {
Variant(u8),
}

#[repr(u8, u8)]
//~^ ERROR conflicting representation hints [E0566]
//~| WARN: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
#[repr(u16)]
enum ConflictingPrimReprs {
Variant,
}

#[repr(C, u8)]
//~^ ERROR conflicting representation hints [E0566]
//~| WARN: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
enum CWithIntsCausesFCW1 {
A,
B,
}

#[repr(C, C, u8, u8, u8)]
//~^ ERROR conflicting representation hints [E0566]
//~| WARN: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
enum CWithIntsCausesFCW2 {
A,
B,
}

fn main() {}
76 changes: 76 additions & 0 deletions tests/ui/repr/repr-repeated-attrs.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
error[E0566]: conflicting representation hints
--> $DIR/repr-repeated-attrs.rs:29:8
|
LL | #[repr(Rust, u8, u8)]
| ^^^^ ^^ ^^

error[E0566]: conflicting representation hints
--> $DIR/repr-repeated-attrs.rs:35:8
|
LL | #[repr(u8, u8)]
| ^^ ^^
...
LL | #[repr(u16)]
| ^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #68585 <https://github.com/rust-lang/rust/issues/68585>
= note: `#[deny(conflicting_repr_hints)]` (part of `#[deny(future_incompatible)]`) on by default

error[E0566]: conflicting representation hints
--> $DIR/repr-repeated-attrs.rs:43:8
|
LL | #[repr(C, u8)]
| ^ ^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #68585 <https://github.com/rust-lang/rust/issues/68585>

error[E0566]: conflicting representation hints
--> $DIR/repr-repeated-attrs.rs:51:8
|
LL | #[repr(C, C, u8, u8, u8)]
| ^ ^ ^^ ^^ ^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #68585 <https://github.com/rust-lang/rust/issues/68585>

error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0566`.
Future incompatibility report: Future breakage diagnostic:
error[E0566]: conflicting representation hints
--> $DIR/repr-repeated-attrs.rs:35:8
|
LL | #[repr(u8, u8)]
| ^^ ^^
...
LL | #[repr(u16)]
| ^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #68585 <https://github.com/rust-lang/rust/issues/68585>
= note: `#[deny(conflicting_repr_hints)]` (part of `#[deny(future_incompatible)]`) on by default

Future breakage diagnostic:
error[E0566]: conflicting representation hints
--> $DIR/repr-repeated-attrs.rs:43:8
|
LL | #[repr(C, u8)]
| ^ ^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #68585 <https://github.com/rust-lang/rust/issues/68585>
= note: `#[deny(conflicting_repr_hints)]` (part of `#[deny(future_incompatible)]`) on by default

Future breakage diagnostic:
error[E0566]: conflicting representation hints
--> $DIR/repr-repeated-attrs.rs:51:8
|
LL | #[repr(C, C, u8, u8, u8)]
| ^ ^ ^^ ^^ ^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #68585 <https://github.com/rust-lang/rust/issues/68585>
= note: `#[deny(conflicting_repr_hints)]` (part of `#[deny(future_incompatible)]`) on by default

Loading