diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 6c940124193..94fb039512a 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -911,16 +911,23 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // regular stability. feature == sym::rustc_private && issue == NonZero::new(27812) - && self.tcx.sess.opts.unstable_opts.force_unstable_if_unmarked + && tcx.sess.opts.unstable_opts.force_unstable_if_unmarked }; // Even if the feature is enabled, we still need check_op to double-check // this if the callee is not safe to expose on stable. if !feature_enabled || !callee_safe_to_expose_on_stable { + let suggestion_span = + tcx.hir_crate_items(()).definitions().next().and_then(|id| { + tcx.crate_level_attribute_injection_span( + tcx.local_def_id_to_hir_id(id), + ) + }); self.check_op(ops::FnCallUnstable { def_id: callee, feature, feature_enabled, safe_to_expose_on_stable: callee_safe_to_expose_on_stable, + suggestion_span, }); } } diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index 7d103055a7c..6a7da13b303 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -1,8 +1,8 @@ //! Concrete error types for all operations which may be invalid in a certain const context. use hir::{ConstContext, LangItem}; -use rustc_errors::Diag; use rustc_errors::codes::*; +use rustc_errors::{Applicability, Diag}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_infer::infer::TyCtxtInferExt; @@ -388,6 +388,7 @@ pub(crate) struct FnCallUnstable { /// expose on stable. pub feature_enabled: bool, pub safe_to_expose_on_stable: bool, + pub suggestion_span: Option, } impl<'tcx> NonConstOp<'tcx> for FnCallUnstable { @@ -407,8 +408,18 @@ impl<'tcx> NonConstOp<'tcx> for FnCallUnstable { def_path: ccx.tcx.def_path_str(self.def_id), }); // FIXME: make this translatable + let msg = format!("add `#![feature({})]` to the crate attributes to enable", self.feature); #[allow(rustc::untranslatable_diagnostic)] - err.help(format!("add `#![feature({})]` to the crate attributes to enable", self.feature)); + if let Some(span) = self.suggestion_span { + err.span_suggestion_verbose( + span, + msg, + format!("#![feature({})]\n", self.feature), + Applicability::MachineApplicable, + ); + } else { + err.help(msg); + } err } diff --git a/tests/ui/stability-attribute/const-stability-attribute-implies-no-feature.stderr b/tests/ui/stability-attribute/const-stability-attribute-implies-no-feature.stderr index 0a5f58288fa..0f2006e932b 100644 --- a/tests/ui/stability-attribute/const-stability-attribute-implies-no-feature.stderr +++ b/tests/ui/stability-attribute/const-stability-attribute-implies-no-feature.stderr @@ -4,7 +4,10 @@ error: `foobar` is not yet stable as a const fn LL | foobar(); | ^^^^^^^^ | - = help: add `#![feature(const_foobar)]` to the crate attributes to enable +help: add `#![feature(const_foobar)]` to the crate attributes to enable + | +LL + #![feature(const_foobar)] + | error: aborting due to 1 previous error