Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
1265a031
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,发现更多精彩内容 >>
提交
1265a031
编写于
12月 26, 2013
作者:
L
Luqman Aden
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
librustc: Implement coercion for traits.
上级
00d87e0d
变更
16
隐藏空白更改
内联
并排
Showing
16 changed file
with
454 addition
and
142 deletion
+454
-142
src/libextra/enum_set.rs
src/libextra/enum_set.rs
+1
-1
src/librustc/metadata/tydecode.rs
src/librustc/metadata/tydecode.rs
+6
-0
src/librustc/metadata/tyencode.rs
src/librustc/metadata/tyencode.rs
+1
-1
src/librustc/middle/astencode.rs
src/librustc/middle/astencode.rs
+102
-12
src/librustc/middle/borrowck/gather_loans/mod.rs
src/librustc/middle/borrowck/gather_loans/mod.rs
+4
-0
src/librustc/middle/borrowck/mod.rs
src/librustc/middle/borrowck/mod.rs
+1
-1
src/librustc/middle/kind.rs
src/librustc/middle/kind.rs
+30
-14
src/librustc/middle/mem_categorization.rs
src/librustc/middle/mem_categorization.rs
+7
-0
src/librustc/middle/trans/consts.rs
src/librustc/middle/trans/consts.rs
+3
-0
src/librustc/middle/trans/expr.rs
src/librustc/middle/trans/expr.rs
+24
-3
src/librustc/middle/trans/meth.rs
src/librustc/middle/trans/meth.rs
+11
-3
src/librustc/middle/ty.rs
src/librustc/middle/ty.rs
+24
-3
src/librustc/middle/typeck/check/regionck.rs
src/librustc/middle/typeck/check/regionck.rs
+42
-0
src/librustc/middle/typeck/check/vtable.rs
src/librustc/middle/typeck/check/vtable.rs
+116
-99
src/librustc/middle/typeck/check/writeback.rs
src/librustc/middle/typeck/check/writeback.rs
+6
-0
src/librustc/middle/typeck/infer/coercion.rs
src/librustc/middle/typeck/infer/coercion.rs
+76
-5
未找到文件。
src/libextra/enum_set.rs
浏览文件 @
1265a031
...
...
@@ -13,7 +13,7 @@
//! This module defines a container which uses an efficient bit mask
//! representation to hold C-like enum variants.
#[deriving(Clone,
Eq,
IterBytes,
ToStr)]
#[deriving(Clone,
Eq,
IterBytes,
ToStr
,
Encodable,
Decodable
)]
/// A specialized Set implementation to use enum types.
pub
struct
EnumSet
<
E
>
{
// We must maintain the invariant that no bits are set
...
...
src/librustc/metadata/tydecode.rs
浏览文件 @
1265a031
...
...
@@ -129,6 +129,12 @@ pub fn parse_trait_ref_data(data: &[u8], crate_num: ast::CrateNum, pos: uint, tc
parse_trait_ref
(
&
mut
st
,
conv
)
}
pub
fn
parse_substs_data
(
data
:
&
[
u8
],
crate_num
:
ast
::
CrateNum
,
pos
:
uint
,
tcx
:
ty
::
ctxt
,
conv
:
conv_did
)
->
ty
::
substs
{
let
mut
st
=
parse_state_from_data
(
data
,
crate_num
,
pos
,
tcx
);
parse_substs
(
&
mut
st
,
conv
)
}
fn
parse_sigil
(
st
:
&
mut
PState
)
->
ast
::
Sigil
{
match
next
(
st
)
{
'@'
=>
ast
::
ManagedSigil
,
...
...
src/librustc/metadata/tyencode.rs
浏览文件 @
1265a031
...
...
@@ -140,7 +140,7 @@ fn enc_opt<T>(w: &mut MemWriter, t: Option<T>, enc_f: |&mut MemWriter, T|) {
}
}
fn
enc_substs
(
w
:
&
mut
MemWriter
,
cx
:
@
ctxt
,
substs
:
&
ty
::
substs
)
{
pub
fn
enc_substs
(
w
:
&
mut
MemWriter
,
cx
:
@
ctxt
,
substs
:
&
ty
::
substs
)
{
enc_region_substs
(
w
,
cx
,
&
substs
.regions
);
enc_opt
(
w
,
substs
.self_ty
,
|
w
,
t
|
enc_ty
(
w
,
cx
,
t
));
mywrite!
(
w
,
"["
);
...
...
src/librustc/middle/astencode.rs
浏览文件 @
1265a031
...
...
@@ -450,15 +450,13 @@ fn tr(&self, xcx: @ExtendedDecodeContext) -> ast::Def {
// ______________________________________________________________________
// Encoding and decoding of adjustment information
impl
tr
for
ty
::
AutoAdjustment
{
fn
tr
(
&
self
,
xcx
:
@
ExtendedDecodeContext
)
->
ty
::
AutoAdjustment
{
match
*
self
{
ty
::
AutoAddEnv
(
r
,
s
)
=>
ty
::
AutoAddEnv
(
r
.tr
(
xcx
),
s
),
ty
::
AutoDerefRef
(
ref
adr
)
=>
{
ty
::
AutoDerefRef
(
ty
::
AutoDerefRef
{
autoderefs
:
adr
.autoderefs
,
autoref
:
adr
.autoref
.map
(|
ar
|
ar
.tr
(
xcx
)),
})
impl
tr
for
ty
::
AutoDerefRef
{
fn
tr
(
&
self
,
xcx
:
@
ExtendedDecodeContext
)
->
ty
::
AutoDerefRef
{
ty
::
AutoDerefRef
{
autoderefs
:
self
.autoderefs
,
autoref
:
match
self
.autoref
{
Some
(
ref
autoref
)
=>
Some
(
autoref
.tr
(
xcx
)),
None
=>
None
}
}
}
...
...
@@ -786,6 +784,8 @@ fn emit_type_param_def(&mut self,
fn
emit_tpbt
(
&
mut
self
,
ecx
:
&
e
::
EncodeContext
,
tpbt
:
ty
::
ty_param_bounds_and_ty
);
fn
emit_substs
(
&
mut
self
,
ecx
:
&
e
::
EncodeContext
,
substs
:
&
ty
::
substs
);
fn
emit_auto_adjustment
(
&
mut
self
,
ecx
:
&
e
::
EncodeContext
,
adj
:
&
ty
::
AutoAdjustment
);
}
impl
<
'a
>
ebml_writer_helpers
for
writer
::
Encoder
<
'a
>
{
...
...
@@ -833,6 +833,40 @@ fn emit_tpbt(&mut self,
})
})
}
fn
emit_substs
(
&
mut
self
,
ecx
:
&
e
::
EncodeContext
,
substs
:
&
ty
::
substs
)
{
self
.emit_opaque
(|
this
|
tyencode
::
enc_substs
(
this
.writer
,
ecx
.ty_str_ctxt
(),
substs
))
}
fn
emit_auto_adjustment
(
&
mut
self
,
ecx
:
&
e
::
EncodeContext
,
adj
:
&
ty
::
AutoAdjustment
)
{
self
.emit_enum
(
"AutoAdjustment"
,
|
this
|
{
match
*
adj
{
ty
::
AutoAddEnv
(
region
,
sigil
)
=>
{
this
.emit_enum_variant
(
"AutoAddEnv"
,
0
,
2
,
|
this
|
{
this
.emit_enum_variant_arg
(
0
,
|
this
|
region
.encode
(
this
));
this
.emit_enum_variant_arg
(
1
,
|
this
|
sigil
.encode
(
this
));
});
}
ty
::
AutoDerefRef
(
ref
auto_deref_ref
)
=>
{
this
.emit_enum_variant
(
"AutoDerefRef"
,
1
,
1
,
|
this
|
{
this
.emit_enum_variant_arg
(
0
,
|
this
|
auto_deref_ref
.encode
(
this
));
});
}
ty
::
AutoObject
(
sigil
,
region
,
m
,
b
,
def_id
,
ref
substs
)
=>
{
this
.emit_enum_variant
(
"AutoObject"
,
2
,
6
,
|
this
|
{
this
.emit_enum_variant_arg
(
0
,
|
this
|
sigil
.encode
(
this
));
this
.emit_enum_variant_arg
(
1
,
|
this
|
region
.encode
(
this
));
this
.emit_enum_variant_arg
(
2
,
|
this
|
m
.encode
(
this
));
this
.emit_enum_variant_arg
(
3
,
|
this
|
b
.encode
(
this
));
this
.emit_enum_variant_arg
(
4
,
|
this
|
def_id
.encode
(
this
));
this
.emit_enum_variant_arg
(
5
,
|
this
|
this
.emit_substs
(
ecx
,
substs
));
});
}
}
});
}
}
trait
write_tag_and_id
{
...
...
@@ -1023,7 +1057,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
ebml_w
.tag
(
c
::
tag_table_adjustments
,
|
ebml_w
|
{
ebml_w
.id
(
id
);
ebml_w
.tag
(
c
::
tag_table_val
,
|
ebml_w
|
{
(
**
adj
)
.encode
(
ebml_w
)
ebml_w
.emit_auto_adjustment
(
ecx
,
**
adj
);
})
})
}
...
...
@@ -1064,6 +1098,8 @@ fn read_type_param_def(&mut self, xcx: @ExtendedDecodeContext)
->
ty
::
TypeParameterDef
;
fn
read_ty_param_bounds_and_ty
(
&
mut
self
,
xcx
:
@
ExtendedDecodeContext
)
->
ty
::
ty_param_bounds_and_ty
;
fn
read_substs
(
&
mut
self
,
xcx
:
@
ExtendedDecodeContext
)
->
ty
::
substs
;
fn
read_auto_adjustment
(
&
mut
self
,
xcx
:
@
ExtendedDecodeContext
)
->
ty
::
AutoAdjustment
;
fn
convert_def_id
(
&
mut
self
,
xcx
:
@
ExtendedDecodeContext
,
source
:
DefIdSource
,
...
...
@@ -1172,6 +1208,61 @@ fn read_ty_param_bounds_and_ty(&mut self, xcx: @ExtendedDecodeContext)
})
}
fn
read_substs
(
&
mut
self
,
xcx
:
@
ExtendedDecodeContext
)
->
ty
::
substs
{
self
.read_opaque
(|
this
,
doc
|
{
tydecode
::
parse_substs_data
(
doc
.data
,
xcx
.dcx.cdata.cnum
,
doc
.start
,
xcx
.dcx.tcx
,
|
s
,
a
|
this
.convert_def_id
(
xcx
,
s
,
a
))
})
}
fn
read_auto_adjustment
(
&
mut
self
,
xcx
:
@
ExtendedDecodeContext
)
->
ty
::
AutoAdjustment
{
self
.read_enum
(
"AutoAdjustment"
,
|
this
|
{
let
variants
=
[
"AutoAddEnv"
,
"AutoDerefRef"
,
"AutoObject"
];
this
.read_enum_variant
(
variants
,
|
this
,
i
|
{
match
i
{
0
=>
{
let
region
:
ty
::
Region
=
this
.read_enum_variant_arg
(
0
,
|
this
|
Decodable
::
decode
(
this
));
let
sigil
:
ast
::
Sigil
=
this
.read_enum_variant_arg
(
1
,
|
this
|
Decodable
::
decode
(
this
));
ty
::
AutoAddEnv
(
region
.tr
(
xcx
),
sigil
)
}
1
=>
{
let
auto_deref_ref
:
ty
::
AutoDerefRef
=
this
.read_enum_variant_arg
(
0
,
|
this
|
Decodable
::
decode
(
this
));
ty
::
AutoDerefRef
(
auto_deref_ref
.tr
(
xcx
))
}
2
=>
{
let
sigil
:
ast
::
Sigil
=
this
.read_enum_variant_arg
(
0
,
|
this
|
Decodable
::
decode
(
this
));
let
region
:
Option
<
ty
::
Region
>
=
this
.read_enum_variant_arg
(
1
,
|
this
|
Decodable
::
decode
(
this
));
let
m
:
ast
::
Mutability
=
this
.read_enum_variant_arg
(
2
,
|
this
|
Decodable
::
decode
(
this
));
let
b
:
ty
::
BuiltinBounds
=
this
.read_enum_variant_arg
(
3
,
|
this
|
Decodable
::
decode
(
this
));
let
def_id
:
ast
::
DefId
=
this
.read_enum_variant_arg
(
4
,
|
this
|
Decodable
::
decode
(
this
));
let
substs
=
this
.read_enum_variant_arg
(
5
,
|
this
|
this
.read_substs
(
xcx
));
let
region
=
match
region
{
Some
(
r
)
=>
Some
(
r
.tr
(
xcx
)),
None
=>
None
};
ty
::
AutoObject
(
sigil
,
region
,
m
,
b
,
def_id
.tr
(
xcx
),
substs
)
}
_
=>
fail
!
(
"bad enum variant for ty::AutoAdjustment"
)
}
})
})
}
fn
convert_def_id
(
&
mut
self
,
xcx
:
@
ExtendedDecodeContext
,
source
:
tydecode
::
DefIdSource
,
...
...
@@ -1289,8 +1380,7 @@ fn decode_side_tables(xcx: @ExtendedDecodeContext,
vtable_map
.get
()
.insert
(
id
,
vtable_res
);
}
c
::
tag_table_adjustments
=>
{
let
adj
:
@
ty
::
AutoAdjustment
=
@
Decodable
::
decode
(
val_dsr
);
adj
.tr
(
xcx
);
let
adj
:
@
ty
::
AutoAdjustment
=
@
val_dsr
.read_auto_adjustment
(
xcx
);
let
mut
adjustments
=
dcx
.tcx
.adjustments
.borrow_mut
();
...
...
src/librustc/middle/borrowck/gather_loans/mod.rs
浏览文件 @
1265a031
...
...
@@ -419,6 +419,10 @@ pub fn guarantee_adjustments(&mut self,
ty
::
AutoUnsafe
(
_
)
=>
{}
}
}
ty
::
AutoObject
(
..
)
=>
{
// XXX: Handle @Trait to &Trait casts here?
}
}
}
...
...
src/librustc/middle/borrowck/mod.rs
浏览文件 @
1265a031
...
...
@@ -490,7 +490,7 @@ pub fn cat_expr_autoderefd(&self,
adj
:
@
ty
::
AutoAdjustment
)
->
mc
::
cmt
{
match
*
adj
{
ty
::
AutoAddEnv
(
..
)
=>
{
ty
::
AutoAddEnv
(
..
)
|
ty
::
AutoObject
(
..
)
=>
{
// no autoderefs
mc
::
cat_expr_unadjusted
(
self
.tcx
,
self
.method_map
,
expr
)
}
...
...
src/librustc/middle/kind.rs
浏览文件 @
1265a031
...
...
@@ -311,14 +311,9 @@ pub fn check_expr(cx: &mut Context, e: @Expr) {
let
_
=
check_durable
(
cx
.tcx
,
interior_type
,
interior
.span
);
}
ExprCast
(
source
,
_
)
=>
{
check_cast_for_escaping_regions
(
cx
,
source
,
e
);
match
ty
::
get
(
ty
::
expr_ty
(
cx
.tcx
,
e
))
.sty
{
ty
::
ty_trait
(
_
,
_
,
_
,
_
,
bounds
)
=>
{
let
source_ty
=
ty
::
expr_ty
(
cx
.tcx
,
source
);
check_trait_cast_bounds
(
cx
,
e
.span
,
source_ty
,
bounds
)
}
_
=>
{
}
}
let
source_ty
=
ty
::
expr_ty
(
cx
.tcx
,
source
);
let
target_ty
=
ty
::
expr_ty
(
cx
.tcx
,
e
);
check_trait_cast
(
cx
,
source_ty
,
target_ty
,
source
.span
);
}
ExprRepeat
(
element
,
count_expr
,
_
)
=>
{
let
count
=
ty
::
eval_repeat_count
(
&
cx
.tcx
,
count_expr
);
...
...
@@ -330,9 +325,31 @@ pub fn check_expr(cx: &mut Context, e: @Expr) {
}
_
=>
{}
}
// Search for auto-adjustments to find trait coercions.
let
adjustments
=
cx
.tcx.adjustments
.borrow
();
match
adjustments
.get
()
.find
(
&
e
.id
)
{
Some
(
&@
ty
::
AutoObject
(
..
))
=>
{
let
source_ty
=
ty
::
expr_ty
(
cx
.tcx
,
e
);
let
target_ty
=
ty
::
expr_ty_adjusted
(
cx
.tcx
,
e
);
check_trait_cast
(
cx
,
source_ty
,
target_ty
,
e
.span
);
}
Some
(
&@
ty
::
AutoAddEnv
(
..
))
|
Some
(
&@
ty
::
AutoDerefRef
(
..
))
|
None
=>
{}
}
visit
::
walk_expr
(
cx
,
e
,
());
}
fn
check_trait_cast
(
cx
:
&
mut
Context
,
source_ty
:
ty
::
t
,
target_ty
:
ty
::
t
,
span
:
Span
)
{
check_cast_for_escaping_regions
(
cx
,
source_ty
,
target_ty
,
span
);
match
ty
::
get
(
target_ty
)
.sty
{
ty
::
ty_trait
(
_
,
_
,
_
,
_
,
bounds
)
=>
{
check_trait_cast_bounds
(
cx
,
span
,
source_ty
,
bounds
);
}
_
=>
{}
}
}
fn
check_ty
(
cx
:
&
mut
Context
,
aty
:
&
Ty
)
{
match
aty
.node
{
ty_path
(
_
,
_
,
id
)
=>
{
...
...
@@ -510,12 +527,12 @@ pub fn check_durable(tcx: ty::ctxt, ty: ty::t, sp: Span) -> bool {
/// FIXME(#5723)---This code should probably move into regionck.
pub
fn
check_cast_for_escaping_regions
(
cx
:
&
Context
,
source
:
&
Expr
,
target
:
&
Expr
)
source_ty
:
ty
::
t
,
target_ty
:
ty
::
t
,
source_span
:
Span
)
{
// Determine what type we are casting to; if it is not an trait, then no
// worries.
let
target_ty
=
ty
::
expr_ty
(
cx
.tcx
,
target
);
match
ty
::
get
(
target_ty
)
.sty
{
ty
::
ty_trait
(
..
)
=>
{}
_
=>
{
return
;
}
...
...
@@ -545,7 +562,6 @@ pub fn check_cast_for_escaping_regions(
// Assuming the trait instance can escape, then ensure that each parameter
// either appears in the trait type or is sendable.
let
target_params
=
ty
::
param_tys_in_type
(
target_ty
);
let
source_ty
=
ty
::
expr_ty
(
cx
.tcx
,
source
);
ty
::
walk_regions_and_ty
(
cx
.tcx
,
source_ty
,
...
...
@@ -555,7 +571,7 @@ pub fn check_cast_for_escaping_regions(
//
// if !target_regions.iter().any(|t_r| is_subregion_of(cx, *t_r, r)) {
// cx.tcx.sess.span_err(
// source
.
span,
// source
_
span,
// format!("source contains borrowed pointer with lifetime \
// not found in the target type `{}`",
// ty_to_str(cx.tcx, target_ty)));
...
...
@@ -570,7 +586,7 @@ pub fn check_cast_for_escaping_regions(
if
target_params
.iter
()
.any
(|
x
|
x
==
&
source_param
)
{
/* case (2) */
}
else
{
check_durable
(
cx
.tcx
,
ty
,
source
.
span
);
/* case (3) */
check_durable
(
cx
.tcx
,
ty
,
source
_
span
);
/* case (3) */
}
}
_
=>
{}
...
...
src/librustc/middle/mem_categorization.rs
浏览文件 @
1265a031
...
...
@@ -347,6 +347,13 @@ pub fn cat_expr(&self, expr: @ast::Expr) -> cmt {
self
.cat_expr_unadjusted
(
expr
)
}
Some
(
&@
ty
::
AutoObject
(
..
))
=>
{
// Implicity casts a concrete object to trait object
// Result is an rvalue
let
expr_ty
=
ty
::
expr_ty_adjusted
(
self
.tcx
,
expr
);
self
.cat_rvalue_node
(
expr
,
expr_ty
)
}
Some
(
&@
ty
::
AutoAddEnv
(
..
))
=>
{
// Convert a bare fn to a closure by adding NULL env.
// Result is an rvalue.
...
...
src/librustc/middle/trans/consts.rs
浏览文件 @
1265a031
...
...
@@ -199,6 +199,9 @@ pub fn const_expr(cx: @CrateContext, e: &ast::Expr) -> (ValueRef, bool) {
cx
.sess
.span_bug
(
e
.span
,
format!
(
"unexpected static function:
\
region {:?} sigil {:?}"
,
*
r
,
*
s
))
}
Some
(
@
ty
::
AutoObject
(
..
))
=>
{
cx
.sess
.span_unimpl
(
e
.span
,
"unimplemented const coercion to trait object"
);
}
Some
(
@
ty
::
AutoDerefRef
(
ref
adj
))
=>
{
let
mut
ty
=
ety
;
let
mut
maybe_ptr
=
None
;
...
...
src/librustc/middle/trans/expr.rs
浏览文件 @
1265a031
...
...
@@ -139,7 +139,7 @@
use
middle
::
trans
::
tvec
;
use
middle
::
trans
::
type_of
;
use
middle
::
ty
::
struct_fields
;
use
middle
::
ty
::{
AutoBorrowObj
,
AutoDerefRef
,
AutoAddEnv
,
AutoUnsafe
};
use
middle
::
ty
::{
AutoBorrowObj
,
AutoDerefRef
,
AutoAddEnv
,
Auto
Object
,
Auto
Unsafe
};
use
middle
::
ty
::{
AutoPtr
,
AutoBorrowVec
,
AutoBorrowVecRef
,
AutoBorrowFn
};
use
middle
::
ty
;
use
util
::
common
::
indenter
;
...
...
@@ -228,6 +228,23 @@ pub fn trans_to_datum(bcx: @Block, expr: &ast::Expr) -> DatumBlock {
}
};
}
AutoObject
(
ref
sigil
,
ref
region
,
_
,
_
,
_
,
_
)
=>
{
let
adjusted_ty
=
ty
::
expr_ty_adjusted
(
bcx
.tcx
(),
expr
);
let
scratch
=
scratch_datum
(
bcx
,
adjusted_ty
,
"__adjust"
,
false
);
let
trait_store
=
match
*
sigil
{
ast
::
BorrowedSigil
=>
ty
::
RegionTraitStore
(
region
.expect
(
"expected valid region"
)),
ast
::
OwnedSigil
=>
ty
::
UniqTraitStore
,
ast
::
ManagedSigil
=>
ty
::
BoxTraitStore
};
bcx
=
meth
::
trans_trait_cast
(
bcx
,
expr
,
expr
.id
,
SaveIn
(
scratch
.val
),
trait_store
,
false
/* no adjustments */
);
datum
=
scratch
.to_appropriate_datum
(
bcx
);
datum
.add_clean
(
bcx
);
}
}
debug!
(
"after adjustments, datum={}"
,
datum
.to_str
(
bcx
.ccx
()));
return
DatumBlock
{
bcx
:
bcx
,
datum
:
datum
};
...
...
@@ -432,6 +449,10 @@ pub fn trans_into(bcx: @Block, expr: &ast::Expr, dest: Dest) -> @Block {
};
}
trans_into_unadjusted
(
bcx
,
expr
,
dest
)
}
pub
fn
trans_into_unadjusted
(
bcx
:
@
Block
,
expr
:
&
ast
::
Expr
,
dest
:
Dest
)
->
@
Block
{
let
ty
=
expr_ty
(
bcx
,
expr
);
debug!
(
"trans_into_unadjusted(expr={}, dest={})"
,
...
...
@@ -778,8 +799,8 @@ fn trans_rvalue_dps_unadjusted(bcx: @Block, expr: &ast::Expr,
ast
::
ExprCast
(
val
,
_
)
=>
{
match
ty
::
get
(
node_id_type
(
bcx
,
expr
.id
))
.sty
{
ty
::
ty_trait
(
_
,
_
,
store
,
_
,
_
)
=>
{
return
meth
::
trans_trait_cast
(
bcx
,
val
,
expr
.id
,
dest
,
store
);
return
meth
::
trans_trait_cast
(
bcx
,
val
,
expr
.id
,
dest
,
store
,
true
/* adjustments */
);
}
_
=>
{
bcx
.tcx
()
.sess
.span_bug
(
expr
.span
,
...
...
src/librustc/middle/trans/meth.rs
浏览文件 @
1265a031
...
...
@@ -646,14 +646,22 @@ pub fn trans_trait_cast(bcx: @Block,
val
:
&
ast
::
Expr
,
id
:
ast
::
NodeId
,
dest
:
expr
::
Dest
,
_
store
:
ty
::
TraitStore
)
_
store
:
ty
::
TraitStore
,
do_adjustments
:
bool
)
->
@
Block
{
let
mut
bcx
=
bcx
;
let
_
icx
=
push_ctxt
(
"impl::trans_cast"
);
// Pick the right trans function
let
trans_into
=
if
do_adjustments
{
expr
::
trans_into
}
else
{
expr
::
trans_into_unadjusted
};
let
lldest
=
match
dest
{
Ignore
=>
{
return
expr
::
trans_into
(
bcx
,
val
,
Ignore
);
return
trans_into
(
bcx
,
val
,
Ignore
);
}
SaveIn
(
dest
)
=>
dest
};
...
...
@@ -668,7 +676,7 @@ pub fn trans_trait_cast(bcx: @Block,
llboxdest
=
PointerCast
(
bcx
,
llboxdest
,
type_of
(
bcx
.ccx
(),
v_ty
)
.ptr_to
());
bcx
=
expr
::
trans_into
(
bcx
,
val
,
SaveIn
(
llboxdest
));
bcx
=
trans_into
(
bcx
,
val
,
SaveIn
(
llboxdest
));
// Store the vtable into the pair or triple.
// This is structured a bit funny because of dynamic borrow failures.
...
...
src/librustc/middle/ty.rs
浏览文件 @
1265a031
...
...
@@ -224,10 +224,14 @@ pub enum Variance {
Bivariant
,
// T<A> <: T<B> -- e.g., unused type parameter
}
#[deriving(Decodable,
Encodable)]
pub
enum
AutoAdjustment
{
AutoAddEnv
(
ty
::
Region
,
ast
::
Sigil
),
AutoDerefRef
(
AutoDerefRef
)
AutoDerefRef
(
AutoDerefRef
),
AutoObject
(
ast
::
Sigil
,
Option
<
ty
::
Region
>
,
ast
::
Mutability
,
ty
::
BuiltinBounds
,
ast
::
DefId
,
/* Trait ID */
ty
::
substs
/* Trait substitutions */
)
}
#[deriving(Decodable,
Encodable)]
...
...
@@ -730,7 +734,7 @@ pub struct ParamBounds {
pub
type
BuiltinBounds
=
EnumSet
<
BuiltinBound
>
;
#[deriving(Clone,
E
q
,
IterBytes,
ToStr)]
#[deriving(Clone,
E
ncodable,
Eq,
Decodable
,
IterBytes,
ToStr)]
#[repr(uint)]
pub
enum
BuiltinBound
{
BoundStatic
,
...
...
@@ -2955,6 +2959,10 @@ pub fn adjust_ty(cx: ctxt,
}
}
}
Some
(
@
AutoObject
(
ref
sigil
,
ref
region
,
m
,
b
,
def_id
,
ref
substs
))
=>
{
trait_adjustment_to_ty
(
cx
,
sigil
,
region
,
def_id
,
substs
,
m
,
b
)
}
};
fn
borrow_vec
(
cx
:
ctxt
,
span
:
Span
,
...
...
@@ -3014,6 +3022,19 @@ fn borrow_obj(cx: ctxt, span: Span, r: Region,
}
}
pub
fn
trait_adjustment_to_ty
(
cx
:
ctxt
,
sigil
:
&
ast
::
Sigil
,
region
:
&
Option
<
Region
>
,
def_id
:
ast
::
DefId
,
substs
:
&
substs
,
m
:
ast
::
Mutability
,
bounds
:
BuiltinBounds
)
->
t
{
let
trait_store
=
match
*
sigil
{
BorrowedSigil
=>
RegionTraitStore
(
region
.expect
(
"expected valid region"
)),
OwnedSigil
=>
UniqTraitStore
,
ManagedSigil
=>
BoxTraitStore
};
mk_trait
(
cx
,
def_id
,
substs
.clone
(),
trait_store
,
m
,
bounds
)
}
impl
AutoRef
{
pub
fn
map_region
(
&
self
,
f
:
|
Region
|
->
Region
)
->
AutoRef
{
match
*
self
{
...
...
src/librustc/middle/typeck/check/regionck.rs
浏览文件 @
1265a031
...
...
@@ -327,6 +327,25 @@ fn visit_expr(rcx: &mut Rcx, expr: @ast::Expr) {
infer
::
AutoBorrow
(
expr
.span
));
}
}
@
ty
::
AutoObject
(
ast
::
BorrowedSigil
,
Some
(
trait_region
),
_
,
_
,
_
,
_
)
=>
{
// Determine if we are casting `expr` to an trait
// instance. If so, we have to be sure that the type of
// the source obeys the trait's region bound.
//
// Note: there is a subtle point here concerning type
// parameters. It is possible that the type of `source`
// contains type parameters, which in turn may contain
// regions that are not visible to us (only the caller
// knows about them). The kind checker is ultimately
// responsible for guaranteeing region safety in that
// particular case. There is an extensive comment on the
// function check_cast_for_escaping_regions() in kind.rs
// explaining how it goes about doing that.
let
source_ty
=
rcx
.fcx
.expr_ty
(
expr
);
constrain_regions_in_type
(
rcx
,
trait_region
,
infer
::
RelateObjectBound
(
expr
.span
),
source_ty
);
}
_
=>
{}
}
}
...
...
@@ -1075,6 +1094,27 @@ fn categorize(rcx: &mut Rcx, expr: @ast::Expr) -> ExprCategorization {
};
}
Some
(
&@
ty
::
AutoObject
(
ast
::
BorrowedSigil
,
Some
(
region
),
_
,
_
,
_
,
_
))
=>
{
expr_ct
.cat
=
ExprCategorization
{
guarantor
:
None
,
pointer
:
BorrowedPointer
(
region
)
};
}
Some
(
&@
ty
::
AutoObject
(
ast
::
OwnedSigil
,
_
,
_
,
_
,
_
,
_
))
=>
{
expr_ct
.cat
=
ExprCategorization
{
guarantor
:
None
,
pointer
:
OwnedPointer
};
}
Some
(
&@
ty
::
AutoObject
(
ast
::
ManagedSigil
,
_
,
_
,
_
,
_
,
_
))
=>
{
expr_ct
.cat
=
ExprCategorization
{
guarantor
:
None
,
pointer
:
OtherPointer
};
}
Some
(
&@
ty
::
AutoDerefRef
(
ref
adjustment
))
=>
{
debug!
(
"adjustment={:?}"
,
adjustment
);
...
...
@@ -1103,6 +1143,8 @@ fn categorize(rcx: &mut Rcx, expr: @ast::Expr) -> ExprCategorization {
}
}
Some
(
..
)
=>
fail
!
(
"invalid or unhandled adjustment"
),
None
=>
{}
}
...
...
src/librustc/middle/typeck/check/vtable.rs
浏览文件 @
1265a031
...
...
@@ -9,8 +9,8 @@
// except according to those terms.
use
middle
::
ty
::
param_ty
;
use
middle
::
ty
;
use
middle
::
ty
::{
AutoAddEnv
,
AutoDerefRef
,
AutoObject
,
param_ty
};
use
middle
::
ty_fold
::
TypeFolder
;
use
middle
::
typeck
::
check
::{
FnCtxt
,
impl_self_ty
};
use
middle
::
typeck
::
check
::{
structurally_resolved_type
};
...
...
@@ -565,6 +565,106 @@ pub fn early_resolve_expr(ex: @ast::Expr,
let
_
indent
=
indenter
();
let
cx
=
fcx
.ccx
;
let
resolve_object_cast
=
|
src
:
@
ast
::
Expr
,
target_ty
:
ty
::
t
|
{
match
ty
::
get
(
target_ty
)
.sty
{
// Bounds of type's contents are not checked here, but in kind.rs.
ty
::
ty_trait
(
target_def_id
,
ref
target_substs
,
store
,
target_mutbl
,
_
bounds
)
=>
{
fn
mutability_allowed
(
a_mutbl
:
ast
::
Mutability
,
b_mutbl
:
ast
::
Mutability
)
->
bool
{
a_mutbl
==
b_mutbl
||
(
a_mutbl
==
ast
::
MutMutable
&&
b_mutbl
==
ast
::
MutImmutable
)
}
// Look up vtables for the type we're casting to,
// passing in the source and target type. The source
// must be a pointer type suitable to the object sigil,
// e.g.: `@x as @Trait`, `&x as &Trait` or `~x as ~Trait`
let
ty
=
structurally_resolved_type
(
fcx
,
ex
.span
,
fcx
.expr_ty
(
src
));
match
(
&
ty
::
get
(
ty
)
.sty
,
store
)
{
(
&
ty
::
ty_box
(
mt
),
ty
::
BoxTraitStore
)
|
(
&
ty
::
ty_uniq
(
mt
),
ty
::
UniqTraitStore
)
|
(
&
ty
::
ty_rptr
(
_
,
mt
),
ty
::
RegionTraitStore
(
..
))
if
!
mutability_allowed
(
mt
.mutbl
,
target_mutbl
)
=>
{
fcx
.tcx
()
.sess
.span_err
(
ex
.span
,
format!
(
"types differ in mutability"
));
}
(
&
ty
::
ty_box
(
mt
),
ty
::
BoxTraitStore
)
|
(
&
ty
::
ty_uniq
(
mt
),
ty
::
UniqTraitStore
)
|
(
&
ty
::
ty_rptr
(
_
,
mt
),
ty
::
RegionTraitStore
(
..
))
=>
{
let
location_info
=
&
location_info_for_expr
(
ex
);
let
vcx
=
fcx
.vtable_context
();
let
target_trait_ref
=
@
ty
::
TraitRef
{
def_id
:
target_def_id
,
substs
:
ty
::
substs
{
tps
:
target_substs
.tps
.clone
(),
regions
:
target_substs
.regions
.clone
(),
self_ty
:
Some
(
mt
.ty
)
}
};
let
param_bounds
=
ty
::
ParamBounds
{
builtin_bounds
:
ty
::
EmptyBuiltinBounds
(),
trait_bounds
:
~
[
target_trait_ref
]
};
let
vtables
=
lookup_vtables_for_param
(
&
vcx
,
location_info
,
None
,
&
param_bounds
,
mt
.ty
,
is_early
);
if
!
is_early
{
insert_vtables
(
fcx
,
ex
.id
,
@~
[
vtables
]);
}
// Now, if this is &trait, we need to link the
// regions.
match
(
&
ty
::
get
(
ty
)
.sty
,
store
)
{
(
&
ty
::
ty_rptr
(
ra
,
_
),
ty
::
RegionTraitStore
(
rb
))
=>
{
infer
::
mk_subr
(
fcx
.infcx
(),
false
,
infer
::
RelateObjectBound
(
ex
.span
),
rb
,
ra
);
}
_
=>
{}
}
}
(
_
,
ty
::
UniqTraitStore
)
=>
{
fcx
.ccx.tcx.sess
.span_err
(
ex
.span
,
format!
(
"can only cast an ~-pointer
\
to a ~-object, not a {}"
,
ty
::
ty_sort_str
(
fcx
.tcx
(),
ty
)));
}
(
_
,
ty
::
BoxTraitStore
)
=>
{
fcx
.ccx.tcx.sess
.span_err
(
ex
.span
,
format!
(
"can only cast an @-pointer
\
to an @-object, not a {}"
,
ty
::
ty_sort_str
(
fcx
.tcx
(),
ty
)));
}
(
_
,
ty
::
RegionTraitStore
(
_
))
=>
{
fcx
.ccx.tcx.sess
.span_err
(
ex
.span
,
format!
(
"can only cast an &-pointer
\
to an &-object, not a {}"
,
ty
::
ty_sort_str
(
fcx
.tcx
(),
ty
)));
}
}
}
_
=>
{
/* not a cast to a trait; ignore */
}
}
};
match
ex
.node
{
ast
::
ExprPath
(
..
)
=>
{
fcx
.opt_node_ty_substs
(
ex
.id
,
|
substs
|
{
...
...
@@ -621,107 +721,24 @@ pub fn early_resolve_expr(ex: @ast::Expr,
ast
::
ExprCast
(
src
,
_
)
=>
{
debug!
(
"vtable resolution on expr {}"
,
ex
.repr
(
fcx
.tcx
()));
let
target_ty
=
fcx
.expr_ty
(
ex
);
match
ty
::
get
(
target_ty
)
.sty
{
// Bounds of type's contents are not checked here, but in kind.rs.
ty
::
ty_trait
(
target_def_id
,
ref
target_substs
,
store
,
target_mutbl
,
_
bounds
)
=>
{
fn
mutability_allowed
(
a_mutbl
:
ast
::
Mutability
,
b_mutbl
:
ast
::
Mutability
)
->
bool
{
a_mutbl
==
b_mutbl
||
(
a_mutbl
==
ast
::
MutMutable
&&
b_mutbl
==
ast
::
MutImmutable
)
}
// Look up vtables for the type we're casting to,
// passing in the source and target type. The source
// must be a pointer type suitable to the object sigil,
// e.g.: `@x as @Trait`, `&x as &Trait` or `~x as ~Trait`
let
ty
=
structurally_resolved_type
(
fcx
,
ex
.span
,
fcx
.expr_ty
(
src
));
match
(
&
ty
::
get
(
ty
)
.sty
,
store
)
{
(
&
ty
::
ty_box
(
mt
),
ty
::
BoxTraitStore
)
|
(
&
ty
::
ty_uniq
(
mt
),
ty
::
UniqTraitStore
)
|
(
&
ty
::
ty_rptr
(
_
,
mt
),
ty
::
RegionTraitStore
(
..
))
if
!
mutability_allowed
(
mt
.mutbl
,
target_mutbl
)
=>
{
fcx
.tcx
()
.sess
.span_err
(
ex
.span
,
format!
(
"types differ in mutability"
));
}
(
&
ty
::
ty_box
(
mt
),
ty
::
BoxTraitStore
)
|
(
&
ty
::
ty_uniq
(
mt
),
ty
::
UniqTraitStore
)
|
(
&
ty
::
ty_rptr
(
_
,
mt
),
ty
::
RegionTraitStore
(
..
))
=>
{
let
location_info
=
&
location_info_for_expr
(
ex
);
let
vcx
=
fcx
.vtable_context
();
let
target_trait_ref
=
@
ty
::
TraitRef
{
def_id
:
target_def_id
,
substs
:
ty
::
substs
{
tps
:
target_substs
.tps
.clone
(),
regions
:
target_substs
.regions
.clone
(),
self_ty
:
Some
(
mt
.ty
)
}
};
let
param_bounds
=
ty
::
ParamBounds
{
builtin_bounds
:
ty
::
EmptyBuiltinBounds
(),
trait_bounds
:
~
[
target_trait_ref
]
};
let
vtables
=
lookup_vtables_for_param
(
&
vcx
,
location_info
,
None
,
&
param_bounds
,
mt
.ty
,
is_early
);
if
!
is_early
{
insert_vtables
(
fcx
,
ex
.id
,
@~
[
vtables
]);
}
// Now, if this is &trait, we need to link the
// regions.
match
(
&
ty
::
get
(
ty
)
.sty
,
store
)
{
(
&
ty
::
ty_rptr
(
ra
,
_
),
ty
::
RegionTraitStore
(
rb
))
=>
{
infer
::
mk_subr
(
fcx
.infcx
(),
false
,
infer
::
RelateObjectBound
(
ex
.span
),
rb
,
ra
);
}
_
=>
{}
}
}
(
_
,
ty
::
UniqTraitStore
)
=>
{
fcx
.ccx.tcx.sess
.span_err
(
ex
.span
,
format!
(
"can only cast an ~-pointer
\
to a ~-object, not a {}"
,
ty
::
ty_sort_str
(
fcx
.tcx
(),
ty
)));
}
(
_
,
ty
::
BoxTraitStore
)
=>
{
fcx
.ccx.tcx.sess
.span_err
(
ex
.span
,
format!
(
"can only cast an @-pointer
\
to an @-object, not a {}"
,
ty
::
ty_sort_str
(
fcx
.tcx
(),
ty
)));
}
(
_
,
ty
::
RegionTraitStore
(
_
))
=>
{
fcx
.ccx.tcx.sess
.span_err
(
ex
.span
,
format!
(
"can only cast an &-pointer
\
to an &-object, not a {}"
,
ty
::
ty_sort_str
(
fcx
.tcx
(),
ty
)));
}
}
}
_
=>
{
/* not a cast to a trait; ignore */
}
}
resolve_object_cast
(
src
,
target_ty
);
}
_
=>
()
}
// Search for auto-adjustments to find trait coercions
let
adjustments
=
fcx
.inh.adjustments
.borrow
();
match
adjustments
.get
()
.find
(
&
ex
.id
)
{
Some
(
&@
AutoObject
(
ref
sigil
,
ref
region
,
m
,
b
,
def_id
,
ref
substs
))
=>
{
debug!
(
"doing trait adjustment for expr {} {} (early? {})"
,
ex
.id
,
ex
.repr
(
fcx
.tcx
()),
is_early
);
let
object_ty
=
ty
::
trait_adjustment_to_ty
(
cx
.tcx
,
sigil
,
region
,
def_id
,
substs
,
m
,
b
);
resolve_object_cast
(
ex
,
object_ty
);
}
Some
(
&@
AutoAddEnv
(
..
))
|
Some
(
&@
AutoDerefRef
(
..
))
|
None
=>
{}
}
}
fn
resolve_expr
(
fcx
:
@
FnCtxt
,
...
...
src/librustc/middle/typeck/check/writeback.rs
浏览文件 @
1265a031
...
...
@@ -182,6 +182,12 @@ fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId)
let
mut
adjustments
=
fcx
.tcx
()
.adjustments
.borrow_mut
();
adjustments
.get
()
.insert
(
id
,
resolved_adj
);
}
Some
(
adjustment
@
@
ty
::
AutoObject
(
..
))
=>
{
debug!
(
"Adjustments for node {}: {:?}"
,
id
,
adjustment
);
let
mut
adjustments
=
fcx
.tcx
()
.adjustments
.borrow_mut
();
adjustments
.get
()
.insert
(
id
,
adjustment
);
}
}
// Resolve the type of the node with id `id`
...
...
src/librustc/middle/typeck/infer/coercion.rs
浏览文件 @
1265a031
...
...
@@ -121,16 +121,61 @@ pub fn tys(&self, a: ty::t, b: ty::t) -> CoerceResult {
});
}
ty
::
ty_
trait
(
_
,
_
,
ty
::
RegionTraitStore
(
..
),
m
,
_
)
=>
{
ty
::
ty_
ptr
(
mt_b
)
=>
{
return
self
.unpack_actual_value
(
a
,
|
sty_a
|
{
self
.coerce_
borrowed_object
(
a
,
sty_a
,
b
,
m
)
self
.coerce_
unsafe_ptr
(
a
,
sty_a
,
b
,
mt_b
)
});
}
ty
::
ty_ptr
(
mt_b
)
=>
{
return
self
.unpack_actual_value
(
a
,
|
sty_a
|
{
self
.coerce_unsafe_ptr
(
a
,
sty_a
,
b
,
mt_b
)
ty
::
ty_trait
(
def_id
,
ref
substs
,
ty
::
BoxTraitStore
,
m
,
bounds
)
=>
{
let
result
=
self
.unpack_actual_value
(
a
,
|
sty_a
|
{
match
*
sty_a
{
ty
::
ty_box
(
..
)
=>
{
self
.coerce_object
(
a
,
sty_a
,
b
,
def_id
,
substs
,
ty
::
BoxTraitStore
,
m
,
bounds
)
}
_
=>
Err
(
ty
::
terr_mismatch
)
}
});
match
result
{
Ok
(
t
)
=>
return
Ok
(
t
),
Err
(
..
)
=>
{}
}
}
ty
::
ty_trait
(
def_id
,
ref
substs
,
ty
::
UniqTraitStore
,
m
,
bounds
)
=>
{
let
result
=
self
.unpack_actual_value
(
a
,
|
sty_a
|
{
match
*
sty_a
{
ty
::
ty_uniq
(
..
)
=>
{
self
.coerce_object
(
a
,
sty_a
,
b
,
def_id
,
substs
,
ty
::
UniqTraitStore
,
m
,
bounds
)
}
_
=>
Err
(
ty
::
terr_mismatch
)
}
});
match
result
{
Ok
(
t
)
=>
return
Ok
(
t
),
Err
(
..
)
=>
{}
}
}
ty
::
ty_trait
(
def_id
,
ref
substs
,
ty
::
RegionTraitStore
(
region
),
m
,
bounds
)
=>
{
let
result
=
self
.unpack_actual_value
(
a
,
|
sty_a
|
{
match
*
sty_a
{
ty
::
ty_rptr
(
..
)
=>
{
self
.coerce_object
(
a
,
sty_a
,
b
,
def_id
,
substs
,
ty
::
RegionTraitStore
(
region
),
m
,
bounds
)
}
_
=>
self
.coerce_borrowed_object
(
a
,
sty_a
,
b
,
m
)
}
});
match
result
{
Ok
(
t
)
=>
return
Ok
(
t
),
Err
(
..
)
=>
{}
}
}
_
=>
{}
...
...
@@ -410,4 +455,30 @@ pub fn coerce_unsafe_ptr(&self,
autoref
:
Some
(
ty
::
AutoUnsafe
(
mt_b
.mutbl
))
})))
}
pub
fn
coerce_object
(
&
self
,
a
:
ty
::
t
,
sty_a
:
&
ty
::
sty
,
b
:
ty
::
t
,
trait_def_id
:
ast
::
DefId
,
trait_substs
:
&
ty
::
substs
,
trait_store
:
ty
::
TraitStore
,
m
:
ast
::
Mutability
,
bounds
:
ty
::
BuiltinBounds
)
->
CoerceResult
{
debug!
(
"coerce_object(a={}, sty_a={:?}, b={})"
,
a
.inf_str
(
self
.infcx
),
sty_a
,
b
.inf_str
(
self
.infcx
));
let
(
sigil
,
region
)
=
match
trait_store
{
ty
::
BoxTraitStore
=>
(
ast
::
ManagedSigil
,
None
),
ty
::
UniqTraitStore
=>
(
ast
::
OwnedSigil
,
None
),
ty
::
RegionTraitStore
(
region
)
=>
(
ast
::
BorrowedSigil
,
Some
(
region
))
};
let
adjustment
=
@
ty
::
AutoObject
(
sigil
,
region
,
m
,
bounds
,
trait_def_id
,
trait_substs
.clone
());
Ok
(
Some
(
adjustment
))
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录