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

renumber regions in generators #47353

Merged
merged 6 commits into from
Jan 22, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
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
9 changes: 9 additions & 0 deletions src/librustc/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,13 @@ macro_rules! make_mir_visitor {

fn super_mir(&mut self,
mir: & $($mutability)* Mir<'tcx>) {
if let Some(yield_ty) = &$($mutability)* mir.yield_ty {
self.visit_ty(yield_ty, TyContext::YieldTy(SourceInfo {
span: mir.span,
scope: ARGUMENT_VISIBILITY_SCOPE,
}));
}

// for best performance, we want to use an iterator rather
// than a for-loop, to avoid calling Mir::invalidate for
// each basic block.
Expand Down Expand Up @@ -852,6 +859,8 @@ pub enum TyContext {
/// The return type of the function.
ReturnTy(SourceInfo),

YieldTy(SourceInfo),

/// A type found at some location.
Location(Location),
}
Expand Down
1 change: 1 addition & 0 deletions src/librustc_mir/borrow_check/nll/constraint_generation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
fn visit_ty(&mut self, ty: &ty::Ty<'tcx>, ty_context: TyContext) {
match ty_context {
TyContext::ReturnTy(source_info) |
TyContext::YieldTy(source_info) |
TyContext::LocalDecl { source_info, .. } => {
span_bug!(source_info.span,
"should not be visiting outside of the CFG: {:?}",
Expand Down
17 changes: 16 additions & 1 deletion src/librustc_mir/borrow_check/nll/renumber.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// except according to those terms.

use rustc::ty::subst::Substs;
use rustc::ty::{self, ClosureSubsts, Ty, TypeFoldable};
use rustc::ty::{self, ClosureSubsts, GeneratorInterior, Ty, TypeFoldable};
use rustc::mir::{BasicBlock, Location, Mir, Statement, StatementKind};
use rustc::mir::visit::{MutVisitor, TyContext};
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
Expand Down Expand Up @@ -90,6 +90,21 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
*constant = self.renumber_regions(ty_context, &*constant);
}

fn visit_generator_interior(&mut self,
interior: &mut GeneratorInterior<'tcx>,
location: Location) {
debug!(
"visit_generator_interior(interior={:?}, location={:?})",
interior,
location,
);

let ty_context = TyContext::Location(location);
*interior = self.renumber_regions(ty_context, interior);

debug!("visit_generator_interior: interior={:?}", interior);
}

fn visit_closure_substs(&mut self, substs: &mut ClosureSubsts<'tcx>, location: Location) {
debug!(
"visit_closure_substs(substs={:?}, location={:?})",
Expand Down
9 changes: 9 additions & 0 deletions src/librustc_mir/borrow_check/nll/type_check/input_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
self.equate_normalized_input_or_output(start_position, input_ty, mir_input_ty);
}

assert!(
mir.yield_ty.is_some() && universal_regions.yield_ty.is_some() ||
mir.yield_ty.is_none() && universal_regions.yield_ty.is_none()
);
if let Some(mir_yield_ty) = mir.yield_ty {
let ur_yield_ty = universal_regions.yield_ty.unwrap();
self.equate_normalized_input_or_output(start_position, ur_yield_ty, mir_yield_ty);
}

// Return types are a bit more complex. They may contain existential `impl Trait`
// types.
debug!(
Expand Down
20 changes: 16 additions & 4 deletions src/librustc_mir/borrow_check/nll/universal_regions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ pub struct UniversalRegions<'tcx> {
/// our special inference variable there, we would mess that up.
pub region_bound_pairs: Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>,

pub yield_ty: Option<Ty<'tcx>>,

relations: UniversalRegionRelations,
}

Expand Down Expand Up @@ -505,6 +507,13 @@ impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> {
num_universals
);

let yield_ty = match defining_ty {
DefiningTy::Generator(def_id, substs, _) => {
Some(substs.generator_yield_ty(def_id, self.infcx.tcx))
}
_ => None,
};

UniversalRegions {
indices,
fr_static,
Expand All @@ -516,6 +525,7 @@ impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> {
unnormalized_output_ty,
unnormalized_input_tys,
region_bound_pairs: self.region_bound_pairs,
yield_ty: yield_ty,
relations: self.relations,
}
}
Expand Down Expand Up @@ -799,10 +809,12 @@ impl<'tcx> UniversalRegionIndices<'tcx> {
/// during initialization. Relies on the `indices` map having been
/// fully initialized.
pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
match r {
ty::ReEarlyBound(..) | ty::ReStatic => *self.indices.get(&r).unwrap(),
ty::ReVar(..) => r.to_region_vid(),
_ => bug!("cannot convert `{:?}` to a region vid", r),
if let ty::ReVar(..) = r {
r.to_region_vid()
} else {
*self.indices.get(&r).unwrap_or_else(|| {
bug!("cannot convert `{:?}` to a region vid", r)
})
}
}

Expand Down
13 changes: 10 additions & 3 deletions src/librustc_mir/util/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ pub fn write_mir_intro<'a, 'gcx, 'tcx>(
w: &mut Write,
) -> io::Result<()> {
write_mir_sig(tcx, src, mir, w)?;
writeln!(w, " {{")?;
writeln!(w, "{{")?;

// construct a scope tree and write it out
let mut scope_tree: FxHashMap<VisibilityScope, Vec<VisibilityScope>> = FxHashMap();
Expand Down Expand Up @@ -585,13 +585,20 @@ fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut Write) -> io::R
write!(w, "{:?}: {}", Place::Local(arg), mir.local_decls[arg].ty)?;
}

write!(w, ") -> {}", mir.return_ty())
write!(w, ") -> {}", mir.return_ty())?;
}
(hir::BodyOwnerKind::Const, _) | (hir::BodyOwnerKind::Static(_), _) | (_, Some(_)) => {
assert_eq!(mir.arg_count, 0);
write!(w, ": {} =", mir.return_ty())
write!(w, ": {} =", mir.return_ty())?;
}
}

if let Some(yield_ty) = mir.yield_ty {
writeln!(w)?;
writeln!(w, "yields {}", yield_ty)?;
}

Ok(())
}

fn write_temp_decls(mir: &Mir, w: &mut Write) -> io::Result<()> {
Expand Down
3 changes: 3 additions & 0 deletions src/test/run-pass/generator/yield-subtype.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// revisions:lexical nll
#![cfg_attr(nll, feature(nll))]

#![feature(generators)]

fn bar<'a>() {
Expand Down
35 changes: 35 additions & 0 deletions src/test/ui/nll/generator-distinct-lifetime.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(generators, nll)]

// Test for issue #47189. Here, both `s` and `t` are live for the
// generator's lifetime, but within the generator they have distinct
// lifetimes. We accept this code -- even though the borrow extends
// over a yield -- because the data that is borrowed (`*x`) is not
// stored on the stack.

// must-compile-successfully

fn foo(x: &mut u32) {
move || {
let s = &mut *x;
yield;
*s += 1;

let t = &mut *x;
yield;
*t += 1;
};
}

fn main() {
foo(&mut 0);
}