]> git.proxmox.com Git - rustc.git/blobdiff - compiler/rustc_typeck/src/check/callee.rs
New upstream version 1.64.0+dfsg1
[rustc.git] / compiler / rustc_typeck / src / check / callee.rs
index 83a8c5ea0219131336adbd3a13d7ee8790c296ec..75f5aced85577ad2209fcd508d918acff5799dce 100644 (file)
@@ -4,8 +4,8 @@ use crate::type_error_struct;
 
 use rustc_errors::{struct_span_err, Applicability, Diagnostic};
 use rustc_hir as hir;
-use rustc_hir::def::{Namespace, Res};
-use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::def::{self, Namespace, Res};
+use rustc_hir::def_id::DefId;
 use rustc_infer::{
     infer,
     traits::{self, Obligation},
@@ -18,12 +18,14 @@ use rustc_middle::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability,
 };
 use rustc_middle::ty::subst::{Subst, SubstsRef};
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable};
+use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::Span;
 use rustc_target::spec::abi;
 use rustc_trait_selection::autoderef::Autoderef;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
+
 use std::iter;
 
 /// Checks that it is legal to call methods of the trait corresponding
@@ -59,7 +61,7 @@ pub fn check_legal_trait_for_method_call(
 
 enum CallStep<'tcx> {
     Builtin(Ty<'tcx>),
-    DeferredClosure(DefId, ty::FnSig<'tcx>),
+    DeferredClosure(LocalDefId, ty::FnSig<'tcx>),
     /// E.g., enum variant constructors.
     Overloaded(MethodCallee<'tcx>),
 }
@@ -117,7 +119,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
 
         // we must check that return type of called functions is WF:
-        self.register_wf_obligation(output.into(), call_expr.span, traits::MiscObligation);
+        self.register_wf_obligation(output.into(), call_expr.span, traits::WellFormed(None));
 
         output
     }
@@ -145,7 +147,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
 
             ty::Closure(def_id, substs) => {
-                assert_eq!(def_id.krate, LOCAL_CRATE);
+                let def_id = def_id.expect_local();
 
                 // Check whether this is a call to a closure where we
                 // haven't yet decided on whether the closure is fn vs
@@ -280,15 +282,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         callee_node: &hir::ExprKind<'_>,
         callee_span: Span,
     ) {
-        let hir_id = self.tcx.hir().get_parent_node(hir_id);
-        let parent_node = self.tcx.hir().get(hir_id);
+        let hir = self.tcx.hir();
+        let parent_hir_id = hir.get_parent_node(hir_id);
+        let parent_node = hir.get(parent_hir_id);
         if let (
             hir::Node::Expr(hir::Expr {
-                kind: hir::ExprKind::Closure { fn_decl_span, .. }, ..
+                kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, body, .. }),
+                ..
             }),
             hir::ExprKind::Block(..),
         ) = (parent_node, callee_node)
         {
+            let fn_decl_span = if hir.body(body).generator_kind
+                == Some(hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure))
+            {
+                // Actually need to unwrap a few more layers of HIR to get to
+                // the _real_ closure...
+                let async_closure = hir.get_parent_node(hir.get_parent_node(parent_hir_id));
+                if let hir::Node::Expr(hir::Expr {
+                    kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }),
+                    ..
+                }) = hir.get(async_closure)
+                {
+                    fn_decl_span
+                } else {
+                    return;
+                }
+            } else {
+                fn_decl_span
+            };
+
             let start = fn_decl_span.shrink_to_lo();
             let end = callee_span.shrink_to_hi();
             err.multipart_suggestion(
@@ -355,7 +378,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             self.param_env,
                             *predicate,
                         );
-                        let result = self.infcx.evaluate_obligation(&obligation);
+                        let result = self.evaluate_obligation(&obligation);
                         self.tcx
                             .sess
                             .struct_span_err(
@@ -369,17 +392,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 (fn_sig, Some(def_id))
             }
             ty::FnPtr(sig) => (sig, None),
-            ref t => {
+            _ => {
                 let mut unit_variant = None;
-                let mut removal_span = call_expr.span;
-                if let ty::Adt(adt_def, ..) = t
-                    && adt_def.is_enum()
-                    && let hir::ExprKind::Call(expr, _) = call_expr.kind
+                if let hir::ExprKind::Path(qpath) = &callee_expr.kind
+                    && let Res::Def(def::DefKind::Ctor(kind, def::CtorKind::Const), _)
+                        = self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id)
+                    // Only suggest removing parens if there are no arguments
+                    && arg_exprs.is_empty()
                 {
-                    removal_span =
-                        expr.span.shrink_to_hi().to(call_expr.span.shrink_to_hi());
+                    let descr = match kind {
+                        def::CtorOf::Struct => "struct",
+                        def::CtorOf::Variant => "enum variant",
+                    };
+                    let removal_span =
+                        callee_expr.span.shrink_to_hi().to(call_expr.span.shrink_to_hi());
                     unit_variant =
-                        self.tcx.sess.source_map().span_to_snippet(expr.span).ok();
+                        Some((removal_span, descr, rustc_hir_pretty::qpath_to_string(qpath)));
                 }
 
                 let callee_ty = self.resolve_vars_if_possible(callee_ty);
@@ -389,8 +417,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     callee_ty,
                     E0618,
                     "expected function, found {}",
-                    match unit_variant {
-                        Some(ref path) => format!("enum variant `{path}`"),
+                    match &unit_variant {
+                        Some((_, kind, path)) => format!("{kind} `{path}`"),
                         None => format!("`{callee_ty}`"),
                     }
                 );
@@ -402,11 +430,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     callee_expr.span,
                 );
 
-                if let Some(ref path) = unit_variant {
+                if let Some((removal_span, kind, path)) = &unit_variant {
                     err.span_suggestion_verbose(
-                        removal_span,
+                        *removal_span,
                         &format!(
-                            "`{path}` is a unit variant, you need to write it without the parentheses",
+                            "`{path}` is a unit {kind}, and does not take parentheses to be constructed",
                         ),
                         "",
                         Applicability::MachineApplicable,
@@ -449,7 +477,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 if let Some(span) = self.tcx.hir().res_span(def) {
                     let callee_ty = callee_ty.to_string();
                     let label = match (unit_variant, inner_callee_path) {
-                        (Some(path), _) => Some(format!("`{path}` defined here")),
+                        (Some((_, kind, path)), _) => Some(format!("{kind} `{path}` defined here")),
                         (_, Some(hir::QPath::Resolved(_, path))) => self
                             .tcx
                             .sess
@@ -532,7 +560,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         call_expr: &'tcx hir::Expr<'tcx>,
         arg_exprs: &'tcx [hir::Expr<'tcx>],
         expected: Expectation<'tcx>,
-        closure_def_id: DefId,
+        closure_def_id: LocalDefId,
         fn_sig: ty::FnSig<'tcx>,
     ) -> Ty<'tcx> {
         // `fn_sig` is the *signature* of the closure being called. We
@@ -555,7 +583,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             arg_exprs,
             fn_sig.c_variadic,
             TupleArgumentsFlag::TupleArguments,
-            Some(closure_def_id),
+            Some(closure_def_id.to_def_id()),
         );
 
         fn_sig.output()