From d4e4e374e76b3769207347a81e64b26b6a2b657f Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 3 Oct 2018 10:07:16 -0400 Subject: [PATCH] apply minimum bounds when checking closure signature Required for test expect-fn-supply-fn.rs to pass; otherwise we have unconstrained inference variables that get inferred to `'empty`. --- src/librustc/traits/select.rs | 6 ++++++ src/librustc_typeck/check/closure.rs | 30 +++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 2ea16823cc65..cdc7e3656d4d 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -3666,8 +3666,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { closure_def_id: DefId, substs: ty::ClosureSubsts<'tcx>, ) -> ty::PolyTraitRef<'tcx> { + debug!( + "closure_trait_ref_unnormalized(obligation={:?}, closure_def_id={:?}, substs={:?})", + obligation, closure_def_id, substs, + ); let closure_type = self.infcx.closure_sig(closure_def_id, substs); + debug!("closure_trait_ref_unnormalized: closure_type = {:?}", closure_type); + // (1) Feels icky to skip the binder here, but OTOH we know // that the self-type is an unboxed closure type and hence is // in fact unparameterized (or at least does not reference any diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 3f4d187813d5..fb7c237a536b 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -13,10 +13,12 @@ use super::{check_fn, Expectation, FnCtxt, GeneratorTypes}; use astconv::AstConv; +use middle::region; use rustc::hir::def_id::DefId; use rustc::infer::{InferOk, InferResult}; use rustc::infer::LateBoundRegionConversionTime; use rustc::infer::type_variable::TypeVariableOrigin; +use rustc::traits::Obligation; use rustc::traits::error_reporting::ArgKind; use rustc::ty::{self, ToPolyTraitRef, Ty, GenericParamDefKind}; use rustc::ty::fold::TypeFoldable; @@ -479,7 +481,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Along the way, it also writes out entries for types that the user // wrote into our tables, which are then later used by the privacy // check. - match self.check_supplied_sig_against_expectation(expr_def_id, decl, &closure_sigs) { + match self.check_supplied_sig_against_expectation(expr_def_id, decl, body, &closure_sigs) { Ok(infer_ok) => self.register_infer_ok_obligations(infer_ok), Err(_) => return self.sig_of_closure_no_expectation(expr_def_id, decl, body), } @@ -523,6 +525,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { &self, expr_def_id: DefId, decl: &hir::FnDecl, + body: &hir::Body, expected_sigs: &ClosureSignatures<'tcx>, ) -> InferResult<'tcx, ()> { // Get the signature S that the user gave. @@ -575,6 +578,31 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } = self.at(cause, self.param_env) .eq(*expected_ty, supplied_ty)?; all_obligations.extend(obligations); + + // Also, require that the supplied type must outlive + // the closure body. + let closure_body_region = self.tcx.mk_region( + ty::ReScope( + region::Scope { + id: body.value.hir_id.local_id, + data: region::ScopeData::Node, + }, + ), + ); + all_obligations.push( + Obligation::new( + cause.clone(), + self.param_env, + ty::Predicate::TypeOutlives( + ty::Binder::dummy( + ty::OutlivesPredicate( + supplied_ty, + closure_body_region, + ), + ), + ), + ), + ); } let (supplied_output_ty, _) = self.infcx.replace_late_bound_regions_with_fresh_var(