diff options
| author | bors <bors@rust-lang.org> | 2017-09-03 16:25:46 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-09-03 16:25:46 +0000 |
| commit | c8642daf93f725685309fc12f9d0908fec54b63a (patch) | |
| tree | 36cdc2201fae2bc78a1c9a765c1c1534cf41b201 /src/libsyntax | |
| parent | 2f2b8b34c2a1e585117714f99b3858da5f1b92b5 (diff) | |
| parent | 291b4eddcefd1d6da1010f8a1f02f05338a44050 (diff) | |
| download | rust-c8642daf93f725685309fc12f9d0908fec54b63a.tar.gz rust-c8642daf93f725685309fc12f9d0908fec54b63a.zip | |
Auto merge of #44191 - arielb1:on-unimplemented-label, r=nikomatsakis
More general `on_unimplemented`, with uses in `Try`
Allow `on_unimplemented` directives to specify both the label and the primary message of the trait error, and allow them to be controlled by flags - currently only to be desugaring-sensitive.
e.g.
```Rust
#[rustc_on_unimplemented(
on(all(direct, from_desugaring="?"),
message="the `?` operator can only be used in a \
function that returns `Result` \
(or another type that implements `{Try}`)",
label="cannot use the `?` operator in a function that returns `{Self}`"),
)]
```
r? @nikomatsakis
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/attr.rs | 25 |
1 files changed, 18 insertions, 7 deletions
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index bf8e0c0996a..adbbc1b0ac5 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -585,6 +585,20 @@ pub fn requests_inline(attrs: &[Attribute]) -> bool { /// Tests if a cfg-pattern matches the cfg set pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Features>) -> bool { + eval_condition(cfg, sess, &mut |cfg| { + 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())) + }) +} + +/// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to +/// evaluate individual items. +pub fn eval_condition<F>(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F) + -> bool + where F: FnMut(&ast::MetaItem) -> bool +{ match cfg.node { ast::MetaItemKind::List(ref mis) => { for mi in mis.iter() { @@ -598,10 +612,10 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat // that they won't fail with the loop above. match &*cfg.name.as_str() { "any" => mis.iter().any(|mi| { - cfg_matches(mi.meta_item().unwrap(), sess, features) + eval_condition(mi.meta_item().unwrap(), sess, eval) }), "all" => mis.iter().all(|mi| { - cfg_matches(mi.meta_item().unwrap(), sess, features) + eval_condition(mi.meta_item().unwrap(), sess, eval) }), "not" => { if mis.len() != 1 { @@ -609,7 +623,7 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat return false; } - !cfg_matches(mis[0].meta_item().unwrap(), sess, features) + !eval_condition(mis[0].meta_item().unwrap(), sess, eval) }, p => { span_err!(sess.span_diagnostic, cfg.span, E0537, "invalid predicate `{}`", p); @@ -618,10 +632,7 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat } }, ast::MetaItemKind::Word | ast::MetaItemKind::NameValue(..) => { - 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())) + eval(cfg) } } } |
