Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
148718b4
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,发现更多精彩内容 >>
提交
148718b4
编写于
6月 23, 2017
作者:
E
Eduard-Mihai Burtescu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Implement const fn {size,align}_of.
上级
2e633406
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
195 addition
and
15 deletion
+195
-15
src/libcore/mem.rs
src/libcore/mem.rs
+43
-0
src/librustc/middle/const_val.rs
src/librustc/middle/const_val.rs
+3
-1
src/librustc_const_eval/eval.rs
src/librustc_const_eval/eval.rs
+23
-0
src/librustc_mir/transform/qualify_consts.rs
src/librustc_mir/transform/qualify_consts.rs
+20
-7
src/librustc_passes/consts.rs
src/librustc_passes/consts.rs
+4
-1
src/librustc_trans/mir/constant.rs
src/librustc_trans/mir/constant.rs
+24
-6
src/test/compile-fail/const-size_of-cycle.rs
src/test/compile-fail/const-size_of-cycle.rs
+18
-0
src/test/run-pass/const-size_of-align_of.rs
src/test/run-pass/const-size_of-align_of.rs
+60
-0
未找到文件。
src/libcore/mem.rs
浏览文件 @
148718b4
...
...
@@ -188,10 +188,30 @@ pub fn forget<T>(t: T) {
/// ```
#[inline]
#[stable(feature
=
"rust1"
,
since
=
"1.0.0"
)]
#[cfg(stage0)]
pub
fn
size_of
<
T
>
()
->
usize
{
unsafe
{
intrinsics
::
size_of
::
<
T
>
()
}
}
/// Returns the size of a type in bytes.
///
/// More specifically, this is the offset in bytes between successive
/// items of the same type, including alignment padding.
///
/// # Examples
///
/// ```
/// use std::mem;
///
/// assert_eq!(4, mem::size_of::<i32>());
/// ```
#[inline]
#[stable(feature
=
"rust1"
,
since
=
"1.0.0"
)]
#[cfg(not(stage0))]
pub
const
fn
size_of
<
T
>
()
->
usize
{
unsafe
{
intrinsics
::
size_of
::
<
T
>
()
}
}
/// Returns the size of the pointed-to value in bytes.
///
/// This is usually the same as `size_of::<T>()`. However, when `T` *has* no
...
...
@@ -279,10 +299,33 @@ pub fn min_align_of_val<T: ?Sized>(val: &T) -> usize {
/// ```
#[inline]
#[stable(feature
=
"rust1"
,
since
=
"1.0.0"
)]
#[cfg(stage0)]
pub
fn
align_of
<
T
>
()
->
usize
{
unsafe
{
intrinsics
::
min_align_of
::
<
T
>
()
}
}
/// Returns the [ABI]-required minimum alignment of a type.
///
/// Every reference to a value of the type `T` must be a multiple of this number.
///
/// This is the alignment used for struct fields. It may be smaller than the preferred alignment.
///
/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface
///
/// # Examples
///
/// ```
/// use std::mem;
///
/// assert_eq!(4, mem::align_of::<i32>());
/// ```
#[inline]
#[stable(feature
=
"rust1"
,
since
=
"1.0.0"
)]
#[cfg(not(stage0))]
pub
const
fn
align_of
<
T
>
()
->
usize
{
unsafe
{
intrinsics
::
min_align_of
::
<
T
>
()
}
}
/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to.
///
/// Every reference to a value of the type `T` must be a multiple of this number.
...
...
src/librustc/middle/const_val.rs
浏览文件 @
148718b4
...
...
@@ -14,7 +14,7 @@
use
hir
;
use
hir
::
def
::
Def
;
use
hir
::
def_id
::
DefId
;
use
ty
::
TyCtxt
;
use
ty
::
{
TyCtxt
,
layout
}
;
use
ty
::
subst
::
Substs
;
use
util
::
common
::
ErrorReported
;
use
rustc_const_math
::
*
;
...
...
@@ -101,6 +101,7 @@ pub enum ErrKind<'tcx> {
IndexOpFeatureGated
,
Math
(
ConstMathErr
),
LayoutError
(
layout
::
LayoutError
<
'tcx
>
),
ErroneousReferencedConstant
(
Box
<
ConstEvalErr
<
'tcx
>>
),
...
...
@@ -164,6 +165,7 @@ pub fn description(&self) -> ConstEvalErrDescription {
MiscCatchAll
=>
simple!
(
"unsupported constant expr"
),
IndexOpFeatureGated
=>
simple!
(
"the index operation on const values is unstable"
),
Math
(
ref
err
)
=>
Simple
(
err
.description
()
.into_cow
()),
LayoutError
(
ref
err
)
=>
Simple
(
err
.to_string
()
.into_cow
()),
ErroneousReferencedConstant
(
_
)
=>
simple!
(
"could not evaluate referenced constant"
),
...
...
src/librustc_const_eval/eval.rs
浏览文件 @
148718b4
...
...
@@ -25,6 +25,7 @@
use
rustc
::
util
::
common
::
ErrorReported
;
use
rustc
::
util
::
nodemap
::
DefIdMap
;
use
syntax
::
abi
::
Abi
;
use
syntax
::
ast
;
use
rustc
::
hir
::{
self
,
Expr
};
use
syntax_pos
::
Span
;
...
...
@@ -340,6 +341,28 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
_
=>
signal!
(
e
,
TypeckError
),
};
if
tcx
.fn_sig
(
def_id
)
.abi
()
==
Abi
::
RustIntrinsic
{
let
layout_of
=
|
ty
:
Ty
<
'tcx
>
|
{
ty
.layout
(
tcx
,
ty
::
ParamEnv
::
empty
(
traits
::
Reveal
::
All
))
.map_err
(|
err
|
{
ConstEvalErr
{
span
:
e
.span
,
kind
:
LayoutError
(
err
)
}
})
};
match
&
tcx
.item_name
(
def_id
)
.as_str
()[
..
]
{
"size_of"
=>
{
let
size
=
layout_of
(
substs
.type_at
(
0
))
?
.size
(
tcx
);
return
Ok
(
Integral
(
Usize
(
ConstUsize
::
new
(
size
.bytes
(),
tcx
.sess.target.uint_type
)
.unwrap
())));
}
"min_align_of"
=>
{
let
align
=
layout_of
(
substs
.type_at
(
0
))
?
.align
(
tcx
);
return
Ok
(
Integral
(
Usize
(
ConstUsize
::
new
(
align
.abi
(),
tcx
.sess.target.uint_type
)
.unwrap
())));
}
_
=>
signal!
(
e
,
TypeckError
)
}
}
let
body
=
if
let
Some
(
node_id
)
=
tcx
.hir
.as_local_node_id
(
def_id
)
{
if
let
Some
(
fn_like
)
=
FnLikeNode
::
from_node
(
tcx
.hir
.get
(
node_id
))
{
if
fn_like
.constness
()
==
hir
::
Constness
::
Const
{
...
...
src/librustc_mir/transform/qualify_consts.rs
浏览文件 @
148718b4
...
...
@@ -749,14 +749,27 @@ fn visit_terminator_kind(&mut self,
self
.visit_operand
(
func
,
location
);
let
fn_ty
=
func
.ty
(
self
.mir
,
self
.tcx
);
let
(
is_shuffle
,
is_const_fn
)
=
match
fn_ty
.sty
{
ty
::
TyFnDef
(
def_id
,
_
)
=>
{
(
self
.tcx
.fn_sig
(
def_id
)
.abi
()
==
Abi
::
PlatformIntrinsic
&&
self
.tcx
.item_name
(
def_id
)
.as_str
()
.starts_with
(
"simd_shuffle"
),
self
.tcx
.is_const_fn
(
def_id
))
let
(
mut
is_shuffle
,
mut
is_const_fn
)
=
(
false
,
false
);
if
let
ty
::
TyFnDef
(
def_id
,
_
)
=
fn_ty
.sty
{
match
self
.tcx
.fn_sig
(
def_id
)
.abi
()
{
Abi
::
RustIntrinsic
|
Abi
::
PlatformIntrinsic
=>
{
assert
!
(
!
self
.tcx
.is_const_fn
(
def_id
));
match
&
self
.tcx
.item_name
(
def_id
)
.as_str
()[
..
]
{
"size_of"
|
"min_align_of"
=>
is_const_fn
=
true
,
name
if
name
.starts_with
(
"simd_shuffle"
)
=>
{
is_shuffle
=
true
;
}
_
=>
{}
}
}
_
=>
{
is_const_fn
=
self
.tcx
.is_const_fn
(
def_id
);
}
}
_
=>
(
false
,
false
)
};
}
for
(
i
,
arg
)
in
args
.iter
()
.enumerate
()
{
self
.nest
(|
this
|
{
...
...
src/librustc_passes/consts.rs
浏览文件 @
148718b4
...
...
@@ -29,7 +29,7 @@
use
rustc
::
middle
::
const_val
::
ConstEvalErr
;
use
rustc
::
middle
::
const_val
::
ErrKind
::{
IndexOpFeatureGated
,
UnimplementedConstVal
,
MiscCatchAll
};
use
rustc
::
middle
::
const_val
::
ErrKind
::{
ErroneousReferencedConstant
,
MiscBinaryOp
,
NonConstPath
};
use
rustc
::
middle
::
const_val
::
ErrKind
::{
TypeckError
,
Math
};
use
rustc
::
middle
::
const_val
::
ErrKind
::{
TypeckError
,
Math
,
LayoutError
};
use
rustc_const_math
::{
ConstMathErr
,
Op
};
use
rustc
::
hir
::
def
::{
Def
,
CtorKind
};
use
rustc
::
hir
::
def_id
::
DefId
;
...
...
@@ -252,6 +252,9 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
Err
(
ConstEvalErr
{
kind
:
Math
(
ConstMathErr
::
Overflow
(
Op
::
Shl
)),
..
})
|
Err
(
ConstEvalErr
{
kind
:
IndexOpFeatureGated
,
..
})
=>
{}
Err
(
ConstEvalErr
{
kind
:
TypeckError
,
..
})
=>
{}
Err
(
ConstEvalErr
{
kind
:
LayoutError
(
ty
::
layout
::
LayoutError
::
Unknown
(
_
)),
..
})
=>
{}
Err
(
msg
)
=>
{
self
.tcx.sess
.add_lint
(
CONST_ERR
,
ex
.id
,
...
...
src/librustc_trans/mir/constant.rs
浏览文件 @
148718b4
...
...
@@ -22,7 +22,8 @@
use
rustc
::
ty
::
cast
::{
CastTy
,
IntTy
};
use
rustc
::
ty
::
subst
::{
Kind
,
Substs
,
Subst
};
use
rustc_data_structures
::
indexed_vec
::{
Idx
,
IndexVec
};
use
{
abi
,
adt
,
base
,
machine
};
use
{
adt
,
base
,
machine
};
use
abi
::{
self
,
Abi
};
use
callee
;
use
builder
::
Builder
;
use
common
::{
self
,
CrateContext
,
const_get_elt
,
val_ty
};
...
...
@@ -339,17 +340,34 @@ fn trans(&mut self) -> Result<Const<'tcx>, ConstEvalErr<'tcx>> {
func
,
fn_ty
)
};
let
mut
const_arg
s
=
IndexVec
::
with_capacity
(
args
.len
());
let
mut
arg_val
s
=
IndexVec
::
with_capacity
(
args
.len
());
for
arg
in
args
{
match
self
.const_operand
(
arg
,
span
)
{
Ok
(
arg
)
=>
{
const_arg
s
.push
(
arg
);
},
Ok
(
arg
)
=>
{
arg_val
s
.push
(
arg
);
},
Err
(
err
)
=>
if
failure
.is_ok
()
{
failure
=
Err
(
err
);
}
}
}
if
let
Some
((
ref
dest
,
target
))
=
*
destination
{
match
MirConstContext
::
trans_def
(
self
.ccx
,
def_id
,
substs
,
const_args
)
{
Ok
(
value
)
=>
self
.store
(
dest
,
value
,
span
),
Err
(
err
)
=>
if
failure
.is_ok
()
{
failure
=
Err
(
err
);
}
if
fn_ty
.fn_sig
(
tcx
)
.abi
()
==
Abi
::
RustIntrinsic
{
let
value
=
match
&
tcx
.item_name
(
def_id
)
.as_str
()[
..
]
{
"size_of"
=>
{
let
llval
=
C_uint
(
self
.ccx
,
self
.ccx
.size_of
(
substs
.type_at
(
0
)));
Const
::
new
(
llval
,
tcx
.types.usize
)
}
"min_align_of"
=>
{
let
llval
=
C_uint
(
self
.ccx
,
self
.ccx
.align_of
(
substs
.type_at
(
0
)));
Const
::
new
(
llval
,
tcx
.types.usize
)
}
_
=>
span_bug!
(
span
,
"{:?} in constant"
,
terminator
.kind
)
};
self
.store
(
dest
,
value
,
span
);
}
else
{
match
MirConstContext
::
trans_def
(
self
.ccx
,
def_id
,
substs
,
arg_vals
)
{
Ok
(
value
)
=>
self
.store
(
dest
,
value
,
span
),
Err
(
err
)
=>
if
failure
.is_ok
()
{
failure
=
Err
(
err
);
}
}
}
target
}
else
{
...
...
src/test/compile-fail/const-size_of-cycle.rs
0 → 100644
浏览文件 @
148718b4
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(const_fn)]
struct
Foo
{
bytes
:
[
u8
;
std
::
mem
::
size_of
::
<
Foo
>
()]
//~^ ERROR unsupported cyclic reference between types/traits detected
}
fn
main
()
{}
src/test/run-pass/const-size_of-align_of.rs
0 → 100644
浏览文件 @
148718b4
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(const_fn)]
use
std
::
mem
;
// Get around the limitations of CTFE in today's Rust.
const
fn
choice_u64
(
c
:
bool
,
a
:
u64
,
b
:
u64
)
->
u64
{
(
-
(
c
as
i64
)
as
u64
)
&
a
|
(
-
(
!
c
as
i64
)
as
u64
)
&
b
}
const
fn
max_usize
(
a
:
usize
,
b
:
usize
)
->
usize
{
choice_u64
(
a
>
b
,
a
as
u64
,
b
as
u64
)
as
usize
}
const
fn
align_to
(
size
:
usize
,
align
:
usize
)
->
usize
{
(
size
+
(
align
-
1
))
&
!
(
align
-
1
)
}
const
fn
packed_union_size_of
<
A
,
B
>
()
->
usize
{
max_usize
(
mem
::
size_of
::
<
A
>
(),
mem
::
size_of
::
<
B
>
())
}
const
fn
union_align_of
<
A
,
B
>
()
->
usize
{
max_usize
(
mem
::
align_of
::
<
A
>
(),
mem
::
align_of
::
<
B
>
())
}
const
fn
union_size_of
<
A
,
B
>
()
->
usize
{
align_to
(
packed_union_size_of
::
<
A
,
B
>
(),
union_align_of
::
<
A
,
B
>
())
}
macro_rules!
fake_union
{
(
$name:ident
{
$a:ty
,
$b:ty
})
=>
(
struct
$name
{
_
align
:
([
$a
;
0
],
[
$b
;
0
]),
_
bytes
:
[
u8
;
union_size_of
::
<
$a
,
$b
>
()]
}
)
}
// Check that we can (poorly) emulate unions by
// calling size_of and align_of at compile-time.
fake_union!
(
U
{
u16
,
[
u8
;
3
]
});
fn
test
(
u
:
U
)
{
assert_eq!
(
mem
::
size_of_val
(
&
u
._bytes
),
4
);
}
fn
main
()
{
assert_eq!
(
mem
::
size_of
::
<
U
>
(),
4
);
assert_eq!
(
mem
::
align_of
::
<
U
>
(),
2
);
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录