Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
ced5e04e
R
Rust
项目概览
int
/
Rust
11 个月 前同步成功
通知
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,发现更多精彩内容 >>
提交
ced5e04e
编写于
9月 26, 2017
作者:
E
Eduard-Mihai Burtescu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
rustc: optimize out uninhabited types and variants.
上级
f62e43da
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
197 addition
and
92 deletion
+197
-92
src/librustc/ty/layout.rs
src/librustc/ty/layout.rs
+105
-46
src/librustc_trans/abi.rs
src/librustc_trans/abi.rs
+3
-0
src/librustc_trans/cabi_x86_64.rs
src/librustc_trans/cabi_x86_64.rs
+2
-0
src/librustc_trans/cabi_x86_win64.rs
src/librustc_trans/cabi_x86_win64.rs
+1
-0
src/librustc_trans/debuginfo/metadata.rs
src/librustc_trans/debuginfo/metadata.rs
+28
-33
src/librustc_trans/mir/block.rs
src/librustc_trans/mir/block.rs
+5
-1
src/librustc_trans/mir/constant.rs
src/librustc_trans/mir/constant.rs
+7
-3
src/librustc_trans/mir/lvalue.rs
src/librustc_trans/mir/lvalue.rs
+18
-7
src/librustc_trans/type_of.rs
src/librustc_trans/type_of.rs
+5
-2
src/test/ui/print_type_sizes/uninhabited.rs
src/test/ui/print_type_sizes/uninhabited.rs
+18
-0
src/test/ui/print_type_sizes/uninhabited.stdout
src/test/ui/print_type_sizes/uninhabited.stdout
+5
-0
未找到文件。
src/librustc/ty/layout.rs
浏览文件 @
ced5e04e
...
...
@@ -755,6 +755,7 @@ pub fn index_by_increasing_offset<'a>(&'a self) -> impl iter::Iterator<Item=usiz
/// in terms of categories of C types there are ABI rules for.
#[derive(Clone,
PartialEq,
Eq,
Hash,
Debug)]
pub
enum
Abi
{
Uninhabited
,
Scalar
(
Scalar
),
Vector
,
Aggregate
{
...
...
@@ -768,7 +769,7 @@ impl Abi {
/// Returns true if the layout corresponds to an unsized type.
pub
fn
is_unsized
(
&
self
)
->
bool
{
match
*
self
{
Abi
::
Scalar
(
_
)
|
Abi
::
Vector
=>
false
,
Abi
::
Uninhabited
|
Abi
::
Scalar
(
_
)
|
Abi
::
Vector
=>
false
,
Abi
::
Aggregate
{
sized
,
..
}
=>
!
sized
}
}
...
...
@@ -776,7 +777,7 @@ pub fn is_unsized(&self) -> bool {
/// Returns true if the fields of the layout are packed.
pub
fn
is_packed
(
&
self
)
->
bool
{
match
*
self
{
Abi
::
Scalar
(
_
)
|
Abi
::
Vector
=>
false
,
Abi
::
Uninhabited
|
Abi
::
Scalar
(
_
)
|
Abi
::
Vector
=>
false
,
Abi
::
Aggregate
{
packed
,
..
}
=>
packed
}
}
...
...
@@ -807,6 +808,7 @@ pub enum Variants {
/// `Some` is the identity function (with a non-null reference).
NicheFilling
{
dataful_variant
:
usize
,
niche_variant
:
usize
,
niche
:
Scalar
,
niche_value
:
u128
,
variants
:
Vec
<
CachedLayout
>
,
...
...
@@ -855,6 +857,18 @@ fn scalar<C: HasDataLayout>(cx: C, scalar: Scalar) -> Self {
primitive_align
:
align
}
}
fn
uninhabited
(
field_count
:
usize
)
->
Self
{
let
align
=
Align
::
from_bytes
(
1
,
1
)
.unwrap
();
CachedLayout
{
variants
:
Variants
::
Single
{
index
:
0
},
fields
:
FieldPlacement
::
Union
(
field_count
),
abi
:
Abi
::
Uninhabited
,
align
,
primitive_align
:
align
,
size
:
Size
::
from_bytes
(
0
)
}
}
}
fn
layout_raw
<
'a
,
'tcx
>
(
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
...
...
@@ -915,13 +929,14 @@ enum StructKind {
bug!
(
"struct cannot be packed and aligned"
);
}
let
mut
align
=
if
packed
{
let
base_
align
=
if
packed
{
dl
.i8_align
}
else
{
dl
.aggregate_align
};
let
mut
primitive_align
=
align
;
let
mut
align
=
base_align
;
let
mut
primitive_align
=
base_align
;
let
mut
sized
=
true
;
// Anything with repr(C) or repr(packed) doesn't optimize.
...
...
@@ -978,13 +993,17 @@ enum StructKind {
}
}
for
i
in
inverse_memory_index
.iter
()
{
let
field
=
fields
[
*
i
as
usize
];
for
&
i
in
&
inverse_memory_index
{
let
field
=
fields
[
i
as
usize
];
if
!
sized
{
bug!
(
"univariant: field #{} of `{}` comes after unsized field"
,
offsets
.len
(),
ty
);
}
if
field
.abi
==
Abi
::
Uninhabited
{
return
Ok
(
CachedLayout
::
uninhabited
(
fields
.len
()));
}
if
field
.is_unsized
()
{
sized
=
false
;
}
...
...
@@ -997,7 +1016,7 @@ enum StructKind {
}
debug!
(
"univariant offset: {:?} field: {:#?}"
,
offset
,
field
);
offsets
[
*
i
as
usize
]
=
offset
;
offsets
[
i
as
usize
]
=
offset
;
offset
=
offset
.checked_add
(
field
.size
,
dl
)
.ok_or
(
LayoutError
::
SizeOverflow
(
ty
))
?
;
...
...
@@ -1124,7 +1143,7 @@ enum StructKind {
// The never type.
ty
::
TyNever
=>
{
univariant
(
&
[],
&
ReprOptions
::
default
(),
StructKind
::
AlwaysSized
)
?
tcx
.intern_layout
(
CachedLayout
::
uninhabited
(
0
))
}
// Potentially-fat pointers.
...
...
@@ -1278,11 +1297,15 @@ enum StructKind {
})
.collect
::
<
Result
<
Vec
<
_
>
,
_
>>
()
})
.collect
::
<
Result
<
Vec
<
_
>
,
_
>>
()
?
;
if
variants
.is_empty
()
{
// Uninhabitable; represent as unit
// (Typechecking will reject discriminant-sizing attrs.)
return
univariant
(
&
[],
&
def
.repr
,
StructKind
::
AlwaysSized
);
let
(
inh_first
,
inh_second
,
inh_third
)
=
{
let
mut
inh_variants
=
(
0
..
variants
.len
())
.filter
(|
&
v
|
{
variants
[
v
]
.iter
()
.all
(|
f
|
f
.abi
!=
Abi
::
Uninhabited
)
});
(
inh_variants
.next
(),
inh_variants
.next
(),
inh_variants
.next
())
};
if
inh_first
.is_none
()
{
// Uninhabited because it has no variants, or only uninhabited ones.
return
Ok
(
tcx
.intern_layout
(
CachedLayout
::
uninhabited
(
0
)));
}
if
def
.is_union
()
{
...
...
@@ -1329,49 +1352,58 @@ enum StructKind {
}));
}
if
!
def
.is_enum
()
||
(
variants
.len
()
==
1
&&
!
def
.repr
.inhibit_enum_layout_opt
()
&&
!
variants
[
0
]
.is_empty
())
{
// Struct, or union, or univariant enum equivalent to a struct.
let
is_struct
=
!
def
.is_enum
()
||
// Only one variant is inhabited.
(
inh_second
.is_none
()
&&
// Representation optimizations are allowed.
!
def
.repr
.inhibit_enum_layout_opt
()
&&
// Inhabited variant either has data ...
(
!
variants
[
inh_first
.unwrap
()]
.is_empty
()
||
// ... or there other, uninhabited, variants.
variants
.len
()
>
1
));
if
is_struct
{
// Struct, or univariant enum equivalent to a struct.
// (Typechecking will reject discriminant-sizing attrs.)
let
kind
=
if
def
.is_enum
()
||
variants
[
0
]
.len
()
==
0
{
let
v
=
inh_first
.unwrap
();
let
kind
=
if
def
.is_enum
()
||
variants
[
v
]
.len
()
==
0
{
StructKind
::
AlwaysSized
}
else
{
let
param_env
=
tcx
.param_env
(
def
.did
);
let
last_field
=
def
.variants
[
0
]
.fields
.last
()
.unwrap
();
let
last_field
=
def
.variants
[
v
]
.fields
.last
()
.unwrap
();
let
always_sized
=
tcx
.type_of
(
last_field
.did
)
.is_sized
(
tcx
,
param_env
,
DUMMY_SP
);
if
!
always_sized
{
StructKind
::
MaybeUnsized
}
else
{
StructKind
::
AlwaysSized
}
};
return
univariant
(
&
variants
[
0
],
&
def
.repr
,
kind
);
let
mut
st
=
univariant_uninterned
(
&
variants
[
v
],
&
def
.repr
,
kind
)
?
;
st
.variants
=
Variants
::
Single
{
index
:
v
};
return
Ok
(
tcx
.intern_layout
(
st
));
}
let
no_explicit_discriminants
=
def
.variants
.iter
()
.enumerate
()
.all
(|(
i
,
v
)|
v
.discr
==
ty
::
VariantDiscr
::
Relative
(
i
));
if
variants
.len
()
==
2
&&
if
inh_second
.is_some
()
&&
inh_third
.is_none
()
&&
!
def
.repr
.inhibit_enum_layout_opt
()
&&
no_explicit_discriminants
{
// Nullable pointer optimization
for
i
in
0
..
2
{
if
!
variants
[
1
-
i
]
.iter
()
.all
(|
f
|
f
.is_zst
())
{
let
(
a
,
b
)
=
(
inh_first
.unwrap
(),
inh_second
.unwrap
());
for
&
(
i
,
other
)
in
&
[(
a
,
b
),
(
b
,
a
)]
{
if
!
variants
[
other
]
.iter
()
.all
(|
f
|
f
.is_zst
())
{
continue
;
}
for
(
field_index
,
field
)
in
variants
[
i
]
.iter
()
.enumerate
()
{
if
let
Some
((
offset
,
niche
,
niche_value
))
=
field
.find_niche
(
cx
)
?
{
let
mut
st
=
vec!
[
univariant_uninterned
(
&
variants
[
0
],
&
def
.repr
,
StructKind
::
AlwaysSized
)
?
,
univariant_uninterned
(
&
variants
[
1
],
&
def
.repr
,
StructKind
::
AlwaysSized
)
?
];
for
(
i
,
v
)
in
st
.iter_mut
()
.enumerate
()
{
v
.variants
=
Variants
::
Single
{
index
:
i
};
}
let
st
=
variants
.iter
()
.enumerate
()
.map
(|(
j
,
v
)|
{
let
mut
st
=
univariant_uninterned
(
v
,
&
def
.repr
,
StructKind
::
AlwaysSized
)
?
;
st
.variants
=
Variants
::
Single
{
index
:
j
};
Ok
(
st
)
})
.collect
::
<
Result
<
Vec
<
_
>
,
_
>>
()
?
;
let
offset
=
st
[
i
]
.fields
.offset
(
field_index
)
+
offset
;
let
CachedLayout
{
size
,
...
...
@@ -1400,6 +1432,7 @@ enum StructKind {
return
Ok
(
tcx
.intern_layout
(
CachedLayout
{
variants
:
Variants
::
NicheFilling
{
dataful_variant
:
i
,
niche_variant
:
other
,
niche
,
niche_value
,
variants
:
st
,
...
...
@@ -1419,11 +1452,15 @@ enum StructKind {
}
let
(
mut
min
,
mut
max
)
=
(
i128
::
max_value
(),
i128
::
min_value
());
for
discr
in
def
.discriminants
(
tcx
)
{
for
(
i
,
discr
)
in
def
.discriminants
(
tcx
)
.enumerate
()
{
if
variants
[
i
]
.iter
()
.any
(|
f
|
f
.abi
==
Abi
::
Uninhabited
)
{
continue
;
}
let
x
=
discr
.to_u128_unchecked
()
as
i128
;
if
x
<
min
{
min
=
x
;
}
if
x
>
max
{
max
=
x
;
}
}
assert
!
(
min
<=
max
,
"discriminant range is {}...{}"
,
min
,
max
);
let
(
min_ity
,
signed
)
=
Integer
::
repr_discr
(
tcx
,
ty
,
&
def
.repr
,
min
,
max
);
let
mut
align
=
dl
.aggregate_align
;
...
...
@@ -1498,6 +1535,9 @@ enum StructKind {
let
old_ity_size
=
min_ity
.size
();
let
new_ity_size
=
ity
.size
();
for
variant
in
&
mut
variants
{
if
variant
.abi
==
Abi
::
Uninhabited
{
continue
;
}
match
variant
.fields
{
FieldPlacement
::
Arbitrary
{
ref
mut
offsets
,
..
}
=>
{
for
i
in
offsets
{
...
...
@@ -1663,16 +1703,11 @@ fn record_layout_for_printing_outlined(tcx: TyCtxt<'a, 'tcx, 'tcx>,
};
match
layout
.variants
{
Variants
::
Single
{
..
}
=>
{
let
variant_names
=
||
{
adt_def
.variants
.iter
()
.map
(|
v
|
format!
(
"{}"
,
v
.name
))
.collect
::
<
Vec
<
_
>>
()
};
debug!
(
"print-type-size `{:#?}` variants: {:?}"
,
layout
,
variant_names
());
assert
!
(
adt_def
.variants
.len
()
<=
1
,
"univariant with variants {:?}"
,
variant_names
());
if
adt_def
.variants
.len
()
==
1
{
let
variant_def
=
&
adt_def
.variants
[
0
];
Variants
::
Single
{
index
}
=>
{
debug!
(
"print-type-size `{:#?}` variant {}"
,
layout
,
adt_def
.variants
[
index
]
.name
);
if
!
adt_def
.variants
.is_empty
()
{
let
variant_def
=
&
adt_def
.variants
[
index
];
let
fields
:
Vec
<
_
>
=
variant_def
.fields
.iter
()
.map
(|
f
|
f
.name
)
.collect
();
record
(
adt_kind
.into
(),
...
...
@@ -1697,7 +1732,7 @@ fn record_layout_for_printing_outlined(tcx: TyCtxt<'a, 'tcx, 'tcx>,
variant_def
.fields
.iter
()
.map
(|
f
|
f
.name
)
.collect
();
build_variant_info
(
Some
(
variant_def
.name
),
&
fields
,
layout
.for_variant
(
i
))
layout
.for_variant
(
cx
,
i
))
})
.collect
();
record
(
adt_kind
.into
(),
match
layout
.variants
{
...
...
@@ -1989,15 +2024,35 @@ fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
}
impl
<
'a
,
'tcx
>
TyLayout
<
'tcx
>
{
pub
fn
for_variant
(
&
self
,
variant_index
:
usize
)
->
Self
{
pub
fn
for_variant
<
C
>
(
&
self
,
cx
:
C
,
variant_index
:
usize
)
->
Self
where
C
:
LayoutOf
<
Ty
<
'tcx
>>
+
HasTyCtxt
<
'tcx
>
,
C
::
TyLayout
:
MaybeResult
<
TyLayout
<
'tcx
>>
{
let
cached
=
match
self
.variants
{
Variants
::
Single
{
..
}
=>
self
.cached
,
Variants
::
Single
{
index
}
if
index
==
variant_index
=>
self
.cached
,
Variants
::
Single
{
index
}
=>
{
// Deny calling for_variant more than once for non-Single enums.
cx
.layout_of
(
self
.ty
)
.map_same
(|
layout
|
{
assert_eq!
(
layout
.variants
,
Variants
::
Single
{
index
});
layout
});
let
fields
=
match
self
.ty.sty
{
ty
::
TyAdt
(
def
,
_
)
=>
def
.variants
[
variant_index
]
.fields
.len
(),
_
=>
bug!
()
};
let
mut
cached
=
CachedLayout
::
uninhabited
(
fields
);
cached
.variants
=
Variants
::
Single
{
index
:
variant_index
};
cx
.tcx
()
.intern_layout
(
cached
)
}
Variants
::
NicheFilling
{
ref
variants
,
..
}
|
Variants
::
Tagged
{
ref
variants
,
..
}
=>
{
&
variants
[
variant_index
]
}
};
assert_eq!
(
cached
.variants
,
Variants
::
Single
{
index
:
variant_index
});
TyLayout
{
...
...
@@ -2138,6 +2193,7 @@ pub fn is_packed(&self) -> bool {
/// Returns true if the type is a ZST and not unsized.
pub
fn
is_zst
(
&
self
)
->
bool
{
match
self
.abi
{
Abi
::
Uninhabited
=>
true
,
Abi
::
Scalar
(
_
)
=>
false
,
Abi
::
Vector
=>
self
.size
.bytes
()
==
0
,
Abi
::
Aggregate
{
sized
,
..
}
=>
sized
&&
self
.size
.bytes
()
==
0
...
...
@@ -2241,11 +2297,13 @@ fn hash_stable<W: StableHasherResult>(&self,
}
NicheFilling
{
dataful_variant
,
niche_variant
,
ref
niche
,
niche_value
,
ref
variants
,
}
=>
{
dataful_variant
.hash_stable
(
hcx
,
hasher
);
niche_variant
.hash_stable
(
hcx
,
hasher
);
niche
.hash_stable
(
hcx
,
hasher
);
niche_value
.hash_stable
(
hcx
,
hasher
);
variants
.hash_stable
(
hcx
,
hasher
);
...
...
@@ -2285,6 +2343,7 @@ fn hash_stable<W: StableHasherResult>(&self,
mem
::
discriminant
(
self
)
.hash_stable
(
hcx
,
hasher
);
match
*
self
{
Uninhabited
=>
{}
Scalar
(
ref
value
)
=>
{
value
.hash_stable
(
hcx
,
hasher
);
}
...
...
src/librustc_trans/abi.rs
浏览文件 @
ced5e04e
...
...
@@ -278,6 +278,7 @@ pub trait LayoutExt<'tcx> {
impl
<
'tcx
>
LayoutExt
<
'tcx
>
for
TyLayout
<
'tcx
>
{
fn
is_aggregate
(
&
self
)
->
bool
{
match
self
.abi
{
layout
::
Abi
::
Uninhabited
|
layout
::
Abi
::
Scalar
(
_
)
|
layout
::
Abi
::
Vector
=>
false
,
layout
::
Abi
::
Aggregate
{
..
}
=>
true
...
...
@@ -286,6 +287,8 @@ fn is_aggregate(&self) -> bool {
fn
homogeneous_aggregate
<
'a
>
(
&
self
,
ccx
:
&
CrateContext
<
'a
,
'tcx
>
)
->
Option
<
Reg
>
{
match
self
.abi
{
layout
::
Abi
::
Uninhabited
=>
None
,
// The primitive for this algorithm.
layout
::
Abi
::
Scalar
(
ref
scalar
)
=>
{
let
kind
=
match
scalar
.value
{
...
...
src/librustc_trans/cabi_x86_64.rs
浏览文件 @
ced5e04e
...
...
@@ -65,6 +65,8 @@ fn classify<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
}
match
layout
.abi
{
layout
::
Abi
::
Uninhabited
=>
{}
layout
::
Abi
::
Scalar
(
ref
scalar
)
=>
{
let
reg
=
match
scalar
.value
{
layout
::
Int
(
..
)
|
...
...
src/librustc_trans/cabi_x86_win64.rs
浏览文件 @
ced5e04e
...
...
@@ -17,6 +17,7 @@
pub
fn
compute_abi_info
(
fty
:
&
mut
FnType
)
{
let
fixup
=
|
a
:
&
mut
ArgType
|
{
match
a
.layout.abi
{
layout
::
Abi
::
Uninhabited
=>
{}
layout
::
Abi
::
Aggregate
{
..
}
=>
{
match
a
.layout.size
.bits
()
{
8
=>
a
.cast_to
(
Reg
::
i8
()),
...
...
src/librustc_trans/debuginfo/metadata.rs
浏览文件 @
ced5e04e
...
...
@@ -1130,43 +1130,38 @@ fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
->
Vec
<
MemberDescription
>
{
let
adt
=
&
self
.enum_type
.ty_adt_def
()
.unwrap
();
match
self
.layout.variants
{
layout
::
Variants
::
Single
{
..
}
=>
{
assert
!
(
adt
.variants
.len
()
<=
1
);
if
adt
.variants
.is_empty
()
{
vec!
[]
}
else
{
let
(
variant_type_metadata
,
member_description_factory
)
=
describe_enum_variant
(
cx
,
self
.layout
,
&
adt
.variants
[
0
],
NoDiscriminant
,
self
.containing_scope
,
self
.span
);
layout
::
Variants
::
Single
{
..
}
if
adt
.variants
.is_empty
()
=>
vec!
[],
layout
::
Variants
::
Single
{
index
}
=>
{
let
(
variant_type_metadata
,
member_description_factory
)
=
describe_enum_variant
(
cx
,
self
.layout
,
&
adt
.variants
[
index
],
NoDiscriminant
,
self
.containing_scope
,
self
.span
);
let
member_descriptions
=
member_description_factory
.create_member_descriptions
(
cx
);
let
member_descriptions
=
member_description_factory
.create_member_descriptions
(
cx
);
set_members_of_composite_type
(
cx
,
variant_type_metadata
,
&
member_descriptions
[
..
]);
vec!
[
MemberDescription
{
name
:
""
.to_string
(),
type_metadata
:
variant_type_metadata
,
offset
:
Size
::
from_bytes
(
0
),
size
:
self
.layout.size
,
align
:
self
.layout.align
,
flags
:
DIFlags
::
FlagZero
}
]
}
set_members_of_composite_type
(
cx
,
variant_type_metadata
,
&
member_descriptions
[
..
]);
vec!
[
MemberDescription
{
name
:
""
.to_string
(),
type_metadata
:
variant_type_metadata
,
offset
:
Size
::
from_bytes
(
0
),
size
:
self
.layout.size
,
align
:
self
.layout.align
,
flags
:
DIFlags
::
FlagZero
}
]
}
layout
::
Variants
::
Tagged
{
ref
variants
,
..
}
=>
{
let
discriminant_info
=
RegularDiscriminant
(
self
.discriminant_type_metadata
.expect
(
""
));
(
0
..
variants
.len
())
.map
(|
i
|
{
let
variant
=
self
.layout
.for_variant
(
i
);
let
variant
=
self
.layout
.for_variant
(
cx
,
i
);
let
(
variant_type_metadata
,
member_desc_factory
)
=
describe_enum_variant
(
cx
,
variant
,
...
...
@@ -1191,8 +1186,8 @@ fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
}
})
.collect
()
}
layout
::
Variants
::
NicheFilling
{
dataful_variant
,
..
}
=>
{
let
variant
=
self
.layout
.for_variant
(
dataful_variant
);
layout
::
Variants
::
NicheFilling
{
dataful_variant
,
niche_variant
,
..
}
=>
{
let
variant
=
self
.layout
.for_variant
(
cx
,
dataful_variant
);
// Create a description of the non-null variant
let
(
variant_type_metadata
,
member_description_factory
)
=
describe_enum_variant
(
cx
,
...
...
@@ -1236,7 +1231,7 @@ fn compute_field_path<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
self
.layout
,
self
.layout.fields
.offset
(
0
),
self
.layout
.field
(
cx
,
0
)
.size
);
name
.push_str
(
&
adt
.variants
[
1
-
dataful
_variant
]
.name
.as_str
());
name
.push_str
(
&
adt
.variants
[
niche
_variant
]
.name
.as_str
());
// Create the (singleton) list of descriptions of union members.
vec!
[
...
...
src/librustc_trans/mir/block.rs
浏览文件 @
ced5e04e
...
...
@@ -710,7 +710,11 @@ fn trans_arguments_untupled(&mut self,
Immediate
(
llval
)
=>
{
for
i
in
0
..
tuple
.layout.fields
.count
()
{
let
field
=
tuple
.layout
.field
(
bcx
.ccx
,
i
);
let
elem
=
bcx
.extract_value
(
llval
,
tuple
.layout
.llvm_field_index
(
i
));
let
elem
=
if
field
.is_zst
()
{
C_undef
(
field
.llvm_type
(
bcx
.ccx
))
}
else
{
bcx
.extract_value
(
llval
,
tuple
.layout
.llvm_field_index
(
i
))
};
// If the tuple is immediate, the elements are as well
let
op
=
OperandRef
{
val
:
Immediate
(
base
::
to_immediate
(
bcx
,
elem
,
field
)),
...
...
src/librustc_trans/mir/constant.rs
浏览文件 @
ced5e04e
...
...
@@ -1099,6 +1099,11 @@ fn trans_const_adt<'a, 'tcx>(
mir
::
AggregateKind
::
Adt
(
_
,
index
,
_
,
_
)
=>
index
,
_
=>
0
,
};
if
let
layout
::
Abi
::
Uninhabited
=
l
.abi
{
return
Const
::
new
(
C_undef
(
l
.llvm_type
(
ccx
)),
t
);
}
match
l
.variants
{
layout
::
Variants
::
Single
{
index
}
=>
{
assert_eq!
(
variant_index
,
index
);
...
...
@@ -1114,7 +1119,6 @@ fn trans_const_adt<'a, 'tcx>(
Const
::
new
(
C_struct
(
ccx
,
&
contents
,
l
.is_packed
()),
t
)
}
else
{
assert_eq!
(
variant_index
,
0
);
build_const_struct
(
ccx
,
l
,
vals
,
None
)
}
}
...
...
@@ -1132,12 +1136,12 @@ fn trans_const_adt<'a, 'tcx>(
Const
::
new
(
discr
,
t
)
}
else
{
let
discr
=
Const
::
new
(
discr
,
discr_field
.ty
);
build_const_struct
(
ccx
,
l
.for_variant
(
variant_index
),
vals
,
Some
(
discr
))
build_const_struct
(
ccx
,
l
.for_variant
(
ccx
,
variant_index
),
vals
,
Some
(
discr
))
}
}
layout
::
Variants
::
NicheFilling
{
dataful_variant
,
niche_value
,
..
}
=>
{
if
variant_index
==
dataful_variant
{
build_const_struct
(
ccx
,
l
.for_variant
(
dataful_variant
),
vals
,
None
)
build_const_struct
(
ccx
,
l
.for_variant
(
ccx
,
dataful_variant
),
vals
,
None
)
}
else
{
let
niche
=
l
.field
(
ccx
,
0
);
let
niche_llty
=
niche
.llvm_type
(
ccx
);
...
...
src/librustc_trans/mir/lvalue.rs
浏览文件 @
ced5e04e
...
...
@@ -115,7 +115,7 @@ pub fn len(&self, ccx: &CrateContext<'a, 'tcx>) -> ValueRef {
assert_eq!
(
count
,
0
);
self
.llextra
}
else
{
common
::
C_usize
(
ccx
,
count
)
C_usize
(
ccx
,
count
)
}
}
else
{
bug!
(
"unexpected layout `{:#?}` in LvalueRef::len"
,
self
.layout
)
...
...
@@ -304,7 +304,12 @@ pub fn trans_get_discr(self, bcx: &Builder<'a, 'tcx>, cast_to: Ty<'tcx>) -> Valu
};
bcx
.intcast
(
lldiscr
,
cast_to
,
signed
)
}
layout
::
Variants
::
NicheFilling
{
dataful_variant
,
niche_value
,
..
}
=>
{
layout
::
Variants
::
NicheFilling
{
dataful_variant
,
niche_variant
,
niche_value
,
..
}
=>
{
let
niche_llty
=
discr
.layout
.llvm_type
(
bcx
.ccx
);
// FIXME(eddyb) Check the actual primitive type here.
let
niche_llval
=
if
niche_value
==
0
{
...
...
@@ -313,8 +318,9 @@ pub fn trans_get_discr(self, bcx: &Builder<'a, 'tcx>, cast_to: Ty<'tcx>) -> Valu
}
else
{
C_uint_big
(
niche_llty
,
niche_value
)
};
let
cmp
=
if
dataful_variant
==
0
{
llvm
::
IntEQ
}
else
{
llvm
::
IntNE
};
bcx
.intcast
(
bcx
.icmp
(
cmp
,
lldiscr
,
niche_llval
),
cast_to
,
false
)
bcx
.select
(
bcx
.icmp
(
llvm
::
IntEQ
,
lldiscr
,
niche_llval
),
C_uint
(
cast_to
,
niche_variant
as
u64
),
C_uint
(
cast_to
,
dataful_variant
as
u64
))
}
}
}
...
...
@@ -324,7 +330,12 @@ pub fn trans_get_discr(self, bcx: &Builder<'a, 'tcx>, cast_to: Ty<'tcx>) -> Valu
pub
fn
trans_set_discr
(
&
self
,
bcx
:
&
Builder
<
'a
,
'tcx
>
,
variant_index
:
usize
)
{
match
self
.layout.variants
{
layout
::
Variants
::
Single
{
index
}
=>
{
assert_eq!
(
variant_index
,
index
);
if
index
!=
variant_index
{
// If the layout of an enum is `Single`, all
// other variants are necessarily uninhabited.
assert_eq!
(
self
.layout
.for_variant
(
bcx
.ccx
,
variant_index
)
.abi
,
layout
::
Abi
::
Uninhabited
);
}
}
layout
::
Variants
::
Tagged
{
..
}
=>
{
let
ptr
=
self
.project_field
(
bcx
,
0
);
...
...
@@ -366,7 +377,7 @@ pub fn trans_set_discr(&self, bcx: &Builder<'a, 'tcx>, variant_index: usize) {
pub
fn
project_index
(
&
self
,
bcx
:
&
Builder
<
'a
,
'tcx
>
,
llindex
:
ValueRef
)
->
LvalueRef
<
'tcx
>
{
LvalueRef
{
llval
:
bcx
.inbounds_gep
(
self
.llval
,
&
[
common
::
C_usize
(
bcx
.ccx
,
0
),
llindex
]),
llval
:
bcx
.inbounds_gep
(
self
.llval
,
&
[
C_usize
(
bcx
.ccx
,
0
),
llindex
]),
llextra
:
ptr
::
null_mut
(),
layout
:
self
.layout
.field
(
bcx
.ccx
,
0
),
alignment
:
self
.alignment
...
...
@@ -376,7 +387,7 @@ pub fn project_index(&self, bcx: &Builder<'a, 'tcx>, llindex: ValueRef)
pub
fn
project_downcast
(
&
self
,
bcx
:
&
Builder
<
'a
,
'tcx
>
,
variant_index
:
usize
)
->
LvalueRef
<
'tcx
>
{
let
mut
downcast
=
*
self
;
downcast
.layout
=
self
.layout
.for_variant
(
variant_index
);
downcast
.layout
=
self
.layout
.for_variant
(
bcx
.ccx
,
variant_index
);
// Cast to the appropriate variant struct type.
let
variant_ty
=
downcast
.layout
.llvm_type
(
bcx
.ccx
);
...
...
src/librustc_trans/type_of.rs
浏览文件 @
ced5e04e
...
...
@@ -27,6 +27,7 @@ fn uncached_llvm_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
return
Type
::
vector
(
&
layout
.field
(
ccx
,
0
)
.llvm_type
(
ccx
),
layout
.fields
.count
()
as
u64
);
}
layout
::
Abi
::
Uninhabited
|
layout
::
Abi
::
Aggregate
{
..
}
=>
{}
}
...
...
@@ -158,7 +159,9 @@ pub trait LayoutLlvmExt<'tcx> {
impl
<
'tcx
>
LayoutLlvmExt
<
'tcx
>
for
TyLayout
<
'tcx
>
{
fn
is_llvm_immediate
(
&
self
)
->
bool
{
match
self
.abi
{
layout
::
Abi
::
Scalar
(
_
)
|
layout
::
Abi
::
Vector
=>
true
,
layout
::
Abi
::
Uninhabited
|
layout
::
Abi
::
Scalar
(
_
)
|
layout
::
Abi
::
Vector
=>
true
,
layout
::
Abi
::
Aggregate
{
..
}
=>
self
.is_zst
()
}
...
...
@@ -230,7 +233,7 @@ fn llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Type {
let
llty
=
if
self
.ty
!=
normal_ty
{
let
mut
layout
=
ccx
.layout_of
(
normal_ty
);
if
let
Some
(
v
)
=
variant_index
{
layout
=
layout
.for_variant
(
v
);
layout
=
layout
.for_variant
(
ccx
,
v
);
}
layout
.llvm_type
(
ccx
)
}
else
{
...
...
src/test/ui/print_type_sizes/uninhabited.rs
0 → 100644
浏览文件 @
ced5e04e
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-flags: -Z print-type-sizes
#![feature(never_type)]
pub
fn
main
()
{
let
_
x
:
Option
<!>
=
None
;
let
_
y
:
Result
<
u32
,
!>
=
Ok
(
42
);
}
src/test/ui/print_type_sizes/uninhabited.stdout
0 → 100644
浏览文件 @
ced5e04e
print-type-size type: `std::result::Result<u32, !>`: 4 bytes, alignment: 4 bytes
print-type-size variant `Ok`: 4 bytes
print-type-size field `.0`: 4 bytes
print-type-size type: `std::option::Option<!>`: 0 bytes, alignment: 1 bytes
print-type-size variant `None`: 0 bytes
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录