Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
e97089da
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,发现更多精彩内容 >>
未验证
提交
e97089da
编写于
12月 27, 2017
作者:
O
Oliver Schneider
提交者:
Oliver Schneider
3月 08, 2018
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Move librustc_const_eval to librustc_mir
上级
918b6d76
变更
25
隐藏空白更改
内联
并排
Showing
25 changed file
with
626 addition
and
642 deletion
+626
-642
src/doc/rustc-ux-guidelines.md
src/doc/rustc-ux-guidelines.md
+0
-1
src/librustc/dep_graph/dep_node.rs
src/librustc/dep_graph/dep_node.rs
+0
-1
src/librustc/ty/maps/config.rs
src/librustc/ty/maps/config.rs
+0
-1
src/librustc_const_eval/Cargo.toml
src/librustc_const_eval/Cargo.toml
+0
-19
src/librustc_const_eval/diagnostics.rs
src/librustc_const_eval/diagnostics.rs
+0
-571
src/librustc_driver/Cargo.toml
src/librustc_driver/Cargo.toml
+0
-1
src/librustc_driver/driver.rs
src/librustc_driver/driver.rs
+1
-2
src/librustc_driver/lib.rs
src/librustc_driver/lib.rs
+0
-2
src/librustc_lint/Cargo.toml
src/librustc_lint/Cargo.toml
+1
-1
src/librustc_lint/lib.rs
src/librustc_lint/lib.rs
+1
-1
src/librustc_lint/types.rs
src/librustc_lint/types.rs
+1
-1
src/librustc_mir/Cargo.toml
src/librustc_mir/Cargo.toml
+1
-1
src/librustc_mir/build/mod.rs
src/librustc_mir/build/mod.rs
+1
-1
src/librustc_mir/const_eval/_match.rs
src/librustc_mir/const_eval/_match.rs
+3
-3
src/librustc_mir/const_eval/check_match.rs
src/librustc_mir/const_eval/check_match.rs
+4
-4
src/librustc_mir/const_eval/eval.rs
src/librustc_mir/const_eval/eval.rs
+0
-0
src/librustc_mir/const_eval/mod.rs
src/librustc_mir/const_eval/mod.rs
+18
-0
src/librustc_mir/const_eval/pattern.rs
src/librustc_mir/const_eval/pattern.rs
+15
-14
src/librustc_mir/diagnostics.rs
src/librustc_mir/diagnostics.rs
+550
-0
src/librustc_mir/hair/mod.rs
src/librustc_mir/hair/mod.rs
+1
-1
src/librustc_mir/interpret/const_eval.rs
src/librustc_mir/interpret/const_eval.rs
+21
-13
src/librustc_mir/lib.rs
src/librustc_mir/lib.rs
+5
-1
src/librustc_passes/Cargo.toml
src/librustc_passes/Cargo.toml
+1
-1
src/librustc_passes/consts.rs
src/librustc_passes/consts.rs
+1
-1
src/librustc_passes/lib.rs
src/librustc_passes/lib.rs
+1
-1
未找到文件。
src/doc/rustc-ux-guidelines.md
浏览文件 @
e97089da
...
...
@@ -64,7 +64,6 @@ for details on how to format and write long error codes.
[
librustc
](
https://github.com/rust-lang/rust/blob/master/src/librustc/diagnostics.rs
)
,
[
libsyntax
](
https://github.com/rust-lang/rust/blob/master/src/libsyntax/diagnostics.rs
)
,
[
librustc_borrowck
](
https://github.com/rust-lang/rust/blob/master/src/librustc_borrowck/diagnostics.rs
)
,
[
librustc_const_eval
](
https://github.com/rust-lang/rust/blob/master/src/librustc_const_eval/diagnostics.rs
)
,
[
librustc_metadata
](
https://github.com/rust-lang/rust/blob/master/src/librustc_metadata/diagnostics.rs
)
,
[
librustc_mir
](
https://github.com/rust-lang/rust/blob/master/src/librustc_mir/diagnostics.rs
)
,
[
librustc_passes
](
https://github.com/rust-lang/rust/blob/master/src/librustc_passes/diagnostics.rs
)
,
...
...
src/librustc/dep_graph/dep_node.rs
浏览文件 @
e97089da
...
...
@@ -63,7 +63,6 @@
use
hir
::
def_id
::{
CrateNum
,
DefId
,
DefIndex
,
CRATE_DEF_INDEX
};
use
hir
::
map
::
DefPathHash
;
use
hir
::{
HirId
,
ItemLocalId
};
use
mir
;
use
ich
::
Fingerprint
;
use
ty
::{
TyCtxt
,
Instance
,
InstanceDef
,
ParamEnv
,
ParamEnvAnd
,
PolyTraitRef
,
Ty
};
...
...
src/librustc/ty/maps/config.rs
浏览文件 @
e97089da
...
...
@@ -13,7 +13,6 @@
use
ty
::{
self
,
Ty
,
TyCtxt
};
use
ty
::
maps
::
queries
;
use
ty
::
subst
::
Substs
;
use
mir
;
use
std
::
hash
::
Hash
;
use
syntax_pos
::
symbol
::
InternedString
;
...
...
src/librustc_const_eval/Cargo.toml
已删除
100644 → 0
浏览文件 @
918b6d76
[package]
authors
=
[
"The Rust Project Developers"
]
name
=
"rustc_const_eval"
version
=
"0.0.0"
[lib]
name
=
"rustc_const_eval"
path
=
"lib.rs"
crate-type
=
["dylib"]
[dependencies]
arena
=
{
path
=
"../libarena"
}
log
=
"0.4"
rustc
=
{
path
=
"../librustc"
}
rustc_const_math
=
{
path
=
"../librustc_const_math"
}
rustc_data_structures
=
{
path
=
"../librustc_data_structures"
}
rustc_errors
=
{
path
=
"../librustc_errors"
}
syntax
=
{
path
=
"../libsyntax"
}
syntax_pos
=
{
path
=
"../libsyntax_pos"
}
src/librustc_const_eval/diagnostics.rs
已删除
100644 → 0
浏览文件 @
918b6d76
// 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.
#![allow(non_snake_case)]
// Error messages for EXXXX errors.
// Each message should start and end with a new line, and be wrapped to 80 characters.
// In vim you can `:set tw=80` and use `gq` to wrap paragraphs. Use `:set tw=0` to disable.
register_long_diagnostics!
{
E0001
:
r##"
#### Note: this error code is no longer emitted by the compiler.
This error suggests that the expression arm corresponding to the noted pattern
will never be reached as for all possible values of the expression being
matched, one of the preceding patterns will match.
This means that perhaps some of the preceding patterns are too general, this
one is too specific or the ordering is incorrect.
For example, the following `match` block has too many arms:
```
match Some(0) {
Some(bar) => {/* ... */}
x => {/* ... */} // This handles the `None` case
_ => {/* ... */} // All possible cases have already been handled
}
```
`match` blocks have their patterns matched in order, so, for example, putting
a wildcard arm above a more specific arm will make the latter arm irrelevant.
Ensure the ordering of the match arm is correct and remove any superfluous
arms.
"##
,
E0002
:
r##"
#### Note: this error code is no longer emitted by the compiler.
This error indicates that an empty match expression is invalid because the type
it is matching on is non-empty (there exist values of this type). In safe code
it is impossible to create an instance of an empty type, so empty match
expressions are almost never desired. This error is typically fixed by adding
one or more cases to the match expression.
An example of an empty type is `enum Empty { }`. So, the following will work:
```
enum Empty {}
fn foo(x: Empty) {
match x {
// empty
}
}
```
However, this won't:
```compile_fail
fn foo(x: Option<String>) {
match x {
// empty
}
}
```
"##
,
E0003
:
r##"
#### Note: this error code is no longer emitted by the compiler.
Not-a-Number (NaN) values cannot be compared for equality and hence can never
match the input to a match expression. So, the following will not compile:
```compile_fail
const NAN: f32 = 0.0 / 0.0;
let number = 0.1f32;
match number {
NAN => { /* ... */ },
_ => {}
}
```
To match against NaN values, you should instead use the `is_nan()` method in a
guard, like so:
```
let number = 0.1f32;
match number {
x if x.is_nan() => { /* ... */ }
_ => {}
}
```
"##
,
E0004
:
r##"
This error indicates that the compiler cannot guarantee a matching pattern for
one or more possible inputs to a match expression. Guaranteed matches are
required in order to assign values to match expressions, or alternatively,
determine the flow of execution. Erroneous code example:
```compile_fail,E0004
enum Terminator {
HastaLaVistaBaby,
TalkToMyHand,
}
let x = Terminator::HastaLaVistaBaby;
match x { // error: non-exhaustive patterns: `HastaLaVistaBaby` not covered
Terminator::TalkToMyHand => {}
}
```
If you encounter this error you must alter your patterns so that every possible
value of the input type is matched. For types with a small number of variants
(like enums) you should probably cover all cases explicitly. Alternatively, the
underscore `_` wildcard pattern can be added after all other patterns to match
"anything else". Example:
```
enum Terminator {
HastaLaVistaBaby,
TalkToMyHand,
}
let x = Terminator::HastaLaVistaBaby;
match x {
Terminator::TalkToMyHand => {}
Terminator::HastaLaVistaBaby => {}
}
// or:
match x {
Terminator::TalkToMyHand => {}
_ => {}
}
```
"##
,
E0005
:
r##"
Patterns used to bind names must be irrefutable, that is, they must guarantee
that a name will be extracted in all cases. Erroneous code example:
```compile_fail,E0005
let x = Some(1);
let Some(y) = x;
// error: refutable pattern in local binding: `None` not covered
```
If you encounter this error you probably need to use a `match` or `if let` to
deal with the possibility of failure. Example:
```
let x = Some(1);
match x {
Some(y) => {
// do something
},
None => {}
}
// or:
if let Some(y) = x {
// do something
}
```
"##
,
E0007
:
r##"
This error indicates that the bindings in a match arm would require a value to
be moved into more than one location, thus violating unique ownership. Code
like the following is invalid as it requires the entire `Option<String>` to be
moved into a variable called `op_string` while simultaneously requiring the
inner `String` to be moved into a variable called `s`.
```compile_fail,E0007
let x = Some("s".to_string());
match x {
op_string @ Some(s) => {}, // error: cannot bind by-move with sub-bindings
None => {},
}
```
See also the error E0303.
"##
,
E0008
:
r##"
Names bound in match arms retain their type in pattern guards. As such, if a
name is bound by move in a pattern, it should also be moved to wherever it is
referenced in the pattern guard code. Doing so however would prevent the name
from being available in the body of the match arm. Consider the following:
```compile_fail,E0008
match Some("hi".to_string()) {
Some(s) if s.len() == 0 => {}, // use s.
_ => {},
}
```
The variable `s` has type `String`, and its use in the guard is as a variable of
type `String`. The guard code effectively executes in a separate scope to the
body of the arm, so the value would be moved into this anonymous scope and
therefore becomes unavailable in the body of the arm.
The problem above can be solved by using the `ref` keyword.
```
match Some("hi".to_string()) {
Some(ref s) if s.len() == 0 => {},
_ => {},
}
```
Though this example seems innocuous and easy to solve, the problem becomes clear
when it encounters functions which consume the value:
```compile_fail,E0008
struct A{}
impl A {
fn consume(self) -> usize {
0
}
}
fn main() {
let a = Some(A{});
match a {
Some(y) if y.consume() > 0 => {}
_ => {}
}
}
```
In this situation, even the `ref` keyword cannot solve it, since borrowed
content cannot be moved. This problem cannot be solved generally. If the value
can be cloned, here is a not-so-specific solution:
```
#[derive(Clone)]
struct A{}
impl A {
fn consume(self) -> usize {
0
}
}
fn main() {
let a = Some(A{});
match a{
Some(ref y) if y.clone().consume() > 0 => {}
_ => {}
}
}
```
If the value will be consumed in the pattern guard, using its clone will not
move its ownership, so the code works.
"##
,
E0009
:
r##"
In a pattern, all values that don't implement the `Copy` trait have to be bound
the same way. The goal here is to avoid binding simultaneously by-move and
by-ref.
This limitation may be removed in a future version of Rust.
Erroneous code example:
```compile_fail,E0009
struct X { x: (), }
let x = Some((X { x: () }, X { x: () }));
match x {
Some((y, ref z)) => {}, // error: cannot bind by-move and by-ref in the
// same pattern
None => panic!()
}
```
You have two solutions:
Solution #1: Bind the pattern's values the same way.
```
struct X { x: (), }
let x = Some((X { x: () }, X { x: () }));
match x {
Some((ref y, ref z)) => {},
// or Some((y, z)) => {}
None => panic!()
}
```
Solution #2: Implement the `Copy` trait for the `X` structure.
However, please keep in mind that the first solution should be preferred.
```
#[derive(Clone, Copy)]
struct X { x: (), }
let x = Some((X { x: () }, X { x: () }));
match x {
Some((y, ref z)) => {},
None => panic!()
}
```
"##
,
E0158
:
r##"
`const` and `static` mean different things. A `const` is a compile-time
constant, an alias for a literal value. This property means you can match it
directly within a pattern.
The `static` keyword, on the other hand, guarantees a fixed location in memory.
This does not always mean that the value is constant. For example, a global
mutex can be declared `static` as well.
If you want to match against a `static`, consider using a guard instead:
```
static FORTY_TWO: i32 = 42;
match Some(42) {
Some(x) if x == FORTY_TWO => {}
_ => {}
}
```
"##
,
E0162
:
r##"
An if-let pattern attempts to match the pattern, and enters the body if the
match was successful. If the match is irrefutable (when it cannot fail to
match), use a regular `let`-binding instead. For instance:
```compile_fail,E0162
struct Irrefutable(i32);
let irr = Irrefutable(0);
// This fails to compile because the match is irrefutable.
if let Irrefutable(x) = irr {
// This body will always be executed.
// ...
}
```
Try this instead:
```
struct Irrefutable(i32);
let irr = Irrefutable(0);
let Irrefutable(x) = irr;
println!("{}", x);
```
"##
,
E0165
:
r##"
A while-let pattern attempts to match the pattern, and enters the body if the
match was successful. If the match is irrefutable (when it cannot fail to
match), use a regular `let`-binding inside a `loop` instead. For instance:
```compile_fail,E0165
struct Irrefutable(i32);
let irr = Irrefutable(0);
// This fails to compile because the match is irrefutable.
while let Irrefutable(x) = irr {
// ...
}
```
Try this instead:
```no_run
struct Irrefutable(i32);
let irr = Irrefutable(0);
loop {
let Irrefutable(x) = irr;
// ...
}
```
"##
,
E0170
:
r##"
Enum variants are qualified by default. For example, given this type:
```
enum Method {
GET,
POST,
}
```
You would match it using:
```
enum Method {
GET,
POST,
}
let m = Method::GET;
match m {
Method::GET => {},
Method::POST => {},
}
```
If you don't qualify the names, the code will bind new variables named "GET" and
"POST" instead. This behavior is likely not what you want, so `rustc` warns when
that happens.
Qualified names are good practice, and most code works well with them. But if
you prefer them unqualified, you can import the variants into scope:
```
use Method::*;
enum Method { GET, POST }
# fn main() {}
```
If you want others to be able to import variants from your module directly, use
`pub use`:
```
pub use Method::*;
pub enum Method { GET, POST }
# fn main() {}
```
"##
,
E0297
:
r##"
#### Note: this error code is no longer emitted by the compiler.
Patterns used to bind names must be irrefutable. That is, they must guarantee
that a name will be extracted in all cases. Instead of pattern matching the
loop variable, consider using a `match` or `if let` inside the loop body. For
instance:
```compile_fail,E0005
let xs : Vec<Option<i32>> = vec![Some(1), None];
// This fails because `None` is not covered.
for Some(x) in xs {
// ...
}
```
Match inside the loop instead:
```
let xs : Vec<Option<i32>> = vec![Some(1), None];
for item in xs {
match item {
Some(x) => {},
None => {},
}
}
```
Or use `if let`:
```
let xs : Vec<Option<i32>> = vec![Some(1), None];
for item in xs {
if let Some(x) = item {
// ...
}
}
```
"##
,
E0301
:
r##"
Mutable borrows are not allowed in pattern guards, because matching cannot have
side effects. Side effects could alter the matched object or the environment
on which the match depends in such a way, that the match would not be
exhaustive. For instance, the following would not match any arm if mutable
borrows were allowed:
```compile_fail,E0301
match Some(()) {
None => { },
option if option.take().is_none() => {
/* impossible, option is `Some` */
},
Some(_) => { } // When the previous match failed, the option became `None`.
}
```
"##
,
E0302
:
r##"
Assignments are not allowed in pattern guards, because matching cannot have
side effects. Side effects could alter the matched object or the environment
on which the match depends in such a way, that the match would not be
exhaustive. For instance, the following would not match any arm if assignments
were allowed:
```compile_fail,E0302
match Some(()) {
None => { },
option if { option = None; false } => { },
Some(_) => { } // When the previous match failed, the option became `None`.
}
```
"##
,
E0303
:
r##"
In certain cases it is possible for sub-bindings to violate memory safety.
Updates to the borrow checker in a future version of Rust may remove this
restriction, but for now patterns must be rewritten without sub-bindings.
Before:
```compile_fail,E0303
match Some("hi".to_string()) {
ref op_string_ref @ Some(s) => {},
None => {},
}
```
After:
```
match Some("hi".to_string()) {
Some(ref s) => {
let op_string_ref = &Some(s);
// ...
},
None => {},
}
```
The `op_string_ref` binding has type `&Option<&String>` in both cases.
See also https://github.com/rust-lang/rust/issues/14587
"##
,
}
register_diagnostics!
{
// E0298, // cannot compare constants
// E0299, // mismatched types between arms
// E0471, // constant evaluation error (in pattern)
}
src/librustc_driver/Cargo.toml
浏览文件 @
e97089da
...
...
@@ -17,7 +17,6 @@ rustc = { path = "../librustc" }
rustc_allocator
=
{
path
=
"../librustc_allocator"
}
rustc_back
=
{
path
=
"../librustc_back"
}
rustc_borrowck
=
{
path
=
"../librustc_borrowck"
}
rustc_const_eval
=
{
path
=
"../librustc_const_eval"
}
rustc_data_structures
=
{
path
=
"../librustc_data_structures"
}
rustc_errors
=
{
path
=
"../librustc_errors"
}
rustc_incremental
=
{
path
=
"../librustc_incremental"
}
...
...
src/librustc_driver/driver.rs
浏览文件 @
e97089da
...
...
@@ -37,7 +37,7 @@
use
rustc_plugin
::
registry
::
Registry
;
use
rustc_plugin
as
plugin
;
use
rustc_passes
::{
self
,
ast_validation
,
loops
,
consts
,
hir_stats
};
use
rustc_
const_eval
::{
self
,
check_match
}
;
use
rustc_
mir
::
const_eval
::
check_match
;
use
super
::
Compilation
;
use
serialize
::
json
;
...
...
@@ -942,7 +942,6 @@ pub fn default_provide(providers: &mut ty::maps::Providers) {
ty
::
provide
(
providers
);
traits
::
provide
(
providers
);
reachable
::
provide
(
providers
);
rustc_const_eval
::
provide
(
providers
);
rustc_passes
::
provide
(
providers
);
middle
::
region
::
provide
(
providers
);
cstore
::
provide
(
providers
);
...
...
src/librustc_driver/lib.rs
浏览文件 @
e97089da
...
...
@@ -35,7 +35,6 @@
extern
crate
rustc_allocator
;
extern
crate
rustc_back
;
extern
crate
rustc_borrowck
;
extern
crate
rustc_const_eval
;
extern
crate
rustc_data_structures
;
extern
crate
rustc_errors
as
errors
;
extern
crate
rustc_passes
;
...
...
@@ -1566,7 +1565,6 @@ pub fn diagnostics_registry() -> errors::registry::Registry {
// FIXME: need to figure out a way to get these back in here
// all_errors.extend_from_slice(get_trans(sess).diagnostics());
all_errors
.extend_from_slice
(
&
rustc_trans_utils
::
DIAGNOSTICS
);
all_errors
.extend_from_slice
(
&
rustc_const_eval
::
DIAGNOSTICS
);
all_errors
.extend_from_slice
(
&
rustc_metadata
::
DIAGNOSTICS
);
all_errors
.extend_from_slice
(
&
rustc_passes
::
DIAGNOSTICS
);
all_errors
.extend_from_slice
(
&
rustc_plugin
::
DIAGNOSTICS
);
...
...
src/librustc_lint/Cargo.toml
浏览文件 @
e97089da
...
...
@@ -12,6 +12,6 @@ test = false
[dependencies]
log
=
"0.4"
rustc
=
{
path
=
"../librustc"
}
rustc_
const_eval
=
{
path
=
"../librustc_const_eval"
}
rustc_
mir
=
{
path
=
"../librustc_mir"
}
syntax
=
{
path
=
"../libsyntax"
}
syntax_pos
=
{
path
=
"../libsyntax_pos"
}
src/librustc_lint/lib.rs
浏览文件 @
e97089da
...
...
@@ -39,7 +39,7 @@
extern
crate
rustc
;
#[macro_use]
extern
crate
log
;
extern
crate
rustc_
const_eval
;
extern
crate
rustc_
mir
;
extern
crate
syntax_pos
;
use
rustc
::
lint
;
...
...
src/librustc_lint/types.rs
浏览文件 @
e97089da
...
...
@@ -15,7 +15,7 @@
use
rustc
::
ty
::{
self
,
AdtKind
,
Ty
,
TyCtxt
};
use
rustc
::
ty
::
layout
::{
self
,
LayoutOf
};
use
middle
::
const_val
::
ConstVal
;
use
rustc_const_eval
::
ConstContext
;
use
rustc_
mir
::
const_eval
::
ConstContext
;
use
rustc
::
mir
::
interpret
::{
Value
,
PrimVal
};
use
util
::
nodemap
::
FxHashSet
;
use
lint
::{
LateContext
,
LintContext
,
LintArray
};
...
...
src/librustc_mir/Cargo.toml
浏览文件 @
e97089da
...
...
@@ -9,13 +9,13 @@ path = "lib.rs"
crate-type
=
["dylib"]
[dependencies]
arena
=
{
path
=
"../libarena"
}
bitflags
=
"1.0"
graphviz
=
{
path
=
"../libgraphviz"
}
log
=
"0.4"
log_settings
=
"0.1.1"
rustc
=
{
path
=
"../librustc"
}
rustc_back
=
{
path
=
"../librustc_back"
}
rustc_const_eval
=
{
path
=
"../librustc_const_eval"
}
rustc_const_math
=
{
path
=
"../librustc_const_math"
}
rustc_data_structures
=
{
path
=
"../librustc_data_structures"
}
rustc_errors
=
{
path
=
"../librustc_errors"
}
...
...
src/librustc_mir/build/mod.rs
浏览文件 @
e97089da
...
...
@@ -21,7 +21,7 @@
use
rustc
::
ty
::
subst
::
Substs
;
use
rustc
::
util
::
nodemap
::
NodeMap
;
use
rustc_back
::
PanicStrategy
;
use
rustc_
const_eval
::
pattern
::{
BindingMode
,
PatternKind
};
use
const_eval
::
pattern
::{
BindingMode
,
PatternKind
};
use
rustc_data_structures
::
indexed_vec
::{
IndexVec
,
Idx
};
use
shim
;
use
std
::
mem
;
...
...
src/librustc_const_eval/_match.rs
→
src/librustc_
mir/
const_eval/_match.rs
浏览文件 @
e97089da
...
...
@@ -13,15 +13,15 @@
use
self
::
WitnessPreference
::
*
;
use
rustc
::
middle
::
const_val
::
ConstVal
;
use
eval
::{
compare_const_vals
};
use
const_eval
::
eval
::{
compare_const_vals
};
use
rustc_const_math
::
ConstInt
;
use
rustc_data_structures
::
fx
::
FxHashMap
;
use
rustc_data_structures
::
indexed_vec
::
Idx
;
use
pattern
::{
FieldPattern
,
Pattern
,
PatternKind
};
use
pattern
::{
PatternFoldable
,
PatternFolder
};
use
const_eval
::
pattern
::{
FieldPattern
,
Pattern
,
PatternKind
};
use
const_eval
::
pattern
::{
PatternFoldable
,
PatternFolder
};
use
rustc
::
hir
::
def_id
::
DefId
;
use
rustc
::
hir
::
RangeEnd
;
...
...
src/librustc_const_eval/check_match.rs
→
src/librustc_
mir/
const_eval/check_match.rs
浏览文件 @
e97089da
...
...
@@ -8,11 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use
_
match
::{
MatchCheckCtxt
,
Matrix
,
expand_pattern
,
is_useful
};
use
_
match
::
Usefulness
::
*
;
use
_
match
::
WitnessPreference
::
*
;
use
const_eval
::
_
match
::{
MatchCheckCtxt
,
Matrix
,
expand_pattern
,
is_useful
};
use
const_eval
::
_
match
::
Usefulness
::
*
;
use
const_eval
::
_
match
::
WitnessPreference
::
*
;
use
pattern
::{
Pattern
,
PatternContext
,
PatternError
,
PatternKind
};
use
const_eval
::
pattern
::{
Pattern
,
PatternContext
,
PatternError
,
PatternKind
};
use
rustc
::
middle
::
expr_use_visitor
::{
ConsumeMode
,
Delegate
,
ExprUseVisitor
};
use
rustc
::
middle
::
expr_use_visitor
::{
LoanCause
,
MutateMode
};
...
...
src/librustc_const_eval/eval.rs
→
src/librustc_
mir/
const_eval/eval.rs
浏览文件 @
e97089da
文件已移动
src/librustc_mir/const_eval/mod.rs
0 → 100644
浏览文件 @
e97089da
// 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.
//! constant evaluation on the HIR and code to validate patterns/matches
mod
eval
;
mod
_
match
;
pub
mod
check_match
;
pub
mod
pattern
;
pub
use
self
::
eval
::
*
;
src/librustc_const_eval/pattern.rs
→
src/librustc_
mir/
const_eval/pattern.rs
浏览文件 @
e97089da
...
...
@@ -8,7 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use
eval
;
use
const_eval
::
eval
;
use
interpret
::{
const_val_field
,
const_discr
};
use
rustc
::
middle
::
const_val
::{
ConstEvalErr
,
ConstVal
,
ConstAggregate
};
use
rustc
::
mir
::{
Field
,
BorrowKind
,
Mutability
};
...
...
@@ -693,7 +694,7 @@ fn lower_lit(&mut self, expr: &'tcx hir::Expr) -> PatternKind<'tcx> {
return
match
expr
.node
{
hir
::
ExprLit
(
ref
lit
)
=>
{
let
ty
=
self
.tables
.expr_ty
(
expr
);
match
::
eval
::
lit_to_const
(
&
lit
.node
,
self
.tcx
,
ty
,
false
)
{
match
super
::
eval
::
lit_to_const
(
&
lit
.node
,
self
.tcx
,
ty
,
false
)
{
Ok
(
value
)
=>
PatternKind
::
Constant
{
value
:
self
.tcx
.mk_const
(
ty
::
Const
{
ty
,
...
...
@@ -716,7 +717,7 @@ fn lower_lit(&mut self, expr: &'tcx hir::Expr) -> PatternKind<'tcx> {
hir
::
ExprLit
(
ref
lit
)
=>
lit
,
_
=>
span_bug!
(
expr
.span
,
"not a literal: {:?}"
,
expr
),
};
match
::
eval
::
lit_to_const
(
&
lit
.node
,
self
.tcx
,
ty
,
true
)
{
match
super
::
eval
::
lit_to_const
(
&
lit
.node
,
self
.tcx
,
ty
,
true
)
{
Ok
(
value
)
=>
PatternKind
::
Constant
{
value
:
self
.tcx
.mk_const
(
ty
::
Const
{
ty
,
...
...
@@ -782,9 +783,9 @@ fn const_to_pat(
ty
::
TyAdt
(
adt_def
,
substs
)
if
adt_def
.is_enum
()
=>
{
match
cv
.val
{
ConstVal
::
Value
(
val
)
=>
{
let
discr
=
self
.tcx
.const_discr
(
self
.param_env
.and
(
(
instance
,
val
,
cv
.ty
)
))
.unwrap
();
let
discr
=
const_discr
(
self
.tcx
,
self
.param_env
,
instance
,
val
,
cv
.ty
)
.unwrap
();
let
variant_index
=
adt_def
.discriminants
(
self
.tcx
)
.position
(|
var
|
var
.to_u128_unchecked
()
==
discr
)
...
...
@@ -801,8 +802,8 @@ fn const_to_pat(
.map
(|(
i
,
_
)|
{
let
field
=
Field
::
new
(
i
);
let
val
=
match
cv
.val
{
ConstVal
::
Value
(
miri
)
=>
self
.tcx
.
const_val_field
(
self
.
param_env
.and
((
instance
,
field
,
miri
,
cv
.ty
))
,
ConstVal
::
Value
(
miri
)
=>
const_val_field
(
self
.
tcx
,
self
.param_env
,
instance
,
field
,
miri
,
cv
.ty
,
)
.unwrap
(),
_
=>
bug!
(
"{:#?} is not a valid tuple"
,
cv
),
};
...
...
@@ -844,8 +845,8 @@ fn const_to_pat(
ConstVal
::
Aggregate
(
ConstAggregate
::
Struct
(
consts
))
=>
{
consts
.iter
()
.find
(|
&&
(
name
,
_
)|
name
==
f
.name
)
.unwrap
()
.1
},
ConstVal
::
Value
(
miri
)
=>
self
.tcx
.
const_val_field
(
self
.
param_env
.and
((
instance
,
field
,
miri
,
cv
.ty
))
,
ConstVal
::
Value
(
miri
)
=>
const_val_field
(
self
.
tcx
,
self
.param_env
,
instance
,
field
,
miri
,
cv
.ty
,
)
.unwrap
(),
_
=>
bug!
(
"{:#?} is not a valid tuple"
,
cv
),
};
...
...
@@ -862,8 +863,8 @@ fn const_to_pat(
let
field
=
Field
::
new
(
i
);
let
val
=
match
cv
.val
{
ConstVal
::
Aggregate
(
ConstAggregate
::
Tuple
(
consts
))
=>
consts
[
i
],
ConstVal
::
Value
(
miri
)
=>
self
.tcx
.
const_val_field
(
self
.
param_env
.and
((
instance
,
field
,
miri
,
cv
.ty
))
,
ConstVal
::
Value
(
miri
)
=>
const_val_field
(
self
.
tcx
,
self
.param_env
,
instance
,
field
,
miri
,
cv
.ty
,
)
.unwrap
(),
_
=>
bug!
(
"{:#?} is not a valid tuple"
,
cv
),
};
...
...
@@ -882,8 +883,8 @@ fn const_to_pat(
let
val
=
match
cv
.val
{
ConstVal
::
Aggregate
(
ConstAggregate
::
Array
(
consts
))
=>
consts
[
i
],
ConstVal
::
Aggregate
(
ConstAggregate
::
Repeat
(
cv
,
_
))
=>
cv
,
ConstVal
::
Value
(
miri
)
=>
self
.tcx
.
const_val_field
(
self
.
param_env
.and
((
instance
,
field
,
miri
,
cv
.ty
))
,
ConstVal
::
Value
(
miri
)
=>
const_val_field
(
self
.
tcx
,
self
.param_env
,
instance
,
field
,
miri
,
cv
.ty
,
)
.unwrap
(),
_
=>
bug!
(
"{:#?} is not a valid tuple"
,
cv
),
};
...
...
src/librustc_mir/diagnostics.rs
浏览文件 @
e97089da
...
...
@@ -12,6 +12,553 @@
register_long_diagnostics!
{
E0001
:
r##"
#### Note: this error code is no longer emitted by the compiler.
This error suggests that the expression arm corresponding to the noted pattern
will never be reached as for all possible values of the expression being
matched, one of the preceding patterns will match.
This means that perhaps some of the preceding patterns are too general, this
one is too specific or the ordering is incorrect.
For example, the following `match` block has too many arms:
```
match Some(0) {
Some(bar) => {/* ... */}
x => {/* ... */} // This handles the `None` case
_ => {/* ... */} // All possible cases have already been handled
}
```
`match` blocks have their patterns matched in order, so, for example, putting
a wildcard arm above a more specific arm will make the latter arm irrelevant.
Ensure the ordering of the match arm is correct and remove any superfluous
arms.
"##
,
E0002
:
r##"
#### Note: this error code is no longer emitted by the compiler.
This error indicates that an empty match expression is invalid because the type
it is matching on is non-empty (there exist values of this type). In safe code
it is impossible to create an instance of an empty type, so empty match
expressions are almost never desired. This error is typically fixed by adding
one or more cases to the match expression.
An example of an empty type is `enum Empty { }`. So, the following will work:
```
enum Empty {}
fn foo(x: Empty) {
match x {
// empty
}
}
```
However, this won't:
```compile_fail
fn foo(x: Option<String>) {
match x {
// empty
}
}
```
"##
,
E0003
:
r##"
#### Note: this error code is no longer emitted by the compiler.
Not-a-Number (NaN) values cannot be compared for equality and hence can never
match the input to a match expression. So, the following will not compile:
```compile_fail
const NAN: f32 = 0.0 / 0.0;
let number = 0.1f32;
match number {
NAN => { /* ... */ },
_ => {}
}
```
To match against NaN values, you should instead use the `is_nan()` method in a
guard, like so:
```
let number = 0.1f32;
match number {
x if x.is_nan() => { /* ... */ }
_ => {}
}
```
"##
,
E0004
:
r##"
This error indicates that the compiler cannot guarantee a matching pattern for
one or more possible inputs to a match expression. Guaranteed matches are
required in order to assign values to match expressions, or alternatively,
determine the flow of execution. Erroneous code example:
```compile_fail,E0004
enum Terminator {
HastaLaVistaBaby,
TalkToMyHand,
}
let x = Terminator::HastaLaVistaBaby;
match x { // error: non-exhaustive patterns: `HastaLaVistaBaby` not covered
Terminator::TalkToMyHand => {}
}
```
If you encounter this error you must alter your patterns so that every possible
value of the input type is matched. For types with a small number of variants
(like enums) you should probably cover all cases explicitly. Alternatively, the
underscore `_` wildcard pattern can be added after all other patterns to match
"anything else". Example:
```
enum Terminator {
HastaLaVistaBaby,
TalkToMyHand,
}
let x = Terminator::HastaLaVistaBaby;
match x {
Terminator::TalkToMyHand => {}
Terminator::HastaLaVistaBaby => {}
}
// or:
match x {
Terminator::TalkToMyHand => {}
_ => {}
}
```
"##
,
E0005
:
r##"
Patterns used to bind names must be irrefutable, that is, they must guarantee
that a name will be extracted in all cases. Erroneous code example:
```compile_fail,E0005
let x = Some(1);
let Some(y) = x;
// error: refutable pattern in local binding: `None` not covered
```
If you encounter this error you probably need to use a `match` or `if let` to
deal with the possibility of failure. Example:
```
let x = Some(1);
match x {
Some(y) => {
// do something
},
None => {}
}
// or:
if let Some(y) = x {
// do something
}
```
"##
,
E0007
:
r##"
This error indicates that the bindings in a match arm would require a value to
be moved into more than one location, thus violating unique ownership. Code
like the following is invalid as it requires the entire `Option<String>` to be
moved into a variable called `op_string` while simultaneously requiring the
inner `String` to be moved into a variable called `s`.
```compile_fail,E0007
let x = Some("s".to_string());
match x {
op_string @ Some(s) => {}, // error: cannot bind by-move with sub-bindings
None => {},
}
```
See also the error E0303.
"##
,
E0008
:
r##"
Names bound in match arms retain their type in pattern guards. As such, if a
name is bound by move in a pattern, it should also be moved to wherever it is
referenced in the pattern guard code. Doing so however would prevent the name
from being available in the body of the match arm. Consider the following:
```compile_fail,E0008
match Some("hi".to_string()) {
Some(s) if s.len() == 0 => {}, // use s.
_ => {},
}
```
The variable `s` has type `String`, and its use in the guard is as a variable of
type `String`. The guard code effectively executes in a separate scope to the
body of the arm, so the value would be moved into this anonymous scope and
therefore becomes unavailable in the body of the arm.
The problem above can be solved by using the `ref` keyword.
```
match Some("hi".to_string()) {
Some(ref s) if s.len() == 0 => {},
_ => {},
}
```
Though this example seems innocuous and easy to solve, the problem becomes clear
when it encounters functions which consume the value:
```compile_fail,E0008
struct A{}
impl A {
fn consume(self) -> usize {
0
}
}
fn main() {
let a = Some(A{});
match a {
Some(y) if y.consume() > 0 => {}
_ => {}
}
}
```
In this situation, even the `ref` keyword cannot solve it, since borrowed
content cannot be moved. This problem cannot be solved generally. If the value
can be cloned, here is a not-so-specific solution:
```
#[derive(Clone)]
struct A{}
impl A {
fn consume(self) -> usize {
0
}
}
fn main() {
let a = Some(A{});
match a{
Some(ref y) if y.clone().consume() > 0 => {}
_ => {}
}
}
```
If the value will be consumed in the pattern guard, using its clone will not
move its ownership, so the code works.
"##
,
E0009
:
r##"
In a pattern, all values that don't implement the `Copy` trait have to be bound
the same way. The goal here is to avoid binding simultaneously by-move and
by-ref.
This limitation may be removed in a future version of Rust.
Erroneous code example:
```compile_fail,E0009
struct X { x: (), }
let x = Some((X { x: () }, X { x: () }));
match x {
Some((y, ref z)) => {}, // error: cannot bind by-move and by-ref in the
// same pattern
None => panic!()
}
```
You have two solutions:
Solution #1: Bind the pattern's values the same way.
```
struct X { x: (), }
let x = Some((X { x: () }, X { x: () }));
match x {
Some((ref y, ref z)) => {},
// or Some((y, z)) => {}
None => panic!()
}
```
Solution #2: Implement the `Copy` trait for the `X` structure.
However, please keep in mind that the first solution should be preferred.
```
#[derive(Clone, Copy)]
struct X { x: (), }
let x = Some((X { x: () }, X { x: () }));
match x {
Some((y, ref z)) => {},
None => panic!()
}
```
"##
,
E0158
:
r##"
`const` and `static` mean different things. A `const` is a compile-time
constant, an alias for a literal value. This property means you can match it
directly within a pattern.
The `static` keyword, on the other hand, guarantees a fixed location in memory.
This does not always mean that the value is constant. For example, a global
mutex can be declared `static` as well.
If you want to match against a `static`, consider using a guard instead:
```
static FORTY_TWO: i32 = 42;
match Some(42) {
Some(x) if x == FORTY_TWO => {}
_ => {}
}
```
"##
,
E0162
:
r##"
An if-let pattern attempts to match the pattern, and enters the body if the
match was successful. If the match is irrefutable (when it cannot fail to
match), use a regular `let`-binding instead. For instance:
```compile_fail,E0162
struct Irrefutable(i32);
let irr = Irrefutable(0);
// This fails to compile because the match is irrefutable.
if let Irrefutable(x) = irr {
// This body will always be executed.
// ...
}
```
Try this instead:
```
struct Irrefutable(i32);
let irr = Irrefutable(0);
let Irrefutable(x) = irr;
println!("{}", x);
```
"##
,
E0165
:
r##"
A while-let pattern attempts to match the pattern, and enters the body if the
match was successful. If the match is irrefutable (when it cannot fail to
match), use a regular `let`-binding inside a `loop` instead. For instance:
```compile_fail,E0165
struct Irrefutable(i32);
let irr = Irrefutable(0);
// This fails to compile because the match is irrefutable.
while let Irrefutable(x) = irr {
// ...
}
```
Try this instead:
```no_run
struct Irrefutable(i32);
let irr = Irrefutable(0);
loop {
let Irrefutable(x) = irr;
// ...
}
```
"##
,
E0170
:
r##"
Enum variants are qualified by default. For example, given this type:
```
enum Method {
GET,
POST,
}
```
You would match it using:
```
enum Method {
GET,
POST,
}
let m = Method::GET;
match m {
Method::GET => {},
Method::POST => {},
}
```
If you don't qualify the names, the code will bind new variables named "GET" and
"POST" instead. This behavior is likely not what you want, so `rustc` warns when
that happens.
Qualified names are good practice, and most code works well with them. But if
you prefer them unqualified, you can import the variants into scope:
```
use Method::*;
enum Method { GET, POST }
# fn main() {}
```
If you want others to be able to import variants from your module directly, use
`pub use`:
```
pub use Method::*;
pub enum Method { GET, POST }
# fn main() {}
```
"##
,
E0297
:
r##"
#### Note: this error code is no longer emitted by the compiler.
Patterns used to bind names must be irrefutable. That is, they must guarantee
that a name will be extracted in all cases. Instead of pattern matching the
loop variable, consider using a `match` or `if let` inside the loop body. For
instance:
```compile_fail,E0005
let xs : Vec<Option<i32>> = vec![Some(1), None];
// This fails because `None` is not covered.
for Some(x) in xs {
// ...
}
```
Match inside the loop instead:
```
let xs : Vec<Option<i32>> = vec![Some(1), None];
for item in xs {
match item {
Some(x) => {},
None => {},
}
}
```
Or use `if let`:
```
let xs : Vec<Option<i32>> = vec![Some(1), None];
for item in xs {
if let Some(x) = item {
// ...
}
}
```
"##
,
E0301
:
r##"
Mutable borrows are not allowed in pattern guards, because matching cannot have
side effects. Side effects could alter the matched object or the environment
on which the match depends in such a way, that the match would not be
exhaustive. For instance, the following would not match any arm if mutable
borrows were allowed:
```compile_fail,E0301
match Some(()) {
None => { },
option if option.take().is_none() => {
/* impossible, option is `Some` */
},
Some(_) => { } // When the previous match failed, the option became `None`.
}
```
"##
,
E0302
:
r##"
Assignments are not allowed in pattern guards, because matching cannot have
side effects. Side effects could alter the matched object or the environment
on which the match depends in such a way, that the match would not be
exhaustive. For instance, the following would not match any arm if assignments
were allowed:
```compile_fail,E0302
match Some(()) {
None => { },
option if { option = None; false } => { },
Some(_) => { } // When the previous match failed, the option became `None`.
}
```
"##
,
E0303
:
r##"
In certain cases it is possible for sub-bindings to violate memory safety.
Updates to the borrow checker in a future version of Rust may remove this
restriction, but for now patterns must be rewritten without sub-bindings.
Before:
```compile_fail,E0303
match Some("hi".to_string()) {
ref op_string_ref @ Some(s) => {},
None => {},
}
```
After:
```
match Some("hi".to_string()) {
Some(ref s) => {
let op_string_ref = &Some(s);
// ...
},
None => {},
}
```
The `op_string_ref` binding has type `&Option<&String>` in both cases.
See also https://github.com/rust-lang/rust/issues/14587
"##
,
E0010
:
r##"
The value of statics and constants must be known at compile time, and they live
for the entire lifetime of a program. Creating a boxed value allocates memory on
...
...
@@ -1771,6 +2318,9 @@ struct Foo<'a> {
}
register_diagnostics!
{
// E0298, // cannot compare constants
// E0299, // mismatched types between arms
// E0471, // constant evaluation error (in pattern)
// E0385, // {} in an aliasable location
E0493
,
// destructors cannot be evaluated at compile-time
E0524
,
// two closures require unique access to `..` at the same time
...
...
src/librustc_mir/hair/mod.rs
浏览文件 @
e97089da
...
...
@@ -27,7 +27,7 @@
pub
mod
cx
;
pub
use
rustc_
const_eval
::
pattern
::{
BindingMode
,
Pattern
,
PatternKind
,
FieldPattern
};
pub
use
const_eval
::
pattern
::{
BindingMode
,
Pattern
,
PatternKind
,
FieldPattern
};
#[derive(Copy,
Clone,
Debug)]
pub
enum
LintLevel
{
...
...
src/librustc_mir/interpret/const_eval.rs
浏览文件 @
e97089da
...
...
@@ -5,7 +5,7 @@
use
rustc
::
mir
;
use
rustc
::
middle
::
const_val
::
ErrKind
::{
CheckMatchError
,
TypeckError
};
use
rustc
::
middle
::
const_val
::{
ConstEvalErr
,
ConstVal
};
use
rustc_
const_eval
::{
lookup_const_by_id
,
ConstContext
};
use
const_eval
::{
lookup_const_by_id
,
ConstContext
};
use
rustc
::
mir
::
Field
;
use
rustc_data_structures
::
indexed_vec
::
Idx
;
...
...
@@ -306,16 +306,19 @@ fn global_item_with_linkage<'a>(
pub
fn
const_val_field
<
'a
,
'tcx
>
(
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
key
:
ty
::
ParamEnvAnd
<
'tcx
,
(
ty
::
Instance
<
'tcx
>
,
mir
::
Field
,
Value
,
Ty
<
'tcx
>
)
>
,
param_env
:
ty
::
ParamEnv
<
'tcx
>
,
instance
:
ty
::
Instance
<
'tcx
>
,
field
:
mir
::
Field
,
val
:
Value
,
ty
:
Ty
<
'tcx
>
,
)
->
::
rustc
::
middle
::
const_val
::
EvalResult
<
'tcx
>
{
trace!
(
"const_val_field: {:#?}"
,
key
);
match
const_val_field_inner
(
tcx
,
key
)
{
match
const_val_field_inner
(
tcx
,
param_env
,
instance
,
field
,
val
,
ty
)
{
Ok
((
field
,
ty
))
=>
Ok
(
tcx
.mk_const
(
ty
::
Const
{
val
:
ConstVal
::
Value
(
field
),
ty
,
})),
Err
(
err
)
=>
Err
(
ConstEvalErr
{
span
:
tcx
.def_span
(
key
.value
.0
.def_id
()),
span
:
tcx
.def_span
(
instance
.def_id
()),
kind
:
err
.into
(),
}),
}
...
...
@@ -323,11 +326,14 @@ pub fn const_val_field<'a, 'tcx>(
fn
const_val_field_inner
<
'a
,
'tcx
>
(
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
key
:
ty
::
ParamEnvAnd
<
'tcx
,
(
ty
::
Instance
<
'tcx
>
,
mir
::
Field
,
Value
,
Ty
<
'tcx
>
)
>
,
param_env
:
ty
::
ParamEnv
<
'tcx
>
,
instance
:
ty
::
Instance
<
'tcx
>
,
field
:
mir
::
Field
,
value
:
Value
,
ty
:
Ty
<
'tcx
>
,
)
->
::
rustc
::
mir
::
interpret
::
EvalResult
<
'tcx
,
(
Value
,
Ty
<
'tcx
>
)
>
{
trace!
(
"const_val_field: {:#?}"
,
key
);
let
(
instance
,
field
,
value
,
ty
)
=
key
.value
;
let
mut
ecx
=
mk_eval_cx
(
tcx
,
instance
,
key
.param_env
)
.unwrap
();
trace!
(
"const_val_field: {:?}, {:?}, {:?}, {:?}"
,
instance
,
field
,
value
,
ty
);
let
mut
ecx
=
mk_eval_cx
(
tcx
,
instance
,
param_env
)
.unwrap
();
let
(
mut
field
,
ty
)
=
match
value
{
Value
::
ByValPair
(
..
)
|
Value
::
ByVal
(
_
)
=>
ecx
.read_field
(
value
,
field
,
ty
)
?
.expect
(
"const_val_field on non-field"
),
Value
::
ByRef
(
ptr
,
align
)
=>
{
...
...
@@ -348,11 +354,13 @@ fn const_val_field_inner<'a, 'tcx>(
pub
fn
const_discr
<
'a
,
'tcx
>
(
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
key
:
ty
::
ParamEnvAnd
<
'tcx
,
(
ty
::
Instance
<
'tcx
>
,
Value
,
Ty
<
'tcx
>
)
>
,
param_env
:
ty
::
ParamEnv
<
'tcx
>
,
instance
:
ty
::
Instance
<
'tcx
>
,
value
:
Value
,
ty
:
Ty
<
'tcx
>
,
)
->
EvalResult
<
'tcx
,
u128
>
{
trace!
(
"const_discr: {:#?}"
,
key
);
let
(
instance
,
value
,
ty
)
=
key
.value
;
let
mut
ecx
=
mk_eval_cx
(
tcx
,
instance
,
key
.param_env
)
.unwrap
();
trace!
(
"const_discr: {:?}, {:?}, {:?}"
,
instance
,
value
,
ty
);
let
mut
ecx
=
mk_eval_cx
(
tcx
,
instance
,
param_env
)
.unwrap
();
let
(
ptr
,
align
)
=
match
value
{
Value
::
ByValPair
(
..
)
|
Value
::
ByVal
(
_
)
=>
{
let
layout
=
ecx
.layout_of
(
ty
)
?
;
...
...
src/librustc_mir/lib.rs
浏览文件 @
e97089da
...
...
@@ -16,6 +16,8 @@
#![deny(warnings)]
#![feature(slice_patterns)]
#![feature(from_ref)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(catch_expr)]
...
...
@@ -38,6 +40,7 @@
#![feature(nonzero)]
#![feature(underscore_lifetimes)]
extern
crate
arena
;
#[macro_use]
extern
crate
bitflags
;
#[macro_use]
extern
crate
log
;
...
...
@@ -52,7 +55,6 @@
extern
crate
syntax_pos
;
extern
crate
rustc_back
;
extern
crate
rustc_const_math
;
extern
crate
rustc_const_eval
;
extern
crate
core
;
// for NonZero
extern
crate
log_settings
;
extern
crate
rustc_apfloat
;
...
...
@@ -69,6 +71,7 @@
pub
mod
util
;
pub
mod
interpret
;
pub
mod
monomorphize
;
pub
mod
const_eval
;
use
rustc
::
ty
::
maps
::
Providers
;
...
...
@@ -77,6 +80,7 @@ pub fn provide(providers: &mut Providers) {
shim
::
provide
(
providers
);
transform
::
provide
(
providers
);
providers
.const_eval
=
interpret
::
const_eval_provider
;
providers
.check_match
=
const_eval
::
check_match
::
check_match
;
}
__
build_diagnostic_array!
{
librustc_mir
,
DIAGNOSTICS
}
src/librustc_passes/Cargo.toml
浏览文件 @
e97089da
...
...
@@ -11,7 +11,7 @@ crate-type = ["dylib"]
[dependencies]
log
=
"0.4"
rustc
=
{
path
=
"../librustc"
}
rustc_
const_eval
=
{
path
=
"../librustc_const_eval"
}
rustc_
mir
=
{
path
=
"../librustc_mir"
}
rustc_const_math
=
{
path
=
"../librustc_const_math"
}
rustc_data_structures
=
{
path
=
"../librustc_data_structures"
}
syntax
=
{
path
=
"../libsyntax"
}
...
...
src/librustc_passes/consts.rs
浏览文件 @
e97089da
...
...
@@ -25,7 +25,7 @@
// by borrowck::gather_loans
use
rustc
::
ty
::
cast
::
CastKind
;
use
rustc_const_eval
::
ConstContext
;
use
rustc_
mir
::
const_eval
::
ConstContext
;
use
rustc
::
middle
::
const_val
::
ConstEvalErr
;
use
rustc
::
middle
::
const_val
::
ErrKind
::{
IndexOpFeatureGated
,
UnimplementedConstVal
,
MiscCatchAll
};
use
rustc
::
middle
::
const_val
::
ErrKind
::{
ErroneousReferencedConstant
,
MiscBinaryOp
,
NonConstPath
};
...
...
src/librustc_passes/lib.rs
浏览文件 @
e97089da
...
...
@@ -23,7 +23,7 @@
#[macro_use]
extern
crate
rustc
;
extern
crate
rustc_
const_eval
;
extern
crate
rustc_
mir
;
extern
crate
rustc_const_math
;
extern
crate
rustc_data_structures
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录