Skip to content

Commit 6c33ef2

Browse files
Consider alias bounds when considering lliveness for alias types in NLL
1 parent b0889cb commit 6c33ef2

File tree

3 files changed

+94
-11
lines changed

3 files changed

+94
-11
lines changed

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

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

1316
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
@@ -555,16 +558,68 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
555558
values::location_set_str(elements, live_at.iter()),
556559
);
557560

558-
let tcx = typeck.tcx();
559-
tcx.for_each_free_region(&value, |live_region| {
560-
let live_region_vid =
561-
typeck.borrowck_context.universal_regions.to_region_vid(live_region);
562-
typeck
563-
.borrowck_context
564-
.constraints
565-
.liveness_constraints
566-
.add_elements(live_region_vid, live_at);
567-
});
561+
struct MakeAllRegionsLive<'a, 'b, 'tcx> {
562+
typeck: &'b mut TypeChecker<'a, 'tcx>,
563+
live_at: &'b IntervalSet<PointIndex>,
564+
}
565+
impl<'tcx> MakeAllRegionsLive<'_, '_, 'tcx> {
566+
fn make_alias_live(&mut self, t: Ty<'tcx>) -> ControlFlow<!> {
567+
let ty::Alias(_kind, alias_ty) = t.kind() else {
568+
bug!();
569+
};
570+
let tcx = self.typeck.infcx.tcx;
571+
let mut outlives_bounds = tcx
572+
.item_bounds(alias_ty.def_id)
573+
.iter_instantiated(tcx, alias_ty.args)
574+
.filter_map(|clause| {
575+
if let Some(outlives) = clause.as_type_outlives_clause()
576+
&& outlives.skip_binder().0 == t
577+
{
578+
Some(outlives.skip_binder().1)
579+
} else {
580+
None
581+
}
582+
});
583+
if let Some(r) = outlives_bounds.next()
584+
&& !r.is_late_bound()
585+
&& outlives_bounds.all(|other_r| {
586+
other_r == r
587+
})
588+
{
589+
r.visit_with(self)
590+
} else {
591+
t.super_visit_with(self)
592+
}
593+
}
594+
}
595+
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MakeAllRegionsLive<'_, '_, 'tcx> {
596+
type BreakTy = !;
597+
598+
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
599+
if r.is_late_bound() {
600+
return ControlFlow::Continue(());
601+
}
602+
let live_region_vid =
603+
self.typeck.borrowck_context.universal_regions.to_region_vid(r);
604+
self.typeck
605+
.borrowck_context
606+
.constraints
607+
.liveness_constraints
608+
.add_elements(live_region_vid, self.live_at);
609+
ControlFlow::Continue(())
610+
}
611+
612+
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
613+
if !t.has_free_regions() {
614+
ControlFlow::Continue(())
615+
} else if let ty::Alias(..) = t.kind() {
616+
self.make_alias_live(t)
617+
} else {
618+
t.super_visit_with(self)
619+
}
620+
}
621+
}
622+
value.visit_with(&mut MakeAllRegionsLive { typeck, live_at });
568623
}
569624

570625
fn compute_drop_data(
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: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// check-pass
2+
3+
#![feature(return_position_impl_trait_in_trait)]
4+
5+
trait Foo {
6+
fn rpitit(&mut self) -> impl Sized + 'static;
7+
}
8+
9+
fn test<T: Foo>(mut t: T) {
10+
let a = t.rpitit();
11+
let b = t.rpitit();
12+
}
13+
14+
fn main() {}

0 commit comments

Comments
 (0)