diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 830eb3d6d8170..1b615b611258f 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -14,31 +14,22 @@ use crate::errors; /// 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 @@ impl<'a> PostExpansionVisitor<'a> { 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 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { 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 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { 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 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { }) => { // 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 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { 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 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } 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 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { 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 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { && 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 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { 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 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { .. }) => 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 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { }; 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 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } 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 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } 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 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { 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 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { }) => { // 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 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { 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(); - } - } + + // `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"); } - // `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(); + + // `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(); } - 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"); + // 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).into_iter().flatten() { + sess.dcx().emit_err(errors::NegativeBoundUnsupported { span }); + } + } 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 }); - } + 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 }); } } } - if !visitor.features.negative_bounds() { - for &span in spans.get(&sym::negative_bounds).iter().copied().flatten() { - sess.dcx().emit_err(errors::NegativeBoundUnsupported { span }); + // 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(); } } - // 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); + // ----------------------------------------------------------------------------- + // **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); } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 0f4927432f6fa..79b79db6ccc07 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -248,10 +248,18 @@ impl<'a> Parser<'a> { 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 @@ impl<'a> Parser<'a> { 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 @@ impl<'a> Parser<'a> { 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)) { diff --git a/tests/ui/auto-traits/ungated-impl.rs b/tests/ui/auto-traits/ungated-impl.rs deleted file mode 100644 index d46b4b01af9c7..0000000000000 --- a/tests/ui/auto-traits/ungated-impl.rs +++ /dev/null @@ -1,7 +0,0 @@ -auto trait MyTrait {} -//~^ ERROR auto traits are experimental and possibly buggy - -impl !MyTrait for *mut T {} -//~^ ERROR negative trait bounds are not fully implemented - -fn main() {} diff --git a/tests/ui/auto-traits/ungated-impl.stderr b/tests/ui/auto-traits/ungated-impl.stderr deleted file mode 100644 index 9d10d46a90283..0000000000000 --- a/tests/ui/auto-traits/ungated-impl.stderr +++ /dev/null @@ -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 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 !MyTrait for *mut T {} - | ^^^^^^^^ - | - = note: see issue #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`. diff --git a/tests/ui/feature-gates/feature-gate-auto-traits.rs b/tests/ui/feature-gates/feature-gate-auto-traits.rs index aab9e784fe9d7..e900fb84a02d9 100644 --- a/tests/ui/feature-gates/feature-gate-auto-traits.rs +++ b/tests/ui/feature-gates/feature-gate-auto-traits.rs @@ -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() {} diff --git a/tests/ui/feature-gates/feature-gate-auto-traits.stderr b/tests/ui/feature-gates/feature-gate-auto-traits.stderr index 8fa5168b2d041..d476b4fecbe58 100644 --- a/tests/ui/feature-gates/feature-gate-auto-traits.stderr +++ b/tests/ui/feature-gates/feature-gate-auto-traits.stderr @@ -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 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 for more information - = help: add `#![feature(negative_impls)]` to the crate attributes to enable + = note: see issue #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 diff --git a/tests/ui/feature-gates/soft-feature-gate-auto_traits.rs b/tests/ui/feature-gates/soft-feature-gate-auto_traits.rs index 0ccbaf1e476a9..01f44df0d7621 100644 --- a/tests/ui/feature-gates/soft-feature-gate-auto_traits.rs +++ b/tests/ui/feature-gates/soft-feature-gate-auto_traits.rs @@ -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 diff --git a/tests/ui/feature-gates/soft-feature-gate-box_patterns.rs b/tests/ui/feature-gates/soft-feature-gate-box_patterns.rs index 8ab0e80e6be31..9fdaa7a0ec08c 100644 --- a/tests/ui/feature-gates/soft-feature-gate-box_patterns.rs +++ b/tests/ui/feature-gates/soft-feature-gate-box_patterns.rs @@ -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 diff --git a/tests/ui/feature-gates/soft-feature-gate-decl_macro.rs b/tests/ui/feature-gates/soft-feature-gate-decl_macro.rs index 7d2d48503797a..dbc0b940265fc 100644 --- a/tests/ui/feature-gates/soft-feature-gate-decl_macro.rs +++ b/tests/ui/feature-gates/soft-feature-gate-decl_macro.rs @@ -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 diff --git a/tests/ui/feature-gates/soft-feature-gate-negative_impls.rs b/tests/ui/feature-gates/soft-feature-gate-negative_impls.rs new file mode 100644 index 0000000000000..0071ce6350b16 --- /dev/null +++ b/tests/ui/feature-gates/soft-feature-gate-negative_impls.rs @@ -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() {} diff --git a/tests/ui/feature-gates/soft-feature-gate-negative_impls.stderr b/tests/ui/feature-gates/soft-feature-gate-negative_impls.stderr new file mode 100644 index 0000000000000..35e125cb2d24c --- /dev/null +++ b/tests/ui/feature-gates/soft-feature-gate-negative_impls.stderr @@ -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 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 + +warning: 1 warning emitted + diff --git a/tests/ui/feature-gates/soft-feature-gate-trait_alias.rs b/tests/ui/feature-gates/soft-feature-gate-trait_alias.rs index 553e88375a2a7..7f929f5198a70 100644 --- a/tests/ui/feature-gates/soft-feature-gate-trait_alias.rs +++ b/tests/ui/feature-gates/soft-feature-gate-trait_alias.rs @@ -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 diff --git a/tests/ui/feature-gates/soft-feature-gate-try_blocks.rs b/tests/ui/feature-gates/soft-feature-gate-try_blocks.rs index aa51e60d56b4a..3f439d0c26893 100644 --- a/tests/ui/feature-gates/soft-feature-gate-try_blocks.rs +++ b/tests/ui/feature-gates/soft-feature-gate-try_blocks.rs @@ -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 diff --git a/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr b/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr index deab31c251f83..4a0532284c176 100644 --- a/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr +++ b/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr @@ -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 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 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. diff --git a/tests/ui/macros/stringify.rs b/tests/ui/macros/stringify.rs index af2ba7a809ad0..46f50593c4e95 100644 --- a/tests/ui/macros/stringify.rs +++ b/tests/ui/macros/stringify.rs @@ -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 diff --git a/tests/ui/parser/trait-item-with-defaultness-pass.rs b/tests/ui/parser/trait-item-with-defaultness-pass.rs index 164d0b13b539c..e8452fcbd5f99 100644 --- a/tests/ui/parser/trait-item-with-defaultness-pass.rs +++ b/tests/ui/parser/trait-item-with-defaultness-pass.rs @@ -1,4 +1,5 @@ //@ check-pass +#![feature(specialization)] fn main() {} diff --git a/tests/ui/specialization/feature-gate-specialization.rs b/tests/ui/specialization/feature-gate-specialization.rs new file mode 100644 index 0000000000000..82e467ad98d32 --- /dev/null +++ b/tests/ui/specialization/feature-gate-specialization.rs @@ -0,0 +1,21 @@ +trait Trait { + type Ty; + const CT: (); + fn fn_(&self); +} + +impl 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 OtherTrait for T { //~ ERROR specialization is experimental + fn fn_() {} +} + +fn main() {} diff --git a/tests/ui/specialization/feature-gate-specialization.stderr b/tests/ui/specialization/feature-gate-specialization.stderr new file mode 100644 index 0000000000000..2efc0faa7c23e --- /dev/null +++ b/tests/ui/specialization/feature-gate-specialization.stderr @@ -0,0 +1,45 @@ +error[E0658]: specialization is experimental + --> $DIR/feature-gate-specialization.rs:8:5 + | +LL | default type Ty = (); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #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 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 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 OtherTrait for T { +LL | | fn fn_() {} +LL | | } + | |_^ + | + = note: see issue #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`. diff --git a/tests/ui/specialization/soft-feature-gate-specialization.default.stderr b/tests/ui/specialization/soft-feature-gate-specialization.default.stderr new file mode 100644 index 0000000000000..f5961090947ed --- /dev/null +++ b/tests/ui/specialization/soft-feature-gate-specialization.default.stderr @@ -0,0 +1,62 @@ +warning: specialization is experimental + --> $DIR/soft-feature-gate-specialization.rs:21:5 + | +LL | default type Ty = (); + | ^^^^^^^ + | + = note: see issue #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 + +warning: specialization is experimental + --> $DIR/soft-feature-gate-specialization.rs:24:5 + | +LL | default const CT: () = (); + | ^^^^^^^ + | + = note: see issue #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 + +warning: specialization is experimental + --> $DIR/soft-feature-gate-specialization.rs:40:1 + | +LL | default impl Trait for () {} + | ^^^^^^^ + | + = note: see issue #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 + +warning: specialization is experimental + --> $DIR/soft-feature-gate-specialization.rs:27:5 + | +LL | default fn fn_(); + | ^^^^^^^ + | + = note: see issue #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 + +warning: specialization is experimental + --> $DIR/soft-feature-gate-specialization.rs:35:1 + | +LL | default fn fn_() {} + | ^^^^^^^ + | + = note: see issue #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 + +warning: 5 warnings emitted + diff --git a/tests/ui/specialization/soft-feature-gate-specialization.min.stderr b/tests/ui/specialization/soft-feature-gate-specialization.min.stderr new file mode 100644 index 0000000000000..aa4ce0cc58be2 --- /dev/null +++ b/tests/ui/specialization/soft-feature-gate-specialization.min.stderr @@ -0,0 +1,38 @@ +warning: specialization is experimental + --> $DIR/soft-feature-gate-specialization.rs:21:5 + | +LL | default type Ty = (); + | ^^^^^^^ + | + = note: see issue #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 + +warning: specialization is experimental + --> $DIR/soft-feature-gate-specialization.rs:24:5 + | +LL | default const CT: () = (); + | ^^^^^^^ + | + = note: see issue #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 + +warning: specialization is experimental + --> $DIR/soft-feature-gate-specialization.rs:40:1 + | +LL | default impl Trait for () {} + | ^^^^^^^ + | + = note: see issue #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 + +warning: 3 warnings emitted + diff --git a/tests/ui/specialization/soft-feature-gate-specialization.rs b/tests/ui/specialization/soft-feature-gate-specialization.rs new file mode 100644 index 0000000000000..46e4b28e61d23 --- /dev/null +++ b/tests/ui/specialization/soft-feature-gate-specialization.rs @@ -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() {} diff --git a/tests/ui/specialization/specialization-feature-gate-default.rs b/tests/ui/specialization/specialization-feature-gate-default.rs deleted file mode 100644 index 8bad3ac0a1fb3..0000000000000 --- a/tests/ui/specialization/specialization-feature-gate-default.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Check that specialization must be ungated to use the `default` keyword - -// gate-test-specialization - -trait Foo { - fn foo(&self); -} - -impl Foo for T { - default fn foo(&self) {} //~ ERROR specialization is unstable -} - -fn main() {} diff --git a/tests/ui/specialization/specialization-feature-gate-default.stderr b/tests/ui/specialization/specialization-feature-gate-default.stderr deleted file mode 100644 index 3e651b6ee4f37..0000000000000 --- a/tests/ui/specialization/specialization-feature-gate-default.stderr +++ /dev/null @@ -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 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`. diff --git a/tests/ui/track-diagnostics/track6.rs b/tests/ui/track-diagnostics/track6.rs index aa75c5691e5f9..38d34f46270a4 100644 --- a/tests/ui/track-diagnostics/track6.rs +++ b/tests/ui/track-diagnostics/track6.rs @@ -12,7 +12,7 @@ pub trait Foo { impl Foo for T { default fn bar() {} - //~^ ERROR specialization is unstable + //~^ ERROR specialization is experimental //~| NOTE created at } diff --git a/tests/ui/track-diagnostics/track6.stderr b/tests/ui/track-diagnostics/track6.stderr index a61f7855e3231..30d518a69cadd 100644 --- a/tests/ui/track-diagnostics/track6.stderr +++ b/tests/ui/track-diagnostics/track6.stderr @@ -1,4 +1,4 @@ -error[E0658]: specialization is unstable +error[E0658]: specialization is experimental --> $DIR/track6.rs:LL:CC | LL | default fn bar() {} diff --git a/tests/ui/traits/negative-impls/feature-gate-negative_impls.rs b/tests/ui/traits/negative-impls/feature-gate-negative_impls.rs index 8d3f6ff6d78c7..1b3c5abe10918 100644 --- a/tests/ui/traits/negative-impls/feature-gate-negative_impls.rs +++ b/tests/ui/traits/negative-impls/feature-gate-negative_impls.rs @@ -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() {} diff --git a/tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr b/tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr index 1777dfcc993f1..36bc5bb4be2bc 100644 --- a/tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr +++ b/tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr @@ -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 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