Skip to content

Commit 3580de8

Browse files
committed
Turn warning into lint
1 parent 2c7099b commit 3580de8

File tree

7 files changed

+305
-268
lines changed

7 files changed

+305
-268
lines changed

src/librustc/hir/check_attr.rs

+2-54
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
//! conflicts between multiple such attributes attached to the same
1515
//! item.
1616
17-
use syntax_pos::{BytePos, Span};
17+
use syntax_pos::Span;
1818
use ty::TyCtxt;
1919

2020
use hir;
@@ -154,59 +154,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
154154
let hints: Vec<_> = item.attrs
155155
.iter()
156156
.filter(|attr| attr.name() == "repr")
157-
.filter_map(|attr| {
158-
let list = attr.meta_item_list();
159-
160-
// Emit warnings with `repr` either has a literal assignment (`#[repr = "C"]`) or
161-
// no hints (``#[repr]`)
162-
let has_hints = list.as_ref().map(|ref list| !list.is_empty()).unwrap_or(false);
163-
if !has_hints {
164-
let mut suggested = false;
165-
let mut warn = if let Some(ref lit) = attr.value_str() {
166-
// avoid warning about empty `repr` on `#[repr = "foo"]`
167-
let sp = match format!("{}", lit).as_ref() {
168-
"C" | "packed" | "rust" | "u*" | "i*" => {
169-
let lo = attr.span.lo() + BytePos(2);
170-
let hi = attr.span.hi() - BytePos(1);
171-
suggested = true;
172-
attr.span.with_lo(lo).with_hi(hi)
173-
}
174-
_ => attr.span, // the literal wasn't a valid `repr` arg
175-
};
176-
let mut warn = self.tcx.sess.struct_span_warn(
177-
sp,
178-
"`repr` attribute isn't configurable with a literal",
179-
);
180-
if suggested {
181-
// if the literal could have been a valid `repr` arg,
182-
// suggest the correct syntax
183-
warn.span_suggestion(
184-
sp,
185-
"give `repr` a hint",
186-
format!("repr({})", lit),
187-
);
188-
} else {
189-
warn.span_label(attr.span, "needs a hint");
190-
}
191-
warn
192-
} else {
193-
let mut warn = self.tcx.sess.struct_span_warn(
194-
attr.span,
195-
"`repr` attribute must have a hint",
196-
);
197-
warn.span_label(attr.span, "needs a hint");
198-
warn
199-
};
200-
if !suggested {
201-
warn.help("valid hints include `#[repr(C)]`, `#[repr(packed)]` and \
202-
`#[repr(rust)]`");
203-
warn.note("for more information, visit \
204-
<https://doc.rust-lang.org/nomicon/other-reprs.html>");
205-
}
206-
warn.emit();
207-
}
208-
list
209-
})
157+
.filter_map(|attr| attr.meta_item_list())
210158
.flat_map(|hints| hints)
211159
.collect();
212160

src/librustc/lint/builtin.rs

+6
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,12 @@ declare_lint! {
206206
"potentially-conflicting impls were erroneously allowed"
207207
}
208208

209+
declare_lint! {
210+
pub BAD_REPR,
211+
Warn,
212+
"detects incorrect use of `repr` attribute"
213+
}
214+
209215
declare_lint! {
210216
pub DEPRECATED,
211217
Warn,

src/librustc_lint/builtin.rs

+69
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,75 @@ impl EarlyLintPass for AnonymousParameters {
673673
}
674674
}
675675

676+
/// Checks for incorrect use use of `repr` attributes.
677+
#[derive(Clone)]
678+
pub struct BadRepr;
679+
680+
impl LintPass for BadRepr {
681+
fn get_lints(&self) -> LintArray {
682+
lint_array!()
683+
}
684+
}
685+
686+
impl EarlyLintPass for BadRepr {
687+
fn check_attribute(&mut self, cx: &EarlyContext, attr: &ast::Attribute) {
688+
if attr.name() == "repr" {
689+
let list = attr.meta_item_list();
690+
691+
// Emit warnings with `repr` either has a literal assignment (`#[repr = "C"]`) or
692+
// no hints (``#[repr]`)
693+
let has_hints = list.as_ref().map(|ref list| !list.is_empty()).unwrap_or(false);
694+
if !has_hints {
695+
let mut suggested = false;
696+
let mut warn = if let Some(ref lit) = attr.value_str() {
697+
// avoid warning about empty `repr` on `#[repr = "foo"]`
698+
let sp = match format!("{}", lit).as_ref() {
699+
"C" | "packed" | "rust" | "u*" | "i*" => {
700+
let lo = attr.span.lo() + BytePos(2);
701+
let hi = attr.span.hi() - BytePos(1);
702+
suggested = true;
703+
attr.span.with_lo(lo).with_hi(hi)
704+
}
705+
_ => attr.span, // the literal wasn't a valid `repr` arg
706+
};
707+
let mut warn = cx.struct_span_lint(
708+
BAD_REPR,
709+
sp,
710+
"`repr` attribute isn't configurable with a literal",
711+
);
712+
if suggested {
713+
// if the literal could have been a valid `repr` arg,
714+
// suggest the correct syntax
715+
warn.span_suggestion(
716+
sp,
717+
"give `repr` a hint",
718+
format!("repr({})", lit),
719+
);
720+
} else {
721+
warn.span_label(attr.span, "needs a hint");
722+
}
723+
warn
724+
} else {
725+
let mut warn = cx.struct_span_lint(
726+
BAD_REPR,
727+
attr.span,
728+
"`repr` attribute must have a hint",
729+
);
730+
warn.span_label(attr.span, "needs a hint");
731+
warn
732+
};
733+
if !suggested {
734+
warn.help("valid hints include `#[repr(C)]`, `#[repr(packed)]` and \
735+
`#[repr(rust)]`");
736+
warn.note("for more information, visit \
737+
<https://doc.rust-lang.org/nomicon/other-reprs.html>");
738+
}
739+
warn.emit();
740+
}
741+
}
742+
}
743+
}
744+
676745
/// Checks for use of attributes which have been deprecated.
677746
#[derive(Clone)]
678747
pub struct DeprecatedAttr {

src/librustc_lint/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
107107
UnusedImportBraces,
108108
AnonymousParameters,
109109
UnusedDocComment,
110+
BadRepr,
110111
);
111112

112113
add_early_builtin_with_new!(sess,

src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@
5959
#![start = "x4300"] //~ WARN unused attribute
6060
// see issue-43106-gating-of-test.rs for crate-level; but non crate-level is below at "4200"
6161
// see issue-43106-gating-of-bench.rs for crate-level; but non crate-level is below at "4100"
62-
#![repr = "3900"] //~ WARN unused attribute
62+
#![repr = "3900"]
63+
//~^ WARN unused attribute
64+
//~| WARN `repr` attribute isn't configurable with a literal
6365
#![path = "3800"] //~ WARN unused attribute
6466
#![abi = "3700"] //~ WARN unused attribute
6567
#![automatically_derived = "3600"] //~ WARN unused attribute

0 commit comments

Comments
 (0)