1 use rustc_errors::{ 2 Applicability, DecorateLint, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, Handler, 3 IntoDiagnostic, 4 }; 5 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; 6 use rustc_middle::mir::{AssertKind, UnsafetyViolationDetails}; 7 use rustc_session::lint::{self, Lint}; 8 use rustc_span::Span; 9 10 #[derive(LintDiagnostic)] 11 pub(crate) enum ConstMutate { 12 #[diag(mir_transform_const_modify)] 13 #[note] 14 Modify { 15 #[note(mir_transform_const_defined_here)] 16 konst: Span, 17 }, 18 #[diag(mir_transform_const_mut_borrow)] 19 #[note] 20 #[note(mir_transform_note2)] 21 MutBorrow { 22 #[note(mir_transform_note3)] 23 method_call: Option<Span>, 24 #[note(mir_transform_const_defined_here)] 25 konst: Span, 26 }, 27 } 28 29 #[derive(Diagnostic)] 30 #[diag(mir_transform_unaligned_packed_ref, code = "E0793")] 31 #[note] 32 #[note(mir_transform_note_ub)] 33 #[help] 34 pub(crate) struct UnalignedPackedRef { 35 #[primary_span] 36 pub span: Span, 37 } 38 39 #[derive(LintDiagnostic)] 40 #[diag(mir_transform_unused_unsafe)] 41 pub(crate) struct UnusedUnsafe { 42 #[label(mir_transform_unused_unsafe)] 43 pub span: Span, 44 #[label] 45 pub nested_parent: Option<Span>, 46 } 47 48 pub(crate) struct RequiresUnsafe { 49 pub span: Span, 50 pub details: RequiresUnsafeDetail, 51 pub enclosing: Option<Span>, 52 pub op_in_unsafe_fn_allowed: bool, 53 } 54 55 // The primary message for this diagnostic should be '{$label} is unsafe and...', 56 // so we need to eagerly translate the label here, which isn't supported by the derive API 57 // We could also exhaustively list out the primary messages for all unsafe violations, 58 // but this would result in a lot of duplication. 59 impl<'sess, G: EmissionGuarantee> IntoDiagnostic<'sess, G> for RequiresUnsafe { 60 #[track_caller] into_diagnostic(self, handler: &'sess Handler) -> DiagnosticBuilder<'sess, G>61 fn into_diagnostic(self, handler: &'sess Handler) -> DiagnosticBuilder<'sess, G> { 62 let mut diag = 63 handler.struct_diagnostic(crate::fluent_generated::mir_transform_requires_unsafe); 64 diag.code(rustc_errors::DiagnosticId::Error("E0133".to_string())); 65 diag.set_span(self.span); 66 diag.span_label(self.span, self.details.label()); 67 diag.note(self.details.note()); 68 let desc = handler.eagerly_translate_to_string(self.details.label(), [].into_iter()); 69 diag.set_arg("details", desc); 70 diag.set_arg("op_in_unsafe_fn_allowed", self.op_in_unsafe_fn_allowed); 71 if let Some(sp) = self.enclosing { 72 diag.span_label(sp, crate::fluent_generated::mir_transform_not_inherited); 73 } 74 diag 75 } 76 } 77 78 #[derive(Copy, Clone)] 79 pub(crate) struct RequiresUnsafeDetail { 80 pub span: Span, 81 pub violation: UnsafetyViolationDetails, 82 } 83 84 impl RequiresUnsafeDetail { note(self) -> DiagnosticMessage85 fn note(self) -> DiagnosticMessage { 86 use UnsafetyViolationDetails::*; 87 match self.violation { 88 CallToUnsafeFunction => crate::fluent_generated::mir_transform_call_to_unsafe_note, 89 UseOfInlineAssembly => crate::fluent_generated::mir_transform_use_of_asm_note, 90 InitializingTypeWith => { 91 crate::fluent_generated::mir_transform_initializing_valid_range_note 92 } 93 CastOfPointerToInt => crate::fluent_generated::mir_transform_const_ptr2int_note, 94 UseOfMutableStatic => crate::fluent_generated::mir_transform_use_of_static_mut_note, 95 UseOfExternStatic => crate::fluent_generated::mir_transform_use_of_extern_static_note, 96 DerefOfRawPointer => crate::fluent_generated::mir_transform_deref_ptr_note, 97 AccessToUnionField => crate::fluent_generated::mir_transform_union_access_note, 98 MutationOfLayoutConstrainedField => { 99 crate::fluent_generated::mir_transform_mutation_layout_constrained_note 100 } 101 BorrowOfLayoutConstrainedField => { 102 crate::fluent_generated::mir_transform_mutation_layout_constrained_borrow_note 103 } 104 CallToFunctionWith => crate::fluent_generated::mir_transform_target_feature_call_note, 105 } 106 } 107 label(self) -> DiagnosticMessage108 fn label(self) -> DiagnosticMessage { 109 use UnsafetyViolationDetails::*; 110 match self.violation { 111 CallToUnsafeFunction => crate::fluent_generated::mir_transform_call_to_unsafe_label, 112 UseOfInlineAssembly => crate::fluent_generated::mir_transform_use_of_asm_label, 113 InitializingTypeWith => { 114 crate::fluent_generated::mir_transform_initializing_valid_range_label 115 } 116 CastOfPointerToInt => crate::fluent_generated::mir_transform_const_ptr2int_label, 117 UseOfMutableStatic => crate::fluent_generated::mir_transform_use_of_static_mut_label, 118 UseOfExternStatic => crate::fluent_generated::mir_transform_use_of_extern_static_label, 119 DerefOfRawPointer => crate::fluent_generated::mir_transform_deref_ptr_label, 120 AccessToUnionField => crate::fluent_generated::mir_transform_union_access_label, 121 MutationOfLayoutConstrainedField => { 122 crate::fluent_generated::mir_transform_mutation_layout_constrained_label 123 } 124 BorrowOfLayoutConstrainedField => { 125 crate::fluent_generated::mir_transform_mutation_layout_constrained_borrow_label 126 } 127 CallToFunctionWith => crate::fluent_generated::mir_transform_target_feature_call_label, 128 } 129 } 130 } 131 132 pub(crate) struct UnsafeOpInUnsafeFn { 133 pub details: RequiresUnsafeDetail, 134 135 /// These spans point to: 136 /// 1. the start of the function body 137 /// 2. the end of the function body 138 /// 3. the function signature 139 pub suggest_unsafe_block: Option<(Span, Span, Span)>, 140 } 141 142 impl<'a> DecorateLint<'a, ()> for UnsafeOpInUnsafeFn { 143 #[track_caller] decorate_lint<'b>( self, diag: &'b mut DiagnosticBuilder<'a, ()>, ) -> &'b mut DiagnosticBuilder<'a, ()>144 fn decorate_lint<'b>( 145 self, 146 diag: &'b mut DiagnosticBuilder<'a, ()>, 147 ) -> &'b mut DiagnosticBuilder<'a, ()> { 148 let handler = diag.handler().expect("lint should not yet be emitted"); 149 let desc = handler.eagerly_translate_to_string(self.details.label(), [].into_iter()); 150 diag.set_arg("details", desc); 151 diag.span_label(self.details.span, self.details.label()); 152 diag.note(self.details.note()); 153 154 if let Some((start, end, fn_sig)) = self.suggest_unsafe_block { 155 diag.span_note(fn_sig, crate::fluent_generated::mir_transform_note); 156 diag.tool_only_multipart_suggestion( 157 crate::fluent_generated::mir_transform_suggestion, 158 vec![(start, " unsafe {".into()), (end, "}".into())], 159 Applicability::MaybeIncorrect, 160 ); 161 } 162 163 diag 164 } 165 msg(&self) -> DiagnosticMessage166 fn msg(&self) -> DiagnosticMessage { 167 crate::fluent_generated::mir_transform_unsafe_op_in_unsafe_fn 168 } 169 } 170 171 pub(crate) enum AssertLint<P> { 172 ArithmeticOverflow(Span, AssertKind<P>), 173 UnconditionalPanic(Span, AssertKind<P>), 174 } 175 176 impl<'a, P: std::fmt::Debug> DecorateLint<'a, ()> for AssertLint<P> { decorate_lint<'b>( self, diag: &'b mut DiagnosticBuilder<'a, ()>, ) -> &'b mut DiagnosticBuilder<'a, ()>177 fn decorate_lint<'b>( 178 self, 179 diag: &'b mut DiagnosticBuilder<'a, ()>, 180 ) -> &'b mut DiagnosticBuilder<'a, ()> { 181 let span = self.span(); 182 let assert_kind = self.panic(); 183 let message = assert_kind.diagnostic_message(); 184 assert_kind.add_args(&mut |name, value| { 185 diag.set_arg(name, value); 186 }); 187 diag.span_label(span, message); 188 189 diag 190 } 191 msg(&self) -> DiagnosticMessage192 fn msg(&self) -> DiagnosticMessage { 193 match self { 194 AssertLint::ArithmeticOverflow(..) => { 195 crate::fluent_generated::mir_transform_arithmetic_overflow 196 } 197 AssertLint::UnconditionalPanic(..) => { 198 crate::fluent_generated::mir_transform_operation_will_panic 199 } 200 } 201 } 202 } 203 204 impl<P> AssertLint<P> { lint(&self) -> &'static Lint205 pub fn lint(&self) -> &'static Lint { 206 match self { 207 AssertLint::ArithmeticOverflow(..) => lint::builtin::ARITHMETIC_OVERFLOW, 208 AssertLint::UnconditionalPanic(..) => lint::builtin::UNCONDITIONAL_PANIC, 209 } 210 } span(&self) -> Span211 pub fn span(&self) -> Span { 212 match self { 213 AssertLint::ArithmeticOverflow(sp, _) | AssertLint::UnconditionalPanic(sp, _) => *sp, 214 } 215 } panic(self) -> AssertKind<P>216 pub fn panic(self) -> AssertKind<P> { 217 match self { 218 AssertLint::ArithmeticOverflow(_, p) | AssertLint::UnconditionalPanic(_, p) => p, 219 } 220 } 221 } 222 223 #[derive(LintDiagnostic)] 224 #[diag(mir_transform_ffi_unwind_call)] 225 pub(crate) struct FfiUnwindCall { 226 #[label(mir_transform_ffi_unwind_call)] 227 pub span: Span, 228 pub foreign: bool, 229 } 230 231 #[derive(LintDiagnostic)] 232 #[diag(mir_transform_fn_item_ref)] 233 pub(crate) struct FnItemRef { 234 #[suggestion(code = "{sugg}", applicability = "unspecified")] 235 pub span: Span, 236 pub sugg: String, 237 pub ident: String, 238 } 239 240 #[derive(LintDiagnostic)] 241 #[diag(mir_transform_must_not_suspend)] 242 pub(crate) struct MustNotSupend<'a> { 243 #[label] 244 pub yield_sp: Span, 245 #[subdiagnostic] 246 pub reason: Option<MustNotSuspendReason>, 247 #[help] 248 pub src_sp: Span, 249 pub pre: &'a str, 250 pub def_path: String, 251 pub post: &'a str, 252 } 253 254 #[derive(Subdiagnostic)] 255 #[note(mir_transform_note)] 256 pub(crate) struct MustNotSuspendReason { 257 #[primary_span] 258 pub span: Span, 259 pub reason: String, 260 } 261 262 #[derive(Diagnostic)] 263 #[diag(mir_transform_simd_shuffle_last_const)] 264 pub(crate) struct SimdShuffleLastConst { 265 #[primary_span] 266 pub span: Span, 267 } 268