Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
a950c373
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,发现更多精彩内容 >>
提交
a950c373
编写于
5月 02, 2017
作者:
N
Niko Matsakis
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
replace the type generalizer with one based on variance
上级
24ea08e9
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
146 addition
and
65 deletion
+146
-65
src/librustc/infer/combine.rs
src/librustc/infer/combine.rs
+86
-35
src/librustc/ty/mod.rs
src/librustc/ty/mod.rs
+60
-0
src/librustc_typeck/variance/constraints.rs
src/librustc_typeck/variance/constraints.rs
+0
-1
src/librustc_typeck/variance/xform.rs
src/librustc_typeck/variance/xform.rs
+0
-29
未找到文件。
src/librustc/infer/combine.rs
浏览文件 @
a950c373
...
...
@@ -42,8 +42,7 @@
use
ty
::{
IntType
,
UintType
};
use
ty
::{
self
,
Ty
,
TyCtxt
};
use
ty
::
error
::
TypeError
;
use
ty
::
fold
::
TypeFoldable
;
use
ty
::
relate
::{
RelateResult
,
TypeRelation
};
use
ty
::
relate
::{
self
,
Relate
,
RelateResult
,
TypeRelation
};
use
traits
::
PredicateObligations
;
use
syntax
::
ast
;
...
...
@@ -207,7 +206,7 @@ pub fn instantiate(&mut self,
// `'?2` and `?3` are fresh region/type inference
// variables. (Down below, we will relate `a_ty <: b_ty`,
// adding constraints like `'x: '?2` and `?1 <: ?3`.)
let
b_ty
=
self
.generalize
(
a_ty
,
b_vid
,
dir
==
EqTo
)
?
;
let
b_ty
=
self
.generalize
(
a_ty
,
b_vid
,
dir
)
?
;
debug!
(
"instantiate(a_ty={:?}, dir={:?}, b_vid={:?}, generalized b_ty={:?})"
,
a_ty
,
dir
,
b_vid
,
b_ty
);
self
.infcx.type_variables
.borrow_mut
()
.instantiate
(
b_vid
,
b_ty
);
...
...
@@ -241,22 +240,30 @@ pub fn instantiate(&mut self,
fn
generalize
(
&
self
,
ty
:
Ty
<
'tcx
>
,
for_vid
:
ty
::
TyVid
,
is_eq_relation
:
bool
)
dir
:
RelationDir
)
->
RelateResult
<
'tcx
,
Ty
<
'tcx
>>
{
// Determine the ambient variance within which `ty` appears.
// The surrounding equation is:
//
// ty [op] ty2
//
// where `op` is either `==`, `<:`, or `:>`. This maps quite
// naturally.
let
ambient_variance
=
match
dir
{
RelationDir
::
EqTo
=>
ty
::
Invariant
,
RelationDir
::
SubtypeOf
=>
ty
::
Covariant
,
RelationDir
::
SupertypeOf
=>
ty
::
Contravariant
,
};
let
mut
generalize
=
Generalizer
{
infcx
:
self
.infcx
,
span
:
self
.trace.cause.span
,
for_vid_sub_root
:
self
.infcx.type_variables
.borrow_mut
()
.sub_root_var
(
for_vid
),
is_eq_relation
:
is_eq_relation
,
cycle_detected
:
false
ambient_variance
:
ambient_variance
,
};
let
u
=
ty
.fold_with
(
&
mut
generalize
);
if
generalize
.cycle_detected
{
Err
(
TypeError
::
CyclicTy
)
}
else
{
Ok
(
u
)
}
generalize
.relate
(
&
ty
,
&
ty
)
}
}
...
...
@@ -264,16 +271,46 @@ struct Generalizer<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
infcx
:
&
'cx
InferCtxt
<
'cx
,
'gcx
,
'tcx
>
,
span
:
Span
,
for_vid_sub_root
:
ty
::
TyVid
,
is_eq_relation
:
bool
,
cycle_detected
:
bool
,
ambient_variance
:
ty
::
Variance
,
}
impl
<
'cx
,
'gcx
,
'tcx
>
ty
::
fold
::
TypeFolder
<
'gcx
,
'tcx
>
for
Generalizer
<
'cx
,
'gcx
,
'tcx
>
{
fn
tcx
<
'a
>
(
&
'a
self
)
->
TyCtxt
<
'a
,
'gcx
,
'tcx
>
{
impl
<
'cx
,
'gcx
,
'tcx
>
TypeRelation
<
'cx
,
'gcx
,
'tcx
>
for
Generalizer
<
'cx
,
'gcx
,
'tcx
>
{
fn
tcx
(
&
self
)
->
TyCtxt
<
'cx
,
'gcx
,
'tcx
>
{
self
.infcx.tcx
}
fn
fold_ty
(
&
mut
self
,
t
:
Ty
<
'tcx
>
)
->
Ty
<
'tcx
>
{
fn
tag
(
&
self
)
->
&
'static
str
{
"Generalizer"
}
fn
a_is_expected
(
&
self
)
->
bool
{
true
}
fn
binders
<
T
>
(
&
mut
self
,
a
:
&
ty
::
Binder
<
T
>
,
b
:
&
ty
::
Binder
<
T
>
)
->
RelateResult
<
'tcx
,
ty
::
Binder
<
T
>>
where
T
:
Relate
<
'tcx
>
{
Ok
(
ty
::
Binder
(
self
.relate
(
a
.skip_binder
(),
b
.skip_binder
())
?
))
}
fn
relate_with_variance
<
T
:
Relate
<
'tcx
>>
(
&
mut
self
,
variance
:
ty
::
Variance
,
a
:
&
T
,
b
:
&
T
)
->
RelateResult
<
'tcx
,
T
>
{
let
old_ambient_variance
=
self
.ambient_variance
;
self
.ambient_variance
=
self
.ambient_variance
.xform
(
variance
);
let
result
=
self
.relate
(
a
,
b
);
self
.ambient_variance
=
old_ambient_variance
;
result
}
fn
tys
(
&
mut
self
,
t
:
Ty
<
'tcx
>
,
t2
:
Ty
<
'tcx
>
)
->
RelateResult
<
'tcx
,
Ty
<
'tcx
>>
{
assert_eq!
(
t
,
t2
);
// we are abusing TypeRelation here; both LHS and RHS ought to be ==
// Check to see whether the type we are genealizing references
// any other type variable related to `vid` via
// subtyping. This is basically our "occurs check", preventing
...
...
@@ -286,41 +323,54 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
if
sub_vid
==
self
.for_vid_sub_root
{
// If sub-roots are equal, then `for_vid` and
// `vid` are related via subtyping.
self
.cycle_detected
=
true
;
self
.tcx
()
.types.err
return
Err
(
TypeError
::
CyclicTy
);
}
else
{
match
variables
.probe_root
(
vid
)
{
Some
(
u
)
=>
{
drop
(
variables
);
self
.
fold_ty
(
u
)
self
.
relate
(
&
u
,
&
u
)
}
None
=>
{
if
!
self
.is_eq_relation
{
let
origin
=
variables
.origin
(
vid
);
let
new_var_id
=
variables
.new_var
(
false
,
origin
,
None
);
let
u
=
self
.tcx
()
.mk_var
(
new_var_id
);
debug!
(
"generalize: replacing original vid={:?} with new={:?}"
,
vid
,
u
);
u
}
else
{
t
match
self
.ambient_variance
{
ty
::
Invariant
=>
Ok
(
t
),
ty
::
Bivariant
|
ty
::
Covariant
|
ty
::
Contravariant
=>
{
let
origin
=
variables
.origin
(
vid
);
let
new_var_id
=
variables
.new_var
(
false
,
origin
,
None
);
let
u
=
self
.tcx
()
.mk_var
(
new_var_id
);
debug!
(
"generalize: replacing original vid={:?} with new={:?}"
,
vid
,
u
);
Ok
(
u
)
}
}
}
}
}
}
ty
::
TyInfer
(
ty
::
IntVar
(
_
))
|
ty
::
TyInfer
(
ty
::
FloatVar
(
_
))
=>
{
// No matter what mode we are in,
// integer/floating-point types must be equal to be
// relatable.
Ok
(
t
)
}
_
=>
{
t
.super_fold_with
(
self
)
relate
::
super_relate_tys
(
self
,
t
,
t
)
}
}
}
fn
fold_region
(
&
mut
self
,
r
:
ty
::
Region
<
'tcx
>
)
->
ty
::
Region
<
'tcx
>
{
fn
regions
(
&
mut
self
,
r
:
ty
::
Region
<
'tcx
>
,
r2
:
ty
::
Region
<
'tcx
>
)
->
RelateResult
<
'tcx
,
ty
::
Region
<
'tcx
>>
{
assert_eq!
(
r
,
r2
);
// we are abusing TypeRelation here; both LHS and RHS ought to be ==
match
*
r
{
// Never make variables for regions bound within the type itself,
// nor for erased regions.
ty
::
ReLateBound
(
..
)
|
ty
::
ReErased
=>
{
return
r
;
}
ty
::
ReErased
=>
{
return
Ok
(
r
);
}
// Early-bound regions should really have been substituted away before
// we get to this point.
...
...
@@ -342,15 +392,16 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
ty
::
ReScope
(
..
)
|
ty
::
ReVar
(
..
)
|
ty
::
ReFree
(
..
)
=>
{
if
self
.is_eq_relation
{
return
r
;
match
self
.ambient_variance
{
ty
::
Invariant
=>
return
Ok
(
r
),
ty
::
Bivariant
|
ty
::
Covariant
|
ty
::
Contravariant
=>
(),
}
}
}
// FIXME: This is non-ideal because we don't give a
// very descriptive origin for this region variable.
self
.infcx
.next_region_var
(
MiscVariable
(
self
.span
))
Ok
(
self
.infcx
.next_region_var
(
MiscVariable
(
self
.span
)
))
}
}
...
...
src/librustc/ty/mod.rs
浏览文件 @
a950c373
...
...
@@ -330,6 +330,66 @@ pub struct CrateVariancesMap {
pub
empty_variance
:
Rc
<
Vec
<
ty
::
Variance
>>
,
}
impl
Variance
{
/// `a.xform(b)` combines the variance of a context with the
/// variance of a type with the following meaning. If we are in a
/// context with variance `a`, and we encounter a type argument in
/// a position with variance `b`, then `a.xform(b)` is the new
/// variance with which the argument appears.
///
/// Example 1:
///
/// *mut Vec<i32>
///
/// Here, the "ambient" variance starts as covariant. `*mut T` is
/// invariant with respect to `T`, so the variance in which the
/// `Vec<i32>` appears is `Covariant.xform(Invariant)`, which
/// yields `Invariant`. Now, the type `Vec<T>` is covariant with
/// respect to its type argument `T`, and hence the variance of
/// the `i32` here is `Invariant.xform(Covariant)`, which results
/// (again) in `Invariant`.
///
/// Example 2:
///
/// fn(*const Vec<i32>, *mut Vec<i32)
///
/// The ambient variance is covariant. A `fn` type is
/// contravariant with respect to its parameters, so the variance
/// within which both pointer types appear is
/// `Covariant.xform(Contravariant)`, or `Contravariant`. `*const
/// T` is covariant with respect to `T`, so the variance within
/// which the first `Vec<i32>` appears is
/// `Contravariant.xform(Covariant)` or `Contravariant`. The same
/// is true for its `i32` argument. In the `*mut T` case, the
/// variance of `Vec<i32>` is `Contravariant.xform(Invariant)`,
/// and hence the outermost type is `Invariant` with respect to
/// `Vec<i32>` (and its `i32` argument).
///
/// Source: Figure 1 of "Taming the Wildcards:
/// Combining Definition- and Use-Site Variance" published in PLDI'11.
pub
fn
xform
(
self
,
v
:
ty
::
Variance
)
->
ty
::
Variance
{
match
(
self
,
v
)
{
// Figure 1, column 1.
(
ty
::
Covariant
,
ty
::
Covariant
)
=>
ty
::
Covariant
,
(
ty
::
Covariant
,
ty
::
Contravariant
)
=>
ty
::
Contravariant
,
(
ty
::
Covariant
,
ty
::
Invariant
)
=>
ty
::
Invariant
,
(
ty
::
Covariant
,
ty
::
Bivariant
)
=>
ty
::
Bivariant
,
// Figure 1, column 2.
(
ty
::
Contravariant
,
ty
::
Covariant
)
=>
ty
::
Contravariant
,
(
ty
::
Contravariant
,
ty
::
Contravariant
)
=>
ty
::
Covariant
,
(
ty
::
Contravariant
,
ty
::
Invariant
)
=>
ty
::
Invariant
,
(
ty
::
Contravariant
,
ty
::
Bivariant
)
=>
ty
::
Bivariant
,
// Figure 1, column 3.
(
ty
::
Invariant
,
_
)
=>
ty
::
Invariant
,
// Figure 1, column 4.
(
ty
::
Bivariant
,
_
)
=>
ty
::
Bivariant
,
}
}
}
#[derive(Clone,
Copy,
Debug,
RustcDecodable,
RustcEncodable)]
pub
struct
MethodCallee
<
'tcx
>
{
/// Impl method ID, for inherent methods, or trait method ID, otherwise.
...
...
src/librustc_typeck/variance/constraints.rs
浏览文件 @
a950c373
...
...
@@ -27,7 +27,6 @@
use
super
::
terms
::
*
;
use
super
::
terms
::
VarianceTerm
::
*
;
use
super
::
xform
::
*
;
pub
struct
ConstraintContext
<
'a
,
'tcx
:
'a
>
{
pub
terms_cx
:
TermsContext
<
'a
,
'tcx
>
,
...
...
src/librustc_typeck/variance/xform.rs
浏览文件 @
a950c373
...
...
@@ -10,35 +10,6 @@
use
rustc
::
ty
;
pub
trait
Xform
{
fn
xform
(
self
,
v
:
Self
)
->
Self
;
}
impl
Xform
for
ty
::
Variance
{
fn
xform
(
self
,
v
:
ty
::
Variance
)
->
ty
::
Variance
{
// "Variance transformation", Figure 1 of The Paper
match
(
self
,
v
)
{
// Figure 1, column 1.
(
ty
::
Covariant
,
ty
::
Covariant
)
=>
ty
::
Covariant
,
(
ty
::
Covariant
,
ty
::
Contravariant
)
=>
ty
::
Contravariant
,
(
ty
::
Covariant
,
ty
::
Invariant
)
=>
ty
::
Invariant
,
(
ty
::
Covariant
,
ty
::
Bivariant
)
=>
ty
::
Bivariant
,
// Figure 1, column 2.
(
ty
::
Contravariant
,
ty
::
Covariant
)
=>
ty
::
Contravariant
,
(
ty
::
Contravariant
,
ty
::
Contravariant
)
=>
ty
::
Covariant
,
(
ty
::
Contravariant
,
ty
::
Invariant
)
=>
ty
::
Invariant
,
(
ty
::
Contravariant
,
ty
::
Bivariant
)
=>
ty
::
Bivariant
,
// Figure 1, column 3.
(
ty
::
Invariant
,
_
)
=>
ty
::
Invariant
,
// Figure 1, column 4.
(
ty
::
Bivariant
,
_
)
=>
ty
::
Bivariant
,
}
}
}
pub
fn
glb
(
v1
:
ty
::
Variance
,
v2
:
ty
::
Variance
)
->
ty
::
Variance
{
// Greatest lower bound of the variance lattice as
// defined in The Paper:
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录