| use std::borrow::Cow; | |
| use rustc_errors::codes::*; | |
| use rustc_errors::formatting::DiagMessageAddArg; | |
| use rustc_errors::{Diag, DiagArgValue, EmissionGuarantee, MultiSpan, Subdiagnostic, msg}; | |
| use rustc_hir::ConstContext; | |
| use rustc_macros::{Diagnostic, Subdiagnostic}; | |
| use rustc_middle::ty::{Mutability, Ty}; | |
| use rustc_span::{Span, Symbol}; | |
| use crate::interpret::InternKind; | |
| #[derive(Diagnostic)] | |
| #[diag( | |
| r#"encountered dangling pointer in final value of {$kind -> | |
| [static] static | |
| [static_mut] mutable static | |
| [const] constant | |
| [promoted] promoted | |
| *[other] {""} | |
| }"# | |
| )] | |
| pub(crate) struct DanglingPtrInFinal { | |
| #[primary_span] | |
| pub span: Span, | |
| pub kind: InternKind, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag( | |
| "#[thread_local] does not support implicit nested statics, please create explicit static items and refer to them instead" | |
| )] | |
| pub(crate) struct NestedStaticInThreadLocal { | |
| #[primary_span] | |
| pub span: Span, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag( | |
| r#"encountered mutable pointer in final value of {$kind -> | |
| [static] static | |
| [static_mut] mutable static | |
| [const] constant | |
| [promoted] promoted | |
| *[other] {""} | |
| }"# | |
| )] | |
| pub(crate) struct MutablePtrInFinal { | |
| #[primary_span] | |
| pub span: Span, | |
| pub kind: InternKind, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag("encountered `const_allocate` pointer in final value that was not made global")] | |
| #[note( | |
| "use `const_make_global` to turn allocated pointers into immutable globals before returning" | |
| )] | |
| pub(crate) struct ConstHeapPtrInFinal { | |
| #[primary_span] | |
| pub span: Span, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag( | |
| r#"encountered partial pointer in final value of {$kind -> | |
| [static] static | |
| [static_mut] mutable static | |
| [const] constant | |
| [promoted] promoted | |
| *[other] {""} | |
| }"# | |
| )] | |
| #[note( | |
| "while pointers can be broken apart into individual bytes during const-evaluation, only complete pointers (with all their bytes in the right order) are supported in the final value" | |
| )] | |
| pub(crate) struct PartialPtrInFinal { | |
| #[primary_span] | |
| pub span: Span, | |
| pub kind: InternKind, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag( | |
| "const function that might be (indirectly) exposed to stable cannot use `#[feature({$gate})]`" | |
| )] | |
| pub(crate) struct UnstableInStableExposed { | |
| pub gate: String, | |
| #[primary_span] | |
| pub span: Span, | |
| #[help( | |
| "mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features" | |
| )] | |
| pub is_function_call: bool, | |
| /// Need to duplicate the field so that fluent also provides it as a variable... | |
| pub is_function_call2: bool, | |
| #[suggestion( | |
| "if the {$is_function_call2 -> | |
| [true] caller | |
| *[false] function | |
| } is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`", | |
| code = "#[rustc_const_unstable(feature = \"...\", issue = \"...\")]\n", | |
| applicability = "has-placeholders" | |
| )] | |
| pub attr_span: Span, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag("thread-local statics cannot be accessed at compile-time", code = E0625)] | |
| pub(crate) struct ThreadLocalAccessErr { | |
| #[primary_span] | |
| pub span: Span, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag("pointers cannot be cast to integers during const eval")] | |
| #[note("at compile-time, pointers do not have an integer value")] | |
| #[note( | |
| "avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior" | |
| )] | |
| pub(crate) struct RawPtrToIntErr { | |
| #[primary_span] | |
| pub span: Span, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag("pointers cannot be reliably compared during const eval")] | |
| #[note("see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information")] | |
| pub(crate) struct RawPtrComparisonErr { | |
| #[primary_span] | |
| pub span: Span, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag("argument to `panic!()` in a const context must have type `&str`")] | |
| pub(crate) struct PanicNonStrErr { | |
| #[primary_span] | |
| pub span: Span, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag(r#"function pointer calls are not allowed in {$kind}s"#)] | |
| pub(crate) struct UnallowedFnPointerCall { | |
| #[primary_span] | |
| pub span: Span, | |
| pub kind: ConstContext, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag("`{$def_path}` is not yet stable as a const fn")] | |
| pub(crate) struct UnstableConstFn { | |
| #[primary_span] | |
| pub span: Span, | |
| pub def_path: String, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag("`{$def_path}` is not yet stable as a const trait")] | |
| pub(crate) struct UnstableConstTrait { | |
| #[primary_span] | |
| pub span: Span, | |
| pub def_path: String, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag("`{$name}` is not yet stable as a const intrinsic")] | |
| pub(crate) struct UnstableIntrinsic { | |
| #[primary_span] | |
| pub span: Span, | |
| pub name: Symbol, | |
| pub feature: Symbol, | |
| #[suggestion( | |
| "add `#![feature({$feature})]` to the crate attributes to enable", | |
| code = "#![feature({feature})]\n", | |
| applicability = "machine-applicable" | |
| )] | |
| pub suggestion: Span, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag("`{$def_path}` cannot be (indirectly) exposed to stable")] | |
| #[help( | |
| "either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]`" | |
| )] | |
| pub(crate) struct UnmarkedConstItemExposed { | |
| #[primary_span] | |
| pub span: Span, | |
| pub def_path: String, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag("intrinsic `{$def_path}` cannot be (indirectly) exposed to stable")] | |
| #[help( | |
| "mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_intrinsic_const_stable_indirect]` (but this requires team approval)" | |
| )] | |
| pub(crate) struct UnmarkedIntrinsicExposed { | |
| #[primary_span] | |
| pub span: Span, | |
| pub def_path: String, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag("mutable borrows of temporaries that have their lifetime extended until the end of the program are not allowed", code = E0764)] | |
| #[note( | |
| "temporaries in constants and statics can have their lifetime extended until the end of the program" | |
| )] | |
| #[note("to avoid accidentally creating global mutable state, such temporaries must be immutable")] | |
| #[help( | |
| "if you really want global mutable state, try replacing the temporary by an interior mutable `static` or a `static mut`" | |
| )] | |
| pub(crate) struct MutableBorrowEscaping { | |
| #[primary_span] | |
| #[label("this mutable borrow refers to such a temporary")] | |
| pub span: Span, | |
| pub kind: ConstContext, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag( | |
| r#"cannot call {$non_or_conditionally}-const formatting macro in {$kind}s"#, | |
| code = E0015, | |
| )] | |
| pub(crate) struct NonConstFmtMacroCall { | |
| #[primary_span] | |
| pub span: Span, | |
| pub kind: ConstContext, | |
| pub non_or_conditionally: &'static str, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag(r#"cannot call {$non_or_conditionally}-const {$def_descr} `{$def_path_str}` in {$kind}s"#, code = E0015)] | |
| pub(crate) struct NonConstFnCall { | |
| #[primary_span] | |
| pub span: Span, | |
| pub def_path_str: String, | |
| pub def_descr: &'static str, | |
| pub kind: ConstContext, | |
| pub non_or_conditionally: &'static str, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag(r#"cannot call non-const intrinsic `{$name}` in {$kind}s"#)] | |
| pub(crate) struct NonConstIntrinsic { | |
| #[primary_span] | |
| pub span: Span, | |
| pub name: Symbol, | |
| pub kind: ConstContext, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag("{$msg}")] | |
| pub(crate) struct UnallowedOpInConstContext { | |
| #[primary_span] | |
| pub span: Span, | |
| pub msg: String, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag(r#"inline assembly is not allowed in {$kind}s"#, code = E0015)] | |
| pub(crate) struct UnallowedInlineAsm { | |
| #[primary_span] | |
| pub span: Span, | |
| pub kind: ConstContext, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag("interior mutable shared borrows of temporaries that have their lifetime extended until the end of the program are not allowed", code = E0492)] | |
| #[note( | |
| "temporaries in constants and statics can have their lifetime extended until the end of the program" | |
| )] | |
| #[note("to avoid accidentally creating global mutable state, such temporaries must be immutable")] | |
| #[help( | |
| "if you really want global mutable state, try replacing the temporary by an interior mutable `static` or a `static mut`" | |
| )] | |
| pub(crate) struct InteriorMutableBorrowEscaping { | |
| #[primary_span] | |
| #[label("this borrow of an interior mutable value refers to such a temporary")] | |
| pub span: Span, | |
| pub kind: ConstContext, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag("constant evaluation is taking a long time")] | |
| #[note( | |
| "this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. | |
| If your compilation actually takes a long time, you can safely allow the lint" | |
| )] | |
| pub(crate) struct LongRunning { | |
| #[help("the constant being evaluated")] | |
| pub item_span: Span, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag("constant evaluation is taking a long time")] | |
| pub(crate) struct LongRunningWarn { | |
| #[primary_span] | |
| #[label("the const evaluator is currently interpreting this expression")] | |
| pub span: Span, | |
| #[help("the constant being evaluated")] | |
| pub item_span: Span, | |
| } | |
| #[derive(Subdiagnostic)] | |
| #[note("impl defined here, but it is not `const`")] | |
| pub(crate) struct NonConstImplNote { | |
| #[primary_span] | |
| pub span: Span, | |
| } | |
| #[derive(Clone)] | |
| pub(crate) struct FrameNote { | |
| 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<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) { | |
| let mut span: MultiSpan = self.span.into(); | |
| if self.has_label && !self.span.is_dummy() { | |
| span.push_span_label(self.span, msg!("the failure occurred here")); | |
| } | |
| let msg = msg!( | |
| r#"{$times -> | |
| [0] inside {$where_ -> | |
| [closure] closure | |
| [instance] `{$instance}` | |
| *[other] {""} | |
| } | |
| *[other] [... {$times} additional calls inside {$where_ -> | |
| [closure] closure | |
| [instance] `{$instance}` | |
| *[other] {""} | |
| } ...] | |
| }"# | |
| ) | |
| .arg("times", self.times) | |
| .arg("where_", self.where_) | |
| .arg("instance", self.instance) | |
| .format(); | |
| diag.span_note(span, msg); | |
| } | |
| } | |
| #[derive(Subdiagnostic)] | |
| #[note(r#"the raw bytes of the constant (size: {$size}, align: {$align}) {"{"}{$bytes}{"}"}"#)] | |
| pub(crate) struct RawBytesNote { | |
| pub size: u64, | |
| pub align: u64, | |
| pub bytes: String, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag(r#"cannot match on `{$ty}` in {$kind}s"#)] | |
| #[note("`{$ty}` cannot be compared in compile-time, and therefore cannot be used in `match`es")] | |
| pub(crate) struct NonConstMatchEq<'tcx> { | |
| #[primary_span] | |
| pub span: Span, | |
| pub ty: Ty<'tcx>, | |
| pub kind: ConstContext, | |
| pub non_or_conditionally: &'static str, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag(r#"cannot use `for` loop on `{$ty}` in {$kind}s"#, code = E0015)] | |
| pub(crate) struct NonConstForLoopIntoIter<'tcx> { | |
| #[primary_span] | |
| pub span: Span, | |
| pub ty: Ty<'tcx>, | |
| pub kind: ConstContext, | |
| pub non_or_conditionally: &'static str, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag(r#"`?` is not allowed on `{$ty}` in {$kind}s"#, code = E0015)] | |
| pub(crate) struct NonConstQuestionBranch<'tcx> { | |
| #[primary_span] | |
| pub span: Span, | |
| pub ty: Ty<'tcx>, | |
| pub kind: ConstContext, | |
| pub non_or_conditionally: &'static str, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag(r#"`?` is not allowed on `{$ty}` in {$kind}s"#, code = E0015)] | |
| pub(crate) struct NonConstQuestionFromResidual<'tcx> { | |
| #[primary_span] | |
| pub span: Span, | |
| pub ty: Ty<'tcx>, | |
| pub kind: ConstContext, | |
| pub non_or_conditionally: &'static str, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag(r#"`try` block cannot convert `{$ty}` to the result in {$kind}s"#, code = E0015)] | |
| pub(crate) struct NonConstTryBlockFromOutput<'tcx> { | |
| #[primary_span] | |
| pub span: Span, | |
| pub ty: Ty<'tcx>, | |
| pub kind: ConstContext, | |
| pub non_or_conditionally: &'static str, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag(r#"cannot convert `{$ty}` into a future in {$kind}s"#, code = E0015)] | |
| pub(crate) struct NonConstAwait<'tcx> { | |
| #[primary_span] | |
| pub span: Span, | |
| pub ty: Ty<'tcx>, | |
| pub kind: ConstContext, | |
| pub non_or_conditionally: &'static str, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag(r#"cannot call {$non_or_conditionally}-const closure in {$kind}s"#, code = E0015)] | |
| pub(crate) struct NonConstClosure { | |
| #[primary_span] | |
| pub span: Span, | |
| pub kind: ConstContext, | |
| #[subdiagnostic] | |
| pub note: Option<NonConstClosureNote>, | |
| pub non_or_conditionally: &'static str, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag(r#"calling const c-variadic functions is unstable in {$kind}s"#, code = E0015)] | |
| pub(crate) struct NonConstCVariadicCall { | |
| #[primary_span] | |
| pub span: Span, | |
| pub kind: ConstContext, | |
| } | |
| #[derive(Subdiagnostic)] | |
| pub(crate) enum NonConstClosureNote { | |
| #[note("function defined here, but it is not `const`")] | |
| FnDef { | |
| #[primary_span] | |
| span: Span, | |
| }, | |
| #[note(r#"function pointers need an RFC before allowed to be called in {$kind}s"#)] | |
| FnPtr { kind: ConstContext }, | |
| #[note(r#"closures need an RFC before allowed to be called in {$kind}s"#)] | |
| Closure { kind: ConstContext }, | |
| } | |
| #[derive(Subdiagnostic)] | |
| #[multipart_suggestion("consider dereferencing here", applicability = "machine-applicable")] | |
| pub(crate) struct ConsiderDereferencing { | |
| pub deref: String, | |
| #[suggestion_part(code = "{deref}")] | |
| pub span: Span, | |
| #[suggestion_part(code = "{deref}")] | |
| pub rhs_span: Span, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag(r#"cannot call {$non_or_conditionally}-const operator in {$kind}s"#, code = E0015)] | |
| pub(crate) struct NonConstOperator { | |
| #[primary_span] | |
| pub span: Span, | |
| pub kind: ConstContext, | |
| #[subdiagnostic] | |
| pub sugg: Option<ConsiderDereferencing>, | |
| pub non_or_conditionally: &'static str, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag(r#"cannot perform {$non_or_conditionally}-const deref coercion on `{$ty}` in {$kind}s"#, code = E0015)] | |
| #[note("attempting to deref into `{$target_ty}`")] | |
| pub(crate) struct NonConstDerefCoercion<'tcx> { | |
| #[primary_span] | |
| pub span: Span, | |
| pub ty: Ty<'tcx>, | |
| pub kind: ConstContext, | |
| pub target_ty: Ty<'tcx>, | |
| #[note("deref defined here")] | |
| pub deref_target: Option<Span>, | |
| pub non_or_conditionally: &'static str, | |
| } | |
| #[derive(Diagnostic)] | |
| #[diag("destructor of `{$dropped_ty}` cannot be evaluated at compile-time", code = E0493)] | |
| pub(crate) struct LiveDrop<'tcx> { | |
| #[primary_span] | |
| #[label(r#"the destructor for this type cannot be evaluated in {$kind}s"#)] | |
| pub span: Span, | |
| pub kind: ConstContext, | |
| pub dropped_ty: Ty<'tcx>, | |
| #[label("value is dropped here")] | |
| pub dropped_at: Span, | |
| } | |
| impl rustc_errors::IntoDiagArg for InternKind { | |
| fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue { | |
| DiagArgValue::Str(Cow::Borrowed(match self { | |
| InternKind::Static(Mutability::Not) => "static", | |
| InternKind::Static(Mutability::Mut) => "static_mut", | |
| InternKind::Constant => "const", | |
| InternKind::Promoted => "promoted", | |
| })) | |
| } | |
| } |