@@ -3913,6 +3913,72 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3913
3913
}
3914
3914
}
3915
3915
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
+
3916
3982
/// A common error is to add an extra semicolon:
3917
3983
///
3918
3984
/// ```
0 commit comments