@@ -1765,7 +1765,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
1765
1765
} ;
1766
1766
1767
1767
err. code ( E0746 ) ;
1768
- err. primary_message ( "return type cannot be a trait object without pointer indirection " ) ;
1768
+ err. primary_message ( "return type cannot have an unboxed trait object" ) ;
1769
1769
err. children . clear ( ) ;
1770
1770
1771
1771
let span = obligation. cause . span ;
@@ -1781,13 +1781,25 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
1781
1781
} else {
1782
1782
( "dyn " , span. shrink_to_lo ( ) )
1783
1783
} ;
1784
-
1785
- err. span_suggestion_verbose (
1786
- impl_span,
1787
- "consider returning an `impl Trait` instead of a `dyn Trait`" ,
1788
- "impl " ,
1789
- Applicability :: MaybeIncorrect ,
1790
- ) ;
1784
+ let alternatively = if visitor
1785
+ . returns
1786
+ . iter ( )
1787
+ . map ( |expr| self . typeck_results . as_ref ( ) . unwrap ( ) . expr_ty_adjusted_opt ( expr) )
1788
+ . collect :: < FxHashSet < _ > > ( )
1789
+ . len ( )
1790
+ <= 1
1791
+ {
1792
+ err. span_suggestion_verbose (
1793
+ impl_span,
1794
+ "consider returning an `impl Trait` instead of a `dyn Trait`" ,
1795
+ "impl " ,
1796
+ Applicability :: MaybeIncorrect ,
1797
+ ) ;
1798
+ "alternatively, "
1799
+ } else {
1800
+ err. help ( "if there were a single returned type, you could use `impl Trait` instead" ) ;
1801
+ ""
1802
+ } ;
1791
1803
1792
1804
let mut sugg = vec ! [
1793
1805
( span. shrink_to_lo( ) , format!( "Box<{pre}" ) ) ,
@@ -1819,7 +1831,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
1819
1831
1820
1832
err. multipart_suggestion (
1821
1833
format ! (
1822
- "alternatively, box the return type, and wrap all of the returned values in \
1834
+ "{ alternatively} box the return type, and wrap all of the returned values in \
1823
1835
`Box::new`",
1824
1836
) ,
1825
1837
sugg,
@@ -1829,6 +1841,41 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
1829
1841
true
1830
1842
}
1831
1843
1844
+ pub ( super ) fn point_at_returns_when_relevant (
1845
+ & self ,
1846
+ err : & mut Diag < ' _ > ,
1847
+ obligation : & PredicateObligation < ' tcx > ,
1848
+ ) {
1849
+ match obligation. cause . code ( ) . peel_derives ( ) {
1850
+ ObligationCauseCode :: SizedReturnType => { }
1851
+ _ => return ,
1852
+ }
1853
+
1854
+ let hir = self . tcx . hir ( ) ;
1855
+ let node = self . tcx . hir_node_by_def_id ( obligation. cause . body_id ) ;
1856
+ if let hir:: Node :: Item ( hir:: Item {
1857
+ kind : hir:: ItemKind :: Fn { body : body_id, .. } , ..
1858
+ } ) = node
1859
+ {
1860
+ let body = hir. body ( * body_id) ;
1861
+ // Point at all the `return`s in the function as they have failed trait bounds.
1862
+ let mut visitor = ReturnsVisitor :: default ( ) ;
1863
+ visitor. visit_body ( body) ;
1864
+ let typeck_results = self . typeck_results . as_ref ( ) . unwrap ( ) ;
1865
+ for expr in & visitor. returns {
1866
+ if let Some ( returned_ty) = typeck_results. node_type_opt ( expr. hir_id ) {
1867
+ let ty = self . resolve_vars_if_possible ( returned_ty) ;
1868
+ if ty. references_error ( ) {
1869
+ // don't print out the [type error] here
1870
+ err. downgrade_to_delayed_bug ( ) ;
1871
+ } else {
1872
+ err. span_label ( expr. span , format ! ( "this returned value is of type `{ty}`" ) ) ;
1873
+ }
1874
+ }
1875
+ }
1876
+ }
1877
+ }
1878
+
1832
1879
pub ( super ) fn report_closure_arg_mismatch (
1833
1880
& self ,
1834
1881
span : Span ,
0 commit comments