rustc_hir_typeck/
errors.rs

1//! Errors emitted by `rustc_hir_typeck`.
2
3use 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    /// Span of the LHS of the range
327    pub expr_span: Span,
328    /// Span of the `..RHS` part of the range
329    pub fru_span: Span,
330    /// Rendered expression of the RHS of the range
331    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        // Only explain that `a ..b` is a range if it's split up
339        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    // FIXME: #114050
571    // #[suggestion(
572    //     hir_typeck_option_result_asref,
573    //     code = ".as_ref()",
574    //     style = "verbose",
575    //     applicability = "machine-applicable"
576    // )]
577    // AsRef {
578    //     #[primary_span]
579    //     span: Span,
580    //     def_path: String,
581    //     expected_ty: Ty<'tcx>,
582    //     expr_ty: Ty<'tcx>,
583    // },
584}
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                    // This error is redundant, we will have already emitted a
740                    // suggestion to use the label when `segment` wasn't found
741                    // (hence the `Res::Err` check).
742                    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}