@@ -31,6 +31,7 @@ use rustc_span::symbol::{Ident, kw, sym};
31
31
use rustc_span:: {
32
32
DUMMY_SP , ErrorGuaranteed , ExpnKind , FileName , MacroKind , Span , Symbol , edit_distance,
33
33
} ;
34
+ use rustc_trait_selection:: error_reporting:: traits:: DefIdOrName ;
34
35
use rustc_trait_selection:: error_reporting:: traits:: on_unimplemented:: OnUnimplementedNote ;
35
36
use rustc_trait_selection:: infer:: InferCtxtExt ;
36
37
use rustc_trait_selection:: traits:: query:: evaluate_obligation:: InferCtxtExt as _;
@@ -45,50 +46,6 @@ use crate::errors::{self, CandidateTraitNote, NoAssociatedItem};
45
46
use crate :: { Expectation , FnCtxt } ;
46
47
47
48
impl < ' a , ' tcx > FnCtxt < ' a , ' tcx > {
48
- fn is_fn_ty ( & self , ty : Ty < ' tcx > , span : Span ) -> bool {
49
- let tcx = self . tcx ;
50
- match ty. kind ( ) {
51
- // Not all of these (e.g., unsafe fns) implement `FnOnce`,
52
- // so we look for these beforehand.
53
- // FIXME(async_closures): These don't impl `FnOnce` by default.
54
- ty:: Closure ( ..) | ty:: FnDef ( ..) | ty:: FnPtr ( ..) => true ,
55
- // If it's not a simple function, look for things which implement `FnOnce`.
56
- _ => {
57
- let Some ( fn_once) = tcx. lang_items ( ) . fn_once_trait ( ) else {
58
- return false ;
59
- } ;
60
-
61
- // This conditional prevents us from asking to call errors and unresolved types.
62
- // It might seem that we can use `predicate_must_hold_modulo_regions`,
63
- // but since a Dummy binder is used to fill in the FnOnce trait's arguments,
64
- // type resolution always gives a "maybe" here.
65
- if self . autoderef ( span, ty) . silence_errors ( ) . any ( |( ty, _) | {
66
- info ! ( "check deref {:?} error" , ty) ;
67
- matches ! ( ty. kind( ) , ty:: Error ( _) | ty:: Infer ( _) )
68
- } ) {
69
- return false ;
70
- }
71
-
72
- self . autoderef ( span, ty) . silence_errors ( ) . any ( |( ty, _) | {
73
- info ! ( "check deref {:?} impl FnOnce" , ty) ;
74
- self . probe ( |_| {
75
- let trait_ref =
76
- ty:: TraitRef :: new ( tcx, fn_once, [ ty, self . next_ty_var ( span) ] ) ;
77
- let poly_trait_ref = ty:: Binder :: dummy ( trait_ref) ;
78
- let obligation = Obligation :: misc (
79
- tcx,
80
- span,
81
- self . body_id ,
82
- self . param_env ,
83
- poly_trait_ref,
84
- ) ;
85
- self . predicate_may_hold ( & obligation)
86
- } )
87
- } )
88
- }
89
- }
90
- }
91
-
92
49
fn is_slice_ty ( & self , ty : Ty < ' tcx > , span : Span ) -> bool {
93
50
self . autoderef ( span, ty)
94
51
. silence_errors ( )
@@ -2367,12 +2324,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2367
2324
let is_accessible = field. vis . is_accessible_from ( scope, tcx) ;
2368
2325
2369
2326
if is_accessible {
2370
- if self . is_fn_ty ( field_ty, span) {
2327
+ if let Some ( ( what, _, _) ) = self . extract_callable_info ( field_ty) {
2328
+ let what = match what {
2329
+ DefIdOrName :: DefId ( def_id) => self . tcx . def_descr ( def_id) ,
2330
+ DefIdOrName :: Name ( what) => what,
2331
+ } ;
2371
2332
let expr_span = expr. span . to ( item_name. span ) ;
2372
2333
err. multipart_suggestion (
2373
2334
format ! (
2374
- "to call the function stored in `{item_name}`, \
2375
- surround the field access with parentheses",
2335
+ "to call the {what} stored in `{item_name}`, \
2336
+ surround the field access with parentheses",
2376
2337
) ,
2377
2338
vec ! [
2378
2339
( expr_span. shrink_to_lo( ) , '(' . to_string( ) ) ,
0 commit comments