Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
f713b501
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,发现更多精彩内容 >>
提交
f713b501
编写于
3月 11, 2022
作者:
B
b-naber
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
change thir to lazily create constants
上级
36748cf8
变更
17
隐藏空白更改
内联
并排
Showing
17 changed file
with
296 addition
and
133 deletion
+296
-133
compiler/rustc_middle/src/query/mod.rs
compiler/rustc_middle/src/query/mod.rs
+5
-0
compiler/rustc_middle/src/thir.rs
compiler/rustc_middle/src/thir.rs
+26
-6
compiler/rustc_middle/src/thir/visit.rs
compiler/rustc_middle/src/thir/visit.rs
+5
-2
compiler/rustc_mir_build/src/build/expr/as_constant.rs
compiler/rustc_mir_build/src/build/expr/as_constant.rs
+120
-10
compiler/rustc_mir_build/src/build/expr/as_place.rs
compiler/rustc_mir_build/src/build/expr/as_place.rs
+3
-0
compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+3
-0
compiler/rustc_mir_build/src/build/expr/as_temp.rs
compiler/rustc_mir_build/src/build/expr/as_temp.rs
+1
-1
compiler/rustc_mir_build/src/build/expr/category.rs
compiler/rustc_mir_build/src/build/expr/category.rs
+6
-3
compiler/rustc_mir_build/src/build/expr/into.rs
compiler/rustc_mir_build/src/build/expr/into.rs
+3
-0
compiler/rustc_mir_build/src/build/expr/mod.rs
compiler/rustc_mir_build/src/build/expr/mod.rs
+1
-1
compiler/rustc_mir_build/src/build/mod.rs
compiler/rustc_mir_build/src/build/mod.rs
+1
-0
compiler/rustc_mir_build/src/check_unsafety.rs
compiler/rustc_mir_build/src/check_unsafety.rs
+3
-0
compiler/rustc_mir_build/src/lib.rs
compiler/rustc_mir_build/src/lib.rs
+1
-0
compiler/rustc_mir_build/src/thir/constant.rs
compiler/rustc_mir_build/src/thir/constant.rs
+7
-1
compiler/rustc_mir_build/src/thir/cx/expr.rs
compiler/rustc_mir_build/src/thir/cx/expr.rs
+50
-79
compiler/rustc_mir_build/src/thir/cx/mod.rs
compiler/rustc_mir_build/src/thir/cx/mod.rs
+1
-22
compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
...ler/rustc_trait_selection/src/traits/const_evaluatable.rs
+60
-8
未找到文件。
compiler/rustc_middle/src/query/mod.rs
浏览文件 @
f713b501
...
...
@@ -955,12 +955,17 @@
desc
{
"get a &core::panic::Location referring to a span"
}
}
// FIXME get rid of this with valtrees
query
lit_to_const
(
key
:
LitToConstInput
<
'tcx
>
)
->
Result
<
ty
::
Const
<
'tcx
>
,
LitToConstError
>
{
desc
{
"converting literal to const"
}
}
query
lit_to_constant
(
key
:
LitToConstInput
<
'tcx
>
)
->
Result
<
mir
::
ConstantKind
<
'tcx
>
,
LitToConstError
>
{
desc
{
"converting literal to mir constant"
}
}
query
check_match
(
key
:
DefId
)
{
desc
{
|
tcx
|
"match-checking `{}`"
,
tcx
.def_path_str
(
key
)
}
cache_on_disk_if
{
key
.is_local
()
}
...
...
compiler/rustc_middle/src/thir.rs
浏览文件 @
f713b501
...
...
@@ -369,7 +369,8 @@ pub enum ExprKind<'tcx> {
},
/// An inline `const` block, e.g. `const {}`.
ConstBlock
{
value
:
Const
<
'tcx
>
,
did
:
DefId
,
substs
:
SubstsRef
<
'tcx
>
,
},
/// An array literal constructed from one repeated element, e.g. `[1; 5]`.
Repeat
{
...
...
@@ -408,13 +409,26 @@ pub enum ExprKind<'tcx> {
},
/// A literal.
Literal
{
literal
:
Const
<
'tcx
>
,
lit
:
&
'tcx
hir
::
Lit
,
neg
:
bool
,
},
/// For literals that don't correspond to anything in the HIR
ScalarLiteral
{
lit
:
ty
::
ScalarInt
,
user_ty
:
Option
<
Canonical
<
'tcx
,
UserType
<
'tcx
>>>
,
},
/// Associated constants and named constants
NamedConst
{
def_id
:
DefId
,
substs
:
SubstsRef
<
'tcx
>
,
user_ty
:
Option
<
Canonical
<
'tcx
,
UserType
<
'tcx
>>>
,
/// The `DefId` of the `const` item this literal
/// was produced from, if this is not a user-written
/// literal value.
const_id
:
Option
<
DefId
>
,
},
ConstParam
{
literal
:
ty
::
Const
<
'tcx
>
,
def_id
:
DefId
,
user_ty
:
Option
<
Canonical
<
'tcx
,
UserType
<
'tcx
>>>
,
},
// FIXME improve docs for `StaticRef` by distinguishing it from `NamedConst`
/// A literal containing the address of a `static`.
///
/// This is only distinguished from `Literal` so that we can register some
...
...
@@ -439,6 +453,12 @@ pub enum ExprKind<'tcx> {
},
}
impl
<
'tcx
>
ExprKind
<
'tcx
>
{
pub
fn
zero_sized_literal
(
user_ty
:
Option
<
Canonical
<
'tcx
,
UserType
<
'tcx
>>>
)
->
Self
{
ExprKind
::
ScalarLiteral
{
lit
:
ty
::
ScalarInt
::
ZST
,
user_ty
}
}
}
/// Represents the association of a field identifier and an expression.
///
/// This is used in struct constructors.
...
...
compiler/rustc_middle/src/thir/visit.rs
浏览文件 @
f713b501
...
...
@@ -93,7 +93,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp
visitor
.visit_expr
(
&
visitor
.thir
()[
value
])
}
}
ConstBlock
{
value
}
=>
visitor
.visit_const
(
value
),
ConstBlock
{
did
:
_
,
substs
:
_
}
=>
{}
Repeat
{
value
,
count
}
=>
{
visitor
.visit_expr
(
&
visitor
.thir
()[
value
]);
visitor
.visit_const
(
count
);
...
...
@@ -122,7 +122,10 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp
visitor
.visit_expr
(
&
visitor
.thir
()[
source
])
}
Closure
{
closure_id
:
_
,
substs
:
_
,
upvars
:
_
,
movability
:
_
,
fake_reads
:
_
}
=>
{}
Literal
{
literal
,
user_ty
:
_
,
const_id
:
_
}
=>
visitor
.visit_const
(
literal
),
Literal
{
lit
:
_
,
neg
:
_
}
=>
{}
ScalarLiteral
{
lit
:
_
,
user_ty
:
_
}
=>
{}
NamedConst
{
def_id
:
_
,
substs
:
_
,
user_ty
:
_
}
=>
{}
ConstParam
{
literal
:
_
,
def_id
:
_
,
user_ty
:
_
}
=>
{}
StaticRef
{
alloc_id
:
_
,
ty
:
_
,
def_id
:
_
}
=>
{}
InlineAsm
{
ref
operands
,
template
:
_
,
options
:
_
,
line_spans
:
_
}
=>
{
for
op
in
&**
operands
{
...
...
compiler/rustc_mir_build/src/build/expr/as_constant.rs
浏览文件 @
f713b501
//! See docs in build/expr/mod.rs
use
crate
::
build
::
Builder
;
use
rustc_middle
::
mir
::
interpret
::{
ConstValue
,
Scalar
};
use
crate
::
thir
::
constant
::
parse_float
;
use
rustc_ast
::
ast
;
use
rustc_hir
::
def_id
::
DefId
;
use
rustc_middle
::
mir
::
interpret
::{
Allocation
,
ConstValue
,
LitToConstError
,
LitToConstInput
,
Scalar
,
};
use
rustc_middle
::
mir
::
*
;
use
rustc_middle
::
thir
::
*
;
use
rustc_middle
::
ty
::
CanonicalUserTypeAnnotation
;
use
rustc_middle
::
ty
::
subst
::
SubstsRef
;
use
rustc_middle
::
ty
::{
self
,
CanonicalUserTypeAnnotation
,
Ty
,
TyCtxt
};
use
rustc_target
::
abi
::
Size
;
impl
<
'a
,
'tcx
>
Builder
<
'a
,
'tcx
>
{
/// Compile `expr`, yielding a compile-time constant. Assumes that
/// `expr` is a valid compile-time constant!
crate
fn
as_constant
(
&
mut
self
,
expr
:
&
Expr
<
'tcx
>
)
->
Constant
<
'tcx
>
{
debug!
(
"expr: {:#?}"
,
expr
);
// FIXME: Maybe we should try to evaluate here and only create an `Unevaluated`
// constant in case the evaluation fails. Need some evaluation function that
// allows normalization to fail.
let
create_uneval_from_def_id
=
|
tcx
:
TyCtxt
<
'tcx
>
,
def_id
:
DefId
,
ty
:
Ty
<
'tcx
>
,
substs
:
SubstsRef
<
'tcx
>
|
{
let
uneval
=
ty
::
Unevaluated
::
new
(
ty
::
WithOptConstParam
::
unknown
(
def_id
),
substs
);
tcx
.mk_const
(
ty
::
ConstS
{
val
:
ty
::
ConstKind
::
Unevaluated
(
uneval
),
ty
})
};
let
this
=
self
;
let
tcx
=
this
.tcx
;
let
Expr
{
ty
,
temp_lifetime
:
_
,
span
,
ref
kind
}
=
*
expr
;
match
*
kind
{
ExprKind
::
Scope
{
region_scope
:
_
,
lint_level
:
_
,
value
}
=>
{
this
.as_constant
(
&
this
.thir
[
value
])
}
ExprKind
::
Literal
{
literal
,
user_ty
,
const_id
:
_
}
=>
{
ExprKind
::
Literal
{
lit
,
neg
}
=>
{
let
literal
=
match
tcx
.at
(
expr
.span
)
.lit_to_constant
(
LitToConstInput
{
lit
:
&
lit
.node
,
ty
,
neg
,
})
{
Ok
(
c
)
=>
c
,
Err
(
LitToConstError
::
Reported
)
=>
ConstantKind
::
Ty
(
tcx
.const_error
(
ty
)),
Err
(
LitToConstError
::
TypeError
)
=>
{
bug!
(
"encountered type error in `lit_to_constant"
)
}
};
Constant
{
span
,
user_ty
:
None
,
literal
:
literal
.into
()
}
}
ExprKind
::
ScalarLiteral
{
lit
,
user_ty
}
=>
{
let
user_ty
=
user_ty
.map
(|
user_ty
|
{
this
.canonical_user_type_annotations
.push
(
CanonicalUserTypeAnnotation
{
span
,
user_ty
,
inferred_ty
:
ty
,
})
});
let
literal
=
ConstantKind
::
Val
(
ConstValue
::
Scalar
(
Scalar
::
Int
(
lit
)),
ty
);
Constant
{
span
,
user_ty
:
user_ty
,
literal
}
}
ExprKind
::
NamedConst
{
def_id
,
substs
,
user_ty
}
=>
{
let
user_ty
=
user_ty
.map
(|
user_ty
|
{
this
.canonical_user_type_annotations
.push
(
CanonicalUserTypeAnnotation
{
span
,
user_ty
,
inferred_ty
:
ty
,
})
});
let
literal
=
ConstantKind
::
Ty
(
create_uneval_from_def_id
(
tcx
,
def_id
,
ty
,
substs
));
Constant
{
user_ty
,
span
,
literal
}
}
ExprKind
::
ConstParam
{
literal
,
def_id
:
_
,
user_ty
}
=>
{
let
user_ty
=
user_ty
.map
(|
user_ty
|
{
this
.canonical_user_type_annotations
.push
(
CanonicalUserTypeAnnotation
{
span
,
...
...
@@ -24,20 +82,72 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
inferred_ty
:
ty
,
})
});
assert_eq!
(
literal
.ty
(),
ty
);
Constant
{
span
,
user_ty
,
literal
:
literal
.into
()
}
let
literal
=
ConstantKind
::
Ty
(
literal
);
Constant
{
user_ty
:
user_ty
,
span
,
literal
}
}
ExprKind
::
ConstBlock
{
did
:
def_id
,
substs
}
=>
{
let
literal
=
ConstantKind
::
Ty
(
create_uneval_from_def_id
(
tcx
,
def_id
,
ty
,
substs
));
Constant
{
user_ty
:
None
,
span
,
literal
}
}
ExprKind
::
StaticRef
{
alloc_id
,
ty
,
..
}
=>
{
let
const_val
=
ConstValue
::
Scalar
(
Scalar
::
from_pointer
(
alloc_id
.into
(),
&
this
.tcx
));
let
const_val
=
ConstValue
::
Scalar
(
Scalar
::
from_pointer
(
alloc_id
.into
(),
&
tcx
));
let
literal
=
ConstantKind
::
Val
(
const_val
,
ty
);
Constant
{
span
,
user_ty
:
None
,
literal
}
}
ExprKind
::
ConstBlock
{
value
}
=>
{
Constant
{
span
:
span
,
user_ty
:
None
,
literal
:
value
.into
()
}
}
_
=>
span_bug!
(
span
,
"expression is not a valid constant {:?}"
,
kind
),
}
}
}
crate
fn
lit_to_constant
<
'tcx
>
(
tcx
:
TyCtxt
<
'tcx
>
,
lit_input
:
LitToConstInput
<
'tcx
>
,
)
->
Result
<
ConstantKind
<
'tcx
>
,
LitToConstError
>
{
let
LitToConstInput
{
lit
,
ty
,
neg
}
=
lit_input
;
let
trunc
=
|
n
|
{
let
param_ty
=
ty
::
ParamEnv
::
reveal_all
()
.and
(
ty
);
let
width
=
tcx
.layout_of
(
param_ty
)
.map_err
(|
_
|
LitToConstError
::
Reported
)
?
.size
;
trace!
(
"trunc {} with size {} and shift {}"
,
n
,
width
.bits
(),
128
-
width
.bits
());
let
result
=
width
.truncate
(
n
);
trace!
(
"trunc result: {}"
,
result
);
Ok
(
ConstValue
::
Scalar
(
Scalar
::
from_uint
(
result
,
width
)))
};
let
value
=
match
(
lit
,
&
ty
.kind
())
{
(
ast
::
LitKind
::
Str
(
s
,
_
),
ty
::
Ref
(
_
,
inner_ty
,
_
))
if
inner_ty
.is_str
()
=>
{
let
s
=
s
.as_str
();
let
allocation
=
Allocation
::
from_bytes_byte_aligned_immutable
(
s
.as_bytes
());
let
allocation
=
tcx
.intern_const_alloc
(
allocation
);
ConstValue
::
Slice
{
data
:
allocation
,
start
:
0
,
end
:
s
.len
()
}
}
(
ast
::
LitKind
::
ByteStr
(
data
),
ty
::
Ref
(
_
,
inner_ty
,
_
))
if
matches!
(
inner_ty
.kind
(),
ty
::
Slice
(
_
))
=>
{
let
allocation
=
Allocation
::
from_bytes_byte_aligned_immutable
(
data
as
&
[
u8
]);
let
allocation
=
tcx
.intern_const_alloc
(
allocation
);
ConstValue
::
Slice
{
data
:
allocation
,
start
:
0
,
end
:
data
.len
()
}
}
(
ast
::
LitKind
::
ByteStr
(
data
),
ty
::
Ref
(
_
,
inner_ty
,
_
))
if
inner_ty
.is_array
()
=>
{
let
id
=
tcx
.allocate_bytes
(
data
);
ConstValue
::
Scalar
(
Scalar
::
from_pointer
(
id
.into
(),
&
tcx
))
}
(
ast
::
LitKind
::
Byte
(
n
),
ty
::
Uint
(
ty
::
UintTy
::
U8
))
=>
{
ConstValue
::
Scalar
(
Scalar
::
from_uint
(
*
n
,
Size
::
from_bytes
(
1
)))
}
(
ast
::
LitKind
::
Int
(
n
,
_
),
ty
::
Uint
(
_
))
|
(
ast
::
LitKind
::
Int
(
n
,
_
),
ty
::
Int
(
_
))
=>
{
trunc
(
if
neg
{
(
*
n
as
i128
)
.overflowing_neg
()
.0
as
u128
}
else
{
*
n
})
?
}
(
ast
::
LitKind
::
Float
(
n
,
_
),
ty
::
Float
(
fty
))
=>
{
parse_float
(
*
n
,
*
fty
,
neg
)
.ok_or
(
LitToConstError
::
Reported
)
?
}
(
ast
::
LitKind
::
Bool
(
b
),
ty
::
Bool
)
=>
ConstValue
::
Scalar
(
Scalar
::
from_bool
(
*
b
)),
(
ast
::
LitKind
::
Char
(
c
),
ty
::
Char
)
=>
ConstValue
::
Scalar
(
Scalar
::
from_char
(
*
c
)),
(
ast
::
LitKind
::
Err
(
_
),
_
)
=>
return
Err
(
LitToConstError
::
Reported
),
_
=>
return
Err
(
LitToConstError
::
TypeError
),
};
Ok
(
ConstantKind
::
Val
(
value
,
ty
))
}
compiler/rustc_mir_build/src/build/expr/as_place.rs
浏览文件 @
f713b501
...
...
@@ -566,6 +566,9 @@ fn expr_as_place(
|
ExprKind
::
Continue
{
..
}
|
ExprKind
::
Return
{
..
}
|
ExprKind
::
Literal
{
..
}
|
ExprKind
::
NamedConst
{
..
}
|
ExprKind
::
ScalarLiteral
{
..
}
|
ExprKind
::
ConstParam
{
..
}
|
ExprKind
::
ConstBlock
{
..
}
|
ExprKind
::
StaticRef
{
..
}
|
ExprKind
::
InlineAsm
{
..
}
...
...
compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
浏览文件 @
f713b501
...
...
@@ -327,6 +327,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
ExprKind
::
Yield
{
..
}
|
ExprKind
::
Literal
{
..
}
|
ExprKind
::
NamedConst
{
..
}
|
ExprKind
::
ScalarLiteral
{
..
}
|
ExprKind
::
ConstParam
{
..
}
|
ExprKind
::
ConstBlock
{
..
}
|
ExprKind
::
StaticRef
{
..
}
|
ExprKind
::
Block
{
..
}
...
...
compiler/rustc_mir_build/src/build/expr/as_temp.rs
浏览文件 @
f713b501
...
...
@@ -70,7 +70,7 @@ fn as_temp_inner(
local_decl
.local_info
=
Some
(
Box
::
new
(
LocalInfo
::
StaticRef
{
def_id
,
is_thread_local
:
true
}));
}
ExprKind
::
Literal
{
const_id
:
Some
(
def_id
)
,
..
}
=>
{
ExprKind
::
NamedConst
{
def_id
,
..
}
=>
{
local_decl
.local_info
=
Some
(
Box
::
new
(
LocalInfo
::
ConstRef
{
def_id
}));
}
_
=>
{}
...
...
compiler/rustc_mir_build/src/build/expr/category.rs
浏览文件 @
f713b501
...
...
@@ -69,9 +69,12 @@ impl Category {
|
ExprKind
::
AssignOp
{
..
}
|
ExprKind
::
ThreadLocalRef
(
_
)
=>
Some
(
Category
::
Rvalue
(
RvalueFunc
::
AsRvalue
)),
ExprKind
::
ConstBlock
{
..
}
|
ExprKind
::
Literal
{
..
}
|
ExprKind
::
StaticRef
{
..
}
=>
{
Some
(
Category
::
Constant
)
}
ExprKind
::
ConstBlock
{
..
}
|
ExprKind
::
Literal
{
..
}
|
ExprKind
::
ScalarLiteral
{
..
}
|
ExprKind
::
ConstParam
{
..
}
|
ExprKind
::
StaticRef
{
..
}
|
ExprKind
::
NamedConst
{
..
}
=>
Some
(
Category
::
Constant
),
ExprKind
::
Loop
{
..
}
|
ExprKind
::
Block
{
..
}
...
...
compiler/rustc_mir_build/src/build/expr/into.rs
浏览文件 @
f713b501
...
...
@@ -533,6 +533,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
ExprKind
::
Closure
{
..
}
|
ExprKind
::
ConstBlock
{
..
}
|
ExprKind
::
Literal
{
..
}
|
ExprKind
::
NamedConst
{
..
}
|
ExprKind
::
ScalarLiteral
{
..
}
|
ExprKind
::
ConstParam
{
..
}
|
ExprKind
::
ThreadLocalRef
(
_
)
|
ExprKind
::
StaticRef
{
..
}
=>
{
debug_assert!
(
match
Category
::
of
(
&
expr
.kind
)
.unwrap
()
{
...
...
compiler/rustc_mir_build/src/build/expr/mod.rs
浏览文件 @
f713b501
...
...
@@ -60,7 +60,7 @@
//! basically the point where the "by value" operations are bridged
//! over to the "by reference" mode (`as_place`).
mod
as_constant
;
crate
mod
as_constant
;
mod
as_operand
;
pub
mod
as_place
;
mod
as_rvalue
;
...
...
compiler/rustc_mir_build/src/build/mod.rs
浏览文件 @
f713b501
...
...
@@ -1078,4 +1078,5 @@ fn get_unit_temp(&mut self) -> Place<'tcx> {
mod
misc
;
mod
scope
;
crate
use
expr
::
as_constant
;
pub
(
crate
)
use
expr
::
category
::
Category
as
ExprCategory
;
compiler/rustc_mir_build/src/check_unsafety.rs
浏览文件 @
f713b501
...
...
@@ -303,6 +303,9 @@ fn visit_expr(&mut self, expr: &Expr<'tcx>) {
|
ExprKind
::
Block
{
..
}
|
ExprKind
::
Borrow
{
..
}
|
ExprKind
::
Literal
{
..
}
|
ExprKind
::
NamedConst
{
..
}
|
ExprKind
::
ScalarLiteral
{
..
}
|
ExprKind
::
ConstParam
{
..
}
|
ExprKind
::
ConstBlock
{
..
}
|
ExprKind
::
Deref
{
..
}
|
ExprKind
::
Index
{
..
}
...
...
compiler/rustc_mir_build/src/lib.rs
浏览文件 @
f713b501
...
...
@@ -27,6 +27,7 @@
pub
fn
provide
(
providers
:
&
mut
Providers
)
{
providers
.check_match
=
thir
::
pattern
::
check_match
;
providers
.lit_to_const
=
thir
::
constant
::
lit_to_const
;
providers
.lit_to_constant
=
build
::
as_constant
::
lit_to_constant
;
providers
.mir_built
=
build
::
mir_built
;
providers
.thir_check_unsafety
=
check_unsafety
::
thir_check_unsafety
;
providers
.thir_check_unsafety_for_const_arg
=
check_unsafety
::
thir_check_unsafety_for_const_arg
;
...
...
compiler/rustc_mir_build/src/thir/constant.rs
浏览文件 @
f713b501
...
...
@@ -7,6 +7,7 @@
use
rustc_span
::
symbol
::
Symbol
;
use
rustc_target
::
abi
::
Size
;
// FIXME Once valtrees are available, get rid of this function and the query
crate
fn
lit_to_const
<
'tcx
>
(
tcx
:
TyCtxt
<
'tcx
>
,
lit_input
:
LitToConstInput
<
'tcx
>
,
...
...
@@ -57,7 +58,12 @@
Ok
(
ty
::
Const
::
from_value
(
tcx
,
lit
,
ty
))
}
fn
parse_float
<
'tcx
>
(
num
:
Symbol
,
fty
:
ty
::
FloatTy
,
neg
:
bool
)
->
Option
<
ConstValue
<
'tcx
>>
{
// FIXME move this to rustc_mir_build::build
pub
(
crate
)
fn
parse_float
<
'tcx
>
(
num
:
Symbol
,
fty
:
ty
::
FloatTy
,
neg
:
bool
,
)
->
Option
<
ConstValue
<
'tcx
>>
{
let
num
=
num
.as_str
();
use
rustc_apfloat
::
ieee
::{
Double
,
Single
};
let
scalar
=
match
fty
{
...
...
compiler/rustc_mir_build/src/thir/cx/expr.rs
浏览文件 @
f713b501
...
...
@@ -14,7 +14,9 @@
Adjust
,
Adjustment
,
AutoBorrow
,
AutoBorrowMutability
,
PointerCast
,
};
use
rustc_middle
::
ty
::
subst
::{
InternalSubsts
,
SubstsRef
};
use
rustc_middle
::
ty
::{
self
,
AdtKind
,
Ty
,
UpvarSubsts
,
UserType
};
use
rustc_middle
::
ty
::{
self
,
AdtKind
,
InlineConstSubsts
,
InlineConstSubstsParts
,
ScalarInt
,
Ty
,
UpvarSubsts
,
UserType
,
};
use
rustc_span
::
def_id
::
DefId
;
use
rustc_span
::
Span
;
use
rustc_target
::
abi
::
VariantIdx
;
...
...
@@ -290,11 +292,7 @@ fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx>
}
}
hir
::
ExprKind
::
Lit
(
ref
lit
)
=>
ExprKind
::
Literal
{
literal
:
self
.const_eval_literal
(
&
lit
.node
,
expr_ty
,
lit
.span
,
false
),
user_ty
:
None
,
const_id
:
None
,
},
hir
::
ExprKind
::
Lit
(
ref
lit
)
=>
ExprKind
::
Literal
{
lit
,
neg
:
false
},
hir
::
ExprKind
::
Binary
(
op
,
ref
lhs
,
ref
rhs
)
=>
{
if
self
.typeck_results
()
.is_method_call
(
expr
)
{
...
...
@@ -359,11 +357,7 @@ fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx>
let
arg
=
self
.mirror_expr
(
arg
);
self
.overloaded_operator
(
expr
,
Box
::
new
([
arg
]))
}
else
if
let
hir
::
ExprKind
::
Lit
(
ref
lit
)
=
arg
.kind
{
ExprKind
::
Literal
{
literal
:
self
.const_eval_literal
(
&
lit
.node
,
expr_ty
,
lit
.span
,
true
),
user_ty
:
None
,
const_id
:
None
,
}
ExprKind
::
Literal
{
lit
,
neg
:
true
}
}
else
{
ExprKind
::
Unary
{
op
:
UnOp
::
Neg
,
arg
:
self
.mirror_expr
(
arg
)
}
}
...
...
@@ -524,11 +518,7 @@ fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx>
ty
,
temp_lifetime
,
span
:
expr
.span
,
kind
:
ExprKind
::
Literal
{
literal
:
ty
::
Const
::
zero_sized
(
self
.tcx
,
ty
),
user_ty
,
const_id
:
None
,
},
kind
:
ExprKind
::
zero_sized_literal
(
user_ty
),
}),
}
}
...
...
@@ -550,11 +540,7 @@ fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx>
ty
,
temp_lifetime
,
span
:
expr
.span
,
kind
:
ExprKind
::
Literal
{
literal
:
ty
::
Const
::
zero_sized
(
self
.tcx
,
ty
),
user_ty
:
None
,
const_id
:
None
,
},
kind
:
ExprKind
::
zero_sized_literal
(
None
),
}),
}
}
...
...
@@ -568,13 +554,21 @@ fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx>
},
hir
::
ExprKind
::
ConstBlock
(
ref
anon_const
)
=>
{
let
anon_const_def_id
=
self
.tcx
.hir
()
.local_def_id
(
anon_const
.hir_id
);
// FIXME Do we want to use `from_inline_const` once valtrees
// are introduced? This would create `ValTree`s that will never be used...
let
value
=
ty
::
Const
::
from_inline_const
(
self
.tcx
,
anon_const_def_id
);
ExprKind
::
ConstBlock
{
value
}
let
tcx
=
self
.tcx
;
let
local_def_id
=
tcx
.hir
()
.local_def_id
(
anon_const
.hir_id
);
let
anon_const_def_id
=
local_def_id
.to_def_id
();
// Need to include the parent substs
let
hir_id
=
tcx
.hir
()
.local_def_id_to_hir_id
(
local_def_id
);
let
ty
=
tcx
.typeck
(
local_def_id
)
.node_type
(
hir_id
);
let
typeck_root_def_id
=
tcx
.typeck_root_def_id
(
anon_const_def_id
);
let
parent_substs
=
tcx
.erase_regions
(
InternalSubsts
::
identity_for_item
(
tcx
,
typeck_root_def_id
));
let
substs
=
InlineConstSubsts
::
new
(
tcx
,
InlineConstSubstsParts
{
parent_substs
,
ty
})
.substs
;
ExprKind
::
ConstBlock
{
did
:
anon_const_def_id
,
substs
}
}
// Now comes the rote stuff:
hir
::
ExprKind
::
Repeat
(
ref
v
,
_
)
=>
{
...
...
@@ -692,32 +686,36 @@ fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx>
};
let
source
=
if
let
Some
((
did
,
offset
,
var_ty
))
=
var
{
let
mk_const
=
|
literal
|
Expr
{
let
param_env_ty
=
self
.param_env
.and
(
var_ty
);
let
size
=
self
.tcx
.layout_of
(
param_env_ty
)
.unwrap_or_else
(|
e
|
{
panic!
(
"could not compute layout for {:?}: {:?}"
,
param_env_ty
,
e
)
})
.size
;
let
lit
=
ScalarInt
::
try_from_uint
(
offset
as
u128
,
size
)
.unwrap
();
let
kind
=
ExprKind
::
ScalarLiteral
{
lit
,
user_ty
:
None
};
let
offset
=
self
.thir.exprs
.push
(
Expr
{
temp_lifetime
,
ty
:
var_ty
,
span
:
expr
.span
,
kind
:
ExprKind
::
Literal
{
literal
,
user_ty
:
None
,
const_id
:
None
},
};
let
offset
=
self
.thir.exprs
.push
(
mk_const
(
ty
::
Const
::
from_bits
(
self
.tcx
,
offset
as
u128
,
self
.param_env
.and
(
var_ty
),
)));
kind
,
});
match
did
{
Some
(
did
)
=>
{
// in case we are offsetting from a computed discriminant
// and not the beginning of discriminants (which is always `0`)
let
substs
=
InternalSubsts
::
identity_for_item
(
self
.tcx
(),
did
);
let
lhs
=
ty
::
ConstS
{
val
:
ty
::
ConstKind
::
Unevaluated
(
ty
::
Unevaluated
::
new
(
ty
::
WithOptConstParam
::
unknown
(
did
),
substs
,
)),
let
kind
=
ExprKind
::
NamedConst
{
def_id
:
did
,
substs
,
user_ty
:
None
};
let
lhs
=
self
.thir.exprs
.push
(
Expr
{
temp_lifetime
,
ty
:
var_ty
,
};
let
lhs
=
self
.thir.exprs
.push
(
mk_const
(
self
.tcx
()
.mk_const
(
lhs
)));
let
bin
=
ExprKind
::
Binary
{
op
:
BinOp
::
Add
,
lhs
:
lhs
,
rhs
:
offset
};
span
:
expr
.span
,
kind
,
});
let
bin
=
ExprKind
::
Binary
{
op
:
BinOp
::
Add
,
lhs
,
rhs
:
offset
};
self
.thir.exprs
.push
(
Expr
{
temp_lifetime
,
ty
:
var_ty
,
...
...
@@ -832,16 +830,7 @@ fn method_callee(
}
};
let
ty
=
self
.tcx
()
.mk_fn_def
(
def_id
,
substs
);
Expr
{
temp_lifetime
,
ty
,
span
,
kind
:
ExprKind
::
Literal
{
literal
:
ty
::
Const
::
zero_sized
(
self
.tcx
(),
ty
),
user_ty
,
const_id
:
None
,
},
}
Expr
{
temp_lifetime
,
ty
,
span
,
kind
:
ExprKind
::
zero_sized_literal
(
user_ty
)
}
}
fn
convert_arm
(
&
mut
self
,
arm
:
&
'tcx
hir
::
Arm
<
'tcx
>
)
->
ArmId
{
...
...
@@ -868,17 +857,9 @@ fn convert_path_expr(&mut self, expr: &'tcx hir::Expr<'tcx>, res: Res) -> ExprKi
Res
::
Def
(
DefKind
::
Fn
,
_
)
|
Res
::
Def
(
DefKind
::
AssocFn
,
_
)
|
Res
::
Def
(
DefKind
::
Ctor
(
_
,
CtorKind
::
Fn
),
_
)
|
Res
::
SelfCtor
(
..
)
=>
{
|
Res
::
SelfCtor
(
_
)
=>
{
let
user_ty
=
self
.user_substs_applied_to_res
(
expr
.hir_id
,
res
);
debug!
(
"convert_path_expr: user_ty={:?}"
,
user_ty
);
ExprKind
::
Literal
{
literal
:
ty
::
Const
::
zero_sized
(
self
.tcx
,
self
.typeck_results
()
.node_type
(
expr
.hir_id
),
),
user_ty
,
const_id
:
None
,
}
ExprKind
::
zero_sized_literal
(
user_ty
)
}
Res
::
Def
(
DefKind
::
ConstParam
,
def_id
)
=>
{
...
...
@@ -889,30 +870,20 @@ fn convert_path_expr(&mut self, expr: &'tcx hir::Expr<'tcx>, res: Res) -> ExprKi
let
index
=
generics
.param_def_id_to_index
[
&
def_id
];
let
name
=
self
.tcx
.hir
()
.name
(
hir_id
);
let
val
=
ty
::
ConstKind
::
Param
(
ty
::
ParamConst
::
new
(
index
,
name
));
ExprKind
::
Literal
{
ExprKind
::
ConstParam
{
literal
:
self
.tcx
.mk_const
(
ty
::
ConstS
{
val
,
ty
:
self
.typeck_results
()
.node_type
(
expr
.hir_id
),
}),
user_ty
:
None
,
const_id
:
Some
(
def_id
)
,
def_id
,
}
}
Res
::
Def
(
DefKind
::
Const
,
def_id
)
|
Res
::
Def
(
DefKind
::
AssocConst
,
def_id
)
=>
{
let
user_ty
=
self
.user_substs_applied_to_res
(
expr
.hir_id
,
res
);
debug!
(
"convert_path_expr: (const) user_ty={:?}"
,
user_ty
);
ExprKind
::
Literal
{
literal
:
self
.tcx
.mk_const
(
ty
::
ConstS
{
val
:
ty
::
ConstKind
::
Unevaluated
(
ty
::
Unevaluated
::
new
(
ty
::
WithOptConstParam
::
unknown
(
def_id
),
substs
,
)),
ty
:
self
.typeck_results
()
.node_type
(
expr
.hir_id
),
}),
user_ty
,
const_id
:
Some
(
def_id
),
}
ExprKind
::
NamedConst
{
def_id
,
substs
,
user_ty
:
user_ty
}
}
Res
::
Def
(
DefKind
::
Ctor
(
_
,
CtorKind
::
Const
),
def_id
)
=>
{
...
...
compiler/rustc_mir_build/src/thir/cx/mod.rs
浏览文件 @
f713b501
...
...
@@ -5,7 +5,6 @@
use
crate
::
thir
::
pattern
::
pat_from_hir
;
use
crate
::
thir
::
util
::
UserAnnotatedTyHelpers
;
use
rustc_ast
as
ast
;
use
rustc_data_structures
::
steal
::
Steal
;
use
rustc_errors
::
ErrorGuaranteed
;
use
rustc_hir
as
hir
;
...
...
@@ -13,9 +12,8 @@
use
rustc_hir
::
HirId
;
use
rustc_hir
::
Node
;
use
rustc_middle
::
middle
::
region
;
use
rustc_middle
::
mir
::
interpret
::{
LitToConstError
,
LitToConstInput
};
use
rustc_middle
::
thir
::
*
;
use
rustc_middle
::
ty
::{
self
,
Ty
,
Ty
Ctxt
};
use
rustc_middle
::
ty
::{
self
,
TyCtxt
};
use
rustc_span
::
Span
;
crate
fn
thir_body
<
'tcx
>
(
...
...
@@ -77,25 +75,6 @@ fn new(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalDefId>) -> Cx<'tcx> {
}
}
crate
fn
const_eval_literal
(
&
mut
self
,
lit
:
&
'tcx
ast
::
LitKind
,
ty
:
Ty
<
'tcx
>
,
sp
:
Span
,
neg
:
bool
,
)
->
ty
::
Const
<
'tcx
>
{
trace!
(
"const_eval_literal: {:#?}, {:?}, {:?}, {:?}"
,
lit
,
ty
,
sp
,
neg
);
match
self
.tcx
.at
(
sp
)
.lit_to_const
(
LitToConstInput
{
lit
,
ty
,
neg
})
{
Ok
(
c
)
=>
c
,
Err
(
LitToConstError
::
Reported
)
=>
{
// create a dummy value and continue compiling
self
.tcx
.const_error
(
ty
)
}
Err
(
LitToConstError
::
TypeError
)
=>
bug!
(
"const_eval_literal: had type error"
),
}
}
crate
fn
pattern_from_hir
(
&
mut
self
,
p
:
&
hir
::
Pat
<
'_
>
)
->
Pat
<
'tcx
>
{
let
p
=
match
self
.tcx
.hir
()
.get
(
p
.hir_id
)
{
Node
::
Pat
(
p
)
|
Node
::
Binding
(
p
)
=>
p
,
...
...
compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
浏览文件 @
f713b501
...
...
@@ -14,7 +14,9 @@
use
rustc_index
::
vec
::
IndexVec
;
use
rustc_infer
::
infer
::
InferCtxt
;
use
rustc_middle
::
mir
;
use
rustc_middle
::
mir
::
interpret
::
ErrorHandled
;
use
rustc_middle
::
mir
::
interpret
::{
ConstValue
,
ErrorHandled
,
LitToConstError
,
LitToConstInput
,
Scalar
,
};
use
rustc_middle
::
thir
;
use
rustc_middle
::
thir
::
abstract_const
::{
self
,
Node
,
NodeId
,
NotConstEvaluatable
};
use
rustc_middle
::
ty
::
subst
::{
Subst
,
SubstsRef
};
...
...
@@ -28,16 +30,16 @@
use
std
::
ops
::
ControlFlow
;
/// Check if a given constant can be evaluated.
#[instrument(skip(infcx),
level
=
"debug"
)]
pub
fn
is_const_evaluatable
<
'cx
,
'tcx
>
(
infcx
:
&
InferCtxt
<
'cx
,
'tcx
>
,
uv
:
ty
::
Unevaluated
<
'tcx
,
()
>
,
param_env
:
ty
::
ParamEnv
<
'tcx
>
,
span
:
Span
,
)
->
Result
<
(),
NotConstEvaluatable
>
{
debug!
(
"is_const_evaluatable({:?})"
,
uv
);
let
tcx
=
infcx
.tcx
;
if
tcx
.features
()
.generic_const_exprs
{
if
infcx
.
tcx
.features
()
.generic_const_exprs
{
match
AbstractConst
::
new
(
tcx
,
uv
)
?
{
// We are looking at a generic abstract constant.
Some
(
ct
)
=>
{
...
...
@@ -304,6 +306,7 @@ fn maybe_supported_error(&mut self, span: Span, msg: &str) -> Result<!, ErrorGua
Err
(
reported
)
}
#[instrument(skip(tcx,
body,
body_id),
level
=
"debug"
)]
fn
new
(
tcx
:
TyCtxt
<
'tcx
>
,
(
body
,
body_id
):
(
&
'a
thir
::
Thir
<
'tcx
>
,
thir
::
ExprId
),
...
...
@@ -315,19 +318,35 @@ struct IsThirPolymorphic<'a, 'tcx> {
thir
:
&
'a
thir
::
Thir
<
'tcx
>
,
}
impl
<
'a
,
'tcx
>
IsThirPolymorphic
<
'a
,
'tcx
>
{
fn
expr_is_poly
(
&
self
,
expr
:
&
thir
::
Expr
<
'tcx
>
)
->
bool
{
if
expr
.ty
.has_param_types_or_consts
()
{
return
true
;
}
match
expr
.kind
{
thir
::
ExprKind
::
NamedConst
{
substs
,
..
}
=>
substs
.has_param_types_or_consts
(),
thir
::
ExprKind
::
ConstParam
{
..
}
=>
true
,
_
=>
false
,
}
}
}
use
thir
::
visit
;
impl
<
'a
,
'tcx
:
'a
>
visit
::
Visitor
<
'a
,
'tcx
>
for
IsThirPolymorphic
<
'a
,
'tcx
>
{
fn
thir
(
&
self
)
->
&
'a
thir
::
Thir
<
'tcx
>
{
&
self
.thir
}
#[instrument(skip(self),
level
=
"debug"
)]
fn
visit_expr
(
&
mut
self
,
expr
:
&
thir
::
Expr
<
'tcx
>
)
{
self
.is_poly
|
=
expr
.ty
.has_param_types_or_consts
(
);
self
.is_poly
|
=
self
.expr_is_poly
(
expr
);
if
!
self
.is_poly
{
visit
::
walk_expr
(
self
,
expr
)
}
}
#[instrument(skip(self),
level
=
"debug"
)]
fn
visit_pat
(
&
mut
self
,
pat
:
&
thir
::
Pat
<
'tcx
>
)
{
self
.is_poly
|
=
pat
.ty
.has_param_types_or_consts
();
if
!
self
.is_poly
{
...
...
@@ -335,6 +354,7 @@ fn visit_pat(&mut self, pat: &thir::Pat<'tcx>) {
}
}
#[instrument(skip(self),
level
=
"debug"
)]
fn
visit_const
(
&
mut
self
,
ct
:
ty
::
Const
<
'tcx
>
)
{
self
.is_poly
|
=
ct
.has_param_types_or_consts
();
}
...
...
@@ -393,16 +413,45 @@ fn build(mut self) -> Result<&'tcx [Node<'tcx>], ErrorGuaranteed> {
fn
recurse_build
(
&
mut
self
,
node
:
thir
::
ExprId
)
->
Result
<
NodeId
,
ErrorGuaranteed
>
{
use
thir
::
ExprKind
;
let
node
=
&
self
.body.exprs
[
node
];
debug!
(
"recurse_build: node={:?}"
,
node
);
Ok
(
match
&
node
.kind
{
// I dont know if handling of these 3 is correct
&
ExprKind
::
Scope
{
value
,
..
}
=>
self
.recurse_build
(
value
)
?
,
&
ExprKind
::
PlaceTypeAscription
{
source
,
..
}
|
&
ExprKind
::
ValueTypeAscription
{
source
,
..
}
=>
self
.recurse_build
(
source
)
?
,
&
ExprKind
::
Literal
{
lit
,
neg
}
=>
{
let
sp
=
node
.span
;
let
constant
=
match
self
.tcx
.at
(
sp
)
.lit_to_const
(
LitToConstInput
{
lit
:
&
lit
.node
,
ty
:
node
.ty
,
neg
})
{
Ok
(
c
)
=>
c
,
Err
(
LitToConstError
::
Reported
)
=>
{
self
.tcx
.const_error
(
node
.ty
)
}
Err
(
LitToConstError
::
TypeError
)
=>
{
bug!
(
"encountered type error in lit_to_constant"
)
}
};
self
.nodes
.push
(
Node
::
Leaf
(
constant
))
}
&
ExprKind
::
ScalarLiteral
{
lit
,
user_ty
:
_
}
=>
{
// FIXME Construct a Valtree from this ScalarInt when introducing Valtrees
let
const_value
=
ConstValue
::
Scalar
(
Scalar
::
Int
(
lit
));
self
.nodes
.push
(
Node
::
Leaf
(
ty
::
Const
::
from_value
(
self
.tcx
,
const_value
,
node
.ty
)))
}
&
ExprKind
::
NamedConst
{
def_id
,
substs
,
user_ty
:
_
}
=>
{
let
uneval
=
ty
::
Unevaluated
::
new
(
ty
::
WithOptConstParam
::
unknown
(
def_id
),
substs
);
// subtle: associated consts are literals this arm handles
// `<T as Trait>::ASSOC` as well as `12`
&
ExprKind
::
Literal
{
literal
,
..
}
=>
self
.nodes
.push
(
Node
::
Leaf
(
literal
)),
let
constant
=
self
.tcx
.mk_const
(
ty
::
ConstS
{
val
:
ty
::
ConstKind
::
Unevaluated
(
uneval
),
ty
:
node
.ty
,
});
self
.nodes
.push
(
Node
::
Leaf
(
constant
))
}
ExprKind
::
ConstParam
{
literal
,
..
}
=>
{
self
.nodes
.push
(
Node
::
Leaf
(
*
literal
))
}
ExprKind
::
Call
{
fun
,
args
,
..
}
=>
{
let
fun
=
self
.recurse_build
(
*
fun
)
?
;
...
...
@@ -585,6 +634,7 @@ pub(super) fn try_unify_abstract_consts<'tcx>(
// on `ErrorGuaranteed`.
}
#[instrument(skip(tcx,
f),
level
=
"debug"
)]
pub
fn
walk_abstract_const
<
'tcx
,
R
,
F
>
(
tcx
:
TyCtxt
<
'tcx
>
,
ct
:
AbstractConst
<
'tcx
>
,
...
...
@@ -593,6 +643,7 @@ pub fn walk_abstract_const<'tcx, R, F>(
where
F
:
FnMut
(
AbstractConst
<
'tcx
>
)
->
ControlFlow
<
R
>
,
{
#[instrument(skip(tcx,
f),
level
=
"debug"
)]
fn
recurse
<
'tcx
,
R
>
(
tcx
:
TyCtxt
<
'tcx
>
,
ct
:
AbstractConst
<
'tcx
>
,
...
...
@@ -600,6 +651,7 @@ fn recurse<'tcx, R>(
)
->
ControlFlow
<
R
>
{
f
(
ct
)
?
;
let
root
=
ct
.root
(
tcx
);
debug!
(
?
root
);
match
root
{
Node
::
Leaf
(
_
)
=>
ControlFlow
::
CONTINUE
,
Node
::
Binop
(
_
,
l
,
r
)
=>
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录