suggest await before try when performing trait selection
This commit is contained in:
parent
114cd006f5
commit
627f473dd4
@ -25,7 +25,7 @@
|
||||
)
|
||||
)]
|
||||
#[doc(alias = "?")]
|
||||
#[cfg_attr(not(bootstrap), lang = "try_trait")]
|
||||
#[cfg_attr(not(bootstrap), lang = "try_trait")]
|
||||
pub trait Try {
|
||||
/// The type of this value when viewed as successful.
|
||||
#[unstable(feature = "try_trait", issue = "42327")]
|
||||
|
@ -400,6 +400,17 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
self.suggest_remove_reference(&obligation, &mut err, &trait_ref);
|
||||
self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref);
|
||||
self.note_version_mismatch(&mut err, &trait_ref);
|
||||
//self.sugggest_await_before_try(&mut err, &obligation, &trait_ref);
|
||||
debug!(
|
||||
"suggest_await_befor_try: trait_predicate={:?} obligation={:?}, trait_ref={:?}",
|
||||
trait_predicate, obligation, trait_ref
|
||||
);
|
||||
self.suggest_await_befor_try(
|
||||
&mut err,
|
||||
&obligation,
|
||||
trait_ref.self_ty(),
|
||||
span,
|
||||
);
|
||||
if self.suggest_impl_trait(&mut err, span, &obligation, &trait_ref) {
|
||||
err.emit();
|
||||
return;
|
||||
|
@ -1,8 +1,10 @@
|
||||
use super::{
|
||||
EvaluationResult, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation,
|
||||
SelectionContext,
|
||||
};
|
||||
|
||||
use crate::infer::InferCtxt;
|
||||
use crate::traits::normalize_projection_type;
|
||||
|
||||
use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder, Style};
|
||||
use rustc_hir as hir;
|
||||
@ -150,6 +152,15 @@ pub trait InferCtxtExt<'tcx> {
|
||||
T: fmt::Display;
|
||||
|
||||
fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>);
|
||||
|
||||
/// Suggest to await before try: future? => future.await?
|
||||
fn suggest_await_befor_try(
|
||||
&self,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
);
|
||||
}
|
||||
|
||||
fn predicate_constraint(generics: &hir::Generics<'_>, pred: String) -> (Span, String) {
|
||||
@ -1765,6 +1776,75 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
suggested_limit, self.tcx.crate_name,
|
||||
));
|
||||
}
|
||||
|
||||
fn suggest_await_befor_try(
|
||||
&self,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
) {
|
||||
debug!("suggest_await_befor_try: obligation={:?}, span={:?}", obligation, span);
|
||||
let body_hir_id = obligation.cause.body_id;
|
||||
let item_id = self.tcx.hir().get_parent_node(body_hir_id);
|
||||
if let Some(body_id) = self.tcx.hir().maybe_body_owned_by(item_id) {
|
||||
let body = self.tcx.hir().body(body_id);
|
||||
if let Some(hir::GeneratorKind::Async(_)) = body.generator_kind {
|
||||
// Check for `Future` implementations by constructing a predicate to
|
||||
// prove: `<T as Future>::Output == U`
|
||||
let future_trait = self.tcx.lang_items().future_trait().unwrap();
|
||||
let item_def_id = self
|
||||
.tcx
|
||||
.associated_items(future_trait)
|
||||
.in_definition_order()
|
||||
.next()
|
||||
.unwrap()
|
||||
.def_id;
|
||||
// `<T as Future>::Output`
|
||||
let projection_ty = ty::ProjectionTy {
|
||||
// `T`
|
||||
substs: self
|
||||
.tcx
|
||||
.mk_substs_trait(ty, self.fresh_substs_for_item(span, item_def_id)),
|
||||
// `Future::Output`
|
||||
item_def_id,
|
||||
};
|
||||
|
||||
let cause = ObligationCause::misc(span, body_hir_id);
|
||||
let mut selcx = SelectionContext::new(self);
|
||||
|
||||
let mut obligations = vec![];
|
||||
let normalized_ty = normalize_projection_type(
|
||||
&mut selcx,
|
||||
obligation.param_env,
|
||||
projection_ty,
|
||||
obligation.cause.clone(),
|
||||
0,
|
||||
&mut obligations,
|
||||
);
|
||||
|
||||
debug!("suggest_await_befor_try: normalized_projection_type {:?}", normalized_ty);
|
||||
let try_trait_ref_id = self.tcx.lang_items().try_trait().unwrap();
|
||||
if let Some(try_trait_ref) = self.tcx.impl_trait_ref(try_trait_ref_id) {
|
||||
let try_predicate = try_trait_ref.without_const().to_predicate();
|
||||
let try_obligation =
|
||||
Obligation::new(cause, obligation.param_env, try_predicate);
|
||||
debug!("suggest_await_befor_try: try_trait_obligation {:?}", try_obligation);
|
||||
if self.predicate_may_hold(&try_obligation) {
|
||||
debug!("try_obligation holds");
|
||||
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
|
||||
err.span_suggestion(
|
||||
span,
|
||||
"consider using `.await` here",
|
||||
format!("{}.await", snippet),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Collect all the returned expressions within the input expression.
|
||||
|
@ -5317,15 +5317,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
item_def_id,
|
||||
};
|
||||
|
||||
let cause = traits::ObligationCause::misc(sp, self.body_id);
|
||||
let normalized_ty = self.fulfillment_cx.borrow_mut().normalize_projection_type(
|
||||
&self.infcx,
|
||||
self.param_env,
|
||||
projection_ty,
|
||||
cause,
|
||||
);
|
||||
debug!("suggest_missing_await: projection_type {:?}", normalized_ty);
|
||||
|
||||
let predicate =
|
||||
ty::Predicate::Projection(ty::Binder::bind(ty::ProjectionPredicate {
|
||||
projection_ty,
|
||||
|
Loading…
x
Reference in New Issue
Block a user