Skip to content

Commit

Permalink
Use the attribute placeholder if the cfg_attr couldn't be parsed
Browse files Browse the repository at this point in the history
  • Loading branch information
estebank committed Dec 3, 2024
1 parent e30e764 commit 9c1546d
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 20 deletions.
43 changes: 23 additions & 20 deletions compiler/rustc_expand/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,27 @@ impl<'a> StripUnconfigured<'a> {
}
}

/// `cfg` and `cfg_attr` gets replaced with an inert `rustc_cfg_placeholder` to keep the
/// attribute "spot" in the AST. This allows suggestions to remove an item to provide a
/// correct suggestion when `#[cfg_attr]`s are present.
fn mk_placeholder(&self, cfg_attr: &ast::Attribute) -> ast::Attribute {
let item = ast::AttrItem {
unsafety: ast::Safety::Default,
path: ast::Path::from_ident(rustc_span::symbol::Ident::with_dummy_span(
sym::rustc_cfg_placeholder,
)),
args: ast::AttrArgs::Empty,
tokens: None,
};
let kind = ast::AttrKind::Normal(P(ast::NormalAttr { item, tokens: None }));
ast::Attribute {
kind,
id: self.sess.psess.attr_id_generator.mk_attr_id(),
style: cfg_attr.style,
span: cfg_attr.span,
}
}

/// Parse and expand a single `cfg_attr` attribute into a list of attributes
/// when the configuration predicate is true, or otherwise expand into an
/// empty list of attributes.
Expand All @@ -282,7 +303,7 @@ impl<'a> StripUnconfigured<'a> {
let Some((cfg_predicate, expanded_attrs)) =
rustc_parse::parse_cfg_attr(cfg_attr, &self.sess.psess)
else {
return vec![];
return vec![self.mk_placeholder(cfg_attr)];
};

// Lint on zero attributes in source.
Expand All @@ -296,25 +317,7 @@ impl<'a> StripUnconfigured<'a> {
}

if !attr::cfg_matches(&cfg_predicate, &self.sess, self.lint_node_id, self.features) {
// `cfg` and `cfg_attr` gets replaced with an inert `rustc_cfg_placeholder` to keep the
// attribute "spot" in the AST. This allows suggestions to remove an item to provide a
// correct suggestion when `#[cfg_attr]`s are present.
let item = ast::AttrItem {
unsafety: ast::Safety::Default,
path: ast::Path::from_ident(rustc_span::symbol::Ident::with_dummy_span(
sym::rustc_cfg_placeholder,
)),
args: ast::AttrArgs::Empty,
tokens: None,
};
let kind = ast::AttrKind::Normal(P(ast::NormalAttr { item, tokens: None }));
let attr: ast::Attribute = ast::Attribute {
kind,
id: self.sess.psess.attr_id_generator.mk_attr_id(),
style: ast::AttrStyle::Outer,
span: cfg_attr.span,
};
return vec![attr];
return vec![self.mk_placeholder(cfg_attr)];
}

if recursive {
Expand Down
15 changes: 15 additions & 0 deletions tests/ui/removing-extern-crate-malformed-cfg.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//@ edition:2018
//@ aux-build:removing-extern-crate.rs
//@ run-rustfix

#![warn(rust_2018_idioms)]

//~ WARNING unused `extern crate`
//~ WARNING unused `extern crate`

mod another {
//~ WARNING unused `extern crate`
//~ WARNING unused `extern crate`
}

fn main() {}
17 changes: 17 additions & 0 deletions tests/ui/removing-extern-crate-malformed-cfg.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//@ edition:2018
//@ aux-build:removing-extern-crate.rs
//@ run-rustfix

#![warn(rust_2018_idioms)]

#[cfg_attr(test, "macro_use")] //~ ERROR expected
extern crate removing_extern_crate as foo; //~ WARNING unused `extern crate`
extern crate core; //~ WARNING unused `extern crate`

mod another {
#[cfg_attr(test)] //~ ERROR expected
extern crate removing_extern_crate as foo; //~ WARNING unused `extern crate`
extern crate core; //~ WARNING unused `extern crate`
}

fn main() {}
76 changes: 76 additions & 0 deletions tests/ui/removing-extern-crate-malformed-cfg.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
error: expected identifier, found `"macro_use"`
--> $DIR/removing-extern-crate-malformed-cfg.rs:7:18
|
LL | #[cfg_attr(test, "macro_use")]
| ^^^^^^^^^^^ expected identifier
|
= help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]`
= note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>

error: expected one of `(`, `,`, `::`, or `=`, found `<eof>`
--> $DIR/removing-extern-crate-malformed-cfg.rs:12:16
|
LL | #[cfg_attr(test)]
| ^^^^ expected one of `(`, `,`, `::`, or `=`
|
= help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]`
= note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>

warning: unused `extern crate`
--> $DIR/removing-extern-crate-malformed-cfg.rs:8:1
|
LL | extern crate removing_extern_crate as foo;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unused
|
note: the lint level is defined here
--> $DIR/removing-extern-crate-malformed-cfg.rs:5:9
|
LL | #![warn(rust_2018_idioms)]
| ^^^^^^^^^^^^^^^^
= note: `#[warn(unused_extern_crates)]` implied by `#[warn(rust_2018_idioms)]`
help: remove the unused `extern crate`
|
LL - #[cfg_attr(test, "macro_use")]
LL - extern crate removing_extern_crate as foo;
LL +
|

warning: unused `extern crate`
--> $DIR/removing-extern-crate-malformed-cfg.rs:9:1
|
LL | extern crate core;
| ^^^^^^^^^^^^^^^^^^ unused
|
help: remove the unused `extern crate`
|
LL - extern crate core;
LL +
|

warning: unused `extern crate`
--> $DIR/removing-extern-crate-malformed-cfg.rs:13:5
|
LL | extern crate removing_extern_crate as foo;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unused
|
help: remove the unused `extern crate`
|
LL - #[cfg_attr(test)]
LL - extern crate removing_extern_crate as foo;
LL +
|

warning: unused `extern crate`
--> $DIR/removing-extern-crate-malformed-cfg.rs:14:5
|
LL | extern crate core;
| ^^^^^^^^^^^^^^^^^^ unused
|
help: remove the unused `extern crate`
|
LL - extern crate core;
LL +
|

error: aborting due to 2 previous errors; 4 warnings emitted

0 comments on commit 9c1546d

Please sign in to comment.