Skip to content

Commit 184d5ef

Browse files
Consider alias bounds when considering lliveness for alias types in NLL
1 parent 96c4dba commit 184d5ef

File tree

3 files changed

+102
-19
lines changed

3 files changed

+102
-19
lines changed

compiler/rustc_borrowck/src/type_check/liveness/trace.rs

Lines changed: 76 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@ use rustc_index::interval::IntervalSet;
55
use rustc_infer::infer::canonical::QueryRegionConstraints;
66
use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location};
77
use rustc_middle::traits::query::DropckOutlivesResult;
8-
use rustc_middle::ty::{RegionVid, Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
8+
use rustc_middle::ty::{
9+
self, RegionVid, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
10+
};
911
use rustc_span::DUMMY_SP;
1012
use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives;
1113
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
14+
use std::ops::ControlFlow;
1215
use std::rc::Rc;
1316

1417
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
@@ -601,34 +604,88 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
601604
values::location_set_str(elements, live_at.iter()),
602605
);
603606

604-
let tcx = typeck.tcx();
605-
let borrowck_context = &mut typeck.borrowck_context;
606-
607607
// When using `-Zpolonius=next`, we want to record the loans that flow into this value's
608608
// regions as being live at the given `live_at` points: this will be used to compute the
609609
// location where a loan goes out of scope.
610-
let num_loans = borrowck_context.borrow_set.len();
611-
let mut value_loans = HybridBitSet::new_empty(num_loans);
612-
613-
tcx.for_each_free_region(&value, |live_region| {
614-
let live_region_vid = borrowck_context.universal_regions.to_region_vid(live_region);
610+
let num_loans = typeck.borrowck_context.borrow_set.len();
611+
let value_loans = &mut HybridBitSet::new_empty(num_loans);
612+
613+
struct MakeAllRegionsLive<'a, 'b, 'tcx> {
614+
typeck: &'b mut TypeChecker<'a, 'tcx>,
615+
live_at: &'b IntervalSet<PointIndex>,
616+
value_loans: &'b mut HybridBitSet<BorrowIndex>,
617+
inflowing_loans: &'b SparseBitMatrix<RegionVid, BorrowIndex>,
618+
}
619+
impl<'tcx> MakeAllRegionsLive<'_, '_, 'tcx> {
620+
fn make_alias_live(&mut self, t: Ty<'tcx>) -> ControlFlow<!> {
621+
let ty::Alias(_kind, alias_ty) = t.kind() else {
622+
bug!();
623+
};
624+
let tcx = self.typeck.infcx.tcx;
625+
let mut outlives_bounds = tcx
626+
.item_bounds(alias_ty.def_id)
627+
.iter_instantiated(tcx, alias_ty.args)
628+
.filter_map(|clause| {
629+
if let Some(outlives) = clause.as_type_outlives_clause()
630+
&& outlives.skip_binder().0 == t
631+
{
632+
Some(outlives.skip_binder().1)
633+
} else {
634+
None
635+
}
636+
});
637+
if let Some(r) = outlives_bounds.next()
638+
&& !r.is_late_bound()
639+
&& outlives_bounds.all(|other_r| {
640+
other_r == r
641+
})
642+
{
643+
r.visit_with(self)
644+
} else {
645+
t.super_visit_with(self)
646+
}
647+
}
648+
}
649+
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MakeAllRegionsLive<'_, '_, 'tcx> {
650+
type BreakTy = !;
615651

616-
borrowck_context
617-
.constraints
618-
.liveness_constraints
619-
.add_elements(live_region_vid, live_at);
652+
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
653+
if r.is_late_bound() {
654+
return ControlFlow::Continue(());
655+
}
656+
let live_region_vid =
657+
self.typeck.borrowck_context.universal_regions.to_region_vid(r);
658+
659+
self.typeck
660+
.borrowck_context
661+
.constraints
662+
.liveness_constraints
663+
.add_elements(live_region_vid, self.live_at);
664+
665+
// There can only be inflowing loans for this region when we are using
666+
// `-Zpolonius=next`.
667+
if let Some(inflowing) = self.inflowing_loans.row(live_region_vid) {
668+
self.value_loans.union(inflowing);
669+
}
670+
ControlFlow::Continue(())
671+
}
620672

621-
// There can only be inflowing loans for this region when we are using
622-
// `-Zpolonius=next`.
623-
if let Some(inflowing) = inflowing_loans.row(live_region_vid) {
624-
value_loans.union(inflowing);
673+
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
674+
if !t.has_free_regions() {
675+
ControlFlow::Continue(())
676+
} else if let ty::Alias(..) = t.kind() {
677+
self.make_alias_live(t)
678+
} else {
679+
t.super_visit_with(self)
680+
}
625681
}
626-
});
682+
}
683+
value.visit_with(&mut MakeAllRegionsLive { typeck, live_at, value_loans, inflowing_loans });
627684

628685
// Record the loans reaching the value.
629686
if !value_loans.is_empty() {
630687
for point in live_at.iter() {
631-
borrowck_context.live_loans.union_row(point, &value_loans);
688+
typeck.borrowck_context.live_loans.union_row(point, value_loans);
632689
}
633690
}
634691
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// check-pass
2+
3+
trait Captures<'a> {}
4+
impl<T> Captures<'_> for T {}
5+
6+
fn foo(x: &i32) -> impl Sized + Captures<'_> + 'static {}
7+
8+
fn main() {
9+
let y;
10+
{
11+
let x = 1;
12+
y = foo(&x);
13+
}
14+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// check-pass
2+
3+
trait Foo {
4+
fn rpitit(&mut self) -> impl Sized + 'static;
5+
}
6+
7+
fn test<T: Foo>(mut t: T) {
8+
let a = t.rpitit();
9+
let b = t.rpitit();
10+
}
11+
12+
fn main() {}

0 commit comments

Comments
 (0)