Skip to content
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

NLL should identify and respect the lifetime annotations that the user wrote #48482

Merged
merged 17 commits into from
Mar 24, 2018
Merged
Changes from 1 commit
Commits
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
Original file line number Diff line number Diff line change
@@ -8,16 +8,27 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! This module provides one pass, `CleanEndRegions`, that reduces the
//! set of `EndRegion` statements in the MIR.
//! This module provides two passes:
//!
//! The "pass" is actually implemented as two traversals (aka visits)
//! of the input MIR. The first traversal, `GatherBorrowedRegions`,
//! finds all of the regions in the MIR that are involved in a borrow.
//! - `CleanEndRegions`, that reduces the set of `EndRegion` statements
//! in the MIR.
//! - `CleanUserAssertTy`, that replaces all `UserAssertTy` statements
//! with `Nop`.
//!
//! The `CleanEndRegions` "pass" is actually implemented as two
//! traversals (aka visits) of the input MIR. The first traversal,
//! `GatherBorrowedRegions`, finds all of the regions in the MIR
//! that are involved in a borrow.
//!
//! The second traversal, `DeleteTrivialEndRegions`, walks over the
//! MIR and removes any `EndRegion` that is applied to a region that
//! was not seen in the previous pass.
//!
//! The `CleanUserAssertTy` pass runs at a distinct time from the
//! `CleanEndRegions` pass. It is important that the `CleanUserAssertTy`
//! pass runs after the MIR borrowck so that the NLL type checker can
//! perform the type assertion when it encounters the `UserAssertTy`
//! statements.

use rustc_data_structures::fx::FxHashSet;

@@ -27,7 +38,7 @@ use rustc::mir::visit::{MutVisitor, Visitor, TyContext};
use rustc::ty::{Ty, RegionKind, TyCtxt};
use transform::{MirPass, MirSource};

pub struct CleanEndRegions;
pub struct CleanupPostBorrowck;

struct GatherBorrowedRegions {
seen_regions: FxHashSet<region::Scope>,
@@ -37,19 +48,24 @@ struct DeleteTrivialEndRegions<'a> {
seen_regions: &'a FxHashSet<region::Scope>,
}

impl MirPass for CleanEndRegions {
pub struct DeleteUserAssertTy;

impl MirPass for CleanupPostBorrowck {
fn run_pass<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
_source: MirSource,
mir: &mut Mir<'tcx>) {
if !tcx.emit_end_regions() { return; }
if tcx.emit_end_regions() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any particular reason for this hunk, or just cleanup? (I sort of prefer the "return early" variant)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So do I actually, this was just left-over from when I had CleanEndRegions and CleanUserAssertTy combined as a single pass and I didn't want an early return to stop the deletion of the UserAssertTy. I can change it back.

let mut gather = GatherBorrowedRegions {
seen_regions: FxHashSet()
};
gather.visit_mir(mir);

let mut gather = GatherBorrowedRegions {
seen_regions: FxHashSet()
};
gather.visit_mir(mir);
let mut delete = DeleteTrivialEndRegions { seen_regions: &mut gather.seen_regions };
delete.visit_mir(mir);
}

let mut delete = DeleteTrivialEndRegions { seen_regions: &mut gather.seen_regions };
let mut delete = DeleteUserAssertTy;
delete.visit_mir(mir);
}
}
@@ -93,7 +109,19 @@ impl<'a, 'tcx> MutVisitor<'tcx> for DeleteTrivialEndRegions<'a> {
}

if delete_it {
statement.kind = StatementKind::Nop;
statement.make_nop();
}
self.super_statement(block, statement, location);
}
}

impl<'tcx> MutVisitor<'tcx> for DeleteUserAssertTy {
fn visit_statement(&mut self,
block: BasicBlock,
statement: &mut Statement<'tcx>,
location: Location) {
if let StatementKind::UserAssertTy(..) = statement.kind {
statement.make_nop();
}
self.super_statement(block, statement, location);
}
7 changes: 4 additions & 3 deletions src/librustc_mir/transform/mod.rs
Original file line number Diff line number Diff line change
@@ -25,7 +25,7 @@ use syntax_pos::Span;

pub mod add_validation;
pub mod add_moves_for_packed_drops;
pub mod clean_end_regions;
pub mod cleanup_post_borrowck;
pub mod check_unsafety;
pub mod simplify_branches;
pub mod simplify;
@@ -192,8 +192,9 @@ fn mir_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Stea

let mut mir = tcx.mir_built(def_id).steal();
run_passes![tcx, mir, def_id, 0;
// Remove all `EndRegion` statements that are not involved in borrows.
clean_end_regions::CleanEndRegions,
// Remove all `UserAssertTy` statements and all `EndRegion` statements that are not
// involved in borrows.
cleanup_post_borrowck::CleanupPostBorrowck,

// What we need to do constant evaluation.
simplify::SimplifyCfg::new("initial"),