Skip to content

Commit

Permalink
merge NLL "constraint generation" into liveness
Browse files Browse the repository at this point in the history
  • Loading branch information
lqd committed Nov 26, 2023
1 parent 626289a commit 96042bc
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 81 deletions.
74 changes: 0 additions & 74 deletions compiler/rustc_borrowck/src/constraint_generation.rs

This file was deleted.

1 change: 0 additions & 1 deletion compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ use self::path_utils::*;

pub mod borrow_set;
mod borrowck_errors;
mod constraint_generation;
mod constraints;
mod dataflow;
mod def_use;
Expand Down
4 changes: 1 addition & 3 deletions compiler/rustc_borrowck/src/nll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ use std::str::FromStr;

use crate::{
borrow_set::BorrowSet,
constraint_generation,
consumers::ConsumerOptions,
diagnostics::RegionErrors,
facts::{AllFacts, AllFactsExt, RustcFacts},
Expand Down Expand Up @@ -141,15 +140,14 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
let MirTypeckRegionConstraints {
placeholder_indices,
placeholder_index_to_region: _,
mut liveness_constraints,
liveness_constraints,
outlives_constraints,
member_constraints,
universe_causes,
type_tests,
} = constraints;
let placeholder_indices = Rc::new(placeholder_indices);

constraint_generation::generate_constraints(infcx.tcx, &mut liveness_constraints, body);
polonius::emit_cfg_and_loan_kills_facts(
infcx.tcx,
&mut all_facts,
Expand Down
84 changes: 81 additions & 3 deletions compiler/rustc_borrowck/src/type_check/liveness/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use itertools::{Either, Itertools};
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::mir::{Body, Local};
use rustc_middle::ty::{RegionVid, TyCtxt};
use rustc_middle::mir::visit::{TyContext, Visitor};
use rustc_middle::mir::{Body, Local, Location, SourceInfo};
use rustc_middle::ty::visit::TypeVisitable;
use rustc_middle::ty::{GenericArgsRef, Region, RegionVid, Ty, TyCtxt};
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
use rustc_mir_dataflow::move_paths::MoveData;
use rustc_mir_dataflow::ResultsCursor;
Expand All @@ -11,7 +13,7 @@ use crate::{
constraints::OutlivesConstraintSet,
facts::{AllFacts, AllFactsExt},
location::LocationTable,
region_infer::values::RegionValueElements,
region_infer::values::{LivenessValues, RegionValueElements},
universal_regions::UniversalRegions,
};

Expand Down Expand Up @@ -65,6 +67,14 @@ pub(super) fn generate<'mir, 'tcx>(
boring_locals,
polonius_drop_used,
);

// Mark regions that should be live where they appear within rvalues or within a call: like
// args, regions, and types.
record_regular_live_regions(
typeck.tcx(),
&mut typeck.borrowck_context.constraints.liveness_constraints,
body,
);
}

// The purpose of `compute_relevant_live_locals` is to define the subset of `Local`
Expand Down Expand Up @@ -132,3 +142,71 @@ fn regions_that_outlive_free_regions<'tcx>(
// Return the final set of things we visited.
outlives_free_region
}

/// Some variables are "regular live" at `location` -- i.e., they may be used later. This means that
/// all regions appearing in their type must be live at `location`.
fn record_regular_live_regions<'tcx>(
tcx: TyCtxt<'tcx>,
liveness_constraints: &mut LivenessValues,
body: &Body<'tcx>,
) {
let mut visitor = LiveVariablesVisitor { tcx, liveness_constraints };
for (bb, data) in body.basic_blocks.iter_enumerated() {
visitor.visit_basic_block_data(bb, data);
}
}

/// Visitor looking for regions that should be live within rvalues or calls.
struct LiveVariablesVisitor<'cx, 'tcx> {
tcx: TyCtxt<'tcx>,
liveness_constraints: &'cx mut LivenessValues,
}

impl<'cx, 'tcx> Visitor<'tcx> for LiveVariablesVisitor<'cx, 'tcx> {
/// We sometimes have `args` within an rvalue, or within a
/// call. Make them live at the location where they appear.
fn visit_args(&mut self, args: &GenericArgsRef<'tcx>, location: Location) {
self.record_regions_live_at(*args, location);
self.super_args(args);
}

/// We sometimes have `region`s within an rvalue, or within a
/// call. Make them live at the location where they appear.
fn visit_region(&mut self, region: Region<'tcx>, location: Location) {
self.record_regions_live_at(region, location);
self.super_region(region);
}

/// We sometimes have `ty`s within an rvalue, or within a
/// call. Make them live at the location where they appear.
fn visit_ty(&mut self, ty: Ty<'tcx>, ty_context: TyContext) {
match ty_context {
TyContext::ReturnTy(SourceInfo { span, .. })
| TyContext::YieldTy(SourceInfo { span, .. })
| TyContext::UserTy(span)
| TyContext::LocalDecl { source_info: SourceInfo { span, .. }, .. } => {
span_bug!(span, "should not be visiting outside of the CFG: {:?}", ty_context);
}
TyContext::Location(location) => {
self.record_regions_live_at(ty, location);
}
}

self.super_ty(ty);
}
}

impl<'cx, 'tcx> LiveVariablesVisitor<'cx, 'tcx> {
/// Some variable is "regular live" at `location` -- i.e., it may be used later. This means that
/// all regions appearing in the type of `value` must be live at `location`.
fn record_regions_live_at<T>(&mut self, value: T, location: Location)
where
T: TypeVisitable<TyCtxt<'tcx>>,
{
debug!("record_regions_live_at(value={:?}, location={:?})", value, location);
self.tcx.for_each_free_region(&value, |live_region| {
let live_region_vid = live_region.as_var();
self.liveness_constraints.add_location(live_region_vid, location);
});
}
}

0 comments on commit 96042bc

Please sign in to comment.