Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
16887192
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,发现更多精彩内容 >>
提交
16887192
编写于
11月 22, 2019
作者:
S
Santiago Pastorino
提交者:
Oliver Scherer
1月 10, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Promote `Ref`s to constants instead of static
上级
a59abfa4
变更
53
隐藏空白更改
内联
并排
Showing
53 changed file
with
447 addition
and
223 deletion
+447
-223
src/librustc/mir/interpret/queries.rs
src/librustc/mir/interpret/queries.rs
+6
-1
src/librustc/mir/mod.rs
src/librustc/mir/mod.rs
+11
-0
src/librustc/traits/fulfill.rs
src/librustc/traits/fulfill.rs
+1
-0
src/librustc/traits/select.rs
src/librustc/traits/select.rs
+7
-2
src/librustc/traits/wf.rs
src/librustc/traits/wf.rs
+3
-1
src/librustc/ty/flags.rs
src/librustc/ty/flags.rs
+1
-1
src/librustc/ty/print/pretty.rs
src/librustc/ty/print/pretty.rs
+22
-14
src/librustc/ty/relate.rs
src/librustc/ty/relate.rs
+4
-4
src/librustc/ty/structural_impls.rs
src/librustc/ty/structural_impls.rs
+3
-3
src/librustc/ty/sty.rs
src/librustc/ty/sty.rs
+7
-6
src/librustc/ty/walk.rs
src/librustc/ty/walk.rs
+2
-1
src/librustc_codegen_ssa/mir/constant.rs
src/librustc_codegen_ssa/mir/constant.rs
+6
-3
src/librustc_mir/borrow_check/type_check/mod.rs
src/librustc_mir/borrow_check/type_check/mod.rs
+48
-11
src/librustc_mir/const_eval.rs
src/librustc_mir/const_eval.rs
+1
-1
src/librustc_mir/const_eval/eval_queries.rs
src/librustc_mir/const_eval/eval_queries.rs
+14
-4
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/cx/expr.rs
+14
-11
src/librustc_mir/hair/pattern/mod.rs
src/librustc_mir/hair/pattern/mod.rs
+1
-0
src/librustc_mir/interpret/intern.rs
src/librustc_mir/interpret/intern.rs
+17
-8
src/librustc_mir/interpret/operand.rs
src/librustc_mir/interpret/operand.rs
+1
-1
src/librustc_mir/monomorphize/collector.rs
src/librustc_mir/monomorphize/collector.rs
+2
-2
src/librustc_mir/transform/check_consts/qualifs.rs
src/librustc_mir/transform/check_consts/qualifs.rs
+3
-1
src/librustc_mir/transform/const_prop.rs
src/librustc_mir/transform/const_prop.rs
+22
-16
src/librustc_mir/transform/promote_consts.rs
src/librustc_mir/transform/promote_consts.rs
+96
-25
src/librustc_typeck/astconv.rs
src/librustc_typeck/astconv.rs
+5
-1
src/librustdoc/clean/utils.rs
src/librustdoc/clean/utils.rs
+6
-2
src/test/codegen/consts.rs
src/test/codegen/consts.rs
+3
-3
src/test/compile-fail/promoted_div_by_zero.rs
src/test/compile-fail/promoted_div_by_zero.rs
+1
-1
src/test/mir-opt/const_prop/ref_deref.rs
src/test/mir-opt/const_prop/ref_deref.rs
+4
-2
src/test/mir-opt/const_prop/slice_len.rs
src/test/mir-opt/const_prop/slice_len.rs
+4
-2
src/test/mir-opt/inline/inline-retag.rs
src/test/mir-opt/inline/inline-retag.rs
+5
-5
src/test/mir-opt/match_false_edges.rs
src/test/mir-opt/match_false_edges.rs
+2
-1
src/test/ui/consts/array-literal-index-oob.rs
src/test/ui/consts/array-literal-index-oob.rs
+1
-0
src/test/ui/consts/array-literal-index-oob.stderr
src/test/ui/consts/array-literal-index-oob.stderr
+8
-1
src/test/ui/consts/const-eval/conditional_array_execution.rs
src/test/ui/consts/const-eval/conditional_array_execution.rs
+1
-0
src/test/ui/consts/const-eval/conditional_array_execution.stderr
...t/ui/consts/const-eval/conditional_array_execution.stderr
+7
-1
src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs
src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs
+2
-0
src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr
src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr
+18
-2
src/test/ui/consts/const-eval/issue-43197.rs
src/test/ui/consts/const-eval/issue-43197.rs
+2
-0
src/test/ui/consts/const-eval/issue-43197.stderr
src/test/ui/consts/const-eval/issue-43197.stderr
+13
-1
src/test/ui/consts/const-eval/issue-44578.rs
src/test/ui/consts/const-eval/issue-44578.rs
+2
-1
src/test/ui/consts/const-eval/issue-44578.stderr
src/test/ui/consts/const-eval/issue-44578.stderr
+7
-1
src/test/ui/consts/const-eval/issue-50814.rs
src/test/ui/consts/const-eval/issue-50814.rs
+4
-2
src/test/ui/consts/const-eval/issue-50814.stderr
src/test/ui/consts/const-eval/issue-50814.stderr
+1
-1
src/test/ui/consts/const-eval/promoted_errors.rs
src/test/ui/consts/const-eval/promoted_errors.rs
+2
-0
src/test/ui/consts/const-eval/promoted_errors.stderr
src/test/ui/consts/const-eval/promoted_errors.stderr
+18
-5
src/test/ui/consts/const-eval/promoted_errors2.rs
src/test/ui/consts/const-eval/promoted_errors2.rs
+2
-0
src/test/ui/consts/const-eval/promoted_errors2.stderr
src/test/ui/consts/const-eval/promoted_errors2.stderr
+18
-5
src/test/ui/consts/const-eval/ub-nonnull.stderr
src/test/ui/consts/const-eval/ub-nonnull.stderr
+1
-1
src/test/ui/consts/miri_unleashed/non_const_fn.rs
src/test/ui/consts/miri_unleashed/non_const_fn.rs
+3
-1
src/test/ui/consts/miri_unleashed/non_const_fn.stderr
src/test/ui/consts/miri_unleashed/non_const_fn.stderr
+7
-1
src/test/ui/consts/zst_no_llvm_alloc.rs
src/test/ui/consts/zst_no_llvm_alloc.rs
+6
-4
src/test/ui/invalid_const_promotion.rs
src/test/ui/invalid_const_promotion.rs
+0
-61
src/test/ui/symbol-names/impl1.legacy.stderr
src/test/ui/symbol-names/impl1.legacy.stderr
+2
-2
未找到文件。
src/librustc/mir/interpret/queries.rs
浏览文件 @
16887192
...
...
@@ -36,11 +36,16 @@ pub fn const_eval_resolve(
param_env
:
ty
::
ParamEnv
<
'tcx
>
,
def_id
:
DefId
,
substs
:
SubstsRef
<
'tcx
>
,
promoted
:
Option
<
mir
::
Promoted
>
,
span
:
Option
<
Span
>
,
)
->
ConstEvalResult
<
'tcx
>
{
let
instance
=
ty
::
Instance
::
resolve
(
self
,
param_env
,
def_id
,
substs
);
if
let
Some
(
instance
)
=
instance
{
self
.const_eval_instance
(
param_env
,
instance
,
span
)
if
let
Some
(
promoted
)
=
promoted
{
self
.const_eval_promoted
(
instance
,
promoted
)
}
else
{
self
.const_eval_instance
(
param_env
,
instance
,
span
)
}
}
else
{
Err
(
ErrorHandled
::
TooGeneric
)
}
...
...
src/librustc/mir/mod.rs
浏览文件 @
16887192
...
...
@@ -166,6 +166,16 @@ pub struct Body<'tcx> {
/// A span representing this MIR, for error reporting.
pub
span
:
Span
,
/// The user may be writing e.g. &[(SOME_CELL, 42)][i].1 and this would get promoted, because
/// we'd statically know that no thing with interior mutability will ever be available to the
/// user without some serious unsafe code. Now this means that our promoted is actually
/// &[(SOME_CELL, 42)] and the MIR using it will do the &promoted[i].1 projection because the
/// index may be a runtime value. Such a promoted value is illegal because it has reachable
/// interior mutability. This flag just makes this situation very obvious where the previous
/// implementation without the flag hid this situation silently.
/// FIXME(oli-obk): rewrite the promoted during promotion to eliminate the cell components.
pub
ignore_interior_mut_in_const_validation
:
bool
,
}
impl
<
'tcx
>
Body
<
'tcx
>
{
...
...
@@ -202,6 +212,7 @@ pub fn new(
spread_arg
:
None
,
var_debug_info
,
span
,
ignore_interior_mut_in_const_validation
:
false
,
control_flow_destroyed
,
}
}
...
...
src/librustc/traits/fulfill.rs
浏览文件 @
16887192
...
...
@@ -515,6 +515,7 @@ fn infer_ty(ty: Ty<'tcx>) -> ty::InferTy {
obligation
.param_env
,
def_id
,
substs
,
None
,
Some
(
obligation
.cause.span
),
)
{
Ok
(
_
)
=>
ProcessResult
::
Changed
(
vec!
[]),
...
...
src/librustc/traits/select.rs
浏览文件 @
16887192
...
...
@@ -802,8 +802,13 @@ fn evaluate_predicate_recursively<'o>(
ty
::
Predicate
::
ConstEvaluatable
(
def_id
,
substs
)
=>
{
if
!
(
obligation
.param_env
,
substs
)
.has_local_value
()
{
match
self
.tcx
()
.const_eval_resolve
(
obligation
.param_env
,
def_id
,
substs
,
None
)
{
match
self
.tcx
()
.const_eval_resolve
(
obligation
.param_env
,
def_id
,
substs
,
None
,
None
,
)
{
Ok
(
_
)
=>
Ok
(
EvaluatedToOk
),
Err
(
_
)
=>
Ok
(
EvaluatedToErr
),
}
...
...
src/librustc/traits/wf.rs
浏览文件 @
16887192
...
...
@@ -359,7 +359,9 @@ fn compute_projection(&mut self, data: ty::ProjectionTy<'tcx>) {
/// Pushes the obligations required for an array length to be WF
/// into `self.out`.
fn
compute_array_len
(
&
mut
self
,
constant
:
ty
::
Const
<
'tcx
>
)
{
if
let
ty
::
ConstKind
::
Unevaluated
(
def_id
,
substs
)
=
constant
.val
{
if
let
ty
::
ConstKind
::
Unevaluated
(
def_id
,
substs
,
promoted
)
=
constant
.val
{
assert
!
(
promoted
.is_none
());
let
obligations
=
self
.nominal_obligations
(
def_id
,
substs
);
self
.out
.extend
(
obligations
);
...
...
src/librustc/ty/flags.rs
浏览文件 @
16887192
...
...
@@ -219,7 +219,7 @@ fn add_region(&mut self, r: ty::Region<'_>) {
fn
add_const
(
&
mut
self
,
c
:
&
ty
::
Const
<
'_
>
)
{
self
.add_ty
(
c
.ty
);
match
c
.val
{
ty
::
ConstKind
::
Unevaluated
(
_
,
substs
)
=>
{
ty
::
ConstKind
::
Unevaluated
(
_
,
substs
,
_
)
=>
{
self
.add_substs
(
substs
);
self
.add_flags
(
TypeFlags
::
HAS_PROJECTION
);
}
...
...
src/librustc/ty/print/pretty.rs
浏览文件 @
16887192
...
...
@@ -841,23 +841,31 @@ fn pretty_print_const(mut self, ct: &'tcx ty::Const<'tcx>) -> Result<Self::Const
match
(
ct
.val
,
&
ct
.ty.kind
)
{
(
_
,
ty
::
FnDef
(
did
,
substs
))
=>
p!
(
print_value_path
(
*
did
,
substs
)),
(
ty
::
ConstKind
::
Unevaluated
(
did
,
substs
),
_
)
=>
match
self
.tcx
()
.def_kind
(
did
)
{
Some
(
DefKind
::
Static
)
|
Some
(
DefKind
::
Const
)
|
Some
(
DefKind
::
AssocConst
)
=>
{
p!
(
print_value_path
(
did
,
substs
))
}
_
=>
{
if
did
.is_local
()
{
let
span
=
self
.tcx
()
.def_span
(
did
);
if
let
Ok
(
snip
)
=
self
.tcx
()
.sess
.source_map
()
.span_to_snippet
(
span
)
{
p!
(
write
(
"{}"
,
snip
))
}
else
{
p!
(
write
(
"_: "
),
print
(
ct
.ty
))
(
ty
::
ConstKind
::
Unevaluated
(
did
,
substs
,
promoted
),
_
)
=>
{
if
let
Some
(
promoted
)
=
promoted
{
p!
(
print_value_path
(
did
,
substs
));
p!
(
write
(
"::{:?}"
,
promoted
));
}
else
{
match
self
.tcx
()
.def_kind
(
did
)
{
Some
(
DefKind
::
Static
)
|
Some
(
DefKind
::
Const
)
|
Some
(
DefKind
::
AssocConst
)
=>
p!
(
print_value_path
(
did
,
substs
)),
_
=>
{
if
did
.is_local
()
{
let
span
=
self
.tcx
()
.def_span
(
did
);
if
let
Ok
(
snip
)
=
self
.tcx
()
.sess
.source_map
()
.span_to_snippet
(
span
)
{
p!
(
write
(
"{}"
,
snip
))
}
else
{
p!
(
write
(
"_: "
),
print
(
ct
.ty
))
}
}
else
{
p!
(
write
(
"_: "
),
print
(
ct
.ty
))
}
}
}
else
{
p!
(
write
(
"_: "
),
print
(
ct
.ty
))
}
}
}
,
}
(
ty
::
ConstKind
::
Infer
(
..
),
_
)
=>
p!
(
write
(
"_: "
),
print
(
ct
.ty
)),
(
ty
::
ConstKind
::
Param
(
ParamConst
{
name
,
..
}),
_
)
=>
p!
(
write
(
"{}"
,
name
)),
(
ty
::
ConstKind
::
Value
(
value
),
_
)
=>
return
self
.pretty_print_const_value
(
value
,
ct
.ty
),
...
...
src/librustc/ty/relate.rs
浏览文件 @
16887192
...
...
@@ -568,12 +568,12 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
// FIXME(const_generics): this is wrong, as it is a projection
(
ty
::
ConstKind
::
Unevaluated
(
a_def_id
,
a_substs
),
ty
::
ConstKind
::
Unevaluated
(
b_def_id
,
b_substs
),
)
if
a_def_id
==
b_def_id
=>
{
ty
::
ConstKind
::
Unevaluated
(
a_def_id
,
a_substs
,
a_promoted
),
ty
::
ConstKind
::
Unevaluated
(
b_def_id
,
b_substs
,
b_promoted
),
)
if
a_def_id
==
b_def_id
&&
a_promoted
==
b_promoted
=>
{
let
substs
=
relation
.relate_with_variance
(
ty
::
Variance
::
Invariant
,
&
a_substs
,
&
b_substs
)
?
;
Ok
(
ty
::
ConstKind
::
Unevaluated
(
a_def_id
,
&
substs
))
Ok
(
ty
::
ConstKind
::
Unevaluated
(
a_def_id
,
&
substs
,
a_promoted
))
}
_
=>
Err
(
TypeError
::
ConstMismatch
(
expected_found
(
relation
,
&
a
,
&
b
))),
};
...
...
src/librustc/ty/structural_impls.rs
浏览文件 @
16887192
...
...
@@ -1037,8 +1037,8 @@ fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
match
*
self
{
ty
::
ConstKind
::
Infer
(
ic
)
=>
ty
::
ConstKind
::
Infer
(
ic
.fold_with
(
folder
)),
ty
::
ConstKind
::
Param
(
p
)
=>
ty
::
ConstKind
::
Param
(
p
.fold_with
(
folder
)),
ty
::
ConstKind
::
Unevaluated
(
did
,
substs
)
=>
{
ty
::
ConstKind
::
Unevaluated
(
did
,
substs
.fold_with
(
folder
))
ty
::
ConstKind
::
Unevaluated
(
did
,
substs
,
promoted
)
=>
{
ty
::
ConstKind
::
Unevaluated
(
did
,
substs
.fold_with
(
folder
)
,
promoted
)
}
ty
::
ConstKind
::
Value
(
_
)
|
ty
::
ConstKind
::
Bound
(
..
)
|
ty
::
ConstKind
::
Placeholder
(
..
)
=>
{
*
self
...
...
@@ -1050,7 +1050,7 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
match
*
self
{
ty
::
ConstKind
::
Infer
(
ic
)
=>
ic
.visit_with
(
visitor
),
ty
::
ConstKind
::
Param
(
p
)
=>
p
.visit_with
(
visitor
),
ty
::
ConstKind
::
Unevaluated
(
_
,
substs
)
=>
substs
.visit_with
(
visitor
),
ty
::
ConstKind
::
Unevaluated
(
_
,
substs
,
_
)
=>
substs
.visit_with
(
visitor
),
ty
::
ConstKind
::
Value
(
_
)
|
ty
::
ConstKind
::
Bound
(
..
)
|
ty
::
ConstKind
::
Placeholder
(
_
)
=>
{
false
}
...
...
src/librustc/ty/sty.rs
浏览文件 @
16887192
...
...
@@ -9,6 +9,7 @@
use
crate
::
middle
::
region
;
use
crate
::
mir
::
interpret
::
ConstValue
;
use
crate
::
mir
::
interpret
::
Scalar
;
use
crate
::
mir
::
Promoted
;
use
crate
::
ty
::
layout
::
VariantIdx
;
use
crate
::
ty
::
subst
::{
GenericArg
,
GenericArgKind
,
InternalSubsts
,
Subst
,
SubstsRef
};
use
crate
::
ty
::{
self
,
AdtDef
,
DefIdTree
,
Discr
,
Ty
,
TyCtxt
,
TypeFlags
,
TypeFoldable
};
...
...
@@ -2375,7 +2376,7 @@ pub fn try_eval_bits(
#[inline]
pub
fn
eval
(
&
self
,
tcx
:
TyCtxt
<
'tcx
>
,
param_env
:
ParamEnv
<
'tcx
>
)
->
&
Const
<
'tcx
>
{
let
try_const_eval
=
|
did
,
param_env
:
ParamEnv
<
'tcx
>
,
substs
|
{
let
try_const_eval
=
|
did
,
param_env
:
ParamEnv
<
'tcx
>
,
substs
,
promoted
|
{
let
param_env_and_substs
=
param_env
.with_reveal_all
()
.and
(
substs
);
// Avoid querying `tcx.const_eval(...)` with any e.g. inference vars.
...
...
@@ -2387,11 +2388,11 @@ pub fn eval(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> &Const<'tcx>
// try to resolve e.g. associated constants to their definition on an impl, and then
// evaluate the const.
tcx
.const_eval_resolve
(
param_env
,
did
,
substs
,
None
)
.ok
()
tcx
.const_eval_resolve
(
param_env
,
did
,
substs
,
promoted
,
None
)
.ok
()
};
match
self
.val
{
ConstKind
::
Unevaluated
(
did
,
substs
)
=>
{
ConstKind
::
Unevaluated
(
did
,
substs
,
promoted
)
=>
{
// HACK(eddyb) when substs contain e.g. inference variables,
// attempt using identity substs instead, that will succeed
// when the expression doesn't depend on any parameters.
...
...
@@ -2401,12 +2402,12 @@ pub fn eval(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> &Const<'tcx>
let
identity_substs
=
InternalSubsts
::
identity_for_item
(
tcx
,
did
);
// The `ParamEnv` needs to match the `identity_substs`.
let
identity_param_env
=
tcx
.param_env
(
did
);
match
try_const_eval
(
did
,
identity_param_env
,
identity_substs
)
{
match
try_const_eval
(
did
,
identity_param_env
,
identity_substs
,
promoted
)
{
Some
(
ct
)
=>
ct
.subst
(
tcx
,
substs
),
None
=>
self
,
}
}
else
{
try_const_eval
(
did
,
param_env
,
substs
)
.unwrap_or
(
self
)
try_const_eval
(
did
,
param_env
,
substs
,
promoted
)
.unwrap_or
(
self
)
}
}
_
=>
self
,
...
...
@@ -2470,7 +2471,7 @@ pub enum ConstKind<'tcx> {
/// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other
/// variants when the code is monomorphic enough for that.
Unevaluated
(
DefId
,
SubstsRef
<
'tcx
>
),
Unevaluated
(
DefId
,
SubstsRef
<
'tcx
>
,
Option
<
Promoted
>
),
/// Used to hold computed value.
Value
(
ConstValue
<
'tcx
>
),
...
...
src/librustc/ty/walk.rs
浏览文件 @
16887192
...
...
@@ -81,7 +81,8 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
|
ty
::
Bound
(
..
)
|
ty
::
Foreign
(
..
)
=>
{}
ty
::
Array
(
ty
,
len
)
=>
{
if
let
ty
::
ConstKind
::
Unevaluated
(
_
,
substs
)
=
len
.val
{
if
let
ty
::
ConstKind
::
Unevaluated
(
_
,
substs
,
promoted
)
=
len
.val
{
assert
!
(
promoted
.is_none
());
stack
.extend
(
substs
.types
()
.rev
());
}
stack
.push
(
len
.ty
);
...
...
src/librustc_codegen_ssa/mir/constant.rs
浏览文件 @
16887192
...
...
@@ -20,7 +20,10 @@ pub fn eval_mir_constant_to_operand(
// use `get_static` to get at their id.
// FIXME(oli-obk): can we unify this somehow, maybe by making const eval of statics
// always produce `&STATIC`. This may also simplify how const eval works with statics.
ty
::
ConstKind
::
Unevaluated
(
def_id
,
substs
)
if
self
.cx
.tcx
()
.is_static
(
def_id
)
=>
{
ty
::
ConstKind
::
Unevaluated
(
def_id
,
substs
,
promoted
)
if
self
.cx
.tcx
()
.is_static
(
def_id
)
=>
{
assert
!
(
promoted
.is_none
());
assert
!
(
substs
.is_empty
(),
"we don't support generic statics yet"
);
let
static_
=
bx
.get_static
(
def_id
);
// we treat operands referring to statics as if they were `&STATIC` instead
...
...
@@ -40,11 +43,11 @@ pub fn eval_mir_constant(
constant
:
&
mir
::
Constant
<
'tcx
>
,
)
->
Result
<&
'tcx
ty
::
Const
<
'tcx
>
,
ErrorHandled
>
{
match
constant
.literal.val
{
ty
::
ConstKind
::
Unevaluated
(
def_id
,
substs
)
=>
{
ty
::
ConstKind
::
Unevaluated
(
def_id
,
substs
,
promoted
)
=>
{
let
substs
=
self
.monomorphize
(
&
substs
);
self
.cx
.tcx
()
.const_eval_resolve
(
ty
::
ParamEnv
::
reveal_all
(),
def_id
,
substs
,
None
)
.const_eval_resolve
(
ty
::
ParamEnv
::
reveal_all
(),
def_id
,
substs
,
promoted
,
None
)
.map_err
(|
err
|
{
self
.cx
.tcx
()
...
...
src/librustc_mir/borrow_check/type_check/mod.rs
浏览文件 @
16887192
...
...
@@ -310,17 +310,54 @@ fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
);
}
}
else
{
if
let
ty
::
ConstKind
::
Unevaluated
(
def_id
,
substs
)
=
constant
.literal.val
{
if
let
Err
(
terr
)
=
self
.cx
.fully_perform_op
(
location
.to_locations
(),
ConstraintCategory
::
Boring
,
self
.cx.param_env
.and
(
type_op
::
ascribe_user_type
::
AscribeUserType
::
new
(
constant
.literal.ty
,
def_id
,
UserSubsts
{
substs
,
user_self_ty
:
None
},
)),
)
{
span_mirbug!
(
self
,
constant
,
"bad constant type {:?} ({:?})"
,
constant
,
terr
);
if
let
ty
::
ConstKind
::
Unevaluated
(
def_id
,
substs
,
promoted
)
=
constant
.literal.val
{
if
let
Some
(
promoted
)
=
promoted
{
let
check_err
=
|
verifier
:
&
mut
TypeVerifier
<
'a
,
'b
,
'tcx
>
,
promoted
:
&
ReadOnlyBodyAndCache
<
'_
,
'tcx
>
,
ty
,
san_ty
|
{
if
let
Err
(
terr
)
=
verifier
.cx
.eq_types
(
san_ty
,
ty
,
location
.to_locations
(),
ConstraintCategory
::
Boring
,
)
{
span_mirbug!
(
verifier
,
promoted
,
"bad promoted type ({:?}: {:?}): {:?}"
,
ty
,
san_ty
,
terr
);
};
};
if
!
self
.errors_reported
{
let
promoted_body
=
self
.promoted
[
promoted
];
self
.sanitize_promoted
(
promoted_body
,
location
);
let
promoted_ty
=
promoted_body
.return_ty
();
check_err
(
self
,
&
promoted_body
,
ty
,
promoted_ty
);
}
}
else
{
if
let
Err
(
terr
)
=
self
.cx
.fully_perform_op
(
location
.to_locations
(),
ConstraintCategory
::
Boring
,
self
.cx.param_env
.and
(
type_op
::
ascribe_user_type
::
AscribeUserType
::
new
(
constant
.literal.ty
,
def_id
,
UserSubsts
{
substs
,
user_self_ty
:
None
},
)),
)
{
span_mirbug!
(
self
,
constant
,
"bad constant type {:?} ({:?})"
,
constant
,
terr
);
}
}
}
if
let
ty
::
FnDef
(
def_id
,
substs
)
=
constant
.literal.ty.kind
{
...
...
src/librustc_mir/const_eval.rs
浏览文件 @
16887192
...
...
@@ -52,7 +52,7 @@ pub(crate) fn const_caller_location<'tcx>(
let
loc_ty
=
tcx
.caller_location_ty
();
let
loc_place
=
ecx
.alloc_caller_location
(
file
,
line
,
col
);
intern_const_alloc_recursive
(
&
mut
ecx
,
None
,
loc_place
)
.unwrap
();
intern_const_alloc_recursive
(
&
mut
ecx
,
None
,
loc_place
,
false
)
.unwrap
();
let
loc_const
=
ty
::
Const
{
ty
:
loc_ty
,
val
:
ty
::
ConstKind
::
Value
(
ConstValue
::
Scalar
(
loc_place
.ptr
.into
())),
...
...
src/librustc_mir/const_eval/eval_queries.rs
浏览文件 @
16887192
...
...
@@ -56,7 +56,12 @@ fn eval_body_using_ecx<'mir, 'tcx>(
ecx
.run
()
?
;
// Intern the result
intern_const_alloc_recursive
(
ecx
,
tcx
.static_mutability
(
cid
.instance
.def_id
()),
ret
)
?
;
intern_const_alloc_recursive
(
ecx
,
tcx
.static_mutability
(
cid
.instance
.def_id
()),
ret
,
body
.ignore_interior_mut_in_const_validation
,
)
?
;
debug!
(
"eval_body_using_ecx done: {:?}"
,
*
ret
);
Ok
(
ret
)
...
...
@@ -171,9 +176,14 @@ fn validate_and_turn_into_const<'tcx>(
let
ecx
=
mk_eval_cx
(
tcx
,
tcx
.def_span
(
key
.value.instance
.def_id
()),
key
.param_env
,
is_static
);
let
val
=
(||
{
let
mplace
=
ecx
.raw_const_to_mplace
(
constant
)
?
;
let
mut
ref_tracking
=
RefTracking
::
new
(
mplace
);
while
let
Some
((
mplace
,
path
))
=
ref_tracking
.todo
.pop
()
{
ecx
.validate_operand
(
mplace
.into
(),
path
,
Some
(
&
mut
ref_tracking
))
?
;
// FIXME do not validate promoteds until a decision on
// https://github.com/rust-lang/rust/issues/67465 is made
if
cid
.promoted
.is_none
()
{
let
mut
ref_tracking
=
RefTracking
::
new
(
mplace
);
while
let
Some
((
mplace
,
path
))
=
ref_tracking
.todo
.pop
()
{
ecx
.validate_operand
(
mplace
.into
(),
path
,
Some
(
&
mut
ref_tracking
))
?
;
}
}
// Now that we validated, turn this into a proper constant.
// Statics/promoteds are always `ByRef`, for the rest `op_to_const` decides
...
...
src/librustc_mir/hair/cx/expr.rs
浏览文件 @
16887192
...
...
@@ -411,15 +411,18 @@ fn make_mirror_unadjusted<'a, 'tcx>(
let
def_id
=
cx
.tcx
.hir
()
.local_def_id
(
count
.hir_id
);
let
substs
=
InternalSubsts
::
identity_for_item
(
cx
.tcx
,
def_id
);
let
span
=
cx
.tcx
.def_span
(
def_id
);
let
count
=
match
cx
.tcx
.const_eval_resolve
(
cx
.param_env
,
def_id
,
substs
,
Some
(
span
))
{
Ok
(
cv
)
=>
cv
.eval_usize
(
cx
.tcx
,
cx
.param_env
),
Err
(
ErrorHandled
::
Reported
)
=>
0
,
Err
(
ErrorHandled
::
TooGeneric
)
=>
{
let
span
=
cx
.tcx
.def_span
(
def_id
);
cx
.tcx.sess
.span_err
(
span
,
"array lengths can't depend on generic parameters"
);
0
}
};
let
count
=
match
cx
.tcx
.const_eval_resolve
(
cx
.param_env
,
def_id
,
substs
,
None
,
Some
(
span
))
{
Ok
(
cv
)
=>
cv
.eval_usize
(
cx
.tcx
,
cx
.param_env
),
Err
(
ErrorHandled
::
Reported
)
=>
0
,
Err
(
ErrorHandled
::
TooGeneric
)
=>
{
let
span
=
cx
.tcx
.def_span
(
def_id
);
cx
.tcx
.sess
.span_err
(
span
,
"array lengths can't depend on generic parameters"
);
0
}
};
ExprKind
::
Repeat
{
value
:
v
.to_ref
(),
count
}
}
...
...
@@ -523,7 +526,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
// and not the beginning of discriminants (which is always `0`)
let
substs
=
InternalSubsts
::
identity_for_item
(
cx
.tcx
(),
did
);
let
lhs
=
mk_const
(
cx
.tcx
()
.mk_const
(
ty
::
Const
{
val
:
ty
::
ConstKind
::
Unevaluated
(
did
,
substs
),
val
:
ty
::
ConstKind
::
Unevaluated
(
did
,
substs
,
None
),
ty
:
var_ty
,
}));
let
bin
=
ExprKind
::
Binary
{
op
:
BinOp
::
Add
,
lhs
,
rhs
:
offset
};
...
...
@@ -719,7 +722,7 @@ fn convert_path_expr<'a, 'tcx>(
debug!
(
"convert_path_expr: (const) user_ty={:?}"
,
user_ty
);
ExprKind
::
Literal
{
literal
:
cx
.tcx
.mk_const
(
ty
::
Const
{
val
:
ty
::
ConstKind
::
Unevaluated
(
def_id
,
substs
),
val
:
ty
::
ConstKind
::
Unevaluated
(
def_id
,
substs
,
None
),
ty
:
cx
.tables
()
.node_type
(
expr
.hir_id
),
}),
user_ty
,
...
...
src/librustc_mir/hair/pattern/mod.rs
浏览文件 @
16887192
...
...
@@ -749,6 +749,7 @@ fn lower_path(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, span: Span) ->
self
.param_env
.with_reveal_all
(),
def_id
,
substs
,
None
,
Some
(
span
),
)
{
Ok
(
value
)
=>
{
...
...
src/librustc_mir/interpret/intern.rs
浏览文件 @
16887192
...
...
@@ -41,6 +41,11 @@ struct InternVisitor<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> {
/// despite the nested mutable reference!
/// The field gets updated when an `UnsafeCell` is encountered.
mutability
:
Mutability
,
/// This flag is to avoid triggering UnsafeCells are not allowed behind references in constants
/// for promoteds.
/// It's a copy of `mir::Body`'s ignore_interior_mut_in_const_validation field
ignore_interior_mut_in_const_validation
:
bool
,
}
#[derive(Copy,
Clone,
Debug,
PartialEq,
Hash,
Eq)]
...
...
@@ -164,14 +169,16 @@ fn visit_aggregate(
// References we encounter inside here are interned as pointing to mutable
// allocations.
let
old
=
std
::
mem
::
replace
(
&
mut
self
.mutability
,
Mutability
::
Mut
);
assert_ne!
(
self
.mode
,
InternMode
::
Const
,
"UnsafeCells are not allowed behind references in constants. This should have
\
been prevented statically by const qualification. If this were allowed one
\
would be able to change a constant at one use site and other use sites could
\
observe that mutation."
,
);
if
!
self
.ignore_interior_mut_in_const_validation
{
assert_ne!
(
self
.mode
,
InternMode
::
Const
,
"UnsafeCells are not allowed behind references in constants. This should
\
have been prevented statically by const qualification. If this were
\
allowed one would be able to change a constant at one use site and other
\
use sites could observe that mutation."
,
);
}
let
walked
=
self
.walk_aggregate
(
mplace
,
fields
);
self
.mutability
=
old
;
return
walked
;
...
...
@@ -266,6 +273,7 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
// The `mutability` of the place, ignoring the type.
place_mut
:
Option
<
hir
::
Mutability
>
,
ret
:
MPlaceTy
<
'tcx
>
,
ignore_interior_mut_in_const_validation
:
bool
,
)
->
InterpResult
<
'tcx
>
{
let
tcx
=
ecx
.tcx
;
let
(
base_mutability
,
base_intern_mode
)
=
match
place_mut
{
...
...
@@ -302,6 +310,7 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
mode
,
leftover_allocations
,
mutability
,
ignore_interior_mut_in_const_validation
,
}
.visit_value
(
mplace
);
if
let
Err
(
error
)
=
interned
{
...
...
src/librustc_mir/interpret/operand.rs
浏览文件 @
16887192
...
...
@@ -532,7 +532,7 @@ pub(super) fn eval_operands(
// Early-return cases.
let
val_val
=
match
val
.val
{
ty
::
ConstKind
::
Param
(
_
)
=>
throw_inval!
(
TooGeneric
),
ty
::
ConstKind
::
Unevaluated
(
def_id
,
substs
)
=>
{
ty
::
ConstKind
::
Unevaluated
(
def_id
,
substs
,
promoted
)
=>
{
let
instance
=
self
.resolve
(
def_id
,
substs
)
?
;
// We use `const_eval` here and `const_eval_raw` elsewhere in mir interpretation.
// The reason we use `const_eval_raw` everywhere else is to prevent cycles during
...
...
src/librustc_mir/monomorphize/collector.rs
浏览文件 @
16887192
...
...
@@ -1249,8 +1249,8 @@ fn collect_const<'tcx>(
collect_miri
(
tcx
,
id
,
output
);
}
}
ty
::
ConstKind
::
Unevaluated
(
def_id
,
substs
)
=>
{
match
tcx
.const_eval_resolve
(
param_env
,
def_id
,
substs
,
None
)
{
ty
::
ConstKind
::
Unevaluated
(
def_id
,
substs
,
promoted
)
=>
{
match
tcx
.const_eval_resolve
(
param_env
,
def_id
,
substs
,
promoted
,
None
)
{
Ok
(
val
)
=>
collect_const
(
tcx
,
val
,
param_substs
,
output
),
Err
(
ErrorHandled
::
Reported
)
=>
{}
Err
(
ErrorHandled
::
TooGeneric
)
=>
{
...
...
src/librustc_mir/transform/check_consts/qualifs.rs
浏览文件 @
16887192
...
...
@@ -102,7 +102,9 @@ fn in_operand(
// Note: this uses `constant.literal.ty` which is a reference or pointer to the
// type of the actual `static` item.
Self
::
in_any_value_of_ty
(
cx
,
constant
.literal.ty
)
}
else
if
let
ty
::
ConstKind
::
Unevaluated
(
def_id
,
_
)
=
constant
.literal.val
{
}
else
if
let
ty
::
ConstKind
::
Unevaluated
(
def_id
,
_
,
promoted
)
=
constant
.literal.val
{
assert
!
(
promoted
.is_none
());
// Don't peek inside trait associated constants.
if
cx
.tcx
.trait_of_item
(
def_id
)
.is_some
()
{
Self
::
in_any_value_of_ty
(
cx
,
constant
.literal.ty
)
...
...
src/librustc_mir/transform/const_prop.rs
浏览文件 @
16887192
...
...
@@ -17,7 +17,7 @@
use
rustc
::
ty
::
layout
::{
HasDataLayout
,
HasTyCtxt
,
LayoutError
,
LayoutOf
,
Size
,
TargetDataLayout
,
TyLayout
,
};
use
rustc
::
ty
::
subst
::
InternalSubsts
;
use
rustc
::
ty
::
subst
::
{
InternalSubsts
,
Subst
}
;
use
rustc
::
ty
::{
self
,
Instance
,
ParamEnv
,
Ty
,
TyCtxt
,
TypeFoldable
};
use
rustc_data_structures
::
fx
::
FxHashMap
;
use
rustc_hir
::
def
::
DefKind
;
...
...
@@ -33,7 +33,6 @@
LocalState
,
LocalValue
,
Memory
,
MemoryKind
,
OpTy
,
Operand
as
InterpOperand
,
PlaceTy
,
Pointer
,
ScalarMaybeUndef
,
StackPopCleanup
,
};
use
crate
::
rustc
::
ty
::
subst
::
Subst
;
use
crate
::
transform
::{
MirPass
,
MirSource
};
/// The maximum number of bytes that we'll allocate space for a return value.
...
...
@@ -265,6 +264,7 @@ struct ConstPropagator<'mir, 'tcx> {
// Because we have `MutVisitor` we can't obtain the `SourceInfo` from a `Location`. So we store
// the last known `SourceInfo` here and just keep revisiting it.
source_info
:
Option
<
SourceInfo
>
,
lint_root
:
Option
<
HirId
>
,
}
impl
<
'mir
,
'tcx
>
LayoutOf
for
ConstPropagator
<
'mir
,
'tcx
>
{
...
...
@@ -344,6 +344,7 @@ fn new(
local_decls
:
body
.local_decls
.clone
(),
ret
:
ret
.map
(
Into
::
into
),
source_info
:
None
,
lint_root
:
None
,
}
}
...
...
@@ -377,10 +378,6 @@ fn use_ecx<F, T>(&mut self, source_info: SourceInfo, f: F) -> Option<T>
F
:
FnOnce
(
&
mut
Self
)
->
InterpResult
<
'tcx
,
T
>
,
{
self
.ecx.tcx.span
=
source_info
.span
;
// FIXME(eddyb) move this to the `Panic(_)` error case, so that
// `f(self)` is always called, and that the only difference when the
// scope's `local_data` is missing, is that the lint isn't emitted.
let
lint_root
=
self
.lint_root
(
source_info
)
?
;
let
r
=
match
f
(
self
)
{
Ok
(
val
)
=>
Some
(
val
),
Err
(
error
)
=>
{
...
...
@@ -414,7 +411,7 @@ fn use_ecx<F, T>(&mut self, source_info: SourceInfo, f: F) -> Option<T>
diagnostic
.report_as_lint
(
self
.ecx.tcx
,
"this expression will panic at runtime"
,
lint_root
,
self
.lint_root
?
,
None
,
);
}
...
...
@@ -426,17 +423,19 @@ fn use_ecx<F, T>(&mut self, source_info: SourceInfo, f: F) -> Option<T>
r
}
fn
eval_constant
(
&
mut
self
,
c
:
&
Constant
<
'tcx
>
,
source_info
:
SourceInfo
,
)
->
Option
<
Const
<
'tcx
>>
{
fn
eval_constant
(
&
mut
self
,
c
:
&
Constant
<
'tcx
>
)
->
Option
<
Const
<
'tcx
>>
{
self
.ecx.tcx.span
=
c
.span
;
// FIXME we need to revisit this for #67176
if
c
.needs_subst
()
{
return
None
;
}
match
self
.ecx
.eval_const_to_op
(
c
.literal
,
None
)
{
Ok
(
op
)
=>
Some
(
op
),
Err
(
error
)
=>
{
let
err
=
error_to_const_error
(
&
self
.ecx
,
error
);
match
self
.lint_root
(
source_info
)
{
match
self
.lint_root
{
Some
(
lint_root
)
if
c
.literal
.needs_subst
()
=>
{
// Out of backwards compatibility we cannot report hard errors in unused
// generic functions using associated constants of the generic parameters.
...
...
@@ -463,7 +462,7 @@ fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option
fn
eval_operand
(
&
mut
self
,
op
:
&
Operand
<
'tcx
>
,
source_info
:
SourceInfo
)
->
Option
<
Const
<
'tcx
>>
{
match
*
op
{
Operand
::
Constant
(
ref
c
)
=>
self
.eval_constant
(
c
,
source_info
),
Operand
::
Constant
(
ref
c
)
=>
self
.eval_constant
(
c
),
Operand
::
Move
(
ref
place
)
|
Operand
::
Copy
(
ref
place
)
=>
{
self
.eval_place
(
place
,
source_info
)
}
...
...
@@ -552,6 +551,11 @@ fn const_prop(
return
None
;
}
// FIXME we need to revisit this for #67176
if
rvalue
.needs_subst
()
{
return
None
;
}
let
overflow_check
=
self
.tcx.sess
.overflow_checks
();
// Perform any special handling for specific Rvalue types.
...
...
@@ -708,7 +712,7 @@ fn should_const_prop(&mut self, op: OpTy<'tcx>) -> bool {
))
=>
l
.is_bits
()
&&
r
.is_bits
(),
interpret
::
Operand
::
Indirect
(
_
)
if
mir_opt_level
>=
2
=>
{
let
mplace
=
op
.assert_mem_place
(
&
self
.ecx
);
intern_const_alloc_recursive
(
&
mut
self
.ecx
,
None
,
mplace
)
intern_const_alloc_recursive
(
&
mut
self
.ecx
,
None
,
mplace
,
false
)
.expect
(
"failed to intern alloc"
);
true
}
...
...
@@ -797,13 +801,14 @@ fn tcx(&self) -> TyCtxt<'tcx> {
fn
visit_constant
(
&
mut
self
,
constant
:
&
mut
Constant
<
'tcx
>
,
location
:
Location
)
{
trace!
(
"visit_constant: {:?}"
,
constant
);
self
.super_constant
(
constant
,
location
);
self
.eval_constant
(
constant
,
self
.source_info
.unwrap
()
);
self
.eval_constant
(
constant
);
}
fn
visit_statement
(
&
mut
self
,
statement
:
&
mut
Statement
<
'tcx
>
,
location
:
Location
)
{
trace!
(
"visit_statement: {:?}"
,
statement
);
let
source_info
=
statement
.source_info
;
self
.source_info
=
Some
(
source_info
);
self
.lint_root
=
self
.lint_root
(
source_info
);
if
let
StatementKind
::
Assign
(
box
(
ref
place
,
ref
mut
rval
))
=
statement
.kind
{
let
place_ty
:
Ty
<
'tcx
>
=
place
.ty
(
&
self
.local_decls
,
self
.tcx
)
.ty
;
if
let
Ok
(
place_layout
)
=
self
.tcx
.layout_of
(
self
.param_env
.and
(
place_ty
))
{
...
...
@@ -855,6 +860,7 @@ fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, location: Loca
let
source_info
=
terminator
.source_info
;
self
.source_info
=
Some
(
source_info
);
self
.super_terminator
(
terminator
,
location
);
self
.lint_root
=
self
.lint_root
(
source_info
);
match
&
mut
terminator
.kind
{
TerminatorKind
::
Assert
{
expected
,
ref
msg
,
ref
mut
cond
,
..
}
=>
{
if
let
Some
(
value
)
=
self
.eval_operand
(
&
cond
,
source_info
)
{
...
...
src/librustc_mir/transform/promote_consts.rs
浏览文件 @
16887192
...
...
@@ -27,7 +27,7 @@
use
rustc_target
::
spec
::
abi
::
Abi
;
use
std
::
cell
::
Cell
;
use
std
::{
iter
,
mem
,
usize
};
use
std
::{
cmp
,
iter
,
mem
,
usize
};
use
crate
::
const_eval
::{
is_const_fn
,
is_unstable_const_fn
};
use
crate
::
transform
::
check_consts
::{
is_lang_panic_fn
,
qualifs
,
ConstKind
,
Item
};
...
...
@@ -761,6 +761,7 @@ struct Promoter<'a, 'tcx> {
source
:
&
'a
mut
BodyAndCache
<
'tcx
>
,
promoted
:
BodyAndCache
<
'tcx
>
,
temps
:
&
'a
mut
IndexVec
<
Local
,
TempState
>
,
extra_statements
:
&
'a
mut
Vec
<
(
Location
,
Statement
<
'tcx
>
)
>
,
/// If true, all nested temps are also kept in the
/// source MIR, not moved to the promoted MIR.
...
...
@@ -903,7 +904,7 @@ fn promote_candidate(
candidate
:
Candidate
,
next_promoted_id
:
usize
,
)
->
Option
<
BodyAndCache
<
'tcx
>>
{
let
mut
operand
=
{
let
mut
rvalue
=
{
let
promoted
=
&
mut
self
.promoted
;
let
promoted_id
=
Promoted
::
new
(
next_promoted_id
);
let
tcx
=
self
.tcx
;
...
...
@@ -927,15 +928,70 @@ fn promote_candidate(
Candidate
::
Ref
(
loc
)
=>
{
let
ref
mut
statement
=
blocks
[
loc
.block
]
.statements
[
loc
.statement_index
];
match
statement
.kind
{
StatementKind
::
Assign
(
box
(
_
,
Rvalue
::
Ref
(
_
,
_
,
ref
mut
place
)))
=>
{
StatementKind
::
Assign
(
box
(
_
,
Rvalue
::
Ref
(
ref
mut
region
,
borrow_kind
,
ref
mut
place
),
))
=>
{
// Use the underlying local for this (necessarily interior) borrow.
let
ty
=
place
.base
.ty
(
local_decls
)
.ty
;
let
span
=
statement
.source_info.span
;
Operand
::
Move
(
Place
{
base
:
mem
::
replace
(
&
mut
place
.base
,
promoted_place
(
ty
,
span
)
.base
),
projection
:
List
::
empty
(),
})
let
ref_ty
=
tcx
.mk_ref
(
tcx
.lifetimes.re_static
,
ty
::
TypeAndMut
{
ty
,
mutbl
:
borrow_kind
.to_mutbl_lossy
()
},
);
promoted
.span
=
span
;
promoted
.local_decls
[
RETURN_PLACE
]
=
LocalDecl
::
new_return_place
(
ref_ty
,
span
);
*
region
=
tcx
.lifetimes.re_static
;
let
mut
projection
=
vec!
[
PlaceElem
::
Deref
];
projection
.extend
(
place
.projection
);
place
.projection
=
tcx
.intern_place_elems
(
&
projection
);
// Create a temp to hold the promoted reference.
// This is because `*r` requires `r` to be a local,
// otherwise we would use the `promoted` directly.
let
mut
promoted_ref
=
LocalDecl
::
new_temp
(
ref_ty
,
span
);
promoted_ref
.source_info
=
statement
.source_info
;
let
promoted_ref
=
local_decls
.push
(
promoted_ref
);
assert_eq!
(
self
.temps
.push
(
TempState
::
Unpromotable
),
promoted_ref
);
let
promoted_ref_rvalue
=
Rvalue
::
Use
(
Operand
::
Constant
(
Box
::
new
(
Constant
{
span
,
user_ty
:
None
,
literal
:
tcx
.mk_const
(
ty
::
Const
{
ty
:
ref_ty
,
val
:
ty
::
ConstKind
::
Unevaluated
(
def_id
,
InternalSubsts
::
identity_for_item
(
tcx
,
def_id
),
Some
(
promoted_id
),
),
}),
})));
let
promoted_ref_statement
=
Statement
{
source_info
:
statement
.source_info
,
kind
:
StatementKind
::
Assign
(
Box
::
new
((
Place
::
from
(
promoted_ref
),
promoted_ref_rvalue
,
))),
};
self
.extra_statements
.push
((
loc
,
promoted_ref_statement
));
Rvalue
::
Ref
(
tcx
.lifetimes.re_static
,
borrow_kind
,
Place
{
base
:
mem
::
replace
(
&
mut
place
.base
,
PlaceBase
::
Local
(
promoted_ref
),
),
projection
:
List
::
empty
(),
},
)
}
_
=>
bug!
(),
}
...
...
@@ -946,7 +1002,10 @@ fn promote_candidate(
StatementKind
::
Assign
(
box
(
_
,
Rvalue
::
Repeat
(
ref
mut
operand
,
_
)))
=>
{
let
ty
=
operand
.ty
(
local_decls
,
self
.tcx
);
let
span
=
statement
.source_info.span
;
mem
::
replace
(
operand
,
Operand
::
Copy
(
promoted_place
(
ty
,
span
)))
Rvalue
::
Use
(
mem
::
replace
(
operand
,
Operand
::
Copy
(
promoted_place
(
ty
,
span
)),
))
}
_
=>
bug!
(),
}
...
...
@@ -958,7 +1017,7 @@ fn promote_candidate(
let
ty
=
args
[
index
]
.ty
(
local_decls
,
self
.tcx
);
let
span
=
terminator
.source_info.span
;
let
operand
=
Operand
::
Copy
(
promoted_place
(
ty
,
span
));
mem
::
replace
(
&
mut
args
[
index
],
operand
)
Rvalue
::
Use
(
mem
::
replace
(
&
mut
args
[
index
],
operand
)
)
}
// We expected a `TerminatorKind::Call` for which we'd like to promote an
// argument. `qualify_consts` saw a `TerminatorKind::Call` here, but
...
...
@@ -975,13 +1034,13 @@ fn promote_candidate(
};
assert_eq!
(
self
.new_block
(),
START_BLOCK
);
self
.visit_
operand
(
&
mut
operand
,
self
.visit_
rvalue
(
&
mut
rvalue
,
Location
{
block
:
BasicBlock
::
new
(
0
),
statement_index
:
usize
::
MAX
},
);
let
span
=
self
.promoted.span
;
self
.assign
(
RETURN_PLACE
,
Rvalue
::
Use
(
operand
)
,
span
);
self
.assign
(
RETURN_PLACE
,
rvalue
,
span
);
Some
(
self
.promoted
)
}
}
...
...
@@ -1020,6 +1079,7 @@ pub fn promote_candidates<'tcx>(
let
mut
promotions
=
IndexVec
::
new
();
let
mut
extra_statements
=
vec!
[];
for
candidate
in
candidates
.into_iter
()
.rev
()
{
match
candidate
{
Candidate
::
Repeat
(
Location
{
block
,
statement_index
})
...
...
@@ -1043,23 +1103,27 @@ pub fn promote_candidates<'tcx>(
let
initial_locals
=
iter
::
once
(
LocalDecl
::
new_return_place
(
tcx
.types.never
,
body
.span
))
.collect
();
let
mut
promoted
=
Body
::
new
(
IndexVec
::
new
(),
// FIXME: maybe try to filter this to avoid blowing up
// memory usage?
body
.source_scopes
.clone
(),
initial_locals
,
IndexVec
::
new
(),
0
,
vec!
[],
body
.span
,
vec!
[],
body
.generator_kind
,
);
promoted
.ignore_interior_mut_in_const_validation
=
true
;
let
promoter
=
Promoter
{
promoted
:
BodyAndCache
::
new
(
Body
::
new
(
IndexVec
::
new
(),
// FIXME: maybe try to filter this to avoid blowing up
// memory usage?
body
.source_scopes
.clone
(),
initial_locals
,
IndexVec
::
new
(),
0
,
vec!
[],
body
.span
,
vec!
[],
body
.generator_kind
,
)),
promoted
:
BodyAndCache
::
new
(
promoted
),
tcx
,
source
:
body
,
temps
:
&
mut
temps
,
extra_statements
:
&
mut
extra_statements
,
keep_original
:
false
,
};
...
...
@@ -1069,6 +1133,13 @@ pub fn promote_candidates<'tcx>(
}
}
// Insert each of `extra_statements` before its indicated location, which
// has to be done in reverse location order, to not invalidate the rest.
extra_statements
.sort_by_key
(|
&
(
loc
,
_
)|
cmp
::
Reverse
(
loc
));
for
(
loc
,
statement
)
in
extra_statements
{
body
[
loc
.block
]
.statements
.insert
(
loc
.statement_index
,
statement
);
}
// Eliminate assignments to, and drops of promoted temps.
let
promoted
=
|
index
:
Local
|
temps
[
index
]
==
TempState
::
PromotedOut
;
for
block
in
body
.basic_blocks_mut
()
{
...
...
src/librustc_typeck/astconv.rs
浏览文件 @
16887192
...
...
@@ -2697,7 +2697,11 @@ pub fn ast_const_to_const(
let
def_id
=
tcx
.hir
()
.local_def_id
(
ast_const
.hir_id
);
let
mut
const_
=
ty
::
Const
{
val
:
ty
::
ConstKind
::
Unevaluated
(
def_id
,
InternalSubsts
::
identity_for_item
(
tcx
,
def_id
)),
val
:
ty
::
ConstKind
::
Unevaluated
(
def_id
,
InternalSubsts
::
identity_for_item
(
tcx
,
def_id
),
None
,
),
ty
,
};
...
...
src/librustdoc/clean/utils.rs
浏览文件 @
16887192
...
...
@@ -460,12 +460,16 @@ pub fn name_from_pat(p: &hir::Pat) -> String {
pub
fn
print_const
(
cx
:
&
DocContext
<
'_
>
,
n
:
&
ty
::
Const
<
'_
>
)
->
String
{
match
n
.val
{
ty
::
ConstKind
::
Unevaluated
(
def_id
,
_
)
=>
{
if
let
Some
(
hir_id
)
=
cx
.tcx
.hir
()
.as_local_hir_id
(
def_id
)
{
ty
::
ConstKind
::
Unevaluated
(
def_id
,
_
,
promoted
)
=>
{
let
mut
s
=
if
let
Some
(
hir_id
)
=
cx
.tcx
.hir
()
.as_local_hir_id
(
def_id
)
{
print_const_expr
(
cx
,
cx
.tcx
.hir
()
.body_owned_by
(
hir_id
))
}
else
{
inline
::
print_inlined_const
(
cx
,
def_id
)
};
if
let
Some
(
promoted
)
=
promoted
{
s
.push_str
(
&
format!
(
"{:?}"
,
promoted
))
}
s
}
_
=>
{
let
mut
s
=
n
.to_string
();
...
...
src/test/codegen/consts.rs
浏览文件 @
16887192
...
...
@@ -14,7 +14,7 @@
// This checks the constants from {low,high}_align_const, they share the same
// constant, but the alignment differs, so the higher one should be used
// CHECK: [[LOW_HIGH:@[0-9]+]] = {{.*}}
, align 4
// CHECK: [[LOW_HIGH:@[0-9]+]] = {{.*}}
getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* @2, i32 0, i32 0, i32 0), {{.*}}, align 8
#[derive(Copy,
Clone)]
...
...
@@ -44,7 +44,7 @@ pub fn inline_enum_const() -> E<i8, i16> {
#[no_mangle]
pub
fn
low_align_const
()
->
E
<
i16
,
[
i16
;
3
]
>
{
// Check that low_align_const and high_align_const use the same constant
// CHECK:
i8* align 2 getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* [[LOW_HIGH]], i32 0, i32 0, i32 0),
// CHECK:
load %"E<i16, [i16; 3]>"*, %"E<i16, [i16; 3]>"** bitcast (<{ i8*, [0 x i8] }>* [[LOW_HIGH]] to %"E<i16, [i16; 3]>"**), align 8
*&
E
::
A
(
0
)
}
...
...
@@ -52,6 +52,6 @@ pub fn inline_enum_const() -> E<i8, i16> {
#[no_mangle]
pub
fn
high_align_const
()
->
E
<
i16
,
i32
>
{
// Check that low_align_const and high_align_const use the same constant
// CHECK:
i8* align 4 getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* [[LOW_HIGH]], i32 0, i32 0, i32 0),
// CHECK:
load %"E<i16, i32>"*, %"E<i16, i32>"** bitcast (<{ i8*, [0 x i8] }>* [[LOW_HIGH]] to %"E<i16, i32>"**), align 8
*&
E
::
A
(
0
)
}
src/test/
run
-fail/promoted_div_by_zero.rs
→
src/test/
compile
-fail/promoted_div_by_zero.rs
浏览文件 @
16887192
#![allow(const_err)]
// error-pattern:
attempt to divide by zero
// error-pattern:
referenced constant has errors
fn
main
()
{
let
x
=
&
(
1
/
(
1
-
1
));
...
...
src/test/mir-opt/const_prop/ref_deref.rs
浏览文件 @
16887192
...
...
@@ -6,7 +6,8 @@ fn main() {
// START rustc.main.ConstProp.before.mir
// bb0: {
// ...
// _2 = &(promoted[0]: i32);
// _4 = const main::promoted[0];
// _2 = _4;
// _1 = (*_2);
// ...
//}
...
...
@@ -14,7 +15,8 @@ fn main() {
// START rustc.main.ConstProp.after.mir
// bb0: {
// ...
// _2 = &(promoted[0]: i32);
// _4 = const main::promoted[0];
// _2 = _4;
// _1 = const 4i32;
// ...
// }
...
...
src/test/mir-opt/const_prop/slice_len.rs
浏览文件 @
16887192
...
...
@@ -6,7 +6,8 @@ fn main() {
// START rustc.main.ConstProp.before.mir
// bb0: {
// ...
// _4 = &(promoted[0]: [u32; 3]);
// _9 = const main::promoted[0];
// _4 = _9;
// _3 = _4;
// _2 = move _3 as &[u32] (Pointer(Unsize));
// ...
...
...
@@ -24,7 +25,8 @@ fn main() {
// START rustc.main.ConstProp.after.mir
// bb0: {
// ...
// _4 = &(promoted[0]: [u32; 3]);
// _9 = const main::promoted[0];
// _4 = _9;
// _3 = _4;
// _2 = move _3 as &[u32] (Pointer(Unsize));
// ...
...
...
src/test/mir-opt/inline/inline-retag.rs
浏览文件 @
16887192
...
...
@@ -25,11 +25,11 @@ fn foo(x: &i32, y: &i32) -> bool {
// ...
// Retag(_3);
// Retag(_6);
// StorageLive(_
9
);
// _
9
= (*_3);
// StorageLive(_1
0
);
// _1
0
= (*_6);
// _0 = Eq(move _
9, move _10
);
// StorageLive(_
11
);
// _
11
= (*_3);
// StorageLive(_1
2
);
// _1
2
= (*_6);
// _0 = Eq(move _
11, move _12
);
// ...
// return;
// }
...
...
src/test/mir-opt/match_false_edges.rs
浏览文件 @
16887192
...
...
@@ -65,7 +65,8 @@ fn main() {
// }
// bb6: { // binding1 and guard
// StorageLive(_6);
// _6 = &(((promoted[0]: std::option::Option<i32>) as Some).0: i32);
// _11 = const full_tested_match::promoted[0];
// _6 = &(((*_11) as Some).0: i32);
// _4 = &shallow _2;
// StorageLive(_7);
// _7 = const guard() -> [return: bb7, unwind: bb1];
...
...
src/test/ui/consts/array-literal-index-oob.rs
浏览文件 @
16887192
...
...
@@ -4,4 +4,5 @@ fn main() {
&
{[
1
,
2
,
3
][
4
]};
//~^ ERROR index out of bounds
//~| ERROR reaching this expression at runtime will panic or abort
//~| ERROR erroneous constant used [E0080]
}
src/test/ui/consts/array-literal-index-oob.stderr
浏览文件 @
16887192
...
...
@@ -14,5 +14,12 @@ LL | &{[1, 2, 3][4]};
| |
| indexing out of bounds: the len is 3 but the index is 4
error: aborting due to 2 previous errors
error[E0080]: erroneous constant used
--> $DIR/array-literal-index-oob.rs:4:5
|
LL | &{[1, 2, 3][4]};
| ^^^^^^^^^^^^^^^ referenced constant has errors
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0080`.
src/test/ui/consts/const-eval/conditional_array_execution.rs
浏览文件 @
16887192
...
...
@@ -10,4 +10,5 @@
fn
main
()
{
println!
(
"{}"
,
FOO
);
//~^ ERROR
//~| ERROR erroneous constant used [E0080]
}
src/test/ui/consts/const-eval/conditional_array_execution.stderr
浏览文件 @
16887192
...
...
@@ -18,6 +18,12 @@ error[E0080]: evaluation of constant expression failed
LL | println!("{}", FOO);
| ^^^ referenced constant has errors
error: aborting due to previous error
error[E0080]: erroneous constant used
--> $DIR/conditional_array_execution.rs:11:20
|
LL | println!("{}", FOO);
| ^^^ referenced constant has errors
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`.
src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs
浏览文件 @
16887192
...
...
@@ -17,6 +17,8 @@ const fn bar(x: fn(usize) -> usize, y: usize) -> usize {
fn
main
()
{
assert_eq!
(
Y
,
4
);
//~^ ERROR evaluation of constant expression failed
//~| ERROR erroneous constant used [E0080]
assert_eq!
(
Z
,
4
);
//~^ ERROR evaluation of constant expression failed
//~| ERROR erroneous constant used [E0080]
}
src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr
浏览文件 @
16887192
...
...
@@ -14,8 +14,16 @@ LL | assert_eq!(Y, 4);
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error[E0080]: erroneous constant used
--> $DIR/const_fn_ptr_fail2.rs:18:5
|
LL | assert_eq!(Y, 4);
| ^^^^^^^^^^^^^^^^^ referenced constant has errors
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error[E0080]: evaluation of constant expression failed
--> $DIR/const_fn_ptr_fail2.rs:2
0
:5
--> $DIR/const_fn_ptr_fail2.rs:2
1
:5
|
LL | assert_eq!(Z, 4);
| ^^^^^^^^^^^-^^^^^
...
...
@@ -24,6 +32,14 @@ LL | assert_eq!(Z, 4);
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error: aborting due to 2 previous errors
error[E0080]: erroneous constant used
--> $DIR/const_fn_ptr_fail2.rs:21:5
|
LL | assert_eq!(Z, 4);
| ^^^^^^^^^^^^^^^^^ referenced constant has errors
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0080`.
src/test/ui/consts/const-eval/issue-43197.rs
浏览文件 @
16887192
...
...
@@ -14,4 +14,6 @@ fn main() {
println!
(
"{} {}"
,
X
,
Y
);
//~^ ERROR evaluation of constant expression failed
//~| ERROR evaluation of constant expression failed
//~| ERROR erroneous constant used [E0080]
//~| ERROR erroneous constant used [E0080]
}
src/test/ui/consts/const-eval/issue-43197.stderr
浏览文件 @
16887192
...
...
@@ -26,12 +26,24 @@ error[E0080]: evaluation of constant expression failed
LL | println!("{} {}", X, Y);
| ^ referenced constant has errors
error[E0080]: erroneous constant used
--> $DIR/issue-43197.rs:14:23
|
LL | println!("{} {}", X, Y);
| ^ referenced constant has errors
error[E0080]: evaluation of constant expression failed
--> $DIR/issue-43197.rs:14:26
|
LL | println!("{} {}", X, Y);
| ^ referenced constant has errors
error: aborting due to 2 previous errors
error[E0080]: erroneous constant used
--> $DIR/issue-43197.rs:14:26
|
LL | println!("{} {}", X, Y);
| ^ referenced constant has errors
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0080`.
src/test/ui/consts/const-eval/issue-44578.rs
浏览文件 @
16887192
...
...
@@ -25,5 +25,6 @@ impl Foo for u16 {
fn
main
()
{
println!
(
"{}"
,
<
Bar
<
u16
,
u8
>
as
Foo
>
::
AMT
);
//~^ ERROR E0080
//~^ ERROR erroneous constant used [E0080]
//~| ERROR evaluation of constant expression failed [E0080]
}
src/test/ui/consts/const-eval/issue-44578.stderr
浏览文件 @
16887192
...
...
@@ -4,6 +4,12 @@ error[E0080]: evaluation of constant expression failed
LL | println!("{}", <Bar<u16, u8> as Foo>::AMT);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
error: aborting due to previous error
error[E0080]: erroneous constant used
--> $DIR/issue-44578.rs:27:20
|
LL | println!("{}", <Bar<u16, u8> as Foo>::AMT);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`.
src/test/ui/consts/const-eval/issue-50814.rs
浏览文件 @
16887192
...
...
@@ -12,11 +12,13 @@ impl Unsigned for U8 {
struct
Sum
<
A
,
B
>
(
A
,
B
);
impl
<
A
:
Unsigned
,
B
:
Unsigned
>
Unsigned
for
Sum
<
A
,
B
>
{
const
MAX
:
u8
=
A
::
MAX
+
B
::
MAX
;
//~ ERROR any use of this value will cause an error
const
MAX
:
u8
=
A
::
MAX
+
B
::
MAX
;
//~^ ERROR any use of this value will cause an error [const_err]
}
fn
foo
<
T
>
(
_
:
T
)
->
&
'static
u8
{
&
Sum
::
<
U8
,
U8
>
::
MAX
//~ ERROR E0080
&
Sum
::
<
U8
,
U8
>
::
MAX
//~^ ERROR E0080
}
fn
main
()
{
...
...
src/test/ui/consts/const-eval/issue-50814.stderr
浏览文件 @
16887192
...
...
@@ -9,7 +9,7 @@ LL | const MAX: u8 = A::MAX + B::MAX;
= note: `#[deny(const_err)]` on by default
error[E0080]: evaluation of constant expression failed
--> $DIR/issue-50814.rs:
19
:5
--> $DIR/issue-50814.rs:
20
:5
|
LL | &Sum::<U8,U8>::MAX
| ^-----------------
...
...
src/test/ui/consts/const-eval/promoted_errors.rs
浏览文件 @
16887192
...
...
@@ -10,11 +10,13 @@ fn main() {
println!
(
"{}"
,
1
/
(
1
-
1
));
//~^ ERROR attempt to divide by zero [const_err]
//~| ERROR const_err
//~| ERROR erroneous constant used [E0080]
let
_
x
=
1
/
(
1
-
1
);
//~^ ERROR const_err
println!
(
"{}"
,
1
/
(
false
as
u32
));
//~^ ERROR attempt to divide by zero [const_err]
//~| ERROR const_err
//~| ERROR erroneous constant used [E0080]
let
_
x
=
1
/
(
false
as
u32
);
//~^ ERROR const_err
}
src/test/ui/consts/const-eval/promoted_errors.stderr
浏览文件 @
16887192
...
...
@@ -22,29 +22,42 @@ error: reaching this expression at runtime will panic or abort
LL | println!("{}", 1/(1-1));
| ^^^^^^^ dividing by zero
error[E0080]: erroneous constant used
--> $DIR/promoted_errors.rs:10:20
|
LL | println!("{}", 1/(1-1));
| ^^^^^^^ referenced constant has errors
error: attempt to divide by zero
--> $DIR/promoted_errors.rs:1
3
:14
--> $DIR/promoted_errors.rs:1
4
:14
|
LL | let _x = 1/(1-1);
| ^^^^^^^
error: attempt to divide by zero
--> $DIR/promoted_errors.rs:1
5
:20
--> $DIR/promoted_errors.rs:1
6
:20
|
LL | println!("{}", 1/(false as u32));
| ^^^^^^^^^^^^^^^^
error: reaching this expression at runtime will panic or abort
--> $DIR/promoted_errors.rs:1
5
:20
--> $DIR/promoted_errors.rs:1
6
:20
|
LL | println!("{}", 1/(false as u32));
| ^^^^^^^^^^^^^^^^ dividing by zero
error[E0080]: erroneous constant used
--> $DIR/promoted_errors.rs:16:20
|
LL | println!("{}", 1/(false as u32));
| ^^^^^^^^^^^^^^^^ referenced constant has errors
error: attempt to divide by zero
--> $DIR/promoted_errors.rs:
18
:14
--> $DIR/promoted_errors.rs:
20
:14
|
LL | let _x = 1/(false as u32);
| ^^^^^^^^^^^^^^^^
error: aborting due to
7
previous errors
error: aborting due to
9
previous errors
For more information about this error, try `rustc --explain E0080`.
src/test/ui/consts/const-eval/promoted_errors2.rs
浏览文件 @
16887192
...
...
@@ -11,11 +11,13 @@ fn main() {
println!
(
"{}"
,
1
/
(
1
-
1
));
//~^ ERROR attempt to divide by zero [const_err]
//~| ERROR const_err
//~| ERROR erroneous constant used [E0080]
let
_
x
=
1
/
(
1
-
1
);
//~^ ERROR const_err
println!
(
"{}"
,
1
/
(
false
as
u32
));
//~^ ERROR attempt to divide by zero [const_err]
//~| ERROR const_err
//~| ERROR erroneous constant used [E0080]
let
_
x
=
1
/
(
false
as
u32
);
//~^ ERROR const_err
}
src/test/ui/consts/const-eval/promoted_errors2.stderr
浏览文件 @
16887192
...
...
@@ -28,29 +28,42 @@ error: reaching this expression at runtime will panic or abort
LL | println!("{}", 1/(1-1));
| ^^^^^^^ dividing by zero
error[E0080]: erroneous constant used
--> $DIR/promoted_errors2.rs:11:20
|
LL | println!("{}", 1/(1-1));
| ^^^^^^^ referenced constant has errors
error: attempt to divide by zero
--> $DIR/promoted_errors2.rs:1
4
:14
--> $DIR/promoted_errors2.rs:1
5
:14
|
LL | let _x = 1/(1-1);
| ^^^^^^^
error: attempt to divide by zero
--> $DIR/promoted_errors2.rs:1
6
:20
--> $DIR/promoted_errors2.rs:1
7
:20
|
LL | println!("{}", 1/(false as u32));
| ^^^^^^^^^^^^^^^^
error: reaching this expression at runtime will panic or abort
--> $DIR/promoted_errors2.rs:1
6
:20
--> $DIR/promoted_errors2.rs:1
7
:20
|
LL | println!("{}", 1/(false as u32));
| ^^^^^^^^^^^^^^^^ dividing by zero
error[E0080]: erroneous constant used
--> $DIR/promoted_errors2.rs:17:20
|
LL | println!("{}", 1/(false as u32));
| ^^^^^^^^^^^^^^^^ referenced constant has errors
error: attempt to divide by zero
--> $DIR/promoted_errors2.rs:
19
:14
--> $DIR/promoted_errors2.rs:
21
:14
|
LL | let _x = 1/(false as u32);
| ^^^^^^^^^^^^^^^^
error: aborting due to
8
previous errors
error: aborting due to
10
previous errors
For more information about this error, try `rustc --explain E0080`.
src/test/ui/consts/const-eval/ub-nonnull.stderr
浏览文件 @
16887192
...
...
@@ -13,7 +13,7 @@ LL | / const OUT_OF_BOUNDS_PTR: NonNull<u8> = { unsafe {
LL | | let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle
LL | | // Use address-of-element for pointer arithmetic. This could wrap around to NULL!
LL | | let out_of_bounds_ptr = &ptr[255];
| | ^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of allocation
6
which has size 1
| | ^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of allocation
8
which has size 1
LL | | mem::transmute(out_of_bounds_ptr)
LL | | } };
| |____-
...
...
src/test/ui/consts/miri_unleashed/non_const_fn.rs
浏览文件 @
16887192
...
...
@@ -11,5 +11,7 @@ fn foo() {}
//~^ WARN any use of this value will cause an error
fn
main
()
{
println!
(
"{:?}"
,
C
);
//~ ERROR: evaluation of constant expression failed
println!
(
"{:?}"
,
C
);
//~^ ERROR: evaluation of constant expression failed
//~| ERROR: erroneous constant used [E0080]
}
src/test/ui/consts/miri_unleashed/non_const_fn.stderr
浏览文件 @
16887192
...
...
@@ -24,6 +24,12 @@ error[E0080]: evaluation of constant expression failed
LL | println!("{:?}", C);
| ^ referenced constant has errors
error: aborting due to previous error
error[E0080]: erroneous constant used
--> $DIR/non_const_fn.rs:14:22
|
LL | println!("{:?}", C);
| ^ referenced constant has errors
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`.
src/test/ui/consts/zst_no_llvm_alloc.rs
浏览文件 @
16887192
...
...
@@ -7,13 +7,15 @@
fn
main
()
{
let
x
:
&
'static
()
=
&
();
assert_
eq
!
(
x
as
*
const
()
as
usize
,
1
);
assert_
ne
!
(
x
as
*
const
()
as
usize
,
1
);
let
x
:
&
'static
Foo
=
&
Foo
;
assert_
eq
!
(
x
as
*
const
Foo
as
usize
,
4
);
assert_
ne
!
(
x
as
*
const
Foo
as
usize
,
4
);
// statics must have a unique address
assert_ne!
(
&
FOO
as
*
const
Foo
as
usize
,
4
);
assert_eq!
(
<
Vec
<
i32
>>
::
new
()
.as_ptr
(),
<&
[
i32
]
>
::
default
()
.as_ptr
());
assert_eq!
(
<
Box
<
[
i32
]
>>
::
default
()
.as_ptr
(),
(
&
[])
.as_ptr
());
// FIXME this two tests should be assert_eq!
// this stopped working since we are promoting to constants instead of statics
assert_ne!
(
<
Vec
<
i32
>>
::
new
()
.as_ptr
(),
<&
[
i32
]
>
::
default
()
.as_ptr
());
assert_ne!
(
<
Box
<
[
i32
]
>>
::
default
()
.as_ptr
(),
(
&
[])
.as_ptr
());
}
src/test/ui/invalid_const_promotion.rs
已删除
100644 → 0
浏览文件 @
a59abfa4
// run-pass
#![allow(unused_mut)]
// ignore-wasm32
// ignore-emscripten
// ignore-sgx no processes
// compile-flags: -C debug_assertions=yes
#![stable(feature
=
"rustc"
,
since
=
"1.0.0"
)]
#![feature(const_fn,
rustc_private,
staged_api,
rustc_attrs)]
#![allow(const_err)]
extern
crate
libc
;
use
std
::
env
;
use
std
::
process
::{
Command
,
Stdio
};
// this will panic in debug mode and overflow in release mode
//
// NB we give bar an unused argument because otherwise memoization
// of the const fn kicks in, causing a different code path in the
// compiler to be executed (see PR #66294).
#[stable(feature
=
"rustc"
,
since
=
"1.0.0"
)]
#[rustc_const_stable(feature
=
"rustc"
,
since
=
"1.0.0"
)]
#[rustc_promotable]
const
fn
bar
(
_
:
bool
)
->
usize
{
0
-
1
}
fn
foo
()
{
let
_
:
&
'static
_
=
&
bar
(
true
);
}
#[cfg(unix)]
fn
check_status
(
status
:
std
::
process
::
ExitStatus
)
{
use
std
::
os
::
unix
::
process
::
ExitStatusExt
;
assert
!
(
status
.signal
()
==
Some
(
libc
::
SIGILL
)
||
status
.signal
()
==
Some
(
libc
::
SIGTRAP
)
||
status
.signal
()
==
Some
(
libc
::
SIGABRT
));
}
#[cfg(not(unix))]
fn
check_status
(
status
:
std
::
process
::
ExitStatus
)
{
assert
!
(
!
status
.success
());
}
fn
main
()
{
let
args
:
Vec
<
String
>
=
env
::
args
()
.collect
();
if
args
.len
()
>
1
&&
args
[
1
]
==
"test"
{
foo
();
return
;
}
let
mut
p
=
Command
::
new
(
&
args
[
0
])
.stdout
(
Stdio
::
piped
())
.stdin
(
Stdio
::
piped
())
.arg
(
"test"
)
.output
()
.unwrap
();
check_status
(
p
.status
);
}
src/test/ui/symbol-names/impl1.legacy.stderr
浏览文件 @
16887192
...
...
@@ -46,13 +46,13 @@ error: def-path(bar::<impl foo::Foo>::baz)
LL | #[rustc_def_path]
| ^^^^^^^^^^^^^^^^^
error: symbol-name(_ZN209_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$C$$u20$...$RP$$u2b$impl1..AutoTrait$u3b$$u20$_$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method17h
92c563325b7ff21a
E)
error: symbol-name(_ZN209_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$C$$u20$...$RP$$u2b$impl1..AutoTrait$u3b$$u20$_$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method17h
f07584432cd4d8be
E)
--> $DIR/impl1.rs:62:13
|
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^
error: demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method::h
92c563325b7ff21a
)
error: demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method::h
f07584432cd4d8be
)
--> $DIR/impl1.rs:62:13
|
LL | #[rustc_symbol_name]
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录