3636//! ```
3737
3838use crate :: FnCtxt ;
39- use rustc_errors:: {
40- struct_span_err, Applicability , Diagnostic , DiagnosticBuilder , ErrorGuaranteed , MultiSpan ,
41- } ;
39+ use rustc_errors:: { struct_span_err, Diagnostic , DiagnosticBuilder , ErrorGuaranteed , MultiSpan } ;
4240use rustc_hir as hir;
4341use rustc_hir:: def_id:: DefId ;
4442use rustc_hir:: intravisit:: { self , Visitor } ;
@@ -58,7 +56,7 @@ use rustc_middle::ty::visit::TypeVisitableExt;
5856use rustc_middle:: ty:: { self , Ty , TypeAndMut } ;
5957use rustc_session:: parse:: feature_err;
6058use rustc_span:: symbol:: sym;
61- use rustc_span:: { self , BytePos , DesugaringKind , Span } ;
59+ use rustc_span:: { self , DesugaringKind } ;
6260use rustc_target:: spec:: abi:: Abi ;
6361use rustc_trait_selection:: infer:: InferCtxtExt as _;
6462use rustc_trait_selection:: traits:: error_reporting:: TypeErrCtxtExt as _;
@@ -1702,9 +1700,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
17021700 ) -> DiagnosticBuilder < ' a , ErrorGuaranteed > {
17031701 let mut err = fcx. err_ctxt ( ) . report_mismatched_types ( cause, expected, found, ty_err) ;
17041702
1705- let mut pointing_at_return_type = false ;
1706- let mut fn_output = None ;
1707-
17081703 let parent_id = fcx. tcx . hir ( ) . parent_id ( id) ;
17091704 let parent = fcx. tcx . hir ( ) . get ( parent_id) ;
17101705 if let Some ( expr) = expression
@@ -1717,7 +1712,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
17171712 // label pointing out the cause for the type coercion will be wrong
17181713 // as prior return coercions would not be relevant (#57664).
17191714 let fn_decl = if let ( Some ( expr) , Some ( blk_id) ) = ( expression, blk_id) {
1720- pointing_at_return_type =
1715+ let pointing_at_return_type =
17211716 fcx. suggest_mismatched_types_on_tail ( & mut err, expr, expected, found, blk_id) ;
17221717 if let ( Some ( cond_expr) , true , false ) = (
17231718 fcx. tcx . hir ( ) . get_if_cause ( expr. hir_id ) ,
@@ -1749,7 +1744,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
17491744
17501745 if let Some ( ( fn_id, fn_decl, can_suggest) ) = fn_decl {
17511746 if blk_id. is_none ( ) {
1752- pointing_at_return_type |= fcx. suggest_missing_return_type (
1747+ fcx. suggest_missing_return_type (
17531748 & mut err,
17541749 & fn_decl,
17551750 expected,
@@ -1758,9 +1753,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
17581753 fn_id,
17591754 ) ;
17601755 }
1761- if !pointing_at_return_type {
1762- fn_output = Some ( & fn_decl. output ) ; // `impl Trait` return type
1763- }
17641756 }
17651757
17661758 let parent_id = fcx. tcx . hir ( ) . get_parent_item ( id) ;
@@ -1795,106 +1787,9 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
17951787 ) ;
17961788 }
17971789
1798- if let ( Some ( sp) , Some ( fn_output) ) = ( ret_coercion_span, fn_output) {
1799- self . add_impl_trait_explanation ( & mut err, cause, fcx, expected, sp, fn_output) ;
1800- }
1801-
18021790 err
18031791 }
18041792
1805- fn add_impl_trait_explanation < ' a > (
1806- & self ,
1807- err : & mut Diagnostic ,
1808- cause : & ObligationCause < ' tcx > ,
1809- fcx : & FnCtxt < ' a , ' tcx > ,
1810- expected : Ty < ' tcx > ,
1811- sp : Span ,
1812- fn_output : & hir:: FnRetTy < ' _ > ,
1813- ) {
1814- let return_sp = fn_output. span ( ) ;
1815- err. span_label ( return_sp, "expected because this return type..." ) ;
1816- err. span_label (
1817- sp,
1818- format ! ( "...is found to be `{}` here" , fcx. resolve_vars_with_obligations( expected) ) ,
1819- ) ;
1820- let impl_trait_msg = "for information on `impl Trait`, see \
1821- <https://doc.rust-lang.org/book/ch10-02-traits.html\
1822- #returning-types-that-implement-traits>";
1823- let trait_obj_msg = "for information on trait objects, see \
1824- <https://doc.rust-lang.org/book/ch17-02-trait-objects.html\
1825- #using-trait-objects-that-allow-for-values-of-different-types>";
1826- err. note ( "to return `impl Trait`, all returned values must be of the same type" ) ;
1827- err. note ( impl_trait_msg) ;
1828- let snippet = fcx
1829- . tcx
1830- . sess
1831- . source_map ( )
1832- . span_to_snippet ( return_sp)
1833- . unwrap_or_else ( |_| "dyn Trait" . to_string ( ) ) ;
1834- let mut snippet_iter = snippet. split_whitespace ( ) ;
1835- let has_impl = snippet_iter. next ( ) . is_some_and ( |s| s == "impl" ) ;
1836- // Only suggest `Box<dyn Trait>` if `Trait` in `impl Trait` is object safe.
1837- let mut is_object_safe = false ;
1838- if let hir:: FnRetTy :: Return ( ty) = fn_output
1839- // Get the return type.
1840- && let hir:: TyKind :: OpaqueDef ( ..) = ty. kind
1841- {
1842- let ty = fcx. astconv ( ) . ast_ty_to_ty ( ty) ;
1843- // Get the `impl Trait`'s `DefId`.
1844- if let ty:: Alias ( ty:: Opaque , ty:: AliasTy { def_id, .. } ) = ty. kind ( )
1845- // Get the `impl Trait`'s `Item` so that we can get its trait bounds and
1846- // get the `Trait`'s `DefId`.
1847- && let hir:: ItemKind :: OpaqueTy ( hir:: OpaqueTy { bounds, .. } ) =
1848- fcx. tcx . hir ( ) . expect_item ( def_id. expect_local ( ) ) . kind
1849- {
1850- // Are of this `impl Trait`'s traits object safe?
1851- is_object_safe = bounds. iter ( ) . all ( |bound| {
1852- bound
1853- . trait_ref ( )
1854- . and_then ( |t| t. trait_def_id ( ) )
1855- . is_some_and ( |def_id| {
1856- fcx. tcx . check_is_object_safe ( def_id)
1857- } )
1858- } )
1859- }
1860- } ;
1861- if has_impl {
1862- if is_object_safe {
1863- err. multipart_suggestion (
1864- "you could change the return type to be a boxed trait object" ,
1865- vec ! [
1866- ( return_sp. with_hi( return_sp. lo( ) + BytePos ( 4 ) ) , "Box<dyn" . to_string( ) ) ,
1867- ( return_sp. shrink_to_hi( ) , ">" . to_string( ) ) ,
1868- ] ,
1869- Applicability :: MachineApplicable ,
1870- ) ;
1871- let sugg = [ sp, cause. span ]
1872- . into_iter ( )
1873- . flat_map ( |sp| {
1874- [
1875- ( sp. shrink_to_lo ( ) , "Box::new(" . to_string ( ) ) ,
1876- ( sp. shrink_to_hi ( ) , ")" . to_string ( ) ) ,
1877- ]
1878- . into_iter ( )
1879- } )
1880- . collect :: < Vec < _ > > ( ) ;
1881- err. multipart_suggestion (
1882- "if you change the return type to expect trait objects, box the returned \
1883- expressions",
1884- sugg,
1885- Applicability :: MaybeIncorrect ,
1886- ) ;
1887- } else {
1888- err. help ( format ! (
1889- "if the trait `{}` were object safe, you could return a boxed trait object" ,
1890- & snippet[ 5 ..]
1891- ) ) ;
1892- }
1893- err. note ( trait_obj_msg) ;
1894- }
1895- err. help ( "you could instead create a new `enum` with a variant for each returned type" ) ;
1896- }
1897-
18981793 /// Checks whether the return type is unsized via an obligation, which makes
18991794 /// sure we consider `dyn Trait: Sized` where clauses, which are trivially
19001795 /// false but technically valid for typeck.
0 commit comments