Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
866250c6
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,发现更多精彩内容 >>
提交
866250c6
编写于
1月 27, 2015
作者:
F
Felix S. Klock II
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
prototype Placer protocol for unstable overloaded-box and placement-in.
上级
1829fa51
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
333 addition
and
5 deletion
+333
-5
src/liballoc/boxed.rs
src/liballoc/boxed.rs
+102
-5
src/libcore/ops.rs
src/libcore/ops.rs
+112
-0
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/expr_use_visitor.rs
+5
-0
src/libsyntax/ext/expand.rs
src/libsyntax/ext/expand.rs
+114
-0
未找到文件。
src/liballoc/boxed.rs
浏览文件 @
866250c6
...
...
@@ -55,13 +55,16 @@
use
core
::
prelude
::
*
;
use
heap
;
use
core
::
any
::
Any
;
use
core
::
cmp
::
Ordering
;
use
core
::
fmt
;
use
core
::
hash
::{
self
,
Hash
};
use
core
::
marker
::
Unsize
;
use
core
::
marker
::
{
self
,
Unsize
}
;
use
core
::
mem
;
use
core
::
ops
::{
CoerceUnsized
,
Deref
,
DerefMut
};
use
core
::
ops
::{
Placer
,
Boxed
,
Place
,
InPlace
,
BoxPlace
};
use
core
::
ptr
::
Unique
;
use
core
::
raw
::{
TraitObject
};
...
...
@@ -83,7 +86,12 @@
#[lang
=
"exchange_heap"
]
#[unstable(feature
=
"box_heap"
,
reason
=
"may be renamed; uncertain about custom allocator design"
)]
pub
const
HEAP
:
()
=
();
pub
const
HEAP
:
ExchangeHeapSingleton
=
ExchangeHeapSingleton
{
_
force_singleton
:
()
};
/// This the singleton type used solely for `boxed::HEAP`.
#[derive(Copy,
Clone)]
pub
struct
ExchangeHeapSingleton
{
_
force_singleton
:
()
}
/// A pointer type for heap allocation.
///
...
...
@@ -91,7 +99,97 @@
#[lang
=
"owned_box"
]
#[stable(feature
=
"rust1"
,
since
=
"1.0.0"
)]
#[fundamental]
pub
struct
Box
<
T
>
(
Unique
<
T
>
);
pub
struct
Box
<
T
:
?
Sized
>
(
Unique
<
T
>
);
/// `IntermediateBox` represents uninitialized backing storage for `Box`.
///
/// FIXME (pnkfelix): Ideally we would just reuse `Box<T>` instead of
/// introducing a separate `IntermediateBox<T>`; but then you hit
/// issues when you e.g. attempt to destructure an instance of `Box`,
/// since it is a lang item and so it gets special handling by the
/// compiler. Easier just to make this parallel type for now.
///
/// FIXME (pnkfelix): Currently the `box` protocol only supports
/// creating instances of sized types. This IntermediateBox is
/// designed to be forward-compatible with a future protocol that
/// supports creating instances of unsized types; that is why the type
/// parameter has the `?Sized` generalization marker, and is also why
/// this carries an explicit size. However, it probably does not need
/// to carry the explicit alignment; that is just a work-around for
/// the fact that the `align_of` intrinsic currently requires the
/// input type to be Sized (which I do not think is strictly
/// necessary).
#[unstable(feature
=
"placement_in"
,
reason
=
"placement box design is still being worked out."
)]
pub
struct
IntermediateBox
<
T
:
?
Sized
>
{
ptr
:
*
mut
u8
,
size
:
usize
,
align
:
usize
,
marker
:
marker
::
PhantomData
<*
mut
T
>
,
}
impl
<
T
>
Place
<
T
>
for
IntermediateBox
<
T
>
{
fn
pointer
(
&
mut
self
)
->
*
mut
T
{
unsafe
{
::
core
::
mem
::
transmute
(
self
.ptr
)
}
}
}
unsafe
fn
finalize
<
T
>
(
b
:
IntermediateBox
<
T
>
)
->
Box
<
T
>
{
let
p
=
b
.ptr
as
*
mut
T
;
mem
::
forget
(
b
);
mem
::
transmute
(
p
)
}
fn
make_place
<
T
>
()
->
IntermediateBox
<
T
>
{
let
size
=
mem
::
size_of
::
<
T
>
();
let
align
=
mem
::
align_of
::
<
T
>
();
let
p
=
if
size
==
0
{
heap
::
EMPTY
as
*
mut
u8
}
else
{
let
p
=
unsafe
{
heap
::
allocate
(
size
,
align
)
};
if
p
.is_null
()
{
panic!
(
"Box make_place allocation failure."
);
}
p
};
IntermediateBox
{
ptr
:
p
,
size
:
size
,
align
:
align
,
marker
:
marker
::
PhantomData
}
}
impl
<
T
>
BoxPlace
<
T
>
for
IntermediateBox
<
T
>
{
fn
make_place
()
->
IntermediateBox
<
T
>
{
make_place
()
}
}
impl
<
T
>
InPlace
<
T
>
for
IntermediateBox
<
T
>
{
type
Owner
=
Box
<
T
>
;
unsafe
fn
finalize
(
self
)
->
Box
<
T
>
{
finalize
(
self
)
}
}
impl
<
T
>
Boxed
for
Box
<
T
>
{
type
Data
=
T
;
type
Place
=
IntermediateBox
<
T
>
;
unsafe
fn
finalize
(
b
:
IntermediateBox
<
T
>
)
->
Box
<
T
>
{
finalize
(
b
)
}
}
impl
<
T
>
Placer
<
T
>
for
ExchangeHeapSingleton
{
type
Place
=
IntermediateBox
<
T
>
;
fn
make_place
(
self
)
->
IntermediateBox
<
T
>
{
make_place
()
}
}
impl
<
T
:
?
Sized
>
Drop
for
IntermediateBox
<
T
>
{
fn
drop
(
&
mut
self
)
{
if
self
.size
>
0
{
unsafe
{
heap
::
deallocate
(
self
.ptr
,
self
.size
,
self
.align
)
}
}
}
}
impl
<
T
>
Box
<
T
>
{
/// Allocates memory on the heap and then moves `x` into it.
...
...
@@ -199,8 +297,7 @@ impl<T: Clone> Clone for Box<T> {
/// let y = x.clone();
/// ```
#[inline]
fn
clone
(
&
self
)
->
Box
<
T
>
{
box
{(
**
self
)
.clone
()}
}
fn
clone
(
&
self
)
->
Box
<
T
>
{
box
(
HEAP
)
{(
**
self
)
.clone
()}
}
/// Copies `source`'s contents into `self` without creating a new allocation.
///
/// # Examples
...
...
src/libcore/ops.rs
浏览文件 @
866250c6
...
...
@@ -1266,3 +1266,115 @@ impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *mut T {}
// *const T -> *const U
impl
<
T
:
?
Sized
+
Unsize
<
U
>
,
U
:
?
Sized
>
CoerceUnsized
<*
const
U
>
for
*
const
T
{}
/// Both `in (PLACE) EXPR` and `box EXPR` desugar into expressions
/// that allocate an intermediate "place" that holds uninitialized
/// state. The desugaring evaluates EXPR, and writes the result at
/// the address returned by the `pointer` method of this trait.
///
/// A `Place` can be thought of as a special representation for a
/// hypothetical `&uninit` reference (which Rust cannot currently
/// express directly). That is, it represents a pointer to
/// uninitialized storage.
///
/// The client is responsible for two steps: First, initializing the
/// payload (it can access its address via `pointer`). Second,
/// converting the agent to an instance of the owning pointer, via the
/// appropriate `finalize` method (see the `InPlace`.
///
/// If evaluating EXPR fails, then the destructor for the
/// implementation of Place to clean up any intermediate state
/// (e.g. deallocate box storage, pop a stack, etc).
pub
trait
Place
<
Data
:
?
Sized
>
{
/// Returns the address where the input value will be written.
/// Note that the data at this address is generally uninitialized,
/// and thus one should use `ptr::write` for initializing it.
fn
pointer
(
&
mut
self
)
->
*
mut
Data
;
}
/// Interface to implementations of `in (PLACE) EXPR`.
///
/// `in (PLACE) EXPR` effectively desugars into:
///
/// ```rust,ignore
/// let p = PLACE;
/// let mut place = Placer::make_place(p);
/// let raw_place = Place::pointer(&mut place);
/// let value = EXPR;
/// unsafe {
/// std::ptr::write(raw_place, value);
/// InPlace::finalize(place)
/// }
/// ```
///
/// The type of `in (PLACE) EXPR` is derived from the type of `PLACE`;
/// if the type of `PLACE` is `P`, then the final type of the whole
/// expression is `P::Place::Owner` (see the `InPlace` and `Boxed`
/// traits).
///
/// Values for types implementing this trait usually are transient
/// intermediate values (e.g. the return value of `Vec::emplace_back`)
/// or `Copy`, since the `make_place` method takes `self` by value.
pub
trait
Placer
<
Data
:
?
Sized
>
{
/// `Place` is the intermedate agent guarding the
/// uninitialized state for `Data`.
type
Place
:
InPlace
<
Data
>
;
/// Creates a fresh place from `self`.
fn
make_place
(
self
)
->
Self
::
Place
;
}
/// Specialization of `Place` trait supporting `in (PLACE) EXPR`.
pub
trait
InPlace
<
Data
:
?
Sized
>
:
Place
<
Data
>
{
/// `Owner` is the type of the end value of `in (PLACE) EXPR`
///
/// Note that when `in (PLACE) EXPR` is solely used for
/// side-effecting an existing data-structure,
/// e.g. `Vec::emplace_back`, then `Owner` need not carry any
/// information at all (e.g. it can be the unit type `()` in that
/// case).
type
Owner
;
/// Converts self into the final value, shifting
/// deallocation/cleanup responsibilities (if any remain), over to
/// the returned instance of `Owner` and forgetting self.
unsafe
fn
finalize
(
self
)
->
Self
::
Owner
;
}
/// Core trait for the `box EXPR` form.
///
/// `box EXPR` effectively desugars into:
///
/// ```rust,ignore
/// let mut place = BoxPlace::make_place();
/// let raw_place = Place::pointer(&mut place);
/// let value = EXPR;
/// unsafe {
/// ::std::ptr::write(raw_place, value);
/// Boxed::finalize(place)
/// }
/// ```
///
/// The type of `box EXPR` is supplied from its surrounding
/// context; in the above expansion, the result type `T` is used
/// to determine which implementation of `Boxed` to use, and that
/// `<T as Boxed>` in turn dictates determines which
/// implementation of `BoxPlace` to use, namely:
/// `<<T as Boxed>::Place as BoxPlace>`.
pub
trait
Boxed
{
/// The kind of data that is stored in this kind of box.
type
Data
;
/* (`Data` unused b/c cannot yet express below bound.) */
/// The place that will negotiate the storage of the data.
type
Place
;
/* should be bounded by BoxPlace<Self::Data> */
/// Converts filled place into final owning value, shifting
/// deallocation/cleanup responsibilities (if any remain), over to
/// returned instance of `Self` and forgetting `filled`.
unsafe
fn
finalize
(
filled
:
Self
::
Place
)
->
Self
;
}
/// Specialization of `Place` trait supporting `box EXPR`.
pub
trait
BoxPlace
<
Data
:
?
Sized
>
:
Place
<
Data
>
{
/// Creates a globally fresh place.
fn
make_place
()
->
Self
;
}
src/librustc/middle/expr_use_visitor.rs
浏览文件 @
866250c6
...
...
@@ -555,6 +555,11 @@ pub fn walk_expr(&mut self, expr: &ast::Expr) {
None
=>
{}
}
self
.consume_expr
(
&**
base
);
if
place
.is_some
()
{
self
.tcx
()
.sess
.span_bug
(
expr
.span
,
"box with explicit place remains after expansion"
);
}
}
ast
::
ExprMac
(
..
)
=>
{
...
...
src/libsyntax/ext/expand.rs
浏览文件 @
866250c6
...
...
@@ -33,6 +33,16 @@
use
visit
::
Visitor
;
use
std_inject
;
// Given suffix ["b","c","d"], returns path `::std::b::c::d` when
// `fld.cx.use_std`, and `::core::b::c::d` otherwise.
fn
mk_core_path
(
fld
:
&
mut
MacroExpander
,
span
:
Span
,
suffix
:
&
[
&
'static
str
])
->
ast
::
Path
{
let
mut
idents
=
vec!
[
fld
.cx
.ident_of_std
(
"core"
)];
for
s
in
suffix
.iter
()
{
idents
.push
(
fld
.cx
.ident_of
(
*
s
));
}
fld
.cx
.path_global
(
span
,
idents
)
}
pub
fn
expand_expr
(
e
:
P
<
ast
::
Expr
>
,
fld
:
&
mut
MacroExpander
)
->
P
<
ast
::
Expr
>
{
fn
push_compiler_expansion
(
fld
:
&
mut
MacroExpander
,
span
:
Span
,
expansion_desc
:
&
str
)
{
fld
.cx
.bt_push
(
ExpnInfo
{
...
...
@@ -47,6 +57,7 @@ fn push_compiler_expansion(fld: &mut MacroExpander, span: Span, expansion_desc:
}
e
.and_then
(|
ast
::
Expr
{
id
,
node
,
span
}|
match
node
{
// expr_mac should really be expr_ext or something; it's the
// entry-point for all syntax extensions.
ast
::
ExprMac
(
mac
)
=>
{
...
...
@@ -71,6 +82,109 @@ fn push_compiler_expansion(fld: &mut MacroExpander, span: Span, expansion_desc:
})
}
// Desugar ExprBox: `in (PLACE) EXPR`
ast
::
ExprBox
(
Some
(
placer
),
value_expr
)
=>
{
// to:
//
// let p = PLACE;
// let mut place = Placer::make_place(p);
// let raw_place = InPlace::pointer(&mut place);
// let value = EXPR;
// unsafe {
// std::ptr::write(raw_place, value);
// InPlace::finalize(place)
// }
let
value_span
=
value_expr
.span
;
let
placer_span
=
placer
.span
;
let
placer_expr
=
fld
.fold_expr
(
placer
);
let
value_expr
=
fld
.fold_expr
(
value_expr
);
let
placer_ident
=
token
::
gensym_ident
(
"placer"
);
let
agent_ident
=
token
::
gensym_ident
(
"place"
);
let
value_ident
=
token
::
gensym_ident
(
"value"
);
let
p_ptr_ident
=
token
::
gensym_ident
(
"p_ptr"
);
let
placer
=
fld
.cx
.expr_ident
(
span
,
placer_ident
);
let
agent
=
fld
.cx
.expr_ident
(
span
,
agent_ident
);
let
value
=
fld
.cx
.expr_ident
(
span
,
value_ident
);
let
p_ptr
=
fld
.cx
.expr_ident
(
span
,
p_ptr_ident
);
let
make_place
=
[
"ops"
,
"Placer"
,
"make_place"
];
let
place_pointer
=
[
"ops"
,
"Place"
,
"pointer"
];
let
ptr_write
=
[
"ptr"
,
"write"
];
let
inplace_finalize
=
[
"ops"
,
"InPlace"
,
"finalize"
];
let
make_call
=
|
fld
:
&
mut
MacroExpander
,
p
,
args
|
{
let
path
=
mk_core_path
(
fld
,
placer_span
,
p
);
let
path
=
fld
.cx
.expr_path
(
path
);
fld
.cx
.expr_call
(
span
,
path
,
args
)
};
let
stmt_let
=
|
fld
:
&
mut
MacroExpander
,
bind
,
expr
|
{
fld
.cx
.stmt_let
(
placer_span
,
false
,
bind
,
expr
)
};
let
stmt_let_mut
=
|
fld
:
&
mut
MacroExpander
,
bind
,
expr
|
{
fld
.cx
.stmt_let
(
placer_span
,
true
,
bind
,
expr
)
};
// let placer = <placer_expr> ;
let
s1
=
stmt_let
(
fld
,
placer_ident
,
placer_expr
);
// let mut place = Placer::make_place(placer);
let
s2
=
{
let
call
=
make_call
(
fld
,
&
make_place
,
vec!
[
placer
]);
stmt_let_mut
(
fld
,
agent_ident
,
call
)
};
// let p_ptr = Place::pointer(&mut place);
let
s3
=
{
let
args
=
vec!
[
fld
.cx
.expr_mut_addr_of
(
placer_span
,
agent
.clone
())];
let
call
=
make_call
(
fld
,
&
place_pointer
,
args
);
stmt_let
(
fld
,
p_ptr_ident
,
call
)
};
// let value = <value_expr>;
let
s4
=
fld
.cx
.stmt_let
(
value_span
,
false
,
value_ident
,
value_expr
);
// unsafe { ptr::write(p_ptr, value); InPlace::finalize(place) }
let
expr
=
{
let
call_ptr_write
=
StmtSemi
(
make_call
(
fld
,
&
ptr_write
,
vec!
[
p_ptr
,
value
]),
ast
::
DUMMY_NODE_ID
);
let
call_ptr_write
=
codemap
::
respan
(
value_span
,
call_ptr_write
);
let
call
=
make_call
(
fld
,
&
inplace_finalize
,
vec!
[
agent
]);
Some
(
fld
.cx
.expr_block
(
P
(
ast
::
Block
{
stmts
:
vec!
[
P
(
call_ptr_write
)],
expr
:
Some
(
call
),
id
:
ast
::
DUMMY_NODE_ID
,
rules
:
ast
::
UnsafeBlock
(
ast
::
CompilerGenerated
),
span
:
span
,
})))
};
let
block
=
fld
.cx
.block_all
(
span
,
vec!
[
s1
,
s2
,
s3
,
s4
],
expr
);
fld
.cx
.expr_block
(
block
)
}
// Issue #22181:
// Eventually a desugaring for `box EXPR`
// (similar to the desugaring above for `in PLACE BLOCK`)
// should go here, desugaring
//
// to:
//
// let mut place = BoxPlace::make_place();
// let raw_place = Place::pointer(&mut place);
// let value = $value;
// unsafe {
// ::std::ptr::write(raw_place, value);
// Boxed::finalize(place)
// }
//
// But for now there are type-inference issues doing that.
ast
::
ExprWhile
(
cond
,
body
,
opt_ident
)
=>
{
let
cond
=
fld
.fold_expr
(
cond
);
let
(
body
,
opt_ident
)
=
expand_loop_block
(
body
,
opt_ident
,
fld
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录