@@ -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 } ;
@@ -1834,6 +1835,58 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1834
1835
}
1835
1836
}
1836
1837
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
+
1837
1890
/// Given a vector of fulfillment errors, try to adjust the spans of the
1838
1891
/// errors to more accurately point at the cause of the failure.
1839
1892
///
0 commit comments