Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
4eaf535d
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,发现更多精彩内容 >>
提交
4eaf535d
编写于
4月 15, 2020
作者:
J
Jonas Schievink
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Treat RETURN_PLACE as a normal Local
Copy its value to the `return_place` upon leaving a call frame
上级
8ce3f840
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
42 addition
and
70 deletion
+42
-70
src/librustc_middle/mir/interpret/error.rs
src/librustc_middle/mir/interpret/error.rs
+0
-3
src/librustc_mir/interpret/eval_context.rs
src/librustc_mir/interpret/eval_context.rs
+26
-25
src/librustc_mir/interpret/operand.rs
src/librustc_mir/interpret/operand.rs
+6
-10
src/librustc_mir/interpret/place.rs
src/librustc_mir/interpret/place.rs
+8
-29
src/librustc_mir/interpret/terminator.rs
src/librustc_mir/interpret/terminator.rs
+0
-1
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/mutable_const.stderr
src/test/ui/consts/miri_unleashed/mutable_const.stderr
+1
-1
未找到文件。
src/librustc_middle/mir/interpret/error.rs
浏览文件 @
4eaf535d
...
...
@@ -361,8 +361,6 @@ pub enum UndefinedBehaviorInfo {
InvalidUndefBytes
(
Option
<
Pointer
>
),
/// Working with a local that is not currently live.
DeadLocal
,
/// Trying to read from the return place of a function.
ReadFromReturnPlace
,
}
impl
fmt
::
Debug
for
UndefinedBehaviorInfo
{
...
...
@@ -424,7 +422,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
"using uninitialized data, but this operation requires initialized memory"
),
DeadLocal
=>
write!
(
f
,
"accessing a dead local variable"
),
ReadFromReturnPlace
=>
write!
(
f
,
"reading from return place"
),
}
}
}
...
...
src/librustc_mir/interpret/eval_context.rs
浏览文件 @
4eaf535d
...
...
@@ -623,35 +623,30 @@ pub fn push_stack_frame(
let
frame
=
M
::
init_frame_extra
(
self
,
pre_frame
)
?
;
self
.stack_mut
()
.push
(
frame
);
// don't allocate at all for trivial constants
if
body
.local_decls
.len
()
>
1
{
// Locals are initially uninitialized.
let
dummy
=
LocalState
{
value
:
LocalValue
::
Uninitialized
,
layout
:
Cell
::
new
(
None
)
};
let
mut
locals
=
IndexVec
::
from_elem
(
dummy
,
&
body
.local_decls
);
// Return place is handled specially by the `eval_place` functions, and the
// entry in `locals` should never be used. Make it dead, to be sure.
locals
[
mir
::
RETURN_PLACE
]
.value
=
LocalValue
::
Dead
;
// Now mark those locals as dead that we do not want to initialize
match
self
.tcx
.def_kind
(
instance
.def_id
())
{
// statics and constants don't have `Storage*` statements, no need to look for them
//
// FIXME: The above is likely untrue. See
// <https://github.com/rust-lang/rust/pull/70004#issuecomment-602022110>. Is it
// okay to ignore `StorageDead`/`StorageLive` annotations during CTFE?
Some
(
DefKind
::
Static
|
DefKind
::
Const
|
DefKind
::
AssocConst
)
=>
{}
_
=>
{
// Mark locals that use `Storage*` annotations as dead on function entry.
let
always_live
=
AlwaysLiveLocals
::
new
(
self
.body
());
for
local
in
locals
.indices
()
{
if
!
always_live
.contains
(
local
)
{
locals
[
local
]
.value
=
LocalValue
::
Dead
;
}
// Locals are initially uninitialized.
let
dummy
=
LocalState
{
value
:
LocalValue
::
Uninitialized
,
layout
:
Cell
::
new
(
None
)
};
let
mut
locals
=
IndexVec
::
from_elem
(
dummy
,
&
body
.local_decls
);
// Now mark those locals as dead that we do not want to initialize
match
self
.tcx
.def_kind
(
instance
.def_id
())
{
// statics and constants don't have `Storage*` statements, no need to look for them
//
// FIXME: The above is likely untrue. See
// <https://github.com/rust-lang/rust/pull/70004#issuecomment-602022110>. Is it
// okay to ignore `StorageDead`/`StorageLive` annotations during CTFE?
Some
(
DefKind
::
Static
|
DefKind
::
Const
|
DefKind
::
AssocConst
)
=>
{}
_
=>
{
// Mark locals that use `Storage*` annotations as dead on function entry.
let
always_live
=
AlwaysLiveLocals
::
new
(
self
.body
());
for
local
in
locals
.indices
()
{
if
!
always_live
.contains
(
local
)
{
locals
[
local
]
.value
=
LocalValue
::
Dead
;
}
}
}
// done
self
.frame_mut
()
.locals
=
locals
;
}
// done
self
.frame_mut
()
.locals
=
locals
;
M
::
after_stack_push
(
self
)
?
;
info!
(
"ENTERING({}) {}"
,
self
.frame_idx
(),
self
.frame
()
.instance
);
...
...
@@ -729,6 +724,12 @@ pub(super) fn pop_stack_frame(&mut self, unwinding: bool) -> InterpResult<'tcx>
let
frame
=
self
.stack_mut
()
.pop
()
.expect
(
"tried to pop a stack frame, but there were none"
);
if
let
Some
(
return_place
)
=
frame
.return_place
{
// Copy the return value to the caller's stack frame.
let
op
=
self
.access_local
(
&
frame
,
mir
::
RETURN_PLACE
,
None
)
?
;
self
.copy_op
(
op
,
return_place
)
?
;
}
// Now where do we jump next?
// Usually we want to clean up (deallocate locals), but in a few rare cases we don't.
...
...
src/librustc_mir/interpret/operand.rs
浏览文件 @
4eaf535d
...
...
@@ -419,7 +419,6 @@ pub fn access_local(
local
:
mir
::
Local
,
layout
:
Option
<
TyAndLayout
<
'tcx
>>
,
)
->
InterpResult
<
'tcx
,
OpTy
<
'tcx
,
M
::
PointerTag
>>
{
assert_ne!
(
local
,
mir
::
RETURN_PLACE
);
let
layout
=
self
.layout_of_local
(
frame
,
local
,
layout
)
?
;
let
op
=
if
layout
.is_zst
()
{
// Do not read from ZST, they might not be initialized
...
...
@@ -454,15 +453,12 @@ pub fn eval_place_to_op(
place
:
mir
::
Place
<
'tcx
>
,
layout
:
Option
<
TyAndLayout
<
'tcx
>>
,
)
->
InterpResult
<
'tcx
,
OpTy
<
'tcx
,
M
::
PointerTag
>>
{
let
base_op
=
match
place
.local
{
mir
::
RETURN_PLACE
=>
throw_ub!
(
ReadFromReturnPlace
),
local
=>
{
// Do not use the layout passed in as argument if the base we are looking at
// here is not the entire place.
let
layout
=
if
place
.projection
.is_empty
()
{
layout
}
else
{
None
};
self
.access_local
(
self
.frame
(),
local
,
layout
)
?
}
let
base_op
=
{
// Do not use the layout passed in as argument if the base we are looking at
// here is not the entire place.
let
layout
=
if
place
.projection
.is_empty
()
{
layout
}
else
{
None
};
self
.access_local
(
self
.frame
(),
place
.local
,
layout
)
?
};
let
op
=
place
...
...
src/librustc_mir/interpret/place.rs
浏览文件 @
4eaf535d
...
...
@@ -276,6 +276,10 @@ pub fn assert_mem_place(self) -> MemPlace<Tag> {
}
impl
<
'tcx
,
Tag
:
::
std
::
fmt
::
Debug
>
PlaceTy
<
'tcx
,
Tag
>
{
pub
fn
null
(
cx
:
&
impl
HasDataLayout
,
layout
:
TyAndLayout
<
'tcx
>
)
->
Self
{
Self
{
place
:
Place
::
null
(
cx
),
layout
}
}
#[inline]
pub
fn
assert_mem_place
(
self
)
->
MPlaceTy
<
'tcx
,
Tag
>
{
MPlaceTy
{
mplace
:
self
.place
.assert_mem_place
(),
layout
:
self
.layout
}
...
...
@@ -636,35 +640,10 @@ pub fn eval_place(
&
mut
self
,
place
:
mir
::
Place
<
'tcx
>
,
)
->
InterpResult
<
'tcx
,
PlaceTy
<
'tcx
,
M
::
PointerTag
>>
{
let
mut
place_ty
=
match
place
.local
{
mir
::
RETURN_PLACE
=>
{
// `return_place` has the *caller* layout, but we want to use our
// `layout to verify our assumption. The caller will validate
// their layout on return.
PlaceTy
{
place
:
match
self
.frame
()
.return_place
{
Some
(
p
)
=>
*
p
,
// Even if we don't have a return place, we sometimes need to
// create this place, but any attempt to read from / write to it
// (even a ZST read/write) needs to error, so let us make this
// a NULL place.
//
// FIXME: Ideally we'd make sure that the place projections also
// bail out.
None
=>
Place
::
null
(
&*
self
),
},
layout
:
self
.layout_of
(
self
.subst_from_current_frame_and_normalize_erasing_regions
(
self
.frame
()
.body
.return_ty
(),
),
)
?
,
}
}
local
=>
PlaceTy
{
// This works even for dead/uninitialized locals; we check further when writing
place
:
Place
::
Local
{
frame
:
self
.frame_idx
(),
local
},
layout
:
self
.layout_of_local
(
self
.frame
(),
local
,
None
)
?
,
},
let
mut
place_ty
=
PlaceTy
{
// This works even for dead/uninitialized locals; we check further when writing
place
:
Place
::
Local
{
frame
:
self
.frame_idx
(),
local
:
place
.local
},
layout
:
self
.layout_of_local
(
self
.frame
(),
place
.local
,
None
)
?
,
};
for
elem
in
place
.projection
.iter
()
{
...
...
src/librustc_mir/interpret/terminator.rs
浏览文件 @
4eaf535d
...
...
@@ -19,7 +19,6 @@ pub(super) fn eval_terminator(
use
rustc_middle
::
mir
::
TerminatorKind
::
*
;
match
terminator
.kind
{
Return
=>
{
self
.frame
()
.return_place
.map
(|
r
|
self
.dump_place
(
*
r
));
self
.pop_stack_frame
(
/* unwinding */
false
)
?
}
...
...
src/test/ui/consts/const-eval/ub-nonnull.stderr
浏览文件 @
4eaf535d
...
...
@@ -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 alloc
8
which has size 1
| | ^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc
11
which has size 1
LL | | mem::transmute(out_of_bounds_ptr)
LL | | } };
| |____-
...
...
src/test/ui/consts/miri_unleashed/mutable_const.stderr
浏览文件 @
4eaf535d
...
...
@@ -11,7 +11,7 @@ LL | / const MUTATING_BEHIND_RAW: () = {
LL | | // Test that `MUTABLE_BEHIND_RAW` is actually immutable, by doing this at const time.
LL | | unsafe {
LL | | *MUTABLE_BEHIND_RAW = 99
| | ^^^^^^^^^^^^^^^^^^^^^^^^ writing to alloc
1
which is read-only
| | ^^^^^^^^^^^^^^^^^^^^^^^^ writing to alloc
2
which is read-only
LL | | }
LL | | };
| |__-
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录