@@ -160,6 +160,33 @@ crate fn placeholder_type_error<'tcx>(
160
160
return ;
161
161
}
162
162
163
+ placeholder_type_error_diag (
164
+ tcx,
165
+ span,
166
+ generics,
167
+ placeholder_types,
168
+ vec ! [ ] ,
169
+ suggest,
170
+ hir_ty,
171
+ kind,
172
+ )
173
+ . emit ( ) ;
174
+ }
175
+
176
+ crate fn placeholder_type_error_diag < ' tcx > (
177
+ tcx : TyCtxt < ' tcx > ,
178
+ span : Option < Span > ,
179
+ generics : & [ hir:: GenericParam < ' _ > ] ,
180
+ placeholder_types : Vec < Span > ,
181
+ additional_spans : Vec < Span > ,
182
+ suggest : bool ,
183
+ hir_ty : Option < & hir:: Ty < ' _ > > ,
184
+ kind : & ' static str ,
185
+ ) -> DiagnosticBuilder < ' tcx , ErrorGuaranteed > {
186
+ if placeholder_types. is_empty ( ) {
187
+ return bad_placeholder ( tcx, additional_spans, kind) ;
188
+ }
189
+
163
190
let type_name = generics. next_type_param_name ( None ) ;
164
191
let mut sugg: Vec < _ > =
165
192
placeholder_types. iter ( ) . map ( |sp| ( * sp, ( * type_name) . to_string ( ) ) ) . collect ( ) ;
@@ -182,7 +209,8 @@ crate fn placeholder_type_error<'tcx>(
182
209
sugg. push ( ( span, format ! ( ", {}" , type_name) ) ) ;
183
210
}
184
211
185
- let mut err = bad_placeholder ( tcx, placeholder_types, kind) ;
212
+ let mut err =
213
+ bad_placeholder ( tcx, placeholder_types. into_iter ( ) . chain ( additional_spans) . collect ( ) , kind) ;
186
214
187
215
// Suggest, but only if it is not a function in const or static
188
216
if suggest {
@@ -218,7 +246,8 @@ crate fn placeholder_type_error<'tcx>(
218
246
) ;
219
247
}
220
248
}
221
- err. emit ( ) ;
249
+
250
+ err
222
251
}
223
252
224
253
fn reject_placeholder_type_signatures_in_item < ' tcx > (
@@ -1868,50 +1897,17 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
1868
1897
generics,
1869
1898
..
1870
1899
} )
1871
- | ImplItem ( hir:: ImplItem { kind : ImplItemKind :: Fn ( sig, _) , ident, generics, .. } )
1872
1900
| Item ( hir:: Item { kind : ItemKind :: Fn ( sig, generics, _) , ident, .. } ) => {
1873
- match get_infer_ret_ty ( & sig. decl . output ) {
1874
- Some ( ty) => {
1875
- let fn_sig = tcx. typeck ( def_id) . liberated_fn_sigs ( ) [ hir_id] ;
1876
- // Typeck doesn't expect erased regions to be returned from `type_of`.
1877
- let fn_sig = tcx. fold_regions ( fn_sig, & mut false , |r, _| match * r {
1878
- ty:: ReErased => tcx. lifetimes . re_static ,
1879
- _ => r,
1880
- } ) ;
1881
- let fn_sig = ty:: Binder :: dummy ( fn_sig) ;
1882
-
1883
- let mut visitor = HirPlaceholderCollector :: default ( ) ;
1884
- visitor. visit_ty ( ty) ;
1885
- let mut diag = bad_placeholder ( tcx, visitor. 0 , "return type" ) ;
1886
- let ret_ty = fn_sig. skip_binder ( ) . output ( ) ;
1887
- if !ret_ty. references_error ( ) {
1888
- if !ret_ty. is_closure ( ) {
1889
- let ret_ty_str = match ret_ty. kind ( ) {
1890
- // Suggest a function pointer return type instead of a unique function definition
1891
- // (e.g. `fn() -> i32` instead of `fn() -> i32 { f }`, the latter of which is invalid
1892
- // syntax)
1893
- ty:: FnDef ( ..) => ret_ty. fn_sig ( tcx) . to_string ( ) ,
1894
- _ => ret_ty. to_string ( ) ,
1895
- } ;
1896
- diag. span_suggestion (
1897
- ty. span ,
1898
- "replace with the correct return type" ,
1899
- ret_ty_str,
1900
- Applicability :: MaybeIncorrect ,
1901
- ) ;
1902
- } else {
1903
- // We're dealing with a closure, so we should suggest using `impl Fn` or trait bounds
1904
- // to prevent the user from getting a papercut while trying to use the unique closure
1905
- // syntax (e.g. `[closure@src/lib.rs:2:5: 2:9]`).
1906
- diag. help ( "consider using an `Fn`, `FnMut`, or `FnOnce` trait bound" ) ;
1907
- diag. note ( "for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html" ) ;
1908
- }
1909
- }
1910
- diag. emit ( ) ;
1901
+ infer_return_ty_for_fn_sig ( tcx, sig, * ident, generics, def_id, & icx)
1902
+ }
1911
1903
1912
- fn_sig
1913
- }
1914
- None => <dyn AstConv < ' _ > >:: ty_of_fn (
1904
+ ImplItem ( hir:: ImplItem { kind : ImplItemKind :: Fn ( sig, _) , ident, generics, .. } ) => {
1905
+ // Do not try to inference the return type for a impl method coming from a trait
1906
+ if let Item ( hir:: Item { kind : ItemKind :: Impl ( i) , .. } ) =
1907
+ tcx. hir ( ) . get ( tcx. hir ( ) . get_parent_node ( hir_id) )
1908
+ && i. of_trait . is_some ( )
1909
+ {
1910
+ <dyn AstConv < ' _ > >:: ty_of_fn (
1915
1911
& icx,
1916
1912
hir_id,
1917
1913
sig. header . unsafety ,
@@ -1920,7 +1916,9 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
1920
1916
generics,
1921
1917
Some ( ident. span ) ,
1922
1918
None ,
1923
- ) ,
1919
+ )
1920
+ } else {
1921
+ infer_return_ty_for_fn_sig ( tcx, sig, * ident, generics, def_id, & icx)
1924
1922
}
1925
1923
}
1926
1924
@@ -1982,6 +1980,70 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
1982
1980
}
1983
1981
}
1984
1982
1983
+ fn infer_return_ty_for_fn_sig < ' tcx > (
1984
+ tcx : TyCtxt < ' tcx > ,
1985
+ sig : & hir:: FnSig < ' _ > ,
1986
+ ident : Ident ,
1987
+ generics : & hir:: Generics < ' _ > ,
1988
+ def_id : LocalDefId ,
1989
+ icx : & ItemCtxt < ' tcx > ,
1990
+ ) -> ty:: PolyFnSig < ' tcx > {
1991
+ let hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def_id) ;
1992
+
1993
+ match get_infer_ret_ty ( & sig. decl . output ) {
1994
+ Some ( ty) => {
1995
+ let fn_sig = tcx. typeck ( def_id) . liberated_fn_sigs ( ) [ hir_id] ;
1996
+ // Typeck doesn't expect erased regions to be returned from `type_of`.
1997
+ let fn_sig = tcx. fold_regions ( fn_sig, & mut false , |r, _| match * r {
1998
+ ty:: ReErased => tcx. lifetimes . re_static ,
1999
+ _ => r,
2000
+ } ) ;
2001
+ let fn_sig = ty:: Binder :: dummy ( fn_sig) ;
2002
+
2003
+ let mut visitor = HirPlaceholderCollector :: default ( ) ;
2004
+ visitor. visit_ty ( ty) ;
2005
+ let mut diag = bad_placeholder ( tcx, visitor. 0 , "return type" ) ;
2006
+ let ret_ty = fn_sig. skip_binder ( ) . output ( ) ;
2007
+ if !ret_ty. references_error ( ) {
2008
+ if !ret_ty. is_closure ( ) {
2009
+ let ret_ty_str = match ret_ty. kind ( ) {
2010
+ // Suggest a function pointer return type instead of a unique function definition
2011
+ // (e.g. `fn() -> i32` instead of `fn() -> i32 { f }`, the latter of which is invalid
2012
+ // syntax)
2013
+ ty:: FnDef ( ..) => ret_ty. fn_sig ( tcx) . to_string ( ) ,
2014
+ _ => ret_ty. to_string ( ) ,
2015
+ } ;
2016
+ diag. span_suggestion (
2017
+ ty. span ,
2018
+ "replace with the correct return type" ,
2019
+ ret_ty_str,
2020
+ Applicability :: MaybeIncorrect ,
2021
+ ) ;
2022
+ } else {
2023
+ // We're dealing with a closure, so we should suggest using `impl Fn` or trait bounds
2024
+ // to prevent the user from getting a papercut while trying to use the unique closure
2025
+ // syntax (e.g. `[closure@src/lib.rs:2:5: 2:9]`).
2026
+ diag. help ( "consider using an `Fn`, `FnMut`, or `FnOnce` trait bound" ) ;
2027
+ diag. note ( "for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html" ) ;
2028
+ }
2029
+ }
2030
+ diag. emit ( ) ;
2031
+
2032
+ fn_sig
2033
+ }
2034
+ None => <dyn AstConv < ' _ > >:: ty_of_fn (
2035
+ icx,
2036
+ hir_id,
2037
+ sig. header . unsafety ,
2038
+ sig. header . abi ,
2039
+ sig. decl ,
2040
+ generics,
2041
+ Some ( ident. span ) ,
2042
+ None ,
2043
+ ) ,
2044
+ }
2045
+ }
2046
+
1985
2047
fn impl_trait_ref ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> Option < ty:: TraitRef < ' _ > > {
1986
2048
let icx = ItemCtxt :: new ( tcx, def_id) ;
1987
2049
match tcx. hir ( ) . expect_item ( def_id. expect_local ( ) ) . kind {
0 commit comments