Rustup (generator support)
This commit is contained in:
parent
4b67bfab52
commit
58a59e9d23
@ -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(
|
||||
|
@ -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),
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
65
tests/run-pass/generator_control_flow.rs
Normal file
65
tests/run-pass/generator_control_flow.rs
Normal 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
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue
Block a user