Skip to content
Merged
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
16 changes: 14 additions & 2 deletions compiler/rustc_attr_ir/src/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,19 @@ impl OptimizeAttr {
}
}

#[derive(PartialEq, Debug, Encodable, Decodable, Copy, Clone, StableHash, PrintAttribute)]
#[derive(
PartialEq,
Eq,
Debug,
PartialOrd,
Ord,
Encodable,
Decodable,
Copy,
Clone,
StableHash,
PrintAttribute
)]
pub enum ReprAttr {
ReprInt(IntType),
ReprRust,
Expand All @@ -188,7 +200,7 @@ pub enum TransparencyError {
MultipleTransparencyAttrs(Span, Span),
}

#[derive(Eq, PartialEq, Debug, Copy, Clone)]
#[derive(Eq, PartialEq, Debug, Copy, Clone, PartialOrd, Ord)]
#[derive(Encodable, Decodable, StableHash, PrintAttribute)]
pub enum IntType {
SignedInt(ast::IntTy),
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_lint/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,8 @@ fn register_builtins(store: &mut LintStore) {
UNUSED_PARENS,
UNUSED_BRACES,
REDUNDANT_SEMICOLONS,
MAP_UNIT_FN
MAP_UNIT_FN,
REPEATED_REPRS
);

add_lint_group!("let_underscore", LET_UNDERSCORE_DROP, LET_UNDERSCORE_LOCK);
Expand Down
25 changes: 25 additions & 0 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ pub mod hardwired {
REFINING_IMPL_TRAIT_INTERNAL,
REFINING_IMPL_TRAIT_REACHABLE,
RENAMED_AND_REMOVED_LINTS,
REPEATED_REPRS,
REPR_C_ENUMS_LARGER_THAN_INT,
RESOLVING_TO_ITEMS_SHADOWING_SUPERTRAIT_ITEMS,
RTSAN_NONBLOCKING_ASYNC,
Expand Down Expand Up @@ -277,6 +278,30 @@ declare_lint! {
};
}

declare_lint! {
/// The `repeated_reprs` lint detects when the same representation is
/// specified more than once in a `#[repr(..)]` attribute.
///
/// ### Example
///
/// ```rust
/// #[repr(C)]
/// #[repr(C)]
/// enum Foo { A }
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// While some representations may be specified more than once, the compiler
/// will reject repeated uses of some others. For consistency, prefer to
/// only specify the representation once.
pub REPEATED_REPRS,
Warn,
"detects repeated representations in `#[repr(..)]` attributes",
}

declare_lint! {
/// The `meta_variable_misuse` lint detects possible meta-variable misuse
/// in macro definitions.
Expand Down
38 changes: 34 additions & 4 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ use rustc_hir::{
};
use rustc_lint_defs::builtin::{
CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, MALFORMED_DIAGNOSTIC_ATTRIBUTES,
MALFORMED_DIAGNOSTIC_FORMAT_LITERALS, MISPLACED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES,
MALFORMED_DIAGNOSTIC_FORMAT_LITERALS, MISPLACED_DIAGNOSTIC_ATTRIBUTES, REPEATED_REPRS,
UNUSED_ATTRIBUTES,
};
use rustc_macros::Diagnostic;
use rustc_middle::hir::nested_filter;
Expand Down Expand Up @@ -1221,20 +1222,49 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
ReprAttr::ReprC => {
is_c = true;
}
ReprAttr::ReprAlign(..) => {}
ReprAttr::ReprPacked(_) => {}
ReprAttr::ReprAlign(..) => (),
ReprAttr::ReprPacked(..) => (),
ReprAttr::ReprSimd => {
is_simd = true;
}
ReprAttr::ReprTransparent => {
is_transparent = true;
}
ReprAttr::ReprInt(_) => {
ReprAttr::ReprInt(..) => {
int_reprs += 1;
}
};
}

if !reprs.is_empty() {
let sorted_reprs = {
let mut to_sort = reprs.to_owned();
to_sort.sort_unstable();
to_sort
};

// To collect all duplicates, get subslices where all of the elements of the subslice
// are equal, then filter out all those whose length is not 1. We could return warnings
// for each of them, but that's annoyingly excessive. So we instead collect all spans in
// one big Vec.
let spans: Vec<Span> = sorted_reprs
.chunk_by(|(a, _), (b, _)| a == b)
.map(ToOwned::to_owned)
.filter(|slice| slice.len() != 1)
.flatten()
.map(|(_, span)| span)
.collect();

if !spans.is_empty() {
self.tcx.emit_node_span_lint(
REPEATED_REPRS,
hir_id,
spans,
diagnostics::RepeatedRepr,
);
}
}

// Just point at all repr hints if there are any incompatibilities.
// This is not ideal, but tracking precisely which ones are at fault is a huge hassle.
let hint_spans = reprs.iter().map(|(_, span)| *span);
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_passes/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,11 @@ pub(crate) struct TransparentIncompatible {
pub target: String,
}

#[derive(Diagnostic)]
#[diag("`#[repr(..)]` attribute is specified more than once")]
#[note("for consistency, only specify the representation once")]
pub(crate) struct RepeatedRepr;

#[derive(Diagnostic)]
#[diag("deprecated attribute must be paired with either stable or unstable attribute", code = E0549)]
pub(crate) struct DeprecatedAttribute {
Expand Down
2 changes: 2 additions & 0 deletions tests/ui/attributes/issue-100631.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
//@ compile-flags: -W repeated-reprs
// issue #100631, make sure `TyCtxt::get_attr` only called by case that compiler
// can reasonably deal with multiple attributes.
// `repr` will use `TyCtxt::get_attrs` since it's `DuplicatesOk`.
#[repr(C)] //~ ERROR: unsupported representation for zero-variant enum [E0084]
//~^ WARN `#[repr(..)]` attribute is specified more than once [repeated_reprs]
#[repr(C)]
enum Foo {}

Expand Down
18 changes: 15 additions & 3 deletions tests/ui/attributes/issue-100631.stderr
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
error[E0084]: unsupported representation for zero-variant enum
--> $DIR/issue-100631.rs:4:8
warning: `#[repr(..)]` attribute is specified more than once
--> $DIR/issue-100631.rs:5:8
|
LL | #[repr(C)]
| ^
LL |
LL | #[repr(C)]
| ^
|
= note: for consistency, only specify the representation once
= note: requested on the command line with `-W repeated-reprs`

error[E0084]: unsupported representation for zero-variant enum
--> $DIR/issue-100631.rs:5:8
|
LL | #[repr(C)]
| ^
...
LL | enum Foo {}
| -------- zero-variant enum

error: aborting due to 1 previous error
error: aborting due to 1 previous error; 1 warning emitted

For more information about this error, try `rustc --explain E0084`.
Original file line number Diff line number Diff line change
Expand Up @@ -449,3 +449,21 @@ note: the lint level is defined here
LL | #![forbid(forbidden_lint_groups)]
| ^^^^^^^^^^^^^^^^^^^^^

Future breakage diagnostic:
error: warn(unused) incompatible with previous forbid
--> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:22:13
|
LL | #![forbid(unused)]
| ------ `forbid` level set here
LL | #![deny(unused)]
LL | #![warn(unused)]
| ^^^^^^ overruled by previous forbid
|
= 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
note: the lint level is defined here
--> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11
|
LL | #![forbid(forbidden_lint_groups)]
| ^^^^^^^^^^^^^^^^^^^^^

18 changes: 18 additions & 0 deletions tests/ui/lint/outer-forbid.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -489,3 +489,21 @@ note: the lint level is defined here
LL | #![forbid(forbidden_lint_groups)]
| ^^^^^^^^^^^^^^^^^^^^^

Future breakage diagnostic:
error: allow(unused) incompatible with previous forbid
--> $DIR/outer-forbid.rs:25:9
|
LL | #![forbid(unused, non_snake_case)]
| ------ `forbid` level set here
...
LL | #[allow(unused)]
| ^^^^^^ overruled by previous forbid
|
= 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 #81670 <https://github.com/rust-lang/rust/issues/81670>
note: the lint level is defined here
--> $DIR/outer-forbid.rs:18:11
|
LL | #![forbid(forbidden_lint_groups)]
| ^^^^^^^^^^^^^^^^^^^^^

5 changes: 2 additions & 3 deletions tests/ui/lint/unused/unused-attr-duplicate.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Tests for repeating attribute warnings.
//@ aux-build:lint_unused_extern_crate.rs
//@ compile-flags:--test
//@ compile-flags:--test -W repeated-reprs
// Not tested due to extra requirements:
// - panic_handler: needs extra setup
// - target_feature: platform-specific
Expand Down Expand Up @@ -64,8 +64,7 @@ fn t1() {}
#[must_use = "some message"]
//~^ ERROR unused attribute
//~| WARN this was previously accepted
// No warnings for #[repr], would require more logic.
#[repr(C)]
#[repr(C)] //~ WARN `#[repr(..)]` attribute is specified more than once [repeated_reprs]
#[repr(C)]
#[non_exhaustive]
#[non_exhaustive] //~ ERROR unused attribute
Expand Down
Loading
Loading