@@ -3932,6 +3932,72 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3932
3932
}
3933
3933
}
3934
3934
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
+
3935
4001
/// A common error is to add an extra semicolon:
3936
4002
///
3937
4003
/// ```
0 commit comments