Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
8667f930
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,发现更多精彩内容 >>
提交
8667f930
编写于
9月 10, 2020
作者:
B
Bastian Kauschke
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
implement `const_evaluatable_checked` feature MVP
上级
a1894e4a
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
122 addition
and
17 deletion
+122
-17
compiler/rustc_feature/src/active.rs
compiler/rustc_feature/src/active.rs
+5
-1
compiler/rustc_span/src/symbol.rs
compiler/rustc_span/src/symbol.rs
+1
-0
compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
...ler/rustc_trait_selection/src/traits/const_evaluatable.rs
+36
-15
compiler/rustc_typeck/src/collect.rs
compiler/rustc_typeck/src/collect.rs
+45
-1
src/test/ui/const-generics/const_evaluatable_checked/simple.rs
...est/ui/const-generics/const_evaluatable_checked/simple.rs
+14
-0
src/test/ui/const-generics/const_evaluatable_checked/simple_fail.rs
...i/const-generics/const_evaluatable_checked/simple_fail.rs
+12
-0
src/test/ui/const-generics/const_evaluatable_checked/simple_fail.stderr
...nst-generics/const_evaluatable_checked/simple_fail.stderr
+9
-0
未找到文件。
compiler/rustc_feature/src/active.rs
浏览文件 @
8667f930
...
...
@@ -585,6 +585,9 @@ pub fn set(&self, features: &mut Features, span: Span) {
/// Allows `if let` guard in match arms.
(
active
,
if_let_guard
,
"1.47.0"
,
Some
(
51114
),
None
),
/// Allows non trivial generic constants which have to be manually propageted upwards.
(
active
,
const_evaluatable_checked
,
"1.48.0"
,
Some
(
0
),
None
),
// -------------------------------------------------------------------------
// feature-group-end: actual feature gates
// -------------------------------------------------------------------------
...
...
@@ -600,6 +603,7 @@ pub fn set(&self, features: &mut Features, span: Span) {
sym
::
const_generics
,
sym
::
let_chains
,
sym
::
raw_dylib
,
sym
::
const_evaluatable_checked
,
sym
::
const_trait_impl
,
sym
::
const_trait_bound_opt_out
,
sym
::
lazy_normalization_consts
,
...
...
@@ -607,6 +611,6 @@ pub fn set(&self, features: &mut Features, span: Span) {
];
/// Some features are not allowed to be used together at the same time, if
/// the two are present, produce an error
/// the two are present, produce an error
.
pub
const
INCOMPATIBLE_FEATURES
:
&
[(
Symbol
,
Symbol
)]
=
&
[(
sym
::
const_generics
,
sym
::
min_const_generics
)];
compiler/rustc_span/src/symbol.rs
浏览文件 @
8667f930
...
...
@@ -348,6 +348,7 @@
const_compare_raw_pointers
,
const_constructor
,
const_eval_limit
,
const_evaluatable_checked
,
const_extern_fn
,
const_fn
,
const_fn_transmute
,
...
...
compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
浏览文件 @
8667f930
...
...
@@ -14,6 +14,24 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
param_env
:
ty
::
ParamEnv
<
'tcx
>
,
span
:
Span
,
)
->
Result
<
(),
ErrorHandled
>
{
debug!
(
"is_const_evaluatable({:?}, {:?})"
,
def
,
substs
);
if
infcx
.tcx
.features
()
.const_evaluatable_checked
{
// FIXME(const_evaluatable_checked): Actually look into generic constants to
// implement const equality.
for
pred
in
param_env
.caller_bounds
()
{
match
pred
.skip_binders
()
{
ty
::
PredicateAtom
::
ConstEvaluatable
(
b_def
,
b_substs
)
=>
{
debug!
(
"is_const_evaluatable: caller_bound={:?}, {:?}"
,
b_def
,
b_substs
);
if
b_def
==
def
&&
b_substs
==
substs
{
debug!
(
"is_const_evaluatable: caller_bound ~~> ok"
);
return
Ok
(());
}
}
_
=>
{}
// don't care
}
}
}
let
future_compat_lint
=
||
{
if
let
Some
(
local_def_id
)
=
def
.did
.as_local
()
{
infcx
.tcx
.struct_span_lint_hir
(
...
...
@@ -38,24 +56,27 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
// See #74595 for more details about this.
let
concrete
=
infcx
.const_eval_resolve
(
param_env
,
def
,
substs
,
None
,
Some
(
span
));
let
def_kind
=
infcx
.tcx
.def_kind
(
def
.did
);
match
def_kind
{
DefKind
::
AnonConst
=>
{
let
mir_body
=
if
let
Some
(
def
)
=
def
.as_const_arg
()
{
infcx
.tcx
.optimized_mir_of_const_arg
(
def
)
}
else
{
infcx
.tcx
.optimized_mir
(
def
.did
)
};
if
mir_body
.is_polymorphic
&&
concrete
.is_ok
()
{
future_compat_lint
();
}
}
_
=>
{
if
substs
.has_param_types_or_consts
()
&&
concrete
.is_ok
()
{
future_compat_lint
();
if
concrete
.is_ok
()
&&
substs
.has_param_types_or_consts
()
{
match
infcx
.tcx
.def_kind
(
def
.did
)
{
DefKind
::
AnonConst
=>
{
let
mir_body
=
if
let
Some
(
def
)
=
def
.as_const_arg
()
{
infcx
.tcx
.optimized_mir_of_const_arg
(
def
)
}
else
{
infcx
.tcx
.optimized_mir
(
def
.did
)
};
if
mir_body
.is_polymorphic
{
future_compat_lint
();
}
}
_
=>
future_compat_lint
(),
}
}
if
concrete
.is_ok
()
{
debug!
(
"is_const_evaluatable: concrete ~~> ok"
);
}
else
{
debug!
(
"is_const_evaluatable: concrete ~~> err"
);
}
concrete
.map
(
drop
)
}
compiler/rustc_typeck/src/collect.rs
浏览文件 @
8667f930
...
...
@@ -37,11 +37,12 @@
use
rustc_middle
::
middle
::
codegen_fn_attrs
::{
CodegenFnAttrFlags
,
CodegenFnAttrs
};
use
rustc_middle
::
mir
::
mono
::
Linkage
;
use
rustc_middle
::
ty
::
query
::
Providers
;
use
rustc_middle
::
ty
::
subst
::
InternalSubsts
;
use
rustc_middle
::
ty
::
subst
::
{
InternalSubsts
,
SubstsRef
}
;
use
rustc_middle
::
ty
::
util
::
Discr
;
use
rustc_middle
::
ty
::
util
::
IntTypeExt
;
use
rustc_middle
::
ty
::{
self
,
AdtKind
,
Const
,
ToPolyTraitRef
,
Ty
,
TyCtxt
};
use
rustc_middle
::
ty
::{
ReprOptions
,
ToPredicate
,
WithConstness
};
use
rustc_middle
::
ty
::{
TypeFoldable
,
TypeVisitor
};
use
rustc_session
::
config
::
SanitizerSet
;
use
rustc_session
::
lint
;
use
rustc_session
::
parse
::
feature_err
;
...
...
@@ -50,6 +51,8 @@
use
rustc_target
::
spec
::
abi
;
use
rustc_trait_selection
::
traits
::
error_reporting
::
suggestions
::
NextTypeParamName
;
use
smallvec
::
SmallVec
;
mod
type_of
;
struct
OnlySelfBounds
(
bool
);
...
...
@@ -1672,10 +1675,51 @@ fn predicates_defined_on(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicate
.alloc_from_iter
(
result
.predicates
.iter
()
.chain
(
inferred_outlives
)
.copied
());
}
}
if
tcx
.features
()
.const_evaluatable_checked
{
let
const_evaluatable
=
const_evaluatable_predicates_of
(
tcx
,
def_id
,
&
result
);
if
result
.predicates
.is_empty
()
{
result
.predicates
=
tcx
.arena
.alloc_from_iter
(
const_evaluatable
);
}
else
{
result
.predicates
=
tcx
.arena
.alloc_from_iter
(
result
.predicates
.iter
()
.copied
()
.chain
(
const_evaluatable
));
}
}
debug!
(
"predicates_defined_on({:?}) = {:?}"
,
def_id
,
result
);
result
}
pub
fn
const_evaluatable_predicates_of
<
'tcx
>
(
tcx
:
TyCtxt
<
'tcx
>
,
def_id
:
DefId
,
predicates
:
&
ty
::
GenericPredicates
<
'tcx
>
,
)
->
impl
Iterator
<
Item
=
(
ty
::
Predicate
<
'tcx
>
,
Span
)
>
{
#[derive(Default)]
struct
ConstCollector
<
'tcx
>
{
ct
:
SmallVec
<
[(
ty
::
WithOptConstParam
<
DefId
>
,
SubstsRef
<
'tcx
>
);
4
]
>
,
}
impl
<
'tcx
>
TypeVisitor
<
'tcx
>
for
ConstCollector
<
'tcx
>
{
fn
visit_const
(
&
mut
self
,
ct
:
&
'tcx
Const
<
'tcx
>
)
->
bool
{
if
let
ty
::
ConstKind
::
Unevaluated
(
def
,
substs
,
None
)
=
ct
.val
{
self
.ct
.push
((
def
,
substs
));
}
false
}
}
let
mut
collector
=
ConstCollector
::
default
();
for
(
pred
,
_
span
)
in
predicates
.predicates
.iter
()
{
pred
.visit_with
(
&
mut
collector
);
}
warn!
(
"const_evaluatable_predicates_of({:?}) = {:?}"
,
def_id
,
collector
.ct
);
collector
.ct
.into_iter
()
.map
(
move
|(
def_id
,
subst
)|
{
(
ty
::
PredicateAtom
::
ConstEvaluatable
(
def_id
,
subst
)
.to_predicate
(
tcx
),
DUMMY_SP
)
})
}
/// Returns a list of all type predicates (explicit and implicit) for the definition with
/// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus
/// `Self: Trait` predicates for traits.
...
...
src/test/ui/const-generics/const_evaluatable_checked/simple.rs
0 → 100644
浏览文件 @
8667f930
// run-pass
#![feature(const_generics,
const_evaluatable_checked)]
#![allow(incomplete_features)]
type
Arr
<
const
N
:
usize
>
=
[
u8
;
N
-
1
];
fn
test
<
const
N
:
usize
>
()
->
Arr
<
N
>
where
Arr
<
N
>
:
Default
{
Default
::
default
()
}
fn
main
()
{
let
x
=
test
::
<
33
>
();
assert_eq!
(
x
,
[
0
;
32
]);
}
src/test/ui/const-generics/const_evaluatable_checked/simple_fail.rs
0 → 100644
浏览文件 @
8667f930
#![feature(const_generics,
const_evaluatable_checked)]
#![allow(incomplete_features)]
type
Arr
<
const
N
:
usize
>
=
[
u8
;
N
-
1
];
//~ ERROR evaluation of constant
fn
test
<
const
N
:
usize
>
()
->
Arr
<
N
>
where
Arr
<
N
>
:
Sized
{
todo!
()
}
fn
main
()
{
test
::
<
0
>
();
}
src/test/ui/const-generics/const_evaluatable_checked/simple_fail.stderr
0 → 100644
浏览文件 @
8667f930
error[E0080]: evaluation of constant value failed
--> $DIR/simple_fail.rs:4:33
|
LL | type Arr<const N: usize> = [u8; N - 1];
| ^^^^^ attempt to compute `0_usize - 1_usize` which would overflow
error: aborting due to previous error
For more information about this error, try `rustc --explain E0080`.
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录