Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
d92e594c
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,发现更多精彩内容 >>
提交
d92e594c
编写于
8月 06, 2016
作者:
E
Eduard Burtescu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
typeck: record `impl Trait` concrete resolutions.
上级
1ef7ddfd
变更
10
展开全部
隐藏空白更改
内联
并排
Showing
10 changed file
with
1224 addition
and
96 deletion
+1224
-96
src/librustc/hir/map/collector.rs
src/librustc/hir/map/collector.rs
+8
-0
src/librustc/hir/map/mod.rs
src/librustc/hir/map/mod.rs
+12
-0
src/librustc_metadata/encoder.rs
src/librustc_metadata/encoder.rs
+14
-0
src/librustc_typeck/astconv.rs
src/librustc_typeck/astconv.rs
+18
-15
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/mod.rs
+60
-22
src/librustc_typeck/check/writeback.rs
src/librustc_typeck/check/writeback.rs
+104
-8
src/librustc_typeck/collect.rs
src/librustc_typeck/collect.rs
+36
-51
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/diagnostics.rs
+3
-0
src/test/run-pass/impl-trait/example-calendar.rs
src/test/run-pass/impl-trait/example-calendar.rs
+929
-0
src/test/run-pass/impl-trait/example-st.rs
src/test/run-pass/impl-trait/example-st.rs
+40
-0
未找到文件。
src/librustc/hir/map/collector.rs
浏览文件 @
d92e594c
...
...
@@ -194,6 +194,14 @@ fn visit_stmt(&mut self, stmt: &'ast Stmt) {
});
}
fn
visit_ty
(
&
mut
self
,
ty
:
&
'ast
Ty
)
{
self
.insert
(
ty
.id
,
NodeTy
(
ty
));
self
.with_parent
(
ty
.id
,
|
this
|
{
intravisit
::
walk_ty
(
this
,
ty
);
});
}
fn
visit_fn
(
&
mut
self
,
fk
:
intravisit
::
FnKind
<
'ast
>
,
fd
:
&
'ast
FnDecl
,
b
:
&
'ast
Block
,
s
:
Span
,
id
:
NodeId
)
{
assert_eq!
(
self
.parent_node
,
id
);
...
...
src/librustc/hir/map/mod.rs
浏览文件 @
d92e594c
...
...
@@ -50,6 +50,7 @@ pub enum Node<'ast> {
NodeVariant
(
&
'ast
Variant
),
NodeExpr
(
&
'ast
Expr
),
NodeStmt
(
&
'ast
Stmt
),
NodeTy
(
&
'ast
Ty
),
NodeLocal
(
&
'ast
Pat
),
NodePat
(
&
'ast
Pat
),
NodeBlock
(
&
'ast
Block
),
...
...
@@ -76,6 +77,7 @@ pub enum MapEntry<'ast> {
EntryVariant
(
NodeId
,
&
'ast
Variant
),
EntryExpr
(
NodeId
,
&
'ast
Expr
),
EntryStmt
(
NodeId
,
&
'ast
Stmt
),
EntryTy
(
NodeId
,
&
'ast
Ty
),
EntryLocal
(
NodeId
,
&
'ast
Pat
),
EntryPat
(
NodeId
,
&
'ast
Pat
),
EntryBlock
(
NodeId
,
&
'ast
Block
),
...
...
@@ -104,6 +106,7 @@ fn from_node(p: NodeId, node: Node<'ast>) -> MapEntry<'ast> {
NodeVariant
(
n
)
=>
EntryVariant
(
p
,
n
),
NodeExpr
(
n
)
=>
EntryExpr
(
p
,
n
),
NodeStmt
(
n
)
=>
EntryStmt
(
p
,
n
),
NodeTy
(
n
)
=>
EntryTy
(
p
,
n
),
NodeLocal
(
n
)
=>
EntryLocal
(
p
,
n
),
NodePat
(
n
)
=>
EntryPat
(
p
,
n
),
NodeBlock
(
n
)
=>
EntryBlock
(
p
,
n
),
...
...
@@ -122,6 +125,7 @@ fn parent_node(self) -> Option<NodeId> {
EntryVariant
(
id
,
_
)
=>
id
,
EntryExpr
(
id
,
_
)
=>
id
,
EntryStmt
(
id
,
_
)
=>
id
,
EntryTy
(
id
,
_
)
=>
id
,
EntryLocal
(
id
,
_
)
=>
id
,
EntryPat
(
id
,
_
)
=>
id
,
EntryBlock
(
id
,
_
)
=>
id
,
...
...
@@ -144,6 +148,7 @@ fn to_node(self) -> Option<Node<'ast>> {
EntryVariant
(
_
,
n
)
=>
NodeVariant
(
n
),
EntryExpr
(
_
,
n
)
=>
NodeExpr
(
n
),
EntryStmt
(
_
,
n
)
=>
NodeStmt
(
n
),
EntryTy
(
_
,
n
)
=>
NodeTy
(
n
),
EntryLocal
(
_
,
n
)
=>
NodeLocal
(
n
),
EntryPat
(
_
,
n
)
=>
NodePat
(
n
),
EntryBlock
(
_
,
n
)
=>
NodeBlock
(
n
),
...
...
@@ -257,6 +262,7 @@ fn dep_node(&self, id0: NodeId) -> DepNode<DefId> {
EntryVariant
(
p
,
_
)
|
EntryExpr
(
p
,
_
)
|
EntryStmt
(
p
,
_
)
|
EntryTy
(
p
,
_
)
|
EntryLocal
(
p
,
_
)
|
EntryPat
(
p
,
_
)
|
EntryBlock
(
p
,
_
)
|
...
...
@@ -297,6 +303,7 @@ fn dep_node(&self, id0: NodeId) -> DepNode<DefId> {
EntryVariant
(
p
,
_
)
|
EntryExpr
(
p
,
_
)
|
EntryStmt
(
p
,
_
)
|
EntryTy
(
p
,
_
)
|
EntryLocal
(
p
,
_
)
|
EntryPat
(
p
,
_
)
|
EntryBlock
(
p
,
_
)
|
...
...
@@ -680,6 +687,7 @@ pub fn opt_span(&self, id: NodeId) -> Option<Span> {
Some
(
NodeVariant
(
variant
))
=>
variant
.span
,
Some
(
NodeExpr
(
expr
))
=>
expr
.span
,
Some
(
NodeStmt
(
stmt
))
=>
stmt
.span
,
Some
(
NodeTy
(
ty
))
=>
ty
.span
,
Some
(
NodeLocal
(
pat
))
=>
pat
.span
,
Some
(
NodePat
(
pat
))
=>
pat
.span
,
Some
(
NodeBlock
(
block
))
=>
block
.span
,
...
...
@@ -971,6 +979,7 @@ fn print_node(&mut self, node: &Node) -> io::Result<()> {
NodeVariant
(
a
)
=>
self
.print_variant
(
&
a
),
NodeExpr
(
a
)
=>
self
.print_expr
(
&
a
),
NodeStmt
(
a
)
=>
self
.print_stmt
(
&
a
),
NodeTy
(
a
)
=>
self
.print_type
(
&
a
),
NodePat
(
a
)
=>
self
.print_pat
(
&
a
),
NodeBlock
(
a
)
=>
self
.print_block
(
&
a
),
NodeLifetime
(
a
)
=>
self
.print_lifetime
(
&
a
),
...
...
@@ -1059,6 +1068,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
Some
(
NodeStmt
(
ref
stmt
))
=>
{
format!
(
"stmt {}{}"
,
pprust
::
stmt_to_string
(
&
stmt
),
id_str
)
}
Some
(
NodeTy
(
ref
ty
))
=>
{
format!
(
"type {}{}"
,
pprust
::
ty_to_string
(
&
ty
),
id_str
)
}
Some
(
NodeLocal
(
ref
pat
))
=>
{
format!
(
"local {}{}"
,
pprust
::
pat_to_string
(
&
pat
),
id_str
)
}
...
...
src/librustc_metadata/encoder.rs
浏览文件 @
d92e594c
...
...
@@ -1390,6 +1390,20 @@ fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) {
intravisit
::
walk_foreign_item
(
self
,
ni
);
encode_info_for_foreign_item
(
self
.ecx
,
self
.rbml_w_for_visit_item
,
ni
,
self
.index
);
}
fn
visit_ty
(
&
mut
self
,
ty
:
&
'tcx
hir
::
Ty
)
{
intravisit
::
walk_ty
(
self
,
ty
);
if
let
hir
::
TyImplTrait
(
_
)
=
ty
.node
{
let
rbml_w
=
&
mut
*
self
.rbml_w_for_visit_item
;
let
def_id
=
self
.ecx.tcx.map
.local_def_id
(
ty
.id
);
let
_
task
=
self
.index
.record
(
def_id
,
rbml_w
);
rbml_w
.start_tag
(
tag_items_data_item
);
encode_def_id_and_key
(
self
.ecx
,
rbml_w
,
def_id
);
encode_family
(
rbml_w
,
'y'
);
encode_bounds_and_type_for_item
(
rbml_w
,
self
.ecx
,
self
.index
,
ty
.id
);
rbml_w
.end_tag
();
}
}
}
fn
encode_info_for_items
<
'a
,
'tcx
>
(
ecx
:
&
EncodeContext
<
'a
,
'tcx
>
,
...
...
src/librustc_typeck/astconv.rs
浏览文件 @
d92e594c
...
...
@@ -1763,25 +1763,28 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
// Create the anonymized type.
let
def_id
=
tcx
.map
.local_def_id
(
ast_ty
.id
);
let
substs
=
if
let
Some
(
anon_scope
)
=
rscope
.anon_type_scope
()
{
anon_scope
.fresh_substs
(
tcx
)
if
let
Some
(
anon_scope
)
=
rscope
.anon_type_scope
()
{
let
substs
=
anon_scope
.fresh_substs
(
tcx
);
let
ty
=
tcx
.mk_anon
(
tcx
.map
.local_def_id
(
ast_ty
.id
),
substs
);
// Collect the bounds, i.e. the `A+B+'c` in `impl A+B+'c`.
let
bounds
=
compute_bounds
(
self
,
ty
,
bounds
,
SizedByDefault
::
Yes
,
Some
(
anon_scope
),
ast_ty
.span
);
let
predicates
=
bounds
.predicates
(
tcx
,
ty
);
let
predicates
=
tcx
.lift_to_global
(
&
predicates
)
.unwrap
();
tcx
.predicates
.borrow_mut
()
.insert
(
def_id
,
ty
::
GenericPredicates
{
predicates
:
VecPerParamSpace
::
new
(
vec!
[],
vec!
[],
predicates
)
});
ty
}
else
{
span_err!
(
tcx
.sess
,
ast_ty
.span
,
E0562
,
"`impl Trait` not allowed outside of function
\
and inherent method return types"
);
tcx
.mk_substs
(
Substs
::
empty
())
};
let
ty
=
tcx
.mk_anon
(
tcx
.map
.local_def_id
(
ast_ty
.id
),
substs
);
// Collect the bounds, i.e. the `A+B+'c` in `impl A+B+'c`.
let
bounds
=
compute_bounds
(
self
,
ty
,
bounds
,
SizedByDefault
::
Yes
,
ast_ty
.span
);
let
predicates
=
tcx
.lift_to_global
(
&
bounds
.predicates
(
tcx
,
ty
))
.unwrap
();
let
predicates
=
ty
::
GenericPredicates
{
predicates
:
VecPerParamSpace
::
new
(
vec!
[],
vec!
[],
predicates
)
};
tcx
.predicates
.borrow_mut
()
.insert
(
def_id
,
predicates
);
ty
tcx
.types.err
}
}
hir
::
TyPath
(
ref
maybe_qself
,
ref
path
)
=>
{
debug!
(
"ast_ty_to_ty: maybe_qself={:?} path={:?}"
,
maybe_qself
,
path
);
...
...
src/librustc_typeck/check/mod.rs
浏览文件 @
d92e594c
...
...
@@ -96,7 +96,7 @@
use
rustc
::
ty
::{
self
,
ToPolyTraitRef
,
Ty
,
TyCtxt
,
Visibility
};
use
rustc
::
ty
::{
MethodCall
,
MethodCallee
};
use
rustc
::
ty
::
adjustment
;
use
rustc
::
ty
::
fold
::
TypeFoldable
;
use
rustc
::
ty
::
fold
::
{
BottomUpFolder
,
TypeFoldable
}
;
use
rustc
::
ty
::
util
::{
Representability
,
IntTypeExt
};
use
require_c_abi_if_variadic
;
use
rscope
::{
ElisionFailureInfo
,
RegionScope
};
...
...
@@ -172,6 +172,12 @@ pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
deferred_call_resolutions
:
RefCell
<
DefIdMap
<
Vec
<
DeferredCallResolutionHandler
<
'gcx
,
'tcx
>>>>
,
deferred_cast_checks
:
RefCell
<
Vec
<
cast
::
CastCheck
<
'tcx
>>>
,
// Anonymized types found in explicit return types and their
// associated fresh inference variable. Writeback resolves these
// variables to get the concrete type, which can be used to
// deanonymize TyAnon, after typeck is done with all functions.
anon_types
:
RefCell
<
DefIdMap
<
Ty
<
'tcx
>>>
,
}
impl
<
'a
,
'gcx
,
'tcx
>
Deref
for
Inherited
<
'a
,
'gcx
,
'tcx
>
{
...
...
@@ -408,6 +414,7 @@ fn enter<F, R>(&'tcx mut self, f: F) -> R
locals
:
RefCell
::
new
(
NodeMap
()),
deferred_call_resolutions
:
RefCell
::
new
(
DefIdMap
()),
deferred_cast_checks
:
RefCell
::
new
(
Vec
::
new
()),
anon_types
:
RefCell
::
new
(
DefIdMap
()),
})
})
}
...
...
@@ -631,32 +638,29 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
body
:
&
'gcx
hir
::
Block
)
->
FnCtxt
<
'a
,
'gcx
,
'tcx
>
{
let
arg_tys
=
&
fn_sig
.inputs
;
let
ret_ty
=
fn_sig
.output
;
let
mut
fn_sig
=
fn_sig
.clone
();
debug!
(
"check_fn(arg_tys={:?}, ret_ty={:?}, fn_id={})"
,
arg_tys
,
ret_ty
,
fn_id
);
debug!
(
"check_fn(sig={:?}, fn_id={})"
,
fn_sig
,
fn_id
);
// Create the function context. This is either derived from scratch or,
// in the case of function expressions, based on the outer context.
let
fcx
=
FnCtxt
::
new
(
inherited
,
ret_ty
,
body
.id
);
let
mut
fcx
=
FnCtxt
::
new
(
inherited
,
fn_sig
.output
,
body
.id
);
*
fcx
.ps
.borrow_mut
()
=
UnsafetyState
::
function
(
unsafety
,
unsafety_id
);
if
let
ty
::
FnConverging
(
ret_ty
)
=
ret_ty
{
fcx
.require_type_is_sized
(
ret_ty
,
decl
.output
.span
(),
traits
::
ReturnType
);
}
debug!
(
"fn-sig-map: fn_id={} fn_sig={:?}"
,
fn_id
,
fn_sig
);
inherited
.tables
.borrow_mut
()
.liberated_fn_sigs
.insert
(
fn_id
,
fn_sig
.clone
());
fn_sig
.output
=
match
fcx
.ret_ty
{
ty
::
FnConverging
(
orig_ret_ty
)
=>
{
fcx
.require_type_is_sized
(
orig_ret_ty
,
decl
.output
.span
(),
traits
::
ReturnType
);
ty
::
FnConverging
(
fcx
.instantiate_anon_types
(
&
orig_ret_ty
))
}
ty
::
FnDiverging
=>
ty
::
FnDiverging
};
fcx
.ret_ty
=
fn_sig
.output
;
{
let
mut
visit
=
GatherLocalsVisitor
{
fcx
:
&
fcx
,
};
// Add formal parameters.
for
(
arg_ty
,
input
)
in
arg_ty
s
.iter
()
.zip
(
&
decl
.inputs
)
{
for
(
arg_ty
,
input
)
in
fn_sig
.input
s
.iter
()
.zip
(
&
decl
.inputs
)
{
// The type of the argument must be well-formed.
//
// NB -- this is now checked in wfcheck, but that
...
...
@@ -672,21 +676,20 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
});
// Check the pattern.
fcx
.check_pat
(
&
input
.pat
,
*
arg_ty
);
fcx
.check_pat
(
&
input
.pat
,
arg_ty
);
fcx
.write_ty
(
input
.id
,
arg_ty
);
}
visit
.visit_block
(
body
);
}
fcx
.check_block_with_expected
(
body
,
match
ret_ty
{
inherited
.tables
.borrow_mut
()
.liberated_fn_sigs
.insert
(
fn_id
,
fn_sig
);
fcx
.check_block_with_expected
(
body
,
match
fcx
.ret_ty
{
ty
::
FnConverging
(
result_type
)
=>
ExpectHasType
(
result_type
),
ty
::
FnDiverging
=>
NoExpectation
});
for
(
input
,
arg
)
in
decl
.inputs
.iter
()
.zip
(
arg_tys
)
{
fcx
.write_ty
(
input
.id
,
arg
);
}
fcx
}
...
...
@@ -1623,6 +1626,41 @@ fn instantiate_bounds(&self,
}
}
/// Replace all anonymized types with fresh inference variables
/// and record them for writeback.
fn
instantiate_anon_types
<
T
:
TypeFoldable
<
'tcx
>>
(
&
self
,
value
:
&
T
)
->
T
{
value
.fold_with
(
&
mut
BottomUpFolder
{
tcx
:
self
.tcx
,
fldop
:
|
ty
|
{
if
let
ty
::
TyAnon
(
def_id
,
substs
)
=
ty
.sty
{
// Use the same type variable if the exact same TyAnon appears more
// than once in the return type (e.g. if it's pased to a type alias).
if
let
Some
(
ty_var
)
=
self
.anon_types
.borrow
()
.get
(
&
def_id
)
{
return
ty_var
;
}
let
ty_var
=
self
.next_ty_var
();
self
.anon_types
.borrow_mut
()
.insert
(
def_id
,
ty_var
);
let
item_predicates
=
self
.tcx
.lookup_predicates
(
def_id
);
let
bounds
=
item_predicates
.instantiate
(
self
.tcx
,
substs
);
let
span
=
self
.tcx.map
.def_id_span
(
def_id
,
codemap
::
DUMMY_SP
);
for
predicate
in
bounds
.predicates
{
// Change the predicate to refer to the type variable,
// which will be the concrete type, instead of the TyAnon.
// This also instantiates nested `impl Trait`.
let
predicate
=
self
.instantiate_anon_types
(
&
predicate
);
// Require that the predicate holds for the concrete type.
let
cause
=
traits
::
ObligationCause
::
new
(
span
,
self
.body_id
,
traits
::
ReturnType
);
self
.register_predicate
(
traits
::
Obligation
::
new
(
cause
,
predicate
));
}
ty_var
}
else
{
ty
}
}})
}
fn
normalize_associated_types_in
<
T
>
(
&
self
,
span
:
Span
,
value
:
&
T
)
->
T
where
T
:
TypeFoldable
<
'tcx
>
...
...
src/librustc_typeck/check/writeback.rs
浏览文件 @
d92e594c
...
...
@@ -18,7 +18,9 @@
use
rustc
::
ty
::{
self
,
Ty
,
TyCtxt
,
MethodCall
,
MethodCallee
};
use
rustc
::
ty
::
adjustment
;
use
rustc
::
ty
::
fold
::{
TypeFolder
,
TypeFoldable
};
use
rustc
::
ty
::
subst
::
ParamSpace
;
use
rustc
::
infer
::{
InferCtxt
,
FixupError
};
use
rustc
::
util
::
nodemap
::
DefIdMap
;
use
write_substs_to_tcx
;
use
write_ty_to_tcx
;
...
...
@@ -62,6 +64,7 @@ pub fn resolve_type_vars_in_fn(&self, decl: &hir::FnDecl, blk: &hir::Block) {
wbcx
.visit_closures
();
wbcx
.visit_liberated_fn_sigs
();
wbcx
.visit_fru_field_types
();
wbcx
.visit_anon_types
();
}
}
...
...
@@ -75,11 +78,48 @@ pub fn resolve_type_vars_in_fn(&self, decl: &hir::FnDecl, blk: &hir::Block) {
struct
WritebackCx
<
'cx
,
'gcx
:
'cx
+
'tcx
,
'tcx
:
'cx
>
{
fcx
:
&
'cx
FnCtxt
<
'cx
,
'gcx
,
'tcx
>
,
// Mapping from free regions of the function to the
// early-bound versions of them, visible from the
// outside of the function. This is needed by, and
// only populated if there are any `impl Trait`.
free_to_bound_regions
:
DefIdMap
<
ty
::
Region
>
}
impl
<
'cx
,
'gcx
,
'tcx
>
WritebackCx
<
'cx
,
'gcx
,
'tcx
>
{
fn
new
(
fcx
:
&
'cx
FnCtxt
<
'cx
,
'gcx
,
'tcx
>
)
->
WritebackCx
<
'cx
,
'gcx
,
'tcx
>
{
WritebackCx
{
fcx
:
fcx
}
let
mut
wbcx
=
WritebackCx
{
fcx
:
fcx
,
free_to_bound_regions
:
DefIdMap
()
};
// Only build the reverse mapping if `impl Trait` is used.
if
fcx
.anon_types
.borrow
()
.is_empty
()
{
return
wbcx
;
}
let
free_substs
=
fcx
.parameter_environment.free_substs
;
for
&
space
in
&
ParamSpace
::
all
()
{
for
(
i
,
r
)
in
free_substs
.regions
.get_slice
(
space
)
.iter
()
.enumerate
()
{
match
*
r
{
ty
::
ReFree
(
ty
::
FreeRegion
{
bound_region
:
ty
::
BoundRegion
::
BrNamed
(
def_id
,
name
,
_
),
..
})
=>
{
let
bound_region
=
ty
::
ReEarlyBound
(
ty
::
EarlyBoundRegion
{
space
:
space
,
index
:
i
as
u32
,
name
:
name
,
});
wbcx
.free_to_bound_regions
.insert
(
def_id
,
bound_region
);
}
_
=>
{
bug!
(
"{:?} is not a free region for an early-bound lifetime"
,
r
);
}
}
}
}
wbcx
}
fn
tcx
(
&
self
)
->
TyCtxt
<
'cx
,
'gcx
,
'tcx
>
{
...
...
@@ -255,6 +295,58 @@ fn visit_closures(&self) {
}
}
fn
visit_anon_types
(
&
self
)
{
if
self
.fcx.writeback_errors
.get
()
{
return
}
let
gcx
=
self
.tcx
()
.global_tcx
();
for
(
&
def_id
,
&
concrete_ty
)
in
self
.fcx.anon_types
.borrow
()
.iter
()
{
let
reason
=
ResolvingAnonTy
(
def_id
);
let
inside_ty
=
self
.resolve
(
&
concrete_ty
,
reason
);
// Convert the type from the function into a type valid outside
// the function, by replacing free regions with early-bound ones.
let
outside_ty
=
gcx
.fold_regions
(
&
inside_ty
,
&
mut
false
,
|
r
,
_
|
{
match
r
{
// 'static is valid everywhere.
ty
::
ReStatic
=>
ty
::
ReStatic
,
// Free regions that come from early-bound regions are valid.
ty
::
ReFree
(
ty
::
FreeRegion
{
bound_region
:
ty
::
BoundRegion
::
BrNamed
(
def_id
,
_
,
_
),
..
})
if
self
.free_to_bound_regions
.contains_key
(
&
def_id
)
=>
{
self
.free_to_bound_regions
[
&
def_id
]
}
ty
::
ReFree
(
_
)
|
ty
::
ReEarlyBound
(
_
)
|
ty
::
ReLateBound
(
..
)
|
ty
::
ReScope
(
_
)
|
ty
::
ReSkolemized
(
..
)
=>
{
let
span
=
reason
.span
(
self
.tcx
());
span_err!
(
self
.tcx
()
.sess
,
span
,
E0564
,
"only named lifetimes are allowed in `impl Trait`,
\
but `{}` was found in the type `{}`"
,
r
,
inside_ty
);
ty
::
ReStatic
}
ty
::
ReVar
(
_
)
|
ty
::
ReEmpty
|
ty
::
ReErased
=>
{
let
span
=
reason
.span
(
self
.tcx
());
span_bug!
(
span
,
"invalid region in impl Trait: {:?}"
,
r
);
}
}
});
gcx
.tcache
.borrow_mut
()
.insert
(
def_id
,
ty
::
TypeScheme
{
ty
:
outside_ty
,
generics
:
ty
::
Generics
::
empty
()
});
}
}
fn
visit_node_id
(
&
self
,
reason
:
ResolveReason
,
id
:
ast
::
NodeId
)
{
// Resolve any borrowings for the node with id `id`
self
.visit_adjustments
(
reason
,
id
);
...
...
@@ -377,7 +469,8 @@ enum ResolveReason {
ResolvingUpvar
(
ty
::
UpvarId
),
ResolvingClosure
(
DefId
),
ResolvingFnSig
(
ast
::
NodeId
),
ResolvingFieldTypes
(
ast
::
NodeId
)
ResolvingFieldTypes
(
ast
::
NodeId
),
ResolvingAnonTy
(
DefId
),
}
impl
<
'a
,
'gcx
,
'tcx
>
ResolveReason
{
...
...
@@ -395,12 +488,9 @@ fn span(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Span {
ResolvingFieldTypes
(
id
)
=>
{
tcx
.map
.span
(
id
)
}
ResolvingClosure
(
did
)
=>
{
if
let
Some
(
node_id
)
=
tcx
.map
.as_local_node_id
(
did
)
{
tcx
.expr_span
(
node_id
)
}
else
{
DUMMY_SP
}
ResolvingClosure
(
did
)
|
ResolvingAnonTy
(
did
)
=>
{
tcx
.map
.def_id_span
(
did
,
DUMMY_SP
)
}
}
}
...
...
@@ -483,6 +573,12 @@ fn report_error(&self, e: FixupError) {
span
,
&
format!
(
"cannot resolve some aspect of data for {:?}"
,
id
));
}
ResolvingAnonTy
(
_
)
=>
{
let
span
=
self
.reason
.span
(
self
.tcx
);
span_err!
(
self
.tcx.sess
,
span
,
E0563
,
"cannot determine a type for this `impl Trait`: {}"
,
e
)
}
}
}
}
...
...
src/librustc_typeck/collect.rs
浏览文件 @
d92e594c
...
...
@@ -1194,10 +1194,11 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt,
// Convert the bounds that follow the colon, e.g. `Bar+Zed` in `trait Foo : Bar+Zed`.
let
self_param_ty
=
tcx
.mk_self_type
();
let
superbounds1
=
compute_bounds
(
&
ccx
.icx
(
scope
),
self_param_ty
,
bounds
,
SizedByDefault
::
No
,
item
.span
);
self_param_ty
,
bounds
,
SizedByDefault
::
No
,
None
,
item
.span
);
let
superbounds1
=
superbounds1
.predicates
(
tcx
,
self_param_ty
);
...
...
@@ -1407,6 +1408,7 @@ fn predicates_for_associated_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
assoc_ty
,
bounds
,
SizedByDefault
::
Yes
,
None
,
trait_item
.span
);
bounds
.predicates
(
ccx
.tcx
,
assoc_ty
)
.into_iter
()
...
...
@@ -1780,6 +1782,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
param_ty
,
&
param
.bounds
,
SizedByDefault
::
Yes
,
None
,
param
.span
);
let
predicates
=
bounds
.predicates
(
ccx
.tcx
,
param_ty
);
result
.predicates
.extend
(
space
,
predicates
.into_iter
());
...
...
@@ -2052,25 +2055,43 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
param_ty
:
ty
::
Ty
<
'tcx
>
,
ast_bounds
:
&
[
hir
::
TyParamBound
],
sized_by_default
:
SizedByDefault
,
anon_scope
:
Option
<
AnonTypeScope
>
,
span
:
Span
)
->
Bounds
<
'tcx
>
{
let
mut
bounds
=
conv_param_bounds
(
astconv
,
span
,
param_ty
,
ast_bounds
);
let
tcx
=
astconv
.tcx
();
let
PartitionedBounds
{
mut
builtin_bounds
,
trait_bounds
,
region_bounds
}
=
partition_bounds
(
tcx
,
span
,
&
ast_bounds
);
if
let
SizedByDefault
::
Yes
=
sized_by_default
{
add_unsized_bound
(
astconv
,
&
mut
bounds
.builtin_bounds
,
ast_bounds
,
span
);
add_unsized_bound
(
astconv
,
&
mut
builtin_bounds
,
ast_bounds
,
span
);
}
bounds
.trait_bounds
.sort_by
(|
a
,
b
|
a
.def_id
()
.cmp
(
&
b
.def_id
()));
let
mut
projection_bounds
=
vec!
[];
let
rscope
=
MaybeWithAnonTypes
::
new
(
ExplicitRscope
,
anon_scope
);
let
mut
trait_bounds
:
Vec
<
_
>
=
trait_bounds
.iter
()
.map
(|
&
bound
|
{
astconv
.instantiate_poly_trait_ref
(
&
rscope
,
bound
,
Some
(
param_ty
),
&
mut
projection_bounds
)
})
.collect
();
let
region_bounds
=
region_bounds
.into_iter
()
.map
(|
r
|
{
ast_region_to_region
(
tcx
,
r
)
})
.collect
();
trait_bounds
.sort_by
(|
a
,
b
|
a
.def_id
()
.cmp
(
&
b
.def_id
()));
bounds
Bounds
{
region_bounds
:
region_bounds
,
builtin_bounds
:
builtin_bounds
,
trait_bounds
:
trait_bounds
,
projection_bounds
:
projection_bounds
,
}
}
/// Converts a specific TyParamBound from the AST into a set of
...
...
@@ -2116,42 +2137,6 @@ fn conv_poly_trait_ref<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
projections
)
}
fn
conv_param_bounds
<
'gcx
:
'tcx
,
'tcx
>
(
astconv
:
&
AstConv
<
'gcx
,
'tcx
>
,
span
:
Span
,
param_ty
:
ty
::
Ty
<
'tcx
>
,
ast_bounds
:
&
[
hir
::
TyParamBound
])
->
Bounds
<
'tcx
>
{
let
tcx
=
astconv
.tcx
();
let
PartitionedBounds
{
builtin_bounds
,
trait_bounds
,
region_bounds
}
=
partition_bounds
(
tcx
,
span
,
&
ast_bounds
);
let
mut
projection_bounds
=
Vec
::
new
();
let
trait_bounds
:
Vec
<
ty
::
PolyTraitRef
>
=
trait_bounds
.iter
()
.map
(|
bound
|
conv_poly_trait_ref
(
astconv
,
param_ty
,
*
bound
,
&
mut
projection_bounds
))
.collect
();
let
region_bounds
:
Vec
<
ty
::
Region
>
=
region_bounds
.into_iter
()
.map
(|
r
|
ast_region_to_region
(
tcx
,
r
))
.collect
();
Bounds
{
region_bounds
:
region_bounds
,
builtin_bounds
:
builtin_bounds
,
trait_bounds
:
trait_bounds
,
projection_bounds
:
projection_bounds
,
}
}
fn
compute_type_scheme_of_foreign_fn_decl
<
'a
,
'tcx
>
(
ccx
:
&
CrateCtxt
<
'a
,
'tcx
>
,
id
:
DefId
,
...
...
src/librustc_typeck/diagnostics.rs
浏览文件 @
d92e594c
...
...
@@ -4086,4 +4086,7 @@ struct Simba {
E0533
,
// `{}` does not name a unit variant, unit struct or a constant
E0562
,
// `impl Trait` not allowed outside of function
// and inherent method return types
E0563
,
// cannot determine a type for this `impl Trait`: {}
E0564
,
// only named lifetimes are allowed in `impl Trait`,
// but `{}` was found in the type `{}`
}
src/test/run-pass/impl-trait/example-calendar.rs
0 → 100644
浏览文件 @
d92e594c
此差异已折叠。
点击以展开。
src/test/run-pass/impl-trait/example-st.rs
0 → 100644
浏览文件 @
d92e594c
// Copyright 2016 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(conservative_impl_trait,
question_mark)]
struct
State
;
type
Error
=
();
trait
Bind
<
F
>
{
type
Output
;
fn
bind
(
self
,
f
:
F
)
->
Self
::
Output
;
}
fn
bind
<
T
,
U
,
A
,
B
,
F
>
(
mut
a
:
A
,
mut
f
:
F
)
->
impl
FnMut
(
&
mut
State
)
->
Result
<
U
,
Error
>
where
F
:
FnMut
(
T
)
->
B
,
A
:
FnMut
(
&
mut
State
)
->
Result
<
T
,
Error
>
,
B
:
FnMut
(
&
mut
State
)
->
Result
<
U
,
Error
>
{
move
|
state
|
{
let
r
=
a
(
state
)
?
;
f
(
r
)(
state
)
}
}
fn
atom
<
T
>
(
x
:
T
)
->
impl
FnMut
(
&
mut
State
)
->
Result
<
T
,
Error
>
{
let
mut
x
=
Some
(
x
);
move
|
_
|
x
.take
()
.map_or
(
Err
(()),
Ok
)
}
fn
main
()
{
assert_eq!
(
bind
(
atom
(
5
),
|
x
|
atom
(
x
>
4
))(
&
mut
State
),
Ok
(
true
));
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录