about summary refs log tree commit diff
path: root/compiler/rustc_const_eval/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_const_eval/src')
-rw-r--r--compiler/rustc_const_eval/src/check_consts/check.rs10
-rw-r--r--compiler/rustc_const_eval/src/check_consts/ops.rs18
-rw-r--r--compiler/rustc_const_eval/src/errors.rs9
3 files changed, 33 insertions, 4 deletions
diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs
index 06d6a5a5af5..ed34996a7a7 100644
--- a/compiler/rustc_const_eval/src/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/check_consts/check.rs
@@ -464,6 +464,12 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
             err_span,
         );
     }
+
+    fn crate_inject_span(&self) -> Option<Span> {
+        self.tcx.hir_crate_items(()).definitions().next().and_then(|id| {
+            self.tcx.crate_level_attribute_injection_span(self.tcx.local_def_id_to_hir_id(id))
+        })
+    }
 }
 
 impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
@@ -809,6 +815,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                                 name: intrinsic.name,
                                 feature,
                                 const_stable_indirect: is_const_stable,
+                                suggestion: self.crate_inject_span(),
                             });
                         }
                         Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => {
@@ -897,7 +904,7 @@ 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.
@@ -907,6 +914,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                                 feature,
                                 feature_enabled,
                                 safe_to_expose_on_stable: callee_safe_to_expose_on_stable,
+                                suggestion_span: self.crate_inject_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..3c83a7b92cd 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<Span>,
 }
 
 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
     }
@@ -436,6 +447,7 @@ pub(crate) struct IntrinsicUnstable {
     pub name: Symbol,
     pub feature: Symbol,
     pub const_stable_indirect: bool,
+    pub suggestion: Option<Span>,
 }
 
 impl<'tcx> NonConstOp<'tcx> for IntrinsicUnstable {
@@ -455,6 +467,8 @@ impl<'tcx> NonConstOp<'tcx> for IntrinsicUnstable {
             span,
             name: self.name,
             feature: self.feature,
+            suggestion: self.suggestion,
+            help: self.suggestion.is_none(),
         })
     }
 }
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index 3fe78171cd9..1ee9214c4b2 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -123,12 +123,19 @@ pub(crate) struct UnstableConstFn {
 
 #[derive(Diagnostic)]
 #[diag(const_eval_unstable_intrinsic)]
-#[help]
 pub(crate) struct UnstableIntrinsic {
     #[primary_span]
     pub span: Span,
     pub name: Symbol,
     pub feature: Symbol,
+    #[suggestion(
+        const_eval_unstable_intrinsic_suggestion,
+        code = "#![feature({feature})]\n",
+        applicability = "machine-applicable"
+    )]
+    pub suggestion: Option<Span>,
+    #[help(const_eval_unstable_intrinsic_suggestion)]
+    pub help: bool,
 }
 
 #[derive(Diagnostic)]