@@ -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 } ;
@@ -1843,6 +1844,58 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
18431844 }
18441845 }
18451846
1847+ pub ( super ) fn collect_unused_for_coerce_return_ty (
1848+ & self ,
1849+ errors : & [ traits:: FulfillmentError < ' tcx > ] ,
1850+ ) {
1851+ for fillment_error in & * errors {
1852+ let obligation = & fillment_error. obligation ;
1853+ let span = obligation. cause . span ;
1854+
1855+ let Some ( mut diag) =
1856+ self . tcx . sess . diagnostic ( ) . steal_diagnostic ( span, StashKey :: MaybeForgetReturn )
1857+ else {
1858+ continue ;
1859+ } ;
1860+
1861+ let root_obligation = & fillment_error. root_obligation ;
1862+ if let Some ( fn_sig) = self . body_fn_sig ( )
1863+ && let ExprBindingObligation ( _, _, hir_id, ..) = root_obligation. cause . code ( )
1864+ && !fn_sig. output ( ) . is_unit ( ) {
1865+ let mut block_num = 0 ;
1866+ let mut found_semi = false ;
1867+ for ( _, node) in self . tcx . hir ( ) . parent_iter ( * hir_id) {
1868+ match node {
1869+ hir:: Node :: Stmt ( stmt) => if let hir:: StmtKind :: Semi ( ref expr) = stmt. kind {
1870+ let expr_ty = self . typeck_results . borrow ( ) . expr_ty ( expr) ;
1871+ let return_ty = fn_sig. output ( ) ;
1872+ if !matches ! ( expr. kind, hir:: ExprKind :: Ret ( ..) ) &&
1873+ self . can_coerce ( expr_ty, return_ty) {
1874+ found_semi = true ;
1875+ }
1876+ } ,
1877+ hir:: Node :: Block ( _block) => if found_semi {
1878+ block_num += 1 ;
1879+ }
1880+ hir:: Node :: Item ( item) => if let hir:: ItemKind :: Fn ( ..) = item. kind {
1881+ break ;
1882+ }
1883+ _ => { }
1884+ }
1885+ }
1886+ if block_num > 1 && found_semi {
1887+ diag. span_suggestion_verbose (
1888+ span. shrink_to_lo ( ) ,
1889+ "you might have meant to return this to infer its type parameters" ,
1890+ "return " ,
1891+ Applicability :: MaybeIncorrect ,
1892+ ) ;
1893+ }
1894+ }
1895+ diag. emit ( ) ;
1896+ }
1897+ }
1898+
18461899 /// Given a vector of fulfillment errors, try to adjust the spans of the
18471900 /// errors to more accurately point at the cause of the failure.
18481901 ///
0 commit comments