about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2018-10-03 10:07:16 -0400
committerNiko Matsakis <niko@alum.mit.edu>2018-10-27 09:06:03 -0400
commitd4e4e374e76b3769207347a81e64b26b6a2b657f (patch)
treef7543ec2f1a38fdd6f1379c7b8aa60446e5f98ba /src
parentbf51840952b701606fa6aa5e076b4e27fb8d9ee8 (diff)
downloadrust-d4e4e374e76b3769207347a81e64b26b6a2b657f.tar.gz
rust-d4e4e374e76b3769207347a81e64b26b6a2b657f.zip
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`.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/traits/select.rs6
-rw-r--r--src/librustc_typeck/check/closure.rs30
2 files changed, 35 insertions, 1 deletions
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 2ea16823cc6..cdc7e3656d4 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 3f4d187813d..fb7c237a536 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(