Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
195c9f47
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,发现更多精彩内容 >>
未验证
提交
195c9f47
编写于
4月 19, 2018
作者:
O
Oliver Schneider
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Allow variant discriminant initializers to refer to other initializers of the same enum
上级
883bf4ba
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
158 addition
and
37 deletion
+158
-37
src/librustc/ty/mod.rs
src/librustc/ty/mod.rs
+23
-17
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/cx/expr.rs
+75
-3
src/test/ui/const-eval/enum_discr.rs
src/test/ui/const-eval/enum_discr.rs
+36
-0
src/test/ui/issue-23302-1.stderr
src/test/ui/issue-23302-1.stderr
+8
-4
src/test/ui/issue-23302-2.stderr
src/test/ui/issue-23302-2.stderr
+8
-4
src/test/ui/issue-36163.stderr
src/test/ui/issue-36163.stderr
+8
-9
未找到文件。
src/librustc/ty/mod.rs
浏览文件 @
195c9f47
...
...
@@ -1972,32 +1972,38 @@ pub fn discriminant_for_variant(&self,
tcx
:
TyCtxt
<
'a
,
'gcx
,
'tcx
>
,
variant_index
:
usize
)
->
Discr
<
'tcx
>
{
let
repr_type
=
self
.repr
.discr_type
();
let
mut
explicit_value
=
repr_type
.initial_discriminant
(
tcx
.global_tcx
());
let
(
val
,
offset
)
=
self
.discriminant_def_for_variant
(
variant_index
);
let
explicit_value
=
val
.and_then
(|
expr_did
|
self
.eval_explicit_discr
(
tcx
,
expr_did
))
.unwrap_or_else
(||
self
.repr
.discr_type
()
.initial_discriminant
(
tcx
.global_tcx
()));
explicit_value
.checked_add
(
tcx
,
offset
as
u128
)
.0
}
/// Yields a DefId for the discriminant and an offset to add to it
/// Alternatively, if there is no explicit discriminant, returns the
/// inferred discriminant directly
pub
fn
discriminant_def_for_variant
(
&
self
,
variant_index
:
usize
,
)
->
(
Option
<
DefId
>
,
usize
)
{
let
mut
explicit_index
=
variant_index
;
let
expr_did
;
loop
{
match
self
.variants
[
explicit_index
]
.discr
{
ty
::
VariantDiscr
::
Relative
(
0
)
=>
break
,
ty
::
VariantDiscr
::
Relative
(
0
)
=>
{
expr_did
=
None
;
break
;
},
ty
::
VariantDiscr
::
Relative
(
distance
)
=>
{
explicit_index
-=
distance
;
}
ty
::
VariantDiscr
::
Explicit
(
expr_did
)
=>
{
match
self
.eval_explicit_discr
(
tcx
,
expr_did
)
{
Some
(
discr
)
=>
{
explicit_value
=
discr
;
break
;
},
None
=>
{
if
explicit_index
==
0
{
break
;
}
explicit_index
-=
1
;
}
}
ty
::
VariantDiscr
::
Explicit
(
did
)
=>
{
expr_did
=
Some
(
did
);
break
;
}
}
}
explicit_value
.checked_add
(
tcx
,
(
variant_index
-
explicit_index
)
as
u128
)
.0
(
expr_did
,
variant_index
-
explicit_index
)
}
pub
fn
destructor
(
&
self
,
tcx
:
TyCtxt
<
'a
,
'gcx
,
'tcx
>
)
->
Option
<
Destructor
>
{
...
...
src/librustc_mir/hair/cx/expr.rs
浏览文件 @
195c9f47
...
...
@@ -589,12 +589,84 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
// Check to see if this cast is a "coercion cast", where the cast is actually done
// using a coercion (or is a no-op).
if
let
Some
(
&
TyCastKind
::
CoercionCast
)
=
cx
.tables
()
.cast_kinds
()
.get
(
source
.hir_id
)
{
.cast_kinds
()
.get
(
source
.hir_id
)
{
// Convert the lexpr to a vexpr.
ExprKind
::
Use
{
source
:
source
.to_ref
()
}
}
else
{
ExprKind
::
Cast
{
source
:
source
.to_ref
()
}
// check whether this is casting an enum variant discriminant
// to prevent cycles, we refer to the discriminant initializer
// which is always an integer and thus doesn't need to know the
// enum's layout (or its tag type) to compute it during const eval
// Example:
// enum Foo {
// A,
// B = A as isize + 4,
// }
// The correct solution would be to add symbolic computations to miri,
// so we wouldn't have to compute and store the actual value
let
var
=
if
let
hir
::
ExprPath
(
ref
qpath
)
=
source
.node
{
let
def
=
cx
.tables
()
.qpath_def
(
qpath
,
source
.hir_id
);
cx
.tables
()
.node_id_to_type
(
source
.hir_id
)
.ty_adt_def
()
.and_then
(|
adt_def
|
{
match
def
{
Def
::
VariantCtor
(
variant_id
,
CtorKind
::
Const
)
=>
{
let
idx
=
adt_def
.variant_index_with_id
(
variant_id
);
let
(
d
,
o
)
=
adt_def
.discriminant_def_for_variant
(
idx
);
use
rustc
::
ty
::
util
::
IntTypeExt
;
let
ty
=
adt_def
.repr
.discr_type
()
.to_ty
(
cx
.tcx
());
Some
((
d
,
o
,
ty
))
}
_
=>
None
,
}
})
}
else
{
None
};
let
source
=
if
let
Some
((
did
,
offset
,
ty
))
=
var
{
let
mk_const
=
|
val
|
Expr
{
temp_lifetime
,
ty
,
span
:
expr
.span
,
kind
:
ExprKind
::
Literal
{
literal
:
Literal
::
Value
{
value
:
cx
.tcx
()
.mk_const
(
ty
::
Const
{
val
,
ty
,
}),
},
},
}
.to_ref
();
let
offset
=
mk_const
(
ConstVal
::
Value
(
Value
::
ByVal
(
PrimVal
::
Bytes
(
offset
as
u128
))),
);
match
did
{
Some
(
did
)
=>
{
// in case we are offsetting from a computed discriminant
// and not the beginning of discriminants (which is always `0`)
let
substs
=
Substs
::
identity_for_item
(
cx
.tcx
(),
did
);
let
lhs
=
mk_const
(
ConstVal
::
Unevaluated
(
did
,
substs
));
let
bin
=
ExprKind
::
Binary
{
op
:
BinOp
::
Add
,
lhs
,
rhs
:
offset
,
};
Expr
{
temp_lifetime
,
ty
,
span
:
expr
.span
,
kind
:
bin
,
}
.to_ref
()
},
None
=>
offset
,
}
}
else
{
source
.to_ref
()
};
ExprKind
::
Cast
{
source
}
}
}
hir
::
ExprType
(
ref
source
,
_
)
=>
return
source
.make_mirror
(
cx
),
...
...
src/test/ui/const-eval/enum_discr.rs
0 → 100644
浏览文件 @
195c9f47
// Copyright 2018 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-pass
// run-pass
enum
Foo
{
X
=
42
,
Y
=
Foo
::
X
as
isize
-
3
,
}
enum
Bar
{
X
,
Y
=
Bar
::
X
as
isize
+
2
,
}
enum
Boo
{
X
=
Boo
::
Y
as
isize
*
2
,
Y
=
9
,
}
fn
main
()
{
assert_eq!
(
Foo
::
X
as
isize
,
42
);
assert_eq!
(
Foo
::
Y
as
isize
,
39
);
assert_eq!
(
Bar
::
X
as
isize
,
0
);
assert_eq!
(
Bar
::
Y
as
isize
,
2
);
assert_eq!
(
Boo
::
X
as
isize
,
18
);
assert_eq!
(
Boo
::
Y
as
isize
,
9
);
}
src/test/ui/issue-23302-1.stderr
浏览文件 @
195c9f47
error[E0391]: cycle detected when
const-evaluat
ing `X::A::{{initializer}}`
error[E0391]: cycle detected when
process
ing `X::A::{{initializer}}`
--> $DIR/issue-23302-1.rs:14:9
|
LL | A = X::A as isize, //~ ERROR E0391
| ^^^^
| ^^^^
^^^^^^^^^
|
note: ...which requires computing layout of `X`...
= note: ...which again requires const-evaluating `X::A::{{initializer}}`, completing the cycle
= note: ...which again requires processing `X::A::{{initializer}}`, completing the cycle
note: cycle used when const-evaluating `X::A::{{initializer}}`
--> $DIR/issue-23302-1.rs:14:9
|
LL | A = X::A as isize, //~ ERROR E0391
| ^^^^^^^^^^^^^
error: aborting due to previous error
...
...
src/test/ui/issue-23302-2.stderr
浏览文件 @
195c9f47
error[E0391]: cycle detected when
const-evaluat
ing `Y::A::{{initializer}}`
error[E0391]: cycle detected when
process
ing `Y::A::{{initializer}}`
--> $DIR/issue-23302-2.rs:14:9
|
LL | A = Y::B as isize, //~ ERROR E0391
| ^^^^
| ^^^^
^^^^^^^^^
|
note: ...which requires computing layout of `Y`...
= note: ...which again requires const-evaluating `Y::A::{{initializer}}`, completing the cycle
= note: ...which again requires processing `Y::A::{{initializer}}`, completing the cycle
note: cycle used when const-evaluating `Y::A::{{initializer}}`
--> $DIR/issue-23302-2.rs:14:9
|
LL | A = Y::B as isize, //~ ERROR E0391
| ^^^^^^^^^^^^^
error: aborting due to previous error
...
...
src/test/ui/issue-36163.stderr
浏览文件 @
195c9f47
error[E0391]: cycle detected when
const-evaluat
ing `Foo::B::{{initializer}}`
error[E0391]: cycle detected when
process
ing `Foo::B::{{initializer}}`
--> $DIR/issue-36163.rs:14:9
|
LL | B = A, //~ ERROR E0391
| ^
|
note: ...which requires processing `Foo::B::{{initializer}}`...
note: ...which requires processing `A`...
--> $DIR/issue-36163.rs:11:18
|
LL | const A: isize = Foo::B as isize;
| ^^^^^^^^^^^^^^^
= note: ...which again requires processing `Foo::B::{{initializer}}`, completing the cycle
note: cycle used when const-evaluating `Foo::B::{{initializer}}`
--> $DIR/issue-36163.rs:14:9
|
LL | B = A, //~ ERROR E0391
| ^
note: ...which requires const-evaluating `A`...
--> $DIR/issue-36163.rs:11:18
|
LL | const A: isize = Foo::B as isize;
| ^^^^^^
note: ...which requires computing layout of `Foo`...
= note: ...which again requires const-evaluating `Foo::B::{{initializer}}`, completing the cycle
error: aborting due to previous error
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录