Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
68daab97
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,发现更多精彩内容 >>
提交
68daab97
编写于
2月 10, 2017
作者:
S
Scott Olson
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Move relevant code into "traits" module.
上级
d8d813c4
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
250 addition
and
246 deletion
+250
-246
src/terminator/mod.rs
src/terminator/mod.rs
+5
-241
src/traits.rs
src/traits.rs
+245
-5
未找到文件。
src/terminator/mod.rs
浏览文件 @
68daab97
use
rustc
::
hir
::
def_id
::
DefId
;
use
rustc
::
mir
;
use
rustc
::
traits
::{
self
,
Reveal
};
use
rustc
::
ty
::
fold
::
TypeFoldable
;
use
rustc
::
ty
::
layout
::{
Layout
,
Size
};
use
rustc
::
ty
::
subst
::
Substs
;
use
rustc
::
ty
::{
self
,
Ty
,
TyCtxt
,
BareFnTy
};
use
syntax
::
codemap
::
{
DUMMY_SP
,
Span
}
;
use
syntax
::
{
ast
,
attr
,
abi
}
;
use
rustc
::
ty
::{
self
,
Ty
,
BareFnTy
};
use
syntax
::
codemap
::
Span
;
use
syntax
::
attr
;
use
error
::{
EvalError
,
EvalResult
};
use
eval_context
::{
EvalContext
,
IntegerExt
,
StackPopCleanup
,
is_inhabited
};
use
lvalue
::
Lvalue
;
use
memory
::{
Pointer
,
FunctionDefinition
,
Function
};
use
memory
::{
Pointer
,
FunctionDefinition
};
use
value
::
PrimVal
;
use
value
::
Value
;
...
...
@@ -19,7 +17,6 @@
mod
drop
;
impl
<
'a
,
'tcx
>
EvalContext
<
'a
,
'tcx
>
{
pub
(
super
)
fn
goto_block
(
&
mut
self
,
target
:
mir
::
BasicBlock
)
{
self
.frame_mut
()
.block
=
target
;
self
.frame_mut
()
.stmt
=
0
;
...
...
@@ -497,29 +494,7 @@ fn call_c_abi(
Ok
(())
}
pub
(
super
)
fn
fulfill_obligation
(
&
self
,
trait_ref
:
ty
::
PolyTraitRef
<
'tcx
>
)
->
traits
::
Vtable
<
'tcx
,
()
>
{
// Do the initial selection for the obligation. This yields the shallow result we are
// looking for -- that is, what specific impl.
self
.tcx
.infer_ctxt
((),
Reveal
::
All
)
.enter
(|
infcx
|
{
let
mut
selcx
=
traits
::
SelectionContext
::
new
(
&
infcx
);
let
obligation
=
traits
::
Obligation
::
new
(
traits
::
ObligationCause
::
misc
(
DUMMY_SP
,
ast
::
DUMMY_NODE_ID
),
trait_ref
.to_poly_trait_predicate
(),
);
let
selection
=
selcx
.select
(
&
obligation
)
.unwrap
()
.unwrap
();
// Currently, we use a fulfillment context to completely resolve all nested obligations.
// This is because they can inform the inference of the impl's type parameters.
let
mut
fulfill_cx
=
traits
::
FulfillmentContext
::
new
();
let
vtable
=
selection
.map
(|
predicate
|
{
fulfill_cx
.register_predicate_obligation
(
&
infcx
,
predicate
);
});
infcx
.drain_fulfillment_cx_or_panic
(
DUMMY_SP
,
&
mut
fulfill_cx
,
&
vtable
)
})
}
fn
unpack_fn_args
(
&
self
,
args
:
&
mut
Vec
<
(
Value
,
Ty
<
'tcx
>
)
>
)
->
EvalResult
<
'tcx
>
{
pub
(
crate
)
fn
unpack_fn_args
(
&
self
,
args
:
&
mut
Vec
<
(
Value
,
Ty
<
'tcx
>
)
>
)
->
EvalResult
<
'tcx
>
{
if
let
Some
((
last
,
last_ty
))
=
args
.pop
()
{
let
last_layout
=
self
.type_layout
(
last_ty
)
?
;
match
(
&
last_ty
.sty
,
last_layout
)
{
...
...
@@ -540,215 +515,4 @@ fn unpack_fn_args(&self, args: &mut Vec<(Value, Ty<'tcx>)>) -> EvalResult<'tcx>
}
Ok
(())
}
/// Trait method, which has to be resolved to an impl method.
fn
trait_method
(
&
mut
self
,
trait_id
:
DefId
,
def_id
:
DefId
,
substs
:
&
'tcx
Substs
<
'tcx
>
,
args
:
&
mut
Vec
<
(
Value
,
Ty
<
'tcx
>
)
>
,
)
->
EvalResult
<
'tcx
,
(
DefId
,
&
'tcx
Substs
<
'tcx
>
,
Vec
<
Pointer
>
)
>
{
let
trait_ref
=
ty
::
TraitRef
::
from_method
(
self
.tcx
,
trait_id
,
substs
);
let
trait_ref
=
self
.tcx
.normalize_associated_type
(
&
ty
::
Binder
(
trait_ref
));
match
self
.fulfill_obligation
(
trait_ref
)
{
traits
::
VtableImpl
(
vtable_impl
)
=>
{
let
impl_did
=
vtable_impl
.impl_def_id
;
let
mname
=
self
.tcx
.item_name
(
def_id
);
// Create a concatenated set of substitutions which includes those from the impl
// and those from the method:
let
(
did
,
substs
)
=
find_method
(
self
.tcx
,
substs
,
impl_did
,
vtable_impl
.substs
,
mname
);
Ok
((
did
,
substs
,
Vec
::
new
()))
}
traits
::
VtableClosure
(
vtable_closure
)
=>
{
let
trait_closure_kind
=
self
.tcx
.lang_items
.fn_trait_kind
(
trait_id
)
.expect
(
"The substitutions should have no type parameters remaining after passing through fulfill_obligation"
);
let
closure_kind
=
self
.tcx
.closure_kind
(
vtable_closure
.closure_def_id
);
trace!
(
"closures {:?}, {:?}"
,
closure_kind
,
trait_closure_kind
);
self
.unpack_fn_args
(
args
)
?
;
let
mut
temporaries
=
Vec
::
new
();
match
(
closure_kind
,
trait_closure_kind
)
{
(
ty
::
ClosureKind
::
Fn
,
ty
::
ClosureKind
::
Fn
)
|
(
ty
::
ClosureKind
::
FnMut
,
ty
::
ClosureKind
::
FnMut
)
|
(
ty
::
ClosureKind
::
FnOnce
,
ty
::
ClosureKind
::
FnOnce
)
|
(
ty
::
ClosureKind
::
Fn
,
ty
::
ClosureKind
::
FnMut
)
=>
{}
// No adapter needed.
(
ty
::
ClosureKind
::
Fn
,
ty
::
ClosureKind
::
FnOnce
)
|
(
ty
::
ClosureKind
::
FnMut
,
ty
::
ClosureKind
::
FnOnce
)
=>
{
// The closure fn is a `fn(&self, ...)` or `fn(&mut self, ...)`.
// We want a `fn(self, ...)`.
// We can produce this by doing something like:
//
// fn call_once(self, ...) { call_mut(&self, ...) }
// fn call_once(mut self, ...) { call_mut(&mut self, ...) }
//
// These are both the same at trans time.
// Interpreter magic: insert an intermediate pointer, so we can skip the
// intermediate function call.
let
ptr
=
match
args
[
0
]
.0
{
Value
::
ByRef
(
ptr
)
=>
ptr
,
Value
::
ByVal
(
primval
)
=>
{
let
ptr
=
self
.alloc_ptr
(
args
[
0
]
.1
)
?
;
let
size
=
self
.type_size
(
args
[
0
]
.1
)
?
.expect
(
"closures are sized"
);
self
.memory
.write_primval
(
ptr
,
primval
,
size
)
?
;
temporaries
.push
(
ptr
);
ptr
},
Value
::
ByValPair
(
a
,
b
)
=>
{
let
ptr
=
self
.alloc_ptr
(
args
[
0
]
.1
)
?
;
self
.write_pair_to_ptr
(
a
,
b
,
ptr
,
args
[
0
]
.1
)
?
;
temporaries
.push
(
ptr
);
ptr
},
};
args
[
0
]
.0
=
Value
::
ByVal
(
PrimVal
::
Ptr
(
ptr
));
args
[
0
]
.1
=
self
.tcx
.mk_mut_ptr
(
args
[
0
]
.1
);
}
_
=>
bug!
(
"cannot convert {:?} to {:?}"
,
closure_kind
,
trait_closure_kind
),
}
Ok
((
vtable_closure
.closure_def_id
,
vtable_closure
.substs.substs
,
temporaries
))
}
traits
::
VtableFnPointer
(
vtable_fn_ptr
)
=>
{
if
let
ty
::
TyFnDef
(
did
,
substs
,
_
)
=
vtable_fn_ptr
.fn_ty.sty
{
args
.remove
(
0
);
self
.unpack_fn_args
(
args
)
?
;
Ok
((
did
,
substs
,
Vec
::
new
()))
}
else
{
bug!
(
"VtableFnPointer did not contain a concrete function: {:?}"
,
vtable_fn_ptr
)
}
}
traits
::
VtableObject
(
ref
data
)
=>
{
let
idx
=
self
.tcx
.get_vtable_index_of_object_method
(
data
,
def_id
)
as
u64
;
if
args
.is_empty
()
{
return
Err
(
EvalError
::
VtableForArgumentlessMethod
);
}
let
(
self_ptr
,
vtable
)
=
args
[
0
]
.0
.expect_ptr_vtable_pair
(
&
self
.memory
)
?
;
let
idx
=
idx
+
3
;
let
offset
=
idx
*
self
.memory
.pointer_size
();
let
fn_ptr
=
self
.memory
.read_ptr
(
vtable
.offset
(
offset
))
?
;
trace!
(
"args: {:#?}"
,
args
);
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_eq!
(
args
.len
(),
2
);
// a function item turned into a closure trait object
// the first arg is just there to give use the vtable
args
.remove
(
0
);
self
.unpack_fn_args
(
args
)
?
;
Ok
((
fn_def
.def_id
,
fn_def
.substs
,
Vec
::
new
()))
},
Function
::
DropGlue
(
_
)
=>
Err
(
EvalError
::
ManuallyCalledDropGlue
),
Function
::
Concrete
(
fn_def
)
=>
{
trace!
(
"sig: {:#?}"
,
fn_def
.sig
);
args
[
0
]
=
(
Value
::
ByVal
(
PrimVal
::
Ptr
(
self_ptr
)),
fn_def
.sig
.inputs
()[
0
],
);
Ok
((
fn_def
.def_id
,
fn_def
.substs
,
Vec
::
new
()))
},
Function
::
Closure
(
fn_def
)
=>
{
self
.unpack_fn_args
(
args
)
?
;
Ok
((
fn_def
.def_id
,
fn_def
.substs
,
Vec
::
new
()))
}
Function
::
FnPtrAsTraitObject
(
sig
)
=>
{
trace!
(
"sig: {:#?}"
,
sig
);
// the first argument was the fat ptr
args
.remove
(
0
);
self
.unpack_fn_args
(
args
)
?
;
let
fn_ptr
=
self
.memory
.read_ptr
(
self_ptr
)
?
;
let
fn_def
=
self
.memory
.get_fn
(
fn_ptr
.alloc_id
)
?
.expect_concrete
()
?
;
assert_eq!
(
sig
,
fn_def
.sig
);
Ok
((
fn_def
.def_id
,
fn_def
.substs
,
Vec
::
new
()))
}
}
},
vtable
=>
bug!
(
"resolved vtable bad vtable {:?} in trans"
,
vtable
),
}
}
}
#[derive(Debug)]
pub
(
super
)
struct
ImplMethod
<
'tcx
>
{
pub
(
super
)
method
:
ty
::
AssociatedItem
,
pub
(
super
)
substs
:
&
'tcx
Substs
<
'tcx
>
,
pub
(
super
)
is_provided
:
bool
,
}
/// Locates the applicable definition of a method, given its name.
pub
(
super
)
fn
get_impl_method
<
'a
,
'tcx
>
(
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
substs
:
&
'tcx
Substs
<
'tcx
>
,
impl_def_id
:
DefId
,
impl_substs
:
&
'tcx
Substs
<
'tcx
>
,
name
:
ast
::
Name
,
)
->
ImplMethod
<
'tcx
>
{
assert
!
(
!
substs
.needs_infer
());
let
trait_def_id
=
tcx
.trait_id_of_impl
(
impl_def_id
)
.unwrap
();
let
trait_def
=
tcx
.lookup_trait_def
(
trait_def_id
);
match
trait_def
.ancestors
(
impl_def_id
)
.defs
(
tcx
,
name
,
ty
::
AssociatedKind
::
Method
)
.next
()
{
Some
(
node_item
)
=>
{
let
substs
=
tcx
.infer_ctxt
((),
Reveal
::
All
)
.enter
(|
infcx
|
{
let
substs
=
substs
.rebase_onto
(
tcx
,
trait_def_id
,
impl_substs
);
let
substs
=
traits
::
translate_substs
(
&
infcx
,
impl_def_id
,
substs
,
node_item
.node
);
tcx
.lift
(
&
substs
)
.unwrap_or_else
(||
{
bug!
(
"trans::meth::get_impl_method: translate_substs
\
returned {:?} which contains inference types/regions"
,
substs
);
})
});
ImplMethod
{
method
:
node_item
.item
,
substs
,
is_provided
:
node_item
.node
.is_from_trait
(),
}
}
None
=>
{
bug!
(
"method {:?} not found in {:?}"
,
name
,
impl_def_id
)
}
}
}
/// Locates the applicable definition of a method, given its name.
pub
fn
find_method
<
'a
,
'tcx
>
(
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
substs
:
&
'tcx
Substs
<
'tcx
>
,
impl_def_id
:
DefId
,
impl_substs
:
&
'tcx
Substs
<
'tcx
>
,
name
:
ast
::
Name
)
->
(
DefId
,
&
'tcx
Substs
<
'tcx
>
)
{
assert
!
(
!
substs
.needs_infer
());
let
trait_def_id
=
tcx
.trait_id_of_impl
(
impl_def_id
)
.unwrap
();
let
trait_def
=
tcx
.lookup_trait_def
(
trait_def_id
);
match
trait_def
.ancestors
(
impl_def_id
)
.defs
(
tcx
,
name
,
ty
::
AssociatedKind
::
Method
)
.next
()
{
Some
(
node_item
)
=>
{
let
substs
=
tcx
.infer_ctxt
((),
Reveal
::
All
)
.enter
(|
infcx
|
{
let
substs
=
substs
.rebase_onto
(
tcx
,
trait_def_id
,
impl_substs
);
let
substs
=
traits
::
translate_substs
(
&
infcx
,
impl_def_id
,
substs
,
node_item
.node
);
tcx
.lift
(
&
substs
)
.unwrap_or_else
(||
{
bug!
(
"find_method: translate_substs
\
returned {:?} which contains inference types/regions"
,
substs
);
})
});
(
node_item
.item.def_id
,
substs
)
}
None
=>
{
bug!
(
"method {:?} not found in {:?}"
,
name
,
impl_def_id
)
}
}
}
src/traits.rs
浏览文件 @
68daab97
use
rustc
::
hir
::
def_id
::
DefId
;
use
rustc
::
traits
::{
self
,
Reveal
,
SelectionContext
};
use
rustc
::
ty
::
subst
::
Substs
;
use
rustc
::
ty
;
use
error
::
EvalResult
;
use
eval_context
::
EvalContext
;
use
memory
::
Pointer
;
use
terminator
::{
get_impl_method
,
ImplMethod
};
use
rustc
::
hir
::
def_id
::
DefId
;
use
rustc
::
ty
::
fold
::
TypeFoldable
;
use
rustc
::
ty
::
subst
::
Substs
;
use
rustc
::
ty
::{
self
,
Ty
,
TyCtxt
};
use
syntax
::
codemap
::
DUMMY_SP
;
use
syntax
::{
ast
,
abi
};
use
error
::{
EvalError
,
EvalResult
};
use
memory
::
Function
;
use
value
::
PrimVal
;
use
value
::
Value
;
impl
<
'a
,
'tcx
>
EvalContext
<
'a
,
'tcx
>
{
/// Trait method, which has to be resolved to an impl method.
pub
(
crate
)
fn
trait_method
(
&
mut
self
,
trait_id
:
DefId
,
def_id
:
DefId
,
substs
:
&
'tcx
Substs
<
'tcx
>
,
args
:
&
mut
Vec
<
(
Value
,
Ty
<
'tcx
>
)
>
,
)
->
EvalResult
<
'tcx
,
(
DefId
,
&
'tcx
Substs
<
'tcx
>
,
Vec
<
Pointer
>
)
>
{
let
trait_ref
=
ty
::
TraitRef
::
from_method
(
self
.tcx
,
trait_id
,
substs
);
let
trait_ref
=
self
.tcx
.normalize_associated_type
(
&
ty
::
Binder
(
trait_ref
));
match
self
.fulfill_obligation
(
trait_ref
)
{
traits
::
VtableImpl
(
vtable_impl
)
=>
{
let
impl_did
=
vtable_impl
.impl_def_id
;
let
mname
=
self
.tcx
.item_name
(
def_id
);
// Create a concatenated set of substitutions which includes those from the impl
// and those from the method:
let
(
did
,
substs
)
=
find_method
(
self
.tcx
,
substs
,
impl_did
,
vtable_impl
.substs
,
mname
);
Ok
((
did
,
substs
,
Vec
::
new
()))
}
traits
::
VtableClosure
(
vtable_closure
)
=>
{
let
trait_closure_kind
=
self
.tcx
.lang_items
.fn_trait_kind
(
trait_id
)
.expect
(
"The substitutions should have no type parameters remaining after passing through fulfill_obligation"
);
let
closure_kind
=
self
.tcx
.closure_kind
(
vtable_closure
.closure_def_id
);
trace!
(
"closures {:?}, {:?}"
,
closure_kind
,
trait_closure_kind
);
self
.unpack_fn_args
(
args
)
?
;
let
mut
temporaries
=
Vec
::
new
();
match
(
closure_kind
,
trait_closure_kind
)
{
(
ty
::
ClosureKind
::
Fn
,
ty
::
ClosureKind
::
Fn
)
|
(
ty
::
ClosureKind
::
FnMut
,
ty
::
ClosureKind
::
FnMut
)
|
(
ty
::
ClosureKind
::
FnOnce
,
ty
::
ClosureKind
::
FnOnce
)
|
(
ty
::
ClosureKind
::
Fn
,
ty
::
ClosureKind
::
FnMut
)
=>
{}
// No adapter needed.
(
ty
::
ClosureKind
::
Fn
,
ty
::
ClosureKind
::
FnOnce
)
|
(
ty
::
ClosureKind
::
FnMut
,
ty
::
ClosureKind
::
FnOnce
)
=>
{
// The closure fn is a `fn(&self, ...)` or `fn(&mut self, ...)`.
// We want a `fn(self, ...)`.
// We can produce this by doing something like:
//
// fn call_once(self, ...) { call_mut(&self, ...) }
// fn call_once(mut self, ...) { call_mut(&mut self, ...) }
//
// These are both the same at trans time.
// Interpreter magic: insert an intermediate pointer, so we can skip the
// intermediate function call.
let
ptr
=
match
args
[
0
]
.0
{
Value
::
ByRef
(
ptr
)
=>
ptr
,
Value
::
ByVal
(
primval
)
=>
{
let
ptr
=
self
.alloc_ptr
(
args
[
0
]
.1
)
?
;
let
size
=
self
.type_size
(
args
[
0
]
.1
)
?
.expect
(
"closures are sized"
);
self
.memory
.write_primval
(
ptr
,
primval
,
size
)
?
;
temporaries
.push
(
ptr
);
ptr
},
Value
::
ByValPair
(
a
,
b
)
=>
{
let
ptr
=
self
.alloc_ptr
(
args
[
0
]
.1
)
?
;
self
.write_pair_to_ptr
(
a
,
b
,
ptr
,
args
[
0
]
.1
)
?
;
temporaries
.push
(
ptr
);
ptr
},
};
args
[
0
]
.0
=
Value
::
ByVal
(
PrimVal
::
Ptr
(
ptr
));
args
[
0
]
.1
=
self
.tcx
.mk_mut_ptr
(
args
[
0
]
.1
);
}
_
=>
bug!
(
"cannot convert {:?} to {:?}"
,
closure_kind
,
trait_closure_kind
),
}
Ok
((
vtable_closure
.closure_def_id
,
vtable_closure
.substs.substs
,
temporaries
))
}
traits
::
VtableFnPointer
(
vtable_fn_ptr
)
=>
{
if
let
ty
::
TyFnDef
(
did
,
substs
,
_
)
=
vtable_fn_ptr
.fn_ty.sty
{
args
.remove
(
0
);
self
.unpack_fn_args
(
args
)
?
;
Ok
((
did
,
substs
,
Vec
::
new
()))
}
else
{
bug!
(
"VtableFnPointer did not contain a concrete function: {:?}"
,
vtable_fn_ptr
)
}
}
traits
::
VtableObject
(
ref
data
)
=>
{
let
idx
=
self
.tcx
.get_vtable_index_of_object_method
(
data
,
def_id
)
as
u64
;
if
args
.is_empty
()
{
return
Err
(
EvalError
::
VtableForArgumentlessMethod
);
}
let
(
self_ptr
,
vtable
)
=
args
[
0
]
.0
.expect_ptr_vtable_pair
(
&
self
.memory
)
?
;
let
idx
=
idx
+
3
;
let
offset
=
idx
*
self
.memory
.pointer_size
();
let
fn_ptr
=
self
.memory
.read_ptr
(
vtable
.offset
(
offset
))
?
;
trace!
(
"args: {:#?}"
,
args
);
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_eq!
(
args
.len
(),
2
);
// a function item turned into a closure trait object
// the first arg is just there to give use the vtable
args
.remove
(
0
);
self
.unpack_fn_args
(
args
)
?
;
Ok
((
fn_def
.def_id
,
fn_def
.substs
,
Vec
::
new
()))
},
Function
::
DropGlue
(
_
)
=>
Err
(
EvalError
::
ManuallyCalledDropGlue
),
Function
::
Concrete
(
fn_def
)
=>
{
trace!
(
"sig: {:#?}"
,
fn_def
.sig
);
args
[
0
]
=
(
Value
::
ByVal
(
PrimVal
::
Ptr
(
self_ptr
)),
fn_def
.sig
.inputs
()[
0
],
);
Ok
((
fn_def
.def_id
,
fn_def
.substs
,
Vec
::
new
()))
},
Function
::
Closure
(
fn_def
)
=>
{
self
.unpack_fn_args
(
args
)
?
;
Ok
((
fn_def
.def_id
,
fn_def
.substs
,
Vec
::
new
()))
}
Function
::
FnPtrAsTraitObject
(
sig
)
=>
{
trace!
(
"sig: {:#?}"
,
sig
);
// the first argument was the fat ptr
args
.remove
(
0
);
self
.unpack_fn_args
(
args
)
?
;
let
fn_ptr
=
self
.memory
.read_ptr
(
self_ptr
)
?
;
let
fn_def
=
self
.memory
.get_fn
(
fn_ptr
.alloc_id
)
?
.expect_concrete
()
?
;
assert_eq!
(
sig
,
fn_def
.sig
);
Ok
((
fn_def
.def_id
,
fn_def
.substs
,
Vec
::
new
()))
}
}
},
vtable
=>
bug!
(
"resolved vtable bad vtable {:?} in trans"
,
vtable
),
}
}
pub
(
crate
)
fn
fulfill_obligation
(
&
self
,
trait_ref
:
ty
::
PolyTraitRef
<
'tcx
>
)
->
traits
::
Vtable
<
'tcx
,
()
>
{
// Do the initial selection for the obligation. This yields the shallow result we are
// looking for -- that is, what specific impl.
self
.tcx
.infer_ctxt
((),
Reveal
::
All
)
.enter
(|
infcx
|
{
let
mut
selcx
=
traits
::
SelectionContext
::
new
(
&
infcx
);
let
obligation
=
traits
::
Obligation
::
new
(
traits
::
ObligationCause
::
misc
(
DUMMY_SP
,
ast
::
DUMMY_NODE_ID
),
trait_ref
.to_poly_trait_predicate
(),
);
let
selection
=
selcx
.select
(
&
obligation
)
.unwrap
()
.unwrap
();
// Currently, we use a fulfillment context to completely resolve all nested obligations.
// This is because they can inform the inference of the impl's type parameters.
let
mut
fulfill_cx
=
traits
::
FulfillmentContext
::
new
();
let
vtable
=
selection
.map
(|
predicate
|
{
fulfill_cx
.register_predicate_obligation
(
&
infcx
,
predicate
);
});
infcx
.drain_fulfillment_cx_or_panic
(
DUMMY_SP
,
&
mut
fulfill_cx
,
&
vtable
)
})
}
/// Creates a dynamic vtable for the given type and vtable origin. This is used only for
/// objects.
///
...
...
@@ -230,3 +394,79 @@ pub(crate) fn resolve_associated_const(
(
def_id
,
substs
)
}
}
#[derive(Debug)]
pub
(
super
)
struct
ImplMethod
<
'tcx
>
{
pub
(
super
)
method
:
ty
::
AssociatedItem
,
pub
(
super
)
substs
:
&
'tcx
Substs
<
'tcx
>
,
pub
(
super
)
is_provided
:
bool
,
}
/// Locates the applicable definition of a method, given its name.
pub
(
super
)
fn
get_impl_method
<
'a
,
'tcx
>
(
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
substs
:
&
'tcx
Substs
<
'tcx
>
,
impl_def_id
:
DefId
,
impl_substs
:
&
'tcx
Substs
<
'tcx
>
,
name
:
ast
::
Name
,
)
->
ImplMethod
<
'tcx
>
{
assert
!
(
!
substs
.needs_infer
());
let
trait_def_id
=
tcx
.trait_id_of_impl
(
impl_def_id
)
.unwrap
();
let
trait_def
=
tcx
.lookup_trait_def
(
trait_def_id
);
match
trait_def
.ancestors
(
impl_def_id
)
.defs
(
tcx
,
name
,
ty
::
AssociatedKind
::
Method
)
.next
()
{
Some
(
node_item
)
=>
{
let
substs
=
tcx
.infer_ctxt
((),
Reveal
::
All
)
.enter
(|
infcx
|
{
let
substs
=
substs
.rebase_onto
(
tcx
,
trait_def_id
,
impl_substs
);
let
substs
=
traits
::
translate_substs
(
&
infcx
,
impl_def_id
,
substs
,
node_item
.node
);
tcx
.lift
(
&
substs
)
.unwrap_or_else
(||
{
bug!
(
"trans::meth::get_impl_method: translate_substs
\
returned {:?} which contains inference types/regions"
,
substs
);
})
});
ImplMethod
{
method
:
node_item
.item
,
substs
,
is_provided
:
node_item
.node
.is_from_trait
(),
}
}
None
=>
{
bug!
(
"method {:?} not found in {:?}"
,
name
,
impl_def_id
)
}
}
}
/// Locates the applicable definition of a method, given its name.
pub
fn
find_method
<
'a
,
'tcx
>
(
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
substs
:
&
'tcx
Substs
<
'tcx
>
,
impl_def_id
:
DefId
,
impl_substs
:
&
'tcx
Substs
<
'tcx
>
,
name
:
ast
::
Name
)
->
(
DefId
,
&
'tcx
Substs
<
'tcx
>
)
{
assert
!
(
!
substs
.needs_infer
());
let
trait_def_id
=
tcx
.trait_id_of_impl
(
impl_def_id
)
.unwrap
();
let
trait_def
=
tcx
.lookup_trait_def
(
trait_def_id
);
match
trait_def
.ancestors
(
impl_def_id
)
.defs
(
tcx
,
name
,
ty
::
AssociatedKind
::
Method
)
.next
()
{
Some
(
node_item
)
=>
{
let
substs
=
tcx
.infer_ctxt
((),
Reveal
::
All
)
.enter
(|
infcx
|
{
let
substs
=
substs
.rebase_onto
(
tcx
,
trait_def_id
,
impl_substs
);
let
substs
=
traits
::
translate_substs
(
&
infcx
,
impl_def_id
,
substs
,
node_item
.node
);
tcx
.lift
(
&
substs
)
.unwrap_or_else
(||
{
bug!
(
"find_method: translate_substs
\
returned {:?} which contains inference types/regions"
,
substs
);
})
});
(
node_item
.item.def_id
,
substs
)
}
None
=>
{
bug!
(
"method {:?} not found in {:?}"
,
name
,
impl_def_id
)
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录