Skip to content

Commit f7f40b9

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 02d1504 commit f7f40b9

File tree

3 files changed

+27
-31
lines changed

3 files changed

+27
-31
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 & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::infer::{GenericKind, VerifyBound};
55
use crate::traits;
66
use crate::ty::subst::{InternalSubsts, Subst};
77
use crate::ty::{self, Ty, TyCtxt};
8-
use crate::util::captures::Captures;
8+
use crate::util::captures::{Captures, Captures2};
99
use rustc_hir::def_id::DefId;
1010

1111
/// The `TypeOutlives` struct has the job of "lowering" a `T: 'a`
@@ -19,7 +19,7 @@ pub struct VerifyBoundCx<'cx, 'tcx> {
1919
region_bound_pairs: &'cx RegionBoundPairs<'tcx>,
2020
implicit_region_bound: Option<ty::Region<'tcx>>,
2121
param_env: ty::ParamEnv<'tcx>,
22-
elaborator: RefCell<traits::Elaborator<'tcx>>,
22+
elaborator: traits::Elaborator<'tcx>,
2323
}
2424

2525
impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
@@ -34,20 +34,20 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
3434
region_bound_pairs,
3535
implicit_region_bound,
3636
param_env,
37-
elaborator: RefCell::new(traits::Elaborator::new(tcx)),
37+
elaborator: traits::Elaborator::new(tcx),
3838
}
3939
}
4040

4141
/// Returns a "verify bound" that encodes what we know about
4242
/// `generic` and the regions it outlives.
43-
pub fn generic_bound(&self, generic: GenericKind<'tcx>) -> VerifyBound<'tcx> {
43+
pub fn generic_bound(&mut self, generic: GenericKind<'tcx>) -> VerifyBound<'tcx> {
4444
match generic {
4545
GenericKind::Param(param_ty) => self.param_bound(param_ty),
4646
GenericKind::Projection(projection_ty) => self.projection_bound(projection_ty),
4747
}
4848
}
4949

50-
fn type_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
50+
fn type_bound(&mut self, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
5151
match ty.kind {
5252
ty::Param(p) => self.param_bound(p),
5353
ty::Projection(data) => self.projection_bound(data),
@@ -86,7 +86,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
8686
pub fn projection_approx_declared_bounds_from_env(
8787
&self,
8888
projection_ty: ty::ProjectionTy<'tcx>,
89-
) -> impl Iterator<Item = ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>> + 'cx + Captures<'tcx>
89+
) -> impl Iterator<Item = ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>> + Captures2<'cx, 'tcx>
9090
{
9191
let tcx = self.tcx;
9292

@@ -106,16 +106,13 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
106106
/// `projection_ty` is known to outlive. Currently requires an
107107
/// exact match.
108108
pub fn projection_declared_bounds_from_trait<'a>(
109-
&'a self,
109+
&'a mut self,
110110
projection_ty: ty::ProjectionTy<'tcx>,
111-
) -> impl Iterator<Item = ty::Region<'tcx>> + 'cx + Captures<'tcx> + 'a
112-
where
113-
'a: 'cx,
114-
{
111+
) -> impl Iterator<Item = ty::Region<'tcx>> + 'a + Captures2<'cx, 'tcx> {
115112
self.declared_projection_bounds_from_trait(projection_ty)
116113
}
117114

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

121118
let projection_ty_as_ty =
@@ -151,7 +148,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
151148
})
152149
}
153150

154-
fn recursive_type_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
151+
fn recursive_type_bound(&mut self, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
155152
let mut bounds = ty
156153
.walk_shallow()
157154
.map(|subty| self.type_bound(subty))
@@ -181,16 +178,16 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
181178
fn declared_generic_bounds_from_env(
182179
&self,
183180
generic: ty::ParamTy,
184-
) -> impl Iterator<Item = ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>> + 'cx + Captures<'tcx>
181+
) -> impl Iterator<Item = ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>> + Captures2<'cx, 'tcx>
185182
{
186183
let generic_ty = generic.to_ty(self.tcx);
187184
self.declared_generic_bounds_from_env_with_compare_fn(move |ty| ty == generic_ty)
188185
}
189186

190187
fn declared_generic_bounds_from_env_with_compare_fn(
191188
&self,
192-
compare_ty: impl Fn(Ty<'tcx>) -> bool + Clone + 'tcx + 'cx,
193-
) -> impl Iterator<Item = ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>> + 'cx + Captures<'tcx>
189+
compare_ty: impl Fn(Ty<'tcx>) -> bool + Clone + 'tcx + Captures<'cx>,
190+
) -> impl Iterator<Item = ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>> + Captures2<'cx, 'tcx>
194191
{
195192
let tcx = self.tcx;
196193

@@ -201,7 +198,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
201198
// like `T` and `T::Item`. It may not work as well for things
202199
// like `<T as Foo<'a>>::Item`.
203200
let c_b = self.param_env.caller_bounds;
204-
let param_bounds = self.collect_outlives_from_predicate_list(compare_ty.clone(), c_b);
201+
let param_bounds = Self::collect_outlives_from_predicate_list(compare_ty.clone(), c_b);
205202

206203
// Next, collect regions we scraped from the well-formedness
207204
// constraints in the fn signature. To do that, we walk the list
@@ -244,12 +241,9 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
244241
/// limitations around higher-ranked bounds described in
245242
/// `region_bounds_declared_on_associated_item`.
246243
fn declared_projection_bounds_from_trait<'a>(
247-
&'a self,
244+
&'a mut self,
248245
projection_ty: ty::ProjectionTy<'tcx>,
249-
) -> impl Iterator<Item = ty::Region<'tcx>> + 'cx + Captures<'tcx> + 'a
250-
where
251-
'a: 'cx,
252-
{
246+
) -> impl Iterator<Item = ty::Region<'tcx>> + 'a + Captures2<'cx, 'tcx> {
253247
debug!("projection_bounds(projection_ty={:?})", projection_ty);
254248
let tcx = self.tcx;
255249
self.region_bounds_declared_on_associated_item(projection_ty.item_def_id)
@@ -287,23 +281,20 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
287281
/// This is for simplicity, and because we are not really smart
288282
/// enough to cope with such bounds anywhere.
289283
fn region_bounds_declared_on_associated_item<'a>(
290-
&'a self,
284+
&'a mut self,
291285
assoc_item_def_id: DefId,
292-
) -> impl Iterator<Item = ty::Region<'tcx>> + 'cx + Captures<'tcx> + 'a
293-
where
294-
'a: 'cx,
295-
{
286+
) -> impl Iterator<Item = ty::Region<'tcx>> + 'a + Captures2<'cx, 'tcx> {
296287
let tcx = self.tcx;
297288
let assoc_item = tcx.associated_item(assoc_item_def_id);
298289
let trait_def_id = assoc_item.container.assert_trait();
299290
let trait_predicates = tcx.predicates_of(trait_def_id).predicates.iter().map(|(p, _)| *p);
300-
let mut elaborator = self.elaborator.borrow_mut();
291+
let elaborator = &mut self.elaborator;
301292
elaborator.clear();
302293
elaborator.extend(trait_predicates);
303294
let identity_substs = InternalSubsts::identity_for_item(tcx, assoc_item_def_id);
304295
let identity_proj = tcx.mk_projection(assoc_item_def_id, identity_substs);
305296

306-
self.collect_outlives_from_predicate_list(
297+
Self::collect_outlives_from_predicate_list(
307298
move |ty| ty == identity_proj,
308299
std::iter::from_fn(move || elaborator.next()),
309300
)
@@ -317,7 +308,6 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
317308
/// that does not involve inference variables and where you
318309
/// otherwise want a precise match.
319310
fn collect_outlives_from_predicate_list(
320-
&self,
321311
compare_ty: impl Fn(Ty<'tcx>) -> bool + 'tcx,
322312
predicates: impl IntoIterator<Item = impl AsRef<ty::Predicate<'tcx>>>,
323313
) -> 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)