Skip to content

Commit ceb2512

Browse files
committed
Auto merge of #57321 - petrochenkov:atokens, r=nikomatsakis
Implement basic input validation for built-in attributes Correct top-level shape (`#[attr]` vs `#[attr(...)]` vs `#[attr = ...]`) is enforced for built-in attributes, built-in attributes must also fit into the "meta-item" syntax (aka the "classic attribute syntax"). For some subset of attributes (found by crater run), errors are lowered to deprecation warnings. NOTE: This PR previously included #57367 as well.
2 parents cccaf9a + d3411d3 commit ceb2512

File tree

106 files changed

+1398
-1625
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

106 files changed

+1398
-1625
lines changed

Diff for: src/librustc/diagnostics.rs

+2-35
Original file line numberDiff line numberDiff line change
@@ -1180,27 +1180,6 @@ fn main() {
11801180
```
11811181
"##,
11821182

1183-
E0296: r##"
1184-
This error indicates that the given recursion limit could not be parsed. Ensure
1185-
that the value provided is a positive integer between quotes.
1186-
1187-
Erroneous code example:
1188-
1189-
```compile_fail,E0296
1190-
#![recursion_limit]
1191-
1192-
fn main() {}
1193-
```
1194-
1195-
And a working example:
1196-
1197-
```
1198-
#![recursion_limit="1000"]
1199-
1200-
fn main() {}
1201-
```
1202-
"##,
1203-
12041183
E0308: r##"
12051184
This error occurs when the compiler was unable to infer the concrete type of a
12061185
variable. It can occur for several cases, the most common of which is a
@@ -2093,20 +2072,6 @@ trait Foo { }
20932072
```
20942073
"##,
20952074

2096-
E0702: r##"
2097-
This error indicates that a `#[non_exhaustive]` attribute had a value. The
2098-
`#[non_exhaustive]` should be empty.
2099-
2100-
Examples of erroneous code:
2101-
2102-
```compile_fail,E0702
2103-
# #![feature(non_exhaustive)]
2104-
2105-
#[non_exhaustive(anything)]
2106-
struct Foo;
2107-
```
2108-
"##,
2109-
21102075
E0718: r##"
21112076
This error indicates that a `#[lang = ".."]` attribute was placed
21122077
on the wrong type of item.
@@ -2138,6 +2103,7 @@ register_diagnostics! {
21382103
E0280, // requirement is not satisfied
21392104
E0284, // cannot resolve type
21402105
// E0285, // overflow evaluation builtin bounds
2106+
// E0296, // replaced with a generic attribute input check
21412107
// E0300, // unexpanded macro
21422108
// E0304, // expected signed integer constant
21432109
// E0305, // expected constant
@@ -2180,4 +2146,5 @@ register_diagnostics! {
21802146
E0709, // multiple different lifetimes used in arguments of `async fn`
21812147
E0710, // an unknown tool name found in scoped lint
21822148
E0711, // a feature has been declared with conflicting stability attributes
2149+
// E0702, // replaced with a generic attribute input check
21832150
}

Diff for: src/librustc/hir/check_attr.rs

-15
Original file line numberDiff line numberDiff line change
@@ -142,15 +142,6 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
142142
return;
143143
}
144144
}
145-
146-
if attr.meta_item_list().is_some() || attr.value_str().is_some() {
147-
struct_span_err!(self.tcx.sess,
148-
attr.span,
149-
E0702,
150-
"attribute should be empty")
151-
.span_label(item.span, "not empty")
152-
.emit();
153-
}
154145
}
155146

156147
/// Check if the `#[marker]` attribute on an `item` is valid.
@@ -165,12 +156,6 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
165156
return;
166157
}
167158
}
168-
169-
if !attr.is_word() {
170-
self.tcx.sess
171-
.struct_span_err(attr.span, "attribute should be empty")
172-
.emit();
173-
}
174159
}
175160

176161
/// Check if the `#[repr]` attributes on `item` are valid.

Diff for: src/librustc/lint/builtin.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -204,12 +204,6 @@ declare_lint! {
204204
"trait-object types were treated as different depending on marker-trait order"
205205
}
206206

207-
declare_lint! {
208-
pub BAD_REPR,
209-
Warn,
210-
"detects incorrect use of `repr` attribute"
211-
}
212-
213207
declare_lint! {
214208
pub DEPRECATED,
215209
Warn,
@@ -359,6 +353,12 @@ pub mod parser {
359353
Allow,
360354
"detects the use of `?` as a macro separator"
361355
}
356+
357+
declare_lint! {
358+
pub ILL_FORMED_ATTRIBUTE_INPUT,
359+
Warn,
360+
"ill-formed attribute inputs that were previously accepted and used in practice"
361+
}
362362
}
363363

364364
declare_lint! {
@@ -431,6 +431,7 @@ impl LintPass for HardwiredLints {
431431
MACRO_USE_EXTERN_CRATE,
432432
MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
433433
parser::QUESTION_MARK_MACRO_SEP,
434+
parser::ILL_FORMED_ATTRIBUTE_INPUT,
434435
DEPRECATED_IN_FUTURE,
435436
)
436437
}

Diff for: src/librustc/lint/levels.rs

-2
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,6 @@ impl<'a> LintLevelsBuilder<'a> {
204204
let mut metas = if let Some(metas) = meta.meta_item_list() {
205205
metas
206206
} else {
207-
let mut err = bad_attr(meta.span);
208-
err.emit();
209207
continue;
210208
};
211209

Diff for: src/librustc/lint/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use hir::def_id::{CrateNum, LOCAL_CRATE};
2828
use hir::intravisit;
2929
use hir;
3030
use lint::builtin::BuiltinLintDiagnostics;
31-
use lint::builtin::parser::QUESTION_MARK_MACRO_SEP;
31+
use lint::builtin::parser::{QUESTION_MARK_MACRO_SEP, ILL_FORMED_ATTRIBUTE_INPUT};
3232
use session::{Session, DiagnosticMessageId};
3333
use std::{hash, ptr};
3434
use syntax::ast;
@@ -82,6 +82,7 @@ impl Lint {
8282
pub fn from_parser_lint_id(lint_id: BufferedEarlyLintId) -> &'static Self {
8383
match lint_id {
8484
BufferedEarlyLintId::QuestionMarkMacroSep => QUESTION_MARK_MACRO_SEP,
85+
BufferedEarlyLintId::IllFormedAttributeInput => ILL_FORMED_ATTRIBUTE_INPUT,
8586
}
8687
}
8788

Diff for: src/librustc/middle/recursion_limit.rs

+3-10
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,11 @@ use syntax::ast;
1111
use rustc_data_structures::sync::Once;
1212

1313
pub fn update_limits(sess: &Session, krate: &ast::Crate) {
14-
update_limit(sess, krate, &sess.recursion_limit, "recursion_limit",
15-
"recursion limit", 64);
16-
update_limit(sess, krate, &sess.type_length_limit, "type_length_limit",
17-
"type length limit", 1048576);
14+
update_limit(krate, &sess.recursion_limit, "recursion_limit", 64);
15+
update_limit(krate, &sess.type_length_limit, "type_length_limit", 1048576);
1816
}
1917

20-
fn update_limit(sess: &Session, krate: &ast::Crate, limit: &Once<usize>,
21-
name: &str, description: &str, default: usize) {
18+
fn update_limit(krate: &ast::Crate, limit: &Once<usize>, name: &str, default: usize) {
2219
for attr in &krate.attrs {
2320
if !attr.check_name(name) {
2421
continue;
@@ -30,10 +27,6 @@ fn update_limit(sess: &Session, krate: &ast::Crate, limit: &Once<usize>,
3027
return;
3128
}
3229
}
33-
34-
span_err!(sess, attr.span, E0296,
35-
"malformed {} attribute, expected #![{}=\"N\"]",
36-
description, name);
3730
}
3831
limit.set(default);
3932
}

Diff for: src/librustc/traits/on_unimplemented.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
157157
note: None,
158158
}))
159159
} else {
160-
return Err(parse_error(tcx, attr.span,
161-
"`#[rustc_on_unimplemented]` requires a value",
162-
"value required here",
163-
Some(r#"eg `#[rustc_on_unimplemented(message="foo")]`"#)));
160+
return Err(ErrorReported);
164161
};
165162
debug!("of_item({:?}/{:?}) = {:?}", trait_def_id, impl_def_id, result);
166163
result

Diff for: src/librustc_driver/driver.rs

+10-16
Original file line numberDiff line numberDiff line change
@@ -1070,15 +1070,6 @@ where
10701070
)
10711071
});
10721072

1073-
// Add all buffered lints from the `ParseSess` to the `Session`.
1074-
sess.parse_sess.buffered_lints.with_lock(|buffered_lints| {
1075-
info!("{} parse sess buffered_lints", buffered_lints.len());
1076-
for BufferedEarlyLint{id, span, msg, lint_id} in buffered_lints.drain(..) {
1077-
let lint = lint::Lint::from_parser_lint_id(lint_id);
1078-
sess.buffer_lint(lint, id, span, &msg);
1079-
}
1080-
});
1081-
10821073
// Done with macro expansion!
10831074

10841075
after_expand(&krate)?;
@@ -1114,6 +1105,15 @@ where
11141105
);
11151106
});
11161107

1108+
// Add all buffered lints from the `ParseSess` to the `Session`.
1109+
sess.parse_sess.buffered_lints.with_lock(|buffered_lints| {
1110+
info!("{} parse sess buffered_lints", buffered_lints.len());
1111+
for BufferedEarlyLint{id, span, msg, lint_id} in buffered_lints.drain(..) {
1112+
let lint = lint::Lint::from_parser_lint_id(lint_id);
1113+
sess.buffer_lint(lint, id, span, &msg);
1114+
}
1115+
});
1116+
11171117
// Lower ast -> hir.
11181118
// First, we need to collect the dep_graph.
11191119
let dep_graph = match future_dep_graph {
@@ -1530,13 +1530,7 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<c
15301530
}
15311531
None
15321532
}
1533-
None => {
1534-
session
1535-
.struct_span_err(a.span, "`crate_type` requires a value")
1536-
.note("for example: `#![crate_type=\"lib\"]`")
1537-
.emit();
1538-
None
1539-
}
1533+
None => None
15401534
}
15411535
} else {
15421536
None

Diff for: src/librustc_lint/builtin.rs

+4-77
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ use syntax::ast::Expr;
3535
use syntax::attr;
3636
use syntax::source_map::Spanned;
3737
use syntax::edition::Edition;
38-
use syntax::feature_gate::{AttributeGate, AttributeType, Stability, deprecated_attributes};
38+
use syntax::feature_gate::{AttributeGate, AttributeTemplate, AttributeType};
39+
use syntax::feature_gate::{Stability, deprecated_attributes};
3940
use syntax_pos::{BytePos, Span, SyntaxContext};
4041
use syntax::symbol::keywords;
4142
use syntax::errors::{Applicability, DiagnosticBuilder};
@@ -689,86 +690,12 @@ impl EarlyLintPass for AnonymousParameters {
689690
}
690691
}
691692

692-
/// Checks for incorrect use of `repr` attributes.
693-
#[derive(Clone)]
694-
pub struct BadRepr;
695-
696-
impl LintPass for BadRepr {
697-
fn get_lints(&self) -> LintArray {
698-
lint_array!()
699-
}
700-
}
701-
702-
impl EarlyLintPass for BadRepr {
703-
fn check_attribute(&mut self, cx: &EarlyContext, attr: &ast::Attribute) {
704-
if attr.name() == "repr" {
705-
let list = attr.meta_item_list();
706-
707-
let repr_str = |lit: &str| { format!("#[repr({})]", lit) };
708-
709-
// Emit warnings with `repr` either has a literal assignment (`#[repr = "C"]`) or
710-
// no hints (``#[repr]`)
711-
let has_hints = list.as_ref().map(|ref list| !list.is_empty()).unwrap_or(false);
712-
if !has_hints {
713-
let mut suggested = false;
714-
let mut warn = if let Some(ref lit) = attr.value_str() {
715-
// avoid warning about empty `repr` on `#[repr = "foo"]`
716-
let mut warn = cx.struct_span_lint(
717-
BAD_REPR,
718-
attr.span,
719-
"`repr` attribute isn't configurable with a literal",
720-
);
721-
match lit.to_string().as_ref() {
722-
| "C" | "packed" | "rust" | "transparent"
723-
| "u8" | "u16" | "u32" | "u64" | "u128" | "usize"
724-
| "i8" | "i16" | "i32" | "i64" | "i128" | "isize" => {
725-
// if the literal could have been a valid `repr` arg,
726-
// suggest the correct syntax
727-
warn.span_suggestion_with_applicability(
728-
attr.span,
729-
"give `repr` a hint",
730-
repr_str(&lit.as_str()),
731-
Applicability::MachineApplicable
732-
);
733-
suggested = true;
734-
}
735-
_ => { // the literal wasn't a valid `repr` arg
736-
warn.span_label(attr.span, "needs a hint");
737-
}
738-
};
739-
warn
740-
} else {
741-
let mut warn = cx.struct_span_lint(
742-
BAD_REPR,
743-
attr.span,
744-
"`repr` attribute must have a hint",
745-
);
746-
warn.span_label(attr.span, "needs a hint");
747-
warn
748-
};
749-
if !suggested {
750-
warn.help(&format!(
751-
"valid hints include `{}`, `{}`, `{}` and `{}`",
752-
repr_str("C"),
753-
repr_str("packed"),
754-
repr_str("rust"),
755-
repr_str("transparent"),
756-
));
757-
warn.note("for more information, visit \
758-
<https://doc.rust-lang.org/reference/type-layout.html>");
759-
}
760-
warn.emit();
761-
}
762-
}
763-
}
764-
}
765-
766693
/// Checks for use of attributes which have been deprecated.
767694
#[derive(Clone)]
768695
pub struct DeprecatedAttr {
769696
// This is not free to compute, so we want to keep it around, rather than
770697
// compute it for every attribute.
771-
depr_attrs: Vec<&'static (&'static str, AttributeType, AttributeGate)>,
698+
depr_attrs: Vec<&'static (&'static str, AttributeType, AttributeTemplate, AttributeGate)>,
772699
}
773700

774701
impl DeprecatedAttr {
@@ -787,7 +714,7 @@ impl LintPass for DeprecatedAttr {
787714

788715
impl EarlyLintPass for DeprecatedAttr {
789716
fn check_attribute(&mut self, cx: &EarlyContext, attr: &ast::Attribute) {
790-
for &&(n, _, ref g) in &self.depr_attrs {
717+
for &&(n, _, _, ref g) in &self.depr_attrs {
791718
if attr.name() == n {
792719
if let &AttributeGate::Gated(Stability::Deprecated(link, suggestion),
793720
ref name,

Diff for: src/librustc_lint/lib.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ use rustc::lint::builtin::{
4848
INTRA_DOC_LINK_RESOLUTION_FAILURE,
4949
MISSING_DOC_CODE_EXAMPLES,
5050
PRIVATE_DOC_TESTS,
51-
parser::QUESTION_MARK_MACRO_SEP
51+
parser::QUESTION_MARK_MACRO_SEP,
52+
parser::ILL_FORMED_ATTRIBUTE_INPUT,
5253
};
5354
use rustc::session;
5455
use rustc::util;
@@ -114,7 +115,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
114115
UnsafeCode,
115116
AnonymousParameters,
116117
UnusedDocComment,
117-
BadRepr,
118118
EllipsisInclusiveRangePatterns,
119119
NonCamelCaseTypes,
120120
);
@@ -336,6 +336,11 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
336336
reference: "issue #52234 <https://github.com/rust-lang/rust/issues/52234>",
337337
edition: None,
338338
},
339+
FutureIncompatibleInfo {
340+
id: LintId::of(ILL_FORMED_ATTRIBUTE_INPUT),
341+
reference: "issue #57571 <https://github.com/rust-lang/rust/issues/57571>",
342+
edition: None,
343+
},
339344
]);
340345

341346
// Register renamed and removed lints.
@@ -385,4 +390,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
385390
"no longer a warning, #[no_mangle] functions always exported");
386391
store.register_removed("private_no_mangle_statics",
387392
"no longer a warning, #[no_mangle] statics always exported");
393+
store.register_removed("bad_repr",
394+
"replaced with a generic attribute input check");
388395
}

0 commit comments

Comments
 (0)