Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
98721608
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,发现更多精彩内容 >>
未验证
提交
98721608
编写于
3月 27, 2018
作者:
O
Oliver Schneider
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Allow let bindings in const fn and constants
上级
68357487
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
193 addition
and
18 deletion
+193
-18
src/librustc_mir/transform/qualify_consts.rs
src/librustc_mir/transform/qualify_consts.rs
+43
-18
src/libsyntax/feature_gate.rs
src/libsyntax/feature_gate.rs
+3
-0
src/test/run-pass/ctfe/const-block-non-item-statement-3.rs
src/test/run-pass/ctfe/const-block-non-item-statement-3.rs
+15
-0
src/test/run-pass/ctfe/const-block-non-item-statement.rs
src/test/run-pass/ctfe/const-block-non-item-statement.rs
+17
-0
src/test/run-pass/ctfe/const-fn-destructuring-arg.rs
src/test/run-pass/ctfe/const-fn-destructuring-arg.rs
+23
-0
src/test/run-pass/ctfe/issue-37550.rs
src/test/run-pass/ctfe/issue-37550.rs
+18
-0
src/test/run-pass/ctfe/locals-in-const-fn.rs
src/test/run-pass/ctfe/locals-in-const-fn.rs
+45
-0
src/test/ui/feature-gate-const_let.rs
src/test/ui/feature-gate-const_let.rs
+20
-0
src/test/ui/feature-gate-const_let.stderr
src/test/ui/feature-gate-const_let.stderr
+9
-0
未找到文件。
src/librustc_mir/transform/qualify_consts.rs
浏览文件 @
98721608
...
...
@@ -32,7 +32,7 @@
use
rustc_target
::
spec
::
abi
::
Abi
;
use
syntax
::
attr
;
use
syntax
::
ast
::
LitKind
;
use
syntax
::
feature_gate
::
UnstableFeatures
;
use
syntax
::
feature_gate
::
{
UnstableFeatures
,
emit_feature_err
,
GateIssue
}
;
use
syntax_pos
::{
Span
,
DUMMY_SP
};
use
std
::
fmt
;
...
...
@@ -120,8 +120,7 @@ struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
rpo
:
ReversePostorder
<
'a
,
'tcx
>
,
tcx
:
TyCtxt
<
'a
,
'gcx
,
'tcx
>
,
param_env
:
ty
::
ParamEnv
<
'tcx
>
,
temp_qualif
:
IndexVec
<
Local
,
Option
<
Qualif
>>
,
return_qualif
:
Option
<
Qualif
>
,
local_qualif
:
IndexVec
<
Local
,
Option
<
Qualif
>>
,
qualif
:
Qualif
,
const_fn_arg_vars
:
BitVector
,
temp_promotion_state
:
IndexVec
<
Local
,
TempState
>
,
...
...
@@ -140,11 +139,11 @@ fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let
param_env
=
tcx
.param_env
(
def_id
);
let
mut
temp
_qualif
=
IndexVec
::
from_elem
(
None
,
&
mir
.local_decls
);
let
mut
local
_qualif
=
IndexVec
::
from_elem
(
None
,
&
mir
.local_decls
);
for
arg
in
mir
.args_iter
()
{
let
mut
qualif
=
Qualif
::
NEEDS_DROP
;
qualif
.restrict
(
mir
.local_decls
[
arg
]
.ty
,
tcx
,
param_env
);
temp
_qualif
[
arg
]
=
Some
(
qualif
);
local
_qualif
[
arg
]
=
Some
(
qualif
);
}
Qualifier
{
...
...
@@ -155,8 +154,7 @@ fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
rpo
,
tcx
,
param_env
,
temp_qualif
,
return_qualif
:
None
,
local_qualif
,
qualif
:
Qualif
::
empty
(),
const_fn_arg_vars
:
BitVector
::
new
(
mir
.local_decls
.len
()),
temp_promotion_state
:
temps
,
...
...
@@ -191,6 +189,11 @@ fn not_const(&mut self) {
fn
statement_like
(
&
mut
self
)
{
self
.add
(
Qualif
::
NOT_CONST
);
if
self
.mode
!=
Mode
::
Fn
{
if
self
.span
.allows_unstable
()
{
emit_feature_err
(
&
self
.tcx.sess.parse_sess
,
"const_let"
,
self
.span
,
GateIssue
::
Language
,
"statements in const fn are unstable"
);
}
let
mut
err
=
struct_span_err!
(
self
.tcx.sess
,
self
.span
,
...
...
@@ -266,6 +269,7 @@ fn try_consume(&mut self) -> bool {
/// Assign the current qualification to the given destination.
fn
assign
(
&
mut
self
,
dest
:
&
Place
<
'tcx
>
,
location
:
Location
)
{
trace!
(
"assign: {:?}"
,
dest
);
let
qualif
=
self
.qualif
;
let
span
=
self
.span
;
let
store
=
|
slot
:
&
mut
Option
<
Qualif
>
|
{
...
...
@@ -281,20 +285,26 @@ fn assign(&mut self, dest: &Place<'tcx>, location: Location) {
if
self
.mir
.local_kind
(
index
)
==
LocalKind
::
Temp
&&
self
.temp_promotion_state
[
index
]
.is_promotable
()
{
debug!
(
"store to promotable temp {:?}"
,
index
);
store
(
&
mut
self
.
temp
_qualif
[
index
]);
store
(
&
mut
self
.
local
_qualif
[
index
]);
}
}
return
;
}
match
*
dest
{
Place
::
Local
(
index
)
if
(
self
.mir
.local_kind
(
index
)
==
LocalKind
::
Var
||
self
.mir
.local_kind
(
index
)
==
LocalKind
::
Arg
)
&&
self
.tcx.sess
.features_untracked
()
.const_let
=>
{
debug!
(
"store to var {:?}"
,
index
);
self
.local_qualif
[
index
]
=
Some
(
self
.qualif
);
}
Place
::
Local
(
index
)
if
self
.mir
.local_kind
(
index
)
==
LocalKind
::
Temp
=>
{
debug!
(
"store to temp {:?}"
,
index
);
store
(
&
mut
self
.
temp
_qualif
[
index
])
store
(
&
mut
self
.
local
_qualif
[
index
])
}
Place
::
Local
(
index
)
if
self
.mir
.local_kind
(
index
)
==
LocalKind
::
ReturnPointer
=>
{
debug!
(
"store to return place {:?}"
,
index
);
store
(
&
mut
self
.
return_qualif
)
store
(
&
mut
self
.
local_qualif
[
RETURN_PLACE
]
)
}
Place
::
Projection
(
box
Projection
{
...
...
@@ -302,7 +312,7 @@ fn assign(&mut self, dest: &Place<'tcx>, location: Location) {
elem
:
ProjectionElem
::
Deref
})
if
self
.mir
.local_kind
(
index
)
==
LocalKind
::
Temp
&&
self
.mir.local_decls
[
index
]
.ty
.is_box
()
&&
self
.
temp
_qualif
[
index
]
.map_or
(
false
,
|
qualif
|
{
&&
self
.
local
_qualif
[
index
]
.map_or
(
false
,
|
qualif
|
{
qualif
.intersects
(
Qualif
::
NOT_CONST
)
})
=>
{
// Part of `box expr`, we should've errored
...
...
@@ -355,10 +365,13 @@ fn qualify_const(&mut self) -> (Qualif, Lrc<IdxSetBuf<Local>>) {
TerminatorKind
::
FalseUnwind
{
..
}
=>
None
,
TerminatorKind
::
Return
=>
{
if
self
.tcx.sess
.features_untracked
()
.const_let
{
break
;
}
// Check for unused values. This usually means
// there are extra statements in the AST.
for
temp
in
mir
.temps_iter
()
{
if
self
.
temp
_qualif
[
temp
]
.is_none
()
{
if
self
.
local
_qualif
[
temp
]
.is_none
()
{
continue
;
}
...
...
@@ -408,7 +421,7 @@ fn qualify_const(&mut self) -> (Qualif, Lrc<IdxSetBuf<Local>>) {
}
}
self
.qualif
=
self
.
return_qualif
.unwrap_or
(
Qualif
::
NOT_CONST
);
self
.qualif
=
self
.
local_qualif
[
RETURN_PLACE
]
.unwrap_or
(
Qualif
::
NOT_CONST
);
// Account for errors in consts by using the
// conservative type qualification instead.
...
...
@@ -453,9 +466,15 @@ fn visit_local(&mut self,
LocalKind
::
ReturnPointer
=>
{
self
.not_const
();
}
LocalKind
::
Var
=>
{
LocalKind
::
Var
if
!
self
.tcx.sess
.features_untracked
()
.const_let
=>
{
if
self
.mode
!=
Mode
::
Fn
&&
self
.span
.allows_unstable
()
{
emit_feature_err
(
&
self
.tcx.sess.parse_sess
,
"const_let"
,
self
.span
,
GateIssue
::
Language
,
"let bindings in const fn are unstable"
);
}
self
.add
(
Qualif
::
NOT_CONST
);
}
LocalKind
::
Var
|
LocalKind
::
Arg
|
LocalKind
::
Temp
=>
{
if
let
LocalKind
::
Arg
=
kind
{
...
...
@@ -466,7 +485,7 @@ fn visit_local(&mut self,
self
.add
(
Qualif
::
NOT_PROMOTABLE
);
}
if
let
Some
(
qualif
)
=
self
.
temp
_qualif
[
local
]
{
if
let
Some
(
qualif
)
=
self
.
local
_qualif
[
local
]
{
self
.add
(
qualif
);
}
else
{
self
.not_const
();
...
...
@@ -588,7 +607,7 @@ fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
// Mark the consumed locals to indicate later drops are noops.
if
let
Operand
::
Move
(
Place
::
Local
(
local
))
=
*
operand
{
self
.
temp_qualif
[
local
]
=
self
.temp
_qualif
[
local
]
.map
(|
q
|
self
.
local_qualif
[
local
]
=
self
.local
_qualif
[
local
]
.map
(|
q
|
q
-
Qualif
::
NEEDS_DROP
);
}
...
...
@@ -1033,7 +1052,7 @@ fn visit_terminator_kind(&mut self,
// HACK(eddyb) Emulate a bit of dataflow analysis,
// conservatively, that drop elaboration will do.
let
needs_drop
=
if
let
Place
::
Local
(
local
)
=
*
place
{
if
self
.
temp
_qualif
[
local
]
.map_or
(
true
,
|
q
|
q
.intersects
(
Qualif
::
NEEDS_DROP
))
{
if
self
.
local
_qualif
[
local
]
.map_or
(
true
,
|
q
|
q
.intersects
(
Qualif
::
NEEDS_DROP
))
{
Some
(
self
.mir.local_decls
[
local
]
.source_info.span
)
}
else
{
None
...
...
@@ -1070,7 +1089,8 @@ fn visit_assign(&mut self,
// Check the allowed const fn argument forms.
if
let
(
Mode
::
ConstFn
,
&
Place
::
Local
(
index
))
=
(
self
.mode
,
dest
)
{
if
self
.mir
.local_kind
(
index
)
==
LocalKind
::
Var
&&
self
.const_fn_arg_vars
.insert
(
index
.index
())
{
self
.const_fn_arg_vars
.insert
(
index
.index
())
&&
!
self
.tcx.sess
.features_untracked
()
.const_let
{
// Direct use of an argument is permitted.
match
*
rvalue
{
...
...
@@ -1086,6 +1106,11 @@ fn visit_assign(&mut self,
// Avoid a generic error for other uses of arguments.
if
self
.qualif
.intersects
(
Qualif
::
FN_ARGUMENT
)
{
let
decl
=
&
self
.mir.local_decls
[
index
];
if
decl
.source_info.span
.allows_unstable
()
{
emit_feature_err
(
&
self
.tcx.sess.parse_sess
,
"const_let"
,
decl
.source_info.span
,
GateIssue
::
Language
,
"locals and patterns in const fn are unstable"
);
}
let
mut
err
=
struct_span_err!
(
self
.tcx.sess
,
decl
.source_info.span
,
...
...
src/libsyntax/feature_gate.rs
浏览文件 @
98721608
...
...
@@ -214,6 +214,9 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
// Allows the definition of `const fn` functions.
(
active
,
const_fn
,
"1.2.0"
,
Some
(
24111
),
None
),
// Allows let bindings and destructuring in `const fn` functions and constants.
(
active
,
const_let
,
"1.22.1"
,
Some
(
48821
),
None
),
// Allows using #[prelude_import] on glob `use` items.
//
// rustc internal
...
...
src/test/run-pass/ctfe/const-block-non-item-statement-3.rs
0 → 100644
浏览文件 @
98721608
// Copyright 2014 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.
#![feature(const_let)]
type
Array
=
[
u32
;
{
let
x
=
2
;
5
}];
pub
fn
main
()
{}
src/test/run-pass/ctfe/const-block-non-item-statement.rs
0 → 100644
浏览文件 @
98721608
// Copyright 2014 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.
#![feature(const_let)]
enum
Foo
{
Bar
=
{
let
x
=
1
;
3
}
}
pub
fn
main
()
{}
src/test/run-pass/ctfe/const-fn-destructuring-arg.rs
0 → 100644
浏览文件 @
98721608
// Copyright 2015 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.
// test that certain things are disallowed in const fn signatures
#![feature(const_fn,
const_let)]
// no destructuring
const
fn
i
((
a
,
b
):
(
u32
,
u32
))
->
u32
{
a
+
b
}
fn
main
()
{}
src/test/run-pass/ctfe/issue-37550.rs
0 → 100644
浏览文件 @
98721608
// Copyright 2017 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.
#![feature(const_fn,
const_let)]
const
fn
x
()
{
let
t
=
true
;
let
x
=
||
t
;
}
fn
main
()
{}
src/test/run-pass/ctfe/locals-in-const-fn.rs
0 → 100644
浏览文件 @
98721608
// 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.
// https://github.com/rust-lang/rust/issues/48821
#![feature(const_fn,
const_let)]
const
fn
foo
(
i
:
usize
)
->
usize
{
let
x
=
i
;
x
}
static
FOO
:
usize
=
foo
(
42
);
const
fn
bar
(
mut
i
:
usize
)
->
usize
{
i
+=
8
;
let
x
=
&
i
;
*
x
}
static
BAR
:
usize
=
bar
(
42
);
const
fn
boo
(
mut
i
:
usize
)
->
usize
{
{
let
mut
x
=
i
;
x
+=
10
;
i
=
x
;
}
i
}
static
BOO
:
usize
=
boo
(
42
);
fn
main
()
{
assert
!
(
FOO
==
42
);
assert
!
(
BAR
==
50
);
assert
!
(
BOO
==
52
);
}
src/test/ui/feature-gate-const_let.rs
0 → 100644
浏览文件 @
98721608
// 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.
// Test use of const let without feature gate.
#![feature(const_fn)]
const
fn
foo
()
->
usize
{
let
x
=
42
;
//~ ERROR blocks in constant functions are limited to items and tail expressions
42
}
fn
main
()
{}
src/test/ui/feature-gate-const_let.stderr
0 → 100644
浏览文件 @
98721608
error[E0016]: blocks in constant functions are limited to items and tail expressions
--> $DIR/feature-gate-const_let.rs:16:13
|
LL | let x = 42; //~ ERROR blocks in constant functions are limited to items and tail expressions
| ^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0016`.
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录