about summary refs log tree commit diff
path: root/compiler/rustc_const_eval
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_const_eval')
-rw-r--r--compiler/rustc_const_eval/messages.ftl5
-rw-r--r--compiler/rustc_const_eval/src/check_consts/mod.rs5
-rw-r--r--compiler/rustc_const_eval/src/const_eval/error.rs21
-rw-r--r--compiler/rustc_const_eval/src/errors.rs25
-rw-r--r--compiler/rustc_const_eval/src/interpret/stack.rs10
5 files changed, 54 insertions, 12 deletions
diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl
index eecc6690f51..ccf9b240d40 100644
--- a/compiler/rustc_const_eval/messages.ftl
+++ b/compiler/rustc_const_eval/messages.ftl
@@ -109,6 +109,8 @@ const_eval_frame_note_inner = inside {$where_ ->
     *[other] {""}
 }
 
+const_eval_frame_note_last = the failure occurred here
+
 const_eval_in_bounds_test = out-of-bounds pointer use
 const_eval_incompatible_calling_conventions =
     calling a function with calling convention {$callee_conv} using calling convention {$caller_conv}
@@ -300,8 +302,7 @@ const_eval_overflow_arith =
 const_eval_overflow_shift =
     overflowing shift by {$shift_amount} in `{$intrinsic}`
 
-const_eval_panic =
-    the evaluated program panicked at '{$msg}', {$file}:{$line}:{$col}
+const_eval_panic = evaluation panicked: {$msg}
 
 const_eval_panic_non_str = argument to `panic!()` in a const context must have type `&str`
 
diff --git a/compiler/rustc_const_eval/src/check_consts/mod.rs b/compiler/rustc_const_eval/src/check_consts/mod.rs
index 659d4a30456..607cb2e497d 100644
--- a/compiler/rustc_const_eval/src/check_consts/mod.rs
+++ b/compiler/rustc_const_eval/src/check_consts/mod.rs
@@ -94,6 +94,11 @@ pub fn rustc_allow_const_fn_unstable(
 /// world into two functions: those that are safe to expose on stable (and hence may not use
 /// unstable features, not even recursively), and those that are not.
 pub fn is_fn_or_trait_safe_to_expose_on_stable(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+    // A default body in a `#[const_trait]` is const-stable when the trait is const-stable.
+    if tcx.is_const_default_method(def_id) {
+        return is_fn_or_trait_safe_to_expose_on_stable(tcx, tcx.parent(def_id));
+    }
+
     match tcx.lookup_const_stability(def_id) {
         None => {
             // In a `staged_api` crate, we do enforce recursive const stability for all unmarked
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index 3e32336d8fc..ffb32fa41eb 100644
--- a/compiler/rustc_const_eval/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
@@ -48,11 +48,8 @@ impl MachineStopType for ConstEvalErrKind {
             | ModifiedGlobal
             | WriteThroughImmutablePointer => {}
             AssertFailure(kind) => kind.add_args(adder),
-            Panic { msg, line, col, file } => {
+            Panic { msg, .. } => {
                 adder("msg".into(), msg.into_diag_arg(&mut None));
-                adder("file".into(), file.into_diag_arg(&mut None));
-                adder("line".into(), line.into_diag_arg(&mut None));
-                adder("col".into(), col.into_diag_arg(&mut None));
             }
         }
     }
@@ -72,7 +69,7 @@ pub fn get_span_and_frames<'tcx>(
     let mut stacktrace = Frame::generate_stacktrace_from_stack(stack);
     // Filter out `requires_caller_location` frames.
     stacktrace.retain(|frame| !frame.instance.def.requires_caller_location(*tcx));
-    let span = stacktrace.first().map(|f| f.span).unwrap_or(tcx.span);
+    let span = stacktrace.last().map(|f| f.span).unwrap_or(tcx.span);
 
     let mut frames = Vec::new();
 
@@ -115,6 +112,20 @@ pub fn get_span_and_frames<'tcx>(
         }
     }
 
+    // In `rustc`, we present const-eval errors from the outer-most place first to the inner-most.
+    // So we reverse the frames here. The first frame will be the same as the span from the current
+    // `TyCtxtAt<'_>`, so we remove it as it would be redundant.
+    frames.reverse();
+    if frames.len() > 0 {
+        frames.remove(0);
+    }
+    if let Some(last) = frames.last_mut()
+        // If the span is not going to be printed, we don't want the span label for `is_last`.
+        && tcx.sess.source_map().span_to_snippet(last.span.source_callsite()).is_ok()
+    {
+        last.has_label = true;
+    }
+
     (span, frames)
 }
 
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index ef756e58c5e..b020eeccf71 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -6,6 +6,7 @@ use rustc_abi::WrappingRange;
 use rustc_errors::codes::*;
 use rustc_errors::{
     Diag, DiagArgValue, DiagCtxtHandle, DiagMessage, Diagnostic, EmissionGuarantee, Level,
+    MultiSpan, SubdiagMessageOp, Subdiagnostic,
 };
 use rustc_hir::ConstContext;
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
@@ -17,6 +18,7 @@ use rustc_middle::mir::interpret::{
 use rustc_middle::ty::{self, Mutability, Ty};
 use rustc_span::{Span, Symbol};
 
+use crate::fluent_generated as fluent;
 use crate::interpret::InternKind;
 
 #[derive(Diagnostic)]
@@ -278,14 +280,31 @@ pub(crate) struct NonConstImplNote {
     pub span: Span,
 }
 
-#[derive(Subdiagnostic, Clone)]
-#[note(const_eval_frame_note)]
+#[derive(Clone)]
 pub struct FrameNote {
-    #[primary_span]
     pub span: Span,
     pub times: i32,
     pub where_: &'static str,
     pub instance: String,
+    pub has_label: bool,
+}
+
+impl Subdiagnostic for FrameNote {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+        self,
+        diag: &mut Diag<'_, G>,
+        f: &F,
+    ) {
+        diag.arg("times", self.times);
+        diag.arg("where_", self.where_);
+        diag.arg("instance", self.instance);
+        let mut span: MultiSpan = self.span.into();
+        if self.has_label && !self.span.is_dummy() {
+            span.push_span_label(self.span, fluent::const_eval_frame_note_last);
+        }
+        let msg = f(diag, fluent::const_eval_frame_note.into());
+        diag.span_note(span, msg);
+    }
 }
 
 #[derive(Subdiagnostic)]
diff --git a/compiler/rustc_const_eval/src/interpret/stack.rs b/compiler/rustc_const_eval/src/interpret/stack.rs
index 7d0e0492792..d7b03776bc4 100644
--- a/compiler/rustc_const_eval/src/interpret/stack.rs
+++ b/compiler/rustc_const_eval/src/interpret/stack.rs
@@ -231,13 +231,19 @@ impl<'tcx> FrameInfo<'tcx> {
     pub fn as_note(&self, tcx: TyCtxt<'tcx>) -> errors::FrameNote {
         let span = self.span;
         if tcx.def_key(self.instance.def_id()).disambiguated_data.data == DefPathData::Closure {
-            errors::FrameNote { where_: "closure", span, instance: String::new(), times: 0 }
+            errors::FrameNote {
+                where_: "closure",
+                span,
+                instance: String::new(),
+                times: 0,
+                has_label: false,
+            }
         } else {
             let instance = format!("{}", self.instance);
             // Note: this triggers a `must_produce_diag` state, which means that if we ever get
             // here we must emit a diagnostic. We should never display a `FrameInfo` unless we
             // actually want to emit a warning or error to the user.
-            errors::FrameNote { where_: "instance", span, instance, times: 0 }
+            errors::FrameNote { where_: "instance", span, instance, times: 0, has_label: false }
         }
     }
 }