diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 9d543563c0f96..d6818d0769fd9 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -300,9 +300,22 @@ pub enum TraitBoundModifier { /// `?Trait` Maybe, + /// `const Trait` + Const(Span), + /// `~const Trait` MaybeConst(Span), + /// `const !Trait` + // + // This parses but will be rejected during AST validation. + ConstNegative, + + /// `const ?Trait` + // + // This parses but will be rejected during AST validation. + ConstMaybe, + /// `~const !Trait` // // This parses but will be rejected during AST validation. @@ -315,10 +328,11 @@ pub enum TraitBoundModifier { } impl TraitBoundModifier { - pub fn to_constness(self) -> Const { + pub fn to_constness(self) -> BoundConstness { match self { - Self::MaybeConst(span) => Const::Yes(span), - _ => Const::No, + Self::Const(span) => BoundConstness::Always(span), + Self::MaybeConst(span) => BoundConstness::Maybe(span), + _ => BoundConstness::Never, } } } @@ -2526,6 +2540,25 @@ pub enum BoundPolarity { Maybe(Span), } +#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] +pub enum BoundConstness { + /// `Type: Trait` + Never, + /// `Type: const Trait` + Always(Span), + /// `Type: ~const Trait` + Maybe(Span), +} + +impl From for BoundConstness { + fn from(constness: Const) -> Self { + match constness { + Const::Yes(span) => Self::Maybe(span), + Const::No => Self::Never, + } + } +} + #[derive(Clone, Encodable, Decodable, Debug)] pub enum FnRetTy { /// Returns type is not specified. diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index b0cd2ec981592..1b8e96819ce30 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -529,6 +529,8 @@ impl Token { } /// Returns `true` if the token can appear at the start of a generic bound. + // FIXME(const_trait_impl): This lacks `Tilde` and `kw::Const` but everythings seems to work + // regardless for some reason? pub fn can_begin_bound(&self) -> bool { self.is_path_start() || self.is_lifetime() diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 83452c2228029..f2bbcced384d2 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -341,7 +341,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_generics(ast_generics, *constness, id, &itctx, |this| { let trait_ref = trait_ref.as_ref().map(|trait_ref| { this.lower_trait_ref( - *constness, + (*constness).into(), trait_ref, &ImplTraitContext::Disallowed(ImplTraitPosition::Trait), ) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 96ed3eee02ed9..b56db94471416 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1318,7 +1318,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: t.span, }, itctx, - ast::Const::No, + ast::BoundConstness::Never, ); let bounds = this.arena.alloc_from_iter([bound]); let lifetime_bound = this.elided_dyn_bound(t.span); @@ -1426,18 +1426,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { GenericBound::Trait( ty, modifier @ (TraitBoundModifier::None + | TraitBoundModifier::Const(_) | TraitBoundModifier::MaybeConst(_) | TraitBoundModifier::Negative), ) => { Some(this.lower_poly_trait_ref(ty, itctx, modifier.to_constness())) } - // `~const ?Bound` will cause an error during AST validation + // `{,~}const ?Bound` will cause an error during AST validation // anyways, so treat it like `?Bound` as compilation proceeds. GenericBound::Trait( _, TraitBoundModifier::Maybe | TraitBoundModifier::MaybeConstMaybe - | TraitBoundModifier::MaybeConstNegative, + | TraitBoundModifier::MaybeConstNegative + | TraitBoundModifier::ConstMaybe + | TraitBoundModifier::ConstNegative, ) => None, GenericBound::Outlives(lifetime) => { if lifetime_bound.is_none() { @@ -2176,7 +2179,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_trait_ref( &mut self, - constness: ast::Const, + constness: ast::BoundConstness, p: &TraitRef, itctx: &ImplTraitContext, ) -> hir::TraitRef<'hir> { @@ -2199,7 +2202,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, p: &PolyTraitRef, itctx: &ImplTraitContext, - constness: ast::Const, + constness: ast::BoundConstness, ) -> hir::PolyTraitRef<'hir> { let bound_generic_params = self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params); @@ -2323,6 +2326,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_trait_bound_modifier(&mut self, f: TraitBoundModifier) -> hir::TraitBoundModifier { match f { TraitBoundModifier::None => hir::TraitBoundModifier::None, + TraitBoundModifier::Const(_) => hir::TraitBoundModifier::Const, TraitBoundModifier::MaybeConst(_) => hir::TraitBoundModifier::MaybeConst, TraitBoundModifier::Negative => { @@ -2333,12 +2337,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - // `MaybeConstMaybe` will cause an error during AST validation, but we need to pick a + // `{,Maybe}ConstMaybe` will cause an error during AST validation, but we need to pick a // placeholder for compilation to proceed. - TraitBoundModifier::MaybeConstMaybe | TraitBoundModifier::Maybe => { - hir::TraitBoundModifier::Maybe - } + TraitBoundModifier::ConstMaybe + | TraitBoundModifier::MaybeConstMaybe + | TraitBoundModifier::Maybe => hir::TraitBoundModifier::Maybe, TraitBoundModifier::MaybeConstNegative => hir::TraitBoundModifier::MaybeConst, + TraitBoundModifier::ConstNegative => hir::TraitBoundModifier::Const, } } @@ -2556,45 +2561,62 @@ struct GenericArgsCtor<'hir> { } impl<'hir> GenericArgsCtor<'hir> { - fn push_constness(&mut self, lcx: &mut LoweringContext<'_, 'hir>, constness: ast::Const) { + fn push_constness( + &mut self, + lcx: &mut LoweringContext<'_, 'hir>, + constness: ast::BoundConstness, + ) { if !lcx.tcx.features().effects { return; } - // if bound is non-const, don't add host effect param - let ast::Const::Yes(span) = constness else { return }; + let (span, body) = match constness { + BoundConstness::Never => return, + BoundConstness::Always(span) => { + let span = lcx.lower_span(span); - let span = lcx.lower_span(span); + let body = hir::ExprKind::Lit( + lcx.arena.alloc(hir::Lit { node: LitKind::Bool(false), span }), + ); - let id = lcx.next_node_id(); - let hir_id = lcx.next_id(); + (span, body) + } + BoundConstness::Maybe(span) => { + let span = lcx.lower_span(span); - let Some(host_param_id) = lcx.host_param_id else { - lcx.tcx.sess.span_delayed_bug( - span, - "no host param id for call in const yet no errors reported", - ); - return; - }; + let Some(host_param_id) = lcx.host_param_id else { + lcx.tcx.sess.span_delayed_bug( + span, + "no host param id for call in const yet no errors reported", + ); + return; + }; - let body = lcx.lower_body(|lcx| { - (&[], { let hir_id = lcx.next_id(); let res = Res::Def(DefKind::ConstParam, host_param_id.to_def_id()); - let expr_kind = hir::ExprKind::Path(hir::QPath::Resolved( + let body = hir::ExprKind::Path(hir::QPath::Resolved( None, lcx.arena.alloc(hir::Path { span, res, - segments: arena_vec![lcx; hir::PathSegment::new(Ident { - name: sym::host, - span, - }, hir_id, res)], + segments: arena_vec![ + lcx; + hir::PathSegment::new( + Ident { name: sym::host, span }, + hir_id, + res + ) + ], }), )); - lcx.expr(span, expr_kind) - }) - }); + + (span, body) + } + }; + let body = lcx.lower_body(|lcx| (&[], lcx.expr(span, body))); + + let id = lcx.next_node_id(); + let hir_id = lcx.next_id(); let def_id = lcx.create_def( lcx.current_hir_id_owner.def_id, diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 5ceeb72f2912a..4f8ac5e6de97d 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -25,7 +25,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { param_mode: ParamMode, itctx: &ImplTraitContext, // constness of the impl/bound if this is a trait path - constness: Option, + constness: Option, ) -> hir::QPath<'hir> { let qself_position = qself.as_ref().map(|q| q.position); let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx)); @@ -179,7 +179,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { param_mode: ParamMode, parenthesized_generic_args: ParenthesizedGenericArgs, itctx: &ImplTraitContext, - constness: Option, + constness: Option, ) -> hir::PathSegment<'hir> { debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment); let (mut generic_args, infer_args) = if let Some(generic_args) = segment.args.as_deref() { diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index 790b583134c0d..e0eef652c82e5 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -46,6 +46,8 @@ ast_passes_const_and_c_variadic = functions cannot be both `const` and C-variadi .const = `const` because of this .variadic = C-variadic because of this +ast_passes_const_bound_trait_object = const trait bounds are not allowed in trait object types + ast_passes_const_without_body = free constant item without body .suggestion = provide a definition for the constant @@ -181,6 +183,8 @@ ast_passes_match_arm_with_no_body = ast_passes_module_nonascii = trying to load file for module `{$name}` with non-ascii identifier name .help = consider using the `#[path]` attribute to specify filesystem path +ast_passes_mutually_exclusive_trait_bound_modifiers = `{$left}` and `{$right}` are mutually exclusive + ast_passes_negative_bound_not_supported = negative bounds are not supported @@ -195,8 +199,6 @@ ast_passes_nomangle_ascii = `#[no_mangle]` requires ASCII identifier ast_passes_obsolete_auto = `impl Trait for .. {"{}"}` is an obsolete syntax .help = use `auto trait Trait {"{}"}` instead -ast_passes_optional_const_exclusive = `~const` and `{$modifier}` are mutually exclusive - ast_passes_optional_trait_object = `?Trait` is not permitted in trait object types ast_passes_optional_trait_supertrait = `?Trait` is not permitted in supertraits diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index e0a7b06c05094..056bc4bce5e61 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1207,6 +1207,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { (BoundKind::TraitObject, TraitBoundModifier::Maybe) => { self.dcx().emit_err(errors::OptionalTraitObject { span: poly.span }); } + (BoundKind::TraitObject, TraitBoundModifier::Const(_)) => { + self.dcx().emit_err(errors::ConstBoundTraitObject { span: poly.span }); + } (_, &TraitBoundModifier::MaybeConst(span)) if let Some(reason) = &self.disallow_tilde_const => { @@ -1235,16 +1238,25 @@ impl<'a> Visitor<'a> for AstValidator<'a> { }; self.dcx().emit_err(errors::TildeConstDisallowed { span, reason }); } - (_, TraitBoundModifier::MaybeConstMaybe) => { - self.dcx().emit_err(errors::OptionalConstExclusive { - span: bound.span(), - modifier: "?", - }); - } - (_, TraitBoundModifier::MaybeConstNegative) => { - self.dcx().emit_err(errors::OptionalConstExclusive { + ( + _, + TraitBoundModifier::ConstMaybe + | TraitBoundModifier::ConstNegative + | TraitBoundModifier::MaybeConstMaybe + | TraitBoundModifier::MaybeConstNegative, + ) => { + let (left, right) = match modify { + TraitBoundModifier::ConstMaybe => ("const", "?"), + TraitBoundModifier::ConstNegative => ("const", "!"), + TraitBoundModifier::MaybeConstMaybe => ("~const", "?"), + TraitBoundModifier::MaybeConstNegative => ("~const", "!"), + _ => unreachable!("unexpected trait bound modifier"), + }; + + self.dcx().emit_err(errors::MutuallyExclusiveTraitBoundModifiers { span: bound.span(), - modifier: "!", + left, + right, }); } _ => {} diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 4283fc7c07d1f..b8891ac14995e 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -540,6 +540,13 @@ pub struct OptionalTraitObject { pub span: Span, } +#[derive(Diagnostic)] +#[diag(ast_passes_const_bound_trait_object)] +pub struct ConstBoundTraitObject { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(ast_passes_tilde_const_disallowed)] pub struct TildeConstDisallowed { @@ -580,11 +587,12 @@ pub enum TildeConstReason { } #[derive(Diagnostic)] -#[diag(ast_passes_optional_const_exclusive)] -pub struct OptionalConstExclusive { +#[diag(ast_passes_mutually_exclusive_trait_bound_modifiers)] +pub struct MutuallyExclusiveTraitBoundModifiers { #[primary_span] pub span: Span, - pub modifier: &'static str, + pub left: &'static str, + pub right: &'static str, } #[derive(Diagnostic)] diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index d6c15ec35b603..d00cfd989f14d 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1567,6 +1567,17 @@ impl<'a> State<'a> { TraitBoundModifier::Maybe => { self.word("?"); } + TraitBoundModifier::Const(_) => { + self.word_space("const"); + } + TraitBoundModifier::ConstNegative => { + self.word_space("const"); + self.word("!"); + } + TraitBoundModifier::ConstMaybe => { + self.word_space("const"); + self.word("?"); + } TraitBoundModifier::MaybeConst(_) => { self.word_space("~const"); } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 760945554f068..61e2bf695ed60 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -425,6 +425,7 @@ pub enum TraitBoundModifier { None, Negative, Maybe, + Const, MaybeConst, } diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 139e1c0ac5fdc..7d4ff167c750d 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -70,7 +70,7 @@ hir_analysis_coercion_between_struct_same_note = expected coercion between the s hir_analysis_coercion_between_struct_single_note = expected a single field to be coerced, none found hir_analysis_const_bound_for_non_const_trait = - ~const can only be applied to `#[const_trait]` traits + {$modifier} can only be applied to `#[const_trait]` traits hir_analysis_const_impl_for_non_const_trait = const `impl` for trait `{$trait_name}` which is not marked with `#[const_trait]` diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index 0748644cc0ab9..efb55ed51dd11 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -112,6 +112,9 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { match ast_bound { hir::GenericBound::Trait(poly_trait_ref, modifier) => { let (constness, polarity) = match modifier { + hir::TraitBoundModifier::Const => { + (ty::BoundConstness::Const, ty::ImplPolarity::Positive) + } hir::TraitBoundModifier::MaybeConst => { (ty::BoundConstness::ConstIfConst, ty::ImplPolarity::Positive) } diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index be73c027fdc86..b495b00ec7047 100644 --- a/compiler/rustc_hir_analysis/src/astconv/generics.rs +++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs @@ -262,7 +262,7 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>( // impl const PartialEq for () {} // ``` // - // Since this is a const impl, we need to insert `` at the end of + // Since this is a const impl, we need to insert a host arg at the end of // `PartialEq`'s generics, but this errors since `Rhs` isn't specified. // To work around this, we infer all arguments until we reach the host param. args.push(ctx.inferred_kind(Some(&args), param, infer_args)); diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 6f8e80172dd26..24c863fa0300d 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -378,7 +378,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { assert!(self_ty.is_none()); } - let arg_count = check_generic_arg_count( + let mut arg_count = check_generic_arg_count( tcx, span, def_id, @@ -390,6 +390,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { infer_args, ); + if let ty::BoundConstness::Const | ty::BoundConstness::ConstIfConst = constness + && generics.has_self + && !tcx.has_attr(def_id, sym::const_trait) + { + let reported = tcx.sess.emit_err(crate::errors::ConstBoundForNonConstTrait { + span, + modifier: constness.to_string(), + }); + arg_count.correct = + Err(GenericArgCountMismatch { reported: Some(reported), invalid_args: vec![] }); + } + // Skip processing if type has no generic parameters. // Traits always have `Self` as a generic parameter, which means they will not return early // here and so associated type bindings will be handled regardless of whether there are any @@ -570,13 +582,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &mut args_ctx, ); - if let ty::BoundConstness::ConstIfConst = constness - && generics.has_self - && !tcx.has_attr(def_id, sym::const_trait) - { - tcx.sess.emit_err(crate::errors::ConstBoundForNonConstTrait { span }); - } - (args, arg_count) } diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index f461b6a94eced..8e2875d2b7f8d 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -410,6 +410,7 @@ pub struct ConstImplForNonConstTrait { pub struct ConstBoundForNonConstTrait { #[primary_span] pub span: Span, + pub modifier: String, } #[derive(Diagnostic)] diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 96de9c447b6fc..06886334a396f 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -311,29 +311,19 @@ impl Visibility { pub enum BoundConstness { /// `T: Trait` NotConst, + /// `T: const Trait` + Const, /// `T: ~const Trait` /// /// Requires resolving to const only when we are in a const context. ConstIfConst, } -impl BoundConstness { - /// Reduce `self` and `constness` to two possible combined states instead of four. - pub fn and(&mut self, constness: hir::Constness) -> hir::Constness { - match (constness, self) { - (hir::Constness::Const, BoundConstness::ConstIfConst) => hir::Constness::Const, - (_, this) => { - *this = BoundConstness::NotConst; - hir::Constness::NotConst - } - } - } -} - impl fmt::Display for BoundConstness { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::NotConst => f.write_str("normal"), + Self::Const => f.write_str("`const`"), Self::ConstIfConst => f.write_str("`~const`"), } } diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 363b8f4bfb9cc..c6bddbfacd6ec 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -95,9 +95,6 @@ parse_compound_assignment_expression_in_let = can't reassign to an uninitialized .suggestion = initialize the variable .help = if you meant to overwrite, remove the `let` binding -parse_const_bounds_missing_tilde = const bounds must start with `~` - .suggestion = add `~` - parse_const_generic_without_braces = expressions must be enclosed in braces to be used as const generic arguments .suggestion = enclose the `const` expression in braces @@ -555,8 +552,8 @@ parse_missing_trait_in_trait_impl = missing trait in a trait impl .suggestion_add_trait = add a trait here .suggestion_remove_for = for an inherent impl, drop this `for` -parse_modifier_lifetime = `{$sigil}` may only modify trait bounds, not lifetime bounds - .suggestion = remove the `{$sigil}` +parse_modifier_lifetime = `{$modifier}` may only modify trait bounds, not lifetime bounds + .suggestion = remove the `{$modifier}` parse_more_than_one_char = character literal may only contain one codepoint .followed_by = this `{$chr}` is followed by the combining {$len -> @@ -729,8 +726,6 @@ parse_switch_ref_box_order = switch the order of `ref` and `box` parse_ternary_operator = Rust has no ternary operator .help = use an `if-else` expression instead -parse_tilde_const_lifetime = `~const` may only modify trait bounds, not lifetime bounds - parse_tilde_is_not_unary_operator = `~` cannot be used as a unary operator .suggestion = use `!` to perform bitwise not diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 008adcc83d0ea..8f21f13749aca 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2549,20 +2549,14 @@ pub(crate) struct AssocLifetime { pub lifetime: Span, } -#[derive(Diagnostic)] -#[diag(parse_tilde_const_lifetime)] -pub(crate) struct TildeConstLifetime { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(parse_modifier_lifetime)] pub(crate) struct ModifierLifetime { #[primary_span] - #[suggestion(style = "tool-only", applicability = "maybe-incorrect", code = "")] + #[suggestion(style = "tool-only", applicability = "maybe-incorrect", code = "{padding}")] pub span: Span, - pub sigil: &'static str, + pub modifier: &'static str, + pub padding: &'static str, } #[derive(Diagnostic)] @@ -2575,15 +2569,6 @@ pub(crate) struct ParenthesizedLifetime { pub snippet: String, } -#[derive(Diagnostic)] -#[diag(parse_const_bounds_missing_tilde)] -pub(crate) struct ConstMissingTilde { - #[primary_span] - pub span: Span, - #[suggestion(code = "~", applicability = "machine-applicable")] - pub start: Span, -} - #[derive(Diagnostic)] #[diag(parse_underscore_literal_suffix)] pub(crate) struct UnderscoreLiteralSuffix { diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index da8cc05ff66e8..200512739a249 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -13,8 +13,8 @@ use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; use rustc_ast::util::case::Case; use rustc_ast::{ - self as ast, BareFnTy, BoundPolarity, FnRetTy, GenericBound, GenericBounds, GenericParam, - Generics, Lifetime, MacCall, MutTy, Mutability, PolyTraitRef, TraitBoundModifier, + self as ast, BareFnTy, BoundConstness, BoundPolarity, FnRetTy, GenericBound, GenericBounds, + GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, PolyTraitRef, TraitBoundModifier, TraitObjectSyntax, Ty, TyKind, }; use rustc_errors::{Applicability, PResult}; @@ -22,24 +22,32 @@ use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{Span, Symbol}; use thin_vec::{thin_vec, ThinVec}; -/// Any `?`, `!`, or `~const` modifiers that appear at the start of a bound. +/// Any `?`, `!`, `const` or `~const` modifiers that appear at the start of a bound. struct BoundModifiers { - /// `?Trait`. - bound_polarity: BoundPolarity, - - /// `~const Trait`. - maybe_const: Option, + polarity: BoundPolarity, + constness: BoundConstness, } impl BoundModifiers { fn to_trait_bound_modifier(&self) -> TraitBoundModifier { - match (self.bound_polarity, self.maybe_const) { - (BoundPolarity::Positive, None) => TraitBoundModifier::None, - (BoundPolarity::Negative(_), None) => TraitBoundModifier::Negative, - (BoundPolarity::Maybe(_), None) => TraitBoundModifier::Maybe, - (BoundPolarity::Positive, Some(sp)) => TraitBoundModifier::MaybeConst(sp), - (BoundPolarity::Negative(_), Some(_)) => TraitBoundModifier::MaybeConstNegative, - (BoundPolarity::Maybe(_), Some(_)) => TraitBoundModifier::MaybeConstMaybe, + match (self.polarity, self.constness) { + (BoundPolarity::Positive, BoundConstness::Never) => TraitBoundModifier::None, + (BoundPolarity::Negative(_), BoundConstness::Never) => TraitBoundModifier::Negative, + (BoundPolarity::Maybe(_), BoundConstness::Never) => TraitBoundModifier::Maybe, + (BoundPolarity::Positive, BoundConstness::Always(sp)) => TraitBoundModifier::Const(sp), + (BoundPolarity::Positive, BoundConstness::Maybe(sp)) => { + TraitBoundModifier::MaybeConst(sp) + } + (BoundPolarity::Negative(_), BoundConstness::Always(_)) => { + TraitBoundModifier::ConstNegative + } + (BoundPolarity::Maybe(_), BoundConstness::Always(_)) => TraitBoundModifier::ConstMaybe, + (BoundPolarity::Negative(_), BoundConstness::Maybe(_)) => { + TraitBoundModifier::MaybeConstNegative + } + (BoundPolarity::Maybe(_), BoundConstness::Maybe(_)) => { + TraitBoundModifier::MaybeConstMaybe + } } } } @@ -786,6 +794,7 @@ impl<'a> Parser<'a> { || self.check(&token::Not) || self.check(&token::Question) || self.check(&token::Tilde) + || self.check_keyword(kw::Const) || self.check_keyword(kw::For) || self.check(&token::OpenDelim(Delimiter::Parenthesis)) } @@ -832,17 +841,31 @@ impl<'a> Parser<'a> { /// Emits an error if any trait bound modifiers were present. fn error_lt_bound_with_modifiers(&self, modifiers: BoundModifiers) { - if let Some(span) = modifiers.maybe_const { - self.sess.emit_err(errors::TildeConstLifetime { span }); + match modifiers.constness { + BoundConstness::Never => {} + BoundConstness::Always(span) => { + self.sess.emit_err(errors::ModifierLifetime { + span, + modifier: "const", + padding: " ", + }); + } + BoundConstness::Maybe(span) => { + self.sess.emit_err(errors::ModifierLifetime { + span, + modifier: "~const", + padding: " ", + }); + } } - match modifiers.bound_polarity { + match modifiers.polarity { BoundPolarity::Positive => {} BoundPolarity::Negative(span) => { - self.sess.emit_err(errors::ModifierLifetime { span, sigil: "!" }); + self.sess.emit_err(errors::ModifierLifetime { span, modifier: "!", padding: "" }); } BoundPolarity::Maybe(span) => { - self.sess.emit_err(errors::ModifierLifetime { span, sigil: "?" }); + self.sess.emit_err(errors::ModifierLifetime { span, modifier: "?", padding: "" }); } } } @@ -867,26 +890,23 @@ impl<'a> Parser<'a> { /// If no modifiers are present, this does not consume any tokens. /// /// ```ebnf - /// TY_BOUND_MODIFIERS = ["~const"] ["?"] + /// TY_BOUND_MODIFIERS = ("~"? "const")? ("?" | "!") /// ``` fn parse_ty_bound_modifiers(&mut self) -> PResult<'a, BoundModifiers> { - let maybe_const = if self.eat(&token::Tilde) { + let constness = if self.eat(&token::Tilde) { let tilde = self.prev_token.span; self.expect_keyword(kw::Const)?; let span = tilde.to(self.prev_token.span); self.sess.gated_spans.gate(sym::const_trait_impl, span); - Some(span) + BoundConstness::Maybe(span) } else if self.eat_keyword(kw::Const) { - let span = self.prev_token.span; - self.sess.gated_spans.gate(sym::const_trait_impl, span); - self.sess.emit_err(errors::ConstMissingTilde { span, start: span.shrink_to_lo() }); - - Some(span) + self.sess.gated_spans.gate(sym::const_trait_impl, self.prev_token.span); + BoundConstness::Always(self.prev_token.span) } else { - None + BoundConstness::Never }; - let bound_polarity = if self.eat(&token::Question) { + let polarity = if self.eat(&token::Question) { BoundPolarity::Maybe(self.prev_token.span) } else if self.eat(&token::Not) { self.sess.gated_spans.gate(sym::negative_bounds, self.prev_token.span); @@ -895,7 +915,7 @@ impl<'a> Parser<'a> { BoundPolarity::Positive }; - Ok(BoundModifiers { bound_polarity, maybe_const }) + Ok(BoundModifiers { polarity, constness }) } /// Parses a type bound according to: diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index a9c0ab557cb33..4bb75d17e04f0 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -449,8 +449,8 @@ impl clean::GenericBound { hir::TraitBoundModifier::None => "", hir::TraitBoundModifier::Maybe => "?", hir::TraitBoundModifier::Negative => "!", - // ~const is experimental; do not display those bounds in rustdoc - hir::TraitBoundModifier::MaybeConst => "", + // `{,~}const` is experimental; do not display those bounds in rustdoc + hir::TraitBoundModifier::Const | hir::TraitBoundModifier::MaybeConst => "", }; if f.alternate() { write!(f, "{modifier_str}{ty:#}", ty = ty.print(cx)) diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 61376ab31dd28..f85b0f05e052f 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -547,6 +547,9 @@ pub(crate) fn from_trait_bound_modifier( None => TraitBoundModifier::None, Maybe => TraitBoundModifier::Maybe, MaybeConst => TraitBoundModifier::MaybeConst, + // FIXME(const_trait_impl): Create rjt::TBM::Const and map to it once always-const bounds + // are less experimental. + Const => TraitBoundModifier::None, // FIXME(negative-bounds): This bound should be rendered negative, but // since that's experimental, maybe let's not add it to the rustdoc json // API just now... diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index a5a4244903c4a..7b821cbaebd4b 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -545,6 +545,12 @@ impl Rewrite for ast::GenericBound { ast::TraitBoundModifier::Maybe => poly_trait_ref .rewrite(context, shape.offset_left(1)?) .map(|s| format!("?{}", s)), + ast::TraitBoundModifier::Const(_) => poly_trait_ref + .rewrite(context, shape.offset_left(6)?) + .map(|s| format!("const {}", s)), + ast::TraitBoundModifier::ConstMaybe => poly_trait_ref + .rewrite(context, shape.offset_left(7)?) + .map(|s| format!("const ?{}", s)), ast::TraitBoundModifier::MaybeConst(_) => poly_trait_ref .rewrite(context, shape.offset_left(7)?) .map(|s| format!("~const {}", s)), @@ -554,6 +560,9 @@ impl Rewrite for ast::GenericBound { ast::TraitBoundModifier::Negative => poly_trait_ref .rewrite(context, shape.offset_left(1)?) .map(|s| format!("!{}", s)), + ast::TraitBoundModifier::ConstNegative => poly_trait_ref + .rewrite(context, shape.offset_left(7)?) + .map(|s| format!("const !{}", s)), ast::TraitBoundModifier::MaybeConstNegative => poly_trait_ref .rewrite(context, shape.offset_left(8)?) .map(|s| format!("~const !{}", s)), diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr index e5ebe1d852861..e6ea4108f4045 100644 --- a/tests/ui/consts/fn_trait_refs.stderr +++ b/tests/ui/consts/fn_trait_refs.stderr @@ -4,13 +4,13 @@ error[E0635]: unknown feature `const_fn_trait_ref_impls` LL | #![feature(const_fn_trait_ref_impls)] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/fn_trait_refs.rs:15:15 | LL | T: ~const Fn<()> + ~const Destruct, | ^^^^^^ -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/fn_trait_refs.rs:15:15 | LL | T: ~const Fn<()> + ~const Destruct, @@ -18,13 +18,13 @@ LL | T: ~const Fn<()> + ~const Destruct, | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/fn_trait_refs.rs:22:15 | LL | T: ~const FnMut<()> + ~const Destruct, | ^^^^^^^^^ -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/fn_trait_refs.rs:22:15 | LL | T: ~const FnMut<()> + ~const Destruct, @@ -32,13 +32,13 @@ LL | T: ~const FnMut<()> + ~const Destruct, | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/fn_trait_refs.rs:29:15 | LL | T: ~const FnOnce<()>, | ^^^^^^^^^^ -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/fn_trait_refs.rs:29:15 | LL | T: ~const FnOnce<()>, @@ -46,13 +46,13 @@ LL | T: ~const FnOnce<()>, | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/fn_trait_refs.rs:36:15 | LL | T: ~const Fn<()> + ~const Destruct, | ^^^^^^ -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/fn_trait_refs.rs:36:15 | LL | T: ~const Fn<()> + ~const Destruct, @@ -60,13 +60,13 @@ LL | T: ~const Fn<()> + ~const Destruct, | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/fn_trait_refs.rs:50:15 | LL | T: ~const FnMut<()> + ~const Destruct, | ^^^^^^^^^ -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/fn_trait_refs.rs:50:15 | LL | T: ~const FnMut<()> + ~const Destruct, diff --git a/tests/ui/consts/unstable-const-fn-in-libcore.stderr b/tests/ui/consts/unstable-const-fn-in-libcore.stderr index 4b649bf43ed3d..08147a4afaf37 100644 --- a/tests/ui/consts/unstable-const-fn-in-libcore.stderr +++ b/tests/ui/consts/unstable-const-fn-in-libcore.stderr @@ -1,4 +1,4 @@ -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/unstable-const-fn-in-libcore.rs:19:39 | LL | const fn unwrap_or_else T>(self, f: F) -> T { diff --git a/tests/ui/generic-const-items/const-trait-impl.rs b/tests/ui/generic-const-items/const-trait-impl.rs index 43cdf818c4694..04c3f3eb4340f 100644 --- a/tests/ui/generic-const-items/const-trait-impl.rs +++ b/tests/ui/generic-const-items/const-trait-impl.rs @@ -1,14 +1,12 @@ -// known-bug: #110395 -// FIXME check-pass +// check-pass // Test that we can call methods from const trait impls inside of generic const items. -#![feature(generic_const_items, const_trait_impl)] +#![feature(generic_const_items, const_trait_impl, effects)] #![allow(incomplete_features)] #![crate_type = "lib"] -// FIXME(generic_const_items, effects): Introduce `const` bounds to make this work. -const CREATE: T = T::create(); +const CREATE: T = T::create(); pub const K0: i32 = CREATE::; pub const K1: i32 = CREATE; // arg inferred @@ -23,3 +21,13 @@ impl const Create for i32 { 4096 } } + +trait Mod { // doesn't need to be a `#[const_trait]` + const CREATE: T; +} + +impl Mod for () { + const CREATE: T = T::create(); +} + +pub const K2: i32 = <() as Mod>::CREATE::; diff --git a/tests/ui/generic-const-items/const-trait-impl.stderr b/tests/ui/generic-const-items/const-trait-impl.stderr deleted file mode 100644 index e7e905427960b..0000000000000 --- a/tests/ui/generic-const-items/const-trait-impl.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0015]: cannot call non-const fn `::create` in constants - --> $DIR/const-trait-impl.rs:11:30 - | -LL | const CREATE: T = T::create(); - | ^^^^^^^^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr index e0513433b8ec1..7fd2ec57b1455 100644 --- a/tests/ui/impl-trait/normalize-tait-in-const.stderr +++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr @@ -1,4 +1,4 @@ -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/normalize-tait-in-const.rs:25:42 | LL | const fn with_positive Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { diff --git a/tests/ui/parser/bounds-type.rs b/tests/ui/parser/bounds-type.rs index 4ae4549ea5896..bd5f6105f51a2 100644 --- a/tests/ui/parser/bounds-type.rs +++ b/tests/ui/parser/bounds-type.rs @@ -13,6 +13,7 @@ struct S< T: ~const ?Tr, // OK T: ~const Tr + 'a, // OK T: ~const 'a, //~ ERROR `~const` may only modify trait bounds, not lifetime bounds + T: const 'a, //~ ERROR `const` may only modify trait bounds, not lifetime bounds >; fn main() {} diff --git a/tests/ui/parser/bounds-type.stderr b/tests/ui/parser/bounds-type.stderr index 005bc1e54bd00..d1210e88d6678 100644 --- a/tests/ui/parser/bounds-type.stderr +++ b/tests/ui/parser/bounds-type.stderr @@ -10,5 +10,11 @@ error: `~const` may only modify trait bounds, not lifetime bounds LL | T: ~const 'a, | ^^^^^^ -error: aborting due to 2 previous errors +error: `const` may only modify trait bounds, not lifetime bounds + --> $DIR/bounds-type.rs:16:8 + | +LL | T: const 'a, + | ^^^^^ + +error: aborting due to 3 previous errors diff --git a/tests/ui/parser/trait-object-delimiters.rs b/tests/ui/parser/trait-object-delimiters.rs index e9b13defe0384..240ae3084d68e 100644 --- a/tests/ui/parser/trait-object-delimiters.rs +++ b/tests/ui/parser/trait-object-delimiters.rs @@ -8,7 +8,7 @@ fn foo2(_: &dyn (Drop + AsRef)) {} //~ ERROR incorrect parentheses around t fn foo2_no_space(_: &dyn(Drop + AsRef)) {} //~ ERROR incorrect parentheses around trait bounds fn foo3(_: &dyn {Drop + AsRef}) {} //~ ERROR expected parameter name, found `{` -//~^ ERROR expected one of `!`, `(`, `)`, `*`, `,`, `?`, `for`, `~`, lifetime, or path, found `{` +//~^ ERROR expected one of `!`, `(`, `)`, `*`, `,`, `?`, `const`, `for`, `~`, lifetime, or path, found `{` //~| ERROR at least one trait is required for an object type fn foo4(_: &dyn >) {} //~ ERROR expected identifier, found `<` diff --git a/tests/ui/parser/trait-object-delimiters.stderr b/tests/ui/parser/trait-object-delimiters.stderr index 519546750938b..2ddb734cee067 100644 --- a/tests/ui/parser/trait-object-delimiters.stderr +++ b/tests/ui/parser/trait-object-delimiters.stderr @@ -34,11 +34,11 @@ error: expected parameter name, found `{` LL | fn foo3(_: &dyn {Drop + AsRef}) {} | ^ expected parameter name -error: expected one of `!`, `(`, `)`, `*`, `,`, `?`, `for`, `~`, lifetime, or path, found `{` +error: expected one of `!`, `(`, `)`, `*`, `,`, `?`, `const`, `for`, `~`, lifetime, or path, found `{` --> $DIR/trait-object-delimiters.rs:10:17 | LL | fn foo3(_: &dyn {Drop + AsRef}) {} - | -^ expected one of 10 possible tokens + | -^ expected one of 11 possible tokens | | | help: missing `,` diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr index 290ef6e2f5fa0..58ad1849d4fab 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr @@ -6,7 +6,7 @@ LL | type Bar: ~const std::ops::Add; | = note: this item cannot have `~const` trait bounds -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/assoc-type.rs:17:22 | LL | type Bar: ~const std::ops::Add; diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bounds-non-const-trait.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bounds-non-const-trait.rs new file mode 100644 index 0000000000000..3582e5e050c98 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bounds-non-const-trait.rs @@ -0,0 +1,12 @@ +// Regression test for issue #117244. +#![feature(const_trait_impl, effects)] + +trait NonConst {} + +const fn perform() {} +//~^ ERROR `~const` can only be applied to `#[const_trait]` traits + +fn operate() {} +//~^ ERROR `const` can only be applied to `#[const_trait]` traits + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bounds-non-const-trait.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bounds-non-const-trait.stderr new file mode 100644 index 0000000000000..08954987d3192 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-bounds-non-const-trait.stderr @@ -0,0 +1,14 @@ +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/const-bounds-non-const-trait.rs:6:28 + | +LL | const fn perform() {} + | ^^^^^^^^ + +error: `const` can only be applied to `#[const_trait]` traits + --> $DIR/const-bounds-non-const-trait.rs:9:21 + | +LL | fn operate() {} + | ^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-parse-not-item.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-parse-not-item.stderr index fc9b5557a6496..ace2e7e46c4e8 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-parse-not-item.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-parse-not-item.stderr @@ -1,4 +1,4 @@ -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/const-closure-parse-not-item.rs:7:32 | LL | const fn test() -> impl ~const Fn() { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr index 73ee0f2151a73..d70b0d66177eb 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr @@ -1,4 +1,4 @@ -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/const-closure-trait-method-fail.rs:14:39 | LL | const fn need_const_closure i32>(x: T) -> i32 { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr index 33ae7131b928e..1642de78692b7 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr @@ -1,4 +1,4 @@ -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/const-closure-trait-method.rs:14:39 | LL | const fn need_const_closure i32>(x: T) -> i32 { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr index 6d61b23e4b7c3..2e448c64d7a40 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr @@ -1,22 +1,22 @@ -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/const-closures.rs:8:19 | LL | F: ~const FnOnce() -> u8, | ^^^^^^^^^^^^^^ -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/const-closures.rs:9:19 | LL | F: ~const FnMut() -> u8, | ^^^^^^^^^^^^^ -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/const-closures.rs:10:19 | LL | F: ~const Fn() -> u8, | ^^^^^^^^^^ -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/const-closures.rs:23:27 | LL | const fn answer u8>(f: &F) -> u8 { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.precise.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.precise.stderr index 13350a6d14a42..7529af9293d44 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.precise.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.precise.stderr @@ -7,7 +7,7 @@ LL | impl const Drop for ConstDropImplWithBounds { = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/const-drop-fail-2.rs:29:26 | LL | const fn check(_: T) {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stock.stderr index 13350a6d14a42..7529af9293d44 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stock.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail-2.stock.stderr @@ -7,7 +7,7 @@ LL | impl const Drop for ConstDropImplWithBounds { = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/const-drop-fail-2.rs:29:26 | LL | const fn check(_: T) {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr index daaba08d7dde9..f166bdf6cecce 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr @@ -1,10 +1,15 @@ -error: `~const` is not allowed here - --> $DIR/const-drop.rs:67:38 +error[E0493]: destructor of `T` cannot be evaluated at compile-time + --> $DIR/const-drop.rs:19:32 | -LL | pub struct ConstDropWithBound(pub core::marker::PhantomData); - | ^^^^^^ +LL | const fn a(_: T) {} + | ^ the destructor for this type cannot be evaluated in constant functions + +error[E0493]: destructor of `S<'_>` cannot be evaluated at compile-time + --> $DIR/const-drop.rs:24:13 | - = note: this item cannot have `~const` trait bounds +LL | let _ = S(&mut c); + | ^^^^^^^^^ the destructor for this type cannot be evaluated in constant functions -error: aborting due to 1 previous error +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.rs index 9da84cdb0525b..4836d2b02ce71 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.rs @@ -4,7 +4,7 @@ #![feature(const_trait_impl)] #![feature(const_mut_refs)] #![feature(never_type)] -// #![cfg_attr(precise, feature(const_precise_live_drops))] +#![cfg_attr(precise, feature(const_precise_live_drops))] use std::marker::Destruct; @@ -63,8 +63,7 @@ mod t { fn foo() {} } - // FIXME(effects): This should be a `const` bound instead of a `~const` one. - pub struct ConstDropWithBound(pub core::marker::PhantomData); + pub struct ConstDropWithBound(pub core::marker::PhantomData); impl const Drop for ConstDropWithBound { fn drop(&mut self) { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr index daaba08d7dde9..23e368870258e 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr @@ -1,10 +1,19 @@ -error: `~const` is not allowed here - --> $DIR/const-drop.rs:67:38 +error[E0493]: destructor of `T` cannot be evaluated at compile-time + --> $DIR/const-drop.rs:19:32 | -LL | pub struct ConstDropWithBound(pub core::marker::PhantomData); - | ^^^^^^ +LL | const fn a(_: T) {} + | ^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions + +error[E0493]: destructor of `S<'_>` cannot be evaluated at compile-time + --> $DIR/const-drop.rs:24:13 | - = note: this item cannot have `~const` trait bounds +LL | let _ = S(&mut c); + | ^^^^^^^^^- value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions -error: aborting due to 1 previous error +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds-trait-objects.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds-trait-objects.rs new file mode 100644 index 0000000000000..3a2a3951e59a6 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds-trait-objects.rs @@ -0,0 +1,8 @@ +#![feature(const_trait_impl)] + +#[const_trait] +trait Trait {} + +fn main() { + let _: &dyn (const Trait); //~ ERROR const trait bounds are not allowed in trait object types +} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds-trait-objects.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds-trait-objects.stderr new file mode 100644 index 0000000000000..a3b615b37f376 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds-trait-objects.stderr @@ -0,0 +1,8 @@ +error: const trait bounds are not allowed in trait object types + --> $DIR/const-trait-bounds-trait-objects.rs:7:17 + | +LL | let _: &dyn (const Trait); + | ^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds.rs new file mode 100644 index 0000000000000..1ebebe632c70a --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds.rs @@ -0,0 +1,31 @@ +// check-pass + +#![feature(const_trait_impl, effects, generic_const_exprs)] +#![allow(incomplete_features)] + +fn main() { + let _ = process::<()>([()]); + let _ = Struct::<(), 4> { field: [1, 0] }; +} + +fn process(input: [(); T::make(2)]) -> [(); T::make(2)] { + input +} + +struct Struct +where + [u32; T::make(P)]:, +{ + field: [u32; T::make(P)], +} + +#[const_trait] +trait Trait { + fn make(input: usize) -> usize; +} + +impl const Trait for () { + fn make(input: usize) -> usize { + input / 2 + } +} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.gated.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.gated.stderr index 663cdd1fe57bb..12f9355e41d4e 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.gated.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.gated.stderr @@ -1,5 +1,5 @@ error: fatal error triggered by #[rustc_error] - --> $DIR/feature-gate.rs:14:1 + --> $DIR/feature-gate.rs:22:1 | LL | fn main() {} | ^^^^^^^^^ diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.rs index 0b409fbaac9e0..015d90aaf21fa 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.rs @@ -10,5 +10,13 @@ trait T {} impl const T for S {} //[stock]~^ ERROR const trait impls are experimental +const fn f() {} //[stock]~ ERROR const trait impls are experimental +fn g() {} //[stock]~ ERROR const trait impls are experimental + +macro_rules! discard { ($ty:ty) => {} } + +discard! { impl ~const T } //[stock]~ ERROR const trait impls are experimental +discard! { impl const T } //[stock]~ ERROR const trait impls are experimental + #[rustc_error] fn main() {} //[gated]~ ERROR fatal error triggered by #[rustc_error] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.stock.stderr index 0e938c1c55d05..c9826aeb1665f 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.stock.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/feature-gate.stock.stderr @@ -7,6 +7,42 @@ LL | impl const T for S {} = note: see issue #67792 for more information = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable +error[E0658]: const trait impls are experimental + --> $DIR/feature-gate.rs:13:15 + | +LL | const fn f() {} + | ^^^^^^ + | + = note: see issue #67792 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0658]: const trait impls are experimental + --> $DIR/feature-gate.rs:14:9 + | +LL | fn g() {} + | ^^^^^ + | + = note: see issue #67792 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0658]: const trait impls are experimental + --> $DIR/feature-gate.rs:18:17 + | +LL | discard! { impl ~const T } + | ^^^^^^ + | + = note: see issue #67792 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0658]: const trait impls are experimental + --> $DIR/feature-gate.rs:19:17 + | +LL | discard! { impl const T } + | ^^^^^ + | + = note: see issue #67792 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + error[E0658]: `const_trait` is a temporary placeholder for marking a trait that is suitable for `const` `impls` and all default bodies as `const`, which may be removed or renamed in the future. --> $DIR/feature-gate.rs:8:1 | @@ -16,6 +52,6 @@ LL | #[const_trait] = note: see issue #67792 for more information = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable -error: aborting due to 2 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/mutually-exclusive-trait-bound-modifiers.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/mutually-exclusive-trait-bound-modifiers.rs new file mode 100644 index 0000000000000..37e285f2c6590 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/mutually-exclusive-trait-bound-modifiers.rs @@ -0,0 +1,20 @@ +#![feature(const_trait_impl)] + +const fn maybe_const_maybe() {} +//~^ ERROR `~const` and `?` are mutually exclusive + +fn const_maybe() {} +//~^ ERROR `const` and `?` are mutually exclusive + +const fn maybe_const_negative() {} +//~^ ERROR `~const` and `!` are mutually exclusive +//~| ERROR negative bounds are not supported + +fn const_negative() {} +//~^ ERROR `const` and `!` are mutually exclusive +//~| ERROR negative bounds are not supported + +#[const_trait] +trait Trait {} + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/mutually-exclusive-trait-bound-modifiers.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/mutually-exclusive-trait-bound-modifiers.stderr new file mode 100644 index 0000000000000..1938f740170b5 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/mutually-exclusive-trait-bound-modifiers.stderr @@ -0,0 +1,38 @@ +error: `~const` and `?` are mutually exclusive + --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:3:31 + | +LL | const fn maybe_const_maybe() {} + | ^^^^^^^^^^^^^ + +error: `const` and `?` are mutually exclusive + --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:6:19 + | +LL | fn const_maybe() {} + | ^^^^^^^^^^^^ + +error: `~const` and `!` are mutually exclusive + --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:9:34 + | +LL | const fn maybe_const_negative() {} + | ^^^^^^^^^^^^^ + +error: `const` and `!` are mutually exclusive + --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:13:22 + | +LL | fn const_negative() {} + | ^^^^^^^^^^^^ + +error: negative bounds are not supported + --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:9:41 + | +LL | const fn maybe_const_negative() {} + | ^ + +error: negative bounds are not supported + --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:13:28 + | +LL | fn const_negative() {} + | ^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.stderr index b2e09d82a905e..ae76cab2f2e66 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.stderr @@ -1,4 +1,4 @@ -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/non-const-op-in-closure-in-const.rs:10:51 | LL | impl const Convert for A where B: ~const From { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr index 12bcdb034bc23..d74a3faccdde5 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr @@ -10,13 +10,13 @@ note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bou LL | trait Bar: ~const Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/super-traits-fail-2.rs:11:19 | LL | trait Bar: ~const Foo {} | ^^^ -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/super-traits-fail-2.rs:11:19 | LL | trait Bar: ~const Foo {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr index b60399c57dca9..c3e35159e2ec1 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr @@ -1,10 +1,10 @@ -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/super-traits-fail-2.rs:11:19 | LL | trait Bar: ~const Foo {} | ^^^ -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/super-traits-fail-2.rs:11:19 | LL | trait Bar: ~const Foo {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.rs index 93fd96f8f2942..9c258b250be6b 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-2.rs @@ -9,8 +9,8 @@ trait Foo { #[cfg_attr(any(yy, ny), const_trait)] trait Bar: ~const Foo {} -// FIXME [ny,nn]~^ ERROR: ~const can only be applied to `#[const_trait]` -// FIXME [ny,nn]~| ERROR: ~const can only be applied to `#[const_trait]` +// FIXME [ny,nn]~^ ERROR: `~const` can only be applied to `#[const_trait]` +// FIXME [ny,nn]~| ERROR: `~const` can only be applied to `#[const_trait]` const fn foo(x: &T) { x.a(); diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr index e10c51ef45aba..83229b5540fc6 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr @@ -10,13 +10,13 @@ note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bou LL | trait Bar: ~const Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/super-traits-fail-3.rs:13:19 | LL | trait Bar: ~const Foo {} | ^^^ -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/super-traits-fail-3.rs:13:19 | LL | trait Bar: ~const Foo {} @@ -24,7 +24,7 @@ LL | trait Bar: ~const Foo {} | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/super-traits-fail-3.rs:18:24 | LL | const fn foo(x: &T) { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr index cd0ee73277d60..9f6d79f3c311c 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr @@ -1,10 +1,10 @@ -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/super-traits-fail-3.rs:13:19 | LL | trait Bar: ~const Foo {} | ^^^ -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/super-traits-fail-3.rs:13:19 | LL | trait Bar: ~const Foo {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs index 5994057b2db2e..6631c544b21d5 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.rs @@ -11,12 +11,12 @@ trait Foo { #[cfg_attr(any(yy, ny), const_trait)] trait Bar: ~const Foo {} -//[ny,nn]~^ ERROR: ~const can only be applied to `#[const_trait]` -//[ny,nn]~| ERROR: ~const can only be applied to `#[const_trait]` +//[ny,nn]~^ ERROR: `~const` can only be applied to `#[const_trait]` +//[ny,nn]~| ERROR: `~const` can only be applied to `#[const_trait]` //[yn,nn]~^^^ ERROR: `~const` is not allowed here const fn foo(x: &T) { - //[yn,nn]~^ ERROR: ~const can only be applied to `#[const_trait]` + //[yn,nn]~^ ERROR: `~const` can only be applied to `#[const_trait]` x.a(); } diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr index 34f6515b572ec..f25a9a19e08e5 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr @@ -10,7 +10,7 @@ note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bou LL | trait Bar: ~const Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/super-traits-fail-3.rs:18:24 | LL | const fn foo(x: &T) { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.rs deleted file mode 100644 index ed911d965d631..0000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.rs +++ /dev/null @@ -1,6 +0,0 @@ -#![feature(const_trait_impl)] - -const fn tilde_question() {} -//~^ ERROR `~const` and `?` are mutually exclusive - -fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.stderr deleted file mode 100644 index 5850ab41c6ba6..0000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-maybe-trait.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: `~const` and `?` are mutually exclusive - --> $DIR/tilde-const-maybe-trait.rs:3:28 - | -LL | const fn tilde_question() {} - | ^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-on-non-const-trait.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-on-non-const-trait.rs new file mode 100644 index 0000000000000..c5736c16add7e --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-on-non-const-trait.rs @@ -0,0 +1,9 @@ +// Regression test for issue #117244. +#![feature(const_trait_impl, effects)] + +trait NonConst {} + +const fn perform() {} +//~^ ERROR `~const` can only be applied to `#[const_trait]` traits + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-on-non-const-trait.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-on-non-const-trait.stderr new file mode 100644 index 0000000000000..bd2d45f08ab25 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-on-non-const-trait.stderr @@ -0,0 +1,8 @@ +error: `~const` can only be applied to `#[const_trait]` traits + --> $DIR/tilde-const-on-non-const-trait.rs:6:28 + | +LL | const fn perform() {} + | ^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/without-tilde.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/without-tilde.rs deleted file mode 100644 index d63381b5f2cc9..0000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/without-tilde.rs +++ /dev/null @@ -1,6 +0,0 @@ -// compile-flags: -Z parse-only - -#![feature(const_trait_impl)] - -struct S; -//~^ ERROR const bounds must start with `~` diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/without-tilde.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/without-tilde.stderr deleted file mode 100644 index 646cdfc78f971..0000000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/without-tilde.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: const bounds must start with `~` - --> $DIR/without-tilde.rs:5:13 - | -LL | struct S; - | -^^^^ - | | - | help: add `~`: `~` - -error: aborting due to 1 previous error - diff --git a/tests/ui/specialization/const_trait_impl.stderr b/tests/ui/specialization/const_trait_impl.stderr index d13cd8f55553d..913d51875cd70 100644 --- a/tests/ui/specialization/const_trait_impl.stderr +++ b/tests/ui/specialization/const_trait_impl.stderr @@ -1,16 +1,16 @@ -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/const_trait_impl.rs:34:16 | LL | impl const A for T { | ^^^^^^^ -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/const_trait_impl.rs:40:16 | LL | impl const A for T { | ^^^^^^^ -error: ~const can only be applied to `#[const_trait]` traits +error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/const_trait_impl.rs:46:16 | LL | impl const A for T {