]> git.lizzy.rs Git - rust.git/commitdiff
Initial pass review comments
authorAlex Crichton <alex@alexcrichton.com>
Wed, 9 Aug 2017 20:56:19 +0000 (13:56 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Wed, 9 Aug 2017 20:56:19 +0000 (13:56 -0700)
34 files changed:
src/librustc/ich/impls_ty.rs
src/librustc/mir/mod.rs
src/librustc/traits/select.rs
src/librustc/ty/flags.rs
src/librustc/ty/outlives.rs
src/librustc/ty/relate.rs
src/librustc/ty/structural_impls.rs
src/librustc/ty/sty.rs
src/librustc/ty/util.rs
src/librustc/ty/walk.rs
src/librustc/util/ppaux.rs
src/librustc_data_structures/indexed_set.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/transform/generator.rs
src/librustc_mir/util/liveness.rs
src/librustc_mir/util/pretty.rs
src/librustc_trans/back/symbol_names.rs
src/librustc_typeck/check/generator_interior.rs
src/librustc_typeck/check/mod.rs
src/test/compile-fail/generator/borrowing.rs [deleted file]
src/test/compile-fail/generator/no-arguments-on-generators.rs [deleted file]
src/test/compile-fail/generator/not-send-sync.rs [deleted file]
src/test/compile-fail/generator/yield-in-const.rs [deleted file]
src/test/compile-fail/generator/yield-in-function.rs [deleted file]
src/test/compile-fail/generator/yield-in-static.rs [deleted file]
src/test/run-pass/generator/auxiliary/xcrate.rs [new file with mode: 0644]
src/test/run-pass/generator/panic-drops.rs
src/test/run-pass/generator/xcrate.rs [new file with mode: 0644]
src/test/ui/generator/borrowing.rs [new file with mode: 0644]
src/test/ui/generator/no-arguments-on-generators.rs [new file with mode: 0644]
src/test/ui/generator/not-send-sync.rs [new file with mode: 0644]
src/test/ui/generator/yield-in-const.rs [new file with mode: 0644]
src/test/ui/generator/yield-in-function.rs [new file with mode: 0644]
src/test/ui/generator/yield-in-static.rs [new file with mode: 0644]

index 9286d3c73ed67452cdd5a94732fa0d7c72a83141..e316fd5f3e6db965bb1d29bb21733b97a867eb67 100644 (file)
@@ -320,7 +320,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 
 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,
index 4063609474bc97a30d003009b5a8fd1332ab7e95..e688af4316032eaf948e7fa83e72757457535450 100644 (file)
@@ -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.
index 9d5494d1fbab638663ecceb90bc9cb93ac7c50cc..52c8b67278e20d48f80a9fd3b085486b63745bf3 100644 (file)
@@ -2126,7 +2126,7 @@ fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Vec<Ty<'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()
             }
 
index 02d50ce29e4f1dc67842806ee142f0c7a2c01731..f40e1d370a99504ab0aec92780d284fd6d72d164 100644 (file)
@@ -89,7 +89,7 @@ fn add_sty(&mut self, st: &ty::TypeVariants) {
                 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) => {
index 3549a7706439edf287e0c37b4a35546da6094a01..657ed4077911c8cd0dd1ea353cce5b366c230fe6 100644 (file)
@@ -122,7 +122,7 @@ fn compute_components(&self, ty: Ty<'tcx>, out: &mut Vec<Component<'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`
index 437f511cb3d0ea7c92ebf89dfceb7d516b438f7d..da94eddf295ea8c4b2eb2a9b75735e3339b1b879 100644 (file)
@@ -531,7 +531,7 @@ fn relate<'a, 'gcx, R>(relation: &mut R,
                            -> 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))
     }
 }
index 087c41a7883ce712df799b2698babc5e36aaef14..cbb0a45cf1e1478c7c8b99aae98adf49c8030867 100644 (file)
@@ -232,8 +232,8 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
 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 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
 
 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)
     }
 }
 
index 2f3fd5244aeaeeee4dcc6ee335ad000798184995..9898ce5d73daa79ffce9b1d6d8869284e1cc603c 100644 (file)
@@ -295,19 +295,17 @@ impl Iterator<Item=Ty<'tcx>> + '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)
index 6bbcc674ef408609c88b40c7988c2045a91c156c..67ec8d2ae63adc4592156fdc1f89550f8f113180 100644 (file)
@@ -570,7 +570,7 @@ pub fn dtorck_constraint_for_ty(self,
             }
 
             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()
             }
index a2087b0b2f1bf185c7c6bedc77b14667f5c99aa3..bfabacdb1721496be8eb7bbcd18ff84b5312ac6d 100644 (file)
@@ -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());
index 33ab83d236f7ca509d4136b9ae2b4f2e393b50f6..ed72f2429487f49a739342072b39dba970bf675b 100644 (file)
@@ -717,7 +717,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
 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)
     }
 }
 
index 821e2b01431c575bd666cabe98ec0466a07b65a5..9fa47cee659583f091b0a0448d3dc690a9d547e9 100644 (file)
@@ -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 @@ pub fn union(&mut self, other: &IdxSet<T>) -> bool {
     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,
+            }
+        }
+    }
 }
index 9b3585fff58b399d1ede5ff1fec720f99f4e8f6a..a81103213b841f92d93c1da62d16d4bcd1a3f507 100644 (file)
@@ -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::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::FnOnce => {
+                        Expr {
+                            ty: closure_ty,
+                            temp_lifetime: temp_lifetime,
+                            span: expr.span,
+                            kind: ExprKind::SelfRef,
+                        }
                     }
                 }
-            }
             } else {
                 Expr {
                     ty: closure_ty,
index dc86bc6818def92fa2f6cf2721237c7840fc0845..f57ba0cf42a1223b6bacb211b10e13dfcfe93ffd 100644 (file)
@@ -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;
 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 @@ fn visit_basic_block_data(&mut self,
             }
         });
 
-        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 @@ fn visit_basic_block_data(&mut self,
                     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 @@ fn run_pass<'a, 'tcx>(&self,
 
         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 @@ fn run_pass<'a, 'tcx>(&self,
 
         generate_drop(tcx,
                       &transform,
-                      node_id,
                       def_id,
                       source,
                       gen_ty,
@@ -772,6 +707,6 @@ fn run_pass<'a, 'tcx>(&self,
 
         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);
     }
 }
index 946e9ff4747439b27283ecf6435e8a3919bec239..fd15c90dc901360ab6c684f2770b014e08bd8062 100644 (file)
@@ -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 @@ fn visit_lvalue(&mut self,
                 // 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 |
index e3087efbfe6263a22d61e8ba95a23a78b881c672..0811783a9e57f7b75c211652c2398cc84b346c81 100644 (file)
@@ -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)
         }
index d646b515bf41e89bd8be81196f27b7b2d6db381d..10b66fb1991087a351150bcc8ec921a8cd7ce349 100644 (file)
@@ -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
index f116620388f16eb61adceb96834dd4d892df00ff..6753d42b0c5499de7fdc44cd89c6ef71689e0d44 100644 (file)
@@ -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 @@ fn record(&mut self, ty: Ty<'tcx>, scope: Option<CodeExtent>, expr: Option<&'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) {
index ed6d0c035de8ce954cd340592c7441c918ad7fa6..fee10f503780a643abf43a64b925d505cfa8267f 100644 (file)
@@ -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 @@ fn check_casts(&self) {
         }
     }
 
-    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 @@ fn check_expr_eq_type(&self,
     }
 
     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 @@ fn check_tup_field(&self,
             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 @@ fn check_expr_kind(&self,
                     // 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();
+                    }
                 }
             }
 
diff --git a/src/test/compile-fail/generator/borrowing.rs b/src/test/compile-fail/generator/borrowing.rs
deleted file mode 100644 (file)
index de10bde..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// 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::Generator;
-
-fn main() {
-    let _b = {
-        let a = 3;
-        (|| yield &a).resume()
-        //~^ ERROR: `a` does not live long enough
-    };
-
-    let _b = {
-        let a = 3;
-        || {
-            yield &a
-            //~^ ERROR: `a` does not live long enough
-        }
-    };
-}
-
diff --git a/src/test/compile-fail/generator/no-arguments-on-generators.rs b/src/test/compile-fail/generator/no-arguments-on-generators.rs
deleted file mode 100644 (file)
index a7e98fe..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// 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)]
-
-fn main() {
-    let gen = |start| { //~ ERROR generators cannot have explicit arguments
-        yield;
-    };
-}
diff --git a/src/test/compile-fail/generator/not-send-sync.rs b/src/test/compile-fail/generator/not-send-sync.rs
deleted file mode 100644 (file)
index 0419758..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-// 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)]
-
-use std::cell::Cell;
-
-fn main() {
-    fn assert_sync<T: Sync>(_: T) {}
-    fn assert_send<T: Send>(_: T) {}
-
-    assert_sync(|| {
-        //~^ ERROR: Sync` is not satisfied
-        let a = Cell::new(2);
-        yield;
-    });
-
-    let a = Cell::new(2);
-    assert_send(|| {
-        //~^ ERROR: Sync` is not satisfied
-        drop(&a);
-        yield;
-    });
-}
diff --git a/src/test/compile-fail/generator/yield-in-const.rs b/src/test/compile-fail/generator/yield-in-const.rs
deleted file mode 100644 (file)
index e166d26..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// 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)]
-
-const A: u8 = { yield 3u8; 3u8};
-//~^ ERROR yield statement outside
diff --git a/src/test/compile-fail/generator/yield-in-function.rs b/src/test/compile-fail/generator/yield-in-function.rs
deleted file mode 100644 (file)
index 2f6c5a9..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// 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)]
-
-fn main() { yield; }
-//~^ ERROR yield statement outside
diff --git a/src/test/compile-fail/generator/yield-in-static.rs b/src/test/compile-fail/generator/yield-in-static.rs
deleted file mode 100644 (file)
index 823a2aa..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// 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)]
-
-static B: u8 = { yield 3u8; 3u8};
-//~^ ERROR yield statement outside
diff --git a/src/test/run-pass/generator/auxiliary/xcrate.rs b/src/test/run-pass/generator/auxiliary/xcrate.rs
new file mode 100644 (file)
index 0000000..519c34c
--- /dev/null
@@ -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;
+        }
+    }
+}
index 4837f68be5eb24ef9efc496ecb451f24cff5ff9b..53cd3235d9d0ceb51d8b4abaf27751a413364a2c 100644 (file)
@@ -24,10 +24,14 @@ fn drop(&mut self) {
     }
 }
 
+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);
diff --git a/src/test/run-pass/generator/xcrate.rs b/src/test/run-pass/generator/xcrate.rs
new file mode 100644 (file)
index 0000000..5d6cdee
--- /dev/null
@@ -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),
+    }
+}
diff --git a/src/test/ui/generator/borrowing.rs b/src/test/ui/generator/borrowing.rs
new file mode 100644 (file)
index 0000000..de10bde
--- /dev/null
@@ -0,0 +1,30 @@
+// 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::Generator;
+
+fn main() {
+    let _b = {
+        let a = 3;
+        (|| yield &a).resume()
+        //~^ ERROR: `a` does not live long enough
+    };
+
+    let _b = {
+        let a = 3;
+        || {
+            yield &a
+            //~^ ERROR: `a` does not live long enough
+        }
+    };
+}
+
diff --git a/src/test/ui/generator/no-arguments-on-generators.rs b/src/test/ui/generator/no-arguments-on-generators.rs
new file mode 100644 (file)
index 0000000..a7e98fe
--- /dev/null
@@ -0,0 +1,17 @@
+// 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)]
+
+fn main() {
+    let gen = |start| { //~ ERROR generators cannot have explicit arguments
+        yield;
+    };
+}
diff --git a/src/test/ui/generator/not-send-sync.rs b/src/test/ui/generator/not-send-sync.rs
new file mode 100644 (file)
index 0000000..0419758
--- /dev/null
@@ -0,0 +1,31 @@
+// 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)]
+
+use std::cell::Cell;
+
+fn main() {
+    fn assert_sync<T: Sync>(_: T) {}
+    fn assert_send<T: Send>(_: T) {}
+
+    assert_sync(|| {
+        //~^ ERROR: Sync` is not satisfied
+        let a = Cell::new(2);
+        yield;
+    });
+
+    let a = Cell::new(2);
+    assert_send(|| {
+        //~^ ERROR: Sync` is not satisfied
+        drop(&a);
+        yield;
+    });
+}
diff --git a/src/test/ui/generator/yield-in-const.rs b/src/test/ui/generator/yield-in-const.rs
new file mode 100644 (file)
index 0000000..e166d26
--- /dev/null
@@ -0,0 +1,14 @@
+// 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)]
+
+const A: u8 = { yield 3u8; 3u8};
+//~^ ERROR yield statement outside
diff --git a/src/test/ui/generator/yield-in-function.rs b/src/test/ui/generator/yield-in-function.rs
new file mode 100644 (file)
index 0000000..2f6c5a9
--- /dev/null
@@ -0,0 +1,14 @@
+// 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)]
+
+fn main() { yield; }
+//~^ ERROR yield statement outside
diff --git a/src/test/ui/generator/yield-in-static.rs b/src/test/ui/generator/yield-in-static.rs
new file mode 100644 (file)
index 0000000..823a2aa
--- /dev/null
@@ -0,0 +1,14 @@
+// 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)]
+
+static B: u8 = { yield 3u8; 3u8};
+//~^ ERROR yield statement outside