diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 20382a81f14..a463fe7b970 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -63,3 +63,27 @@ pub(crate) struct PanicNonStrErr { #[primary_span] pub span: Span, } + +#[derive(SessionDiagnostic)] +#[error(const_eval::mut_deref, code = "E0658")] +pub(crate) struct MutDerefErr { + #[primary_span] + pub span: Span, + pub kind: ConstContext, +} + +#[derive(SessionDiagnostic)] +#[error(const_eval::transient_mut_borrow, code = "E0658")] +pub(crate) struct TransientMutBorrowErr { + #[primary_span] + pub span: Span, + pub kind: ConstContext, +} + +#[derive(SessionDiagnostic)] +#[error(const_eval::transient_mut_borrow_raw, code = "E0658")] +pub(crate) struct TransientMutBorrowErrRaw { + #[primary_span] + pub span: Span, + pub kind: ConstContext, +} diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index 181dbacdc82..17376e59e09 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -23,7 +23,8 @@ use rustc_trait_selection::traits::SelectionContext; use super::ConstCx; use crate::errors::{ - NonConstOpErr, PanicNonStrErr, RawPtrComparisonErr, RawPtrToIntErr, StaticAccessErr, + MutDerefErr, NonConstOpErr, PanicNonStrErr, RawPtrComparisonErr, RawPtrToIntErr, + StaticAccessErr, TransientMutBorrowErr, TransientMutBorrowErrRaw, }; use crate::util::{call_kind, CallDesugaringKind, CallKind}; @@ -595,17 +596,17 @@ impl<'tcx> NonConstOp<'tcx> for TransientMutBorrow { ccx: &ConstCx<'_, 'tcx>, span: Span, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - let raw = match self.0 { - hir::BorrowKind::Raw => "raw ", - hir::BorrowKind::Ref => "", - }; - - feature_err( - &ccx.tcx.sess.parse_sess, - sym::const_mut_refs, - span, - &format!("{}mutable references are not allowed in {}s", raw, ccx.const_kind()), - ) + let kind = ccx.const_kind(); + match self.0 { + hir::BorrowKind::Raw => ccx + .tcx + .sess + .create_feature_err(TransientMutBorrowErrRaw { span, kind }, sym::const_mut_refs), + hir::BorrowKind::Ref => ccx + .tcx + .sess + .create_feature_err(TransientMutBorrowErr { span, kind }, sym::const_mut_refs), + } } } @@ -626,12 +627,9 @@ impl<'tcx> NonConstOp<'tcx> for MutDeref { ccx: &ConstCx<'_, 'tcx>, span: Span, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - feature_err( - &ccx.tcx.sess.parse_sess, - sym::const_mut_refs, - span, - &format!("mutation through a reference is not allowed in {}s", ccx.const_kind()), - ) + ccx.tcx + .sess + .create_feature_err(MutDerefErr { span, kind: ccx.const_kind() }, sym::const_mut_refs) } } diff --git a/compiler/rustc_error_messages/locales/en-US/const_eval.ftl b/compiler/rustc_error_messages/locales/en-US/const_eval.ftl index 30de7d5a24f..f1a8c8c47cc 100644 --- a/compiler/rustc_error_messages/locales/en-US/const_eval.ftl +++ b/compiler/rustc_error_messages/locales/en-US/const_eval.ftl @@ -26,3 +26,22 @@ const-eval-raw-ptr-comparison = .note = see issue #53020 for more information const-eval-panic-non-str = argument to `panic!()` in a const context must have type `&str` + +const-eval-mut-deref = + mutation through a reference is not allowed in { $kind -> + [constant function] constant functions + [static] statics + *[constant] constants + } + +const-eval-transient-mut-borrow = mutable references are not allowed in { $kind -> + [constant function] constant functions + [static] statics + *[constant] constants + } + +const-eval-transient-mut-borrow-raw = raw mutable references are not allowed in { $kind -> + [constant function] constant functions + [static] statics + *[constant] constants + } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 2a5ddd4e9e4..edce70d19cc 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -2,7 +2,7 @@ use crate::cgu_reuse_tracker::CguReuseTracker; use crate::code_stats::CodeStats; pub use crate::code_stats::{DataTypeKind, FieldInfo, SizeKind, VariantInfo}; use crate::config::{self, CrateType, OutputType, SwitchWithOptPath}; -use crate::parse::ParseSess; +use crate::parse::{add_feature_diagnostics, ParseSess}; use crate::search_paths::{PathKind, SearchPath}; use crate::{filesearch, lint}; @@ -458,6 +458,15 @@ impl Session { ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { self.parse_sess.create_err(err) } + pub fn create_feature_err<'a>( + &'a self, + err: impl SessionDiagnostic<'a>, + feature: Symbol, + ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + let mut err = self.parse_sess.create_err(err); + add_feature_diagnostics(&mut err, &self.parse_sess, feature); + err + } pub fn emit_err<'a>(&'a self, err: impl SessionDiagnostic<'a>) -> ErrorGuaranteed { self.parse_sess.emit_err(err) }