]>
Commit | Line | Data |
---|---|---|
7cac9316 | 1 | use super::method::MethodCallee; |
f035d41b | 2 | use super::{Expectation, FnCtxt, TupleArgumentsFlag}; |
dfeec247 | 3 | use crate::type_error_struct; |
1a4d82fc | 4 | |
5e7ed085 | 5 | use rustc_errors::{struct_span_err, Applicability, Diagnostic}; |
dfeec247 | 6 | use rustc_hir as hir; |
6a06907d | 7 | use rustc_hir::def::{Namespace, Res}; |
dfeec247 | 8 | use rustc_hir::def_id::{DefId, LOCAL_CRATE}; |
17df50a5 XL |
9 | use rustc_infer::{ |
10 | infer, | |
11 | traits::{self, Obligation}, | |
12 | }; | |
13 | use rustc_infer::{ | |
14 | infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}, | |
15 | traits::ObligationCause, | |
16 | }; | |
ba9703b0 XL |
17 | use rustc_middle::ty::adjustment::{ |
18 | Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, | |
19 | }; | |
c295e0f8 | 20 | use rustc_middle::ty::subst::{Subst, SubstsRef}; |
ba9703b0 | 21 | use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; |
3dfed10e | 22 | use rustc_span::symbol::{sym, Ident}; |
dfeec247 | 23 | use rustc_span::Span; |
83c7162d | 24 | use rustc_target::spec::abi; |
f035d41b | 25 | use rustc_trait_selection::autoderef::Autoderef; |
17df50a5 | 26 | use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; |
cdc7bbd5 | 27 | use std::iter; |
60c5eb7d | 28 | |
9fa01778 | 29 | /// Checks that it is legal to call methods of the trait corresponding |
1a4d82fc | 30 | /// to `trait_id` (this only cares about the trait, not the specific |
9fa01778 | 31 | /// method that is called). |
f9f354fc XL |
32 | pub fn check_legal_trait_for_method_call( |
33 | tcx: TyCtxt<'_>, | |
34 | span: Span, | |
35 | receiver: Option<Span>, | |
5869c6ff | 36 | expr_span: Span, |
f9f354fc XL |
37 | trait_id: DefId, |
38 | ) { | |
ea8adc8c | 39 | if tcx.lang_items().drop_trait() == Some(trait_id) { |
f9f354fc XL |
40 | let mut err = struct_span_err!(tcx.sess, span, E0040, "explicit use of destructor method"); |
41 | err.span_label(span, "explicit destructor calls not allowed"); | |
42 | ||
5869c6ff | 43 | let (sp, suggestion) = receiver |
f9f354fc | 44 | .and_then(|s| tcx.sess.source_map().span_to_snippet(s).ok()) |
5869c6ff | 45 | .filter(|snippet| !snippet.is_empty()) |
04454e1e | 46 | .map(|snippet| (expr_span, format!("drop({snippet})"))) |
5869c6ff | 47 | .unwrap_or_else(|| (span, "drop".to_string())); |
f9f354fc XL |
48 | |
49 | err.span_suggestion( | |
5869c6ff XL |
50 | sp, |
51 | "consider using `drop` function", | |
52 | suggestion, | |
53 | Applicability::MaybeIncorrect, | |
f9f354fc XL |
54 | ); |
55 | ||
56 | err.emit(); | |
1a4d82fc JJ |
57 | } |
58 | } | |
59 | ||
1a4d82fc | 60 | enum CallStep<'tcx> { |
7cac9316 | 61 | Builtin(Ty<'tcx>), |
04454e1e | 62 | DeferredClosure(DefId, ty::FnSig<'tcx>), |
9fa01778 | 63 | /// E.g., enum variant constructors. |
7cac9316 | 64 | Overloaded(MethodCallee<'tcx>), |
1a4d82fc JJ |
65 | } |
66 | ||
dc9dc135 | 67 | impl<'a, 'tcx> FnCtxt<'a, 'tcx> { |
0731742a XL |
68 | pub fn check_call( |
69 | &self, | |
dfeec247 XL |
70 | call_expr: &'tcx hir::Expr<'tcx>, |
71 | callee_expr: &'tcx hir::Expr<'tcx>, | |
72 | arg_exprs: &'tcx [hir::Expr<'tcx>], | |
0731742a XL |
73 | expected: Expectation<'tcx>, |
74 | ) -> Ty<'tcx> { | |
c295e0f8 XL |
75 | let original_callee_ty = match &callee_expr.kind { |
76 | hir::ExprKind::Path(hir::QPath::Resolved(..) | hir::QPath::TypeRelative(..)) => self | |
77 | .check_expr_with_expectation_and_args( | |
78 | callee_expr, | |
79 | Expectation::NoExpectation, | |
80 | arg_exprs, | |
81 | ), | |
82 | _ => self.check_expr(callee_expr), | |
83 | }; | |
84 | ||
c30ab7b3 SL |
85 | let expr_ty = self.structurally_resolved_type(call_expr.span, original_callee_ty); |
86 | ||
87 | let mut autoderef = self.autoderef(callee_expr.span, expr_ty); | |
7cac9316 XL |
88 | let mut result = None; |
89 | while result.is_none() && autoderef.next().is_some() { | |
0731742a | 90 | result = self.try_overloaded_call_step(call_expr, callee_expr, arg_exprs, &autoderef); |
7cac9316 | 91 | } |
f035d41b | 92 | self.register_predicates(autoderef.into_obligations()); |
a7813a04 | 93 | |
9e0c209e | 94 | let output = match result { |
a7813a04 XL |
95 | None => { |
96 | // this will report an error since original_callee_ty is not a fn | |
6a06907d XL |
97 | self.confirm_builtin_call( |
98 | call_expr, | |
99 | callee_expr, | |
100 | original_callee_ty, | |
101 | arg_exprs, | |
102 | expected, | |
103 | ) | |
a7813a04 | 104 | } |
1a4d82fc | 105 | |
7cac9316 | 106 | Some(CallStep::Builtin(callee_ty)) => { |
6a06907d | 107 | self.confirm_builtin_call(call_expr, callee_expr, callee_ty, arg_exprs, expected) |
85aaf69f | 108 | } |
85aaf69f | 109 | |
04454e1e FG |
110 | Some(CallStep::DeferredClosure(def_id, fn_sig)) => { |
111 | self.confirm_deferred_closure_call(call_expr, arg_exprs, expected, def_id, fn_sig) | |
a7813a04 | 112 | } |
c34b1796 | 113 | |
a7813a04 | 114 | Some(CallStep::Overloaded(method_callee)) => { |
7cac9316 | 115 | self.confirm_overloaded_call(call_expr, arg_exprs, expected, method_callee) |
a7813a04 | 116 | } |
9e0c209e SL |
117 | }; |
118 | ||
119 | // we must check that return type of called functions is WF: | |
f035d41b | 120 | self.register_wf_obligation(output.into(), call_expr.span, traits::MiscObligation); |
9e0c209e SL |
121 | |
122 | output | |
1a4d82fc JJ |
123 | } |
124 | ||
0731742a XL |
125 | fn try_overloaded_call_step( |
126 | &self, | |
dfeec247 XL |
127 | call_expr: &'tcx hir::Expr<'tcx>, |
128 | callee_expr: &'tcx hir::Expr<'tcx>, | |
129 | arg_exprs: &'tcx [hir::Expr<'tcx>], | |
dc9dc135 | 130 | autoderef: &Autoderef<'a, 'tcx>, |
0731742a | 131 | ) -> Option<CallStep<'tcx>> { |
f035d41b XL |
132 | let adjusted_ty = |
133 | self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false)); | |
0731742a XL |
134 | debug!( |
135 | "try_overloaded_call_step(call_expr={:?}, adjusted_ty={:?})", | |
136 | call_expr, adjusted_ty | |
137 | ); | |
a7813a04 XL |
138 | |
139 | // If the callee is a bare function or a closure, then we're all set. | |
1b1a35ee | 140 | match *adjusted_ty.kind() { |
b7449926 | 141 | ty::FnDef(..) | ty::FnPtr(_) => { |
f035d41b | 142 | let adjustments = self.adjust_steps(autoderef); |
7cac9316 XL |
143 | self.apply_adjustments(callee_expr, adjustments); |
144 | return Some(CallStep::Builtin(adjusted_ty)); | |
a7813a04 | 145 | } |
85aaf69f | 146 | |
b7449926 | 147 | ty::Closure(def_id, substs) => { |
a7813a04 XL |
148 | assert_eq!(def_id.krate, LOCAL_CRATE); |
149 | ||
150 | // Check whether this is a call to a closure where we | |
151 | // haven't yet decided on whether the closure is fn vs | |
152 | // fnmut vs fnonce. If so, we have to defer further processing. | |
ba9703b0 XL |
153 | if self.closure_kind(substs).is_none() { |
154 | let closure_sig = substs.as_closure().sig(); | |
155 | let closure_sig = self | |
0731742a XL |
156 | .replace_bound_vars_with_fresh_vars( |
157 | call_expr.span, | |
158 | infer::FnCall, | |
fc512014 | 159 | closure_sig, |
0731742a XL |
160 | ) |
161 | .0; | |
f035d41b | 162 | let adjustments = self.adjust_steps(autoderef); |
0731742a XL |
163 | self.record_deferred_call_resolution( |
164 | def_id, | |
165 | DeferredCallResolution { | |
166 | call_expr, | |
167 | callee_expr, | |
168 | adjusted_ty, | |
169 | adjustments, | |
ba9703b0 | 170 | fn_sig: closure_sig, |
0731742a XL |
171 | closure_substs: substs, |
172 | }, | |
173 | ); | |
04454e1e | 174 | return Some(CallStep::DeferredClosure(def_id, closure_sig)); |
a7813a04 XL |
175 | } |
176 | } | |
1a4d82fc | 177 | |
a7813a04 XL |
178 | // Hack: we know that there are traits implementing Fn for &F |
179 | // where F:Fn and so forth. In the particular case of types | |
180 | // like `x: &mut FnMut()`, if there is a call `x()`, we would | |
181 | // normally translate to `FnMut::call_mut(&mut x, ())`, but | |
182 | // that winds up requiring `mut x: &mut FnMut()`. A little | |
183 | // over the top. The simplest fix by far is to just ignore | |
184 | // this case and deref again, so we wind up with | |
185 | // `FnMut::call_mut(&mut *x, ())`. | |
b7449926 | 186 | ty::Ref(..) if autoderef.step_count() == 0 => { |
a7813a04 | 187 | return None; |
1a4d82fc | 188 | } |
a7813a04 XL |
189 | |
190 | _ => {} | |
1a4d82fc | 191 | } |
1a4d82fc | 192 | |
0731742a XL |
193 | // Now, we look for the implementation of a Fn trait on the object's type. |
194 | // We first do it with the explicit instruction to look for an impl of | |
195 | // `Fn<Tuple>`, with the tuple `Tuple` having an arity corresponding | |
196 | // to the number of call parameters. | |
197 | // If that fails (or_else branch), we try again without specifying the | |
198 | // shape of the tuple (hence the None). This allows to detect an Fn trait | |
199 | // is implemented, and use this information for diagnostic. | |
200 | self.try_overloaded_call_traits(call_expr, adjusted_ty, Some(arg_exprs)) | |
201 | .or_else(|| self.try_overloaded_call_traits(call_expr, adjusted_ty, None)) | |
202 | .map(|(autoref, method)| { | |
f035d41b | 203 | let mut adjustments = self.adjust_steps(autoderef); |
0731742a XL |
204 | adjustments.extend(autoref); |
205 | self.apply_adjustments(callee_expr, adjustments); | |
206 | CallStep::Overloaded(method) | |
207 | }) | |
a7813a04 | 208 | } |
1a4d82fc | 209 | |
0731742a XL |
210 | fn try_overloaded_call_traits( |
211 | &self, | |
dfeec247 | 212 | call_expr: &hir::Expr<'_>, |
0731742a | 213 | adjusted_ty: Ty<'tcx>, |
dfeec247 | 214 | opt_arg_exprs: Option<&'tcx [hir::Expr<'tcx>]>, |
0731742a | 215 | ) -> Option<(Option<Adjustment<'tcx>>, MethodCallee<'tcx>)> { |
a7813a04 | 216 | // Try the options that are least restrictive on the caller first. |
136023e0 | 217 | for (opt_trait_def_id, method_name, borrow) in [ |
3dfed10e XL |
218 | (self.tcx.lang_items().fn_trait(), Ident::with_dummy_span(sym::call), true), |
219 | (self.tcx.lang_items().fn_mut_trait(), Ident::with_dummy_span(sym::call_mut), true), | |
220 | (self.tcx.lang_items().fn_once_trait(), Ident::with_dummy_span(sym::call_once), false), | |
0731742a | 221 | ] { |
5e7ed085 | 222 | let Some(trait_def_id) = opt_trait_def_id else { continue }; |
a7813a04 | 223 | |
dfeec247 XL |
224 | let opt_input_types = opt_arg_exprs.map(|arg_exprs| { |
225 | [self.tcx.mk_tup(arg_exprs.iter().map(|e| { | |
dc9dc135 XL |
226 | self.next_ty_var(TypeVariableOrigin { |
227 | kind: TypeVariableOriginKind::TypeInference, | |
228 | span: e.span, | |
229 | }) | |
dfeec247 XL |
230 | }))] |
231 | }); | |
0731742a XL |
232 | let opt_input_types = opt_input_types.as_ref().map(AsRef::as_ref); |
233 | ||
234 | if let Some(ok) = self.lookup_method_in_trait( | |
235 | call_expr.span, | |
236 | method_name, | |
237 | trait_def_id, | |
238 | adjusted_ty, | |
239 | opt_input_types, | |
240 | ) { | |
0bf4aa26 XL |
241 | let method = self.register_infer_ok_obligations(ok); |
242 | let mut autoref = None; | |
243 | if borrow { | |
f035d41b XL |
244 | // Check for &self vs &mut self in the method signature. Since this is either |
245 | // the Fn or FnMut trait, it should be one of those. | |
5e7ed085 | 246 | let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].kind() else { |
c295e0f8 XL |
247 | // The `fn`/`fn_mut` lang item is ill-formed, which should have |
248 | // caused an error elsewhere. | |
249 | self.tcx | |
250 | .sess | |
251 | .delay_span_bug(call_expr.span, "input to call/call_mut is not a ref?"); | |
252 | return None; | |
253 | }; | |
f035d41b XL |
254 | |
255 | let mutbl = match mutbl { | |
256 | hir::Mutability::Not => AutoBorrowMutability::Not, | |
257 | hir::Mutability::Mut => AutoBorrowMutability::Mut { | |
258 | // For initial two-phase borrow | |
259 | // deployment, conservatively omit | |
260 | // overloaded function call ops. | |
261 | allow_two_phase_borrow: AllowTwoPhase::No, | |
262 | }, | |
263 | }; | |
264 | autoref = Some(Adjustment { | |
5099ac24 | 265 | kind: Adjust::Borrow(AutoBorrow::Ref(*region, mutbl)), |
f035d41b XL |
266 | target: method.sig.inputs()[0], |
267 | }); | |
a7813a04 | 268 | } |
0bf4aa26 | 269 | return Some((autoref, method)); |
a7813a04 | 270 | } |
1a4d82fc | 271 | } |
a7813a04 XL |
272 | |
273 | None | |
274 | } | |
275 | ||
532ac7d7 XL |
276 | /// Give appropriate suggestion when encountering `||{/* not callable */}()`, where the |
277 | /// likely intention is to call the closure, suggest `(||{})()`. (#55851) | |
278 | fn identify_bad_closure_def_and_call( | |
279 | &self, | |
5e7ed085 | 280 | err: &mut Diagnostic, |
532ac7d7 | 281 | hir_id: hir::HirId, |
dfeec247 | 282 | callee_node: &hir::ExprKind<'_>, |
532ac7d7 XL |
283 | callee_span: Span, |
284 | ) { | |
dc9dc135 XL |
285 | let hir_id = self.tcx.hir().get_parent_node(hir_id); |
286 | let parent_node = self.tcx.hir().get(hir_id); | |
532ac7d7 | 287 | if let ( |
e74abb32 | 288 | hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(_, _, _, sp, ..), .. }), |
532ac7d7 | 289 | hir::ExprKind::Block(..), |
dfeec247 XL |
290 | ) = (parent_node, callee_node) |
291 | { | |
532ac7d7 | 292 | let start = sp.shrink_to_lo(); |
60c5eb7d | 293 | let end = callee_span.shrink_to_hi(); |
532ac7d7 XL |
294 | err.multipart_suggestion( |
295 | "if you meant to create this closure and immediately call it, surround the \ | |
3c0e092e | 296 | closure with parentheses", |
532ac7d7 XL |
297 | vec![(start, "(".to_string()), (end, ")".to_string())], |
298 | Applicability::MaybeIncorrect, | |
299 | ); | |
300 | } | |
301 | } | |
302 | ||
5099ac24 FG |
303 | /// Give appropriate suggestion when encountering `[("a", 0) ("b", 1)]`, where the |
304 | /// likely intention is to create an array containing tuples. | |
305 | fn maybe_suggest_bad_array_definition( | |
306 | &self, | |
5e7ed085 | 307 | err: &mut Diagnostic, |
5099ac24 FG |
308 | call_expr: &'tcx hir::Expr<'tcx>, |
309 | callee_expr: &'tcx hir::Expr<'tcx>, | |
310 | ) -> bool { | |
311 | let hir_id = self.tcx.hir().get_parent_node(call_expr.hir_id); | |
312 | let parent_node = self.tcx.hir().get(hir_id); | |
313 | if let ( | |
314 | hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Array(_), .. }), | |
315 | hir::ExprKind::Tup(exp), | |
316 | hir::ExprKind::Call(_, args), | |
317 | ) = (parent_node, &callee_expr.kind, &call_expr.kind) | |
04454e1e | 318 | && args.len() == exp.len() |
5099ac24 | 319 | { |
04454e1e FG |
320 | let start = callee_expr.span.shrink_to_hi(); |
321 | err.span_suggestion( | |
322 | start, | |
323 | "consider separating array elements with a comma", | |
324 | ",".to_string(), | |
325 | Applicability::MaybeIncorrect, | |
326 | ); | |
327 | return true; | |
5099ac24 FG |
328 | } |
329 | false | |
330 | } | |
331 | ||
0731742a XL |
332 | fn confirm_builtin_call( |
333 | &self, | |
dfeec247 | 334 | call_expr: &'tcx hir::Expr<'tcx>, |
6a06907d | 335 | callee_expr: &'tcx hir::Expr<'tcx>, |
0731742a | 336 | callee_ty: Ty<'tcx>, |
dfeec247 | 337 | arg_exprs: &'tcx [hir::Expr<'tcx>], |
0731742a XL |
338 | expected: Expectation<'tcx>, |
339 | ) -> Ty<'tcx> { | |
29967ef6 | 340 | let (fn_sig, def_id) = match *callee_ty.kind() { |
17df50a5 | 341 | ty::FnDef(def_id, subst) => { |
04454e1e | 342 | let fn_sig = self.tcx.bound_fn_sig(def_id).subst(self.tcx, subst); |
c295e0f8 | 343 | |
17df50a5 XL |
344 | // Unit testing: function items annotated with |
345 | // `#[rustc_evaluate_where_clauses]` trigger special output | |
346 | // to let us test the trait evaluation system. | |
347 | if self.tcx.has_attr(def_id, sym::rustc_evaluate_where_clauses) { | |
348 | let predicates = self.tcx.predicates_of(def_id); | |
349 | let predicates = predicates.instantiate(self.tcx, subst); | |
350 | for (predicate, predicate_span) in | |
351 | predicates.predicates.iter().zip(&predicates.spans) | |
352 | { | |
353 | let obligation = Obligation::new( | |
354 | ObligationCause::dummy_with_span(callee_expr.span), | |
355 | self.param_env, | |
c295e0f8 | 356 | *predicate, |
17df50a5 XL |
357 | ); |
358 | let result = self.infcx.evaluate_obligation(&obligation); | |
359 | self.tcx | |
360 | .sess | |
361 | .struct_span_err( | |
362 | callee_expr.span, | |
363 | &format!("evaluate({:?}) = {:?}", predicate, result), | |
364 | ) | |
365 | .span_label(*predicate_span, "predicate") | |
366 | .emit(); | |
367 | } | |
368 | } | |
c295e0f8 | 369 | (fn_sig, Some(def_id)) |
17df50a5 | 370 | } |
b7449926 | 371 | ty::FnPtr(sig) => (sig, None), |
476ff2be SL |
372 | ref t => { |
373 | let mut unit_variant = None; | |
3c0e092e | 374 | let mut removal_span = call_expr.span; |
04454e1e FG |
375 | if let ty::Adt(adt_def, ..) = t |
376 | && adt_def.is_enum() | |
377 | && let hir::ExprKind::Call(expr, _) = call_expr.kind | |
378 | { | |
379 | removal_span = | |
380 | expr.span.shrink_to_hi().to(call_expr.span.shrink_to_hi()); | |
381 | unit_variant = | |
382 | self.tcx.sess.source_map().span_to_snippet(expr.span).ok(); | |
476ff2be | 383 | } |
2c00a5a8 | 384 | |
c295e0f8 | 385 | let callee_ty = self.resolve_vars_if_possible(callee_ty); |
6a06907d XL |
386 | let mut err = type_error_struct!( |
387 | self.tcx.sess, | |
388 | callee_expr.span, | |
389 | callee_ty, | |
390 | E0618, | |
391 | "expected function, found {}", | |
392 | match unit_variant { | |
04454e1e FG |
393 | Some(ref path) => format!("enum variant `{path}`"), |
394 | None => format!("`{callee_ty}`"), | |
6a06907d XL |
395 | } |
396 | ); | |
397 | ||
398 | self.identify_bad_closure_def_and_call( | |
399 | &mut err, | |
400 | call_expr.hir_id, | |
401 | &callee_expr.kind, | |
402 | callee_expr.span, | |
403 | ); | |
404 | ||
405 | if let Some(ref path) = unit_variant { | |
3c0e092e XL |
406 | err.span_suggestion_verbose( |
407 | removal_span, | |
6a06907d | 408 | &format!( |
04454e1e | 409 | "`{path}` is a unit variant, you need to write it without the parentheses", |
6a06907d | 410 | ), |
3c0e092e | 411 | String::new(), |
6a06907d | 412 | Applicability::MachineApplicable, |
532ac7d7 | 413 | ); |
6a06907d | 414 | } |
532ac7d7 | 415 | |
6a06907d XL |
416 | let mut inner_callee_path = None; |
417 | let def = match callee_expr.kind { | |
418 | hir::ExprKind::Path(ref qpath) => { | |
419 | self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id) | |
a1dfa0c6 | 420 | } |
6a06907d XL |
421 | hir::ExprKind::Call(ref inner_callee, _) => { |
422 | // If the call spans more than one line and the callee kind is | |
423 | // itself another `ExprCall`, that's a clue that we might just be | |
424 | // missing a semicolon (Issue #51055) | |
425 | let call_is_multiline = | |
426 | self.tcx.sess.source_map().is_multiline(call_expr.span); | |
427 | if call_is_multiline { | |
428 | err.span_suggestion( | |
429 | callee_expr.span.shrink_to_hi(), | |
430 | "consider using a semicolon here", | |
431 | ";".to_owned(), | |
432 | Applicability::MaybeIncorrect, | |
433 | ); | |
0731742a | 434 | } |
6a06907d XL |
435 | if let hir::ExprKind::Path(ref inner_qpath) = inner_callee.kind { |
436 | inner_callee_path = Some(inner_qpath); | |
437 | self.typeck_results.borrow().qpath_res(inner_qpath, inner_callee.hir_id) | |
438 | } else { | |
439 | Res::Err | |
a1dfa0c6 | 440 | } |
6a06907d XL |
441 | } |
442 | _ => Res::Err, | |
443 | }; | |
444 | ||
5099ac24 FG |
445 | if !self.maybe_suggest_bad_array_definition(&mut err, call_expr, callee_expr) { |
446 | err.span_label(call_expr.span, "call expression requires function"); | |
447 | } | |
6a06907d XL |
448 | |
449 | if let Some(span) = self.tcx.hir().res_span(def) { | |
450 | let callee_ty = callee_ty.to_string(); | |
451 | let label = match (unit_variant, inner_callee_path) { | |
04454e1e | 452 | (Some(path), _) => Some(format!("`{path}` defined here")), |
6a06907d XL |
453 | (_, Some(hir::QPath::Resolved(_, path))) => self |
454 | .tcx | |
455 | .sess | |
456 | .source_map() | |
457 | .span_to_snippet(path.span) | |
458 | .ok() | |
04454e1e | 459 | .map(|p| format!("`{p}` defined here returns `{callee_ty}`")), |
6a06907d XL |
460 | _ => { |
461 | match def { | |
462 | // Emit a different diagnostic for local variables, as they are not | |
463 | // type definitions themselves, but rather variables *of* that type. | |
464 | Res::Local(hir_id) => Some(format!( | |
465 | "`{}` has type `{}`", | |
466 | self.tcx.hir().name(hir_id), | |
467 | callee_ty | |
468 | )), | |
469 | Res::Def(kind, def_id) if kind.ns() == Some(Namespace::ValueNS) => { | |
470 | Some(format!( | |
471 | "`{}` defined here", | |
472 | self.tcx.def_path_str(def_id), | |
473 | )) | |
474 | } | |
04454e1e | 475 | _ => Some(format!("`{callee_ty}` defined here")), |
ba9703b0 | 476 | } |
ba9703b0 | 477 | } |
6a06907d XL |
478 | }; |
479 | if let Some(label) = label { | |
480 | err.span_label(span, label); | |
92a42be0 SL |
481 | } |
482 | } | |
6a06907d | 483 | err.emit(); |
92a42be0 | 484 | |
a7813a04 XL |
485 | // This is the "default" function signature, used in case of error. |
486 | // In that case, we check each argument against "error" in order to | |
487 | // set up all the node type bindings. | |
0731742a | 488 | ( |
fc512014 | 489 | ty::Binder::dummy(self.tcx.mk_fn_sig( |
0731742a | 490 | self.err_args(arg_exprs.len()).into_iter(), |
f035d41b | 491 | self.tcx.ty_error(), |
0731742a XL |
492 | false, |
493 | hir::Unsafety::Normal, | |
494 | abi::Abi::Rust, | |
495 | )), | |
496 | None, | |
497 | ) | |
a7813a04 XL |
498 | } |
499 | }; | |
1a4d82fc | 500 | |
a7813a04 XL |
501 | // Replace any late-bound regions that appear in the function |
502 | // signature with region variables. We also have to | |
503 | // renormalize the associated types at this point, since they | |
504 | // previously appeared within a `Binder<>` and hence would not | |
505 | // have been normalized before. | |
dfeec247 | 506 | let fn_sig = |
fc512014 XL |
507 | self.replace_bound_vars_with_fresh_vars(call_expr.span, infer::FnCall, fn_sig).0; |
508 | let fn_sig = self.normalize_associated_types_in(call_expr.span, fn_sig); | |
a7813a04 XL |
509 | |
510 | // Call the generic checker. | |
0731742a XL |
511 | let expected_arg_tys = self.expected_inputs_for_expected_output( |
512 | call_expr.span, | |
513 | expected, | |
514 | fn_sig.output(), | |
e74abb32 | 515 | fn_sig.inputs(), |
0731742a XL |
516 | ); |
517 | self.check_argument_types( | |
518 | call_expr.span, | |
e1599b0c | 519 | call_expr, |
e74abb32 | 520 | fn_sig.inputs(), |
a2a8927a | 521 | expected_arg_tys, |
0731742a | 522 | arg_exprs, |
532ac7d7 | 523 | fn_sig.c_variadic, |
0731742a | 524 | TupleArgumentsFlag::DontTupleArguments, |
29967ef6 | 525 | def_id, |
0731742a | 526 | ); |
a7813a04 | 527 | |
476ff2be | 528 | fn_sig.output() |
a7813a04 | 529 | } |
85aaf69f | 530 | |
0731742a XL |
531 | fn confirm_deferred_closure_call( |
532 | &self, | |
dfeec247 XL |
533 | call_expr: &'tcx hir::Expr<'tcx>, |
534 | arg_exprs: &'tcx [hir::Expr<'tcx>], | |
0731742a | 535 | expected: Expectation<'tcx>, |
04454e1e | 536 | closure_def_id: DefId, |
0731742a XL |
537 | fn_sig: ty::FnSig<'tcx>, |
538 | ) -> Ty<'tcx> { | |
5e7ed085 | 539 | // `fn_sig` is the *signature* of the closure being called. We |
a7813a04 XL |
540 | // don't know the full details yet (`Fn` vs `FnMut` etc), but we |
541 | // do know the types expected for each argument and the return | |
542 | // type. | |
543 | ||
0731742a XL |
544 | let expected_arg_tys = self.expected_inputs_for_expected_output( |
545 | call_expr.span, | |
546 | expected, | |
6a06907d | 547 | fn_sig.output(), |
0731742a XL |
548 | fn_sig.inputs(), |
549 | ); | |
550 | ||
551 | self.check_argument_types( | |
552 | call_expr.span, | |
e1599b0c | 553 | call_expr, |
0731742a | 554 | fn_sig.inputs(), |
a2a8927a | 555 | expected_arg_tys, |
0731742a | 556 | arg_exprs, |
532ac7d7 | 557 | fn_sig.c_variadic, |
0731742a | 558 | TupleArgumentsFlag::TupleArguments, |
04454e1e | 559 | Some(closure_def_id), |
0731742a | 560 | ); |
a7813a04 | 561 | |
476ff2be | 562 | fn_sig.output() |
a7813a04 | 563 | } |
85aaf69f | 564 | |
0731742a XL |
565 | fn confirm_overloaded_call( |
566 | &self, | |
dfeec247 XL |
567 | call_expr: &'tcx hir::Expr<'tcx>, |
568 | arg_exprs: &'tcx [hir::Expr<'tcx>], | |
0731742a XL |
569 | expected: Expectation<'tcx>, |
570 | method_callee: MethodCallee<'tcx>, | |
571 | ) -> Ty<'tcx> { | |
572 | let output_type = self.check_method_argument_types( | |
573 | call_expr.span, | |
e1599b0c | 574 | call_expr, |
0731742a XL |
575 | Ok(method_callee), |
576 | arg_exprs, | |
577 | TupleArgumentsFlag::TupleArguments, | |
578 | expected, | |
579 | ); | |
a7813a04 | 580 | |
3b2f2976 | 581 | self.write_method_call(call_expr.hir_id, method_callee); |
9e0c209e | 582 | output_type |
a7813a04 | 583 | } |
1a4d82fc JJ |
584 | } |
585 | ||
62682a34 | 586 | #[derive(Debug)] |
dc9dc135 | 587 | pub struct DeferredCallResolution<'tcx> { |
dfeec247 XL |
588 | call_expr: &'tcx hir::Expr<'tcx>, |
589 | callee_expr: &'tcx hir::Expr<'tcx>, | |
85aaf69f | 590 | adjusted_ty: Ty<'tcx>, |
7cac9316 | 591 | adjustments: Vec<Adjustment<'tcx>>, |
85aaf69f | 592 | fn_sig: ty::FnSig<'tcx>, |
e74abb32 | 593 | closure_substs: SubstsRef<'tcx>, |
85aaf69f SL |
594 | } |
595 | ||
dc9dc135 XL |
596 | impl<'a, 'tcx> DeferredCallResolution<'tcx> { |
597 | pub fn resolve(self, fcx: &FnCtxt<'a, 'tcx>) { | |
c30ab7b3 | 598 | debug!("DeferredCallResolution::resolve() {:?}", self); |
85aaf69f SL |
599 | |
600 | // we should not be invoked until the closure kind has been | |
601 | // determined by upvar inference | |
ba9703b0 | 602 | assert!(fcx.closure_kind(self.closure_substs).is_some()); |
85aaf69f SL |
603 | |
604 | // We may now know enough to figure out fn vs fnmut etc. | |
0731742a | 605 | match fcx.try_overloaded_call_traits(self.call_expr, self.adjusted_ty, None) { |
7cac9316 | 606 | Some((autoref, method_callee)) => { |
85aaf69f SL |
607 | // One problem is that when we get here, we are going |
608 | // to have a newly instantiated function signature | |
609 | // from the call trait. This has to be reconciled with | |
610 | // the older function signature we had before. In | |
611 | // principle we *should* be able to fn_sigs(), but we | |
612 | // can't because of the annoying need for a TypeTrace. | |
613 | // (This always bites me, should find a way to | |
614 | // refactor it.) | |
7cac9316 | 615 | let method_sig = method_callee.sig; |
85aaf69f | 616 | |
c30ab7b3 | 617 | debug!("attempt_resolution: method_callee={:?}", method_callee); |
85aaf69f | 618 | |
476ff2be | 619 | for (method_arg_ty, self_arg_ty) in |
cdc7bbd5 | 620 | iter::zip(method_sig.inputs().iter().skip(1), self.fn_sig.inputs()) |
0731742a | 621 | { |
5099ac24 | 622 | fcx.demand_eqtype(self.call_expr.span, *self_arg_ty, *method_arg_ty); |
85aaf69f SL |
623 | } |
624 | ||
dfeec247 | 625 | fcx.demand_eqtype(self.call_expr.span, method_sig.output(), self.fn_sig.output()); |
85aaf69f | 626 | |
7cac9316 XL |
627 | let mut adjustments = self.adjustments; |
628 | adjustments.extend(autoref); | |
629 | fcx.apply_adjustments(self.callee_expr, adjustments); | |
630 | ||
0731742a | 631 | fcx.write_method_call(self.call_expr.hir_id, method_callee); |
85aaf69f SL |
632 | } |
633 | None => { | |
136023e0 XL |
634 | // This can happen if `#![no_core]` is used and the `fn/fn_mut/fn_once` |
635 | // lang items are not defined (issue #86238). | |
636 | let mut err = fcx.inh.tcx.sess.struct_span_err( | |
0731742a | 637 | self.call_expr.span, |
136023e0 | 638 | "failed to find an overloaded call trait for closure call", |
0731742a | 639 | ); |
136023e0 XL |
640 | err.help( |
641 | "make sure the `fn`/`fn_mut`/`fn_once` lang items are defined \ | |
642 | and have associated `call`/`call_mut`/`call_once` functions", | |
643 | ); | |
644 | err.emit(); | |
85aaf69f SL |
645 | } |
646 | } | |
647 | } | |
648 | } |