mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-22 12:43:36 +00:00
move const_eval
and check_match
out of librustc
This commit is contained in:
parent
6cc449ad24
commit
3eac64747f
23
mk/crates.mk
23
mk/crates.mk
@ -58,7 +58,7 @@ RUSTC_CRATES := rustc rustc_typeck rustc_mir rustc_borrowck rustc_resolve rustc_
|
||||
rustc_trans rustc_back rustc_llvm rustc_privacy rustc_lint \
|
||||
rustc_data_structures rustc_front rustc_platform_intrinsics \
|
||||
rustc_plugin rustc_metadata rustc_passes rustc_save_analysis \
|
||||
rustc_const_eval
|
||||
rustc_const_eval rustc_const_math
|
||||
HOST_CRATES := syntax syntax_ext $(RUSTC_CRATES) rustdoc fmt_macros \
|
||||
flate arena graphviz rbml log serialize
|
||||
TOOLS := compiletest rustdoc rustc rustbook error_index_generator
|
||||
@ -93,35 +93,38 @@ DEPS_syntax := std term serialize log arena libc rustc_bitflags rustc_unicode
|
||||
DEPS_syntax_ext := syntax fmt_macros
|
||||
|
||||
DEPS_rustc_const_math := std syntax log serialize
|
||||
DEPS_rustc_const_eval := rustc_const_math rustc syntax log serialize rustc_front \
|
||||
rustc_back graphviz
|
||||
|
||||
DEPS_rustc := syntax fmt_macros flate arena serialize getopts rbml rustc_front\
|
||||
log graphviz rustc_back rustc_data_structures\
|
||||
rustc_const_eval
|
||||
rustc_const_math
|
||||
DEPS_rustc_back := std syntax rustc_front flate log libc
|
||||
DEPS_rustc_borrowck := rustc rustc_front rustc_mir log graphviz syntax
|
||||
DEPS_rustc_data_structures := std log serialize
|
||||
DEPS_rustc_driver := arena flate getopts graphviz libc rustc rustc_back rustc_borrowck \
|
||||
rustc_typeck rustc_mir rustc_resolve log syntax serialize rustc_llvm \
|
||||
rustc_trans rustc_privacy rustc_lint rustc_front rustc_plugin \
|
||||
rustc_metadata syntax_ext rustc_passes rustc_save_analysis
|
||||
rustc_metadata syntax_ext rustc_passes rustc_save_analysis rustc_const_eval
|
||||
DEPS_rustc_front := std syntax log serialize
|
||||
DEPS_rustc_lint := rustc log syntax
|
||||
DEPS_rustc_lint := rustc log syntax rustc_const_eval
|
||||
DEPS_rustc_llvm := native:rustllvm libc std rustc_bitflags
|
||||
DEPS_rustc_metadata := rustc rustc_front syntax rbml rustc_const_eval
|
||||
DEPS_rustc_passes := syntax rustc core rustc_front
|
||||
DEPS_rustc_mir := rustc rustc_front syntax rustc_const_eval
|
||||
DEPS_rustc_metadata := rustc rustc_front syntax rbml rustc_const_math
|
||||
DEPS_rustc_passes := syntax rustc core rustc_front rustc_const_eval
|
||||
DEPS_rustc_mir := rustc rustc_front syntax rustc_const_math rustc_const_eval
|
||||
DEPS_rustc_resolve := arena rustc rustc_front log syntax
|
||||
DEPS_rustc_platform_intrinsics := std
|
||||
DEPS_rustc_plugin := rustc rustc_metadata syntax rustc_mir
|
||||
DEPS_rustc_privacy := rustc rustc_front log syntax
|
||||
DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back rustc_mir \
|
||||
log syntax serialize rustc_llvm rustc_front rustc_platform_intrinsics \
|
||||
rustc_const_eval
|
||||
rustc_const_math rustc_const_eval
|
||||
DEPS_rustc_save_analysis := rustc log syntax rustc_front
|
||||
DEPS_rustc_typeck := rustc syntax rustc_front rustc_platform_intrinsics rustc_const_eval
|
||||
DEPS_rustc_typeck := rustc syntax rustc_front rustc_platform_intrinsics rustc_const_math \
|
||||
rustc_const_eval
|
||||
|
||||
DEPS_rustdoc := rustc rustc_driver native:hoedown serialize getopts \
|
||||
test rustc_lint rustc_front
|
||||
test rustc_lint rustc_front rustc_const_eval
|
||||
|
||||
|
||||
TOOL_DEPS_compiletest := test getopts log
|
||||
|
@ -14,273 +14,6 @@
|
||||
// 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##"
|
||||
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:
|
||||
|
||||
```compile_fail
|
||||
match foo {
|
||||
Some(bar) => {/* ... */}
|
||||
None => {/* ... */}
|
||||
_ => {/* ... */} // 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##"
|
||||
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
|
||||
enum Empty {}
|
||||
|
||||
fn foo(x: Option<String>) {
|
||||
match x {
|
||||
// empty
|
||||
}
|
||||
}
|
||||
```
|
||||
"##,
|
||||
|
||||
E0003: r##"
|
||||
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
|
||||
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
|
||||
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:
|
||||
|
||||
```compile_fail
|
||||
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
|
||||
let x = Some("s".to_string());
|
||||
|
||||
match x {
|
||||
op_string @ Some(s) => {},
|
||||
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
|
||||
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 become unavailable in the body of the arm. Although this example seems
|
||||
innocuous, the problem is most clear when considering functions that take their
|
||||
argument by value.
|
||||
|
||||
```compile_fail
|
||||
match Some("hi".to_string()) {
|
||||
Some(s) if { drop(s); false } => (),
|
||||
Some(s) => {}, // use s.
|
||||
_ => {},
|
||||
}
|
||||
```
|
||||
|
||||
The value would be dropped in the guard then become unavailable not only in the
|
||||
body of that arm but also in all subsequent arms! The solution is to bind by
|
||||
reference when using guards or refactor the entire expression, perhaps by
|
||||
putting the condition inside the body of the arm.
|
||||
"##,
|
||||
|
||||
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
|
||||
struct X { x: (), }
|
||||
|
||||
let x = Some((X { x: () }, X { x: () }));
|
||||
match x {
|
||||
Some((y, ref z)) => {},
|
||||
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!()
|
||||
}
|
||||
```
|
||||
"##,
|
||||
|
||||
E0020: r##"
|
||||
This error indicates that an attempt was made to divide by zero (or take the
|
||||
remainder of a zero divisor) in a static or constant expression. Erroneous
|
||||
@ -762,128 +495,6 @@ attributes:
|
||||
See also https://doc.rust-lang.org/book/no-stdlib.html
|
||||
"##,
|
||||
|
||||
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
|
||||
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.
|
||||
foo(x);
|
||||
}
|
||||
```
|
||||
|
||||
Try this instead:
|
||||
|
||||
```ignore
|
||||
struct Irrefutable(i32);
|
||||
let irr = Irrefutable(0);
|
||||
|
||||
let Irrefutable(x) = irr;
|
||||
foo(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
|
||||
struct Irrefutable(i32);
|
||||
let irr = Irrefutable(0);
|
||||
|
||||
// This fails to compile because the match is irrefutable.
|
||||
while let Irrefutable(x) = irr {
|
||||
...
|
||||
}
|
||||
|
||||
Try this instead:
|
||||
|
||||
```
|
||||
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:
|
||||
|
||||
```ignore
|
||||
use Method::*;
|
||||
enum Method { GET, POST }
|
||||
```
|
||||
|
||||
If you want others to be able to import variants from your module directly, use
|
||||
`pub use`:
|
||||
|
||||
```ignore
|
||||
pub use Method::*;
|
||||
enum Method { GET, POST }
|
||||
```
|
||||
"##,
|
||||
|
||||
E0229: r##"
|
||||
An associated type binding was done outside of the type parameter declaration
|
||||
and `where` clause. Erroneous code example:
|
||||
@ -1573,135 +1184,6 @@ that the value provided is a positive integer between quotes, like so:
|
||||
```
|
||||
"##,
|
||||
|
||||
E0297: r##"
|
||||
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
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
||||
```ignore
|
||||
// Before.
|
||||
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
|
||||
"##,
|
||||
|
||||
E0306: r##"
|
||||
In an array literal `[x; N]`, `N` is the number of elements in the array. This
|
||||
must be an unsigned integer. Erroneous code example:
|
||||
|
||||
```compile_fail
|
||||
let x = [0i32; true]; // error: expected positive integer for repeat count,
|
||||
// found boolean
|
||||
```
|
||||
|
||||
Working example:
|
||||
|
||||
```
|
||||
let x = [0i32; 2];
|
||||
```
|
||||
"##,
|
||||
|
||||
E0307: r##"
|
||||
The length of an array is part of its type. For this reason, this length must
|
||||
be a compile-time constant. Erroneous code example:
|
||||
|
||||
```compile_fail
|
||||
let len = 10;
|
||||
let x = [0i32; len]; // error: expected constant integer for repeat count,
|
||||
// found variable
|
||||
```
|
||||
"##,
|
||||
|
||||
E0308: r##"
|
||||
This error occurs when the compiler was unable to infer the concrete type of a
|
||||
variable. It can occur for several cases, the most common of which is a
|
||||
@ -1991,8 +1473,6 @@ register_diagnostics! {
|
||||
E0280, // requirement is not satisfied
|
||||
E0284, // cannot resolve type
|
||||
// E0285, // overflow evaluation builtin bounds
|
||||
E0298, // mismatched types between arms
|
||||
E0299, // mismatched types between arms
|
||||
// E0300, // unexpanded macro
|
||||
// E0304, // expected signed integer constant
|
||||
// E0305, // expected constant
|
||||
@ -2003,7 +1483,6 @@ register_diagnostics! {
|
||||
E0315, // cannot invoke closure outside of its lifetime
|
||||
E0316, // nested quantification of lifetimes
|
||||
E0453, // overruled by outer forbid
|
||||
E0471, // constant evaluation error: ..
|
||||
E0473, // dereference of reference outside its lifetime
|
||||
E0474, // captured variable `..` does not outlive the enclosing closure
|
||||
E0475, // index of slice outside its lifetime
|
||||
|
@ -91,8 +91,7 @@ pub mod lint;
|
||||
pub mod middle {
|
||||
pub mod astconv_util;
|
||||
pub mod expr_use_visitor; // STAGE0: increase glitch immunity
|
||||
pub mod check_match;
|
||||
pub mod const_eval;
|
||||
pub mod const_val;
|
||||
pub mod const_qualif;
|
||||
pub mod cstore;
|
||||
pub mod dataflow;
|
||||
|
101
src/librustc/middle/const_val.rs
Normal file
101
src/librustc/middle/const_val.rs
Normal file
@ -0,0 +1,101 @@
|
||||
// Copyright 2012-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.
|
||||
|
||||
use syntax::parse::token::InternedString;
|
||||
use syntax::ast;
|
||||
use std::rc::Rc;
|
||||
use middle::def_id::DefId;
|
||||
use std::hash;
|
||||
use std::mem::transmute;
|
||||
use rustc_const_math::*;
|
||||
use self::ConstVal::*;
|
||||
|
||||
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub enum ConstVal {
|
||||
Float(f64),
|
||||
Integral(ConstInt),
|
||||
Str(InternedString),
|
||||
ByteStr(Rc<Vec<u8>>),
|
||||
Bool(bool),
|
||||
Struct(ast::NodeId),
|
||||
Tuple(ast::NodeId),
|
||||
Function(DefId),
|
||||
Array(ast::NodeId, u64),
|
||||
Repeat(ast::NodeId, u64),
|
||||
Char(char),
|
||||
/// A value that only occurs in case `eval_const_expr` reported an error. You should never
|
||||
/// handle this case. Its sole purpose is to allow more errors to be reported instead of
|
||||
/// causing a fatal error.
|
||||
Dummy,
|
||||
}
|
||||
|
||||
impl hash::Hash for ConstVal {
|
||||
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||
match *self {
|
||||
Float(a) => unsafe { transmute::<_,u64>(a) }.hash(state),
|
||||
Integral(a) => a.hash(state),
|
||||
Str(ref a) => a.hash(state),
|
||||
ByteStr(ref a) => a.hash(state),
|
||||
Bool(a) => a.hash(state),
|
||||
Struct(a) => a.hash(state),
|
||||
Tuple(a) => a.hash(state),
|
||||
Function(a) => a.hash(state),
|
||||
Array(a, n) => { a.hash(state); n.hash(state) },
|
||||
Repeat(a, n) => { a.hash(state); n.hash(state) },
|
||||
Char(c) => c.hash(state),
|
||||
Dummy => ().hash(state),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Note that equality for `ConstVal` means that the it is the same
|
||||
/// constant, not that the rust values are equal. In particular, `NaN
|
||||
/// == NaN` (at least if it's the same NaN; distinct encodings for NaN
|
||||
/// are considering unequal).
|
||||
impl PartialEq for ConstVal {
|
||||
fn eq(&self, other: &ConstVal) -> bool {
|
||||
match (self, other) {
|
||||
(&Float(a), &Float(b)) => unsafe{transmute::<_,u64>(a) == transmute::<_,u64>(b)},
|
||||
(&Integral(a), &Integral(b)) => a == b,
|
||||
(&Str(ref a), &Str(ref b)) => a == b,
|
||||
(&ByteStr(ref a), &ByteStr(ref b)) => a == b,
|
||||
(&Bool(a), &Bool(b)) => a == b,
|
||||
(&Struct(a), &Struct(b)) => a == b,
|
||||
(&Tuple(a), &Tuple(b)) => a == b,
|
||||
(&Function(a), &Function(b)) => a == b,
|
||||
(&Array(a, an), &Array(b, bn)) => (a == b) && (an == bn),
|
||||
(&Repeat(a, an), &Repeat(b, bn)) => (a == b) && (an == bn),
|
||||
(&Char(a), &Char(b)) => a == b,
|
||||
(&Dummy, &Dummy) => true, // FIXME: should this be false?
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for ConstVal { }
|
||||
|
||||
impl ConstVal {
|
||||
pub fn description(&self) -> &'static str {
|
||||
match *self {
|
||||
Float(_) => "float",
|
||||
Integral(i) => i.description(),
|
||||
Str(_) => "string literal",
|
||||
ByteStr(_) => "byte string literal",
|
||||
Bool(_) => "boolean",
|
||||
Struct(_) => "struct",
|
||||
Tuple(_) => "tuple",
|
||||
Function(_) => "function definition",
|
||||
Array(..) => "array",
|
||||
Repeat(..) => "repeat",
|
||||
Char(..) => "char",
|
||||
Dummy => "dummy value",
|
||||
}
|
||||
}
|
||||
}
|
@ -9,7 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
use graphviz::IntoCow;
|
||||
use middle::const_eval::ConstVal;
|
||||
use middle::const_val::ConstVal;
|
||||
use rustc_const_math::{ConstUsize, ConstInt};
|
||||
use middle::def_id::DefId;
|
||||
use ty::subst::Substs;
|
||||
@ -999,7 +999,7 @@ impl<'tcx> Debug for Literal<'tcx> {
|
||||
|
||||
/// Write a `ConstVal` in a way closer to the original source code than the `Debug` output.
|
||||
fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ConstVal) -> fmt::Result {
|
||||
use middle::const_eval::ConstVal::*;
|
||||
use middle::const_val::ConstVal::*;
|
||||
match *const_val {
|
||||
Float(f) => write!(fmt, "{:?}", f),
|
||||
Integral(n) => write!(fmt, "{}", n),
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use middle::const_eval::ConstVal;
|
||||
use middle::const_val::ConstVal;
|
||||
use middle::def_id::DefId;
|
||||
use ty::subst::Substs;
|
||||
use ty::{ClosureSubsts, FnOutput, Region, Ty};
|
||||
|
@ -11,8 +11,6 @@
|
||||
//! misc. type-system utilities too small to deserve their own file
|
||||
|
||||
use back::svh::Svh;
|
||||
use middle::const_eval::{self, ConstVal, ErrKind};
|
||||
use middle::const_eval::EvalHint::UncheckedExprHint;
|
||||
use middle::def_id::DefId;
|
||||
use ty::subst;
|
||||
use infer;
|
||||
@ -269,41 +267,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
(a, b)
|
||||
}
|
||||
|
||||
/// Returns the repeat count for a repeating vector expression.
|
||||
pub fn eval_repeat_count(&self, count_expr: &hir::Expr) -> usize {
|
||||
let hint = UncheckedExprHint(self.types.usize);
|
||||
match const_eval::eval_const_expr_partial(self, count_expr, hint, None) {
|
||||
Ok(ConstVal::Integral(ConstInt::Usize(count))) => {
|
||||
let val = count.as_u64(self.sess.target.uint_type);
|
||||
assert_eq!(val as usize as u64, val);
|
||||
val as usize
|
||||
},
|
||||
Ok(const_val) => {
|
||||
span_err!(self.sess, count_expr.span, E0306,
|
||||
"expected positive integer for repeat count, found {}",
|
||||
const_val.description());
|
||||
0
|
||||
}
|
||||
Err(err) => {
|
||||
let err_msg = match count_expr.node {
|
||||
hir::ExprPath(None, hir::Path {
|
||||
global: false,
|
||||
ref segments,
|
||||
..
|
||||
}) if segments.len() == 1 =>
|
||||
format!("found variable"),
|
||||
_ => match err.kind {
|
||||
ErrKind::MiscCatchAll => format!("but found {}", err.description()),
|
||||
_ => format!("but {}", err.description())
|
||||
}
|
||||
};
|
||||
span_err!(self.sess, count_expr.span, E0307,
|
||||
"expected constant integer for repeat count, {}", err_msg);
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Given a set of predicates that apply to an object type, returns
|
||||
/// the region bounds that the (erased) `Self` type must
|
||||
/// outlive. Precisely *because* the `Self` type is erased, the
|
||||
|
19
src/librustc_const_eval/Cargo.toml
Normal file
19
src/librustc_const_eval/Cargo.toml
Normal file
@ -0,0 +1,19 @@
|
||||
[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]
|
||||
log = { path = "../liblog" }
|
||||
serialize = { path = "../libserialize" }
|
||||
rustc = { path = "../librustc" }
|
||||
rustc_front = { path = "../librustc_front" }
|
||||
rustc_back = { path = "../librustc_back" }
|
||||
rustc_const_math = { path = "../librustc_const_math" }
|
||||
syntax = { path = "../libsyntax" }
|
||||
graphviz = { path = "../libgraphviz" }
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
@ -12,22 +12,22 @@ pub use self::Constructor::*;
|
||||
use self::Usefulness::*;
|
||||
use self::WitnessPreference::*;
|
||||
|
||||
use dep_graph::DepNode;
|
||||
use middle::const_eval::{compare_const_vals, ConstVal};
|
||||
use middle::const_eval::{eval_const_expr, eval_const_expr_partial};
|
||||
use middle::const_eval::{const_expr_to_pat, lookup_const_by_id};
|
||||
use middle::const_eval::EvalHint::ExprTypeChecked;
|
||||
use middle::def::*;
|
||||
use middle::def_id::{DefId};
|
||||
use middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor};
|
||||
use middle::expr_use_visitor::{LoanCause, MutateMode};
|
||||
use middle::expr_use_visitor as euv;
|
||||
use infer;
|
||||
use middle::mem_categorization::{cmt};
|
||||
use middle::pat_util::*;
|
||||
use traits::ProjectionMode;
|
||||
use ty::*;
|
||||
use ty;
|
||||
use rustc::dep_graph::DepNode;
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
use ::{eval_const_expr, eval_const_expr_partial, compare_const_vals};
|
||||
use ::{const_expr_to_pat, lookup_const_by_id};
|
||||
use ::EvalHint::ExprTypeChecked;
|
||||
use rustc::middle::def::*;
|
||||
use rustc::middle::def_id::{DefId};
|
||||
use rustc::middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor};
|
||||
use rustc::middle::expr_use_visitor::{LoanCause, MutateMode};
|
||||
use rustc::middle::expr_use_visitor as euv;
|
||||
use rustc::infer;
|
||||
use rustc::middle::mem_categorization::{cmt};
|
||||
use rustc::middle::pat_util::*;
|
||||
use rustc::traits::ProjectionMode;
|
||||
use rustc::ty::*;
|
||||
use rustc::ty;
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt;
|
||||
use std::iter::{FromIterator, IntoIterator, repeat};
|
||||
@ -44,7 +44,7 @@ use syntax::codemap::{Span, Spanned, DUMMY_SP};
|
||||
use rustc_front::fold::{Folder, noop_fold_pat};
|
||||
use rustc_front::print::pprust::pat_to_string;
|
||||
use syntax::ptr::P;
|
||||
use util::nodemap::FnvHashMap;
|
||||
use rustc::util::nodemap::FnvHashMap;
|
||||
|
||||
pub const DUMMY_WILD_PAT: &'static Pat = &Pat {
|
||||
id: DUMMY_NODE_ID,
|
||||
@ -546,7 +546,7 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor,
|
||||
ty::TyTuple(_) => PatKind::Tup(pats.collect()),
|
||||
|
||||
ty::TyEnum(adt, _) | ty::TyStruct(adt, _) => {
|
||||
let v = adt.variant_of_ctor(ctor);
|
||||
let v = ctor.variant_for_adt(adt);
|
||||
match v.kind() {
|
||||
VariantKind::Struct => {
|
||||
let field_pats: hir::HirVec<_> = v.fields.iter()
|
||||
@ -617,13 +617,13 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor,
|
||||
})
|
||||
}
|
||||
|
||||
impl<'tcx, 'container> ty::AdtDefData<'tcx, 'container> {
|
||||
fn variant_of_ctor(&self,
|
||||
ctor: &Constructor)
|
||||
-> &VariantDefData<'tcx, 'container> {
|
||||
match ctor {
|
||||
&Variant(vid) => self.variant_with_id(vid),
|
||||
_ => self.struct_variant()
|
||||
impl Constructor {
|
||||
fn variant_for_adt<'tcx, 'container, 'a>(&self,
|
||||
adt: &'a ty::AdtDefData<'tcx, 'container>)
|
||||
-> &'a VariantDefData<'tcx, 'container> {
|
||||
match self {
|
||||
&Variant(vid) => adt.variant_with_id(vid),
|
||||
_ => adt.struct_variant()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -843,7 +843,7 @@ pub fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> us
|
||||
_ => 1
|
||||
},
|
||||
ty::TyEnum(adt, _) | ty::TyStruct(adt, _) => {
|
||||
adt.variant_of_ctor(ctor).fields.len()
|
||||
ctor.variant_for_adt(adt).fields.len()
|
||||
}
|
||||
ty::TyArray(_, n) => n,
|
||||
_ => 0
|
||||
@ -924,7 +924,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
|
||||
PatKind::Struct(_, ref pattern_fields, _) => {
|
||||
let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def();
|
||||
let adt = cx.tcx.node_id_to_type(pat_id).ty_adt_def().unwrap();
|
||||
let variant = adt.variant_of_ctor(constructor);
|
||||
let variant = constructor.variant_for_adt(adt);
|
||||
let def_variant = adt.variant_of_def(def);
|
||||
if variant.did == def_variant.did {
|
||||
Some(variant.fields.iter().map(|sf| {
|
545
src/librustc_const_eval/diagnostics.rs
Normal file
545
src/librustc_const_eval/diagnostics.rs
Normal file
@ -0,0 +1,545 @@
|
||||
// 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##"
|
||||
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:
|
||||
|
||||
```compile_fail
|
||||
match foo {
|
||||
Some(bar) => {/* ... */}
|
||||
None => {/* ... */}
|
||||
_ => {/* ... */} // 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##"
|
||||
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
|
||||
enum Empty {}
|
||||
|
||||
fn foo(x: Option<String>) {
|
||||
match x {
|
||||
// empty
|
||||
}
|
||||
}
|
||||
```
|
||||
"##,
|
||||
|
||||
|
||||
E0003: r##"
|
||||
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
|
||||
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
|
||||
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:
|
||||
|
||||
```compile_fail
|
||||
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
|
||||
let x = Some("s".to_string());
|
||||
|
||||
match x {
|
||||
op_string @ Some(s) => {},
|
||||
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
|
||||
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 become unavailable in the body of the arm. Although this example seems
|
||||
innocuous, the problem is most clear when considering functions that take their
|
||||
argument by value.
|
||||
|
||||
```compile_fail
|
||||
match Some("hi".to_string()) {
|
||||
Some(s) if { drop(s); false } => (),
|
||||
Some(s) => {}, // use s.
|
||||
_ => {},
|
||||
}
|
||||
```
|
||||
|
||||
The value would be dropped in the guard then become unavailable not only in the
|
||||
body of that arm but also in all subsequent arms! The solution is to bind by
|
||||
reference when using guards or refactor the entire expression, perhaps by
|
||||
putting the condition inside the body of the arm.
|
||||
"##,
|
||||
|
||||
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
|
||||
struct X { x: (), }
|
||||
|
||||
let x = Some((X { x: () }, X { x: () }));
|
||||
match x {
|
||||
Some((y, ref z)) => {},
|
||||
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
|
||||
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.
|
||||
foo(x);
|
||||
}
|
||||
```
|
||||
|
||||
Try this instead:
|
||||
|
||||
```ignore
|
||||
struct Irrefutable(i32);
|
||||
let irr = Irrefutable(0);
|
||||
|
||||
let Irrefutable(x) = irr;
|
||||
foo(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
|
||||
struct Irrefutable(i32);
|
||||
let irr = Irrefutable(0);
|
||||
|
||||
// This fails to compile because the match is irrefutable.
|
||||
while let Irrefutable(x) = irr {
|
||||
...
|
||||
}
|
||||
|
||||
Try this instead:
|
||||
|
||||
```
|
||||
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:
|
||||
|
||||
```ignore
|
||||
use Method::*;
|
||||
enum Method { GET, POST }
|
||||
```
|
||||
|
||||
If you want others to be able to import variants from your module directly, use
|
||||
`pub use`:
|
||||
|
||||
```ignore
|
||||
pub use Method::*;
|
||||
enum Method { GET, POST }
|
||||
```
|
||||
"##,
|
||||
|
||||
|
||||
E0297: r##"
|
||||
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
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
||||
```ignore
|
||||
// Before.
|
||||
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
|
||||
"##,
|
||||
|
||||
E0306: r##"
|
||||
In an array literal `[x; N]`, `N` is the number of elements in the array. This
|
||||
must be an unsigned integer. Erroneous code example:
|
||||
|
||||
```compile_fail
|
||||
let x = [0i32; true]; // error: expected positive integer for repeat count,
|
||||
// found boolean
|
||||
```
|
||||
|
||||
Working example:
|
||||
|
||||
```
|
||||
let x = [0i32; 2];
|
||||
```
|
||||
"##,
|
||||
|
||||
E0307: r##"
|
||||
The length of an array is part of its type. For this reason, this length must
|
||||
be a compile-time constant. Erroneous code example:
|
||||
|
||||
```compile_fail
|
||||
let len = 10;
|
||||
let x = [0i32; len]; // error: expected constant integer for repeat count,
|
||||
// found variable
|
||||
```
|
||||
"##,
|
||||
|
||||
}
|
||||
|
||||
|
||||
register_diagnostics! {
|
||||
E0298, // mismatched types between arms
|
||||
E0299, // mismatched types between arms
|
||||
E0471, // constant evaluation error: ..
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
@ -10,23 +10,24 @@
|
||||
|
||||
//#![allow(non_camel_case_types)]
|
||||
|
||||
use self::ConstVal::*;
|
||||
use rustc::middle::const_val::ConstVal::*;
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
use self::ErrKind::*;
|
||||
use self::EvalHint::*;
|
||||
|
||||
use front::map as ast_map;
|
||||
use front::map::blocks::FnLikeNode;
|
||||
use lint;
|
||||
use middle::cstore::{self, CrateStore, InlinedItem};
|
||||
use {infer, traits};
|
||||
use middle::def::Def;
|
||||
use middle::def_id::DefId;
|
||||
use middle::pat_util::def_to_path;
|
||||
use ty::{self, subst, Ty, TyCtxt};
|
||||
use ty::util::IntTypeExt;
|
||||
use traits::ProjectionMode;
|
||||
use middle::astconv_util::ast_ty_to_prim_ty;
|
||||
use util::nodemap::NodeMap;
|
||||
use rustc::front::map as ast_map;
|
||||
use rustc::front::map::blocks::FnLikeNode;
|
||||
use rustc::middle::cstore::{self, CrateStore, InlinedItem};
|
||||
use rustc::{infer, traits};
|
||||
use rustc::middle::def::Def;
|
||||
use rustc::middle::def_id::DefId;
|
||||
use rustc::middle::pat_util::def_to_path;
|
||||
use rustc::ty::{self, Ty, TyCtxt, subst};
|
||||
use rustc::ty::util::IntTypeExt;
|
||||
use rustc::traits::ProjectionMode;
|
||||
use rustc::middle::astconv_util::ast_ty_to_prim_ty;
|
||||
use rustc::util::nodemap::NodeMap;
|
||||
use rustc::lint;
|
||||
|
||||
use graphviz::IntoCow;
|
||||
use syntax::ast;
|
||||
@ -34,7 +35,6 @@ use rustc_front::hir::{Expr, PatKind};
|
||||
use rustc_front::hir;
|
||||
use rustc_front::intravisit::FnKind;
|
||||
use syntax::codemap::Span;
|
||||
use syntax::parse::token::InternedString;
|
||||
use syntax::ptr::P;
|
||||
use syntax::codemap;
|
||||
use syntax::attr::IntType;
|
||||
@ -42,9 +42,6 @@ use syntax::attr::IntType;
|
||||
use std::borrow::Cow;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::hash_map::Entry::Vacant;
|
||||
use std::hash;
|
||||
use std::mem::transmute;
|
||||
use std::rc::Rc;
|
||||
|
||||
use rustc_const_math::*;
|
||||
|
||||
@ -241,89 +238,6 @@ pub fn lookup_const_fn_by_id<'tcx>(tcx: &TyCtxt<'tcx>, def_id: DefId)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub enum ConstVal {
|
||||
Float(f64),
|
||||
Integral(ConstInt),
|
||||
Str(InternedString),
|
||||
ByteStr(Rc<Vec<u8>>),
|
||||
Bool(bool),
|
||||
Struct(ast::NodeId),
|
||||
Tuple(ast::NodeId),
|
||||
Function(DefId),
|
||||
Array(ast::NodeId, u64),
|
||||
Repeat(ast::NodeId, u64),
|
||||
Char(char),
|
||||
/// A value that only occurs in case `eval_const_expr` reported an error. You should never
|
||||
/// handle this case. Its sole purpose is to allow more errors to be reported instead of
|
||||
/// causing a fatal error.
|
||||
Dummy,
|
||||
}
|
||||
|
||||
impl hash::Hash for ConstVal {
|
||||
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||
match *self {
|
||||
Float(a) => unsafe { transmute::<_,u64>(a) }.hash(state),
|
||||
Integral(a) => a.hash(state),
|
||||
Str(ref a) => a.hash(state),
|
||||
ByteStr(ref a) => a.hash(state),
|
||||
Bool(a) => a.hash(state),
|
||||
Struct(a) => a.hash(state),
|
||||
Tuple(a) => a.hash(state),
|
||||
Function(a) => a.hash(state),
|
||||
Array(a, n) => { a.hash(state); n.hash(state) },
|
||||
Repeat(a, n) => { a.hash(state); n.hash(state) },
|
||||
Char(c) => c.hash(state),
|
||||
Dummy => ().hash(state),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Note that equality for `ConstVal` means that the it is the same
|
||||
/// constant, not that the rust values are equal. In particular, `NaN
|
||||
/// == NaN` (at least if it's the same NaN; distinct encodings for NaN
|
||||
/// are considering unequal).
|
||||
impl PartialEq for ConstVal {
|
||||
fn eq(&self, other: &ConstVal) -> bool {
|
||||
match (self, other) {
|
||||
(&Float(a), &Float(b)) => unsafe{transmute::<_,u64>(a) == transmute::<_,u64>(b)},
|
||||
(&Integral(a), &Integral(b)) => a == b,
|
||||
(&Str(ref a), &Str(ref b)) => a == b,
|
||||
(&ByteStr(ref a), &ByteStr(ref b)) => a == b,
|
||||
(&Bool(a), &Bool(b)) => a == b,
|
||||
(&Struct(a), &Struct(b)) => a == b,
|
||||
(&Tuple(a), &Tuple(b)) => a == b,
|
||||
(&Function(a), &Function(b)) => a == b,
|
||||
(&Array(a, an), &Array(b, bn)) => (a == b) && (an == bn),
|
||||
(&Repeat(a, an), &Repeat(b, bn)) => (a == b) && (an == bn),
|
||||
(&Char(a), &Char(b)) => a == b,
|
||||
(&Dummy, &Dummy) => true, // FIXME: should this be false?
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for ConstVal { }
|
||||
|
||||
impl ConstVal {
|
||||
pub fn description(&self) -> &'static str {
|
||||
match *self {
|
||||
Float(_) => "float",
|
||||
Integral(i) => i.description(),
|
||||
Str(_) => "string literal",
|
||||
ByteStr(_) => "byte string literal",
|
||||
Bool(_) => "boolean",
|
||||
Struct(_) => "struct",
|
||||
Tuple(_) => "tuple",
|
||||
Function(_) => "function definition",
|
||||
Array(..) => "array",
|
||||
Repeat(..) => "repeat",
|
||||
Char(..) => "char",
|
||||
Dummy => "dummy value",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn const_expr_to_pat(tcx: &ty::TyCtxt, expr: &Expr, pat_id: ast::NodeId, span: Span)
|
||||
-> Result<P<hir::Pat>, DefId> {
|
||||
let pat_ty = tcx.expr_ty(expr);
|
||||
@ -352,7 +266,6 @@ pub fn const_expr_to_pat(tcx: &ty::TyCtxt, expr: &Expr, pat_id: ast::NodeId, spa
|
||||
}
|
||||
_ => { }
|
||||
}
|
||||
|
||||
let pat = match expr.node {
|
||||
hir::ExprTup(ref exprs) =>
|
||||
PatKind::Tup(try!(exprs.iter()
|
||||
@ -1275,3 +1188,39 @@ pub fn compare_lit_exprs<'tcx>(tcx: &TyCtxt<'tcx>,
|
||||
};
|
||||
compare_const_vals(&a, &b)
|
||||
}
|
||||
|
||||
|
||||
/// Returns the repeat count for a repeating vector expression.
|
||||
pub fn eval_repeat_count(tcx: &TyCtxt, count_expr: &hir::Expr) -> usize {
|
||||
let hint = UncheckedExprHint(tcx.types.usize);
|
||||
match eval_const_expr_partial(tcx, count_expr, hint, None) {
|
||||
Ok(Integral(Usize(count))) => {
|
||||
let val = count.as_u64(tcx.sess.target.uint_type);
|
||||
assert_eq!(val as usize as u64, val);
|
||||
val as usize
|
||||
},
|
||||
Ok(const_val) => {
|
||||
span_err!(tcx.sess, count_expr.span, E0306,
|
||||
"expected positive integer for repeat count, found {}",
|
||||
const_val.description());
|
||||
0
|
||||
}
|
||||
Err(err) => {
|
||||
let err_msg = match count_expr.node {
|
||||
hir::ExprPath(None, hir::Path {
|
||||
global: false,
|
||||
ref segments,
|
||||
..
|
||||
}) if segments.len() == 1 =>
|
||||
format!("found variable"),
|
||||
_ => match err.kind {
|
||||
MiscCatchAll => format!("but found {}", err.description()),
|
||||
_ => format!("but {}", err.description())
|
||||
}
|
||||
};
|
||||
span_err!(tcx.sess, count_expr.span, E0307,
|
||||
"expected constant integer for repeat count, {}", err_msg);
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
53
src/librustc_const_eval/lib.rs
Normal file
53
src/librustc_const_eval/lib.rs
Normal file
@ -0,0 +1,53 @@
|
||||
// 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
|
||||
//!
|
||||
//! # Note
|
||||
//!
|
||||
//! This API is completely unstable and subject to change.
|
||||
|
||||
#![crate_name = "rustc_const_eval"]
|
||||
#![unstable(feature = "rustc_private", issue = "27812")]
|
||||
#![crate_type = "dylib"]
|
||||
#![crate_type = "rlib"]
|
||||
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
|
||||
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
|
||||
html_root_url = "https://doc.rust-lang.org/nightly/")]
|
||||
|
||||
|
||||
#![feature(rustc_private)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(rustc_diagnostic_macros)]
|
||||
#![feature(slice_patterns)]
|
||||
#![feature(iter_arith)]
|
||||
#![feature(question_mark)]
|
||||
|
||||
#[macro_use] extern crate syntax;
|
||||
#[macro_use] extern crate log;
|
||||
extern crate rustc;
|
||||
extern crate rustc_front;
|
||||
extern crate rustc_back;
|
||||
extern crate rustc_const_math;
|
||||
extern crate graphviz;
|
||||
|
||||
extern crate serialize as rustc_serialize; // used by deriving
|
||||
|
||||
// NB: This module needs to be declared first so diagnostics are
|
||||
// registered before they are used.
|
||||
pub mod diagnostics;
|
||||
|
||||
mod eval;
|
||||
pub mod check_match;
|
||||
|
||||
pub use eval::*;
|
||||
|
||||
// Build the diagnostics array at the end so that the metadata includes error use sites.
|
||||
__build_diagnostic_array! { librustc_const_eval, DIAGNOSTICS }
|
@ -326,7 +326,7 @@ macro_rules! impl_binop {
|
||||
impl ::std::ops::$op for ConstInt {
|
||||
type Output = Result<Self, ConstMathErr>;
|
||||
fn $func(self, rhs: Self) -> Result<Self, ConstMathErr> {
|
||||
match try!(self.infer(rhs)) {
|
||||
match self.infer(rhs)? {
|
||||
(I8(a), I8(b)) => a.$checked_func(b).map(I8),
|
||||
(I16(a), I16(b)) => a.$checked_func(b).map(I16),
|
||||
(I32(a), I32(b)) => a.$checked_func(b).map(I32),
|
||||
@ -353,7 +353,7 @@ macro_rules! derive_binop {
|
||||
impl ::std::ops::$op for ConstInt {
|
||||
type Output = Result<Self, ConstMathErr>;
|
||||
fn $func(self, rhs: Self) -> Result<Self, ConstMathErr> {
|
||||
match try!(self.infer(rhs)) {
|
||||
match self.infer(rhs)? {
|
||||
(I8(a), I8(b)) => Ok(I8(a.$func(b))),
|
||||
(I16(a), I16(b)) => Ok(I16(a.$func(b))),
|
||||
(I32(a), I32(b)) => Ok(I32(a.$func(b))),
|
||||
|
@ -17,6 +17,7 @@ log = { path = "../liblog" }
|
||||
rustc = { path = "../librustc" }
|
||||
rustc_back = { path = "../librustc_back" }
|
||||
rustc_borrowck = { path = "../librustc_borrowck" }
|
||||
rustc_const_eval = { path = "../librustc_const_eval" }
|
||||
rustc_front = { path = "../librustc_front" }
|
||||
rustc_lint = { path = "../librustc_lint" }
|
||||
rustc_llvm = { path = "../librustc_llvm" }
|
||||
|
@ -38,6 +38,7 @@ use rustc_plugin as plugin;
|
||||
use rustc_front::hir;
|
||||
use rustc_front::lowering::{lower_crate, LoweringContext};
|
||||
use rustc_passes::{no_asm, loops, consts, const_fn, rvalues, static_recursion};
|
||||
use rustc_const_eval::check_match;
|
||||
use super::Compilation;
|
||||
|
||||
use serialize::json;
|
||||
@ -851,7 +852,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
||||
|
||||
time(time_passes,
|
||||
"match checking",
|
||||
|| middle::check_match::check_crate(tcx));
|
||||
|| check_match::check_crate(tcx));
|
||||
|
||||
// this must run before MIR dump, because
|
||||
// "not all control paths return a value" is reported here.
|
||||
|
@ -40,6 +40,7 @@ extern crate libc;
|
||||
extern crate rustc;
|
||||
extern crate rustc_back;
|
||||
extern crate rustc_borrowck;
|
||||
extern crate rustc_const_eval;
|
||||
extern crate rustc_passes;
|
||||
extern crate rustc_front;
|
||||
extern crate rustc_lint;
|
||||
@ -1090,6 +1091,7 @@ pub fn diagnostics_registry() -> diagnostics::registry::Registry {
|
||||
all_errors.extend_from_slice(&rustc_resolve::DIAGNOSTICS);
|
||||
all_errors.extend_from_slice(&rustc_privacy::DIAGNOSTICS);
|
||||
all_errors.extend_from_slice(&rustc_trans::DIAGNOSTICS);
|
||||
all_errors.extend_from_slice(&rustc_const_eval::DIAGNOSTICS);
|
||||
|
||||
Registry::new(&all_errors)
|
||||
}
|
||||
|
@ -12,5 +12,6 @@ crate-type = ["dylib"]
|
||||
log = { path = "../liblog" }
|
||||
rustc = { path = "../librustc" }
|
||||
rustc_back = { path = "../librustc_back" }
|
||||
rustc_const_eval = { path = "../librustc_const_eval" }
|
||||
rustc_front = { path = "../librustc_front" }
|
||||
syntax = { path = "../libsyntax" }
|
||||
|
@ -46,6 +46,7 @@ extern crate rustc;
|
||||
extern crate log;
|
||||
extern crate rustc_front;
|
||||
extern crate rustc_back;
|
||||
extern crate rustc_const_eval;
|
||||
|
||||
pub use rustc::lint as lint;
|
||||
pub use rustc::middle as middle;
|
||||
|
@ -14,8 +14,9 @@ use middle::def_id::DefId;
|
||||
use rustc::infer;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use middle::const_eval::{eval_const_expr_partial, ConstVal};
|
||||
use middle::const_eval::EvalHint::ExprTypeChecked;
|
||||
use middle::const_val::ConstVal;
|
||||
use rustc_const_eval::eval_const_expr_partial;
|
||||
use rustc_const_eval::EvalHint::ExprTypeChecked;
|
||||
use util::nodemap::{FnvHashSet};
|
||||
use lint::{LateContext, LintContext, LintArray};
|
||||
use lint::{LintPass, LateLintPass};
|
||||
|
@ -13,6 +13,7 @@ graphviz = { path = "../libgraphviz" }
|
||||
log = { path = "../liblog" }
|
||||
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_front = { path = "../librustc_front" }
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
use build::{BlockAnd, BlockAndExtension, Builder};
|
||||
use rustc_data_structures::fnv::FnvHashMap;
|
||||
use rustc::middle::const_eval::ConstVal;
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
use rustc::ty::{AdtDef, Ty};
|
||||
use rustc::mir::repr::*;
|
||||
use hair::*;
|
||||
|
@ -19,7 +19,7 @@ use build::Builder;
|
||||
use build::matches::{Candidate, MatchPair, Test, TestKind};
|
||||
use hair::*;
|
||||
use rustc_data_structures::fnv::FnvHashMap;
|
||||
use rustc::middle::const_eval::ConstVal;
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc::mir::repr::*;
|
||||
use syntax::codemap::Span;
|
||||
|
@ -94,7 +94,7 @@ use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::mir::repr::*;
|
||||
use syntax::codemap::{Span, DUMMY_SP};
|
||||
use syntax::parse::token::intern_and_get_ident;
|
||||
use rustc::middle::const_eval::ConstVal;
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
use rustc_const_math::ConstInt;
|
||||
|
||||
pub struct Scope<'tcx> {
|
||||
|
@ -16,7 +16,8 @@ use hair::cx::block;
|
||||
use hair::cx::to_ref::ToRef;
|
||||
use rustc::front::map;
|
||||
use rustc::middle::def::Def;
|
||||
use rustc::middle::const_eval::{self, ConstVal};
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
use rustc_const_eval as const_eval;
|
||||
use rustc::middle::region::CodeExtent;
|
||||
use rustc::middle::pat_util;
|
||||
use rustc::ty::{self, VariantDef, Ty};
|
||||
|
@ -18,7 +18,8 @@
|
||||
use hair::*;
|
||||
use rustc::mir::repr::*;
|
||||
|
||||
use rustc::middle::const_eval::{self, ConstVal};
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
use rustc_const_eval as const_eval;
|
||||
use rustc::middle::def_id::DefId;
|
||||
use rustc::infer::InferCtxt;
|
||||
use rustc::ty::subst::{Subst, Substs};
|
||||
|
@ -11,7 +11,7 @@
|
||||
use hair::*;
|
||||
use hair::cx::Cx;
|
||||
use rustc_data_structures::fnv::FnvHashMap;
|
||||
use rustc::middle::const_eval;
|
||||
use rustc_const_eval as const_eval;
|
||||
use rustc::middle::def::Def;
|
||||
use rustc::middle::pat_util::{pat_is_resolved_const, pat_is_binding};
|
||||
use rustc::ty::{self, Ty};
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
use rustc::mir::repr::{BinOp, BorrowKind, Field, Literal, Mutability, UnOp,
|
||||
TypedConstVal};
|
||||
use rustc::middle::const_eval::ConstVal;
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
use rustc::middle::def_id::DefId;
|
||||
use rustc::middle::region::CodeExtent;
|
||||
use rustc::ty::subst::Substs;
|
||||
|
@ -33,6 +33,7 @@ extern crate rustc_front;
|
||||
extern crate rustc_back;
|
||||
extern crate syntax;
|
||||
extern crate rustc_const_math;
|
||||
extern crate rustc_const_eval;
|
||||
|
||||
pub mod build;
|
||||
pub mod graphviz;
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use rustc::middle::const_eval::ConstVal;
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc::mir::repr::*;
|
||||
use rustc::mir::transform::{MirPass, Pass};
|
||||
|
@ -11,5 +11,6 @@ crate-type = ["dylib"]
|
||||
[dependencies]
|
||||
log = { path = "../liblog" }
|
||||
rustc = { path = "../librustc" }
|
||||
rustc_const_eval = { path = "../librustc_const_eval" }
|
||||
rustc_front = { path = "../librustc_front" }
|
||||
syntax = { path = "../libsyntax" }
|
||||
|
@ -26,9 +26,10 @@
|
||||
|
||||
use rustc::dep_graph::DepNode;
|
||||
use rustc::ty::cast::{CastKind};
|
||||
use rustc::middle::const_eval::{self, ConstEvalErr};
|
||||
use rustc::middle::const_eval::ErrKind::IndexOpFeatureGated;
|
||||
use rustc::middle::const_eval::EvalHint::ExprTypeChecked;
|
||||
use rustc_const_eval::{ConstEvalErr, lookup_const_fn_by_id, compare_lit_exprs};
|
||||
use rustc_const_eval::{eval_const_expr_partial, lookup_const_by_id};
|
||||
use rustc_const_eval::ErrKind::IndexOpFeatureGated;
|
||||
use rustc_const_eval::EvalHint::ExprTypeChecked;
|
||||
use rustc::middle::def::Def;
|
||||
use rustc::middle::def_id::DefId;
|
||||
use rustc::middle::expr_use_visitor as euv;
|
||||
@ -169,7 +170,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
|
||||
def_id: DefId,
|
||||
ret_ty: Ty<'tcx>)
|
||||
-> bool {
|
||||
if let Some(fn_like) = const_eval::lookup_const_fn_by_id(self.tcx, def_id) {
|
||||
if let Some(fn_like) = lookup_const_fn_by_id(self.tcx, def_id) {
|
||||
if
|
||||
// we are in a static/const initializer
|
||||
self.mode != Mode::Var &&
|
||||
@ -335,7 +336,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
|
||||
self.global_expr(Mode::Const, &start);
|
||||
self.global_expr(Mode::Const, &end);
|
||||
|
||||
match const_eval::compare_lit_exprs(self.tcx, start, end) {
|
||||
match compare_lit_exprs(self.tcx, start, end) {
|
||||
Some(Ordering::Less) |
|
||||
Some(Ordering::Equal) => {}
|
||||
Some(Ordering::Greater) => {
|
||||
@ -431,7 +432,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
|
||||
match node_ty.sty {
|
||||
ty::TyUint(_) | ty::TyInt(_) if div_or_rem => {
|
||||
if !self.qualif.intersects(ConstQualif::NOT_CONST) {
|
||||
match const_eval::eval_const_expr_partial(
|
||||
match eval_const_expr_partial(
|
||||
self.tcx, ex, ExprTypeChecked, None) {
|
||||
Ok(_) => {}
|
||||
Err(ConstEvalErr { kind: IndexOpFeatureGated, ..}) => {},
|
||||
@ -611,7 +612,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
|
||||
Some(Def::Const(did)) |
|
||||
Some(Def::AssociatedConst(did)) => {
|
||||
let substs = Some(v.tcx.node_id_item_substs(e.id).substs);
|
||||
if let Some((expr, _)) = const_eval::lookup_const_by_id(v.tcx, did, substs) {
|
||||
if let Some((expr, _)) = lookup_const_by_id(v.tcx, did, substs) {
|
||||
let inner = v.global_expr(Mode::Const, expr);
|
||||
v.add_qualif(inner);
|
||||
}
|
||||
|
@ -30,6 +30,7 @@
|
||||
extern crate core;
|
||||
extern crate rustc;
|
||||
extern crate rustc_front;
|
||||
extern crate rustc_const_eval;
|
||||
|
||||
#[macro_use] extern crate log;
|
||||
#[macro_use] extern crate syntax;
|
||||
|
@ -16,6 +16,7 @@ graphviz = { path = "../libgraphviz" }
|
||||
log = { path = "../liblog" }
|
||||
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_front = { path = "../librustc_front" }
|
||||
|
@ -189,9 +189,8 @@ use self::Opt::*;
|
||||
use self::FailureHandler::*;
|
||||
|
||||
use llvm::{ValueRef, BasicBlockRef};
|
||||
use middle::check_match::StaticInliner;
|
||||
use middle::check_match;
|
||||
use middle::const_eval;
|
||||
use rustc_const_eval::check_match::{self, StaticInliner};
|
||||
use rustc_const_eval::{compare_lit_exprs, eval_const_expr};
|
||||
use middle::def::{Def, DefMap};
|
||||
use middle::def_id::DefId;
|
||||
use middle::expr_use_visitor as euv;
|
||||
@ -241,7 +240,7 @@ struct ConstantExpr<'a>(&'a hir::Expr);
|
||||
|
||||
impl<'a> ConstantExpr<'a> {
|
||||
fn eq(self, other: ConstantExpr<'a>, tcx: &TyCtxt) -> bool {
|
||||
match const_eval::compare_lit_exprs(tcx, self.0, other.0) {
|
||||
match compare_lit_exprs(tcx, self.0, other.0) {
|
||||
Some(result) => result == Ordering::Equal,
|
||||
None => panic!("compare_list_exprs: type mismatch"),
|
||||
}
|
||||
@ -611,11 +610,11 @@ fn enter_opt<'a, 'p, 'blk, 'tcx>(
|
||||
|
||||
let ctor = match opt {
|
||||
&ConstantValue(ConstantExpr(expr), _) => check_match::ConstantValue(
|
||||
const_eval::eval_const_expr(bcx.tcx(), &expr)
|
||||
eval_const_expr(bcx.tcx(), &expr)
|
||||
),
|
||||
&ConstantRange(ConstantExpr(lo), ConstantExpr(hi), _) => check_match::ConstantRange(
|
||||
const_eval::eval_const_expr(bcx.tcx(), &lo),
|
||||
const_eval::eval_const_expr(bcx.tcx(), &hi)
|
||||
eval_const_expr(bcx.tcx(), &lo),
|
||||
eval_const_expr(bcx.tcx(), &hi)
|
||||
),
|
||||
&SliceLengthEqual(n, _) =>
|
||||
check_match::Slice(n),
|
||||
|
@ -13,7 +13,8 @@ use llvm;
|
||||
use llvm::{ConstFCmp, ConstICmp, SetLinkage, SetUnnamedAddr};
|
||||
use llvm::{InternalLinkage, ValueRef, Bool, True};
|
||||
use middle::const_qualif::ConstQualif;
|
||||
use middle::const_eval::{self, ConstEvalErr};
|
||||
use rustc_const_eval::{ConstEvalErr, lookup_const_fn_by_id, lookup_const_by_id, ErrKind};
|
||||
use rustc_const_eval::eval_repeat_count;
|
||||
use middle::def::Def;
|
||||
use middle::def_id::DefId;
|
||||
use rustc::front::map as hir_map;
|
||||
@ -197,7 +198,7 @@ fn const_fn_call<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
arg_vals: &[ValueRef],
|
||||
param_substs: &'tcx Substs<'tcx>,
|
||||
trueconst: TrueConst) -> Result<ValueRef, ConstEvalFailure> {
|
||||
let fn_like = const_eval::lookup_const_fn_by_id(ccx.tcx(), def_id);
|
||||
let fn_like = lookup_const_fn_by_id(ccx.tcx(), def_id);
|
||||
let fn_like = fn_like.expect("lookup_const_fn_by_id failed in const_fn_call");
|
||||
|
||||
let body = match fn_like.body().expr {
|
||||
@ -228,7 +229,7 @@ pub fn get_const_expr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
let substs = monomorphize::apply_param_substs(ccx.tcx(),
|
||||
param_substs,
|
||||
&substs.erase_regions());
|
||||
match const_eval::lookup_const_by_id(ccx.tcx(), def_id, Some(substs)) {
|
||||
match lookup_const_by_id(ccx.tcx(), def_id, Some(substs)) {
|
||||
Some((ref expr, _ty)) => expr,
|
||||
None => {
|
||||
ccx.sess().span_bug(ref_expr.span, "constant item not found")
|
||||
@ -534,12 +535,12 @@ fn const_err(cx: &CrateContext,
|
||||
Ok(())
|
||||
},
|
||||
(Err(err), TrueConst::Yes) => {
|
||||
let err = ConstEvalErr{ span: e.span, kind: const_eval::ErrKind::Math(err) };
|
||||
let err = ConstEvalErr{ span: e.span, kind: ErrKind::Math(err) };
|
||||
cx.tcx().sess.span_err(e.span, &err.description());
|
||||
Err(Compiletime(err))
|
||||
},
|
||||
(Err(err), TrueConst::No) => {
|
||||
let err = ConstEvalErr{ span: e.span, kind: const_eval::ErrKind::Math(err) };
|
||||
let err = ConstEvalErr{ span: e.span, kind: ErrKind::Math(err) };
|
||||
cx.tcx().sess.span_warn(e.span, &err.description());
|
||||
Err(Runtime(err))
|
||||
},
|
||||
@ -883,7 +884,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
hir::ExprRepeat(ref elem, ref count) => {
|
||||
let unit_ty = ety.sequence_element_type(cx.tcx());
|
||||
let llunitty = type_of::type_of(cx, unit_ty);
|
||||
let n = cx.tcx().eval_repeat_count(count);
|
||||
let n = eval_repeat_count(cx.tcx(), count);
|
||||
let unit_val = const_expr(cx, &elem, param_substs, fn_args, trueconst)?.0;
|
||||
let vs = vec![unit_val; n];
|
||||
if val_ty(unit_val) != llunitty {
|
||||
|
@ -52,6 +52,7 @@ extern crate rustc_mir;
|
||||
extern crate rustc_platform_intrinsics as intrinsics;
|
||||
extern crate serialize;
|
||||
extern crate rustc_const_math;
|
||||
extern crate rustc_const_eval;
|
||||
|
||||
#[macro_use] extern crate log;
|
||||
#[macro_use] extern crate syntax;
|
||||
|
@ -10,8 +10,9 @@
|
||||
|
||||
use llvm::ValueRef;
|
||||
use rustc::ty::{Ty, TypeFoldable};
|
||||
use rustc::middle::const_eval::{self, ConstVal};
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
use rustc_const_math::ConstInt::*;
|
||||
use rustc_const_eval::lookup_const_by_id;
|
||||
use rustc::mir::repr as mir;
|
||||
use abi;
|
||||
use common::{self, BlockAndBuilder, C_bool, C_bytes, C_floating_f64, C_integral,
|
||||
@ -114,7 +115,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
}
|
||||
|
||||
let substs = Some(bcx.monomorphize(substs));
|
||||
let expr = const_eval::lookup_const_by_id(bcx.tcx(), def_id, substs)
|
||||
let expr = lookup_const_by_id(bcx.tcx(), def_id, substs)
|
||||
.expect("def was const, but lookup_const_by_id failed").0;
|
||||
// FIXME: this is falling back to translating from HIR. This is not easy to fix,
|
||||
// because we would have somehow adapt const_eval to work on MIR rather than HIR.
|
||||
|
@ -11,7 +11,7 @@
|
||||
use llvm::ValueRef;
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc::ty::cast::{CastTy, IntTy};
|
||||
use middle::const_eval::ConstVal;
|
||||
use middle::const_val::ConstVal;
|
||||
use rustc_const_math::ConstInt;
|
||||
use rustc::mir::repr as mir;
|
||||
|
||||
|
@ -30,6 +30,7 @@ use value::Value;
|
||||
use rustc::ty::{self, Ty};
|
||||
|
||||
use rustc_front::hir;
|
||||
use rustc_const_eval::eval_repeat_count;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::parse::token::InternedString;
|
||||
@ -218,7 +219,7 @@ fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
return expr::trans_into(bcx, &element, Ignore);
|
||||
}
|
||||
SaveIn(lldest) => {
|
||||
match bcx.tcx().eval_repeat_count(&count_expr) {
|
||||
match eval_repeat_count(bcx.tcx(), &count_expr) {
|
||||
0 => expr::trans_into(bcx, &element, Ignore),
|
||||
1 => expr::trans_into(bcx, &element, SaveIn(lldest)),
|
||||
count => {
|
||||
@ -270,7 +271,7 @@ fn elements_required(bcx: Block, content_expr: &hir::Expr) -> usize {
|
||||
},
|
||||
hir::ExprVec(ref es) => es.len(),
|
||||
hir::ExprRepeat(_, ref count_expr) => {
|
||||
bcx.tcx().eval_repeat_count(&count_expr)
|
||||
eval_repeat_count(bcx.tcx(), &count_expr)
|
||||
}
|
||||
_ => bcx.tcx().sess.span_bug(content_expr.span,
|
||||
"unexpected vec content")
|
||||
|
@ -15,6 +15,7 @@ arena = { path = "../libarena" }
|
||||
fmt_macros = { path = "../libfmt_macros" }
|
||||
rustc = { path = "../librustc" }
|
||||
rustc_back = { path = "../librustc_back" }
|
||||
rustc_const_eval = { path = "../librustc_const_eval" }
|
||||
rustc_const_math = { path = "../librustc_const_math" }
|
||||
rustc_front = { path = "../librustc_front" }
|
||||
rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" }
|
||||
|
@ -49,8 +49,9 @@
|
||||
//! an rptr (`&r.T`) use the region `r` that appears in the rptr.
|
||||
|
||||
use middle::astconv_util::{prim_ty_to_ty, prohibit_type_params, prohibit_projection};
|
||||
use middle::const_eval::{self, ConstVal};
|
||||
use middle::const_eval::EvalHint::UncheckedExprHint;
|
||||
use middle::const_val::ConstVal;
|
||||
use rustc_const_eval::eval_const_expr_partial;
|
||||
use rustc_const_eval::EvalHint::UncheckedExprHint;
|
||||
use middle::def::{self, Def};
|
||||
use middle::def_id::DefId;
|
||||
use middle::resolve_lifetime as rl;
|
||||
@ -1681,7 +1682,7 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
|
||||
}
|
||||
hir::TyFixedLengthVec(ref ty, ref e) => {
|
||||
let hint = UncheckedExprHint(tcx.types.usize);
|
||||
match const_eval::eval_const_expr_partial(tcx, &e, hint, None) {
|
||||
match eval_const_expr_partial(tcx, &e, hint, None) {
|
||||
Ok(ConstVal::Integral(ConstInt::Usize(i))) => {
|
||||
let i = i.as_u64(tcx.sess.target.uint_type);
|
||||
assert_eq!(i as usize as u64, i);
|
||||
|
@ -130,6 +130,7 @@ use rustc_front::hir;
|
||||
use rustc_front::hir::{Visibility, PatKind};
|
||||
use rustc_front::print::pprust;
|
||||
use rustc_back::slice;
|
||||
use rustc_const_eval::eval_repeat_count;
|
||||
|
||||
mod assoc;
|
||||
pub mod dropck;
|
||||
@ -3592,7 +3593,7 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
}
|
||||
hir::ExprRepeat(ref element, ref count_expr) => {
|
||||
check_expr_has_type(fcx, &count_expr, tcx.types.usize);
|
||||
let count = fcx.tcx().eval_repeat_count(&count_expr);
|
||||
let count = eval_repeat_count(fcx.tcx(), &count_expr);
|
||||
|
||||
let uty = match expected {
|
||||
ExpectHasType(uty) => {
|
||||
|
@ -66,8 +66,9 @@ use constrained_type_params as ctp;
|
||||
use coherence;
|
||||
use middle::lang_items::SizedTraitLangItem;
|
||||
use middle::resolve_lifetime;
|
||||
use middle::const_eval::{self, ConstVal};
|
||||
use middle::const_eval::EvalHint::UncheckedExprHint;
|
||||
use middle::const_val::ConstVal;
|
||||
use rustc_const_eval::EvalHint::UncheckedExprHint;
|
||||
use rustc_const_eval::eval_const_expr_partial;
|
||||
use rustc::ty::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace, VecPerParamSpace};
|
||||
use rustc::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
|
||||
use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeScheme};
|
||||
@ -1045,7 +1046,7 @@ fn convert_enum_def<'tcx>(tcx: &TyCtxt<'tcx>,
|
||||
|
||||
let ty_hint = repr_ty.to_ty(tcx);
|
||||
let hint = UncheckedExprHint(ty_hint);
|
||||
match const_eval::eval_const_expr_partial(tcx, e, hint, None) {
|
||||
match eval_const_expr_partial(tcx, e, hint, None) {
|
||||
Ok(ConstVal::Integral(i)) => {
|
||||
// FIXME: eval_const_expr_partial should return an error if the hint is wrong
|
||||
match (repr_ty, i) {
|
||||
|
@ -93,6 +93,7 @@ extern crate rustc_platform_intrinsics as intrinsics;
|
||||
extern crate rustc_front;
|
||||
extern crate rustc_back;
|
||||
extern crate rustc_const_math;
|
||||
extern crate rustc_const_eval;
|
||||
|
||||
pub use rustc::dep_graph;
|
||||
pub use rustc::front;
|
||||
|
@ -14,6 +14,7 @@ arena = { path = "../libarena" }
|
||||
getopts = { path = "../libgetopts" }
|
||||
rustc = { path = "../librustc" }
|
||||
rustc_back = { path = "../librustc_back" }
|
||||
rustc_const_eval = { path = "../librustc_const_eval" }
|
||||
rustc_driver = { path = "../librustc_driver" }
|
||||
rustc_front = { path = "../librustc_front" }
|
||||
rustc_lint = { path = "../librustc_lint" }
|
||||
|
@ -22,7 +22,8 @@ use rustc::middle::def_id::DefId;
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc::ty::subst;
|
||||
use rustc::middle::stability;
|
||||
use rustc::middle::const_eval;
|
||||
|
||||
use rustc_const_eval::lookup_const_by_id;
|
||||
|
||||
use core::DocContext;
|
||||
use doctree;
|
||||
@ -336,7 +337,7 @@ pub fn build_impl(cx: &DocContext,
|
||||
let did = assoc_const.def_id;
|
||||
let type_scheme = tcx.lookup_item_type(did);
|
||||
let default = if assoc_const.has_value {
|
||||
Some(const_eval::lookup_const_by_id(tcx, did, None)
|
||||
Some(lookup_const_by_id(tcx, did, None)
|
||||
.unwrap().0.span.to_src(cx))
|
||||
} else {
|
||||
None
|
||||
@ -483,10 +484,9 @@ fn build_module(cx: &DocContext, tcx: &TyCtxt,
|
||||
|
||||
fn build_const(cx: &DocContext, tcx: &TyCtxt,
|
||||
did: DefId) -> clean::Constant {
|
||||
use rustc::middle::const_eval;
|
||||
use rustc_front::print::pprust;
|
||||
|
||||
let (expr, ty) = const_eval::lookup_const_by_id(tcx, did, None).unwrap_or_else(|| {
|
||||
let (expr, ty) = lookup_const_by_id(tcx, did, None).unwrap_or_else(|| {
|
||||
panic!("expected lookup_const_by_id to succeed for {:?}", did);
|
||||
});
|
||||
debug!("converting constant expr {:?} to snippet", expr);
|
||||
|
@ -35,6 +35,7 @@ extern crate arena;
|
||||
extern crate getopts;
|
||||
extern crate libc;
|
||||
extern crate rustc;
|
||||
extern crate rustc_const_eval;
|
||||
extern crate rustc_trans;
|
||||
extern crate rustc_driver;
|
||||
extern crate rustc_resolve;
|
||||
|
@ -23,7 +23,7 @@ use rustc::mir::transform::{self, MirPass};
|
||||
use rustc::mir::repr::{Mir, Literal};
|
||||
use rustc::mir::visit::MutVisitor;
|
||||
use rustc::ty;
|
||||
use rustc::middle::const_eval::ConstVal;
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
use rustc_const_math::ConstInt;
|
||||
use rustc_plugin::Registry;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user