Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
50076b00
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,发现更多精彩内容 >>
提交
50076b00
编写于
8月 04, 2017
作者:
E
Eduard-Mihai Burtescu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
rustc: intern ConstVal's in TyCtxt.
上级
e6bce950
变更
31
隐藏空白更改
内联
并排
Showing
31 changed file
with
347 addition
and
240 deletion
+347
-240
src/librustc/hir/mod.rs
src/librustc/hir/mod.rs
+1
-1
src/librustc/ich/impls_ty.rs
src/librustc/ich/impls_ty.rs
+19
-19
src/librustc/middle/const_val.rs
src/librustc/middle/const_val.rs
+40
-14
src/librustc/mir/mod.rs
src/librustc/mir/mod.rs
+8
-7
src/librustc/mir/visit.rs
src/librustc/mir/visit.rs
+2
-2
src/librustc/ty/context.rs
src/librustc/ty/context.rs
+37
-1
src/librustc/ty/mod.rs
src/librustc/ty/mod.rs
+2
-2
src/librustc_const_eval/_match.rs
src/librustc_const_eval/_match.rs
+25
-22
src/librustc_const_eval/check_match.rs
src/librustc_const_eval/check_match.rs
+2
-2
src/librustc_const_eval/eval.rs
src/librustc_const_eval/eval.rs
+76
-66
src/librustc_const_eval/pattern.rs
src/librustc_const_eval/pattern.rs
+28
-31
src/librustc_lint/types.rs
src/librustc_lint/types.rs
+2
-2
src/librustc_metadata/decoder.rs
src/librustc_metadata/decoder.rs
+15
-0
src/librustc_mir/build/expr/as_rvalue.rs
src/librustc_mir/build/expr/as_rvalue.rs
+7
-3
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/build/matches/mod.rs
+3
-3
src/librustc_mir/build/matches/test.rs
src/librustc_mir/build/matches/test.rs
+19
-19
src/librustc_mir/build/misc.rs
src/librustc_mir/build/misc.rs
+11
-3
src/librustc_mir/build/mod.rs
src/librustc_mir/build/mod.rs
+1
-5
src/librustc_mir/hair/cx/block.rs
src/librustc_mir/hair/cx/block.rs
+1
-4
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/cx/expr.rs
+4
-9
src/librustc_mir/hair/cx/mod.rs
src/librustc_mir/hair/cx/mod.rs
+22
-6
src/librustc_mir/shim.rs
src/librustc_mir/shim.rs
+4
-4
src/librustc_mir/transform/elaborate_drops.rs
src/librustc_mir/transform/elaborate_drops.rs
+3
-1
src/librustc_mir/transform/generator.rs
src/librustc_mir/transform/generator.rs
+3
-3
src/librustc_mir/transform/simplify_branches.rs
src/librustc_mir/transform/simplify_branches.rs
+1
-1
src/librustc_mir/transform/type_check.rs
src/librustc_mir/transform/type_check.rs
+1
-1
src/librustc_mir/util/elaborate_drops.rs
src/librustc_mir/util/elaborate_drops.rs
+3
-1
src/librustc_passes/mir_stats.rs
src/librustc_passes/mir_stats.rs
+1
-1
src/librustc_trans/mir/analyze.rs
src/librustc_trans/mir/analyze.rs
+1
-1
src/librustc_trans/mir/constant.rs
src/librustc_trans/mir/constant.rs
+4
-5
src/librustc_typeck/collect.rs
src/librustc_typeck/collect.rs
+1
-1
未找到文件。
src/librustc/hir/mod.rs
浏览文件 @
50076b00
...
...
@@ -611,7 +611,7 @@ pub enum BindingAnnotation {
RefMut
,
}
#[derive(Clone,
PartialEq,
Eq,
RustcEncodable,
RustcDecodable,
Hash,
Debug)]
#[derive(C
opy,
C
lone,
PartialEq,
Eq,
RustcEncodable,
RustcDecodable,
Hash,
Debug)]
pub
enum
RangeEnd
{
Included
,
Excluded
,
...
...
src/librustc/ich/impls_ty.rs
浏览文件 @
50076b00
...
...
@@ -16,7 +16,6 @@
StableHasherResult
};
use
std
::
hash
as
std_hash
;
use
std
::
mem
;
use
syntax_pos
::
symbol
::
InternedString
;
use
middle
::
region
;
use
ty
;
...
...
@@ -272,52 +271,49 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
fn
hash_stable
<
W
:
StableHasherResult
>
(
&
self
,
hcx
:
&
mut
StableHashingContext
<
'a
,
'gcx
,
'tcx
>
,
hasher
:
&
mut
StableHasher
<
W
>
)
{
use
middle
::
const_val
::
ConstVal
;
use
middle
::
const_val
::
ConstVal
::
*
;
use
middle
::
const_val
::
ConstAggregate
::
*
;
mem
::
discriminant
(
self
)
.hash_stable
(
hcx
,
hasher
);
match
*
self
{
ConstVal
::
Float
(
ref
value
)
=>
{
Float
(
ref
value
)
=>
{
value
.hash_stable
(
hcx
,
hasher
);
}
ConstVal
::
Integral
(
ref
value
)
=>
{
Integral
(
ref
value
)
=>
{
value
.hash_stable
(
hcx
,
hasher
);
}
ConstVal
::
Str
(
ref
value
)
=>
{
Str
(
ref
value
)
=>
{
value
.hash_stable
(
hcx
,
hasher
);
}
ConstVal
::
ByteStr
(
ref
value
)
=>
{
ByteStr
(
ref
value
)
=>
{
value
.hash_stable
(
hcx
,
hasher
);
}
ConstVal
::
Bool
(
value
)
=>
{
Bool
(
value
)
=>
{
value
.hash_stable
(
hcx
,
hasher
);
}
C
onstVal
::
C
har
(
value
)
=>
{
Char
(
value
)
=>
{
value
.hash_stable
(
hcx
,
hasher
);
}
ConstVal
::
Variant
(
def_id
)
=>
{
Variant
(
def_id
)
=>
{
def_id
.hash_stable
(
hcx
,
hasher
);
}
ConstVal
::
Function
(
def_id
,
substs
)
=>
{
Function
(
def_id
,
substs
)
=>
{
def_id
.hash_stable
(
hcx
,
hasher
);
substs
.hash_stable
(
hcx
,
hasher
);
}
ConstVal
::
Struct
(
ref
name_value_map
)
=>
{
let
mut
values
:
Vec
<
(
InternedString
,
&
ConstVal
)
>
=
name_value_map
.iter
()
.map
(|(
name
,
val
)|
(
name
.as_str
(),
val
))
.collect
();
Aggregate
(
Struct
(
ref
name_values
))
=>
{
let
mut
values
=
name_values
.to_vec
();
values
.sort_unstable_by_key
(|
&
(
ref
name
,
_
)|
name
.clone
());
values
.hash_stable
(
hcx
,
hasher
);
}
ConstVal
::
Tuple
(
ref
value
)
=>
{
Aggregate
(
Tuple
(
ref
value
)
)
=>
{
value
.hash_stable
(
hcx
,
hasher
);
}
ConstVal
::
Array
(
ref
value
)
=>
{
Aggregate
(
Array
(
ref
value
)
)
=>
{
value
.hash_stable
(
hcx
,
hasher
);
}
ConstVal
::
Repeat
(
ref
value
,
times
)
=>
{
Aggregate
(
Repeat
(
ref
value
,
times
)
)
=>
{
value
.hash_stable
(
hcx
,
hasher
);
times
.hash_stable
(
hcx
,
hasher
);
}
...
...
@@ -325,6 +321,10 @@ fn hash_stable<W: StableHasherResult>(&self,
}
}
impl_stable_hash_for!
(
struct
::
middle
::
const_val
::
ByteArray
<
'tcx
>
{
data
});
impl_stable_hash_for!
(
struct
ty
::
ClosureSubsts
<
'tcx
>
{
substs
});
impl_stable_hash_for!
(
struct
ty
::
GeneratorInterior
<
'tcx
>
{
witness
});
...
...
src/librustc/middle/const_val.rs
浏览文件 @
50076b00
...
...
@@ -9,6 +9,7 @@
// except according to those terms.
use
self
::
ConstVal
::
*
;
use
self
::
ConstAggregate
::
*
;
pub
use
rustc_const_math
::
ConstInt
;
use
hir
;
...
...
@@ -22,30 +23,55 @@
use
graphviz
::
IntoCow
;
use
errors
::
DiagnosticBuilder
;
use
serialize
::{
self
,
Encodable
,
Encoder
,
Decodable
,
Decoder
};
use
syntax
::
symbol
::
InternedString
;
use
syntax
::
ast
;
use
syntax_pos
::
Span
;
use
std
::
borrow
::
Cow
;
use
std
::
collections
::
BTreeMap
;
use
std
::
rc
::
Rc
;
pub
type
EvalResult
<
'tcx
>
=
Result
<
ConstVal
<
'tcx
>
,
ConstEvalErr
<
'tcx
>>
;
pub
type
EvalResult
<
'tcx
>
=
Result
<
&
'tcx
ConstVal
<
'tcx
>
,
ConstEvalErr
<
'tcx
>>
;
#[derive(Clone,
Debug,
Hash,
RustcEncodable,
RustcDecodable,
Eq,
PartialEq)]
#[derive(C
opy,
C
lone,
Debug,
Hash,
RustcEncodable,
RustcDecodable,
Eq,
PartialEq)]
pub
enum
ConstVal
<
'tcx
>
{
Float
(
ConstFloat
),
Integral
(
ConstInt
),
Str
(
InternedString
),
ByteStr
(
Rc
<
Vec
<
u8
>
>
),
ByteStr
(
ByteArray
<
'tcx
>
),
Bool
(
bool
),
Char
(
char
),
Variant
(
DefId
),
Function
(
DefId
,
&
'tcx
Substs
<
'tcx
>
),
Struct
(
BTreeMap
<
ast
::
Name
,
ConstVal
<
'tcx
>>
),
Tuple
(
Vec
<
ConstVal
<
'tcx
>>
),
Array
(
Vec
<
ConstVal
<
'tcx
>>
),
Repeat
(
Box
<
ConstVal
<
'tcx
>>
,
u64
),
Aggregate
(
ConstAggregate
<
'tcx
>
),
}
impl
<
'tcx
>
serialize
::
UseSpecializedDecodable
for
&
'tcx
ConstVal
<
'tcx
>
{}
#[derive(Copy,
Clone,
Debug,
Hash,
RustcEncodable,
Eq,
PartialEq)]
pub
struct
ByteArray
<
'tcx
>
{
pub
data
:
&
'tcx
[
u8
],
}
impl
<
'tcx
>
serialize
::
UseSpecializedDecodable
for
ByteArray
<
'tcx
>
{}
#[derive(Copy,
Clone,
Debug,
Hash,
Eq,
PartialEq)]
pub
enum
ConstAggregate
<
'tcx
>
{
Struct
(
&
'tcx
[(
ast
::
Name
,
&
'tcx
ConstVal
<
'tcx
>
)]),
Tuple
(
&
'tcx
[
&
'tcx
ConstVal
<
'tcx
>
]),
Array
(
&
'tcx
[
&
'tcx
ConstVal
<
'tcx
>
]),
Repeat
(
&
'tcx
ConstVal
<
'tcx
>
,
u64
),
}
impl
<
'tcx
>
Encodable
for
ConstAggregate
<
'tcx
>
{
fn
encode
<
S
:
Encoder
>
(
&
self
,
_
:
&
mut
S
)
->
Result
<
(),
S
::
Error
>
{
bug!
(
"should never encode ConstAggregate::{:?}"
,
self
)
}
}
impl
<
'tcx
>
Decodable
for
ConstAggregate
<
'tcx
>
{
fn
decode
<
D
:
Decoder
>
(
_
:
&
mut
D
)
->
Result
<
Self
,
D
::
Error
>
{
bug!
(
"should never decode ConstAggregate"
)
}
}
impl
<
'tcx
>
ConstVal
<
'tcx
>
{
...
...
@@ -58,11 +84,11 @@ pub fn description(&self) -> &'static str {
Bool
(
_
)
=>
"boolean"
,
Char
(
..
)
=>
"char"
,
Variant
(
_
)
=>
"enum variant"
,
Struct
(
_
)
=>
"struct"
,
Tuple
(
_
)
=>
"tuple"
,
Aggregate
(
Struct
(
_
)
)
=>
"struct"
,
Aggregate
(
Tuple
(
_
)
)
=>
"tuple"
,
Function
(
..
)
=>
"function definition"
,
A
rray
(
..
)
=>
"array"
,
Repeat
(
..
)
=>
"repeat"
,
A
ggregate
(
Array
(
..
)
)
=>
"array"
,
Aggregate
(
Repeat
(
..
)
)
=>
"repeat"
,
}
}
...
...
@@ -233,7 +259,7 @@ pub fn eval_length(tcx: TyCtxt,
let
param_env
=
ty
::
ParamEnv
::
empty
(
Reveal
::
UserFacing
);
let
substs
=
Substs
::
identity_for_item
(
tcx
.global_tcx
(),
count_def_id
);
match
tcx
.at
(
count_expr
.span
)
.const_eval
(
param_env
.and
((
count_def_id
,
substs
)))
{
Ok
(
Integral
(
Usize
(
count
)))
=>
{
Ok
(
&
Integral
(
Usize
(
count
)))
=>
{
let
val
=
count
.as_u64
(
tcx
.sess.target.uint_type
);
assert_eq!
(
val
as
usize
as
u64
,
val
);
Ok
(
val
as
usize
)
...
...
src/librustc/mir/mod.rs
浏览文件 @
50076b00
...
...
@@ -1190,7 +1190,9 @@ pub fn function_handle<'a>(
Operand
::
Constant
(
box
Constant
{
span
,
ty
:
tcx
.type_of
(
def_id
)
.subst
(
tcx
,
substs
),
literal
:
Literal
::
Value
{
value
:
ConstVal
::
Function
(
def_id
,
substs
)
},
literal
:
Literal
::
Value
{
value
:
tcx
.mk_const
(
ConstVal
::
Function
(
def_id
,
substs
))
},
})
}
...
...
@@ -1478,7 +1480,7 @@ pub enum Literal<'tcx> {
substs
:
&
'tcx
Substs
<
'tcx
>
,
},
Value
{
value
:
ConstVal
<
'tcx
>
,
value
:
&
'tcx
ConstVal
<
'tcx
>
,
},
Promoted
{
// Index into the `promoted` vector of `Mir`.
...
...
@@ -1516,9 +1518,9 @@ fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ConstVal) -> fmt::Result {
match
*
const_val
{
Float
(
f
)
=>
write!
(
fmt
,
"{:?}"
,
f
),
Integral
(
n
)
=>
write!
(
fmt
,
"{}"
,
n
),
Str
(
ref
s
)
=>
write!
(
fmt
,
"{:?}"
,
s
),
ByteStr
(
ref
bytes
)
=>
{
let
escaped
:
String
=
bytes
Str
(
s
)
=>
write!
(
fmt
,
"{:?}"
,
s
),
ByteStr
(
bytes
)
=>
{
let
escaped
:
String
=
bytes
.data
.iter
()
.flat_map
(|
&
ch
|
ascii
::
escape_default
(
ch
)
.map
(|
c
|
c
as
char
))
.collect
();
...
...
@@ -1528,8 +1530,7 @@ fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ConstVal) -> fmt::Result {
Char
(
c
)
=>
write!
(
fmt
,
"{:?}"
,
c
),
Variant
(
def_id
)
|
Function
(
def_id
,
_
)
=>
write!
(
fmt
,
"{}"
,
item_path_str
(
def_id
)),
Struct
(
_
)
|
Tuple
(
_
)
|
Array
(
_
)
|
Repeat
(
..
)
=>
bug!
(
"ConstVal `{:?}` should not be in MIR"
,
const_val
),
Aggregate
(
_
)
=>
bug!
(
"`ConstVal::{:?}` should not be in MIR"
,
const_val
),
}
}
...
...
src/librustc/mir/visit.rs
浏览文件 @
50076b00
...
...
@@ -233,7 +233,7 @@ fn visit_generator_interior(&mut self,
}
fn
visit_const_val
(
&
mut
self
,
const_val
:
&
$
(
$mutability
)
*
ConstVal
,
const_val
:
&
$
(
$mutability
)
*
&
'tcx
ConstVal
<
'tcx
>
,
_
:
Location
)
{
self
.super_const_val
(
const_val
);
}
...
...
@@ -760,7 +760,7 @@ fn super_closure_substs(&mut self,
_
substs
:
&
$
(
$mutability
)
*
ClosureSubsts
<
'tcx
>
)
{
}
fn
super_const_val
(
&
mut
self
,
_
const_val
:
&
$
(
$mutability
)
*
ConstVal
)
{
fn
super_const_val
(
&
mut
self
,
_
const_val
:
&
$
(
$mutability
)
*
&
'tcx
ConstVal
<
'tcx
>
)
{
}
fn
super_const_int
(
&
mut
self
,
_
const_int
:
&
ConstInt
)
{
...
...
src/librustc/ty/context.rs
浏览文件 @
50076b00
...
...
@@ -21,6 +21,7 @@
use
hir
::
map
::
DefPathHash
;
use
lint
::{
self
,
Lint
};
use
ich
::{
self
,
StableHashingContext
,
NodeIdHashingMode
};
use
middle
::
const_val
::
ConstVal
;
use
middle
::
free_region
::
FreeRegionMap
;
use
middle
::
lang_items
;
use
middle
::
resolve_lifetime
::{
self
,
ObjectLifetimeDefault
};
...
...
@@ -108,6 +109,7 @@ pub struct CtxtInterners<'tcx> {
region
:
RefCell
<
FxHashSet
<
Interned
<
'tcx
,
RegionKind
>>>
,
existential_predicates
:
RefCell
<
FxHashSet
<
Interned
<
'tcx
,
Slice
<
ExistentialPredicate
<
'tcx
>>>>>
,
predicates
:
RefCell
<
FxHashSet
<
Interned
<
'tcx
,
Slice
<
Predicate
<
'tcx
>>>>>
,
const_
:
RefCell
<
FxHashSet
<
Interned
<
'tcx
,
ConstVal
<
'tcx
>>>>
,
}
impl
<
'gcx
:
'tcx
,
'tcx
>
CtxtInterners
<
'tcx
>
{
...
...
@@ -120,6 +122,7 @@ fn new(arena: &'tcx DroplessArena) -> CtxtInterners<'tcx> {
region
:
RefCell
::
new
(
FxHashSet
()),
existential_predicates
:
RefCell
::
new
(
FxHashSet
()),
predicates
:
RefCell
::
new
(
FxHashSet
()),
const_
:
RefCell
::
new
(
FxHashSet
()),
}
}
...
...
@@ -934,6 +937,32 @@ pub fn alloc_adt_def(self,
self
.global_arenas.adt_def
.alloc
(
def
)
}
pub
fn
alloc_byte_array
(
self
,
bytes
:
&
[
u8
])
->
&
'gcx
[
u8
]
{
if
bytes
.is_empty
()
{
&
[]
}
else
{
self
.global_interners.arena
.alloc_slice
(
bytes
)
}
}
pub
fn
alloc_constval_slice
(
self
,
values
:
&
[
&
'tcx
ConstVal
<
'gcx
>
])
->
&
'gcx
[
&
'tcx
ConstVal
<
'gcx
>
]
{
if
values
.is_empty
()
{
&
[]
}
else
{
self
.global_interners.arena
.alloc_slice
(
values
)
}
}
pub
fn
alloc_name_constval_slice
(
self
,
values
:
&
[(
ast
::
Name
,
&
'tcx
ConstVal
<
'gcx
>
)])
->
&
'gcx
[(
ast
::
Name
,
&
'tcx
ConstVal
<
'gcx
>
)]
{
if
values
.is_empty
()
{
&
[]
}
else
{
self
.global_interners.arena
.alloc_slice
(
values
)
}
}
pub
fn
intern_stability
(
self
,
stab
:
attr
::
Stability
)
->
&
'gcx
attr
::
Stability
{
if
let
Some
(
st
)
=
self
.stability_interner
.borrow
()
.get
(
&
stab
)
{
return
st
;
...
...
@@ -1507,6 +1536,12 @@ fn borrow<'a>(&'a self) -> &'a [Predicate<'lcx>] {
}
}
impl
<
'tcx
:
'lcx
,
'lcx
>
Borrow
<
ConstVal
<
'lcx
>>
for
Interned
<
'tcx
,
ConstVal
<
'tcx
>>
{
fn
borrow
<
'a
>
(
&
'a
self
)
->
&
'a
ConstVal
<
'lcx
>
{
&
self
.0
}
}
macro_rules!
intern_method
{
(
$lt_tcx:tt
,
$name:ident
:
$method:ident
(
$alloc:ty
,
$alloc_method:ident
,
...
...
@@ -1587,7 +1622,8 @@ pub fn keep_local<'tcx, T: ty::TypeFoldable<'tcx>>(x: &T) -> bool {
&
ty
::
ReVar
(
_
)
|
&
ty
::
ReSkolemized
(
..
)
=>
true
,
_
=>
false
}
})
->
RegionKind
})
->
RegionKind
,
const_
:
mk_const
(
/*|c: &Const| keep_local(&c.ty)*/
|
_
|
false
)
->
ConstVal
<
'tcx
>
);
macro_rules!
slice_interners
{
...
...
src/librustc/ty/mod.rs
浏览文件 @
50076b00
...
...
@@ -1601,7 +1601,7 @@ pub fn discriminants(&'a self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
if
let
VariantDiscr
::
Explicit
(
expr_did
)
=
v
.discr
{
let
substs
=
Substs
::
identity_for_item
(
tcx
.global_tcx
(),
expr_did
);
match
tcx
.const_eval
(
param_env
.and
((
expr_did
,
substs
)))
{
Ok
(
ConstVal
::
Integral
(
v
))
=>
{
Ok
(
&
ConstVal
::
Integral
(
v
))
=>
{
discr
=
v
;
}
err
=>
{
...
...
@@ -1641,7 +1641,7 @@ pub fn discriminant_for_variant(&self,
ty
::
VariantDiscr
::
Explicit
(
expr_did
)
=>
{
let
substs
=
Substs
::
identity_for_item
(
tcx
.global_tcx
(),
expr_did
);
match
tcx
.const_eval
(
param_env
.and
((
expr_did
,
substs
)))
{
Ok
(
ConstVal
::
Integral
(
v
))
=>
{
Ok
(
&
ConstVal
::
Integral
(
v
))
=>
{
explicit_value
=
v
;
break
;
}
...
...
src/librustc_const_eval/_match.rs
浏览文件 @
50076b00
...
...
@@ -182,13 +182,13 @@ fn lower_byte_str_pattern<'p>(&mut self, pat: &'p Pattern<'tcx>) -> Vec<&'p Patt
self
.byte_array_map
.entry
(
pat
)
.or_insert_with
(||
{
match
pat
.kind
{
box
PatternKind
::
Constant
{
value
:
ConstVal
::
ByteStr
(
ref
data
)
value
:
&
ConstVal
::
ByteStr
(
b
)
}
=>
{
data
.iter
()
.map
(|
c
|
&*
pattern_arena
.alloc
(
Pattern
{
b
.data
.iter
()
.map
(|
&
b
|
&*
pattern_arena
.alloc
(
Pattern
{
ty
:
tcx
.types.u8
,
span
:
pat
.span
,
kind
:
box
PatternKind
::
Constant
{
value
:
ConstVal
::
Integral
(
ConstInt
::
U8
(
*
c
))
value
:
tcx
.mk_const
(
ConstVal
::
Integral
(
ConstInt
::
U8
(
b
)
))
}
}))
.collect
()
}
...
...
@@ -228,9 +228,9 @@ pub enum Constructor<'tcx> {
/// Enum variants.
Variant
(
DefId
),
/// Literal values.
ConstantValue
(
ConstVal
<
'tcx
>
),
ConstantValue
(
&
'tcx
ConstVal
<
'tcx
>
),
/// Ranges of literal values (`2...5` and `2..5`).
ConstantRange
(
ConstVal
<
'tcx
>
,
ConstVal
<
'tcx
>
,
RangeEnd
),
ConstantRange
(
&
'tcx
ConstVal
<
'tcx
>
,
&
'tcx
ConstVal
<
'tcx
>
,
RangeEnd
),
/// Array patterns of length n.
Slice
(
usize
),
}
...
...
@@ -370,7 +370,7 @@ fn apply_constructor<'a>(
_
=>
{
match
*
ctor
{
ConstantValue
(
ref
v
)
=>
PatternKind
::
Constant
{
value
:
v
.clone
()
},
ConstantValue
(
value
)
=>
PatternKind
::
Constant
{
value
},
_
=>
PatternKind
::
Wild
,
}
}
...
...
@@ -404,8 +404,11 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
{
debug!
(
"all_constructors({:?})"
,
pcx
.ty
);
match
pcx
.ty.sty
{
ty
::
TyBool
=>
[
true
,
false
]
.iter
()
.map
(|
b
|
ConstantValue
(
ConstVal
::
Bool
(
*
b
)))
.collect
(),
ty
::
TyBool
=>
{
[
true
,
false
]
.iter
()
.map
(|
&
b
|
{
ConstantValue
(
cx
.tcx
.mk_const
(
ConstVal
::
Bool
(
b
)))
})
.collect
()
}
ty
::
TySlice
(
ref
sub_ty
)
=>
{
if
cx
.is_uninhabited
(
sub_ty
)
{
vec!
[
Slice
(
0
)]
...
...
@@ -511,8 +514,8 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>(
for
row
in
patterns
{
match
*
row
.kind
{
PatternKind
::
Constant
{
value
:
ConstVal
::
ByteStr
(
ref
data
)
}
=>
{
max_fixed_len
=
cmp
::
max
(
max_fixed_len
,
data
.len
());
PatternKind
::
Constant
{
value
:
&
ConstVal
::
ByteStr
(
b
)
}
=>
{
max_fixed_len
=
cmp
::
max
(
max_fixed_len
,
b
.
data
.len
());
}
PatternKind
::
Slice
{
ref
prefix
,
slice
:
None
,
ref
suffix
}
=>
{
let
fixed_len
=
prefix
.len
()
+
suffix
.len
();
...
...
@@ -715,10 +718,10 @@ fn pat_constructors<'tcx>(_cx: &mut MatchCheckCtxt,
Some
(
vec!
[
Single
]),
PatternKind
::
Variant
{
adt_def
,
variant_index
,
..
}
=>
Some
(
vec!
[
Variant
(
adt_def
.variants
[
variant_index
]
.did
)]),
PatternKind
::
Constant
{
ref
value
}
=>
Some
(
vec!
[
ConstantValue
(
value
.clone
()
)]),
PatternKind
::
Range
{
ref
lo
,
ref
hi
,
ref
end
}
=>
Some
(
vec!
[
ConstantRange
(
lo
.clone
(),
hi
.clone
(),
end
.clone
()
)]),
PatternKind
::
Constant
{
value
}
=>
Some
(
vec!
[
ConstantValue
(
value
)]),
PatternKind
::
Range
{
lo
,
hi
,
end
}
=>
Some
(
vec!
[
ConstantRange
(
lo
,
hi
,
end
)]),
PatternKind
::
Array
{
..
}
=>
match
pcx
.ty.sty
{
ty
::
TyArray
(
_
,
length
)
=>
Some
(
vec!
[
Slice
(
length
)]),
_
=>
span_bug!
(
pat
.span
,
"bad ty {:?} for array pattern"
,
pcx
.ty
)
...
...
@@ -806,7 +809,7 @@ fn slice_pat_covered_by_constructor(_tcx: TyCtxt, _span: Span,
suffix
:
&
[
Pattern
])
->
Result
<
bool
,
ErrorReported
>
{
let
data
=
match
*
ctor
{
ConstantValue
(
ConstVal
::
ByteStr
(
ref
data
))
=>
data
,
ConstantValue
(
&
ConstVal
::
ByteStr
(
b
))
=>
b
.
data
,
_
=>
bug!
()
};
...
...
@@ -820,7 +823,7 @@ fn slice_pat_covered_by_constructor(_tcx: TyCtxt, _span: Span,
data
[
data
.len
()
-
suffix
.len
()
..
]
.iter
()
.zip
(
suffix
))
{
match
pat
.kind
{
box
PatternKind
::
Constant
{
ref
value
}
=>
match
*
value
{
box
PatternKind
::
Constant
{
value
}
=>
match
*
value
{
ConstVal
::
Integral
(
ConstInt
::
U8
(
u
))
=>
{
if
u
!=
*
ch
{
return
Ok
(
false
);
...
...
@@ -843,19 +846,19 @@ fn constructor_covered_by_range(tcx: TyCtxt, span: Span,
let
cmp_from
=
|
c_from
|
Ok
(
compare_const_vals
(
tcx
,
span
,
c_from
,
from
)
?
!=
Ordering
::
Less
);
let
cmp_to
=
|
c_to
|
compare_const_vals
(
tcx
,
span
,
c_to
,
to
);
match
*
ctor
{
ConstantValue
(
ref
value
)
=>
{
ConstantValue
(
value
)
=>
{
let
to
=
cmp_to
(
value
)
?
;
let
end
=
(
to
==
Ordering
::
Less
)
||
(
end
==
RangeEnd
::
Included
&&
to
==
Ordering
::
Equal
);
Ok
(
cmp_from
(
value
)
?
&&
end
)
},
ConstantRange
(
ref
from
,
ref
to
,
RangeEnd
::
Included
)
=>
{
ConstantRange
(
from
,
to
,
RangeEnd
::
Included
)
=>
{
let
to
=
cmp_to
(
to
)
?
;
let
end
=
(
to
==
Ordering
::
Less
)
||
(
end
==
RangeEnd
::
Included
&&
to
==
Ordering
::
Equal
);
Ok
(
cmp_from
(
from
)
?
&&
end
)
},
ConstantRange
(
ref
from
,
ref
to
,
RangeEnd
::
Excluded
)
=>
{
ConstantRange
(
from
,
to
,
RangeEnd
::
Excluded
)
=>
{
let
to
=
cmp_to
(
to
)
?
;
let
end
=
(
to
==
Ordering
::
Less
)
||
(
end
==
RangeEnd
::
Excluded
&&
to
==
Ordering
::
Equal
);
...
...
@@ -919,11 +922,11 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
Some
(
vec!
[
subpattern
])
}
PatternKind
::
Constant
{
ref
value
}
=>
{
PatternKind
::
Constant
{
value
}
=>
{
match
*
constructor
{
Slice
(
..
)
=>
match
*
value
{
ConstVal
::
ByteStr
(
ref
data
)
=>
{
if
wild_patterns
.len
()
==
data
.len
()
{
ConstVal
::
ByteStr
(
b
)
=>
{
if
wild_patterns
.len
()
==
b
.
data
.len
()
{
Some
(
cx
.lower_byte_str_pattern
(
pat
))
}
else
{
None
...
...
src/librustc_const_eval/check_match.rs
浏览文件 @
50076b00
...
...
@@ -140,7 +140,7 @@ fn check_patterns(&self, has_guard: bool, pats: &[P<Pat>]) {
fn
check_match
(
&
self
,
scrut
:
&
hir
::
Expr
,
arms
:
&
[
hir
::
Arm
],
arms
:
&
'tcx
[
hir
::
Arm
],
source
:
hir
::
MatchSource
)
{
for
arm
in
arms
{
...
...
@@ -231,7 +231,7 @@ fn conservative_is_uninhabited(&self, scrutinee_ty: Ty<'tcx>) -> bool {
}
}
fn
check_irrefutable
(
&
self
,
pat
:
&
Pat
,
origin
:
&
str
)
{
fn
check_irrefutable
(
&
self
,
pat
:
&
'tcx
Pat
,
origin
:
&
str
)
{
let
module
=
self
.tcx.hir
.get_module_parent
(
pat
.id
);
MatchCheckCtxt
::
create_and_enter
(
self
.tcx
,
module
,
|
ref
mut
cx
|
{
let
mut
patcx
=
PatternContext
::
new
(
self
.tcx
,
...
...
src/librustc_const_eval/eval.rs
浏览文件 @
50076b00
...
...
@@ -9,8 +9,9 @@
// except according to those terms.
use
rustc
::
middle
::
const_val
::
ConstVal
::
*
;
use
rustc
::
middle
::
const_val
::
ConstAggregate
::
*
;
use
rustc
::
middle
::
const_val
::
ErrKind
::
*
;
use
rustc
::
middle
::
const_val
::{
ConstVal
,
ConstEvalErr
,
EvalResult
,
ErrKind
};
use
rustc
::
middle
::
const_val
::{
ByteArray
,
ConstVal
,
ConstEvalErr
,
EvalResult
,
ErrKind
};
use
rustc
::
hir
::
map
as
hir_map
;
use
rustc
::
hir
::
map
::
blocks
::
FnLikeNode
;
...
...
@@ -88,7 +89,7 @@ pub struct ConstContext<'a, 'tcx: 'a> {
tables
:
&
'a
ty
::
TypeckTables
<
'tcx
>
,
param_env
:
ty
::
ParamEnv
<
'tcx
>
,
substs
:
&
'tcx
Substs
<
'tcx
>
,
fn_args
:
Option
<
NodeMap
<
ConstVal
<
'tcx
>>>
fn_args
:
Option
<
NodeMap
<
&
'tcx
ConstVal
<
'tcx
>>>
}
impl
<
'a
,
'tcx
>
ConstContext
<
'a
,
'tcx
>
{
...
...
@@ -107,7 +108,7 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
/// Evaluate a constant expression in a context where the expression isn't
/// guaranteed to be evaluable.
pub
fn
eval
(
&
self
,
e
:
&
Expr
)
->
EvalResult
<
'tcx
>
{
pub
fn
eval
(
&
self
,
e
:
&
'tcx
Expr
)
->
EvalResult
<
'tcx
>
{
if
self
.tables.tainted_by_errors
{
signal!
(
e
,
TypeckError
);
}
...
...
@@ -118,7 +119,7 @@ pub fn eval(&self, e: &Expr) -> EvalResult<'tcx> {
type
CastResult
<
'tcx
>
=
Result
<
ConstVal
<
'tcx
>
,
ErrKind
<
'tcx
>>
;
fn
eval_const_expr_partial
<
'a
,
'tcx
>
(
cx
:
&
ConstContext
<
'a
,
'tcx
>
,
e
:
&
Expr
)
->
EvalResult
<
'tcx
>
{
e
:
&
'tcx
Expr
)
->
EvalResult
<
'tcx
>
{
let
tcx
=
cx
.tcx
;
let
ety
=
cx
.tables
.expr_ty
(
e
)
.subst
(
tcx
,
cx
.substs
);
...
...
@@ -133,57 +134,66 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
const
I32_OVERFLOW
:
u128
=
i32
::
min_value
()
as
u32
as
u128
;
const
I64_OVERFLOW
:
u128
=
i64
::
min_value
()
as
u64
as
u128
;
const
I128_OVERFLOW
:
u128
=
i128
::
min_value
()
as
u128
;
match
(
&
lit
.node
,
&
ety
.sty
)
{
let
negated
=
match
(
&
lit
.node
,
&
ety
.sty
)
{
(
&
LitKind
::
Int
(
I8_OVERFLOW
,
_
),
&
ty
::
TyInt
(
IntTy
::
I8
))
|
(
&
LitKind
::
Int
(
I8_OVERFLOW
,
Signed
(
IntTy
::
I8
)),
_
)
=>
{
return
Ok
(
Integral
(
I8
(
i8
::
min_value
()
)))
Some
(
I8
(
i8
::
min_value
(
)))
},
(
&
LitKind
::
Int
(
I16_OVERFLOW
,
_
),
&
ty
::
TyInt
(
IntTy
::
I16
))
|
(
&
LitKind
::
Int
(
I16_OVERFLOW
,
Signed
(
IntTy
::
I16
)),
_
)
=>
{
return
Ok
(
Integral
(
I16
(
i16
::
min_value
()
)))
Some
(
I16
(
i16
::
min_value
(
)))
},
(
&
LitKind
::
Int
(
I32_OVERFLOW
,
_
),
&
ty
::
TyInt
(
IntTy
::
I32
))
|
(
&
LitKind
::
Int
(
I32_OVERFLOW
,
Signed
(
IntTy
::
I32
)),
_
)
=>
{
return
Ok
(
Integral
(
I32
(
i32
::
min_value
()
)))
Some
(
I32
(
i32
::
min_value
(
)))
},
(
&
LitKind
::
Int
(
I64_OVERFLOW
,
_
),
&
ty
::
TyInt
(
IntTy
::
I64
))
|
(
&
LitKind
::
Int
(
I64_OVERFLOW
,
Signed
(
IntTy
::
I64
)),
_
)
=>
{
return
Ok
(
Integral
(
I64
(
i64
::
min_value
()
)))
Some
(
I64
(
i64
::
min_value
(
)))
},
(
&
LitKind
::
Int
(
I128_OVERFLOW
,
_
),
&
ty
::
TyInt
(
IntTy
::
I128
))
|
(
&
LitKind
::
Int
(
I128_OVERFLOW
,
Signed
(
IntTy
::
I128
)),
_
)
=>
{
return
Ok
(
Integral
(
I128
(
i128
::
min_value
()
)))
Some
(
I128
(
i128
::
min_value
(
)))
},
(
&
LitKind
::
Int
(
n
,
_
),
&
ty
::
TyInt
(
IntTy
::
Is
))
|
(
&
LitKind
::
Int
(
n
,
Signed
(
IntTy
::
Is
)),
_
)
=>
{
match
tcx
.sess.target.int_type
{
IntTy
::
I16
=>
if
n
==
I16_OVERFLOW
{
return
Ok
(
Integral
(
Isize
(
Is16
(
i16
::
min_value
()))));
Some
(
Isize
(
Is16
(
i16
::
min_value
())))
}
else
{
None
},
IntTy
::
I32
=>
if
n
==
I32_OVERFLOW
{
return
Ok
(
Integral
(
Isize
(
Is32
(
i32
::
min_value
()))));
Some
(
Isize
(
Is32
(
i32
::
min_value
())))
}
else
{
None
},
IntTy
::
I64
=>
if
n
==
I64_OVERFLOW
{
return
Ok
(
Integral
(
Isize
(
Is64
(
i64
::
min_value
()))));
Some
(
Isize
(
Is64
(
i64
::
min_value
())))
}
else
{
None
},
_
=>
span_bug!
(
e
.span
,
"typeck error"
)
}
},
_
=>
{},
_
=>
None
};
if
let
Some
(
i
)
=
negated
{
return
Ok
(
tcx
.mk_const
(
Integral
(
i
)));
}
}
match
cx
.eval
(
inner
)
?
{
tcx
.mk_const
(
match
*
cx
.eval
(
inner
)
?
{
Float
(
f
)
=>
Float
(
-
f
),
Integral
(
i
)
=>
Integral
(
math!
(
e
,
-
i
)),
const_val
=>
signal!
(
e
,
NegateOn
(
const_val
)),
}
}
)
}
hir
::
ExprUnary
(
hir
::
UnNot
,
ref
inner
)
=>
{
match
cx
.eval
(
inner
)
?
{
tcx
.mk_const
(
match
*
cx
.eval
(
inner
)
?
{
Integral
(
i
)
=>
Integral
(
math!
(
e
,
!
i
)),
Bool
(
b
)
=>
Bool
(
!
b
),
const_val
=>
signal!
(
e
,
NotOn
(
const_val
)),
}
}
)
}
hir
::
ExprUnary
(
hir
::
UnDeref
,
_
)
=>
signal!
(
e
,
UnimplementedConstVal
(
"deref operation"
)),
hir
::
ExprBinary
(
op
,
ref
a
,
ref
b
)
=>
{
...
...
@@ -191,7 +201,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
// gives us a type through a type-suffix, cast or const def type
// we need to re-eval the other value of the BinOp if it was
// not inferred
match
(
cx
.eval
(
a
)
?
,
cx
.eval
(
b
)
?
)
{
tcx
.mk_const
(
match
(
*
cx
.eval
(
a
)
?
,
*
cx
.eval
(
b
)
?
)
{
(
Float
(
a
),
Float
(
b
))
=>
{
use
std
::
cmp
::
Ordering
::
*
;
match
op
.node
{
...
...
@@ -260,7 +270,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
}
_
=>
signal!
(
e
,
MiscBinaryOp
),
}
}
)
}
hir
::
ExprCast
(
ref
base
,
_
)
=>
{
let
base_val
=
cx
.eval
(
base
)
?
;
...
...
@@ -268,8 +278,8 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
if
ety
==
base_ty
{
base_val
}
else
{
match
cast_const
(
tcx
,
base_val
,
ety
)
{
Ok
(
val
)
=>
val
,
match
cast_const
(
tcx
,
*
base_val
,
ety
)
{
Ok
(
val
)
=>
tcx
.mk_const
(
val
)
,
Err
(
kind
)
=>
signal!
(
e
,
kind
),
}
}
...
...
@@ -291,32 +301,32 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
}
},
Def
::
VariantCtor
(
variant_def
,
CtorKind
::
Const
)
=>
{
Variant
(
variant_def
)
tcx
.mk_const
(
Variant
(
variant_def
)
)
}
Def
::
VariantCtor
(
_
,
CtorKind
::
Fn
)
=>
{
signal!
(
e
,
UnimplementedConstVal
(
"enum variants"
));
}
Def
::
StructCtor
(
_
,
CtorKind
::
Const
)
=>
{
ConstVal
::
Struct
(
Default
::
default
(
))
tcx
.mk_const
(
Aggregate
(
Struct
(
&
[])
))
}
Def
::
StructCtor
(
_
,
CtorKind
::
Fn
)
=>
{
signal!
(
e
,
UnimplementedConstVal
(
"tuple struct constructors"
))
}
Def
::
Local
(
id
)
=>
{
debug!
(
"Def::Local({:?}): {:?}"
,
id
,
cx
.fn_args
);
if
let
Some
(
val
)
=
cx
.fn_args
.as_ref
()
.and_then
(|
args
|
args
.get
(
&
id
))
{
val
.clone
()
if
let
Some
(
&
val
)
=
cx
.fn_args
.as_ref
()
.and_then
(|
args
|
args
.get
(
&
id
))
{
val
}
else
{
signal!
(
e
,
NonConstPath
);
}
},
Def
::
Method
(
id
)
|
Def
::
Fn
(
id
)
=>
Function
(
id
,
substs
),
Def
::
Method
(
id
)
|
Def
::
Fn
(
id
)
=>
tcx
.mk_const
(
Function
(
id
,
substs
)
),
Def
::
Err
=>
span_bug!
(
e
.span
,
"typeck error"
),
_
=>
signal!
(
e
,
NonConstPath
),
}
}
hir
::
ExprCall
(
ref
callee
,
ref
args
)
=>
{
let
(
def_id
,
substs
)
=
match
cx
.eval
(
callee
)
?
{
let
(
def_id
,
substs
)
=
match
*
cx
.eval
(
callee
)
?
{
Function
(
def_id
,
substs
)
=>
(
def_id
,
substs
),
_
=>
signal!
(
e
,
TypeckError
),
};
...
...
@@ -329,14 +339,14 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
};
match
&
tcx
.item_name
(
def_id
)[
..
]
{
"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
())));
let
size
=
layout_of
(
substs
.type_at
(
0
))
?
.size
(
tcx
)
.bytes
()
;
return
Ok
(
tcx
.mk_const
(
Integral
(
Usize
(
ConstUsize
::
new
(
size
,
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
())));
let
align
=
layout_of
(
substs
.type_at
(
0
))
?
.align
(
tcx
)
.abi
()
;
return
Ok
(
tcx
.mk_const
(
Integral
(
Usize
(
ConstUsize
::
new
(
align
,
tcx
.sess.target.uint_type
)
.unwrap
())))
)
;
}
_
=>
signal!
(
e
,
TypeckError
)
}
...
...
@@ -385,38 +395,39 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
callee_cx
.eval
(
&
body
.value
)
?
},
hir
::
ExprLit
(
ref
lit
)
=>
match
lit_to_const
(
&
lit
.node
,
tcx
,
ety
)
{
Ok
(
val
)
=>
val
,
Ok
(
val
)
=>
tcx
.mk_const
(
val
)
,
Err
(
err
)
=>
signal!
(
e
,
err
),
},
hir
::
ExprBlock
(
ref
block
)
=>
{
match
block
.expr
{
Some
(
ref
expr
)
=>
cx
.eval
(
expr
)
?
,
None
=>
Tuple
(
vec!
[]
),
None
=>
tcx
.mk_const
(
Aggregate
(
Tuple
(
&
[]))
),
}
}
hir
::
ExprType
(
ref
e
,
_
)
=>
cx
.eval
(
e
)
?
,
hir
::
ExprTup
(
ref
fields
)
=>
{
Tuple
(
fields
.iter
()
.map
(|
e
|
cx
.eval
(
e
))
.collect
::
<
Result
<
_
,
_
>>
()
?
)
let
values
=
fields
.iter
()
.map
(|
e
|
cx
.eval
(
e
))
.collect
::
<
Result
<
Vec
<
_
>
,
_
>>
()
?
;
tcx
.mk_const
(
Aggregate
(
Tuple
(
tcx
.alloc_constval_slice
(
&
values
))))
}
hir
::
ExprStruct
(
_
,
ref
fields
,
_
)
=>
{
Struct
(
fields
.iter
()
.map
(|
f
|
{
tcx
.mk_const
(
Aggregate
(
Struct
(
tcx
.alloc_name_constval_slice
(
&
fields
.iter
()
.map
(|
f
|
{
cx
.eval
(
&
f
.expr
)
.map
(|
v
|
(
f
.name.node
,
v
))
})
.collect
::
<
Result
<
_
,
_
>>
()
?
)
})
.collect
::
<
Result
<
Vec
<
_
>
,
_
>>
()
?
)))
)
}
hir
::
ExprIndex
(
ref
arr
,
ref
idx
)
=>
{
if
!
tcx
.sess.features
.borrow
()
.const_indexing
{
signal!
(
e
,
IndexOpFeatureGated
);
}
let
arr
=
cx
.eval
(
arr
)
?
;
let
idx
=
match
cx
.eval
(
idx
)
?
{
let
idx
=
match
*
cx
.eval
(
idx
)
?
{
Integral
(
Usize
(
i
))
=>
i
.as_u64
(
tcx
.sess.target.uint_type
),
_
=>
signal!
(
idx
,
IndexNotUsize
),
};
assert_eq!
(
idx
as
usize
as
u64
,
idx
);
match
arr
{
A
rray
(
ref
v
)
=>
{
if
let
Some
(
elem
)
=
v
.get
(
idx
as
usize
)
{
elem
.clone
()
match
*
arr
{
A
ggregate
(
Array
(
v
)
)
=>
{
if
let
Some
(
&
elem
)
=
v
.get
(
idx
as
usize
)
{
elem
}
else
{
let
n
=
v
.len
()
as
u64
;
assert_eq!
(
n
as
usize
as
u64
,
n
);
...
...
@@ -424,44 +435,43 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
}
}
Repeat
(
..
,
n
)
if
idx
>=
n
=>
{
Aggregate
(
Repeat
(
..
,
n
)
)
if
idx
>=
n
=>
{
signal!
(
e
,
IndexOutOfBounds
{
len
:
n
,
index
:
idx
})
}
Repeat
(
ref
elem
,
_
)
=>
(
**
elem
)
.clone
()
,
Aggregate
(
Repeat
(
elem
,
_
))
=>
elem
,
ByteStr
(
ref
data
)
if
idx
>=
data
.len
()
as
u64
=>
{
signal!
(
e
,
IndexOutOfBounds
{
len
:
data
.len
()
as
u64
,
index
:
idx
})
ByteStr
(
b
)
if
idx
>=
b
.
data
.len
()
as
u64
=>
{
signal!
(
e
,
IndexOutOfBounds
{
len
:
b
.
data
.len
()
as
u64
,
index
:
idx
})
}
ByteStr
(
data
)
=>
{
Integral
(
U8
(
data
[
idx
as
usize
]
))
ByteStr
(
b
)
=>
{
tcx
.mk_const
(
Integral
(
U8
(
b
.data
[
idx
as
usize
])
))
},
_
=>
signal!
(
e
,
IndexedNonVec
),
}
}
hir
::
ExprArray
(
ref
v
)
=>
{
Array
(
v
.iter
()
.map
(|
e
|
cx
.eval
(
e
))
.collect
::
<
Result
<
_
,
_
>>
()
?
)
let
values
=
v
.iter
()
.map
(|
e
|
cx
.eval
(
e
))
.collect
::
<
Result
<
Vec
<
_
>
,
_
>>
()
?
;
tcx
.mk_const
(
Aggregate
(
Array
(
tcx
.alloc_constval_slice
(
&
values
))))
}
hir
::
ExprRepeat
(
ref
elem
,
_
)
=>
{
let
n
=
match
ety
.sty
{
ty
::
TyArray
(
_
,
n
)
=>
n
as
u64
,
_
=>
span_bug!
(
e
.span
,
"typeck error"
)
};
Repeat
(
Box
::
new
(
cx
.eval
(
elem
)
?
),
n
)
tcx
.mk_const
(
Aggregate
(
Repeat
(
cx
.eval
(
elem
)
?
,
n
))
)
},
hir
::
ExprTupField
(
ref
base
,
index
)
=>
{
let
c
=
cx
.eval
(
base
)
?
;
if
let
Tuple
(
ref
fields
)
=
c
{
fields
[
index
.node
]
.clone
()
if
let
Aggregate
(
Tuple
(
fields
))
=
*
cx
.eval
(
base
)
?
{
fields
[
index
.node
]
}
else
{
signal!
(
base
,
ExpectedConstTuple
);
}
}
hir
::
ExprField
(
ref
base
,
field_name
)
=>
{
let
c
=
cx
.eval
(
base
)
?
;
if
let
Struct
(
ref
fields
)
=
c
{
if
let
Some
(
f
)
=
fields
.get
(
&
field_name
.node
)
{
f
.clone
()
if
let
Aggregate
(
Struct
(
fields
))
=
*
cx
.eval
(
base
)
?
{
if
let
Some
(
&
(
_
,
f
))
=
fields
.iter
()
.find
(|
&&
(
name
,
_
)|
name
==
field_name
.node
)
{
f
}
else
{
signal!
(
e
,
MissingStructField
);
}
...
...
@@ -625,7 +635,7 @@ fn cast_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
Err
(
ErrKind
::
UnimplementedConstVal
(
"casting a bytestr to a raw ptr"
))
},
ty
::
TyRef
(
_
,
ty
::
TypeAndMut
{
ref
ty
,
mutbl
:
hir
::
MutImmutable
})
=>
match
ty
.sty
{
ty
::
TyArray
(
ty
,
n
)
if
ty
==
tcx
.types.u8
&&
n
==
b
.
len
()
=>
Ok
(
ByteStr
(
b
)
),
ty
::
TyArray
(
ty
,
n
)
if
ty
==
tcx
.types.u8
&&
n
==
b
.
data
.len
()
=>
Ok
(
val
),
ty
::
TySlice
(
_
)
=>
{
Err
(
ErrKind
::
UnimplementedConstVal
(
"casting a bytestr to slice"
))
},
...
...
@@ -645,7 +655,7 @@ fn cast_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
}
fn
lit_to_const
<
'a
,
'tcx
>
(
lit
:
&
ast
::
LitKind
,
fn
lit_to_const
<
'a
,
'tcx
>
(
lit
:
&
'tcx
ast
::
LitKind
,
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
mut
ty
:
Ty
<
'tcx
>
)
->
Result
<
ConstVal
<
'tcx
>
,
ErrKind
<
'tcx
>>
{
...
...
@@ -660,7 +670,7 @@ fn lit_to_const<'a, 'tcx>(lit: &ast::LitKind,
match
*
lit
{
LitKind
::
Str
(
ref
s
,
_
)
=>
Ok
(
Str
(
s
.as_str
())),
LitKind
::
ByteStr
(
ref
data
)
=>
Ok
(
ByteStr
(
data
.clone
()
)),
LitKind
::
ByteStr
(
ref
data
)
=>
Ok
(
ByteStr
(
ByteArray
{
data
}
)),
LitKind
::
Byte
(
n
)
=>
Ok
(
Integral
(
U8
(
n
))),
LitKind
::
Int
(
n
,
hint
)
=>
{
match
(
&
ty
.sty
,
hint
)
{
...
...
@@ -708,8 +718,8 @@ pub fn compare_const_vals(tcx: TyCtxt, span: Span, a: &ConstVal, b: &ConstVal)
(
&
Float
(
a
),
&
Float
(
b
))
=>
a
.try_cmp
(
b
)
.ok
(),
(
&
Str
(
ref
a
),
&
Str
(
ref
b
))
=>
Some
(
a
.cmp
(
b
)),
(
&
Bool
(
a
),
&
Bool
(
b
))
=>
Some
(
a
.cmp
(
&
b
)),
(
&
ByteStr
(
ref
a
),
&
ByteStr
(
ref
b
))
=>
Some
(
a
.cmp
(
b
)),
(
&
Char
(
a
),
&
Char
(
ref
b
))
=>
Some
(
a
.cmp
(
b
)),
(
&
ByteStr
(
a
),
&
ByteStr
(
b
))
=>
Some
(
a
.data
.cmp
(
b
.data
)),
(
&
Char
(
a
),
&
Char
(
b
))
=>
Some
(
a
.cmp
(
&
b
)),
_
=>
None
,
};
...
...
@@ -729,8 +739,8 @@ pub fn compare_const_vals(tcx: TyCtxt, span: Span, a: &ConstVal, b: &ConstVal)
impl
<
'a
,
'tcx
>
ConstContext
<
'a
,
'tcx
>
{
pub
fn
compare_lit_exprs
(
&
self
,
span
:
Span
,
a
:
&
Expr
,
b
:
&
Expr
)
->
Result
<
Ordering
,
ErrorReported
>
{
a
:
&
'tcx
Expr
,
b
:
&
'tcx
Expr
)
->
Result
<
Ordering
,
ErrorReported
>
{
let
tcx
=
self
.tcx
;
let
a
=
match
self
.eval
(
a
)
{
Ok
(
a
)
=>
a
,
...
...
src/librustc_const_eval/pattern.rs
浏览文件 @
50076b00
...
...
@@ -83,12 +83,12 @@ pub enum PatternKind<'tcx> {
},
Constant
{
value
:
ConstVal
<
'tcx
>
,
value
:
&
'tcx
ConstVal
<
'tcx
>
,
},
Range
{
lo
:
ConstVal
<
'tcx
>
,
hi
:
ConstVal
<
'tcx
>
,
lo
:
&
'tcx
ConstVal
<
'tcx
>
,
hi
:
&
'tcx
ConstVal
<
'tcx
>
,
end
:
RangeEnd
,
},
...
...
@@ -112,15 +112,12 @@ fn print_const_val(value: &ConstVal, f: &mut fmt::Formatter) -> fmt::Result {
ConstVal
::
Float
(
ref
x
)
=>
write!
(
f
,
"{}"
,
x
),
ConstVal
::
Integral
(
ref
i
)
=>
write!
(
f
,
"{}"
,
i
),
ConstVal
::
Str
(
ref
s
)
=>
write!
(
f
,
"{:?}"
,
&
s
[
..
]),
ConstVal
::
ByteStr
(
ref
b
)
=>
write!
(
f
,
"{:?}"
,
&
b
[
..
]
),
ConstVal
::
ByteStr
(
b
)
=>
write!
(
f
,
"{:?}"
,
b
.data
),
ConstVal
::
Bool
(
b
)
=>
write!
(
f
,
"{:?}"
,
b
),
ConstVal
::
Char
(
c
)
=>
write!
(
f
,
"{:?}"
,
c
),
ConstVal
::
Variant
(
_
)
|
ConstVal
::
Struct
(
_
)
|
ConstVal
::
Tuple
(
_
)
|
ConstVal
::
Function
(
..
)
|
ConstVal
::
Array
(
..
)
|
ConstVal
::
Repeat
(
..
)
=>
bug!
(
"{:?} not printable in a pattern"
,
value
)
ConstVal
::
Aggregate
(
_
)
=>
bug!
(
"{:?} not printable in a pattern"
,
value
)
}
}
...
...
@@ -230,12 +227,12 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
write!
(
f
,
"{}"
,
subpattern
)
}
PatternKind
::
Constant
{
ref
value
}
=>
{
PatternKind
::
Constant
{
value
}
=>
{
print_const_val
(
value
,
f
)
}
PatternKind
::
Range
{
ref
lo
,
ref
hi
,
ref
end
}
=>
{
PatternKind
::
Range
{
lo
,
hi
,
end
}
=>
{
print_const_val
(
lo
,
f
)
?
;
match
*
end
{
match
end
{
RangeEnd
::
Included
=>
write!
(
f
,
"..."
)
?
,
RangeEnd
::
Excluded
=>
write!
(
f
,
".."
)
?
,
}
...
...
@@ -278,7 +275,7 @@ impl<'a, 'tcx> Pattern<'tcx> {
pub
fn
from_hir
(
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
param_env_and_substs
:
ty
::
ParamEnvAnd
<
'tcx
,
&
'tcx
Substs
<
'tcx
>>
,
tables
:
&
'a
ty
::
TypeckTables
<
'tcx
>
,
pat
:
&
hir
::
Pat
)
->
Self
{
pat
:
&
'tcx
hir
::
Pat
)
->
Self
{
let
mut
pcx
=
PatternContext
::
new
(
tcx
,
param_env_and_substs
,
tables
);
let
result
=
pcx
.lower_pattern
(
pat
);
if
!
pcx
.errors
.is_empty
()
{
...
...
@@ -302,7 +299,7 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
}
pub
fn
lower_pattern
(
&
mut
self
,
pat
:
&
hir
::
Pat
)
->
Pattern
<
'tcx
>
{
pub
fn
lower_pattern
(
&
mut
self
,
pat
:
&
'tcx
hir
::
Pat
)
->
Pattern
<
'tcx
>
{
let
mut
ty
=
self
.tables
.node_id_to_type
(
pat
.hir_id
);
let
kind
=
match
pat
.node
{
...
...
@@ -310,11 +307,11 @@ pub fn lower_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
PatKind
::
Lit
(
ref
value
)
=>
self
.lower_lit
(
value
),
PatKind
::
Range
(
ref
lo
,
ref
hi
,
ref
end
)
=>
{
PatKind
::
Range
(
ref
lo
,
ref
hi
,
end
)
=>
{
match
(
self
.lower_lit
(
lo
),
self
.lower_lit
(
hi
))
{
(
PatternKind
::
Constant
{
value
:
lo
},
PatternKind
::
Constant
{
value
:
hi
})
=>
{
PatternKind
::
Range
{
lo
:
lo
,
hi
:
hi
,
end
:
end
.clone
()
}
PatternKind
::
Range
{
lo
,
hi
,
end
}
}
_
=>
PatternKind
::
Wild
}
...
...
@@ -474,11 +471,11 @@ pub fn lower_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
}
}
fn
lower_patterns
(
&
mut
self
,
pats
:
&
[
P
<
hir
::
Pat
>
])
->
Vec
<
Pattern
<
'tcx
>>
{
fn
lower_patterns
(
&
mut
self
,
pats
:
&
'tcx
[
P
<
hir
::
Pat
>
])
->
Vec
<
Pattern
<
'tcx
>>
{
pats
.iter
()
.map
(|
p
|
self
.lower_pattern
(
p
))
.collect
()
}
fn
lower_opt_pattern
(
&
mut
self
,
pat
:
&
Option
<
P
<
hir
::
Pat
>>
)
->
Option
<
Pattern
<
'tcx
>>
fn
lower_opt_pattern
(
&
mut
self
,
pat
:
&
'tcx
Option
<
P
<
hir
::
Pat
>>
)
->
Option
<
Pattern
<
'tcx
>>
{
pat
.as_ref
()
.map
(|
p
|
self
.lower_pattern
(
p
))
}
...
...
@@ -521,9 +518,9 @@ fn slice_or_array_pattern(
&
mut
self
,
span
:
Span
,
ty
:
Ty
<
'tcx
>
,
prefix
:
&
[
P
<
hir
::
Pat
>
],
slice
:
&
Option
<
P
<
hir
::
Pat
>>
,
suffix
:
&
[
P
<
hir
::
Pat
>
])
prefix
:
&
'tcx
[
P
<
hir
::
Pat
>
],
slice
:
&
'tcx
Option
<
P
<
hir
::
Pat
>>
,
suffix
:
&
'tcx
[
P
<
hir
::
Pat
>
])
->
PatternKind
<
'tcx
>
{
let
prefix
=
self
.lower_patterns
(
prefix
);
...
...
@@ -631,17 +628,17 @@ fn lower_path(&mut self,
}
}
fn
lower_lit
(
&
mut
self
,
expr
:
&
hir
::
Expr
)
->
PatternKind
<
'tcx
>
{
fn
lower_lit
(
&
mut
self
,
expr
:
&
'tcx
hir
::
Expr
)
->
PatternKind
<
'tcx
>
{
let
const_cx
=
eval
::
ConstContext
::
new
(
self
.tcx
,
self
.param_env
.and
(
self
.substs
),
self
.tables
);
match
const_cx
.eval
(
expr
)
{
Ok
(
value
)
=>
{
if
let
ConstVal
::
Variant
(
def_id
)
=
value
{
if
let
ConstVal
::
Variant
(
def_id
)
=
*
value
{
let
ty
=
self
.tables
.expr_ty
(
expr
);
self
.lower_variant_or_leaf
(
Def
::
Variant
(
def_id
),
ty
,
vec!
[])
}
else
{
PatternKind
::
Constant
{
value
:
value
}
PatternKind
::
Constant
{
value
}
}
}
Err
(
e
)
=>
{
...
...
@@ -652,7 +649,7 @@ fn lower_lit(&mut self, expr: &hir::Expr) -> PatternKind<'tcx> {
}
fn
lower_const_expr
(
&
mut
self
,
expr
:
&
hir
::
Expr
,
expr
:
&
'tcx
hir
::
Expr
,
pat_id
:
ast
::
NodeId
,
span
:
Span
)
->
Pattern
<
'tcx
>
{
...
...
@@ -819,8 +816,8 @@ fn super_fold_with<F: PatternFolder<$lt_tcx>>(&self, _: &mut F) -> Self {
}
CloneImpls!
{
<
'tcx
>
Span
,
Field
,
Mutability
,
ast
::
Name
,
ast
::
NodeId
,
usize
,
ConstVal
<
'tcx
>
,
Region
<
'tcx
>
,
Ty
<
'tcx
>
,
BindingMode
<
'tcx
>
,
&
'tcx
AdtDef
,
Span
,
Field
,
Mutability
,
ast
::
Name
,
ast
::
NodeId
,
usize
,
&
'tcx
ConstVal
<
'tcx
>
,
Region
<
'tcx
>
,
Ty
<
'tcx
>
,
BindingMode
<
'tcx
>
,
&
'tcx
AdtDef
,
&
'tcx
Substs
<
'tcx
>
,
&
'tcx
Kind
<
'tcx
>
}
...
...
@@ -892,18 +889,18 @@ fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
subpattern
:
subpattern
.fold_with
(
folder
),
},
PatternKind
::
Constant
{
ref
value
value
}
=>
PatternKind
::
Constant
{
value
:
value
.fold_with
(
folder
)
},
PatternKind
::
Range
{
ref
lo
,
ref
hi
,
ref
end
,
lo
,
hi
,
end
,
}
=>
PatternKind
::
Range
{
lo
:
lo
.fold_with
(
folder
),
hi
:
hi
.fold_with
(
folder
),
end
:
end
.clone
()
,
end
,
},
PatternKind
::
Slice
{
ref
prefix
,
...
...
src/librustc_lint/types.rs
浏览文件 @
50076b00
...
...
@@ -76,7 +76,7 @@ fn get_lints(&self) -> LintArray {
}
impl
<
'a
,
'tcx
>
LateLintPass
<
'a
,
'tcx
>
for
TypeLimits
{
fn
check_expr
(
&
mut
self
,
cx
:
&
LateContext
,
e
:
&
hir
::
Expr
)
{
fn
check_expr
(
&
mut
self
,
cx
:
&
LateContext
<
'a
,
'tcx
>
,
e
:
&
'tcx
hir
::
Expr
)
{
match
e
.node
{
hir
::
ExprUnary
(
hir
::
UnNeg
,
ref
expr
)
=>
{
// propagate negation, if the negation itself isn't negated
...
...
@@ -117,7 +117,7 @@ fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
cx
.param_env
.and
(
substs
),
cx
.tables
);
match
const_cx
.eval
(
&
r
)
{
Ok
(
ConstVal
::
Integral
(
i
))
=>
{
Ok
(
&
ConstVal
::
Integral
(
i
))
=>
{
i
.is_negative
()
||
i
.to_u64
()
.map
(|
i
|
i
>=
bits
)
...
...
src/librustc_metadata/decoder.rs
浏览文件 @
50076b00
...
...
@@ -16,6 +16,7 @@
use
rustc
::
hir
::
map
::{
DefKey
,
DefPath
,
DefPathData
,
DefPathHash
};
use
rustc
::
hir
;
use
rustc
::
middle
::
const_val
::{
ByteArray
,
ConstVal
};
use
rustc
::
middle
::
cstore
::
LinkagePreference
;
use
rustc
::
hir
::
def
::{
self
,
Def
,
CtorKind
};
use
rustc
::
hir
::
def_id
::{
CrateNum
,
DefId
,
DefIndex
,
CRATE_DEF_INDEX
,
LOCAL_CRATE
};
...
...
@@ -377,6 +378,20 @@ fn specialized_decode(&mut self)
}
}
impl
<
'a
,
'tcx
>
SpecializedDecoder
<
ByteArray
<
'tcx
>>
for
DecodeContext
<
'a
,
'tcx
>
{
fn
specialized_decode
(
&
mut
self
)
->
Result
<
ByteArray
<
'tcx
>
,
Self
::
Error
>
{
Ok
(
ByteArray
{
data
:
self
.tcx
()
.alloc_byte_array
(
&
Vec
::
decode
(
self
)
?
)
})
}
}
impl
<
'a
,
'tcx
>
SpecializedDecoder
<&
'tcx
ConstVal
<
'tcx
>>
for
DecodeContext
<
'a
,
'tcx
>
{
fn
specialized_decode
(
&
mut
self
)
->
Result
<&
'tcx
ConstVal
<
'tcx
>
,
Self
::
Error
>
{
Ok
(
self
.tcx
()
.mk_const
(
Decodable
::
decode
(
self
)
?
))
}
}
impl
<
'a
,
'tcx
>
MetadataBlob
{
pub
fn
is_compatible
(
&
self
)
->
bool
{
self
.raw_bytes
()
.starts_with
(
METADATA_HEADER
)
...
...
src/librustc_mir/build/expr/as_rvalue.rs
浏览文件 @
50076b00
...
...
@@ -197,7 +197,7 @@ fn expr_as_rvalue(&mut self,
span
:
expr_span
,
ty
:
this
.hir
.tcx
()
.types.u32
,
literal
:
Literal
::
Value
{
value
:
ConstVal
::
Integral
(
ConstInt
::
U32
(
0
)),
value
:
this
.hir
.tcx
()
.mk_const
(
ConstVal
::
Integral
(
ConstInt
::
U32
(
0
)
)),
},
}));
box
AggregateKind
::
Generator
(
closure_id
,
substs
,
interior
)
...
...
@@ -391,7 +391,9 @@ fn neg_1_literal(&mut self, span: Span, ty: ty::Ty<'tcx>) -> Operand<'tcx> {
}
};
Literal
::
Value
{
value
:
ConstVal
::
Integral
(
val
)
}
Literal
::
Value
{
value
:
self
.hir
.tcx
()
.mk_const
(
ConstVal
::
Integral
(
val
))
}
}
_
=>
{
span_bug!
(
span
,
"Invalid type for neg_1_literal: `{:?}`"
,
ty
)
...
...
@@ -424,7 +426,9 @@ fn minval_literal(&mut self, span: Span, ty: ty::Ty<'tcx>) -> Operand<'tcx> {
}
};
Literal
::
Value
{
value
:
ConstVal
::
Integral
(
val
)
}
Literal
::
Value
{
value
:
self
.hir
.tcx
()
.mk_const
(
ConstVal
::
Integral
(
val
))
}
}
_
=>
{
span_bug!
(
span
,
"Invalid type for minval_literal: `{:?}`"
,
ty
)
...
...
src/librustc_mir/build/matches/mod.rs
浏览文件 @
50076b00
...
...
@@ -301,13 +301,13 @@ enum TestKind<'tcx> {
// test the branches of enum
SwitchInt
{
switch_ty
:
Ty
<
'tcx
>
,
options
:
Vec
<
ConstVal
<
'tcx
>>
,
indices
:
FxHashMap
<
ConstVal
<
'tcx
>
,
usize
>
,
options
:
Vec
<
&
'tcx
ConstVal
<
'tcx
>>
,
indices
:
FxHashMap
<
&
'tcx
ConstVal
<
'tcx
>
,
usize
>
,
},
// test for equality
Eq
{
value
:
ConstVal
<
'tcx
>
,
value
:
&
'tcx
ConstVal
<
'tcx
>
,
ty
:
Ty
<
'tcx
>
,
},
...
...
src/librustc_mir/build/matches/test.rs
浏览文件 @
50076b00
...
...
@@ -61,24 +61,24 @@ pub fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> {
}
}
PatternKind
::
Constant
{
ref
value
}
=>
{
PatternKind
::
Constant
{
value
}
=>
{
Test
{
span
:
match_pair
.pattern.span
,
kind
:
TestKind
::
Eq
{
value
:
value
.clone
()
,
value
,
ty
:
match_pair
.pattern.ty
.clone
()
}
}
}
PatternKind
::
Range
{
ref
lo
,
ref
hi
,
ref
end
}
=>
{
PatternKind
::
Range
{
lo
,
hi
,
end
}
=>
{
Test
{
span
:
match_pair
.pattern.span
,
kind
:
TestKind
::
Range
{
lo
:
Literal
::
Value
{
value
:
lo
.clone
()
},
hi
:
Literal
::
Value
{
value
:
hi
.clone
()
},
lo
:
Literal
::
Value
{
value
:
lo
},
hi
:
Literal
::
Value
{
value
:
hi
},
ty
:
match_pair
.pattern.ty
.clone
(),
end
:
end
.clone
()
,
end
,
},
}
}
...
...
@@ -112,8 +112,8 @@ pub fn add_cases_to_switch<'pat>(&mut self,
test_lvalue
:
&
Lvalue
<
'tcx
>
,
candidate
:
&
Candidate
<
'pat
,
'tcx
>
,
switch_ty
:
Ty
<
'tcx
>
,
options
:
&
mut
Vec
<
ConstVal
<
'tcx
>>
,
indices
:
&
mut
FxHashMap
<
ConstVal
<
'tcx
>
,
usize
>
)
options
:
&
mut
Vec
<
&
'tcx
ConstVal
<
'tcx
>>
,
indices
:
&
mut
FxHashMap
<
&
'tcx
ConstVal
<
'tcx
>
,
usize
>
)
->
bool
{
let
match_pair
=
match
candidate
.match_pairs
.iter
()
.find
(|
mp
|
mp
.lvalue
==
*
test_lvalue
)
{
...
...
@@ -122,13 +122,13 @@ pub fn add_cases_to_switch<'pat>(&mut self,
};
match
*
match_pair
.pattern.kind
{
PatternKind
::
Constant
{
ref
value
}
=>
{
PatternKind
::
Constant
{
value
}
=>
{
// if the lvalues match, the type should match
assert_eq!
(
match_pair
.pattern.ty
,
switch_ty
);
indices
.entry
(
value
.clone
()
)
indices
.entry
(
value
)
.or_insert_with
(||
{
options
.push
(
value
.clone
()
);
options
.push
(
value
);
options
.len
()
-
1
});
true
...
...
@@ -228,9 +228,9 @@ pub fn perform_test(&mut self,
assert
!
(
options
.len
()
>
0
&&
options
.len
()
<=
2
);
let
(
true_bb
,
false_bb
)
=
(
self
.cfg
.start_new_block
(),
self
.cfg
.start_new_block
());
let
ret
=
match
&
options
[
0
]
{
&
ConstVal
::
Bool
(
true
)
=>
vec!
[
true_bb
,
false_bb
],
&
ConstVal
::
Bool
(
false
)
=>
vec!
[
false_bb
,
true_bb
],
let
ret
=
match
*
options
[
0
]
{
ConstVal
::
Bool
(
true
)
=>
vec!
[
true_bb
,
false_bb
],
ConstVal
::
Bool
(
false
)
=>
vec!
[
false_bb
,
true_bb
],
v
=>
span_bug!
(
test
.span
,
"expected boolean value but got {:?}"
,
v
)
};
(
ret
,
TerminatorKind
::
if_
(
self
.hir
.tcx
(),
Operand
::
Consume
(
lvalue
.clone
()),
...
...
@@ -258,12 +258,12 @@ pub fn perform_test(&mut self,
ret
}
TestKind
::
Eq
{
ref
value
,
mut
ty
}
=>
{
TestKind
::
Eq
{
value
,
mut
ty
}
=>
{
let
mut
val
=
Operand
::
Consume
(
lvalue
.clone
());
// If we're using b"..." as a pattern, we need to insert an
// unsizing coercion, as the byte string has the type &[u8; N].
let
expect
=
if
let
ConstVal
::
ByteStr
(
ref
bytes
)
=
*
value
{
let
expect
=
if
let
ConstVal
::
ByteStr
(
bytes
)
=
*
value
{
let
tcx
=
self
.hir
.tcx
();
// Unsize the lvalue to &[u8], too, if necessary.
...
...
@@ -279,10 +279,10 @@ pub fn perform_test(&mut self,
assert
!
(
ty
.is_slice
());
let
array_ty
=
tcx
.mk_array
(
tcx
.types.u8
,
bytes
.len
());
let
array_ty
=
tcx
.mk_array
(
tcx
.types.u8
,
bytes
.
data
.
len
());
let
array_ref
=
tcx
.mk_imm_ref
(
tcx
.types.re_static
,
array_ty
);
let
array
=
self
.literal_operand
(
test
.span
,
array_ref
,
Literal
::
Value
{
value
:
value
.clone
()
value
});
let
slice
=
self
.temp
(
ty
,
test
.span
);
...
...
@@ -291,7 +291,7 @@ pub fn perform_test(&mut self,
Operand
::
Consume
(
slice
)
}
else
{
self
.literal_operand
(
test
.span
,
ty
,
Literal
::
Value
{
value
:
value
.clone
()
value
})
};
...
...
src/librustc_mir/build/misc.rs
浏览文件 @
50076b00
...
...
@@ -59,7 +59,11 @@ pub fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
ty
::
TyBool
=>
{
self
.hir
.false_literal
()
}
ty
::
TyChar
=>
Literal
::
Value
{
value
:
ConstVal
::
Char
(
'\0'
)
},
ty
::
TyChar
=>
{
Literal
::
Value
{
value
:
self
.hir
.tcx
()
.mk_const
(
ConstVal
::
Char
(
'\0'
))
}
}
ty
::
TyUint
(
ity
)
=>
{
let
val
=
match
ity
{
ast
::
UintTy
::
U8
=>
ConstInt
::
U8
(
0
),
...
...
@@ -74,7 +78,9 @@ pub fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
}
};
Literal
::
Value
{
value
:
ConstVal
::
Integral
(
val
)
}
Literal
::
Value
{
value
:
self
.hir
.tcx
()
.mk_const
(
ConstVal
::
Integral
(
val
))
}
}
ty
::
TyInt
(
ity
)
=>
{
let
val
=
match
ity
{
...
...
@@ -90,7 +96,9 @@ pub fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
}
};
Literal
::
Value
{
value
:
ConstVal
::
Integral
(
val
)
}
Literal
::
Value
{
value
:
self
.hir
.tcx
()
.mk_const
(
ConstVal
::
Integral
(
val
))
}
}
_
=>
{
span_bug!
(
span
,
"Invalid type for zero_literal: `{:?}`"
,
ty
)
...
...
src/librustc_mir/build/mod.rs
浏览文件 @
50076b00
...
...
@@ -11,7 +11,6 @@
use
build
;
use
hair
::
cx
::
Cx
;
use
hair
::
Pattern
;
use
rustc
::
hir
;
use
rustc
::
hir
::
def_id
::
DefId
;
use
rustc
::
middle
::
region
;
...
...
@@ -537,10 +536,7 @@ fn args_and_body(&mut self,
let
lvalue
=
Lvalue
::
Local
(
Local
::
new
(
index
+
1
));
if
let
Some
(
pattern
)
=
pattern
{
let
pattern
=
Pattern
::
from_hir
(
self
.hir
.tcx
()
.global_tcx
(),
self
.hir.param_env
.and
(
self
.hir.identity_substs
),
self
.hir
.tables
(),
pattern
);
let
pattern
=
self
.hir
.pattern_from_hir
(
pattern
);
scope
=
self
.declare_bindings
(
scope
,
ast_body
.span
,
&
pattern
);
unpack!
(
block
=
self
.lvalue_into_pattern
(
block
,
pattern
,
&
lvalue
));
}
...
...
src/librustc_mir/hair/cx/block.rs
浏览文件 @
50076b00
...
...
@@ -64,10 +64,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
first_statement_index
:
index
as
u32
,
});
let
pattern
=
Pattern
::
from_hir
(
cx
.tcx
.global_tcx
(),
cx
.param_env
.and
(
cx
.identity_substs
),
cx
.tables
(),
&
local
.pat
);
let
pattern
=
cx
.pattern_from_hir
(
&
local
.pat
);
result
.push
(
StmtRef
::
Mirror
(
Box
::
new
(
Stmt
{
kind
:
StmtKind
::
Let
{
remainder_scope
:
remainder_scope
,
...
...
src/librustc_mir/hair/cx/expr.rs
浏览文件 @
50076b00
...
...
@@ -473,7 +473,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
let
def_id
=
cx
.tcx.hir
.body_owner_def_id
(
count
);
let
substs
=
Substs
::
identity_for_item
(
cx
.tcx
.global_tcx
(),
def_id
);
let
count
=
match
cx
.tcx
.at
(
c
.span
)
.const_eval
(
cx
.param_env
.and
((
def_id
,
substs
)))
{
Ok
(
ConstVal
::
Integral
(
ConstInt
::
Usize
(
u
)))
=>
u
,
Ok
(
&
ConstVal
::
Integral
(
ConstInt
::
Usize
(
u
)))
=>
u
,
Ok
(
other
)
=>
bug!
(
"constant evaluation of repeat count yielded {:?}"
,
other
),
Err
(
s
)
=>
cx
.fatal_const_eval_err
(
&
s
,
c
.span
,
"expression"
)
};
...
...
@@ -597,7 +597,7 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
span
:
expr
.span
,
kind
:
ExprKind
::
Literal
{
literal
:
Literal
::
Value
{
value
:
ConstVal
::
Function
(
def_id
,
substs
),
value
:
cx
.tcx
.mk_const
(
ConstVal
::
Function
(
def_id
,
substs
)
),
},
},
}
...
...
@@ -612,12 +612,7 @@ fn to_borrow_kind(m: hir::Mutability) -> BorrowKind {
fn
convert_arm
<
'a
,
'gcx
,
'tcx
>
(
cx
:
&
mut
Cx
<
'a
,
'gcx
,
'tcx
>
,
arm
:
&
'tcx
hir
::
Arm
)
->
Arm
<
'tcx
>
{
Arm
{
patterns
:
arm
.pats
.iter
()
.map
(|
p
|
{
Pattern
::
from_hir
(
cx
.tcx
.global_tcx
(),
cx
.param_env
.and
(
cx
.identity_substs
),
cx
.tables
(),
p
)
})
.collect
(),
patterns
:
arm
.pats
.iter
()
.map
(|
p
|
cx
.pattern_from_hir
(
p
))
.collect
(),
guard
:
arm
.guard
.to_ref
(),
body
:
arm
.body
.to_ref
(),
}
...
...
@@ -635,7 +630,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
Def
::
StructCtor
(
def_id
,
CtorKind
::
Fn
)
|
Def
::
VariantCtor
(
def_id
,
CtorKind
::
Fn
)
=>
ExprKind
::
Literal
{
literal
:
Literal
::
Value
{
value
:
ConstVal
::
Function
(
def_id
,
substs
),
value
:
cx
.tcx
.mk_const
(
ConstVal
::
Function
(
def_id
,
substs
)
),
},
},
...
...
src/librustc_mir/hair/cx/mod.rs
浏览文件 @
50076b00
...
...
@@ -113,7 +113,11 @@ pub fn usize_ty(&mut self) -> Ty<'tcx> {
pub
fn
usize_literal
(
&
mut
self
,
value
:
u64
)
->
Literal
<
'tcx
>
{
match
ConstUsize
::
new
(
value
,
self
.tcx.sess.target.uint_type
)
{
Ok
(
val
)
=>
Literal
::
Value
{
value
:
ConstVal
::
Integral
(
ConstInt
::
Usize
(
val
))
},
Ok
(
val
)
=>
{
Literal
::
Value
{
value
:
self
.tcx
.mk_const
(
ConstVal
::
Integral
(
ConstInt
::
Usize
(
val
)))
}
}
Err
(
_
)
=>
bug!
(
"usize literal out of range for target"
),
}
}
...
...
@@ -127,11 +131,11 @@ pub fn unit_ty(&mut self) -> Ty<'tcx> {
}
pub
fn
true_literal
(
&
mut
self
)
->
Literal
<
'tcx
>
{
Literal
::
Value
{
value
:
ConstVal
::
Bool
(
true
)
}
Literal
::
Value
{
value
:
self
.tcx
.mk_const
(
ConstVal
::
Bool
(
true
)
)
}
}
pub
fn
false_literal
(
&
mut
self
)
->
Literal
<
'tcx
>
{
Literal
::
Value
{
value
:
ConstVal
::
Bool
(
false
)
}
Literal
::
Value
{
value
:
self
.tcx
.mk_const
(
ConstVal
::
Bool
(
false
)
)
}
}
pub
fn
const_eval_literal
(
&
mut
self
,
e
:
&
hir
::
Expr
)
->
Literal
<
'tcx
>
{
...
...
@@ -139,12 +143,24 @@ pub fn const_eval_literal(&mut self, e: &hir::Expr) -> Literal<'tcx> {
let
const_cx
=
ConstContext
::
new
(
tcx
,
self
.param_env
.and
(
self
.identity_substs
),
self
.tables
());
match
const_cx
.eval
(
e
)
{
Ok
(
value
)
=>
Literal
::
Value
{
value
:
value
},
match
const_cx
.eval
(
tcx
.hir
.expect_expr
(
e
.id
)
)
{
Ok
(
value
)
=>
Literal
::
Value
{
value
},
Err
(
s
)
=>
self
.fatal_const_eval_err
(
&
s
,
e
.span
,
"expression"
)
}
}
pub
fn
pattern_from_hir
(
&
mut
self
,
p
:
&
hir
::
Pat
)
->
Pattern
<
'tcx
>
{
let
tcx
=
self
.tcx
.global_tcx
();
let
p
=
match
tcx
.hir
.get
(
p
.id
)
{
hir
::
map
::
NodePat
(
p
)
|
hir
::
map
::
NodeBinding
(
p
)
=>
p
,
node
=>
bug!
(
"pattern became {:?}"
,
node
)
};
Pattern
::
from_hir
(
tcx
,
self
.param_env
.and
(
self
.identity_substs
),
self
.tables
(),
p
)
}
pub
fn
fatal_const_eval_err
(
&
mut
self
,
err
:
&
ConstEvalErr
<
'tcx
>
,
primary_span
:
Span
,
...
...
@@ -170,7 +186,7 @@ pub fn trait_method(&mut self,
let
method_ty
=
method_ty
.subst
(
self
.tcx
,
substs
);
return
(
method_ty
,
Literal
::
Value
{
value
:
ConstVal
::
Function
(
item
.def_id
,
substs
),
value
:
self
.tcx
.mk_const
(
ConstVal
::
Function
(
item
.def_id
,
substs
)
),
});
}
}
...
...
src/librustc_mir/shim.rs
浏览文件 @
50076b00
...
...
@@ -407,7 +407,7 @@ fn make_clone_call(
span
:
self
.span
,
ty
:
tcx
.mk_fn_def
(
self
.def_id
,
substs
),
literal
:
Literal
::
Value
{
value
:
ConstVal
::
Function
(
self
.def_id
,
substs
),
value
:
tcx
.mk_const
(
ConstVal
::
Function
(
self
.def_id
,
substs
)
),
},
});
...
...
@@ -472,7 +472,7 @@ fn make_usize(&self, value: usize) -> Box<Constant<'tcx>> {
span
:
self
.span
,
ty
:
self
.tcx.types.usize
,
literal
:
Literal
::
Value
{
value
:
ConstVal
::
Integral
(
ConstInt
::
Usize
(
value
))
value
:
self
.tcx
.mk_const
(
ConstVal
::
Integral
(
ConstInt
::
Usize
(
value
)
))
}
}
}
...
...
@@ -711,8 +711,8 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
span
,
ty
:
tcx
.type_of
(
def_id
),
literal
:
Literal
::
Value
{
value
:
ConstVal
::
Function
(
def_id
,
Substs
::
identity_for_item
(
tcx
,
def_id
)),
value
:
tcx
.mk_const
(
ConstVal
::
Function
(
def_id
,
Substs
::
identity_for_item
(
tcx
,
def_id
))
)
,
},
}),
vec!
[
rcvr
]
...
...
src/librustc_mir/transform/elaborate_drops.rs
浏览文件 @
50076b00
...
...
@@ -520,7 +520,9 @@ fn constant_bool(&self, span: Span, val: bool) -> Rvalue<'tcx> {
Rvalue
::
Use
(
Operand
::
Constant
(
Box
::
new
(
Constant
{
span
,
ty
:
self
.tcx.types.bool
,
literal
:
Literal
::
Value
{
value
:
ConstVal
::
Bool
(
val
)
}
literal
:
Literal
::
Value
{
value
:
self
.tcx
.mk_const
(
ConstVal
::
Bool
(
val
))
}
})))
}
...
...
src/librustc_mir/transform/generator.rs
浏览文件 @
50076b00
...
...
@@ -175,7 +175,7 @@ fn set_state(&self, state_disc: u32, source_info: SourceInfo) -> Statement<'tcx>
span
:
source_info
.span
,
ty
:
self
.tcx.types.u32
,
literal
:
Literal
::
Value
{
value
:
ConstVal
::
Integral
(
ConstInt
::
U32
(
state_disc
)),
value
:
self
.tcx
.mk_const
(
ConstVal
::
Integral
(
ConstInt
::
U32
(
state_disc
)
)),
},
});
Statement
{
...
...
@@ -553,7 +553,7 @@ fn insert_panic_on_resume_after_return<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
span
:
mir
.span
,
ty
:
tcx
.types.bool
,
literal
:
Literal
::
Value
{
value
:
ConstVal
::
Bool
(
false
),
value
:
tcx
.mk_const
(
ConstVal
::
Bool
(
false
)
),
},
}),
expected
:
true
,
...
...
@@ -603,7 +603,7 @@ fn create_generator_resume_function<'a, 'tcx>(
span
:
mir
.span
,
ty
:
tcx
.types.bool
,
literal
:
Literal
::
Value
{
value
:
ConstVal
::
Bool
(
false
),
value
:
tcx
.mk_const
(
ConstVal
::
Bool
(
false
)
),
},
}),
expected
:
true
,
...
...
src/librustc_mir/transform/simplify_branches.rs
浏览文件 @
50076b00
...
...
@@ -56,7 +56,7 @@ fn run_pass<'a, 'tcx>(&self,
},
TerminatorKind
::
Assert
{
target
,
cond
:
Operand
::
Constant
(
box
Constant
{
literal
:
Literal
::
Value
{
value
:
ConstVal
::
Bool
(
cond
)
value
:
&
ConstVal
::
Bool
(
cond
)
},
..
}),
expected
,
..
}
if
cond
==
expected
=>
{
TerminatorKind
::
Goto
{
target
:
target
}
...
...
src/librustc_mir/transform/type_check.rs
浏览文件 @
50076b00
...
...
@@ -572,7 +572,7 @@ fn is_box_free(&self, operand: &Operand<'tcx>) -> bool {
match
operand
{
&
Operand
::
Constant
(
box
Constant
{
literal
:
Literal
::
Value
{
value
:
ConstVal
::
Function
(
def_id
,
_
),
..
value
:
&
ConstVal
::
Function
(
def_id
,
_
),
..
},
..
})
=>
{
Some
(
def_id
)
==
self
.tcx
()
.lang_items
()
.box_free_fn
()
...
...
src/librustc_mir/util/elaborate_drops.rs
浏览文件 @
50076b00
...
...
@@ -922,7 +922,9 @@ fn constant_usize(&self, val: u16) -> Operand<'tcx> {
Operand
::
Constant
(
box
Constant
{
span
:
self
.source_info.span
,
ty
:
self
.tcx
()
.types.usize
,
literal
:
Literal
::
Value
{
value
:
ConstVal
::
Integral
(
self
.tcx
()
.const_usize
(
val
))
}
literal
:
Literal
::
Value
{
value
:
self
.tcx
()
.mk_const
(
ConstVal
::
Integral
(
self
.tcx
()
.const_usize
(
val
)))
}
})
}
...
...
src/librustc_passes/mir_stats.rs
浏览文件 @
50076b00
...
...
@@ -257,7 +257,7 @@ fn visit_closure_substs(&mut self,
}
fn
visit_const_val
(
&
mut
self
,
const_val
:
&
ConstVal
,
const_val
:
&
&
'tcx
ConstVal
<
'tcx
>
,
_
:
Location
)
{
self
.record
(
"ConstVal"
,
const_val
);
self
.super_const_val
(
const_val
);
...
...
src/librustc_trans/mir/analyze.rs
浏览文件 @
50076b00
...
...
@@ -110,7 +110,7 @@ fn visit_terminator_kind(&mut self,
mir
::
TerminatorKind
::
Call
{
func
:
mir
::
Operand
::
Constant
(
box
mir
::
Constant
{
literal
:
Literal
::
Value
{
value
:
ConstVal
::
Function
(
def_id
,
_
),
..
value
:
&
ConstVal
::
Function
(
def_id
,
_
),
..
},
..
}),
ref
args
,
..
...
...
src/librustc_trans/mir/constant.rs
浏览文件 @
50076b00
...
...
@@ -90,11 +90,11 @@ pub fn from_constint<'a>(ccx: &CrateContext<'a, 'tcx>, ci: &ConstInt)
/// Translate ConstVal into a LLVM constant value.
pub
fn
from_constval
<
'a
>
(
ccx
:
&
CrateContext
<
'a
,
'tcx
>
,
cv
:
ConstVal
,
cv
:
&
ConstVal
,
ty
:
Ty
<
'tcx
>
)
->
Const
<
'tcx
>
{
let
llty
=
type_of
::
type_of
(
ccx
,
ty
);
let
val
=
match
cv
{
let
val
=
match
*
cv
{
ConstVal
::
Float
(
v
)
=>
{
let
bits
=
match
v
.ty
{
ast
::
FloatTy
::
F32
=>
C_u32
(
ccx
,
v
.bits
as
u32
),
...
...
@@ -105,12 +105,11 @@ pub fn from_constval<'a>(ccx: &CrateContext<'a, 'tcx>,
ConstVal
::
Bool
(
v
)
=>
C_bool
(
ccx
,
v
),
ConstVal
::
Integral
(
ref
i
)
=>
return
Const
::
from_constint
(
ccx
,
i
),
ConstVal
::
Str
(
ref
v
)
=>
C_str_slice
(
ccx
,
v
.clone
()),
ConstVal
::
ByteStr
(
ref
v
)
=>
consts
::
addr_of
(
ccx
,
C_bytes
(
ccx
,
v
),
1
,
"byte_str"
),
ConstVal
::
ByteStr
(
v
)
=>
consts
::
addr_of
(
ccx
,
C_bytes
(
ccx
,
v
.data
),
1
,
"byte_str"
),
ConstVal
::
Char
(
c
)
=>
C_integral
(
Type
::
char
(
ccx
),
c
as
u64
,
false
),
ConstVal
::
Function
(
..
)
=>
C_null
(
type_of
::
type_of
(
ccx
,
ty
)),
ConstVal
::
Variant
(
_
)
|
ConstVal
::
Struct
(
_
)
|
ConstVal
::
Tuple
(
_
)
|
ConstVal
::
Array
(
..
)
|
ConstVal
::
Repeat
(
..
)
=>
{
ConstVal
::
Aggregate
(
..
)
=>
{
bug!
(
"MIR must not use `{:?}` (aggregates are expanded to MIR rvalues)"
,
cv
)
}
};
...
...
src/librustc_typeck/collect.rs
浏览文件 @
50076b00
...
...
@@ -572,7 +572,7 @@ fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
match
result
{
Ok
(
ConstVal
::
Integral
(
x
))
=>
Some
(
x
),
Ok
(
&
ConstVal
::
Integral
(
x
))
=>
Some
(
x
),
_
=>
None
}
}
else
if
let
Some
(
discr
)
=
repr_type
.disr_incr
(
tcx
,
prev_discr
)
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录