@@ -1130,6 +1130,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
11301130 } ;
11311131
11321132 self . note_obligation_cause ( & mut err, obligation) ;
1133+ self . point_at_returns_when_relevant ( & mut err, & obligation) ;
11331134
11341135 err. emit ( ) ;
11351136 }
@@ -1737,35 +1738,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
17371738 // Recursively look for `TraitObject` types and if there's only one, use that span to
17381739 // suggest `impl Trait`.
17391740
1740- struct ReturnsVisitor < ' v > ( Vec < & ' v hir:: Expr < ' v > > ) ;
1741-
1742- impl < ' v > Visitor < ' v > for ReturnsVisitor < ' v > {
1743- type Map = rustc:: hir:: map:: Map < ' v > ;
1744-
1745- fn nested_visit_map ( & mut self ) -> hir:: intravisit:: NestedVisitorMap < ' _ , Self :: Map > {
1746- hir:: intravisit:: NestedVisitorMap :: None
1747- }
1748-
1749- fn visit_expr ( & mut self , ex : & ' v hir:: Expr < ' v > ) {
1750- match ex. kind {
1751- hir:: ExprKind :: Ret ( Some ( ex) ) => self . 0 . push ( ex) ,
1752- _ => { }
1753- }
1754- hir:: intravisit:: walk_expr ( self , ex) ;
1755- }
1756-
1757- fn visit_body ( & mut self , body : & ' v hir:: Body < ' v > ) {
1758- if body. generator_kind ( ) . is_none ( ) {
1759- if let hir:: ExprKind :: Block ( block, None ) = body. value . kind {
1760- if let Some ( expr) = block. expr {
1761- self . 0 . push ( expr) ;
1762- }
1763- }
1764- }
1765- hir:: intravisit:: walk_body ( self , body) ;
1766- }
1767- }
1768-
17691741 // Visit to make sure there's a single `return` type to suggest `impl Trait`,
17701742 // otherwise suggest using `Box<dyn Trait>` or an enum.
17711743 let mut visitor = ReturnsVisitor ( vec ! [ ] ) ;
@@ -1893,6 +1865,38 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
18931865 false
18941866 }
18951867
1868+ fn point_at_returns_when_relevant (
1869+ & self ,
1870+ err : & mut DiagnosticBuilder < ' tcx > ,
1871+ obligation : & PredicateObligation < ' tcx > ,
1872+ ) {
1873+ if let ObligationCauseCode :: SizedReturnType = obligation. cause . code . peel_derives ( ) {
1874+ } else {
1875+ return ;
1876+ }
1877+
1878+ let hir = self . tcx . hir ( ) ;
1879+ let parent_node = hir. get_parent_node ( obligation. cause . body_id ) ;
1880+ let node = hir. find ( parent_node) ;
1881+ if let Some ( hir:: Node :: Item ( hir:: Item { kind : hir:: ItemKind :: Fn ( _, _, body_id) , .. } ) ) =
1882+ node
1883+ {
1884+ let body = hir. body ( * body_id) ;
1885+ // Point at all the `return`s in the function as they have failed trait bounds.
1886+ let mut visitor = ReturnsVisitor ( vec ! [ ] ) ;
1887+ visitor. visit_body ( & body) ;
1888+ let tables = self . in_progress_tables . map ( |t| t. borrow ( ) ) . unwrap ( ) ;
1889+ for expr in & visitor. 0 {
1890+ if let Some ( returned_ty) = tables. node_type_opt ( expr. hir_id ) {
1891+ err. span_label (
1892+ expr. span ,
1893+ & format ! ( "this returned value is of type `{}`" , returned_ty) ,
1894+ ) ;
1895+ }
1896+ }
1897+ }
1898+ }
1899+
18961900 /// Given some node representing a fn-like thing in the HIR map,
18971901 /// returns a span and `ArgKind` information that describes the
18981902 /// arguments it expects. This can be supplied to
@@ -2911,19 +2915,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
29112915 }
29122916 ObligationCauseCode :: RepeatVec ( suggest_const_in_array_repeat_expressions) => {
29132917 err. note (
2914- "the `Copy` trait is required because the \
2915- repeated element will be copied",
2918+ "the `Copy` trait is required because the repeated element will be copied" ,
29162919 ) ;
29172920 if suggest_const_in_array_repeat_expressions {
29182921 err. note (
29192922 "this array initializer can be evaluated at compile-time, for more \
2920- information, see issue \
2921- https://github.com/rust-lang/rust/issues/49147",
2923+ information, see issue \
2924+ https://github.com/rust-lang/rust/issues/49147",
29222925 ) ;
29232926 if tcx. sess . opts . unstable_features . is_nightly_build ( ) {
29242927 err. help (
29252928 "add `#![feature(const_in_array_repeat_expressions)]` to the \
2926- crate attributes to enable",
2929+ crate attributes to enable",
29272930 ) ;
29282931 }
29292932 }
@@ -2941,16 +2944,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
29412944 }
29422945 }
29432946 ObligationCauseCode :: SizedReturnType => {
2944- err. note (
2945- "the return type of a function must have a \
2946- statically known size",
2947- ) ;
2947+ err. note ( "the return type of a function must have a statically known size" ) ;
29482948 }
29492949 ObligationCauseCode :: SizedYieldType => {
2950- err. note (
2951- "the yield type of a generator must have a \
2952- statically known size",
2953- ) ;
2950+ err. note ( "the yield type of a generator must have a statically known size" ) ;
29542951 }
29552952 ObligationCauseCode :: AssignmentLhsSized => {
29562953 err. note ( "the left-hand-side of an assignment must have a statically known size" ) ;
@@ -2966,12 +2963,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
29662963 if last {
29672964 err. note (
29682965 "the last field of a packed struct may only have a \
2969- dynamically sized type if it does not need drop to be run",
2966+ dynamically sized type if it does not need drop to be run",
29702967 ) ;
29712968 } else {
29722969 err. note (
2973- "only the last field of a struct may have a dynamically \
2974- sized type",
2970+ "only the last field of a struct may have a dynamically sized type" ,
29752971 ) ;
29762972 }
29772973 }
@@ -3025,13 +3021,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
30253021 ObligationCauseCode :: CompareImplMethodObligation { .. } => {
30263022 err. note ( & format ! (
30273023 "the requirement `{}` appears on the impl method \
3028- but not on the corresponding trait method",
3024+ but not on the corresponding trait method",
30293025 predicate
30303026 ) ) ;
30313027 }
30323028 ObligationCauseCode :: CompareImplTypeObligation { .. } => {
30333029 err. note ( & format ! (
3034- "the requirement `{}` appears on the associated impl type\
3030+ "the requirement `{}` appears on the associated impl type \
30353031 but not on the corresponding associated trait type",
30363032 predicate
30373033 ) ) ;
@@ -3043,8 +3039,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
30433039 err. help ( "see issue #48214" ) ;
30443040 if tcx. sess . opts . unstable_features . is_nightly_build ( ) {
30453041 err. help (
3046- "add `#![feature(trivial_bounds)]` to the \
3047- crate attributes to enable",
3042+ "add `#![feature(trivial_bounds)]` to the crate attributes to enable" ,
30483043 ) ;
30493044 }
30503045 }
@@ -3186,3 +3181,32 @@ pub fn suggest_constraining_type_param(
31863181 }
31873182 false
31883183}
3184+
3185+ struct ReturnsVisitor < ' v > ( Vec < & ' v hir:: Expr < ' v > > ) ;
3186+
3187+ impl < ' v > Visitor < ' v > for ReturnsVisitor < ' v > {
3188+ type Map = rustc:: hir:: map:: Map < ' v > ;
3189+
3190+ fn nested_visit_map ( & mut self ) -> hir:: intravisit:: NestedVisitorMap < ' _ , Self :: Map > {
3191+ hir:: intravisit:: NestedVisitorMap :: None
3192+ }
3193+
3194+ fn visit_expr ( & mut self , ex : & ' v hir:: Expr < ' v > ) {
3195+ match ex. kind {
3196+ hir:: ExprKind :: Ret ( Some ( ex) ) => self . 0 . push ( ex) ,
3197+ _ => { }
3198+ }
3199+ hir:: intravisit:: walk_expr ( self , ex) ;
3200+ }
3201+
3202+ fn visit_body ( & mut self , body : & ' v hir:: Body < ' v > ) {
3203+ if body. generator_kind ( ) . is_none ( ) {
3204+ if let hir:: ExprKind :: Block ( block, None ) = body. value . kind {
3205+ if let Some ( expr) = block. expr {
3206+ self . 0 . push ( expr) ;
3207+ }
3208+ }
3209+ }
3210+ hir:: intravisit:: walk_body ( self , body) ;
3211+ }
3212+ }
0 commit comments