]>
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 XL |
45 | .filter(|snippet| !snippet.is_empty()) |
46 | .map(|snippet| (expr_span, format!("drop({})", snippet))) | |
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>), |
85aaf69f | 62 | DeferredClosure(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 | |
a7813a04 | 110 | Some(CallStep::DeferredClosure(fn_sig)) => { |
9e0c209e | 111 | self.confirm_deferred_closure_call(call_expr, arg_exprs, expected, 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 | ); | |
ba9703b0 | 174 | return Some(CallStep::DeferredClosure(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) | |
318 | { | |
319 | if args.len() == exp.len() { | |
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; | |
328 | } | |
329 | } | |
330 | false | |
331 | } | |
332 | ||
0731742a XL |
333 | fn confirm_builtin_call( |
334 | &self, | |
dfeec247 | 335 | call_expr: &'tcx hir::Expr<'tcx>, |
6a06907d | 336 | callee_expr: &'tcx hir::Expr<'tcx>, |
0731742a | 337 | callee_ty: Ty<'tcx>, |
dfeec247 | 338 | arg_exprs: &'tcx [hir::Expr<'tcx>], |
0731742a XL |
339 | expected: Expectation<'tcx>, |
340 | ) -> Ty<'tcx> { | |
29967ef6 | 341 | let (fn_sig, def_id) = match *callee_ty.kind() { |
17df50a5 | 342 | ty::FnDef(def_id, subst) => { |
c295e0f8 XL |
343 | let fn_sig = self.tcx.fn_sig(def_id).subst(self.tcx, subst); |
344 | ||
17df50a5 XL |
345 | // Unit testing: function items annotated with |
346 | // `#[rustc_evaluate_where_clauses]` trigger special output | |
347 | // to let us test the trait evaluation system. | |
348 | if self.tcx.has_attr(def_id, sym::rustc_evaluate_where_clauses) { | |
349 | let predicates = self.tcx.predicates_of(def_id); | |
350 | let predicates = predicates.instantiate(self.tcx, subst); | |
351 | for (predicate, predicate_span) in | |
352 | predicates.predicates.iter().zip(&predicates.spans) | |
353 | { | |
354 | let obligation = Obligation::new( | |
355 | ObligationCause::dummy_with_span(callee_expr.span), | |
356 | self.param_env, | |
c295e0f8 | 357 | *predicate, |
17df50a5 XL |
358 | ); |
359 | let result = self.infcx.evaluate_obligation(&obligation); | |
360 | self.tcx | |
361 | .sess | |
362 | .struct_span_err( | |
363 | callee_expr.span, | |
364 | &format!("evaluate({:?}) = {:?}", predicate, result), | |
365 | ) | |
366 | .span_label(*predicate_span, "predicate") | |
367 | .emit(); | |
368 | } | |
369 | } | |
c295e0f8 | 370 | (fn_sig, Some(def_id)) |
17df50a5 | 371 | } |
b7449926 | 372 | ty::FnPtr(sig) => (sig, None), |
476ff2be SL |
373 | ref t => { |
374 | let mut unit_variant = None; | |
3c0e092e | 375 | let mut removal_span = call_expr.span; |
5869c6ff | 376 | if let ty::Adt(adt_def, ..) = t { |
476ff2be | 377 | if adt_def.is_enum() { |
5869c6ff | 378 | if let hir::ExprKind::Call(expr, _) = call_expr.kind { |
3c0e092e XL |
379 | removal_span = |
380 | expr.span.shrink_to_hi().to(call_expr.span.shrink_to_hi()); | |
ba9703b0 XL |
381 | unit_variant = |
382 | self.tcx.sess.source_map().span_to_snippet(expr.span).ok(); | |
476ff2be SL |
383 | } |
384 | } | |
385 | } | |
2c00a5a8 | 386 | |
c295e0f8 | 387 | let callee_ty = self.resolve_vars_if_possible(callee_ty); |
6a06907d XL |
388 | let mut err = type_error_struct!( |
389 | self.tcx.sess, | |
390 | callee_expr.span, | |
391 | callee_ty, | |
392 | E0618, | |
393 | "expected function, found {}", | |
394 | match unit_variant { | |
395 | Some(ref path) => format!("enum variant `{}`", path), | |
396 | None => format!("`{}`", callee_ty), | |
397 | } | |
398 | ); | |
399 | ||
400 | self.identify_bad_closure_def_and_call( | |
401 | &mut err, | |
402 | call_expr.hir_id, | |
403 | &callee_expr.kind, | |
404 | callee_expr.span, | |
405 | ); | |
406 | ||
407 | if let Some(ref path) = unit_variant { | |
3c0e092e XL |
408 | err.span_suggestion_verbose( |
409 | removal_span, | |
6a06907d | 410 | &format!( |
3c0e092e | 411 | "`{}` is a unit variant, you need to write it without the parentheses", |
6a06907d XL |
412 | path |
413 | ), | |
3c0e092e | 414 | String::new(), |
6a06907d | 415 | Applicability::MachineApplicable, |
532ac7d7 | 416 | ); |
6a06907d | 417 | } |
532ac7d7 | 418 | |
6a06907d XL |
419 | let mut inner_callee_path = None; |
420 | let def = match callee_expr.kind { | |
421 | hir::ExprKind::Path(ref qpath) => { | |
422 | self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id) | |
a1dfa0c6 | 423 | } |
6a06907d XL |
424 | hir::ExprKind::Call(ref inner_callee, _) => { |
425 | // If the call spans more than one line and the callee kind is | |
426 | // itself another `ExprCall`, that's a clue that we might just be | |
427 | // missing a semicolon (Issue #51055) | |
428 | let call_is_multiline = | |
429 | self.tcx.sess.source_map().is_multiline(call_expr.span); | |
430 | if call_is_multiline { | |
431 | err.span_suggestion( | |
432 | callee_expr.span.shrink_to_hi(), | |
433 | "consider using a semicolon here", | |
434 | ";".to_owned(), | |
435 | Applicability::MaybeIncorrect, | |
436 | ); | |
0731742a | 437 | } |
6a06907d XL |
438 | if let hir::ExprKind::Path(ref inner_qpath) = inner_callee.kind { |
439 | inner_callee_path = Some(inner_qpath); | |
440 | self.typeck_results.borrow().qpath_res(inner_qpath, inner_callee.hir_id) | |
441 | } else { | |
442 | Res::Err | |
a1dfa0c6 | 443 | } |
6a06907d XL |
444 | } |
445 | _ => Res::Err, | |
446 | }; | |
447 | ||
5099ac24 FG |
448 | if !self.maybe_suggest_bad_array_definition(&mut err, call_expr, callee_expr) { |
449 | err.span_label(call_expr.span, "call expression requires function"); | |
450 | } | |
6a06907d XL |
451 | |
452 | if let Some(span) = self.tcx.hir().res_span(def) { | |
453 | let callee_ty = callee_ty.to_string(); | |
454 | let label = match (unit_variant, inner_callee_path) { | |
455 | (Some(path), _) => Some(format!("`{}` defined here", path)), | |
456 | (_, Some(hir::QPath::Resolved(_, path))) => self | |
457 | .tcx | |
458 | .sess | |
459 | .source_map() | |
460 | .span_to_snippet(path.span) | |
461 | .ok() | |
462 | .map(|p| format!("`{}` defined here returns `{}`", p, callee_ty)), | |
463 | _ => { | |
464 | match def { | |
465 | // Emit a different diagnostic for local variables, as they are not | |
466 | // type definitions themselves, but rather variables *of* that type. | |
467 | Res::Local(hir_id) => Some(format!( | |
468 | "`{}` has type `{}`", | |
469 | self.tcx.hir().name(hir_id), | |
470 | callee_ty | |
471 | )), | |
472 | Res::Def(kind, def_id) if kind.ns() == Some(Namespace::ValueNS) => { | |
473 | Some(format!( | |
474 | "`{}` defined here", | |
475 | self.tcx.def_path_str(def_id), | |
476 | )) | |
477 | } | |
478 | _ => Some(format!("`{}` defined here", callee_ty)), | |
ba9703b0 | 479 | } |
ba9703b0 | 480 | } |
6a06907d XL |
481 | }; |
482 | if let Some(label) = label { | |
483 | err.span_label(span, label); | |
92a42be0 SL |
484 | } |
485 | } | |
6a06907d | 486 | err.emit(); |
92a42be0 | 487 | |
a7813a04 XL |
488 | // This is the "default" function signature, used in case of error. |
489 | // In that case, we check each argument against "error" in order to | |
490 | // set up all the node type bindings. | |
0731742a | 491 | ( |
fc512014 | 492 | ty::Binder::dummy(self.tcx.mk_fn_sig( |
0731742a | 493 | self.err_args(arg_exprs.len()).into_iter(), |
f035d41b | 494 | self.tcx.ty_error(), |
0731742a XL |
495 | false, |
496 | hir::Unsafety::Normal, | |
497 | abi::Abi::Rust, | |
498 | )), | |
499 | None, | |
500 | ) | |
a7813a04 XL |
501 | } |
502 | }; | |
1a4d82fc | 503 | |
a7813a04 XL |
504 | // Replace any late-bound regions that appear in the function |
505 | // signature with region variables. We also have to | |
506 | // renormalize the associated types at this point, since they | |
507 | // previously appeared within a `Binder<>` and hence would not | |
508 | // have been normalized before. | |
dfeec247 | 509 | let fn_sig = |
fc512014 XL |
510 | self.replace_bound_vars_with_fresh_vars(call_expr.span, infer::FnCall, fn_sig).0; |
511 | let fn_sig = self.normalize_associated_types_in(call_expr.span, fn_sig); | |
a7813a04 XL |
512 | |
513 | // Call the generic checker. | |
0731742a XL |
514 | let expected_arg_tys = self.expected_inputs_for_expected_output( |
515 | call_expr.span, | |
516 | expected, | |
517 | fn_sig.output(), | |
e74abb32 | 518 | fn_sig.inputs(), |
0731742a XL |
519 | ); |
520 | self.check_argument_types( | |
521 | call_expr.span, | |
e1599b0c | 522 | call_expr, |
e74abb32 | 523 | fn_sig.inputs(), |
a2a8927a | 524 | expected_arg_tys, |
0731742a | 525 | arg_exprs, |
532ac7d7 | 526 | fn_sig.c_variadic, |
0731742a | 527 | TupleArgumentsFlag::DontTupleArguments, |
29967ef6 | 528 | def_id, |
0731742a | 529 | ); |
a7813a04 | 530 | |
476ff2be | 531 | fn_sig.output() |
a7813a04 | 532 | } |
85aaf69f | 533 | |
0731742a XL |
534 | fn confirm_deferred_closure_call( |
535 | &self, | |
dfeec247 XL |
536 | call_expr: &'tcx hir::Expr<'tcx>, |
537 | arg_exprs: &'tcx [hir::Expr<'tcx>], | |
0731742a XL |
538 | expected: Expectation<'tcx>, |
539 | fn_sig: ty::FnSig<'tcx>, | |
540 | ) -> Ty<'tcx> { | |
5e7ed085 | 541 | // `fn_sig` is the *signature* of the closure being called. We |
a7813a04 XL |
542 | // don't know the full details yet (`Fn` vs `FnMut` etc), but we |
543 | // do know the types expected for each argument and the return | |
544 | // type. | |
545 | ||
0731742a XL |
546 | let expected_arg_tys = self.expected_inputs_for_expected_output( |
547 | call_expr.span, | |
548 | expected, | |
6a06907d | 549 | fn_sig.output(), |
0731742a XL |
550 | fn_sig.inputs(), |
551 | ); | |
552 | ||
553 | self.check_argument_types( | |
554 | call_expr.span, | |
e1599b0c | 555 | call_expr, |
0731742a | 556 | fn_sig.inputs(), |
a2a8927a | 557 | expected_arg_tys, |
0731742a | 558 | arg_exprs, |
532ac7d7 | 559 | fn_sig.c_variadic, |
0731742a XL |
560 | TupleArgumentsFlag::TupleArguments, |
561 | None, | |
562 | ); | |
a7813a04 | 563 | |
476ff2be | 564 | fn_sig.output() |
a7813a04 | 565 | } |
85aaf69f | 566 | |
0731742a XL |
567 | fn confirm_overloaded_call( |
568 | &self, | |
dfeec247 XL |
569 | call_expr: &'tcx hir::Expr<'tcx>, |
570 | arg_exprs: &'tcx [hir::Expr<'tcx>], | |
0731742a XL |
571 | expected: Expectation<'tcx>, |
572 | method_callee: MethodCallee<'tcx>, | |
573 | ) -> Ty<'tcx> { | |
574 | let output_type = self.check_method_argument_types( | |
575 | call_expr.span, | |
e1599b0c | 576 | call_expr, |
0731742a XL |
577 | Ok(method_callee), |
578 | arg_exprs, | |
579 | TupleArgumentsFlag::TupleArguments, | |
580 | expected, | |
581 | ); | |
a7813a04 | 582 | |
3b2f2976 | 583 | self.write_method_call(call_expr.hir_id, method_callee); |
9e0c209e | 584 | output_type |
a7813a04 | 585 | } |
1a4d82fc JJ |
586 | } |
587 | ||
62682a34 | 588 | #[derive(Debug)] |
dc9dc135 | 589 | pub struct DeferredCallResolution<'tcx> { |
dfeec247 XL |
590 | call_expr: &'tcx hir::Expr<'tcx>, |
591 | callee_expr: &'tcx hir::Expr<'tcx>, | |
85aaf69f | 592 | adjusted_ty: Ty<'tcx>, |
7cac9316 | 593 | adjustments: Vec<Adjustment<'tcx>>, |
85aaf69f | 594 | fn_sig: ty::FnSig<'tcx>, |
e74abb32 | 595 | closure_substs: SubstsRef<'tcx>, |
85aaf69f SL |
596 | } |
597 | ||
dc9dc135 XL |
598 | impl<'a, 'tcx> DeferredCallResolution<'tcx> { |
599 | pub fn resolve(self, fcx: &FnCtxt<'a, 'tcx>) { | |
c30ab7b3 | 600 | debug!("DeferredCallResolution::resolve() {:?}", self); |
85aaf69f SL |
601 | |
602 | // we should not be invoked until the closure kind has been | |
603 | // determined by upvar inference | |
ba9703b0 | 604 | assert!(fcx.closure_kind(self.closure_substs).is_some()); |
85aaf69f SL |
605 | |
606 | // We may now know enough to figure out fn vs fnmut etc. | |
0731742a | 607 | match fcx.try_overloaded_call_traits(self.call_expr, self.adjusted_ty, None) { |
7cac9316 | 608 | Some((autoref, method_callee)) => { |
85aaf69f SL |
609 | // One problem is that when we get here, we are going |
610 | // to have a newly instantiated function signature | |
611 | // from the call trait. This has to be reconciled with | |
612 | // the older function signature we had before. In | |
613 | // principle we *should* be able to fn_sigs(), but we | |
614 | // can't because of the annoying need for a TypeTrace. | |
615 | // (This always bites me, should find a way to | |
616 | // refactor it.) | |
7cac9316 | 617 | let method_sig = method_callee.sig; |
85aaf69f | 618 | |
c30ab7b3 | 619 | debug!("attempt_resolution: method_callee={:?}", method_callee); |
85aaf69f | 620 | |
476ff2be | 621 | for (method_arg_ty, self_arg_ty) in |
cdc7bbd5 | 622 | iter::zip(method_sig.inputs().iter().skip(1), self.fn_sig.inputs()) |
0731742a | 623 | { |
5099ac24 | 624 | fcx.demand_eqtype(self.call_expr.span, *self_arg_ty, *method_arg_ty); |
85aaf69f SL |
625 | } |
626 | ||
dfeec247 | 627 | fcx.demand_eqtype(self.call_expr.span, method_sig.output(), self.fn_sig.output()); |
85aaf69f | 628 | |
7cac9316 XL |
629 | let mut adjustments = self.adjustments; |
630 | adjustments.extend(autoref); | |
631 | fcx.apply_adjustments(self.callee_expr, adjustments); | |
632 | ||
0731742a | 633 | fcx.write_method_call(self.call_expr.hir_id, method_callee); |
85aaf69f SL |
634 | } |
635 | None => { | |
136023e0 XL |
636 | // This can happen if `#![no_core]` is used and the `fn/fn_mut/fn_once` |
637 | // lang items are not defined (issue #86238). | |
638 | let mut err = fcx.inh.tcx.sess.struct_span_err( | |
0731742a | 639 | self.call_expr.span, |
136023e0 | 640 | "failed to find an overloaded call trait for closure call", |
0731742a | 641 | ); |
136023e0 XL |
642 | err.help( |
643 | "make sure the `fn`/`fn_mut`/`fn_once` lang items are defined \ | |
644 | and have associated `call`/`call_mut`/`call_once` functions", | |
645 | ); | |
646 | err.emit(); | |
85aaf69f SL |
647 | } |
648 | } | |
649 | } | |
650 | } |