Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
2a3084b5
R
Rust
项目概览
int
/
Rust
12 个月 前同步成功
通知
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,发现更多精彩内容 >>
提交
2a3084b5
编写于
7月 31, 2012
作者:
G
Graydon Hoare
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Start implementing structured constants.
上级
285fc535
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
196 addition
and
172 deletion
+196
-172
src/rustc/middle/check_const.rs
src/rustc/middle/check_const.rs
+2
-0
src/rustc/middle/trans/alt.rs
src/rustc/middle/trans/alt.rs
+3
-3
src/rustc/middle/trans/base.rs
src/rustc/middle/trans/base.rs
+2
-169
src/rustc/middle/trans/consts.rs
src/rustc/middle/trans/consts.rs
+175
-0
src/rustc/rustc.rc
src/rustc/rustc.rc
+1
-0
src/test/run-pass/const-rec-and-tup.rs
src/test/run-pass/const-rec-and-tup.rs
+13
-0
未找到文件。
src/rustc/middle/check_const.rs
浏览文件 @
2a3084b5
...
...
@@ -101,6 +101,8 @@ fn check_expr(sess: session, def_map: resolve3::DefMap,
}
}
}
expr_tup
(
*
)
|
expr_rec
(
*
)
{
}
_
{
sess
.span_err
(
e
.span
,
~
"constant contains unimplemented expression type"
);
...
...
src/rustc/middle/trans/alt.rs
浏览文件 @
2a3084b5
...
...
@@ -58,14 +58,14 @@ fn trans_opt(bcx: block, o: opt) -> opt_result {
}
_
{
ret
single_result
(
rslt
(
bcx
,
trans_
const_expr
(
ccx
,
l
)));
rslt
(
bcx
,
consts
::
const_expr
(
ccx
,
l
)));
}
}
}
var
(
disr_val
,
_
)
{
ret
single_result
(
rslt
(
bcx
,
C_int
(
ccx
,
disr_val
)));
}
range
(
l1
,
l2
)
{
ret
range_result
(
rslt
(
bcx
,
trans_
const_expr
(
ccx
,
l1
)),
rslt
(
bcx
,
trans_
const_expr
(
ccx
,
l2
)));
ret
range_result
(
rslt
(
bcx
,
consts
::
const_expr
(
ccx
,
l1
)),
rslt
(
bcx
,
consts
::
const_expr
(
ccx
,
l2
)));
}
}
}
...
...
src/rustc/middle/trans/base.rs
浏览文件 @
2a3084b5
...
...
@@ -1420,35 +1420,6 @@ fn store_temp_expr(cx: block, action: copy_action, dst: ValueRef,
ret
move_val
(
cx
,
action
,
dst
,
src
,
t
);
}
fn
trans_crate_lit
(
cx
:
@
crate_ctxt
,
e
:
@
ast
::
expr
,
lit
:
ast
::
lit
)
->
ValueRef
{
let
_
icx
=
cx
.insn_ctxt
(
~
"trans_crate_lit"
);
alt
lit
.node
{
ast
::
lit_int
(
i
,
t
)
{
C_integral
(
T_int_ty
(
cx
,
t
),
i
as
u64
,
True
)
}
ast
::
lit_uint
(
u
,
t
)
{
C_integral
(
T_uint_ty
(
cx
,
t
),
u
,
False
)
}
ast
::
lit_int_unsuffixed
(
i
)
{
let
lit_int_ty
=
ty
::
node_id_to_type
(
cx
.tcx
,
e
.id
);
alt
ty
::
get
(
lit_int_ty
)
.struct
{
ty
::
ty_int
(
t
)
{
C_integral
(
T_int_ty
(
cx
,
t
),
i
as
u64
,
True
)
}
ty
::
ty_uint
(
t
)
{
C_integral
(
T_uint_ty
(
cx
,
t
),
i
as
u64
,
False
)
}
_
{
cx
.sess
.span_bug
(
lit
.span
,
~
"integer literal doesn't have a type"
);
}
}
}
ast
::
lit_float
(
fs
,
t
)
{
C_floating
(
*
fs
,
T_float_ty
(
cx
,
t
))
}
ast
::
lit_bool
(
b
)
{
C_bool
(
b
)
}
ast
::
lit_nil
{
C_nil
()
}
ast
::
lit_str
(
s
)
{
cx
.sess
.span_unimpl
(
lit
.span
,
~
"unique string in this context"
);
}
}
}
fn
trans_lit
(
cx
:
block
,
e
:
@
ast
::
expr
,
lit
:
ast
::
lit
,
dest
:
dest
)
->
block
{
let
_
icx
=
cx
.insn_ctxt
(
~
"trans_lit"
);
if
dest
==
ignore
{
ret
cx
;
}
...
...
@@ -1456,12 +1427,11 @@ fn trans_lit(cx: block, e: @ast::expr, lit: ast::lit, dest: dest) -> block {
ast
::
lit_str
(
s
)
{
tvec
::
trans_estr
(
cx
,
s
,
ast
::
vstore_fixed
(
none
),
dest
)
}
_
{
store_in_dest
(
cx
,
trans_crate
_lit
(
cx
.ccx
(),
e
,
lit
),
dest
)
store_in_dest
(
cx
,
consts
::
const
_lit
(
cx
.ccx
(),
e
,
lit
),
dest
)
}
}
}
fn
trans_boxed_expr
(
bcx
:
block
,
contents
:
@
ast
::
expr
,
t
:
ty
::
t
,
heap
:
heap
,
dest
:
dest
)
->
block
{
...
...
@@ -1473,7 +1443,6 @@ fn trans_boxed_expr(bcx: block, contents: @ast::expr,
ret
store_in_dest
(
bcx
,
box
,
dest
);
}
fn
trans_unary
(
bcx
:
block
,
op
:
ast
::
unop
,
e
:
@
ast
::
expr
,
un_expr
:
@
ast
::
expr
,
dest
:
dest
)
->
block
{
let
_
icx
=
bcx
.insn_ctxt
(
~
"trans_unary"
);
...
...
@@ -4716,142 +4685,6 @@ fn trans_enum_variant(ccx: @crate_ctxt, enum_id: ast::node_id,
finish_fn
(
fcx
,
lltop
);
}
// FIXME (#2530): this should do some structural hash-consing to avoid
// duplicate constants. I think. Maybe LLVM has a magical mode that does so
// later on?
fn
trans_const_expr
(
cx
:
@
crate_ctxt
,
e
:
@
ast
::
expr
)
->
ValueRef
{
let
_
icx
=
cx
.insn_ctxt
(
~
"trans_const_expr"
);
alt
e
.node
{
ast
::
expr_lit
(
lit
)
{
trans_crate_lit
(
cx
,
e
,
*
lit
)
}
// If we have a vstore, just keep going; it has to be a string
ast
::
expr_vstore
(
e
,
_
)
{
trans_const_expr
(
cx
,
e
)
}
ast
::
expr_binary
(
b
,
e1
,
e2
)
{
let
te1
=
trans_const_expr
(
cx
,
e1
);
let
te2
=
trans_const_expr
(
cx
,
e2
);
let
te2
=
cast_shift_const_rhs
(
b
,
te1
,
te2
);
/* Neither type is bottom, and we expect them to be unified already,
* so the following is safe. */
let
ty
=
ty
::
expr_ty
(
cx
.tcx
,
e1
);
let
is_float
=
ty
::
type_is_fp
(
ty
);
let
signed
=
ty
::
type_is_signed
(
ty
);
ret
alt
b
{
ast
::
add
{
if
is_float
{
llvm
::
LLVMConstFAdd
(
te1
,
te2
)
}
else
{
llvm
::
LLVMConstAdd
(
te1
,
te2
)
}
}
ast
::
subtract
{
if
is_float
{
llvm
::
LLVMConstFSub
(
te1
,
te2
)
}
else
{
llvm
::
LLVMConstSub
(
te1
,
te2
)
}
}
ast
::
mul
{
if
is_float
{
llvm
::
LLVMConstFMul
(
te1
,
te2
)
}
else
{
llvm
::
LLVMConstMul
(
te1
,
te2
)
}
}
ast
::
div
{
if
is_float
{
llvm
::
LLVMConstFDiv
(
te1
,
te2
)
}
else
if
signed
{
llvm
::
LLVMConstSDiv
(
te1
,
te2
)
}
else
{
llvm
::
LLVMConstUDiv
(
te1
,
te2
)
}
}
ast
::
rem
{
if
is_float
{
llvm
::
LLVMConstFRem
(
te1
,
te2
)
}
else
if
signed
{
llvm
::
LLVMConstSRem
(
te1
,
te2
)
}
else
{
llvm
::
LLVMConstURem
(
te1
,
te2
)
}
}
ast
::
and
|
ast
::
or
{
cx
.sess
.span_unimpl
(
e
.span
,
~
"binop logic"
);
}
ast
::
bitxor
{
llvm
::
LLVMConstXor
(
te1
,
te2
)
}
ast
::
bitand
{
llvm
::
LLVMConstAnd
(
te1
,
te2
)
}
ast
::
bitor
{
llvm
::
LLVMConstOr
(
te1
,
te2
)
}
ast
::
shl
{
llvm
::
LLVMConstShl
(
te1
,
te2
)
}
ast
::
shr
{
if
signed
{
llvm
::
LLVMConstAShr
(
te1
,
te2
)
}
else
{
llvm
::
LLVMConstLShr
(
te1
,
te2
)
}
}
ast
::
eq
|
ast
::
lt
|
ast
::
le
|
ast
::
ne
|
ast
::
ge
|
ast
::
gt
{
cx
.sess
.span_unimpl
(
e
.span
,
~
"binop comparator"
);
}
}
}
ast
::
expr_unary
(
u
,
e
)
{
let
te
=
trans_const_expr
(
cx
,
e
);
let
ty
=
ty
::
expr_ty
(
cx
.tcx
,
e
);
let
is_float
=
ty
::
type_is_fp
(
ty
);
ret
alt
u
{
ast
::
box
(
_
)
|
ast
::
uniq
(
_
)
|
ast
::
deref
{
cx
.sess
.span_bug
(
e
.span
,
~
"bad unop type in trans_const_expr"
);
}
ast
::
not
{
llvm
::
LLVMConstNot
(
te
)
}
ast
::
neg
{
if
is_float
{
llvm
::
LLVMConstFNeg
(
te
)
}
else
{
llvm
::
LLVMConstNeg
(
te
)
}
}
}
}
ast
::
expr_cast
(
base
,
tp
)
{
let
ety
=
ty
::
expr_ty
(
cx
.tcx
,
e
),
llty
=
type_of
(
cx
,
ety
);
let
basety
=
ty
::
expr_ty
(
cx
.tcx
,
base
);
let
v
=
trans_const_expr
(
cx
,
base
);
alt
check
(
cast_type_kind
(
basety
),
cast_type_kind
(
ety
))
{
(
cast_integral
,
cast_integral
)
{
let
s
=
if
ty
::
type_is_signed
(
basety
)
{
True
}
else
{
False
};
llvm
::
LLVMConstIntCast
(
v
,
llty
,
s
)
}
(
cast_integral
,
cast_float
)
{
if
ty
::
type_is_signed
(
basety
)
{
llvm
::
LLVMConstSIToFP
(
v
,
llty
)
}
else
{
llvm
::
LLVMConstUIToFP
(
v
,
llty
)
}
}
(
cast_float
,
cast_float
)
{
llvm
::
LLVMConstFPCast
(
v
,
llty
)
}
(
cast_float
,
cast_integral
)
{
if
ty
::
type_is_signed
(
ety
)
{
llvm
::
LLVMConstFPToSI
(
v
,
llty
)
}
else
{
llvm
::
LLVMConstFPToUI
(
v
,
llty
)
}
}
}
}
ast
::
expr_path
(
path
)
{
alt
cx
.tcx.def_map
.find
(
e
.id
)
{
some
(
ast
::
def_const
(
def_id
))
{
// Don't know how to handle external consts
assert
ast_util
::
is_local
(
def_id
);
alt
cx
.tcx.items
.get
(
def_id
.node
)
{
ast_map
::
node_item
(
@
{
node
:
ast
::
item_const
(
_
,
subexpr
),
_
},
_
)
{
// FIXME (#2530): Instead of recursing here to regenerate
// the values for other constants, we should just look up
// the already-defined value.
trans_const_expr
(
cx
,
subexpr
)
}
_
{
cx
.sess
.span_bug
(
e
.span
,
~
"expected item"
);
}
}
}
_
{
cx
.sess
.span_bug
(
e
.span
,
~
"expected to find a const def"
)
}
}
}
_
{
cx
.sess
.span_bug
(
e
.span
,
~
"bad constant expression type in trans_const_expr"
);
}
}
}
fn
trans_const
(
ccx
:
@
crate_ctxt
,
e
:
@
ast
::
expr
,
id
:
ast
::
node_id
)
{
let
_
icx
=
ccx
.insn_ctxt
(
~
"trans_const"
);
let
v
=
trans_const_expr
(
ccx
,
e
);
// The scalars come back as 1st class LLVM vals
// which we have to stick into global constants.
let
g
=
get_item_val
(
ccx
,
id
);
llvm
::
LLVMSetInitializer
(
g
,
v
);
llvm
::
LLVMSetGlobalConstant
(
g
,
True
);
}
fn
trans_class_ctor
(
ccx
:
@
crate_ctxt
,
path
:
path
,
decl
:
ast
::
fn_decl
,
body
:
ast
::
blk
,
llctor_decl
:
ValueRef
,
psubsts
:
param_substs
,
ctor_id
:
ast
::
node_id
,
...
...
@@ -5008,7 +4841,7 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
}
}
}
ast
::
item_const
(
_
,
expr
)
{
trans_const
(
ccx
,
expr
,
item
.id
);
}
ast
::
item_const
(
_
,
expr
)
{
consts
::
trans_const
(
ccx
,
expr
,
item
.id
);
}
ast
::
item_foreign_mod
(
foreign_mod
)
{
let
abi
=
alt
attr
::
foreign_abi
(
item
.attrs
)
{
either
::
right
(
abi_
)
{
abi_
}
...
...
src/rustc/middle/trans/consts.rs
0 → 100644
浏览文件 @
2a3084b5
import
common
::
*
;
import
syntax
::{
ast
,
ast_util
,
codemap
,
ast_map
};
import
base
::
get_insn_ctxt
;
fn
const_lit
(
cx
:
@
crate_ctxt
,
e
:
@
ast
::
expr
,
lit
:
ast
::
lit
)
->
ValueRef
{
let
_
icx
=
cx
.insn_ctxt
(
~
"trans_lit"
);
alt
lit
.node
{
ast
::
lit_int
(
i
,
t
)
{
C_integral
(
T_int_ty
(
cx
,
t
),
i
as
u64
,
True
)
}
ast
::
lit_uint
(
u
,
t
)
{
C_integral
(
T_uint_ty
(
cx
,
t
),
u
,
False
)
}
ast
::
lit_int_unsuffixed
(
i
)
{
let
lit_int_ty
=
ty
::
node_id_to_type
(
cx
.tcx
,
e
.id
);
alt
ty
::
get
(
lit_int_ty
)
.struct
{
ty
::
ty_int
(
t
)
{
C_integral
(
T_int_ty
(
cx
,
t
),
i
as
u64
,
True
)
}
ty
::
ty_uint
(
t
)
{
C_integral
(
T_uint_ty
(
cx
,
t
),
i
as
u64
,
False
)
}
_
{
cx
.sess
.span_bug
(
lit
.span
,
~
"integer literal doesn't have a type"
);
}
}
}
ast
::
lit_float
(
fs
,
t
)
{
C_floating
(
*
fs
,
T_float_ty
(
cx
,
t
))
}
ast
::
lit_bool
(
b
)
{
C_bool
(
b
)
}
ast
::
lit_nil
{
C_nil
()
}
ast
::
lit_str
(
s
)
{
cx
.sess
.span_unimpl
(
lit
.span
,
~
"unique string in this context"
);
}
}
}
// FIXME (#2530): this should do some structural hash-consing to avoid
// duplicate constants. I think. Maybe LLVM has a magical mode that does so
// later on?
fn
const_expr
(
cx
:
@
crate_ctxt
,
e
:
@
ast
::
expr
)
->
ValueRef
{
let
_
icx
=
cx
.insn_ctxt
(
~
"const_expr"
);
alt
e
.node
{
ast
::
expr_lit
(
lit
)
{
consts
::
const_lit
(
cx
,
e
,
*
lit
)
}
// If we have a vstore, just keep going; it has to be a string
ast
::
expr_vstore
(
e
,
_
)
{
const_expr
(
cx
,
e
)
}
ast
::
expr_binary
(
b
,
e1
,
e2
)
{
let
te1
=
const_expr
(
cx
,
e1
);
let
te2
=
const_expr
(
cx
,
e2
);
let
te2
=
base
::
cast_shift_const_rhs
(
b
,
te1
,
te2
);
/* Neither type is bottom, and we expect them to be unified already,
* so the following is safe. */
let
ty
=
ty
::
expr_ty
(
cx
.tcx
,
e1
);
let
is_float
=
ty
::
type_is_fp
(
ty
);
let
signed
=
ty
::
type_is_signed
(
ty
);
ret
alt
b
{
ast
::
add
{
if
is_float
{
llvm
::
LLVMConstFAdd
(
te1
,
te2
)
}
else
{
llvm
::
LLVMConstAdd
(
te1
,
te2
)
}
}
ast
::
subtract
{
if
is_float
{
llvm
::
LLVMConstFSub
(
te1
,
te2
)
}
else
{
llvm
::
LLVMConstSub
(
te1
,
te2
)
}
}
ast
::
mul
{
if
is_float
{
llvm
::
LLVMConstFMul
(
te1
,
te2
)
}
else
{
llvm
::
LLVMConstMul
(
te1
,
te2
)
}
}
ast
::
div
{
if
is_float
{
llvm
::
LLVMConstFDiv
(
te1
,
te2
)
}
else
if
signed
{
llvm
::
LLVMConstSDiv
(
te1
,
te2
)
}
else
{
llvm
::
LLVMConstUDiv
(
te1
,
te2
)
}
}
ast
::
rem
{
if
is_float
{
llvm
::
LLVMConstFRem
(
te1
,
te2
)
}
else
if
signed
{
llvm
::
LLVMConstSRem
(
te1
,
te2
)
}
else
{
llvm
::
LLVMConstURem
(
te1
,
te2
)
}
}
ast
::
and
|
ast
::
or
{
cx
.sess
.span_unimpl
(
e
.span
,
~
"binop logic"
);
}
ast
::
bitxor
{
llvm
::
LLVMConstXor
(
te1
,
te2
)
}
ast
::
bitand
{
llvm
::
LLVMConstAnd
(
te1
,
te2
)
}
ast
::
bitor
{
llvm
::
LLVMConstOr
(
te1
,
te2
)
}
ast
::
shl
{
llvm
::
LLVMConstShl
(
te1
,
te2
)
}
ast
::
shr
{
if
signed
{
llvm
::
LLVMConstAShr
(
te1
,
te2
)
}
else
{
llvm
::
LLVMConstLShr
(
te1
,
te2
)
}
}
ast
::
eq
|
ast
::
lt
|
ast
::
le
|
ast
::
ne
|
ast
::
ge
|
ast
::
gt
{
cx
.sess
.span_unimpl
(
e
.span
,
~
"binop comparator"
);
}
}
}
ast
::
expr_unary
(
u
,
e
)
{
let
te
=
const_expr
(
cx
,
e
);
let
ty
=
ty
::
expr_ty
(
cx
.tcx
,
e
);
let
is_float
=
ty
::
type_is_fp
(
ty
);
ret
alt
u
{
ast
::
box
(
_
)
|
ast
::
uniq
(
_
)
|
ast
::
deref
{
cx
.sess
.span_bug
(
e
.span
,
~
"bad unop type in const_expr"
);
}
ast
::
not
{
llvm
::
LLVMConstNot
(
te
)
}
ast
::
neg
{
if
is_float
{
llvm
::
LLVMConstFNeg
(
te
)
}
else
{
llvm
::
LLVMConstNeg
(
te
)
}
}
}
}
ast
::
expr_cast
(
base
,
tp
)
{
let
ety
=
ty
::
expr_ty
(
cx
.tcx
,
e
),
llty
=
type_of
::
type_of
(
cx
,
ety
);
let
basety
=
ty
::
expr_ty
(
cx
.tcx
,
base
);
let
v
=
const_expr
(
cx
,
base
);
alt
check
(
base
::
cast_type_kind
(
basety
),
base
::
cast_type_kind
(
ety
))
{
(
base
::
cast_integral
,
base
::
cast_integral
)
{
let
s
=
if
ty
::
type_is_signed
(
basety
)
{
True
}
else
{
False
};
llvm
::
LLVMConstIntCast
(
v
,
llty
,
s
)
}
(
base
::
cast_integral
,
base
::
cast_float
)
{
if
ty
::
type_is_signed
(
basety
)
{
llvm
::
LLVMConstSIToFP
(
v
,
llty
)
}
else
{
llvm
::
LLVMConstUIToFP
(
v
,
llty
)
}
}
(
base
::
cast_float
,
base
::
cast_float
)
{
llvm
::
LLVMConstFPCast
(
v
,
llty
)
}
(
base
::
cast_float
,
base
::
cast_integral
)
{
if
ty
::
type_is_signed
(
ety
)
{
llvm
::
LLVMConstFPToSI
(
v
,
llty
)
}
else
{
llvm
::
LLVMConstFPToUI
(
v
,
llty
)
}
}
}
}
ast
::
expr_tup
(
es
)
{
C_struct
(
es
.map
(|
e
|
const_expr
(
cx
,
e
)))
}
ast
::
expr_rec
(
fs
,
none
)
{
C_struct
(
fs
.map
(|
f
|
const_expr
(
cx
,
f
.node.expr
)))
}
ast
::
expr_path
(
path
)
{
alt
cx
.tcx.def_map
.find
(
e
.id
)
{
some
(
ast
::
def_const
(
def_id
))
{
// Don't know how to handle external consts
assert
ast_util
::
is_local
(
def_id
);
alt
cx
.tcx.items
.get
(
def_id
.node
)
{
ast_map
::
node_item
(
@
{
node
:
ast
::
item_const
(
_
,
subexpr
),
_
},
_
)
{
// FIXME (#2530): Instead of recursing here to regenerate
// the values for other constants, we should just look up
// the already-defined value.
const_expr
(
cx
,
subexpr
)
}
_
{
cx
.sess
.span_bug
(
e
.span
,
~
"expected item"
);
}
}
}
_
{
cx
.sess
.span_bug
(
e
.span
,
~
"expected to find a const def"
)
}
}
}
_
{
cx
.sess
.span_bug
(
e
.span
,
~
"bad constant expression type in consts::const_expr"
);
}
}
}
fn
trans_const
(
ccx
:
@
crate_ctxt
,
e
:
@
ast
::
expr
,
id
:
ast
::
node_id
)
{
let
_
icx
=
ccx
.insn_ctxt
(
~
"trans_const"
);
let
v
=
const_expr
(
ccx
,
e
);
// The scalars come back as 1st class LLVM vals
// which we have to stick into global constants.
let
g
=
base
::
get_item_val
(
ccx
,
id
);
llvm
::
LLVMSetInitializer
(
g
,
v
);
llvm
::
LLVMSetGlobalConstant
(
g
,
True
);
}
src/rustc/rustc.rc
浏览文件 @
2a3084b5
...
...
@@ -40,6 +40,7 @@ import back_ = back;
mod
middle
{
mod
trans
{
mod
common
;
mod
consts
;
mod
type_of
;
mod
build
;
mod
base
;
...
...
src/test/run-pass/const-rec-and-tup.rs
0 → 100644
浏览文件 @
2a3084b5
const
x
:
(
int
,
int
)
=
(
0xfeedf00dd
,
0xca11ab1e
);
const
y
:
{
x
:
(
int
,
int
),
y
:
{
a
:
float
,
b
:
float
}
}
=
{
x
:
(
0xf0f0f0f0_f0f0f0f0
,
0xabababab_abababab
),
y
:
{
a
:
3.14159265358979323846
,
b
:
2.7182818284590452354
}
};
fn
main
()
{
let
(
p
,
_
)
=
y
.x
;
assert
p
==
0xf0f0f0f0_f0f0f0f0
;
io
::
println
(
fmt!
{
"0x%x"
,
p
as
uint
});
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录