]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #53413 - eddyb:featured-in-the-latest-edition, r=varkor
authorCorey Farwell <coreyf@rwell.org>
Fri, 17 Aug 2018 15:23:44 +0000 (08:23 -0700)
committerGitHub <noreply@github.com>
Fri, 17 Aug 2018 15:23:44 +0000 (08:23 -0700)
Warn that `#![feature(rust_2018_preview)]` is implied when the edition is set to Rust 2018.

cc @varkor @petrochenkov @joshtriplett

1  2 
src/libsyntax/feature_gate.rs

index 395e5c98652326091ed5ce6f79d573698426722c,dcae9b1e9ca7eabfa494328cb63d7100266b7364..7a8a7b073185a6477dfeb8fdbb73dec1995d1202
@@@ -1526,29 -1526,27 +1526,29 @@@ impl<'a> Visitor<'a> for PostExpansionV
              }
          }
  
 -        match attr.parse_meta(self.context.parse_sess) {
 -            Ok(meta) => {
 -                // allow attr_literals in #[repr(align(x))] and #[repr(packed(n))]
 -                let mut allow_attr_literal = false;
 -                if attr.path == "repr" {
 -                    if let Some(content) = meta.meta_item_list() {
 -                        allow_attr_literal = content.iter().any(
 -                            |c| c.check_name("align") || c.check_name("packed"));
 +        if !self.context.features.unrestricted_attribute_tokens {
 +            // Unfortunately, `parse_meta` cannot be called speculatively because it can report
 +            // errors by itself, so we have to call it only if the feature is disabled.
 +            match attr.parse_meta(self.context.parse_sess) {
 +                Ok(meta) => {
 +                    // allow attr_literals in #[repr(align(x))] and #[repr(packed(n))]
 +                    let mut allow_attr_literal = false;
 +                    if attr.path == "repr" {
 +                        if let Some(content) = meta.meta_item_list() {
 +                            allow_attr_literal = content.iter().any(
 +                                |c| c.check_name("align") || c.check_name("packed"));
 +                        }
                      }
 -                }
  
 -                if !allow_attr_literal && contains_novel_literal(&meta) {
 -                    gate_feature_post!(&self, attr_literals, attr.span,
 -                                    "non-string literals in attributes, or string \
 -                                    literals in top-level positions, are experimental");
 +                    if !allow_attr_literal && contains_novel_literal(&meta) {
 +                        gate_feature_post!(&self, attr_literals, attr.span,
 +                                        "non-string literals in attributes, or string \
 +                                        literals in top-level positions, are experimental");
 +                    }
 +                }
 +                Err(mut err) => {
 +                    err.help("try enabling `#![feature(unrestricted_attribute_tokens)]`").emit()
                  }
 -            }
 -            Err(mut err) => {
 -                err.cancel();
 -                gate_feature_post!(&self, unrestricted_attribute_tokens, attr.span,
 -                                    "arbitrary tokens in non-macro attributes are unstable");
              }
          }
      }
@@@ -1922,15 -1920,18 +1922,23 @@@ pub fn get_features(span_handler: &Hand
          err.emit();
      }
  
 +    // Some features are known to be incomplete and using them is likely to have
 +    // unanticipated results, such as compiler crashes. We warn the user about these
 +    // to alert them.
 +    let incomplete_features = ["generic_associated_types"];
 +
      let mut features = Features::new();
      let mut edition_enabled_features = FxHashMap();
  
-     for &(name, .., f_edition, set) in ACTIVE_FEATURES.iter() {
+     for &edition in ALL_EDITIONS {
+         if edition <= crate_edition {
+             // The `crate_edition` implies its respective umbrella feature-gate
+             // (i.e. `#![feature(rust_20XX_preview)]` isn't needed on edition 20XX).
+             edition_enabled_features.insert(Symbol::intern(edition.feature_name()), edition);
+         }
+     }
+     for &(name, .., f_edition, set) in ACTIVE_FEATURES {
          if let Some(f_edition) = f_edition {
              if f_edition <= crate_edition {
                  set(&mut features, DUMMY_SP);
          }
      }
  
+     // Process the edition umbrella feature-gates first, to ensure
+     // `edition_enabled_features` is completed before it's queried.
      for attr in krate_attrs {
          if !attr.check_name("feature") {
              continue
  
          let list = match attr.meta_item_list() {
              Some(list) => list,
-             None => {
-                 span_err!(span_handler, attr.span, E0555,
-                           "malformed feature attribute, expected #![feature(...)]");
-                 continue
-             }
+             None => continue,
          };
  
          for mi in list {
              let name = if let Some(word) = mi.word() {
                  word.name()
              } else {
-                 span_err!(span_handler, mi.span, E0556,
-                           "malformed feature, expected just one word");
                  continue
              };
  
 +            if incomplete_features.iter().any(|f| *f == name.as_str()) {
 +                span_handler.struct_span_warn(
 +                    mi.span,
 +                    &format!(
 +                        "the feature `{}` is incomplete and may cause the compiler to crash",
 +                        name
 +                    )
 +                ).emit();
 +            }
 +
              if let Some(edition) = ALL_EDITIONS.iter().find(|e| name == e.feature_name()) {
                  if *edition <= crate_edition {
-                     continue
+                     continue;
                  }
  
-                 for &(name, .., f_edition, set) in ACTIVE_FEATURES.iter() {
+                 for &(name, .., f_edition, set) in ACTIVE_FEATURES {
                      if let Some(f_edition) = f_edition {
                          if f_edition <= *edition {
                              // FIXME(Manishearth) there is currently no way to set
                          }
                      }
                  }
+             }
+         }
+     }
+     for attr in krate_attrs {
+         if !attr.check_name("feature") {
+             continue
+         }
+         let list = match attr.meta_item_list() {
+             Some(list) => list,
+             None => {
+                 span_err!(span_handler, attr.span, E0555,
+                           "malformed feature attribute, expected #![feature(...)]");
+                 continue
+             }
+         };
  
+         for mi in list {
+             let name = if let Some(word) = mi.word() {
+                 word.name()
+             } else {
+                 span_err!(span_handler, mi.span, E0556,
+                           "malformed feature, expected just one word");
                  continue
+             };
+             if let Some(edition) = edition_enabled_features.get(&name) {
+                 struct_span_warn!(
+                     span_handler,
+                     mi.span,
+                     E0705,
+                     "the feature `{}` is included in the Rust {} edition",
+                     name,
+                     edition,
+                 ).emit();
+                 continue;
+             }
+             if ALL_EDITIONS.iter().any(|e| name == e.feature_name()) {
+                 // Handled in the separate loop above.
+                 continue;
              }
  
              if let Some((.., set)) = ACTIVE_FEATURES.iter().find(|f| name == f.0) {
-                 if let Some(edition) = edition_enabled_features.get(&name) {
-                     struct_span_warn!(
-                         span_handler,
-                         mi.span,
-                         E0705,
-                         "the feature `{}` is included in the Rust {} edition",
-                         name,
-                         edition,
-                     ).emit();
-                 } else {
-                     set(&mut features, mi.span);
-                     features.declared_lang_features.push((name, mi.span, None));
-                 }
+                 set(&mut features, mi.span);
+                 features.declared_lang_features.push((name, mi.span, None));
                  continue
              }