@@ -3913,6 +3913,72 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
39133913 }
39143914 }
39153915
3916+ /// A possible error is to forget to add `.await` when using futures:
3917+ ///
3918+ /// ```
3919+ /// #![feature(async_await)]
3920+ ///
3921+ /// async fn make_u32() -> u32 {
3922+ /// 22
3923+ /// }
3924+ ///
3925+ /// fn take_u32(x: u32) {}
3926+ ///
3927+ /// async fn foo() {
3928+ /// let x = make_u32();
3929+ /// take_u32(x);
3930+ /// }
3931+ /// ```
3932+ ///
3933+ /// This routine checks if the found type `T` implements `Future<Output=U>` where `U` is the
3934+ /// expected type. If this is the case, and we are inside of an async body, it suggests adding
3935+ /// `.await` to the tail of the expression.
3936+ fn suggest_missing_await (
3937+ & self ,
3938+ err : & mut DiagnosticBuilder < ' tcx > ,
3939+ expr : & hir:: Expr ,
3940+ expected : Ty < ' tcx > ,
3941+ found : Ty < ' tcx > ,
3942+ ) {
3943+ // `.await` is not permitted outside of `async` bodies, so don't bother to suggest if the
3944+ // body isn't `async`.
3945+ let item_id = self . tcx ( ) . hir ( ) . get_parent_node_by_hir_id ( self . body_id ) ;
3946+ if let Some ( body_id) = self . tcx ( ) . hir ( ) . maybe_body_owned_by ( item_id) {
3947+ let body = self . tcx ( ) . hir ( ) . body ( body_id) ;
3948+ if let Some ( hir:: GeneratorKind :: Async ) = body. generator_kind {
3949+ let sp = expr. span ;
3950+ // Check for `Future` implementations by constructing a predicate to
3951+ // prove: `<T as Future>::Output == U`
3952+ let future_trait = self . tcx . lang_items ( ) . future_trait ( ) . unwrap ( ) ;
3953+ let item_def_id = self . tcx . associated_items ( future_trait) . next ( ) . unwrap ( ) . def_id ;
3954+ let predicate = ty:: Predicate :: Projection ( ty:: Binder :: bind ( ty:: ProjectionPredicate {
3955+ // `<T as Future>::Output`
3956+ projection_ty : ty:: ProjectionTy {
3957+ // `T`
3958+ substs : self . tcx . mk_substs_trait (
3959+ found,
3960+ self . fresh_substs_for_item ( sp, item_def_id)
3961+ ) ,
3962+ // `Future::Output`
3963+ item_def_id,
3964+ } ,
3965+ ty : expected,
3966+ } ) ) ;
3967+ let obligation = traits:: Obligation :: new ( self . misc ( sp) , self . param_env , predicate) ;
3968+ if self . infcx . predicate_may_hold ( & obligation) {
3969+ if let Ok ( code) = self . sess ( ) . source_map ( ) . span_to_snippet ( sp) {
3970+ err. span_suggestion (
3971+ sp,
3972+ "consider using `.await` here" ,
3973+ format ! ( "{}.await" , code) ,
3974+ Applicability :: MaybeIncorrect ,
3975+ ) ;
3976+ }
3977+ }
3978+ }
3979+ }
3980+ }
3981+
39163982 /// A common error is to add an extra semicolon:
39173983 ///
39183984 /// ```
0 commit comments