@@ -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 } ;
@@ -26,6 +26,7 @@ use rustc_infer::infer::error_reporting::{FailureCode, ObligationCauseExt};
26
26
use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
27
27
use rustc_infer:: infer:: TypeTrace ;
28
28
use rustc_infer:: infer:: { DefineOpaqueTypes , InferOk } ;
29
+ use rustc_middle:: traits:: ObligationCauseCode :: ExprBindingObligation ;
29
30
use rustc_middle:: ty:: adjustment:: AllowTwoPhase ;
30
31
use rustc_middle:: ty:: visit:: TypeVisitableExt ;
31
32
use rustc_middle:: ty:: { self , IsSuggestable , Ty } ;
@@ -1843,6 +1844,58 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1843
1844
}
1844
1845
}
1845
1846
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
+
1846
1899
/// Given a vector of fulfillment errors, try to adjust the spans of the
1847
1900
/// errors to more accurately point at the cause of the failure.
1848
1901
///
0 commit comments