Skip to content

Commit 2180c24

Browse files
committed
Make lifetimes in constants live at the point of use
1 parent 08a60ac commit 2180c24

File tree

5 files changed

+58
-27
lines changed

5 files changed

+58
-27
lines changed

src/librustc_mir/borrow_check/nll/type_check/mod.rs

+41-23
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,17 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
276276

277277
fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
278278
self.super_constant(constant, location);
279-
self.sanitize_type(constant, constant.literal.ty);
279+
let ty = self.sanitize_type(constant, constant.literal.ty);
280+
281+
self.cx.infcx.tcx.for_each_free_region(&ty, |live_region| {
282+
let live_region_vid =
283+
self.cx.borrowck_context.universal_regions.to_region_vid(live_region);
284+
self.cx
285+
.borrowck_context
286+
.constraints
287+
.liveness_constraints
288+
.add_element(live_region_vid, location);
289+
});
280290

281291
if let Some(annotation_index) = constant.user_ty {
282292
if let Err(terr) = self.cx.relate_type_and_user_type(
@@ -528,56 +538,64 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
528538

529539
let parent_body = mem::replace(&mut self.body, promoted_body);
530540

541+
// Use new sets of constraints and closure bounds so that we can
542+
// modify their locations.
531543
let all_facts = &mut None;
532544
let mut constraints = Default::default();
533545
let mut closure_bounds = Default::default();
546+
let mut liveness_constraints = LivenessValues::new(
547+
Rc::new(RegionValueElements::new(promoted_body)),
548+
);
534549
// Don't try to add borrow_region facts for the promoted MIR
535-
mem::swap(self.cx.borrowck_context.all_facts, all_facts);
536550

537-
// Use a new sets of constraints and closure bounds so that we can
538-
// modify their locations.
539-
mem::swap(
540-
&mut self.cx.borrowck_context.constraints.outlives_constraints,
541-
&mut constraints
542-
);
543-
mem::swap(
544-
&mut self.cx.borrowck_context.constraints.closure_bounds_mapping,
545-
&mut closure_bounds
546-
);
551+
let mut swap_constraints = |this: &mut Self| {
552+
mem::swap(this.cx.borrowck_context.all_facts, all_facts);
553+
mem::swap(
554+
&mut this.cx.borrowck_context.constraints.outlives_constraints,
555+
&mut constraints
556+
);
557+
mem::swap(
558+
&mut this.cx.borrowck_context.constraints.closure_bounds_mapping,
559+
&mut closure_bounds
560+
);
561+
mem::swap(
562+
&mut this.cx.borrowck_context.constraints.liveness_constraints,
563+
&mut liveness_constraints
564+
);
565+
};
566+
567+
swap_constraints(self);
547568

548569
self.visit_body(promoted_body);
549570

571+
550572
if !self.errors_reported {
551573
// if verifier failed, don't do further checks to avoid ICEs
552574
self.cx.typeck_mir(promoted_body);
553575
}
554576

555577
self.body = parent_body;
556578
// Merge the outlives constraints back in, at the given location.
557-
mem::swap(self.cx.borrowck_context.all_facts, all_facts);
558-
mem::swap(
559-
&mut self.cx.borrowck_context.constraints.outlives_constraints,
560-
&mut constraints
561-
);
562-
mem::swap(
563-
&mut self.cx.borrowck_context.constraints.closure_bounds_mapping,
564-
&mut closure_bounds
565-
);
579+
swap_constraints(self);
566580

567581
let locations = location.to_locations();
568582
for constraint in constraints.outlives().iter() {
569583
let mut constraint = *constraint;
570584
constraint.locations = locations;
571585
if let ConstraintCategory::Return
572-
| ConstraintCategory::UseAsConst
573-
| ConstraintCategory::UseAsStatic = constraint.category
586+
| ConstraintCategory::UseAsConst
587+
| ConstraintCategory::UseAsStatic = constraint.category
574588
{
575589
// "Returning" from a promoted is an assigment to a
576590
// temporary from the user's point of view.
577591
constraint.category = ConstraintCategory::Boring;
578592
}
579593
self.cx.borrowck_context.constraints.outlives_constraints.push(constraint)
580594
}
595+
for live_region in liveness_constraints.rows() {
596+
self.cx.borrowck_context.constraints.liveness_constraints
597+
.add_element(live_region, location);
598+
}
581599

582600
if !closure_bounds.is_empty() {
583601
let combined_bounds_mapping = closure_bounds
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: higher-ranked subtype error
2+
--> $DIR/due-to-where-clause.rs:2:5
3+
|
4+
LL | test::<FooS>(&mut 42);
5+
| ^^^^^^^^^^^^^^^^^^^^^
6+
7+
error: aborting due to previous error
8+

src/test/ui/hrtb/due-to-where-clause.rs

-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
// ignore-compare-mode-nll
2-
// ^ This code works in nll mode.
3-
41
fn main() {
52
test::<FooS>(&mut 42); //~ ERROR implementation of `Foo` is not general enough
63
}

src/test/ui/hrtb/due-to-where-clause.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: implementation of `Foo` is not general enough
2-
--> $DIR/due-to-where-clause.rs:5:5
2+
--> $DIR/due-to-where-clause.rs:2:5
33
|
44
LL | test::<FooS>(&mut 42);
55
| ^^^^^^^^^^^^ implementation of `Foo` is not general enough

src/test/ui/nll/promoted-liveness.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Test that promoted that have larger mir bodies than their containing function
2+
// don't cause an ICE.
3+
4+
// check-pass
5+
6+
fn main() {
7+
&["0", "1", "2", "3", "4", "5", "6", "7"];
8+
}

0 commit comments

Comments
 (0)