From 4e8199b572f2035b7749cba276ece3a26630d23e Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:18:21 +0200 Subject: Adding upstream version 1.67.1+dfsg1. Signed-off-by: Daniel Baumann --- compiler/rustc_hir_typeck/src/closure.rs | 250 ++++++++++++++----------------- 1 file changed, 115 insertions(+), 135 deletions(-) (limited to 'compiler/rustc_hir_typeck/src/closure.rs') diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index a5a45f75e..429cb60ba 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -4,24 +4,26 @@ use super::{check_fn, Expectation, FnCtxt, GeneratorTypes}; use hir::def::DefKind; use rustc_hir as hir; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::LocalDefId; use rustc_hir::lang_items::LangItem; use rustc_hir_analysis::astconv::AstConv; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_infer::infer::{InferOk, InferResult}; +use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{self, Ty}; use rustc_span::source_map::Span; use rustc_target::spec::abi::Abi; +use rustc_trait_selection::traits; use rustc_trait_selection::traits::error_reporting::ArgKind; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; use std::cmp; use std::iter; /// What signature do we *expect* the closure to have from context? -#[derive(Debug)] +#[derive(Debug, Clone, TypeFoldable, TypeVisitable)] struct ExpectedSig<'tcx> { /// Span that gave us this expectation, if we know that. cause_span: Option, @@ -33,24 +35,20 @@ struct ClosureSignatures<'tcx> { bound_sig: ty::PolyFnSig<'tcx>, /// The signature within the function body. /// This mostly differs in the sense that lifetimes are now early bound and any - /// opaque types from the signature expectation are overriden in case there are + /// opaque types from the signature expectation are overridden in case there are /// explicit hidden types written by the user in the closure signature. liberated_sig: ty::FnSig<'tcx>, } impl<'a, 'tcx> FnCtxt<'a, 'tcx> { - #[instrument(skip(self, expr, _capture, decl, body_id), level = "debug")] + #[instrument(skip(self, closure), level = "debug")] pub fn check_expr_closure( &self, - expr: &hir::Expr<'_>, - _capture: hir::CaptureBy, - decl: &'tcx hir::FnDecl<'tcx>, - body_id: hir::BodyId, - gen: Option, + closure: &hir::Closure<'tcx>, + expr_span: Span, expected: Expectation<'tcx>, ) -> Ty<'tcx> { - trace!("decl = {:#?}", decl); - trace!("expr = {:#?}", expr); + trace!("decl = {:#?}", closure.fn_decl); // It's always helpful for inference if we know the kind of // closure sooner rather than later, so first examine the expected @@ -59,42 +57,37 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(ty) => self.deduce_expectations_from_expected_type(ty), None => (None, None), }; - let body = self.tcx.hir().body(body_id); - self.check_closure(expr, expected_kind, decl, body, gen, expected_sig) + let body = self.tcx.hir().body(closure.body); + self.check_closure(closure, expr_span, expected_kind, body, expected_sig) } - #[instrument(skip(self, expr, body, decl), level = "debug", ret)] + #[instrument(skip(self, closure, body), level = "debug", ret)] fn check_closure( &self, - expr: &hir::Expr<'_>, + closure: &hir::Closure<'tcx>, + expr_span: Span, opt_kind: Option, - decl: &'tcx hir::FnDecl<'tcx>, body: &'tcx hir::Body<'tcx>, - gen: Option, expected_sig: Option>, ) -> Ty<'tcx> { - trace!("decl = {:#?}", decl); - let expr_def_id = self.tcx.hir().local_def_id(expr.hir_id); + trace!("decl = {:#?}", closure.fn_decl); + let expr_def_id = closure.def_id; debug!(?expr_def_id); let ClosureSignatures { bound_sig, liberated_sig } = - self.sig_of_closure(expr.hir_id, expr_def_id.to_def_id(), decl, body, expected_sig); + self.sig_of_closure(expr_def_id, closure.fn_decl, body, expected_sig); debug!(?bound_sig, ?liberated_sig); - let return_type_pre_known = !liberated_sig.output().is_ty_infer(); - + let mut fcx = FnCtxt::new(self, self.param_env.without_const(), body.value.hir_id); let generator_types = check_fn( - self, - self.param_env.without_const(), + &mut fcx, liberated_sig, - decl, - expr.hir_id, + closure.fn_decl, + expr_def_id, body, - gen, - return_type_pre_known, - ) - .1; + closure.movability, + ); let parent_substs = InternalSubsts::identity_for_item( self.tcx, @@ -103,7 +96,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let tupled_upvars_ty = self.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::ClosureSynthetic, - span: self.tcx.hir().span(expr.hir_id), + span: self.tcx.def_span(expr_def_id), }); if let Some(GeneratorTypes { resume_ty, yield_ty, interior, movability }) = generator_types @@ -149,7 +142,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None => self.next_ty_var(TypeVariableOrigin { // FIXME(eddyb) distinguish closure kind inference variables from the rest. kind: TypeVariableOriginKind::ClosureSynthetic, - span: expr.span, + span: expr_span, }), }; @@ -174,34 +167,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected_ty: Ty<'tcx>, ) -> (Option>, Option) { match *expected_ty.kind() { - ty::Opaque(def_id, substs) => { - let bounds = self.tcx.bound_explicit_item_bounds(def_id); - let sig = - bounds.subst_iter_copied(self.tcx, substs).find_map(|(pred, span)| match pred - .kind() - .skip_binder() - { - ty::PredicateKind::Projection(proj_predicate) => self - .deduce_sig_from_projection( - Some(span), - pred.kind().rebind(proj_predicate), - ), - _ => None, - }); - - let kind = bounds - .0 - .iter() - .filter_map(|(pred, _)| match pred.kind().skip_binder() { - ty::PredicateKind::Trait(tp) => { - self.tcx.fn_trait_kind_from_lang_item(tp.def_id()) - } - _ => None, - }) - .fold(None, |best, cur| Some(best.map_or(cur, |best| cmp::min(best, cur)))); - trace!(?sig, ?kind); - (sig, kind) - } + ty::Opaque(def_id, substs) => self.deduce_signature_from_predicates( + self.tcx.bound_explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs), + ), ty::Dynamic(ref object_type, ..) => { let sig = object_type.projection_bounds().find_map(|pb| { let pb = pb.with_self_ty(self.tcx, self.tcx.types.trait_object_dummy_self); @@ -209,10 +177,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }); let kind = object_type .principal_def_id() - .and_then(|did| self.tcx.fn_trait_kind_from_lang_item(did)); + .and_then(|did| self.tcx.fn_trait_kind_from_def_id(did)); (sig, kind) } - ty::Infer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid), + ty::Infer(ty::TyVar(vid)) => self.deduce_signature_from_predicates( + self.obligations_for_self_ty(vid).map(|obl| (obl.predicate, obl.cause.span)), + ), ty::FnPtr(sig) => { let expected_sig = ExpectedSig { cause_span: None, sig }; (Some(expected_sig), Some(ty::ClosureKind::Fn)) @@ -221,37 +191,57 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn deduce_expectations_from_obligations( + fn deduce_signature_from_predicates( &self, - expected_vid: ty::TyVid, + predicates: impl DoubleEndedIterator, Span)>, ) -> (Option>, Option) { - let expected_sig = - self.obligations_for_self_ty(expected_vid).find_map(|(_, obligation)| { - debug!(?obligation.predicate); - - let bound_predicate = obligation.predicate.kind(); - if let ty::PredicateKind::Projection(proj_predicate) = - obligation.predicate.kind().skip_binder() - { - // Given a Projection predicate, we can potentially infer - // the complete signature. + let mut expected_sig = None; + let mut expected_kind = None; + + for obligation in traits::elaborate_predicates_with_span( + self.tcx, + // Reverse the obligations here, since `elaborate_*` uses a stack, + // and we want to keep inference generally in the same order of + // the registered obligations. + predicates.rev(), + ) { + debug!(?obligation.predicate); + let bound_predicate = obligation.predicate.kind(); + + // Given a Projection predicate, we can potentially infer + // the complete signature. + if expected_sig.is_none() + && let ty::PredicateKind::Clause(ty::Clause::Projection(proj_predicate)) = bound_predicate.skip_binder() + { + expected_sig = self.normalize( + obligation.cause.span, self.deduce_sig_from_projection( - Some(obligation.cause.span), + Some(obligation.cause.span), bound_predicate.rebind(proj_predicate), - ) - } else { - None - } - }); + ), + ); + } - // Even if we can't infer the full signature, we may be able to - // infer the kind. This can occur when we elaborate a predicate - // like `F : Fn`. Note that due to subtyping we could encounter - // many viable options, so pick the most restrictive. - let expected_kind = self - .obligations_for_self_ty(expected_vid) - .filter_map(|(tr, _)| self.tcx.fn_trait_kind_from_lang_item(tr.def_id())) - .fold(None, |best, cur| Some(best.map_or(cur, |best| cmp::min(best, cur)))); + // Even if we can't infer the full signature, we may be able to + // infer the kind. This can occur when we elaborate a predicate + // like `F : Fn`. Note that due to subtyping we could encounter + // many viable options, so pick the most restrictive. + let trait_def_id = match bound_predicate.skip_binder() { + ty::PredicateKind::Clause(ty::Clause::Projection(data)) => { + Some(data.projection_ty.trait_def_id(self.tcx)) + } + ty::PredicateKind::Clause(ty::Clause::Trait(data)) => Some(data.def_id()), + _ => None, + }; + if let Some(closure_kind) = + trait_def_id.and_then(|def_id| self.tcx.fn_trait_kind_from_def_id(def_id)) + { + expected_kind = Some( + expected_kind + .map_or_else(|| closure_kind, |current| cmp::min(current, closure_kind)), + ); + } + } (expected_sig, expected_kind) } @@ -272,7 +262,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let trait_def_id = projection.trait_def_id(tcx); - let is_fn = tcx.fn_trait_kind_from_lang_item(trait_def_id).is_some(); + let is_fn = tcx.is_fn_trait(trait_def_id); let gen_trait = tcx.require_lang_item(LangItem::Generator, cause_span); let is_gen = gen_trait == trait_def_id; if !is_fn && !is_gen { @@ -323,30 +313,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn sig_of_closure( &self, - hir_id: hir::HirId, - expr_def_id: DefId, + expr_def_id: LocalDefId, decl: &hir::FnDecl<'_>, body: &hir::Body<'_>, expected_sig: Option>, ) -> ClosureSignatures<'tcx> { if let Some(e) = expected_sig { - self.sig_of_closure_with_expectation(hir_id, expr_def_id, decl, body, e) + self.sig_of_closure_with_expectation(expr_def_id, decl, body, e) } else { - self.sig_of_closure_no_expectation(hir_id, expr_def_id, decl, body) + self.sig_of_closure_no_expectation(expr_def_id, decl, body) } } /// If there is no expected signature, then we will convert the /// types that the user gave into a signature. - #[instrument(skip(self, hir_id, expr_def_id, decl, body), level = "debug")] + #[instrument(skip(self, expr_def_id, decl, body), level = "debug")] fn sig_of_closure_no_expectation( &self, - hir_id: hir::HirId, - expr_def_id: DefId, + expr_def_id: LocalDefId, decl: &hir::FnDecl<'_>, body: &hir::Body<'_>, ) -> ClosureSignatures<'tcx> { - let bound_sig = self.supplied_sig_of_closure(hir_id, expr_def_id, decl, body); + let bound_sig = self.supplied_sig_of_closure(expr_def_id, decl, body); self.closure_sigs(expr_def_id, body, bound_sig) } @@ -392,17 +380,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// /// # Arguments /// - /// - `expr_def_id`: the `DefId` of the closure expression + /// - `expr_def_id`: the `LocalDefId` of the closure expression /// - `decl`: the HIR declaration of the closure /// - `body`: the body of the closure /// - `expected_sig`: the expected signature (if any). Note that /// this is missing a binder: that is, there may be late-bound /// regions with depth 1, which are bound then by the closure. - #[instrument(skip(self, hir_id, expr_def_id, decl, body), level = "debug")] + #[instrument(skip(self, expr_def_id, decl, body), level = "debug")] fn sig_of_closure_with_expectation( &self, - hir_id: hir::HirId, - expr_def_id: DefId, + expr_def_id: LocalDefId, decl: &hir::FnDecl<'_>, body: &hir::Body<'_>, expected_sig: ExpectedSig<'tcx>, @@ -411,7 +398,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // expectation if things don't see to match up with what we // expect. if expected_sig.sig.c_variadic() != decl.c_variadic { - return self.sig_of_closure_no_expectation(hir_id, expr_def_id, decl, body); + return self.sig_of_closure_no_expectation(expr_def_id, decl, body); } else if expected_sig.sig.skip_binder().inputs_and_output.len() != decl.inputs.len() + 1 { return self.sig_of_closure_with_mismatched_number_of_arguments( expr_def_id, @@ -447,27 +434,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Along the way, it also writes out entries for types that the user // wrote into our typeck results, which are then later used by the privacy // check. - match self.merge_supplied_sig_with_expectation( - hir_id, - expr_def_id, - decl, - body, - closure_sigs, - ) { + match self.merge_supplied_sig_with_expectation(expr_def_id, decl, body, closure_sigs) { Ok(infer_ok) => self.register_infer_ok_obligations(infer_ok), - Err(_) => self.sig_of_closure_no_expectation(hir_id, expr_def_id, decl, body), + Err(_) => self.sig_of_closure_no_expectation(expr_def_id, decl, body), } } fn sig_of_closure_with_mismatched_number_of_arguments( &self, - expr_def_id: DefId, + expr_def_id: LocalDefId, decl: &hir::FnDecl<'_>, body: &hir::Body<'_>, expected_sig: ExpectedSig<'tcx>, ) -> ClosureSignatures<'tcx> { let hir = self.tcx.hir(); - let expr_map_node = hir.get_if_local(expr_def_id).unwrap(); + let expr_map_node = hir.get_by_def_id(expr_def_id); let expected_args: Vec<_> = expected_sig .sig .skip_binder() @@ -475,18 +456,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .iter() .map(|ty| ArgKind::from_expected_ty(*ty, None)) .collect(); - let (closure_span, found_args) = match self.get_fn_like_arguments(expr_map_node) { - Some((sp, args)) => (Some(sp), args), - None => (None, Vec::new()), - }; + let (closure_span, closure_arg_span, found_args) = + match self.get_fn_like_arguments(expr_map_node) { + Some((sp, arg_sp, args)) => (Some(sp), arg_sp, args), + None => (None, None, Vec::new()), + }; let expected_span = - expected_sig.cause_span.unwrap_or_else(|| hir.span_if_local(expr_def_id).unwrap()); + expected_sig.cause_span.unwrap_or_else(|| self.tcx.def_span(expr_def_id)); self.report_arg_count_mismatch( expected_span, closure_span, expected_args, found_args, true, + closure_arg_span, ) .emit(); @@ -498,11 +481,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Enforce the user's types against the expectation. See /// `sig_of_closure_with_expectation` for details on the overall /// strategy. - #[instrument(level = "debug", skip(self, hir_id, expr_def_id, decl, body, expected_sigs))] + #[instrument(level = "debug", skip(self, expr_def_id, decl, body, expected_sigs))] fn merge_supplied_sig_with_expectation( &self, - hir_id: hir::HirId, - expr_def_id: DefId, + expr_def_id: LocalDefId, decl: &hir::FnDecl<'_>, body: &hir::Body<'_>, mut expected_sigs: ClosureSignatures<'tcx>, @@ -511,7 +493,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // // (See comment on `sig_of_closure_with_expectation` for the // meaning of these letters.) - let supplied_sig = self.supplied_sig_of_closure(hir_id, expr_def_id, decl, body); + let supplied_sig = self.supplied_sig_of_closure(expr_def_id, decl, body); debug!(?supplied_sig); @@ -591,8 +573,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { #[instrument(skip(self, decl, body), level = "debug", ret)] fn supplied_sig_of_closure( &self, - hir_id: hir::HirId, - expr_def_id: DefId, + expr_def_id: LocalDefId, decl: &hir::FnDecl<'_>, body: &hir::Body<'_>, ) -> ty::PolyFnSig<'tcx> { @@ -601,6 +582,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { trace!("decl = {:#?}", decl); debug!(?body.generator_kind); + let hir_id = self.tcx.hir().local_def_id_to_hir_id(expr_def_id); let bound_vars = self.tcx.late_bound_vars(hir_id); // First, convert the types that the user supplied (if any). @@ -642,7 +624,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); // Astconv can't normalize inputs or outputs with escaping bound vars, // so normalize them here, after we've wrapped them in a binder. - let result = self.normalize_associated_types_in(self.tcx.hir().span(hir_id), result); + let result = self.normalize(self.tcx.hir().span(hir_id), result); let c_result = self.inh.infcx.canonicalize_response(result); self.typeck_results.borrow_mut().user_provided_sigs.insert(expr_def_id, c_result); @@ -659,7 +641,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { #[instrument(skip(self), level = "debug", ret)] fn deduce_future_output_from_obligations( &self, - expr_def_id: DefId, + expr_def_id: LocalDefId, body_id: hir::HirId, ) -> Option> { let ret_coercion = self.ret_coercion.as_ref().unwrap_or_else(|| { @@ -677,7 +659,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // where R is the return type we are expecting. This type `T` // will be our output. let bound_predicate = predicate.kind(); - if let ty::PredicateKind::Projection(proj_predicate) = bound_predicate.skip_binder() { + if let ty::PredicateKind::Clause(ty::Clause::Projection(proj_predicate)) = + bound_predicate.skip_binder() + { self.deduce_future_output_from_projection( span, bound_predicate.rebind(proj_predicate), @@ -689,7 +673,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let output_ty = match *ret_ty.kind() { ty::Infer(ty::TyVar(ret_vid)) => { - self.obligations_for_self_ty(ret_vid).find_map(|(_, obligation)| { + self.obligations_for_self_ty(ret_vid).find_map(|obligation| { get_future_output(obligation.predicate, obligation.cause.span) })? } @@ -808,17 +792,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn closure_sigs( &self, - expr_def_id: DefId, + expr_def_id: LocalDefId, body: &hir::Body<'_>, bound_sig: ty::PolyFnSig<'tcx>, ) -> ClosureSignatures<'tcx> { - let liberated_sig = self.tcx().liberate_late_bound_regions(expr_def_id, bound_sig); - let liberated_sig = self.inh.normalize_associated_types_in( - body.value.span, - body.value.hir_id, - self.param_env, - liberated_sig, - ); + let liberated_sig = + self.tcx().liberate_late_bound_regions(expr_def_id.to_def_id(), bound_sig); + let liberated_sig = self.normalize(body.value.span, liberated_sig); ClosureSignatures { bound_sig, liberated_sig } } } -- cgit v1.2.3