1use std::borrow::Cow;
4
5use rustc_abi::ExternAbi;
6use rustc_ast::{AssignOpKind, Label};
7use rustc_errors::codes::*;
8use rustc_errors::{
9 Applicability, Diag, DiagArgValue, DiagCtxtHandle, DiagSymbolList, Diagnostic,
10 EmissionGuarantee, IntoDiagArg, Level, MultiSpan, Subdiagnostic,
11};
12use rustc_hir as hir;
13use rustc_hir::ExprKind;
14use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
15use rustc_middle::ty::{self, Ty};
16use rustc_span::edition::{Edition, LATEST_STABLE_EDITION};
17use rustc_span::source_map::Spanned;
18use rustc_span::{Ident, Span, Symbol};
19
20use crate::{FnCtxt, fluent_generated as fluent};
21
22#[derive(Diagnostic)]
23#[diag(hir_typeck_base_expression_double_dot, code = E0797)]
24pub(crate) struct BaseExpressionDoubleDot {
25 #[primary_span]
26 pub span: Span,
27 #[suggestion(
28 hir_typeck_base_expression_double_dot_enable_default_field_values,
29 code = "#![feature(default_field_values)]\n",
30 applicability = "machine-applicable",
31 style = "verbose"
32 )]
33 pub default_field_values_suggestion: Option<Span>,
34 #[subdiagnostic]
35 pub add_expr: Option<BaseExpressionDoubleDotAddExpr>,
36 #[subdiagnostic]
37 pub remove_dots: Option<BaseExpressionDoubleDotRemove>,
38}
39
40#[derive(Subdiagnostic)]
41#[suggestion(
42 hir_typeck_base_expression_double_dot_remove,
43 code = "",
44 applicability = "machine-applicable",
45 style = "verbose"
46)]
47pub(crate) struct BaseExpressionDoubleDotRemove {
48 #[primary_span]
49 pub span: Span,
50}
51
52#[derive(Subdiagnostic)]
53#[suggestion(
54 hir_typeck_base_expression_double_dot_add_expr,
55 code = "/* expr */",
56 applicability = "has-placeholders",
57 style = "verbose"
58)]
59pub(crate) struct BaseExpressionDoubleDotAddExpr {
60 #[primary_span]
61 pub span: Span,
62}
63
64#[derive(Diagnostic)]
65#[diag(hir_typeck_field_multiply_specified_in_initializer, code = E0062)]
66pub(crate) struct FieldMultiplySpecifiedInInitializer {
67 #[primary_span]
68 #[label]
69 pub span: Span,
70 #[label(hir_typeck_previous_use_label)]
71 pub prev_span: Span,
72 pub ident: Ident,
73}
74
75#[derive(Diagnostic)]
76#[diag(hir_typeck_return_stmt_outside_of_fn_body, code = E0572)]
77pub(crate) struct ReturnStmtOutsideOfFnBody {
78 #[primary_span]
79 pub span: Span,
80 #[label(hir_typeck_encl_body_label)]
81 pub encl_body_span: Option<Span>,
82 #[label(hir_typeck_encl_fn_label)]
83 pub encl_fn_span: Option<Span>,
84 pub statement_kind: ReturnLikeStatementKind,
85}
86
87pub(crate) enum ReturnLikeStatementKind {
88 Return,
89 Become,
90}
91
92impl IntoDiagArg for ReturnLikeStatementKind {
93 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
94 let kind = match self {
95 Self::Return => "return",
96 Self::Become => "become",
97 }
98 .into();
99
100 DiagArgValue::Str(kind)
101 }
102}
103
104#[derive(Diagnostic)]
105#[diag(hir_typeck_rustcall_incorrect_args)]
106pub(crate) struct RustCallIncorrectArgs {
107 #[primary_span]
108 pub span: Span,
109}
110
111#[derive(Diagnostic)]
112#[diag(hir_typeck_yield_expr_outside_of_coroutine, code = E0627)]
113pub(crate) struct YieldExprOutsideOfCoroutine {
114 #[primary_span]
115 pub span: Span,
116}
117
118#[derive(Diagnostic)]
119#[diag(hir_typeck_struct_expr_non_exhaustive, code = E0639)]
120pub(crate) struct StructExprNonExhaustive {
121 #[primary_span]
122 pub span: Span,
123 pub what: &'static str,
124}
125
126#[derive(Diagnostic)]
127#[diag(hir_typeck_functional_record_update_on_non_struct, code = E0436)]
128pub(crate) struct FunctionalRecordUpdateOnNonStruct {
129 #[primary_span]
130 pub span: Span,
131}
132
133#[derive(Diagnostic)]
134#[diag(hir_typeck_address_of_temporary_taken, code = E0745)]
135pub(crate) struct AddressOfTemporaryTaken {
136 #[primary_span]
137 #[label]
138 pub span: Span,
139}
140
141#[derive(Subdiagnostic)]
142pub(crate) enum AddReturnTypeSuggestion {
143 #[suggestion(
144 hir_typeck_add_return_type_add,
145 code = " -> {found}",
146 applicability = "machine-applicable"
147 )]
148 Add {
149 #[primary_span]
150 span: Span,
151 found: String,
152 },
153 #[suggestion(
154 hir_typeck_add_return_type_missing_here,
155 code = " -> _",
156 applicability = "has-placeholders"
157 )]
158 MissingHere {
159 #[primary_span]
160 span: Span,
161 },
162}
163
164#[derive(Subdiagnostic)]
165pub(crate) enum ExpectedReturnTypeLabel<'tcx> {
166 #[label(hir_typeck_expected_default_return_type)]
167 Unit {
168 #[primary_span]
169 span: Span,
170 },
171 #[label(hir_typeck_expected_return_type)]
172 Other {
173 #[primary_span]
174 span: Span,
175 expected: Ty<'tcx>,
176 },
177}
178
179#[derive(Diagnostic)]
180#[diag(hir_typeck_explicit_destructor, code = E0040)]
181pub(crate) struct ExplicitDestructorCall {
182 #[primary_span]
183 #[label]
184 pub span: Span,
185 #[subdiagnostic]
186 pub sugg: ExplicitDestructorCallSugg,
187}
188
189#[derive(Subdiagnostic)]
190pub(crate) enum ExplicitDestructorCallSugg {
191 #[suggestion(hir_typeck_suggestion, code = "drop", applicability = "maybe-incorrect")]
192 Empty(#[primary_span] Span),
193 #[multipart_suggestion(hir_typeck_suggestion, style = "short")]
194 Snippet {
195 #[suggestion_part(code = "drop(")]
196 lo: Span,
197 #[suggestion_part(code = ")")]
198 hi: Span,
199 },
200}
201
202#[derive(Diagnostic)]
203#[diag(hir_typeck_missing_parentheses_in_range, code = E0689)]
204pub(crate) struct MissingParenthesesInRange<'tcx> {
205 #[primary_span]
206 #[label(hir_typeck_missing_parentheses_in_range)]
207 pub span: Span,
208 pub ty: Ty<'tcx>,
209 pub method_name: String,
210 #[subdiagnostic]
211 pub add_missing_parentheses: Option<AddMissingParenthesesInRange>,
212}
213
214#[derive(LintDiagnostic)]
215pub(crate) enum NeverTypeFallbackFlowingIntoUnsafe {
216 #[help]
217 #[diag(hir_typeck_never_type_fallback_flowing_into_unsafe_call)]
218 Call {
219 #[subdiagnostic]
220 sugg: SuggestAnnotations,
221 },
222 #[help]
223 #[diag(hir_typeck_never_type_fallback_flowing_into_unsafe_method)]
224 Method {
225 #[subdiagnostic]
226 sugg: SuggestAnnotations,
227 },
228 #[help]
229 #[diag(hir_typeck_never_type_fallback_flowing_into_unsafe_path)]
230 Path {
231 #[subdiagnostic]
232 sugg: SuggestAnnotations,
233 },
234 #[help]
235 #[diag(hir_typeck_never_type_fallback_flowing_into_unsafe_union_field)]
236 UnionField {
237 #[subdiagnostic]
238 sugg: SuggestAnnotations,
239 },
240 #[help]
241 #[diag(hir_typeck_never_type_fallback_flowing_into_unsafe_deref)]
242 Deref {
243 #[subdiagnostic]
244 sugg: SuggestAnnotations,
245 },
246}
247
248#[derive(LintDiagnostic)]
249#[help]
250#[diag(hir_typeck_dependency_on_unit_never_type_fallback)]
251pub(crate) struct DependencyOnUnitNeverTypeFallback<'tcx> {
252 #[note]
253 pub obligation_span: Span,
254 pub obligation: ty::Predicate<'tcx>,
255 #[subdiagnostic]
256 pub sugg: SuggestAnnotations,
257}
258
259#[derive(Clone)]
260pub(crate) enum SuggestAnnotation {
261 Unit(Span),
262 Path(Span),
263 Local(Span),
264 Turbo(Span, usize, usize),
265}
266
267#[derive(Clone)]
268pub(crate) struct SuggestAnnotations {
269 pub suggestions: Vec<SuggestAnnotation>,
270}
271impl Subdiagnostic for SuggestAnnotations {
272 fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
273 if self.suggestions.is_empty() {
274 return;
275 }
276
277 let mut suggestions = vec![];
278 for suggestion in self.suggestions {
279 match suggestion {
280 SuggestAnnotation::Unit(span) => {
281 suggestions.push((span, "()".to_string()));
282 }
283 SuggestAnnotation::Path(span) => {
284 suggestions.push((span.shrink_to_lo(), "<() as ".to_string()));
285 suggestions.push((span.shrink_to_hi(), ">".to_string()));
286 }
287 SuggestAnnotation::Local(span) => {
288 suggestions.push((span, ": ()".to_string()));
289 }
290 SuggestAnnotation::Turbo(span, n_args, idx) => suggestions.push((
291 span,
292 format!(
293 "::<{}>",
294 (0..n_args)
295 .map(|i| if i == idx { "()" } else { "_" })
296 .collect::<Vec<_>>()
297 .join(", "),
298 ),
299 )),
300 }
301 }
302
303 diag.multipart_suggestion_verbose(
304 "use `()` annotations to avoid fallback changes",
305 suggestions,
306 Applicability::MachineApplicable,
307 );
308 }
309}
310
311#[derive(Subdiagnostic)]
312#[multipart_suggestion(
313 hir_typeck_add_missing_parentheses_in_range,
314 style = "verbose",
315 applicability = "maybe-incorrect"
316)]
317pub(crate) struct AddMissingParenthesesInRange {
318 pub func_name: String,
319 #[suggestion_part(code = "(")]
320 pub left: Span,
321 #[suggestion_part(code = ")")]
322 pub right: Span,
323}
324
325pub(crate) struct TypeMismatchFruTypo {
326 pub expr_span: Span,
328 pub fru_span: Span,
330 pub expr: Option<String>,
332}
333
334impl Subdiagnostic for TypeMismatchFruTypo {
335 fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
336 diag.arg("expr", self.expr.as_deref().unwrap_or("NONE"));
337
338 if self.expr_span.between(self.fru_span).is_empty() {
340 diag.span_note(self.expr_span.to(self.fru_span), fluent::hir_typeck_fru_note);
341 } else {
342 let mut multispan: MultiSpan = vec![self.expr_span, self.fru_span].into();
343 multispan.push_span_label(self.expr_span, fluent::hir_typeck_fru_expr);
344 multispan.push_span_label(self.fru_span, fluent::hir_typeck_fru_expr2);
345 diag.span_note(multispan, fluent::hir_typeck_fru_note);
346 }
347
348 diag.span_suggestion(
349 self.expr_span.shrink_to_hi(),
350 fluent::hir_typeck_fru_suggestion,
351 ", ",
352 Applicability::MaybeIncorrect,
353 );
354 }
355}
356
357#[derive(LintDiagnostic)]
358#[diag(hir_typeck_lossy_provenance_int2ptr)]
359#[help]
360pub(crate) struct LossyProvenanceInt2Ptr<'tcx> {
361 pub expr_ty: Ty<'tcx>,
362 pub cast_ty: Ty<'tcx>,
363 #[subdiagnostic]
364 pub sugg: LossyProvenanceInt2PtrSuggestion,
365}
366
367#[derive(Diagnostic)]
368#[diag(hir_typeck_ptr_cast_add_auto_to_object, code = E0804)]
369#[note]
370#[help]
371pub(crate) struct PtrCastAddAutoToObject {
372 #[primary_span]
373 #[label]
374 pub span: Span,
375 pub traits_len: usize,
376 pub traits: DiagSymbolList<String>,
377}
378
379#[derive(Subdiagnostic)]
380#[multipart_suggestion(hir_typeck_suggestion, applicability = "has-placeholders")]
381pub(crate) struct LossyProvenanceInt2PtrSuggestion {
382 #[suggestion_part(code = "(...).with_addr(")]
383 pub lo: Span,
384 #[suggestion_part(code = ")")]
385 pub hi: Span,
386}
387
388#[derive(LintDiagnostic)]
389#[diag(hir_typeck_lossy_provenance_ptr2int)]
390#[help]
391pub(crate) struct LossyProvenancePtr2Int<'tcx> {
392 pub expr_ty: Ty<'tcx>,
393 pub cast_ty: Ty<'tcx>,
394 #[subdiagnostic]
395 pub sugg: LossyProvenancePtr2IntSuggestion<'tcx>,
396}
397
398#[derive(Subdiagnostic)]
399pub(crate) enum LossyProvenancePtr2IntSuggestion<'tcx> {
400 #[multipart_suggestion(hir_typeck_suggestion, applicability = "maybe-incorrect")]
401 NeedsParensCast {
402 #[suggestion_part(code = "(")]
403 expr_span: Span,
404 #[suggestion_part(code = ").addr() as {cast_ty}")]
405 cast_span: Span,
406 cast_ty: Ty<'tcx>,
407 },
408 #[multipart_suggestion(hir_typeck_suggestion, applicability = "maybe-incorrect")]
409 NeedsParens {
410 #[suggestion_part(code = "(")]
411 expr_span: Span,
412 #[suggestion_part(code = ").addr()")]
413 cast_span: Span,
414 },
415 #[suggestion(
416 hir_typeck_suggestion,
417 code = ".addr() as {cast_ty}",
418 applicability = "maybe-incorrect"
419 )]
420 NeedsCast {
421 #[primary_span]
422 cast_span: Span,
423 cast_ty: Ty<'tcx>,
424 },
425 #[suggestion(hir_typeck_suggestion, code = ".addr()", applicability = "maybe-incorrect")]
426 Other {
427 #[primary_span]
428 cast_span: Span,
429 },
430}
431
432#[derive(Subdiagnostic)]
433pub(crate) enum HelpUseLatestEdition {
434 #[help(hir_typeck_help_set_edition_cargo)]
435 #[note(hir_typeck_note_edition_guide)]
436 Cargo { edition: Edition },
437 #[help(hir_typeck_help_set_edition_standalone)]
438 #[note(hir_typeck_note_edition_guide)]
439 Standalone { edition: Edition },
440}
441
442impl HelpUseLatestEdition {
443 pub(crate) fn new() -> Self {
444 let edition = LATEST_STABLE_EDITION;
445 if rustc_session::utils::was_invoked_from_cargo() {
446 Self::Cargo { edition }
447 } else {
448 Self::Standalone { edition }
449 }
450 }
451}
452
453#[derive(Diagnostic)]
454#[diag(hir_typeck_no_field_on_type, code = E0609)]
455pub(crate) struct NoFieldOnType<'tcx> {
456 #[primary_span]
457 pub(crate) span: Span,
458 pub(crate) ty: Ty<'tcx>,
459 pub(crate) field: Ident,
460}
461
462#[derive(Diagnostic)]
463#[diag(hir_typeck_no_field_on_variant, code = E0609)]
464pub(crate) struct NoFieldOnVariant<'tcx> {
465 #[primary_span]
466 pub(crate) span: Span,
467 pub(crate) container: Ty<'tcx>,
468 pub(crate) ident: Ident,
469 pub(crate) field: Ident,
470 #[label(hir_typeck_no_field_on_variant_enum)]
471 pub(crate) enum_span: Span,
472 #[label(hir_typeck_no_field_on_variant_field)]
473 pub(crate) field_span: Span,
474}
475
476#[derive(Diagnostic)]
477#[diag(hir_typeck_cant_dereference, code = E0614)]
478pub(crate) struct CantDereference<'tcx> {
479 #[primary_span]
480 #[label(hir_typeck_cant_dereference_label)]
481 pub(crate) span: Span,
482 pub(crate) ty: Ty<'tcx>,
483}
484
485#[derive(Diagnostic)]
486#[diag(hir_typeck_expected_array_or_slice, code = E0529)]
487pub(crate) struct ExpectedArrayOrSlice<'tcx> {
488 #[primary_span]
489 #[label(hir_typeck_expected_array_or_slice_label)]
490 pub(crate) span: Span,
491 pub(crate) ty: Ty<'tcx>,
492 pub(crate) slice_pat_semantics: bool,
493 #[subdiagnostic]
494 pub(crate) as_deref: Option<AsDerefSuggestion>,
495 #[subdiagnostic]
496 pub(crate) slicing: Option<SlicingSuggestion>,
497}
498
499#[derive(Subdiagnostic)]
500#[suggestion(
501 hir_typeck_as_deref_suggestion,
502 code = ".as_deref()",
503 style = "verbose",
504 applicability = "maybe-incorrect"
505)]
506pub(crate) struct AsDerefSuggestion {
507 #[primary_span]
508 pub(crate) span: Span,
509}
510
511#[derive(Subdiagnostic)]
512#[suggestion(
513 hir_typeck_slicing_suggestion,
514 code = "[..]",
515 style = "verbose",
516 applicability = "maybe-incorrect"
517)]
518pub(crate) struct SlicingSuggestion {
519 #[primary_span]
520 pub(crate) span: Span,
521}
522
523#[derive(Diagnostic)]
524#[diag(hir_typeck_invalid_callee, code = E0618)]
525pub(crate) struct InvalidCallee<'tcx> {
526 #[primary_span]
527 pub span: Span,
528 pub ty: Ty<'tcx>,
529 pub found: String,
530}
531
532#[derive(Diagnostic)]
533#[diag(hir_typeck_int_to_fat, code = E0606)]
534pub(crate) struct IntToWide<'tcx> {
535 #[primary_span]
536 #[label(hir_typeck_int_to_fat_label)]
537 pub span: Span,
538 pub metadata: &'tcx str,
539 pub expr_ty: Ty<'tcx>,
540 pub cast_ty: Ty<'tcx>,
541 #[label(hir_typeck_int_to_fat_label_nightly)]
542 pub expr_if_nightly: Option<Span>,
543 pub known_wide: bool,
544}
545
546#[derive(Subdiagnostic)]
547pub(crate) enum OptionResultRefMismatch {
548 #[suggestion(
549 hir_typeck_option_result_copied,
550 code = ".copied()",
551 style = "verbose",
552 applicability = "machine-applicable"
553 )]
554 Copied {
555 #[primary_span]
556 span: Span,
557 def_path: String,
558 },
559 #[suggestion(
560 hir_typeck_option_result_cloned,
561 code = ".cloned()",
562 style = "verbose",
563 applicability = "machine-applicable"
564 )]
565 Cloned {
566 #[primary_span]
567 span: Span,
568 def_path: String,
569 },
570 }
585
586pub(crate) struct RemoveSemiForCoerce {
587 pub expr: Span,
588 pub ret: Span,
589 pub semi: Span,
590}
591
592impl Subdiagnostic for RemoveSemiForCoerce {
593 fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
594 let mut multispan: MultiSpan = self.semi.into();
595 multispan.push_span_label(self.expr, fluent::hir_typeck_remove_semi_for_coerce_expr);
596 multispan.push_span_label(self.ret, fluent::hir_typeck_remove_semi_for_coerce_ret);
597 multispan.push_span_label(self.semi, fluent::hir_typeck_remove_semi_for_coerce_semi);
598 diag.span_note(multispan, fluent::hir_typeck_remove_semi_for_coerce);
599
600 diag.tool_only_span_suggestion(
601 self.semi,
602 fluent::hir_typeck_remove_semi_for_coerce_suggestion,
603 "",
604 Applicability::MaybeIncorrect,
605 );
606 }
607}
608
609#[derive(Diagnostic)]
610#[diag(hir_typeck_union_pat_multiple_fields)]
611pub(crate) struct UnionPatMultipleFields {
612 #[primary_span]
613 pub span: Span,
614}
615
616#[derive(Diagnostic)]
617#[diag(hir_typeck_union_pat_dotdot)]
618pub(crate) struct UnionPatDotDot {
619 #[primary_span]
620 pub span: Span,
621}
622
623#[derive(Subdiagnostic)]
624#[multipart_suggestion(
625 hir_typeck_use_is_empty,
626 applicability = "maybe-incorrect",
627 style = "verbose"
628)]
629pub(crate) struct UseIsEmpty<'tcx> {
630 #[suggestion_part(code = "!")]
631 pub lo: Span,
632 #[suggestion_part(code = ".is_empty()")]
633 pub hi: Span,
634 pub expr_ty: Ty<'tcx>,
635}
636
637#[derive(Diagnostic)]
638#[diag(hir_typeck_arg_mismatch_indeterminate)]
639pub(crate) struct ArgMismatchIndeterminate {
640 #[primary_span]
641 pub span: Span,
642}
643
644#[derive(Subdiagnostic)]
645pub(crate) enum SuggestBoxing {
646 #[note(hir_typeck_suggest_boxing_note)]
647 #[multipart_suggestion(
648 hir_typeck_suggest_boxing_when_appropriate,
649 applicability = "machine-applicable"
650 )]
651 Unit {
652 #[suggestion_part(code = "Box::new(())")]
653 start: Span,
654 #[suggestion_part(code = "")]
655 end: Span,
656 },
657 #[note(hir_typeck_suggest_boxing_note)]
658 AsyncBody,
659 #[note(hir_typeck_suggest_boxing_note)]
660 #[multipart_suggestion(
661 hir_typeck_suggest_boxing_when_appropriate,
662 applicability = "machine-applicable"
663 )]
664 ExprFieldShorthand {
665 #[suggestion_part(code = "{ident}: Box::new(")]
666 start: Span,
667 #[suggestion_part(code = ")")]
668 end: Span,
669 ident: Ident,
670 },
671 #[note(hir_typeck_suggest_boxing_note)]
672 #[multipart_suggestion(
673 hir_typeck_suggest_boxing_when_appropriate,
674 applicability = "machine-applicable"
675 )]
676 Other {
677 #[suggestion_part(code = "Box::new(")]
678 start: Span,
679 #[suggestion_part(code = ")")]
680 end: Span,
681 },
682}
683
684#[derive(Subdiagnostic)]
685#[suggestion(
686 hir_typeck_suggest_ptr_null_mut,
687 applicability = "maybe-incorrect",
688 style = "verbose",
689 code = "core::ptr::null_mut()"
690)]
691pub(crate) struct SuggestPtrNullMut {
692 #[primary_span]
693 pub span: Span,
694}
695
696#[derive(LintDiagnostic)]
697#[diag(hir_typeck_trivial_cast)]
698#[help]
699pub(crate) struct TrivialCast<'tcx> {
700 pub numeric: bool,
701 pub expr_ty: Ty<'tcx>,
702 pub cast_ty: Ty<'tcx>,
703}
704
705pub(crate) struct BreakNonLoop<'a> {
706 pub span: Span,
707 pub head: Option<Span>,
708 pub kind: &'a str,
709 pub suggestion: String,
710 pub loop_label: Option<Label>,
711 pub break_label: Option<Label>,
712 pub break_expr_kind: &'a ExprKind<'a>,
713 pub break_expr_span: Span,
714}
715
716impl<'a, G: EmissionGuarantee> Diagnostic<'_, G> for BreakNonLoop<'a> {
717 #[track_caller]
718 fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> {
719 let mut diag = Diag::new(dcx, level, fluent::hir_typeck_break_non_loop);
720 diag.span(self.span);
721 diag.code(E0571);
722 diag.arg("kind", self.kind);
723 diag.span_label(self.span, fluent::hir_typeck_label);
724 if let Some(head) = self.head {
725 diag.span_label(head, fluent::hir_typeck_label2);
726 }
727 diag.span_suggestion(
728 self.span,
729 fluent::hir_typeck_suggestion,
730 self.suggestion,
731 Applicability::MaybeIncorrect,
732 );
733 if let (Some(label), None) = (self.loop_label, self.break_label) {
734 match self.break_expr_kind {
735 ExprKind::Path(hir::QPath::Resolved(
736 None,
737 hir::Path { segments: [segment], res: hir::def::Res::Err, .. },
738 )) if label.ident.to_string() == format!("'{}", segment.ident) => {
739 diag.downgrade_to_delayed_bug();
743 }
744 _ => {
745 diag.span_suggestion(
746 self.break_expr_span,
747 fluent::hir_typeck_break_expr_suggestion,
748 label.ident,
749 Applicability::MaybeIncorrect,
750 );
751 }
752 }
753 }
754 diag
755 }
756}
757
758#[derive(Diagnostic)]
759#[diag(hir_typeck_continue_labeled_block, code = E0696)]
760pub(crate) struct ContinueLabeledBlock {
761 #[primary_span]
762 #[label]
763 pub span: Span,
764 #[label(hir_typeck_block_label)]
765 pub block_span: Span,
766}
767
768#[derive(Diagnostic)]
769#[diag(hir_typeck_break_inside_closure, code = E0267)]
770pub(crate) struct BreakInsideClosure<'a> {
771 #[primary_span]
772 #[label]
773 pub span: Span,
774 #[label(hir_typeck_closure_label)]
775 pub closure_span: Span,
776 pub name: &'a str,
777}
778
779#[derive(Diagnostic)]
780#[diag(hir_typeck_break_inside_coroutine, code = E0267)]
781pub(crate) struct BreakInsideCoroutine<'a> {
782 #[primary_span]
783 #[label]
784 pub span: Span,
785 #[label(hir_typeck_coroutine_label)]
786 pub coroutine_span: Span,
787 pub name: &'a str,
788 pub kind: &'a str,
789 pub source: &'a str,
790}
791
792#[derive(Diagnostic)]
793#[diag(hir_typeck_outside_loop, code = E0268)]
794pub(crate) struct OutsideLoop<'a> {
795 #[primary_span]
796 #[label]
797 pub spans: Vec<Span>,
798 pub name: &'a str,
799 pub is_break: bool,
800 #[subdiagnostic]
801 pub suggestion: Option<OutsideLoopSuggestion>,
802}
803#[derive(Subdiagnostic)]
804#[multipart_suggestion(hir_typeck_outside_loop_suggestion, applicability = "maybe-incorrect")]
805pub(crate) struct OutsideLoopSuggestion {
806 #[suggestion_part(code = "'block: ")]
807 pub block_span: Span,
808 #[suggestion_part(code = " 'block")]
809 pub break_spans: Vec<Span>,
810}
811
812#[derive(Diagnostic)]
813#[diag(hir_typeck_unlabeled_in_labeled_block, code = E0695)]
814pub(crate) struct UnlabeledInLabeledBlock<'a> {
815 #[primary_span]
816 #[label]
817 pub span: Span,
818 pub cf_type: &'a str,
819}
820
821#[derive(Diagnostic)]
822#[diag(hir_typeck_unlabeled_cf_in_while_condition, code = E0590)]
823pub(crate) struct UnlabeledCfInWhileCondition<'a> {
824 #[primary_span]
825 #[label]
826 pub span: Span,
827 pub cf_type: &'a str,
828}
829
830#[derive(Diagnostic)]
831#[diag(hir_typeck_no_associated_item, code = E0599)]
832pub(crate) struct NoAssociatedItem<'tcx> {
833 #[primary_span]
834 pub span: Span,
835 pub item_kind: &'static str,
836 pub item_ident: Ident,
837 pub ty_prefix: Cow<'static, str>,
838 pub ty: Ty<'tcx>,
839 pub trait_missing_method: bool,
840}
841
842#[derive(Subdiagnostic)]
843#[note(hir_typeck_candidate_trait_note)]
844pub(crate) struct CandidateTraitNote {
845 #[primary_span]
846 pub span: Span,
847 pub trait_name: String,
848 pub item_name: Ident,
849 pub action_or_ty: String,
850}
851
852#[derive(Diagnostic)]
853#[diag(hir_typeck_cannot_cast_to_bool, code = E0054)]
854pub(crate) struct CannotCastToBool<'tcx> {
855 #[primary_span]
856 pub span: Span,
857 pub expr_ty: Ty<'tcx>,
858 #[subdiagnostic]
859 pub help: CannotCastToBoolHelp,
860}
861
862#[derive(Diagnostic)]
863#[diag(hir_typeck_cast_enum_drop)]
864pub(crate) struct CastEnumDrop<'tcx> {
865 #[primary_span]
866 pub span: Span,
867 pub expr_ty: Ty<'tcx>,
868 pub cast_ty: Ty<'tcx>,
869}
870
871#[derive(Diagnostic)]
872#[diag(hir_typeck_cast_unknown_pointer, code = E0641)]
873pub(crate) struct CastUnknownPointer {
874 #[primary_span]
875 pub span: Span,
876 pub to: bool,
877 #[subdiagnostic]
878 pub sub: CastUnknownPointerSub,
879}
880
881pub(crate) enum CastUnknownPointerSub {
882 To(Span),
883 From(Span),
884}
885
886impl rustc_errors::Subdiagnostic for CastUnknownPointerSub {
887 fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
888 match self {
889 CastUnknownPointerSub::To(span) => {
890 let msg = diag.eagerly_translate(fluent::hir_typeck_label_to);
891 diag.span_label(span, msg);
892 let msg = diag.eagerly_translate(fluent::hir_typeck_note);
893 diag.note(msg);
894 }
895 CastUnknownPointerSub::From(span) => {
896 let msg = diag.eagerly_translate(fluent::hir_typeck_label_from);
897 diag.span_label(span, msg);
898 }
899 }
900 }
901}
902
903#[derive(Subdiagnostic)]
904pub(crate) enum CannotCastToBoolHelp {
905 #[suggestion(
906 hir_typeck_suggestion,
907 applicability = "machine-applicable",
908 code = " != 0",
909 style = "verbose"
910 )]
911 Numeric(#[primary_span] Span),
912 #[label(hir_typeck_label)]
913 Unsupported(#[primary_span] Span),
914}
915
916#[derive(Diagnostic)]
917#[diag(hir_typeck_ctor_is_private, code = E0603)]
918pub(crate) struct CtorIsPrivate {
919 #[primary_span]
920 pub span: Span,
921 pub def: String,
922}
923
924#[derive(Subdiagnostic)]
925#[note(hir_typeck_deref_is_empty)]
926pub(crate) struct DerefImplsIsEmpty<'tcx> {
927 #[primary_span]
928 pub span: Span,
929 pub deref_ty: Ty<'tcx>,
930}
931
932#[derive(Subdiagnostic)]
933#[multipart_suggestion(
934 hir_typeck_convert_using_method,
935 applicability = "machine-applicable",
936 style = "verbose"
937)]
938pub(crate) struct SuggestConvertViaMethod<'tcx> {
939 #[suggestion_part(code = "{sugg}")]
940 pub span: Span,
941 #[suggestion_part(code = "")]
942 pub borrow_removal_span: Option<Span>,
943 pub sugg: String,
944 pub expected: Ty<'tcx>,
945 pub found: Ty<'tcx>,
946}
947
948#[derive(Subdiagnostic)]
949#[note(hir_typeck_note_caller_chooses_ty_for_ty_param)]
950pub(crate) struct NoteCallerChoosesTyForTyParam<'tcx> {
951 pub ty_param_name: Symbol,
952 pub found_ty: Ty<'tcx>,
953}
954
955#[derive(Subdiagnostic)]
956pub(crate) enum SuggestBoxingForReturnImplTrait {
957 #[multipart_suggestion(hir_typeck_rpit_change_return_type, applicability = "maybe-incorrect")]
958 ChangeReturnType {
959 #[suggestion_part(code = "Box<dyn")]
960 start_sp: Span,
961 #[suggestion_part(code = ">")]
962 end_sp: Span,
963 },
964 #[multipart_suggestion(hir_typeck_rpit_box_return_expr, applicability = "maybe-incorrect")]
965 BoxReturnExpr {
966 #[suggestion_part(code = "Box::new(")]
967 starts: Vec<Span>,
968 #[suggestion_part(code = ")")]
969 ends: Vec<Span>,
970 },
971}
972
973#[derive(Diagnostic)]
974#[diag(hir_typeck_self_ctor_from_outer_item, code = E0401)]
975pub(crate) struct SelfCtorFromOuterItem {
976 #[primary_span]
977 pub span: Span,
978 #[label]
979 pub impl_span: Span,
980 #[subdiagnostic]
981 pub sugg: Option<ReplaceWithName>,
982 #[subdiagnostic]
983 pub item: Option<InnerItem>,
984}
985
986#[derive(Subdiagnostic)]
987#[label(hir_typeck_self_ctor_from_outer_item_inner_item)]
988pub(crate) struct InnerItem {
989 #[primary_span]
990 pub span: Span,
991}
992
993#[derive(LintDiagnostic)]
994#[diag(hir_typeck_self_ctor_from_outer_item)]
995pub(crate) struct SelfCtorFromOuterItemLint {
996 #[label]
997 pub impl_span: Span,
998 #[subdiagnostic]
999 pub sugg: Option<ReplaceWithName>,
1000 #[subdiagnostic]
1001 pub item: Option<InnerItem>,
1002}
1003
1004#[derive(Subdiagnostic)]
1005#[suggestion(hir_typeck_suggestion, code = "{name}", applicability = "machine-applicable")]
1006pub(crate) struct ReplaceWithName {
1007 #[primary_span]
1008 pub span: Span,
1009 pub name: String,
1010}
1011
1012#[derive(Diagnostic)]
1013#[diag(hir_typeck_cast_thin_pointer_to_wide_pointer, code = E0607)]
1014pub(crate) struct CastThinPointerToWidePointer<'tcx> {
1015 #[primary_span]
1016 pub span: Span,
1017 pub expr_ty: Ty<'tcx>,
1018 pub cast_ty: Ty<'tcx>,
1019 #[note(hir_typeck_teach_help)]
1020 pub(crate) teach: bool,
1021}
1022
1023#[derive(Diagnostic)]
1024#[diag(hir_typeck_pass_to_variadic_function, code = E0617)]
1025pub(crate) struct PassToVariadicFunction<'a, 'tcx> {
1026 #[primary_span]
1027 pub span: Span,
1028 pub ty: Ty<'tcx>,
1029 pub cast_ty: &'a str,
1030 #[suggestion(code = " as {cast_ty}", applicability = "machine-applicable", style = "verbose")]
1031 pub sugg_span: Span,
1032 #[note(hir_typeck_teach_help)]
1033 pub(crate) teach: bool,
1034}
1035
1036#[derive(Diagnostic)]
1037#[diag(hir_typeck_fn_item_to_variadic_function, code = E0617)]
1038#[help]
1039#[note]
1040pub(crate) struct PassFnItemToVariadicFunction {
1041 #[primary_span]
1042 pub span: Span,
1043 #[suggestion(code = " as {replace}", applicability = "machine-applicable", style = "verbose")]
1044 pub sugg_span: Span,
1045 pub replace: String,
1046}
1047
1048#[derive(Subdiagnostic)]
1049#[suggestion(
1050 hir_typeck_replace_comma_with_semicolon,
1051 applicability = "machine-applicable",
1052 style = "verbose",
1053 code = "; "
1054)]
1055pub(crate) struct ReplaceCommaWithSemicolon {
1056 #[primary_span]
1057 pub comma_span: Span,
1058 pub descr: &'static str,
1059}
1060
1061#[derive(LintDiagnostic)]
1062#[diag(hir_typeck_supertrait_item_shadowing)]
1063pub(crate) struct SupertraitItemShadowing {
1064 pub item: Symbol,
1065 pub subtrait: Symbol,
1066 #[subdiagnostic]
1067 pub shadower: SupertraitItemShadower,
1068 #[subdiagnostic]
1069 pub shadowee: SupertraitItemShadowee,
1070}
1071
1072#[derive(Subdiagnostic)]
1073#[note(hir_typeck_supertrait_item_shadower)]
1074pub(crate) struct SupertraitItemShadower {
1075 pub subtrait: Symbol,
1076 #[primary_span]
1077 pub span: Span,
1078}
1079
1080#[derive(Subdiagnostic)]
1081pub(crate) enum SupertraitItemShadowee {
1082 #[note(hir_typeck_supertrait_item_shadowee)]
1083 Labeled {
1084 #[primary_span]
1085 span: Span,
1086 supertrait: Symbol,
1087 },
1088 #[note(hir_typeck_supertrait_item_multiple_shadowee)]
1089 Several {
1090 #[primary_span]
1091 spans: MultiSpan,
1092 traits: DiagSymbolList,
1093 },
1094}
1095
1096#[derive(Diagnostic)]
1097#[diag(hir_typeck_register_type_unstable)]
1098pub(crate) struct RegisterTypeUnstable<'a> {
1099 #[primary_span]
1100 pub span: Span,
1101 pub ty: Ty<'a>,
1102}
1103
1104#[derive(Diagnostic)]
1105#[diag(hir_typeck_naked_asm_outside_naked_fn)]
1106pub(crate) struct NakedAsmOutsideNakedFn {
1107 #[primary_span]
1108 pub span: Span,
1109}
1110
1111#[derive(Diagnostic)]
1112#[diag(hir_typeck_no_patterns)]
1113pub(crate) struct NoPatterns {
1114 #[primary_span]
1115 pub span: Span,
1116}
1117
1118#[derive(Diagnostic)]
1119#[diag(hir_typeck_params_not_allowed)]
1120#[help]
1121pub(crate) struct ParamsNotAllowed {
1122 #[primary_span]
1123 pub span: Span,
1124}
1125
1126pub(crate) struct NakedFunctionsAsmBlock {
1127 pub span: Span,
1128 pub multiple_asms: Vec<Span>,
1129 pub non_asms: Vec<Span>,
1130}
1131
1132impl<G: EmissionGuarantee> Diagnostic<'_, G> for NakedFunctionsAsmBlock {
1133 #[track_caller]
1134 fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> {
1135 let mut diag = Diag::new(dcx, level, fluent::hir_typeck_naked_functions_asm_block);
1136 diag.span(self.span);
1137 diag.code(E0787);
1138 for span in self.multiple_asms.iter() {
1139 diag.span_label(*span, fluent::hir_typeck_label_multiple_asm);
1140 }
1141 for span in self.non_asms.iter() {
1142 diag.span_label(*span, fluent::hir_typeck_label_non_asm);
1143 }
1144 diag
1145 }
1146}
1147
1148pub(crate) fn maybe_emit_plus_equals_diagnostic<'a>(
1149 fnctxt: &FnCtxt<'a, '_>,
1150 assign_op: Spanned<AssignOpKind>,
1151 lhs_expr: &hir::Expr<'_>,
1152) -> Result<(), Diag<'a>> {
1153 if assign_op.node == hir::AssignOpKind::AddAssign
1154 && let hir::ExprKind::Binary(bin_op, left, right) = &lhs_expr.kind
1155 && bin_op.node == hir::BinOpKind::And
1156 && crate::op::contains_let_in_chain(left)
1157 && let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = &right.kind
1158 && matches!(path.res, hir::def::Res::Local(_))
1159 {
1160 let mut err = fnctxt.dcx().struct_span_err(
1161 assign_op.span,
1162 "binary assignment operation `+=` cannot be used in a let chain",
1163 );
1164
1165 err.span_label(
1166 lhs_expr.span,
1167 "you are add-assigning the right-hand side expression to the result of this let-chain",
1168 );
1169
1170 err.span_label(assign_op.span, "cannot use `+=` in a let chain");
1171
1172 err.span_suggestion(
1173 assign_op.span,
1174 "you might have meant to compare with `==` instead of assigning with `+=`",
1175 "==",
1176 Applicability::MaybeIncorrect,
1177 );
1178
1179 return Err(err);
1180 }
1181 Ok(())
1182}
1183
1184#[derive(Diagnostic)]
1185#[diag(hir_typeck_naked_functions_must_naked_asm, code = E0787)]
1186pub(crate) struct NakedFunctionsMustNakedAsm {
1187 #[primary_span]
1188 #[label]
1189 pub span: Span,
1190}
1191
1192#[derive(Diagnostic)]
1193#[diag(hir_typeck_abi_cannot_be_called)]
1194pub(crate) struct AbiCannotBeCalled {
1195 #[primary_span]
1196 #[note]
1197 pub span: Span,
1198 pub abi: ExternAbi,
1199}
1200
1201#[derive(Diagnostic)]
1202#[diag(hir_typeck_const_continue_bad_label)]
1203pub(crate) struct ConstContinueBadLabel {
1204 #[primary_span]
1205 pub span: Span,
1206}
1207
1208#[derive(Diagnostic)]
1209#[diag(hir_typeck_project_on_non_pin_project_type)]
1210pub(crate) struct ProjectOnNonPinProjectType {
1211 #[primary_span]
1212 pub span: Span,
1213 #[note]
1214 pub def_span: Option<Span>,
1215 #[suggestion(code = "#[pin_v2]\n", applicability = "machine-applicable")]
1216 pub sugg_span: Option<Span>,
1217}