Skip to content

Commit fdc18b3

Browse files
committedJan 22, 2018
Auto merge of rust-lang#47353 - nikomatsakis:nll-issue-47189, r=pnkfelix+nmatsakis
renumber regions in generators This fixes rust-lang#47189, but I think we still have to double check various things around how to treat generators in MIR type check + borrow check (e.g., what borrows should be invalidated by a `Suspend`? What consistency properties should type check be enforcing anyway around the "interior" type?) Also fixes rust-lang#47587 thanks to @spastorino's commit. r? @pnkfelix

File tree

8 files changed

+99
-8
lines changed

8 files changed

+99
-8
lines changed
 

‎src/librustc/mir/visit.rs

+9
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,13 @@ macro_rules! make_mir_visitor {
277277

278278
fn super_mir(&mut self,
279279
mir: & $($mutability)* Mir<'tcx>) {
280+
if let Some(yield_ty) = &$($mutability)* mir.yield_ty {
281+
self.visit_ty(yield_ty, TyContext::YieldTy(SourceInfo {
282+
span: mir.span,
283+
scope: ARGUMENT_VISIBILITY_SCOPE,
284+
}));
285+
}
286+
280287
// for best performance, we want to use an iterator rather
281288
// than a for-loop, to avoid calling Mir::invalidate for
282289
// each basic block.
@@ -852,6 +859,8 @@ pub enum TyContext {
852859
/// The return type of the function.
853860
ReturnTy(SourceInfo),
854861

862+
YieldTy(SourceInfo),
863+
855864
/// A type found at some location.
856865
Location(Location),
857866
}

‎src/librustc_mir/borrow_check/nll/constraint_generation.rs

+1
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
6969
fn visit_ty(&mut self, ty: &ty::Ty<'tcx>, ty_context: TyContext) {
7070
match ty_context {
7171
TyContext::ReturnTy(source_info) |
72+
TyContext::YieldTy(source_info) |
7273
TyContext::LocalDecl { source_info, .. } => {
7374
span_bug!(source_info.span,
7475
"should not be visiting outside of the CFG: {:?}",

‎src/librustc_mir/borrow_check/nll/renumber.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

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

93+
fn visit_generator_interior(&mut self,
94+
interior: &mut GeneratorInterior<'tcx>,
95+
location: Location) {
96+
debug!(
97+
"visit_generator_interior(interior={:?}, location={:?})",
98+
interior,
99+
location,
100+
);
101+
102+
let ty_context = TyContext::Location(location);
103+
*interior = self.renumber_regions(ty_context, interior);
104+
105+
debug!("visit_generator_interior: interior={:?}", interior);
106+
}
107+
93108
fn visit_closure_substs(&mut self, substs: &mut ClosureSubsts<'tcx>, location: Location) {
94109
debug!(
95110
"visit_closure_substs(substs={:?}, location={:?})",

‎src/librustc_mir/borrow_check/nll/type_check/input_output.rs

+9
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,15 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
6060
self.equate_normalized_input_or_output(start_position, input_ty, mir_input_ty);
6161
}
6262

63+
assert!(
64+
mir.yield_ty.is_some() && universal_regions.yield_ty.is_some() ||
65+
mir.yield_ty.is_none() && universal_regions.yield_ty.is_none()
66+
);
67+
if let Some(mir_yield_ty) = mir.yield_ty {
68+
let ur_yield_ty = universal_regions.yield_ty.unwrap();
69+
self.equate_normalized_input_or_output(start_position, ur_yield_ty, mir_yield_ty);
70+
}
71+
6372
// Return types are a bit more complex. They may contain existential `impl Trait`
6473
// types.
6574
debug!(

‎src/librustc_mir/borrow_check/nll/universal_regions.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ pub struct UniversalRegions<'tcx> {
9696
/// our special inference variable there, we would mess that up.
9797
pub region_bound_pairs: Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>,
9898

99+
pub yield_ty: Option<Ty<'tcx>>,
100+
99101
relations: UniversalRegionRelations,
100102
}
101103

@@ -505,6 +507,13 @@ impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> {
505507
num_universals
506508
);
507509

510+
let yield_ty = match defining_ty {
511+
DefiningTy::Generator(def_id, substs, _) => {
512+
Some(substs.generator_yield_ty(def_id, self.infcx.tcx))
513+
}
514+
_ => None,
515+
};
516+
508517
UniversalRegions {
509518
indices,
510519
fr_static,
@@ -516,6 +525,7 @@ impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> {
516525
unnormalized_output_ty,
517526
unnormalized_input_tys,
518527
region_bound_pairs: self.region_bound_pairs,
528+
yield_ty: yield_ty,
519529
relations: self.relations,
520530
}
521531
}
@@ -794,10 +804,12 @@ impl<'tcx> UniversalRegionIndices<'tcx> {
794804
/// during initialization. Relies on the `indices` map having been
795805
/// fully initialized.
796806
pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
797-
match r {
798-
ty::ReEarlyBound(..) | ty::ReStatic => *self.indices.get(&r).unwrap(),
799-
ty::ReVar(..) => r.to_region_vid(),
800-
_ => bug!("cannot convert `{:?}` to a region vid", r),
807+
if let ty::ReVar(..) = r {
808+
r.to_region_vid()
809+
} else {
810+
*self.indices.get(&r).unwrap_or_else(|| {
811+
bug!("cannot convert `{:?}` to a region vid", r)
812+
})
801813
}
802814
}
803815

‎src/librustc_mir/util/pretty.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ pub fn write_mir_intro<'a, 'gcx, 'tcx>(
518518
w: &mut Write,
519519
) -> io::Result<()> {
520520
write_mir_sig(tcx, src, mir, w)?;
521-
writeln!(w, " {{")?;
521+
writeln!(w, "{{")?;
522522

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

584-
write!(w, ") -> {}", mir.return_ty())
584+
write!(w, ") -> {}", mir.return_ty())?;
585585
}
586586
(hir::BodyOwnerKind::Const, _) | (hir::BodyOwnerKind::Static(_), _) | (_, Some(_)) => {
587587
assert_eq!(mir.arg_count, 0);
588-
write!(w, ": {} =", mir.return_ty())
588+
write!(w, ": {} =", mir.return_ty())?;
589589
}
590590
}
591+
592+
if let Some(yield_ty) = mir.yield_ty {
593+
writeln!(w)?;
594+
writeln!(w, "yields {}", yield_ty)?;
595+
}
596+
597+
Ok(())
591598
}
592599

593600
fn write_temp_decls(mir: &Mir, w: &mut Write) -> io::Result<()> {

‎src/test/run-pass/generator/yield-subtype.rs

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// revisions:lexical nll
12+
#![cfg_attr(nll, feature(nll))]
13+
1114
#![feature(generators)]
1215

1316
fn bar<'a>() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(generators, nll)]
12+
13+
// Test for issue #47189. Here, both `s` and `t` are live for the
14+
// generator's lifetime, but within the generator they have distinct
15+
// lifetimes. We accept this code -- even though the borrow extends
16+
// over a yield -- because the data that is borrowed (`*x`) is not
17+
// stored on the stack.
18+
19+
// must-compile-successfully
20+
21+
fn foo(x: &mut u32) {
22+
move || {
23+
let s = &mut *x;
24+
yield;
25+
*s += 1;
26+
27+
let t = &mut *x;
28+
yield;
29+
*t += 1;
30+
};
31+
}
32+
33+
fn main() {
34+
foo(&mut 0);
35+
}

0 commit comments

Comments
 (0)
Please sign in to comment.