Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
7c720ce6
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,发现更多精彩内容 >>
提交
7c720ce6
编写于
7月 16, 2021
作者:
R
Ralf Jung
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
get rid of incorrect erase_for_fmt
上级
4e280656
变更
12
隐藏空白更改
内联
并排
Showing
12 changed file
with
81 addition
and
119 deletion
+81
-119
compiler/rustc_middle/src/mir/interpret/allocation.rs
compiler/rustc_middle/src/mir/interpret/allocation.rs
+3
-1
compiler/rustc_middle/src/mir/interpret/pointer.rs
compiler/rustc_middle/src/mir/interpret/pointer.rs
+5
-21
compiler/rustc_middle/src/mir/interpret/value.rs
compiler/rustc_middle/src/mir/interpret/value.rs
+17
-35
compiler/rustc_middle/src/ty/print/pretty.rs
compiler/rustc_middle/src/ty/print/pretty.rs
+5
-5
compiler/rustc_mir/src/interpret/eval_context.rs
compiler/rustc_mir/src/interpret/eval_context.rs
+7
-7
compiler/rustc_mir/src/interpret/intrinsics.rs
compiler/rustc_mir/src/interpret/intrinsics.rs
+1
-1
compiler/rustc_mir/src/interpret/memory.rs
compiler/rustc_mir/src/interpret/memory.rs
+8
-6
compiler/rustc_mir/src/interpret/operand.rs
compiler/rustc_mir/src/interpret/operand.rs
+24
-12
compiler/rustc_mir/src/interpret/place.rs
compiler/rustc_mir/src/interpret/place.rs
+0
-23
compiler/rustc_mir/src/interpret/validity.rs
compiler/rustc_mir/src/interpret/validity.rs
+8
-5
compiler/rustc_mir/src/transform/const_prop.rs
compiler/rustc_mir/src/transform/const_prop.rs
+2
-2
compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
+1
-1
未找到文件。
compiler/rustc_middle/src/mir/interpret/allocation.rs
浏览文件 @
7c720ce6
...
...
@@ -377,7 +377,9 @@ pub fn write_scalar(
}
};
let
(
bytes
,
provenance
)
=
match
val
.to_bits_or_ptr
(
range
.size
)
{
// `to_bits_or_ptr_internal` is the right method because we just want to store this data
// as-is into memory.
let
(
bytes
,
provenance
)
=
match
val
.to_bits_or_ptr_internal
(
range
.size
)
{
Err
(
val
)
=>
{
let
(
provenance
,
offset
)
=
val
.into_parts
();
(
u128
::
from
(
offset
.bytes
()),
Some
(
provenance
))
...
...
compiler/rustc_middle/src/mir/interpret/pointer.rs
浏览文件 @
7c720ce6
...
...
@@ -89,7 +89,7 @@ impl<T: HasDataLayout> PointerArithmetic for T {}
pub
trait
Provenance
:
Copy
{
/// Says whether the `offset` field of `Pointer`s with this provenance is the actual physical address.
/// If `true, ptr-to-int casts work by simply discarding the provenance.
/// If `false`, ptr-to-int casts are not supported.
/// If `false`, ptr-to-int casts are not supported.
The offset *must* be relative in that case.
const
OFFSET_IS_ADDR
:
bool
;
/// Determines how a pointer should be printed.
...
...
@@ -97,8 +97,9 @@ fn fmt(ptr: &Pointer<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result
where
Self
:
Sized
;
/// "Erasing" a tag converts it to the default tag type if possible. Used only for formatting purposes!
fn
erase_for_fmt
(
self
)
->
AllocId
;
/// Provenance must always be able to identify the allocation this ptr points to.
/// (Identifying the offset in that allocation, however, is harder -- use `Memory::ptr_get_alloc` for that.)
fn
get_alloc_id
(
self
)
->
AllocId
;
}
impl
Provenance
for
AllocId
{
...
...
@@ -120,7 +121,7 @@ fn fmt(ptr: &Pointer<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Ok
(())
}
fn
erase_for_fmt
(
self
)
->
AllocId
{
fn
get_alloc_id
(
self
)
->
AllocId
{
self
}
}
...
...
@@ -177,14 +178,6 @@ pub fn into_pointer_or_addr(self) -> Result<Pointer<Tag>, Size> {
None
=>
Err
(
self
.offset
),
}
}
#[inline(always)]
pub
fn
map_erase_for_fmt
(
self
)
->
Pointer
<
Option
<
AllocId
>>
where
Tag
:
Provenance
,
{
Pointer
{
offset
:
self
.offset
,
provenance
:
self
.provenance
.map
(
Provenance
::
erase_for_fmt
)
}
}
}
impl
<
Tag
>
Pointer
<
Option
<
Tag
>>
{
...
...
@@ -208,15 +201,6 @@ pub fn into_parts(self) -> (Tag, Size) {
(
self
.provenance
,
self
.offset
)
}
#[inline(always)]
pub
fn
erase_for_fmt
(
self
)
->
Pointer
where
Tag
:
Provenance
,
{
// FIXME: This is wrong! `self.offset` might be an absolute address.
Pointer
{
offset
:
self
.offset
,
provenance
:
self
.provenance
.erase_for_fmt
()
}
}
pub
fn
map_provenance
(
self
,
f
:
impl
FnOnce
(
Tag
)
->
Tag
)
->
Self
{
Pointer
{
provenance
:
f
(
self
.provenance
),
..
self
}
}
...
...
compiler/rustc_middle/src/mir/interpret/value.rs
浏览文件 @
7c720ce6
...
...
@@ -289,9 +289,10 @@ pub fn from_f64(f: Double) -> Self {
/// This is almost certainly not the method you want! You should dispatch on the type
/// and use `to_{u8,u16,...}`/`scalar_to_ptr` to perform ptr-to-int / int-to-ptr casts as needed.
///
/// This method only exists for the benefit of low-level memory operations.
/// This method only exists for the benefit of low-level operations that truly need to treat the
/// scalar in whatever form it is.
#[inline]
pub
fn
to_bits_or_ptr
(
self
,
target_size
:
Size
)
->
Result
<
u128
,
Pointer
<
Tag
>>
{
pub
fn
to_bits_or_ptr
_internal
(
self
,
target_size
:
Size
)
->
Result
<
u128
,
Pointer
<
Tag
>>
{
assert_ne!
(
target_size
.bytes
(),
0
,
"you should never look at the bits of a ZST"
);
match
self
{
Scalar
::
Int
(
int
)
=>
Ok
(
int
.assert_bits
(
target_size
)),
...
...
@@ -304,32 +305,23 @@ pub fn to_bits_or_ptr(self, target_size: Size) -> Result<u128, Pointer<Tag>> {
}
impl
<
'tcx
,
Tag
:
Provenance
>
Scalar
<
Tag
>
{
/// Erase the tag from the scalar, if any.
///
/// Used by error reporting code to avoid having the error type depend on `Tag`.
#[inline]
pub
fn
erase_for_fmt
(
self
)
->
Scalar
{
match
self
{
Scalar
::
Ptr
(
ptr
,
sz
)
=>
Scalar
::
Ptr
(
ptr
.erase_for_fmt
(),
sz
),
Scalar
::
Int
(
int
)
=>
Scalar
::
Int
(
int
),
}
}
/// Fundamental scalar-to-int (cast) operation. Many convenience wrappers exist below, that you
/// likely want to use instead.
///
/// Will perform ptr-to-int casts if needed and possible.
/// If that fails, we know the offset is relative, so we return an "erased" Scalar
/// (which is useful for error messages but not much else).
#[inline]
pub
fn
try_to_int
(
self
)
->
Option
<
ScalarInt
>
{
pub
fn
try_to_int
(
self
)
->
Result
<
ScalarInt
,
Scalar
<
AllocId
>
>
{
match
self
{
Scalar
::
Int
(
int
)
=>
Some
(
int
),
Scalar
::
Int
(
int
)
=>
Ok
(
int
),
Scalar
::
Ptr
(
ptr
,
sz
)
=>
{
if
Tag
::
OFFSET_IS_ADDR
{
Some
(
ScalarInt
::
try_from_uint
(
ptr
.offset
.bytes
(),
Size
::
from_bytes
(
sz
))
.unwrap
(),
)
Ok
(
ScalarInt
::
try_from_uint
(
ptr
.offset
.bytes
(),
Size
::
from_bytes
(
sz
))
.unwrap
())
}
else
{
None
// We know `offset` is relative, since `OFFSET_IS_ADDR == false`.
let
(
tag
,
offset
)
=
ptr
.into_parts
();
Err
(
Scalar
::
Ptr
(
Pointer
::
new
(
tag
.get_alloc_id
(),
offset
),
sz
))
}
}
}
...
...
@@ -340,19 +332,20 @@ pub fn assert_int(self) -> ScalarInt {
self
.try_to_int
()
.unwrap
()
}
/// This throws UB (instead of ICEing) on a size mismatch since size mismatches can arise in
/// Miri when someone declares a function that we shim (such as `malloc`) with a wrong type.
#[inline]
pub
fn
to_bits
(
self
,
target_size
:
Size
)
->
InterpResult
<
'tcx
,
u128
>
{
assert_ne!
(
target_size
.bytes
(),
0
,
"you should never look at the bits of a ZST"
);
self
.try_to_int
()
.ok_or_else
(||
err_unsup!
(
ReadPointerAsBytes
))
?
.to_bits
(
target_size
)
.map_err
(|
size
|
{
self
.try_to_int
()
.map_err
(|
_
|
err_unsup!
(
ReadPointerAsBytes
))
?
.to_bits
(
target_size
)
.map_err
(
|
size
|
{
err_ub!
(
ScalarSizeMismatch
{
target_size
:
target_size
.bytes
(),
data_size
:
size
.bytes
(),
})
.into
()
})
},
)
}
#[inline(always)]
...
...
@@ -522,17 +515,6 @@ pub fn check_init(self) -> InterpResult<'static, Scalar<Tag>> {
}
impl
<
'tcx
,
Tag
:
Provenance
>
ScalarMaybeUninit
<
Tag
>
{
/// Erase the tag from the scalar, if any.
///
/// Used by error reporting code to avoid having the error type depend on `Tag`.
#[inline]
pub
fn
erase_for_fmt
(
self
)
->
ScalarMaybeUninit
{
match
self
{
ScalarMaybeUninit
::
Scalar
(
s
)
=>
ScalarMaybeUninit
::
Scalar
(
s
.erase_for_fmt
()),
ScalarMaybeUninit
::
Uninit
=>
ScalarMaybeUninit
::
Uninit
,
}
}
#[inline(always)]
pub
fn
to_bool
(
self
)
->
InterpResult
<
'tcx
,
bool
>
{
self
.check_init
()
?
.to_bool
()
...
...
compiler/rustc_middle/src/ty/print/pretty.rs
浏览文件 @
7c720ce6
use
crate
::
middle
::
cstore
::{
ExternCrate
,
ExternCrateSource
};
use
crate
::
mir
::
interpret
::{
AllocRange
,
ConstValue
,
GlobalAlloc
,
Pointer
,
Scalar
};
use
crate
::
mir
::
interpret
::{
AllocRange
,
ConstValue
,
GlobalAlloc
,
Pointer
,
Provenance
,
Scalar
};
use
crate
::
ty
::
subst
::{
GenericArg
,
GenericArgKind
,
Subst
};
use
crate
::
ty
::{
self
,
ConstInt
,
DefIdTree
,
ParamConst
,
ScalarInt
,
Ty
,
TyCtxt
,
TypeFoldable
};
use
rustc_apfloat
::
ieee
::{
Double
,
Single
};
...
...
@@ -1107,9 +1107,9 @@ fn pretty_print_const_scalar_int(
/// This is overridden for MIR printing because we only want to hide alloc ids from users, not
/// from MIR where it is actually useful.
fn
pretty_print_const_pointer
(
fn
pretty_print_const_pointer
<
Tag
:
Provenance
>
(
mut
self
,
_
:
Pointer
,
_
:
Pointer
<
Tag
>
,
ty
:
Ty
<
'tcx
>
,
print_ty
:
bool
,
)
->
Result
<
Self
::
Const
,
Self
::
Error
>
{
...
...
@@ -1680,9 +1680,9 @@ fn region_should_not_be_omitted(&self, region: ty::Region<'_>) -> bool {
}
}
fn
pretty_print_const_pointer
(
fn
pretty_print_const_pointer
<
Tag
:
Provenance
>
(
self
,
p
:
Pointer
,
p
:
Pointer
<
Tag
>
,
ty
:
Ty
<
'tcx
>
,
print_ty
:
bool
,
)
->
Result
<
Self
::
Const
,
Self
::
Error
>
{
...
...
compiler/rustc_mir/src/interpret/eval_context.rs
浏览文件 @
7c720ce6
...
...
@@ -897,11 +897,11 @@ pub fn storage_dead(&mut self, local: mir::Local) -> InterpResult<'tcx> {
fn
deallocate_local
(
&
mut
self
,
local
:
LocalValue
<
M
::
PointerTag
>
)
->
InterpResult
<
'tcx
>
{
if
let
LocalValue
::
Live
(
Operand
::
Indirect
(
MemPlace
{
ptr
,
..
}))
=
local
{
// All locals have a backing allocation, even if the allocation is empty
// due to the local having ZST type.
// due to the local having ZST type.
Hence we can `unwrap`.
trace!
(
"deallocating local {:?}: {:?}"
,
local
,
self
.memory
.dump_alloc
(
ptr
.provenance
.unwrap
()
.
erase_for_fmt
())
self
.memory
.dump_alloc
(
ptr
.provenance
.unwrap
()
.
get_alloc_id
())
);
self
.memory
.deallocate
(
ptr
,
None
,
MemoryKind
::
Stack
)
?
;
};
...
...
@@ -989,28 +989,28 @@ fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
},
mplace
.ptr
,
)
?
;
allocs
.extend
(
mplace
.ptr
.
map_erase_for_fmt
()
.provenance
);
allocs
.extend
(
mplace
.ptr.
provenance
.map
(
Provenance
::
get_alloc_id
)
);
}
LocalValue
::
Live
(
Operand
::
Immediate
(
Immediate
::
Scalar
(
val
)))
=>
{
write!
(
fmt
,
" {:?}"
,
val
)
?
;
if
let
ScalarMaybeUninit
::
Scalar
(
Scalar
::
Ptr
(
ptr
,
_
size
))
=
val
{
allocs
.push
(
ptr
.provenance
.
erase_for_fmt
());
allocs
.push
(
ptr
.provenance
.
get_alloc_id
());
}
}
LocalValue
::
Live
(
Operand
::
Immediate
(
Immediate
::
ScalarPair
(
val1
,
val2
)))
=>
{
write!
(
fmt
,
" ({:?}, {:?})"
,
val1
,
val2
)
?
;
if
let
ScalarMaybeUninit
::
Scalar
(
Scalar
::
Ptr
(
ptr
,
_
size
))
=
val1
{
allocs
.push
(
ptr
.provenance
.
erase_for_fmt
());
allocs
.push
(
ptr
.provenance
.
get_alloc_id
());
}
if
let
ScalarMaybeUninit
::
Scalar
(
Scalar
::
Ptr
(
ptr
,
_
size
))
=
val2
{
allocs
.push
(
ptr
.provenance
.
erase_for_fmt
());
allocs
.push
(
ptr
.provenance
.
get_alloc_id
());
}
}
}
write!
(
fmt
,
": {:?}"
,
self
.ecx.memory
.dump_allocs
(
allocs
))
}
Place
::
Ptr
(
mplace
)
=>
match
mplace
.ptr
.
map_erase_for_fmt
()
.provenance
{
Place
::
Ptr
(
mplace
)
=>
match
mplace
.ptr.
provenance
.map
(
Provenance
::
get_alloc_id
)
{
Some
(
alloc_id
)
=>
write!
(
fmt
,
"by align({}) ref {:?}: {:?}"
,
...
...
compiler/rustc_mir/src/interpret/intrinsics.rs
浏览文件 @
7c720ce6
...
...
@@ -362,7 +362,7 @@ pub fn emulate_intrinsic(
//
// Control flow is weird because we cannot early-return (to reach the
// `go_to_block` at the end).
let
done
=
if
let
(
Some
(
a
),
Some
(
b
))
=
(
a
.try_to_int
(),
b
.try_to_int
())
{
let
done
=
if
let
(
Ok
(
a
),
Ok
(
b
))
=
(
a
.try_to_int
(),
b
.try_to_int
())
{
let
a
=
a
.try_to_machine_usize
(
*
self
.tcx
)
.unwrap
();
let
b
=
b
.try_to_machine_usize
(
*
self
.tcx
)
.unwrap
();
if
a
==
b
&&
a
!=
0
{
...
...
compiler/rustc_mir/src/interpret/memory.rs
浏览文件 @
7c720ce6
...
...
@@ -757,12 +757,12 @@ pub fn get_fn(
ptr
:
Pointer
<
Option
<
M
::
PointerTag
>>
,
)
->
InterpResult
<
'tcx
,
FnVal
<
'tcx
,
M
::
ExtraFnVal
>>
{
trace!
(
"get_fn({:?})"
,
ptr
);
let
(
alloc_id
,
offset
,
ptr
)
=
self
.ptr_get_alloc
(
ptr
)
?
;
let
(
alloc_id
,
offset
,
_
ptr
)
=
self
.ptr_get_alloc
(
ptr
)
?
;
if
offset
.bytes
()
!=
0
{
throw_ub!
(
InvalidFunctionPointer
(
ptr
.erase_for_fmt
(
)))
throw_ub!
(
InvalidFunctionPointer
(
Pointer
::
new
(
alloc_id
,
offset
)))
}
self
.get_fn_alloc
(
alloc_id
)
.ok_or_else
(||
err_ub!
(
InvalidFunctionPointer
(
ptr
.erase_for_fmt
(
)))
.into
())
.ok_or_else
(||
err_ub!
(
InvalidFunctionPointer
(
Pointer
::
new
(
alloc_id
,
offset
)))
.into
())
}
pub
fn
mark_immutable
(
&
mut
self
,
id
:
AllocId
)
->
InterpResult
<
'tcx
>
{
...
...
@@ -801,7 +801,7 @@ pub fn leak_report(&self, static_roots: &[AllocId]) -> usize {
if
reachable
.insert
(
id
)
{
// This is a new allocation, add its relocations to `todo`.
if
let
Some
((
_
,
alloc
))
=
self
.alloc_map
.get
(
id
)
{
todo
.extend
(
alloc
.relocations
()
.values
()
.map
(|
tag
|
tag
.
erase_for_fmt
()));
todo
.extend
(
alloc
.relocations
()
.values
()
.map
(|
tag
|
tag
.
get_alloc_id
()));
}
}
}
...
...
@@ -841,7 +841,7 @@ fn write_allocation_track_relocs<'tcx, Tag: Provenance, Extra>(
allocs_to_print
:
&
mut
VecDeque
<
AllocId
>
,
alloc
:
&
Allocation
<
Tag
,
Extra
>
,
)
->
std
::
fmt
::
Result
{
for
alloc_id
in
alloc
.relocations
()
.values
()
.map
(|
tag
|
tag
.
erase_for_fmt
())
{
for
alloc_id
in
alloc
.relocations
()
.values
()
.map
(|
tag
|
tag
.
get_alloc_id
())
{
allocs_to_print
.push_back
(
alloc_id
);
}
write!
(
fmt
,
"{}"
,
pretty
::
display_allocation
(
tcx
,
alloc
))
...
...
@@ -1129,7 +1129,9 @@ pub fn copy_repeatedly(
/// Machine pointer introspection.
impl
<
'mir
,
'tcx
,
M
:
Machine
<
'mir
,
'tcx
>>
Memory
<
'mir
,
'tcx
,
M
>
{
pub
fn
scalar_to_ptr
(
&
self
,
scalar
:
Scalar
<
M
::
PointerTag
>
)
->
Pointer
<
Option
<
M
::
PointerTag
>>
{
match
scalar
.to_bits_or_ptr
(
self
.pointer_size
())
{
// We use `to_bits_or_ptr_internal` since we are just implementing the method people need to
// call to force getting out a pointer.
match
scalar
.to_bits_or_ptr_internal
(
self
.pointer_size
())
{
Err
(
ptr
)
=>
ptr
.into
(),
Ok
(
bits
)
=>
{
let
addr
=
u64
::
try_from
(
bits
)
.unwrap
();
...
...
compiler/rustc_mir/src/interpret/operand.rs
浏览文件 @
7c720ce6
...
...
@@ -118,8 +118,14 @@ fn p<'a, 'tcx, F: std::fmt::Write, Tag: Provenance>(
ty
:
Ty
<
'tcx
>
,
)
->
Result
<
FmtPrinter
<
'a
,
'tcx
,
F
>
,
std
::
fmt
::
Error
>
{
match
s
{
ScalarMaybeUninit
::
Scalar
(
s
)
=>
{
cx
.pretty_print_const_scalar
(
s
.erase_for_fmt
(),
ty
,
true
)
ScalarMaybeUninit
::
Scalar
(
Scalar
::
Int
(
int
))
=>
{
cx
.pretty_print_const_scalar_int
(
int
,
ty
,
true
)
}
ScalarMaybeUninit
::
Scalar
(
Scalar
::
Ptr
(
ptr
,
_
sz
))
=>
{
// Just print the ptr value. `pretty_print_const_scalar_ptr` would also try to
// print what is points to, which would fail since it has no access to the local
// memory.
cx
.pretty_print_const_pointer
(
ptr
,
ty
,
true
)
}
ScalarMaybeUninit
::
Uninit
=>
cx
.typed_value
(
|
mut
this
|
{
...
...
@@ -139,11 +145,11 @@ fn p<'a, 'tcx, F: std::fmt::Write, Tag: Provenance>(
p
(
cx
,
s
,
ty
)
?
;
return
Ok
(());
}
write!
(
f
,
"{}: {}"
,
s
.erase_for_fmt
()
,
self
.layout.ty
)
write!
(
f
,
"{}: {}"
,
s
,
self
.layout.ty
)
}
Immediate
::
ScalarPair
(
a
,
b
)
=>
{
// FIXME(oli-obk): at least print tuples and slices nicely
write!
(
f
,
"({}, {}): {}"
,
a
.erase_for_fmt
(),
b
.erase_for_fmt
()
,
self
.layout.ty
,)
write!
(
f
,
"({}, {}): {}"
,
a
,
b
,
self
.layout.ty
,)
}
}
})
...
...
@@ -693,8 +699,9 @@ pub fn read_discriminant(
Ok
(
match
*
tag_encoding
{
TagEncoding
::
Direct
=>
{
let
tag_bits
=
tag_val
.to_bits
(
tag_layout
.size
)
.map_err
(|
_
|
err_ub!
(
InvalidTag
(
tag_val
.erase_for_fmt
())))
?
;
.try_to_int
()
.map_err
(|
dbg_val
|
err_ub!
(
InvalidTag
(
dbg_val
)))
?
.assert_bits
(
tag_layout
.size
);
// Cast bits from tag layout to discriminant layout.
let
discr_val
=
self
.cast_from_scalar
(
tag_bits
,
tag_layout
,
discr_layout
.ty
);
let
discr_bits
=
discr_val
.assert_bits
(
discr_layout
.size
);
...
...
@@ -711,7 +718,7 @@ pub fn read_discriminant(
}
_
=>
span_bug!
(
self
.cur_span
(),
"tagged layout for non-adt non-generator"
),
}
.ok_or_else
(||
err_ub!
(
InvalidTag
(
tag_val
.erase_for_fmt
(
))))
?
;
.ok_or_else
(||
err_ub!
(
InvalidTag
(
Scalar
::
from_uint
(
tag_bits
,
tag_layout
.size
))))
?
;
// Return the cast value, and the index.
(
discr_val
,
index
.0
)
}
...
...
@@ -720,18 +727,23 @@ pub fn read_discriminant(
// discriminant (encoded in niche/tag) and variant index are the same.
let
variants_start
=
niche_variants
.start
()
.as_u32
();
let
variants_end
=
niche_variants
.end
()
.as_u32
();
let
variant
=
match
tag_val
.to_bits_or_ptr
(
tag_layout
.size
)
{
Err
(
ptr
)
=>
{
// The niche must be just 0 (which an inbounds pointer value never is)
let
variant
=
match
tag_val
.try_to_int
()
{
Err
(
dbg_val
)
=>
{
// So this is a pointer then, and casting to an int failed.
// Can only happen during CTFE.
let
ptr
=
self
.scalar_to_ptr
(
tag_val
);
// The niche must be just 0, and the ptr not null, then we know this is
// okay. Everything else, we conservatively reject.
let
ptr_valid
=
niche_start
==
0
&&
variants_start
==
variants_end
&&
!
self
.memory
.ptr_may_be_null
(
ptr
.into
()
);
&&
!
self
.memory
.ptr_may_be_null
(
ptr
);
if
!
ptr_valid
{
throw_ub!
(
InvalidTag
(
tag_val
.erase_for_fmt
()
))
throw_ub!
(
InvalidTag
(
dbg_val
))
}
dataful_variant
}
Ok
(
tag_bits
)
=>
{
let
tag_bits
=
tag_bits
.assert_bits
(
tag_layout
.size
);
// We need to use machine arithmetic to get the relative variant idx:
// variant_index_relative = tag_val - niche_start_val
let
tag_val
=
ImmTy
::
from_uint
(
tag_bits
,
tag_layout
);
...
...
compiler/rustc_mir/src/interpret/place.rs
浏览文件 @
7c720ce6
...
...
@@ -62,17 +62,6 @@ fn has_meta(self) -> bool {
Self
::
None
|
Self
::
Poison
=>
false
,
}
}
pub
fn
erase_for_fmt
(
self
)
->
MemPlaceMeta
where
Tag
:
Provenance
,
{
match
self
{
Self
::
Meta
(
s
)
=>
MemPlaceMeta
::
Meta
(
s
.erase_for_fmt
()),
Self
::
None
=>
MemPlaceMeta
::
None
,
Self
::
Poison
=>
MemPlaceMeta
::
Poison
,
}
}
}
#[derive(Copy,
Clone,
Hash,
PartialEq,
Eq,
HashStable)]
...
...
@@ -182,18 +171,6 @@ fn from(mplace: MPlaceTy<'tcx, Tag>) -> Self {
}
impl
<
Tag
>
MemPlace
<
Tag
>
{
#[inline]
pub
fn
erase_for_fmt
(
self
)
->
MemPlace
where
Tag
:
Provenance
,
{
MemPlace
{
ptr
:
self
.ptr
.map_erase_for_fmt
(),
align
:
self
.align
,
meta
:
self
.meta
.erase_for_fmt
(),
}
}
#[inline(always)]
pub
fn
from_ptr
(
ptr
:
Pointer
<
Option
<
Tag
>>
,
align
:
Align
)
->
Self
{
MemPlace
{
ptr
,
align
,
meta
:
MemPlaceMeta
::
None
}
...
...
compiler/rustc_mir/src/interpret/validity.rs
浏览文件 @
7c720ce6
...
...
@@ -535,7 +535,7 @@ fn try_visit_primitive(
// types below!
if
self
.ctfe_mode
.is_some
()
{
// Integers/floats in CTFE: Must be scalar bits, pointers are dangerous
let
is_bits
=
value
.check_init
()
.map_or
(
false
,
|
v
|
v
.try_to_int
()
.is_
some
());
let
is_bits
=
value
.check_init
()
.map_or
(
false
,
|
v
|
v
.try_to_int
()
.is_
ok
());
if
!
is_bits
{
throw_validation_failure!
(
self
.path
,
{
"{}"
,
value
}
expected
{
"initialized plain (non-pointer) bytes"
}
...
...
@@ -652,11 +652,14 @@ fn visit_scalar(
err_ub!
(
InvalidUninitBytes
(
None
))
=>
{
"{}"
,
value
}
expected
{
"something {}"
,
wrapping_range_format
(
valid_range
,
max_hi
)
},
);
let
bits
=
match
value
.to_bits_or_ptr
(
op
.layout.size
)
{
Err
(
ptr
)
=>
{
let
bits
=
match
value
.try_to_int
()
{
Err
(
_
)
=>
{
// So this is a pointer then, and casting to an int failed.
// Can only happen during CTFE.
let
ptr
=
self
.ecx
.scalar_to_ptr
(
value
);
if
lo
==
1
&&
hi
==
max_hi
{
// Only null is the niche. So make sure the ptr is NOT null.
if
self
.ecx.memory
.ptr_may_be_null
(
ptr
.into
()
)
{
if
self
.ecx.memory
.ptr_may_be_null
(
ptr
)
{
throw_validation_failure!
(
self
.path
,
{
"a potentially null pointer"
}
expected
{
...
...
@@ -678,7 +681,7 @@ fn visit_scalar(
)
}
}
Ok
(
data
)
=>
data
,
Ok
(
int
)
=>
int
.assert_bits
(
op
.layout.size
)
,
};
// Now compare. This is slightly subtle because this is a special "wrap-around" range.
if
wrapping_range_contains
(
&
valid_range
,
bits
)
{
...
...
compiler/rustc_mir/src/transform/const_prop.rs
浏览文件 @
7c720ce6
...
...
@@ -921,12 +921,12 @@ fn should_const_prop(&mut self, op: &OpTy<'tcx>) -> bool {
match
**
op
{
interpret
::
Operand
::
Immediate
(
Immediate
::
Scalar
(
ScalarMaybeUninit
::
Scalar
(
s
)))
=>
{
s
.try_to_int
()
.is_
some
()
s
.try_to_int
()
.is_
ok
()
}
interpret
::
Operand
::
Immediate
(
Immediate
::
ScalarPair
(
ScalarMaybeUninit
::
Scalar
(
l
),
ScalarMaybeUninit
::
Scalar
(
r
),
))
=>
l
.try_to_int
()
.is_
some
()
&&
r
.try_to_int
()
.is_some
(),
))
=>
l
.try_to_int
()
.is_
ok
()
&&
r
.try_to_int
()
.is_ok
(),
_
=>
false
,
}
}
...
...
compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
浏览文件 @
7c720ce6
...
...
@@ -123,7 +123,7 @@ fn from_const<'tcx>(
// straight to the result, after doing a bit of checking. (We
// could remove this branch and just fall through, which
// is more general but much slower.)
if
let
Ok
(
bits
)
=
scalar
.to_bits_or_ptr
(
target_size
)
{
if
let
Ok
(
bits
)
=
scalar
.to_bits_or_ptr
_internal
(
target_size
)
{
return
Some
(
bits
);
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录