Skip to content

Commit

Permalink
Auto merge of #57321 - petrochenkov:atokens, r=<try>
Browse files Browse the repository at this point in the history
Implement basic input validation for built-in attributes + Stabilize `unrestricted_attribute_tokens`

Based on #57272

---

In accordance with the plan in https://internals.rust-lang.org/t/unrestricted-attribute-tokens-feature-status/8561:
- The correct top-level shape (`#[attr]` vs `#[attr(...)]` vs `#[attr = ...]`) is enforced for built-in attributes.
- For non-built-in non-macro attributes:
    - The key-value form is restricted to bare minimum required to support what we support on stable - unsuffixed literals (#34981).
    - Arbitrary token streams in remaining forms (`#[attr(token_stream)]`, `#[attr{token_stream}]`, `#[attr[token_stream]]` ) are now allowed without a feature gate, like in macro attributes.

This will close #55208 once completed.
Need to go through crater first.
  • Loading branch information
bors committed Jan 4, 2019
2 parents c0bbc39 + 3b37f15 commit b9139d2
Show file tree
Hide file tree
Showing 161 changed files with 1,563 additions and 1,599 deletions.
37 changes: 2 additions & 35 deletions src/librustc/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1180,27 +1180,6 @@ fn main() {
```
"##,

E0296: r##"
This error indicates that the given recursion limit could not be parsed. Ensure
that the value provided is a positive integer between quotes.
Erroneous code example:
```compile_fail,E0296
#![recursion_limit]
fn main() {}
```
And a working example:
```
#![recursion_limit="1000"]
fn main() {}
```
"##,

E0308: r##"
This error occurs when the compiler was unable to infer the concrete type of a
variable. It can occur for several cases, the most common of which is a
Expand Down Expand Up @@ -2093,20 +2072,6 @@ trait Foo { }
```
"##,

E0702: r##"
This error indicates that a `#[non_exhaustive]` attribute had a value. The
`#[non_exhaustive]` should be empty.
Examples of erroneous code:
```compile_fail,E0702
# #![feature(non_exhaustive)]
#[non_exhaustive(anything)]
struct Foo;
```
"##,

E0718: r##"
This error indicates that a `#[lang = ".."]` attribute was placed
on the wrong type of item.
Expand Down Expand Up @@ -2138,6 +2103,7 @@ register_diagnostics! {
E0280, // requirement is not satisfied
E0284, // cannot resolve type
// E0285, // overflow evaluation builtin bounds
// E0296, // replaced with a generic attribute input check
// E0300, // unexpanded macro
// E0304, // expected signed integer constant
// E0305, // expected constant
Expand Down Expand Up @@ -2180,4 +2146,5 @@ register_diagnostics! {
E0709, // multiple different lifetimes used in arguments of `async fn`
E0710, // an unknown tool name found in scoped lint
E0711, // a feature has been declared with conflicting stability attributes
// E0702, // replaced with a generic attribute input check
}
15 changes: 0 additions & 15 deletions src/librustc/hir/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,15 +137,6 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
return;
}
}

if attr.meta_item_list().is_some() || attr.value_str().is_some() {
struct_span_err!(self.tcx.sess,
attr.span,
E0702,
"attribute should be empty")
.span_label(item.span, "not empty")
.emit();
}
}

/// Check if the `#[marker]` attribute on an `item` is valid.
Expand All @@ -160,12 +151,6 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
return;
}
}

if !attr.is_word() {
self.tcx.sess
.struct_span_err(attr.span, "attribute should be empty")
.emit();
}
}

/// Check if the `#[repr]` attributes on `item` are valid.
Expand Down
2 changes: 0 additions & 2 deletions src/librustc/lint/levels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,6 @@ impl<'a> LintLevelsBuilder<'a> {
let mut metas = if let Some(metas) = meta.meta_item_list() {
metas
} else {
let mut err = bad_attr(meta.span);
err.emit();
continue;
};

Expand Down
13 changes: 3 additions & 10 deletions src/librustc/middle/recursion_limit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,11 @@ use syntax::ast;
use rustc_data_structures::sync::Once;

pub fn update_limits(sess: &Session, krate: &ast::Crate) {
update_limit(sess, krate, &sess.recursion_limit, "recursion_limit",
"recursion limit", 64);
update_limit(sess, krate, &sess.type_length_limit, "type_length_limit",
"type length limit", 1048576);
update_limit(krate, &sess.recursion_limit, "recursion_limit", 64);
update_limit(krate, &sess.type_length_limit, "type_length_limit", 1048576);
}

fn update_limit(sess: &Session, krate: &ast::Crate, limit: &Once<usize>,
name: &str, description: &str, default: usize) {
fn update_limit(krate: &ast::Crate, limit: &Once<usize>, name: &str, default: usize) {
for attr in &krate.attrs {
if !attr.check_name(name) {
continue;
Expand All @@ -30,10 +27,6 @@ fn update_limit(sess: &Session, krate: &ast::Crate, limit: &Once<usize>,
return;
}
}

span_err!(sess, attr.span, E0296,
"malformed {} attribute, expected #![{}=\"N\"]",
description, name);
}
limit.set(default);
}
5 changes: 1 addition & 4 deletions src/librustc/traits/on_unimplemented.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
note: None,
}))
} else {
return Err(parse_error(tcx, attr.span,
"`#[rustc_on_unimplemented]` requires a value",
"value required here",
Some(r#"eg `#[rustc_on_unimplemented(message="foo")]`"#)));
return Err(ErrorReported);
};
debug!("of_item({:?}/{:?}) = {:?}", trait_def_id, impl_def_id, result);
result
Expand Down
4 changes: 1 addition & 3 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2801,16 +2801,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
self.impl_polarity(def_id1) == self.impl_polarity(def_id2)
&& trait1_is_empty
&& trait2_is_empty
} else if self.features().marker_trait_attr {
} else {
let is_marker_impl = |def_id: DefId| -> bool {
let trait_ref = self.impl_trait_ref(def_id);
trait_ref.map_or(false, |tr| self.trait_def(tr.def_id).is_marker)
};
self.impl_polarity(def_id1) == self.impl_polarity(def_id2)
&& is_marker_impl(def_id1)
&& is_marker_impl(def_id2)
} else {
false
}
}

Expand Down
31 changes: 11 additions & 20 deletions src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1101,23 +1101,20 @@ where
ast_validation::check_crate(sess, &krate)
});

time(sess, "name resolution", || -> CompileResult {
time(sess, "name resolution", || {
resolver.resolve_crate(&krate);
Ok(())
})?;
});

// Needs to go *after* expansion to be able to check the results of macro expansion.
time(sess, "complete gated feature checking", || {
sess.track_errors(|| {
syntax::feature_gate::check_crate(
&krate,
&sess.parse_sess,
&sess.features_untracked(),
&attributes,
sess.opts.unstable_features,
);
})
})?;
syntax::feature_gate::check_crate(
&krate,
&sess.parse_sess,
&sess.features_untracked(),
&attributes,
sess.opts.unstable_features,
);
});

// Lower ast -> hir.
// First, we need to collect the dep_graph.
Expand Down Expand Up @@ -1530,13 +1527,7 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<c
}
None
}
None => {
session
.struct_span_err(a.span, "`crate_type` requires a value")
.note("for example: `#![crate_type=\"lib\"]`")
.emit();
None
}
None => None
}
} else {
None
Expand Down
7 changes: 4 additions & 3 deletions src/librustc_lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ use syntax::ast::Expr;
use syntax::attr;
use syntax::source_map::Spanned;
use syntax::edition::Edition;
use syntax::feature_gate::{AttributeGate, AttributeType, Stability, deprecated_attributes};
use syntax::feature_gate::{AttributeGate, AttributeMeta, AttributeType};
use syntax::feature_gate::{Stability, deprecated_attributes};
use syntax_pos::{BytePos, Span, SyntaxContext};
use syntax::symbol::keywords;
use syntax::errors::{Applicability, DiagnosticBuilder};
Expand Down Expand Up @@ -752,7 +753,7 @@ impl EarlyLintPass for BadRepr {
pub struct DeprecatedAttr {
// This is not free to compute, so we want to keep it around, rather than
// compute it for every attribute.
depr_attrs: Vec<&'static (&'static str, AttributeType, AttributeGate)>,
depr_attrs: Vec<&'static (&'static str, AttributeType, AttributeMeta::Type, AttributeGate)>,
}

impl DeprecatedAttr {
Expand All @@ -771,7 +772,7 @@ impl LintPass for DeprecatedAttr {

impl EarlyLintPass for DeprecatedAttr {
fn check_attribute(&mut self, cx: &EarlyContext, attr: &ast::Attribute) {
for &&(n, _, ref g) in &self.depr_attrs {
for &&(n, _, _, ref g) in &self.depr_attrs {
if attr.name() == n {
if let &AttributeGate::Gated(Stability::Deprecated(link, suggestion),
ref name,
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_lint/unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes {
fn check_attribute(&mut self, cx: &LateContext, attr: &ast::Attribute) {
debug!("checking attribute: {:?}", attr);
// Note that check_name() marks the attribute as used if it matches.
for &(ref name, ty, _) in BUILTIN_ATTRIBUTES {
for &(ref name, ty, ..) in BUILTIN_ATTRIBUTES {
match ty {
AttributeType::Whitelisted if attr.check_name(name) => {
debug!("{:?} is Whitelisted", name);
Expand All @@ -256,7 +256,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes {
cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute");
// Is it a builtin attribute that must be used at the crate level?
let known_crate = BUILTIN_ATTRIBUTES.iter()
.find(|&&(builtin, ty, _)| name == builtin && ty == AttributeType::CrateLevel)
.find(|&&(builtin, ty, ..)| name == builtin && ty == AttributeType::CrateLevel)
.is_some();

// Has a plugin registered this attribute as one that must be used at
Expand Down
5 changes: 1 addition & 4 deletions src/librustc_plugin/load.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,7 @@ pub fn load_plugins(sess: &Session,

let plugins = match attr.meta_item_list() {
Some(xs) => xs,
None => {
call_malformed_plugin_attribute(sess, attr.span);
continue;
}
None => continue,
};

for plugin in plugins {
Expand Down
15 changes: 1 addition & 14 deletions src/librustc_typeck/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2134,12 +2134,7 @@ fn from_target_feature(
) {
let list = match attr.meta_item_list() {
Some(list) => list,
None => {
let msg = "#[target_feature] attribute must be of the form \
#[target_feature(..)]";
tcx.sess.span_err(attr.span, &msg);
return;
}
None => return,
};
let rust_features = tcx.features();
for item in list {
Expand Down Expand Up @@ -2337,14 +2332,6 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen
).emit();
}
codegen_fn_attrs.export_name = Some(s);
} else {
struct_span_err!(
tcx.sess,
attr.span,
E0558,
"`export_name` attribute has invalid format"
).span_label(attr.span, "did you mean #[export_name=\"*\"]?")
.emit();
}
} else if attr.check_name("target_feature") {
if tcx.fn_sig(id).unsafety() == Unsafety::Normal {
Expand Down
24 changes: 1 addition & 23 deletions src/librustc_typeck/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3785,29 +3785,6 @@ For more information about the inline attribute, https:
read://doc.rust-lang.org/reference.html#inline-attributes
"##,

E0558: r##"
The `export_name` attribute was malformed.
Erroneous code example:
```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail)
#[export_name] // error: `export_name` attribute has invalid format
pub fn something() {}
fn main() {}
```
The `export_name` attribute expects a string in order to determine the name of
the exported symbol. Example:
```
#[export_name = "some_function"] // ok!
pub fn something() {}
fn main() {}
```
"##,

E0559: r##"
An unknown field was specified into an enum's structure variant.
Expand Down Expand Up @@ -4881,6 +4858,7 @@ register_diagnostics! {
// E0372, // coherence not object safe
E0377, // the trait `CoerceUnsized` may only be implemented for a coercion
// between structures with the same definition
// E0558, // replaced with a generic attribute input check
E0533, // `{}` does not name a unit variant, unit struct or a constant
// E0563, // cannot determine a type for this `impl Trait`: {} // removed in 6383de15
E0564, // only named lifetimes are allowed in `impl Trait`,
Expand Down
3 changes: 0 additions & 3 deletions src/libsyntax/attr/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,9 +436,6 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
}
_ => unreachable!()
}
} else {
span_err!(diagnostic, attr.span(), E0548, "incorrect stability attribute type");
continue
}
}

Expand Down
9 changes: 3 additions & 6 deletions src/libsyntax/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,12 +187,9 @@ impl<'a> StripUnconfigured<'a> {
true
};

let meta_item = if let Some(meta_item) = attr.meta() {
meta_item
} else {
// Not a well-formed meta-item. Why? We don't know.
return error(attr.span, "`cfg` is not a well-formed meta-item",
"#[cfg(/* predicate */)]");
let meta_item = match attr.parse_meta(self.sess) {
Ok(meta_item) => meta_item,
Err(mut err) => { err.emit(); return true; }
};
let nested_meta_items = if let Some(nested_meta_items) = meta_item.meta_item_list() {
nested_meta_items
Expand Down
4 changes: 2 additions & 2 deletions src/libsyntax/diagnostic_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -389,12 +389,12 @@ register_diagnostics! {
E0545, // incorrect 'issue'
E0546, // missing 'feature'
E0547, // missing 'issue'
E0548, // incorrect stability attribute type
// E0548, // replaced with a generic attribute input check
E0549, // rustc_deprecated attribute must be paired with either stable or unstable attribute
E0550, // multiple deprecated attributes
E0551, // incorrect meta item
E0553, // multiple rustc_const_unstable attributes
E0555, // malformed feature attribute, expected #![feature(...)]
// E0555, // replaced with a generic attribute input check
E0556, // malformed feature, expected just one word
E0584, // file for module `..` found at both .. and ..
E0629, // missing 'feature' (rustc_const_unstable)
Expand Down
4 changes: 4 additions & 0 deletions src/libsyntax/ext/derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ pub fn collect_derives(cx: &mut ExtCtxt, attrs: &mut Vec<ast::Attribute>) -> Vec
if attr.path != "derive" {
return true;
}
if !attr.is_meta_item_list() {
cx.span_err(attr.span, "attribute must be of the form `#[derive(...)]`");
return false;
}

match attr.parse_list(cx.parse_sess,
|parser| parser.parse_path_allowing_meta(PathStyle::Mod)) {
Expand Down
Loading

0 comments on commit b9139d2

Please sign in to comment.