mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Rollup merge of #154527 - fmease:more-soft-gates, r=nnethercote
Emit pre-expansion feature gate warnings for negative impls and specialization Follow up to rust-lang/rust#154475; part of rust-lang/rust#154045. This shouldn't need any extra input from T-compiler or T-lang since it's legitimized by [MCP 535](https://github.com/rust-lang/compiler-team/issues/535). However, I have a feeling that negative impls & specialization behind "`#[cfg(feature = "nightly")]`" are more prevalent in the ecosystem compared to e.g., auto traits & box patterns, so these new warnings will probably hit a bunch of users. In any case, it's only a warning for now not an error so e.g., running crater "in deny mode" or nominating for a T-lang meeting discussion would be disproportionate (esp. since T-lang [has confirmed in the past](https://github.com/rust-lang/rust/pull/116393#issuecomment-1745571299) that this is a T-compiler matter).
This commit is contained in:
@@ -14,31 +14,22 @@
|
||||
|
||||
/// The common case.
|
||||
macro_rules! gate {
|
||||
($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{
|
||||
($visitor:expr, $feature:ident, $span:expr, $explain:expr $(, $help:expr)?) => {{
|
||||
if !$visitor.features.$feature() && !$span.allows_unstable(sym::$feature) {
|
||||
feature_err(&$visitor.sess, sym::$feature, $span, $explain).emit();
|
||||
}
|
||||
}};
|
||||
($visitor:expr, $feature:ident, $span:expr, $explain:expr, $help:expr) => {{
|
||||
if !$visitor.features.$feature() && !$span.allows_unstable(sym::$feature) {
|
||||
feature_err(&$visitor.sess, sym::$feature, $span, $explain).with_help($help).emit();
|
||||
feature_err($visitor.sess, sym::$feature, $span, $explain)
|
||||
$(.with_help($help))?
|
||||
.emit();
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
/// The unusual case, where the `has_feature` condition is non-standard.
|
||||
macro_rules! gate_alt {
|
||||
($visitor:expr, $has_feature:expr, $name:expr, $span:expr, $explain:expr) => {{
|
||||
($visitor:expr, $has_feature:expr, $name:expr, $span:expr, $explain:expr $(, $notes:expr)?) => {{
|
||||
if !$has_feature && !$span.allows_unstable($name) {
|
||||
feature_err(&$visitor.sess, $name, $span, $explain).emit();
|
||||
}
|
||||
}};
|
||||
($visitor:expr, $has_feature:expr, $name:expr, $span:expr, $explain:expr, $notes: expr) => {{
|
||||
if !$has_feature && !$span.allows_unstable($name) {
|
||||
let mut diag = feature_err(&$visitor.sess, $name, $span, $explain);
|
||||
for note in $notes {
|
||||
diag.note(*note);
|
||||
}
|
||||
#[allow(unused_mut)]
|
||||
let mut diag = feature_err($visitor.sess, $name, $span, $explain);
|
||||
$(for ¬e in $notes { diag.note(note); })?
|
||||
diag.emit();
|
||||
}
|
||||
}};
|
||||
@@ -51,21 +42,12 @@ macro_rules! gate_multi {
|
||||
let spans: Vec<_> =
|
||||
$spans.filter(|span| !span.allows_unstable(sym::$feature)).collect();
|
||||
if !spans.is_empty() {
|
||||
feature_err(&$visitor.sess, sym::$feature, spans, $explain).emit();
|
||||
feature_err($visitor.sess, sym::$feature, spans, $explain).emit();
|
||||
}
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
/// The legacy case.
|
||||
macro_rules! gate_legacy {
|
||||
($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{
|
||||
if !$visitor.features.$feature() && !$span.allows_unstable(sym::$feature) {
|
||||
feature_warn(&$visitor.sess, sym::$feature, $span, $explain);
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
pub fn check_attribute(attr: &ast::Attribute, sess: &Session, features: &Features) {
|
||||
PostExpansionVisitor { sess, features }.visit_attribute(attr)
|
||||
}
|
||||
@@ -77,6 +59,15 @@ struct PostExpansionVisitor<'a> {
|
||||
features: &'a Features,
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// POST-EXPANSION FEATURE GATES FOR UNSTABLE ATTRIBUTES ETC.
|
||||
// **LEGACY** POST-EXPANSION FEATURE GATES FOR UNSTABLE SYNTAX **LEGACY**
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// IMPORTANT: Don't add any new post-expansion feature gates for new unstable syntax!
|
||||
// It's a legacy mechanism for them.
|
||||
// Instead, register a pre-expansion feature gate using `gate_all` in fn `check_crate`.
|
||||
|
||||
impl<'a> PostExpansionVisitor<'a> {
|
||||
/// Feature gate `impl Trait` inside `type Alias = $type_expr;`.
|
||||
fn check_impl_trait(&self, ty: &ast::Ty, in_associated_ty: bool) {
|
||||
@@ -89,14 +80,14 @@ fn visit_ty(&mut self, ty: &ast::Ty) {
|
||||
if let ast::TyKind::ImplTrait(..) = ty.kind {
|
||||
if self.in_associated_ty {
|
||||
gate!(
|
||||
&self.vis,
|
||||
self.vis,
|
||||
impl_trait_in_assoc_type,
|
||||
ty.span,
|
||||
"`impl Trait` in associated types is unstable"
|
||||
);
|
||||
} else {
|
||||
gate!(
|
||||
&self.vis,
|
||||
self.vis,
|
||||
type_alias_impl_trait,
|
||||
ty.span,
|
||||
"`impl Trait` in type aliases is unstable"
|
||||
@@ -211,7 +202,7 @@ fn visit_item(&mut self, i: &'a ast::Item) {
|
||||
for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) {
|
||||
if item.has_name(sym::simd) {
|
||||
gate!(
|
||||
&self,
|
||||
self,
|
||||
repr_simd,
|
||||
attr.span,
|
||||
"SIMD types are experimental and possibly buggy"
|
||||
@@ -224,35 +215,30 @@ fn visit_item(&mut self, i: &'a ast::Item) {
|
||||
ast::ItemKind::Impl(ast::Impl { of_trait: Some(of_trait), .. }) => {
|
||||
if let ast::ImplPolarity::Negative(span) = of_trait.polarity {
|
||||
gate!(
|
||||
&self,
|
||||
self,
|
||||
negative_impls,
|
||||
span.to(of_trait.trait_ref.path.span),
|
||||
"negative trait bounds are not fully implemented; \
|
||||
use marker types for now"
|
||||
"negative impls are experimental",
|
||||
"use marker types for now"
|
||||
);
|
||||
}
|
||||
|
||||
if let ast::Defaultness::Default(_) = of_trait.defaultness {
|
||||
gate!(&self, specialization, i.span, "specialization is unstable");
|
||||
gate!(self, specialization, i.span, "specialization is experimental");
|
||||
}
|
||||
}
|
||||
|
||||
ast::ItemKind::Trait(box ast::Trait { is_auto: ast::IsAuto::Yes, .. }) => {
|
||||
gate!(
|
||||
&self,
|
||||
auto_traits,
|
||||
i.span,
|
||||
"auto traits are experimental and possibly buggy"
|
||||
);
|
||||
gate!(self, auto_traits, i.span, "auto traits are experimental and possibly buggy");
|
||||
}
|
||||
|
||||
ast::ItemKind::TraitAlias(..) => {
|
||||
gate!(&self, trait_alias, i.span, "trait aliases are experimental");
|
||||
gate!(self, trait_alias, i.span, "trait aliases are experimental");
|
||||
}
|
||||
|
||||
ast::ItemKind::MacroDef(_, ast::MacroDef { macro_rules: false, .. }) => {
|
||||
let msg = "`macro` is experimental";
|
||||
gate!(&self, decl_macro, i.span, msg);
|
||||
gate!(self, decl_macro, i.span, msg);
|
||||
}
|
||||
|
||||
ast::ItemKind::TyAlias(box ast::TyAlias { ty: Some(ty), .. }) => {
|
||||
@@ -264,7 +250,7 @@ fn visit_item(&mut self, i: &'a ast::Item) {
|
||||
}) => {
|
||||
// Make sure this is only allowed if the feature gate is enabled.
|
||||
// #![feature(min_generic_const_args)]
|
||||
gate!(&self, min_generic_const_args, i.span, "top-level `type const` are unstable");
|
||||
gate!(self, min_generic_const_args, i.span, "top-level `type const` are unstable");
|
||||
}
|
||||
|
||||
_ => {}
|
||||
@@ -280,7 +266,7 @@ fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
|
||||
let links_to_llvm = link_name.is_some_and(|val| val.as_str().starts_with("llvm."));
|
||||
if links_to_llvm {
|
||||
gate!(
|
||||
&self,
|
||||
self,
|
||||
link_llvm_intrinsics,
|
||||
i.span,
|
||||
"linking to LLVM intrinsics is experimental"
|
||||
@@ -288,7 +274,7 @@ fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
|
||||
}
|
||||
}
|
||||
ast::ForeignItemKind::TyAlias(..) => {
|
||||
gate!(&self, extern_types, i.span, "extern types are experimental");
|
||||
gate!(self, extern_types, i.span, "extern types are experimental");
|
||||
}
|
||||
ast::ForeignItemKind::MacCall(..) => {}
|
||||
}
|
||||
@@ -303,10 +289,10 @@ fn visit_ty(&mut self, ty: &'a ast::Ty) {
|
||||
self.check_late_bound_lifetime_defs(&fn_ptr_ty.generic_params);
|
||||
}
|
||||
ast::TyKind::Never => {
|
||||
gate!(&self, never_type, ty.span, "the `!` type is experimental");
|
||||
gate!(self, never_type, ty.span, "the `!` type is experimental");
|
||||
}
|
||||
ast::TyKind::Pat(..) => {
|
||||
gate!(&self, pattern_types, ty.span, "pattern types are unstable");
|
||||
gate!(self, pattern_types, ty.span, "pattern types are unstable");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@@ -339,7 +325,7 @@ fn visit_generic_args(&mut self, args: &'a ast::GenericArgs) {
|
||||
&& let ast::FnRetTy::Ty(ref ty) = generic_args.output
|
||||
&& matches!(ty.kind, ast::TyKind::Never)
|
||||
{
|
||||
gate!(&self, never_type, ty.span, "the `!` type is experimental");
|
||||
gate!(self, never_type, ty.span, "the `!` type is experimental");
|
||||
}
|
||||
visit::walk_generic_args(self, args);
|
||||
}
|
||||
@@ -348,7 +334,7 @@ fn visit_expr(&mut self, e: &'a ast::Expr) {
|
||||
match e.kind {
|
||||
ast::ExprKind::TryBlock(_, None) => {
|
||||
// `try { ... }` is old and is only gated post-expansion here.
|
||||
gate!(&self, try_blocks, e.span, "`try` expression is experimental");
|
||||
gate!(self, try_blocks, e.span, "`try` expression is experimental");
|
||||
}
|
||||
ast::ExprKind::TryBlock(_, Some(_)) => {
|
||||
// `try_blocks_heterogeneous` is new, and gated pre-expansion instead.
|
||||
@@ -359,10 +345,10 @@ fn visit_expr(&mut self, e: &'a ast::Expr) {
|
||||
..
|
||||
}) => match suffix {
|
||||
Some(sym::f16) => {
|
||||
gate!(&self, f16, e.span, "the type `f16` is unstable")
|
||||
gate!(self, f16, e.span, "the type `f16` is unstable")
|
||||
}
|
||||
Some(sym::f128) => {
|
||||
gate!(&self, f128, e.span, "the type `f128` is unstable")
|
||||
gate!(self, f128, e.span, "the type `f128` is unstable")
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
@@ -381,7 +367,7 @@ fn visit_pat(&mut self, pattern: &'a ast::Pat) {
|
||||
};
|
||||
if let PatKind::Range(Some(_), None, Spanned { .. }) = inner_pat.kind {
|
||||
gate!(
|
||||
&self,
|
||||
self,
|
||||
half_open_range_patterns_in_slices,
|
||||
pat.span,
|
||||
"`X..` patterns in slices are experimental"
|
||||
@@ -390,7 +376,7 @@ fn visit_pat(&mut self, pattern: &'a ast::Pat) {
|
||||
}
|
||||
}
|
||||
PatKind::Box(..) => {
|
||||
gate!(&self, box_patterns, pattern.span, "box pattern syntax is experimental");
|
||||
gate!(self, box_patterns, pattern.span, "box pattern syntax is experimental");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@@ -412,7 +398,7 @@ fn visit_fn(&mut self, fn_kind: FnKind<'a>, _: &AttrVec, span: Span, _: NodeId)
|
||||
}
|
||||
|
||||
if fn_kind.ctxt() != Some(FnCtxt::Foreign) && fn_kind.decl().c_variadic() {
|
||||
gate!(&self, c_variadic, span, "C-variadic functions are unstable");
|
||||
gate!(self, c_variadic, span, "C-variadic functions are unstable");
|
||||
}
|
||||
|
||||
visit::walk_fn(self, fn_kind)
|
||||
@@ -424,7 +410,7 @@ fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) {
|
||||
ast::AssocItemKind::Type(box ast::TyAlias { ty, .. }) => {
|
||||
if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) {
|
||||
gate!(
|
||||
&self,
|
||||
self,
|
||||
associated_type_defaults,
|
||||
i.span,
|
||||
"associated type defaults are unstable"
|
||||
@@ -441,18 +427,13 @@ fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) {
|
||||
}) => {
|
||||
// Make sure this is only allowed if the feature gate is enabled.
|
||||
// #![feature(min_generic_const_args)]
|
||||
gate!(
|
||||
&self,
|
||||
min_generic_const_args,
|
||||
i.span,
|
||||
"associated `type const` are unstable"
|
||||
);
|
||||
gate!(self, min_generic_const_args, i.span, "associated `type const` are unstable");
|
||||
// Make sure associated `type const` defaults in traits are only allowed
|
||||
// if the feature gate is enabled.
|
||||
// #![feature(associated_type_defaults)]
|
||||
if ctxt == AssocCtxt::Trait && rhs.is_some() {
|
||||
gate!(
|
||||
&self,
|
||||
self,
|
||||
associated_type_defaults,
|
||||
i.span,
|
||||
"associated type defaults are unstable"
|
||||
@@ -469,13 +450,15 @@ fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) {
|
||||
self.features.specialization() || (is_fn && self.features.min_specialization()),
|
||||
sym::specialization,
|
||||
i.span,
|
||||
"specialization is unstable"
|
||||
"specialization is experimental"
|
||||
);
|
||||
}
|
||||
visit::walk_assoc_item(self, i, ctxt)
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
||||
maybe_stage_features(sess, features, krate);
|
||||
check_incompatible_features(sess, features);
|
||||
@@ -484,166 +467,170 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
||||
|
||||
let mut visitor = PostExpansionVisitor { sess, features };
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// PRE-EXPANSION FEATURE GATES FOR UNSTABLE SYNTAX
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
let spans = sess.psess.gated_spans.spans.borrow();
|
||||
macro_rules! gate_all {
|
||||
($gate:ident, $msg:literal) => {
|
||||
if let Some(spans) = spans.get(&sym::$gate) {
|
||||
for span in spans {
|
||||
gate!(&visitor, $gate, *span, $msg);
|
||||
}
|
||||
}
|
||||
};
|
||||
($gate:ident, $msg:literal, $help:literal) => {
|
||||
if let Some(spans) = spans.get(&sym::$gate) {
|
||||
for span in spans {
|
||||
gate!(&visitor, $gate, *span, $msg, $help);
|
||||
}
|
||||
($feature:ident, $explain:literal $(, $help:literal)?) => {
|
||||
for &span in spans.get(&sym::$feature).into_iter().flatten() {
|
||||
gate!(visitor, $feature, span, $explain $(, $help)?);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// tidy-alphabetical-start
|
||||
gate_all!(async_for_loop, "`for await` loops are experimental");
|
||||
gate_all!(builtin_syntax, "`builtin #` syntax is unstable");
|
||||
gate_all!(const_block_items, "const block items are experimental");
|
||||
gate_all!(const_closures, "const closures are experimental");
|
||||
gate_all!(const_trait_impl, "const trait impls are experimental");
|
||||
gate_all!(contracts, "contracts are incomplete");
|
||||
gate_all!(contracts_internals, "contract internal machinery is for internal use only");
|
||||
gate_all!(coroutines, "coroutine syntax is experimental");
|
||||
gate_all!(default_field_values, "default values on fields are experimental");
|
||||
gate_all!(ergonomic_clones, "ergonomic clones are experimental");
|
||||
gate_all!(explicit_tail_calls, "`become` expression is experimental");
|
||||
gate_all!(final_associated_functions, "`final` on trait functions is experimental");
|
||||
gate_all!(fn_delegation, "functions delegation is not yet fully implemented");
|
||||
gate_all!(frontmatter, "frontmatters are experimental");
|
||||
gate_all!(gen_blocks, "gen blocks are experimental");
|
||||
gate_all!(generic_const_items, "generic const items are experimental");
|
||||
gate_all!(global_registration, "global registration is experimental");
|
||||
gate_all!(guard_patterns, "guard patterns are experimental", "consider using match arm guards");
|
||||
gate_all!(impl_restriction, "`impl` restrictions are experimental");
|
||||
gate_all!(min_generic_const_args, "unbraced const blocks as const args are experimental");
|
||||
gate_all!(more_qualified_paths, "usage of qualified paths in this context is experimental");
|
||||
gate_all!(mut_ref, "mutable by-reference bindings are experimental");
|
||||
gate_all!(pin_ergonomics, "pinned reference syntax is experimental");
|
||||
gate_all!(postfix_match, "postfix match is experimental");
|
||||
gate_all!(return_type_notation, "return type notation is experimental");
|
||||
gate_all!(super_let, "`super let` is experimental");
|
||||
gate_all!(try_blocks_heterogeneous, "`try bikeshed` expression is experimental");
|
||||
gate_all!(unsafe_binders, "unsafe binder types are experimental");
|
||||
gate_all!(unsafe_fields, "`unsafe` fields are experimental");
|
||||
gate_all!(where_clause_attrs, "attributes in `where` clause are unstable");
|
||||
gate_all!(yeet_expr, "`do yeet` expression is experimental");
|
||||
// tidy-alphabetical-end
|
||||
|
||||
gate_all!(
|
||||
async_trait_bounds,
|
||||
"`async` trait bounds are unstable",
|
||||
"use the desugared name of the async trait, such as `AsyncFn`"
|
||||
);
|
||||
gate_all!(async_for_loop, "`for await` loops are experimental");
|
||||
gate_all!(
|
||||
closure_lifetime_binder,
|
||||
"`for<...>` binders for closures are experimental",
|
||||
"consider removing `for<...>`"
|
||||
);
|
||||
gate_all!(more_qualified_paths, "usage of qualified paths in this context is experimental");
|
||||
// yield can be enabled either by `coroutines` or `gen_blocks`
|
||||
if let Some(spans) = spans.get(&sym::yield_expr) {
|
||||
for span in spans {
|
||||
if (!visitor.features.coroutines() && !span.allows_unstable(sym::coroutines))
|
||||
&& (!visitor.features.gen_blocks() && !span.allows_unstable(sym::gen_blocks))
|
||||
&& (!visitor.features.yield_expr() && !span.allows_unstable(sym::yield_expr))
|
||||
{
|
||||
// Emit yield_expr as the error, since that will be sufficient. You can think of it
|
||||
// as coroutines and gen_blocks imply yield_expr.
|
||||
feature_err(&visitor.sess, sym::yield_expr, *span, "yield syntax is experimental")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
gate_all!(gen_blocks, "gen blocks are experimental");
|
||||
gate_all!(const_trait_impl, "const trait impls are experimental");
|
||||
gate_all!(
|
||||
half_open_range_patterns_in_slices,
|
||||
"half-open range patterns in slices are unstable"
|
||||
);
|
||||
gate_all!(try_blocks_heterogeneous, "`try bikeshed` expression is experimental");
|
||||
gate_all!(yeet_expr, "`do yeet` expression is experimental");
|
||||
gate_all!(const_closures, "const closures are experimental");
|
||||
gate_all!(builtin_syntax, "`builtin #` syntax is unstable");
|
||||
gate_all!(ergonomic_clones, "ergonomic clones are experimental");
|
||||
gate_all!(explicit_tail_calls, "`become` expression is experimental");
|
||||
gate_all!(generic_const_items, "generic const items are experimental");
|
||||
gate_all!(guard_patterns, "guard patterns are experimental", "consider using match arm guards");
|
||||
gate_all!(default_field_values, "default values on fields are experimental");
|
||||
gate_all!(fn_delegation, "functions delegation is not yet fully implemented");
|
||||
gate_all!(postfix_match, "postfix match is experimental");
|
||||
gate_all!(mut_ref, "mutable by-reference bindings are experimental");
|
||||
gate_all!(min_generic_const_args, "unbraced const blocks as const args are experimental");
|
||||
// associated_const_equality is stabilized as part of min_generic_const_args
|
||||
if let Some(spans) = spans.get(&sym::associated_const_equality) {
|
||||
for span in spans {
|
||||
if !visitor.features.min_generic_const_args()
|
||||
&& !span.allows_unstable(sym::min_generic_const_args)
|
||||
{
|
||||
feature_err(
|
||||
&visitor.sess,
|
||||
sym::min_generic_const_args,
|
||||
*span,
|
||||
"associated const equality is incomplete",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
// `mgca_type_const_syntax` is part of `min_generic_const_args` so either
|
||||
// or both are enabled we don't need to emit a feature error.
|
||||
if let Some(spans) = spans.get(&sym::mgca_type_const_syntax) {
|
||||
for span in spans {
|
||||
if visitor.features.min_generic_const_args()
|
||||
|| visitor.features.mgca_type_const_syntax()
|
||||
|| span.allows_unstable(sym::min_generic_const_args)
|
||||
|| span.allows_unstable(sym::mgca_type_const_syntax)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
feature_err(
|
||||
&visitor.sess,
|
||||
sym::min_generic_const_args,
|
||||
*span,
|
||||
"`type const` syntax is experimental",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
||||
// `associated_const_equality` will be stabilized as part of `min_generic_const_args`.
|
||||
for &span in spans.get(&sym::associated_const_equality).into_iter().flatten() {
|
||||
gate!(visitor, min_generic_const_args, span, "associated const equality is incomplete");
|
||||
}
|
||||
|
||||
gate_all!(global_registration, "global registration is experimental");
|
||||
gate_all!(return_type_notation, "return type notation is experimental");
|
||||
gate_all!(pin_ergonomics, "pinned reference syntax is experimental");
|
||||
gate_all!(unsafe_fields, "`unsafe` fields are experimental");
|
||||
gate_all!(unsafe_binders, "unsafe binder types are experimental");
|
||||
gate_all!(contracts, "contracts are incomplete");
|
||||
gate_all!(contracts_internals, "contract internal machinery is for internal use only");
|
||||
gate_all!(where_clause_attrs, "attributes in `where` clause are unstable");
|
||||
gate_all!(super_let, "`super let` is experimental");
|
||||
gate_all!(frontmatter, "frontmatters are experimental");
|
||||
gate_all!(coroutines, "coroutine syntax is experimental");
|
||||
gate_all!(const_block_items, "const block items are experimental");
|
||||
gate_all!(final_associated_functions, "`final` on trait functions is experimental");
|
||||
gate_all!(impl_restriction, "`impl` restrictions are experimental");
|
||||
|
||||
if !visitor.features.never_patterns() {
|
||||
if let Some(spans) = spans.get(&sym::never_patterns) {
|
||||
for &span in spans {
|
||||
if span.allows_unstable(sym::never_patterns) {
|
||||
continue;
|
||||
}
|
||||
let sm = sess.source_map();
|
||||
// We gate two types of spans: the span of a `!` pattern, and the span of a
|
||||
// match arm without a body. For the latter we want to give the user a normal
|
||||
// error.
|
||||
if let Ok(snippet) = sm.span_to_snippet(span)
|
||||
&& snippet == "!"
|
||||
{
|
||||
feature_err(sess, sym::never_patterns, span, "`!` patterns are experimental")
|
||||
.emit();
|
||||
} else {
|
||||
let suggestion = span.shrink_to_hi();
|
||||
sess.dcx().emit_err(errors::MatchArmWithNoBody { span, suggestion });
|
||||
}
|
||||
}
|
||||
// `mgca_type_const_syntax` is part of `min_generic_const_args` so if
|
||||
// either or both are enabled we don't need to emit a feature error.
|
||||
for &span in spans.get(&sym::mgca_type_const_syntax).into_iter().flatten() {
|
||||
if visitor.features.min_generic_const_args()
|
||||
|| visitor.features.mgca_type_const_syntax()
|
||||
|| span.allows_unstable(sym::min_generic_const_args)
|
||||
|| span.allows_unstable(sym::mgca_type_const_syntax)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
feature_err(
|
||||
visitor.sess,
|
||||
sym::min_generic_const_args,
|
||||
span,
|
||||
"`type const` syntax is experimental",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
||||
// Negative bounds are *super* internal.
|
||||
// Under no circumstances do we want to advertise the feature name to users!
|
||||
if !visitor.features.negative_bounds() {
|
||||
for &span in spans.get(&sym::negative_bounds).iter().copied().flatten() {
|
||||
for &span in spans.get(&sym::negative_bounds).into_iter().flatten() {
|
||||
sess.dcx().emit_err(errors::NegativeBoundUnsupported { span });
|
||||
}
|
||||
}
|
||||
|
||||
// All uses of `gate_all_legacy_dont_use!` below this point were added in #65742,
|
||||
// and subsequently disabled (with the non-early gating readded).
|
||||
// We emit an early future-incompatible warning for these.
|
||||
// New syntax gates should go above here to get a hard error gate.
|
||||
macro_rules! gate_all_legacy_dont_use {
|
||||
($gate:ident, $msg:literal) => {
|
||||
for span in spans.get(&sym::$gate).unwrap_or(&vec![]) {
|
||||
gate_legacy!(&visitor, $gate, *span, $msg);
|
||||
if !visitor.features.never_patterns() {
|
||||
for &span in spans.get(&sym::never_patterns).into_iter().flatten() {
|
||||
if span.allows_unstable(sym::never_patterns) {
|
||||
continue;
|
||||
}
|
||||
// We gate two types of spans: the span of a `!` pattern, and the span of a
|
||||
// match arm without a body. For the latter we want to give the user a normal
|
||||
// error.
|
||||
if let Ok("!") = sess.source_map().span_to_snippet(span).as_deref() {
|
||||
feature_err(sess, sym::never_patterns, span, "`!` patterns are experimental")
|
||||
.emit();
|
||||
} else {
|
||||
let suggestion = span.shrink_to_hi();
|
||||
sess.dcx().emit_err(errors::MatchArmWithNoBody { span, suggestion });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Yield exprs can be enabled either by `yield_expr`, by `coroutines` or by `gen_blocks`.
|
||||
for &span in spans.get(&sym::yield_expr).into_iter().flatten() {
|
||||
if (!visitor.features.coroutines() && !span.allows_unstable(sym::coroutines))
|
||||
&& (!visitor.features.gen_blocks() && !span.allows_unstable(sym::gen_blocks))
|
||||
&& (!visitor.features.yield_expr() && !span.allows_unstable(sym::yield_expr))
|
||||
{
|
||||
// Only mentioned `yield_expr` in the diagnostic since that'll be sufficient.
|
||||
// You can think of it as `coroutines` and `gen_blocks` implying `yield_expr`.
|
||||
feature_err(visitor.sess, sym::yield_expr, span, "yield syntax is experimental").emit();
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// **LEGACY** SOFT PRE-EXPANSION FEATURE GATES FOR UNSTABLE SYNTAX **LEGACY**
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// IMPORTANT: Do not extend the list below! New syntax should go above and use `gate_all`.
|
||||
|
||||
// FIXME(#154045): Migrate all of these to erroring feature gates and
|
||||
// remove the corresponding post-expansion feature gates.
|
||||
|
||||
macro_rules! soft_gate_all_legacy_dont_use {
|
||||
($feature:ident, $explain:literal) => {
|
||||
for &span in spans.get(&sym::$feature).into_iter().flatten() {
|
||||
if !visitor.features.$feature() && !span.allows_unstable(sym::$feature) {
|
||||
feature_warn(&visitor.sess, sym::$feature, span, $explain);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
gate_all_legacy_dont_use!(box_patterns, "box pattern syntax is experimental");
|
||||
gate_all_legacy_dont_use!(trait_alias, "trait aliases are experimental");
|
||||
gate_all_legacy_dont_use!(decl_macro, "`macro` is experimental");
|
||||
gate_all_legacy_dont_use!(try_blocks, "`try` blocks are unstable");
|
||||
gate_all_legacy_dont_use!(auto_traits, "`auto` traits are unstable");
|
||||
// tidy-alphabetical-start
|
||||
soft_gate_all_legacy_dont_use!(auto_traits, "`auto` traits are unstable");
|
||||
soft_gate_all_legacy_dont_use!(box_patterns, "box pattern syntax is experimental");
|
||||
soft_gate_all_legacy_dont_use!(decl_macro, "`macro` is experimental");
|
||||
soft_gate_all_legacy_dont_use!(negative_impls, "negative impls are experimental");
|
||||
soft_gate_all_legacy_dont_use!(specialization, "specialization is experimental");
|
||||
soft_gate_all_legacy_dont_use!(trait_alias, "trait aliases are experimental");
|
||||
soft_gate_all_legacy_dont_use!(try_blocks, "`try` blocks are unstable");
|
||||
// tidy-alphabetical-end
|
||||
|
||||
for &span in spans.get(&sym::min_specialization).into_iter().flatten() {
|
||||
if !visitor.features.specialization()
|
||||
&& !visitor.features.min_specialization()
|
||||
&& !span.allows_unstable(sym::specialization)
|
||||
&& !span.allows_unstable(sym::min_specialization)
|
||||
{
|
||||
feature_warn(visitor.sess, sym::specialization, span, "specialization is experimental");
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
visit::walk_crate(&mut visitor, krate);
|
||||
}
|
||||
|
||||
@@ -248,10 +248,18 @@ fn parse_item_kind(
|
||||
self.parse_use_item()?
|
||||
} else if self.check_fn_front_matter(check_pub, case) {
|
||||
// FUNCTION ITEM
|
||||
let defaultness = def_();
|
||||
if let Defaultness::Default(span) = defaultness {
|
||||
// Default functions should only require feature `min_specialization`. We remove the
|
||||
// `specialization` tag again as such spans *require* feature `specialization` to be
|
||||
// enabled. In a later stage, we make `specialization` imply `min_specialization`.
|
||||
self.psess.gated_spans.gate(sym::min_specialization, span);
|
||||
self.psess.gated_spans.ungate_last(sym::specialization, span);
|
||||
}
|
||||
let (ident, sig, generics, contract, body) =
|
||||
self.parse_fn(attrs, fn_parse_mode, lo, vis, case)?;
|
||||
ItemKind::Fn(Box::new(Fn {
|
||||
defaultness: def_(),
|
||||
defaultness,
|
||||
ident,
|
||||
sig,
|
||||
generics,
|
||||
@@ -603,6 +611,7 @@ fn is_async_fn(&self) -> bool {
|
||||
fn parse_polarity(&mut self) -> ast::ImplPolarity {
|
||||
// Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type.
|
||||
if self.check(exp!(Bang)) && self.look_ahead(1, |t| t.can_begin_type()) {
|
||||
self.psess.gated_spans.gate(sym::negative_impls, self.token.span);
|
||||
self.bump(); // `!`
|
||||
ast::ImplPolarity::Negative(self.prev_token.span)
|
||||
} else {
|
||||
@@ -1015,6 +1024,7 @@ fn parse_defaultness(&mut self) -> Defaultness {
|
||||
if self.check_keyword(exp!(Default))
|
||||
&& self.look_ahead(1, |t| t.is_non_raw_ident_where(|i| i.name != kw::As))
|
||||
{
|
||||
self.psess.gated_spans.gate(sym::specialization, self.token.span);
|
||||
self.bump(); // `default`
|
||||
Defaultness::Default(self.prev_token_uninterpolated_span())
|
||||
} else if self.eat_keyword(exp!(Final)) {
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
auto trait MyTrait {}
|
||||
//~^ ERROR auto traits are experimental and possibly buggy
|
||||
|
||||
impl<T> !MyTrait for *mut T {}
|
||||
//~^ ERROR negative trait bounds are not fully implemented
|
||||
|
||||
fn main() {}
|
||||
@@ -1,23 +0,0 @@
|
||||
error[E0658]: auto traits are experimental and possibly buggy
|
||||
--> $DIR/ungated-impl.rs:1:1
|
||||
|
|
||||
LL | auto trait MyTrait {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #13231 <https://github.com/rust-lang/rust/issues/13231> for more information
|
||||
= help: add `#![feature(auto_traits)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: negative trait bounds are not fully implemented; use marker types for now
|
||||
--> $DIR/ungated-impl.rs:4:9
|
||||
|
|
||||
LL | impl<T> !MyTrait for *mut T {}
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: see issue #68318 <https://github.com/rust-lang/rust/issues/68318> for more information
|
||||
= help: add `#![feature(negative_impls)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
@@ -1,12 +1,5 @@
|
||||
// Test that default and negative trait implementations are gated by
|
||||
// `auto_traits` feature gate
|
||||
auto trait DummyAutoTrait {} //~ ERROR auto traits are experimental and possibly buggy
|
||||
|
||||
struct DummyStruct;
|
||||
|
||||
auto trait AutoDummyTrait {}
|
||||
//~^ ERROR auto traits are experimental and possibly buggy
|
||||
|
||||
impl !AutoDummyTrait for DummyStruct {}
|
||||
//~^ ERROR negative trait bounds are not fully implemented; use marker types for now
|
||||
pub unsafe auto trait AnotherAutoTrait {} //~ ERROR auto traits are experimental and possibly buggy
|
||||
|
||||
fn main() {}
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
error[E0658]: auto traits are experimental and possibly buggy
|
||||
--> $DIR/feature-gate-auto-traits.rs:6:1
|
||||
--> $DIR/feature-gate-auto-traits.rs:1:1
|
||||
|
|
||||
LL | auto trait AutoDummyTrait {}
|
||||
LL | auto trait DummyAutoTrait {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #13231 <https://github.com/rust-lang/rust/issues/13231> for more information
|
||||
= help: add `#![feature(auto_traits)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: negative trait bounds are not fully implemented; use marker types for now
|
||||
--> $DIR/feature-gate-auto-traits.rs:9:6
|
||||
error[E0658]: auto traits are experimental and possibly buggy
|
||||
--> $DIR/feature-gate-auto-traits.rs:3:1
|
||||
|
|
||||
LL | impl !AutoDummyTrait for DummyStruct {}
|
||||
| ^^^^^^^^^^^^^^^
|
||||
LL | pub unsafe auto trait AnotherAutoTrait {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #68318 <https://github.com/rust-lang/rust/issues/68318> for more information
|
||||
= help: add `#![feature(negative_impls)]` to the crate attributes to enable
|
||||
= note: see issue #13231 <https://github.com/rust-lang/rust/issues/13231> for more information
|
||||
= help: add `#![feature(auto_traits)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// For historical reasons, auto traits don't have a proper pre-expansion feature gate.
|
||||
// We're now at least issuing a *warning* for those that only exist before macro expansion.
|
||||
// FIXME(#154045): Turn their post-expansion feature gate into a proper pre-expansion one.
|
||||
// For historical reasons, auto traits don't have an erroring pre-expansion feature gate.
|
||||
// We're now at least issuing a warning for those that only exist before macro expansion.
|
||||
// FIXME(#154045): Turn this pre-expansion warning into an error and remove the post-expansion gate.
|
||||
// As part of this, move these test cases into `feature-gate-auto-traits.rs`.
|
||||
//@ check-pass
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// For historical reasons, box patterns don't have a proper pre-expansion feature gate.
|
||||
// We're now at least issuing a *warning* for those that only exist before macro expansion.
|
||||
// FIXME(#154045): Turn their post-expansion feature gate into a proper pre-expansion one.
|
||||
// For historical reasons, box patterns don't have an erroring pre-expansion feature gate.
|
||||
// We're now at least issuing a warning for those that only exist before macro expansion.
|
||||
// FIXME(#154045): Turn this pre-expansion warning into an error and remove the post-expansion gate.
|
||||
// As part of this, move these test cases into `feature-gate-box_patterns.rs`.
|
||||
//@ check-pass
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// For historical reasons, decl macros 2.0 don't have a proper pre-expansion feature gate.
|
||||
// We're now at least issuing a *warning* for those that only exist before macro expansion.
|
||||
// FIXME(#154045): Turn their post-expansion feature gate into a proper pre-expansion one.
|
||||
// For historical reasons, decl macros 2.0 don't have an erroring pre-expansion feature gate.
|
||||
// We're now at least issuing a warning for those that only exist before macro expansion.
|
||||
// FIXME(#154045): Turn this pre-expansion warning into an error and remove the post-expansion gate.
|
||||
// As part of this, move these test cases into `feature-gate-decl_macro.rs`.
|
||||
//@ check-pass
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// For historical reasons, negative impls don't have an erroring pre-expansion feature gate.
|
||||
// We're now at least issuing a warning for those that only exist before macro expansion.
|
||||
// FIXME(#154045): Turn this pre-expansion warning into an error and remove the post-expansion gate.
|
||||
// As part of this, move these test cases into `feature-gate-negative_impls.rs`.
|
||||
//@ check-pass
|
||||
|
||||
#[cfg(false)]
|
||||
impl !Trait for () {}
|
||||
//~^ WARN negative impls are experimental
|
||||
//~| WARN unstable syntax can change at any point in the future
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,14 @@
|
||||
warning: negative impls are experimental
|
||||
--> $DIR/soft-feature-gate-negative_impls.rs:8:6
|
||||
|
|
||||
LL | impl !Trait for () {}
|
||||
| ^
|
||||
|
|
||||
= note: see issue #68318 <https://github.com/rust-lang/rust/issues/68318> for more information
|
||||
= help: add `#![feature(negative_impls)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
= warning: unstable syntax can change at any point in the future, causing a hard error!
|
||||
= note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// For historical reasons, trait aliases don't have a proper pre-expansion feature gate.
|
||||
// We're now at least issuing a *warning* for those that only exist before macro expansion.
|
||||
// FIXME(#154045): Turn their post-expansion feature gate into a proper pre-expansion one.
|
||||
// For historical reasons, trait aliases don't have an erroring pre-expansion feature gate.
|
||||
// We're now at least issuing a warning for those that only exist before macro expansion.
|
||||
// FIXME(#154045): Turn this pre-expansion warning into an error and remove the post-expansion gate.
|
||||
// As part of this, move these test cases into `feature-gate-trait-alias.rs`.
|
||||
//@ check-pass
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// For historical reasons, try blocks don't have a proper pre-expansion feature gate.
|
||||
// We're now at least issuing a *warning* for those that only exist before macro expansion.
|
||||
// FIXME(#154045): Turn their post-expansion feature gate into a proper pre-expansion one.
|
||||
// For historical reasons, try blocks don't have an erroring pre-expansion feature gate.
|
||||
// We're now at least issuing a warning for those that only exist before macro expansion.
|
||||
// FIXME(#154045): Turn this pre-expansion warning into an error and remove the post-expansion gate.
|
||||
// As part of this, move these test cases into `feature-gate-try_blocks.rs`.
|
||||
//@ edition: 2018
|
||||
//@ check-pass
|
||||
|
||||
@@ -46,6 +46,16 @@ error[E0405]: cannot find trait `r#use` in this scope
|
||||
LL | fn binder() -> impl Sized + for<'a> use<> {}
|
||||
| ^^^ not found in this scope
|
||||
|
||||
error[E0658]: const trait impls are experimental
|
||||
--> $DIR/bound-modifiers.rs:12:32
|
||||
|
|
||||
LL | fn constness() -> impl Sized + const use<> {}
|
||||
| ^^^^^
|
||||
|
|
||||
= note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
|
||||
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: `async` trait bounds are unstable
|
||||
--> $DIR/bound-modifiers.rs:7:32
|
||||
|
|
||||
@@ -57,16 +67,6 @@ LL | fn asyncness() -> impl Sized + async use<> {}
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
= help: use the desugared name of the async trait, such as `AsyncFn`
|
||||
|
||||
error[E0658]: const trait impls are experimental
|
||||
--> $DIR/bound-modifiers.rs:12:32
|
||||
|
|
||||
LL | fn constness() -> impl Sized + const use<> {}
|
||||
| ^^^^^
|
||||
|
|
||||
= note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
|
||||
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0405, E0658.
|
||||
|
||||
@@ -9,12 +9,13 @@
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(coroutines)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(macro_guard_matcher)]
|
||||
#![feature(more_qualified_paths)]
|
||||
#![feature(never_patterns)]
|
||||
#![feature(specialization)]
|
||||
#![feature(trait_alias)]
|
||||
#![feature(try_blocks)]
|
||||
#![feature(yeet_expr)]
|
||||
#![feature(macro_guard_matcher)]
|
||||
#![deny(unused_macros)]
|
||||
|
||||
// These macros force the use of AST pretty-printing by converting the input to
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
//@ check-pass
|
||||
#![feature(specialization)]
|
||||
|
||||
fn main() {}
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
trait Trait {
|
||||
type Ty;
|
||||
const CT: ();
|
||||
fn fn_(&self);
|
||||
}
|
||||
|
||||
impl<T> Trait for T {
|
||||
default type Ty = (); //~ ERROR specialization is experimental
|
||||
default const CT: () = (); //~ ERROR specialization is experimental
|
||||
default fn fn_(&self) {} //~ ERROR specialization is experimental
|
||||
}
|
||||
|
||||
trait OtherTrait {
|
||||
fn fn_();
|
||||
}
|
||||
|
||||
default impl<T> OtherTrait for T { //~ ERROR specialization is experimental
|
||||
fn fn_() {}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,45 @@
|
||||
error[E0658]: specialization is experimental
|
||||
--> $DIR/feature-gate-specialization.rs:8:5
|
||||
|
|
||||
LL | default type Ty = ();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
|
||||
= help: add `#![feature(specialization)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: specialization is experimental
|
||||
--> $DIR/feature-gate-specialization.rs:9:5
|
||||
|
|
||||
LL | default const CT: () = ();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
|
||||
= help: add `#![feature(specialization)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: specialization is experimental
|
||||
--> $DIR/feature-gate-specialization.rs:10:5
|
||||
|
|
||||
LL | default fn fn_(&self) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
|
||||
= help: add `#![feature(specialization)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: specialization is experimental
|
||||
--> $DIR/feature-gate-specialization.rs:17:1
|
||||
|
|
||||
LL | / default impl<T> OtherTrait for T {
|
||||
LL | | fn fn_() {}
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
|
||||
= help: add `#![feature(specialization)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
@@ -0,0 +1,62 @@
|
||||
warning: specialization is experimental
|
||||
--> $DIR/soft-feature-gate-specialization.rs:21:5
|
||||
|
|
||||
LL | default type Ty = ();
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
|
||||
= help: add `#![feature(specialization)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
= warning: unstable syntax can change at any point in the future, causing a hard error!
|
||||
= note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
|
||||
|
||||
warning: specialization is experimental
|
||||
--> $DIR/soft-feature-gate-specialization.rs:24:5
|
||||
|
|
||||
LL | default const CT: () = ();
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
|
||||
= help: add `#![feature(specialization)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
= warning: unstable syntax can change at any point in the future, causing a hard error!
|
||||
= note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
|
||||
|
||||
warning: specialization is experimental
|
||||
--> $DIR/soft-feature-gate-specialization.rs:40:1
|
||||
|
|
||||
LL | default impl Trait for () {}
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
|
||||
= help: add `#![feature(specialization)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
= warning: unstable syntax can change at any point in the future, causing a hard error!
|
||||
= note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
|
||||
|
||||
warning: specialization is experimental
|
||||
--> $DIR/soft-feature-gate-specialization.rs:27:5
|
||||
|
|
||||
LL | default fn fn_();
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
|
||||
= help: add `#![feature(specialization)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
= warning: unstable syntax can change at any point in the future, causing a hard error!
|
||||
= note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
|
||||
|
||||
warning: specialization is experimental
|
||||
--> $DIR/soft-feature-gate-specialization.rs:35:1
|
||||
|
|
||||
LL | default fn fn_() {}
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
|
||||
= help: add `#![feature(specialization)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
= warning: unstable syntax can change at any point in the future, causing a hard error!
|
||||
= note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
|
||||
|
||||
warning: 5 warnings emitted
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
warning: specialization is experimental
|
||||
--> $DIR/soft-feature-gate-specialization.rs:21:5
|
||||
|
|
||||
LL | default type Ty = ();
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
|
||||
= help: add `#![feature(specialization)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
= warning: unstable syntax can change at any point in the future, causing a hard error!
|
||||
= note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
|
||||
|
||||
warning: specialization is experimental
|
||||
--> $DIR/soft-feature-gate-specialization.rs:24:5
|
||||
|
|
||||
LL | default const CT: () = ();
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
|
||||
= help: add `#![feature(specialization)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
= warning: unstable syntax can change at any point in the future, causing a hard error!
|
||||
= note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
|
||||
|
||||
warning: specialization is experimental
|
||||
--> $DIR/soft-feature-gate-specialization.rs:40:1
|
||||
|
|
||||
LL | default impl Trait for () {}
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
|
||||
= help: add `#![feature(specialization)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
= warning: unstable syntax can change at any point in the future, causing a hard error!
|
||||
= note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
|
||||
|
||||
warning: 3 warnings emitted
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
// For historical reasons, item modifier `default` doesn't have a proper pre-expansion feature gate.
|
||||
// We're now at least issuing a warning for those that only exist before macro expansion.
|
||||
// FIXME(#154045): Turn this pre-expansion warning into an error and remove the post-expansion gate.
|
||||
// As part of this, move these test cases into `feature-gate-specialization.rs`.
|
||||
//
|
||||
// Moreover, `specialization` implies `min_specialization` similar to the post-expansion gate.
|
||||
//
|
||||
// However, while we only gate `default` *associated* functions only behind `min_specialization` OR
|
||||
// `specialization` in the post-expansion case, in the pre-expansion case we gate all kinds of
|
||||
// functions (free, assoc, foreign) behind `min_specialization` OR `specialization` if marked with
|
||||
// `default` for simplicity of implementation. Ultimately it doesn't matter since we later reject
|
||||
// `default` on anything other than impls & impl assoc items during semantic analysis.
|
||||
//
|
||||
//@ revisions: default min full
|
||||
//@ check-pass
|
||||
#![cfg_attr(min, feature(min_specialization))]
|
||||
#![cfg_attr(full, feature(specialization))]
|
||||
|
||||
#[cfg(false)]
|
||||
impl Trait for () {
|
||||
default type Ty = ();
|
||||
//[default,min]~^ WARN specialization is experimental
|
||||
//[default,min]~| WARN unstable syntax can change at any point in the future
|
||||
default const CT: () = ();
|
||||
//[default,min]~^ WARN specialization is experimental
|
||||
//[default,min]~| WARN unstable syntax can change at any point in the future
|
||||
default fn fn_();
|
||||
//[default]~^ WARN specialization is experimental
|
||||
//[default]~| WARN unstable syntax can change at any point in the future
|
||||
}
|
||||
|
||||
// While free ty/ct/fn items marked `default` are
|
||||
// semantically malformed we still need to gate the keyword!
|
||||
#[cfg(false)]
|
||||
default fn fn_() {}
|
||||
//[default]~^ WARN specialization is experimental
|
||||
//[default]~| WARN unstable syntax can change at any point in the future
|
||||
|
||||
#[cfg(false)]
|
||||
default impl Trait for () {}
|
||||
//[default,min]~^ WARN specialization is experimental
|
||||
//[default,min]~| WARN unstable syntax can change at any point in the future
|
||||
|
||||
fn main() {}
|
||||
@@ -1,13 +0,0 @@
|
||||
// Check that specialization must be ungated to use the `default` keyword
|
||||
|
||||
// gate-test-specialization
|
||||
|
||||
trait Foo {
|
||||
fn foo(&self);
|
||||
}
|
||||
|
||||
impl<T> Foo for T {
|
||||
default fn foo(&self) {} //~ ERROR specialization is unstable
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -1,13 +0,0 @@
|
||||
error[E0658]: specialization is unstable
|
||||
--> $DIR/specialization-feature-gate-default.rs:10:5
|
||||
|
|
||||
LL | default fn foo(&self) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
|
||||
= help: add `#![feature(specialization)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
@@ -12,7 +12,7 @@ pub trait Foo {
|
||||
|
||||
impl<T> Foo for T {
|
||||
default fn bar() {}
|
||||
//~^ ERROR specialization is unstable
|
||||
//~^ ERROR specialization is experimental
|
||||
//~| NOTE created at
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
error[E0658]: specialization is unstable
|
||||
error[E0658]: specialization is experimental
|
||||
--> $DIR/track6.rs:LL:CC
|
||||
|
|
||||
LL | default fn bar() {}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
trait MyTrait {}
|
||||
impl !MyTrait for u32 {} //~ ERROR negative trait bounds are not fully implemented
|
||||
|
||||
impl !MyTrait for u32 {} //~ ERROR negative impls are experimental
|
||||
|
||||
fn main() {}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
error[E0658]: negative trait bounds are not fully implemented; use marker types for now
|
||||
--> $DIR/feature-gate-negative_impls.rs:2:6
|
||||
error[E0658]: negative impls are experimental
|
||||
--> $DIR/feature-gate-negative_impls.rs:3:6
|
||||
|
|
||||
LL | impl !MyTrait for u32 {}
|
||||
| ^^^^^^^^
|
||||
@@ -7,6 +7,7 @@ LL | impl !MyTrait for u32 {}
|
||||
= note: see issue #68318 <https://github.com/rust-lang/rust/issues/68318> for more information
|
||||
= help: add `#![feature(negative_impls)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
= help: use marker types for now
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
Reference in New Issue
Block a user