@@ -11,7 +11,7 @@ use crate::{
11
11
use rustc_ast as ast;
12
12
use rustc_data_structures:: fx:: FxIndexSet ;
13
13
use rustc_errors:: {
14
- pluralize, Applicability , Diagnostic , DiagnosticId , ErrorGuaranteed , MultiSpan ,
14
+ pluralize, Applicability , Diagnostic , DiagnosticId , ErrorGuaranteed , MultiSpan , StashKey ,
15
15
} ;
16
16
use rustc_hir as hir;
17
17
use rustc_hir:: def:: { CtorOf , DefKind , Res } ;
@@ -27,6 +27,7 @@ use rustc_infer::infer::error_reporting::{FailureCode, ObligationCauseExt};
27
27
use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
28
28
use rustc_infer:: infer:: TypeTrace ;
29
29
use rustc_infer:: infer:: { DefineOpaqueTypes , InferOk } ;
30
+ use rustc_middle:: traits:: ObligationCauseCode :: ExprBindingObligation ;
30
31
use rustc_middle:: ty:: adjustment:: AllowTwoPhase ;
31
32
use rustc_middle:: ty:: visit:: TypeVisitableExt ;
32
33
use rustc_middle:: ty:: { self , IsSuggestable , Ty , TyCtxt } ;
@@ -1375,7 +1376,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1375
1376
}
1376
1377
_ => bug ! ( "unexpected type: {:?}" , ty. normalized) ,
1377
1378
} ,
1378
- Res :: Def ( DefKind :: Struct | DefKind :: Union | DefKind :: TyAlias | DefKind :: AssocTy , _)
1379
+ Res :: Def (
1380
+ DefKind :: Struct | DefKind :: Union | DefKind :: TyAlias { .. } | DefKind :: AssocTy ,
1381
+ _,
1382
+ )
1379
1383
| Res :: SelfTyParam { .. }
1380
1384
| Res :: SelfTyAlias { .. } => match ty. normalized . ty_adt_def ( ) {
1381
1385
Some ( adt) if !adt. is_enum ( ) => {
@@ -1845,6 +1849,55 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1845
1849
}
1846
1850
}
1847
1851
1852
+ pub ( super ) fn collect_unused_stmts_for_coerce_return_ty (
1853
+ & self ,
1854
+ errors_causecode : Vec < ( Span , ObligationCauseCode < ' tcx > ) > ,
1855
+ ) {
1856
+ for ( span, code) in errors_causecode {
1857
+ let Some ( mut diag) =
1858
+ self . tcx . sess . diagnostic ( ) . steal_diagnostic ( span, StashKey :: MaybeForgetReturn )
1859
+ else {
1860
+ continue ;
1861
+ } ;
1862
+
1863
+ if let Some ( fn_sig) = self . body_fn_sig ( )
1864
+ && let ExprBindingObligation ( _, _, hir_id, ..) = code
1865
+ && !fn_sig. output ( ) . is_unit ( )
1866
+ {
1867
+ let mut block_num = 0 ;
1868
+ let mut found_semi = false ;
1869
+ for ( _, node) in self . tcx . hir ( ) . parent_iter ( hir_id) {
1870
+ match node {
1871
+ hir:: Node :: Stmt ( stmt) => if let hir:: StmtKind :: Semi ( ref expr) = stmt. kind {
1872
+ let expr_ty = self . typeck_results . borrow ( ) . expr_ty ( expr) ;
1873
+ let return_ty = fn_sig. output ( ) ;
1874
+ if !matches ! ( expr. kind, hir:: ExprKind :: Ret ( ..) ) &&
1875
+ self . can_coerce ( expr_ty, return_ty) {
1876
+ found_semi = true ;
1877
+ }
1878
+ } ,
1879
+ hir:: Node :: Block ( _block) => if found_semi {
1880
+ block_num += 1 ;
1881
+ }
1882
+ hir:: Node :: Item ( item) => if let hir:: ItemKind :: Fn ( ..) = item. kind {
1883
+ break ;
1884
+ }
1885
+ _ => { }
1886
+ }
1887
+ }
1888
+ if block_num > 1 && found_semi {
1889
+ diag. span_suggestion_verbose (
1890
+ span. shrink_to_lo ( ) ,
1891
+ "you might have meant to return this to infer its type parameters" ,
1892
+ "return " ,
1893
+ Applicability :: MaybeIncorrect ,
1894
+ ) ;
1895
+ }
1896
+ }
1897
+ diag. emit ( ) ;
1898
+ }
1899
+ }
1900
+
1848
1901
/// Given a vector of fulfillment errors, try to adjust the spans of the
1849
1902
/// errors to more accurately point at the cause of the failure.
1850
1903
///
0 commit comments