use rustc_errors::{ Applicability, DecorateLint, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, Handler, IntoDiagnostic, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::mir::{AssertKind, UnsafetyViolationDetails}; use rustc_session::lint::{self, Lint}; use rustc_span::Span; #[derive(LintDiagnostic)] pub(crate) enum ConstMutate { #[diag(mir_transform_const_modify)] #[note] Modify { #[note(mir_transform_const_defined_here)] konst: Span, }, #[diag(mir_transform_const_mut_borrow)] #[note] #[note(mir_transform_note2)] MutBorrow { #[note(mir_transform_note3)] method_call: Option, #[note(mir_transform_const_defined_here)] konst: Span, }, } #[derive(Diagnostic)] #[diag(mir_transform_unaligned_packed_ref, code = "E0793")] #[note] #[note(mir_transform_note_ub)] #[help] pub(crate) struct UnalignedPackedRef { #[primary_span] pub span: Span, } #[derive(LintDiagnostic)] #[diag(mir_transform_unused_unsafe)] pub(crate) struct UnusedUnsafe { #[label(mir_transform_unused_unsafe)] pub span: Span, #[label] pub nested_parent: Option, } pub(crate) struct RequiresUnsafe { pub span: Span, pub details: RequiresUnsafeDetail, pub enclosing: Option, pub op_in_unsafe_fn_allowed: bool, } // The primary message for this diagnostic should be '{$label} is unsafe and...', // so we need to eagerly translate the label here, which isn't supported by the derive API // We could also exhaustively list out the primary messages for all unsafe violations, // but this would result in a lot of duplication. impl<'sess, G: EmissionGuarantee> IntoDiagnostic<'sess, G> for RequiresUnsafe { #[track_caller] fn into_diagnostic(self, handler: &'sess Handler) -> DiagnosticBuilder<'sess, G> { let mut diag = handler.struct_diagnostic(crate::fluent_generated::mir_transform_requires_unsafe); diag.code(rustc_errors::DiagnosticId::Error("E0133".to_string())); diag.set_span(self.span); diag.span_label(self.span, self.details.label()); diag.note(self.details.note()); let desc = handler.eagerly_translate_to_string(self.details.label(), [].into_iter()); diag.set_arg("details", desc); diag.set_arg("op_in_unsafe_fn_allowed", self.op_in_unsafe_fn_allowed); if let Some(sp) = self.enclosing { diag.span_label(sp, crate::fluent_generated::mir_transform_not_inherited); } diag } } #[derive(Copy, Clone)] pub(crate) struct RequiresUnsafeDetail { pub span: Span, pub violation: UnsafetyViolationDetails, } impl RequiresUnsafeDetail { fn note(self) -> DiagnosticMessage { use UnsafetyViolationDetails::*; match self.violation { CallToUnsafeFunction => crate::fluent_generated::mir_transform_call_to_unsafe_note, UseOfInlineAssembly => crate::fluent_generated::mir_transform_use_of_asm_note, InitializingTypeWith => { crate::fluent_generated::mir_transform_initializing_valid_range_note } CastOfPointerToInt => crate::fluent_generated::mir_transform_const_ptr2int_note, UseOfMutableStatic => crate::fluent_generated::mir_transform_use_of_static_mut_note, UseOfExternStatic => crate::fluent_generated::mir_transform_use_of_extern_static_note, DerefOfRawPointer => crate::fluent_generated::mir_transform_deref_ptr_note, AccessToUnionField => crate::fluent_generated::mir_transform_union_access_note, MutationOfLayoutConstrainedField => { crate::fluent_generated::mir_transform_mutation_layout_constrained_note } BorrowOfLayoutConstrainedField => { crate::fluent_generated::mir_transform_mutation_layout_constrained_borrow_note } CallToFunctionWith => crate::fluent_generated::mir_transform_target_feature_call_note, } } fn label(self) -> DiagnosticMessage { use UnsafetyViolationDetails::*; match self.violation { CallToUnsafeFunction => crate::fluent_generated::mir_transform_call_to_unsafe_label, UseOfInlineAssembly => crate::fluent_generated::mir_transform_use_of_asm_label, InitializingTypeWith => { crate::fluent_generated::mir_transform_initializing_valid_range_label } CastOfPointerToInt => crate::fluent_generated::mir_transform_const_ptr2int_label, UseOfMutableStatic => crate::fluent_generated::mir_transform_use_of_static_mut_label, UseOfExternStatic => crate::fluent_generated::mir_transform_use_of_extern_static_label, DerefOfRawPointer => crate::fluent_generated::mir_transform_deref_ptr_label, AccessToUnionField => crate::fluent_generated::mir_transform_union_access_label, MutationOfLayoutConstrainedField => { crate::fluent_generated::mir_transform_mutation_layout_constrained_label } BorrowOfLayoutConstrainedField => { crate::fluent_generated::mir_transform_mutation_layout_constrained_borrow_label } CallToFunctionWith => crate::fluent_generated::mir_transform_target_feature_call_label, } } } pub(crate) struct UnsafeOpInUnsafeFn { pub details: RequiresUnsafeDetail, /// These spans point to: /// 1. the start of the function body /// 2. the end of the function body /// 3. the function signature pub suggest_unsafe_block: Option<(Span, Span, Span)>, } impl<'a> DecorateLint<'a, ()> for UnsafeOpInUnsafeFn { #[track_caller] fn decorate_lint<'b>( self, diag: &'b mut DiagnosticBuilder<'a, ()>, ) -> &'b mut DiagnosticBuilder<'a, ()> { let handler = diag.handler().expect("lint should not yet be emitted"); let desc = handler.eagerly_translate_to_string(self.details.label(), [].into_iter()); diag.set_arg("details", desc); diag.span_label(self.details.span, self.details.label()); diag.note(self.details.note()); if let Some((start, end, fn_sig)) = self.suggest_unsafe_block { diag.span_note(fn_sig, crate::fluent_generated::mir_transform_note); diag.tool_only_multipart_suggestion( crate::fluent_generated::mir_transform_suggestion, vec![(start, " unsafe {".into()), (end, "}".into())], Applicability::MaybeIncorrect, ); } diag } fn msg(&self) -> DiagnosticMessage { crate::fluent_generated::mir_transform_unsafe_op_in_unsafe_fn } } pub(crate) enum AssertLint

{ ArithmeticOverflow(Span, AssertKind

), UnconditionalPanic(Span, AssertKind

), } impl<'a, P: std::fmt::Debug> DecorateLint<'a, ()> for AssertLint

{ fn decorate_lint<'b>( self, diag: &'b mut DiagnosticBuilder<'a, ()>, ) -> &'b mut DiagnosticBuilder<'a, ()> { let span = self.span(); let assert_kind = self.panic(); let message = assert_kind.diagnostic_message(); assert_kind.add_args(&mut |name, value| { diag.set_arg(name, value); }); diag.span_label(span, message); diag } fn msg(&self) -> DiagnosticMessage { match self { AssertLint::ArithmeticOverflow(..) => { crate::fluent_generated::mir_transform_arithmetic_overflow } AssertLint::UnconditionalPanic(..) => { crate::fluent_generated::mir_transform_operation_will_panic } } } } impl

AssertLint

{ pub fn lint(&self) -> &'static Lint { match self { AssertLint::ArithmeticOverflow(..) => lint::builtin::ARITHMETIC_OVERFLOW, AssertLint::UnconditionalPanic(..) => lint::builtin::UNCONDITIONAL_PANIC, } } pub fn span(&self) -> Span { match self { AssertLint::ArithmeticOverflow(sp, _) | AssertLint::UnconditionalPanic(sp, _) => *sp, } } pub fn panic(self) -> AssertKind

{ match self { AssertLint::ArithmeticOverflow(_, p) | AssertLint::UnconditionalPanic(_, p) => p, } } } #[derive(LintDiagnostic)] #[diag(mir_transform_ffi_unwind_call)] pub(crate) struct FfiUnwindCall { #[label(mir_transform_ffi_unwind_call)] pub span: Span, pub foreign: bool, } #[derive(LintDiagnostic)] #[diag(mir_transform_fn_item_ref)] pub(crate) struct FnItemRef { #[suggestion(code = "{sugg}", applicability = "unspecified")] pub span: Span, pub sugg: String, pub ident: String, } #[derive(LintDiagnostic)] #[diag(mir_transform_must_not_suspend)] pub(crate) struct MustNotSupend<'a> { #[label] pub yield_sp: Span, #[subdiagnostic] pub reason: Option, #[help] pub src_sp: Span, pub pre: &'a str, pub def_path: String, pub post: &'a str, } #[derive(Subdiagnostic)] #[note(mir_transform_note)] pub(crate) struct MustNotSuspendReason { #[primary_span] pub span: Span, pub reason: String, } #[derive(Diagnostic)] #[diag(mir_transform_simd_shuffle_last_const)] pub(crate) struct SimdShuffleLastConst { #[primary_span] pub span: Span, }