-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Add a cfg_attr syntax extension #16230
Conversation
cc #12479 |
out.attrs.push(cx.attribute(attr.span, attr)); | ||
} | ||
|
||
box(GC) out |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Must you always clone this? Seems like the clone is unnecessary if the config doesn't match.
if cfg_matches(cx, cfg) {
let mut out = (*it).clone();
out.attrs.push(cx.attribute(attr.span, attr));
box(GC) out
} else {
it
}
👍 I like this grammar. |
@kballard updated. |
@@ -303,6 +303,12 @@ fn is_ignored(cx: &TestCtxt, i: Gc<ast::Item>) -> bool { | |||
// check ignore(cfg(foo, bar)) | |||
attr.check_name("ignore") && match attr.meta_item_list() { | |||
Some(ref cfgs) => { | |||
if cfgs.iter().any(|cfg| cfg.check_name("cfg")) { | |||
cx.sess.span_warn(attr.span, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe use cfg.span
here?
This extends cfg-gating to attributes. ```rust #[cfg_attr(<cfg pattern>, <attr>)] ``` will expand to ```rust #[<attr>] ``` if the `<cfg pattern>` matches the current cfg environment, and nothing if it does not. The grammar for the cfg pattern has a simple recursive structure: * `value` and `key = "value"` are cfg patterns, * `not(<cfg pattern>)` is a cfg pattern and matches if `<cfg pattern>` does not. * `all(<cfg pattern>, ...)` is a cfg pattern and matches if all of the `<cfg pattern>`s do. * `any(<cfg pattern>, ...)` is a cfg pattern and matches if any of the `<cfg pattern>`s do. Examples: ```rust // only derive Show for assert_eq! in tests #[cfg_attr(test, deriving(Show))] struct Foo { ... } // only derive Show for assert_eq! in tests and debug builds #[cfg_attr(any(test, not(ndebug)), deriving(Show))] struct Foo { ... } // ignore a test in certain cases #[test] #[cfg_attr(all(not(target_os = "linux"), target_endian = "big"), ignore)] fn test_broken_thing() { ... } // Avoid duplication when fixing staging issues in rustc #[cfg_attr(not(stage0), lang="iter")] pub trait Iterator<T> { ... } ```
Replace `#[ignore(cfg(a, b))]` with `#[cfg_attr(all(a, b), ignore)]`
ast::MetaList(ref pred, ref mis) => { | ||
match pred.get() { | ||
"any" => mis.iter().any(|mi| cfg_matches(cx, *mi)), | ||
"all" => mis.iter().all(|mi| cfg_matches(cx, *mi)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems a little odd to introduce a new sub-language for cfg_attr
that isn't present in cfg
. Couldn't any
be emulated by multiple #[cfg_attr]
and could many clauses be allowed to emulate all
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. For one it's error prone, as I can see code easily ending up out of sync like #[cfg_attr(a, deriving(Show, Clone, Eq))] #[cfg_attr(b, deriving(Show, Clone))]
. It will also double-define the attribute if both a
and b
are set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cc #2119
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@alexcrichton I like this proposal because the new sub-language makes a lot more sense than our current #[cfg]
behavior, and it provides a model that we can use to modify #[cfg]
to match in the future.
This is on hold pending an RFC to move |
For now (bors's queue is quite full), I'm going to close this while we wait on the RFC. |
This extends cfg-gating to attributes.
#[cfg_attr(<cfg pattern>, <attr>)]
will expand to
if the
<cfg pattern>
matches the current cfg environment, and nothingif it does not. The grammar for the cfg pattern has a simple
recursive structure:
value
andkey = "value"
are cfg patterns,not(<cfg pattern>)
is a cfg pattern and matches if<cfg pattern>
does not.
all(<cfg pattern>, ...)
is a cfg pattern and matches if all of the<cfg pattern>
s do.any(<cfg pattern>, ...)
is a cfg pattern and matches if any of the<cfg pattern>
s do.Examples:
I also deprecated the
#[ignore(cfg(...))]
syntax in favor of#[cfg_attr(..., ignore)]
.I think this cfg pattern syntax is a good system to move
#[cfg(...)]
to as well, but that should probably go through an RFC first.