Skip to content

Commit 9f06c3d

Browse files
committed
Port SuggestRemoveSemiOrReturnBinding
1 parent 6fa4c7d commit 9f06c3d

File tree

4 files changed

+97
-46
lines changed

4 files changed

+97
-46
lines changed

compiler/rustc_error_messages/locales/en-US/infer.ftl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,3 +330,8 @@ infer_ril_static_introduced_by = "`'static` lifetime requirement introduced by t
330330
331331
infer_where_remove = remove the `where` clause
332332
infer_where_copy_predicates = copy the `where` clause predicates from the trait
333+
334+
infer_srs_remove_and_box = consider removing this semicolon and boxing the expressions
335+
infer_srs_remove = consider removing this semicolon
336+
infer_srs_add = consider returning the local binding `{$ident}`
337+
infer_srs_add_one = consider returning one of these bindings

compiler/rustc_infer/src/errors/mod.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,3 +1006,47 @@ pub enum WhereClauseSuggestions {
10061006
trait_predicates: String,
10071007
},
10081008
}
1009+
1010+
#[derive(Subdiagnostic)]
1011+
pub enum SuggestRemoveSemiOrReturnBinding {
1012+
#[multipart_suggestion(infer_srs_remove_and_box, applicability = "machine-applicable")]
1013+
RemoveAndBox {
1014+
#[suggestion_part(code = "Box::new(")]
1015+
first_lo: Span,
1016+
#[suggestion_part(code = ")")]
1017+
first_hi: Span,
1018+
#[suggestion_part(code = "Box::new(")]
1019+
second_lo: Span,
1020+
#[suggestion_part(code = ")")]
1021+
second_hi: Span,
1022+
#[suggestion_part(code = "")]
1023+
sp: Span,
1024+
},
1025+
#[suggestion(
1026+
infer_srs_remove,
1027+
style = "short",
1028+
code = "",
1029+
applicability = "machine-applicable"
1030+
)]
1031+
Remove {
1032+
#[primary_span]
1033+
sp: Span,
1034+
},
1035+
#[suggestion(
1036+
infer_srs_add,
1037+
style = "verbose",
1038+
code = "{code}",
1039+
applicability = "maybe-incorrect"
1040+
)]
1041+
Add {
1042+
#[primary_span]
1043+
sp: Span,
1044+
code: String,
1045+
ident: Ident,
1046+
},
1047+
#[note(infer_srs_add_one)]
1048+
AddOne {
1049+
#[primary_span]
1050+
spans: MultiSpan,
1051+
},
1052+
}

compiler/rustc_infer/src/infer/error_reporting/mod.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -750,15 +750,16 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
750750
};
751751
let msg = "`match` arms have incompatible types";
752752
err.span_label(outer, msg);
753-
self.suggest_remove_semi_or_return_binding(
754-
err,
753+
if let Some(subdiag) = self.suggest_remove_semi_or_return_binding(
755754
prior_arm_block_id,
756755
prior_arm_ty,
757756
prior_arm_span,
758757
arm_block_id,
759758
arm_ty,
760759
arm_span,
761-
);
760+
) {
761+
err.subdiagnostic(subdiag);
762+
}
762763
if let Some(ret_sp) = opt_suggest_box_span {
763764
// Get return type span and point to it.
764765
self.suggest_boxing_for_return_impl_trait(
@@ -783,15 +784,16 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
783784
if let Some(sp) = outer_span {
784785
err.span_label(sp, "`if` and `else` have incompatible types");
785786
}
786-
self.suggest_remove_semi_or_return_binding(
787-
err,
787+
if let Some(subdiag) = self.suggest_remove_semi_or_return_binding(
788788
Some(then_id),
789789
then_ty,
790790
then_span,
791791
Some(else_id),
792792
else_ty,
793793
else_span,
794-
);
794+
) {
795+
err.subdiagnostic(subdiag);
796+
}
795797
if let Some(ret_sp) = opt_suggest_box_span {
796798
self.suggest_boxing_for_return_impl_trait(
797799
err,

compiler/rustc_infer/src/infer/error_reporting/suggest.rs

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,20 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
1111
use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TypeVisitable};
1212
use rustc_span::{sym, BytePos, Span};
1313

14-
use crate::errors::SuggAddLetForLetChains;
14+
use crate::errors::{SuggAddLetForLetChains, SuggestRemoveSemiOrReturnBinding};
1515

1616
use super::TypeErrCtxt;
1717

1818
impl<'tcx> TypeErrCtxt<'_, 'tcx> {
1919
pub(super) fn suggest_remove_semi_or_return_binding(
2020
&self,
21-
err: &mut Diagnostic,
2221
first_id: Option<hir::HirId>,
2322
first_ty: Ty<'tcx>,
2423
first_span: Span,
2524
second_id: Option<hir::HirId>,
2625
second_ty: Ty<'tcx>,
2726
second_span: Span,
28-
) {
27+
) -> Option<SuggestRemoveSemiOrReturnBinding> {
2928
let remove_semicolon = [
3029
(first_id, self.resolve_vars_if_possible(second_ty)),
3130
(second_id, self.resolve_vars_if_possible(first_ty)),
@@ -37,35 +36,29 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
3736
});
3837
match remove_semicolon {
3938
Some((sp, StatementAsExpression::NeedsBoxing)) => {
40-
err.multipart_suggestion(
41-
"consider removing this semicolon and boxing the expressions",
42-
vec![
43-
(first_span.shrink_to_lo(), "Box::new(".to_string()),
44-
(first_span.shrink_to_hi(), ")".to_string()),
45-
(second_span.shrink_to_lo(), "Box::new(".to_string()),
46-
(second_span.shrink_to_hi(), ")".to_string()),
47-
(sp, String::new()),
48-
],
49-
Applicability::MachineApplicable,
50-
);
39+
Some(SuggestRemoveSemiOrReturnBinding::RemoveAndBox {
40+
first_lo: first_span.shrink_to_lo(),
41+
first_hi: first_span.shrink_to_hi(),
42+
second_lo: second_span.shrink_to_lo(),
43+
second_hi: second_span.shrink_to_hi(),
44+
sp,
45+
})
5146
}
5247
Some((sp, StatementAsExpression::CorrectType)) => {
53-
err.span_suggestion_short(
54-
sp,
55-
"consider removing this semicolon",
56-
"",
57-
Applicability::MachineApplicable,
58-
);
48+
Some(SuggestRemoveSemiOrReturnBinding::Remove { sp })
5949
}
6050
None => {
51+
let mut ret = None;
6152
for (id, ty) in [(first_id, second_ty), (second_id, first_ty)] {
6253
if let Some(id) = id
6354
&& let hir::Node::Block(blk) = self.tcx.hir().get(id)
64-
&& self.consider_returning_binding(blk, ty, err)
55+
&& let Some(diag) = self.consider_returning_binding_diag(blk, ty)
6556
{
57+
ret = Some(diag);
6658
break;
6759
}
6860
}
61+
ret
6962
}
7063
}
7164
}
@@ -655,16 +648,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
655648

656649
/// Suggest returning a local binding with a compatible type if the block
657650
/// has no return expression.
658-
pub fn consider_returning_binding(
651+
pub fn consider_returning_binding_diag(
659652
&self,
660653
blk: &'tcx hir::Block<'tcx>,
661654
expected_ty: Ty<'tcx>,
662-
err: &mut Diagnostic,
663-
) -> bool {
655+
) -> Option<SuggestRemoveSemiOrReturnBinding> {
664656
let blk = blk.innermost_block();
665657
// Do not suggest if we have a tail expr.
666658
if blk.expr.is_some() {
667-
return false;
659+
return None;
668660
}
669661
let mut shadowed = FxIndexSet::default();
670662
let mut candidate_idents = vec![];
@@ -733,7 +725,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
733725
match &candidate_idents[..] {
734726
[(ident, _ty)] => {
735727
let sm = self.tcx.sess.source_map();
736-
if let Some(stmt) = blk.stmts.last() {
728+
let (span, sugg) = if let Some(stmt) = blk.stmts.last() {
737729
let stmt_span = sm.stmt_span(stmt.span, blk.span);
738730
let sugg = if sm.is_multiline(blk.span)
739731
&& let Some(spacing) = sm.indentation_before(stmt_span)
@@ -742,12 +734,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
742734
} else {
743735
format!(" {ident}")
744736
};
745-
err.span_suggestion_verbose(
746-
stmt_span.shrink_to_hi(),
747-
format!("consider returning the local binding `{ident}`"),
748-
sugg,
749-
Applicability::MaybeIncorrect,
750-
);
737+
(stmt_span.shrink_to_hi(), sugg)
751738
} else {
752739
let sugg = if sm.is_multiline(blk.span)
753740
&& let Some(spacing) = sm.indentation_before(blk.span.shrink_to_lo())
@@ -757,21 +744,34 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
757744
format!(" {ident} ")
758745
};
759746
let left_span = sm.span_through_char(blk.span, '{').shrink_to_hi();
760-
err.span_suggestion_verbose(
747+
(
761748
sm.span_extend_while(left_span, |c| c.is_whitespace()).unwrap_or(left_span),
762-
format!("consider returning the local binding `{ident}`"),
763749
sugg,
764-
Applicability::MaybeIncorrect,
765-
);
766-
}
767-
true
750+
)
751+
};
752+
Some(SuggestRemoveSemiOrReturnBinding::Add { sp: span, code: sugg, ident: *ident })
768753
}
769754
values if (1..3).contains(&values.len()) => {
770755
let spans = values.iter().map(|(ident, _)| ident.span).collect::<Vec<_>>();
771-
err.span_note(spans, "consider returning one of these bindings");
756+
Some(SuggestRemoveSemiOrReturnBinding::AddOne { spans: spans.into() })
757+
}
758+
_ => None,
759+
}
760+
}
761+
762+
pub fn consider_returning_binding(
763+
&self,
764+
blk: &'tcx hir::Block<'tcx>,
765+
expected_ty: Ty<'tcx>,
766+
err: &mut Diagnostic,
767+
) -> bool {
768+
let diag = self.consider_returning_binding_diag(blk, expected_ty);
769+
match diag {
770+
Some(diag) => {
771+
err.subdiagnostic(diag);
772772
true
773773
}
774-
_ => false,
774+
None => false,
775775
}
776776
}
777777
}

0 commit comments

Comments
 (0)