Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
8405770b
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,发现更多精彩内容 >>
提交
8405770b
编写于
3月 02, 2017
作者:
O
Oliver Schneider
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Rustup to rustc 1.17.0-nightly (
be760566
2017-02-28)
上级
8878a403
变更
7
显示空白变更内容
内联
并排
Showing
7 changed file
with
71 addition
and
104 deletion
+71
-104
src/error.rs
src/error.rs
+4
-5
src/eval_context.rs
src/eval_context.rs
+14
-11
src/memory.rs
src/memory.rs
+14
-46
src/terminator/drop.rs
src/terminator/drop.rs
+2
-2
src/terminator/mod.rs
src/terminator/mod.rs
+26
-29
src/traits.rs
src/traits.rs
+10
-10
tests/compile-fail/cast_fn_ptr.rs
tests/compile-fail/cast_fn_ptr.rs
+1
-1
未找到文件。
src/error.rs
浏览文件 @
8405770b
use
std
::
error
::
Error
;
use
std
::
fmt
;
use
rustc
::
mir
;
use
rustc
::
ty
::{
BareFnTy
,
Ty
,
FnSig
,
layout
};
use
syntax
::
abi
::
Abi
;
use
rustc
::
ty
::{
PolyFnSig
,
Ty
,
layout
};
use
memory
::{
Pointer
,
Function
};
use
rustc_const_math
::
ConstMathErr
;
use
syntax
::
codemap
::
Span
;
#[derive(Clone,
Debug)]
pub
enum
EvalError
<
'tcx
>
{
FunctionPointerTyMismatch
(
Abi
,
&
'tcx
FnSig
<
'tcx
>
,
&
'tcx
BareFnTy
<
'tcx
>
),
FunctionPointerTyMismatch
(
PolyFnSig
<
'tcx
>
,
PolyFnSig
<
'tcx
>
),
NoMirFor
(
String
),
UnterminatedCString
(
Pointer
),
DanglingPointerDeref
,
...
...
@@ -151,8 +150,8 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
ptr
.offset
,
ptr
.offset
+
size
,
ptr
.alloc_id
,
allocation_size
)
},
EvalError
::
NoMirFor
(
ref
func
)
=>
write!
(
f
,
"no mir for `{}`"
,
func
),
EvalError
::
FunctionPointerTyMismatch
(
abi
,
sig
,
got
)
=>
write!
(
f
,
"tried to call a function with
abi {:?} and sig {:?} through a function pointer of type {:?}"
,
abi
,
sig
,
got
),
EvalError
::
FunctionPointerTyMismatch
(
sig
,
got
)
=>
write!
(
f
,
"tried to call a function with
sig {} through a function pointer of type {}"
,
sig
.skip_binder
(),
got
.skip_binder
()
),
EvalError
::
ArrayIndexOutOfBounds
(
span
,
len
,
index
)
=>
write!
(
f
,
"index out of bounds: the len is {} but the index is {} at {:?}"
,
len
,
index
,
span
),
EvalError
::
Math
(
span
,
ref
err
)
=>
...
...
src/eval_context.rs
浏览文件 @
8405770b
...
...
@@ -181,8 +181,6 @@ pub(super) fn const_to_value(&mut self, const_val: &ConstVal) -> EvalResult<'tcx
Float
(
ConstFloat
::
F32
(
f
))
=>
PrimVal
::
from_f32
(
f
),
Float
(
ConstFloat
::
F64
(
f
))
=>
PrimVal
::
from_f64
(
f
),
Float
(
ConstFloat
::
FInfer
{
..
})
=>
bug!
(
"uninferred constants only exist before typeck"
),
Bool
(
b
)
=>
PrimVal
::
from_bool
(
b
),
Char
(
c
)
=>
PrimVal
::
from_char
(
c
),
...
...
@@ -196,7 +194,7 @@ pub(super) fn const_to_value(&mut self, const_val: &ConstVal) -> EvalResult<'tcx
Struct
(
_
)
=>
unimplemented!
(),
Tuple
(
_
)
=>
unimplemented!
(),
Function
(
_
)
=>
unimplemented!
(),
Function
(
_
,
_
)
=>
unimplemented!
(),
Array
(
_
)
=>
unimplemented!
(),
Repeat
(
_
,
_
)
=>
unimplemented!
(),
};
...
...
@@ -457,7 +455,10 @@ pub(super) fn eval_rvalue_into_lvalue(
General
{
discr
,
ref
variants
,
..
}
=>
{
if
let
mir
::
AggregateKind
::
Adt
(
adt_def
,
variant
,
_
,
_
)
=
*
kind
{
let
discr_val
=
adt_def
.variants
[
variant
]
.disr_val
;
let
discr_val
=
adt_def
.discriminants
(
self
.tcx
)
.nth
(
variant
)
.expect
(
"broken mir: Adt variant id invalid"
)
.to_u128_unchecked
();
let
discr_size
=
discr
.size
()
.bytes
();
if
variants
[
variant
]
.packed
{
let
ptr
=
self
.force_allocation
(
dest
)
?
.to_ptr_and_extra
()
.0
;
...
...
@@ -530,7 +531,10 @@ pub(super) fn eval_rvalue_into_lvalue(
CEnum
{
..
}
=>
{
assert_eq!
(
operands
.len
(),
0
);
if
let
mir
::
AggregateKind
::
Adt
(
adt_def
,
variant
,
_
,
_
)
=
*
kind
{
let
n
=
adt_def
.variants
[
variant
]
.disr_val
;
let
n
=
adt_def
.discriminants
(
self
.tcx
)
.nth
(
variant
)
.expect
(
"broken mir: Adt variant index invalid"
)
.to_u128_unchecked
();
self
.write_primval
(
dest
,
PrimVal
::
Bytes
(
n
),
dest_ty
)
?
;
}
else
{
bug!
(
"tried to assign {:?} to Layout::CEnum"
,
kind
);
...
...
@@ -640,9 +644,8 @@ pub(super) fn eval_rvalue_into_lvalue(
}
ReifyFnPointer
=>
match
self
.operand_ty
(
operand
)
.sty
{
ty
::
TyFnDef
(
def_id
,
substs
,
fn_ty
)
=>
{
let
fn_ty
=
self
.tcx
.erase_regions
(
&
fn_ty
);
let
fn_ptr
=
self
.memory
.create_fn_ptr
(
self
.tcx
,
def_id
,
substs
,
fn_ty
);
ty
::
TyFnDef
(
def_id
,
substs
,
sig
)
=>
{
let
fn_ptr
=
self
.memory
.create_fn_ptr
(
def_id
,
substs
,
sig
);
self
.write_value
(
Value
::
ByVal
(
PrimVal
::
Ptr
(
fn_ptr
)),
dest
,
dest_ty
)
?
;
},
ref
other
=>
bug!
(
"reify fn pointer on {:?}"
,
other
),
...
...
@@ -658,8 +661,8 @@ pub(super) fn eval_rvalue_into_lvalue(
ClosureFnPointer
=>
match
self
.operand_ty
(
operand
)
.sty
{
ty
::
TyClosure
(
def_id
,
substs
)
=>
{
let
fn_ty
=
self
.tcx
.closure_type
(
def_id
,
substs
);
let
fn_ptr
=
self
.memory
.create_fn_ptr_from_noncapture_closure
(
self
.tcx
,
def_id
,
substs
,
fn_ty
);
let
fn_ty
=
self
.tcx
.closure_type
(
def_id
);
let
fn_ptr
=
self
.memory
.create_fn_ptr_from_noncapture_closure
(
def_id
,
substs
,
fn_ty
);
self
.write_value
(
Value
::
ByVal
(
PrimVal
::
Ptr
(
fn_ptr
)),
dest
,
dest_ty
)
?
;
},
ref
other
=>
bug!
(
"reify fn pointer on {:?}"
,
other
),
...
...
@@ -673,7 +676,7 @@ pub(super) fn eval_rvalue_into_lvalue(
let
ptr
=
self
.force_allocation
(
lval
)
?
.to_ptr
();
let
discr_val
=
self
.read_discriminant_value
(
ptr
,
ty
)
?
;
if
let
ty
::
TyAdt
(
adt_def
,
_
)
=
ty
.sty
{
if
adt_def
.
variants
.iter
()
.all
(|
v
|
discr_val
!=
v
.disr_val
)
{
if
adt_def
.
discriminants
(
self
.tcx
)
.all
(|
v
|
discr_val
!=
v
.to_u128_unchecked
()
)
{
return
Err
(
EvalError
::
InvalidDiscriminant
);
}
}
else
{
...
...
src/memory.rs
浏览文件 @
8405770b
...
...
@@ -3,12 +3,10 @@
use
std
::{
fmt
,
iter
,
ptr
,
mem
,
io
};
use
rustc
::
hir
::
def_id
::
DefId
;
use
rustc
::
ty
::{
self
,
BareFnTy
,
ClosureTy
,
ClosureSubsts
,
TyCtxt
};
use
rustc
::
ty
::{
self
,
PolyFnSig
,
ClosureSubsts
};
use
rustc
::
ty
::
subst
::
Substs
;
use
rustc
::
ty
::
layout
::{
self
,
TargetDataLayout
};
use
syntax
::
abi
::
Abi
;
use
error
::{
EvalError
,
EvalResult
};
use
value
::
PrimVal
;
...
...
@@ -109,8 +107,7 @@ pub fn never_ptr() -> Self {
pub
struct
FunctionDefinition
<
'tcx
>
{
pub
def_id
:
DefId
,
pub
substs
:
&
'tcx
Substs
<
'tcx
>
,
pub
abi
:
Abi
,
pub
sig
:
&
'tcx
ty
::
FnSig
<
'tcx
>
,
pub
sig
:
PolyFnSig
<
'tcx
>
,
}
/// Either a concrete function, or a glue function
...
...
@@ -127,7 +124,7 @@ pub enum Function<'tcx> {
DropGlue
(
ty
::
Ty
<
'tcx
>
),
/// Glue required to treat the ptr part of a fat pointer
/// as a function pointer
FnPtrAsTraitObject
(
&
'tcx
ty
::
FnSig
<
'tcx
>
),
FnPtrAsTraitObject
(
Poly
FnSig
<
'tcx
>
),
/// Glue for Closures
Closure
(
FunctionDefinition
<
'tcx
>
),
/// Glue for noncapturing closures casted to function pointers
...
...
@@ -217,67 +214,43 @@ pub fn allocations(&self) -> ::std::collections::hash_map::Iter<AllocId, Allocat
self
.alloc_map
.iter
()
}
pub
fn
create_closure_ptr
(
&
mut
self
,
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
def_id
:
DefId
,
substs
:
ClosureSubsts
<
'tcx
>
,
fn_ty
:
ClosureTy
<
'tcx
>
)
->
Pointer
{
// FIXME: this is a hack
let
fn_ty
=
tcx
.mk_bare_fn
(
ty
::
BareFnTy
{
unsafety
:
fn_ty
.unsafety
,
abi
:
fn_ty
.abi
,
sig
:
fn_ty
.sig
,
});
pub
fn
create_closure_ptr
(
&
mut
self
,
def_id
:
DefId
,
substs
:
ClosureSubsts
<
'tcx
>
,
sig
:
PolyFnSig
<
'tcx
>
)
->
Pointer
{
self
.create_fn_alloc
(
Function
::
Closure
(
FunctionDefinition
{
def_id
,
substs
:
substs
.substs
,
abi
:
fn_ty
.abi
,
// FIXME: why doesn't this compile?
//sig: tcx.erase_late_bound_regions(&fn_ty.sig),
sig
:
fn_ty
.sig
.skip_binder
(),
sig
,
}))
}
pub
fn
create_fn_ptr_from_noncapture_closure
(
&
mut
self
,
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
def_id
:
DefId
,
substs
:
ClosureSubsts
<
'tcx
>
,
fn_ty
:
ClosureTy
<
'tcx
>
)
->
Pointer
{
// FIXME: this is a hack
let
fn_ty
=
tcx
.mk_bare_fn
(
ty
::
BareFnTy
{
unsafety
:
fn_ty
.unsafety
,
abi
:
fn_ty
.abi
,
sig
:
fn_ty
.sig
,
});
pub
fn
create_fn_ptr_from_noncapture_closure
(
&
mut
self
,
def_id
:
DefId
,
substs
:
ClosureSubsts
<
'tcx
>
,
sig
:
PolyFnSig
<
'tcx
>
)
->
Pointer
{
self
.create_fn_alloc
(
Function
::
NonCaptureClosureAsFnPtr
(
FunctionDefinition
{
def_id
,
substs
:
substs
.substs
,
abi
:
Abi
::
Rust
,
// adjust abi
// FIXME: why doesn't this compile?
//sig: tcx.erase_late_bound_regions(&fn_ty.sig),
sig
:
fn_ty
.sig
.skip_binder
(),
sig
,
}))
}
pub
fn
create_fn_as_trait_glue
(
&
mut
self
,
_
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
def_id
:
DefId
,
substs
:
&
'tcx
Substs
<
'tcx
>
,
fn_ty
:
&
'tcx
BareFnTy
<
'tcx
>
)
->
Pointer
{
pub
fn
create_fn_as_trait_glue
(
&
mut
self
,
def_id
:
DefId
,
substs
:
&
'tcx
Substs
,
sig
:
PolyFnSig
<
'tcx
>
)
->
Pointer
{
self
.create_fn_alloc
(
Function
::
FnDefAsTraitObject
(
FunctionDefinition
{
def_id
,
substs
,
abi
:
fn_ty
.abi
,
// FIXME: why doesn't this compile?
//sig: tcx.erase_late_bound_regions(&fn_ty.sig),
sig
:
fn_ty
.sig
.skip_binder
(),
sig
,
}))
}
pub
fn
create_fn_ptr_as_trait_glue
(
&
mut
self
,
fn_ty
:
&
'tcx
BareFnTy
<
'tcx
>
)
->
Pointer
{
self
.create_fn_alloc
(
Function
::
FnPtrAsTraitObject
(
fn_ty
.sig
.skip_binder
()
))
pub
fn
create_fn_ptr_as_trait_glue
(
&
mut
self
,
sig
:
PolyFnSig
<
'tcx
>
)
->
Pointer
{
self
.create_fn_alloc
(
Function
::
FnPtrAsTraitObject
(
sig
))
}
pub
fn
create_drop_glue
(
&
mut
self
,
ty
:
ty
::
Ty
<
'tcx
>
)
->
Pointer
{
self
.create_fn_alloc
(
Function
::
DropGlue
(
ty
))
}
pub
fn
create_fn_ptr
(
&
mut
self
,
_
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
def_id
:
DefId
,
substs
:
&
'tcx
Substs
<
'tcx
>
,
fn_ty
:
&
'tcx
BareFnTy
<
'tcx
>
)
->
Pointer
{
pub
fn
create_fn_ptr
(
&
mut
self
,
def_id
:
DefId
,
substs
:
&
'tcx
Substs
,
sig
:
PolyFnSig
<
'tcx
>
)
->
Pointer
{
self
.create_fn_alloc
(
Function
::
Concrete
(
FunctionDefinition
{
def_id
,
substs
,
abi
:
fn_ty
.abi
,
// FIXME: why doesn't this compile?
//sig: tcx.erase_late_bound_regions(&fn_ty.sig),
sig
:
fn_ty
.sig
.skip_binder
(),
sig
,
}))
}
...
...
@@ -623,12 +596,7 @@ pub fn leak_report(&self) -> usize {
fn
dump_fn_def
<
'tcx
>
(
fn_def
:
FunctionDefinition
<
'tcx
>
)
->
String
{
let
name
=
ty
::
tls
::
with
(|
tcx
|
tcx
.item_path_str
(
fn_def
.def_id
));
let
abi
=
if
fn_def
.abi
==
Abi
::
Rust
{
format!
(
""
)
}
else
{
format!
(
"extern {} "
,
fn_def
.abi
)
};
format!
(
"function pointer: {}: {}{}"
,
name
,
abi
,
fn_def
.sig
)
format!
(
"function pointer: {}: {}"
,
name
,
fn_def
.sig
.skip_binder
())
}
/// Byte accessors
...
...
src/terminator/drop.rs
浏览文件 @
8405770b
...
...
@@ -97,7 +97,7 @@ pub fn drop(
let
(
adt_ptr
,
extra
)
=
lval
.to_ptr_and_extra
();
// run drop impl before the fields' drop impls
if
let
Some
(
drop_def_id
)
=
adt_def
.destructor
()
{
if
let
Some
(
drop_def_id
)
=
adt_def
.destructor
(
self
.tcx
)
{
let
trait_ref
=
ty
::
Binder
(
ty
::
TraitRef
{
def_id
:
self
.tcx.lang_items
.drop_trait
()
.unwrap
(),
substs
:
self
.tcx
.mk_substs_trait
(
ty
,
&
[]),
...
...
@@ -121,7 +121,7 @@ pub fn drop(
Layout
::
General
{
..
}
=>
{
let
discr_val
=
self
.read_discriminant_value
(
adt_ptr
,
ty
)
?
as
u128
;
let
ptr
=
self
.force_allocation
(
lval
)
?
.to_ptr
();
match
adt_def
.
variants
.iter
()
.position
(|
v
|
discr_val
==
v
.disr_val
)
{
match
adt_def
.
discriminants
(
self
.tcx
)
.position
(|
v
|
discr_val
==
v
.to_u128_unchecked
()
)
{
Some
(
i
)
=>
{
lval
=
Lvalue
::
Ptr
{
ptr
,
...
...
src/terminator/mod.rs
浏览文件 @
8405770b
...
...
@@ -3,8 +3,10 @@
use
rustc
::
ty
::
layout
::
Layout
;
use
rustc
::
ty
::
subst
::
Substs
;
use
rustc
::
ty
::{
self
,
Ty
};
use
rustc_const_math
::
ConstInt
;
use
syntax
::
codemap
::
Span
;
use
syntax
::
attr
;
use
syntax
::
abi
::
Abi
;
use
error
::{
EvalError
,
EvalResult
};
use
eval_context
::{
EvalContext
,
IntegerExt
,
StackPopCleanup
,
is_inhabited
};
...
...
@@ -62,11 +64,9 @@ pub(super) fn eval_terminator(
let
func_ty
=
self
.operand_ty
(
func
);
let
fn_def
=
match
func_ty
.sty
{
ty
::
TyFnPtr
(
bare_
fn_ty
)
=>
{
ty
::
TyFnPtr
(
bare_
sig
)
=>
{
let
fn_ptr
=
self
.eval_operand_to_primval
(
func
)
?
.to_ptr
()
?
;
let
fn_def
=
self
.memory
.get_fn
(
fn_ptr
.alloc_id
)
?
;
let
bare_sig
=
self
.tcx
.erase_late_bound_regions_and_normalize
(
&
bare_fn_ty
.sig
);
let
bare_sig
=
self
.tcx
.erase_regions
(
&
bare_sig
);
match
fn_def
{
Function
::
Concrete
(
fn_def
)
=>
{
// transmuting function pointers in miri is fine as long as the number of
...
...
@@ -74,21 +74,21 @@ pub(super) fn eval_terminator(
// FIXME: also check the size of the arguments' type and the return type
// Didn't get it to work, since that triggers an assertion in rustc which
// checks whether the type has escaping regions
if
fn_def
.
abi
!=
bare_fn_ty
.abi
||
fn_def
.sig.variadic
!=
bare_sig
.variadic
||
fn_def
.sig
.inputs
()
.
len
()
!=
bare_sig
.inputs
()
.len
()
{
return
Err
(
EvalError
::
FunctionPointerTyMismatch
(
fn_def
.
abi
,
fn_def
.sig
,
bare_fn_ty
));
if
fn_def
.
sig
.abi
()
!=
bare_sig
.abi
()
||
fn_def
.sig
.variadic
()
!=
bare_sig
.variadic
()
||
fn_def
.sig
.inputs
()
.
skip_binder
()
.len
()
!=
bare_sig
.inputs
()
.skip_binder
()
.len
()
{
return
Err
(
EvalError
::
FunctionPointerTyMismatch
(
fn_def
.
sig
,
bare_sig
));
}
},
Function
::
NonCaptureClosureAsFnPtr
(
fn_def
)
=>
{
if
fn_def
.abi
!=
bare_fn_ty
.abi
||
fn_def
.sig.variadic
!=
bare_sig
.variadic
||
fn_def
.sig
.inputs
()
.len
()
!=
1
{
return
Err
(
EvalError
::
FunctionPointerTyMismatch
(
fn_def
.
abi
,
fn_def
.sig
,
bare_fn_ty
));
assert_eq!
(
fn_def
.sig
.abi
(),
Abi
::
RustCall
);
if
fn_def
.sig
.variadic
()
!=
bare_sig
.variadic
()
||
fn_def
.sig
.inputs
()
.
skip_binder
()
.
len
()
!=
1
{
return
Err
(
EvalError
::
FunctionPointerTyMismatch
(
fn_def
.
sig
,
bare_sig
));
}
if
let
ty
::
TyTuple
(
fields
,
_
)
=
fn_def
.sig
.inputs
()[
0
]
.sty
{
if
fields
.len
()
!=
bare_sig
.inputs
()
.len
()
{
return
Err
(
EvalError
::
FunctionPointerTyMismatch
(
fn_def
.
abi
,
fn_def
.sig
,
bare_fn_ty
));
if
let
ty
::
TyTuple
(
fields
,
_
)
=
fn_def
.sig
.inputs
()
.skip_binder
()
[
0
]
.sty
{
if
fields
.len
()
!=
bare_sig
.inputs
()
.
skip_binder
()
.
len
()
{
return
Err
(
EvalError
::
FunctionPointerTyMismatch
(
fn_def
.
sig
,
bare_sig
));
}
}
},
...
...
@@ -99,8 +99,7 @@ pub(super) fn eval_terminator(
ty
::
TyFnDef
(
def_id
,
substs
,
fn_ty
)
=>
Function
::
Concrete
(
FunctionDefinition
{
def_id
,
substs
,
abi
:
fn_ty
.abi
,
sig
:
fn_ty
.sig
.skip_binder
(),
sig
:
fn_ty
,
}),
_
=>
{
...
...
@@ -165,8 +164,8 @@ fn eval_fn_call(
use
syntax
::
abi
::
Abi
;
match
fn_def
{
// Intrinsics can only be addressed directly
Function
::
Concrete
(
FunctionDefinition
{
def_id
,
substs
,
abi
:
Abi
::
RustIntrinsic
,
sig
})
=>
{
let
ty
=
sig
.output
();
Function
::
Concrete
(
FunctionDefinition
{
def_id
,
substs
,
sig
})
if
sig
.abi
()
==
Abi
::
RustIntrinsic
=>
{
let
ty
=
*
sig
.output
()
.skip_binder
();
let
layout
=
self
.type_layout
(
ty
)
?
;
let
(
ret
,
target
)
=
match
destination
{
Some
(
dest
)
if
is_inhabited
(
self
.tcx
,
ty
)
=>
dest
,
...
...
@@ -177,8 +176,8 @@ fn eval_fn_call(
Ok
(())
},
// C functions can only be addressed directly
Function
::
Concrete
(
FunctionDefinition
{
def_id
,
abi
:
Abi
::
C
,
sig
,
..
})
=>
{
let
ty
=
sig
.output
();
Function
::
Concrete
(
FunctionDefinition
{
def_id
,
sig
,
..
})
if
sig
.abi
()
==
Abi
::
C
=>
{
let
ty
=
*
sig
.output
()
.skip_binder
();
let
(
ret
,
target
)
=
destination
.unwrap
();
self
.call_c_abi
(
def_id
,
arg_operands
,
ret
,
ty
)
?
;
self
.dump_local
(
ret
);
...
...
@@ -186,8 +185,7 @@ fn eval_fn_call(
Ok
(())
},
Function
::
DropGlue
(
_
)
=>
Err
(
EvalError
::
ManuallyCalledDropGlue
),
Function
::
Concrete
(
FunctionDefinition
{
def_id
,
abi
:
Abi
::
RustCall
,
sig
,
substs
})
|
Function
::
Concrete
(
FunctionDefinition
{
def_id
,
abi
:
Abi
::
Rust
,
sig
,
substs
})
=>
{
Function
::
Concrete
(
FunctionDefinition
{
def_id
,
sig
,
substs
})
if
sig
.abi
()
==
Abi
::
Rust
||
sig
.abi
()
==
Abi
::
RustCall
=>
{
let
mut
args
=
Vec
::
new
();
for
arg
in
arg_operands
{
let
arg_val
=
self
.eval_operand
(
arg
)
?
;
...
...
@@ -204,20 +202,20 @@ fn eval_fn_call(
};
// FIXME(eddyb) Detect ADT constructors more efficiently.
if
let
Some
(
adt_def
)
=
sig
.output
()
.ty_adt_def
()
{
if
let
Some
(
v
)
=
adt_def
.variants
.iter
()
.find
(|
v
|
resolved_def_id
==
v
.did
)
{
if
let
Some
(
adt_def
)
=
sig
.output
()
.skip_binder
()
.ty_adt_def
()
{
let
dids
=
adt_def
.variants
.iter
()
.map
(|
v
|
v
.did
);
let
discrs
=
adt_def
.discriminants
(
self
.tcx
)
.map
(
ConstInt
::
to_u128_unchecked
);
if
let
Some
((
_
,
disr_val
))
=
dids
.zip
(
discrs
)
.find
(|
&
(
did
,
_
)|
resolved_def_id
==
did
)
{
let
(
lvalue
,
target
)
=
destination
.expect
(
"tuple struct constructors can't diverge"
);
let
dest_ty
=
self
.tcx
.item_type
(
adt_def
.did
);
let
dest_layout
=
self
.type_layout
(
dest_ty
)
?
;
trace!
(
"layout({:?}) = {:#?}"
,
dest_ty
,
dest_layout
);
match
*
dest_layout
{
Layout
::
Univariant
{
..
}
=>
{
let
disr_val
=
v
.disr_val
;
assert_eq!
(
disr_val
,
0
);
self
.assign_fields
(
lvalue
,
dest_ty
,
args
)
?
;
},
Layout
::
General
{
discr
,
ref
variants
,
..
}
=>
{
let
disr_val
=
v
.disr_val
;
let
discr_size
=
discr
.size
()
.bytes
();
self
.assign_discr_and_fields
(
lvalue
,
...
...
@@ -230,7 +228,6 @@ fn eval_fn_call(
)
?
;
},
Layout
::
StructWrappedNullablePointer
{
nndiscr
,
ref
discrfield
,
..
}
=>
{
let
disr_val
=
v
.disr_val
;
if
nndiscr
as
u128
==
disr_val
{
self
.assign_fields
(
lvalue
,
dest_ty
,
args
)
?
;
}
else
{
...
...
@@ -268,7 +265,7 @@ fn eval_fn_call(
span
,
)
},
Function
::
NonCaptureClosureAsFnPtr
(
FunctionDefinition
{
def_id
,
abi
:
Abi
::
Rust
,
substs
,
sig
})
=>
{
Function
::
NonCaptureClosureAsFnPtr
(
FunctionDefinition
{
def_id
,
substs
,
sig
})
if
sig
.abi
()
==
Abi
::
RustCall
=>
{
let
mut
args
=
Vec
::
new
();
for
arg
in
arg_operands
{
let
arg_val
=
self
.eval_operand
(
arg
)
?
;
...
...
@@ -277,7 +274,7 @@ fn eval_fn_call(
}
args
.insert
(
0
,
(
Value
::
ByVal
(
PrimVal
::
Undef
),
sig
.inputs
()[
0
],
sig
.inputs
()
.skip_binder
()
[
0
],
));
self
.eval_fn_call_inner
(
def_id
,
...
...
src/traits.rs
浏览文件 @
8405770b
...
...
@@ -113,7 +113,7 @@ pub(crate) fn trait_method(
match
self
.memory
.get_fn
(
fn_ptr
.alloc_id
)
?
{
Function
::
FnDefAsTraitObject
(
fn_def
)
=>
{
trace!
(
"sig: {:#?}"
,
fn_def
.sig
);
assert
!
(
fn_def
.
abi
!=
abi
::
Abi
::
RustCall
);
assert
!
(
fn_def
.
sig
.abi
()
!=
abi
::
Abi
::
RustCall
);
assert_eq!
(
args
.len
(),
2
);
// a function item turned into a closure trait object
// the first arg is just there to give use the vtable
...
...
@@ -126,14 +126,14 @@ pub(crate) fn trait_method(
trace!
(
"sig: {:#?}"
,
fn_def
.sig
);
args
[
0
]
=
(
Value
::
ByVal
(
PrimVal
::
Ptr
(
self_ptr
)),
fn_def
.sig
.inputs
()[
0
],
fn_def
.sig
.inputs
()
.skip_binder
()
[
0
],
);
Ok
((
fn_def
.def_id
,
fn_def
.substs
,
Vec
::
new
()))
},
Function
::
NonCaptureClosureAsFnPtr
(
fn_def
)
=>
{
args
.insert
(
0
,
(
Value
::
ByVal
(
PrimVal
::
Undef
),
fn_def
.sig
.inputs
()[
0
],
fn_def
.sig
.inputs
()
.skip_binder
()
[
0
],
));
Ok
((
fn_def
.def_id
,
fn_def
.substs
,
Vec
::
new
()))
}
...
...
@@ -155,7 +155,7 @@ pub(crate) fn trait_method(
Function
::
NonCaptureClosureAsFnPtr
(
fn_def
)
=>
{
args
.insert
(
0
,
(
Value
::
ByVal
(
PrimVal
::
Undef
),
fn_def
.sig
.inputs
()[
0
],
fn_def
.sig
.inputs
()
.skip_binder
()
[
0
],
));
fn_def
},
...
...
@@ -220,7 +220,7 @@ pub fn get_vtable(&mut self, trait_ref: ty::PolyTraitRef<'tcx>) -> EvalResult<'t
_
=>
bug!
(
"bad function type: {}"
,
fn_ty
),
};
let
fn_ty
=
self
.tcx
.erase_regions
(
&
fn_ty
);
self
.memory
.create_fn_ptr
(
self
.tcx
,
mth
.method.def_id
,
mth
.substs
,
fn_ty
)
self
.memory
.create_fn_ptr
(
mth
.method.def_id
,
mth
.substs
,
fn_ty
)
}))
.collect
::
<
Vec
<
_
>>
()
.into_iter
()
...
...
@@ -233,15 +233,15 @@ pub fn get_vtable(&mut self, trait_ref: ty::PolyTraitRef<'tcx>) -> EvalResult<'t
..
}
)
=>
{
let
closure_type
=
self
.tcx
.closure_type
(
closure_def_id
,
substs
);
vec!
[
Some
(
self
.memory
.create_closure_ptr
(
self
.tcx
,
closure_def_id
,
substs
,
closure_type
))]
.into_iter
()
let
closure_type
=
self
.tcx
.closure_type
(
closure_def_id
);
vec!
[
Some
(
self
.memory
.create_closure_ptr
(
closure_def_id
,
substs
,
closure_type
))]
.into_iter
()
}
// turn a function definition into a Fn trait object
traits
::
VtableFnPointer
(
traits
::
VtableFnPointerData
{
fn_ty
,
..
})
=>
{
match
fn_ty
.sty
{
ty
::
TyFnDef
(
did
,
substs
,
bare_fn_ty
)
=>
{
vec!
[
Some
(
self
.memory
.create_fn_as_trait_glue
(
self
.tcx
,
did
,
substs
,
bare_fn_ty
))]
.into_iter
()
vec!
[
Some
(
self
.memory
.create_fn_as_trait_glue
(
did
,
substs
,
bare_fn_ty
))]
.into_iter
()
},
ty
::
TyFnPtr
(
bare_fn_ty
)
=>
{
vec!
[
Some
(
self
.memory
.create_fn_ptr_as_trait_glue
(
bare_fn_ty
))]
.into_iter
()
...
...
@@ -275,13 +275,13 @@ pub fn get_vtable(&mut self, trait_ref: ty::PolyTraitRef<'tcx>) -> EvalResult<'t
// in case there is no drop function to be called, this still needs to be initialized
self
.memory
.write_usize
(
vtable
,
0
)
?
;
if
let
ty
::
TyAdt
(
adt_def
,
substs
)
=
trait_ref
.self_ty
()
.sty
{
if
let
Some
(
drop_def_id
)
=
adt_def
.destructor
()
{
if
let
Some
(
drop_def_id
)
=
adt_def
.destructor
(
self
.tcx
)
{
let
fn_ty
=
match
self
.tcx
.item_type
(
drop_def_id
)
.sty
{
ty
::
TyFnDef
(
_
,
_
,
fn_ty
)
=>
self
.tcx
.erase_regions
(
&
fn_ty
),
_
=>
bug!
(
"drop method is not a TyFnDef"
),
};
// The real type is taken from the self argument in `fn drop(&mut self)`
let
real_ty
=
match
fn_ty
.
sig
.skip_binder
()
.inputs
()[
0
]
.sty
{
let
real_ty
=
match
fn_ty
.
inputs
()
.skip_binder
()[
0
]
.sty
{
ty
::
TyRef
(
_
,
mt
)
=>
self
.monomorphize
(
mt
.ty
,
substs
),
_
=>
bug!
(
"first argument of Drop::drop must be &mut T"
),
};
...
...
tests/compile-fail/cast_fn_ptr.rs
浏览文件 @
8405770b
...
...
@@ -5,5 +5,5 @@ fn f() {}
std
::
mem
::
transmute
::
<
fn
(),
fn
(
i32
)
>
(
f
)
};
g
(
42
)
//~ ERROR tried to call a function with
abi Rust and sig
g
(
42
)
//~ ERROR tried to call a function with
sig fn() through a function pointer of type fn(i32)
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录