mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 00:03:43 +00:00
Initial pass review comments
This commit is contained in:
parent
c25ddf21f1
commit
352577f4bb
@ -320,7 +320,7 @@ for ::middle::const_val::ConstVal<'tcx> {
|
||||
|
||||
impl_stable_hash_for!(struct ty::ClosureSubsts<'tcx> { substs });
|
||||
|
||||
impl_stable_hash_for!(tuple_struct ty::GeneratorInterior<'tcx> { ty });
|
||||
impl_stable_hash_for!(struct ty::GeneratorInterior<'tcx> { witness });
|
||||
|
||||
impl_stable_hash_for!(struct ty::GenericPredicates<'tcx> {
|
||||
parent,
|
||||
|
@ -411,8 +411,13 @@ pub struct LocalDecl<'tcx> {
|
||||
/// True if this corresponds to a user-declared local variable.
|
||||
pub is_user_variable: bool,
|
||||
|
||||
/// True if this an internal local.
|
||||
/// True if this is an internal local.
|
||||
/// Such locals are not checked against the legal types in a generator.
|
||||
///
|
||||
/// Scalar state variables created by optimizations (e.g. nonzeroing drop
|
||||
/// flags) should not be included in generator OIBIT computations.
|
||||
/// Therefore, we mark them as `internal` so we can ignore them when
|
||||
/// sanity-checking the OIBIT list.
|
||||
pub internal: bool,
|
||||
|
||||
/// Type of this local.
|
||||
|
@ -2126,7 +2126,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
ty::TyGenerator(def_id, ref substs, interior) => {
|
||||
let witness = iter::once(interior.witness());
|
||||
let witness = iter::once(interior.witness);
|
||||
substs.upvar_tys(def_id, self.tcx()).chain(witness).collect()
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,7 @@ impl FlagComputation {
|
||||
self.add_flags(TypeFlags::HAS_TY_CLOSURE);
|
||||
self.add_flags(TypeFlags::HAS_LOCAL_NAMES);
|
||||
self.add_substs(&substs.substs);
|
||||
self.add_ty(interior.witness());
|
||||
self.add_ty(interior.witness);
|
||||
}
|
||||
|
||||
&ty::TyClosure(_, ref substs) => {
|
||||
|
@ -122,7 +122,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
// But generators can have additional interior types
|
||||
self.compute_components(interior.witness(), out);
|
||||
self.compute_components(interior.witness, out);
|
||||
}
|
||||
|
||||
// OutlivesTypeParameterEnv -- the actual checking that `X:'a`
|
||||
|
@ -531,7 +531,7 @@ impl<'tcx> Relate<'tcx> for ty::GeneratorInterior<'tcx> {
|
||||
-> RelateResult<'tcx, ty::GeneratorInterior<'tcx>>
|
||||
where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
|
||||
{
|
||||
let interior = relation.relate(&a.witness(), &b.witness())?;
|
||||
let interior = relation.relate(&a.witness, &b.witness)?;
|
||||
Ok(ty::GeneratorInterior::new(interior))
|
||||
}
|
||||
}
|
||||
|
@ -232,8 +232,8 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ClosureSubsts<'a> {
|
||||
impl<'a, 'tcx> Lift<'tcx> for ty::GeneratorInterior<'a> {
|
||||
type Lifted = ty::GeneratorInterior<'tcx>;
|
||||
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
|
||||
tcx.lift(&self.witness()).map(|witness| {
|
||||
ty::GeneratorInterior(witness)
|
||||
tcx.lift(&self.witness).map(|witness| {
|
||||
ty::GeneratorInterior { witness }
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -737,11 +737,11 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ClosureSubsts<'tcx> {
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::GeneratorInterior<'tcx> {
|
||||
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
||||
ty::GeneratorInterior(self.0.fold_with(folder))
|
||||
ty::GeneratorInterior::new(self.witness.fold_with(folder))
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.0.visit_with(visitor)
|
||||
self.witness.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -295,19 +295,17 @@ impl<'a, 'gcx, 'tcx> ClosureSubsts<'tcx> {
|
||||
/// The state transformation MIR pass may only produce layouts which mention types in this tuple.
|
||||
/// Upvars are not counted here.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub struct GeneratorInterior<'tcx>(pub Ty<'tcx>);
|
||||
pub struct GeneratorInterior<'tcx> {
|
||||
pub witness: Ty<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> GeneratorInterior<'tcx> {
|
||||
pub fn new(witness: Ty<'tcx>) -> GeneratorInterior<'tcx> {
|
||||
GeneratorInterior(witness)
|
||||
}
|
||||
|
||||
pub fn witness(&self) -> Ty<'tcx> {
|
||||
self.0
|
||||
GeneratorInterior { witness }
|
||||
}
|
||||
|
||||
pub fn as_slice(&self) -> &'tcx Slice<Ty<'tcx>> {
|
||||
match self.0.sty {
|
||||
match self.witness.sty {
|
||||
ty::TyTuple(s, _) => s,
|
||||
_ => bug!(),
|
||||
}
|
||||
@ -638,10 +636,8 @@ pub struct GenSig<'tcx> {
|
||||
pub return_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[allow(warnings)]
|
||||
pub type PolyGenSig<'tcx> = Binder<GenSig<'tcx>>;
|
||||
|
||||
#[allow(warnings)]
|
||||
impl<'tcx> PolyGenSig<'tcx> {
|
||||
pub fn yield_ty(&self) -> ty::Binder<Ty<'tcx>> {
|
||||
self.map_bound_ref(|sig| sig.yield_ty)
|
||||
|
@ -570,7 +570,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
ty::TyGenerator(def_id, substs, interior) => {
|
||||
substs.upvar_tys(def_id, self).chain(iter::once(interior.witness())).map(|ty| {
|
||||
substs.upvar_tys(def_id, self).chain(iter::once(interior.witness)).map(|ty| {
|
||||
self.dtorck_constraint_for_ty(span, for_ty, depth+1, ty)
|
||||
}).collect()
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
|
||||
}
|
||||
ty::TyGenerator(_, ref substs, ref interior) => {
|
||||
stack.extend(substs.substs.types().rev());
|
||||
stack.push(interior.witness());
|
||||
stack.push(interior.witness);
|
||||
}
|
||||
ty::TyTuple(ts, _) => {
|
||||
stack.extend(ts.iter().cloned().rev());
|
||||
|
@ -717,7 +717,7 @@ impl<'tcx> fmt::Display for ty::TraitRef<'tcx> {
|
||||
|
||||
impl<'tcx> fmt::Display for ty::GeneratorInterior<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
self.witness.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,9 +9,11 @@
|
||||
// except according to those terms.
|
||||
|
||||
use std::fmt;
|
||||
use std::iter;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::ops::{Deref, DerefMut, Range};
|
||||
use std::slice;
|
||||
use bitslice::{BitSlice, Word};
|
||||
use bitslice::{bitwise, Union, Subtract};
|
||||
use indexed_vec::Idx;
|
||||
@ -161,4 +163,41 @@ impl<T: Idx> IdxSet<T> {
|
||||
pub fn subtract(&mut self, other: &IdxSet<T>) -> bool {
|
||||
bitwise(self.words_mut(), other.words(), &Subtract)
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> Iter<T> {
|
||||
Iter {
|
||||
cur: None,
|
||||
iter: self.words().iter().enumerate(),
|
||||
_pd: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Iter<'a, T: Idx> {
|
||||
cur: Option<(Word, usize)>,
|
||||
iter: iter::Enumerate<slice::Iter<'a, Word>>,
|
||||
_pd: PhantomData<fn(&T)>,
|
||||
}
|
||||
|
||||
impl<'a, T: Idx> Iterator for Iter<'a, T> {
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<T> {
|
||||
let word_bits = mem::size_of::<Word>() * 8;
|
||||
loop {
|
||||
if let Some((ref mut word, offset)) = self.cur {
|
||||
let bit_pos = word.trailing_zeros();
|
||||
if bit_pos != word_bits as u32 {
|
||||
let bit = 1 << bit_pos;
|
||||
*word ^= bit;
|
||||
return Some(T::new(bit + offset))
|
||||
}
|
||||
}
|
||||
|
||||
match self.iter.next() {
|
||||
Some((i, word)) => self.cur = Some((*word, word_bits * i)),
|
||||
None => return None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -703,57 +703,57 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
let region = cx.tcx.mk_region(region);
|
||||
|
||||
let self_expr = if let ty::TyClosure(..) = closure_ty.sty {
|
||||
match cx.tcx.closure_kind(closure_def_id) {
|
||||
ty::ClosureKind::Fn => {
|
||||
let ref_closure_ty = cx.tcx.mk_ref(region,
|
||||
ty::TypeAndMut {
|
||||
ty: closure_ty,
|
||||
mutbl: hir::MutImmutable,
|
||||
});
|
||||
Expr {
|
||||
ty: closure_ty,
|
||||
temp_lifetime: temp_lifetime,
|
||||
span: expr.span,
|
||||
kind: ExprKind::Deref {
|
||||
arg: Expr {
|
||||
ty: ref_closure_ty,
|
||||
temp_lifetime: temp_lifetime,
|
||||
span: expr.span,
|
||||
kind: ExprKind::SelfRef,
|
||||
}
|
||||
.to_ref(),
|
||||
},
|
||||
match cx.tcx.closure_kind(closure_def_id) {
|
||||
ty::ClosureKind::Fn => {
|
||||
let ref_closure_ty = cx.tcx.mk_ref(region,
|
||||
ty::TypeAndMut {
|
||||
ty: closure_ty,
|
||||
mutbl: hir::MutImmutable,
|
||||
});
|
||||
Expr {
|
||||
ty: closure_ty,
|
||||
temp_lifetime: temp_lifetime,
|
||||
span: expr.span,
|
||||
kind: ExprKind::Deref {
|
||||
arg: Expr {
|
||||
ty: ref_closure_ty,
|
||||
temp_lifetime: temp_lifetime,
|
||||
span: expr.span,
|
||||
kind: ExprKind::SelfRef,
|
||||
}
|
||||
.to_ref(),
|
||||
},
|
||||
}
|
||||
}
|
||||
ty::ClosureKind::FnMut => {
|
||||
let ref_closure_ty = cx.tcx.mk_ref(region,
|
||||
ty::TypeAndMut {
|
||||
ty: closure_ty,
|
||||
mutbl: hir::MutMutable,
|
||||
});
|
||||
Expr {
|
||||
ty: closure_ty,
|
||||
temp_lifetime: temp_lifetime,
|
||||
span: expr.span,
|
||||
kind: ExprKind::Deref {
|
||||
arg: Expr {
|
||||
ty: ref_closure_ty,
|
||||
temp_lifetime: temp_lifetime,
|
||||
span: expr.span,
|
||||
kind: ExprKind::SelfRef,
|
||||
}.to_ref(),
|
||||
},
|
||||
}
|
||||
}
|
||||
ty::ClosureKind::FnOnce => {
|
||||
Expr {
|
||||
ty: closure_ty,
|
||||
temp_lifetime: temp_lifetime,
|
||||
span: expr.span,
|
||||
kind: ExprKind::SelfRef,
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::ClosureKind::FnMut => {
|
||||
let ref_closure_ty = cx.tcx.mk_ref(region,
|
||||
ty::TypeAndMut {
|
||||
ty: closure_ty,
|
||||
mutbl: hir::MutMutable,
|
||||
});
|
||||
Expr {
|
||||
ty: closure_ty,
|
||||
temp_lifetime: temp_lifetime,
|
||||
span: expr.span,
|
||||
kind: ExprKind::Deref {
|
||||
arg: Expr {
|
||||
ty: ref_closure_ty,
|
||||
temp_lifetime: temp_lifetime,
|
||||
span: expr.span,
|
||||
kind: ExprKind::SelfRef,
|
||||
}.to_ref(),
|
||||
},
|
||||
}
|
||||
}
|
||||
ty::ClosureKind::FnOnce => {
|
||||
Expr {
|
||||
ty: closure_ty,
|
||||
temp_lifetime: temp_lifetime,
|
||||
span: expr.span,
|
||||
kind: ExprKind::SelfRef,
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Expr {
|
||||
ty: closure_ty,
|
||||
|
@ -10,8 +10,6 @@
|
||||
|
||||
//! Transforms generators into state machines
|
||||
|
||||
#![allow(warnings)]
|
||||
|
||||
use rustc::hir;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
@ -23,11 +21,11 @@ use rustc::ty::subst::{Kind, Substs};
|
||||
use util::dump_mir;
|
||||
use util::liveness;
|
||||
use rustc_const_math::ConstInt;
|
||||
use rustc_data_structures::bitvec::BitVector;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use std::collections::HashMap;
|
||||
use std::borrow::Cow;
|
||||
use std::iter::once;
|
||||
use std::mem;
|
||||
use syntax::ast::NodeId;
|
||||
use transform::simplify;
|
||||
|
||||
@ -150,7 +148,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx> {
|
||||
}
|
||||
});
|
||||
|
||||
ret_val.map(|(state_idx, resume, v, drop)| {
|
||||
if let Some((state_idx, resume, v, drop)) = ret_val {
|
||||
let bb_idx = {
|
||||
let bb_targets = &mut self.bb_targets;
|
||||
let bb_target = &mut self.bb_target_count;
|
||||
@ -168,54 +166,12 @@ impl<'a, 'tcx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx> {
|
||||
self.make_state(state_idx, v)),
|
||||
});
|
||||
data.terminator.as_mut().unwrap().kind = TerminatorKind::Return;
|
||||
});
|
||||
}
|
||||
|
||||
self.super_basic_block_data(block, data);
|
||||
}
|
||||
}
|
||||
|
||||
fn get_body_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: NodeId) -> (bool, hir::BodyId) {
|
||||
// Figure out what primary body this item has.
|
||||
match tcx.hir.get(node_id) {
|
||||
hir::map::NodeItem(item) => {
|
||||
match item.node {
|
||||
hir::ItemConst(_, body) |
|
||||
hir::ItemStatic(_, _, body) |
|
||||
hir::ItemFn(.., body) => (false, body),
|
||||
_ => bug!(),
|
||||
}
|
||||
}
|
||||
hir::map::NodeTraitItem(item) => {
|
||||
match item.node {
|
||||
hir::TraitItemKind::Const(_, Some(body)) |
|
||||
hir::TraitItemKind::Method(_,
|
||||
hir::TraitMethod::Provided(body)) => (false, body),
|
||||
_ => bug!(),
|
||||
}
|
||||
}
|
||||
hir::map::NodeImplItem(item) => {
|
||||
match item.node {
|
||||
hir::ImplItemKind::Const(_, body) |
|
||||
hir::ImplItemKind::Method(_, body) => (false, body),
|
||||
_ => bug!(),
|
||||
}
|
||||
}
|
||||
hir::map::NodeExpr(expr) => {
|
||||
// FIXME(eddyb) Closures should have separate
|
||||
// function definition IDs and expression IDs.
|
||||
// Type-checking should not let closures get
|
||||
// this far in a constant position.
|
||||
// Assume that everything other than closures
|
||||
// is a constant "initializer" expression.
|
||||
match expr.node {
|
||||
hir::ExprClosure(_, _, body, _, _) => (true, body),
|
||||
_ => (false, hir::BodyId { node_id: expr.id })
|
||||
}
|
||||
}
|
||||
_ => bug!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn ensure_generator_state_argument<'a, 'tcx>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
node_id: NodeId,
|
||||
@ -281,7 +237,6 @@ fn replace_result_variable<'tcx>(ret_ty: Ty<'tcx>,
|
||||
fn locals_live_across_suspend_points<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
mir: &Mir<'tcx>,
|
||||
source: MirSource) -> liveness::LocalSet {
|
||||
use rustc_data_structures::indexed_set::IdxSetBuf;
|
||||
let mut set = liveness::LocalSet::new_empty(mir.local_decls.len());
|
||||
let result = liveness::liveness_of_locals(mir);
|
||||
liveness::dump_mir(tcx, "generator_liveness", source, mir, &result);
|
||||
@ -299,18 +254,12 @@ fn locals_live_across_suspend_points<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
}
|
||||
|
||||
fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
def_id: DefId,
|
||||
source: MirSource,
|
||||
interior: GeneratorInterior<'tcx>,
|
||||
mir: &mut Mir<'tcx>)
|
||||
-> (HashMap<Local, (Ty<'tcx>, usize)>, GeneratorLayout<'tcx>)
|
||||
{
|
||||
let source_info = SourceInfo {
|
||||
span: mir.span,
|
||||
scope: ARGUMENT_VISIBILITY_SCOPE,
|
||||
};
|
||||
|
||||
let mut live_locals = locals_live_across_suspend_points(tcx, mir, source);
|
||||
let live_locals = locals_live_across_suspend_points(tcx, mir, source);
|
||||
|
||||
let allowed = tcx.erase_regions(&interior.as_slice());
|
||||
|
||||
@ -319,34 +268,23 @@ fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
continue;
|
||||
}
|
||||
if !allowed.contains(&decl.ty) {
|
||||
tcx.sess.span_warn(mir.span,
|
||||
&format!("generator contains type {} in MIR, but typeck only knows about {}",
|
||||
decl.ty,
|
||||
interior));
|
||||
span_bug!(mir.span,
|
||||
"Broken MIR: generator contains type {} in MIR, \
|
||||
but typeck only knows about {}",
|
||||
decl.ty,
|
||||
interior);
|
||||
}
|
||||
}
|
||||
|
||||
let upvar_len = mir.upvar_decls.len();
|
||||
let live_decls : Vec<_> = mir.local_decls
|
||||
.iter_enumerated_mut()
|
||||
.filter(|&(local, _)| live_locals.contains(&local))
|
||||
.collect();
|
||||
|
||||
let mut remap = HashMap::new();
|
||||
let unit = tcx.mk_nil();
|
||||
let mut vars: Vec<_> = live_decls.into_iter().enumerate().map(|(idx, (local, decl))| {
|
||||
let var = decl.clone();
|
||||
*decl = LocalDecl {
|
||||
mutability: Mutability::Mut,
|
||||
ty: unit,
|
||||
name: None,
|
||||
source_info,
|
||||
internal: false,
|
||||
is_user_variable: false,
|
||||
};
|
||||
remap.insert(local, (var.ty, upvar_len + 1 + idx));
|
||||
var
|
||||
}).collect();
|
||||
let dummy_local = LocalDecl::new_internal(tcx.mk_nil(), mir.span);
|
||||
let live_decls = live_locals.iter().map(|local| {
|
||||
let var = mem::replace(&mut mir.local_decls[local], dummy_local.clone());
|
||||
(local, var)
|
||||
});
|
||||
let (remap, vars) = live_decls.enumerate().map(|(idx, (local, var))| {
|
||||
((local, (var.ty, upvar_len + 1 + idx)), var)
|
||||
}).unzip();
|
||||
|
||||
let layout = GeneratorLayout {
|
||||
fields: vars
|
||||
@ -369,7 +307,7 @@ fn insert_entry_point<'tcx>(mir: &mut Mir<'tcx>,
|
||||
fn elaborate_generator_drops<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
def_id: DefId,
|
||||
mir: &mut Mir<'tcx>) {
|
||||
use util::elaborate_drops::{elaborate_drop, Unwind, DropElaborator, DropStyle, DropFlagMode};
|
||||
use util::elaborate_drops::{elaborate_drop, Unwind};
|
||||
use util::patch::MirPatch;
|
||||
use shim::DropShimElaborator;
|
||||
|
||||
@ -418,7 +356,6 @@ fn elaborate_generator_drops<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
fn generate_drop<'a, 'tcx>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
transform: &TransformVisitor<'a, 'tcx>,
|
||||
node_id: NodeId,
|
||||
def_id: DefId,
|
||||
source: MirSource,
|
||||
gen_ty: Ty<'tcx>,
|
||||
@ -439,7 +376,7 @@ fn generate_drop<'a, 'tcx>(
|
||||
is_cleanup: false,
|
||||
});
|
||||
|
||||
let mut cases: Vec<_> = transform.bb_targets.iter().filter_map(|(&(r, u), &s)| {
|
||||
let mut cases: Vec<_> = transform.bb_targets.iter().filter_map(|(&(_, u), &s)| {
|
||||
u.map(|d| (s, d))
|
||||
}).collect();
|
||||
|
||||
@ -581,10 +518,9 @@ fn insert_resume_after_return<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
cleanup
|
||||
}
|
||||
|
||||
fn generate_resume<'a, 'tcx>(
|
||||
fn generate_entry_point<'a, 'tcx>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
mut transform: TransformVisitor<'a, 'tcx>,
|
||||
node_id: NodeId,
|
||||
def_id: DefId,
|
||||
source: MirSource,
|
||||
cleanup: Option<BasicBlock>,
|
||||
@ -721,7 +657,7 @@ impl MirPass for StateTransform {
|
||||
|
||||
let new_ret_local = replace_result_variable(ret_ty, mir);
|
||||
|
||||
let (remap, layout) = compute_layout(tcx, def_id, source, interior, mir);
|
||||
let (remap, layout) = compute_layout(tcx, source, interior, mir);
|
||||
|
||||
let tail_block = BasicBlock::new(mir.basic_blocks().len());
|
||||
|
||||
@ -763,7 +699,6 @@ impl MirPass for StateTransform {
|
||||
|
||||
generate_drop(tcx,
|
||||
&transform,
|
||||
node_id,
|
||||
def_id,
|
||||
source,
|
||||
gen_ty,
|
||||
@ -772,6 +707,6 @@ impl MirPass for StateTransform {
|
||||
|
||||
mir.generator_drop = Some(box drop_impl);
|
||||
|
||||
generate_resume(tcx, transform, node_id, def_id, source, arg_cleanup, mir);
|
||||
generate_entry_point(tcx, transform, def_id, source, arg_cleanup, mir);
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,29 @@
|
||||
// except according to those terms.
|
||||
|
||||
//! Liveness analysis which computes liveness of MIR local variables at the boundary of basic blocks
|
||||
//!
|
||||
//! This analysis considers references as being used only at the point of the
|
||||
//! borrow. This means that this does not track uses because of references that
|
||||
//! already exist:
|
||||
//!
|
||||
//! ```Rust
|
||||
//! fn foo() {
|
||||
//! x = 0;
|
||||
//! // `x` is live here
|
||||
//! GLOBAL = &x: *const u32;
|
||||
//! // but not here, even while it can be accessed through `GLOBAL`.
|
||||
//! foo();
|
||||
//! x = 1;
|
||||
//! // `x` is live again here, because it is assigned to `OTHER_GLOBAL`
|
||||
//! OTHER_GLOBAL = &x: *const u32;
|
||||
//! // ...
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! This means that users of this analysis still have to check whether
|
||||
//! pre-existing references can be used to access the value (e.g. at movable
|
||||
//! generator yield points, all pre-existing references are invalidated, so this
|
||||
//! doesn't matter).
|
||||
|
||||
use rustc::mir::*;
|
||||
use rustc::mir::visit::{LvalueContext, Visitor};
|
||||
@ -60,7 +83,7 @@ impl<'tcx> Visitor<'tcx> for BlockInfoVisitor {
|
||||
// Borrows only consider their local used at the point of the borrow.
|
||||
// This won't affect the results since we use this analysis for generators
|
||||
// and we only care about the result at suspension points. Borrows cannot
|
||||
// cross suspension points so this behavoir is unproblematic.
|
||||
// cross suspension points so this behavior is unproblematic.
|
||||
LvalueContext::Borrow { .. } |
|
||||
|
||||
LvalueContext::Inspect |
|
||||
|
@ -348,7 +348,9 @@ fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut Write)
|
||||
|
||||
write!(w, ") -> {}", mir.return_ty)
|
||||
}
|
||||
_ => {
|
||||
MirSource::Const(..) |
|
||||
MirSource::Static(..) |
|
||||
MirSource::Promoted(..) => {
|
||||
assert_eq!(mir.arg_count, 0);
|
||||
write!(w, ": {} =", mir.return_ty)
|
||||
}
|
||||
|
@ -287,9 +287,7 @@ fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance
|
||||
|
||||
let hash = get_symbol_hash(tcx, Some(def_id), instance_ty, Some(substs));
|
||||
|
||||
let buffer = SymbolPathBuffer::from_interned(tcx.def_symbol_name(def_id));
|
||||
|
||||
buffer.finish(hash)
|
||||
SymbolPathBuffer::from_interned(tcx.def_symbol_name(def_id)).finish(hash)
|
||||
}
|
||||
|
||||
// Follow C++ namespace-mangling style, see
|
||||
|
@ -8,14 +8,15 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use log;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||
use rustc::hir::{self, Body, Pat, PatKind, Expr};
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::ty::Ty;
|
||||
use rustc::middle::region::{RegionMaps, CodeExtent};
|
||||
use util::nodemap::FxHashSet;
|
||||
use rustc::ty::Ty;
|
||||
use std::rc::Rc;
|
||||
use super::FnCtxt;
|
||||
use util::nodemap::FxHashSet;
|
||||
|
||||
struct InteriorVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
|
||||
@ -28,36 +29,34 @@ impl<'a, 'gcx, 'tcx> InteriorVisitor<'a, 'gcx, 'tcx> {
|
||||
use syntax_pos::DUMMY_SP;
|
||||
|
||||
if scope.map(|s| self.fcx.tcx.yield_in_extent(s).is_some()).unwrap_or(true) {
|
||||
if self.fcx.tcx.sess.verbose() {
|
||||
if log_enabled!(log::LogLevel::Debug) {
|
||||
if let Some(s) = scope {
|
||||
self.fcx.tcx.sess.span_warn(s.span(&self.fcx.tcx.hir).unwrap_or(DUMMY_SP),
|
||||
&format!("type in generator with scope = {:?}, type = {:?}",
|
||||
scope,
|
||||
self.fcx.resolve_type_vars_if_possible(&ty)));
|
||||
let span = s.span(&self.fcx.tcx.hir).unwrap_or(DUMMY_SP);
|
||||
debug!("type in generator with scope = {:?}, type = {:?}, span = {:?}",
|
||||
scope,
|
||||
self.fcx.resolve_type_vars_if_possible(&ty),
|
||||
span);
|
||||
} else {
|
||||
self.fcx.tcx.sess.span_warn(DUMMY_SP,
|
||||
&format!("type in generator WITHOUT scope, type = {:?}",
|
||||
self.fcx.resolve_type_vars_if_possible(&ty)));
|
||||
debug!("type in generator WITHOUT scope, type = {:?}",
|
||||
self.fcx.resolve_type_vars_if_possible(&ty));
|
||||
}
|
||||
if let Some(e) = expr {
|
||||
self.fcx.tcx.sess.span_warn(e.span,
|
||||
&format!("type from expression: {:?}", e));
|
||||
debug!("type from expression: {:?}, span={:?}", e, e.span);
|
||||
}
|
||||
}
|
||||
self.types.insert(ty);
|
||||
} else if self.fcx.tcx.sess.verbose() {
|
||||
} else {
|
||||
if let Some(e) = expr {
|
||||
self.fcx.tcx.sess.span_warn(e.span,
|
||||
&format!("NO type from expression: {:?}", e));
|
||||
debug!("NO type from expression: {:?}, span = {:?}", e, e.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn find_interior<'a, 'gcx, 'tcx>(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
|
||||
def_id: DefId,
|
||||
body_id: hir::BodyId,
|
||||
witness: Ty<'tcx>) {
|
||||
pub fn resolve_interior<'a, 'gcx, 'tcx>(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
|
||||
def_id: DefId,
|
||||
body_id: hir::BodyId,
|
||||
witness: Ty<'tcx>) {
|
||||
let body = fcx.tcx.hir.body(body_id);
|
||||
let mut visitor = InteriorVisitor {
|
||||
fcx,
|
||||
@ -74,10 +73,7 @@ pub fn find_interior<'a, 'gcx, 'tcx>(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
|
||||
|
||||
let tuple = fcx.tcx.intern_tup(&types, false);
|
||||
|
||||
if fcx.tcx.sess.verbose() {
|
||||
fcx.tcx.sess.span_warn(body.value.span,
|
||||
&format!("Types in generator {:?}", tuple));
|
||||
}
|
||||
debug!("Types in generator {:?}, span = {:?}", tuple, body.value.span);
|
||||
|
||||
// Unify the tuple with the witness
|
||||
match fcx.at(&fcx.misc(body.value.span), fcx.param_env).eq(witness, tuple) {
|
||||
|
@ -892,7 +892,7 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
fcx.closure_analyze(body);
|
||||
fcx.select_obligations_where_possible();
|
||||
fcx.check_casts();
|
||||
fcx.find_generator_interiors(def_id);
|
||||
fcx.resolve_generator_interiors(def_id);
|
||||
fcx.select_all_obligations_or_error();
|
||||
|
||||
if fn_decl.is_some() {
|
||||
@ -2107,10 +2107,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn find_generator_interiors(&self, def_id: DefId) {
|
||||
fn resolve_generator_interiors(&self, def_id: DefId) {
|
||||
let mut deferred_generator_interiors = self.deferred_generator_interiors.borrow_mut();
|
||||
for (body_id, witness) in deferred_generator_interiors.drain(..) {
|
||||
generator_interior::find_interior(self, def_id, body_id, witness);
|
||||
generator_interior::resolve_interior(self, def_id, body_id, witness);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2677,8 +2677,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
pub fn check_expr_has_type_or_error(&self,
|
||||
expr: &'gcx hir::Expr,
|
||||
expected: Ty<'tcx>) -> Ty<'tcx> {
|
||||
expr: &'gcx hir::Expr,
|
||||
expected: Ty<'tcx>) -> Ty<'tcx> {
|
||||
self.check_expr_meets_expectation_or_error(expr, ExpectHasType(expected))
|
||||
}
|
||||
|
||||
@ -3138,13 +3138,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
return field_ty;
|
||||
}
|
||||
|
||||
if tuple_like {
|
||||
if tuple_like {
|
||||
type_error_struct!(self.tcx().sess, expr.span, expr_t, E0612,
|
||||
"attempted out-of-bounds tuple index `{}` on type `{}`",
|
||||
idx.node, expr_t).emit();
|
||||
} else {
|
||||
"attempted out-of-bounds tuple index `{}` on type `{}`",
|
||||
idx.node, expr_t).emit();
|
||||
} else {
|
||||
self.no_such_field_err(expr.span, idx.node, expr_t).emit();
|
||||
}
|
||||
}
|
||||
|
||||
self.tcx().types.err
|
||||
}
|
||||
@ -3733,14 +3733,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
// Only check this if not in an `if` condition, as the
|
||||
// mistyped comparison help is more appropriate.
|
||||
if !self.tcx.expr_is_lval(&lhs) {
|
||||
struct_span_err!(
|
||||
self.tcx.sess, expr.span, E0070,
|
||||
"invalid left-hand side expression")
|
||||
.span_label(
|
||||
expr.span,
|
||||
"left-hand of expression not valid")
|
||||
.emit();
|
||||
}
|
||||
struct_span_err!(self.tcx.sess, expr.span, E0070,
|
||||
"invalid left-hand side expression")
|
||||
.span_label(expr.span, "left-hand of expression not valid")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
25
src/test/run-pass/generator/auxiliary/xcrate.rs
Normal file
25
src/test/run-pass/generator/auxiliary/xcrate.rs
Normal file
@ -0,0 +1,25 @@
|
||||
// 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, generator_trait, conservative_impl_trait)]
|
||||
|
||||
use std::ops::Generator;
|
||||
|
||||
fn bar() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
pub fn foo() -> impl Generator<Yield = (), Return = ()> {
|
||||
|| {
|
||||
if bar() {
|
||||
yield;
|
||||
}
|
||||
}
|
||||
}
|
@ -24,10 +24,14 @@ impl Drop for B {
|
||||
}
|
||||
}
|
||||
|
||||
fn bool_true() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let b = B;
|
||||
let mut foo = || {
|
||||
if true {
|
||||
if bool_true() {
|
||||
panic!();
|
||||
}
|
||||
drop(b);
|
||||
@ -42,7 +46,7 @@ fn main() {
|
||||
assert_eq!(A.load(Ordering::SeqCst), 1);
|
||||
|
||||
let mut foo = || {
|
||||
if true {
|
||||
if bool_true() {
|
||||
panic!();
|
||||
}
|
||||
drop(B);
|
||||
|
26
src/test/run-pass/generator/xcrate.rs
Normal file
26
src/test/run-pass/generator/xcrate.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// 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.
|
||||
|
||||
// aux-build:xcrate.rs
|
||||
|
||||
#![feature(generators, generator_trait)]
|
||||
|
||||
extern crate xcrate;
|
||||
|
||||
use std::ops::{GeneratorState, Generator};
|
||||
|
||||
fn main() {
|
||||
let mut foo = xcrate::foo();
|
||||
|
||||
match foo.resume() {
|
||||
GeneratorState::Complete(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user