Skip to content

Commit 42351b4

Browse files
committed
Use impl Trait lifetime bounds in regionck
If the user explicitly provides lifetime bounds on an impl Trait return type, it's not necessary to search for or require a least region. This change uses the required region bounds of the impl Trait predicates to directly apply lifetime bounds and skip least region searching where possible.
1 parent 5125bfd commit 42351b4

File tree

2 files changed

+28
-15
lines changed

2 files changed

+28
-15
lines changed

src/librustc_typeck/check/mod.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,10 @@ struct AnonTypeDecl<'tcx> {
255255
/// other words, `?C` should not include `'b`, even though it's a
256256
/// lifetime parameter on `foo`.)
257257
concrete_ty: Ty<'tcx>,
258+
259+
/// A list of all required region bounds on the impl Trait type,
260+
/// e.g. `'a` and `'b` in `fn foo<'a, 'b, 'c>() -> impl Trait<'c> + 'a + 'b`.
261+
required_region_bounds: Vec<ty::Region<'tcx>>,
258262
}
259263

260264
impl<'a, 'gcx, 'tcx> Deref for Inherited<'a, 'gcx, 'tcx> {
@@ -1983,16 +1987,23 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
19831987
}
19841988
let span = self.tcx.def_span(def_id);
19851989
let ty_var = self.next_ty_var(TypeVariableOrigin::TypeInference(span));
1986-
self.anon_types.borrow_mut().insert(def_id, AnonTypeDecl {
1987-
substs: substs,
1988-
concrete_ty: ty_var
1989-
});
1990-
debug!("instantiate_anon_types: ty_var={:?}", ty_var);
19911990

19921991
let predicates_of = self.tcx.predicates_of(def_id);
19931992
debug!("instantiate_anon_types: predicates_of={:?}", predicates_of);
19941993
let bounds = predicates_of.instantiate(self.tcx, substs);
19951994

1995+
let required_region_bounds =
1996+
self.tcx.required_region_bounds(ty, bounds.predicates.clone());
1997+
debug!("instantiate_anon_types: required_region_bounds={:?}",
1998+
required_region_bounds);
1999+
2000+
self.anon_types.borrow_mut().insert(def_id, AnonTypeDecl {
2001+
substs,
2002+
concrete_ty: ty_var,
2003+
required_region_bounds,
2004+
});
2005+
debug!("instantiate_anon_types: ty_var={:?}", ty_var);
2006+
19962007
for predicate in bounds.predicates {
19972008
// Change the predicate to refer to the type variable,
19982009
// which will be the concrete type, instead of the TyAnon.

src/librustc_typeck/check/regionck.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -153,14 +153,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
153153
let node_id = body.value.id;
154154
let mut rcx = RegionCtxt::new(self, RepeatingScope(node_id), node_id, Subject(subject));
155155

156+
rcx.free_region_map.relate_free_regions_from_predicates(
157+
&self.param_env.caller_bounds);
158+
156159
if self.err_count_since_creation() == 0 {
157160
// regionck assumes typeck succeeded
158161
rcx.visit_fn_body(fn_id, body, self.tcx.hir.span(fn_id));
159162
}
160163

161-
rcx.free_region_map.relate_free_regions_from_predicates(
162-
&self.param_env.caller_bounds);
163-
164164
rcx.resolve_regions_and_report_errors();
165165

166166
// In this mode, we also copy the free-region-map into the
@@ -475,6 +475,15 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
475475

476476
let span = self.tcx.def_span(def_id);
477477

478+
// If there are required region bounds, we can just skip
479+
// ahead. There will already be a registered region
480+
// obligation related `concrete_ty` to those regions.
481+
if anon_defn.required_region_bounds.len() != 0 {
482+
continue;
483+
}
484+
485+
// There were no `required_region_bounds`,
486+
// so we have to search for a `least_region`.
478487
// Go through all the regions used as arguments to the
479488
// abstract type. These are the parameters to the abstract
480489
// type; so in our example above, `substs` would contain
@@ -503,13 +512,6 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
503512
// There are two regions (`lr` and
504513
// `subst_arg`) which are not relatable. We can't
505514
// find a best choice.
506-
507-
// FIXME We don't need to issue an error
508-
// if there is a lifetime bound in the
509-
// `impl Trait` already (e.g., `impl Foo +
510-
// 'a`). `required_region_bounds` could be
511-
// applied during the instantiation phase
512-
// to find this, I suspect.
513515
self.tcx
514516
.sess
515517
.struct_span_err(span, "ambiguous lifetime bound in `impl Trait`")

0 commit comments

Comments
 (0)