mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 08:44:35 +00:00
Auto merge of #32628 - Manishearth:rollup, r=Manishearth
Rollup of 4 pull requests - Successful merges: #32259, #32494, #32612, #32618 - Failed merges: #32562
This commit is contained in:
commit
30a3849f22
25
mk/crates.mk
25
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
|
||||
@ -92,36 +92,39 @@ DEPS_test := std getopts term native:rust_test_helpers
|
||||
DEPS_syntax := std term serialize log arena libc rustc_bitflags rustc_unicode
|
||||
DEPS_syntax_ext := syntax fmt_macros
|
||||
|
||||
DEPS_rustc_const_eval := std syntax
|
||||
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
|
||||
|
@ -131,7 +131,7 @@ declarations.
|
||||
## Trait objects with associated types
|
||||
|
||||
There’s one more bit of syntax we should talk about: trait objects. If you
|
||||
try to create a trait object from an associated type, like this:
|
||||
try to create a trait object from a trait with an associated type, like this:
|
||||
|
||||
```rust,ignore
|
||||
# trait Graph {
|
||||
|
@ -18,7 +18,7 @@ log = { path = "../liblog" }
|
||||
rbml = { path = "../librbml" }
|
||||
rustc_back = { path = "../librustc_back" }
|
||||
rustc_bitflags = { path = "../librustc_bitflags" }
|
||||
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" }
|
||||
serialize = { path = "../libserialize" }
|
||||
|
@ -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
|
||||
|
@ -55,7 +55,7 @@ extern crate rustc_front;
|
||||
extern crate rustc_data_structures;
|
||||
extern crate serialize;
|
||||
extern crate collections;
|
||||
extern crate rustc_const_eval;
|
||||
extern crate rustc_const_math;
|
||||
#[macro_use] extern crate log;
|
||||
#[macro_use] extern crate syntax;
|
||||
#[macro_use] #[no_link] extern crate rustc_bitflags;
|
||||
@ -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,8 +9,8 @@
|
||||
// except according to those terms.
|
||||
|
||||
use graphviz::IntoCow;
|
||||
use middle::const_eval::ConstVal;
|
||||
use rustc_const_eval::{ConstUsize, ConstInt};
|
||||
use middle::const_val::ConstVal;
|
||||
use rustc_const_math::{ConstUsize, ConstInt};
|
||||
use middle::def_id::DefId;
|
||||
use ty::subst::Substs;
|
||||
use ty::{self, AdtDef, ClosureSubsts, FnOutput, Region, Ty};
|
||||
@ -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,12 +8,12 @@
|
||||
// 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};
|
||||
use mir::repr::*;
|
||||
use rustc_const_eval::ConstUsize;
|
||||
use rustc_const_math::ConstUsize;
|
||||
use rustc_data_structures::tuple_slice::TupleSlice;
|
||||
use syntax::codemap::Span;
|
||||
|
||||
|
@ -136,6 +136,7 @@ pub struct Options {
|
||||
pub no_trans: bool,
|
||||
pub error_format: ErrorOutputType,
|
||||
pub treat_err_as_bug: bool,
|
||||
pub continue_parse_after_error: bool,
|
||||
pub mir_opt_level: usize,
|
||||
|
||||
/// if true, build up the dep-graph
|
||||
@ -257,6 +258,7 @@ pub fn basic_options() -> Options {
|
||||
parse_only: false,
|
||||
no_trans: false,
|
||||
treat_err_as_bug: false,
|
||||
continue_parse_after_error: false,
|
||||
mir_opt_level: 1,
|
||||
build_dep_graph: false,
|
||||
dump_dep_graph: false,
|
||||
@ -631,6 +633,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
||||
"run all passes except translation; no output"),
|
||||
treat_err_as_bug: bool = (false, parse_bool,
|
||||
"treat all errors that occur as bugs"),
|
||||
continue_parse_after_error: bool = (false, parse_bool,
|
||||
"attempt to recover from parse errors (experimental)"),
|
||||
incr_comp: bool = (false, parse_bool,
|
||||
"enable incremental compilation (experimental)"),
|
||||
dump_dep_graph: bool = (false, parse_bool,
|
||||
@ -1045,6 +1049,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
|
||||
let parse_only = debugging_opts.parse_only;
|
||||
let no_trans = debugging_opts.no_trans;
|
||||
let treat_err_as_bug = debugging_opts.treat_err_as_bug;
|
||||
let continue_parse_after_error = debugging_opts.continue_parse_after_error;
|
||||
let mir_opt_level = debugging_opts.mir_opt_level.unwrap_or(1);
|
||||
let incremental_compilation = debugging_opts.incr_comp;
|
||||
let dump_dep_graph = debugging_opts.dump_dep_graph;
|
||||
@ -1224,6 +1229,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
|
||||
parse_only: parse_only,
|
||||
no_trans: no_trans,
|
||||
treat_err_as_bug: treat_err_as_bug,
|
||||
continue_parse_after_error: continue_parse_after_error,
|
||||
mir_opt_level: mir_opt_level,
|
||||
build_dep_graph: incremental_compilation || dump_dep_graph,
|
||||
dump_dep_graph: dump_dep_graph,
|
||||
|
@ -50,7 +50,7 @@ use syntax::attr::{self, AttrMetaMethods};
|
||||
use syntax::codemap::{DUMMY_SP, Span};
|
||||
use syntax::parse::token::InternedString;
|
||||
|
||||
use rustc_const_eval::ConstInt;
|
||||
use rustc_const_math::ConstInt;
|
||||
|
||||
use rustc_front::hir;
|
||||
use rustc_front::hir::{ItemImpl, ItemTrait, PatKind};
|
||||
|
@ -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;
|
||||
@ -22,7 +20,7 @@ use ty::{self, Ty, TyCtxt, TypeAndMut, TypeFlags, TypeFoldable};
|
||||
use ty::{Disr, ParameterEnvironment};
|
||||
use ty::TypeVariants::*;
|
||||
|
||||
use rustc_const_eval::{ConstInt, ConstIsize, ConstUsize};
|
||||
use rustc_const_math::{ConstInt, ConstIsize, ConstUsize};
|
||||
|
||||
use std::cmp;
|
||||
use std::hash::{Hash, SipHasher, Hasher};
|
||||
@ -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
|
||||
|
@ -11,4 +11,9 @@ 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,11 +42,8 @@ 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_eval::*;
|
||||
use rustc_const_math::*;
|
||||
|
||||
macro_rules! math {
|
||||
($e:expr, $op:expr) => {
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// 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.
|
||||
//
|
||||
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Rusty Mathematics
|
||||
//! constant evaluation on the HIR and code to validate patterns/matches
|
||||
//!
|
||||
//! # Note
|
||||
//!
|
||||
@ -25,19 +25,29 @@
|
||||
|
||||
#![feature(rustc_private)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(rustc_diagnostic_macros)]
|
||||
#![feature(slice_patterns)]
|
||||
#![feature(iter_arith)]
|
||||
#![feature(question_mark)]
|
||||
|
||||
#[macro_use] extern crate log;
|
||||
#[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
|
||||
|
||||
mod int;
|
||||
mod us;
|
||||
mod is;
|
||||
mod err;
|
||||
// NB: This module needs to be declared first so diagnostics are
|
||||
// registered before they are used.
|
||||
pub mod diagnostics;
|
||||
|
||||
pub use int::*;
|
||||
pub use us::*;
|
||||
pub use is::*;
|
||||
pub use err::ConstMathErr;
|
||||
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 }
|
||||
|
14
src/librustc_const_math/Cargo.toml
Normal file
14
src/librustc_const_math/Cargo.toml
Normal file
@ -0,0 +1,14 @@
|
||||
[package]
|
||||
authors = ["The Rust Project Developers"]
|
||||
name = "rustc_const_math"
|
||||
version = "0.0.0"
|
||||
|
||||
[lib]
|
||||
name = "rustc_const_math"
|
||||
path = "lib.rs"
|
||||
crate-type = ["dylib"]
|
||||
|
||||
[dependencies]
|
||||
log = { path = "../liblog" }
|
||||
serialize = { path = "../libserialize" }
|
||||
syntax = { path = "../libsyntax" }
|
@ -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))),
|
43
src/librustc_const_math/lib.rs
Normal file
43
src/librustc_const_math/lib.rs
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright 2012-2013 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.
|
||||
|
||||
//! Rusty Mathematics
|
||||
//!
|
||||
//! # Note
|
||||
//!
|
||||
//! This API is completely unstable and subject to change.
|
||||
|
||||
#![crate_name = "rustc_const_math"]
|
||||
#![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(question_mark)]
|
||||
|
||||
#[macro_use] extern crate log;
|
||||
#[macro_use] extern crate syntax;
|
||||
|
||||
extern crate serialize as rustc_serialize; // used by deriving
|
||||
|
||||
mod int;
|
||||
mod us;
|
||||
mod is;
|
||||
mod err;
|
||||
|
||||
pub use int::*;
|
||||
pub use us::*;
|
||||
pub use is::*;
|
||||
pub use err::ConstMathErr;
|
@ -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;
|
||||
@ -428,6 +429,8 @@ pub fn phase_1_parse_input<'a>(sess: &'a Session,
|
||||
// memory, but they do not restore the initial state.
|
||||
syntax::ext::mtwt::reset_tables();
|
||||
token::reset_ident_interner();
|
||||
let continue_after_error = sess.opts.continue_parse_after_error;
|
||||
sess.diagnostic().set_continue_after_error(continue_after_error);
|
||||
|
||||
let krate = time(sess.time_passes(), "parsing", || {
|
||||
match *input {
|
||||
@ -443,6 +446,8 @@ pub fn phase_1_parse_input<'a>(sess: &'a Session,
|
||||
}
|
||||
})?;
|
||||
|
||||
sess.diagnostic().set_continue_after_error(true);
|
||||
|
||||
if sess.opts.debugging_opts.ast_json_noexpand {
|
||||
println!("{}", json::as_json(&krate));
|
||||
}
|
||||
@ -851,7 +856,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};
|
||||
|
@ -15,7 +15,7 @@ rbml = { path = "../librbml" }
|
||||
rustc = { path = "../librustc" }
|
||||
rustc_back = { path = "../librustc_back" }
|
||||
rustc_bitflags = { path = "../librustc_bitflags" }
|
||||
rustc_const_eval = { path = "../librustc_const_eval" }
|
||||
rustc_const_math = { path = "../librustc_const_math" }
|
||||
rustc_front = { path = "../librustc_front" }
|
||||
rustc_llvm = { path = "../librustc_llvm" }
|
||||
serialize = { path = "../libserialize" }
|
||||
|
@ -36,7 +36,7 @@ use rustc::ty::subst;
|
||||
use rustc::ty::{ImplContainer, TraitContainer};
|
||||
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, VariantKind};
|
||||
|
||||
use rustc_const_eval::ConstInt;
|
||||
use rustc_const_math::ConstInt;
|
||||
|
||||
use rustc::mir;
|
||||
use rustc::mir::visit::MutVisitor;
|
||||
|
@ -37,7 +37,7 @@ extern crate rustc;
|
||||
extern crate rustc_back;
|
||||
extern crate rustc_front;
|
||||
extern crate rustc_llvm;
|
||||
extern crate rustc_const_eval;
|
||||
extern crate rustc_const_math;
|
||||
|
||||
pub use rustc::middle;
|
||||
|
||||
|
@ -14,6 +14,7 @@ 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" }
|
||||
syntax = { path = "../libsyntax" }
|
||||
|
@ -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,8 +94,8 @@ 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_const_eval::ConstInt;
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
use rustc_const_math::ConstInt;
|
||||
|
||||
pub struct Scope<'tcx> {
|
||||
/// the scope-id within the scope_datas
|
||||
|
@ -10,13 +10,14 @@
|
||||
|
||||
use hair::*;
|
||||
use rustc_data_structures::fnv::FnvHashMap;
|
||||
use rustc_const_eval::ConstInt;
|
||||
use rustc_const_math::ConstInt;
|
||||
use hair::cx::Cx;
|
||||
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};
|
||||
@ -26,7 +27,7 @@ use rustc::ty::{self, Ty, TyCtxt};
|
||||
use syntax::codemap::Span;
|
||||
use syntax::parse::token;
|
||||
use rustc_front::hir;
|
||||
use rustc_const_eval::{ConstInt, ConstUsize};
|
||||
use rustc_const_math::{ConstInt, ConstUsize};
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Cx<'a, 'tcx: 'a> {
|
||||
|
@ -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;
|
||||
|
@ -32,6 +32,7 @@ extern crate rustc_data_structures;
|
||||
extern crate rustc_front;
|
||||
extern crate rustc_back;
|
||||
extern crate syntax;
|
||||
extern crate rustc_const_math;
|
||||
extern crate rustc_const_eval;
|
||||
|
||||
pub mod build;
|
||||
|
@ -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;
|
||||
|
@ -17,6 +17,7 @@ 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" }
|
||||
rustc_llvm = { path = "../librustc_llvm" }
|
||||
|
@ -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;
|
||||
@ -38,7 +39,7 @@ use rustc::ty::adjustment::{AdjustUnsafeFnPointer, AdjustMutToConstPointer};
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::cast::{CastTy,IntTy};
|
||||
use util::nodemap::NodeMap;
|
||||
use rustc_const_eval::{ConstInt, ConstMathErr, ConstUsize, ConstIsize};
|
||||
use rustc_const_math::{ConstInt, ConstMathErr, ConstUsize, ConstIsize};
|
||||
|
||||
use rustc_front::hir;
|
||||
|
||||
@ -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 {
|
||||
|
@ -51,6 +51,7 @@ pub extern crate rustc_llvm as llvm;
|
||||
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;
|
||||
|
@ -10,8 +10,9 @@
|
||||
|
||||
use llvm::ValueRef;
|
||||
use rustc::ty::{Ty, TypeFoldable};
|
||||
use rustc::middle::const_eval::{self, ConstVal};
|
||||
use rustc_const_eval::ConstInt::*;
|
||||
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,8 +11,8 @@
|
||||
use llvm::ValueRef;
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc::ty::cast::{CastTy, IntTy};
|
||||
use middle::const_eval::ConstVal;
|
||||
use rustc_const_eval::ConstInt;
|
||||
use middle::const_val::ConstVal;
|
||||
use rustc_const_math::ConstInt;
|
||||
use rustc::mir::repr as mir;
|
||||
|
||||
use asm;
|
||||
|
@ -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")
|
||||
|
@ -16,5 +16,6 @@ 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;
|
||||
@ -65,7 +66,7 @@ use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope,
|
||||
use util::common::{ErrorReported, FN_OUTPUT_NAME};
|
||||
use util::nodemap::FnvHashSet;
|
||||
|
||||
use rustc_const_eval::ConstInt;
|
||||
use rustc_const_math::ConstInt;
|
||||
|
||||
use syntax::{abi, ast};
|
||||
use syntax::codemap::{Span, Pos};
|
||||
@ -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};
|
||||
@ -81,7 +82,7 @@ use util::common::{ErrorReported, MemoizationMap};
|
||||
use util::nodemap::{FnvHashMap, FnvHashSet};
|
||||
use write_ty_to_tcx;
|
||||
|
||||
use rustc_const_eval::ConstInt;
|
||||
use rustc_const_math::ConstInt;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashSet;
|
||||
@ -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) {
|
||||
|
@ -92,6 +92,7 @@ extern crate rustc;
|
||||
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;
|
||||
|
@ -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;
|
||||
|
@ -837,8 +837,6 @@ impl<K, V, S> HashMap<K, V, S>
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn keys<'a>(&'a self) -> Keys<'a, K, V> {
|
||||
fn first<A, B>((a, _): (A, B)) -> A { a }
|
||||
let first: fn((&'a K,&'a V)) -> &'a K = first; // coerce to fn ptr
|
||||
|
||||
Keys { inner: self.iter().map(first) }
|
||||
}
|
||||
|
||||
@ -862,8 +860,6 @@ impl<K, V, S> HashMap<K, V, S>
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn values<'a>(&'a self) -> Values<'a, K, V> {
|
||||
fn second<A, B>((_, b): (A, B)) -> B { b }
|
||||
let second: fn((&'a K,&'a V)) -> &'a V = second; // coerce to fn ptr
|
||||
|
||||
Values { inner: self.iter().map(second) }
|
||||
}
|
||||
|
||||
@ -997,8 +993,6 @@ impl<K, V, S> HashMap<K, V, S>
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
pub fn drain(&mut self) -> Drain<K, V> {
|
||||
fn last_two<A, B, C>((_, b, c): (A, B, C)) -> (B, C) { (b, c) }
|
||||
let last_two: fn((SafeHash, K, V)) -> (K, V) = last_two; // coerce to fn pointer
|
||||
|
||||
Drain {
|
||||
inner: self.table.drain().map(last_two),
|
||||
}
|
||||
@ -1404,8 +1398,6 @@ impl<K, V, S> IntoIterator for HashMap<K, V, S>
|
||||
/// ```
|
||||
fn into_iter(self) -> IntoIter<K, V> {
|
||||
fn last_two<A, B, C>((_, b, c): (A, B, C)) -> (B, C) { (b, c) }
|
||||
let last_two: fn((SafeHash, K, V)) -> (K, V) = last_two;
|
||||
|
||||
IntoIter {
|
||||
inner: self.table.into_iter().map(last_two)
|
||||
}
|
||||
|
@ -415,8 +415,6 @@ impl<T, S> HashSet<T, S>
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
pub fn drain(&mut self) -> Drain<T> {
|
||||
fn first<A, B>((a, _): (A, B)) -> A { a }
|
||||
let first: fn((T, ())) -> T = first; // coerce to fn pointer
|
||||
|
||||
Drain { iter: self.map.drain().map(first) }
|
||||
}
|
||||
|
||||
@ -892,8 +890,6 @@ impl<T, S> IntoIterator for HashSet<T, S>
|
||||
/// ```
|
||||
fn into_iter(self) -> IntoIter<T> {
|
||||
fn first<A, B>((a, _): (A, B)) -> A { a }
|
||||
let first: fn((T, ())) -> T = first;
|
||||
|
||||
IntoIter { iter: self.map.into_iter().map(first) }
|
||||
}
|
||||
}
|
||||
|
@ -370,6 +370,7 @@ pub struct Handler {
|
||||
emit: RefCell<Box<Emitter>>,
|
||||
pub can_emit_warnings: bool,
|
||||
treat_err_as_bug: bool,
|
||||
continue_after_error: Cell<bool>,
|
||||
delayed_span_bug: RefCell<Option<(MultiSpan, String)>>,
|
||||
}
|
||||
|
||||
@ -392,10 +393,15 @@ impl Handler {
|
||||
emit: RefCell::new(e),
|
||||
can_emit_warnings: can_emit_warnings,
|
||||
treat_err_as_bug: treat_err_as_bug,
|
||||
continue_after_error: Cell::new(true),
|
||||
delayed_span_bug: RefCell::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_continue_after_error(&self, continue_after_error: bool) {
|
||||
self.continue_after_error.set(continue_after_error);
|
||||
}
|
||||
|
||||
pub fn struct_dummy<'a>(&'a self) -> DiagnosticBuilder<'a> {
|
||||
DiagnosticBuilder::new(&self.emit, Level::Cancelled, "")
|
||||
}
|
||||
@ -612,6 +618,7 @@ impl Handler {
|
||||
lvl: Level) {
|
||||
if lvl == Warning && !self.can_emit_warnings { return }
|
||||
self.emit.borrow_mut().emit(msp, msg, None, lvl);
|
||||
if !self.continue_after_error.get() { self.abort_if_errors(); }
|
||||
}
|
||||
pub fn emit_with_code(&self,
|
||||
msp: Option<&MultiSpan>,
|
||||
@ -620,10 +627,12 @@ impl Handler {
|
||||
lvl: Level) {
|
||||
if lvl == Warning && !self.can_emit_warnings { return }
|
||||
self.emit.borrow_mut().emit(msp, msg, Some(code), lvl);
|
||||
if !self.continue_after_error.get() { self.abort_if_errors(); }
|
||||
}
|
||||
pub fn custom_emit(&self, rsp: RenderSpan, msg: &str, lvl: Level) {
|
||||
if lvl == Warning && !self.can_emit_warnings { return }
|
||||
self.emit.borrow_mut().custom_emit(&rsp, msg, lvl);
|
||||
if !self.continue_after_error.get() { self.abort_if_errors(); }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,15 +16,15 @@
|
||||
#[macro_use] extern crate rustc;
|
||||
extern crate rustc_front;
|
||||
extern crate rustc_plugin;
|
||||
extern crate rustc_const_eval;
|
||||
extern crate rustc_const_math;
|
||||
extern crate syntax;
|
||||
|
||||
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_const_eval::ConstInt;
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
use rustc_const_math::ConstInt;
|
||||
use rustc_plugin::Registry;
|
||||
|
||||
use syntax::ast::NodeId;
|
||||
|
@ -8,6 +8,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Z continue-parse-after-error
|
||||
|
||||
// For style and consistency reasons, non-parametrized enum variants must
|
||||
// be used simply as `ident` instead of `ident ()`.
|
||||
// This test-case covers enum matching.
|
||||
|
@ -8,6 +8,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Z continue-parse-after-error
|
||||
|
||||
enum bird {
|
||||
pub duck,
|
||||
//~^ ERROR: expected identifier, found keyword `pub`
|
||||
|
@ -8,6 +8,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Z continue-parse-after-error
|
||||
|
||||
macro_rules! parallel {
|
||||
(
|
||||
// If future has `pred`/`moelarry` fragments (where "pred" is
|
||||
|
@ -8,6 +8,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Z continue-parse-after-error
|
||||
|
||||
macro_rules! ignored_item {
|
||||
() => {
|
||||
fn foo() {}
|
||||
|
@ -8,6 +8,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Z continue-parse-after-error
|
||||
|
||||
// Test that the parser is error correcting missing idents. Despite a parsing
|
||||
// error (or two), we still run type checking (and don't get extra errors there).
|
||||
|
||||
|
@ -8,6 +8,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Z continue-parse-after-error
|
||||
|
||||
// Test that we can recover from missing braces in the parser.
|
||||
|
||||
trait Foo {
|
||||
|
@ -8,6 +8,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Z continue-parse-after-error
|
||||
|
||||
// Test that we can recover from mismatched braces in the parser.
|
||||
|
||||
trait Foo {
|
||||
|
@ -8,6 +8,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Z continue-parse-after-error
|
||||
|
||||
struct Self;
|
||||
//~^ ERROR expected identifier, found keyword `Self`
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Z parse-only
|
||||
// compile-flags: -Z parse-only -Z continue-parse-after-error
|
||||
|
||||
fn main() {
|
||||
let x = "\x80"; //~ ERROR may only be used
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Z parse-only
|
||||
// compile-flags: -Z parse-only -Z continue-parse-after-error
|
||||
|
||||
// ignore-tidy-cr
|
||||
// ignore-tidy-tab
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Z parse-only
|
||||
// compile-flags: -Z parse-only -Z continue-parse-after-error
|
||||
|
||||
|
||||
extern
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Z parse-only
|
||||
// compile-flags: -Z parse-only -Z continue-parse-after-error
|
||||
|
||||
|
||||
// ignore-tidy-tab
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Z parse-only
|
||||
// compile-flags: -Z parse-only -Z continue-parse-after-error
|
||||
|
||||
|
||||
// ignore-tidy-tab
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Z parse-only
|
||||
// compile-flags: -Z parse-only -Z continue-parse-after-error
|
||||
|
||||
|
||||
trait Serializable<'self, T> { //~ ERROR no longer a special lifetime
|
||||
|
@ -8,6 +8,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Z parse-only -Z continue-parse-after-error
|
||||
|
||||
fn main() {
|
||||
let _ = b"\u{a66e}";
|
||||
//~^ ERROR unicode escape sequences cannot be used as a byte or in a byte string
|
||||
|
@ -8,6 +8,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Z parse-only -Z continue-parse-after-error
|
||||
|
||||
fn main() {
|
||||
0b121; //~ ERROR invalid digit for a base 2 literal
|
||||
0b10_10301; //~ ERROR invalid digit for a base 2 literal
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Z parse-only
|
||||
// compile-flags: -Z parse-only -Z continue-parse-after-error
|
||||
static c3: char =
|
||||
'\x1' //~ ERROR: numeric character escape is too short
|
||||
;
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Z parse-only
|
||||
// compile-flags: -Z parse-only -Z continue-parse-after-error
|
||||
|
||||
fn main() {
|
||||
0o1.0; //~ ERROR: octal float literal is not supported
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Z parse-only
|
||||
// compile-flags: -Z parse-only -Z continue-parse-after-error
|
||||
|
||||
// ignore-tidy-cr
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Z parse-only
|
||||
// compile-flags: -Z parse-only -Z continue-parse-after-error
|
||||
|
||||
pub fn main() {
|
||||
let s = "\u{lol}";
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Z parse-only
|
||||
// compile-flags: -Z parse-only -Z continue-parse-after-error
|
||||
|
||||
trait A {
|
||||
fn foo(*mut self); //~ ERROR cannot pass self by raw pointer
|
||||
|
Loading…
Reference in New Issue
Block a user