Skip to content

enable non-lexical lifetimes in the MIR borrow checker #45538

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 33 commits into from
Nov 1, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
c42a645
execute liveness, write a simple test
nikomatsakis Oct 24, 2017
acc5c43
add a test for the subtle case around calls
nikomatsakis Oct 24, 2017
9a47fd2
factor out `pre_defs` field by going backwards
nikomatsakis Oct 24, 2017
16b5f24
rename `BlockInfo` and `BlockInfoVisitor` to `DefsUses`
nikomatsakis Oct 24, 2017
bd25116
extend `dump_mir` to work for any tcx, not just global tcx
nikomatsakis Oct 24, 2017
ea03a43
introduce `apply` helper that applies a DefUse set to live bits
nikomatsakis Oct 24, 2017
1f06ba4
extend liveness to compute intrablock liveness and add unit tests
nikomatsakis Oct 24, 2017
8535a4a
add helper `for_each_free_region` that iterates over free regions
nikomatsakis Oct 24, 2017
7523c73
introduce liveness constraints into NLL code
nikomatsakis Oct 24, 2017
899c7ad
avoid unnecessary copies in liveness computation
nikomatsakis Oct 24, 2017
cb56ff5
reorder liveness to bring the more significant code up top
nikomatsakis Oct 24, 2017
e029378
extend liveness to distinguish "drop" and "non-drop" uses
nikomatsakis Oct 24, 2017
af09f72
preliminary support for may-dangle attribute and drop constraints
nikomatsakis Oct 24, 2017
24442ff
add subregion between borrow region and resulting reference
nikomatsakis Oct 24, 2017
7414060
update the format of liveness debug dumps to be more readable
nikomatsakis Oct 25, 2017
5b2adcc
factor out NLL invocation interface
nikomatsakis Oct 25, 2017
f700728
make end-point optional in the borrow check
nikomatsakis Oct 25, 2017
b8615f3
add reborrow constraints
spastorino Oct 25, 2017
dde61f3
add basic region subtyping inference
spastorino Oct 25, 2017
68c4844
make nll separately invokable
nikomatsakis Oct 26, 2017
5aa1cbf
make `MirSource::from_local_def_id` invokable with 'gcx and 'tcx
nikomatsakis Oct 26, 2017
29cdd73
make `closure_self_ty` invokable with `'gcx` and `'tcx`
nikomatsakis Oct 26, 2017
b2c248e
reorder 'gcx and 'tcx in `BorrowckErrors` impl
nikomatsakis Oct 26, 2017
82b287a
test "needs drop" on region-erased, lifted types
nikomatsakis Oct 30, 2017
8144917
make the dataflow / mir-borrowck types carry a `'tcx` lifetime
nikomatsakis Oct 30, 2017
a94b01a
connect MIR borrowck with NLL
nikomatsakis Oct 30, 2017
f27eb1e
change region display to `'_#Nr`, update the `newtype_index!` macro
nikomatsakis Oct 30, 2017
bf57a23
WIP patch `compile-fail/nll/region-ends-after-if-condition.rs`
nikomatsakis Oct 30, 2017
7675ea9
remove the NLL pass (it is now invoked by mir borrowck)
nikomatsakis Oct 30, 2017
99aa313
runtest: fix mir directory and delete outdated MIR files
nikomatsakis Oct 31, 2017
d9fb792
treat -Znll as implying -Zborrowck-mir
nikomatsakis Oct 31, 2017
9b3af6c
rewrite `write_mir_fn_graphviz` to cope with non-global tcx
nikomatsakis Oct 31, 2017
aae3e74
patch mir-opt reference files
nikomatsakis Oct 31, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/librustc/middle/region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ pub struct BlockRemainder {

newtype_index!(FirstStatementIndex
{
DEBUG_NAME = "",
DEBUG_FORMAT = "{}",
MAX = SCOPE_DATA_REMAINDER_MAX,
});

Expand Down
18 changes: 13 additions & 5 deletions src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ pub enum BorrowKind {

newtype_index!(Local
{
DEBUG_NAME = "_",
DEBUG_FORMAT = "_{}",
const RETURN_POINTER = 0,
});

Expand Down Expand Up @@ -553,7 +553,7 @@ pub struct UpvarDecl {
///////////////////////////////////////////////////////////////////////////
// BasicBlock

newtype_index!(BasicBlock { DEBUG_NAME = "bb" });
newtype_index!(BasicBlock { DEBUG_FORMAT = "bb{}" });

///////////////////////////////////////////////////////////////////////////
// BasicBlockData and Terminator
Expand Down Expand Up @@ -1135,7 +1135,7 @@ pub type LvalueProjection<'tcx> = Projection<'tcx, Lvalue<'tcx>, Local, Ty<'tcx>
/// and the index is a local.
pub type LvalueElem<'tcx> = ProjectionElem<'tcx, Local, Ty<'tcx>>;

newtype_index!(Field { DEBUG_NAME = "field" });
newtype_index!(Field { DEBUG_FORMAT = "field[{}]" });

impl<'tcx> Lvalue<'tcx> {
pub fn field(self, f: Field, ty: Ty<'tcx>) -> Lvalue<'tcx> {
Expand Down Expand Up @@ -1202,7 +1202,7 @@ impl<'tcx> Debug for Lvalue<'tcx> {

newtype_index!(VisibilityScope
{
DEBUG_NAME = "scope",
DEBUG_FORMAT = "scope[{}]",
const ARGUMENT_VISIBILITY_SCOPE = 0,
});

Expand Down Expand Up @@ -1529,7 +1529,7 @@ pub struct Constant<'tcx> {
pub literal: Literal<'tcx>,
}

newtype_index!(Promoted { DEBUG_NAME = "promoted" });
newtype_index!(Promoted { DEBUG_FORMAT = "promoted[{}]" });

#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub enum Literal<'tcx> {
Expand Down Expand Up @@ -1637,6 +1637,14 @@ impl fmt::Debug for Location {
}

impl Location {
/// Returns the location immediately after this one within the enclosing block.
///
/// Note that if this location represents a terminator, then the
/// resulting location would be out of bounds and invalid.
pub fn successor_within_block(&self) -> Location {
Location { block: self.block, statement_index: self.statement_index + 1 }
}

pub fn dominates(&self, other: &Location, dominators: &Dominators<BasicBlock>) -> bool {
if self.block == other.block {
self.statement_index <= other.statement_index
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/mir/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ pub enum MirSource {
GeneratorDrop(NodeId),
}

impl<'a, 'tcx> MirSource {
pub fn from_local_def_id(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> MirSource {
impl<'a, 'gcx, 'tcx> MirSource {
pub fn from_local_def_id(tcx: TyCtxt<'a, 'gcx, 'tcx>, def_id: DefId) -> MirSource {
let id = tcx.hir.as_local_node_id(def_id).expect("mir source requires local def-id");
Self::from_node(tcx, id)
}

pub fn from_node(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId) -> MirSource {
pub fn from_node(tcx: TyCtxt<'a, 'gcx, 'tcx>, id: NodeId) -> MirSource {
use hir::*;

// Handle constants in enum discriminants, types, and repeat expressions.
Expand Down
37 changes: 37 additions & 0 deletions src/librustc/ty/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,43 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
{
value.fold_with(&mut RegionFolder::new(self, skipped_regions, &mut f))
}

pub fn for_each_free_region<T,F>(self,
value: &T,
callback: F)
where F: FnMut(ty::Region<'tcx>),
T: TypeFoldable<'tcx>,
{
value.visit_with(&mut RegionVisitor { current_depth: 0, callback });

struct RegionVisitor<F> {
current_depth: u32,
callback: F,
}

impl<'tcx, F> TypeVisitor<'tcx> for RegionVisitor<F>
where F : FnMut(ty::Region<'tcx>)
{
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> bool {
self.current_depth += 1;
t.skip_binder().visit_with(self);
self.current_depth -= 1;

false // keep visiting
}

fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
match *r {
ty::ReLateBound(debruijn, _) if debruijn.depth < self.current_depth => {
/* ignore bound regions */
}
_ => (self.callback)(r),
}

false // keep visiting
}
}
}
}

/// Folds over the substructure of a type, visiting its component
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_borrowck/borrowck/check_loans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
// 3. Where does old loan expire.

let previous_end_span =
old_loan.kill_scope.span(self.tcx(), &self.bccx.region_scope_tree).end_point();
Some(old_loan.kill_scope.span(self.tcx(), &self.bccx.region_scope_tree)
.end_point());

let mut err = match (new_loan.kind, old_loan.kind) {
(ty::MutBorrow, ty::MutBorrow) =>
Expand Down
12 changes: 10 additions & 2 deletions src/librustc_data_structures/indexed_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,19 @@ pub struct IdxSet<T: Idx> {
}

impl<T: Idx> fmt::Debug for IdxSetBuf<T> {
fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { self.bits.fmt(w) }
fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
w.debug_list()
.entries(self.iter())
.finish()
}
}

impl<T: Idx> fmt::Debug for IdxSet<T> {
fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { self.bits.fmt(w) }
fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
w.debug_list()
.entries(self.iter())
.finish()
}
}

impl<T: Idx> IdxSetBuf<T> {
Expand Down
35 changes: 19 additions & 16 deletions src/librustc_data_structures/indexed_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,22 +47,22 @@ macro_rules! newtype_index {
newtype_index!(
@type[$name]
@max[::std::u32::MAX]
@debug_name[unsafe {::std::intrinsics::type_name::<$name>() }]);
@debug_format["{}"]);
);

// Define any constants
($name:ident { $($tokens:tt)+ }) => (
newtype_index!(
@type[$name]
@max[::std::u32::MAX]
@debug_name[unsafe {::std::intrinsics::type_name::<$name>() }]
@debug_format["{}"]
$($tokens)+);
);

// ---- private rules ----

// Base case, user-defined constants (if any) have already been defined
(@type[$type:ident] @max[$max:expr] @debug_name[$debug_name:expr]) => (
(@type[$type:ident] @max[$max:expr] @debug_format[$debug_format:expr]) => (
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord,
RustcEncodable, RustcDecodable)]
pub struct $type(pub u32);
Expand All @@ -79,40 +79,43 @@ macro_rules! newtype_index {

impl ::std::fmt::Debug for $type {
fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(fmt, "{}{}", $debug_name, self.0)
write!(fmt, $debug_format, self.0)
}
}
);

// Rewrite final without comma to one that includes comma
(@type[$type:ident] @max[$max:expr] @debug_name[$debug_name:expr]
(@type[$type:ident] @max[$max:expr] @debug_format[$debug_format:expr]
$name:ident = $constant:expr) => (
newtype_index!(@type[$type] @max[$max] @debug_name[$debug_name] $name = $constant,);
newtype_index!(@type[$type] @max[$max] @debug_format[$debug_format] $name = $constant,);
);

// Rewrite final const without comma to one that includes comma
(@type[$type:ident] @max[$_max:expr] @debug_name[$debug_name:expr]
(@type[$type:ident] @max[$_max:expr] @debug_format[$debug_format:expr]
const $name:ident = $constant:expr) => (
newtype_index!(@type[$type] @max[$max] @debug_name[$debug_name] const $name = $constant,);
newtype_index!(@type[$type]
@max[$max]
@debug_format[$debug_format]
const $name = $constant,);
);

// Replace existing default for max
(@type[$type:ident] @max[$_max:expr] @debug_name[$debug_name:expr]
(@type[$type:ident] @max[$_max:expr] @debug_format[$debug_format:expr]
MAX = $max:expr, $($tokens:tt)*) => (
newtype_index!(@type[$type] @max[$max] @debug_name[$debug_name] $($tokens)*);
newtype_index!(@type[$type] @max[$max] @debug_format[$debug_format] $($tokens)*);
);

// Replace existing default for debug_name
(@type[$type:ident] @max[$max:expr] @debug_name[$_debug_name:expr]
DEBUG_NAME = $debug_name:expr, $($tokens:tt)*) => (
newtype_index!(@type[$type] @max[$max] @debug_name[$debug_name] $($tokens)*);
// Replace existing default for debug_format
(@type[$type:ident] @max[$max:expr] @debug_format[$_debug_format:expr]
DEBUG_FORMAT = $debug_format:expr, $($tokens:tt)*) => (
newtype_index!(@type[$type] @max[$max] @debug_format[$debug_format] $($tokens)*);
);

// Assign a user-defined constant (as final param)
(@type[$type:ident] @max[$max:expr] @debug_name[$debug_name:expr]
(@type[$type:ident] @max[$max:expr] @debug_format[$debug_format:expr]
const $name:ident = $constant:expr, $($tokens:tt)*) => (
pub const $name: $type = $type($constant);
newtype_index!(@type[$type] @max[$max] @debug_name[$debug_name] $($tokens)*);
newtype_index!(@type[$type] @max[$max] @debug_format[$debug_format] $($tokens)*);
);
}

Expand Down
1 change: 0 additions & 1 deletion src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1003,7 +1003,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,

passes.push_pass(MIR_VALIDATED, mir::transform::qualify_consts::QualifyAndPromoteConstants);
passes.push_pass(MIR_VALIDATED, mir::transform::simplify::SimplifyCfg::new("qualify-consts"));
passes.push_pass(MIR_VALIDATED, mir::transform::nll::NLL);

// borrowck runs between MIR_VALIDATED and MIR_OPTIMIZED.

Expand Down
Loading