@@ -11,7 +11,7 @@ use crate::{
1111use rustc_ast as ast;
1212use rustc_data_structures:: fx:: FxIndexSet ;
1313use rustc_errors:: {
14- pluralize, Applicability , Diagnostic , DiagnosticId , ErrorGuaranteed , MultiSpan ,
14+ pluralize, Applicability , Diagnostic , DiagnosticId , ErrorGuaranteed , MultiSpan , StashKey ,
1515} ;
1616use rustc_hir as hir;
1717use rustc_hir:: def:: { CtorOf , DefKind , Res } ;
@@ -26,6 +26,7 @@ use rustc_infer::infer::error_reporting::{FailureCode, ObligationCauseExt};
2626use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
2727use rustc_infer:: infer:: TypeTrace ;
2828use rustc_infer:: infer:: { DefineOpaqueTypes , InferOk } ;
29+ use rustc_middle:: traits:: ObligationCauseCode :: ExprBindingObligation ;
2930use rustc_middle:: ty:: adjustment:: AllowTwoPhase ;
3031use rustc_middle:: ty:: visit:: TypeVisitableExt ;
3132use rustc_middle:: ty:: { self , IsSuggestable , Ty } ;
@@ -1834,6 +1835,58 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
18341835 }
18351836 }
18361837
1838+ pub ( super ) fn collect_unused_for_coerce_return_ty (
1839+ & self ,
1840+ errors : & [ traits:: FulfillmentError < ' tcx > ] ,
1841+ ) {
1842+ for fillment_error in & * errors {
1843+ let obligation = & fillment_error. obligation ;
1844+ let span = obligation. cause . span ;
1845+
1846+ let Some ( mut diag) =
1847+ self . tcx . sess . diagnostic ( ) . steal_diagnostic ( span, StashKey :: MaybeForgetReturn )
1848+ else {
1849+ continue ;
1850+ } ;
1851+
1852+ let root_obligation = & fillment_error. root_obligation ;
1853+ if let Some ( fn_sig) = self . body_fn_sig ( )
1854+ && let ExprBindingObligation ( _, _, hir_id, ..) = root_obligation. cause . code ( )
1855+ && !fn_sig. output ( ) . is_unit ( ) {
1856+ let mut block_num = 0 ;
1857+ let mut found_semi = false ;
1858+ for ( _, node) in self . tcx . hir ( ) . parent_iter ( * hir_id) {
1859+ match node {
1860+ hir:: Node :: Stmt ( stmt) => if let hir:: StmtKind :: Semi ( ref expr) = stmt. kind {
1861+ let expr_ty = self . typeck_results . borrow ( ) . expr_ty ( expr) ;
1862+ let return_ty = fn_sig. output ( ) ;
1863+ if !matches ! ( expr. kind, hir:: ExprKind :: Ret ( ..) ) &&
1864+ self . can_coerce ( expr_ty, return_ty) {
1865+ found_semi = true ;
1866+ }
1867+ } ,
1868+ hir:: Node :: Block ( _block) => if found_semi {
1869+ block_num += 1 ;
1870+ }
1871+ hir:: Node :: Item ( item) => if let hir:: ItemKind :: Fn ( ..) = item. kind {
1872+ break ;
1873+ }
1874+ _ => { }
1875+ }
1876+ }
1877+ if block_num > 1 && found_semi {
1878+ diag. span_suggestion_verbose (
1879+ span. shrink_to_lo ( ) ,
1880+ "you might have meant to return this to infer its type parameters" ,
1881+ "return " ,
1882+ Applicability :: MaybeIncorrect ,
1883+ ) ;
1884+ }
1885+ }
1886+ diag. emit ( ) ;
1887+ }
1888+ }
1889+
18371890 /// Given a vector of fulfillment errors, try to adjust the spans of the
18381891 /// errors to more accurately point at the cause of the failure.
18391892 ///
0 commit comments