@@ -1130,6 +1130,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
1130
1130
} ;
1131
1131
1132
1132
self . note_obligation_cause ( & mut err, obligation) ;
1133
+ self . point_at_returns_when_relevant ( & mut err, & obligation) ;
1133
1134
1134
1135
err. emit ( ) ;
1135
1136
}
@@ -1737,35 +1738,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
1737
1738
// Recursively look for `TraitObject` types and if there's only one, use that span to
1738
1739
// suggest `impl Trait`.
1739
1740
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
-
1769
1741
// Visit to make sure there's a single `return` type to suggest `impl Trait`,
1770
1742
// otherwise suggest using `Box<dyn Trait>` or an enum.
1771
1743
let mut visitor = ReturnsVisitor ( vec ! [ ] ) ;
@@ -1893,6 +1865,38 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
1893
1865
false
1894
1866
}
1895
1867
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
+
1896
1900
/// Given some node representing a fn-like thing in the HIR map,
1897
1901
/// returns a span and `ArgKind` information that describes the
1898
1902
/// arguments it expects. This can be supplied to
@@ -2911,19 +2915,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
2911
2915
}
2912
2916
ObligationCauseCode :: RepeatVec ( suggest_const_in_array_repeat_expressions) => {
2913
2917
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" ,
2916
2919
) ;
2917
2920
if suggest_const_in_array_repeat_expressions {
2918
2921
err. note (
2919
2922
"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",
2922
2925
) ;
2923
2926
if tcx. sess . opts . unstable_features . is_nightly_build ( ) {
2924
2927
err. help (
2925
2928
"add `#![feature(const_in_array_repeat_expressions)]` to the \
2926
- crate attributes to enable",
2929
+ crate attributes to enable",
2927
2930
) ;
2928
2931
}
2929
2932
}
@@ -2941,16 +2944,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
2941
2944
}
2942
2945
}
2943
2946
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" ) ;
2948
2948
}
2949
2949
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" ) ;
2954
2951
}
2955
2952
ObligationCauseCode :: AssignmentLhsSized => {
2956
2953
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> {
2966
2963
if last {
2967
2964
err. note (
2968
2965
"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",
2970
2967
) ;
2971
2968
} else {
2972
2969
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" ,
2975
2971
) ;
2976
2972
}
2977
2973
}
@@ -3025,13 +3021,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
3025
3021
ObligationCauseCode :: CompareImplMethodObligation { .. } => {
3026
3022
err. note ( & format ! (
3027
3023
"the requirement `{}` appears on the impl method \
3028
- but not on the corresponding trait method",
3024
+ but not on the corresponding trait method",
3029
3025
predicate
3030
3026
) ) ;
3031
3027
}
3032
3028
ObligationCauseCode :: CompareImplTypeObligation { .. } => {
3033
3029
err. note ( & format ! (
3034
- "the requirement `{}` appears on the associated impl type\
3030
+ "the requirement `{}` appears on the associated impl type \
3035
3031
but not on the corresponding associated trait type",
3036
3032
predicate
3037
3033
) ) ;
@@ -3043,8 +3039,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
3043
3039
err. help ( "see issue #48214" ) ;
3044
3040
if tcx. sess . opts . unstable_features . is_nightly_build ( ) {
3045
3041
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" ,
3048
3043
) ;
3049
3044
}
3050
3045
}
@@ -3186,3 +3181,32 @@ pub fn suggest_constraining_type_param(
3186
3181
}
3187
3182
false
3188
3183
}
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