Rustup (generator support)

This commit is contained in:
Oliver Schneider 2017-08-30 11:13:01 +02:00
parent 4b67bfab52
commit 58a59e9d23
No known key found for this signature in database
GPG Key ID: A69F8D225B3AD7D9
4 changed files with 96 additions and 11 deletions

View File

@ -480,15 +480,22 @@ fn collect_storage_annotations<'tcx>(mir: &'tcx mir::Mir<'tcx>) -> HashSet<mir::
// Subtract 1 because `local_decls` includes the ReturnMemoryPointer, but we don't store a local
// `Value` for that.
let annotated_locals = collect_storage_annotations(mir);
let num_locals = mir.local_decls.len() - 1;
let mut locals = vec![None; num_locals];
for i in 0..num_locals {
let local = mir::Local::new(i + 1);
if !annotated_locals.contains(&local) {
locals[i] = Some(Value::ByVal(PrimVal::Undef));
// FIXME: generators produce broken storage annotations (https://github.com/rust-lang/rust/issues/44179)
let locals = if mir.generator_layout.is_some() {
vec![Some(Value::ByVal(PrimVal::Undef)); num_locals]
} else {
let annotated_locals = collect_storage_annotations(mir);
let mut locals = vec![None; num_locals];
for i in 0..num_locals {
let local = mir::Local::new(i + 1);
if !annotated_locals.contains(&local) {
locals[i] = Some(Value::ByVal(PrimVal::Undef));
}
}
}
locals
};
self.stack.push(Frame {
mir,
@ -2426,6 +2433,12 @@ fn resolve_associated_item<'a, 'tcx>(
let substs = tcx.erase_regions(&substs);
ty::Instance::new(def_id, substs)
}
::rustc::traits::VtableGenerator(closure_data) => {
ty::Instance {
def: ty::InstanceDef::Item(closure_data.closure_def_id),
substs: closure_data.substs.substs
}
}
::rustc::traits::VtableClosure(closure_data) => {
let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_id).unwrap();
resolve_closure(

View File

@ -137,8 +137,9 @@ pub(super) fn eval_terminator(
if expected == cond_val {
self.goto_block(target);
} else {
use rustc::mir::AssertMessage::*;
return match *msg {
mir::AssertMessage::BoundsCheck { ref len, ref index } => {
BoundsCheck { ref len, ref index } => {
let span = terminator.source_info.span;
let len = self.eval_operand_to_primval(len)
.expect("can't eval len")
@ -148,13 +149,17 @@ pub(super) fn eval_terminator(
.to_u64()?;
err!(ArrayIndexOutOfBounds(span, len, index))
}
mir::AssertMessage::Math(ref err) => {
Math(ref err) => {
err!(Math(terminator.source_info.span, err.clone()))
}
GeneratorResumedAfterReturn |
GeneratorResumedAfterPanic => unimplemented!(),
};
}
}
Yield { .. } => unimplemented!("{:#?}", terminator.kind),
GeneratorDrop => unimplemented!(),
DropAndReplace { .. } => unimplemented!(),
Resume => unimplemented!(),
Unreachable => return err!(Unreachable),

View File

@ -355,7 +355,7 @@ fn try_validate(
TyRef(..) | TyFnPtr(..) | TyFnDef(..) | TyNever => true,
TyAdt(adt, _) if adt.is_box() => true,
TySlice(_) | TyAdt(_, _) | TyTuple(..) | TyClosure(..) | TyArray(..) |
TyDynamic(..) => false,
TyDynamic(..) | TyGenerator(..) => false,
TyParam(_) | TyInfer(_) | TyProjection(_) | TyAnon(..) | TyError => {
bug!("I got an incomplete/unnormalized type for validation")
}
@ -630,7 +630,9 @@ fn try_validate(
// Is there other things we can/should check? Like vtable pointers?
Ok(())
}
_ => bug!("We already establishd that this is a type we support."),
// FIXME: generators aren't validated right now
TyGenerator(..) => Ok(()),
_ => bug!("We already established that this is a type we support. ({})", query.ty),
}
}
}

View File

@ -0,0 +1,65 @@
// 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)]
use std::ops::{GeneratorState, Generator};
fn finish<T>(mut amt: usize, mut t: T) -> T::Return
where T: Generator<Yield = ()>
{
loop {
match t.resume() {
GeneratorState::Yielded(()) => amt -= 1,
GeneratorState::Complete(ret) => {
assert_eq!(amt, 0);
return ret
}
}
}
}
fn main() {
finish(1, || yield);
finish(3, || {
let mut x = 0;
yield;
x += 1;
yield;
x += 1;
yield;
assert_eq!(x, 2);
});
finish(8, || {
for _ in 0..8 {
yield;
}
});
finish(1, || {
if true {
yield;
} else {
}
});
finish(1, || {
if false {
} else {
yield;
}
});
finish(2, || {
if { yield; false } {
yield;
panic!()
}
yield
});
}