Port ConsiderAddingAwait

This commit is contained in:
IQuant 2023-01-31 19:12:48 +03:00
parent 9f06c3d87f
commit fdbec623c4
3 changed files with 74 additions and 38 deletions

View File

@ -335,3 +335,7 @@ infer_srs_remove_and_box = consider removing this semicolon and boxing the expre
infer_srs_remove = consider removing this semicolon infer_srs_remove = consider removing this semicolon
infer_srs_add = consider returning the local binding `{$ident}` infer_srs_add = consider returning the local binding `{$ident}`
infer_srs_add_one = consider returning one of these bindings infer_srs_add_one = consider returning one of these bindings
infer_await_both_futures = consider `await`ing on both `Future`s
infer_await_future = consider `await`ing on the `Future`
infer_await_note = calling an async function returns a future

View File

@ -1050,3 +1050,46 @@ pub enum SuggestRemoveSemiOrReturnBinding {
spans: MultiSpan, spans: MultiSpan,
}, },
} }
#[derive(Subdiagnostic)]
pub enum ConsiderAddingAwait {
#[help(infer_await_both_futures)]
BothFuturesHelp,
#[multipart_suggestion(infer_await_both_futures, applicability = "maybe-incorrect")]
BothFuturesSugg {
#[suggestion_part(code = ".await")]
first: Span,
#[suggestion_part(code = ".await")]
second: Span,
},
#[suggestion(
infer_await_future,
code = ".await",
style = "verbose",
applicability = "maybe-incorrect"
)]
FutureSugg {
#[primary_span]
span: Span,
},
#[suggestion(
infer_await_future,
code = ".await",
style = "verbose",
applicability = "maybe-incorrect"
)]
#[note(infer_await_note)]
FutureSuggWithNote {
#[primary_span]
span: Span,
},
#[multipart_suggestion(
infer_await_future,
style = "verbose",
applicability = "maybe-incorrect"
)]
FutureSuggMultiple {
#[suggestion_part(code = ".await")]
spans: Vec<Span>,
},
}

View File

@ -11,7 +11,9 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TypeVisitable}; use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TypeVisitable};
use rustc_span::{sym, BytePos, Span}; use rustc_span::{sym, BytePos, Span};
use crate::errors::{SuggAddLetForLetChains, SuggestRemoveSemiOrReturnBinding}; use crate::errors::{
ConsiderAddingAwait, SuggAddLetForLetChains, SuggestRemoveSemiOrReturnBinding,
};
use super::TypeErrCtxt; use super::TypeErrCtxt;
@ -191,7 +193,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
return; return;
} }
match ( let subdiag = match (
self.get_impl_future_output_ty(exp_found.expected), self.get_impl_future_output_ty(exp_found.expected),
self.get_impl_future_output_ty(exp_found.found), self.get_impl_future_output_ty(exp_found.found),
) { ) {
@ -200,65 +202,52 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
{ {
ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => { ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => {
let then_span = self.find_block_span_from_hir_id(*then_id); let then_span = self.find_block_span_from_hir_id(*then_id);
diag.multipart_suggestion( Some(ConsiderAddingAwait::BothFuturesSugg {
"consider `await`ing on both `Future`s", first: then_span.shrink_to_hi(),
vec![ second: exp_span.shrink_to_hi(),
(then_span.shrink_to_hi(), ".await".to_string()), })
(exp_span.shrink_to_hi(), ".await".to_string()),
],
Applicability::MaybeIncorrect,
);
} }
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
prior_arms, prior_arms,
.. ..
}) => { }) => {
if let [.., arm_span] = &prior_arms[..] { if let [.., arm_span] = &prior_arms[..] {
diag.multipart_suggestion( Some(ConsiderAddingAwait::BothFuturesSugg {
"consider `await`ing on both `Future`s", first: arm_span.shrink_to_hi(),
vec![ second: exp_span.shrink_to_hi(),
(arm_span.shrink_to_hi(), ".await".to_string()), })
(exp_span.shrink_to_hi(), ".await".to_string()),
],
Applicability::MaybeIncorrect,
);
} else { } else {
diag.help("consider `await`ing on both `Future`s"); Some(ConsiderAddingAwait::BothFuturesHelp)
} }
} }
_ => { _ => Some(ConsiderAddingAwait::BothFuturesHelp),
diag.help("consider `await`ing on both `Future`s");
}
}, },
(_, Some(ty)) if self.same_type_modulo_infer(exp_found.expected, ty) => { (_, Some(ty)) if self.same_type_modulo_infer(exp_found.expected, ty) => {
self.suggest_await_on_future(diag, exp_span); Some(ConsiderAddingAwait::FutureSuggWithNote { span: exp_span.shrink_to_hi() })
diag.span_note(exp_span, "calling an async function returns a future");
} }
(Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code() (Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code()
{ {
ObligationCauseCode::Pattern { span: Some(then_span), .. } => { ObligationCauseCode::Pattern { span: Some(then_span), .. } => {
self.suggest_await_on_future(diag, then_span.shrink_to_hi()); Some(ConsiderAddingAwait::FutureSugg { span: then_span.shrink_to_hi() })
} }
ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => { ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => {
let then_span = self.find_block_span_from_hir_id(*then_id); let then_span = self.find_block_span_from_hir_id(*then_id);
self.suggest_await_on_future(diag, then_span.shrink_to_hi()); Some(ConsiderAddingAwait::FutureSugg { span: then_span.shrink_to_hi() })
} }
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
ref prior_arms, ref prior_arms,
.. ..
}) => { }) => Some({
diag.multipart_suggestion_verbose( ConsiderAddingAwait::FutureSuggMultiple {
"consider `await`ing on the `Future`", spans: prior_arms.iter().map(|arm| arm.shrink_to_hi()).collect(),
prior_arms }
.iter() }),
.map(|arm| (arm.shrink_to_hi(), ".await".to_string())) _ => None,
.collect(),
Applicability::MaybeIncorrect,
);
}
_ => {}
}, },
_ => {} _ => None,
};
if let Some(subdiag) = subdiag {
diag.subdiagnostic(subdiag);
} }
} }