From 664c8ed301c8089e77775ac3a52d3f3d938e74d3 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 12 May 2019 17:12:49 +0100 Subject: [PATCH 1/3] Always use the stronger outlives version for opaque types --- src/librustc/infer/opaque_types/mod.rs | 34 +++++++++++++++---- .../can-return-unconstrained-closure.rs | 4 +++ .../issue-57464-unexpected-regions.rs | 7 ++++ 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index f85fd524a5d..6bf23ab864a 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -284,18 +284,40 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { debug!("constrain_opaque_type: def_id={:?}", def_id); debug!("constrain_opaque_type: opaque_defn={:#?}", opaque_defn); + let tcx = self.tcx; + let concrete_ty = self.resolve_type_vars_if_possible(&opaque_defn.concrete_ty); debug!("constrain_opaque_type: concrete_ty={:?}", concrete_ty); - let abstract_type_generics = self.tcx.generics_of(def_id); + let abstract_type_generics = tcx.generics_of(def_id); - let span = self.tcx.def_span(def_id); + let span = tcx.def_span(def_id); - // If there are required region bounds, we can just skip - // ahead. There will already be a registered region - // obligation related `concrete_ty` to those regions. + // If there are required region bounds, we can use them. if opaque_defn.has_required_region_bounds { + let predicates_of = tcx.predicates_of(def_id); + debug!( + "constrain_opaque_type: predicates: {:#?}", + predicates_of, + ); + let bounds = predicates_of.instantiate(tcx, opaque_defn.substs); + debug!("constrain_opaque_type: bounds={:#?}", bounds); + let opaque_type = tcx.mk_opaque(def_id, opaque_defn.substs); + + let required_region_bounds = tcx.required_region_bounds( + opaque_type, + bounds.predicates.clone(), + ); + debug_assert!(!required_region_bounds.is_empty()); + + for region in required_region_bounds { + concrete_ty.visit_with(&mut OpaqueTypeOutlivesVisitor { + infcx: self, + least_region: region, + span, + }); + } return; } @@ -371,7 +393,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } - let least_region = least_region.unwrap_or(self.tcx.lifetimes.re_static); + let least_region = least_region.unwrap_or(tcx.lifetimes.re_static); debug!("constrain_opaque_types: least_region={:?}", least_region); concrete_ty.visit_with(&mut OpaqueTypeOutlivesVisitor { diff --git a/src/test/ui/impl-trait/can-return-unconstrained-closure.rs b/src/test/ui/impl-trait/can-return-unconstrained-closure.rs index a982b176ecd..90a7519074b 100644 --- a/src/test/ui/impl-trait/can-return-unconstrained-closure.rs +++ b/src/test/ui/impl-trait/can-return-unconstrained-closure.rs @@ -16,4 +16,8 @@ fn make_identity() -> impl Sized { |x: &'static i32| x } +fn make_identity_static() -> impl Sized + 'static { + |x: &'static i32| x +} + fn main() {} diff --git a/src/test/ui/impl-trait/issue-57464-unexpected-regions.rs b/src/test/ui/impl-trait/issue-57464-unexpected-regions.rs index 29e271c68ec..11f1a392239 100644 --- a/src/test/ui/impl-trait/issue-57464-unexpected-regions.rs +++ b/src/test/ui/impl-trait/issue-57464-unexpected-regions.rs @@ -17,6 +17,13 @@ fn wrapped_closure() -> impl Sized { A(f) } +fn wrapped_closure_with_bound() -> impl Sized + 'static { + let f = |x| x; + f(&0); + A(f) +} + fn main() { let x: Box = Box::new(wrapped_closure()); + let y: Box = Box::new(wrapped_closure_with_bound()); } From 1f5145e2735083475d586f4a6a1a389a090f30e4 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 12 May 2019 17:52:33 +0100 Subject: [PATCH 2/3] Treat generators the same as closure for escaping lifetimes --- src/librustc/infer/opaque_types/mod.rs | 17 +++++++++++++++++ src/test/run-pass/impl-trait/lifetimes.rs | 6 ++++++ 2 files changed, 23 insertions(+) diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index 6bf23ab864a..a8dca9062bd 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -705,6 +705,23 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ReverseMapper<'cx, 'gcx, 'tcx> self.tcx.mk_closure(def_id, ty::ClosureSubsts { substs }) } + ty::Generator(def_id, substs, movability) => { + let generics = self.tcx.generics_of(def_id); + let substs = self.tcx.mk_substs(substs.substs.iter().enumerate().map( + |(index, &kind)| { + if index < generics.parent_count { + // Accommodate missing regions in the parent kinds... + self.fold_kind_mapping_missing_regions_to_empty(kind) + } else { + // ...but not elsewhere. + self.fold_kind_normally(kind) + } + }, + )); + + self.tcx.mk_generator(def_id, ty::GeneratorSubsts { substs }, movability) + } + _ => ty.super_fold_with(self), } } diff --git a/src/test/run-pass/impl-trait/lifetimes.rs b/src/test/run-pass/impl-trait/lifetimes.rs index 5a21e1dd817..9a9843375e4 100644 --- a/src/test/run-pass/impl-trait/lifetimes.rs +++ b/src/test/run-pass/impl-trait/lifetimes.rs @@ -1,6 +1,7 @@ // run-pass #![allow(warnings)] +#![feature(generators)] use std::fmt::Debug; @@ -112,6 +113,11 @@ impl<'unnecessary_lifetime> MyVec { fn iter_doesnt_capture_unnecessary_lifetime<'s>(&'s self) -> impl Iterator { self.0.iter().flat_map(|inner_vec| inner_vec.iter()) } + + fn generator_doesnt_capture_unnecessary_lifetime<'s: 's>() -> impl Sized { + || yield + } } + fn main() {} From 9a4f0abd7a385416acf9d93b9d77ea1fdf755f93 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 12 May 2019 18:51:40 +0100 Subject: [PATCH 3/3] Don't allow any ReScope in impl trait types This shouldn't be possible any more, but if it does happen, emit an error rather than maybe panicking later when NLL finds a the ReScope. Impl trait in bindings is sufficiently broken that I don't think this breaks anything that works for it. --- src/librustc/infer/opaque_types/mod.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index a8dca9062bd..4351f94df2f 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -611,10 +611,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ReverseMapper<'cx, 'gcx, 'tcx> ty::ReLateBound(..) | // ignore `'static`, as that can appear anywhere - ty::ReStatic | - - // ignore `ReScope`, which may appear in impl Trait in bindings. - ty::ReScope(..) => return r, + ty::ReStatic => return r, _ => { } }