|
2 | 2 |
|
3 | 3 | use std::borrow::Cow;
|
4 | 4 |
|
| 5 | +use rustc_ast::Label; |
5 | 6 | use rustc_errors::codes::*;
|
6 | 7 | use rustc_errors::{
|
7 | 8 | Applicability, Diag, DiagArgValue, DiagCtxtHandle, DiagSymbolList, Diagnostic,
|
8 | 9 | EmissionGuarantee, IntoDiagArg, Level, MultiSpan, Subdiagnostic,
|
9 | 10 | };
|
| 11 | +use rustc_hir as hir; |
| 12 | +use rustc_hir::ExprKind; |
10 | 13 | use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
11 | 14 | use rustc_middle::ty::{self, Ty};
|
12 | 15 | use rustc_span::edition::{Edition, LATEST_STABLE_EDITION};
|
@@ -721,6 +724,131 @@ pub(crate) struct TrivialCast<'tcx> {
|
721 | 724 | pub cast_ty: Ty<'tcx>,
|
722 | 725 | }
|
723 | 726 |
|
| 727 | +pub(crate) struct BreakNonLoop<'a> { |
| 728 | + pub span: Span, |
| 729 | + pub head: Option<Span>, |
| 730 | + pub kind: &'a str, |
| 731 | + pub suggestion: String, |
| 732 | + pub loop_label: Option<Label>, |
| 733 | + pub break_label: Option<Label>, |
| 734 | + pub break_expr_kind: &'a ExprKind<'a>, |
| 735 | + pub break_expr_span: Span, |
| 736 | +} |
| 737 | + |
| 738 | +impl<'a, G: EmissionGuarantee> Diagnostic<'_, G> for BreakNonLoop<'a> { |
| 739 | + #[track_caller] |
| 740 | + fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { |
| 741 | + let mut diag = Diag::new(dcx, level, fluent::hir_typeck_break_non_loop); |
| 742 | + diag.span(self.span); |
| 743 | + diag.code(E0571); |
| 744 | + diag.arg("kind", self.kind); |
| 745 | + diag.span_label(self.span, fluent::hir_typeck_label); |
| 746 | + if let Some(head) = self.head { |
| 747 | + diag.span_label(head, fluent::hir_typeck_label2); |
| 748 | + } |
| 749 | + diag.span_suggestion( |
| 750 | + self.span, |
| 751 | + fluent::hir_typeck_suggestion, |
| 752 | + self.suggestion, |
| 753 | + Applicability::MaybeIncorrect, |
| 754 | + ); |
| 755 | + if let (Some(label), None) = (self.loop_label, self.break_label) { |
| 756 | + match self.break_expr_kind { |
| 757 | + ExprKind::Path(hir::QPath::Resolved( |
| 758 | + None, |
| 759 | + hir::Path { segments: [segment], res: hir::def::Res::Err, .. }, |
| 760 | + )) if label.ident.to_string() == format!("'{}", segment.ident) => { |
| 761 | + // This error is redundant, we will have already emitted a |
| 762 | + // suggestion to use the label when `segment` wasn't found |
| 763 | + // (hence the `Res::Err` check). |
| 764 | + diag.downgrade_to_delayed_bug(); |
| 765 | + } |
| 766 | + _ => { |
| 767 | + diag.span_suggestion( |
| 768 | + self.break_expr_span, |
| 769 | + fluent::hir_typeck_break_expr_suggestion, |
| 770 | + label.ident, |
| 771 | + Applicability::MaybeIncorrect, |
| 772 | + ); |
| 773 | + } |
| 774 | + } |
| 775 | + } |
| 776 | + diag |
| 777 | + } |
| 778 | +} |
| 779 | + |
| 780 | +#[derive(Diagnostic)] |
| 781 | +#[diag(hir_typeck_continue_labeled_block, code = E0696)] |
| 782 | +pub(crate) struct ContinueLabeledBlock { |
| 783 | + #[primary_span] |
| 784 | + #[label] |
| 785 | + pub span: Span, |
| 786 | + #[label(hir_typeck_block_label)] |
| 787 | + pub block_span: Span, |
| 788 | +} |
| 789 | + |
| 790 | +#[derive(Diagnostic)] |
| 791 | +#[diag(hir_typeck_break_inside_closure, code = E0267)] |
| 792 | +pub(crate) struct BreakInsideClosure<'a> { |
| 793 | + #[primary_span] |
| 794 | + #[label] |
| 795 | + pub span: Span, |
| 796 | + #[label(hir_typeck_closure_label)] |
| 797 | + pub closure_span: Span, |
| 798 | + pub name: &'a str, |
| 799 | +} |
| 800 | + |
| 801 | +#[derive(Diagnostic)] |
| 802 | +#[diag(hir_typeck_break_inside_coroutine, code = E0267)] |
| 803 | +pub(crate) struct BreakInsideCoroutine<'a> { |
| 804 | + #[primary_span] |
| 805 | + #[label] |
| 806 | + pub span: Span, |
| 807 | + #[label(hir_typeck_coroutine_label)] |
| 808 | + pub coroutine_span: Span, |
| 809 | + pub name: &'a str, |
| 810 | + pub kind: &'a str, |
| 811 | + pub source: &'a str, |
| 812 | +} |
| 813 | + |
| 814 | +#[derive(Diagnostic)] |
| 815 | +#[diag(hir_typeck_outside_loop, code = E0268)] |
| 816 | +pub(crate) struct OutsideLoop<'a> { |
| 817 | + #[primary_span] |
| 818 | + #[label] |
| 819 | + pub spans: Vec<Span>, |
| 820 | + pub name: &'a str, |
| 821 | + pub is_break: bool, |
| 822 | + #[subdiagnostic] |
| 823 | + pub suggestion: Option<OutsideLoopSuggestion>, |
| 824 | +} |
| 825 | +#[derive(Subdiagnostic)] |
| 826 | +#[multipart_suggestion(hir_typeck_outside_loop_suggestion, applicability = "maybe-incorrect")] |
| 827 | +pub(crate) struct OutsideLoopSuggestion { |
| 828 | + #[suggestion_part(code = "'block: ")] |
| 829 | + pub block_span: Span, |
| 830 | + #[suggestion_part(code = " 'block")] |
| 831 | + pub break_spans: Vec<Span>, |
| 832 | +} |
| 833 | + |
| 834 | +#[derive(Diagnostic)] |
| 835 | +#[diag(hir_typeck_unlabeled_in_labeled_block, code = E0695)] |
| 836 | +pub(crate) struct UnlabeledInLabeledBlock<'a> { |
| 837 | + #[primary_span] |
| 838 | + #[label] |
| 839 | + pub span: Span, |
| 840 | + pub cf_type: &'a str, |
| 841 | +} |
| 842 | + |
| 843 | +#[derive(Diagnostic)] |
| 844 | +#[diag(hir_typeck_unlabeled_cf_in_while_condition, code = E0590)] |
| 845 | +pub(crate) struct UnlabeledCfInWhileCondition<'a> { |
| 846 | + #[primary_span] |
| 847 | + #[label] |
| 848 | + pub span: Span, |
| 849 | + pub cf_type: &'a str, |
| 850 | +} |
| 851 | + |
724 | 852 | #[derive(Diagnostic)]
|
725 | 853 | #[diag(hir_typeck_no_associated_item, code = E0599)]
|
726 | 854 | pub(crate) struct NoAssociatedItem {
|
|
0 commit comments