1use std::iter;
2
3use rustc_ast::util::parser::ExprPrecedence;
4use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey};
5use rustc_hir::def::{self, CtorKind, Namespace, Res};
6use rustc_hir::def_id::DefId;
7use rustc_hir::{self as hir, HirId, LangItem};
8use rustc_hir_analysis::autoderef::Autoderef;
9use rustc_infer::infer;
10use rustc_infer::traits::{Obligation, ObligationCause, ObligationCauseCode};
11use rustc_middle::ty::adjustment::{
12 Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability,
13};
14use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt};
15use rustc_middle::{bug, span_bug};
16use rustc_span::def_id::LocalDefId;
17use rustc_span::{Span, sym};
18use rustc_trait_selection::error_reporting::traits::DefIdOrName;
19use rustc_trait_selection::infer::InferCtxtExt as _;
20use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
21use tracing::{debug, instrument};
22
23use super::method::MethodCallee;
24use super::method::probe::ProbeScope;
25use super::{Expectation, FnCtxt, TupleArgumentsFlag};
26use crate::{errors, fluent_generated};
27
28pub(crate) fn check_legal_trait_for_method_call(
32 tcx: TyCtxt<'_>,
33 span: Span,
34 receiver: Option<Span>,
35 expr_span: Span,
36 trait_id: DefId,
37 _body_id: DefId,
38) -> Result<(), ErrorGuaranteed> {
39 if tcx.is_lang_item(trait_id, LangItem::Drop) {
40 let sugg = if let Some(receiver) = receiver.filter(|s| !s.is_empty()) {
41 errors::ExplicitDestructorCallSugg::Snippet {
42 lo: expr_span.shrink_to_lo(),
43 hi: receiver.shrink_to_hi().to(expr_span.shrink_to_hi()),
44 }
45 } else {
46 errors::ExplicitDestructorCallSugg::Empty(span)
47 };
48 return Err(tcx.dcx().emit_err(errors::ExplicitDestructorCall { span, sugg }));
49 }
50 tcx.ensure_ok().coherent_trait(trait_id)
51}
52
53#[derive(Debug)]
54enum CallStep<'tcx> {
55 Builtin(Ty<'tcx>),
56 DeferredClosure(LocalDefId, ty::FnSig<'tcx>),
57 Overloaded(MethodCallee<'tcx>),
59}
60
61impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
62 pub(crate) fn check_expr_call(
63 &self,
64 call_expr: &'tcx hir::Expr<'tcx>,
65 callee_expr: &'tcx hir::Expr<'tcx>,
66 arg_exprs: &'tcx [hir::Expr<'tcx>],
67 expected: Expectation<'tcx>,
68 ) -> Ty<'tcx> {
69 let original_callee_ty = match &callee_expr.kind {
70 hir::ExprKind::Path(hir::QPath::Resolved(..) | hir::QPath::TypeRelative(..)) => self
71 .check_expr_with_expectation_and_args(
72 callee_expr,
73 Expectation::NoExpectation,
74 Some((call_expr, arg_exprs)),
75 ),
76 _ => self.check_expr(callee_expr),
77 };
78
79 let expr_ty = self.structurally_resolve_type(call_expr.span, original_callee_ty);
80
81 let mut autoderef = self.autoderef(callee_expr.span, expr_ty);
82 let mut result = None;
83 while result.is_none() && autoderef.next().is_some() {
84 result = self.try_overloaded_call_step(call_expr, callee_expr, arg_exprs, &autoderef);
85 }
86 self.register_predicates(autoderef.into_obligations());
87
88 let output = match result {
89 None => {
90 for arg in arg_exprs {
93 self.check_expr(arg);
94 }
95
96 if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = &callee_expr.kind
97 && let [segment] = path.segments
98 {
99 self.dcx().try_steal_modify_and_emit_err(
100 segment.ident.span,
101 StashKey::CallIntoMethod,
102 |err| {
103 self.suggest_call_as_method(
105 err, segment, arg_exprs, call_expr, expected,
106 );
107 },
108 );
109 }
110
111 let guar = self.report_invalid_callee(call_expr, callee_expr, expr_ty, arg_exprs);
112 Ty::new_error(self.tcx, guar)
113 }
114
115 Some(CallStep::Builtin(callee_ty)) => {
116 self.confirm_builtin_call(call_expr, callee_expr, callee_ty, arg_exprs, expected)
117 }
118
119 Some(CallStep::DeferredClosure(def_id, fn_sig)) => {
120 self.confirm_deferred_closure_call(call_expr, arg_exprs, expected, def_id, fn_sig)
121 }
122
123 Some(CallStep::Overloaded(method_callee)) => {
124 self.confirm_overloaded_call(call_expr, arg_exprs, expected, method_callee)
125 }
126 };
127
128 self.register_wf_obligation(
130 output.into(),
131 call_expr.span,
132 ObligationCauseCode::WellFormed(None),
133 );
134
135 output
136 }
137
138 #[instrument(level = "debug", skip(self, call_expr, callee_expr, arg_exprs, autoderef), ret)]
139 fn try_overloaded_call_step(
140 &self,
141 call_expr: &'tcx hir::Expr<'tcx>,
142 callee_expr: &'tcx hir::Expr<'tcx>,
143 arg_exprs: &'tcx [hir::Expr<'tcx>],
144 autoderef: &Autoderef<'a, 'tcx>,
145 ) -> Option<CallStep<'tcx>> {
146 let adjusted_ty =
147 self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false));
148
149 match *adjusted_ty.kind() {
151 ty::FnDef(..) | ty::FnPtr(..) => {
152 let adjustments = self.adjust_steps(autoderef);
153 self.apply_adjustments(callee_expr, adjustments);
154 return Some(CallStep::Builtin(adjusted_ty));
155 }
156
157 ty::Closure(def_id, args) if self.closure_kind(adjusted_ty).is_none() => {
161 let def_id = def_id.expect_local();
162 let closure_sig = args.as_closure().sig();
163 let closure_sig = self.instantiate_binder_with_fresh_vars(
164 call_expr.span,
165 infer::FnCall,
166 closure_sig,
167 );
168 let adjustments = self.adjust_steps(autoderef);
169 self.record_deferred_call_resolution(
170 def_id,
171 DeferredCallResolution {
172 call_expr,
173 callee_expr,
174 closure_ty: adjusted_ty,
175 adjustments,
176 fn_sig: closure_sig,
177 },
178 );
179 return Some(CallStep::DeferredClosure(def_id, closure_sig));
180 }
181
182 ty::CoroutineClosure(def_id, args) if self.closure_kind(adjusted_ty).is_none() => {
188 let def_id = def_id.expect_local();
189 let closure_args = args.as_coroutine_closure();
190 let coroutine_closure_sig = self.instantiate_binder_with_fresh_vars(
191 call_expr.span,
192 infer::FnCall,
193 closure_args.coroutine_closure_sig(),
194 );
195 let tupled_upvars_ty = self.next_ty_var(callee_expr.span);
196 let kind_ty = self.next_ty_var(callee_expr.span);
201 let call_sig = self.tcx.mk_fn_sig(
202 [coroutine_closure_sig.tupled_inputs_ty],
203 coroutine_closure_sig.to_coroutine(
204 self.tcx,
205 closure_args.parent_args(),
206 kind_ty,
207 self.tcx.coroutine_for_closure(def_id),
208 tupled_upvars_ty,
209 ),
210 coroutine_closure_sig.c_variadic,
211 coroutine_closure_sig.safety,
212 coroutine_closure_sig.abi,
213 );
214 let adjustments = self.adjust_steps(autoderef);
215 self.record_deferred_call_resolution(
216 def_id,
217 DeferredCallResolution {
218 call_expr,
219 callee_expr,
220 closure_ty: adjusted_ty,
221 adjustments,
222 fn_sig: call_sig,
223 },
224 );
225 return Some(CallStep::DeferredClosure(def_id, call_sig));
226 }
227
228 ty::Ref(..) if autoderef.step_count() == 0 => {
241 return None;
242 }
243
244 ty::Error(_) => {
245 return None;
246 }
247
248 _ => {}
249 }
250
251 self.try_overloaded_call_traits(call_expr, adjusted_ty, Some(arg_exprs))
259 .or_else(|| self.try_overloaded_call_traits(call_expr, adjusted_ty, None))
260 .map(|(autoref, method)| {
261 let mut adjustments = self.adjust_steps(autoderef);
262 adjustments.extend(autoref);
263 self.apply_adjustments(callee_expr, adjustments);
264 CallStep::Overloaded(method)
265 })
266 }
267
268 fn try_overloaded_call_traits(
269 &self,
270 call_expr: &hir::Expr<'_>,
271 adjusted_ty: Ty<'tcx>,
272 opt_arg_exprs: Option<&'tcx [hir::Expr<'tcx>]>,
273 ) -> Option<(Option<Adjustment<'tcx>>, MethodCallee<'tcx>)> {
274 let call_trait_choices = if self.shallow_resolve(adjusted_ty).is_coroutine_closure() {
287 [
288 (self.tcx.lang_items().async_fn_trait(), sym::async_call, true),
289 (self.tcx.lang_items().async_fn_mut_trait(), sym::async_call_mut, true),
290 (self.tcx.lang_items().async_fn_once_trait(), sym::async_call_once, false),
291 (self.tcx.lang_items().fn_trait(), sym::call, true),
292 (self.tcx.lang_items().fn_mut_trait(), sym::call_mut, true),
293 (self.tcx.lang_items().fn_once_trait(), sym::call_once, false),
294 ]
295 } else {
296 [
297 (self.tcx.lang_items().fn_trait(), sym::call, true),
298 (self.tcx.lang_items().fn_mut_trait(), sym::call_mut, true),
299 (self.tcx.lang_items().fn_once_trait(), sym::call_once, false),
300 (self.tcx.lang_items().async_fn_trait(), sym::async_call, true),
301 (self.tcx.lang_items().async_fn_mut_trait(), sym::async_call_mut, true),
302 (self.tcx.lang_items().async_fn_once_trait(), sym::async_call_once, false),
303 ]
304 };
305
306 for (opt_trait_def_id, method_name, borrow) in call_trait_choices {
308 let Some(trait_def_id) = opt_trait_def_id else { continue };
309
310 let opt_input_type = opt_arg_exprs.map(|arg_exprs| {
311 Ty::new_tup_from_iter(self.tcx, arg_exprs.iter().map(|e| self.next_ty_var(e.span)))
312 });
313
314 if let Some(ok) = self.lookup_method_for_operator(
315 self.misc(call_expr.span),
316 method_name,
317 trait_def_id,
318 adjusted_ty,
319 opt_input_type,
320 ) {
321 let method = self.register_infer_ok_obligations(ok);
322 let mut autoref = None;
323 if borrow {
324 let ty::Ref(_, _, mutbl) = method.sig.inputs()[0].kind() else {
327 bug!("Expected `FnMut`/`Fn` to take receiver by-ref/by-mut")
328 };
329
330 let mutbl = AutoBorrowMutability::new(*mutbl, AllowTwoPhase::No);
334
335 autoref = Some(Adjustment {
336 kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)),
337 target: method.sig.inputs()[0],
338 });
339 }
340
341 return Some((autoref, method));
342 }
343 }
344
345 None
346 }
347
348 fn identify_bad_closure_def_and_call(
351 &self,
352 err: &mut Diag<'_>,
353 hir_id: hir::HirId,
354 callee_node: &hir::ExprKind<'_>,
355 callee_span: Span,
356 ) {
357 let hir::ExprKind::Block(..) = callee_node else {
358 return;
360 };
361
362 let fn_decl_span = if let hir::Node::Expr(&hir::Expr {
363 kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }),
364 ..
365 }) = self.tcx.parent_hir_node(hir_id)
366 {
367 fn_decl_span
368 } else if let Some((
369 _,
370 hir::Node::Expr(&hir::Expr {
371 hir_id: parent_hir_id,
372 kind:
373 hir::ExprKind::Closure(&hir::Closure {
374 kind:
375 hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
376 hir::CoroutineDesugaring::Async,
377 hir::CoroutineSource::Closure,
378 )),
379 ..
380 }),
381 ..
382 }),
383 )) = self.tcx.hir_parent_iter(hir_id).nth(3)
384 {
385 if let hir::Node::Expr(&hir::Expr {
388 kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }),
389 ..
390 }) = self.tcx.parent_hir_node(parent_hir_id)
391 {
392 fn_decl_span
393 } else {
394 return;
395 }
396 } else {
397 return;
398 };
399
400 let start = fn_decl_span.shrink_to_lo();
401 let end = callee_span.shrink_to_hi();
402 err.multipart_suggestion(
403 "if you meant to create this closure and immediately call it, surround the \
404 closure with parentheses",
405 vec![(start, "(".to_string()), (end, ")".to_string())],
406 Applicability::MaybeIncorrect,
407 );
408 }
409
410 fn maybe_suggest_bad_array_definition(
413 &self,
414 err: &mut Diag<'_>,
415 call_expr: &'tcx hir::Expr<'tcx>,
416 callee_expr: &'tcx hir::Expr<'tcx>,
417 ) -> bool {
418 let parent_node = self.tcx.parent_hir_node(call_expr.hir_id);
419 if let (
420 hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Array(_), .. }),
421 hir::ExprKind::Tup(exp),
422 hir::ExprKind::Call(_, args),
423 ) = (parent_node, &callee_expr.kind, &call_expr.kind)
424 && args.len() == exp.len()
425 {
426 let start = callee_expr.span.shrink_to_hi();
427 err.span_suggestion(
428 start,
429 "consider separating array elements with a comma",
430 ",",
431 Applicability::MaybeIncorrect,
432 );
433 return true;
434 }
435 false
436 }
437
438 fn confirm_builtin_call(
439 &self,
440 call_expr: &'tcx hir::Expr<'tcx>,
441 callee_expr: &'tcx hir::Expr<'tcx>,
442 callee_ty: Ty<'tcx>,
443 arg_exprs: &'tcx [hir::Expr<'tcx>],
444 expected: Expectation<'tcx>,
445 ) -> Ty<'tcx> {
446 let (fn_sig, def_id) = match *callee_ty.kind() {
447 ty::FnDef(def_id, args) => {
448 self.enforce_context_effects(Some(call_expr.hir_id), call_expr.span, def_id, args);
449 let fn_sig = self.tcx.fn_sig(def_id).instantiate(self.tcx, args);
450
451 #[allow(rustc::untranslatable_diagnostic)]
456 #[allow(rustc::diagnostic_outside_of_impl)]
457 if self.tcx.has_attr(def_id, sym::rustc_evaluate_where_clauses) {
458 let predicates = self.tcx.predicates_of(def_id);
459 let predicates = predicates.instantiate(self.tcx, args);
460 for (predicate, predicate_span) in predicates {
461 let obligation = Obligation::new(
462 self.tcx,
463 ObligationCause::dummy_with_span(callee_expr.span),
464 self.param_env,
465 predicate,
466 );
467 let result = self.evaluate_obligation(&obligation);
468 self.dcx()
469 .struct_span_err(
470 callee_expr.span,
471 format!("evaluate({predicate:?}) = {result:?}"),
472 )
473 .with_span_label(predicate_span, "predicate")
474 .emit();
475 }
476 }
477 (fn_sig, Some(def_id))
478 }
479
480 ty::FnPtr(sig_tys, hdr) => (sig_tys.with(hdr), None),
482
483 _ => unreachable!(),
484 };
485
486 let fn_sig = self.instantiate_binder_with_fresh_vars(call_expr.span, infer::FnCall, fn_sig);
492 let fn_sig = self.normalize(call_expr.span, fn_sig);
493
494 self.check_argument_types(
495 call_expr.span,
496 call_expr,
497 fn_sig.inputs(),
498 fn_sig.output(),
499 expected,
500 arg_exprs,
501 fn_sig.c_variadic,
502 TupleArgumentsFlag::DontTupleArguments,
503 def_id,
504 );
505
506 if fn_sig.abi == rustc_abi::ExternAbi::RustCall {
507 let sp = arg_exprs.last().map_or(call_expr.span, |expr| expr.span);
508 if let Some(ty) = fn_sig.inputs().last().copied() {
509 self.register_bound(
510 ty,
511 self.tcx.require_lang_item(hir::LangItem::Tuple, Some(sp)),
512 self.cause(sp, ObligationCauseCode::RustCall),
513 );
514 self.require_type_is_sized(ty, sp, ObligationCauseCode::RustCall);
515 } else {
516 self.dcx().emit_err(errors::RustCallIncorrectArgs { span: sp });
517 }
518 }
519
520 if let Some(def_id) = def_id
521 && self.tcx.def_kind(def_id) == hir::def::DefKind::Fn
522 && self.tcx.is_intrinsic(def_id, sym::const_eval_select)
523 {
524 let fn_sig = self.resolve_vars_if_possible(fn_sig);
525 for idx in 0..=1 {
526 let arg_ty = fn_sig.inputs()[idx + 1];
527 let span = arg_exprs.get(idx + 1).map_or(call_expr.span, |arg| arg.span);
528 if let ty::FnDef(def_id, _args) = *arg_ty.kind() {
534 if idx == 0 && !self.tcx.is_const_fn(def_id) {
535 self.dcx().emit_err(errors::ConstSelectMustBeConst { span });
536 }
537 } else {
538 self.dcx().emit_err(errors::ConstSelectMustBeFn { span, ty: arg_ty });
539 }
540 }
541 }
542
543 fn_sig.output()
544 }
545
546 fn suggest_call_as_method(
549 &self,
550 diag: &mut Diag<'_>,
551 segment: &'tcx hir::PathSegment<'tcx>,
552 arg_exprs: &'tcx [hir::Expr<'tcx>],
553 call_expr: &'tcx hir::Expr<'tcx>,
554 expected: Expectation<'tcx>,
555 ) {
556 if let [callee_expr, rest @ ..] = arg_exprs {
557 let Some(callee_ty) = self.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr)
558 else {
559 return;
560 };
561
562 let Ok(pick) = self.lookup_probe_for_diagnostic(
566 segment.ident,
567 callee_ty,
568 call_expr,
569 ProbeScope::AllTraits,
572 expected.only_has_type(self),
573 ) else {
574 return;
575 };
576
577 let pick = self.confirm_method_for_diagnostic(
578 call_expr.span,
579 callee_expr,
580 call_expr,
581 callee_ty,
582 &pick,
583 segment,
584 );
585 if pick.illegal_sized_bound.is_some() {
586 return;
587 }
588
589 let Some(callee_expr_span) = callee_expr.span.find_ancestor_inside(call_expr.span)
590 else {
591 return;
592 };
593 let up_to_rcvr_span = segment.ident.span.until(callee_expr_span);
594 let rest_span = callee_expr_span.shrink_to_hi().to(call_expr.span.shrink_to_hi());
595 let rest_snippet = if let Some(first) = rest.first() {
596 self.tcx
597 .sess
598 .source_map()
599 .span_to_snippet(first.span.to(call_expr.span.shrink_to_hi()))
600 } else {
601 Ok(")".to_string())
602 };
603
604 if let Ok(rest_snippet) = rest_snippet {
605 let sugg = if callee_expr.precedence() >= ExprPrecedence::Unambiguous {
606 vec![
607 (up_to_rcvr_span, "".to_string()),
608 (rest_span, format!(".{}({rest_snippet}", segment.ident)),
609 ]
610 } else {
611 vec![
612 (up_to_rcvr_span, "(".to_string()),
613 (rest_span, format!(").{}({rest_snippet}", segment.ident)),
614 ]
615 };
616 let self_ty = self.resolve_vars_if_possible(pick.callee.sig.inputs()[0]);
617 diag.multipart_suggestion(
618 format!(
619 "use the `.` operator to call the method `{}{}` on `{self_ty}`",
620 self.tcx
621 .associated_item(pick.callee.def_id)
622 .trait_container(self.tcx)
623 .map_or_else(
624 || String::new(),
625 |trait_def_id| self.tcx.def_path_str(trait_def_id) + "::"
626 ),
627 segment.ident
628 ),
629 sugg,
630 Applicability::MaybeIncorrect,
631 );
632 }
633 }
634 }
635
636 fn report_invalid_callee(
637 &self,
638 call_expr: &'tcx hir::Expr<'tcx>,
639 callee_expr: &'tcx hir::Expr<'tcx>,
640 callee_ty: Ty<'tcx>,
641 arg_exprs: &'tcx [hir::Expr<'tcx>],
642 ) -> ErrorGuaranteed {
643 if let Some((_, _, args)) = self.extract_callable_info(callee_ty)
646 && let Err(err) = args.error_reported()
647 {
648 return err;
649 }
650
651 let mut unit_variant = None;
652 if let hir::ExprKind::Path(qpath) = &callee_expr.kind
653 && let Res::Def(def::DefKind::Ctor(kind, CtorKind::Const), _)
654 = self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id)
655 && arg_exprs.is_empty()
657 && call_expr.span.contains(callee_expr.span)
658 {
659 let descr = match kind {
660 def::CtorOf::Struct => "struct",
661 def::CtorOf::Variant => "enum variant",
662 };
663 let removal_span = callee_expr.span.shrink_to_hi().to(call_expr.span.shrink_to_hi());
664 unit_variant =
665 Some((removal_span, descr, rustc_hir_pretty::qpath_to_string(&self.tcx, qpath)));
666 }
667
668 let callee_ty = self.resolve_vars_if_possible(callee_ty);
669 let mut path = None;
670 let mut err = self.dcx().create_err(errors::InvalidCallee {
671 span: callee_expr.span,
672 ty: callee_ty,
673 found: match &unit_variant {
674 Some((_, kind, path)) => format!("{kind} `{path}`"),
675 None => format!("`{}`", self.tcx.short_string(callee_ty, &mut path)),
676 },
677 });
678 *err.long_ty_path() = path;
679 if callee_ty.references_error() {
680 err.downgrade_to_delayed_bug();
681 }
682
683 self.identify_bad_closure_def_and_call(
684 &mut err,
685 call_expr.hir_id,
686 &callee_expr.kind,
687 callee_expr.span,
688 );
689
690 if let Some((removal_span, kind, path)) = &unit_variant {
691 err.span_suggestion_verbose(
692 *removal_span,
693 format!(
694 "`{path}` is a unit {kind}, and does not take parentheses to be constructed",
695 ),
696 "",
697 Applicability::MachineApplicable,
698 );
699 }
700
701 if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = callee_expr.kind
702 && let Res::Local(_) = path.res
703 && let [segment] = &path.segments
704 {
705 for id in self.tcx.hir_free_items() {
706 if let Some(node) = self.tcx.hir_get_if_local(id.owner_id.into())
707 && let hir::Node::Item(item) = node
708 && let hir::ItemKind::Fn { ident, .. } = item.kind
709 && ident.name == segment.ident.name
710 {
711 err.span_label(
712 self.tcx.def_span(id.owner_id),
713 "this function of the same name is available here, but it's shadowed by \
714 the local binding",
715 );
716 }
717 }
718 }
719
720 let mut inner_callee_path = None;
721 let def = match callee_expr.kind {
722 hir::ExprKind::Path(ref qpath) => {
723 self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id)
724 }
725 hir::ExprKind::Call(inner_callee, _) => {
726 if let hir::ExprKind::Path(ref inner_qpath) = inner_callee.kind {
727 inner_callee_path = Some(inner_qpath);
728 self.typeck_results.borrow().qpath_res(inner_qpath, inner_callee.hir_id)
729 } else {
730 Res::Err
731 }
732 }
733 _ => Res::Err,
734 };
735
736 if !self.maybe_suggest_bad_array_definition(&mut err, call_expr, callee_expr) {
737 let call_is_multiline = self
741 .tcx
742 .sess
743 .source_map()
744 .is_multiline(call_expr.span.with_lo(callee_expr.span.hi()))
745 && call_expr.span.eq_ctxt(callee_expr.span);
746 if call_is_multiline {
747 err.span_suggestion(
748 callee_expr.span.shrink_to_hi(),
749 "consider using a semicolon here to finish the statement",
750 ";",
751 Applicability::MaybeIncorrect,
752 );
753 }
754 if let Some((maybe_def, output_ty, _)) = self.extract_callable_info(callee_ty)
755 && !self.type_is_sized_modulo_regions(self.param_env, output_ty)
756 {
757 let descr = match maybe_def {
758 DefIdOrName::DefId(def_id) => self.tcx.def_descr(def_id),
759 DefIdOrName::Name(name) => name,
760 };
761 err.span_label(
762 callee_expr.span,
763 format!("this {descr} returns an unsized value `{output_ty}`, so it cannot be called")
764 );
765 if let DefIdOrName::DefId(def_id) = maybe_def
766 && let Some(def_span) = self.tcx.hir_span_if_local(def_id)
767 {
768 err.span_label(def_span, "the callable type is defined here");
769 }
770 } else {
771 err.span_label(call_expr.span, "call expression requires function");
772 }
773 }
774
775 if let Some(span) = self.tcx.hir_res_span(def) {
776 let callee_ty = callee_ty.to_string();
777 let label = match (unit_variant, inner_callee_path) {
778 (Some((_, kind, path)), _) => {
779 err.arg("kind", kind);
780 err.arg("path", path);
781 Some(fluent_generated::hir_typeck_invalid_defined_kind)
782 }
783 (_, Some(hir::QPath::Resolved(_, path))) => {
784 self.tcx.sess.source_map().span_to_snippet(path.span).ok().map(|p| {
785 err.arg("func", p);
786 fluent_generated::hir_typeck_invalid_fn_defined
787 })
788 }
789 _ => {
790 match def {
791 Res::Local(hir_id) => {
794 err.arg("local_name", self.tcx.hir_name(hir_id));
795 Some(fluent_generated::hir_typeck_invalid_local)
796 }
797 Res::Def(kind, def_id) if kind.ns() == Some(Namespace::ValueNS) => {
798 err.arg("path", self.tcx.def_path_str(def_id));
799 Some(fluent_generated::hir_typeck_invalid_defined)
800 }
801 _ => {
802 err.arg("path", callee_ty);
803 Some(fluent_generated::hir_typeck_invalid_defined)
804 }
805 }
806 }
807 };
808 if let Some(label) = label {
809 err.span_label(span, label);
810 }
811 }
812 err.emit()
813 }
814
815 fn confirm_deferred_closure_call(
816 &self,
817 call_expr: &'tcx hir::Expr<'tcx>,
818 arg_exprs: &'tcx [hir::Expr<'tcx>],
819 expected: Expectation<'tcx>,
820 closure_def_id: LocalDefId,
821 fn_sig: ty::FnSig<'tcx>,
822 ) -> Ty<'tcx> {
823 self.check_argument_types(
828 call_expr.span,
829 call_expr,
830 fn_sig.inputs(),
831 fn_sig.output(),
832 expected,
833 arg_exprs,
834 fn_sig.c_variadic,
835 TupleArgumentsFlag::TupleArguments,
836 Some(closure_def_id.to_def_id()),
837 );
838
839 fn_sig.output()
840 }
841
842 #[tracing::instrument(level = "debug", skip(self, span))]
843 pub(super) fn enforce_context_effects(
844 &self,
845 call_hir_id: Option<HirId>,
846 span: Span,
847 callee_did: DefId,
848 callee_args: GenericArgsRef<'tcx>,
849 ) {
850 if !self.tcx.features().const_trait_impl() {
855 return;
856 }
857
858 if self.tcx.has_attr(self.body_id, sym::rustc_do_not_const_check) {
860 return;
861 }
862
863 let host = match self.tcx.hir_body_const_context(self.body_id) {
864 Some(hir::ConstContext::Const { .. } | hir::ConstContext::Static(_)) => {
865 ty::BoundConstness::Const
866 }
867 Some(hir::ConstContext::ConstFn) => ty::BoundConstness::Maybe,
868 None => return,
869 };
870
871 if self.tcx.is_conditionally_const(callee_did) {
874 let q = self.tcx.const_conditions(callee_did);
875 for (idx, (cond, pred_span)) in
877 q.instantiate(self.tcx, callee_args).into_iter().enumerate()
878 {
879 let cause = self.cause(
880 span,
881 if let Some(hir_id) = call_hir_id {
882 ObligationCauseCode::HostEffectInExpr(callee_did, pred_span, hir_id, idx)
883 } else {
884 ObligationCauseCode::WhereClause(callee_did, pred_span)
885 },
886 );
887 self.register_predicate(Obligation::new(
888 self.tcx,
889 cause,
890 self.param_env,
891 cond.to_host_effect_clause(self.tcx, host),
892 ));
893 }
894 } else {
895 }
898 }
899
900 fn confirm_overloaded_call(
901 &self,
902 call_expr: &'tcx hir::Expr<'tcx>,
903 arg_exprs: &'tcx [hir::Expr<'tcx>],
904 expected: Expectation<'tcx>,
905 method: MethodCallee<'tcx>,
906 ) -> Ty<'tcx> {
907 self.check_argument_types(
908 call_expr.span,
909 call_expr,
910 &method.sig.inputs()[1..],
911 method.sig.output(),
912 expected,
913 arg_exprs,
914 method.sig.c_variadic,
915 TupleArgumentsFlag::TupleArguments,
916 Some(method.def_id),
917 );
918
919 self.write_method_call_and_enforce_effects(call_expr.hir_id, call_expr.span, method);
920
921 method.sig.output()
922 }
923}
924
925#[derive(Debug)]
926pub(crate) struct DeferredCallResolution<'tcx> {
927 call_expr: &'tcx hir::Expr<'tcx>,
928 callee_expr: &'tcx hir::Expr<'tcx>,
929 closure_ty: Ty<'tcx>,
930 adjustments: Vec<Adjustment<'tcx>>,
931 fn_sig: ty::FnSig<'tcx>,
932}
933
934impl<'a, 'tcx> DeferredCallResolution<'tcx> {
935 pub(crate) fn resolve(self, fcx: &FnCtxt<'a, 'tcx>) {
936 debug!("DeferredCallResolution::resolve() {:?}", self);
937
938 assert!(fcx.closure_kind(self.closure_ty).is_some());
941
942 match fcx.try_overloaded_call_traits(self.call_expr, self.closure_ty, None) {
944 Some((autoref, method_callee)) => {
945 let method_sig = method_callee.sig;
954
955 debug!("attempt_resolution: method_callee={:?}", method_callee);
956
957 for (method_arg_ty, self_arg_ty) in
958 iter::zip(method_sig.inputs().iter().skip(1), self.fn_sig.inputs())
959 {
960 fcx.demand_eqtype(self.call_expr.span, *self_arg_ty, *method_arg_ty);
961 }
962
963 fcx.demand_eqtype(self.call_expr.span, method_sig.output(), self.fn_sig.output());
964
965 let mut adjustments = self.adjustments;
966 adjustments.extend(autoref);
967 fcx.apply_adjustments(self.callee_expr, adjustments);
968
969 fcx.write_method_call_and_enforce_effects(
970 self.call_expr.hir_id,
971 self.call_expr.span,
972 method_callee,
973 );
974 }
975 None => {
976 span_bug!(
977 self.call_expr.span,
978 "Expected to find a suitable `Fn`/`FnMut`/`FnOnce` implementation for `{}`",
979 self.closure_ty
980 )
981 }
982 }
983 }
984}