• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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