Auto merge of #28246 - huonw:lang-tracking-issues, r=alexcrichton
This is similar to the libs version, which allow an `issue` field in the `#[unstable]` attribute. cc #28244
This commit is contained in:
commit
d2a5b117c1
12 changed files with 139 additions and 104 deletions
|
@ -47,20 +47,24 @@ with open(feature_gate_source, 'r') as f:
|
||||||
is_feature_line = True
|
is_feature_line = True
|
||||||
|
|
||||||
if is_feature_line:
|
if is_feature_line:
|
||||||
line = line.replace("(", "").replace("),", "").replace(")", "")
|
# turn ` ("foo", "1.0.0", Some(10), Active)` into
|
||||||
|
# `"foo", "1.0.0", Some(10), Active`
|
||||||
|
line = line.strip(' ,()')
|
||||||
parts = line.split(",")
|
parts = line.split(",")
|
||||||
if len(parts) != 3:
|
if len(parts) != 4:
|
||||||
print("error: unexpected number of components in line: " + original_line)
|
print("error: unexpected number of components in line: " + original_line)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
feature_name = parts[0].strip().replace('"', "")
|
feature_name = parts[0].strip().replace('"', "")
|
||||||
since = parts[1].strip().replace('"', "")
|
since = parts[1].strip().replace('"', "")
|
||||||
status = parts[2].strip()
|
issue = parts[2].strip()
|
||||||
|
status = parts[3].strip()
|
||||||
assert len(feature_name) > 0
|
assert len(feature_name) > 0
|
||||||
assert len(since) > 0
|
assert len(since) > 0
|
||||||
|
assert len(issue) > 0
|
||||||
assert len(status) > 0
|
assert len(status) > 0
|
||||||
|
|
||||||
language_feature_names += [feature_name]
|
language_feature_names += [feature_name]
|
||||||
language_features += [(feature_name, since, status)]
|
language_features += [(feature_name, since, issue, status)]
|
||||||
|
|
||||||
assert len(language_features) > 0
|
assert len(language_features) > 0
|
||||||
|
|
||||||
|
@ -158,7 +162,7 @@ for f in language_features:
|
||||||
status = "unstable"
|
status = "unstable"
|
||||||
stable_since = None
|
stable_since = None
|
||||||
|
|
||||||
if f[2] == "Accepted":
|
if f[3] == "Accepted":
|
||||||
status = "stable"
|
status = "stable"
|
||||||
if status == "stable":
|
if status == "stable":
|
||||||
stable_since = f[1]
|
stable_since = f[1]
|
||||||
|
|
|
@ -18,7 +18,7 @@ use util::nodemap::NodeMap;
|
||||||
|
|
||||||
use syntax::{ast};
|
use syntax::{ast};
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use syntax::feature_gate::emit_feature_err;
|
use syntax::feature_gate::{GateIssue, emit_feature_err};
|
||||||
use rustc_front::visit::Visitor;
|
use rustc_front::visit::Visitor;
|
||||||
use rustc_front::visit;
|
use rustc_front::visit;
|
||||||
use rustc_front::hir;
|
use rustc_front::hir;
|
||||||
|
@ -143,7 +143,7 @@ impl<'a, 'ast: 'a> CheckItemRecursionVisitor<'a, 'ast> {
|
||||||
if !self.sess.features.borrow().static_recursion {
|
if !self.sess.features.borrow().static_recursion {
|
||||||
emit_feature_err(&self.sess.parse_sess.span_diagnostic,
|
emit_feature_err(&self.sess.parse_sess.span_diagnostic,
|
||||||
"static_recursion",
|
"static_recursion",
|
||||||
*self.root_span, "recursive static");
|
*self.root_span, GateIssue::Language, "recursive static");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
span_err!(self.sess, *self.root_span, E0265, "recursive constant");
|
span_err!(self.sess, *self.root_span, E0265, "recursive constant");
|
||||||
|
|
|
@ -22,7 +22,7 @@ use syntax::parse::token::InternedString;
|
||||||
use syntax::codemap::{Span, DUMMY_SP};
|
use syntax::codemap::{Span, DUMMY_SP};
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::ast::NodeId;
|
use syntax::ast::NodeId;
|
||||||
use syntax::feature_gate::emit_feature_err;
|
use syntax::feature_gate::{GateIssue, emit_feature_err};
|
||||||
use util::nodemap::{DefIdMap, FnvHashSet, FnvHashMap};
|
use util::nodemap::{DefIdMap, FnvHashSet, FnvHashMap};
|
||||||
|
|
||||||
use rustc_front::hir;
|
use rustc_front::hir;
|
||||||
|
@ -294,18 +294,14 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
|
||||||
self.used_features.insert(feature.clone(), attr::Unstable);
|
self.used_features.insert(feature.clone(), attr::Unstable);
|
||||||
|
|
||||||
if !self.active_features.contains(feature) {
|
if !self.active_features.contains(feature) {
|
||||||
let mut msg = match *reason {
|
let msg = match *reason {
|
||||||
Some(ref r) => format!("use of unstable library feature '{}': {}",
|
Some(ref r) => format!("use of unstable library feature '{}': {}",
|
||||||
&feature, &r),
|
&feature, &r),
|
||||||
None => format!("use of unstable library feature '{}'", &feature)
|
None => format!("use of unstable library feature '{}'", &feature)
|
||||||
};
|
};
|
||||||
if let Some(n) = issue {
|
|
||||||
use std::fmt::Write;
|
|
||||||
write!(&mut msg, " (see issue #{})", n).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
emit_feature_err(&self.tcx.sess.parse_sess.span_diagnostic,
|
emit_feature_err(&self.tcx.sess.parse_sess.span_diagnostic,
|
||||||
&feature, span, &msg);
|
&feature, span, GateIssue::Library(issue), &msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(&Stability { level, ref feature, .. }) => {
|
Some(&Stability { level, ref feature, .. }) => {
|
||||||
|
|
|
@ -70,7 +70,7 @@ use util::nodemap::FnvHashSet;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
use syntax::{abi, ast};
|
use syntax::{abi, ast};
|
||||||
use syntax::codemap::{Span, Pos};
|
use syntax::codemap::{Span, Pos};
|
||||||
use syntax::feature_gate::emit_feature_err;
|
use syntax::feature_gate::{GateIssue, emit_feature_err};
|
||||||
use syntax::parse::token;
|
use syntax::parse::token;
|
||||||
|
|
||||||
use rustc_front::print::pprust;
|
use rustc_front::print::pprust;
|
||||||
|
@ -797,7 +797,7 @@ fn create_substs_for_ast_trait_ref<'a,'tcx>(this: &AstConv<'tcx>,
|
||||||
// only with `Fn()` etc.
|
// only with `Fn()` etc.
|
||||||
if !this.tcx().sess.features.borrow().unboxed_closures && trait_def.paren_sugar {
|
if !this.tcx().sess.features.borrow().unboxed_closures && trait_def.paren_sugar {
|
||||||
emit_feature_err(&this.tcx().sess.parse_sess.span_diagnostic,
|
emit_feature_err(&this.tcx().sess.parse_sess.span_diagnostic,
|
||||||
"unboxed_closures", span,
|
"unboxed_closures", span, GateIssue::Language,
|
||||||
"\
|
"\
|
||||||
the precise format of `Fn`-family traits' type parameters is \
|
the precise format of `Fn`-family traits' type parameters is \
|
||||||
subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead");
|
subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead");
|
||||||
|
@ -810,7 +810,7 @@ fn create_substs_for_ast_trait_ref<'a,'tcx>(this: &AstConv<'tcx>,
|
||||||
// only with `Fn()` etc.
|
// only with `Fn()` etc.
|
||||||
if !this.tcx().sess.features.borrow().unboxed_closures && !trait_def.paren_sugar {
|
if !this.tcx().sess.features.borrow().unboxed_closures && !trait_def.paren_sugar {
|
||||||
emit_feature_err(&this.tcx().sess.parse_sess.span_diagnostic,
|
emit_feature_err(&this.tcx().sess.parse_sess.span_diagnostic,
|
||||||
"unboxed_closures", span,
|
"unboxed_closures", span, GateIssue::Language,
|
||||||
"\
|
"\
|
||||||
parenthetical notation is only stable when used with `Fn`-family traits");
|
parenthetical notation is only stable when used with `Fn`-family traits");
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,9 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||||
-> Box<base::MacResult+'cx> {
|
-> Box<base::MacResult+'cx> {
|
||||||
if !cx.ecfg.enable_asm() {
|
if !cx.ecfg.enable_asm() {
|
||||||
feature_gate::emit_feature_err(
|
feature_gate::emit_feature_err(
|
||||||
&cx.parse_sess.span_diagnostic, "asm", sp, feature_gate::EXPLAIN_ASM);
|
&cx.parse_sess.span_diagnostic, "asm", sp,
|
||||||
|
feature_gate::GateIssue::Language,
|
||||||
|
feature_gate::EXPLAIN_ASM);
|
||||||
return DummyResult::expr(sp);
|
return DummyResult::expr(sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ pub fn expand_syntax_ext<'cx>(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]
|
||||||
feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic,
|
feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic,
|
||||||
"concat_idents",
|
"concat_idents",
|
||||||
sp,
|
sp,
|
||||||
|
feature_gate::GateIssue::Language,
|
||||||
feature_gate::EXPLAIN_CONCAT_IDENTS);
|
feature_gate::EXPLAIN_CONCAT_IDENTS);
|
||||||
return base::DummyResult::expr(sp);
|
return base::DummyResult::expr(sp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,6 +105,7 @@ fn expand_derive(cx: &mut ExtCtxt,
|
||||||
feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic,
|
feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic,
|
||||||
"custom_derive",
|
"custom_derive",
|
||||||
titem.span,
|
titem.span,
|
||||||
|
feature_gate::GateIssue::Language,
|
||||||
feature_gate::EXPLAIN_CUSTOM_DERIVE);
|
feature_gate::EXPLAIN_CUSTOM_DERIVE);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -778,6 +778,7 @@ pub fn expand_item_mac(it: P<ast::Item>,
|
||||||
&fld.cx.parse_sess.span_diagnostic,
|
&fld.cx.parse_sess.span_diagnostic,
|
||||||
"allow_internal_unstable",
|
"allow_internal_unstable",
|
||||||
it.span,
|
it.span,
|
||||||
|
feature_gate::GateIssue::Language,
|
||||||
feature_gate::EXPLAIN_ALLOW_INTERNAL_UNSTABLE)
|
feature_gate::EXPLAIN_ALLOW_INTERNAL_UNSTABLE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1469,7 +1470,8 @@ pub fn expand_type(t: P<ast::Ty>, fld: &mut MacroExpander) -> P<ast::Ty> {
|
||||||
&fld.cx.parse_sess.span_diagnostic,
|
&fld.cx.parse_sess.span_diagnostic,
|
||||||
"type_macros",
|
"type_macros",
|
||||||
t.span,
|
t.span,
|
||||||
"type macros are experimental (see issue: #27336)");
|
feature_gate::GateIssue::Language,
|
||||||
|
"type macros are experimental");
|
||||||
|
|
||||||
DummyResult::raw_ty(t.span)
|
DummyResult::raw_ty(t.span)
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut base::ExtCtxt,
|
||||||
feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic,
|
feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic,
|
||||||
"log_syntax",
|
"log_syntax",
|
||||||
sp,
|
sp,
|
||||||
|
feature_gate::GateIssue::Language,
|
||||||
feature_gate::EXPLAIN_LOG_SYNTAX);
|
feature_gate::EXPLAIN_LOG_SYNTAX);
|
||||||
return base::DummyResult::any(sp);
|
return base::DummyResult::any(sp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ pub fn expand_trace_macros(cx: &mut ExtCtxt,
|
||||||
feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic,
|
feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic,
|
||||||
"trace_macros",
|
"trace_macros",
|
||||||
sp,
|
sp,
|
||||||
|
feature_gate::GateIssue::Language,
|
||||||
feature_gate::EXPLAIN_TRACE_MACROS);
|
feature_gate::EXPLAIN_TRACE_MACROS);
|
||||||
return base::DummyResult::any(sp);
|
return base::DummyResult::any(sp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,147 +47,147 @@ use std::cmp;
|
||||||
// stable (active).
|
// stable (active).
|
||||||
// NB: The featureck.py script parses this information directly out of the source
|
// NB: The featureck.py script parses this information directly out of the source
|
||||||
// so take care when modifying it.
|
// so take care when modifying it.
|
||||||
const KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[
|
const KNOWN_FEATURES: &'static [(&'static str, &'static str, Option<u32>, Status)] = &[
|
||||||
("globs", "1.0.0", Accepted),
|
("globs", "1.0.0", None, Accepted),
|
||||||
("macro_rules", "1.0.0", Accepted),
|
("macro_rules", "1.0.0", None, Accepted),
|
||||||
("struct_variant", "1.0.0", Accepted),
|
("struct_variant", "1.0.0", None, Accepted),
|
||||||
("asm", "1.0.0", Active),
|
("asm", "1.0.0", None, Active),
|
||||||
("managed_boxes", "1.0.0", Removed),
|
("managed_boxes", "1.0.0", None, Removed),
|
||||||
("non_ascii_idents", "1.0.0", Active),
|
("non_ascii_idents", "1.0.0", None, Active),
|
||||||
("thread_local", "1.0.0", Active),
|
("thread_local", "1.0.0", None, Active),
|
||||||
("link_args", "1.0.0", Active),
|
("link_args", "1.0.0", None, Active),
|
||||||
("plugin_registrar", "1.0.0", Active),
|
("plugin_registrar", "1.0.0", None, Active),
|
||||||
("log_syntax", "1.0.0", Active),
|
("log_syntax", "1.0.0", None, Active),
|
||||||
("trace_macros", "1.0.0", Active),
|
("trace_macros", "1.0.0", None, Active),
|
||||||
("concat_idents", "1.0.0", Active),
|
("concat_idents", "1.0.0", None, Active),
|
||||||
("intrinsics", "1.0.0", Active),
|
("intrinsics", "1.0.0", None, Active),
|
||||||
("lang_items", "1.0.0", Active),
|
("lang_items", "1.0.0", None, Active),
|
||||||
|
|
||||||
("simd", "1.0.0", Active),
|
("simd", "1.0.0", Some(27731), Active),
|
||||||
("default_type_params", "1.0.0", Accepted),
|
("default_type_params", "1.0.0", None, Accepted),
|
||||||
("quote", "1.0.0", Active),
|
("quote", "1.0.0", None, Active),
|
||||||
("link_llvm_intrinsics", "1.0.0", Active),
|
("link_llvm_intrinsics", "1.0.0", None, Active),
|
||||||
("linkage", "1.0.0", Active),
|
("linkage", "1.0.0", None, Active),
|
||||||
("struct_inherit", "1.0.0", Removed),
|
("struct_inherit", "1.0.0", None, Removed),
|
||||||
|
|
||||||
("quad_precision_float", "1.0.0", Removed),
|
("quad_precision_float", "1.0.0", None, Removed),
|
||||||
|
|
||||||
("rustc_diagnostic_macros", "1.0.0", Active),
|
("rustc_diagnostic_macros", "1.0.0", None, Active),
|
||||||
("unboxed_closures", "1.0.0", Active),
|
("unboxed_closures", "1.0.0", None, Active),
|
||||||
("reflect", "1.0.0", Active),
|
("reflect", "1.0.0", None, Active),
|
||||||
("import_shadowing", "1.0.0", Removed),
|
("import_shadowing", "1.0.0", None, Removed),
|
||||||
("advanced_slice_patterns", "1.0.0", Active),
|
("advanced_slice_patterns", "1.0.0", None, Active),
|
||||||
("tuple_indexing", "1.0.0", Accepted),
|
("tuple_indexing", "1.0.0", None, Accepted),
|
||||||
("associated_types", "1.0.0", Accepted),
|
("associated_types", "1.0.0", None, Accepted),
|
||||||
("visible_private_types", "1.0.0", Active),
|
("visible_private_types", "1.0.0", None, Active),
|
||||||
("slicing_syntax", "1.0.0", Accepted),
|
("slicing_syntax", "1.0.0", None, Accepted),
|
||||||
("box_syntax", "1.0.0", Active),
|
("box_syntax", "1.0.0", None, Active),
|
||||||
("placement_in_syntax", "1.0.0", Active),
|
("placement_in_syntax", "1.0.0", None, Active),
|
||||||
("pushpop_unsafe", "1.2.0", Active),
|
("pushpop_unsafe", "1.2.0", None, Active),
|
||||||
("on_unimplemented", "1.0.0", Active),
|
("on_unimplemented", "1.0.0", None, Active),
|
||||||
("simd_ffi", "1.0.0", Active),
|
("simd_ffi", "1.0.0", None, Active),
|
||||||
("allocator", "1.0.0", Active),
|
("allocator", "1.0.0", None, Active),
|
||||||
("needs_allocator", "1.4.0", Active),
|
("needs_allocator", "1.4.0", None, Active),
|
||||||
("linked_from", "1.3.0", Active),
|
("linked_from", "1.3.0", None, Active),
|
||||||
|
|
||||||
("if_let", "1.0.0", Accepted),
|
("if_let", "1.0.0", None, Accepted),
|
||||||
("while_let", "1.0.0", Accepted),
|
("while_let", "1.0.0", None, Accepted),
|
||||||
|
|
||||||
("plugin", "1.0.0", Active),
|
("plugin", "1.0.0", None, Active),
|
||||||
("start", "1.0.0", Active),
|
("start", "1.0.0", None, Active),
|
||||||
("main", "1.0.0", Active),
|
("main", "1.0.0", None, Active),
|
||||||
|
|
||||||
("fundamental", "1.0.0", Active),
|
("fundamental", "1.0.0", None, Active),
|
||||||
|
|
||||||
// A temporary feature gate used to enable parser extensions needed
|
// A temporary feature gate used to enable parser extensions needed
|
||||||
// to bootstrap fix for #5723.
|
// to bootstrap fix for #5723.
|
||||||
("issue_5723_bootstrap", "1.0.0", Accepted),
|
("issue_5723_bootstrap", "1.0.0", None, Accepted),
|
||||||
|
|
||||||
// A way to temporarily opt out of opt in copy. This will *never* be accepted.
|
// A way to temporarily opt out of opt in copy. This will *never* be accepted.
|
||||||
("opt_out_copy", "1.0.0", Removed),
|
("opt_out_copy", "1.0.0", None, Removed),
|
||||||
|
|
||||||
// OIBIT specific features
|
// OIBIT specific features
|
||||||
("optin_builtin_traits", "1.0.0", Active),
|
("optin_builtin_traits", "1.0.0", None, Active),
|
||||||
|
|
||||||
// macro reexport needs more discussion and stabilization
|
// macro reexport needs more discussion and stabilization
|
||||||
("macro_reexport", "1.0.0", Active),
|
("macro_reexport", "1.0.0", None, Active),
|
||||||
|
|
||||||
// These are used to test this portion of the compiler, they don't actually
|
// These are used to test this portion of the compiler, they don't actually
|
||||||
// mean anything
|
// mean anything
|
||||||
("test_accepted_feature", "1.0.0", Accepted),
|
("test_accepted_feature", "1.0.0", None, Accepted),
|
||||||
("test_removed_feature", "1.0.0", Removed),
|
("test_removed_feature", "1.0.0", None, Removed),
|
||||||
|
|
||||||
// Allows use of #[staged_api]
|
// Allows use of #[staged_api]
|
||||||
("staged_api", "1.0.0", Active),
|
("staged_api", "1.0.0", None, Active),
|
||||||
|
|
||||||
// Allows using items which are missing stability attributes
|
// Allows using items which are missing stability attributes
|
||||||
("unmarked_api", "1.0.0", Active),
|
("unmarked_api", "1.0.0", None, Active),
|
||||||
|
|
||||||
// Allows using #![no_std]
|
// Allows using #![no_std]
|
||||||
("no_std", "1.0.0", Active),
|
("no_std", "1.0.0", None, Active),
|
||||||
|
|
||||||
// Allows using #![no_core]
|
// Allows using #![no_core]
|
||||||
("no_core", "1.3.0", Active),
|
("no_core", "1.3.0", None, Active),
|
||||||
|
|
||||||
// Allows using `box` in patterns; RFC 469
|
// Allows using `box` in patterns; RFC 469
|
||||||
("box_patterns", "1.0.0", Active),
|
("box_patterns", "1.0.0", None, Active),
|
||||||
|
|
||||||
// Allows using the unsafe_no_drop_flag attribute (unlikely to
|
// Allows using the unsafe_no_drop_flag attribute (unlikely to
|
||||||
// switch to Accepted; see RFC 320)
|
// switch to Accepted; see RFC 320)
|
||||||
("unsafe_no_drop_flag", "1.0.0", Active),
|
("unsafe_no_drop_flag", "1.0.0", None, Active),
|
||||||
|
|
||||||
// Allows the use of custom attributes; RFC 572
|
// Allows the use of custom attributes; RFC 572
|
||||||
("custom_attribute", "1.0.0", Active),
|
("custom_attribute", "1.0.0", None, Active),
|
||||||
|
|
||||||
// Allows the use of #[derive(Anything)] as sugar for
|
// Allows the use of #[derive(Anything)] as sugar for
|
||||||
// #[derive_Anything].
|
// #[derive_Anything].
|
||||||
("custom_derive", "1.0.0", Active),
|
("custom_derive", "1.0.0", None, Active),
|
||||||
|
|
||||||
// Allows the use of rustc_* attributes; RFC 572
|
// Allows the use of rustc_* attributes; RFC 572
|
||||||
("rustc_attrs", "1.0.0", Active),
|
("rustc_attrs", "1.0.0", None, Active),
|
||||||
|
|
||||||
// Allows the use of #[allow_internal_unstable]. This is an
|
// Allows the use of #[allow_internal_unstable]. This is an
|
||||||
// attribute on macro_rules! and can't use the attribute handling
|
// attribute on macro_rules! and can't use the attribute handling
|
||||||
// below (it has to be checked before expansion possibly makes
|
// below (it has to be checked before expansion possibly makes
|
||||||
// macros disappear).
|
// macros disappear).
|
||||||
("allow_internal_unstable", "1.0.0", Active),
|
("allow_internal_unstable", "1.0.0", None, Active),
|
||||||
|
|
||||||
// #23121. Array patterns have some hazards yet.
|
// #23121. Array patterns have some hazards yet.
|
||||||
("slice_patterns", "1.0.0", Active),
|
("slice_patterns", "1.0.0", None, Active),
|
||||||
|
|
||||||
// Allows use of unary negate on unsigned integers, e.g. -e for e: u8
|
// Allows use of unary negate on unsigned integers, e.g. -e for e: u8
|
||||||
("negate_unsigned", "1.0.0", Active),
|
("negate_unsigned", "1.0.0", None, Active),
|
||||||
|
|
||||||
// Allows the definition of associated constants in `trait` or `impl`
|
// Allows the definition of associated constants in `trait` or `impl`
|
||||||
// blocks.
|
// blocks.
|
||||||
("associated_consts", "1.0.0", Active),
|
("associated_consts", "1.0.0", None, Active),
|
||||||
|
|
||||||
// Allows the definition of `const fn` functions.
|
// Allows the definition of `const fn` functions.
|
||||||
("const_fn", "1.2.0", Active),
|
("const_fn", "1.2.0", None, Active),
|
||||||
|
|
||||||
// Allows using #[prelude_import] on glob `use` items.
|
// Allows using #[prelude_import] on glob `use` items.
|
||||||
("prelude_import", "1.2.0", Active),
|
("prelude_import", "1.2.0", None, Active),
|
||||||
|
|
||||||
// Allows the definition recursive static items.
|
// Allows the definition recursive static items.
|
||||||
("static_recursion", "1.3.0", Active),
|
("static_recursion", "1.3.0", None, Active),
|
||||||
|
|
||||||
// Allows default type parameters to influence type inference.
|
// Allows default type parameters to influence type inference.
|
||||||
("default_type_parameter_fallback", "1.3.0", Active),
|
("default_type_parameter_fallback", "1.3.0", None, Active),
|
||||||
|
|
||||||
// Allows associated type defaults
|
// Allows associated type defaults
|
||||||
("associated_type_defaults", "1.2.0", Active),
|
("associated_type_defaults", "1.2.0", None, Active),
|
||||||
// Allows macros to appear in the type position.
|
// Allows macros to appear in the type position.
|
||||||
|
|
||||||
("type_macros", "1.3.0", Active),
|
("type_macros", "1.3.0", Some(27336), Active),
|
||||||
|
|
||||||
// allow `repr(simd)`, and importing the various simd intrinsics
|
// allow `repr(simd)`, and importing the various simd intrinsics
|
||||||
("repr_simd", "1.4.0", Active),
|
("repr_simd", "1.4.0", Some(27731), Active),
|
||||||
|
|
||||||
// Allows cfg(target_feature = "...").
|
// Allows cfg(target_feature = "...").
|
||||||
("cfg_target_feature", "1.4.0", Active),
|
("cfg_target_feature", "1.4.0", None, Active),
|
||||||
|
|
||||||
// allow `extern "platform-intrinsic" { ... }`
|
// allow `extern "platform-intrinsic" { ... }`
|
||||||
("platform_intrinsics", "1.4.0", Active),
|
("platform_intrinsics", "1.4.0", Some(27731), Active),
|
||||||
];
|
];
|
||||||
// (changing above list without updating src/doc/reference.md makes @cmr sad)
|
// (changing above list without updating src/doc/reference.md makes @cmr sad)
|
||||||
|
|
||||||
|
@ -393,7 +393,7 @@ impl GatedCfg {
|
||||||
let (cfg, feature, has_feature) = GATED_CFGS[self.index];
|
let (cfg, feature, has_feature) = GATED_CFGS[self.index];
|
||||||
if !has_feature(features) {
|
if !has_feature(features) {
|
||||||
let explain = format!("`cfg({})` is experimental and subject to change", cfg);
|
let explain = format!("`cfg({})` is experimental and subject to change", cfg);
|
||||||
emit_feature_err(diagnostic, feature, self.span, &explain);
|
emit_feature_err(diagnostic, feature, self.span, GateIssue::Language, &explain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -495,21 +495,21 @@ pub fn check_for_box_syntax(f: Option<&Features>, diag: &SpanHandler, span: Span
|
||||||
if let Some(&Features { allow_box: true, .. }) = f {
|
if let Some(&Features { allow_box: true, .. }) = f {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
emit_feature_err(diag, "box_syntax", span, EXPLAIN_BOX_SYNTAX);
|
emit_feature_err(diag, "box_syntax", span, GateIssue::Language, EXPLAIN_BOX_SYNTAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_for_placement_in(f: Option<&Features>, diag: &SpanHandler, span: Span) {
|
pub fn check_for_placement_in(f: Option<&Features>, diag: &SpanHandler, span: Span) {
|
||||||
if let Some(&Features { allow_placement_in: true, .. }) = f {
|
if let Some(&Features { allow_placement_in: true, .. }) = f {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
emit_feature_err(diag, "placement_in_syntax", span, EXPLAIN_PLACEMENT_IN);
|
emit_feature_err(diag, "placement_in_syntax", span, GateIssue::Language, EXPLAIN_PLACEMENT_IN);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_for_pushpop_syntax(f: Option<&Features>, diag: &SpanHandler, span: Span) {
|
pub fn check_for_pushpop_syntax(f: Option<&Features>, diag: &SpanHandler, span: Span) {
|
||||||
if let Some(&Features { allow_pushpop_unsafe: true, .. }) = f {
|
if let Some(&Features { allow_pushpop_unsafe: true, .. }) = f {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
emit_feature_err(diag, "pushpop_unsafe", span, EXPLAIN_PUSHPOP_UNSAFE);
|
emit_feature_err(diag, "pushpop_unsafe", span, GateIssue::Language, EXPLAIN_PUSHPOP_UNSAFE);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Context<'a> {
|
struct Context<'a> {
|
||||||
|
@ -529,7 +529,7 @@ impl<'a> Context<'a> {
|
||||||
let has_feature = self.has_feature(feature);
|
let has_feature = self.has_feature(feature);
|
||||||
debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", feature, span, has_feature);
|
debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", feature, span, has_feature);
|
||||||
if !has_feature {
|
if !has_feature {
|
||||||
emit_feature_err(self.span_handler, feature, span, explain);
|
emit_feature_err(self.span_handler, feature, span, GateIssue::Language, explain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn has_feature(&self, feature: &str) -> bool {
|
fn has_feature(&self, feature: &str) -> bool {
|
||||||
|
@ -583,8 +583,35 @@ impl<'a> Context<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn emit_feature_err(diag: &SpanHandler, feature: &str, span: Span, explain: &str) {
|
fn find_lang_feature_issue(feature: &str) -> Option<u32> {
|
||||||
diag.span_err(span, explain);
|
let info = KNOWN_FEATURES.iter()
|
||||||
|
.find(|t| t.0 == feature)
|
||||||
|
.unwrap();
|
||||||
|
let issue = info.2;
|
||||||
|
if let Active = info.3 {
|
||||||
|
// FIXME (#28244): enforce that active features have issue numbers
|
||||||
|
// assert!(issue.is_some())
|
||||||
|
}
|
||||||
|
issue
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum GateIssue {
|
||||||
|
Language,
|
||||||
|
Library(Option<u32>)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn emit_feature_err(diag: &SpanHandler, feature: &str, span: Span, issue: GateIssue,
|
||||||
|
explain: &str) {
|
||||||
|
let issue = match issue {
|
||||||
|
GateIssue::Language => find_lang_feature_issue(feature),
|
||||||
|
GateIssue::Library(lib) => lib,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(n) = issue {
|
||||||
|
diag.span_err(span, &format!("{} (see issue #{})", explain, n));
|
||||||
|
} else {
|
||||||
|
diag.span_err(span, explain);
|
||||||
|
}
|
||||||
|
|
||||||
// #23973: do not suggest `#![feature(...)]` if we are in beta/stable
|
// #23973: do not suggest `#![feature(...)]` if we are in beta/stable
|
||||||
if option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some() { return; }
|
if option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some() { return; }
|
||||||
|
@ -955,14 +982,14 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
match KNOWN_FEATURES.iter()
|
match KNOWN_FEATURES.iter()
|
||||||
.find(|& &(n, _, _)| name == n) {
|
.find(|& &(n, _, _, _)| name == n) {
|
||||||
Some(&(name, _, Active)) => {
|
Some(&(name, _, _, Active)) => {
|
||||||
cx.enable_feature(name);
|
cx.enable_feature(name);
|
||||||
}
|
}
|
||||||
Some(&(_, _, Removed)) => {
|
Some(&(_, _, _, Removed)) => {
|
||||||
span_handler.span_err(mi.span, "feature has been removed");
|
span_handler.span_err(mi.span, "feature has been removed");
|
||||||
}
|
}
|
||||||
Some(&(_, _, Accepted)) => {
|
Some(&(_, _, _, Accepted)) => {
|
||||||
accepted_features.push(mi.span);
|
accepted_features.push(mi.span);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
|
|
@ -14,7 +14,7 @@ macro_rules! Id {
|
||||||
|
|
||||||
struct Foo<T> {
|
struct Foo<T> {
|
||||||
x: Id!(T)
|
x: Id!(T)
|
||||||
//~^ ERROR: type macros are experimental (see issue: #27336)
|
//~^ ERROR: type macros are experimental (see issue #27336)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
Loading…
Add table
Reference in a new issue