Skip to content

Commit a66a2e3

Browse files
Rollup merge of #150550 - borrowck_cleanup_2, r=lcnr
Miscellaneous cleanups to borrowck related code r? lcnr
2 parents 619f137 + 3705ebb commit a66a2e3

File tree

9 files changed

+90
-95
lines changed

9 files changed

+90
-95
lines changed

compiler/rustc_borrowck/src/borrow_set.rs

Lines changed: 39 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -253,19 +253,52 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> {
253253
}
254254

255255
let region = region.as_var();
256-
257-
let borrow = BorrowData {
256+
let borrow = |activation_location| BorrowData {
258257
kind,
259258
region,
260259
reserve_location: location,
261-
activation_location: TwoPhaseActivation::NotTwoPhase,
260+
activation_location,
262261
borrowed_place,
263262
assigned_place: *assigned_place,
264263
};
265-
let (idx, _) = self.location_map.insert_full(location, borrow);
266-
let idx = BorrowIndex::from(idx);
267264

268-
self.insert_as_pending_if_two_phase(location, assigned_place, kind, idx);
265+
let idx = if !kind.is_two_phase_borrow() {
266+
debug!(" -> {:?}", location);
267+
let (idx, _) = self
268+
.location_map
269+
.insert_full(location, borrow(TwoPhaseActivation::NotTwoPhase));
270+
BorrowIndex::from(idx)
271+
} else {
272+
// When we encounter a 2-phase borrow statement, it will always
273+
// be assigning into a temporary TEMP:
274+
//
275+
// TEMP = &foo
276+
//
277+
// so extract `temp`.
278+
let Some(temp) = assigned_place.as_local() else {
279+
span_bug!(
280+
self.body.source_info(location).span,
281+
"expected 2-phase borrow to assign to a local, not `{:?}`",
282+
assigned_place,
283+
);
284+
};
285+
286+
// Consider the borrow not activated to start. When we find an activation, we'll update
287+
// this field.
288+
let (idx, _) = self
289+
.location_map
290+
.insert_full(location, borrow(TwoPhaseActivation::NotActivated));
291+
let idx = BorrowIndex::from(idx);
292+
293+
// Insert `temp` into the list of pending activations. From
294+
// now on, we'll be on the lookout for a use of it. Note that
295+
// we are guaranteed that this use will come after the
296+
// assignment.
297+
let prev = self.pending_activations.insert(temp, idx);
298+
assert_eq!(prev, None, "temporary associated with multiple two phase borrows");
299+
300+
idx
301+
};
269302

270303
self.local_map.entry(borrowed_place.local).or_default().insert(idx);
271304
}
@@ -334,62 +367,3 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> {
334367
self.super_rvalue(rvalue, location)
335368
}
336369
}
337-
338-
impl<'a, 'tcx> GatherBorrows<'a, 'tcx> {
339-
/// If this is a two-phase borrow, then we will record it
340-
/// as "pending" until we find the activating use.
341-
fn insert_as_pending_if_two_phase(
342-
&mut self,
343-
start_location: Location,
344-
assigned_place: &mir::Place<'tcx>,
345-
kind: mir::BorrowKind,
346-
borrow_index: BorrowIndex,
347-
) {
348-
debug!(
349-
"Borrows::insert_as_pending_if_two_phase({:?}, {:?}, {:?})",
350-
start_location, assigned_place, borrow_index,
351-
);
352-
353-
if !kind.allows_two_phase_borrow() {
354-
debug!(" -> {:?}", start_location);
355-
return;
356-
}
357-
358-
// When we encounter a 2-phase borrow statement, it will always
359-
// be assigning into a temporary TEMP:
360-
//
361-
// TEMP = &foo
362-
//
363-
// so extract `temp`.
364-
let Some(temp) = assigned_place.as_local() else {
365-
span_bug!(
366-
self.body.source_info(start_location).span,
367-
"expected 2-phase borrow to assign to a local, not `{:?}`",
368-
assigned_place,
369-
);
370-
};
371-
372-
// Consider the borrow not activated to start. When we find an activation, we'll update
373-
// this field.
374-
{
375-
let borrow_data = &mut self.location_map[borrow_index.as_usize()];
376-
borrow_data.activation_location = TwoPhaseActivation::NotActivated;
377-
}
378-
379-
// Insert `temp` into the list of pending activations. From
380-
// now on, we'll be on the lookout for a use of it. Note that
381-
// we are guaranteed that this use will come after the
382-
// assignment.
383-
let old_value = self.pending_activations.insert(temp, borrow_index);
384-
if let Some(old_index) = old_value {
385-
span_bug!(
386-
self.body.source_info(start_location).span,
387-
"found already pending activation for temp: {:?} \
388-
at borrow_index: {:?} with associated data {:?}",
389-
temp,
390-
old_index,
391-
self.location_map[old_index.as_usize()]
392-
);
393-
}
394-
}
395-
}

compiler/rustc_borrowck/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,7 +1301,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
13011301
(Read(kind), BorrowKind::Mut { .. }) => {
13021302
// Reading from mere reservations of mutable-borrows is OK.
13031303
if !is_active(this.dominators(), borrow, location) {
1304-
assert!(borrow.kind.allows_two_phase_borrow());
1304+
assert!(borrow.kind.is_two_phase_borrow());
13051305
return ControlFlow::Continue(());
13061306
}
13071307

@@ -1464,7 +1464,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
14641464
}
14651465
BorrowKind::Mut { .. } => {
14661466
let wk = WriteKind::MutableBorrow(bk);
1467-
if bk.allows_two_phase_borrow() {
1467+
if bk.is_two_phase_borrow() {
14681468
(Deep, Reservation(wk))
14691469
} else {
14701470
(Deep, Write(wk))

compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> {
264264
}
265265
BorrowKind::Mut { .. } => {
266266
let wk = WriteKind::MutableBorrow(bk);
267-
if bk.allows_two_phase_borrow() {
267+
if bk.is_two_phase_borrow() {
268268
(Deep, Reservation(wk))
269269
} else {
270270
(Deep, Write(wk))
@@ -384,7 +384,7 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> {
384384
// Reading from mere reservations of mutable-borrows is OK.
385385
if !is_active(this.dominators, borrow, location) {
386386
// If the borrow isn't active yet, reads don't invalidate it
387-
assert!(borrow.kind.allows_two_phase_borrow());
387+
assert!(borrow.kind.is_two_phase_borrow());
388388
return ControlFlow::Continue(());
389389
}
390390

compiler/rustc_borrowck/src/type_check/free_region_relations.rs

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,9 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
229229
// not ready to process them yet.
230230
// - Then compute the implied bounds. This will adjust
231231
// the `region_bound_pairs` and so forth.
232-
// - After this is done, we'll process the constraints, once
233-
// the `relations` is built.
232+
// - After this is done, we'll register the constraints in
233+
// the `BorrowckInferCtxt`. Checking these constraints is
234+
// handled later by actual borrow checking.
234235
let mut normalized_inputs_and_output =
235236
Vec::with_capacity(self.universal_regions.unnormalized_input_tys.len() + 1);
236237
for ty in unnormalized_input_output_tys {
@@ -254,6 +255,15 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
254255
constraints.push(c)
255256
}
256257

258+
// Currently `implied_outlives_bounds` will normalize the provided
259+
// `Ty`, despite this it's still important to normalize the ty ourselves
260+
// as normalization may introduce new region variables (#136547).
261+
//
262+
// If we do not add implied bounds for the type involving these new
263+
// region variables then we'll wind up with the normalized form of
264+
// the signature having not-wf types due to unsatisfied region
265+
// constraints.
266+
//
257267
// Note: we need this in examples like
258268
// ```
259269
// trait Foo {
@@ -262,7 +272,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
262272
// }
263273
// impl Foo for () {
264274
// type Bar = ();
265-
// fn foo(&self) ->&() {}
275+
// fn foo(&self) -> &() {}
266276
// }
267277
// ```
268278
// Both &Self::Bar and &() are WF
@@ -277,6 +287,15 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
277287
}
278288

279289
// Add implied bounds from impl header.
290+
//
291+
// We don't use `assumed_wf_types` to source the entire set of implied bounds for
292+
// a few reasons:
293+
// - `DefiningTy` for closure has the `&'env Self` type while `assumed_wf_types` doesn't
294+
// - We compute implied bounds from the unnormalized types in the `DefiningTy` but do not
295+
// do so for types in impl headers
296+
// - We must compute the normalized signature and then compute implied bounds from that
297+
// in order to connect any unconstrained region vars created during normalization to
298+
// the types of the locals corresponding to the inputs and outputs of the item. (#136547)
280299
if matches!(tcx.def_kind(defining_ty_def_id), DefKind::AssocFn | DefKind::AssocConst) {
281300
for &(ty, _) in tcx.assumed_wf_types(tcx.local_parent(defining_ty_def_id)) {
282301
let result: Result<_, ErrorGuaranteed> = param_env
@@ -352,10 +371,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
352371
known_type_outlives_obligations.push(outlives);
353372
}
354373

355-
/// Update the type of a single local, which should represent
356-
/// either the return type of the MIR or one of its arguments. At
357-
/// the same time, compute and add any implied bounds that come
358-
/// from this local.
374+
/// Compute and add any implied bounds that come from a given type.
359375
#[instrument(level = "debug", skip(self))]
360376
fn add_implied_bounds(
361377
&mut self,

compiler/rustc_borrowck/src/universal_regions.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -207,10 +207,10 @@ struct UniversalRegionIndices<'tcx> {
207207
/// `ty::Region` to the internal `RegionVid` we are using. This is
208208
/// used because trait matching and type-checking will feed us
209209
/// region constraints that reference those regions and we need to
210-
/// be able to map them to our internal `RegionVid`. This is
211-
/// basically equivalent to an `GenericArgs`, except that it also
212-
/// contains an entry for `ReStatic` -- it might be nice to just
213-
/// use an args, and then handle `ReStatic` another way.
210+
/// be able to map them to our internal `RegionVid`.
211+
///
212+
/// This is similar to just using `GenericArgs`, except that it contains
213+
/// an entry for `'static`, and also late bound parameters in scope.
214214
indices: FxIndexMap<ty::Region<'tcx>, RegionVid>,
215215

216216
/// The vid assigned to `'static`. Used only for diagnostics.

compiler/rustc_const_eval/src/interpret/step.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
218218
// A fresh reference was created, make sure it gets retagged.
219219
let val = M::retag_ptr_value(
220220
self,
221-
if borrow_kind.allows_two_phase_borrow() {
221+
if borrow_kind.is_two_phase_borrow() {
222222
mir::RetagKind::TwoPhase
223223
} else {
224224
mir::RetagKind::Default

compiler/rustc_middle/src/mir/statement.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -842,7 +842,7 @@ impl BorrowKind {
842842

843843
/// Returns whether borrows represented by this kind are allowed to be split into separate
844844
/// Reservation and Activation phases.
845-
pub fn allows_two_phase_borrow(&self) -> bool {
845+
pub fn is_two_phase_borrow(&self) -> bool {
846846
match *self {
847847
BorrowKind::Shared
848848
| BorrowKind::Fake(_)

compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -61,23 +61,28 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
6161
"compute_implied_outlives_bounds assumes region obligations are empty before starting"
6262
);
6363

64-
let normalize_ty = |ty| -> Result<_, NoSolution> {
65-
// We must normalize the type so we can compute the right outlives components.
66-
// for example, if we have some constrained param type like `T: Trait<Out = U>`,
67-
// and we know that `&'a T::Out` is WF, then we want to imply `U: 'a`.
68-
let ty = ocx
69-
.deeply_normalize(&ObligationCause::dummy_with_span(span), param_env, ty)
70-
.map_err(|_| NoSolution)?;
71-
Ok(ty)
72-
};
64+
// FIXME: This doesn't seem right. All call sites already normalize `ty`:
65+
// - `Ty`s from the `DefiningTy` in Borrowck: we have to normalize in the caller
66+
// in order to get implied bounds involving any unconstrained region vars
67+
// created as part of normalizing the sig. See #136547
68+
// - `Ty`s from impl headers in Borrowck and in Non-Borrowck contexts: we have
69+
// to normalize in the caller as computing implied bounds from unnormalized
70+
// types would be unsound. See #100989
71+
//
72+
// We must normalize the type so we can compute the right outlives components.
73+
// for example, if we have some constrained param type like `T: Trait<Out = U>`,
74+
// and we know that `&'a T::Out` is WF, then we want to imply `U: 'a`.
75+
let normalized_ty = ocx
76+
.deeply_normalize(&ObligationCause::dummy_with_span(span), param_env, ty)
77+
.map_err(|_| NoSolution)?;
7378

7479
// Sometimes when we ask what it takes for T: WF, we get back that
7580
// U: WF is required; in that case, we push U onto this stack and
7681
// process it next. Because the resulting predicates aren't always
7782
// guaranteed to be a subset of the original type, so we need to store the
7883
// WF args we've computed in a set.
7984
let mut checked_wf_args = rustc_data_structures::fx::FxHashSet::default();
80-
let mut wf_args = vec![ty.into(), normalize_ty(ty)?.into()];
85+
let mut wf_args = vec![ty.into(), normalized_ty.into()];
8186

8287
let mut outlives_bounds: Vec<OutlivesBound<'tcx>> = vec![];
8388

@@ -103,8 +108,8 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
103108
continue;
104109
};
105110
match pred {
106-
// FIXME(const_generics): Make sure that `<'a, 'b, const N: &'a &'b u32>` is sound
107-
// if we ever support that
111+
// FIXME(generic_const_parameter_types): Make sure that `<'a, 'b, const N: &'a &'b u32>`
112+
// is sound if we ever support that
108113
ty::PredicateKind::Clause(ty::ClauseKind::Trait(..))
109114
| ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..))
110115
| ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))

compiler/rustc_traits/src/implied_outlives_bounds.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//! Provider for the `implied_outlives_bounds` query.
2-
//! Do not call this query directory. See
2+
//! Do not call this query directly. See
33
//! [`rustc_trait_selection::traits::query::type_op::implied_outlives_bounds`].
44
55
use rustc_infer::infer::TyCtxtInferExt;

0 commit comments

Comments
 (0)