Skip to content

Commit 6fb0711

Browse files
committed
refactor: Don't require a RefCell in VerifyBoundCx
Avoids the risk of attempting to borrow `elaborator` twice by accident. The need for `Captures2` is odd, but it seems like `impl Trait` kept generating lifetime constraints that forced `'a` or `'cx` to be identical to `'tcx` otherwise (due to `'tcx` being invariant I think).
1 parent 13eec85 commit 6fb0711

File tree

3 files changed

+27
-33
lines changed

3 files changed

+27
-33
lines changed

src/librustc/infer/outlives/obligations.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ where
454454
}
455455
}
456456

457-
impl<'cx, 'tcx> TypeOutlivesDelegate<'tcx> for &'cx InferCtxt<'cx, 'tcx> {
457+
impl<'cx, 'tcx> TypeOutlivesDelegate<'tcx> for &'_ InferCtxt<'cx, 'tcx> {
458458
fn push_sub_region_constraint(
459459
&mut self,
460460
origin: SubregionOrigin<'tcx>,

src/librustc/infer/outlives/verify.rs

Lines changed: 20 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1-
use std::cell::RefCell;
2-
31
use crate::hir::def_id::DefId;
42
use crate::infer::outlives::env::RegionBoundPairs;
53
use crate::infer::{GenericKind, VerifyBound};
64
use crate::traits;
75
use crate::ty::subst::{InternalSubsts, Subst};
86
use crate::ty::{self, Ty, TyCtxt};
9-
use crate::util::captures::Captures;
7+
use crate::util::captures::{Captures, Captures2};
108

119
/// The `TypeOutlives` struct has the job of "lowering" a `T: 'a`
1210
/// obligation into a series of `'a: 'b` constraints and "verifys", as
@@ -19,7 +17,7 @@ pub struct VerifyBoundCx<'cx, 'tcx> {
1917
region_bound_pairs: &'cx RegionBoundPairs<'tcx>,
2018
implicit_region_bound: Option<ty::Region<'tcx>>,
2119
param_env: ty::ParamEnv<'tcx>,
22-
elaborator: RefCell<traits::Elaborator<'tcx>>,
20+
elaborator: traits::Elaborator<'tcx>,
2321
}
2422

2523
impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
@@ -34,20 +32,20 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
3432
region_bound_pairs,
3533
implicit_region_bound,
3634
param_env,
37-
elaborator: RefCell::new(traits::Elaborator::new(tcx)),
35+
elaborator: traits::Elaborator::new(tcx),
3836
}
3937
}
4038

4139
/// Returns a "verify bound" that encodes what we know about
4240
/// `generic` and the regions it outlives.
43-
pub fn generic_bound(&self, generic: GenericKind<'tcx>) -> VerifyBound<'tcx> {
41+
pub fn generic_bound(&mut self, generic: GenericKind<'tcx>) -> VerifyBound<'tcx> {
4442
match generic {
4543
GenericKind::Param(param_ty) => self.param_bound(param_ty),
4644
GenericKind::Projection(projection_ty) => self.projection_bound(projection_ty),
4745
}
4846
}
4947

50-
fn type_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
48+
fn type_bound(&mut self, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
5149
match ty.kind {
5250
ty::Param(p) => self.param_bound(p),
5351
ty::Projection(data) => self.projection_bound(data),
@@ -86,7 +84,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
8684
pub fn projection_approx_declared_bounds_from_env(
8785
&self,
8886
projection_ty: ty::ProjectionTy<'tcx>,
89-
) -> impl Iterator<Item = ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>> + 'cx + Captures<'tcx>
87+
) -> impl Iterator<Item = ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>> + Captures2<'cx, 'tcx>
9088
{
9189
let tcx = self.tcx;
9290

@@ -106,16 +104,13 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
106104
/// `projection_ty` is known to outlive. Currently requires an
107105
/// exact match.
108106
pub fn projection_declared_bounds_from_trait<'a>(
109-
&'a self,
107+
&'a mut self,
110108
projection_ty: ty::ProjectionTy<'tcx>,
111-
) -> impl Iterator<Item = ty::Region<'tcx>> + 'cx + Captures<'tcx> + 'a
112-
where
113-
'a: 'cx,
114-
{
109+
) -> impl Iterator<Item = ty::Region<'tcx>> + 'a + Captures2<'cx, 'tcx> {
115110
self.declared_projection_bounds_from_trait(projection_ty)
116111
}
117112

118-
pub fn projection_bound(&self, projection_ty: ty::ProjectionTy<'tcx>) -> VerifyBound<'tcx> {
113+
pub fn projection_bound(&mut self, projection_ty: ty::ProjectionTy<'tcx>) -> VerifyBound<'tcx> {
119114
debug!("projection_bound(projection_ty={:?})", projection_ty);
120115

121116
let projection_ty_as_ty =
@@ -151,7 +146,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
151146
})
152147
}
153148

154-
fn recursive_type_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
149+
fn recursive_type_bound(&mut self, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
155150
let mut bounds = ty
156151
.walk_shallow()
157152
.map(|subty| self.type_bound(subty))
@@ -177,16 +172,16 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
177172
fn declared_generic_bounds_from_env(
178173
&self,
179174
generic: ty::ParamTy,
180-
) -> impl Iterator<Item = ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>> + 'cx + Captures<'tcx>
175+
) -> impl Iterator<Item = ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>> + Captures2<'cx, 'tcx>
181176
{
182177
let generic_ty = generic.to_ty(self.tcx);
183178
self.declared_generic_bounds_from_env_with_compare_fn(move |ty| ty == generic_ty)
184179
}
185180

186181
fn declared_generic_bounds_from_env_with_compare_fn(
187182
&self,
188-
compare_ty: impl Fn(Ty<'tcx>) -> bool + Clone + 'tcx + 'cx,
189-
) -> impl Iterator<Item = ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>> + 'cx + Captures<'tcx>
183+
compare_ty: impl Fn(Ty<'tcx>) -> bool + Clone + 'tcx + Captures<'cx>,
184+
) -> impl Iterator<Item = ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>> + Captures2<'cx, 'tcx>
190185
{
191186
let tcx = self.tcx;
192187

@@ -197,7 +192,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
197192
// like `T` and `T::Item`. It may not work as well for things
198193
// like `<T as Foo<'a>>::Item`.
199194
let c_b = self.param_env.caller_bounds;
200-
let param_bounds = self.collect_outlives_from_predicate_list(compare_ty.clone(), c_b);
195+
let param_bounds = Self::collect_outlives_from_predicate_list(compare_ty.clone(), c_b);
201196

202197
// Next, collect regions we scraped from the well-formedness
203198
// constraints in the fn signature. To do that, we walk the list
@@ -240,12 +235,9 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
240235
/// limitations around higher-ranked bounds described in
241236
/// `region_bounds_declared_on_associated_item`.
242237
fn declared_projection_bounds_from_trait<'a>(
243-
&'a self,
238+
&'a mut self,
244239
projection_ty: ty::ProjectionTy<'tcx>,
245-
) -> impl Iterator<Item = ty::Region<'tcx>> + 'cx + Captures<'tcx> + 'a
246-
where
247-
'a: 'cx,
248-
{
240+
) -> impl Iterator<Item = ty::Region<'tcx>> + 'a + Captures2<'cx, 'tcx> {
249241
debug!("projection_bounds(projection_ty={:?})", projection_ty);
250242
let tcx = self.tcx;
251243
self.region_bounds_declared_on_associated_item(projection_ty.item_def_id)
@@ -283,23 +275,20 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
283275
/// This is for simplicity, and because we are not really smart
284276
/// enough to cope with such bounds anywhere.
285277
fn region_bounds_declared_on_associated_item<'a>(
286-
&'a self,
278+
&'a mut self,
287279
assoc_item_def_id: DefId,
288-
) -> impl Iterator<Item = ty::Region<'tcx>> + 'cx + Captures<'tcx> + 'a
289-
where
290-
'a: 'cx,
291-
{
280+
) -> impl Iterator<Item = ty::Region<'tcx>> + 'a + Captures2<'cx, 'tcx> {
292281
let tcx = self.tcx;
293282
let assoc_item = tcx.associated_item(assoc_item_def_id);
294283
let trait_def_id = assoc_item.container.assert_trait();
295284
let trait_predicates = tcx.predicates_of(trait_def_id).predicates.iter().map(|(p, _)| *p);
296-
let mut elaborator = self.elaborator.borrow_mut();
285+
let elaborator = &mut self.elaborator;
297286
elaborator.clear();
298287
elaborator.extend(trait_predicates);
299288
let identity_substs = InternalSubsts::identity_for_item(tcx, assoc_item_def_id);
300289
let identity_proj = tcx.mk_projection(assoc_item_def_id, identity_substs);
301290

302-
self.collect_outlives_from_predicate_list(
291+
Self::collect_outlives_from_predicate_list(
303292
move |ty| ty == identity_proj,
304293
std::iter::from_fn(move || elaborator.next()),
305294
)
@@ -313,7 +302,6 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
313302
/// that does not involve inference variables and where you
314303
/// otherwise want a precise match.
315304
fn collect_outlives_from_predicate_list(
316-
&self,
317305
compare_ty: impl Fn(Ty<'tcx>) -> bool + 'tcx,
318306
predicates: impl IntoIterator<Item = impl AsRef<ty::Predicate<'tcx>>>,
319307
) -> impl Iterator<Item = ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>> {

src/librustc/util/captures.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,9 @@
88
pub trait Captures<'a> {}
99

1010
impl<'a, T: ?Sized> Captures<'a> for T {}
11+
12+
// FIXME(eddyb) false positive, the lifetime parameter is "phantom" but needed.
13+
#[allow(unused_lifetimes)]
14+
pub trait Captures2<'a, 'b> {}
15+
16+
impl<'a, 'b, T: ?Sized> Captures2<'a, 'b> for T {}

0 commit comments

Comments
 (0)