if let (Some(feats), Some(gated_cfg)) = (features, GatedCfg::gate(cfg)) {
gated_cfg.check_and_emit(sess, feats);
}
- sess.config.contains(&(cfg.name(), cfg.value_str()))
+ let error = |span, msg| { sess.span_diagnostic.span_err(span, msg); true };
+ if cfg.ident.segments.len() != 1 {
+ return error(cfg.ident.span, "`cfg` predicate key must be an identifier");
+ }
+ match &cfg.node {
+ MetaItemKind::List(..) => {
+ error(cfg.span, "unexpected parentheses after `cfg` predicate key")
+ }
+ MetaItemKind::NameValue(lit) if !lit.node.is_str() => {
+ error(lit.span, "literal in `cfg` predicate value must be a string")
+ }
+ MetaItemKind::NameValue(..) | MetaItemKind::Word => {
+ sess.config.contains(&(cfg.name(), cfg.value_str()))
+ }
+ }
})
}
// Determine if a node with the given attributes should be included in this configuration.
pub fn in_cfg(&mut self, attrs: &[ast::Attribute]) -> bool {
attrs.iter().all(|attr| {
- let mis = if !is_cfg(attr) {
+ if !is_cfg(attr) {
return true;
- } else if let Some(mis) = attr.meta_item_list() {
- mis
+ }
+
+ let error = |span, msg, suggestion: &str| {
+ let mut err = self.sess.span_diagnostic.struct_span_err(span, msg);
+ if !suggestion.is_empty() {
+ err.span_suggestion(span, "expected syntax is", suggestion.into());
+ }
+ err.emit();
+ true
+ };
+
+ let meta_item = if let Some(meta_item) = attr.meta() {
+ meta_item
} else {
- return true;
+ // 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 nested_meta_items = if let Some(nested_meta_items) = meta_item.meta_item_list() {
+ nested_meta_items
+ } else {
+ return error(meta_item.span, "`cfg` is not followed by parentheses",
+ "cfg(/* predicate */)");
};
- if mis.len() != 1 {
- self.sess.span_diagnostic.span_err(attr.span, "expected 1 cfg-pattern");
- return true;
+ if nested_meta_items.is_empty() {
+ return error(meta_item.span, "`cfg` predicate is not specified", "");
+ } else if nested_meta_items.len() > 1 {
+ return error(nested_meta_items.last().unwrap().span,
+ "multiple `cfg` predicates are specified", "");
}
- if !mis[0].is_meta_item() {
- self.sess.span_diagnostic.span_err(mis[0].span, "unexpected literal");
- return true;
+ match nested_meta_items[0].meta_item() {
+ Some(meta_item) => attr::cfg_matches(meta_item, self.sess, self.features),
+ None => error(nested_meta_items[0].span,
+ "`cfg` predicate key cannot be a literal", ""),
}
-
- attr::cfg_matches(mis[0].meta_item().unwrap(), self.sess, self.features)
})
}
--- /dev/null
+#[cfg] //~ ERROR `cfg` is not followed by parentheses
+struct S1;
+
+#[cfg = 10] //~ ERROR `cfg` is not followed by parentheses
+struct S2;
+
+#[cfg()] //~ ERROR `cfg` predicate is not specified
+struct S3;
+
+#[cfg(a, b)] //~ ERROR multiple `cfg` predicates are specified
+struct S4;
+
+#[cfg("str")] //~ ERROR `cfg` predicate key cannot be a literal
+struct S5;
+
+#[cfg(a::b)] //~ ERROR `cfg` predicate key must be an identifier
+struct S6;
+
+#[cfg(a())] //~ ERROR invalid predicate `a`
+struct S7;
+
+#[cfg(a = 10)] //~ ERROR literal in `cfg` predicate value must be a string
+struct S8;
+
+macro_rules! generate_s9 {
+ ($expr: expr) => {
+ #[cfg(feature = $expr)] //~ ERROR `cfg` is not a well-formed meta-item
+ struct S9;
+ }
+}
+
+generate_s9!(concat!("nonexistent"));
--- /dev/null
+error: `cfg` is not followed by parentheses
+ --> $DIR/cfg-attr-syntax-validation.rs:1:1
+ |
+LL | #[cfg] //~ ERROR `cfg` is not followed by parentheses
+ | ^^^^^^ help: expected syntax is: `cfg(/* predicate */)`
+
+error: `cfg` is not followed by parentheses
+ --> $DIR/cfg-attr-syntax-validation.rs:4:1
+ |
+LL | #[cfg = 10] //~ ERROR `cfg` is not followed by parentheses
+ | ^^^^^^^^^^^ help: expected syntax is: `cfg(/* predicate */)`
+
+error: `cfg` predicate is not specified
+ --> $DIR/cfg-attr-syntax-validation.rs:7:1
+ |
+LL | #[cfg()] //~ ERROR `cfg` predicate is not specified
+ | ^^^^^^^^
+
+error: multiple `cfg` predicates are specified
+ --> $DIR/cfg-attr-syntax-validation.rs:10:10
+ |
+LL | #[cfg(a, b)] //~ ERROR multiple `cfg` predicates are specified
+ | ^
+
+error: `cfg` predicate key cannot be a literal
+ --> $DIR/cfg-attr-syntax-validation.rs:13:7
+ |
+LL | #[cfg("str")] //~ ERROR `cfg` predicate key cannot be a literal
+ | ^^^^^
+
+error: `cfg` predicate key must be an identifier
+ --> $DIR/cfg-attr-syntax-validation.rs:16:7
+ |
+LL | #[cfg(a::b)] //~ ERROR `cfg` predicate key must be an identifier
+ | ^^^^
+
+error[E0537]: invalid predicate `a`
+ --> $DIR/cfg-attr-syntax-validation.rs:19:7
+ |
+LL | #[cfg(a())] //~ ERROR invalid predicate `a`
+ | ^^^
+
+error: literal in `cfg` predicate value must be a string
+ --> $DIR/cfg-attr-syntax-validation.rs:22:11
+ |
+LL | #[cfg(a = 10)] //~ ERROR literal in `cfg` predicate value must be a string
+ | ^^
+
+error: `cfg` is not a well-formed meta-item
+ --> $DIR/cfg-attr-syntax-validation.rs:27:9
+ |
+LL | #[cfg(feature = $expr)] //~ ERROR `cfg` is not a well-formed meta-item
+ | ^^^^^^^^^^^^^^^^^^^^^^^ help: expected syntax is: `#[cfg(/* predicate */)]`
+...
+LL | generate_s9!(concat!("nonexistent"));
+ | ------------------------------------- in this macro invocation
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0537`.