Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
3d292b79
R
Rust
项目概览
int
/
Rust
接近 1 年 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
3d292b79
编写于
2月 03, 2018
作者:
B
bors
浏览文件
操作
浏览文件
下载
差异文件
Auto merge of #47845 - Zoxc:gen-fixes, r=nikomatsakis
Generator bugfixes r? @nikomatsakis
上级
aa0a5a86
6c66e11f
变更
21
隐藏空白更改
内联
并排
Showing
21 changed file
with
342 addition
and
52 deletion
+342
-52
src/librustc/middle/region.rs
src/librustc/middle/region.rs
+7
-2
src/librustc/traits/error_reporting.rs
src/librustc/traits/error_reporting.rs
+4
-0
src/librustc/traits/mod.rs
src/librustc/traits/mod.rs
+2
-0
src/librustc/traits/structural_impls.rs
src/librustc/traits/structural_impls.rs
+3
-0
src/librustc/ty/sty.rs
src/librustc/ty/sty.rs
+10
-3
src/librustc_mir/borrow_check/error_reporting.rs
src/librustc_mir/borrow_check/error_reporting.rs
+2
-2
src/librustc_mir/borrow_check/nll/type_check/mod.rs
src/librustc_mir/borrow_check/nll/type_check/mod.rs
+10
-5
src/librustc_mir/dataflow/impls/borrowed_locals.rs
src/librustc_mir/dataflow/impls/borrowed_locals.rs
+118
-0
src/librustc_mir/dataflow/impls/mod.rs
src/librustc_mir/dataflow/impls/mod.rs
+4
-0
src/librustc_mir/dataflow/mod.rs
src/librustc_mir/dataflow/mod.rs
+1
-0
src/librustc_mir/transform/generator.rs
src/librustc_mir/transform/generator.rs
+51
-17
src/librustc_typeck/check/generator_interior.rs
src/librustc_typeck/check/generator_interior.rs
+4
-4
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/mod.rs
+3
-1
src/libsyntax/parse/token.rs
src/libsyntax/parse/token.rs
+1
-0
src/test/run-pass/generator/too-live-local-in-immovable-gen.rs
...est/run-pass/generator/too-live-local-in-immovable-gen.rs
+28
-0
src/test/ui/generator/generator-with-nll.stderr
src/test/ui/generator/generator-with-nll.stderr
+9
-9
src/test/ui/generator/pattern-borrow.rs
src/test/ui/generator/pattern-borrow.rs
+23
-0
src/test/ui/generator/pattern-borrow.stderr
src/test/ui/generator/pattern-borrow.stderr
+10
-0
src/test/ui/generator/sized-yield.rs
src/test/ui/generator/sized-yield.rs
+21
-0
src/test/ui/generator/sized-yield.stderr
src/test/ui/generator/sized-yield.stderr
+22
-0
src/test/ui/generator/yield-while-local-borrowed.stderr
src/test/ui/generator/yield-while-local-borrowed.stderr
+9
-9
未找到文件。
src/librustc/middle/region.rs
浏览文件 @
3d292b79
...
...
@@ -467,9 +467,13 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
}
fn
visit_pat
(
&
mut
self
,
pat
:
&
'tcx
Pat
)
{
intravisit
::
walk_pat
(
self
,
pat
);
self
.expr_and_pat_count
+=
1
;
intravisit
::
walk_pat
(
self
,
pat
);
if
pat
.id
==
self
.id
{
self
.result
=
Some
(
self
.expr_and_pat_count
);
}
}
fn
visit_expr
(
&
mut
self
,
expr
:
&
'tcx
Expr
)
{
...
...
@@ -814,7 +818,8 @@ pub fn free_scope<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, fr: &ty::FreeReg
/// Checks whether the given scope contains a `yield`. If so,
/// returns `Some((span, expr_count))` with the span of a yield we found and
/// the number of expressions appearing before the `yield` in the body.
/// the number of expressions and patterns appearing before the `yield` in the body + 1.
/// If there a are multiple yields in a scope, the one with the highest number is returned.
pub
fn
yield_in_scope
(
&
self
,
scope
:
Scope
)
->
Option
<
(
Span
,
usize
)
>
{
self
.yield_in_scope
.get
(
&
scope
)
.cloned
()
}
...
...
src/librustc/traits/error_reporting.rs
浏览文件 @
3d292b79
...
...
@@ -1266,6 +1266,10 @@ fn note_obligation_cause_code<T>(&self,
err
.note
(
"the return type of a function must have a
\
statically known size"
);
}
ObligationCauseCode
::
SizedYieldType
=>
{
err
.note
(
"the yield type of a generator must have a
\
statically known size"
);
}
ObligationCauseCode
::
AssignmentLhsSized
=>
{
err
.note
(
"the left-hand-side of an assignment must have a statically known size"
);
}
...
...
src/librustc/traits/mod.rs
浏览文件 @
3d292b79
...
...
@@ -151,6 +151,8 @@ pub enum ObligationCauseCode<'tcx> {
VariableType
(
ast
::
NodeId
),
/// Return type must be Sized
SizedReturnType
,
/// Yield type must be Sized
SizedYieldType
,
/// [T,..n] --> T must be Copy
RepeatVec
,
...
...
src/librustc/traits/structural_impls.rs
浏览文件 @
3d292b79
...
...
@@ -209,6 +209,7 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
super
::
VariableType
(
id
)
=>
Some
(
super
::
VariableType
(
id
)),
super
::
ReturnType
(
id
)
=>
Some
(
super
::
ReturnType
(
id
)),
super
::
SizedReturnType
=>
Some
(
super
::
SizedReturnType
),
super
::
SizedYieldType
=>
Some
(
super
::
SizedYieldType
),
super
::
RepeatVec
=>
Some
(
super
::
RepeatVec
),
super
::
FieldSized
(
item
)
=>
Some
(
super
::
FieldSized
(
item
)),
super
::
ConstSized
=>
Some
(
super
::
ConstSized
),
...
...
@@ -526,6 +527,7 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
super
::
VariableType
(
_
)
|
super
::
ReturnType
(
_
)
|
super
::
SizedReturnType
|
super
::
SizedYieldType
|
super
::
ReturnNoExpression
|
super
::
RepeatVec
|
super
::
FieldSized
(
_
)
|
...
...
@@ -574,6 +576,7 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
super
::
VariableType
(
_
)
|
super
::
ReturnType
(
_
)
|
super
::
SizedReturnType
|
super
::
SizedYieldType
|
super
::
ReturnNoExpression
|
super
::
RepeatVec
|
super
::
FieldSized
(
_
)
|
...
...
src/librustc/ty/sty.rs
浏览文件 @
3d292b79
...
...
@@ -390,14 +390,21 @@ impl Iterator<Item=Ty<'tcx>> + 'a
state
.map
(
move
|
d
|
d
.ty
.subst
(
tcx
,
self
.substs
))
}
/// This is the types of the fields of a generate which
/// is available before the generator transformation.
/// It includes the upvars and the state discriminant which is u32.
pub
fn
pre_transforms_tys
(
self
,
def_id
:
DefId
,
tcx
:
TyCtxt
<
'a
,
'gcx
,
'tcx
>
)
->
impl
Iterator
<
Item
=
Ty
<
'tcx
>>
+
'a
{
self
.upvar_tys
(
def_id
,
tcx
)
.chain
(
iter
::
once
(
tcx
.types.u32
))
}
/// This is the types of all the fields stored in a generator.
/// It includes the upvars, state types and the state discriminant which is u32.
pub
fn
field_tys
(
self
,
def_id
:
DefId
,
tcx
:
TyCtxt
<
'a
,
'gcx
,
'tcx
>
)
->
impl
Iterator
<
Item
=
Ty
<
'tcx
>>
+
'a
{
let
upvars
=
self
.upvar_tys
(
def_id
,
tcx
);
let
state
=
self
.state_tys
(
def_id
,
tcx
);
upvars
.chain
(
iter
::
once
(
tcx
.types.u32
))
.chain
(
state
)
self
.pre_transforms_tys
(
def_id
,
tcx
)
.chain
(
self
.state_tys
(
def_id
,
tcx
))
}
}
...
...
src/librustc_mir/borrow_check/error_reporting.rs
浏览文件 @
3d292b79
...
...
@@ -746,12 +746,12 @@ fn describe_field_from_ty(&self, ty: &ty::Ty, field: Field) -> String {
self
.describe_field_from_ty
(
&
tnm
.ty
,
field
)
}
ty
::
TyArray
(
ty
,
_
)
|
ty
::
TySlice
(
ty
)
=>
self
.describe_field_from_ty
(
&
ty
,
field
),
ty
::
TyClosure
(
closure_def_id
,
_
)
=>
{
ty
::
TyClosure
(
def_id
,
_
)
|
ty
::
TyGenerator
(
def_id
,
_
,
_
)
=>
{
// Convert the def-id into a node-id. node-ids are only valid for
// the local code in the current crate, so this returns an `Option` in case
// the closure comes from another crate. But in that case we wouldn't
// be borrowck'ing it, so we can just unwrap:
let
node_id
=
self
.tcx.hir
.as_local_node_id
(
closure_
def_id
)
.unwrap
();
let
node_id
=
self
.tcx.hir
.as_local_node_id
(
def_id
)
.unwrap
();
let
freevar
=
self
.tcx
.with_freevars
(
node_id
,
|
fv
|
fv
[
field
.index
()]);
self
.tcx.hir
.name
(
freevar
.var_id
())
.to_string
()
...
...
src/librustc_mir/borrow_check/nll/type_check/mod.rs
浏览文件 @
3d292b79
...
...
@@ -533,15 +533,17 @@ fn field_ty(
}
}
ty
::
TyGenerator
(
def_id
,
substs
,
_
)
=>
{
// Try
upvars first. `field_tys` requires final optimized MIR.
if
let
Some
(
ty
)
=
substs
.
upvar
_tys
(
def_id
,
tcx
)
.nth
(
field
.index
())
{
// Try
pre-transform fields first (upvars and current state)
if
let
Some
(
ty
)
=
substs
.
pre_transforms
_tys
(
def_id
,
tcx
)
.nth
(
field
.index
())
{
return
Ok
(
ty
);
}
// Then try `field_tys` which contains all the fields, but it
// requires the final optimized MIR.
return
match
substs
.field_tys
(
def_id
,
tcx
)
.nth
(
field
.index
())
{
Some
(
ty
)
=>
Ok
(
ty
),
None
=>
Err
(
FieldAccessError
::
OutOfRange
{
field_count
:
substs
.field_tys
(
def_id
,
tcx
)
.count
()
+
1
,
field_count
:
substs
.field_tys
(
def_id
,
tcx
)
.count
(),
}),
};
}
...
...
@@ -1233,13 +1235,16 @@ fn aggregate_field_ty(
}
}
AggregateKind
::
Generator
(
def_id
,
substs
,
_
)
=>
{
if
let
Some
(
ty
)
=
substs
.upvar_tys
(
def_id
,
tcx
)
.nth
(
field_index
)
{
// Try pre-transform fields first (upvars and current state)
if
let
Some
(
ty
)
=
substs
.pre_transforms_tys
(
def_id
,
tcx
)
.nth
(
field_index
)
{
Ok
(
ty
)
}
else
{
// Then try `field_tys` which contains all the fields, but it
// requires the final optimized MIR.
match
substs
.field_tys
(
def_id
,
tcx
)
.nth
(
field_index
)
{
Some
(
ty
)
=>
Ok
(
ty
),
None
=>
Err
(
FieldAccessError
::
OutOfRange
{
field_count
:
substs
.field_tys
(
def_id
,
tcx
)
.count
()
+
1
,
field_count
:
substs
.field_tys
(
def_id
,
tcx
)
.count
(),
}),
}
}
...
...
src/librustc_mir/dataflow/impls/borrowed_locals.rs
0 → 100644
浏览文件 @
3d292b79
// 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.
pub
use
super
::
*
;
use
rustc
::
mir
::
*
;
use
rustc
::
mir
::
visit
::
Visitor
;
use
dataflow
::
BitDenotation
;
/// This calculates if any part of a MIR local could have previously been borrowed.
/// This means that once a local has been borrowed, its bit will always be set
/// from that point and onwards, even if the borrow ends. You could also think of this
/// as computing the lifetimes of infinite borrows.
/// This is used to compute which locals are live during a yield expression for
/// immovable generators.
#[derive(Copy,
Clone)]
pub
struct
HaveBeenBorrowedLocals
<
'a
,
'tcx
:
'a
>
{
mir
:
&
'a
Mir
<
'tcx
>
,
}
impl
<
'a
,
'tcx
:
'a
>
HaveBeenBorrowedLocals
<
'a
,
'tcx
>
{
pub
fn
new
(
mir
:
&
'a
Mir
<
'tcx
>
)
->
Self
{
HaveBeenBorrowedLocals
{
mir
:
mir
}
}
pub
fn
mir
(
&
self
)
->
&
Mir
<
'tcx
>
{
self
.mir
}
}
impl
<
'a
,
'tcx
>
BitDenotation
for
HaveBeenBorrowedLocals
<
'a
,
'tcx
>
{
type
Idx
=
Local
;
fn
name
()
->
&
'static
str
{
"has_been_borrowed_locals"
}
fn
bits_per_block
(
&
self
)
->
usize
{
self
.mir.local_decls
.len
()
}
fn
start_block_effect
(
&
self
,
_
sets
:
&
mut
IdxSet
<
Local
>
)
{
// Nothing is borrowed on function entry
}
fn
statement_effect
(
&
self
,
sets
:
&
mut
BlockSets
<
Local
>
,
loc
:
Location
)
{
BorrowedLocalsVisitor
{
sets
,
}
.visit_statement
(
loc
.block
,
&
self
.mir
[
loc
.block
]
.statements
[
loc
.statement_index
],
loc
);
}
fn
terminator_effect
(
&
self
,
sets
:
&
mut
BlockSets
<
Local
>
,
loc
:
Location
)
{
BorrowedLocalsVisitor
{
sets
,
}
.visit_terminator
(
loc
.block
,
self
.mir
[
loc
.block
]
.terminator
(),
loc
);
}
fn
propagate_call_return
(
&
self
,
_
in_out
:
&
mut
IdxSet
<
Local
>
,
_
call_bb
:
mir
::
BasicBlock
,
_
dest_bb
:
mir
::
BasicBlock
,
_
dest_place
:
&
mir
::
Place
)
{
// Nothing to do when a call returns successfully
}
}
impl
<
'a
,
'tcx
>
BitwiseOperator
for
HaveBeenBorrowedLocals
<
'a
,
'tcx
>
{
#[inline]
fn
join
(
&
self
,
pred1
:
usize
,
pred2
:
usize
)
->
usize
{
pred1
|
pred2
// "maybe" means we union effects of both preds
}
}
impl
<
'a
,
'tcx
>
InitialFlow
for
HaveBeenBorrowedLocals
<
'a
,
'tcx
>
{
#[inline]
fn
bottom_value
()
->
bool
{
false
// bottom = unborrowed
}
}
struct
BorrowedLocalsVisitor
<
'b
,
'c
:
'b
>
{
sets
:
&
'b
mut
BlockSets
<
'c
,
Local
>
,
}
fn
find_local
<
'tcx
>
(
place
:
&
Place
<
'tcx
>
)
->
Option
<
Local
>
{
match
*
place
{
Place
::
Local
(
l
)
=>
Some
(
l
),
Place
::
Static
(
..
)
=>
None
,
Place
::
Projection
(
ref
proj
)
=>
{
match
proj
.elem
{
ProjectionElem
::
Deref
=>
None
,
_
=>
find_local
(
&
proj
.base
)
}
}
}
}
impl
<
'tcx
,
'b
,
'c
>
Visitor
<
'tcx
>
for
BorrowedLocalsVisitor
<
'b
,
'c
>
{
fn
visit_rvalue
(
&
mut
self
,
rvalue
:
&
Rvalue
<
'tcx
>
,
location
:
Location
)
{
if
let
Rvalue
::
Ref
(
_
,
_
,
ref
place
)
=
*
rvalue
{
if
let
Some
(
local
)
=
find_local
(
place
)
{
self
.sets
.gen
(
&
local
);
}
}
self
.super_rvalue
(
rvalue
,
location
)
}
}
src/librustc_mir/dataflow/impls/mod.rs
浏览文件 @
3d292b79
...
...
@@ -33,6 +33,10 @@
pub
use
self
::
storage_liveness
::
*
;
mod
borrowed_locals
;
pub
use
self
::
borrowed_locals
::
*
;
#[allow(dead_code)]
pub
(
super
)
mod
borrows
;
...
...
src/librustc_mir/dataflow/mod.rs
浏览文件 @
3d292b79
...
...
@@ -30,6 +30,7 @@
pub
use
self
::
impls
::{
DefinitelyInitializedPlaces
,
MovingOutStatements
};
pub
use
self
::
impls
::
EverInitializedPlaces
;
pub
use
self
::
impls
::
borrows
::{
Borrows
,
BorrowData
};
pub
use
self
::
impls
::
HaveBeenBorrowedLocals
;
pub
(
crate
)
use
self
::
impls
::
borrows
::{
ActiveBorrows
,
Reservations
,
ReserveOrActivateIndex
};
pub
use
self
::
at_location
::{
FlowAtLocation
,
FlowsAtLocation
};
pub
(
crate
)
use
self
::
drop_flag_effects
::
*
;
...
...
src/librustc_mir/transform/generator.rs
浏览文件 @
3d292b79
...
...
@@ -78,7 +78,8 @@
use
transform
::{
MirPass
,
MirSource
};
use
transform
::
simplify
;
use
transform
::
no_landing_pads
::
no_landing_pads
;
use
dataflow
::{
do_dataflow
,
DebugFormatted
,
MaybeStorageLive
,
state_for_location
};
use
dataflow
::{
do_dataflow
,
DebugFormatted
,
state_for_location
};
use
dataflow
::{
MaybeStorageLive
,
HaveBeenBorrowedLocals
};
pub
struct
StateTransform
;
...
...
@@ -369,17 +370,33 @@ fn locals_live_across_suspend_points<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
HashMap
<
BasicBlock
,
liveness
::
LocalSet
>
)
{
let
dead_unwinds
=
IdxSetBuf
::
new_empty
(
mir
.basic_blocks
()
.len
());
let
node_id
=
tcx
.hir
.as_local_node_id
(
source
.def_id
)
.unwrap
();
let
analysis
=
MaybeStorageLive
::
new
(
mir
);
// Calculate when MIR locals have live storage. This gives us an upper bound of their
// lifetimes.
let
storage_live_analysis
=
MaybeStorageLive
::
new
(
mir
);
let
storage_live
=
do_dataflow
(
tcx
,
mir
,
node_id
,
&
[],
&
dead_unwinds
,
analysis
,
do_dataflow
(
tcx
,
mir
,
node_id
,
&
[],
&
dead_unwinds
,
storage_live_
analysis
,
|
bd
,
p
|
DebugFormatted
::
new
(
&
bd
.mir
()
.local_decls
[
p
]));
// Find the MIR locals which do not use StorageLive/StorageDead statements.
// The storage of these locals are always live.
let
mut
ignored
=
StorageIgnored
(
IdxSetBuf
::
new_filled
(
mir
.local_decls
.len
()));
ignored
.visit_mir
(
mir
);
let
mut
borrowed_locals
=
BorrowedLocals
(
IdxSetBuf
::
new_empty
(
mir
.local_decls
.len
()));
borrowed_locals
.visit_mir
(
mir
);
// Calculate the MIR locals which have been previously
// borrowed (even if they are still active).
// This is only used for immovable generators.
let
borrowed_locals
=
if
!
movable
{
let
analysis
=
HaveBeenBorrowedLocals
::
new
(
mir
);
let
result
=
do_dataflow
(
tcx
,
mir
,
node_id
,
&
[],
&
dead_unwinds
,
analysis
,
|
bd
,
p
|
DebugFormatted
::
new
(
&
bd
.mir
()
.local_decls
[
p
]));
Some
((
analysis
,
result
))
}
else
{
None
};
// Calculate the liveness of MIR locals ignoring borrows.
let
mut
set
=
liveness
::
LocalSet
::
new_empty
(
mir
.local_decls
.len
());
let
mut
liveness
=
liveness
::
liveness_of_locals
(
mir
,
LivenessMode
{
include_regular_use
:
true
,
...
...
@@ -396,24 +413,41 @@ fn locals_live_across_suspend_points<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
statement_index
:
data
.statements
.len
(),
};
let
storage_liveness
=
state_for_location
(
loc
,
&
analysis
,
&
storage_live
,
mir
);
if
let
Some
((
ref
analysis
,
ref
result
))
=
borrowed_locals
{
let
borrowed_locals
=
state_for_location
(
loc
,
analysis
,
result
,
mir
);
// The `liveness` variable contains the liveness of MIR locals ignoring borrows.
// This is correct for movable generators since borrows cannot live across
// suspension points. However for immovable generators we need to account for
// borrows, so we conseratively assume that all borrowed locals live forever.
// To do this we just union our `liveness` result with `borrowed_locals`, which
// contains all the locals which has been borrowed before this suspension point.
// If a borrow is converted to a raw reference, we must also assume that it lives
// forever. Note that the final liveness is still bounded by the storage liveness
// of the local, which happens using the `intersect` operation below.
liveness
.outs
[
block
]
.union
(
&
borrowed_locals
);
}
let
mut
storage_liveness
=
state_for_location
(
loc
,
&
storage_live_analysis
,
&
storage_live
,
mir
);
// Store the storage liveness for later use so we can restore the state
// after a suspension point
storage_liveness_map
.insert
(
block
,
storage_liveness
.clone
());
let
mut
live_locals
=
storage_liveness
;
// Mark locals without storage statements as always having live storage
live_local
s
.union
(
&
ignored
.0
);
storage_livenes
s
.union
(
&
ignored
.0
);
if
!
movable
{
// For immovable generators we consider borrowed locals to always be live.
// This effectively makes those locals use just the storage liveness.
liveness
.outs
[
block
]
.union
(
&
borrowed_locals
.0
);
}
// Locals live are live at this point only if they are used across
// suspension points (the `liveness` variable)
// and their storage is live (the `storage_liveness` variable)
storage_liveness
.intersect
(
&
liveness
.outs
[
block
]);
// Locals live are live at this point only if they are used across suspension points
// and their storage is live
live_locals
.intersect
(
&
liveness
.outs
[
block
]);
let
live_locals
=
storage_liveness
;
// Add the locals life at this suspension point to the set of locals which live across
// any suspension points
...
...
src/librustc_typeck/check/generator_interior.rs
浏览文件 @
3d292b79
...
...
@@ -150,15 +150,15 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
}
fn
visit_pat
(
&
mut
self
,
pat
:
&
'tcx
Pat
)
{
intravisit
::
walk_pat
(
self
,
pat
);
self
.expr_count
+=
1
;
if
let
PatKind
::
Binding
(
..
)
=
pat
.node
{
let
scope
=
self
.region_scope_tree
.var_scope
(
pat
.hir_id.local_id
);
let
ty
=
self
.fcx.tables
.borrow
()
.pat_ty
(
pat
);
self
.record
(
ty
,
Some
(
scope
),
None
,
pat
.span
);
}
self
.expr_count
+=
1
;
intravisit
::
walk_pat
(
self
,
pat
);
}
fn
visit_expr
(
&
mut
self
,
expr
:
&
'tcx
Expr
)
{
...
...
src/librustc_typeck/check/mod.rs
浏览文件 @
3d292b79
...
...
@@ -1015,7 +1015,9 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
let
span
=
body
.value.span
;
if
body
.is_generator
&&
can_be_generator
.is_some
()
{
fcx
.yield_ty
=
Some
(
fcx
.next_ty_var
(
TypeVariableOrigin
::
TypeInference
(
span
)));
let
yield_ty
=
fcx
.next_ty_var
(
TypeVariableOrigin
::
TypeInference
(
span
));
fcx
.require_type_is_sized
(
yield_ty
,
span
,
traits
::
SizedYieldType
);
fcx
.yield_ty
=
Some
(
yield_ty
);
}
GatherLocalsVisitor
{
fcx
:
&
fcx
,
}
.visit_body
(
body
);
...
...
src/libsyntax/parse/token.rs
浏览文件 @
3d292b79
...
...
@@ -112,6 +112,7 @@ fn ident_can_begin_expr(ident: ast::Ident) -> bool {
keywords
::
Unsafe
.name
(),
keywords
::
While
.name
(),
keywords
::
Yield
.name
(),
keywords
::
Static
.name
(),
]
.contains
(
&
ident
.name
)
}
...
...
src/test/run-pass/generator/too-live-local-in-immovable-gen.rs
0 → 100644
浏览文件 @
3d292b79
// Copyright 2018 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
()
{
unsafe
{
static
move
||
{
// Tests that the generator transformation finds out that `a` is not live
// during the yield expression. Type checking will also compute liveness
// and it should also find out that `a` is not live.
// The compiler will panic if the generator transformation finds that
// `a` is live and type checking finds it dead.
let
a
=
{
yield
();
4i32
};
&
a
;
};
}
}
src/test/ui/generator/generator-with-nll.stderr
浏览文件 @
3d292b79
error[E0626]: borrow may still be in use when generator yields (Mir)
--> $DIR/generator-with-nll.rs:20:17
|
20 | let b = &mut true; //~ ERROR borrow may still be in use when generator yields (Ast)
| ^^^^^^^^^
21 | //~^ borrow may still be in use when generator yields (Mir)
22 | yield ();
| -------- possible yield occurs here
error[E0626]: borrow may still be in use when generator yields (Ast)
--> $DIR/generator-with-nll.rs:19:23
|
...
...
@@ -25,5 +16,14 @@ error[E0626]: borrow may still be in use when generator yields (Ast)
22 | yield ();
| -------- possible yield occurs here
error[E0626]: borrow may still be in use when generator yields (Mir)
--> $DIR/generator-with-nll.rs:20:17
|
20 | let b = &mut true; //~ ERROR borrow may still be in use when generator yields (Ast)
| ^^^^^^^^^
21 | //~^ borrow may still be in use when generator yields (Mir)
22 | yield ();
| -------- possible yield occurs here
error: aborting due to 3 previous errors
src/test/ui/generator/pattern-borrow.rs
0 → 100644
浏览文件 @
3d292b79
// Copyright 2018 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)]
enum
Test
{
A
(
i32
),
B
,
}
fn
main
()
{
}
fn
fun
(
test
:
Test
)
{
move
||
{
if
let
Test
::
A
(
ref
_
a
)
=
test
{
//~ ERROR borrow may still be in use when generator yields
yield
();
}
};
}
src/test/ui/generator/pattern-borrow.stderr
0 → 100644
浏览文件 @
3d292b79
error[E0626]: borrow may still be in use when generator yields
--> $DIR/pattern-borrow.rs:19:24
|
19 | if let Test::A(ref _a) = test { //~ ERROR borrow may still be in use when generator yields
| ^^^^^^
20 | yield ();
| -------- possible yield occurs here
error: aborting due to previous error
src/test/ui/generator/sized-yield.rs
0 → 100644
浏览文件 @
3d292b79
// Copyright 2018 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
s
=
String
::
from
(
"foo"
);
let
mut
gen
=
move
||
{
//~ ERROR the trait bound `str: std::marker::Sized` is not satisfied
yield
s
[
..
];
};
gen
.resume
();
//~ ERROR the trait bound `str: std::marker::Sized` is not satisfied
}
src/test/ui/generator/sized-yield.stderr
0 → 100644
浏览文件 @
3d292b79
error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
--> $DIR/sized-yield.rs:17:26
|
17 | let mut gen = move || { //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied
| __________________________^
18 | | yield s[..];
19 | | };
| |____^ `str` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `str`
= note: the yield type of a generator must have a statically known size
error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
--> $DIR/sized-yield.rs:20:8
|
20 | gen.resume(); //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied
| ^^^^^^ `str` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `str`
error: aborting due to 2 previous errors
src/test/ui/generator/yield-while-local-borrowed.stderr
浏览文件 @
3d292b79
error[E0626]: borrow may still be in use when generator yields (Mir)
--> $DIR/yield-while-local-borrowed.rs:24:17
|
24 | let a = &mut 3;
| ^^^^^^
...
27 | yield();
| ------- possible yield occurs here
error[E0626]: borrow may still be in use when generator yields (Ast)
--> $DIR/yield-while-local-borrowed.rs:24:22
|
...
...
@@ -25,6 +16,15 @@ error[E0626]: borrow may still be in use when generator yields (Ast)
55 | yield();
| ------- possible yield occurs here
error[E0626]: borrow may still be in use when generator yields (Mir)
--> $DIR/yield-while-local-borrowed.rs:24:17
|
24 | let a = &mut 3;
| ^^^^^^
...
27 | yield();
| ------- possible yield occurs here
error[E0626]: borrow may still be in use when generator yields (Mir)
--> $DIR/yield-while-local-borrowed.rs:52:21
|
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录