@@ -1765,7 +1765,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
17651765 } ;
17661766
17671767 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" ) ;
17691769 err. children . clear ( ) ;
17701770
17711771 let span = obligation. cause . span ;
@@ -1781,13 +1781,25 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
17811781 } else {
17821782 ( "dyn " , span. shrink_to_lo ( ) )
17831783 } ;
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+ } ;
17911803
17921804 let mut sugg = vec ! [
17931805 ( span. shrink_to_lo( ) , format!( "Box<{pre}" ) ) ,
@@ -1819,7 +1831,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
18191831
18201832 err. multipart_suggestion (
18211833 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 \
18231835 `Box::new`",
18241836 ) ,
18251837 sugg,
@@ -1829,6 +1841,41 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
18291841 true
18301842 }
18311843
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+
18321879 pub ( super ) fn report_closure_arg_mismatch (
18331880 & self ,
18341881 span : Span ,
0 commit comments