@@ -3932,6 +3932,72 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
39323932 }
39333933 }
39343934
3935+ /// A possible error is to forget to add `.await` when using futures:
3936+ ///
3937+ /// ```
3938+ /// #![feature(async_await)]
3939+ ///
3940+ /// async fn make_u32() -> u32 {
3941+ /// 22
3942+ /// }
3943+ ///
3944+ /// fn take_u32(x: u32) {}
3945+ ///
3946+ /// async fn foo() {
3947+ /// let x = make_u32();
3948+ /// take_u32(x);
3949+ /// }
3950+ /// ```
3951+ ///
3952+ /// This routine checks if the found type `T` implements `Future<Output=U>` where `U` is the
3953+ /// expected type. If this is the case, and we are inside of an async body, it suggests adding
3954+ /// `.await` to the tail of the expression.
3955+ fn suggest_missing_await (
3956+ & self ,
3957+ err : & mut DiagnosticBuilder < ' tcx > ,
3958+ expr : & hir:: Expr ,
3959+ expected : Ty < ' tcx > ,
3960+ found : Ty < ' tcx > ,
3961+ ) {
3962+ // `.await` is not permitted outside of `async` bodies, so don't bother to suggest if the
3963+ // body isn't `async`.
3964+ let item_id = self . tcx ( ) . hir ( ) . get_parent_node ( self . body_id ) ;
3965+ if let Some ( body_id) = self . tcx ( ) . hir ( ) . maybe_body_owned_by ( item_id) {
3966+ let body = self . tcx ( ) . hir ( ) . body ( body_id) ;
3967+ if let Some ( hir:: GeneratorKind :: Async ) = body. generator_kind {
3968+ let sp = expr. span ;
3969+ // Check for `Future` implementations by constructing a predicate to
3970+ // prove: `<T as Future>::Output == U`
3971+ let future_trait = self . tcx . lang_items ( ) . future_trait ( ) . unwrap ( ) ;
3972+ let item_def_id = self . tcx . associated_items ( future_trait) . next ( ) . unwrap ( ) . def_id ;
3973+ let predicate = ty:: Predicate :: Projection ( ty:: Binder :: bind ( ty:: ProjectionPredicate {
3974+ // `<T as Future>::Output`
3975+ projection_ty : ty:: ProjectionTy {
3976+ // `T`
3977+ substs : self . tcx . mk_substs_trait (
3978+ found,
3979+ self . fresh_substs_for_item ( sp, item_def_id)
3980+ ) ,
3981+ // `Future::Output`
3982+ item_def_id,
3983+ } ,
3984+ ty : expected,
3985+ } ) ) ;
3986+ let obligation = traits:: Obligation :: new ( self . misc ( sp) , self . param_env , predicate) ;
3987+ if self . infcx . predicate_may_hold ( & obligation) {
3988+ if let Ok ( code) = self . sess ( ) . source_map ( ) . span_to_snippet ( sp) {
3989+ err. span_suggestion (
3990+ sp,
3991+ "consider using `.await` here" ,
3992+ format ! ( "{}.await" , code) ,
3993+ Applicability :: MaybeIncorrect ,
3994+ ) ;
3995+ }
3996+ }
3997+ }
3998+ }
3999+ }
4000+
39354001 /// A common error is to add an extra semicolon:
39364002 ///
39374003 /// ```
0 commit comments