use errors::{Applicability, DiagnosticBuilder, Handler};
use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::sync::Lock;
use rustc_target::spec::abi::Abi;
use syntax_pos::{Span, DUMMY_SP, MultiSpan};
use log::debug;
// Allows `impl Trait` with multiple unrelated lifetimes.
(active, member_constraints, "1.37.0", Some(61977), None),
+ // Allows `async || body` closures.
+ (active, async_closure, "1.37.0", Some(62290), None),
+
// -------------------------------------------------------------------------
// feature-group-end: actual feature gates
// -------------------------------------------------------------------------
attribute is just used for rustc unit \
tests and will never be stable",
cfg_fn!(rustc_attrs))),
+ (sym::rustc_dump_env_program_clauses, Whitelisted, template!(Word), Gated(Stability::Unstable,
+ sym::rustc_attrs,
+ "the `#[rustc_dump_env_program_clauses]` \
+ attribute is just used for rustc unit \
+ tests and will never be stable",
+ cfg_fn!(rustc_attrs))),
+ (sym::rustc_object_lifetime_default, Whitelisted, template!(Word), Gated(Stability::Unstable,
+ sym::rustc_attrs,
+ "the `#[rustc_object_lifetime_default]` \
+ attribute is just used for rustc unit \
+ tests and will never be stable",
+ cfg_fn!(rustc_attrs))),
(sym::rustc_test_marker, Normal, template!(Word), Gated(Stability::Unstable,
sym::rustc_attrs,
"the `#[rustc_test_marker]` attribute \
"internal implementation detail",
cfg_fn!(rustc_attrs))),
+ (sym::rustc_allocator_nounwind, Whitelisted, template!(Word), Gated(Stability::Unstable,
+ sym::rustc_attrs,
+ "internal implementation detail",
+ cfg_fn!(rustc_attrs))),
+
+ (sym::rustc_builtin_macro, Whitelisted, template!(Word), Gated(Stability::Unstable,
+ sym::rustc_attrs,
+ "internal implementation detail",
+ cfg_fn!(rustc_attrs))),
+
+ (sym::rustc_promotable, Whitelisted, template!(Word), Gated(Stability::Unstable,
+ sym::rustc_attrs,
+ "internal implementation detail",
+ cfg_fn!(rustc_attrs))),
+
+ (sym::rustc_allow_const_fn_ptr, Whitelisted, template!(Word), Gated(Stability::Unstable,
+ sym::rustc_attrs,
+ "internal implementation detail",
+ cfg_fn!(rustc_attrs))),
+
(sym::rustc_dummy, Normal, template!(Word /* doesn't matter*/), Gated(Stability::Unstable,
sym::rustc_attrs,
"used by the test suite",
}
debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
return;
+ } else {
+ for segment in &attr.path.segments {
+ if segment.ident.as_str().starts_with("rustc") {
+ let msg = "attributes starting with `rustc` are \
+ reserved for use by the `rustc` compiler";
+ gate_feature!(self, rustc_attrs, segment.ident.span, msg);
+ }
+ }
}
for &(n, ty) in self.plugin_attributes {
if attr.path == n {
return;
}
}
- if !attr::is_known(attr) {
- if attr.name_or_empty().as_str().starts_with("rustc_") {
- let msg = "unless otherwise specified, attributes with the prefix `rustc_` \
- are reserved for internal compiler diagnostics";
- gate_feature!(self, rustc_attrs, attr.span, msg);
- } else if !is_macro {
- // Only run the custom attribute lint during regular feature gate
- // checking. Macro gating runs before the plugin attributes are
- // registered, so we skip this in that case.
- let msg = format!("The attribute `{}` is currently unknown to the compiler and \
- may have meaning added to it in the future", attr.path);
- gate_feature!(self, custom_attribute, attr.span, &msg);
- }
+ if !is_macro && !attr::is_known(attr) {
+ // Only run the custom attribute lint during regular feature gate
+ // checking. Macro gating runs before the plugin attributes are
+ // registered, so we skip this in that case.
+ let msg = format!("The attribute `{}` is currently unknown to the compiler and \
+ may have meaning added to it in the future", attr.path);
+ gate_feature!(self, custom_attribute, attr.span, &msg);
}
}
}
"labels on blocks are unstable");
}
}
- ast::ExprKind::Closure(_, ast::IsAsync::Async { .. }, ..) => {
- gate_feature_post!(&self, async_await, e.span, "async closures are unstable");
- }
ast::ExprKind::Async(..) => {
gate_feature_post!(&self, async_await, e.span, "async blocks are unstable");
}
features
}
+fn for_each_in_lock<T>(vec: &Lock<Vec<T>>, f: impl Fn(&T)) {
+ vec.borrow().iter().for_each(f);
+}
+
pub fn check_crate(krate: &ast::Crate,
sess: &ParseSess,
features: &Features,
plugin_attributes,
};
- sess
- .param_attr_spans
- .borrow()
- .iter()
- .for_each(|span| gate_feature!(
- &ctx,
- param_attrs,
- *span,
- "attributes on function parameters are unstable"
- ));
-
- sess
- .let_chains_spans
- .borrow()
- .iter()
- .for_each(|span| gate_feature!(
- &ctx,
- let_chains,
- *span,
- "`let` expressions in this position are experimental"
- ));
+ for_each_in_lock(&sess.param_attr_spans, |span| gate_feature!(
+ &ctx,
+ param_attrs,
+ *span,
+ "attributes on function parameters are unstable"
+ ));
+
+ for_each_in_lock(&sess.let_chains_spans, |span| gate_feature!(
+ &ctx,
+ let_chains,
+ *span,
+ "`let` expressions in this position are experimental"
+ ));
+
+ for_each_in_lock(&sess.async_closure_spans, |span| gate_feature!(
+ &ctx,
+ async_closure,
+ *span,
+ "async closures are unstable"
+ ));
let visitor = &mut PostExpansionVisitor {
context: &ctx,