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