Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement tool_attributes feature (RFC 2103) #50030

Merged
merged 9 commits into from
May 3, 2018
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
26 changes: 26 additions & 0 deletions src/doc/unstable-book/src/language-features/tool-attributes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# `tool_attributes`

The tracking issue for this feature is: [#44690]

[#44690]: https://github.com/rust-lang/rust/issues/44690

------------------------

Tool attributes let you use scoped attributes to control the behavior
of certain tools.

Currently tool names which can be appear in scoped attributes are restricted to
`clippy` and `rustfmt`.

## An example

```rust
#![feature(tool_attributes)]

#[rustfmt::skip]
fn foo() { println!("hello, world"); }

fn main() {
foo();
}
```
7 changes: 2 additions & 5 deletions src/librustc/hir/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,10 +153,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
// ```
let hints: Vec<_> = item.attrs
.iter()
.filter(|attr| match attr.name() {
Some(name) => name == "repr",
None => false,
})
.filter(|attr| attr.name() == "repr")
.filter_map(|attr| attr.meta_item_list())
.flat_map(|hints| hints)
.collect();
Expand Down Expand Up @@ -311,7 +308,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {

fn check_used(&self, item: &hir::Item, target: Target) {
for attr in &item.attrs {
if attr.name().map(|name| name == "used").unwrap_or(false) && target != Target::Static {
if attr.name() == "used" && target != Target::Static {
self.tcx.sess
.span_err(attr.span, "attribute must be applied to a `static` variable");
}
Expand Down
21 changes: 14 additions & 7 deletions src/librustc/ich/impls_syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for [ast::Attribute] {
let filtered: AccumulateVec<[&ast::Attribute; 8]> = self
.iter()
.filter(|attr| {
!attr.is_sugared_doc &&
attr.name().map(|name| !hcx.is_ignored_attr(name)).unwrap_or(true)
!attr.is_sugared_doc && !hcx.is_ignored_attr(attr.name())
})
.collect();

Expand All @@ -211,12 +210,23 @@ impl<'a> HashStable<StableHashingContext<'a>> for [ast::Attribute] {
}
}

impl<'a> HashStable<StableHashingContext<'a>> for ast::Path {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
self.segments.len().hash_stable(hcx, hasher);
for segment in &self.segments {
segment.ident.name.hash_stable(hcx, hasher);
}
}
}

impl<'a> HashStable<StableHashingContext<'a>> for ast::Attribute {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
// Make sure that these have been filtered out.
debug_assert!(self.name().map(|name| !hcx.is_ignored_attr(name)).unwrap_or(true));
debug_assert!(!hcx.is_ignored_attr(self.name()));
debug_assert!(!self.is_sugared_doc);

let ast::Attribute {
Expand All @@ -229,10 +239,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for ast::Attribute {
} = *self;

style.hash_stable(hcx, hasher);
path.segments.len().hash_stable(hcx, hasher);
for segment in &path.segments {
segment.ident.name.hash_stable(hcx, hasher);
}
path.hash_stable(hcx, hasher);
for tt in tokens.trees() {
tt.hash_stable(hcx, hasher);
}
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/lint/levels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ impl<'a> LintLevelsBuilder<'a> {
"malformed lint attribute");
};
for attr in attrs {
let level = match attr.name().and_then(|name| Level::from_str(&name.as_str())) {
let level = match Level::from_str(&attr.name().as_str()) {
None => continue,
Some(lvl) => lvl,
};
Expand All @@ -221,7 +221,7 @@ impl<'a> LintLevelsBuilder<'a> {
continue
}
};
let name = word.ident.name;
let name = word.name();
match store.check_lint_name(&name.as_str()) {
CheckLintNameResult::Ok(ids) => {
let src = LintSource::Node(name, li.span);
Expand Down Expand Up @@ -260,7 +260,7 @@ impl<'a> LintLevelsBuilder<'a> {
Some(li.span.into()),
&msg);
if name.as_str().chars().any(|c| c.is_uppercase()) {
let name_lower = name.as_str().to_lowercase();
let name_lower = name.as_str().to_lowercase().to_string();
if let CheckLintNameResult::NoLint =
store.check_lint_name(&name_lower) {
db.emit();
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
} else {
// Emit errors for non-staged-api crates.
for attr in attrs {
let tag = unwrap_or!(attr.name(), continue);
let tag = attr.name();
if tag == "unstable" || tag == "stable" || tag == "rustc_deprecated" {
attr::mark_used(attr);
self.tcx.sess.span_err(attr.span(), "stability attributes may not be used \
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/session/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1683,7 +1683,7 @@ pub fn parse_cfgspecs(cfgspecs: Vec<String>) -> ast::CrateConfig {
early_error(ErrorOutputType::default(), &msg)
}

(meta_item.ident.name, meta_item.value_str())
(meta_item.name(), meta_item.value_str())
})
.collect::<ast::CrateConfig>()
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/traits/on_unimplemented.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective {
for command in self.subcommands.iter().chain(Some(self)).rev() {
if let Some(ref condition) = command.condition {
if !attr::eval_condition(condition, &tcx.sess.parse_sess, &mut |c| {
options.contains(&(c.ident.name.as_str().to_string(),
options.contains(&(c.name().as_str().to_string(),
match c.value_str().map(|s| s.as_str().to_string()) {
Some(s) => Some(s),
None => None
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_driver/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1060,7 +1060,7 @@ impl RustcDefaultCalls {
let mut cfgs = Vec::new();
for &(name, ref value) in sess.parse_sess.config.iter() {
let gated_cfg = GatedCfg::gate(&ast::MetaItem {
ident: ast::Ident::with_empty_ctxt(name),
ident: ast::Path::from_ident(name.to_ident()),
node: ast::MetaItemKind::Word,
span: DUMMY_SP,
});
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_incremental/assert_dep_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ impl<'a, 'tcx> IfThisChanged<'a, 'tcx> {
for list_item in attr.meta_item_list().unwrap_or_default() {
match list_item.word() {
Some(word) if value.is_none() =>
value = Some(word.ident.name),
value = Some(word.name()),
_ =>
// FIXME better-encapsulate meta_item (don't directly access `node`)
span_bug!(list_item.span(), "unexpected meta-item {:?}", list_item.node),
Expand Down
3 changes: 1 addition & 2 deletions src/librustc_lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -675,9 +675,8 @@ impl LintPass for DeprecatedAttr {

impl EarlyLintPass for DeprecatedAttr {
fn check_attribute(&mut self, cx: &EarlyContext, attr: &ast::Attribute) {
let name = unwrap_or!(attr.name(), return);
for &&(n, _, ref g) in &self.depr_attrs {
if name == n {
if attr.name() == n {
if let &AttributeGate::Gated(Stability::Deprecated(link),
ref name,
ref reason,
Expand Down
1 change: 0 additions & 1 deletion src/librustc_lint/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]

#[macro_use]
extern crate syntax;
#[macro_use]
extern crate rustc;
Expand Down
3 changes: 1 addition & 2 deletions src/librustc_lint/unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,6 @@ impl LintPass for UnusedAttributes {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes {
fn check_attribute(&mut self, cx: &LateContext, attr: &ast::Attribute) {
debug!("checking attribute: {:?}", attr);
let name = unwrap_or!(attr.name(), return);

// Note that check_name() marks the attribute as used if it matches.
for &(ref name, ty, _) in BUILTIN_ATTRIBUTES {
match ty {
Expand All @@ -213,6 +211,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes {
}
}

let name = attr.name();
if !attr::is_used(attr) {
debug!("Emitting warning for: {:?}", attr);
cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute");
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -702,7 +702,7 @@ impl<'a> Resolver<'a> {
match attr.meta_item_list() {
Some(names) => for attr in names {
if let Some(word) = attr.word() {
imports.imports.push((word.ident.name, attr.span()));
imports.imports.push((word.name(), attr.span()));
} else {
span_err!(self.session, attr.span(), E0466, "bad macro import");
}
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_resolve/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ impl<'a> base::Resolver for Resolver<'a> {
fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<ast::Attribute>, allow_derive: bool)
-> Option<ast::Attribute> {
for i in 0..attrs.len() {
let name = unwrap_or!(attrs[i].name(), continue);
let name = attrs[i].name();

if self.session.plugin_attributes.borrow().iter()
.any(|&(ref attr_nm, _)| name == &**attr_nm) {
Expand All @@ -231,7 +231,7 @@ impl<'a> base::Resolver for Resolver<'a> {

// Check for legacy derives
for i in 0..attrs.len() {
let name = unwrap_or!(attrs[i].name(), continue);
let name = attrs[i].name();

if name == "derive" {
let result = attrs[i].parse_list(&self.session.parse_sess, |parser| {
Expand Down
Loading