Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
5b984891
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,发现更多精彩内容 >>
提交
5b984891
编写于
4月 22, 2019
作者:
O
Oliver Scherer
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Make the `type_name` intrinsic's output deterministic
上级
14178efa
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
306 addition
and
27 deletion
+306
-27
src/librustc/mir/interpret/allocation.rs
src/librustc/mir/interpret/allocation.rs
+6
-4
src/librustc_codegen_llvm/intrinsic.rs
src/librustc_codegen_llvm/intrinsic.rs
+2
-3
src/librustc_codegen_ssa/mir/operand.rs
src/librustc_codegen_ssa/mir/operand.rs
+6
-6
src/librustc_mir/const_eval.rs
src/librustc_mir/const_eval.rs
+3
-1
src/librustc_mir/interpret/intrinsics.rs
src/librustc_mir/interpret/intrinsics.rs
+3
-0
src/librustc_mir/interpret/intrinsics/type_name.rs
src/librustc_mir/interpret/intrinsics/type_name.rs
+228
-0
src/librustc_mir/interpret/mod.rs
src/librustc_mir/interpret/mod.rs
+2
-0
src/test/run-pass/issues/issue-21058.rs
src/test/run-pass/issues/issue-21058.rs
+55
-12
src/test/run-pass/tydesc-name.rs
src/test/run-pass/tydesc-name.rs
+1
-1
未找到文件。
src/librustc/mir/interpret/allocation.rs
浏览文件 @
5b984891
...
...
@@ -12,6 +12,7 @@
use
rustc_data_structures
::
sorted_map
::
SortedMap
;
use
rustc_macros
::
HashStable
;
use
rustc_target
::
abi
::
HasDataLayout
;
use
std
::
borrow
::
Cow
;
/// Used by `check_bounds` to indicate whether the pointer needs to be just inbounds
/// or also inbounds of a *live* allocation.
...
...
@@ -112,10 +113,11 @@ impl AllocationExtra<()> for () { }
impl
<
Tag
,
Extra
>
Allocation
<
Tag
,
Extra
>
{
/// Creates a read-only allocation initialized by the given bytes
pub
fn
from_bytes
(
slice
:
&
[
u8
],
align
:
Align
,
extra
:
Extra
)
->
Self
{
let
undef_mask
=
UndefMask
::
new
(
Size
::
from_bytes
(
slice
.len
()
as
u64
),
true
);
pub
fn
from_bytes
<
'a
>
(
slice
:
impl
Into
<
Cow
<
'a
,
[
u8
]
>>
,
align
:
Align
,
extra
:
Extra
)
->
Self
{
let
bytes
=
slice
.into
()
.into_owned
();
let
undef_mask
=
UndefMask
::
new
(
Size
::
from_bytes
(
bytes
.len
()
as
u64
),
true
);
Self
{
bytes
:
slice
.to_owned
()
,
bytes
,
relocations
:
Relocations
::
new
(),
undef_mask
,
align
,
...
...
@@ -124,7 +126,7 @@ pub fn from_bytes(slice: &[u8], align: Align, extra: Extra) -> Self {
}
}
pub
fn
from_byte_aligned_bytes
(
slice
:
&
[
u8
]
,
extra
:
Extra
)
->
Self
{
pub
fn
from_byte_aligned_bytes
<
'a
>
(
slice
:
impl
Into
<
Cow
<
'a
,
[
u8
]
>>
,
extra
:
Extra
)
->
Self
{
Allocation
::
from_bytes
(
slice
,
Align
::
from_bytes
(
1
)
.unwrap
(),
extra
)
}
...
...
src/librustc_codegen_llvm/intrinsic.rs
浏览文件 @
5b984891
...
...
@@ -20,7 +20,6 @@
use
rustc_codegen_ssa
::
common
::{
IntPredicate
,
TypeKind
};
use
rustc
::
hir
;
use
syntax
::
ast
::{
self
,
FloatTy
};
use
syntax
::
symbol
::
LocalInternedString
;
use
rustc_codegen_ssa
::
traits
::
*
;
...
...
@@ -213,8 +212,8 @@ fn codegen_intrinsic_call(
}
"type_name"
=>
{
let
tp_ty
=
substs
.type_at
(
0
);
let
ty_name
=
LocalInternedString
::
intern
(
&
tp_ty
.to_string
()
);
self
.const_str_slice
(
ty_name
)
let
ty_name
=
rustc_mir
::
interpret
::
type_name
(
self
.tcx
,
tp_ty
);
OperandRef
::
from_const
(
self
,
ty_name
)
.immediate_or_packed_pair
(
self
)
}
"type_id"
=>
{
self
.const_u64
(
self
.tcx
.type_id_hash
(
substs
.type_at
(
0
)))
...
...
src/librustc_codegen_ssa/mir/operand.rs
浏览文件 @
5b984891
...
...
@@ -68,11 +68,11 @@ pub fn new_zst<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
pub
fn
from_const
<
Bx
:
BuilderMethods
<
'a
,
'tcx
,
Value
=
V
>>
(
bx
:
&
mut
Bx
,
val
:
&
'tcx
ty
::
Const
<
'tcx
>
)
->
Result
<
Self
,
ErrorHandled
>
{
)
->
Self
{
let
layout
=
bx
.layout_of
(
val
.ty
);
if
layout
.is_zst
()
{
return
O
k
(
OperandRef
::
new_zst
(
bx
,
layout
)
);
return
O
perandRef
::
new_zst
(
bx
,
layout
);
}
let
val
=
match
val
.val
{
...
...
@@ -110,14 +110,14 @@ pub fn from_const<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
OperandValue
::
Pair
(
a_llval
,
b_llval
)
},
ConstValue
::
ByRef
(
ptr
,
alloc
)
=>
{
return
Ok
(
bx
.load_operand
(
bx
.from_const_alloc
(
layout
,
alloc
,
ptr
.offset
)
));
return
bx
.load_operand
(
bx
.from_const_alloc
(
layout
,
alloc
,
ptr
.offset
));
},
};
O
k
(
O
perandRef
{
OperandRef
{
val
,
layout
}
)
}
}
/// Asserts that this operand refers to a scalar and returns
...
...
@@ -468,7 +468,7 @@ pub fn codegen_operand(
mir
::
Operand
::
Constant
(
ref
constant
)
=>
{
let
ty
=
self
.monomorphize
(
&
constant
.ty
);
self
.eval_mir_constant
(
constant
)
.
and_then
(|
c
|
OperandRef
::
from_const
(
bx
,
c
))
.
map
(|
c
|
OperandRef
::
from_const
(
bx
,
c
))
.unwrap_or_else
(|
err
|
{
match
err
{
// errored or at least linted
...
...
src/librustc_mir/const_eval.rs
浏览文件 @
5b984891
...
...
@@ -116,7 +116,9 @@ fn op_to_const<'tcx>(
ptr
.offset
.bytes
(),
),
Scalar
::
Raw
{
..
}
=>
(
ecx
.tcx
.intern_const_alloc
(
Allocation
::
from_byte_aligned_bytes
(
b
""
,
())),
ecx
.tcx
.intern_const_alloc
(
Allocation
::
from_byte_aligned_bytes
(
b
""
as
&
[
u8
],
(),
)),
0
,
),
};
...
...
src/librustc_mir/interpret/intrinsics.rs
浏览文件 @
5b984891
...
...
@@ -14,6 +14,9 @@
Machine
,
PlaceTy
,
OpTy
,
InterpretCx
,
};
mod
type_name
;
pub
use
type_name
::
*
;
fn
numeric_intrinsic
<
'tcx
,
Tag
>
(
name
:
&
str
,
...
...
src/librustc_mir/interpret/intrinsics/type_name.rs
0 → 100644
浏览文件 @
5b984891
use
rustc
::
ty
::{
TyCtxt
,
Ty
,
subst
::{
UnpackedKind
,
Kind
},
print
::{
Printer
,
PrettyPrinter
,
Print
},
self
,
};
use
rustc
::
hir
::
map
::{
DefPathData
,
DisambiguatedDefPathData
};
use
rustc
::
hir
::
def_id
::
CrateNum
;
use
std
::
fmt
::
Write
;
use
rustc
::
mir
::
interpret
::{
Allocation
,
ConstValue
};
struct
AbsolutePathPrinter
<
'a
,
'tcx
>
{
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
path
:
String
,
}
impl
<
'tcx
>
Printer
<
'tcx
,
'tcx
>
for
AbsolutePathPrinter
<
'_
,
'tcx
>
{
type
Error
=
std
::
fmt
::
Error
;
type
Path
=
Self
;
type
Region
=
Self
;
type
Type
=
Self
;
type
DynExistential
=
Self
;
type
Const
=
Self
;
fn
tcx
<
'a
>
(
&
'a
self
)
->
TyCtxt
<
'a
,
'tcx
,
'tcx
>
{
self
.tcx
}
fn
print_region
(
self
,
_
region
:
ty
::
Region
<
'_
>
)
->
Result
<
Self
::
Region
,
Self
::
Error
>
{
Ok
(
self
)
}
fn
print_type
(
self
,
ty
:
Ty
<
'tcx
>
)
->
Result
<
Self
::
Type
,
Self
::
Error
>
{
match
ty
.sty
{
// types without identity
|
ty
::
Bool
|
ty
::
Char
|
ty
::
Int
(
_
)
|
ty
::
Uint
(
_
)
|
ty
::
Float
(
_
)
|
ty
::
Str
|
ty
::
Array
(
_
,
_
)
|
ty
::
Slice
(
_
)
|
ty
::
RawPtr
(
_
)
|
ty
::
Ref
(
_
,
_
,
_
)
|
ty
::
FnPtr
(
_
)
|
ty
::
Never
|
ty
::
Tuple
(
_
)
|
ty
::
Dynamic
(
_
,
_
)
|
ty
::
Adt
(
..
)
|
ty
::
Foreign
(
_
)
// should be unreachable, but there's no hurt in printing it (and better than ICEing)
|
ty
::
Error
=>
self
.pretty_print_type
(
ty
),
|
ty
::
Infer
(
_
)
|
ty
::
Bound
(
_
,
_
)
|
ty
::
Param
(
_
)
|
ty
::
Placeholder
(
_
)
|
ty
::
Projection
(
_
)
|
ty
::
UnnormalizedProjection
(
_
)
|
ty
::
GeneratorWitness
(
_
)
=>
bug!
(
"{:#?} in `type_name` should not happen because we are always monomorphized"
,
ty
,
),
// types with identity (print the module path instead)
|
ty
::
FnDef
(
did
,
substs
)
|
ty
::
Opaque
(
did
,
substs
)
=>
self
.print_def_path
(
did
,
substs
),
ty
::
Closure
(
did
,
substs
)
=>
self
.print_def_path
(
did
,
substs
.substs
),
ty
::
Generator
(
did
,
substs
,
_
)
=>
self
.print_def_path
(
did
,
substs
.substs
),
}
}
fn
print_const
(
self
,
_
:
&
'tcx
ty
::
Const
<
'tcx
>
,
)
->
Result
<
Self
::
Const
,
Self
::
Error
>
{
// don't print constants to the user
Ok
(
self
)
}
fn
print_dyn_existential
(
mut
self
,
predicates
:
&
'tcx
ty
::
List
<
ty
::
ExistentialPredicate
<
'tcx
>>
,
)
->
Result
<
Self
::
DynExistential
,
Self
::
Error
>
{
let
mut
first
=
true
;
for
p
in
predicates
{
if
!
first
{
write!
(
self
,
"+"
)
?
;
}
first
=
false
;
self
=
p
.print
(
self
)
?
;
}
Ok
(
self
)
}
fn
path_crate
(
mut
self
,
cnum
:
CrateNum
)
->
Result
<
Self
::
Path
,
Self
::
Error
>
{
self
.path
.push_str
(
&
self
.tcx
.original_crate_name
(
cnum
)
.as_str
());
Ok
(
self
)
}
fn
path_qualified
(
self
,
self_ty
:
Ty
<
'tcx
>
,
trait_ref
:
Option
<
ty
::
TraitRef
<
'tcx
>>
,
)
->
Result
<
Self
::
Path
,
Self
::
Error
>
{
self
.pretty_path_qualified
(
self_ty
,
trait_ref
)
}
fn
path_append_impl
(
self
,
print_prefix
:
impl
FnOnce
(
Self
)
->
Result
<
Self
::
Path
,
Self
::
Error
>
,
_
disambiguated_data
:
&
DisambiguatedDefPathData
,
self_ty
:
Ty
<
'tcx
>
,
trait_ref
:
Option
<
ty
::
TraitRef
<
'tcx
>>
,
)
->
Result
<
Self
::
Path
,
Self
::
Error
>
{
self
.pretty_path_append_impl
(
|
mut
cx
|
{
cx
=
print_prefix
(
cx
)
?
;
cx
.path
.push_str
(
"::"
);
Ok
(
cx
)
},
self_ty
,
trait_ref
,
)
}
fn
path_append
(
mut
self
,
print_prefix
:
impl
FnOnce
(
Self
)
->
Result
<
Self
::
Path
,
Self
::
Error
>
,
disambiguated_data
:
&
DisambiguatedDefPathData
,
)
->
Result
<
Self
::
Path
,
Self
::
Error
>
{
self
=
print_prefix
(
self
)
?
;
// Skip `::{{constructor}}` on tuple/unit structs.
match
disambiguated_data
.data
{
DefPathData
::
Ctor
=>
return
Ok
(
self
),
_
=>
{}
}
self
.path
.push_str
(
"::"
);
self
.path
.push_str
(
&
disambiguated_data
.data
.as_interned_str
()
.as_str
());
Ok
(
self
)
}
fn
path_generic_args
(
mut
self
,
print_prefix
:
impl
FnOnce
(
Self
)
->
Result
<
Self
::
Path
,
Self
::
Error
>
,
args
:
&
[
Kind
<
'tcx
>
],
)
->
Result
<
Self
::
Path
,
Self
::
Error
>
{
self
=
print_prefix
(
self
)
?
;
let
args
=
args
.iter
()
.cloned
()
.filter
(|
arg
|
{
match
arg
.unpack
()
{
UnpackedKind
::
Lifetime
(
_
)
=>
false
,
_
=>
true
,
}
});
if
args
.clone
()
.next
()
.is_some
()
{
self
.generic_delimiters
(|
cx
|
cx
.comma_sep
(
args
))
}
else
{
Ok
(
self
)
}
}
}
impl
PrettyPrinter
<
'tcx
,
'tcx
>
for
AbsolutePathPrinter
<
'_
,
'tcx
>
{
fn
region_should_not_be_omitted
(
&
self
,
_
region
:
ty
::
Region
<
'_
>
,
)
->
bool
{
false
}
fn
comma_sep
<
T
>
(
mut
self
,
mut
elems
:
impl
Iterator
<
Item
=
T
>
,
)
->
Result
<
Self
,
Self
::
Error
>
where
T
:
Print
<
'tcx
,
'tcx
,
Self
,
Output
=
Self
,
Error
=
Self
::
Error
>
{
if
let
Some
(
first
)
=
elems
.next
()
{
self
=
first
.print
(
self
)
?
;
for
elem
in
elems
{
self
.path
.push_str
(
", "
);
self
=
elem
.print
(
self
)
?
;
}
}
Ok
(
self
)
}
fn
generic_delimiters
(
mut
self
,
f
:
impl
FnOnce
(
Self
)
->
Result
<
Self
,
Self
::
Error
>
,
)
->
Result
<
Self
,
Self
::
Error
>
{
write!
(
self
,
"<"
)
?
;
self
=
f
(
self
)
?
;
write!
(
self
,
">"
)
?
;
Ok
(
self
)
}
}
impl
Write
for
AbsolutePathPrinter
<
'_
,
'_
>
{
fn
write_str
(
&
mut
self
,
s
:
&
str
)
->
std
::
fmt
::
Result
{
Ok
(
self
.path
.push_str
(
s
))
}
}
/// Produces an absolute path representation of the given type. See also the documentation on
/// `std::any::type_name`
pub
fn
type_name
<
'a
,
'tcx
>
(
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
ty
:
Ty
<
'tcx
>
)
->
&
'tcx
ty
::
Const
<
'tcx
>
{
let
path
=
AbsolutePathPrinter
{
tcx
,
path
:
String
::
new
()
}
.print_type
(
ty
)
.unwrap
()
.path
;
let
len
=
path
.len
();
let
alloc
=
Allocation
::
from_byte_aligned_bytes
(
path
.into_bytes
(),
());
let
alloc
=
tcx
.intern_const_alloc
(
alloc
);
tcx
.mk_const
(
ty
::
Const
{
val
:
ConstValue
::
Slice
{
data
:
alloc
,
start
:
0
,
end
:
len
,
},
ty
:
tcx
.mk_static_str
(),
})
}
src/librustc_mir/interpret/mod.rs
浏览文件 @
5b984891
...
...
@@ -32,3 +32,5 @@
pub
use
self
::
visitor
::{
ValueVisitor
,
MutValueVisitor
};
pub
use
self
::
validity
::
RefTracking
;
pub
use
self
::
intrinsics
::
type_name
;
src/test/run-pass/issues/issue-21058.rs
浏览文件 @
5b984891
...
...
@@ -2,21 +2,64 @@
#![allow(dead_code)]
#![feature(core_intrinsics)]
use
std
::
fmt
::
Debug
;
struct
NT
(
str
);
struct
DST
{
a
:
u32
,
b
:
str
}
macro_rules!
check
{
(
val
:
$ty_of:expr
,
$expected:expr
)
=>
{
assert_eq!
(
type_name_of_val
(
$ty_of
),
$expected
);
};
(
$ty:ty
,
$expected:expr
)
=>
{
assert_eq!
(
unsafe
{
std
::
intrinsics
::
type_name
::
<
$ty
>
()},
$expected
);
};
}
fn
main
()
{
// type_name should support unsized types
assert_eq!
(
unsafe
{(
// Slice
std
::
intrinsics
::
type_name
::
<
[
u8
]
>
(),
// str
std
::
intrinsics
::
type_name
::
<
str
>
(),
// Trait
std
::
intrinsics
::
type_name
::
<
dyn
Send
>
(),
// Newtype
std
::
intrinsics
::
type_name
::
<
NT
>
(),
// DST
std
::
intrinsics
::
type_name
::
<
DST
>
()
)},
(
"[u8]"
,
"str"
,
"dyn std::marker::Send"
,
"NT"
,
"DST"
));
check!
([
u8
],
"[u8]"
);
check!
(
str
,
"str"
);
check!
(
dyn
Send
,
"dyn core::marker::Send"
);
check!
(
NT
,
"issue_21058::NT"
);
check!
(
DST
,
"issue_21058::DST"
);
check!
(
&
i32
,
"&i32"
);
check!
(
&
'static
i32
,
"&i32"
);
check!
((
i32
,
u32
),
"(i32, u32)"
);
check!
(
val
:
foo
(),
"issue_21058::Foo"
);
check!
(
val
:
Foo
::
new
,
"issue_21058::Foo::new"
);
check!
(
val
:
<
Foo
as
Debug
>
::
fmt
,
"<issue_21058::Foo as core::fmt::Debug>::fmt"
);
check!
(
val
:
||
{},
"issue_21058::main::{{closure}}"
);
bar
::
<
i32
>
();
}
trait
Trait
{
type
Assoc
;
}
impl
Trait
for
i32
{
type
Assoc
=
String
;
}
fn
bar
<
T
:
Trait
>
()
{
check!
(
T
::
Assoc
,
"alloc::string::String"
);
check!
(
T
,
"i32"
);
}
fn
type_name_of_val
<
T
>
(
_
:
T
)
->
&
'static
str
{
unsafe
{
std
::
intrinsics
::
type_name
::
<
T
>
()
}
}
#[derive(Debug)]
struct
Foo
;
impl
Foo
{
fn
new
()
->
Self
{
Foo
}
}
fn
foo
()
->
impl
Debug
{
Foo
}
src/test/run-pass/tydesc-name.rs
浏览文件 @
5b984891
...
...
@@ -11,6 +11,6 @@ struct Foo<T> {
pub
fn
main
()
{
unsafe
{
assert_eq!
(
type_name
::
<
isize
>
(),
"isize"
);
assert_eq!
(
type_name
::
<
Foo
<
usize
>>
(),
"Foo<usize>"
);
assert_eq!
(
type_name
::
<
Foo
<
usize
>>
(),
"
tydesc_name::
Foo<usize>"
);
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录