about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-09-03 16:25:46 +0000
committerbors <bors@rust-lang.org>2017-09-03 16:25:46 +0000
commitc8642daf93f725685309fc12f9d0908fec54b63a (patch)
tree36cdc2201fae2bc78a1c9a765c1c1534cf41b201 /src/libsyntax
parent2f2b8b34c2a1e585117714f99b3858da5f1b92b5 (diff)
parent291b4eddcefd1d6da1010f8a1f02f05338a44050 (diff)
downloadrust-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.rs25
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)
         }
     }
 }