parse_name_value_directive(line, "exec-env").map(|nv| {
// nv is either FOO or FOO=BAR
let mut strs: Vec<String> = nv.as_slice()
- .splitn('=', 1)
+ .splitn(1, '=')
.map(|s| s.to_string())
.collect();
use header;
use procsrv;
use util::logv;
-#[cfg(target_os = "win32")]
+#[cfg(target_os = "windows")]
+#[cfg(stage0, target_os = "win32")] // NOTE: Remove after snapshot
use util;
use std::io::File;
use std::str;
use std::string::String;
use std::task;
+use std::time::Duration;
use test::MetricMap;
pub fn run(config: Config, testfile: String) {
.expect(format!("failed to exec `{}`", config.adb_path).as_slice());
loop {
//waiting 1 second for gdbserver start
- timer::sleep(1000);
+ timer::sleep(Duration::milliseconds(1000));
let result = task::try(proc() {
tcp::TcpStream::connect("127.0.0.1", 5039).unwrap();
});
format!("{}:{}:", testfile.display(), ee.line)
}).collect::<Vec<String> >();
- #[cfg(target_os = "win32")]
+ #[cfg(target_os = "windows")]
+ #[cfg(stage0, target_os = "win32")] // NOTE: Remove after snapshot
fn to_lower( s : &str ) -> String {
let i = s.chars();
let c : Vec<char> = i.map( |c| {
String::from_chars(c.as_slice())
}
- #[cfg(target_os = "win32")]
+ #[cfg(target_os = "windows")]
+ #[cfg(stage0, target_os = "win32")] // NOTE: Remove after snapshot
fn prefix_matches( line : &str, prefix : &str ) -> bool {
to_lower(line).as_slice().starts_with(to_lower(prefix).as_slice())
}
format!("{} {}", prog, args.connect(" "))
}
-#[cfg(target_os = "win32")]
+#[cfg(target_os = "windows")]
+#[cfg(stage0, target_os = "win32")] // NOTE: Remove after snapshot
fn make_cmdline(libpath: &str, prog: &str, args: &[String]) -> String {
format!("{} {} {}", lib_path_cmd_prefix(libpath), prog, args.connect(" "))
}
// Build the LD_LIBRARY_PATH variable as it would be seen on the command line
// for diagnostic purposes
-#[cfg(target_os = "win32")]
+#[cfg(target_os = "windows")]
+#[cfg(stage0, target_os = "win32")] // NOTE: Remove after snapshot
fn lib_path_cmd_prefix(path: &str) -> String {
format!("{}=\"{}\"", util::lib_path_env_var(), util::make_new_path(path))
}
use common::Config;
-#[cfg(target_os = "win32")]
+#[cfg(target_os = "windows")]
+#[cfg(stage0, target_os = "win32")] // NOTE: Remove after snapshot
use std::os::getenv;
/// Conversion table from triple OS name to Rust SYSNAME
static OS_TABLE: &'static [(&'static str, &'static str)] = &[
- ("mingw32", "win32"),
- ("win32", "win32"),
+ ("mingw32", "windows"),
+ ("win32", "windows"),
+ ("windows", "windows"),
("darwin", "macos"),
("android", "android"),
("linux", "linux"),
fail!("Cannot determine OS from triple");
}
-#[cfg(target_os = "win32")]
+#[cfg(target_os = "windows")]
+#[cfg(stage0, target_os = "win32")] // NOTE: Remove after snapshot
pub fn make_new_path(path: &str) -> String {
// Windows just uses PATH as the library search path, so we have to
}
}
-#[cfg(target_os = "win32")]
+#[cfg(target_os = "windows")]
+#[cfg(stage0, target_os = "win32")] // NOTE: Remove after snapshot
pub fn lib_path_env_var() -> &'static str { "PATH" }
-#[cfg(target_os = "win32")]
+#[cfg(target_os = "windows")]
+#[cfg(stage0, target_os = "win32")] // NOTE: Remove after snapshot
pub fn path_div() -> &'static str { ";" }
pub fn logv(config: &Config, s: String) {
compiler is linking to. There are currently three known types of native
libraries:
-* Dynamic - `#[link(name = "readline")]
-* Static - `#[link(name = "my_build_dependency", kind = "static")]
-* Frameworks - `#[link(name = "CoreFoundation", kind = "framework")]
+* Dynamic - `#[link(name = "readline")]`
+* Static - `#[link(name = "my_build_dependency", kind = "static")]`
+* Frameworks - `#[link(name = "CoreFoundation", kind = "framework")]`
Note that frameworks are only available on OSX targets.
The full complement of runtime features is defined by the [`Runtime`
trait](std/rt/trait.Runtime.html) and the [`Task`
struct](std/rt/task/struct.Task.html). A `Task` is constant among all runtime
-implementations, but each runtime implements has its own implementation of the
+implementations, but each runtime has its own implementation of the
`Runtime` trait.
The local `Task` stores the runtime value inside of itself, and then ownership
For benchmarks relating to processing/generating data, one can set the
`bytes` field to the number of bytes consumed/produced in each
-iteration; this will used to show the throughput of the benchmark.
+iteration; this will be used to show the throughput of the benchmark.
This must be the amount used in each iteration, *not* the total
amount.
Going the opposite direction, from `*const` to a reference `&`, is not
safe. A `&T` is always valid, and so, at a minimum, the raw pointer
-`*const T` has to be a valid to a valid instance of type `T`. Furthermore,
+`*const T` has to point to a valid instance of type `T`. Furthermore,
the resulting pointer must satisfy the aliasing and mutability laws of
references. The compiler assumes these properties are true for any
references, no matter how they are created, and so any conversion from
```{ignore}
let x = 5i;
-let y: int = if x == 5 { 10i; } else { 15i; };
+let y: int = if x == 5i { 10i; } else { 15i; };
```
Note the semicolons after the 10 and 15. Rust will give us the following error:
```
`while` loops are the correct choice when you're not sure how many times
-you need to loop.
+you need to loop.
If you need an infinite loop, you may be tempted to write this:
.ok().expect("Failed to read line");
```
-Do you remember this code?
+Do you remember this code?
```
enum OptionalInt {
our code in this file. We'll talk about multiple-file projects later on in the
guide.
+Before we move on, let me show you one more Cargo command: `run`. `cargo run`
+is kind of like `cargo build`, but it also then runs the produced exectuable.
+Try it out:
+
+```{notrust,ignore}
+$ cargo run
+ Compiling guessing_game v0.1.0 (file:/home/you/projects/guessing_game)
+ Running `target/guessing_game`
+Hello, world!
+$
+```
+
+Great! The `run` command comes in handy when you need to rapidly iterate on a project.
+Our game is just such a project, we need to quickly test each iteration before moving on to the next one.
+
## Processing a Guess
Let's get to it! The first thing we need to do for our guessing game is
Excellent! Try running our new program a few times:
```{notrust,ignore}
-$ ./target/guessing_game
+$ ./target/guessing_game
Guess the number!
The secret number is: 7
Please input your guess.
4
You guessed: 4
-$ ./target/guessing_game
+$ ./target/guessing_game
Guess the number!
The secret number is: 83
Please input your guess.
5
You guessed: 5
-$ ./target/guessing_game
+$ ./target/guessing_game
Guess the number!
The secret number is: -29
Please input your guess.
```{notrust,ignore}
$ cargo build
Compiling guessing_game v0.1.0 (file:/home/you/projects/guessing_game)
-$ ./target/guessing_game
+$ ./target/guessing_game
Guess the number!
The secret number is: 57
Please input your guess.
println!("You guessed: {}", input);
- match cmp(input, secret_number) {
+ match cmp(input, secret_number) {
Less => println!("Too small!"),
Greater => println!("Too big!"),
Equal => { println!("You win!"); },
standard input, and you can guess anything. Try it:
```{notrust,ignore}
-$ ./target/guessing_game
+$ ./target/guessing_game
Guess the number!
The secret number is: 73
Please input your guess.
```{notrust,ignore}
$ cargo build
Compiling guessing_game v0.1.0 (file:/home/you/projects/guessing_game)
-$ ./target/guessing_game
+$ ./target/guessing_game
Guess the number!
The secret number is: 17
Please input your guess.
```{notrust,ignore}
$ cargo build
Compiling guessing_game v0.1.0 (file:/home/you/projects/guessing_game)
-$ ./target/guessing_game
+$ ./target/guessing_game
Guess the number!
The secret number is: 58
Please input your guess.
```{notrust,ignore}
$ cargo build
Compiling guessing_game v0.1.0 (file:/home/you/projects/guessing_game)
-$ ./target/guessing_game
+$ ./target/guessing_game
Guess the number!
The secret number is: 59
Please input your guess.
```{rust,ignore}
$ cargo build
Compiling guessing_game v0.1.0 (file:/home/you/projects/guessing_game)
-$ ./target/guessing_game
+$ ./target/guessing_game
Guess the number!
The secret number is: 61
Please input your guess.
This will work:
-```{notrust,ignore}
-$ cargo build
- Compiling modules v0.1.0 (file:/home/you/projects/modules)
-$
-```
-
-Before we move on, let me show you one more Cargo command: `run`. `cargo run`
-is kind of like `cargo build`, but it also then runs the produced exectuable.
-Try it out:
-
```{notrust,ignore}
$ cargo run
Compiling modules v0.1.0 (file:/home/steve/tmp/modules)
All of our references so far have been to variables we've created on the stack.
In Rust, the simplest way to allocate heap variables is using a *box*. To
create a box, use the `box` keyword:
-
+
```{rust}
let x = box 5i;
```
This allocates an integer `5` on the heap, and creates a binding `x` that
refers to it.. The great thing about boxed pointers is that we don't have to
-manually free this allocation! If we write
+manually free this allocation! If we write
```{rust}
{
```{rust,ignore}
let x = inverse(25.0f64);
-println!("{}", x + 2.0f64); // error: binary operation `+` cannot be applied
+println!("{}", x + 2.0f64); // error: binary operation `+` cannot be applied
// to type `core::result::Result<f64,collections::string::String>`
```
# Macros
# Unsafe
-
that does _not_ occur in the set of [keywords](#keywords).
-Note: `XID_start` and `XID_continue` as character properties cover the
-character ranges used to form the more familiar C and Java language-family
-identifiers.
+> **Note**: `XID_start` and `XID_continue` as character properties cover the
+> character ranges used to form the more familiar C and Java language-family
+> identifiers.
### Delimiter-restricted productions
##### Use declarations
~~~~ {.ebnf .gram}
-use_decl : "pub" ? "use" [ ident '=' path
+use_decl : "pub" ? "use" [ path "as" ident
| path_glob ] ;
path_glob : ident [ "::" [ path_glob
module item. These declarations may appear at the top of [modules](#modules) and
[blocks](#blocks).
-*Note*: Unlike in many languages,
-`use` declarations in Rust do *not* declare linkage dependency with external crates.
-Rather, [`extern crate` declarations](#extern-crate-declarations) declare linkage dependencies.
+> **Note**: Unlike in many languages,
+> `use` declarations in Rust do *not* declare linkage dependency with external crates.
+> Rather, [`extern crate` declarations](#extern-crate-declarations) declare linkage dependencies.
Use declarations support a number of convenient shortcuts:
- * Rebinding the target name as a new local name, using the syntax `use x = p::q::r;`.
+ * Rebinding the target name as a new local name, using the syntax `use p::q::r as x;`.
* Simultaneously binding a list of paths differing only in their final element,
using the glob-like brace syntax `use a::b::{c,d,e,f};`
* Binding all paths matching a given prefix, using the asterisk wildcard syntax `use a::b::*;`
Immutable static items are stored in the read-only data section.
The constant value bound to a static item is, like all constant values, evaluated at compile time.
Static items have the `static` lifetime, which outlives all other lifetimes in a Rust program.
+Only values stored in the global data section (such as string constants
+and static items) can have the `static` lifetime;
+dynamically constructed values cannot safely be assigned the `static` lifetime.
Static items are declared with the `static` keyword.
A static item must have a _constant expression_ giving its definition.
# impl Shape for int { fn area(&self) -> f64 { 0.0 } }
# impl Circle for int { fn radius(&self) -> f64 { 0.0 } }
# let mycircle = 0;
-let mycircle: Circle = ~mycircle as ~Circle;
+let mycircle = box mycircle as Box<Circle>;
let nonsense = mycircle.radius() * mycircle.area();
~~~~
- `crate_id` - specify the this crate's crate ID.
- `crate_type` - see [linkage](#linkage).
- `feature` - see [compiler features](#compiler-features).
+- `no_builtins` - disable optimizing certain code patterns to invocations of
+ library functions that are assumed to exist
- `no_main` - disable emitting the `main` symbol. Useful when some other
object being linked to defines `main`.
- `no_start` - disable linking to the `native` crate, which specifies the
"start" language item.
- `no_std` - disable linking to the `std` crate.
-- `no_builtins` - disable optimizing certain code patterns to invocations of
- library functions that are assumed to exist
### Module-only attributes
### Function-only attributes
-- `plugin_registrar` - mark this function as the registration point for
- compiler plugins, such as loadable syntax extensions.
- `main` - indicates that this function should be passed to the entry point,
rather than the function in the crate root named `main`.
+- `plugin_registrar` - mark this function as the registration point for
+ compiler plugins, such as loadable syntax extensions.
- `start` - indicates that this function should be used as the entry point,
overriding the "start" language item. See the "start" [language
item](#language-items) for more details.
### Miscellaneous attributes
+- `export_name` - on statics and functions, this determines the name of the
+ exported symbol.
- `link_section` - on statics and functions, this specifies the section of the
object file that this item's contents will be placed into.
- `macro_export` - export a macro for cross-crate usage.
symbol for this item to its identifier.
- `packed` - on structs or enums, eliminate any padding that would be used to
align fields.
+- `phase` - on `extern crate` statements, allows specifying which "phase" of
+ compilation the crate should be loaded for. Currently, there are two
+ choices: `link` and `plugin`. `link` is the default. `plugin` will load the
+ crate at compile-time and use any syntax extensions or lints that the crate
+ defines. They can both be specified, `#[phase(link, plugin)]` to use a crate
+ both at runtime and compiletime.
- `repr` - on C-like enums, this sets the underlying type used for
representation. Useful for FFI. Takes one argument, which is the primitive
type this enum should be represented for, or `C`, which specifies that it
- `unsafe_no_drop_flag` - on structs, remove the flag that prevents
destructors from being run twice. Destructors might be run multiple times on
the same object with this attribute.
-- `phase` - on `extern crate` statements, allows specifying which "phase" of
- compilation the crate should be loaded for. Currently, there are two
- choices: `link` and `plugin`. `link` is the default. `plugin` will load the
- crate at compile-time and use any syntax extensions or lints that the crate
- defines. They can both be specified, `#[phase(link, plugin)]` to use a crate
- both at runtime and compiletime.
### Conditional compilation
For any lint check `C`:
- * `warn(C)` warns about violations of `C` but continues compilation,
- * `deny(C)` signals an error after encountering a violation of `C`,
* `allow(C)` overrides the check for `C` so that violations will go
unreported,
+ * `deny(C)` signals an error after encountering a violation of `C`,
* `forbid(C)` is the same as `deny(C)`, but also forbids changing the lint
- level afterwards.
+ level afterwards,
+ * `warn(C)` warns about violations of `C` but continues compilation.
The lint checks supported by the compiler can be found via `rustc -W help`,
along with their default settings.
#### Built-in Traits
+* `copy`
+ : Types that do not move ownership when used by-value.
+* `drop`
+ : Have destructors.
* `send`
: Able to be sent across task boundaries.
* `sized`
: Has a size known at compile time.
-* `copy`
- : Types that do not move ownership when used by-value.
* `sync`
: Able to be safely shared between tasks when aliased.
-* `drop`
- : Have destructors.
#### Operators
: Elements have a right shift operation.
* `index`
: Elements can be indexed.
+* `index_mut`
+ : ___Needs filling in___
* `eq`
: Elements can be compared for equality.
* `ord`
* `deref_mut`
: `*` can be applied, yielding a mutable reference to another type
-
These are functions:
+* `fn`
+ : ___Needs filling in___
+* `fn_mut`
+ : ___Needs filling in___
+* `fn_once`
+ : ___Needs filling in___
* `str_eq`
: Compare two strings (`&str`) for equality.
* `strdup_uniq`
#### Types
-* `unsafe`
- : A type whose contents can be mutated through an immutable reference
* `type_id`
: The type returned by the `type_id` intrinsic.
+* `unsafe`
+ : A type whose contents can be mutated through an immutable reference
#### Marker types
These types help drive the compiler's analysis
-* `covariant_type`
- : The type parameter should be considered covariant
-* `contravariant_type`
- : The type parameter should be considered contravariant
-* `invariant_type`
- : The type parameter should be considered invariant
-* `covariant_lifetime`
- : The lifetime parameter should be considered covariant
-* `contravariant_lifetime`
- : The lifetime parameter should be considered contravariant
-* `invariant_lifetime`
- : The lifetime parameter should be considered invariant
-* `no_send_bound`
- : This type does not implement "send", even if eligible
+* `begin_unwind`
+ : ___Needs filling in___
* `no_copy_bound`
: This type does not implement "copy", even if eligible
+* `no_send_bound`
+ : This type does not implement "send", even if eligible
* `no_sync_bound`
: This type does not implement "sync", even if eligible
* `managed_bound`
: This type implements "managed"
-
+* `eh_personality`
+ : ___Needs filling in___
+* `exchange_free`
+ : Free memory that was allocated on the exchange heap.
+* `exchange_malloc`
+ : Allocate memory on the exchange heap.
+* `closure_exchange_malloc`
+ : ___Needs filling in___
* `fail_`
: Abort the program with an error.
* `fail_bounds_check`
: Abort the program with a bounds check error.
-* `exchange_malloc`
- : Allocate memory on the exchange heap.
-* `exchange_free`
- : Free memory that was allocated on the exchange heap.
-* `malloc`
- : Allocate memory on the managed heap.
* `free`
: Free memory that was allocated on the managed heap.
+* `gc`
+ : ___Needs filling in___
+* `exchange_heap`
+ : ___Needs filling in___
+* `managed_heap`
+ : ___Needs filling in___
+* `iterator`
+ : ___Needs filling in___
+* `contravariant_lifetime`
+ : The lifetime parameter should be considered contravariant
+* `covariant_lifetime`
+ : The lifetime parameter should be considered covariant
+* `invariant_lifetime`
+ : The lifetime parameter should be considered invariant
+* `malloc`
+ : Allocate memory on the managed heap.
+* `opaque`
+ : ___Needs filling in___
+* `owned_box`
+ : ___Needs filling in___
+* `stack_exhausted`
+ : ___Needs filling in___
+* `start`
+ : ___Needs filling in___
+* `contravariant_type`
+ : The type parameter should be considered contravariant
+* `covariant_type`
+ : The type parameter should be considered covariant
+* `invariant_type`
+ : The type parameter should be considered invariant
+* `ty_desc`
+ : ___Needs filling in___
+* `ty_visitor`
+ : ___Needs filling in___
> **Note:** This list is likely to become out of date. We should auto-generate it
> from `librustc/middle/lang_items.rs`.
* Comparison traits: `PartialEq`, `Eq`, `PartialOrd`, `Ord`.
* Serialization: `Encodable`, `Decodable`. These require `serialize`.
* `Clone`, to create `T` from `&T` via a copy.
-* `Hash`, to iterate over the bytes in a data type.
-* `Rand`, to create a random instance of a data type.
* `Default`, to create an empty instance of a data type.
-* `Zero`, to create a zero instance of a numeric data type.
* `FromPrimitive`, to create an instance from a numeric primitive.
+* `Hash`, to iterate over the bytes in a data type.
+* `Rand`, to create a random instance of a data type.
* `Show`, to format a value using the `{}` formatter.
+* `Zero`, to create a zero instance of a numeric data type.
### Stability
The currently implemented features of the reference compiler are:
-* `macro_rules` - The definition of new macros. This does not encompass
- macro-invocation, that is always enabled by default, this only
- covers the definition of new macros. There are currently
- various problems with invoking macros, how they interact with
- their environment, and possibly how they are used outside of
- location in which they are defined. Macro definitions are
- likely to change slightly in the future, so they are currently
- hidden behind this feature.
+* `asm` - The `asm!` macro provides a means for inline assembly. This is often
+ useful, but the exact syntax for this feature along with its semantics
+ are likely to change, so this macro usage must be opted into.
+
+* `concat_idents` - Allows use of the `concat_idents` macro, which is in many
+ ways insufficient for concatenating identifiers, and may
+ be removed entirely for something more wholsome.
+
+* `default_type_params` - Allows use of default type parameters. The future of
+ this feature is uncertain.
* `globs` - Importing everything in a module through `*`. This is currently a
large source of bugs in name resolution for Rust, and it's not clear
whether this will continue as a feature or not. For these reasons,
the glob import statement has been hidden behind this feature flag.
-* `struct_variant` - Structural enum variants (those with named fields). It is
- currently unknown whether this style of enum variant is as
- fully supported as the tuple-forms, and it's not certain
- that this style of variant should remain in the language.
- For now this style of variant is hidden behind a feature
- flag.
+* `intrinsics` - Allows use of the "rust-intrinsics" ABI. Compiler intrinsics
+ are inherently unstable and no promise about them is made.
-* `once_fns` - Onceness guarantees a closure is only executed once. Defining a
- closure as `once` is unlikely to be supported going forward. So
- they are hidden behind this feature until they are to be removed.
+* `lang_items` - Allows use of the `#[lang]` attribute. Like `intrinsics`,
+ lang items are inherently unstable and no promise about
+ them is made.
-* `asm` - The `asm!` macro provides a means for inline assembly. This is often
- useful, but the exact syntax for this feature along with its semantics
- are likely to change, so this macro usage must be opted into.
+* `link_args` - This attribute is used to specify custom flags to the linker,
+ but usage is strongly discouraged. The compiler's usage of the
+ system linker is not guaranteed to continue in the future, and
+ if the system linker is not used then specifying custom flags
+ doesn't have much meaning.
+
+* `linkage` - Allows use of the `linkage` attribute, which is not portable.
+
+* `log_syntax` - Allows use of the `log_syntax` macro attribute, which is a
+ nasty hack that will certainly be removed.
+
+* `macro_rules` - The definition of new macros. This does not encompass
+ macro-invocation, that is always enabled by default, this only
+ covers the definition of new macros. There are currently
+ various problems with invoking macros, how they interact with
+ their environment, and possibly how they are used outside of
+ location in which they are defined. Macro definitions are
+ likely to change slightly in the future, so they are currently
+ hidden behind this feature.
* `managed_boxes` - Usage of `@` is gated due to many
planned changes to this feature. In the past, this has meant
now until the specification of identifiers is fully
fleshed out.
-* `thread_local` - The usage of the `#[thread_local]` attribute is experimental
- and should be seen as unstable. This attribute is used to
- declare a `static` as being unique per-thread leveraging
- LLVM's implementation which works in concert with the kernel
- loader and dynamic linker. This is not necessarily available
- on all platforms, and usage of it is discouraged (rust
- focuses more on task-local data instead of thread-local
- data).
+* `once_fns` - Onceness guarantees a closure is only executed once. Defining a
+ closure as `once` is unlikely to be supported going forward. So
+ they are hidden behind this feature until they are to be removed.
-* `link_args` - This attribute is used to specify custom flags to the linker,
- but usage is strongly discouraged. The compiler's usage of the
- system linker is not guaranteed to continue in the future, and
- if the system linker is not used then specifying custom flags
- doesn't have much meaning.
+* `overloaded_calls` - Allow implementing the `Fn*` family of traits on user
+ types, allowing overloading the call operator (`()`).
+ This feature may still undergo changes before being
+ stabilized.
* `phase` - Usage of the `#[phase]` attribute allows loading compiler plugins
for custom lints or syntax extensions. The implementation is considered
in need of a overhaul, and it is not clear that plugins
defined using this will continue to work.
-* `log_syntax` - Allows use of the `log_syntax` macro attribute, which is a
- nasty hack that will certainly be removed.
-
-* `trace_macros` - Allows use of the `trace_macros` macro, which is a nasty
- hack that will certainly be removed.
-
-* `concat_idents` - Allows use of the `concat_idents` macro, which is in many
- ways insufficient for concatenating identifiers, and may
- be removed entirely for something more wholsome.
-
-* `unsafe_destructor` - Allows use of the `#[unsafe_destructor]` attribute,
- which is considered wildly unsafe and will be
- obsoleted by language improvements.
-
-* `intrinsics` - Allows use of the "rust-intrinsics" ABI. Compiler intrinsics
- are inherently unstable and no promise about them is made.
-
-* `lang_items` - Allows use of the `#[lang]` attribute. Like `intrinsics`,
- lang items are inherently unstable and no promise about
- them is made.
-
-* `simd` - Allows use of the `#[simd]` attribute, which is overly simple and
- not the SIMD interface we want to expose in the long term.
-
-* `default_type_params` - Allows use of default type parameters. The future of
- this feature is uncertain.
-
* `quote` - Allows use of the `quote_*!` family of macros, which are
implemented very poorly and will likely change significantly
with a proper implementation.
-* `linkage` - Allows use of the `linkage` attribute, which is not portable.
+* `rustc_diagnostic_macros`- A mysterious feature, used in the implementation
+ of rustc, not meant for mortals.
+
+* `simd` - Allows use of the `#[simd]` attribute, which is overly simple and
+ not the SIMD interface we want to expose in the long term.
* `struct_inherit` - Allows using struct inheritance, which is barely
implemented and will probably be removed. Don't use this.
-* `overloaded_calls` - Allow implementing the `Fn*` family of traits on user
- types, allowing overloading the call operator (`()`).
- This feature may still undergo changes before being
- stabilized.
+* `struct_variant` - Structural enum variants (those with named fields). It is
+ currently unknown whether this style of enum variant is as
+ fully supported as the tuple-forms, and it's not certain
+ that this style of variant should remain in the language.
+ For now this style of variant is hidden behind a feature
+ flag.
+
+* `thread_local` - The usage of the `#[thread_local]` attribute is experimental
+ and should be seen as unstable. This attribute is used to
+ declare a `static` as being unique per-thread leveraging
+ LLVM's implementation which works in concert with the kernel
+ loader and dynamic linker. This is not necessarily available
+ on all platforms, and usage of it is discouraged (rust
+ focuses more on task-local data instead of thread-local
+ data).
+
+* `trace_macros` - Allows use of the `trace_macros` macro, which is a nasty
+ hack that will certainly be removed.
* `unboxed_closure_sugar` - Allows using `|Foo| -> Bar` as a trait bound
meaning one of the `Fn` traits. Still
experimental.
-* `rustc_diagnostic_macros`- A mysterious feature, used in the implementation
- of rustc, not meant for mortals.
-
* `unboxed_closures` - A work in progress feature with many known bugs.
+* `unsafe_destructor` - Allows use of the `#[unsafe_destructor]` attribute,
+ which is considered wildly unsafe and will be
+ obsoleted by language improvements.
+
If a feature is promoted to a language feature, then all existing programs will
start to receive compilation warnings about #[feature] directives which enabled
the new feature (because the directive is no longer necessary). However, if
region containing all of its uses; it is otherwise identical in meaning to
declaring the item outside the statement block.
-Note: there is no implicit capture of the function's dynamic environment when
-declaring a function-local item.
+> **Note**: there is no implicit capture of the function's dynamic environment when
+> declaring a function-local item.
#### Slot declarations
References arise by (automatic) conversion from owning pointers, managed pointers,
or by applying the borrowing operator `&` to some other value,
including [lvalues, rvalues or temporaries](#lvalues,-rvalues-and-temporaries).
- References are written `&content`, or in some cases `&'f content` for some lifetime-variable `f`,
+ A borrow expression is written `&content`.
+
+ A reference type is written `&'f type` for some lifetime-variable `f`,
+ or just `&type` when the lifetime can be elided;
for example `&int` means a reference to an integer.
Copying a reference is a "shallow" operation:
it involves only copying the pointer itself.
elif 'android' in os:
os = 'android'
elif 'win' in os or 'mingw' in os:
- os = 'win32'
+ os = 'windows'
cfg = [
"target_arch = \"" + arch + "\"",
"target_os = \"" + os + "\"",
]
f.write("#[cfg(" + ', '.join(cfg) + ")]\n")
+ if os == "windows": # NOTE: Remove after snapshot
+ f.write("#[cfg(stage0, target_arch = \"%s\", target_os = \"win32\")]\n" % (arch,))
version = run([llconfig, '--version']).strip()
f.write("""
fn bsearch_range_table(c: char, r: &'static [(char,char)]) -> bool {
use core::cmp::{Equal, Less, Greater};
- use core::slice::ImmutableVector;
- use core::option::None;
- r.bsearch(|&(lo,hi)| {
+ use core::slice::ImmutableSlice;
+ r.binary_search(|&(lo,hi)| {
if lo <= c && c <= hi { Equal }
else if hi < c { Less }
else { Greater }
- }) != None
+ }).found().is_some()
}\n
""")
f.write("pub mod conversions {")
f.write("""
use core::cmp::{Equal, Less, Greater};
- use core::slice::ImmutableVector;
+ use core::slice::ImmutableSlice;
use core::tuple::Tuple2;
use core::option::{Option, Some, None};
+ use core::slice;
pub fn to_lower(c: char) -> char {
match bsearch_case_table(c, LuLl_table) {
}
fn bsearch_case_table(c: char, table: &'static [(char, char)]) -> Option<uint> {
- table.bsearch(|&(key, _)| {
+ match table.binary_search(|&(key, _)| {
if c == key { Equal }
else if key < c { Less }
else { Greater }
- })
+ }) {
+ slice::Found(i) => Some(i),
+ slice::NotFound(_) => None,
+ }
}
""")
def emit_grapheme_module(f, grapheme_table, grapheme_cats):
f.write("""pub mod grapheme {
- use core::option::{Some, None};
- use core::slice::ImmutableVector;
+ use core::slice::ImmutableSlice;
+ use core::slice;
#[allow(non_camel_case_types)]
#[deriving(Clone)]
fn bsearch_range_value_table(c: char, r: &'static [(char, char, GraphemeCat)]) -> GraphemeCat {
use core::cmp::{Equal, Less, Greater};
- match r.bsearch(|&(lo, hi, _)| {
+ match r.binary_search(|&(lo, hi, _)| {
if lo <= c && c <= hi { Equal }
else if hi < c { Less }
else { Greater }
}) {
- Some(idx) => {
+ slice::Found(idx) => {
let (_, _, cat) = r[idx];
cat
}
- None => GC_Any
+ slice::NotFound(_) => GC_Any
}
}
def emit_charwidth_module(f, width_table):
f.write("pub mod charwidth {\n")
f.write(" use core::option::{Option, Some, None};\n")
- f.write(" use core::slice::ImmutableVector;\n")
+ f.write(" use core::slice::ImmutableSlice;\n")
+ f.write(" use core::slice;\n")
f.write("""
fn bsearch_range_value_table(c: char, is_cjk: bool, r: &'static [(char, char, u8, u8)]) -> u8 {
use core::cmp::{Equal, Less, Greater};
- match r.bsearch(|&(lo, hi, _, _)| {
+ match r.binary_search(|&(lo, hi, _, _)| {
if lo <= c && c <= hi { Equal }
else if hi < c { Less }
else { Greater }
}) {
- Some(idx) => {
+ slice::Found(idx) => {
let (_, _, r_ncjk, r_cjk) = r[idx];
if is_cjk { r_cjk } else { r_ncjk }
}
- None => 1
+ slice::NotFound(_) => 1
}
}
""")
f.write("""
fn bsearch_range_value_table(c: char, r: &'static [(char, char, u8)]) -> u8 {
- use core::option::{Some, None};
use core::cmp::{Equal, Less, Greater};
- use core::slice::ImmutableVector;
- match r.bsearch(|&(lo, hi, _)| {
+ use core::slice::ImmutableSlice;
+ use core::slice;
+ match r.binary_search(|&(lo, hi, _)| {
if lo <= c && c <= hi { Equal }
else if hi < c { Less }
else { Greater }
}) {
- Some(idx) => {
+ slice::Found(idx) => {
let (_, _, result) = r[idx];
result
}
- None => 0
+ slice::NotFound(_) => 0
}
}\n
""")
if !exists('g:rust_conceal_mod_path')
hi! link Conceal Operator
endif
-
-setlocal conceallevel=2
let b:delimitMate_excluded_regions = delimitMate#Get("excluded_regions") . ',rustLifetimeCandidate,rustGenericLifetimeCandidate'
endif
+if has('conceal') && exists('g:rust_conceal')
+ let b:rust_set_conceallevel=1
+ setlocal conceallevel=2
+endif
+
" Motion Commands {{{1
" Bind motion commands to support hanging indents
\|else
\|unlet! b:delimitMate_excluded_regions
\|endif
+ \|if exists('b:rust_set_conceallevel')
+ \|setlocal conceallevel<
+ \|unlet b:rust_set_conceallevel
+ \|endif
\|unlet! b:rust_last_rustc_args b:rust_last_args
\|delcommand RustRun
\|delcommand RustExpand
use std::prelude::*;
use std::mem;
- use slice::ImmutableVector;
+ use slice::ImmutableSlice;
use super::{Hash, Hasher, Writer};
struct MyWriterHasher;
use str::Str;
use string::String;
- use slice::{Vector, ImmutableVector};
+ use slice::{Slice, ImmutableSlice};
use vec::Vec;
use super::super::{Hash, Writer};
impl<'a, T> Iterator<&'a mut T> for MutItems<'a, T> {
#[inline]
+ #[allow(deprecated)] // mut_shift_ref
fn next(&mut self) -> Option<&'a mut T> {
if self.nelts == 0 {
return None;
impl<'a, T> DoubleEndedIterator<&'a mut T> for MutItems<'a, T> {
#[inline]
+ #[allow(deprecated)] // mut_shift_ref
fn next_back(&mut self) -> Option<&'a mut T> {
if self.nelts == 0 {
return None;
## Traits
A number of traits add methods that allow you to accomplish tasks with slices.
-These traits include `ImmutableVector`, which is defined for `&[T]` types,
-and `MutableVector`, defined for `&mut [T]` types.
+These traits include `ImmutableSlice`, which is defined for `&[T]` types,
+and `MutableSlice`, defined for `&mut [T]` types.
An example is the method `.slice(a, b)` that returns an immutable "view" into
a `Vec` or another slice from the index interval `[a, b)`:
use vec::Vec;
pub use core::slice::{ref_slice, mut_ref_slice, Splits, Windows};
-pub use core::slice::{Chunks, Vector, ImmutableVector, ImmutableEqVector};
-pub use core::slice::{ImmutableOrdVector, MutableVector, Items, MutItems};
+pub use core::slice::{Chunks, Slice, ImmutableSlice, ImmutablePartialEqSlice};
+pub use core::slice::{ImmutableOrdSlice, MutableSlice, Items, MutItems};
pub use core::slice::{MutSplits, MutChunks};
-pub use core::slice::{bytes, MutableCloneableVector};
+pub use core::slice::{bytes, MutableCloneableSlice};
+pub use core::slice::{BinarySearchResult, Found, NotFound};
// Functional utilities
fn connect_vec(&self, sep: &T) -> Vec<T>;
}
-impl<'a, T: Clone, V: Vector<T>> VectorVector<T> for &'a [V] {
+impl<'a, T: Clone, V: Slice<T>> VectorVector<T> for &'a [V] {
fn concat_vec(&self) -> Vec<T> {
let size = self.iter().fold(0u, |acc, v| acc + v.as_slice().len());
let mut result = Vec::with_capacity(size);
/// Extension methods for vectors such that their elements are
/// mutable.
-pub trait MutableVectorAllocating<'a, T> {
+pub trait MutableSliceAllocating<'a, T> {
/// Sort the vector, in place, using `compare` to compare
/// elements.
///
fn move_from(self, src: Vec<T>, start: uint, end: uint) -> uint;
}
-impl<'a,T> MutableVectorAllocating<'a, T> for &'a mut [T] {
+impl<'a,T> MutableSliceAllocating<'a, T> for &'a mut [T] {
#[inline]
fn sort_by(self, compare: |&T, &T| -> Ordering) {
merge_sort(self, compare)
/// Methods for mutable vectors with orderable elements, such as
/// in-place sorting.
-pub trait MutableOrdVector<T> {
+pub trait MutableOrdSlice<T> {
/// Sort the vector, in place.
///
/// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`.
fn prev_permutation(self) -> bool;
}
-impl<'a, T: Ord> MutableOrdVector<T> for &'a mut [T] {
+impl<'a, T: Ord> MutableOrdSlice<T> for &'a mut [T] {
#[inline]
fn sort(self) {
self.sort_by(|a,b| a.cmp(b))
use {Collection, MutableSeq};
use super::*;
- use std::slice::{Vector, ImmutableVector};
+ use std::slice::{Slice, ImmutableSlice};
use string::String;
use vec::Vec;
fn test_splitn_char_iterator() {
let data = "\nMäry häd ä little lämb\nLittle lämb\n";
- let split: Vec<&str> = data.splitn(' ', 3).collect();
+ let split: Vec<&str> = data.splitn(3, ' ').collect();
assert_eq!(split, vec!["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
- let split: Vec<&str> = data.splitn(|c: char| c == ' ', 3).collect();
+ let split: Vec<&str> = data.splitn(3, |c: char| c == ' ').collect();
assert_eq!(split, vec!["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
// Unicode
- let split: Vec<&str> = data.splitn('ä', 3).collect();
+ let split: Vec<&str> = data.splitn(3, 'ä').collect();
assert_eq!(split, vec!["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
- let split: Vec<&str> = data.splitn(|c: char| c == 'ä', 3).collect();
+ let split: Vec<&str> = data.splitn(3, |c: char| c == 'ä').collect();
assert_eq!(split, vec!["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
}
fn test_rsplitn_char_iterator() {
let data = "\nMäry häd ä little lämb\nLittle lämb\n";
- let mut split: Vec<&str> = data.rsplitn(' ', 3).collect();
+ let mut split: Vec<&str> = data.rsplitn(3, ' ').collect();
split.reverse();
assert_eq!(split, vec!["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
- let mut split: Vec<&str> = data.rsplitn(|c: char| c == ' ', 3).collect();
+ let mut split: Vec<&str> = data.rsplitn(3, |c: char| c == ' ').collect();
split.reverse();
assert_eq!(split, vec!["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
// Unicode
- let mut split: Vec<&str> = data.rsplitn('ä', 3).collect();
+ let mut split: Vec<&str> = data.rsplitn(3, 'ä').collect();
split.reverse();
assert_eq!(split, vec!["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
- let mut split: Vec<&str> = data.rsplitn(|c: char| c == 'ä', 3).collect();
+ let mut split: Vec<&str> = data.rsplitn(3, |c: char| c == 'ä').collect();
split.reverse();
assert_eq!(split, vec!["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
}
use core::fmt;
use core::mem;
use core::ptr;
-use core::raw::Slice;
+// FIXME: ICE's abound if you import the `Slice` type while importing `Slice` trait
+use RawSlice = core::raw::Slice;
+use core::slice::Slice;
use {Collection, Mutable, MutableSeq};
use hash;
use str;
-use str::{CharRange, StrAllocating, MaybeOwned, Owned, Slice};
+use str::{CharRange, StrAllocating, MaybeOwned, Owned};
+use MaybeOwnedSlice = str::Slice; // So many `Slice`s...
use vec::Vec;
/// A growable string stored as a UTF-8 encoded buffer.
/// ```
pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> MaybeOwned<'a> {
if str::is_utf8(v) {
- return Slice(unsafe { mem::transmute(v) })
+ return MaybeOwnedSlice(unsafe { mem::transmute(v) })
}
static TAG_CONT_U8: u8 = 128u8;
let mut i = 0;
let total = v.len();
fn unsafe_get(xs: &[u8], i: uint) -> u8 {
- unsafe { *xs.unsafe_ref(i) }
+ unsafe { *xs.unsafe_get(i) }
}
fn safe_get(xs: &[u8], i: uint, total: uint) -> u8 {
if i >= total {
unsafe {
// Attempt to not use an intermediate buffer by just pushing bytes
// directly onto this string.
- let slice = Slice {
+ let slice = RawSlice {
data: self.vec.as_ptr().offset(cur_len as int),
len: 4,
};
// such thing as invalid pointers and memory unsafety. The
// reason is performance, without doing this we can get the
// bench_iter_large microbenchmark down to about 30000 ns/iter
- // (using .unsafe_ref to index self.stack directly, 38000
+ // (using .unsafe_get to index self.stack directly, 38000
// ns/iter with [] checked indexing), but this smashes that down
// to 13500 ns/iter.
//
use core::prelude::*;
use alloc::heap::{allocate, reallocate, deallocate};
-use core::raw::Slice;
+use RawSlice = core::raw::Slice;
+use core::slice::Slice;
use core::cmp::max;
use core::default::Default;
use core::fmt;
use core::uint;
use {Collection, Mutable, MutableSeq};
-use slice::{MutableOrdVector, MutableVectorAllocating, CloneableVector};
+use slice::{MutableOrdSlice, MutableSliceAllocating, CloneableVector};
use slice::{Items, MutItems};
unsafe {
ptr::write(
self.as_mut_slice().unsafe_mut_ref(len),
- other.unsafe_ref(i).clone());
+ other.unsafe_get(i).clone());
self.set_len(len + 1);
}
}
impl<T: Eq> Eq for Vec<T> {}
-impl<T: PartialEq, V: Vector<T>> Equiv<V> for Vec<T> {
+impl<T: PartialEq, V: Slice<T>> Equiv<V> for Vec<T> {
#[inline]
fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() }
}
// decrement len before the read(), so a failure on Drop doesn't
// re-drop the just-failed value.
self.len -= 1;
- ptr::read(self.as_slice().unsafe_ref(self.len));
+ ptr::read(self.as_slice().unsafe_get(self.len));
}
}
}
#[inline]
pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
unsafe {
- mem::transmute(Slice {
+ mem::transmute(RawSlice {
data: self.as_mut_ptr() as *const T,
len: self.len,
})
/// assert!(vec.tailn(2) == [3, 4]);
/// ```
#[inline]
+ #[deprecated = "use slice_from"]
pub fn tailn<'a>(&'a self, n: uint) -> &'a [T] {
- self.as_slice().tailn(n)
+ self.as_slice().slice_from(n)
}
/// Returns a reference to the last element of a vector, or `None` if it is
}
}
-impl<T> Vector<T> for Vec<T> {
+impl<T> Slice<T> for Vec<T> {
/// Work with `self` as a slice.
///
/// # Example
/// ```
#[inline]
fn as_slice<'a>(&'a self) -> &'a [T] {
- unsafe { mem::transmute(Slice { data: self.as_ptr(), len: self.len }) }
+ unsafe { mem::transmute(RawSlice { data: self.as_ptr(), len: self.len }) }
}
}
-impl<T: Clone, V: Vector<T>> Add<V, Vec<T>> for Vec<T> {
+impl<T: Clone, V: Slice<T>> Add<V, Vec<T>> for Vec<T> {
#[inline]
fn add(&self, rhs: &V) -> Vec<T> {
let mut res = Vec::with_capacity(self.len() + rhs.as_slice().len());
} else {
unsafe {
self.len -= 1;
- Some(ptr::read(self.as_slice().unsafe_ref(self.len())))
+ Some(ptr::read(self.as_slice().unsafe_get(self.len())))
}
}
}
Less, Greater, Equal};
use option::{Option, Some, None};
- macro_rules! eq_impl(
+ macro_rules! partial_eq_impl(
($($t:ty)*) => ($(
#[unstable = "Trait is unstable."]
impl PartialEq for $t {
fn ne(&self, _other: &()) -> bool { false }
}
- eq_impl!(bool char uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
+ partial_eq_impl!(bool char uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
- macro_rules! totaleq_impl(
+ macro_rules! eq_impl(
($($t:ty)*) => ($(
#[unstable = "Trait is unstable."]
impl Eq for $t {}
)*)
)
- totaleq_impl!(() bool char uint u8 u16 u32 u64 int i8 i16 i32 i64)
+ eq_impl!(() bool char uint u8 u16 u32 u64 int i8 i16 i32 i64)
- macro_rules! ord_impl(
+ macro_rules! partial_ord_impl(
($($t:ty)*) => ($(
#[unstable = "Trait is unstable."]
impl PartialOrd for $t {
}
}
- ord_impl!(char uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
+ partial_ord_impl!(char uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64)
- macro_rules! totalord_impl(
+ macro_rules! ord_impl(
($($t:ty)*) => ($(
#[unstable = "Trait is unstable."]
impl Ord for $t {
}
}
- totalord_impl!(char uint u8 u16 u32 u64 int i8 i16 i32 i64)
+ ord_impl!(char uint u8 u16 u32 u64 int i8 i16 i32 i64)
// & pointers
#[unstable = "Trait is unstable."]
use num::{Float, FPNaN, FPInfinite, ToPrimitive, Primitive};
use num::{Zero, One, cast};
use result::Ok;
-use slice::{ImmutableVector, MutableVector};
+use slice::{ImmutableSlice, MutableSlice};
use slice;
use str::StrSlice;
use ops::Deref;
use result::{Ok, Err};
use result;
-use slice::{Vector, ImmutableVector};
+use slice::{Slice, ImmutableSlice};
use slice;
use str::StrSlice;
use str;
use fmt;
use iter::DoubleEndedIterator;
use num::{Int, cast, zero};
-use slice::{ImmutableVector, MutableVector};
+use slice::{ImmutableSlice, MutableSlice};
/// A type that represents a specific radix
#[doc(hidden)]
use cmp::{PartialEq, Eq, Ord};
use default::Default;
-use slice::Vector;
+use slice::Slice;
use iter::{Iterator, DoubleEndedIterator, FromIterator, ExactSize};
use mem;
use slice;
// Trait implementations
/////////////////////////////////////////////////////////////////////////////
-impl<T> Vector<T> for Option<T> {
+impl<T> Slice<T> for Option<T> {
/// Convert from `Option<T>` to `&[T]` (without copying)
#[inline]
fn as_slice<'a>(&'a self) -> &'a [T] {
pub use tuple::{Tuple1, Tuple2, Tuple3, Tuple4};
pub use tuple::{Tuple5, Tuple6, Tuple7, Tuple8};
pub use tuple::{Tuple9, Tuple10, Tuple11, Tuple12};
-pub use slice::{ImmutableEqVector, ImmutableOrdVector};
-pub use slice::{MutableVector};
-pub use slice::{Vector, ImmutableVector};
+pub use slice::{ImmutablePartialEqSlice, ImmutableOrdSlice};
+pub use slice::{MutableSlice};
+pub use slice::{Slice, ImmutableSlice};
//!
//! For more details `std::slice`.
+#![stable]
#![doc(primitive = "slice")]
// How this module is organized.
use mem;
use mem::size_of;
use kinds::marker;
-use raw::{Repr, Slice};
+use raw::Repr;
+// Avoid conflicts with *both* the Slice trait (buggy) and the `slice::raw` module.
+use RawSlice = raw::Slice;
+
//
// Extension traits
//
/// Extension methods for vectors
-pub trait ImmutableVector<'a, T> {
+#[unstable = "may merge with other traits; region parameter may disappear"]
+pub trait ImmutableSlice<'a, T> {
/**
* Returns a slice of self spanning the interval [`start`, `end`).
*
* Fails when the slice (or part of it) is outside the bounds of self,
* or when `start` > `end`.
*/
+ #[unstable]
fn slice(&self, start: uint, end: uint) -> &'a [T];
/**
*
* Fails when `start` points outside the bounds of self.
*/
+ #[unstable]
fn slice_from(&self, start: uint) -> &'a [T];
/**
*
* Fails when `end` points outside the bounds of self.
*/
+ #[unstable]
fn slice_to(&self, end: uint) -> &'a [T];
/// Divides one slice into two at an index.
/// indices from `[mid, len)` (excluding the index `len` itself).
///
/// Fails if `mid > len`.
+ #[unstable]
fn split_at(&self, mid: uint) -> (&'a [T], &'a [T]);
/// Returns an iterator over the vector
+ #[unstable = "iterator type may change"]
fn iter(self) -> Items<'a, T>;
/// Returns an iterator over the subslices of the vector which are
/// separated by elements that match `pred`. The matched element
/// is not contained in the subslices.
+ #[unstable = "iterator type may change"]
fn split(self, pred: |&T|: 'a -> bool) -> Splits<'a, T>;
/// Returns an iterator over the subslices of the vector which are
/// separated by elements that match `pred`, limited to splitting
/// at most `n` times. The matched element is not contained in
/// the subslices.
+ #[unstable = "iterator type may change"]
fn splitn(self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<'a, T>;
/// Returns an iterator over the subslices of the vector which are
/// separated by elements that match `pred` limited to splitting
/// at most `n` times. This starts at the end of the vector and
/// works backwards. The matched element is not contained in the
/// subslices.
+ #[unstable = "iterator type may change"]
fn rsplitn(self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<'a, T>;
/**
* ```
*
*/
+ #[unstable = "iterator type may change"]
fn windows(self, size: uint) -> Windows<'a, T>;
/**
*
* ```
*
*/
+ #[unstable = "iterator type may change"]
fn chunks(self, size: uint) -> Chunks<'a, T>;
/// Returns the element of a vector at the given index, or `None` if the
/// index is out of bounds
+ #[unstable]
fn get(&self, index: uint) -> Option<&'a T>;
/// Returns the first element of a vector, or `None` if it is empty
+ #[unstable = "name may change"]
fn head(&self) -> Option<&'a T>;
/// Returns all but the first element of a vector
+ #[unstable = "name may change"]
fn tail(&self) -> &'a [T];
/// Returns all but the first `n' elements of a vector
+ #[deprecated = "use slice_from"]
fn tailn(&self, n: uint) -> &'a [T];
/// Returns all but the last element of a vector
+ #[unstable = "name may change"]
fn init(&self) -> &'a [T];
/// Returns all but the last `n' elements of a vector
+ #[deprecated = "use slice_to but note the arguments are different"]
fn initn(&self, n: uint) -> &'a [T];
/// Returns the last element of a vector, or `None` if it is empty.
+ #[unstable = "name may change"]
fn last(&self) -> Option<&'a T>;
/// Returns a pointer to the element at the given index, without doing
/// bounds checking.
+ #[deprecated = "renamed to `unsafe_get`"]
unsafe fn unsafe_ref(self, index: uint) -> &'a T;
+ /// Returns a pointer to the element at the given index, without doing
+ /// bounds checking.
+ #[unstable]
+ unsafe fn unsafe_get(self, index: uint) -> &'a T;
+
/**
* Returns an unsafe pointer to the vector's buffer
*
* Modifying the vector may cause its buffer to be reallocated, which
* would also make any pointers to it invalid.
*/
+ #[unstable]
fn as_ptr(&self) -> *const T;
/**
* Returns the index where the comparator returned `Equal`, or `None` if
* not found.
*/
+ #[deprecated = "use binary_search"]
fn bsearch(&self, f: |&T| -> Ordering) -> Option<uint>;
+ /// Binary search a sorted vector with a comparator function.
+ ///
+ /// The comparator function should implement an order consistent
+ /// with the sort order of the underlying vector, returning an
+ /// order code that indicates whether its argument is `Less`,
+ /// `Equal` or `Greater` the desired target.
+ ///
+ /// If the value is found then `Found` is returned, containing the
+ /// index of the matching element; if the value is not found then
+ /// `NotFound` is returned, containing the index where a matching
+ /// element could be inserted while maintaining sorted order.
+ #[unstable]
+ fn binary_search(&self, f: |&T| -> Ordering) -> BinarySearchResult;
+
/**
* Returns an immutable reference to the first element in this slice
* and adjusts the slice in place so that it no longer contains
*
* Returns `None` if vector is empty
*/
+ #[deprecated = "find some other way. sorry"]
fn shift_ref(&mut self) -> Option<&'a T>;
/**
*
* Returns `None` if slice is empty.
*/
+ #[deprecated = "find some other way. sorry"]
fn pop_ref(&mut self) -> Option<&'a T>;
}
-impl<'a,T> ImmutableVector<'a, T> for &'a [T] {
+#[unstable]
+impl<'a,T> ImmutableSlice<'a, T> for &'a [T] {
#[inline]
fn slice(&self, start: uint, end: uint) -> &'a [T] {
assert!(start <= end);
assert!(end <= self.len());
unsafe {
- transmute(Slice {
+ transmute(RawSlice {
data: self.as_ptr().offset(start as int),
len: (end - start)
})
fn tail(&self) -> &'a [T] { self.slice(1, self.len()) }
#[inline]
+ #[deprecated = "use slice_from"]
fn tailn(&self, n: uint) -> &'a [T] { self.slice(n, self.len()) }
#[inline]
}
#[inline]
+ #[deprecated = "use slice_to but note the arguments are different"]
fn initn(&self, n: uint) -> &'a [T] {
self.slice(0, self.len() - n)
}
}
#[inline]
+ #[deprecated = "renamed to `unsafe_get`"]
unsafe fn unsafe_ref(self, index: uint) -> &'a T {
transmute(self.repr().data.offset(index as int))
}
+ #[inline]
+ unsafe fn unsafe_get(self, index: uint) -> &'a T {
+ transmute(self.repr().data.offset(index as int))
+ }
+
#[inline]
fn as_ptr(&self) -> *const T {
self.repr().data
}
+ #[deprecated = "use binary_search"]
fn bsearch(&self, f: |&T| -> Ordering) -> Option<uint> {
let mut base : uint = 0;
let mut lim : uint = self.len();
return None;
}
+ #[unstable]
+ fn binary_search(&self, f: |&T| -> Ordering) -> BinarySearchResult {
+ let mut base : uint = 0;
+ let mut lim : uint = self.len();
+
+ while lim != 0 {
+ let ix = base + (lim >> 1);
+ match f(&self[ix]) {
+ Equal => return Found(ix),
+ Less => {
+ base = ix + 1;
+ lim -= 1;
+ }
+ Greater => ()
+ }
+ lim >>= 1;
+ }
+ return NotFound(base);
+ }
+
fn shift_ref(&mut self) -> Option<&'a T> {
unsafe {
- let s: &mut Slice<T> = transmute(self);
+ let s: &mut RawSlice<T> = transmute(self);
match raw::shift_ptr(s) {
Some(p) => Some(&*p),
None => None
fn pop_ref(&mut self) -> Option<&'a T> {
unsafe {
- let s: &mut Slice<T> = transmute(self);
+ let s: &mut RawSlice<T> = transmute(self);
match raw::pop_ptr(s) {
Some(p) => Some(&*p),
None => None
/// Extension methods for vectors such that their elements are
/// mutable.
-pub trait MutableVector<'a, T> {
+#[experimental = "may merge with other traits; may lose region param; needs review"]
+pub trait MutableSlice<'a, T> {
/// Returns a mutable reference to the element at the given index,
/// or `None` if the index is out of bounds
fn get_mut(self, index: uint) -> Option<&'a mut T>;
*
* Returns `None` if slice is empty
*/
+ #[deprecated = "find some other way. sorry"]
fn mut_shift_ref(&mut self) -> Option<&'a mut T>;
/**
*
* Returns `None` if slice is empty.
*/
+ #[deprecated = "find some other way. sorry"]
fn mut_pop_ref(&mut self) -> Option<&'a mut T>;
/// Swaps two elements in a vector.
unsafe fn copy_memory(self, src: &[T]);
}
-impl<'a,T> MutableVector<'a, T> for &'a mut [T] {
+#[experimental = "trait is experimental"]
+impl<'a,T> MutableSlice<'a, T> for &'a mut [T] {
#[inline]
fn get_mut(self, index: uint) -> Option<&'a mut T> {
if index < self.len() { Some(&mut self[index]) } else { None }
assert!(start <= end);
assert!(end <= self.len());
unsafe {
- transmute(Slice {
+ transmute(RawSlice {
data: self.as_mut_ptr().offset(start as int) as *const T,
len: (end - start)
})
fn mut_shift_ref(&mut self) -> Option<&'a mut T> {
unsafe {
- let s: &mut Slice<T> = transmute(self);
+ let s: &mut RawSlice<T> = transmute(self);
match raw::shift_ptr(s) {
// FIXME #13933: this `&` -> `&mut` cast is a little
// dubious
fn mut_pop_ref(&mut self) -> Option<&'a mut T> {
unsafe {
- let s: &mut Slice<T> = transmute(self);
+ let s: &mut RawSlice<T> = transmute(self);
match raw::pop_ptr(s) {
// FIXME #13933: this `&` -> `&mut` cast is a little
// dubious
}
/// Extension methods for vectors contain `PartialEq` elements.
-pub trait ImmutableEqVector<T:PartialEq> {
+#[unstable = "may merge with other traits"]
+pub trait ImmutablePartialEqSlice<T:PartialEq> {
/// Find the first index containing a matching value
fn position_elem(&self, t: &T) -> Option<uint>;
fn ends_with(&self, needle: &[T]) -> bool;
}
-impl<'a,T:PartialEq> ImmutableEqVector<T> for &'a [T] {
+#[unstable = "trait is unstable"]
+impl<'a,T:PartialEq> ImmutablePartialEqSlice<T> for &'a [T] {
#[inline]
fn position_elem(&self, x: &T) -> Option<uint> {
self.iter().position(|y| *x == *y)
}
/// Extension methods for vectors containing `Ord` elements.
-pub trait ImmutableOrdVector<T: Ord> {
+#[unstable = "may merge with other traits"]
+pub trait ImmutableOrdSlice<T: Ord> {
/**
* Binary search a sorted vector for a given element.
*
* Returns the index of the element or None if not found.
*/
+ #[deprecated = "use binary_search_elem"]
fn bsearch_elem(&self, x: &T) -> Option<uint>;
+
+ /**
+ * Binary search a sorted vector for a given element.
+ *
+ * If the value is found then `Found` is returned, containing the
+ * index of the matching element; if the value is not found then
+ * `NotFound` is returned, containing the index where a matching
+ * element could be inserted while maintaining sorted order.
+ */
+ #[unstable]
+ fn binary_search_elem(&self, x: &T) -> BinarySearchResult;
}
-impl<'a, T: Ord> ImmutableOrdVector<T> for &'a [T] {
+#[unstable = "trait is unstable"]
+impl<'a, T: Ord> ImmutableOrdSlice<T> for &'a [T] {
+ #[deprecated = "use binary_search_elem"]
+ #[allow(deprecated)]
fn bsearch_elem(&self, x: &T) -> Option<uint> {
self.bsearch(|p| p.cmp(x))
}
+
+ #[unstable]
+ fn binary_search_elem(&self, x: &T) -> BinarySearchResult {
+ self.binary_search(|p| p.cmp(x))
+ }
}
/// Trait for &[T] where T is Cloneable
-pub trait MutableCloneableVector<T> {
+#[unstable = "may merge with other traits"]
+pub trait MutableCloneableSlice<T> {
+ /// Copies as many elements from `src` as it can into `self` (the
+ /// shorter of `self.len()` and `src.len()`). Returns the number
+ /// of elements copied.
+ #[deprecated = "renamed to clone_from_slice"]
+ fn copy_from(self, s: &[T]) -> uint { self.clone_from_slice(s) }
+
/// Copies as many elements from `src` as it can into `self` (the
/// shorter of `self.len()` and `src.len()`). Returns the number
/// of elements copied.
/// # Example
///
/// ```rust
- /// use std::slice::MutableCloneableVector;
+ /// use std::slice::MutableCloneableSlice;
///
/// let mut dst = [0i, 0, 0];
/// let src = [1i, 2];
/// assert!(dst.copy_from(src2) == 3);
/// assert!(dst == [3i, 4, 5]);
/// ```
- fn copy_from(self, &[T]) -> uint;
+ fn clone_from_slice(self, &[T]) -> uint;
}
-impl<'a, T:Clone> MutableCloneableVector<T> for &'a mut [T] {
+#[unstable = "trait is unstable"]
+impl<'a, T:Clone> MutableCloneableSlice<T> for &'a mut [T] {
#[inline]
- fn copy_from(self, src: &[T]) -> uint {
+ fn clone_from_slice(self, src: &[T]) -> uint {
for (a, b) in self.mut_iter().zip(src.iter()) {
a.clone_from(b);
}
//
/// Any vector that can be represented as a slice.
-pub trait Vector<T> {
+#[unstable = "may merge with other traits"]
+pub trait Slice<T> {
/// Work with `self` as a slice.
fn as_slice<'a>(&'a self) -> &'a [T];
}
-impl<'a,T> Vector<T> for &'a [T] {
+#[unstable = "trait is unstable"]
+impl<'a,T> Slice<T> for &'a [T] {
#[inline(always)]
fn as_slice<'a>(&'a self) -> &'a [T] { *self }
}
+#[experimental = "trait is experimental"]
impl<'a, T> Collection for &'a [T] {
/// Returns the length of a vector
#[inline]
}
}
+#[unstable = "waiting for DST"]
impl<'a, T> Default for &'a [T] {
fn default() -> &'a [T] { &[] }
}
// The shared definition of the `Item` and `MutItems` iterators
macro_rules! iterator {
(struct $name:ident -> $ptr:ty, $elem:ty) => {
+ #[experimental = "needs review"]
impl<'a, T> Iterator<$elem> for $name<'a, T> {
#[inline]
fn next(&mut self) -> Option<$elem> {
}
}
+ #[experimental = "needs review"]
impl<'a, T> DoubleEndedIterator<$elem> for $name<'a, T> {
#[inline]
fn next_back(&mut self) -> Option<$elem> {
}
/// Immutable slice iterator
+#[experimental = "needs review"]
pub struct Items<'a, T> {
ptr: *const T,
end: *const T,
iterator!{struct Items -> *const T, &'a T}
+#[experimental = "needs review"]
impl<'a, T> ExactSize<&'a T> for Items<'a, T> {}
+#[experimental = "needs review"]
impl<'a, T> Clone for Items<'a, T> {
fn clone(&self) -> Items<'a, T> { *self }
}
+#[experimental = "needs review"]
impl<'a, T> RandomAccessIterator<&'a T> for Items<'a, T> {
#[inline]
fn indexable(&self) -> uint {
}
/// Mutable slice iterator
+#[experimental = "needs review"]
pub struct MutItems<'a, T> {
ptr: *mut T,
end: *mut T,
iterator!{struct MutItems -> *mut T, &'a mut T}
+#[experimental = "needs review"]
impl<'a, T> ExactSize<&'a mut T> for MutItems<'a, T> {}
/// An iterator over the slices of a vector separated by elements that
/// match a predicate function.
+#[experimental = "needs review"]
pub struct Splits<'a, T> {
v: &'a [T],
pred: |t: &T|: 'a -> bool,
finished: bool
}
+#[experimental = "needs review"]
impl<'a, T> Iterator<&'a [T]> for Splits<'a, T> {
#[inline]
fn next(&mut self) -> Option<&'a [T]> {
}
}
+#[experimental = "needs review"]
impl<'a, T> DoubleEndedIterator<&'a [T]> for Splits<'a, T> {
#[inline]
fn next_back(&mut self) -> Option<&'a [T]> {
/// An iterator over the subslices of the vector which are separated
/// by elements that match `pred`.
+#[experimental = "needs review"]
pub struct MutSplits<'a, T> {
v: &'a mut [T],
pred: |t: &T|: 'a -> bool,
finished: bool
}
+#[experimental = "needs review"]
impl<'a, T> Iterator<&'a mut [T]> for MutSplits<'a, T> {
#[inline]
fn next(&mut self) -> Option<&'a mut [T]> {
}
}
+#[experimental = "needs review"]
impl<'a, T> DoubleEndedIterator<&'a mut [T]> for MutSplits<'a, T> {
#[inline]
fn next_back(&mut self) -> Option<&'a mut [T]> {
/// An iterator over the slices of a vector separated by elements that
/// match a predicate function, splitting at most a fixed number of times.
+#[experimental = "needs review"]
pub struct SplitsN<'a, T> {
iter: Splits<'a, T>,
count: uint,
invert: bool
}
+#[experimental = "needs review"]
impl<'a, T> Iterator<&'a [T]> for SplitsN<'a, T> {
#[inline]
fn next(&mut self) -> Option<&'a [T]> {
/// An iterator over the (overlapping) slices of length `size` within
/// a vector.
#[deriving(Clone)]
+#[experimental = "needs review"]
pub struct Windows<'a, T> {
v: &'a [T],
size: uint
}
+#[experimental = "needs review"]
impl<'a, T> Iterator<&'a [T]> for Windows<'a, T> {
#[inline]
fn next(&mut self) -> Option<&'a [T]> {
/// When the vector len is not evenly divided by the chunk size,
/// the last slice of the iteration will be the remainder.
#[deriving(Clone)]
+#[experimental = "needs review"]
pub struct Chunks<'a, T> {
v: &'a [T],
size: uint
}
+#[experimental = "needs review"]
impl<'a, T> Iterator<&'a [T]> for Chunks<'a, T> {
#[inline]
fn next(&mut self) -> Option<&'a [T]> {
}
}
+#[experimental = "needs review"]
impl<'a, T> DoubleEndedIterator<&'a [T]> for Chunks<'a, T> {
#[inline]
fn next_back(&mut self) -> Option<&'a [T]> {
}
}
+#[experimental = "needs review"]
impl<'a, T> RandomAccessIterator<&'a [T]> for Chunks<'a, T> {
#[inline]
fn indexable(&self) -> uint {
/// An iterator over a vector in (non-overlapping) mutable chunks (`size` elements at a time). When
/// the vector len is not evenly divided by the chunk size, the last slice of the iteration will be
/// the remainder.
+#[experimental = "needs review"]
pub struct MutChunks<'a, T> {
v: &'a mut [T],
chunk_size: uint
}
+#[experimental = "needs review"]
impl<'a, T> Iterator<&'a mut [T]> for MutChunks<'a, T> {
#[inline]
fn next(&mut self) -> Option<&'a mut [T]> {
}
}
+#[experimental = "needs review"]
impl<'a, T> DoubleEndedIterator<&'a mut [T]> for MutChunks<'a, T> {
#[inline]
fn next_back(&mut self) -> Option<&'a mut [T]> {
+/// The result of calling `binary_search`.
+///
+/// `Found` means the search succeeded, and the contained value is the
+/// index of the matching element. `NotFound` means the search
+/// succeeded, and the contained value is an index where a matching
+/// value could be inserted while maintaining sort order.
+#[deriving(PartialEq, Show)]
+#[experimental = "needs review"]
+pub enum BinarySearchResult {
+ /// The index of the found value.
+ Found(uint),
+ /// The index where the value should have been found.
+ NotFound(uint)
+}
+
+#[experimental = "needs review"]
+impl BinarySearchResult {
+ /// Converts a `Found` to `Some`, `NotFound` to `None`.
+ /// Similar to `Result::ok`.
+ pub fn found(&self) -> Option<uint> {
+ match *self {
+ Found(i) => Some(i),
+ NotFound(_) => None
+ }
+ }
+
+ /// Convert a `Found` to `None`, `NotFound` to `Some`.
+ /// Similar to `Result::err`.
+ pub fn not_found(&self) -> Option<uint> {
+ match *self {
+ Found(_) => None,
+ NotFound(i) => Some(i)
+ }
+ }
+}
+
+
//
// Free functions
/**
* Converts a pointer to A into a slice of length 1 (without copying).
*/
+#[unstable = "waiting for DST"]
pub fn ref_slice<'a, A>(s: &'a A) -> &'a [A] {
unsafe {
- transmute(Slice { data: s, len: 1 })
+ transmute(RawSlice { data: s, len: 1 })
}
}
/**
* Converts a pointer to A into a slice of length 1 (without copying).
*/
+#[unstable = "waiting for DST"]
pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] {
unsafe {
let ptr: *const A = transmute(s);
- transmute(Slice { data: ptr, len: 1 })
+ transmute(RawSlice { data: ptr, len: 1 })
}
}
//
/// Unsafe operations
+#[experimental = "needs review"]
pub mod raw {
use mem::transmute;
use ptr::RawPtr;
}
/// Operations on `[u8]`.
+#[experimental = "needs review"]
pub mod bytes {
use collections::Collection;
use ptr;
- use slice::MutableVector;
+ use slice::MutableSlice;
/// A trait for operations on mutable `[u8]`s.
pub trait MutableByteVector {
// Boilerplate traits
//
+#[unstable = "waiting for DST"]
impl<'a,T:PartialEq> PartialEq for &'a [T] {
fn eq(&self, other: & &'a [T]) -> bool {
self.len() == other.len() &&
}
}
+#[unstable = "waiting for DST"]
impl<'a,T:Eq> Eq for &'a [T] {}
-impl<'a,T:PartialEq, V: Vector<T>> Equiv<V> for &'a [T] {
+#[unstable = "waiting for DST"]
+impl<'a,T:PartialEq, V: Slice<T>> Equiv<V> for &'a [T] {
#[inline]
fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() }
}
+#[unstable = "waiting for DST"]
impl<'a,T:Ord> Ord for &'a [T] {
fn cmp(&self, other: & &'a [T]) -> Ordering {
order::cmp(self.iter(), other.iter())
}
}
+#[unstable = "waiting for DST"]
impl<'a, T: PartialOrd> PartialOrd for &'a [T] {
#[inline]
fn partial_cmp(&self, other: &&'a [T]) -> Option<Ordering> {
use num::{CheckedMul, Saturating};
use option::{Option, None, Some};
use raw::Repr;
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
use slice;
use uint;
use collections::Collection;
use ptr::RawPtr;
use raw::Slice;
- use slice::{ImmutableVector};
+ use slice::{ImmutableSlice};
use str::{is_utf8, StrSlice};
/// Converts a slice of bytes to a string slice without checking
/// # Example
///
/// ```rust
- /// let v: Vec<&str> = "Mary had a little lambda".splitn(' ', 2).collect();
+ /// let v: Vec<&str> = "Mary had a little lambda".splitn(2, ' ').collect();
/// assert_eq!(v, vec!["Mary", "had", "a little lambda"]);
///
- /// let v: Vec<&str> = "abc1def2ghi".splitn(|c: char| c.is_digit(), 1).collect();
+ /// let v: Vec<&str> = "abc1def2ghi".splitn(1, |c: char| c.is_digit()).collect();
/// assert_eq!(v, vec!["abc", "def2ghi"]);
///
- /// let v: Vec<&str> = "lionXXtigerXleopard".splitn('X', 2).collect();
+ /// let v: Vec<&str> = "lionXXtigerXleopard".splitn(2, 'X').collect();
/// assert_eq!(v, vec!["lion", "", "tigerXleopard"]);
///
- /// let v: Vec<&str> = "abcXdef".splitn('X', 0).collect();
+ /// let v: Vec<&str> = "abcXdef".splitn(0, 'X').collect();
/// assert_eq!(v, vec!["abcXdef"]);
///
- /// let v: Vec<&str> = "".splitn('X', 1).collect();
+ /// let v: Vec<&str> = "".splitn(1, 'X').collect();
/// assert_eq!(v, vec![""]);
/// ```
- fn splitn<Sep: CharEq>(&self, sep: Sep, count: uint) -> CharSplitsN<'a, Sep>;
+ fn splitn<Sep: CharEq>(&self, count: uint, sep: Sep) -> CharSplitsN<'a, Sep>;
/// An iterator over substrings of `self`, separated by characters
/// matched by `sep`.
/// # Example
///
/// ```rust
- /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(' ', 2).collect();
+ /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(2, ' ').collect();
/// assert_eq!(v, vec!["lamb", "little", "Mary had a"]);
///
- /// let v: Vec<&str> = "abc1def2ghi".rsplitn(|c: char| c.is_digit(), 1).collect();
+ /// let v: Vec<&str> = "abc1def2ghi".rsplitn(1, |c: char| c.is_digit()).collect();
/// assert_eq!(v, vec!["ghi", "abc1def"]);
///
- /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn('X', 2).collect();
+ /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(2, 'X').collect();
/// assert_eq!(v, vec!["leopard", "tiger", "lionX"]);
/// ```
- fn rsplitn<Sep: CharEq>(&self, sep: Sep, count: uint) -> CharSplitsN<'a, Sep>;
+ fn rsplitn<Sep: CharEq>(&self, count: uint, sep: Sep) -> CharSplitsN<'a, Sep>;
/// An iterator over the start and end indices of the disjoint
/// matches of `sep` within `self`.
}
#[inline]
- fn splitn<Sep: CharEq>(&self, sep: Sep, count: uint)
+ fn splitn<Sep: CharEq>(&self, count: uint, sep: Sep)
-> CharSplitsN<'a, Sep> {
CharSplitsN {
iter: self.split(sep),
}
#[inline]
- fn rsplitn<Sep: CharEq>(&self, sep: Sep, count: uint)
+ fn rsplitn<Sep: CharEq>(&self, count: uint, sep: Sep)
-> CharSplitsN<'a, Sep> {
CharSplitsN {
iter: self.split(sep),
mod ptr;
mod raw;
mod result;
+mod slice;
mod tuple;
--- /dev/null
+// 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.
+
+use std::slice::{Found, NotFound};
+
+#[test]
+fn binary_search_not_found() {
+ let b = [1i, 2, 4, 6, 8, 9];
+ assert!(b.binary_search(|v| v.cmp(&6)) == Found(3));
+ let b = [1i, 2, 4, 6, 8, 9];
+ assert!(b.binary_search(|v| v.cmp(&5)) == NotFound(3));
+ let b = [1i, 2, 4, 6, 7, 8, 9];
+ assert!(b.binary_search(|v| v.cmp(&6)) == Found(3));
+ let b = [1i, 2, 4, 6, 7, 8, 9];
+ assert!(b.binary_search(|v| v.cmp(&5)) == NotFound(3));
+ let b = [1i, 2, 4, 6, 8, 9];
+ assert!(b.binary_search(|v| v.cmp(&8)) == Found(4));
+ let b = [1i, 2, 4, 6, 8, 9];
+ assert!(b.binary_search(|v| v.cmp(&7)) == NotFound(4));
+ let b = [1i, 2, 4, 6, 7, 8, 9];
+ assert!(b.binary_search(|v| v.cmp(&8)) == Found(5));
+ let b = [1i, 2, 4, 5, 6, 8, 9];
+ assert!(b.binary_search(|v| v.cmp(&7)) == NotFound(5));
+ let b = [1i, 2, 4, 5, 6, 8, 9];
+ assert!(b.binary_search(|v| v.cmp(&0)) == NotFound(0));
+ let b = [1i, 2, 4, 5, 6, 8];
+ assert!(b.binary_search(|v| v.cmp(&9)) == NotFound(6));
+}
}
}
-impl<'a, T: PartialEq, V: Vector<T>> Equiv<V> for MaybeOwnedVector<'a, T> {
+impl<'a, T: PartialEq, V: Slice<T>> Equiv<V> for MaybeOwnedVector<'a, T> {
fn equiv(&self, other: &V) -> bool {
self.as_slice() == other.as_slice()
}
// In any case, with `Vector` in place, the client can just use
// `as_slice` if they prefer that over `match`.
-impl<'b,T> slice::Vector<T> for MaybeOwnedVector<'b,T> {
+impl<'b,T> Slice<T> for MaybeOwnedVector<'b,T> {
fn as_slice<'a>(&'a self) -> &'a [T] {
match self {
&Growable(ref v) => v.as_slice(),
use std::rt::task::TaskOpts;
use std::rt::task::Task;
use std::rt::local::Local;
+ use std::time::Duration;
use {TaskState, PoolConfig, SchedPool};
use basic;
// doesn't exit before emptying the work queue
pool.spawn(TaskOpts::new(), proc() {
spawn(proc() {
- timer::sleep(10);
+ timer::sleep(Duration::milliseconds(10));
});
});
}
}
- #[cfg(target_os = "win32")]
+ #[cfg(target_os = "windows")]
+ #[cfg(stage0, target_os = "win32")] // NOTE: Remove after snapshot
pub mod os {
pub mod common {
pub mod posix01 {
// Consts tend to vary per OS so we pull their definitions out
// into this module.
- #[cfg(target_os = "win32")]
+ #[cfg(target_os = "windows")]
+ #[cfg(stage0, target_os = "win32")] // NOTE: Remove after snapshot
pub mod os {
pub mod c95 {
use types::os::arch::c95::{c_int, c_uint};
// so be careful when trying to write portable code; it won't always work
// with the same POSIX functions and types as other platforms.
- #[cfg(target_os = "win32")]
+ #[cfg(target_os = "windows")]
+ #[cfg(stage0, target_os = "win32")] // NOTE: Remove after snapshot
pub mod posix88 {
pub mod stat_ {
use types::os::common::posix01::{stat, utimbuf};
}
}
- #[cfg(target_os = "win32")]
+ #[cfg(target_os = "windows")]
+ #[cfg(stage0, target_os = "win32")] // NOTE: Remove after snapshot
pub mod posix01 {
pub mod stat_ {
}
}
- #[cfg(target_os = "win32")]
+ #[cfg(target_os = "windows")]
+ #[cfg(stage0, target_os = "win32")] // NOTE: Remove after snapshot
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
#[cfg(target_os = "macos")]
}
- #[cfg(target_os = "win32")]
+ #[cfg(target_os = "windows")]
+ #[cfg(stage0, target_os = "win32")] // NOTE: Remove after snapshot
pub mod bsd44 {
}
}
- #[cfg(target_os = "win32")]
+ #[cfg(target_os = "windows")]
+ #[cfg(stage0, target_os = "win32")] // NOTE: Remove after snapshot
pub mod extra {
pub mod kernel32 {
#[path = "timer_unix.rs"]
pub mod timer;
-#[cfg(target_os = "win32")]
+#[cfg(target_os = "windows")]
+#[cfg(stage0, target_os = "win32")] // NOTE: Remove after snapshot
#[path = "timer_win32.rs"]
pub mod timer;
rtio::Ignored => { ret.push(None); Ok(None) }
rtio::InheritFd(fd) => {
ret.push(None);
- Ok(Some(file::FileDesc::new(fd, true)))
+ Ok(Some(file::FileDesc::new(fd, false)))
}
rtio::CreatePipe(readable, _writable) => {
let (reader, writer) = try!(pipe());
FromStr for Ratio<T> {
/// Parses `numer/denom` or just `numer`.
fn from_str(s: &str) -> Option<Ratio<T>> {
- let mut split = s.splitn('/', 1);
+ let mut split = s.splitn(1, '/');
let num = split.next().and_then(|n| FromStr::from_str(n));
let den = split.next().or(Some("1")).and_then(|d| FromStr::from_str(d));
FromStrRadix for Ratio<T> {
/// Parses `numer/denom` where the numbers are in base `radix`.
fn from_str_radix(s: &str, radix: uint) -> Option<Ratio<T>> {
- let split: Vec<&str> = s.splitn('/', 1).collect();
+ let split: Vec<&str> = s.splitn(1, '/').collect();
if split.len() < 2 {
None
} else {
static MP_VEC: [(uint, uint), .. 2] = [(0,MIDPOINT), (MIDPOINT, 0)];
macro_rules! ind (
($x:expr) => {
- *self.mem.unsafe_ref(($x as uint >> 3) & (RAND_SIZE_64 - 1))
+ *self.mem.unsafe_get(($x as uint >> 3) & (RAND_SIZE_64 - 1))
}
);
let mix = if $j == 0 {!mix} else {mix};
unsafe {
- let x = *self.mem.unsafe_ref(base + mr_offset);
- a = mix + *self.mem.unsafe_ref(base + m2_offset);
+ let x = *self.mem.unsafe_get(base + mr_offset);
+ a = mix + *self.mem.unsafe_get(base + m2_offset);
let y = ind!(x) + a + b;
self.mem.unsafe_set(base + mr_offset, y);
let mix = if $j == 0 {!mix} else {mix};
unsafe {
- let x = *self.mem.unsafe_ref(base + mr_offset);
- a = mix + *self.mem.unsafe_ref(base + m2_offset);
+ let x = *self.mem.unsafe_get(base + mr_offset);
+ a = mix + *self.mem.unsafe_get(base + m2_offset);
let y = ind!(x) + a + b;
self.mem.unsafe_set(base + mr_offset, y);
self.isaac64();
}
self.cnt -= 1;
- unsafe { *self.rsl.unsafe_ref(self.cnt) }
+ unsafe { *self.rsl.unsafe_get(self.cnt) }
}
}
use std::fmt;
use std::iter;
use std::num;
+use std::slice;
/// Static data containing Unicode ranges for general categories and scripts.
use unicode::regex::{UNICODE_CLASSES, PERLD, PERLS, PERLW};
min = try!(self.parse_uint(inner.as_slice()));
max = Some(min);
} else {
- let pieces: Vec<&str> = inner.as_slice().splitn(',', 1).collect();
+ let pieces: Vec<&str> = inner.as_slice().splitn(1, ',').collect();
let (smin, smax) = (pieces[0], pieces[1]);
if smin.len() == 0 {
return self.err("Max repetitions cannot be specified \
}
fn find_class(classes: NamedClasses, name: &str) -> Option<Vec<(char, char)>> {
- match classes.bsearch(|&(s, _)| s.cmp(&name)) {
- Some(i) => Some(Vec::from_slice(classes[i].val1())),
- None => None,
+ match classes.binary_search(|&(s, _)| s.cmp(&name)) {
+ slice::Found(i) => Some(Vec::from_slice(classes[i].val1())),
+ slice::NotFound(_) => None,
}
}
use std::cmp;
use std::mem;
-use std::slice::MutableVector;
+use std::slice::MutableSlice;
use compile::{
Program,
Match, OneChar, CharClass, Any, EmptyBegin, EmptyEnd, EmptyWordBoundary,
let negate = flags & FLAG_NEGATED > 0;
let casei = flags & FLAG_NOCASE > 0;
let found = ranges.as_slice();
- let found = found.bsearch(|&rc| class_cmp(casei, c, rc));
- let found = found.is_some();
+ let found = found.binary_search(|&rc| class_cmp(casei, c, rc))
+ .found().is_some();
if found ^ negate {
self.add(nlist, pc+1, caps);
}
// Try the common ASCII case before invoking binary search.
match c {
'_' | '0' .. '9' | 'a' .. 'z' | 'A' .. 'Z' => true,
- _ => PERLW.bsearch(|&(start, end)| {
+ _ => PERLW.binary_search(|&(start, end)| {
if c >= start && c <= end {
Equal
} else if start > c {
} else {
Less
}
- }).is_some()
+ }).found().is_some()
}
}
use core::iter::Iterator;
use core::collections::Collection;
use core::str::StrSlice;
- use core::slice::{MutableVector, ImmutableVector};
+ use core::slice::{MutableSlice, ImmutableSlice};
use super::{memcmp, memset, memcpy, memmove};
// OSX has -dead_strip, which doesn't rely on ffunction_sections
// FIXME(#13846) this should be enabled for windows
let ffunction_sections = sess.targ_cfg.os != abi::OsMacos &&
- sess.targ_cfg.os != abi::OsWin32;
+ sess.targ_cfg.os != abi::OsWindows;
let fdata_sections = ffunction_sections;
let reloc_model = match sess.opts.cg.relocation_model.as_slice() {
// instead of hard-coded gcc.
// For win32, there is no cc command, so we add a condition to make it use gcc.
match sess.targ_cfg.os {
- abi::OsWin32 => "gcc",
+ abi::OsWindows => "gcc",
_ => "cc",
}.to_string()
}
}
config::CrateTypeDylib => {
let (prefix, suffix) = match sess.targ_cfg.os {
- abi::OsWin32 => (loader::WIN32_DLL_PREFIX, loader::WIN32_DLL_SUFFIX),
+ abi::OsWindows => (loader::WIN32_DLL_PREFIX, loader::WIN32_DLL_SUFFIX),
abi::OsMacos => (loader::MACOS_DLL_PREFIX, loader::MACOS_DLL_SUFFIX),
abi::OsLinux => (loader::LINUX_DLL_PREFIX, loader::LINUX_DLL_SUFFIX),
abi::OsAndroid => (loader::ANDROID_DLL_PREFIX, loader::ANDROID_DLL_SUFFIX),
}
config::CrateTypeExecutable => {
match sess.targ_cfg.os {
- abi::OsWin32 => out_filename.with_extension("exe"),
+ abi::OsWindows => out_filename.with_extension("exe"),
abi::OsMacos |
abi::OsLinux |
abi::OsAndroid |
// subset we wanted.
//
// FIXME(#11937) we should invoke the system linker directly
- if sess.targ_cfg.os != abi::OsWin32 {
+ if sess.targ_cfg.os != abi::OsWindows {
cmd.arg("-nodefaultlibs");
}
cmd.arg("-Wl,-dead_strip");
}
- if sess.targ_cfg.os == abi::OsWin32 {
+ if sess.targ_cfg.os == abi::OsWindows {
// Make sure that we link to the dynamic libgcc, otherwise cross-module
// DWARF stack unwinding will not work.
// This behavior may be overridden by --link-args "-static-libgcc"
// Converts a library file-stem into a cc -l argument
fn unlib<'a>(config: &config::Config, stem: &'a [u8]) -> &'a [u8] {
- if stem.starts_with("lib".as_bytes()) && config.os != abi::OsWin32 {
+ if stem.starts_with("lib".as_bytes()) && config.os != abi::OsWindows {
stem.tailn(3)
} else {
stem
{
let mut cg = basic_codegen_options();
for option in matches.opt_strs("C").move_iter() {
- let mut iter = option.as_slice().splitn('=', 1);
+ let mut iter = option.as_slice().splitn(1, '=');
let key = iter.next().unwrap();
let value = iter.next();
let option_to_lookup = key.replace("-", "_");
pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
let tos = match sess.targ_cfg.os {
- abi::OsWin32 => InternedString::new("win32"),
+ abi::OsWindows => InternedString::new("windows"),
abi::OsMacos => InternedString::new("macos"),
abi::OsLinux => InternedString::new("linux"),
abi::OsAndroid => InternedString::new("android"),
};
let fam = match sess.targ_cfg.os {
- abi::OsWin32 => InternedString::new("windows"),
+ abi::OsWindows => InternedString::new("windows"),
_ => InternedString::new("unix")
};
None
}
static os_names : &'static [(&'static str, abi::Os)] = &[
- ("mingw32", abi::OsWin32),
- ("win32", abi::OsWin32),
+ ("mingw32", abi::OsWindows),
+ ("win32", abi::OsWindows),
+ ("windows", abi::OsWindows),
("darwin", abi::OsMacos),
("android", abi::OsAndroid),
("linux", abi::OsLinux),
let mut externs = HashMap::new();
for arg in matches.opt_strs("extern").iter() {
- let mut parts = arg.as_slice().splitn('=', 1);
+ let mut parts = arg.as_slice().splitn(1, '=');
let name = match parts.next() {
Some(s) => s,
None => early_error("--extern value must not be empty"),
plugin::build::find_plugin_registrar(
sess.diagnostic(), krate)));
- let freevars = time(time_passes, "freevar finding", (), |_|
- freevars::annotate_freevars(&def_map, krate));
+ let (freevars, capture_modes) =
+ time(time_passes, "freevar finding", (), |_|
+ freevars::annotate_freevars(&def_map, krate));
let region_map = time(time_passes, "region resolution", (), |_|
middle::region::resolve_crate(&sess, krate));
let stability_index = time(time_passes, "stability index", (), |_|
stability::Index::build(krate));
- let ty_cx = ty::mk_ctxt(sess, def_map, named_region_map, ast_map,
- freevars, region_map, lang_items, stability_index);
+ let ty_cx = ty::mk_ctxt(sess,
+ def_map,
+ named_region_map,
+ ast_map,
+ freevars,
+ capture_modes,
+ region_map,
+ lang_items,
+ stability_index);
// passes are timed inside typeck
typeck::check_crate(&ty_cx, trait_map, krate);
}
fn parse_pretty(sess: &Session, name: &str) -> (PpMode, Option<driver::UserIdentifiedItem>) {
- let mut split = name.splitn('=', 1);
+ let mut split = name.splitn(1, '=');
let first = split.next().unwrap();
let opt_second = split.next();
let first = match first {
fn fold_item_underscore(cx: &mut Context, item: &ast::Item_) -> ast::Item_ {
let item = match *item {
- ast::ItemImpl(ref a, ref b, c, ref methods) => {
- let methods = methods.iter().filter(|m| method_in_cfg(cx, &***m))
- .map(|x| *x).collect();
- ast::ItemImpl((*a).clone(), (*b).clone(), c, methods)
+ ast::ItemImpl(ref a, ref b, c, ref impl_items) => {
+ let impl_items = impl_items.iter()
+ .filter(|ii| {
+ impl_item_in_cfg(cx, &**ii)
+ })
+ .map(|x| *x)
+ .collect();
+ ast::ItemImpl((*a).clone(), (*b).clone(), c, impl_items)
}
ast::ItemTrait(ref a, ref b, ref c, ref methods) => {
let methods = methods.iter()
return (cx.in_cfg)(item.attrs.as_slice());
}
-fn method_in_cfg(cx: &mut Context, meth: &ast::Method) -> bool {
- return (cx.in_cfg)(meth.attrs.as_slice());
+fn trait_method_in_cfg(cx: &mut Context, meth: &ast::TraitItem) -> bool {
+ match *meth {
+ ast::RequiredMethod(ref meth) => (cx.in_cfg)(meth.attrs.as_slice()),
+ ast::ProvidedMethod(meth) => (cx.in_cfg)(meth.attrs.as_slice())
+ }
}
-fn trait_method_in_cfg(cx: &mut Context, meth: &ast::TraitMethod) -> bool {
- match *meth {
- ast::Required(ref meth) => (cx.in_cfg)(meth.attrs.as_slice()),
- ast::Provided(meth) => (cx.in_cfg)(meth.attrs.as_slice())
+fn impl_item_in_cfg(cx: &mut Context, impl_item: &ast::ImplItem) -> bool {
+ match *impl_item {
+ ast::MethodImplItem(meth) => (cx.in_cfg)(meth.attrs.as_slice()),
}
}
},
ast::TyBox(_) => { self.gate_box(t.span); }
- ast::TyUnboxedFn(_) => {
+ ast::TyUnboxedFn(..) => {
self.gate_feature("unboxed_closure_sugar",
t.span,
"unboxed closure trait sugar is experimental");
let mainfn = (quote_item!(&cx.ext_cx,
pub fn main() {
#![main]
- use std::slice::Vector;
+ use std::slice::Slice;
test::test_main_static(::std::os::args().as_slice(), TESTS);
}
)).unwrap();
// FIXME: #14406 these are processed in trans, which happens after the
// lint pass
"cold",
+ "export_name",
"inline",
"link",
"link_name",
"packed",
"static_assert",
"thread_local",
+ "no_debug",
// not used anywhere (!?) but apparently we want to keep them around
"comment",
node: m.id
};
- match cx.tcx.methods.borrow().find_copy(&did) {
+ match cx.tcx.impl_or_trait_items.borrow().find_copy(&did) {
None => cx.sess().span_bug(m.span, "missing method descriptor?!"),
Some(md) => {
- match md.container {
- ty::TraitContainer(..) => TraitDefaultImpl,
- ty::ImplContainer(cid) => {
- match ty::impl_trait_ref(cx.tcx, cid) {
- Some(..) => TraitImpl,
- None => PlainImpl
+ match md {
+ ty::MethodTraitItem(md) => {
+ match md.container {
+ ty::TraitContainer(..) => TraitDefaultImpl,
+ ty::ImplContainer(cid) => {
+ match ty::impl_trait_ref(cx.tcx, cid) {
+ Some(..) => TraitImpl,
+ None => PlainImpl
+ }
+ }
}
}
}
trait_id: trait_id,
method_num: index,
..
- }) => ty::trait_method(cx.tcx, trait_id, index).def_id
+ }) => {
+ match ty::trait_item(cx.tcx,
+ trait_id,
+ index) {
+ ty::MethodTraitItem(method) => {
+ method.def_id
+ }
+ }
+ }
}
}
None => return
visit::walk_generics(self, g, ());
}
- fn visit_trait_method(&mut self, m: &ast::TraitMethod, _: ()) {
+ fn visit_trait_item(&mut self, m: &ast::TraitItem, _: ()) {
run_lints!(self, check_trait_method, m);
- visit::walk_trait_method(self, m, ());
+ visit::walk_trait_item(self, m, ());
}
fn visit_opt_lifetime_ref(&mut self, sp: Span, lt: &Option<ast::Lifetime>, _: ()) {
fn check_fn(&mut self, _: &Context,
_: &FnKind, _: &ast::FnDecl, _: &ast::Block, _: Span, _: ast::NodeId) { }
fn check_ty_method(&mut self, _: &Context, _: &ast::TypeMethod) { }
- fn check_trait_method(&mut self, _: &Context, _: &ast::TraitMethod) { }
+ fn check_trait_method(&mut self, _: &Context, _: &ast::TraitItem) { }
fn check_struct_def(&mut self, _: &Context,
_: &ast::StructDef, _: ast::Ident, _: &ast::Generics, _: ast::NodeId) { }
fn check_struct_def_post(&mut self, _: &Context,
pub static tag_mod_impl: uint = 0x1f;
-pub static tag_item_trait_method: uint = 0x20;
+pub static tag_item_trait_item: uint = 0x20;
pub static tag_item_trait_ref: uint = 0x21;
pub static tag_item_super_trait_ref: uint = 0x22;
pub static tag_item_variances: uint = 0x2a;
/*
- trait items contain tag_item_trait_method elements,
- impl items contain tag_item_impl_method elements, and classes
+ trait items contain tag_item_trait_item elements,
+ impl items contain tag_item_impl_item elements, and classes
have both. That's because some code treats classes like traits,
and other code treats them like impls. Because classes can contain
- both, tag_item_trait_method and tag_item_impl_method have to be two
+ both, tag_item_trait_item and tag_item_impl_item have to be two
different tags.
*/
-pub static tag_item_impl_method: uint = 0x30;
+pub static tag_item_impl_item: uint = 0x30;
pub static tag_item_trait_method_explicit_self: uint = 0x31;
tag_table_adjustments = 0x51,
tag_table_moves_map = 0x52,
tag_table_capture_map = 0x53,
- tag_table_unboxed_closure_type = 0x54,
+ tag_table_unboxed_closures = 0x54,
tag_table_upvar_borrow_map = 0x55,
+ tag_table_capture_modes = 0x56,
}
static first_astencode_tag: uint = tag_ast as uint;
-static last_astencode_tag: uint = tag_table_upvar_borrow_map as uint;
+static last_astencode_tag: uint = tag_table_capture_modes as uint;
impl astencode_tag {
pub fn from_uint(value : uint) -> Option<astencode_tag> {
let is_a_tag = first_astencode_tag <= value && value <= last_astencode_tag;
}
}
-pub static tag_item_trait_method_sort: uint = 0x60;
+pub static tag_item_trait_item_sort: uint = 0x60;
-pub static tag_item_impl_type_basename: uint = 0x61;
+pub static tag_item_trait_parent_sort: uint = 0x61;
+
+pub static tag_item_impl_type_basename: uint = 0x62;
pub static tag_crate_triple: uint = 0x66;
pub static tag_unboxed_closures: uint = 0x95;
pub static tag_unboxed_closure: uint = 0x96;
pub static tag_unboxed_closure_type: uint = 0x97;
+pub static tag_unboxed_closure_kind: uint = 0x98;
+
+pub static tag_struct_fields: uint = 0x99;
+pub static tag_struct_field: uint = 0x9a;
+pub static tag_struct_field_id: uint = 0x9b;
-pub static tag_struct_fields: uint = 0x98;
-pub static tag_struct_field: uint = 0x99;
-pub static tag_struct_field_id: uint = 0x9a;
+pub static tag_attribute_is_sugared_doc: uint = 0x9c;
-pub static tag_attribute_is_sugared_doc: uint = 0x9b;
use metadata::cstore;
use metadata::decoder;
use middle::lang_items;
+use middle::resolve;
use middle::ty;
use middle::typeck;
use middle::subst::VecPerParamSpace;
}
/// Returns information about the given implementation.
-pub fn get_impl_methods(cstore: &cstore::CStore, impl_def_id: ast::DefId)
- -> Vec<ast::DefId> {
+pub fn get_impl_items(cstore: &cstore::CStore, impl_def_id: ast::DefId)
+ -> Vec<ty::ImplOrTraitItemId> {
let cdata = cstore.get_crate_data(impl_def_id.krate);
- decoder::get_impl_methods(&*cdata, impl_def_id.node)
+ decoder::get_impl_items(&*cdata, impl_def_id.node)
}
-pub fn get_method(tcx: &ty::ctxt, def: ast::DefId) -> ty::Method {
+pub fn get_impl_or_trait_item(tcx: &ty::ctxt, def: ast::DefId)
+ -> ty::ImplOrTraitItem {
let cdata = tcx.sess.cstore.get_crate_data(def.krate);
- decoder::get_method(tcx.sess.cstore.intr.clone(), &*cdata, def.node, tcx)
+ decoder::get_impl_or_trait_item(tcx.sess.cstore.intr.clone(),
+ &*cdata,
+ def.node,
+ tcx)
}
-pub fn get_method_name_and_explicit_self(cstore: &cstore::CStore,
- def: ast::DefId)
- -> (ast::Ident,
- ty::ExplicitSelfCategory)
-{
+pub fn get_trait_item_name_and_kind(cstore: &cstore::CStore, def: ast::DefId)
+ -> (ast::Ident, resolve::TraitItemKind) {
let cdata = cstore.get_crate_data(def.krate);
- decoder::get_method_name_and_explicit_self(cstore.intr.clone(), &*cdata, def.node)
+ decoder::get_trait_item_name_and_kind(cstore.intr.clone(),
+ &*cdata,
+ def.node)
}
-pub fn get_trait_method_def_ids(cstore: &cstore::CStore,
- def: ast::DefId) -> Vec<ast::DefId> {
+pub fn get_trait_item_def_ids(cstore: &cstore::CStore, def: ast::DefId)
+ -> Vec<ty::ImplOrTraitItemId> {
let cdata = cstore.get_crate_data(def.krate);
- decoder::get_trait_method_def_ids(&*cdata, def.node)
+ decoder::get_trait_item_def_ids(&*cdata, def.node)
}
pub fn get_item_variances(cstore: &cstore::CStore,
decoder::each_implementation_for_trait(&*cdata, def_id.node, callback)
}
-/// If the given def ID describes a method belonging to a trait (either a
+/// If the given def ID describes an item belonging to a trait (either a
/// default method or an implementation of a trait method), returns the ID of
/// the trait that the method belongs to. Otherwise, returns `None`.
-pub fn get_trait_of_method(cstore: &cstore::CStore,
- def_id: ast::DefId,
- tcx: &ty::ctxt)
- -> Option<ast::DefId> {
+pub fn get_trait_of_item(cstore: &cstore::CStore,
+ def_id: ast::DefId,
+ tcx: &ty::ctxt)
+ -> Option<ast::DefId> {
let cdata = cstore.get_crate_data(def_id.krate);
- decoder::get_trait_of_method(&*cdata, def_id.node, tcx)
+ decoder::get_trait_of_item(&*cdata, def_id.node, tcx)
}
pub fn get_tuple_struct_definition_if_ctor(cstore: &cstore::CStore,
use metadata::csearch::StaticMethodInfo;
use metadata::csearch;
use metadata::cstore;
-use metadata::tydecode::{parse_ty_data, parse_def_id,
- parse_type_param_def_data,
- parse_bare_fn_ty_data, parse_trait_ref_data};
-use middle::lang_items;
+use metadata::tydecode::{parse_ty_data, parse_def_id};
+use metadata::tydecode::{parse_type_param_def_data, parse_bare_fn_ty_data};
+use metadata::tydecode::{parse_trait_ref_data};
use middle::def;
+use middle::lang_items;
+use middle::resolve::TraitItemKind;
use middle::subst;
use middle::ty::{ImplContainer, TraitContainer};
use middle::ty;
}
}
-fn item_method_sort(item: rbml::Doc) -> char {
+fn item_sort(item: rbml::Doc) -> char {
let mut ret = 'r';
- reader::tagged_docs(item, tag_item_trait_method_sort, |doc| {
+ reader::tagged_docs(item, tag_item_trait_item_sort, |doc| {
ret = doc.as_str_slice().as_bytes()[0] as char;
false
});
UnsafeFn => DlDef(def::DefFn(did, ast::UnsafeFn)),
Fn => DlDef(def::DefFn(did, ast::NormalFn)),
StaticMethod | UnsafeStaticMethod => {
- let fn_style = if fam == UnsafeStaticMethod { ast::UnsafeFn } else
- { ast::NormalFn };
+ let fn_style = if fam == UnsafeStaticMethod {
+ ast::UnsafeFn
+ } else {
+ ast::NormalFn
+ };
// def_static_method carries an optional field of its enclosing
// trait or enclosing impl (if this is an inherent static method).
// So we need to detect whether this is in a trait or not, which
// we do through the mildly hacky way of checking whether there is
- // a trait_method_sort.
+ // a trait_parent_sort.
let provenance = if reader::maybe_get_doc(
- item, tag_item_trait_method_sort).is_some() {
+ item, tag_item_trait_parent_sort).is_some() {
def::FromTrait(item_reqd_and_translated_parent_item(cnum,
item))
} else {
None => {}
Some(inherent_impl_doc) => {
let _ = reader::tagged_docs(inherent_impl_doc,
- tag_item_impl_method,
- |impl_method_def_id_doc| {
- let impl_method_def_id =
- reader::with_doc_data(impl_method_def_id_doc,
- parse_def_id);
- let impl_method_def_id =
- translate_def_id(cdata, impl_method_def_id);
- match maybe_find_item(impl_method_def_id.node, items) {
+ tag_item_impl_item,
+ |impl_item_def_id_doc| {
+ let impl_item_def_id = item_def_id(impl_item_def_id_doc,
+ cdata);
+ match maybe_find_item(impl_item_def_id.node, items) {
None => {}
Some(impl_method_doc) => {
match item_family(impl_method_doc) {
item_name(&*intr, impl_method_doc);
let static_method_def_like =
item_to_def_like(impl_method_doc,
- impl_method_def_id,
+ impl_item_def_id,
cdata.cnum);
callback(static_method_def_like,
static_method_name,
}
}
-/// Returns information about the given implementation.
-pub fn get_impl_methods(cdata: Cmd, impl_id: ast::NodeId) -> Vec<ast::DefId> {
- let mut methods = Vec::new();
+/// Returns the def IDs of all the items in the given implementation.
+pub fn get_impl_items(cdata: Cmd, impl_id: ast::NodeId)
+ -> Vec<ty::ImplOrTraitItemId> {
+ let mut impl_items = Vec::new();
reader::tagged_docs(lookup_item(impl_id, cdata.data()),
- tag_item_impl_method, |doc| {
- let m_did = reader::with_doc_data(doc, parse_def_id);
- methods.push(translate_def_id(cdata, m_did));
+ tag_item_impl_item, |doc| {
+ let def_id = item_def_id(doc, cdata);
+ match item_sort(doc) {
+ 'r' | 'p' => impl_items.push(ty::MethodTraitItemId(def_id)),
+ _ => fail!("unknown impl item sort"),
+ }
true
});
- methods
+ impl_items
}
-pub fn get_method_name_and_explicit_self(intr: Rc<IdentInterner>,
- cdata: Cmd,
- id: ast::NodeId)
- -> (ast::Ident,
- ty::ExplicitSelfCategory) {
- let method_doc = lookup_item(id, cdata.data());
- let name = item_name(&*intr, method_doc);
- let explicit_self = get_explicit_self(method_doc);
- (name, explicit_self)
+pub fn get_trait_item_name_and_kind(intr: Rc<IdentInterner>,
+ cdata: Cmd,
+ id: ast::NodeId)
+ -> (ast::Ident, TraitItemKind) {
+ let doc = lookup_item(id, cdata.data());
+ let name = item_name(&*intr, doc);
+ match item_sort(doc) {
+ 'r' | 'p' => {
+ let explicit_self = get_explicit_self(doc);
+ (name, TraitItemKind::from_explicit_self_category(explicit_self))
+ }
+ c => {
+ fail!("get_trait_item_name_and_kind(): unknown trait item kind \
+ in metadata: `{}`", c)
+ }
+ }
}
-pub fn get_method(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId,
- tcx: &ty::ctxt) -> ty::Method
-{
+pub fn get_impl_or_trait_item(intr: Rc<IdentInterner>,
+ cdata: Cmd,
+ id: ast::NodeId,
+ tcx: &ty::ctxt)
+ -> ty::ImplOrTraitItem {
let method_doc = lookup_item(id, cdata.data());
let def_id = item_def_id(method_doc, cdata);
};
let name = item_name(&*intr, method_doc);
- let type_param_defs = item_ty_param_defs(method_doc, tcx, cdata,
- tag_item_method_tps);
- let rp_defs = item_region_param_defs(method_doc, cdata);
- let fty = doc_method_fty(method_doc, tcx, cdata);
- let vis = item_visibility(method_doc);
- let explicit_self = get_explicit_self(method_doc);
- let provided_source = get_provided_source(method_doc, cdata);
-
- ty::Method::new(
- name,
- ty::Generics {
- types: type_param_defs,
- regions: rp_defs,
- },
- fty,
- explicit_self,
- vis,
- def_id,
- container,
- provided_source
- )
-}
-
-pub fn get_trait_method_def_ids(cdata: Cmd,
- id: ast::NodeId) -> Vec<ast::DefId> {
+
+ match item_sort(method_doc) {
+ 'r' | 'p' => {
+ let type_param_defs = item_ty_param_defs(method_doc, tcx, cdata,
+ tag_item_method_tps);
+ let rp_defs = item_region_param_defs(method_doc, cdata);
+ let fty = doc_method_fty(method_doc, tcx, cdata);
+ let vis = item_visibility(method_doc);
+ let explicit_self = get_explicit_self(method_doc);
+ let provided_source = get_provided_source(method_doc, cdata);
+
+ let generics = ty::Generics {
+ types: type_param_defs,
+ regions: rp_defs,
+ };
+ ty::MethodTraitItem(Rc::new(ty::Method::new(name,
+ generics,
+ fty,
+ explicit_self,
+ vis,
+ def_id,
+ container,
+ provided_source)))
+ }
+ _ => fail!("unknown impl/trait item sort"),
+ }
+}
+
+pub fn get_trait_item_def_ids(cdata: Cmd, id: ast::NodeId)
+ -> Vec<ty::ImplOrTraitItemId> {
let data = cdata.data();
let item = lookup_item(id, data);
let mut result = Vec::new();
- reader::tagged_docs(item, tag_item_trait_method, |mth| {
- result.push(item_def_id(mth, cdata));
+ reader::tagged_docs(item, tag_item_trait_item, |mth| {
+ let def_id = item_def_id(mth, cdata);
+ match item_sort(mth) {
+ 'r' | 'p' => result.push(ty::MethodTraitItemId(def_id)),
+ _ => fail!("unknown trait item sort"),
+ }
true
});
result
Decodable::decode(&mut decoder).unwrap()
}
-pub fn get_provided_trait_methods(intr: Rc<IdentInterner>, cdata: Cmd,
- id: ast::NodeId, tcx: &ty::ctxt)
+pub fn get_provided_trait_methods(intr: Rc<IdentInterner>,
+ cdata: Cmd,
+ id: ast::NodeId,
+ tcx: &ty::ctxt)
-> Vec<Rc<ty::Method>> {
let data = cdata.data();
let item = lookup_item(id, data);
let mut result = Vec::new();
- reader::tagged_docs(item, tag_item_trait_method, |mth_id| {
+ reader::tagged_docs(item, tag_item_trait_item, |mth_id| {
let did = item_def_id(mth_id, cdata);
let mth = lookup_item(did.node, data);
- if item_method_sort(mth) == 'p' {
- result.push(Rc::new(get_method(intr.clone(), cdata, did.node, tcx)));
+ if item_sort(mth) == 'p' {
+ let trait_item = get_impl_or_trait_item(intr.clone(),
+ cdata,
+ did.node,
+ tcx);
+ match trait_item {
+ ty::MethodTraitItem(ref method) => {
+ result.push((*method).clone())
+ }
+ }
}
true
});
if !ret { return None }
let mut impl_method_ids = Vec::new();
- reader::tagged_docs(item, tag_item_impl_method, |impl_method_doc| {
- impl_method_ids.push(reader::with_doc_data(impl_method_doc, parse_def_id));
+ reader::tagged_docs(item, tag_item_impl_item, |impl_method_doc| {
+ impl_method_ids.push(item_def_id(impl_method_doc, cdata));
true
});
});
}
-pub fn get_trait_of_method(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt)
- -> Option<ast::DefId> {
+pub fn get_trait_of_item(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt)
+ -> Option<ast::DefId> {
let item_doc = lookup_item(id, cdata.data());
let parent_item_id = match item_parent_item(item_doc) {
None => return None,
use rbml::writer;
use rbml::io::SeekableMemWriter;
-/// A borrowed version of ast::InlinedItem.
+/// A borrowed version of `ast::InlinedItem`.
pub enum InlinedItemRef<'a> {
IIItemRef(&'a ast::Item),
- IIMethodRef(ast::DefId, bool, &'a ast::Method),
+ IITraitItemRef(ast::DefId, InlinedTraitItemRef<'a>),
IIForeignRef(&'a ast::ForeignItem)
}
+/// A borrowed version of `ast::InlinedTraitItem`.
+pub enum InlinedTraitItemRef<'a> {
+ ProvidedInlinedTraitItemRef(&'a Method),
+ RequiredInlinedTraitItemRef(&'a Method),
+}
+
pub type Encoder<'a> = writer::Encoder<'a, SeekableMemWriter>;
pub type EncodeInlinedItem<'a> = |ecx: &EncodeContext,
rbml_w: &mut Encoder,
exp: &middle::resolve::Export2)
-> bool {
- let impl_methods = ecx.tcx.impl_methods.borrow();
+ let impl_items = ecx.tcx.impl_items.borrow();
match ecx.tcx.inherent_impls.borrow().find(&exp.def_id) {
Some(implementations) => {
for base_impl_did in implementations.borrow().iter() {
- for &method_did in impl_methods.get(base_impl_did).iter() {
- let m = ty::method(ecx.tcx, method_did);
- if m.explicit_self == ty::StaticExplicitSelfCategory {
- encode_reexported_static_method(rbml_w, exp, m.def_id, m.ident);
+ for &method_did in impl_items.get(base_impl_did).iter() {
+ let impl_item = ty::impl_or_trait_item(
+ ecx.tcx,
+ method_did.def_id());
+ match impl_item {
+ ty::MethodTraitItem(ref m) => {
+ if m.explicit_self ==
+ ty::StaticExplicitSelfCategory {
+ encode_reexported_static_method(rbml_w,
+ exp,
+ m.def_id,
+ m.ident);
+ }
+ }
}
}
}
rbml_w: &mut Encoder,
exp: &middle::resolve::Export2)
-> bool {
- match ecx.tcx.trait_methods_cache.borrow().find(&exp.def_id) {
- Some(methods) => {
- for m in methods.iter() {
- if m.explicit_self == ty::StaticExplicitSelfCategory {
- encode_reexported_static_method(rbml_w, exp, m.def_id, m.ident);
+ match ecx.tcx.trait_items_cache.borrow().find(&exp.def_id) {
+ Some(trait_items) => {
+ for trait_item in trait_items.iter() {
+ match *trait_item {
+ ty::MethodTraitItem(ref m) if m.explicit_self ==
+ ty::StaticExplicitSelfCategory => {
+ encode_reexported_static_method(rbml_w,
+ exp,
+ m.def_id,
+ m.ident);
+ }
+ _ => {}
}
}
rbml_w.end_tag();
}
+fn encode_unboxed_closure_kind(rbml_w: &mut Encoder,
+ kind: ty::UnboxedClosureKind) {
+ rbml_w.start_tag(tag_unboxed_closure_kind);
+ let ch = match kind {
+ ty::FnUnboxedClosureKind => 'f',
+ ty::FnMutUnboxedClosureKind => 'm',
+ ty::FnOnceUnboxedClosureKind => 'o',
+ };
+ rbml_w.wr_str(ch.to_string().as_slice());
+ rbml_w.end_tag();
+}
+
fn encode_explicit_self(rbml_w: &mut Encoder,
explicit_self: &ty::ExplicitSelfCategory) {
rbml_w.start_tag(tag_item_trait_method_explicit_self);
}
}
-fn encode_method_sort(rbml_w: &mut Encoder, sort: char) {
- rbml_w.start_tag(tag_item_trait_method_sort);
+fn encode_item_sort(rbml_w: &mut Encoder, sort: char) {
+ rbml_w.start_tag(tag_item_trait_item_sort);
+ rbml_w.writer.write(&[ sort as u8 ]);
+ rbml_w.end_tag();
+}
+
+fn encode_parent_sort(rbml_w: &mut Encoder, sort: char) {
+ rbml_w.start_tag(tag_item_trait_parent_sort);
rbml_w.writer.write(&[ sort as u8 ]);
rbml_w.end_tag();
}
encode_method_ty_fields(ecx, rbml_w, m);
encode_parent_item(rbml_w, local_def(parent_id));
+ encode_item_sort(rbml_w, 'r');
let stab = stability::lookup(ecx.tcx, m.def_id);
encode_stability(rbml_w, stab);
for &ast_method in ast_method_opt.iter() {
let any_types = !pty.generics.types.is_empty();
if any_types || is_default_impl || should_inline(ast_method.attrs.as_slice()) {
- encode_inlined_item(ecx, rbml_w,
- IIMethodRef(local_def(parent_id), false,
- &*ast_method));
+ encode_inlined_item(ecx,
+ rbml_w,
+ IITraitItemRef(local_def(parent_id),
+ RequiredInlinedTraitItemRef(
+ &*ast_method)));
} else {
encode_symbol(ecx, rbml_w, m.def_id.node);
}
None => {}
}
}
- ItemImpl(_, ref opt_trait, ty, ref ast_methods) => {
+ ItemImpl(_, ref opt_trait, ty, ref ast_items) => {
// We need to encode information about the default methods we
// have inherited, so we drive this based on the impl structure.
- let impl_methods = tcx.impl_methods.borrow();
- let methods = impl_methods.get(&def_id);
+ let impl_items = tcx.impl_items.borrow();
+ let items = impl_items.get(&def_id);
add_to_index(item, rbml_w, index);
rbml_w.start_tag(tag_items_data_item);
}
_ => {}
}
- for &method_def_id in methods.iter() {
- rbml_w.start_tag(tag_item_impl_method);
- let s = def_to_string(method_def_id);
- rbml_w.writer.write(s.as_bytes());
+ for &item_def_id in items.iter() {
+ rbml_w.start_tag(tag_item_impl_item);
+ match item_def_id {
+ ty::MethodTraitItemId(item_def_id) => {
+ encode_def_id(rbml_w, item_def_id);
+ encode_item_sort(rbml_w, 'r');
+ }
+ }
rbml_w.end_tag();
}
for ast_trait_ref in opt_trait.iter() {
encode_stability(rbml_w, stab);
rbml_w.end_tag();
- // Iterate down the methods, emitting them. We rely on the
- // assumption that all of the actually implemented methods
+ // Iterate down the trait items, emitting them. We rely on the
+ // assumption that all of the actually implemented trait items
// appear first in the impl structure, in the same order they do
// in the ast. This is a little sketchy.
- let num_implemented_methods = ast_methods.len();
- for (i, &method_def_id) in methods.iter().enumerate() {
- let ast_method = if i < num_implemented_methods {
- Some(*ast_methods.get(i))
- } else { None };
+ let num_implemented_methods = ast_items.len();
+ for (i, &trait_item_def_id) in items.iter().enumerate() {
+ let ast_item = if i < num_implemented_methods {
+ Some(*ast_items.get(i))
+ } else {
+ None
+ };
index.push(entry {
- val: method_def_id.node as i64,
+ val: trait_item_def_id.def_id().node as i64,
pos: rbml_w.writer.tell().unwrap(),
});
- encode_info_for_method(ecx,
- rbml_w,
- &*ty::method(tcx, method_def_id),
- path.clone(),
- false,
- item.id,
- ast_method)
+
+ let trait_item_type =
+ ty::impl_or_trait_item(tcx, trait_item_def_id.def_id());
+ match (trait_item_type, ast_item) {
+ (ty::MethodTraitItem(method_type),
+ Some(ast::MethodImplItem(ast_method))) => {
+ encode_info_for_method(ecx,
+ rbml_w,
+ &*method_type,
+ path.clone(),
+ false,
+ item.id,
+ Some(ast_method))
+ }
+ (ty::MethodTraitItem(method_type), None) => {
+ encode_info_for_method(ecx,
+ rbml_w,
+ &*method_type,
+ path.clone(),
+ false,
+ item.id,
+ None)
+ }
+ }
}
}
ItemTrait(_, _, ref super_traits, ref ms) => {
encode_attributes(rbml_w, item.attrs.as_slice());
encode_visibility(rbml_w, vis);
encode_stability(rbml_w, stab);
- for &method_def_id in ty::trait_method_def_ids(tcx, def_id).iter() {
- rbml_w.start_tag(tag_item_trait_method);
- encode_def_id(rbml_w, method_def_id);
+ for &method_def_id in ty::trait_item_def_ids(tcx, def_id).iter() {
+ rbml_w.start_tag(tag_item_trait_item);
+ match method_def_id {
+ ty::MethodTraitItemId(method_def_id) => {
+ encode_def_id(rbml_w, method_def_id);
+ encode_item_sort(rbml_w, 'r');
+ }
+ }
rbml_w.end_tag();
rbml_w.start_tag(tag_mod_child);
- rbml_w.wr_str(def_to_string(method_def_id).as_slice());
+ rbml_w.wr_str(def_to_string(method_def_id.def_id()).as_slice());
rbml_w.end_tag();
}
encode_path(rbml_w, path.clone());
rbml_w.end_tag();
- // Now output the method info for each method.
- let r = ty::trait_method_def_ids(tcx, def_id);
- for (i, &method_def_id) in r.iter().enumerate() {
- assert_eq!(method_def_id.krate, ast::LOCAL_CRATE);
-
- let method_ty = ty::method(tcx, method_def_id);
+ // Now output the trait item info for each trait item.
+ let r = ty::trait_item_def_ids(tcx, def_id);
+ for (i, &item_def_id) in r.iter().enumerate() {
+ assert_eq!(item_def_id.def_id().krate, ast::LOCAL_CRATE);
index.push(entry {
- val: method_def_id.node as i64,
+ val: item_def_id.def_id().node as i64,
pos: rbml_w.writer.tell().unwrap(),
});
rbml_w.start_tag(tag_items_data_item);
- encode_method_ty_fields(ecx, rbml_w, &*method_ty);
- encode_parent_item(rbml_w, def_id);
-
- let stab = stability::lookup(tcx, method_def_id);
- encode_stability(rbml_w, stab);
-
- let elem = ast_map::PathName(method_ty.ident.name);
- encode_path(rbml_w, path.clone().chain(Some(elem).move_iter()));
-
- match method_ty.explicit_self {
- ty::StaticExplicitSelfCategory => {
- encode_family(rbml_w,
- fn_style_static_method_family(
- method_ty.fty.fn_style));
-
- let pty = ty::lookup_item_type(tcx, method_def_id);
- encode_bounds_and_type(rbml_w, ecx, &pty);
- }
-
- _ => {
- encode_family(rbml_w,
- style_fn_family(
- method_ty.fty.fn_style));
- }
- }
-
- match ms.get(i) {
- &Required(ref tm) => {
- encode_attributes(rbml_w, tm.attrs.as_slice());
- encode_method_sort(rbml_w, 'r');
- encode_method_argument_names(rbml_w, &*tm.decl);
- }
+ let trait_item_type =
+ ty::impl_or_trait_item(tcx, item_def_id.def_id());
+ match trait_item_type {
+ ty::MethodTraitItem(method_ty) => {
+ let method_def_id = item_def_id.def_id();
+
+ encode_method_ty_fields(ecx, rbml_w, &*method_ty);
+ encode_parent_item(rbml_w, def_id);
+
+ let stab = stability::lookup(tcx, method_def_id);
+ encode_stability(rbml_w, stab);
+
+ let elem = ast_map::PathName(method_ty.ident.name);
+ encode_path(rbml_w,
+ path.clone().chain(Some(elem).move_iter()));
+
+ match method_ty.explicit_self {
+ ty::StaticExplicitSelfCategory => {
+ encode_family(rbml_w,
+ fn_style_static_method_family(
+ method_ty.fty.fn_style));
+
+ let pty = ty::lookup_item_type(tcx,
+ method_def_id);
+ encode_bounds_and_type(rbml_w, ecx, &pty);
+ }
+
+ _ => {
+ encode_family(rbml_w,
+ style_fn_family(
+ method_ty.fty.fn_style));
+ }
+ }
- &Provided(m) => {
- encode_attributes(rbml_w, m.attrs.as_slice());
- // If this is a static method, we've already encoded
- // this.
- if method_ty.explicit_self != ty::StaticExplicitSelfCategory {
- // FIXME: I feel like there is something funny going on.
- let pty = ty::lookup_item_type(tcx, method_def_id);
- encode_bounds_and_type(rbml_w, ecx, &pty);
+ match ms.get(i) {
+ &RequiredMethod(ref tm) => {
+ encode_attributes(rbml_w, tm.attrs.as_slice());
+ encode_item_sort(rbml_w, 'r');
+ encode_parent_sort(rbml_w, 't');
+ encode_method_argument_names(rbml_w, &*tm.decl);
+ }
+
+ &ProvidedMethod(m) => {
+ encode_attributes(rbml_w, m.attrs.as_slice());
+ // If this is a static method, we've already
+ // encoded this.
+ if method_ty.explicit_self !=
+ ty::StaticExplicitSelfCategory {
+ // FIXME: I feel like there is something funny
+ // going on.
+ let pty = ty::lookup_item_type(tcx, method_def_id);
+ encode_bounds_and_type(rbml_w, ecx, &pty);
+ }
+ encode_item_sort(rbml_w, 'p');
+ encode_parent_sort(rbml_w, 't');
+ encode_inlined_item(
+ ecx,
+ rbml_w,
+ IITraitItemRef(
+ def_id,
+ ProvidedInlinedTraitItemRef(&*m)));
+ encode_method_argument_names(rbml_w,
+ &*m.pe_fn_decl());
+ }
}
- encode_method_sort(rbml_w, 'p');
- encode_inlined_item(ecx, rbml_w,
- IIMethodRef(def_id, true, &*m));
- encode_method_argument_names(rbml_w, &*m.pe_fn_decl());
}
}
ecx: &'a EncodeContext,
rbml_w: &'a mut Encoder) {
rbml_w.start_tag(tag_unboxed_closures);
- for (unboxed_closure_id, unboxed_closure_type) in
- ecx.tcx.unboxed_closure_types.borrow().iter() {
+ for (unboxed_closure_id, unboxed_closure) in ecx.tcx
+ .unboxed_closures
+ .borrow()
+ .iter() {
if unboxed_closure_id.krate != LOCAL_CRATE {
continue
}
rbml_w.start_tag(tag_unboxed_closure);
encode_def_id(rbml_w, *unboxed_closure_id);
rbml_w.start_tag(tag_unboxed_closure_type);
- write_closure_type(ecx, rbml_w, unboxed_closure_type);
+ write_closure_type(ecx, rbml_w, &unboxed_closure.closure_type);
rbml_w.end_tag();
+ encode_unboxed_closure_kind(rbml_w, unboxed_closure.kind);
rbml_w.end_tag();
}
rbml_w.end_tag();
// dynamic libraries
fn dylibname(&self) -> Option<(&'static str, &'static str)> {
match self.os {
- abi::OsWin32 => Some((WIN32_DLL_PREFIX, WIN32_DLL_SUFFIX)),
+ abi::OsWindows => Some((WIN32_DLL_PREFIX, WIN32_DLL_SUFFIX)),
abi::OsMacos => Some((MACOS_DLL_PREFIX, MACOS_DLL_SUFFIX)),
abi::OsLinux => Some((LINUX_DLL_PREFIX, LINUX_DLL_SUFFIX)),
abi::OsAndroid => Some((ANDROID_DLL_PREFIX, ANDROID_DLL_SUFFIX)),
match os {
abi::OsMacos => Some("__DATA,__note.rustc"),
abi::OsiOS => Some("__DATA,__note.rustc"),
- abi::OsWin32 => Some(".note.rustc"),
+ abi::OsWindows => Some(".note.rustc"),
abi::OsLinux => Some(".note.rustc"),
abi::OsAndroid => Some(".note.rustc"),
abi::OsFreebsd => Some(".note.rustc"),
match os {
abi::OsMacos => "__note.rustc",
abi::OsiOS => unreachable!(),
- abi::OsWin32 => ".note.rustc",
+ abi::OsWindows => ".note.rustc",
abi::OsLinux => ".note.rustc",
abi::OsAndroid => ".note.rustc",
abi::OsFreebsd => ".note.rustc",
}
'k' => {
let did = parse_def(st, NominalType, |x,y| conv(x,y));
- return ty::mk_unboxed_closure(st.tcx, did);
+ let region = parse_region(st, conv);
+ return ty::mk_unboxed_closure(st.tcx, did, region);
}
'e' => {
return ty::mk_err();
enc_substs(w, cx, substs);
mywrite!(w, "]");
}
- ty::ty_unboxed_closure(def) => {
+ ty::ty_unboxed_closure(def, region) => {
mywrite!(w, "k{}", (cx.ds)(def));
+ enc_region(w, cx, region);
}
ty::ty_err => {
mywrite!(w, "e");
use metadata::decoder;
use middle::def;
use e = metadata::encoder;
+use middle::freevars::{CaptureMode, freevar_entry};
use middle::freevars;
-use middle::freevars::freevar_entry;
use middle::region;
use metadata::tydecode;
use metadata::tydecode::{DefIdSource, NominalType, TypeWithId, TypeParameter,
let id = match ii {
e::IIItemRef(i) => i.id,
e::IIForeignRef(i) => i.id,
- e::IIMethodRef(_, _, m) => m.id,
+ e::IITraitItemRef(_, e::ProvidedInlinedTraitItemRef(m)) => m.id,
+ e::IITraitItemRef(_, e::RequiredInlinedTraitItemRef(m)) => m.id,
};
debug!("> Encoding inlined item: {} ({})",
ecx.tcx.map.path_to_string(id),
let ident = match ii {
ast::IIItem(i) => i.ident,
ast::IIForeign(i) => i.ident,
- ast::IIMethod(_, _, m) => m.pe_ident(),
+ ast::IITraitItem(_, iti) => {
+ match iti {
+ ast::ProvidedInlinedTraitItem(m) => m.pe_ident(),
+ ast::RequiredInlinedTraitItem(m) => m.pe_ident(),
+ }
+ }
};
debug!("Fn named: {}", token::get_ident(ident));
debug!("< Decoded inlined fn: {}::{}",
match ii {
// HACK we're not dropping items.
- e::IIItemRef(i) => ast::IIItem(fold::noop_fold_item(i, &mut fld)
- .expect_one("expected one item")),
- e::IIMethodRef(d, p, m) => ast::IIMethod(d, p, fold::noop_fold_method(m, &mut fld)
- .expect_one(
- "noop_fold_method must produce exactly one method")),
- e::IIForeignRef(i) => ast::IIForeign(fold::noop_fold_foreign_item(i, &mut fld))
+ e::IIItemRef(i) => {
+ ast::IIItem(fold::noop_fold_item(i, &mut fld)
+ .expect_one("expected one item"))
+ }
+ e::IITraitItemRef(d, iti) => {
+ ast::IITraitItem(d, match iti {
+ e::ProvidedInlinedTraitItemRef(m) => {
+ ast::ProvidedInlinedTraitItem(
+ fold::noop_fold_method(m, &mut fld)
+ .expect_one("noop_fold_method must produce \
+ exactly one method"))
+ }
+ e::RequiredInlinedTraitItemRef(m) => {
+ ast::RequiredInlinedTraitItem(
+ fold::noop_fold_method(m, &mut fld)
+ .expect_one("noop_fold_method must produce \
+ exactly one method"))
+ }
+ })
+ }
+ e::IIForeignRef(i) => {
+ ast::IIForeign(fold::noop_fold_foreign_item(i, &mut fld))
+ }
}
}
ast::IIItem(i) => {
ast::IIItem(fld.fold_item(i).expect_one("expected one item"))
}
- ast::IIMethod(d, is_provided, m) => {
- ast::IIMethod(xcx.tr_def_id(d), is_provided, fld.fold_method(m)
- .expect_one("expected one method"))
+ ast::IITraitItem(d, iti) => {
+ match iti {
+ ast::ProvidedInlinedTraitItem(m) => {
+ ast::IITraitItem(
+ xcx.tr_def_id(d),
+ ast::ProvidedInlinedTraitItem(
+ fld.fold_method(m)
+ .expect_one("expected one method")))
+ }
+ ast::RequiredInlinedTraitItem(m) => {
+ ast::IITraitItem(
+ xcx.tr_def_id(d),
+ ast::RequiredInlinedTraitItem(
+ fld.fold_method(m)
+ .expect_one("expected one method")))
+ }
+ }
}
ast::IIForeign(i) => ast::IIForeign(fld.fold_foreign_item(i))
}
(*fv).encode(rbml_w).unwrap();
}
+fn encode_capture_mode(rbml_w: &mut Encoder, cm: CaptureMode) {
+ cm.encode(rbml_w).unwrap();
+}
+
trait rbml_decoder_helper {
fn read_freevar_entry(&mut self, xcx: &ExtendedDecodeContext)
-> freevar_entry;
+ fn read_capture_mode(&mut self) -> CaptureMode;
}
impl<'a> rbml_decoder_helper for reader::Decoder<'a> {
let fv: freevar_entry = Decodable::decode(self).unwrap();
fv.tr(xcx)
}
+
+ fn read_capture_mode(&mut self) -> CaptureMode {
+ let cm: CaptureMode = Decodable::decode(self).unwrap();
+ cm
+ }
}
impl tr for freevar_entry {
}).unwrap()
}
+pub fn encode_unboxed_closure_kind(ebml_w: &mut Encoder,
+ kind: ty::UnboxedClosureKind) {
+ ebml_w.emit_enum("UnboxedClosureKind", |ebml_w| {
+ match kind {
+ ty::FnUnboxedClosureKind => {
+ ebml_w.emit_enum_variant("FnUnboxedClosureKind", 0, 3, |_| {
+ Ok(())
+ })
+ }
+ ty::FnMutUnboxedClosureKind => {
+ ebml_w.emit_enum_variant("FnMutUnboxedClosureKind", 1, 3, |_| {
+ Ok(())
+ })
+ }
+ ty::FnOnceUnboxedClosureKind => {
+ ebml_w.emit_enum_variant("FnOnceUnboxedClosureKind",
+ 2,
+ 3,
+ |_| {
+ Ok(())
+ })
+ }
+ }
+ }).unwrap()
+}
pub fn encode_vtable_origin(ecx: &e::EncodeContext,
- rbml_w: &mut Encoder,
- vtable_origin: &typeck::vtable_origin) {
+ rbml_w: &mut Encoder,
+ vtable_origin: &typeck::vtable_origin) {
rbml_w.emit_enum("vtable_origin", |rbml_w| {
match *vtable_origin {
typeck::vtable_static(def_id, ref substs, ref vtable_res) => {
}
}
+ for &cm in tcx.capture_modes.borrow().find(&id).iter() {
+ rbml_w.tag(c::tag_table_capture_modes, |rbml_w| {
+ rbml_w.id(id);
+ rbml_w.tag(c::tag_table_val, |rbml_w| {
+ encode_capture_mode(rbml_w, *cm);
+ })
+ })
+ }
+
let lid = ast::DefId { krate: ast::LOCAL_CRATE, node: id };
for &pty in tcx.tcache.borrow().find(&lid).iter() {
rbml_w.tag(c::tag_table_tcache, |rbml_w| {
})
}
- for unboxed_closure_type in tcx.unboxed_closure_types
- .borrow()
- .find(&ast_util::local_def(id))
- .iter() {
- rbml_w.tag(c::tag_table_unboxed_closure_type, |rbml_w| {
+ for unboxed_closure in tcx.unboxed_closures
+ .borrow()
+ .find(&ast_util::local_def(id))
+ .iter() {
+ rbml_w.tag(c::tag_table_unboxed_closures, |rbml_w| {
rbml_w.id(id);
rbml_w.tag(c::tag_table_val, |rbml_w| {
- rbml_w.emit_closure_type(ecx, *unboxed_closure_type)
+ rbml_w.emit_closure_type(ecx, &unboxed_closure.closure_type);
+ encode_unboxed_closure_kind(rbml_w, unboxed_closure.kind)
})
})
}
-> ty::Polytype;
fn read_substs(&mut self, xcx: &ExtendedDecodeContext) -> subst::Substs;
fn read_auto_adjustment(&mut self, xcx: &ExtendedDecodeContext) -> ty::AutoAdjustment;
- fn read_unboxed_closure_type(&mut self, xcx: &ExtendedDecodeContext)
- -> ty::ClosureTy;
+ fn read_unboxed_closure(&mut self, xcx: &ExtendedDecodeContext)
+ -> ty::UnboxedClosure;
fn convert_def_id(&mut self,
xcx: &ExtendedDecodeContext,
source: DefIdSource,
}).unwrap()
}
- fn read_unboxed_closure_type(&mut self, xcx: &ExtendedDecodeContext)
- -> ty::ClosureTy {
- self.read_opaque(|this, doc| {
+ fn read_unboxed_closure(&mut self, xcx: &ExtendedDecodeContext)
+ -> ty::UnboxedClosure {
+ let closure_type = self.read_opaque(|this, doc| {
Ok(tydecode::parse_ty_closure_data(
doc.data,
xcx.dcx.cdata.cnum,
doc.start,
xcx.dcx.tcx,
|s, a| this.convert_def_id(xcx, s, a)))
- }).unwrap()
+ }).unwrap();
+ let variants = [
+ "FnUnboxedClosureKind",
+ "FnMutUnboxedClosureKind",
+ "FnOnceUnboxedClosureKind"
+ ];
+ let kind = self.read_enum_variant(variants, |_, i| {
+ Ok(match i {
+ 0 => ty::FnUnboxedClosureKind,
+ 1 => ty::FnMutUnboxedClosureKind,
+ 2 => ty::FnOnceUnboxedClosureKind,
+ _ => fail!("bad enum variant for ty::UnboxedClosureKind"),
+ })
+ }).unwrap();
+ ty::UnboxedClosure {
+ closure_type: closure_type,
+ kind: kind,
+ }
}
fn convert_def_id(&mut self,
let ub: ty::UpvarBorrow = Decodable::decode(val_dsr).unwrap();
dcx.tcx.upvar_borrow_map.borrow_mut().insert(upvar_id, ub.tr(xcx));
}
+ c::tag_table_capture_modes => {
+ let capture_mode = val_dsr.read_capture_mode();
+ dcx.tcx
+ .capture_modes
+ .borrow_mut()
+ .insert(id, capture_mode);
+ }
c::tag_table_tcache => {
let pty = val_dsr.read_polytype(xcx);
let lid = ast::DefId { krate: ast::LOCAL_CRATE, node: id };
let adj: ty::AutoAdjustment = val_dsr.read_auto_adjustment(xcx);
dcx.tcx.adjustments.borrow_mut().insert(id, adj);
}
- c::tag_table_unboxed_closure_type => {
- let unboxed_closure_type =
- val_dsr.read_unboxed_closure_type(xcx);
+ c::tag_table_unboxed_closures => {
+ let unboxed_closure =
+ val_dsr.read_unboxed_closure(xcx);
dcx.tcx
- .unboxed_closure_types
+ .unboxed_closures
.borrow_mut()
.insert(ast_util::local_def(id),
- unboxed_closure_type);
+ unboxed_closure);
}
_ => {
xcx.dcx.tcx.sess.bug(
self.bccx, borrow_span, cause,
cmt.clone(), loan_region);
+ debug!("guarantee_valid(): restrictions={:?}", restr);
+
// Create the loan record (if needed).
let loan = match restr {
restrictions::Safe => {
}
mc::cat_deref(cmt_base, _, mc::BorrowedPtr(ty::ImmBorrow, lt)) |
- mc::cat_deref(cmt_base, _, mc::BorrowedPtr(ty::UniqueImmBorrow, lt)) |
- mc::cat_deref(cmt_base, _, mc::Implicit(ty::ImmBorrow, lt)) |
- mc::cat_deref(cmt_base, _, mc::Implicit(ty::UniqueImmBorrow, lt)) => {
+ mc::cat_deref(cmt_base, _, mc::Implicit(ty::ImmBorrow, lt)) => {
// R-Deref-Imm-Borrowed
if !self.bccx.is_subregion_of(self.loan_region, lt) {
self.bccx.report(
mc::cat_deref(cmt_base, _, pk) => {
match pk {
mc::BorrowedPtr(ty::MutBorrow, lt) |
- mc::Implicit(ty::MutBorrow, lt) => {
+ mc::BorrowedPtr(ty::UniqueImmBorrow, lt) |
+ mc::Implicit(ty::MutBorrow, lt) |
+ mc::Implicit(ty::UniqueImmBorrow, lt) => {
// R-Deref-Mut-Borrowed
if !self.bccx.is_subregion_of(self.loan_region, lt) {
self.bccx.report(
tcx: &ty::ctxt) -> ast::NodeId {
match tcx.map.get(closure_id) {
ast_map::NodeExpr(expr) => match expr.node {
- ast::ExprProc(_decl, block) |
- ast::ExprFnBlock(_decl, block) => { block.id }
+ ast::ExprProc(_, block) |
+ ast::ExprFnBlock(_, _, block) |
+ ast::ExprUnboxedFn(_, _, _, block) => { block.id }
_ => fail!("encountered non-closure id: {}", closure_id)
},
_ => fail!("encountered non-expr id: {}", closure_id)
self.visit_expr(&**e, cx);
self.visit_block(&**b, Loop);
}
- ast::ExprFnBlock(_, ref b) |
+ ast::ExprFnBlock(_, _, ref b) |
ast::ExprProc(_, ref b) |
- ast::ExprUnboxedFn(_, ref b) => {
+ ast::ExprUnboxedFn(_, _, _, ref b) => {
self.visit_block(&**b, Closure);
}
ast::ExprBreak(_) => self.require_loop("break", cx, e.span),
match tcx.map.find(def_id.node) {
Some(ast_map::NodeItem(..))
- | Some(ast_map::NodeMethod(..))
+ | Some(ast_map::NodeImplItem(..))
| Some(ast_map::NodeForeignItem(..))
- | Some(ast_map::NodeTraitMethod(..)) => true,
+ | Some(ast_map::NodeTraitItem(..)) => true,
_ => false
}
}
method_num: index,
..
}) => {
- let def_id = ty::trait_method(self.tcx,
- trait_id, index).def_id;
- self.check_def_id(def_id);
+ let trait_item = ty::trait_item(self.tcx,
+ trait_id,
+ index);
+ match trait_item {
+ ty::MethodTraitItem(method) => {
+ self.check_def_id(method.def_id);
+ }
+ }
}
}
}
_ => ()
}
}
- ast_map::NodeTraitMethod(trait_method) => {
- visit::walk_trait_method(self, &*trait_method, ctxt);
+ ast_map::NodeTraitItem(trait_method) => {
+ visit::walk_trait_item(self, &*trait_method, ctxt);
}
- ast_map::NodeMethod(method) => {
- visit::walk_block(self, &*method.pe_body(), ctxt);
+ ast_map::NodeImplItem(impl_item) => {
+ match *impl_item {
+ ast::MethodImplItem(method) => {
+ visit::walk_block(self, &*method.pe_body(), ctxt);
+ }
+ }
}
ast_map::NodeForeignItem(foreign_item) => {
visit::walk_foreign_item(self, &*foreign_item, ctxt);
self.worklist.push(item.id);
}
match item.node {
- ast::ItemImpl(_, Some(ref _trait_ref), _, ref methods) => {
- for method in methods.iter() {
- self.worklist.push(method.id);
+ ast::ItemImpl(_, Some(ref _trait_ref), _, ref impl_items) => {
+ for impl_item in impl_items.iter() {
+ match *impl_item {
+ ast::MethodImplItem(method) => {
+ self.worklist.push(method.id);
+ }
+ }
}
}
_ => ()
// This is done to handle the case where, for example, the static
// method of a private type is used, but the type itself is never
// called directly.
- let impl_methods = self.tcx.impl_methods.borrow();
+ let impl_items = self.tcx.impl_items.borrow();
match self.tcx.inherent_impls.borrow().find(&local_def(id)) {
None => (),
Some(impl_list) => {
for impl_did in impl_list.borrow().iter() {
- for method_did in impl_methods.get(impl_did).iter() {
- if self.live_symbols.contains(&method_did.node) {
+ for item_did in impl_items.get(impl_did).iter() {
+ if self.live_symbols.contains(&item_did.def_id()
+ .node) {
return true;
}
}
}
// Overwrite so that we don't warn the trait method itself.
- fn visit_trait_method(&mut self, trait_method: &ast::TraitMethod, _: ()) {
+ fn visit_trait_item(&mut self, trait_method: &ast::TraitItem, _: ()) {
match *trait_method {
- ast::Provided(ref method) => {
+ ast::ProvidedMethod(ref method) => {
visit::walk_block(self, &*method.pe_body(), ())
}
- ast::Required(_) => ()
+ ast::RequiredMethod(_) => ()
}
}
}
fn from_method_id(tcx: &ty::ctxt, method_id: ast::DefId)
-> OverloadedCallType {
let method_descriptor =
- match tcx.methods.borrow_mut().find(&method_id) {
+ match tcx.impl_or_trait_items.borrow_mut().find(&method_id) {
+ Some(&ty::MethodTraitItem(ref method_descriptor)) => {
+ (*method_descriptor).clone()
+ }
None => {
tcx.sess.bug("overloaded call method wasn't in method \
map")
}
- Some(ref method_descriptor) => (*method_descriptor).clone(),
};
let impl_id = match method_descriptor.container {
ty::TraitContainer(_) => {
ast::ExprForLoop(ref pat, ref head, ref blk, _) => {
// The pattern lives as long as the block.
debug!("walk_expr for loop case: blk id={}", blk.id);
- self.walk_expr(&**head);
+ self.consume_expr(&**head);
- let head_cmt = return_if_err!(self.mc.cat_expr(&**head));
- self.walk_pat(head_cmt, pat.clone());
+ // Fetch the type of the value that the iteration yields to
+ // produce the pattern's categorized mutable type.
+ let pattern_type = ty::node_id_to_type(self.tcx(), pat.id);
+ let pat_cmt = self.mc.cat_rvalue(pat.id,
+ pat.span,
+ ty::ReScope(blk.id),
+ pattern_type);
+ self.walk_pat(pat_cmt, pat.clone());
self.walk_block(&**blk);
}
}
ast::PatIdent(ast::BindByValue(_), _, _) => {
let mode = copy_or_move(typer.tcx(), cmt_pat.ty, PatBindingMove);
+ debug!("walk_pat binding consuming pat");
delegate.consume_pat(pat, cmt_pat, mode);
}
_ => {
use middle::mem_categorization::Typer;
use middle::resolve;
use middle::ty;
-use util::nodemap::{DefIdSet, NodeMap, NodeSet};
+use util::nodemap::{NodeMap, NodeSet};
+use syntax::ast;
use syntax::codemap::Span;
-use syntax::{ast};
-use syntax::visit;
use syntax::visit::Visitor;
+use syntax::visit;
-#[deriving(Show)]
+#[deriving(Clone, Decodable, Encodable, Show)]
pub enum CaptureMode {
/// Copy/move the value from this llvm ValueRef into the environment.
CaptureByValue,
pub type freevar_map = NodeMap<Vec<freevar_entry>>;
-pub type UnboxedClosureList = DefIdSet;
+pub type CaptureModeMap = NodeMap<CaptureMode>;
struct CollectFreevarsVisitor<'a> {
seen: NodeSet,
refs: Vec<freevar_entry>,
def_map: &'a resolve::DefMap,
+ capture_mode_map: &'a mut CaptureModeMap,
}
impl<'a> Visitor<int> for CollectFreevarsVisitor<'a> {
fn visit_expr(&mut self, expr: &ast::Expr, depth: int) {
match expr.node {
- ast::ExprFnBlock(..) | ast::ExprProc(..) |
- ast::ExprUnboxedFn(..) => {
+ ast::ExprProc(..) => {
+ self.capture_mode_map.insert(expr.id, CaptureByValue);
+ visit::walk_expr(self, expr, depth + 1)
+ }
+ ast::ExprFnBlock(_, _, _) => {
+ // NOTE(stage0): After snapshot, change to:
+ //
+ //let capture_mode = match capture_clause {
+ // ast::CaptureByValue => CaptureByValue,
+ // ast::CaptureByRef => CaptureByRef,
+ //};
+ let capture_mode = CaptureByRef;
+ self.capture_mode_map.insert(expr.id, capture_mode);
+ visit::walk_expr(self, expr, depth + 1)
+ }
+ ast::ExprUnboxedFn(capture_clause, _, _, _) => {
+ let capture_mode = match capture_clause {
+ ast::CaptureByValue => CaptureByValue,
+ ast::CaptureByRef => CaptureByRef,
+ };
+ self.capture_mode_map.insert(expr.id, capture_mode);
visit::walk_expr(self, expr, depth + 1)
}
ast::ExprPath(..) => {
_ => visit::walk_expr(self, expr, depth)
}
}
-
-
}
// Searches through part of the AST for all references to locals or
// Since we want to be able to collect upvars in some arbitrary piece
// of the AST, we take a walker function that we invoke with a visitor
// in order to start the search.
-fn collect_freevars(def_map: &resolve::DefMap, blk: &ast::Block) -> Vec<freevar_entry> {
+fn collect_freevars(def_map: &resolve::DefMap,
+ blk: &ast::Block,
+ capture_mode_map: &mut CaptureModeMap)
+ -> Vec<freevar_entry> {
let mut v = CollectFreevarsVisitor {
seen: NodeSet::new(),
refs: Vec::new(),
def_map: def_map,
+ capture_mode_map: &mut *capture_mode_map,
};
v.visit_block(blk, 1);
+
v.refs
}
struct AnnotateFreevarsVisitor<'a> {
def_map: &'a resolve::DefMap,
freevars: freevar_map,
+ capture_mode_map: CaptureModeMap,
}
impl<'a> Visitor<()> for AnnotateFreevarsVisitor<'a> {
fn visit_fn(&mut self, fk: &visit::FnKind, fd: &ast::FnDecl,
blk: &ast::Block, s: Span, nid: ast::NodeId, _: ()) {
- let vars = collect_freevars(self.def_map, blk);
+ let vars = collect_freevars(self.def_map,
+ blk,
+ &mut self.capture_mode_map);
self.freevars.insert(nid, vars);
visit::walk_fn(self, fk, fd, blk, s, ());
}
// node of interest rather than building up the free variables in
// one pass. This could be improved upon if it turns out to matter.
pub fn annotate_freevars(def_map: &resolve::DefMap, krate: &ast::Crate)
- -> freevar_map {
+ -> (freevar_map, CaptureModeMap) {
let mut visitor = AnnotateFreevarsVisitor {
def_map: def_map,
freevars: NodeMap::new(),
+ capture_mode_map: NodeMap::new(),
};
visit::walk_crate(&mut visitor, krate, ());
- visitor.freevars
+ let AnnotateFreevarsVisitor {
+ freevars,
+ capture_mode_map,
+ ..
+ } = visitor;
+ (freevars, capture_mode_map)
}
pub fn with_freevars<T>(tcx: &ty::ctxt, fid: ast::NodeId, f: |&[freevar_entry]| -> T) -> T {
}
}
-pub fn get_capture_mode<T: Typer>(tcx: &T, closure_expr_id: ast::NodeId) -> CaptureMode {
- let fn_ty = tcx.node_ty(closure_expr_id).ok().expect("couldn't find closure ty?");
- match ty::ty_closure_store(fn_ty) {
- ty::RegionTraitStore(..) => CaptureByRef,
- ty::UniqTraitStore => CaptureByValue
- }
+pub fn get_capture_mode<T:Typer>(tcx: &T, closure_expr_id: ast::NodeId)
+ -> CaptureMode {
+ tcx.capture_mode(closure_expr_id)
}
b(check_for_bare)
}
- ty::ty_unboxed_closure(_) => {}
+ ty::ty_unboxed_closure(..) => {}
ref s => {
cx.tcx.sess.bug(format!("expect fn type in kind checker, not \
self.propagate_through_expr(&**e, succ)
}
- ExprFnBlock(_, ref blk) |
+ ExprFnBlock(_, _, ref blk) |
ExprProc(_, ref blk) |
- ExprUnboxedFn(_, ref blk) => {
+ ExprUnboxedFn(_, _, _, ref blk) => {
debug!("{} is an ExprFnBlock, ExprProc, or ExprUnboxedFn",
expr_to_string(expr));
#![allow(non_camel_case_types)]
use middle::def;
+use middle::freevars;
use middle::ty;
use middle::typeck;
-use util::nodemap::NodeMap;
+use util::nodemap::{DefIdMap, NodeMap};
use util::ppaux::{ty_to_string, Repr};
use syntax::ast::{MutImmutable, MutMutable};
fn is_method_call(&self, id: ast::NodeId) -> bool;
fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<ast::NodeId>;
fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow;
+ fn capture_mode(&self, closure_expr_id: ast::NodeId)
+ -> freevars::CaptureMode;
+ fn unboxed_closures<'a>(&'a self)
+ -> &'a RefCell<DefIdMap<ty::UnboxedClosure>>;
}
impl MutabilityCategory {
}))
}
}
- ty::ty_unboxed_closure(_) => {
+ ty::ty_unboxed_closure(closure_id, _) => {
+ let unboxed_closures = self.typer
+ .unboxed_closures()
+ .borrow();
+ let kind = unboxed_closures.get(&closure_id).kind;
+ let onceness = match kind {
+ ty::FnUnboxedClosureKind |
+ ty::FnMutUnboxedClosureKind => ast::Many,
+ ty::FnOnceUnboxedClosureKind => ast::Once,
+ };
Ok(Rc::new(cmt_ {
id: id,
span: span,
cat: cat_copied_upvar(CopiedUpvar {
upvar_id: var_id,
- onceness: ast::Many,
+ onceness: onceness,
capturing_proc: fn_node_id,
}),
mutbl: MutabilityCategory::from_def(&def),
ast::ItemTrait(_, _, _, ref methods) if item.vis != ast::Public => {
for m in methods.iter() {
match *m {
- ast::Provided(ref m) => self.parents.insert(m.id, item.id),
- ast::Required(ref m) => self.parents.insert(m.id, item.id),
+ ast::ProvidedMethod(ref m) => self.parents.insert(m.id, item.id),
+ ast::RequiredMethod(ref m) => self.parents.insert(m.id, item.id),
};
}
}
// undefined symbols at linkage time if this case is not handled.
//
// * Private trait impls for private types can be completely ignored
- ast::ItemImpl(_, _, ref ty, ref methods) => {
+ ast::ItemImpl(_, _, ref ty, ref impl_items) => {
let public_ty = match ty.node {
ast::TyPath(_, _, id) => {
match self.tcx.def_map.borrow().get_copy(&id) {
});
if public_ty || public_trait {
- for method in methods.iter() {
- let meth_public = match method.pe_explicit_self().node {
- ast::SelfStatic => public_ty,
- _ => true,
- } && method.pe_vis() == ast::Public;
- if meth_public || tr.is_some() {
- self.exported_items.insert(method.id);
+ for impl_item in impl_items.iter() {
+ match *impl_item {
+ ast::MethodImplItem(method) => {
+ let meth_public =
+ match method.pe_explicit_self().node {
+ ast::SelfStatic => public_ty,
+ _ => true,
+ } && method.pe_vis() == ast::Public;
+ if meth_public || tr.is_some() {
+ self.exported_items.insert(method.id);
+ }
+ }
}
}
}
ast::ItemTrait(_, _, _, ref methods) if public_first => {
for method in methods.iter() {
match *method {
- ast::Provided(ref m) => {
+ ast::ProvidedMethod(ref m) => {
debug!("provided {}", m.id);
self.exported_items.insert(m.id);
}
- ast::Required(ref m) => {
+ ast::RequiredMethod(ref m) => {
debug!("required {}", m.id);
self.exported_items.insert(m.id);
}
}
debug!("privacy - is {:?} a public method", did);
- return match self.tcx.methods.borrow().find(&did) {
- Some(meth) => {
- debug!("privacy - well at least it's a method: {:?}", meth);
+ return match self.tcx.impl_or_trait_items.borrow().find(&did) {
+ Some(&ty::MethodTraitItem(ref meth)) => {
+ debug!("privacy - well at least it's a method: {:?}",
+ *meth);
match meth.container {
ty::TraitContainer(id) => {
debug!("privacy - recursing on trait {:?}", id);
// invocation.
// FIXME(#10573) is this the right behavior? Why not consider
// where the method was defined?
- Some(ast_map::NodeMethod(ref m)) => {
- let imp = self.tcx.map.get_parent_did(closest_private_id);
- match ty::impl_trait_ref(self.tcx, imp) {
- Some(..) => return Allowable,
- _ if m.pe_vis() == ast::Public => return Allowable,
- _ => m.pe_vis()
+ Some(ast_map::NodeImplItem(ref ii)) => {
+ match **ii {
+ ast::MethodImplItem(m) => {
+ let imp = self.tcx
+ .map
+ .get_parent_did(closest_private_id);
+ match ty::impl_trait_ref(self.tcx, imp) {
+ Some(..) => return Allowable,
+ _ if m.pe_vis() == ast::Public => {
+ return Allowable
+ }
+ _ => m.pe_vis()
+ }
+ }
}
}
- Some(ast_map::NodeTraitMethod(_)) => {
+ Some(ast_map::NodeTraitItem(_)) => {
return Allowable;
}
}
// Given the ID of a method, checks to ensure it's in scope.
- fn check_static_method(&mut self, span: Span, method_id: ast::DefId,
+ fn check_static_method(&mut self,
+ span: Span,
+ method_id: ast::DefId,
name: ast::Ident) {
// If the method is a default method, we need to use the def_id of
// the default implementation.
- let method_id = ty::method(self.tcx, method_id).provided_source
- .unwrap_or(method_id);
+ let method_id = match ty::impl_or_trait_item(self.tcx, method_id) {
+ ty::MethodTraitItem(method_type) => {
+ method_type.provided_source.unwrap_or(method_id)
+ }
+ };
let string = token::get_ident(name);
self.report_error(self.ensure_public(span,
match item.node {
// implementations of traits don't need visibility qualifiers because
// that's controlled by having the trait in scope.
- ast::ItemImpl(_, Some(..), _, ref methods) => {
+ ast::ItemImpl(_, Some(..), _, ref impl_items) => {
check_inherited(item.span, item.vis,
"visibility qualifiers have no effect on trait \
impls");
- for m in methods.iter() {
- check_inherited(m.span, m.pe_vis(), "");
+ for impl_item in impl_items.iter() {
+ match *impl_item {
+ ast::MethodImplItem(m) => {
+ check_inherited(m.span, m.pe_vis(), "");
+ }
+ }
}
}
ast::ItemTrait(_, _, _, ref methods) => {
for m in methods.iter() {
match *m {
- ast::Provided(ref m) => {
+ ast::ProvidedMethod(ref m) => {
check_inherited(m.span, m.pe_vis(),
"unnecessary visibility");
}
- ast::Required(ref m) => {
+ ast::RequiredMethod(ref m) => {
check_inherited(m.span, m.vis,
"unnecessary visibility");
}
};
check_inherited(tcx, item.span, item.vis);
match item.node {
- ast::ItemImpl(_, _, _, ref methods) => {
- for m in methods.iter() {
- check_inherited(tcx, m.span, m.pe_vis());
+ ast::ItemImpl(_, _, _, ref impl_items) => {
+ for impl_item in impl_items.iter() {
+ match *impl_item {
+ ast::MethodImplItem(m) => {
+ check_inherited(tcx, m.span, m.pe_vis());
+ }
+ }
}
}
ast::ItemForeignMod(ref fm) => {
ast::ItemTrait(_, _, _, ref methods) => {
for m in methods.iter() {
match *m {
- ast::Required(..) => {}
- ast::Provided(ref m) => check_inherited(tcx, m.span,
+ ast::RequiredMethod(..) => {}
+ ast::ProvidedMethod(ref m) => check_inherited(tcx, m.span,
m.pe_vis()),
}
}
// (i.e. we could just return here to not check them at
// all, or some worse estimation of whether an impl is
// publicly visible.
- ast::ItemImpl(ref g, ref trait_ref, self_, ref methods) => {
+ ast::ItemImpl(ref g, ref trait_ref, self_, ref impl_items) => {
// `impl [... for] Private` is never visible.
let self_contains_private;
// impl [... for] Public<...>, but not `impl [... for]
// are private (because `T` won't be visible externally).
let trait_or_some_public_method =
trait_ref.is_some() ||
- methods.iter().any(|m| self.exported_items.contains(&m.id));
+ impl_items.iter()
+ .any(|impl_item| {
+ match *impl_item {
+ ast::MethodImplItem(m) => {
+ self.exported_items.contains(&m.id)
+ }
+ }
+ });
if !self_contains_private &&
not_private_trait &&
match *trait_ref {
None => {
- for method in methods.iter() {
- visit::walk_method_helper(self, &**method, ())
+ for impl_item in impl_items.iter() {
+ match *impl_item {
+ ast::MethodImplItem(method) => {
+ visit::walk_method_helper(self,
+ &*method,
+ ())
+ }
+ }
}
}
Some(ref tr) => {
// impl Public<Private> { ... }. Any public static
// methods will be visible as `Public::foo`.
let mut found_pub_static = false;
- for method in methods.iter() {
- if method.pe_explicit_self().node == ast::SelfStatic &&
- self.exported_items.contains(&method.id) {
- found_pub_static = true;
- visit::walk_method_helper(self, &**method, ());
+ for impl_item in impl_items.iter() {
+ match *impl_item {
+ ast::MethodImplItem(method) => {
+ if method.pe_explicit_self().node ==
+ ast::SelfStatic &&
+ self.exported_items
+ .contains(&method.id) {
+ found_pub_static = true;
+ visit::walk_method_helper(self,
+ &*method,
+ ());
+ }
+ }
}
}
if found_pub_static {
_ => false,
}
}
- Some(ast_map::NodeTraitMethod(trait_method)) => {
+ Some(ast_map::NodeTraitItem(trait_method)) => {
match *trait_method {
- ast::Required(_) => false,
- ast::Provided(_) => true,
+ ast::RequiredMethod(_) => false,
+ ast::ProvidedMethod(_) => true,
}
}
- Some(ast_map::NodeMethod(method)) => {
- if generics_require_inlining(method.pe_generics()) ||
- attributes_specify_inlining(method.attrs.as_slice()) {
- true
- } else {
- let impl_did = self.tcx.map.get_parent_did(node_id);
- // Check the impl. If the generics on the self type of the
- // impl require inlining, this method does too.
- assert!(impl_did.krate == ast::LOCAL_CRATE);
- match self.tcx.map.expect_item(impl_did.node).node {
- ast::ItemImpl(ref generics, _, _, _) => {
- generics_require_inlining(generics)
+ Some(ast_map::NodeImplItem(impl_item)) => {
+ match *impl_item {
+ ast::MethodImplItem(method) => {
+ if generics_require_inlining(method.pe_generics()) ||
+ attributes_specify_inlining(
+ method.attrs.as_slice()) {
+ true
+ } else {
+ let impl_did = self.tcx
+ .map
+ .get_parent_did(node_id);
+ // Check the impl. If the generics on the self
+ // type of the impl require inlining, this method
+ // does too.
+ assert!(impl_did.krate == ast::LOCAL_CRATE);
+ match self.tcx
+ .map
+ .expect_item(impl_did.node)
+ .node {
+ ast::ItemImpl(ref generics, _, _, _) => {
+ generics_require_inlining(generics)
+ }
+ _ => false
+ }
}
- _ => false
}
}
}
}
}
}
- ast_map::NodeTraitMethod(trait_method) => {
+ ast_map::NodeTraitItem(trait_method) => {
match *trait_method {
- ast::Required(..) => {
+ ast::RequiredMethod(..) => {
// Keep going, nothing to get exported
}
- ast::Provided(ref method) => {
+ ast::ProvidedMethod(ref method) => {
visit::walk_block(self, &*method.pe_body(), ())
}
}
}
- ast_map::NodeMethod(method) => {
- let did = self.tcx.map.get_parent_did(search_item);
- if method_might_be_inlined(self.tcx, &*method, did) {
- visit::walk_block(self, &*method.pe_body(), ())
+ ast_map::NodeImplItem(impl_item) => {
+ match *impl_item {
+ ast::MethodImplItem(method) => {
+ let did = self.tcx.map.get_parent_did(search_item);
+ if method_might_be_inlined(self.tcx, &*method, did) {
+ visit::walk_block(self, &*method.pe_body(), ())
+ }
+ }
}
}
// Nothing to recurse on for these
use syntax::ast::*;
use syntax::ast;
use syntax::ast_util::{local_def, PostExpansionMethod};
-use syntax::ast_util::{walk_pat, trait_method_to_ty_method};
+use syntax::ast_util::{walk_pat, trait_item_to_ty_method};
use syntax::ext::mtwt;
use syntax::parse::token::special_names;
use syntax::parse::token::special_idents;
use std::collections::{HashMap, HashSet};
use std::cell::{Cell, RefCell};
-use std::gc::{Gc, GC};
+use std::gc::GC;
use std::mem::replace;
use std::rc::{Rc, Weak};
use std::uint;
NoSuggestion,
Field,
Method,
- TraitMethod,
+ TraitItem,
StaticMethod(String),
StaticTraitMethod(String),
}
ConstantItemRibKind
}
-// Methods can be required or provided. Required methods only occur in traits.
+// Methods can be required or provided. RequiredMethod methods only occur in traits.
enum MethodSort {
- Required,
- Provided(NodeId)
+ RequiredMethod,
+ ProvidedMethod(NodeId)
}
enum UseLexicalScopeFlag {
}
#[deriving(Clone, Eq, PartialEq)]
-enum MethodIsStaticFlag {
- MethodIsNotStatic,
- MethodIsStatic,
+pub enum TraitItemKind {
+ NonstaticMethodTraitItemKind,
+ StaticMethodTraitItemKind,
}
-impl MethodIsStaticFlag {
- fn from_explicit_self_category(explicit_self_category:
- ExplicitSelfCategory)
- -> MethodIsStaticFlag {
+impl TraitItemKind {
+ pub fn from_explicit_self_category(explicit_self_category:
+ ExplicitSelfCategory)
+ -> TraitItemKind {
if explicit_self_category == StaticExplicitSelfCategory {
- MethodIsStatic
+ StaticMethodTraitItemKind
} else {
- MethodIsNotStatic
+ NonstaticMethodTraitItemKind
}
}
}
graph_root: NameBindings,
- method_map: RefCell<FnvHashMap<(Name, DefId), MethodIsStaticFlag>>,
+ trait_item_map: RefCell<FnvHashMap<(Name, DefId), TraitItemKind>>,
structs: FnvHashMap<DefId, Vec<Name>>,
graph_root: graph_root,
- method_map: RefCell::new(FnvHashMap::new()),
+ trait_item_map: RefCell::new(FnvHashMap::new()),
structs: FnvHashMap::new(),
unresolved_imports: 0,
parent
}
- ItemImpl(_, None, ty, ref methods) => {
+ ItemImpl(_, None, ty, ref impl_items) => {
// If this implements an anonymous trait, then add all the
// methods within to a new module, if the type was defined
// within this module.
}
};
- // For each method...
- for method in methods.iter() {
- // Add the method to the module.
- let ident = method.pe_ident();
- let method_name_bindings =
- self.add_child(ident,
- new_parent.clone(),
- ForbidDuplicateValues,
- method.span);
- let def = match method.pe_explicit_self().node {
- SelfStatic => {
- // Static methods become
- // `def_static_method`s.
- DefStaticMethod(local_def(method.id),
- FromImpl(local_def(
- item.id)),
- method.pe_fn_style())
- }
- _ => {
- // Non-static methods become
- // `def_method`s.
- DefMethod(local_def(method.id), None)
- }
- };
+ // For each implementation item...
+ for impl_item in impl_items.iter() {
+ match *impl_item {
+ MethodImplItem(method) => {
+ // Add the method to the module.
+ let ident = method.pe_ident();
+ let method_name_bindings =
+ self.add_child(ident,
+ new_parent.clone(),
+ ForbidDuplicateValues,
+ method.span);
+ let def = match method.pe_explicit_self()
+ .node {
+ SelfStatic => {
+ // Static methods become
+ // `def_static_method`s.
+ DefStaticMethod(
+ local_def(method.id),
+ FromImpl(local_def(item.id)),
+ method.pe_fn_style())
+ }
+ _ => {
+ // Non-static methods become
+ // `def_method`s.
+ DefMethod(local_def(method.id),
+ None)
+ }
+ };
- let is_public = method.pe_vis() == ast::Public;
- method_name_bindings.define_value(def,
- method.span,
- is_public);
+ let is_public =
+ method.pe_vis() == ast::Public;
+ method_name_bindings.define_value(
+ def,
+ method.span,
+ is_public);
+ }
+ }
}
}
_ => {}
// Add the names of all the methods to the trait info.
for method in methods.iter() {
- let ty_m = trait_method_to_ty_method(method);
+ let ty_m = trait_item_to_ty_method(method);
let ident = ty_m.ident;
(DefStaticMethod(local_def(ty_m.id),
FromTrait(local_def(item.id)),
ty_m.fn_style),
- MethodIsStatic)
+ StaticMethodTraitItemKind)
}
_ => {
// Non-static methods become `def_method`s.
(DefMethod(local_def(ty_m.id),
Some(local_def(item.id))),
- MethodIsNotStatic)
+ NonstaticMethodTraitItemKind)
}
};
ty_m.span);
method_name_bindings.define_value(def, ty_m.span, true);
- self.method_map
+ self.trait_item_map
.borrow_mut()
.insert((ident.name, def_id), static_flag);
}
debug!("(building reduced graph for external \
crate) building type {}", final_ident);
- // If this is a trait, add all the method names
- // to the trait info.
+ // If this is a trait, add all the trait item names to the trait
+ // info.
- let method_def_ids =
- csearch::get_trait_method_def_ids(&self.session.cstore, def_id);
- for &method_def_id in method_def_ids.iter() {
- let (method_name, explicit_self) =
- csearch::get_method_name_and_explicit_self(&self.session.cstore,
- method_def_id);
+ let trait_item_def_ids =
+ csearch::get_trait_item_def_ids(&self.session.cstore, def_id);
+ for trait_item_def_id in trait_item_def_ids.iter() {
+ let (trait_item_name, trait_item_kind) =
+ csearch::get_trait_item_name_and_kind(
+ &self.session.cstore,
+ trait_item_def_id.def_id());
- debug!("(building reduced graph for \
- external crate) ... adding \
- trait method '{}'",
- token::get_ident(method_name));
+ debug!("(building reduced graph for external crate) ... \
+ adding trait item '{}'",
+ token::get_ident(trait_item_name));
- self.method_map
+ self.trait_item_map
.borrow_mut()
- .insert((method_name.name, def_id),
- MethodIsStaticFlag::from_explicit_self_category(
- explicit_self));
+ .insert((trait_item_name.name, def_id),
+ trait_item_kind);
if is_exported {
- self.external_exports.insert(method_def_id);
+ self.external_exports
+ .insert(trait_item_def_id.def_id());
}
}
ItemRibKind),
|this| {
this.resolve_type_parameters(&generics.ty_params);
+ this.resolve_where_clause(&generics.where_clause);
visit::walk_item(this, item, ());
});
}
ItemImpl(ref generics,
ref implemented_traits,
ref self_type,
- ref methods) => {
+ ref impl_items) => {
self.resolve_implementation(item.id,
generics,
implemented_traits,
&**self_type,
- methods.as_slice());
+ impl_items.as_slice());
}
ItemTrait(ref generics, ref unbound, ref traits, ref methods) => {
NormalRibKind),
|this| {
this.resolve_type_parameters(&generics.ty_params);
+ this.resolve_where_clause(&generics.where_clause);
// Resolve derived traits.
for trt in traits.iter() {
// FIXME #4951: Do we need a node ID here?
match *method {
- ast::Required(ref ty_m) => {
+ ast::RequiredMethod(ref ty_m) => {
this.with_type_parameter_rib
(HasTypeParameters(&ty_m.generics,
FnSpace,
item.id,
- MethodRibKind(item.id, Required)),
+ MethodRibKind(item.id, RequiredMethod)),
|this| {
// Resolve the method-specific type
// parameters.
this.resolve_type_parameters(
&ty_m.generics.ty_params);
+ this.resolve_where_clause(&ty_m.generics
+ .where_clause);
for argument in ty_m.decl.inputs.iter() {
this.resolve_type(&*argument.ty);
this.resolve_type(&*ty_m.decl.output);
});
}
- ast::Provided(ref m) => {
+ ast::ProvidedMethod(ref m) => {
this.resolve_method(MethodRibKind(item.id,
- Provided(m.id)),
+ ProvidedMethod(m.id)),
&**m)
}
}
}
HasTypeParameters(ref generics, _, _, _) => {
this.resolve_type_parameters(&generics.ty_params);
+ this.resolve_where_clause(&generics.where_clause);
}
}
}
}
+ fn resolve_where_clause(&mut self, where_clause: &ast::WhereClause) {
+ for predicate in where_clause.predicates.iter() {
+ match self.resolve_identifier(predicate.ident,
+ TypeNS,
+ true,
+ predicate.span) {
+ Some((def @ DefTyParam(_, _, _), last_private)) => {
+ self.record_def(predicate.id, (def, last_private));
+ }
+ _ => {
+ self.resolve_error(
+ predicate.span,
+ format!("undeclared type parameter `{}`",
+ token::get_ident(
+ predicate.ident)).as_slice());
+ }
+ }
+
+ for bound in predicate.bounds.iter() {
+ self.resolve_type_parameter_bound(predicate.id, bound);
+ }
+ }
+ }
+
fn resolve_struct(&mut self,
id: NodeId,
generics: &Generics,
|this| {
// Resolve the type parameters.
this.resolve_type_parameters(&generics.ty_params);
+ this.resolve_where_clause(&generics.where_clause);
// Resolve the super struct.
match super_struct {
generics: &Generics,
opt_trait_reference: &Option<TraitRef>,
self_type: &Ty,
- methods: &[Gc<Method>]) {
+ impl_items: &[ImplItem]) {
// If applicable, create a rib for the type parameters.
self.with_type_parameter_rib(HasTypeParameters(generics,
TypeSpace,
|this| {
// Resolve the type parameters.
this.resolve_type_parameters(&generics.ty_params);
+ this.resolve_where_clause(&generics.where_clause);
// Resolve the trait reference, if necessary.
this.with_optional_trait_ref(id, opt_trait_reference, |this| {
this.resolve_type(self_type);
this.with_current_self_type(self_type, |this| {
- for method in methods.iter() {
- // If this is a trait impl, ensure the method exists in trait
- this.check_trait_method(&**method);
-
- // We also need a new scope for the method-specific type parameters.
- this.resolve_method(MethodRibKind(id, Provided(method.id)),
- &**method);
+ for impl_item in impl_items.iter() {
+ match *impl_item {
+ MethodImplItem(method) => {
+ // If this is a trait impl, ensure the method
+ // exists in trait
+ this.check_trait_item(method.pe_ident(),
+ method.span);
+
+ // We also need a new scope for the method-
+ // specific type parameters.
+ this.resolve_method(
+ MethodRibKind(id,
+ ProvidedMethod(method.id)),
+ &*method);
+ }
+ }
}
});
});
});
}
- fn check_trait_method(&self, method: &Method) {
+ fn check_trait_item(&self, ident: Ident, span: Span) {
// If there is a TraitRef in scope for an impl, then the method must be in the trait.
for &(did, ref trait_ref) in self.current_trait_ref.iter() {
- let method_name = method.pe_ident().name;
+ let method_name = ident.name;
- if self.method_map.borrow().find(&(method_name, did)).is_none() {
+ if self.trait_item_map.borrow().find(&(method_name, did)).is_none() {
let path_str = self.path_idents_to_string(&trait_ref.path);
- self.resolve_error(method.span,
+ self.resolve_error(span,
format!("method `{}` is not a member of trait `{}`",
token::get_name(method_name),
path_str).as_slice());
TraitModuleKind | ImplModuleKind => {
match containing_module.def_id.get() {
Some(def_id) => {
- match self.method_map.borrow().find(&(ident.name, def_id)) {
- Some(&MethodIsStatic) => (),
+ match self.trait_item_map.borrow().find(&(ident.name, def_id)) {
+ Some(&StaticMethodTraitItemKind) => (),
None => (),
_ => {
debug!("containing module was a trait or impl \
}
}
Some(DefMethod(_, None)) if allowed == Everything => return Method,
- Some(DefMethod(_, Some(_))) => return TraitMethod,
+ Some(DefMethod(_, Some(_))) => return TraitItem,
_ => ()
}
}
}
// Look for a method in the current trait.
- let method_map = self.method_map.borrow();
+ let trait_item_map = self.trait_item_map.borrow();
match self.current_trait_ref {
Some((did, ref trait_ref)) => {
let path_str = self.path_idents_to_string(&trait_ref.path);
- match method_map.find(&(name, did)) {
- Some(&MethodIsStatic) => return StaticTraitMethod(path_str),
- Some(_) => return TraitMethod,
+ match trait_item_map.find(&(name, did)) {
+ Some(&StaticMethodTraitItemKind) => return StaticTraitMethod(path_str),
+ Some(_) => return TraitItem,
None => {}
}
}
Field =>
format!("`self.{}`", wrong_name),
Method
- | TraitMethod =>
+ | TraitItem =>
format!("to call `self.{}`", wrong_name),
StaticTraitMethod(path_str)
| StaticMethod(path_str) =>
visit::walk_expr(self, expr, ());
}
- ExprFnBlock(fn_decl, block) |
+ ExprFnBlock(_, fn_decl, block) |
ExprProc(fn_decl, block) |
- ExprUnboxedFn(fn_decl, block) => {
+ ExprUnboxedFn(_, _, fn_decl, block) => {
self.resolve_function(FunctionRibKind(expr.id, block.id),
Some(fn_decl), NoTypeParameters,
block);
// Look for the current trait.
match self.current_trait_ref {
Some((trait_def_id, _)) => {
- let method_map = self.method_map.borrow();
+ let trait_item_map = self.trait_item_map.borrow();
- if method_map.contains_key(&(name, trait_def_id)) {
+ if trait_item_map.contains_key(&(name, trait_def_id)) {
add_trait_info(&mut found_traits, trait_def_id, name);
}
}
self.populate_module_if_necessary(&search_module);
{
- let method_map = self.method_map.borrow();
+ let trait_item_map = self.trait_item_map.borrow();
for (_, child_names) in search_module.children.borrow().iter() {
let def = match child_names.def_for_namespace(TypeNS) {
Some(def) => def,
DefTrait(trait_def_id) => trait_def_id,
_ => continue,
};
- if method_map.contains_key(&(name, trait_def_id)) {
+ if trait_item_map.contains_key(&(name, trait_def_id)) {
add_trait_info(&mut found_traits, trait_def_id, name);
}
}
Some(DefTrait(trait_def_id)) => trait_def_id,
Some(..) | None => continue,
};
- if self.method_map.borrow().contains_key(&(name, did)) {
+ if self.trait_item_map.borrow().contains_key(&(name, did)) {
add_trait_info(&mut found_traits, did, name);
self.used_imports.insert((import.type_id, TypeNS));
}
let mut result = String::from_str("<");
result.push_str(ty_to_string(&*ty).as_slice());
- match ty::trait_of_method(&self.analysis.ty_cx,
- ast_util::local_def(method.id)) {
+ match ty::trait_of_item(&self.analysis.ty_cx,
+ ast_util::local_def(method.id)) {
Some(def_id) => {
result.push_str(" as ");
result.push_str(
).as_slice());
},
},
- None => match ty::trait_of_method(&self.analysis.ty_cx,
- ast_util::local_def(method.id)) {
+ None => match ty::trait_of_item(&self.analysis.ty_cx,
+ ast_util::local_def(method.id)) {
Some(def_id) => {
scope_id = def_id.node;
match self.analysis.ty_cx.map.get(def_id.node) {
let qualname = qualname.as_slice();
// record the decl for this def (if it has one)
- let decl_id = ty::trait_method_of_method(&self.analysis.ty_cx,
- ast_util::local_def(method.id))
- .filtered(|def_id| method.id != 0 && def_id.node == 0);
+ let decl_id = ty::trait_item_of_item(&self.analysis.ty_cx,
+ ast_util::local_def(method.id))
+ .filtered(|def_id| {
+ match *def_id {
+ ty::MethodTraitItemId(def_id) => {
+ method.id != 0 && def_id.node == 0
+ }
+ }
+ });
+ let decl_id = match decl_id {
+ None => None,
+ Some(ty::MethodTraitItemId(def_id)) => Some(def_id),
+ };
let sub_span = self.span.sub_span_after_keyword(method.span, keywords::Fn);
self.fmt.method_str(method.span,
type_parameters: &ast::Generics,
trait_ref: &Option<ast::TraitRef>,
typ: ast::P<ast::Ty>,
- methods: &Vec<Gc<ast::Method>>) {
+ impl_items: &Vec<ast::ImplItem>) {
match typ.node {
ast::TyPath(ref path, _, id) => {
match self.lookup_type_ref(id) {
}
self.process_generic_params(type_parameters, item.span, "", item.id, e);
- for method in methods.iter() {
- visit::walk_method_helper(self, &**method, e)
+ for impl_item in impl_items.iter() {
+ match *impl_item {
+ ast::MethodImplItem(method) => {
+ visit::walk_method_helper(self, &*method, e)
+ }
+ }
}
}
e: DxrVisitorEnv,
generics: &ast::Generics,
trait_refs: &Vec<ast::TraitRef>,
- methods: &Vec<ast::TraitMethod>) {
+ methods: &Vec<ast::TraitItem>) {
let qualname = self.analysis.ty_cx.map.path_to_string(item.id);
let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Trait);
// walk generics and methods
self.process_generic_params(generics, item.span, qualname.as_slice(), item.id, e);
for method in methods.iter() {
- self.visit_trait_method(method, e)
+ self.visit_trait_item(method, e)
}
}
def::DefStaticMethod(declid, provenence, _) => {
let sub_span = self.span.sub_span_for_meth_name(ex.span);
let defid = if declid.krate == ast::LOCAL_CRATE {
- let m = ty::method(&self.analysis.ty_cx, declid);
+ let ti = ty::impl_or_trait_item(&self.analysis.ty_cx,
+ declid);
match provenence {
- def::FromTrait(def_id) =>
- Some(ty::trait_methods(&self.analysis.ty_cx, def_id)
- .iter().find(|mr| mr.ident.name == m.ident.name).unwrap().def_id),
+ def::FromTrait(def_id) => {
+ Some(ty::trait_items(&self.analysis.ty_cx,
+ def_id)
+ .iter()
+ .find(|mr| {
+ match **mr {
+ ty::MethodTraitItem(ref mr) => {
+ mr.ident.name == ti.ident()
+ .name
+ }
+ }
+ })
+ .unwrap()
+ .def_id())
+ }
def::FromImpl(def_id) => {
- let impl_methods = self.analysis.ty_cx.impl_methods.borrow();
- Some(*impl_methods.get(&def_id)
- .iter().find(|mr|
- ty::method(
- &self.analysis.ty_cx, **mr).ident.name == m.ident.name)
- .unwrap())
+ let impl_items = self.analysis
+ .ty_cx
+ .impl_items
+ .borrow();
+ Some(impl_items.get(&def_id)
+ .iter()
+ .find(|mr| {
+ match **mr {
+ ty::MethodTraitItemId(mr) => {
+ ty::impl_or_trait_item(
+ &self.analysis
+ .ty_cx,
+ mr).ident()
+ .name ==
+ ti.ident().name
+ }
+ }
+ }).unwrap()
+ .def_id())
}
}
} else {
typeck::MethodStatic(def_id) |
typeck::MethodStaticUnboxedClosure(def_id) => {
// method invoked on an object with a concrete type (not a static method)
- let decl_id = ty::trait_method_of_method(&self.analysis.ty_cx, def_id);
+ let decl_id =
+ match ty::trait_item_of_item(&self.analysis.ty_cx,
+ def_id) {
+ None => None,
+ Some(ty::MethodTraitItemId(decl_id)) => Some(decl_id),
+ };
- // This incantation is required if the method referenced is a trait's
- // default implementation.
- let def_id = ty::method(&self.analysis.ty_cx, def_id).provided_source
- .unwrap_or(def_id);
+ // This incantation is required if the method referenced is a
+ // trait's default implementation.
+ let def_id = match ty::impl_or_trait_item(&self.analysis
+ .ty_cx,
+ def_id) {
+ ty::MethodTraitItem(method) => {
+ method.provided_source.unwrap_or(def_id)
+ }
+ };
(Some(def_id), decl_id)
}
typeck::MethodParam(mp) => {
// method invoked on a type parameter
- let method = ty::trait_method(&self.analysis.ty_cx,
- mp.trait_id,
- mp.method_num);
- (None, Some(method.def_id))
+ let trait_item = ty::trait_item(&self.analysis.ty_cx,
+ mp.trait_id,
+ mp.method_num);
+ match trait_item {
+ ty::MethodTraitItem(method) => {
+ (None, Some(method.def_id))
+ }
+ }
},
typeck::MethodObject(mo) => {
// method invoked on a trait instance
- let method = ty::trait_method(&self.analysis.ty_cx,
- mo.trait_id,
- mo.method_num);
- (None, Some(method.def_id))
+ let trait_item = ty::trait_item(&self.analysis.ty_cx,
+ mo.trait_id,
+ mo.method_num);
+ match trait_item {
+ ty::MethodTraitItem(method) => {
+ (None, Some(method.def_id))
+ }
+ }
},
};
let sub_span = self.span.sub_span_for_meth_name(ex.span);
self.process_static(item, e, typ, mt, &*expr),
ast::ItemStruct(def, ref ty_params) => self.process_struct(item, e, &*def, ty_params),
ast::ItemEnum(ref def, ref ty_params) => self.process_enum(item, e, def, ty_params),
- ast::ItemImpl(ref ty_params, ref trait_ref, typ, ref methods) =>
- self.process_impl(item, e, ty_params, trait_ref, typ, methods),
+ ast::ItemImpl(ref ty_params,
+ ref trait_ref,
+ typ,
+ ref impl_items) => {
+ self.process_impl(item,
+ e,
+ ty_params,
+ trait_ref,
+ typ,
+ impl_items)
+ }
ast::ItemTrait(ref generics, _, ref trait_refs, ref methods) =>
self.process_trait(item, e, generics, trait_refs, methods),
ast::ItemMod(ref m) => self.process_mod(item, e, m),
}
}
- fn visit_trait_method(&mut self, tm: &ast::TraitMethod, e: DxrVisitorEnv) {
+ fn visit_trait_item(&mut self, tm: &ast::TraitItem, e: DxrVisitorEnv) {
match *tm {
- ast::Required(ref method_type) => {
+ ast::RequiredMethod(ref method_type) => {
if generated_code(method_type.span) {
return;
}
- let mut scope_id ;
- let mut qualname = match ty::trait_of_method(&self.analysis.ty_cx,
- ast_util::local_def(method_type.id)) {
+ let mut scope_id;
+ let mut qualname = match ty::trait_of_item(&self.analysis.ty_cx,
+ ast_util::local_def(method_type.id)) {
Some(def_id) => {
scope_id = def_id.node;
ty::item_path_str(&self.analysis.ty_cx, def_id).append("::")
method_type.id,
e);
}
- ast::Provided(method) => self.process_method(&*method, e),
+ ast::ProvidedMethod(method) => self.process_method(&*method, e),
}
}
"Expected struct type, but not ty_struct"),
}
},
- ast::ExprFnBlock(decl, body) => {
+ ast::ExprFnBlock(_, decl, body) => {
if generated_code(body.span) {
return
}
use syntax::{attr, visit};
use syntax::ast;
use syntax::ast::{Attribute, Block, Crate, DefId, FnDecl, NodeId, Variant};
-use syntax::ast::{Item, Required, Provided, TraitMethod, TypeMethod, Method};
+use syntax::ast::{Item, RequiredMethod, ProvidedMethod, TraitItem, TypeMethod, Method};
use syntax::ast::{Generics, StructDef, StructField, Ident};
use syntax::ast_util::is_local;
use syntax::attr::Stability;
visit::walk_fn(self, fk, fd, b, s, stab)
}
- fn visit_trait_method(&mut self, t: &TraitMethod, parent: Option<Stability>) {
+ fn visit_trait_item(&mut self, t: &TraitItem, parent: Option<Stability>) {
let stab = match *t {
- Required(TypeMethod {attrs: ref attrs, id: id, ..}) =>
+ RequiredMethod(TypeMethod {attrs: ref attrs, id: id, ..}) =>
self.annotate(id, attrs.as_slice(), parent),
// work around lack of pattern matching for @ types
- Provided(method) => match *method {
+ ProvidedMethod(method) => match *method {
Method {attrs: ref attrs, id: id, ..} =>
self.annotate(id, attrs.as_slice(), parent)
}
};
- visit::walk_trait_method(self, t, stab)
+ visit::walk_trait_item(self, t, stab)
}
fn visit_variant(&mut self, v: &Variant, g: &Generics, parent: Option<Stability>) {
/// Lookup the stability for a node, loading external crate
/// metadata as necessary.
-pub fn lookup(tcx: &ty::ctxt, id: DefId) -> Option<Stability> {
+pub fn lookup(tcx: &ty::ctxt, id: DefId) -> Option<Stability> {
// is this definition the implementation of a trait method?
- match ty::trait_method_of_method(tcx, id) {
- Some(trait_method_id) if trait_method_id != id => {
+ match ty::trait_item_of_item(tcx, id) {
+ Some(ty::MethodTraitItemId(trait_method_id))
+ if trait_method_id != id => {
lookup(tcx, trait_method_id)
}
_ if is_local(id) => {
return Univariant(mk_struct(cx, ftys.as_slice(), packed), dtor)
}
- ty::ty_unboxed_closure(def_id) => {
+ ty::ty_unboxed_closure(def_id, _) => {
let upvars = ty::unboxed_closure_upvars(cx.tcx(), def_id);
let upvar_types = upvars.iter().map(|u| u.ty).collect::<Vec<_>>();
return Univariant(mk_struct(cx, upvar_types.as_slice(), false),
use middle::trans::build::*;
use middle::trans::builder::{Builder, noname};
use middle::trans::callee;
+use middle::trans::cleanup::{CleanupMethods, ScopeId};
use middle::trans::cleanup;
-use middle::trans::cleanup::CleanupMethods;
use middle::trans::common::*;
use middle::trans::consts;
use middle::trans::controlflow;
f
}
+pub fn self_type_for_unboxed_closure(ccx: &CrateContext,
+ closure_id: ast::DefId)
+ -> ty::t {
+ let unboxed_closure_type = ty::mk_unboxed_closure(ccx.tcx(),
+ closure_id,
+ ty::ReStatic);
+ let unboxed_closures = ccx.tcx.unboxed_closures.borrow();
+ let unboxed_closure = unboxed_closures.get(&closure_id);
+ match unboxed_closure.kind {
+ ty::FnUnboxedClosureKind => {
+ ty::mk_imm_rptr(&ccx.tcx, ty::ReStatic, unboxed_closure_type)
+ }
+ ty::FnMutUnboxedClosureKind => {
+ ty::mk_mut_rptr(&ccx.tcx, ty::ReStatic, unboxed_closure_type)
+ }
+ ty::FnOnceUnboxedClosureKind => unboxed_closure_type,
+ }
+}
+
+pub fn kind_for_unboxed_closure(ccx: &CrateContext, closure_id: ast::DefId)
+ -> ty::UnboxedClosureKind {
+ let unboxed_closures = ccx.tcx.unboxed_closures.borrow();
+ unboxed_closures.get(&closure_id).kind
+}
+
pub fn decl_rust_fn(ccx: &CrateContext, fn_ty: ty::t, name: &str) -> ValueRef {
let (inputs, output, abi, env) = match ty::get(fn_ty).sty {
ty::ty_bare_fn(ref f) => {
ty::ty_closure(ref f) => {
(f.sig.inputs.clone(), f.sig.output, f.abi, Some(Type::i8p(ccx)))
}
- ty::ty_unboxed_closure(closure_did) => {
- let unboxed_closure_types = ccx.tcx
- .unboxed_closure_types
- .borrow();
- let function_type = unboxed_closure_types.get(&closure_did);
- let llenvironment_type = type_of(ccx, fn_ty).ptr_to();
+ ty::ty_unboxed_closure(closure_did, _) => {
+ let unboxed_closures = ccx.tcx.unboxed_closures.borrow();
+ let unboxed_closure = unboxed_closures.get(&closure_did);
+ let function_type = unboxed_closure.closure_type.clone();
+ let self_type = self_type_for_unboxed_closure(ccx, closure_did);
+ let llenvironment_type = type_of_explicit_arg(ccx, self_type);
(function_type.sig.inputs.clone(),
function_type.sig.output,
RustCall,
}
})
}
- ty::ty_unboxed_closure(def_id) => {
+ ty::ty_unboxed_closure(def_id, _) => {
let repr = adt::represent_type(cx.ccx(), t);
let upvars = ty::unboxed_closure_upvars(cx.tcx(), def_id);
for (i, upvar) in upvars.iter().enumerate() {
_ => tcx.sess.bug("unexpected item variant in has_nested_returns")
}
}
- Some(ast_map::NodeTraitMethod(trait_method)) => {
+ Some(ast_map::NodeTraitItem(trait_method)) => {
match *trait_method {
- ast::Provided(m) => {
+ ast::ProvidedMethod(m) => {
match m.node {
ast::MethDecl(_, _, _, _, _, _, blk, _) => {
let mut explicit = CheckForNestedReturnsVisitor { found: false };
ast::MethMac(_) => tcx.sess.bug("unexpanded macro")
}
}
- ast::Required(_) => tcx.sess.bug("unexpected variant: required trait method in \
- has_nested_returns")
+ ast::RequiredMethod(_) => {
+ tcx.sess.bug("unexpected variant: required trait method \
+ in has_nested_returns")
+ }
}
}
- Some(ast_map::NodeMethod(m)) => {
- match m.node {
- ast::MethDecl(_, _, _, _, _, _, blk, _) => {
- let mut explicit = CheckForNestedReturnsVisitor { found: false };
- let mut implicit = CheckForNestedReturnsVisitor { found: false };
- visit::walk_method_helper(&mut explicit, &*m, false);
- visit::walk_expr_opt(&mut implicit, blk.expr, true);
- explicit.found || implicit.found
+ Some(ast_map::NodeImplItem(ref ii)) => {
+ match **ii {
+ ast::MethodImplItem(ref m) => {
+ match m.node {
+ ast::MethDecl(_, _, _, _, _, _, blk, _) => {
+ let mut explicit = CheckForNestedReturnsVisitor {
+ found: false,
+ };
+ let mut implicit = CheckForNestedReturnsVisitor {
+ found: false,
+ };
+ visit::walk_method_helper(&mut explicit,
+ &**m,
+ false);
+ visit::walk_expr_opt(&mut implicit,
+ blk.expr,
+ true);
+ explicit.found || implicit.found
+ }
+ ast::MethMac(_) => tcx.sess.bug("unexpanded macro")
+ }
}
- ast::MethMac(_) => tcx.sess.bug("unexpanded macro")
}
}
Some(ast_map::NodeExpr(e)) => {
match e.node {
- ast::ExprFnBlock(_, blk) | ast::ExprProc(_, blk) | ast::ExprUnboxedFn(_, blk) => {
+ ast::ExprFnBlock(_, _, blk) |
+ ast::ExprProc(_, blk) |
+ ast::ExprUnboxedFn(_, _, _, blk) => {
let mut explicit = CheckForNestedReturnsVisitor { found: false };
let mut implicit = CheckForNestedReturnsVisitor { found: false };
visit::walk_expr(&mut explicit, &*e, false);
output_type: ty::t,
param_substs: &'a param_substs,
sp: Option<Span>,
- block_arena: &'a TypedArena<Block<'a>>,
- handle_items: HandleItemsFlag)
+ block_arena: &'a TypedArena<Block<'a>>)
-> FunctionContext<'a> {
param_substs.validate();
block_arena: block_arena,
ccx: ccx,
debug_context: debug_context,
- scopes: RefCell::new(Vec::new()),
- handle_items: handle_items,
+ scopes: RefCell::new(Vec::new())
};
if has_env {
/// Creates rvalue datums for each of the incoming function arguments and
/// tuples the arguments. These will later be stored into appropriate lvalue
/// datums.
+///
+/// FIXME(pcwalton): Reduce the amount of code bloat this is responsible for.
fn create_datums_for_fn_args_under_call_abi<
'a>(
mut bcx: &'a Block<'a>,
abi: Abi,
has_env: bool,
is_unboxed_closure: IsUnboxedClosureFlag,
- maybe_load_env: <'a> |&'a Block<'a>| -> &'a Block<'a>,
- handle_items: HandleItemsFlag) {
+ maybe_load_env: <'a>|&'a Block<'a>, ScopeId|
+ -> &'a Block<'a>) {
ccx.stats.n_closures.set(ccx.stats.n_closures.get() + 1);
let _icx = push_ctxt("trans_closure");
output_type,
param_substs,
Some(body.span),
- &arena,
- handle_items);
+ &arena);
let mut bcx = init_function(&fcx, false, output_type);
// cleanup scope for the incoming arguments
}
};
- bcx = maybe_load_env(bcx);
+ bcx = maybe_load_env(bcx, cleanup::CustomScope(arg_scope));
// Up until here, IR instructions for this function have explicitly not been annotated with
// source code location, so we don't step into call setup code. From here on, source location
llfndecl: ValueRef,
param_substs: ¶m_substs,
id: ast::NodeId,
- attrs: &[ast::Attribute],
- handle_items: HandleItemsFlag) {
+ attrs: &[ast::Attribute]) {
let _s = StatRecorder::new(ccx, ccx.tcx.map.path_to_string(id).to_string());
debug!("trans_fn(param_substs={})", param_substs.repr(ccx.tcx()));
let _icx = push_ctxt("trans_fn");
abi,
false,
NotUnboxedClosure,
- |bcx| bcx,
- handle_items);
+ |bcx, _| bcx);
}
pub fn trans_enum_variant(ccx: &CrateContext,
};
if !type_is_zero_size(ccx, result_ty) {
- let repr = adt::represent_type(ccx, result_ty);
-
match args {
callee::ArgExprs(exprs) => {
let fields = exprs.iter().map(|x| *x).enumerate().collect::<Vec<_>>();
- bcx = expr::trans_adt(bcx, &*repr, disr, fields.as_slice(),
+ bcx = expr::trans_adt(bcx, result_ty, disr, fields.as_slice(),
None, expr::SaveIn(llresult));
}
_ => ccx.sess().bug("expected expr as arguments for variant/struct tuple constructor")
let arena = TypedArena::new();
let fcx = new_fn_ctxt(ccx, llfndecl, ctor_id, false, result_ty,
- param_substs, None, &arena, TranslateItems);
+ param_substs, None, &arena);
let bcx = init_function(&fcx, false, result_ty);
assert!(!fcx.needs_ret_allocas);
llfn,
¶m_substs::empty(),
item.id,
- None,
- TranslateItems);
+ None);
} else {
trans_fn(ccx,
&**decl,
llfn,
¶m_substs::empty(),
item.id,
- item.attrs.as_slice(),
- TranslateItems);
+ item.attrs.as_slice());
}
- } else {
- // Be sure to travel more than just one layer deep to catch nested
- // items in blocks and such.
- let mut v = TransItemVisitor{ ccx: ccx };
- v.visit_block(&**body, ());
}
+
+ // Be sure to travel more than just one layer deep to catch nested
+ // items in blocks and such.
+ let mut v = TransItemVisitor{ ccx: ccx };
+ v.visit_block(&**body, ());
}
- ast::ItemImpl(ref generics, _, _, ref ms) => {
- meth::trans_impl(ccx, item.ident, ms.as_slice(), generics, item.id);
+ ast::ItemImpl(ref generics, _, _, ref impl_items) => {
+ meth::trans_impl(ccx,
+ item.ident,
+ impl_items.as_slice(),
+ generics,
+ item.id);
}
ast::ItemMod(ref m) => {
trans_mod(ccx, m);
let (fn_sig, abi, has_env) = match ty::get(fn_ty).sty {
ty::ty_closure(ref f) => (f.sig.clone(), f.abi, true),
ty::ty_bare_fn(ref f) => (f.sig.clone(), f.abi, false),
- ty::ty_unboxed_closure(closure_did) => {
- let unboxed_closure_types = ccx.tcx
- .unboxed_closure_types
- .borrow();
- let function_type = unboxed_closure_types.get(&closure_did);
+ ty::ty_unboxed_closure(closure_did, _) => {
+ let unboxed_closures = ccx.tcx.unboxed_closures.borrow();
+ let function_type = unboxed_closures.get(&closure_did)
+ .closure_type
+ .clone();
(function_type.sig.clone(), RustCall, true)
}
_ => fail!("expected closure or function.")
v
}
- ast_map::NodeTraitMethod(trait_method) => {
- debug!("get_item_val(): processing a NodeTraitMethod");
+ ast_map::NodeTraitItem(trait_method) => {
+ debug!("get_item_val(): processing a NodeTraitItem");
match *trait_method {
- ast::Required(_) => {
+ ast::RequiredMethod(_) => {
ccx.sess().bug("unexpected variant: required trait method in \
get_item_val()");
}
- ast::Provided(m) => {
+ ast::ProvidedMethod(m) => {
register_method(ccx, id, &*m)
}
}
}
- ast_map::NodeMethod(m) => {
- register_method(ccx, id, &*m)
+ ast_map::NodeImplItem(ii) => {
+ match *ii {
+ ast::MethodImplItem(m) => register_method(ccx, id, &*m),
+ }
}
ast_map::NodeForeignItem(ni) => {
use middle::trans::cabi_mips;
use middle::trans::type_::Type;
use syntax::abi::{X86, X86_64, Arm, Mips, Mipsel};
-use syntax::abi::{OsWin32};
+use syntax::abi::{OsWindows};
#[deriving(Clone, PartialEq)]
pub enum ArgKind {
match ccx.sess().targ_cfg.arch {
X86 => cabi_x86::compute_abi_info(ccx, atys, rty, ret_def),
X86_64 =>
- if ccx.sess().targ_cfg.os == OsWin32 {
+ if ccx.sess().targ_cfg.os == OsWindows {
cabi_x86_win64::compute_abi_info(ccx, atys, rty, ret_def)
} else {
cabi_x86_64::compute_abi_info(ccx, atys, rty, ret_def)
// except according to those terms.
-use syntax::abi::{OsWin32, OsMacos, OsiOS};
+use syntax::abi::{OsWindows, OsMacos, OsiOS};
use llvm::*;
use super::cabi::*;
use super::common::*;
enum Strategy { RetValue(Type), RetPointer }
let strategy = match ccx.sess().targ_cfg.os {
- OsWin32 | OsMacos | OsiOS => {
+ OsWindows | OsMacos | OsiOS => {
match llsize_of_alloc(ccx, rty) {
1 => RetValue(Type::i8(ccx)),
2 => RetValue(Type::i16(ccx)),
Intrinsic(ast::NodeId, subst::Substs),
- TraitMethod(MethodData)
+ TraitItem(MethodData)
}
pub struct Callee<'a> {
return_type,
&empty_param_substs,
None,
- &block_arena,
- TranslateItems);
+ &block_arena);
let mut bcx = init_function(&fcx, false, return_type);
// Create the substituted versions of the self type.
assert!(substs.types.all(|t| !ty::type_needs_infer(*t)));
// Load the info for the appropriate trait if necessary.
- match ty::trait_of_method(tcx, def_id) {
+ match ty::trait_of_item(tcx, def_id) {
None => {}
Some(trait_id) => {
ty::populate_implementations_for_trait_if_necessary(tcx, trait_id)
// So, what we need to do is find this substitution and
// compose it with the one we already have.
- let impl_id = ty::method(tcx, def_id).container_id();
- let method = ty::method(tcx, source_id);
- let trait_ref = ty::impl_trait_ref(tcx, impl_id)
- .expect("could not find trait_ref for impl with \
- default methods");
-
- // Compute the first substitution
- let first_subst = make_substs_for_receiver_types(
- tcx, &*trait_ref, &*method);
-
- // And compose them
- let new_substs = first_subst.subst(tcx, &substs);
-
- debug!("trans_fn_with_vtables - default method: \
- substs = {}, trait_subst = {}, \
- first_subst = {}, new_subst = {}, \
- vtables = {}",
- substs.repr(tcx), trait_ref.substs.repr(tcx),
- first_subst.repr(tcx), new_substs.repr(tcx),
- vtables.repr(tcx));
-
- let param_vtables =
- resolve_default_method_vtables(bcx, impl_id, &substs, vtables);
-
- debug!("trans_fn_with_vtables - default method: \
- param_vtables = {}",
- param_vtables.repr(tcx));
-
- (true, source_id, new_substs, param_vtables)
+ let impl_id = ty::impl_or_trait_item(tcx, def_id).container()
+ .id();
+ let impl_or_trait_item = ty::impl_or_trait_item(tcx, source_id);
+ match impl_or_trait_item {
+ ty::MethodTraitItem(method) => {
+ let trait_ref = ty::impl_trait_ref(tcx, impl_id)
+ .expect("could not find trait_ref for impl with \
+ default methods");
+
+ // Compute the first substitution
+ let first_subst = make_substs_for_receiver_types(
+ tcx, &*trait_ref, &*method);
+
+ // And compose them
+ let new_substs = first_subst.subst(tcx, &substs);
+
+ debug!("trans_fn_with_vtables - default method: \
+ substs = {}, trait_subst = {}, \
+ first_subst = {}, new_subst = {}, \
+ vtables = {}",
+ substs.repr(tcx), trait_ref.substs.repr(tcx),
+ first_subst.repr(tcx), new_substs.repr(tcx),
+ vtables.repr(tcx));
+
+ let param_vtables =
+ resolve_default_method_vtables(bcx,
+ impl_id,
+ &substs,
+ vtables);
+
+ debug!("trans_fn_with_vtables - default method: \
+ param_vtables = {}",
+ param_vtables.repr(tcx));
+
+ (true, source_id, new_substs, param_vtables)
+ }
+ }
}
};
Fn(llfn) => {
(llfn, None, None)
}
- TraitMethod(d) => {
+ TraitItem(d) => {
(d.llfn, None, Some(d.llself))
}
Closure(d) => {
use middle::trans::adt;
use middle::trans::base::*;
use middle::trans::build::*;
+use middle::trans::cleanup::{CleanupMethods, ScopeId};
use middle::trans::common::*;
use middle::trans::datum::{Datum, DatumBlock, Expr, Lvalue, rvalue_scratch_datum};
use middle::trans::debuginfo;
fn load_unboxed_closure_environment<'a>(
bcx: &'a Block<'a>,
- freevars: &Vec<freevars::freevar_entry>)
+ arg_scope_id: ScopeId,
+ freevars: &Vec<freevars::freevar_entry>,
+ closure_id: ast::DefId)
-> &'a Block<'a> {
let _icx = push_ctxt("closure::load_environment");
return bcx
}
- let llenv = bcx.fcx.llenv.unwrap();
+ // Special case for small by-value selfs.
+ let self_type = self_type_for_unboxed_closure(bcx.ccx(), closure_id);
+ let kind = kind_for_unboxed_closure(bcx.ccx(), closure_id);
+ let llenv = if kind == ty::FnOnceUnboxedClosureKind &&
+ !arg_is_indirect(bcx.ccx(), self_type) {
+ let datum = rvalue_scratch_datum(bcx,
+ self_type,
+ "unboxed_closure_env");
+ store_ty(bcx, bcx.fcx.llenv.unwrap(), datum.val, self_type);
+ assert!(freevars.len() <= 1);
+ datum.val
+ } else {
+ bcx.fcx.llenv.unwrap()
+ };
+
for (i, freevar) in freevars.iter().enumerate() {
let upvar_ptr = GEPi(bcx, llenv, [0, i]);
let def_id = freevar.def.def_id();
bcx.fcx.llupvars.borrow_mut().insert(def_id.node, upvar_ptr);
+
+ if kind == ty::FnOnceUnboxedClosureKind {
+ bcx.fcx.schedule_drop_mem(arg_scope_id,
+ upvar_ptr,
+ node_id_type(bcx, def_id.node))
+ }
}
bcx
ty::ty_fn_abi(fty),
true,
NotUnboxedClosure,
- |bcx| load_environment(bcx, cdata_ty, &freevars, store),
- bcx.fcx.handle_items);
+ |bcx, _| load_environment(bcx, cdata_ty, &freevars, store));
fill_fn_pair(bcx, dest_addr, llfn, llbox);
bcx
}
pub fn get_or_create_declaration_if_unboxed_closure(ccx: &CrateContext,
closure_id: ast::DefId)
-> Option<ValueRef> {
- if !ccx.tcx.unboxed_closure_types.borrow().contains_key(&closure_id) {
+ if !ccx.tcx.unboxed_closures.borrow().contains_key(&closure_id) {
// Not an unboxed closure.
return None
}
None => {}
}
- let function_type = ty::mk_unboxed_closure(&ccx.tcx, closure_id);
+ let function_type = ty::mk_unboxed_closure(&ccx.tcx,
+ closure_id,
+ ty::ReStatic);
let symbol = ccx.tcx.map.with_path(closure_id.node, |path| {
mangle_internal_name_by_path_and_seq(path, "unboxed_closure")
});
bcx.ccx(),
closure_id).unwrap();
- // Untuple the arguments.
- let unboxed_closure_types = bcx.tcx().unboxed_closure_types.borrow();
- let /*mut*/ function_type = (*unboxed_closure_types.get(&closure_id)).clone();
- /*function_type.sig.inputs =
- match ty::get(*function_type.sig.inputs.get(0)).sty {
- ty::ty_tup(ref tuple_types) => {
- tuple_types.iter().map(|x| (*x).clone()).collect()
- }
- _ => {
- bcx.tcx().sess.span_bug(body.span,
- "unboxed closure wasn't a tuple?!")
- }
- };*/
+ let unboxed_closures = bcx.tcx().unboxed_closures.borrow();
+ let function_type = unboxed_closures.get(&closure_id)
+ .closure_type
+ .clone();
let function_type = ty::mk_closure(bcx.tcx(), function_type);
let freevars: Vec<freevars::freevar_entry> =
ty::ty_fn_abi(function_type),
true,
IsUnboxedClosure,
- |bcx| load_unboxed_closure_environment(bcx, freevars_ptr),
- bcx.fcx.handle_items);
+ |bcx, arg_scope| {
+ load_unboxed_closure_environment(bcx,
+ arg_scope,
+ freevars_ptr,
+ closure_id)
+ });
// Don't hoist this to the top of the function. It's perfectly legitimate
// to have a zero-size unboxed closure (in which case dest will be
let repr = adt::represent_type(bcx.ccx(), node_id_type(bcx, id));
// Create the closure.
- for freevar in freevars_ptr.iter() {
+ for (i, freevar) in freevars_ptr.iter().enumerate() {
let datum = expr::trans_local_var(bcx, freevar.def);
let upvar_slot_dest = adt::trans_field_ptr(bcx,
&*repr,
dest_addr,
0,
- 0);
+ i);
bcx = datum.store_to(bcx, upvar_slot_dest);
}
adt::trans_set_discr(bcx, &*repr, dest_addr, 0);
let arena = TypedArena::new();
let empty_param_substs = param_substs::empty();
let fcx = new_fn_ctxt(ccx, llfn, ast::DUMMY_NODE_ID, true, f.sig.output,
- &empty_param_substs, None, &arena, TranslateItems);
+ &empty_param_substs, None, &arena);
let bcx = init_function(&fcx, true, f.sig.output);
let args = create_datums_for_fn_args(&fcx,
use llvm::{True, False, Bool};
use mc = middle::mem_categorization;
use middle::def;
+use middle::freevars;
use middle::lang_items::LangItem;
use middle::subst;
use middle::subst::Subst;
use middle::ty;
use middle::typeck;
use util::ppaux::Repr;
-use util::nodemap::NodeMap;
+use util::nodemap::{DefIdMap, NodeMap};
use arena::TypedArena;
use std::collections::HashMap;
pub type RvalueDatum = datum::Datum<datum::Rvalue>;
pub type LvalueDatum = datum::Datum<datum::Lvalue>;
-#[deriving(Clone, Eq, PartialEq)]
-pub enum HandleItemsFlag {
- IgnoreItems,
- TranslateItems,
-}
-
// Function context. Every LLVM function we create will have one of
// these.
pub struct FunctionContext<'a> {
// Cleanup scopes.
pub scopes: RefCell<Vec<cleanup::CleanupScope<'a>> >,
-
- // How to handle items encountered during translation of this function.
- pub handle_items: HandleItemsFlag,
}
impl<'a> FunctionContext<'a> {
self.tcx().region_maps.temporary_scope(rvalue_id)
}
+ fn unboxed_closures<'a>(&'a self)
+ -> &'a RefCell<DefIdMap<ty::UnboxedClosure>> {
+ &self.tcx().unboxed_closures
+ }
+
fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow {
self.tcx().upvar_borrow_map.borrow().get_copy(&upvar_id)
}
+
+ fn capture_mode(&self, closure_expr_id: ast::NodeId)
+ -> freevars::CaptureMode {
+ self.tcx().capture_modes.borrow().get_copy(&closure_expr_id)
+ }
}
pub struct Result<'a> {
debuginfo::create_local_var_metadata(bcx, &**local);
}
}
- ast::DeclItem(ref i) => {
- match fcx.handle_items {
- TranslateItems => trans_item(cx.fcx.ccx, &**i),
- IgnoreItems => {}
- }
- }
+ // Inner items are visited by `trans_item`/`trans_meth`.
+ ast::DeclItem(_) => {},
}
}
ast::StmtMac(..) => cx.tcx().sess.bug("unexpanded macro")
// Check the discriminant; if the `None` case, exit the loop.
let option_representation = adt::represent_type(loopback_bcx_out.ccx(),
method_result_type);
- let i8_type = Type::i8(loopback_bcx_out.ccx());
let lldiscriminant = adt::trans_get_discr(loopback_bcx_out,
&*option_representation,
option_datum.val,
- Some(i8_type));
- let llzero = C_u8(loopback_bcx_out.ccx(), 0);
- let llcondition = ICmp(loopback_bcx_out, IntNE, lldiscriminant, llzero);
+ None);
+ let i1_type = Type::i1(loopback_bcx_out.ccx());
+ let llcondition = Trunc(loopback_bcx_out, lldiscriminant, i1_type);
CondBr(loopback_bcx_out, llcondition, body_bcx_in.llbb, cleanup_llbb);
// Now we're in the body. Unpack the `Option` value into the programmer-
use syntax::codemap::{Span, Pos};
use syntax::{abi, ast, codemap, ast_util, ast_map};
use syntax::ast_util::PostExpansionMethod;
-use syntax::owned_slice::OwnedSlice;
use syntax::parse::token;
use syntax::parse::token::special_idents;
return FunctionDebugContext { repr: FunctionWithoutDebugInfo };
}
- let empty_generics = ast::Generics { lifetimes: Vec::new(),
- ty_params: OwnedSlice::empty() };
+ let empty_generics = ast_util::empty_generics();
let fnitem = cx.tcx.map.get(fn_ast_id);
let (ident, fn_decl, generics, top_level_block, span, has_path) = match fnitem {
ast_map::NodeItem(ref item) => {
+ if contains_nodebug_attribute(item.attrs.as_slice()) {
+ return FunctionDebugContext { repr: FunctionWithoutDebugInfo };
+ }
+
match item.node {
ast::ItemFn(fn_decl, _, _, ref generics, top_level_block) => {
(item.ident, fn_decl, generics, top_level_block, item.span, true)
}
}
}
- ast_map::NodeMethod(ref method) => {
- (method.pe_ident(),
- method.pe_fn_decl(),
- method.pe_generics(),
- method.pe_body(),
- method.span,
- true)
+ ast_map::NodeImplItem(ref item) => {
+ match **item {
+ ast::MethodImplItem(ref method) => {
+ if contains_nodebug_attribute(method.attrs.as_slice()) {
+ return FunctionDebugContext {
+ repr: FunctionWithoutDebugInfo
+ };
+ }
+
+ (method.pe_ident(),
+ method.pe_fn_decl(),
+ method.pe_generics(),
+ method.pe_body(),
+ method.span,
+ true)
+ }
+ }
}
ast_map::NodeExpr(ref expr) => {
match expr.node {
- ast::ExprFnBlock(fn_decl, top_level_block) |
+ ast::ExprFnBlock(_, fn_decl, top_level_block) |
ast::ExprProc(fn_decl, top_level_block) |
- ast::ExprUnboxedFn(fn_decl, top_level_block) => {
+ ast::ExprUnboxedFn(_, _, fn_decl, top_level_block) => {
let name = format!("fn{}", token::gensym("fn"));
let name = token::str_to_ident(name.as_slice());
(name, fn_decl,
"create_function_debug_context: expected an expr_fn_block here")
}
}
- ast_map::NodeTraitMethod(ref trait_method) => {
+ ast_map::NodeTraitItem(ref trait_method) => {
match **trait_method {
- ast::Provided(ref method) => {
+ ast::ProvidedMethod(ref method) => {
+ if contains_nodebug_attribute(method.attrs.as_slice()) {
+ return FunctionDebugContext {
+ repr: FunctionWithoutDebugInfo
+ };
+ }
+
(method.pe_ident(),
method.pe_fn_decl(),
method.pe_generics(),
// Utility Functions
//=-----------------------------------------------------------------------------
+fn contains_nodebug_attribute(attributes: &[ast::Attribute]) -> bool {
+ attributes.iter().any(|attr| {
+ let meta_item: &ast::MetaItem = &*attr.node.value;
+ match meta_item.node {
+ ast::MetaWord(ref value) => value.get() == "no_debug",
+ _ => false
+ }
+ })
+}
+
/// Return codemap::Loc corresponding to the beginning of the span
fn span_start(cx: &CrateContext, span: Span) -> codemap::Loc {
cx.sess().codemap().lookup_char_pos(span.lo)
})
}
- ast::ExprFnBlock(ref decl, ref block) |
+ ast::ExprFnBlock(_, ref decl, ref block) |
ast::ExprProc(ref decl, ref block) |
- ast::ExprUnboxedFn(ref decl, ref block) => {
+ ast::ExprUnboxedFn(_, _, ref decl, ref block) => {
with_new_scope(cx,
block.span,
scope_stack,
push_debuginfo_type_name(cx, sig.output, true, output);
}
},
- ty::ty_unboxed_closure(_) => {
+ ty::ty_unboxed_closure(..) => {
output.push_str("closure");
}
ty::ty_err |
controlflow::trans_block(bcx, &**blk, dest)
}
ast::ExprStruct(_, ref fields, base) => {
- trans_rec_or_struct(bcx,
- fields.as_slice(),
- base,
- expr.span,
- expr.id,
- dest)
+ trans_struct(bcx,
+ fields.as_slice(),
+ base,
+ expr.span,
+ expr.id,
+ dest)
}
ast::ExprTup(ref args) => {
- let repr = adt::represent_type(bcx.ccx(), expr_ty(bcx, expr));
let numbered_fields: Vec<(uint, Gc<ast::Expr>)> =
args.iter().enumerate().map(|(i, arg)| (i, *arg)).collect();
- trans_adt(bcx, &*repr, 0, numbered_fields.as_slice(), None, dest)
+ trans_adt(bcx, expr_ty(bcx, expr), 0, numbered_fields.as_slice(), None, dest)
}
ast::ExprLit(lit) => {
match lit.node {
ast::ExprVec(..) | ast::ExprRepeat(..) => {
tvec::trans_fixed_vstore(bcx, expr, expr, dest)
}
- ast::ExprFnBlock(ref decl, ref body) |
+ ast::ExprFnBlock(_, ref decl, ref body) |
ast::ExprProc(ref decl, ref body) => {
let expr_ty = expr_ty(bcx, expr);
let store = ty::ty_closure_store(expr_ty);
expr_to_string(expr), expr_ty.repr(tcx));
closure::trans_expr_fn(bcx, store, &**decl, &**body, expr.id, dest)
}
- ast::ExprUnboxedFn(decl, body) => {
+ ast::ExprUnboxedFn(_, _, decl, body) => {
closure::trans_unboxed_closure(bcx, &*decl, &*body, expr.id, dest)
}
ast::ExprCall(ref f, ref args) => {
}
}
-fn trans_rec_or_struct<'a>(
- bcx: &'a Block<'a>,
- fields: &[ast::Field],
- base: Option<Gc<ast::Expr>>,
- expr_span: codemap::Span,
- id: ast::NodeId,
- dest: Dest)
- -> &'a Block<'a> {
+fn trans_struct<'a>(bcx: &'a Block<'a>,
+ fields: &[ast::Field],
+ base: Option<Gc<ast::Expr>>,
+ expr_span: codemap::Span,
+ id: ast::NodeId,
+ dest: Dest) -> &'a Block<'a> {
let _icx = push_ctxt("trans_rec");
- let bcx = bcx;
let ty = node_id_type(bcx, id);
let tcx = bcx.tcx();
}
};
- let repr = adt::represent_type(bcx.ccx(), ty);
- trans_adt(bcx, &*repr, discr, numbered_fields.as_slice(), optbase, dest)
+ trans_adt(bcx, ty, discr, numbered_fields.as_slice(), optbase, dest)
})
}
* - `optbase` contains information on the base struct (if any) from
* which remaining fields are copied; see comments on `StructBaseInfo`.
*/
-pub fn trans_adt<'a>(bcx: &'a Block<'a>,
- repr: &adt::Repr,
+pub fn trans_adt<'a>(mut bcx: &'a Block<'a>,
+ ty: ty::t,
discr: ty::Disr,
fields: &[(uint, Gc<ast::Expr>)],
optbase: Option<StructBaseInfo>,
dest: Dest) -> &'a Block<'a> {
let _icx = push_ctxt("trans_adt");
let fcx = bcx.fcx;
- let mut bcx = bcx;
+ let repr = adt::represent_type(bcx.ccx(), ty);
+
+ // If we don't care about the result, just make a
+ // temporary stack slot
let addr = match dest {
- Ignore => {
- for &(_i, ref e) in fields.iter() {
- bcx = trans_into(bcx, &**e, Ignore);
- }
- for sbi in optbase.iter() {
- // FIXME #7261: this moves entire base, not just certain fields
- bcx = trans_into(bcx, &*sbi.expr, Ignore);
- }
- return bcx;
- }
- SaveIn(pos) => pos
+ SaveIn(pos) => pos,
+ Ignore => alloc_ty(bcx, ty, "temp"),
};
// This scope holds intermediates that must be cleaned should
// failure occur before the ADT as a whole is ready.
let custom_cleanup_scope = fcx.push_custom_cleanup_scope();
+ // First we trans the base, if we have one, to the dest
+ for base in optbase.iter() {
+ assert_eq!(discr, 0);
+
+ match ty::expr_kind(bcx.tcx(), &*base.expr) {
+ ty::LvalueExpr => {
+ let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, &*base.expr, "base"));
+ for &(i, t) in base.fields.iter() {
+ let datum = base_datum.get_element(
+ t, |srcval| adt::trans_field_ptr(bcx, &*repr, srcval, discr, i));
+ let dest = adt::trans_field_ptr(bcx, &*repr, addr, discr, i);
+ bcx = datum.store_to(bcx, dest);
+ }
+ },
+ ty::RvalueDpsExpr | ty::RvalueDatumExpr => {
+ bcx = trans_into(bcx, &*base.expr, SaveIn(addr));
+ },
+ ty::RvalueStmtExpr => bcx.tcx().sess.bug("unexpected expr kind for struct base expr")
+ }
+ }
+
+ // Now, we just overwrite the fields we've explicity specified
for &(i, ref e) in fields.iter() {
- let dest = adt::trans_field_ptr(bcx, repr, addr, discr, i);
+ let dest = adt::trans_field_ptr(bcx, &*repr, addr, discr, i);
let e_ty = expr_ty_adjusted(bcx, &**e);
bcx = trans_into(bcx, &**e, SaveIn(dest));
let scope = cleanup::CustomScope(custom_cleanup_scope);
fcx.schedule_drop_mem(scope, dest, e_ty);
}
- for base in optbase.iter() {
- // FIXME #6573: is it sound to use the destination's repr on the base?
- // And, would it ever be reasonable to be here with discr != 0?
- let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, &*base.expr, "base"));
- for &(i, t) in base.fields.iter() {
- let datum = base_datum.get_element(
- t,
- |srcval| adt::trans_field_ptr(bcx, repr, srcval, discr, i));
- let dest = adt::trans_field_ptr(bcx, repr, addr, discr, i);
- bcx = datum.store_to(bcx, dest);
- }
- }
-
- adt::trans_set_discr(bcx, repr, addr, discr);
+ adt::trans_set_discr(bcx, &*repr, addr, discr);
fcx.pop_custom_cleanup_scope(custom_cleanup_scope);
- return bcx;
+ // If we don't care about the result drop the temporary we made
+ match dest {
+ SaveIn(_) => bcx,
+ Ignore => {
+ bcx = glue::drop_ty(bcx, addr, ty);
+ base::call_lifetime_end(bcx, addr);
+ bcx
+ }
+ }
}
llwrapfn: ValueRef,
param_substs: ¶m_substs,
id: ast::NodeId,
- hash: Option<&str>,
- handle_items: HandleItemsFlag) {
+ hash: Option<&str>) {
let _icx = push_ctxt("foreign::build_foreign_fn");
let fnty = ty::node_id_to_type(ccx.tcx(), id);
unsafe { // unsafe because we call LLVM operations
// Build up the Rust function (`foo0` above).
- let llrustfn = build_rust_fn(ccx, decl, body, param_substs, attrs, id,
- hash, handle_items);
+ let llrustfn = build_rust_fn(ccx, decl, body, param_substs, attrs, id, hash);
// Build up the foreign wrapper (`foo` above).
return build_wrap_fn(ccx, llrustfn, llwrapfn, &tys, mty);
param_substs: ¶m_substs,
attrs: &[ast::Attribute],
id: ast::NodeId,
- hash: Option<&str>,
- handle_items: HandleItemsFlag)
+ hash: Option<&str>)
-> ValueRef {
let _icx = push_ctxt("foreign::foreign::build_rust_fn");
let tcx = ccx.tcx();
let llfn = base::decl_internal_rust_fn(ccx, t, ps.as_slice());
base::set_llvm_fn_attrs(attrs, llfn);
- base::trans_fn(ccx, decl, body, llfn, param_substs, id, [], handle_items);
+ base::trans_fn(ccx, decl, body, llfn, param_substs, id, []);
llfn
}
let llforeign_arg_ty = *tys.fn_ty.arg_tys.get(i);
let foreign_indirect = llforeign_arg_ty.is_indirect();
+ if llforeign_arg_ty.is_ignore() {
+ debug!("skipping ignored arg #{}", i);
+ llrust_args.push(C_undef(llrust_ty));
+ continue;
+ }
+
// skip padding
let foreign_index = next_foreign_arg(llforeign_arg_ty.pad.is_some());
let mut llforeign_arg = get_param(llwrapfn, foreign_index);
let arena = TypedArena::new();
let empty_param_substs = param_substs::empty();
let fcx = new_fn_ctxt(ccx, llfn, ast::DUMMY_NODE_ID, false, ty::mk_nil(),
- &empty_param_substs, None, &arena, TranslateItems);
+ &empty_param_substs, None, &arena);
let bcx = init_function(&fcx, false, ty::mk_nil());
ccx.sess().bug("maybe_get_item_ast returned a found_parent \
with a non-item parent");
}
- csearch::found(ast::IIMethod(impl_did, is_provided, mth)) => {
- ccx.external.borrow_mut().insert(fn_id, Some(mth.id));
- ccx.external_srcs.borrow_mut().insert(mth.id, fn_id);
+ csearch::found(ast::IITraitItem(impl_did, impl_item)) => {
+ match impl_item {
+ ast::ProvidedInlinedTraitItem(mth) |
+ ast::RequiredInlinedTraitItem(mth) => {
+ ccx.external.borrow_mut().insert(fn_id, Some(mth.id));
+ ccx.external_srcs.borrow_mut().insert(mth.id, fn_id);
- ccx.stats.n_inlines.set(ccx.stats.n_inlines.get() + 1);
-
- // If this is a default method, we can't look up the
- // impl type. But we aren't going to translate anyways, so don't.
- if is_provided { return local_def(mth.id); }
+ ccx.stats.n_inlines.set(ccx.stats.n_inlines.get() + 1);
+ }
+ }
- let impl_tpt = ty::lookup_item_type(ccx.tcx(), impl_did);
- let unparameterized =
- impl_tpt.generics.types.is_empty() &&
- mth.pe_generics().ty_params.is_empty();
+ match impl_item {
+ ast::ProvidedInlinedTraitItem(mth) => {
+ // If this is a default method, we can't look up the
+ // impl type. But we aren't going to translate anyways, so
+ // don't.
+ local_def(mth.id)
+ }
+ ast::RequiredInlinedTraitItem(mth) => {
+ let impl_tpt = ty::lookup_item_type(ccx.tcx(), impl_did);
+ let unparameterized = impl_tpt.generics.types.is_empty() &&
+ mth.pe_generics().ty_params.is_empty();
- if unparameterized {
- let llfn = get_item_val(ccx, mth.id);
- trans_fn(ccx, &*mth.pe_fn_decl(), &*mth.pe_body(), llfn,
- ¶m_substs::empty(), mth.id, [], TranslateItems);
- }
- local_def(mth.id)
+ if unparameterized {
+ let llfn = get_item_val(ccx, mth.id);
+ trans_fn(ccx,
+ &*mth.pe_fn_decl(),
+ &*mth.pe_body(),
+ llfn,
+ ¶m_substs::empty(),
+ mth.id,
+ []);
+ }
+ local_def(mth.id)
+ }
+ }
}
};
}
use util::ppaux::Repr;
use std::c_str::ToCStr;
-use std::gc::Gc;
use syntax::abi::{Rust, RustCall};
use syntax::parse::token;
use syntax::{ast, ast_map, visit};
*/
pub fn trans_impl(ccx: &CrateContext,
name: ast::Ident,
- methods: &[Gc<ast::Method>],
+ impl_items: &[ast::ImplItem],
generics: &ast::Generics,
id: ast::NodeId) {
let _icx = push_ctxt("meth::trans_impl");
// items that we need to translate.
if !generics.ty_params.is_empty() {
let mut v = TransItemVisitor{ ccx: ccx };
- for method in methods.iter() {
- visit::walk_method_helper(&mut v, &**method, ());
+ for impl_item in impl_items.iter() {
+ match *impl_item {
+ ast::MethodImplItem(method) => {
+ visit::walk_method_helper(&mut v, &*method, ());
+ }
+ }
}
return;
}
- for method in methods.iter() {
- if method.pe_generics().ty_params.len() == 0u {
- let llfn = get_item_val(ccx, method.id);
- trans_fn(ccx,
- &*method.pe_fn_decl(),
- &*method.pe_body(),
- llfn,
- ¶m_substs::empty(),
- method.id,
- [],
- TranslateItems);
- } else {
- let mut v = TransItemVisitor{ ccx: ccx };
- visit::walk_method_helper(&mut v, &**method, ());
+ for impl_item in impl_items.iter() {
+ match *impl_item {
+ ast::MethodImplItem(method) => {
+ if method.pe_generics().ty_params.len() == 0u {
+ let llfn = get_item_val(ccx, method.id);
+ trans_fn(ccx,
+ &*method.pe_fn_decl(),
+ &*method.pe_body(),
+ llfn,
+ ¶m_substs::empty(),
+ method.id,
+ []);
+ }
+ let mut v = TransItemVisitor {
+ ccx: ccx,
+ };
+ visit::walk_method_helper(&mut v, &*method, ());
+ }
}
}
}
let mname = if method_id.krate == ast::LOCAL_CRATE {
match bcx.tcx().map.get(method_id.node) {
- ast_map::NodeTraitMethod(method) => {
+ ast_map::NodeTraitItem(method) => {
let ident = match *method {
- ast::Required(ref m) => m.ident,
- ast::Provided(ref m) => m.pe_ident()
+ ast::RequiredMethod(ref m) => m.ident,
+ ast::ProvidedMethod(ref m) => m.pe_ident()
};
ident.name
}
}
}
-fn method_with_name(ccx: &CrateContext,
- impl_id: ast::DefId,
- name: ast::Name) -> ast::DefId {
+fn method_with_name(ccx: &CrateContext, impl_id: ast::DefId, name: ast::Name)
+ -> ast::DefId {
match ccx.impl_method_cache.borrow().find_copy(&(impl_id, name)) {
Some(m) => return m,
None => {}
}
- let methods = ccx.tcx.impl_methods.borrow();
- let methods = methods.find(&impl_id)
- .expect("could not find impl while translating");
- let meth_did = methods.iter().find(|&did| ty::method(&ccx.tcx, *did).ident.name == name)
- .expect("could not find method while translating");
-
- ccx.impl_method_cache.borrow_mut().insert((impl_id, name), *meth_did);
- *meth_did
+ let impl_items = ccx.tcx.impl_items.borrow();
+ let impl_items =
+ impl_items.find(&impl_id)
+ .expect("could not find impl while translating");
+ let meth_did = impl_items.iter()
+ .find(|&did| {
+ match *did {
+ ty::MethodTraitItemId(did) => {
+ ty::impl_or_trait_item(&ccx.tcx,
+ did).ident()
+ .name ==
+ name
+ }
+ }
+ }).expect("could not find method while \
+ translating");
+
+ ccx.impl_method_cache.borrow_mut().insert((impl_id, name),
+ meth_did.def_id());
+ meth_did.def_id()
}
fn trans_monomorphized_callee<'a>(
match vtbl {
typeck::vtable_static(impl_did, rcvr_substs, rcvr_origins) => {
let ccx = bcx.ccx();
- let mname = ty::trait_method(ccx.tcx(), trait_id, n_method).ident;
+ let mname = match ty::trait_item(ccx.tcx(), trait_id, n_method) {
+ ty::MethodTraitItem(method) => method.ident,
+ };
let mth_id = method_with_name(bcx.ccx(), impl_did, mname.name);
// create a concatenated set of substitutions which includes
return Callee {
bcx: bcx,
- data: TraitMethod(MethodData {
+ data: TraitItem(MethodData {
llfn: mptr,
llself: llself,
})
fn get_callee_substitutions_for_unboxed_closure(bcx: &Block,
def_id: ast::DefId)
-> subst::Substs {
- let self_ty = ty::mk_unboxed_closure(bcx.tcx(), def_id);
+ let self_ty = ty::mk_unboxed_closure(bcx.tcx(), def_id, ty::ReStatic);
subst::Substs::erased(
VecPerParamSpace::new(Vec::new(),
vec![
ty::populate_implementations_for_trait_if_necessary(bcx.tcx(), trt_id);
- let trait_method_def_ids = ty::trait_method_def_ids(tcx, trt_id);
- trait_method_def_ids.iter().map(|method_def_id| {
- let ident = ty::method(tcx, *method_def_id).ident;
+ let trait_item_def_ids = ty::trait_item_def_ids(tcx, trt_id);
+ trait_item_def_ids.iter().map(|method_def_id| {
+ let method_def_id = method_def_id.def_id();
+ let ident = ty::impl_or_trait_item(tcx, method_def_id).ident();
// The substitutions we have are on the impl, so we grab
// the method type from the impl to substitute into.
let m_id = method_with_name(ccx, impl_id, ident.name);
- let m = ty::method(tcx, m_id);
- debug!("(making impl vtable) emitting method {} at subst {}",
- m.repr(tcx),
- substs.repr(tcx));
- if m.generics.has_type_params(subst::FnSpace) ||
- ty::type_has_self(ty::mk_bare_fn(tcx, m.fty.clone())) {
- debug!("(making impl vtable) method has self or type params: {}",
- token::get_ident(ident));
- C_null(Type::nil(ccx).ptr_to())
- } else {
- let mut fn_ref = trans_fn_ref_with_vtables(bcx,
- m_id,
- ExprId(0),
- substs.clone(),
- vtables.clone());
- if m.explicit_self == ty::ByValueExplicitSelfCategory {
- fn_ref = trans_unboxing_shim(bcx,
- fn_ref,
- &*m,
- m_id,
- substs.clone());
+ let ti = ty::impl_or_trait_item(tcx, m_id);
+ match ti {
+ ty::MethodTraitItem(m) => {
+ debug!("(making impl vtable) emitting method {} at subst {}",
+ m.repr(tcx),
+ substs.repr(tcx));
+ if m.generics.has_type_params(subst::FnSpace) ||
+ ty::type_has_self(ty::mk_bare_fn(tcx, m.fty.clone())) {
+ debug!("(making impl vtable) method has self or type \
+ params: {}",
+ token::get_ident(ident));
+ C_null(Type::nil(ccx).ptr_to())
+ } else {
+ let mut fn_ref = trans_fn_ref_with_vtables(
+ bcx,
+ m_id,
+ ExprId(0),
+ substs.clone(),
+ vtables.clone());
+ if m.explicit_self == ty::ByValueExplicitSelfCategory {
+ fn_ref = trans_unboxing_shim(bcx,
+ fn_ref,
+ &*m,
+ m_id,
+ substs.clone());
+ }
+ fn_ref
+ }
}
- fn_ref
}
}).collect()
}
if abi != abi::Rust {
foreign::trans_rust_fn_with_foreign_abi(
ccx, &**decl, &**body, [], d, &psubsts, fn_id.node,
- Some(hash.as_slice()), IgnoreItems);
+ Some(hash.as_slice()));
} else {
- trans_fn(ccx, &**decl, &**body, d, &psubsts, fn_id.node, [],
- IgnoreItems);
+ trans_fn(ccx, &**decl, &**body, d, &psubsts, fn_id.node, []);
}
d
}
d
}
- ast_map::NodeMethod(mth) => {
- let d = mk_lldecl(abi::Rust);
- set_llvm_fn_attrs(mth.attrs.as_slice(), d);
- trans_fn(ccx, &*mth.pe_fn_decl(), &*mth.pe_body(), d, &psubsts, mth.id, [],
- IgnoreItems);
- d
+ ast_map::NodeImplItem(ii) => {
+ match *ii {
+ ast::MethodImplItem(mth) => {
+ let d = mk_lldecl(abi::Rust);
+ set_llvm_fn_attrs(mth.attrs.as_slice(), d);
+ trans_fn(ccx,
+ &*mth.pe_fn_decl(),
+ &*mth.pe_body(),
+ d,
+ &psubsts,
+ mth.id,
+ []);
+ d
+ }
+ }
}
- ast_map::NodeTraitMethod(method) => {
+ ast_map::NodeTraitItem(method) => {
match *method {
- ast::Provided(mth) => {
+ ast::ProvidedMethod(mth) => {
let d = mk_lldecl(abi::Rust);
set_llvm_fn_attrs(mth.attrs.as_slice(), d);
trans_fn(ccx, &*mth.pe_fn_decl(), &*mth.pe_body(), d,
- &psubsts, mth.id, [], IgnoreItems);
+ &psubsts, mth.id, []);
d
}
_ => {
use middle::ty;
use util::ppaux::ty_to_string;
-use std::rc::Rc;
use arena::TypedArena;
use libc::c_uint;
use syntax::ast::DefId;
pub struct Reflector<'a, 'b> {
visitor_val: ValueRef,
- visitor_methods: &'a [Rc<ty::Method>],
+ visitor_items: &'a [ty::ImplOrTraitItem],
final_bcx: &'b Block<'b>,
tydesc_ty: Type,
bcx: &'b Block<'b>
pub fn visit(&mut self, ty_name: &str, args: &[ValueRef]) {
let fcx = self.bcx.fcx;
let tcx = self.bcx.tcx();
- let mth_idx = ty::method_idx(token::str_to_ident(format!(
+ let mth_idx = ty::impl_or_trait_item_idx(token::str_to_ident(format!(
"visit_{}", ty_name).as_slice()),
- self.visitor_methods.as_slice()).expect(
+ self.visitor_items.as_slice()).expect(
format!("couldn't find visit method for {}", ty_name).as_slice());
- let mth_ty =
- ty::mk_bare_fn(tcx,
- self.visitor_methods[mth_idx].fty.clone());
+ let method = match self.visitor_items[mth_idx] {
+ ty::MethodTraitItem(ref method) => (*method).clone(),
+ };
+ let mth_ty = ty::mk_bare_fn(tcx, method.fty.clone());
let v = self.visitor_val;
debug!("passing {} args:", args.len());
let mut bcx = self.bcx;
let empty_param_substs = param_substs::empty();
let fcx = new_fn_ctxt(ccx, llfdecl, ast::DUMMY_NODE_ID, false,
ty::mk_u64(), &empty_param_substs,
- None, &arena, TranslateItems);
+ None, &arena);
let bcx = init_function(&fcx, false, ty::mk_u64());
// we know the return type of llfdecl is an int here, so
let final = fcx.new_temp_block("final");
let tydesc_ty = ty::get_tydesc_ty(bcx.tcx()).unwrap();
let tydesc_ty = type_of(bcx.ccx(), tydesc_ty);
- let visitor_methods = ty::trait_methods(bcx.tcx(), visitor_trait_id);
+ let visitor_items = ty::trait_items(bcx.tcx(), visitor_trait_id);
let mut r = Reflector {
visitor_val: visitor_val,
- visitor_methods: visitor_methods.as_slice(),
+ visitor_items: visitor_items.as_slice(),
final_bcx: final,
tydesc_ty: tydesc_ty,
bcx: bcx
let name = llvm_type_name(cx, an_enum, did, tps);
adt::incomplete_type_of(cx, &*repr, name.as_slice())
}
- ty::ty_unboxed_closure(did) => {
+ ty::ty_unboxed_closure(did, _) => {
// Only create the named struct, but don't fill it in. We
// fill it in *after* placing it into the type cache.
let repr = adt::represent_type(cx, t);
use middle::const_eval;
use middle::def;
use middle::dependency_format;
+use middle::freevars::CaptureModeMap;
+use middle::freevars;
use middle::lang_items::{FnMutTraitLangItem, OpaqueStructLangItem};
use middle::lang_items::{TyDescStructLangItem, TyVisitorTraitLangItem};
-use middle::freevars;
use middle::resolve;
use middle::resolve_lifetime;
-use middle::subst;
-use middle::subst::{Subst, Substs, VecPerParamSpace};
use middle::stability;
+use middle::subst::{Subst, Substs, VecPerParamSpace};
+use middle::subst;
use middle::ty;
use middle::typeck;
use middle::typeck::MethodCall;
}
#[deriving(Clone)]
-pub enum MethodContainer {
+pub enum ImplOrTraitItemContainer {
TraitContainer(ast::DefId),
ImplContainer(ast::DefId),
}
+impl ImplOrTraitItemContainer {
+ pub fn id(&self) -> ast::DefId {
+ match *self {
+ TraitContainer(id) => id,
+ ImplContainer(id) => id,
+ }
+ }
+}
+
+#[deriving(Clone)]
+pub enum ImplOrTraitItem {
+ MethodTraitItem(Rc<Method>),
+}
+
+impl ImplOrTraitItem {
+ fn id(&self) -> ImplOrTraitItemId {
+ match *self {
+ MethodTraitItem(ref method) => MethodTraitItemId(method.def_id),
+ }
+ }
+
+ pub fn def_id(&self) -> ast::DefId {
+ match *self {
+ MethodTraitItem(ref method) => method.def_id,
+ }
+ }
+
+ pub fn ident(&self) -> ast::Ident {
+ match *self {
+ MethodTraitItem(ref method) => method.ident,
+ }
+ }
+
+ pub fn container(&self) -> ImplOrTraitItemContainer {
+ match *self {
+ MethodTraitItem(ref method) => method.container,
+ }
+ }
+}
+
+#[deriving(Clone)]
+pub enum ImplOrTraitItemId {
+ MethodTraitItemId(ast::DefId),
+}
+
+impl ImplOrTraitItemId {
+ pub fn def_id(&self) -> ast::DefId {
+ match *self {
+ MethodTraitItemId(def_id) => def_id,
+ }
+ }
+}
+
#[deriving(Clone)]
pub struct Method {
pub ident: ast::Ident,
pub explicit_self: ExplicitSelfCategory,
pub vis: ast::Visibility,
pub def_id: ast::DefId,
- pub container: MethodContainer,
+ pub container: ImplOrTraitItemContainer,
// If this method is provided, we need to know where it came from
pub provided_source: Option<ast::DefId>
explicit_self: ExplicitSelfCategory,
vis: ast::Visibility,
def_id: ast::DefId,
- container: MethodContainer,
+ container: ImplOrTraitItemContainer,
provided_source: Option<ast::DefId>)
-> Method {
Method {
/// other items.
pub item_substs: RefCell<NodeMap<ItemSubsts>>,
- /// Maps from a method to the method "descriptor"
- pub methods: RefCell<DefIdMap<Rc<Method>>>,
+ /// Maps from a trait item to the trait item "descriptor"
+ pub impl_or_trait_items: RefCell<DefIdMap<ImplOrTraitItem>>,
- /// Maps from a trait def-id to a list of the def-ids of its methods
- pub trait_method_def_ids: RefCell<DefIdMap<Rc<Vec<DefId>>>>,
+ /// Maps from a trait def-id to a list of the def-ids of its trait items
+ pub trait_item_def_ids: RefCell<DefIdMap<Rc<Vec<ImplOrTraitItemId>>>>,
- /// A cache for the trait_methods() routine
- pub trait_methods_cache: RefCell<DefIdMap<Rc<Vec<Rc<Method>>>>>,
+ /// A cache for the trait_items() routine
+ pub trait_items_cache: RefCell<DefIdMap<Rc<Vec<ImplOrTraitItem>>>>,
pub impl_trait_cache: RefCell<DefIdMap<Option<Rc<ty::TraitRef>>>>,
/// Methods in these implementations don't need to be exported.
pub inherent_impls: RefCell<DefIdMap<Rc<RefCell<Vec<ast::DefId>>>>>,
- /// Maps a DefId of an impl to a list of its methods.
+ /// Maps a DefId of an impl to a list of its items.
/// Note that this contains all of the impls that we know about,
/// including ones in other crates. It's not clear that this is the best
/// way to do it.
- pub impl_methods: RefCell<DefIdMap<Vec<ast::DefId>>>,
+ pub impl_items: RefCell<DefIdMap<Vec<ImplOrTraitItemId>>>,
/// Set of used unsafe nodes (functions or blocks). Unsafe nodes not
/// present in this set can be warned about.
/// Records the type of each unboxed closure. The def ID is the ID of the
/// expression defining the unboxed closure.
- pub unboxed_closure_types: RefCell<DefIdMap<ClosureTy>>,
+ pub unboxed_closures: RefCell<DefIdMap<UnboxedClosure>>,
pub node_lint_levels: RefCell<HashMap<(ast::NodeId, lint::LintId),
lint::LevelSource>>,
/// Maps any item's def-id to its stability index.
pub stability: RefCell<stability::Index>,
+
+ /// Maps closures to their capture clauses.
+ pub capture_modes: RefCell<CaptureModeMap>,
}
pub enum tbox_flag {
ty_closure(Box<ClosureTy>),
ty_trait(Box<TyTrait>),
ty_struct(DefId, Substs),
- ty_unboxed_closure(DefId),
+ ty_unboxed_closure(DefId, Region),
ty_tup(Vec<t>),
ty_param(ParamTy), // type parameter
pub type node_type_table = RefCell<HashMap<uint,t>>;
+/// Records information about each unboxed closure.
+pub struct UnboxedClosure {
+ /// The type of the unboxed closure.
+ pub closure_type: ClosureTy,
+ /// The kind of unboxed closure this is.
+ pub kind: UnboxedClosureKind,
+}
+
+#[deriving(PartialEq, Eq)]
+pub enum UnboxedClosureKind {
+ FnUnboxedClosureKind,
+ FnMutUnboxedClosureKind,
+ FnOnceUnboxedClosureKind,
+}
+
pub fn mk_ctxt(s: Session,
dm: resolve::DefMap,
named_region_map: resolve_lifetime::NamedRegionMap,
map: ast_map::Map,
freevars: freevars::freevar_map,
+ capture_modes: freevars::CaptureModeMap,
region_maps: middle::region::RegionMaps,
lang_items: middle::lang_items::LanguageItems,
stability: stability::Index)
tc_cache: RefCell::new(HashMap::new()),
ast_ty_to_ty_cache: RefCell::new(NodeMap::new()),
enum_var_cache: RefCell::new(DefIdMap::new()),
- methods: RefCell::new(DefIdMap::new()),
- trait_method_def_ids: RefCell::new(DefIdMap::new()),
- trait_methods_cache: RefCell::new(DefIdMap::new()),
+ impl_or_trait_items: RefCell::new(DefIdMap::new()),
+ trait_item_def_ids: RefCell::new(DefIdMap::new()),
+ trait_items_cache: RefCell::new(DefIdMap::new()),
impl_trait_cache: RefCell::new(DefIdMap::new()),
ty_param_defs: RefCell::new(NodeMap::new()),
adjustments: RefCell::new(NodeMap::new()),
destructors: RefCell::new(DefIdSet::new()),
trait_impls: RefCell::new(DefIdMap::new()),
inherent_impls: RefCell::new(DefIdMap::new()),
- impl_methods: RefCell::new(DefIdMap::new()),
+ impl_items: RefCell::new(DefIdMap::new()),
used_unsafe: RefCell::new(NodeSet::new()),
used_mut_nodes: RefCell::new(NodeSet::new()),
impl_vtables: RefCell::new(DefIdMap::new()),
method_map: RefCell::new(FnvHashMap::new()),
vtable_map: RefCell::new(FnvHashMap::new()),
dependency_formats: RefCell::new(HashMap::new()),
- unboxed_closure_types: RefCell::new(DefIdMap::new()),
+ unboxed_closures: RefCell::new(DefIdMap::new()),
node_lint_levels: RefCell::new(HashMap::new()),
transmute_restrictions: RefCell::new(Vec::new()),
- stability: RefCell::new(stability)
+ stability: RefCell::new(stability),
+ capture_modes: RefCell::new(capture_modes),
}
}
}
match &st {
&ty_nil | &ty_bool | &ty_char | &ty_int(_) | &ty_float(_) | &ty_uint(_) |
- &ty_str | &ty_unboxed_closure(_) => {}
+ &ty_str => {}
// You might think that we could just return ty_err for
// any type containing ty_err as a component, and get
// rid of the has_ty_err flag -- likewise for ty_bot (with
flags |= has_params as uint;
}
}
+ &ty_unboxed_closure(_, ref region) => flags |= rflags(*region),
&ty_infer(_) => flags |= needs_infer as uint,
&ty_enum(_, ref substs) | &ty_struct(_, ref substs) => {
flags |= sflags(substs);
mk_t(cx, ty_struct(struct_id, substs))
}
-pub fn mk_unboxed_closure(cx: &ctxt, closure_id: ast::DefId) -> t {
- mk_t(cx, ty_unboxed_closure(closure_id))
+pub fn mk_unboxed_closure(cx: &ctxt, closure_id: ast::DefId, region: Region)
+ -> t {
+ mk_t(cx, ty_unboxed_closure(closure_id, region))
}
pub fn mk_var(cx: &ctxt, v: TyVid) -> t { mk_infer(cx, TyVar(v)) }
}
match get(ty).sty {
ty_nil | ty_bot | ty_bool | ty_char | ty_int(_) | ty_uint(_) | ty_float(_) |
- ty_str | ty_infer(_) | ty_param(_) | ty_unboxed_closure(_) | ty_err => {
- }
+ ty_str | ty_infer(_) | ty_param(_) | ty_unboxed_closure(..) |
+ ty_err => {}
ty_box(ty) | ty_uniq(ty) => maybe_walk_ty(ty, f),
ty_ptr(ref tm) | ty_rptr(_, ref tm) | ty_vec(ref tm, _) => {
maybe_walk_ty(tm.ty, f);
pub fn type_is_structural(ty: t) -> bool {
match get(ty).sty {
ty_struct(..) | ty_tup(_) | ty_enum(..) | ty_closure(_) |
- ty_vec(_, Some(_)) | ty_unboxed_closure(_) => true,
+ ty_vec(_, Some(_)) | ty_unboxed_closure(..) => true,
_ => type_is_slice(ty) | type_is_trait(ty)
}
}
apply_lang_items(cx, did, res)
}
- ty_unboxed_closure(did) => {
+ ty_unboxed_closure(did, r) => {
+ // FIXME(#14449): `borrowed_contents` below assumes `&mut`
+ // unboxed closure.
let upvars = unboxed_closure_upvars(cx, did);
TypeContents::union(upvars.as_slice(),
- |f| tc_ty(cx, f.ty, cache))
+ |f| tc_ty(cx, f.ty, cache)) |
+ borrowed_contents(r, MutMutable)
}
ty_tup(ref tys) => {
r
}
- ty_unboxed_closure(did) => {
+ ty_unboxed_closure(did, _) => {
let upvars = unboxed_closure_upvars(cx, did);
upvars.iter().any(|f| type_requires(cx, seen, r_ty, f.ty))
}
r
}
- ty_unboxed_closure(did) => {
+ ty_unboxed_closure(did, _) => {
let upvars = unboxed_closure_upvars(cx, did);
find_nonrepresentable(cx,
sp,
pub fn ty_closure_store(fty: t) -> TraitStore {
match get(fty).sty {
ty_closure(ref f) => f.store,
- ty_unboxed_closure(_) => {
+ ty_unboxed_closure(..) => {
// Close enough for the purposes of all the callers of this
// function (which is soon to be deprecated anyhow).
UniqTraitStore
Err(s) => tcx.sess.fatal(s.as_slice()),
}
}
- typeck::MethodParam(typeck::MethodParam{trait_id: trt_id,
- method_num: n_mth, ..}) |
- typeck::MethodObject(typeck::MethodObject{trait_id: trt_id,
- method_num: n_mth, ..}) => {
- ty::trait_method(tcx, trt_id, n_mth).generics.types.clone()
+ typeck::MethodParam(typeck::MethodParam{
+ trait_id: trt_id,
+ method_num: n_mth,
+ ..
+ }) |
+ typeck::MethodObject(typeck::MethodObject{
+ trait_id: trt_id,
+ method_num: n_mth,
+ ..
+ }) => {
+ match ty::trait_item(tcx, trt_id, n_mth) {
+ ty::MethodTraitItem(method) => method.generics.types.clone(),
+ }
}
}
}
.collect::<Vec<String>>()).as_slice());
}
-pub fn method_idx(id: ast::Ident, meths: &[Rc<Method>]) -> Option<uint> {
- meths.iter().position(|m| m.ident == id)
+pub fn impl_or_trait_item_idx(id: ast::Ident, trait_items: &[ImplOrTraitItem])
+ -> Option<uint> {
+ trait_items.iter().position(|m| m.ident() == id)
}
/// Returns a vector containing the indices of all type parameters that appear
ty_struct(id, _) => {
format!("struct {}", item_path_str(cx, id))
}
- ty_unboxed_closure(_) => "closure".to_string(),
+ ty_unboxed_closure(..) => "closure".to_string(),
ty_tup(_) => "tuple".to_string(),
ty_infer(TyVar(_)) => "inferred type".to_string(),
ty_infer(IntVar(_)) => "integral variable".to_string(),
match item.node {
ItemTrait(_, _, _, ref ms) => {
let (_, p) = ast_util::split_trait_methods(ms.as_slice());
- p.iter().map(|m| method(cx, ast_util::local_def(m.id))).collect()
+ p.iter()
+ .map(|m| {
+ match impl_or_trait_item(
+ cx,
+ ast_util::local_def(m.id)) {
+ MethodTraitItem(m) => m,
+ }
+ })
+ .collect()
}
_ => {
cx.sess.bug(format!("provided_trait_methods: `{}` is \
/*!
* Helper for looking things up in the various maps
* that are populated during typeck::collect (e.g.,
- * `cx.methods`, `cx.tcache`, etc). All of these share
+ * `cx.impl_or_trait_items`, `cx.tcache`, etc). All of these share
* the pattern that if the id is local, it should have
* been loaded into the map by the `typeck::collect` phase.
* If the def-id is external, then we have to go consult
v
}
-pub fn trait_method(cx: &ctxt, trait_did: ast::DefId, idx: uint) -> Rc<Method> {
- let method_def_id = *ty::trait_method_def_ids(cx, trait_did).get(idx);
- ty::method(cx, method_def_id)
+pub fn trait_item(cx: &ctxt, trait_did: ast::DefId, idx: uint)
+ -> ImplOrTraitItem {
+ let method_def_id = ty::trait_item_def_ids(cx, trait_did).get(idx)
+ .def_id();
+ impl_or_trait_item(cx, method_def_id)
}
-
-pub fn trait_methods(cx: &ctxt, trait_did: ast::DefId) -> Rc<Vec<Rc<Method>>> {
- let mut trait_methods = cx.trait_methods_cache.borrow_mut();
- match trait_methods.find_copy(&trait_did) {
- Some(methods) => methods,
+pub fn trait_items(cx: &ctxt, trait_did: ast::DefId)
+ -> Rc<Vec<ImplOrTraitItem>> {
+ let mut trait_items = cx.trait_items_cache.borrow_mut();
+ match trait_items.find_copy(&trait_did) {
+ Some(trait_items) => trait_items,
None => {
- let def_ids = ty::trait_method_def_ids(cx, trait_did);
- let methods: Rc<Vec<Rc<Method>>> = Rc::new(def_ids.iter().map(|d| {
- ty::method(cx, *d)
- }).collect());
- trait_methods.insert(trait_did, methods.clone());
- methods
+ let def_ids = ty::trait_item_def_ids(cx, trait_did);
+ let items: Rc<Vec<ImplOrTraitItem>> =
+ Rc::new(def_ids.iter()
+ .map(|d| impl_or_trait_item(cx, d.def_id()))
+ .collect());
+ trait_items.insert(trait_did, items.clone());
+ items
}
}
}
-pub fn method(cx: &ctxt, id: ast::DefId) -> Rc<Method> {
- lookup_locally_or_in_crate_store("methods", id,
- &mut *cx.methods.borrow_mut(), || {
- Rc::new(csearch::get_method(cx, id))
+pub fn impl_or_trait_item(cx: &ctxt, id: ast::DefId) -> ImplOrTraitItem {
+ lookup_locally_or_in_crate_store("impl_or_trait_items",
+ id,
+ &mut *cx.impl_or_trait_items
+ .borrow_mut(),
+ || {
+ csearch::get_impl_or_trait_item(cx, id)
})
}
-pub fn trait_method_def_ids(cx: &ctxt, id: ast::DefId) -> Rc<Vec<DefId>> {
- lookup_locally_or_in_crate_store("trait_method_def_ids",
+pub fn trait_item_def_ids(cx: &ctxt, id: ast::DefId)
+ -> Rc<Vec<ImplOrTraitItemId>> {
+ lookup_locally_or_in_crate_store("trait_item_def_ids",
id,
- &mut *cx.trait_method_def_ids.borrow_mut(),
+ &mut *cx.trait_item_def_ids.borrow_mut(),
|| {
- Rc::new(csearch::get_trait_method_def_ids(&cx.sess.cstore, id))
+ Rc::new(csearch::get_trait_item_def_ids(&cx.sess.cstore, id))
})
}
ty_trait(box TyTrait { def_id: id, .. }) |
ty_struct(id, _) |
ty_enum(id, _) |
- ty_unboxed_closure(id) => Some(id),
+ ty_unboxed_closure(id, _) => Some(id),
_ => None
}
}
csearch::each_implementation_for_type(&tcx.sess.cstore, type_id,
|impl_def_id| {
- let methods = csearch::get_impl_methods(&tcx.sess.cstore, impl_def_id);
+ let impl_items = csearch::get_impl_items(&tcx.sess.cstore,
+ impl_def_id);
// Record the trait->implementation mappings, if applicable.
let associated_traits = csearch::get_impl_trait(tcx, impl_def_id);
// For any methods that use a default implementation, add them to
// the map. This is a bit unfortunate.
- for &method_def_id in methods.iter() {
- for &source in ty::method(tcx, method_def_id).provided_source.iter() {
- tcx.provided_method_sources.borrow_mut().insert(method_def_id, source);
+ for impl_item_def_id in impl_items.iter() {
+ let method_def_id = impl_item_def_id.def_id();
+ match impl_or_trait_item(tcx, method_def_id) {
+ MethodTraitItem(method) => {
+ for &source in method.provided_source.iter() {
+ tcx.provided_method_sources
+ .borrow_mut()
+ .insert(method_def_id, source);
+ }
+ }
}
}
// Store the implementation info.
- tcx.impl_methods.borrow_mut().insert(impl_def_id, methods);
+ tcx.impl_items.borrow_mut().insert(impl_def_id, impl_items);
// If this is an inherent implementation, record it.
if associated_traits.is_none() {
csearch::each_implementation_for_trait(&tcx.sess.cstore, trait_id,
|implementation_def_id| {
- let methods = csearch::get_impl_methods(&tcx.sess.cstore, implementation_def_id);
+ let impl_items = csearch::get_impl_items(&tcx.sess.cstore, implementation_def_id);
// Record the trait->implementation mapping.
record_trait_implementation(tcx, trait_id, implementation_def_id);
// For any methods that use a default implementation, add them to
// the map. This is a bit unfortunate.
- for &method_def_id in methods.iter() {
- for &source in ty::method(tcx, method_def_id).provided_source.iter() {
- tcx.provided_method_sources.borrow_mut().insert(method_def_id, source);
+ for impl_item_def_id in impl_items.iter() {
+ let method_def_id = impl_item_def_id.def_id();
+ match impl_or_trait_item(tcx, method_def_id) {
+ MethodTraitItem(method) => {
+ for &source in method.provided_source.iter() {
+ tcx.provided_method_sources
+ .borrow_mut()
+ .insert(method_def_id, source);
+ }
+ }
}
}
// Store the implementation info.
- tcx.impl_methods.borrow_mut().insert(implementation_def_id, methods);
+ tcx.impl_items.borrow_mut().insert(implementation_def_id, impl_items);
});
tcx.populated_external_traits.borrow_mut().insert(trait_id);
pub fn impl_of_method(tcx: &ctxt, def_id: ast::DefId)
-> Option<ast::DefId> {
if def_id.krate != LOCAL_CRATE {
- return match csearch::get_method(tcx, def_id).container {
+ return match csearch::get_impl_or_trait_item(tcx,
+ def_id).container() {
TraitContainer(_) => None,
ImplContainer(def_id) => Some(def_id),
};
}
- match tcx.methods.borrow().find_copy(&def_id) {
- Some(method) => {
- match method.container {
+ match tcx.impl_or_trait_items.borrow().find_copy(&def_id) {
+ Some(trait_item) => {
+ match trait_item.container() {
TraitContainer(_) => None,
ImplContainer(def_id) => Some(def_id),
}
}
}
-/// If the given def ID describes a method belonging to a trait (either a
+/// If the given def ID describes an item belonging to a trait (either a
/// default method or an implementation of a trait method), return the ID of
/// the trait that the method belongs to. Otherwise, return `None`.
-pub fn trait_of_method(tcx: &ctxt, def_id: ast::DefId)
- -> Option<ast::DefId> {
+pub fn trait_of_item(tcx: &ctxt, def_id: ast::DefId) -> Option<ast::DefId> {
if def_id.krate != LOCAL_CRATE {
- return csearch::get_trait_of_method(&tcx.sess.cstore, def_id, tcx);
+ return csearch::get_trait_of_item(&tcx.sess.cstore, def_id, tcx);
}
- match tcx.methods.borrow().find_copy(&def_id) {
- Some(method) => {
- match method.container {
+ match tcx.impl_or_trait_items.borrow().find_copy(&def_id) {
+ Some(impl_or_trait_item) => {
+ match impl_or_trait_item.container() {
TraitContainer(def_id) => Some(def_id),
ImplContainer(def_id) => trait_id_of_impl(tcx, def_id),
}
}
}
-/// If the given def ID describes a method belonging to a trait, (either a
+/// If the given def ID describes an item belonging to a trait, (either a
/// default method or an implementation of a trait method), return the ID of
/// the method inside trait definition (this means that if the given def ID
/// is already that of the original trait method, then the return value is
/// the same).
/// Otherwise, return `None`.
-pub fn trait_method_of_method(tcx: &ctxt,
- def_id: ast::DefId) -> Option<ast::DefId> {
- let method = match tcx.methods.borrow().find(&def_id) {
+pub fn trait_item_of_item(tcx: &ctxt, def_id: ast::DefId)
+ -> Option<ImplOrTraitItemId> {
+ let impl_item = match tcx.impl_or_trait_items.borrow().find(&def_id) {
Some(m) => m.clone(),
None => return None,
};
- let name = method.ident.name;
- match trait_of_method(tcx, def_id) {
+ let name = match impl_item {
+ MethodTraitItem(method) => method.ident.name,
+ };
+ match trait_of_item(tcx, def_id) {
Some(trait_did) => {
- let trait_methods = ty::trait_methods(tcx, trait_did);
- trait_methods.iter()
- .position(|m| m.ident.name == name)
- .map(|idx| ty::trait_method(tcx, trait_did, idx).def_id)
+ let trait_items = ty::trait_items(tcx, trait_did);
+ trait_items.iter()
+ .position(|m| m.ident().name == name)
+ .map(|idx| ty::trait_item(tcx, trait_did, idx).id())
}
None => None
}
}
ty_infer(_) => unreachable!(),
ty_err => byte!(23),
- ty_unboxed_closure(d) => {
+ ty_unboxed_closure(d, r) => {
byte!(24);
did(&mut state, d);
+ region(&mut state, r);
}
}
});
fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow {
self.upvar_borrow_map.borrow().get_copy(&upvar_id)
}
+
+ fn capture_mode(&self, closure_expr_id: ast::NodeId)
+ -> freevars::CaptureMode {
+ self.capture_modes.borrow().get_copy(&closure_expr_id)
+ }
+
+ fn unboxed_closures<'a>(&'a self)
+ -> &'a RefCell<DefIdMap<UnboxedClosure>> {
+ &self.unboxed_closures
+ }
}
/// The category of explicit self.
UniqTraitStore => {}
}
}
+ ty_unboxed_closure(_, ref region) => accumulator.push(*region),
ty_nil |
ty_bot |
ty_bool |
ty_tup(_) |
ty_param(_) |
ty_infer(_) |
- ty_unboxed_closure(_) |
ty_err => {}
}
})
ty::ty_struct(did, ref substs) => {
ty::ty_struct(did, substs.fold_with(this))
}
- ty::ty_unboxed_closure(did) => {
- ty::ty_unboxed_closure(did)
+ ty::ty_unboxed_closure(did, ref region) => {
+ ty::ty_unboxed_closure(did, region.fold_with(this))
}
ty::ty_nil | ty::ty_bot | ty::ty_bool | ty::ty_char | ty::ty_str |
ty::ty_int(_) | ty::ty_uint(_) | ty::ty_float(_) |
use middle::const_eval;
use middle::def;
-use middle::lang_items::FnMutTraitLangItem;
+use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem};
+use middle::lang_items::{FnOnceTraitLangItem};
use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs};
use middle::subst::{VecPerParamSpace};
use middle::ty;
pub fn trait_ref_for_unboxed_function<AC:AstConv,
RS:RegionScope>(
- this: &AC,
- rscope: &RS,
- unboxed_function: &ast::UnboxedFnTy,
- self_ty: Option<ty::t>)
- -> ty::TraitRef
-{
- let fn_mut_trait_did = this.tcx()
- .lang_items
- .require(FnMutTraitLangItem)
- .unwrap();
+ this: &AC,
+ rscope: &RS,
+ unboxed_function: &ast::UnboxedFnTy,
+ self_ty: Option<ty::t>)
+ -> ty::TraitRef {
+ let lang_item = match unboxed_function.kind {
+ ast::FnUnboxedClosureKind => FnTraitLangItem,
+ ast::FnMutUnboxedClosureKind => FnMutTraitLangItem,
+ ast::FnOnceUnboxedClosureKind => FnOnceTraitLangItem,
+ };
+ let trait_did = this.tcx().lang_items.require(lang_item).unwrap();
let input_types =
unboxed_function.decl
.inputs
}
ty::TraitRef {
- def_id: fn_mut_trait_did,
+ def_id: trait_did,
substs: substs,
}
}
None);
ty::mk_closure(tcx, fn_decl)
}
- ast::TyUnboxedFn(_) => {
+ ast::TyUnboxedFn(..) => {
tcx.sess.span_err(ast_ty.span,
"cannot use unboxed functions here");
ty::mk_err()
// methods from them.
let mut method_count = 0;
ty::each_bound_trait_and_supertraits(tcx, &[subtrait], |bound_ref| {
- if bound_ref.def_id == trait_ref.def_id { false }
- else {
- method_count += ty::trait_methods(tcx, bound_ref.def_id).len();
+ if bound_ref.def_id == trait_ref.def_id {
+ false
+ } else {
+ let trait_items = ty::trait_items(tcx, bound_ref.def_id);
+ for trait_item in trait_items.iter() {
+ match *trait_item {
+ ty::MethodTraitItem(_) => method_count += 1,
+ }
+ }
true
}
});
},
ty_enum(did, _) |
ty_struct(did, _) |
- ty_unboxed_closure(did) => {
+ ty_unboxed_closure(did, _) => {
if self.check_traits == CheckTraitsAndInherentMethods {
self.push_inherent_impl_candidates_for_type(did);
}
ty_param(p) => {
self.push_inherent_candidates_from_param(self_ty, restrict_to, p);
}
- ty_unboxed_closure(closure_did) => {
+ ty_unboxed_closure(closure_did, _) => {
self.push_unboxed_closure_call_candidates_if_applicable(
closure_did);
}
ty::populate_implementations_for_trait_if_necessary(self.tcx(), trait_did);
// Look for explicit implementations.
- let impl_methods = self.tcx().impl_methods.borrow();
+ let impl_items = self.tcx().impl_items.borrow();
for impl_infos in self.tcx().trait_impls.borrow().find(&trait_did).iter() {
for impl_did in impl_infos.borrow().iter() {
- let methods = impl_methods.get(impl_did);
- self.push_candidates_from_impl(*impl_did, methods.as_slice(), true);
+ let items = impl_items.get(impl_did);
+ self.push_candidates_from_impl(*impl_did,
+ items.as_slice(),
+ true);
}
}
}
trait_did: DefId,
closure_did: DefId,
closure_function_type: &ClosureTy) {
- let method =
- ty::trait_methods(self.tcx(), trait_did).get(0).clone();
+ let trait_item = ty::trait_items(self.tcx(), trait_did).get(0)
+ .clone();
+ let method = match trait_item {
+ ty::MethodTraitItem(method) => method,
+ };
let vcx = self.fcx.vtable_context();
let region_params =
let arguments_type = *closure_function_type.sig.inputs.get(0);
let return_type = closure_function_type.sig.output;
+ let closure_region =
+ vcx.infcx.next_region_var(MiscVariable(self.span));
let unboxed_closure_type = ty::mk_unboxed_closure(self.tcx(),
- closure_did);
+ closure_did,
+ closure_region);
self.extension_candidates.push(Candidate {
rcvr_match_condition:
RcvrMatchesIfSubtype(unboxed_closure_type),
fn push_unboxed_closure_call_candidates_if_applicable(
&mut self,
closure_did: DefId) {
- // FIXME(pcwalton): Try `Fn` and `FnOnce` too.
- let trait_did = match self.tcx().lang_items.fn_mut_trait() {
- Some(trait_did) => trait_did,
- None => return,
- };
-
- match self.tcx()
- .unboxed_closure_types
- .borrow()
- .find(&closure_did) {
- None => {} // Fall through to try inherited.
- Some(closure_function_type) => {
- self.push_unboxed_closure_call_candidate_if_applicable(
- trait_did,
- closure_did,
- closure_function_type);
- return
+ let trait_dids = [
+ self.tcx().lang_items.fn_trait(),
+ self.tcx().lang_items.fn_mut_trait(),
+ self.tcx().lang_items.fn_once_trait()
+ ];
+ for optional_trait_did in trait_dids.iter() {
+ let trait_did = match *optional_trait_did {
+ Some(trait_did) => trait_did,
+ None => continue,
+ };
+
+ match self.tcx().unboxed_closures.borrow().find(&closure_did) {
+ None => {} // Fall through to try inherited.
+ Some(closure) => {
+ self.push_unboxed_closure_call_candidate_if_applicable(
+ trait_did,
+ closure_did,
+ &closure.closure_type);
+ return
+ }
}
- }
- match self.fcx
- .inh
- .unboxed_closure_types
- .borrow()
- .find(&closure_did) {
- Some(closure_function_type) => {
- self.push_unboxed_closure_call_candidate_if_applicable(
- trait_did,
- closure_did,
- closure_function_type);
- return
+ match self.fcx.inh.unboxed_closures.borrow().find(&closure_did) {
+ Some(closure) => {
+ self.push_unboxed_closure_call_candidate_if_applicable(
+ trait_did,
+ closure_did,
+ &closure.closure_type);
+ return
+ }
+ None => {}
}
- None => {}
}
self.tcx().sess.bug("didn't find unboxed closure type in tcx map or \
let this_bound_idx = next_bound_idx;
next_bound_idx += 1;
- let trait_methods = ty::trait_methods(tcx, bound_trait_ref.def_id);
- match trait_methods.iter().position(|m| {
- m.explicit_self != ty::StaticExplicitSelfCategory &&
- m.ident.name == self.m_name }) {
+ let trait_items = ty::trait_items(tcx, bound_trait_ref.def_id);
+ match trait_items.iter().position(|ti| {
+ match *ti {
+ ty::MethodTraitItem(ref m) => {
+ m.explicit_self != ty::StaticExplicitSelfCategory &&
+ m.ident.name == self.m_name
+ }
+ }
+ }) {
Some(pos) => {
- let method = trait_methods.get(pos).clone();
-
- match mk_cand(bound_trait_ref, method, pos, this_bound_idx) {
+ let method = match *trait_items.get(pos) {
+ ty::MethodTraitItem(ref method) => (*method).clone(),
+ };
+
+ match mk_cand(bound_trait_ref,
+ method,
+ pos,
+ this_bound_idx) {
Some(cand) => {
debug!("pushing inherent candidate for param: {}",
cand.repr(self.tcx()));
// metadata if necessary.
ty::populate_implementations_for_type_if_necessary(self.tcx(), did);
- let impl_methods = self.tcx().impl_methods.borrow();
+ let impl_items = self.tcx().impl_items.borrow();
for impl_infos in self.tcx().inherent_impls.borrow().find(&did).iter() {
for impl_did in impl_infos.borrow().iter() {
- let methods = impl_methods.get(impl_did);
- self.push_candidates_from_impl(*impl_did, methods.as_slice(), false);
+ let items = impl_items.get(impl_did);
+ self.push_candidates_from_impl(*impl_did,
+ items.as_slice(),
+ false);
}
}
}
fn push_candidates_from_impl(&mut self,
impl_did: DefId,
- impl_methods: &[DefId],
+ impl_items: &[ImplOrTraitItemId],
is_extension: bool) {
let did = if self.report_statics == ReportStaticMethods {
// we only want to report each base trait once
debug!("push_candidates_from_impl: {} {}",
token::get_name(self.m_name),
- impl_methods.iter().map(|&did| ty::method(self.tcx(), did).ident)
- .collect::<Vec<ast::Ident>>()
- .repr(self.tcx()));
-
- let method = match impl_methods.iter().map(|&did| ty::method(self.tcx(), did))
- .find(|m| m.ident.name == self.m_name) {
- Some(method) => method,
+ impl_items.iter()
+ .map(|&did| {
+ ty::impl_or_trait_item(self.tcx(),
+ did.def_id()).ident()
+ })
+ .collect::<Vec<ast::Ident>>()
+ .repr(self.tcx()));
+
+ let method = match impl_items.iter()
+ .map(|&did| {
+ ty::impl_or_trait_item(self.tcx(),
+ did.def_id())
+ })
+ .find(|m| {
+ m.ident().name == self.m_name
+ }) {
+ Some(ty::MethodTraitItem(method)) => method,
None => { return; } // No method with the right name.
};
let did = if self.report_statics == ReportStaticMethods {
// If we're reporting statics, we want to report the trait
// definition if possible, rather than an impl
- match ty::trait_method_of_method(self.tcx(), impl_did) {
- None => {debug!("(report candidate) No trait method found"); impl_did},
- Some(trait_did) => {debug!("(report candidate) Found trait ref"); trait_did}
+ match ty::trait_item_of_item(self.tcx(), impl_did) {
+ None => {
+ debug!("(report candidate) No trait method \
+ found");
+ impl_did
+ }
+ Some(MethodTraitItemId(trait_did)) => {
+ debug!("(report candidate) Found trait ref");
+ trait_did
+ }
}
} else {
// If it is an instantiated default method, use the original
use std::rc::Rc;
use std::gc::Gc;
use syntax::abi;
-use syntax::ast::{Provided, Required};
+use syntax::ast::{ProvidedMethod, RequiredMethod};
use syntax::ast;
use syntax::ast_map;
use syntax::ast_util::{local_def, PostExpansionMethod};
method_map: MethodMap,
vtable_map: vtable_map,
upvar_borrow_map: RefCell<ty::UpvarBorrowMap>,
- unboxed_closure_types: RefCell<DefIdMap<ty::ClosureTy>>,
+ unboxed_closures: RefCell<DefIdMap<ty::UnboxedClosure>>,
}
/// When type-checking an expression, we propagate downward
method_map: RefCell::new(FnvHashMap::new()),
vtable_map: RefCell::new(FnvHashMap::new()),
upvar_borrow_map: RefCell::new(HashMap::new()),
- unboxed_closure_types: RefCell::new(DefIdMap::new()),
+ unboxed_closures: RefCell::new(DefIdMap::new()),
}
}
}
check_bare_fn(ccx, &**decl, &**body, it.id, fn_pty.ty, param_env);
}
- ast::ItemImpl(_, ref opt_trait_ref, _, ref ms) => {
+ ast::ItemImpl(_, ref opt_trait_ref, _, ref impl_items) => {
debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
- for m in ms.iter() {
- check_method_body(ccx, &impl_pty.generics, &**m);
+ for impl_item in impl_items.iter() {
+ match *impl_item {
+ ast::MethodImplItem(m) => {
+ check_method_body(ccx, &impl_pty.generics, &*m);
+ }
+ }
}
match *opt_trait_ref {
Some(ref ast_trait_ref) => {
let impl_trait_ref =
ty::node_id_to_trait_ref(ccx.tcx, ast_trait_ref.ref_id);
- check_impl_methods_against_trait(ccx,
- it.span,
- ast_trait_ref,
- &*impl_trait_ref,
- ms.as_slice());
+ check_impl_items_against_trait(ccx,
+ it.span,
+ ast_trait_ref,
+ &*impl_trait_ref,
+ impl_items.as_slice());
vtable::resolve_impl(ccx.tcx, it, &impl_pty.generics, &*impl_trait_ref);
}
None => { }
let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
for trait_method in (*trait_methods).iter() {
match *trait_method {
- Required(..) => {
+ RequiredMethod(..) => {
// Nothing to do, since required methods don't have
// bodies to check.
}
- Provided(m) => {
+ ProvidedMethod(m) => {
check_method_body(ccx, &trait_def.generics, &*m);
}
}
item_generics.repr(ccx.tcx),
method.id);
let method_def_id = local_def(method.id);
- let method_ty = ty::method(ccx.tcx, method_def_id);
+ let method_ty = match ty::impl_or_trait_item(ccx.tcx, method_def_id) {
+ ty::MethodTraitItem(ref method_ty) => (*method_ty).clone(),
+ };
let method_generics = &method_ty.generics;
let param_env = ty::construct_parameter_environment(ccx.tcx,
param_env);
}
-fn check_impl_methods_against_trait(ccx: &CrateCtxt,
- impl_span: Span,
- ast_trait_ref: &ast::TraitRef,
- impl_trait_ref: &ty::TraitRef,
- impl_methods: &[Gc<ast::Method>]) {
+fn check_impl_items_against_trait(ccx: &CrateCtxt,
+ impl_span: Span,
+ ast_trait_ref: &ast::TraitRef,
+ impl_trait_ref: &ty::TraitRef,
+ impl_items: &[ast::ImplItem]) {
// Locate trait methods
let tcx = ccx.tcx;
- let trait_methods = ty::trait_methods(tcx, impl_trait_ref.def_id);
+ let trait_items = ty::trait_items(tcx, impl_trait_ref.def_id);
// Check existing impl methods to see if they are both present in trait
// and compatible with trait signature
- for impl_method in impl_methods.iter() {
- let impl_method_def_id = local_def(impl_method.id);
- let impl_method_ty = ty::method(ccx.tcx, impl_method_def_id);
-
- // If this is an impl of a trait method, find the corresponding
- // method definition in the trait.
- let opt_trait_method_ty =
- trait_methods.iter().
- find(|tm| tm.ident.name == impl_method_ty.ident.name);
- match opt_trait_method_ty {
- Some(trait_method_ty) => {
- compare_impl_method(ccx.tcx,
- &*impl_method_ty,
- impl_method.span,
- impl_method.pe_body().id,
- &**trait_method_ty,
- &impl_trait_ref.substs);
- }
- None => {
- // This is span_bug as it should have already been caught in resolve.
- tcx.sess.span_bug(
- impl_method.span,
- format!(
- "method `{}` is not a member of trait `{}`",
- token::get_ident(impl_method_ty.ident),
- pprust::path_to_string(&ast_trait_ref.path)).as_slice());
+ for impl_item in impl_items.iter() {
+ match *impl_item {
+ ast::MethodImplItem(impl_method) => {
+ let impl_method_def_id = local_def(impl_method.id);
+ let impl_item_ty = ty::impl_or_trait_item(ccx.tcx,
+ impl_method_def_id);
+
+ // If this is an impl of a trait method, find the
+ // corresponding method definition in the trait.
+ let opt_trait_method_ty =
+ trait_items.iter()
+ .find(|ti| {
+ ti.ident().name == impl_item_ty.ident()
+ .name
+ });
+ match opt_trait_method_ty {
+ Some(trait_method_ty) => {
+ match (trait_method_ty, &impl_item_ty) {
+ (&ty::MethodTraitItem(ref trait_method_ty),
+ &ty::MethodTraitItem(ref impl_method_ty)) => {
+ compare_impl_method(ccx.tcx,
+ &**impl_method_ty,
+ impl_method.span,
+ impl_method.pe_body().id,
+ &**trait_method_ty,
+ &impl_trait_ref.substs);
+ }
+ }
+ }
+ None => {
+ // This is span_bug as it should have already been
+ // caught in resolve.
+ tcx.sess.span_bug(
+ impl_method.span,
+ format!(
+ "method `{}` is not a member of trait `{}`",
+ token::get_ident(impl_item_ty.ident()),
+ pprust::path_to_string(
+ &ast_trait_ref.path)).as_slice());
+ }
+ }
}
}
}
let provided_methods = ty::provided_trait_methods(tcx,
impl_trait_ref.def_id);
let mut missing_methods = Vec::new();
- for trait_method in trait_methods.iter() {
- let is_implemented =
- impl_methods.iter().any(
- |m| m.pe_ident().name == trait_method.ident.name);
- let is_provided =
- provided_methods.iter().any(
- |m| m.ident.name == trait_method.ident.name);
- if !is_implemented && !is_provided {
- missing_methods.push(
- format!("`{}`", token::get_ident(trait_method.ident)));
+ for trait_item in trait_items.iter() {
+ match *trait_item {
+ ty::MethodTraitItem(ref trait_method) => {
+ let is_implemented =
+ impl_items.iter().any(|ii| {
+ match *ii {
+ ast::MethodImplItem(m) => {
+ m.pe_ident().name == trait_method.ident.name
+ }
+ }
+ });
+ let is_provided =
+ provided_methods.iter().any(
+ |m| m.ident.name == trait_method.ident.name);
+ if !is_implemented && !is_provided {
+ missing_methods.push(
+ format!("`{}`",
+ token::get_ident(trait_method.ident)));
+ }
+ }
}
}
}
/**
- * Checks that a method from an impl/class conforms to the signature of
+ * Checks that a method from an impl conforms to the signature of
* the same method as declared in the trait.
*
* # Parameters
VtableContext {
infcx: self.infcx(),
param_env: &self.inh.param_env,
- unboxed_closure_types: &self.inh.unboxed_closure_types,
+ unboxed_closures: &self.inh.unboxed_closures,
}
}
}
fn check_unboxed_closure(fcx: &FnCtxt,
expr: &ast::Expr,
+ kind: ast::UnboxedClosureKind,
decl: &ast::FnDecl,
body: ast::P<ast::Block>) {
// The `RegionTraitStore` is a lie, but we ignore it so it doesn't
abi::RustCall,
None);
+ let region = match fcx.infcx().anon_regions(expr.span, 1) {
+ Err(_) => {
+ fcx.ccx.tcx.sess.span_bug(expr.span,
+ "can't make anon regions here?!")
+ }
+ Ok(regions) => *regions.get(0),
+ };
let closure_type = ty::mk_unboxed_closure(fcx.ccx.tcx,
- local_def(expr.id));
+ local_def(expr.id),
+ region);
fcx.write_ty(expr.id, closure_type);
check_fn(fcx.ccx,
fcx.inh);
// Tuple up the arguments and insert the resulting function type into
- // the `unboxed_closure_types` table.
+ // the `unboxed_closures` table.
fn_ty.sig.inputs = vec![ty::mk_tup(fcx.tcx(), fn_ty.sig.inputs)];
+ let kind = match kind {
+ ast::FnUnboxedClosureKind => ty::FnUnboxedClosureKind,
+ ast::FnMutUnboxedClosureKind => ty::FnMutUnboxedClosureKind,
+ ast::FnOnceUnboxedClosureKind => ty::FnOnceUnboxedClosureKind,
+ };
+
+ let unboxed_closure = ty::UnboxedClosure {
+ closure_type: fn_ty,
+ kind: kind,
+ };
+
fcx.inh
- .unboxed_closure_types
+ .unboxed_closures
.borrow_mut()
- .insert(local_def(expr.id), fn_ty);
+ .insert(local_def(expr.id), unboxed_closure);
}
fn check_expr_fn(fcx: &FnCtxt,
ast::ExprMatch(ref discrim, ref arms) => {
_match::check_match(fcx, expr, &**discrim, arms.as_slice());
}
- ast::ExprFnBlock(ref decl, ref body) => {
+ ast::ExprFnBlock(_, ref decl, ref body) => {
let region = astconv::opt_ast_region_to_region(fcx,
fcx.infcx(),
expr.span,
body.clone(),
expected);
}
- ast::ExprUnboxedFn(ref decl, ref body) => {
+ ast::ExprUnboxedFn(_, kind, ref decl, ref body) => {
check_unboxed_closure(fcx,
expr,
+ kind,
&**decl,
*body);
}
use middle::typeck::infer;
use middle::typeck::MethodCall;
use middle::pat_util;
-use util::nodemap::NodeMap;
+use util::nodemap::{DefIdMap, NodeMap};
use util::ppaux::{ty_to_string, region_to_string, Repr};
use syntax::ast;
fn upvar_borrow(&self, id: ty::UpvarId) -> ty::UpvarBorrow {
self.fcx.inh.upvar_borrow_map.borrow().get_copy(&id)
}
+
+ fn capture_mode(&self, closure_expr_id: ast::NodeId)
+ -> freevars::CaptureMode {
+ self.tcx().capture_modes.borrow().get_copy(&closure_expr_id)
+ }
+
+ fn unboxed_closures<'a>(&'a self)
+ -> &'a RefCell<DefIdMap<ty::UnboxedClosure>> {
+ &self.fcx.inh.unboxed_closures
+ }
}
pub fn regionck_expr(fcx: &FnCtxt, e: &ast::Expr) {
visit::walk_expr(rcx, expr, ());
}
- ast::ExprFnBlock(_, ref body) |
+ ast::ExprFnBlock(_, _, ref body) |
ast::ExprProc(_, ref body) |
- ast::ExprUnboxedFn(_, ref body) => {
+ ast::ExprUnboxedFn(_, _, _, ref body) => {
check_expr_fn_block(rcx, expr, &**body);
}
}
});
}
+ ty::ty_unboxed_closure(_, region) => {
+ freevars::with_freevars(tcx, expr.id, |freevars| {
+ // No free variables means that there is no environment and
+ // hence the closure has static lifetime. Otherwise, the
+ // closure must not outlive the variables it closes over
+ // by-reference.
+ if !freevars.is_empty() {
+ constrain_free_variables(rcx, region, expr, freevars);
+ }
+ })
+ }
_ => ()
}
pub struct VtableContext<'a> {
pub infcx: &'a infer::InferCtxt<'a>,
pub param_env: &'a ty::ParameterEnvironment,
- pub unboxed_closure_types: &'a RefCell<DefIdMap<ty::ClosureTy>>,
+ pub unboxed_closures: &'a RefCell<DefIdMap<ty::UnboxedClosure>>,
}
impl<'a> VtableContext<'a> {
-> Option<vtable_origin> {
let tcx = vcx.tcx();
let closure_def_id = match ty::get(ty).sty {
- ty::ty_unboxed_closure(closure_def_id) => closure_def_id,
+ ty::ty_unboxed_closure(closure_def_id, _) => closure_def_id,
_ => return None,
};
let fn_traits = [
- tcx.lang_items.fn_trait(),
- tcx.lang_items.fn_mut_trait(),
- tcx.lang_items.fn_once_trait()
+ (ty::FnUnboxedClosureKind, tcx.lang_items.fn_trait()),
+ (ty::FnMutUnboxedClosureKind, tcx.lang_items.fn_mut_trait()),
+ (ty::FnOnceUnboxedClosureKind, tcx.lang_items.fn_once_trait()),
];
- for fn_trait in fn_traits.iter() {
- match *fn_trait {
- Some(ref fn_trait) if *fn_trait == trait_ref.def_id => {}
+ for tuple in fn_traits.iter() {
+ let kind = match tuple {
+ &(kind, Some(ref fn_trait)) if *fn_trait == trait_ref.def_id => {
+ kind
+ }
_ => continue,
};
// Check to see whether the argument and return types match.
- let unboxed_closure_types = tcx.unboxed_closure_types.borrow();
- let closure_type = match unboxed_closure_types.find(&closure_def_id) {
- Some(closure_type) => (*closure_type).clone(),
+ let unboxed_closures = tcx.unboxed_closures.borrow();
+ let closure_type = match unboxed_closures.find(&closure_def_id) {
+ Some(closure) => {
+ if closure.kind != kind {
+ continue
+ }
+ closure.closure_type.clone()
+ }
None => {
// Try the inherited unboxed closure type map.
- let unboxed_closure_types = vcx.unboxed_closure_types
- .borrow();
- match unboxed_closure_types.find(&closure_def_id) {
- Some(closure_type) => (*closure_type).clone(),
+ let unboxed_closures = vcx.unboxed_closures.borrow();
+ match unboxed_closures.find(&closure_def_id) {
+ Some(closure) => {
+ if closure.kind != kind {
+ continue
+ }
+ closure.closure_type.clone()
+ }
None => {
tcx.sess.span_bug(span,
"didn't find unboxed closure type \
debug!("impl_trait_ref={}", impl_trait_ref.repr(tcx));
let infcx = &infer::new_infer_ctxt(tcx);
- let unboxed_closure_types = RefCell::new(DefIdMap::new());
+ let unboxed_closures = RefCell::new(DefIdMap::new());
let vcx = VtableContext {
infcx: infcx,
param_env: ¶m_env,
- unboxed_closure_types: &unboxed_closure_types,
+ unboxed_closures: &unboxed_closures,
};
// Resolve the vtables for the trait reference on the impl. This
pub fn trans_resolve_method(tcx: &ty::ctxt, id: ast::NodeId,
substs: &subst::Substs) -> vtable_res {
let generics = ty::lookup_item_type(tcx, ast_util::local_def(id)).generics;
- let unboxed_closure_types = RefCell::new(DefIdMap::new());
+ let unboxed_closures = RefCell::new(DefIdMap::new());
let vcx = VtableContext {
infcx: &infer::new_infer_ctxt(tcx),
param_env: &ty::construct_parameter_environment(tcx, &ty::Generics::empty(), id),
- unboxed_closure_types: &unboxed_closure_types,
+ unboxed_closures: &unboxed_closures,
};
lookup_vtables(&vcx,
let mut wbcx = WritebackCx::new(fcx);
wbcx.visit_expr(e, ());
wbcx.visit_upvar_borrow_map();
- wbcx.visit_unboxed_closure_types();
+ wbcx.visit_unboxed_closures();
}
pub fn resolve_type_vars_in_fn(fcx: &FnCtxt,
}
}
wbcx.visit_upvar_borrow_map();
- wbcx.visit_unboxed_closure_types();
+ wbcx.visit_unboxed_closures();
}
pub fn resolve_impl_res(infcx: &infer::InferCtxt,
MethodCall::expr(e.id));
match e.node {
- ast::ExprFnBlock(ref decl, _) |
+ ast::ExprFnBlock(_, ref decl, _) |
ast::ExprProc(ref decl, _) |
- ast::ExprUnboxedFn(ref decl, _) => {
+ ast::ExprUnboxedFn(_, _, ref decl, _) => {
for input in decl.inputs.iter() {
let _ = self.visit_node_id(ResolvingExpr(e.span),
input.id);
}
}
- fn visit_unboxed_closure_types(&self) {
+ fn visit_unboxed_closures(&self) {
if self.fcx.writeback_errors.get() {
return
}
- for (def_id, closure_ty) in self.fcx
- .inh
- .unboxed_closure_types
- .borrow()
- .iter() {
- let closure_ty = self.resolve(closure_ty,
+ for (def_id, unboxed_closure) in self.fcx
+ .inh
+ .unboxed_closures
+ .borrow()
+ .iter() {
+ let closure_ty = self.resolve(&unboxed_closure.closure_type,
ResolvingUnboxedClosure(*def_id));
+ let unboxed_closure = ty::UnboxedClosure {
+ closure_type: closure_ty,
+ kind: unboxed_closure.kind,
+ };
self.fcx
.tcx()
- .unboxed_closure_types
+ .unboxed_closures
.borrow_mut()
- .insert(*def_id, closure_ty);
+ .insert(*def_id, unboxed_closure);
}
}
use middle::subst;
use middle::subst::{Substs};
use middle::ty::get;
-use middle::ty::{ImplContainer, lookup_item_type};
+use middle::ty::{ImplContainer, ImplOrTraitItemId, MethodTraitItemId};
+use middle::ty::{lookup_item_type};
use middle::ty::{t, ty_bool, ty_char, ty_bot, ty_box, ty_enum, ty_err};
use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int, ty_nil};
use middle::ty::{ty_param, Polytype, ty_ptr};
match get(t).sty {
ty_enum(def_id, _) |
ty_struct(def_id, _) |
- ty_unboxed_closure(def_id) => {
+ ty_unboxed_closure(def_id, _) => {
if def_id.krate == ast::LOCAL_CRATE {
found_nominal = true;
}
match get(base_type).sty {
ty_enum(def_id, _) |
ty_struct(def_id, _) |
- ty_unboxed_closure(def_id) => {
+ ty_unboxed_closure(def_id, _) => {
Some(def_id)
}
ty_rptr(_, ty::mt {ty, ..}) | ty_uniq(ty) => match ty::get(ty).sty {
}
}
- let impl_methods = self.create_impl_from_item(item);
+ let impl_items = self.create_impl_from_item(item);
for associated_trait in associated_traits.iter() {
let trait_ref = ty::node_id_to_trait_ref(
}
}
- tcx.impl_methods.borrow_mut().insert(impl_did, impl_methods);
+ tcx.impl_items.borrow_mut().insert(impl_did, impl_items);
}
// Creates default method IDs and performs type substitutions for an impl
// and trait pair. Then, for each provided method in the trait, inserts a
// `ProvidedMethodInfo` instance into the `provided_method_sources` map.
- fn instantiate_default_methods(&self,
- impl_id: DefId,
- trait_ref: &ty::TraitRef,
- all_methods: &mut Vec<DefId>) {
+ fn instantiate_default_methods(
+ &self,
+ impl_id: DefId,
+ trait_ref: &ty::TraitRef,
+ all_impl_items: &mut Vec<ImplOrTraitItemId>) {
let tcx = self.crate_context.tcx;
debug!("instantiate_default_methods(impl_id={:?}, trait_ref={})",
impl_id, trait_ref.repr(tcx));
Some(trait_method.def_id)));
debug!("new_method_ty={}", new_method_ty.repr(tcx));
- all_methods.push(new_did);
+ all_impl_items.push(MethodTraitItemId(new_did));
// construct the polytype for the method based on the
// method_ty. it will have all the generics from the
debug!("new_polytype={}", new_polytype.repr(tcx));
tcx.tcache.borrow_mut().insert(new_did, new_polytype);
- tcx.methods.borrow_mut().insert(new_did, new_method_ty);
+ tcx.impl_or_trait_items
+ .borrow_mut()
+ .insert(new_did, ty::MethodTraitItem(new_method_ty));
// Pair the new synthesized ID up with the
// ID of the method.
}
}
- // Converts an implementation in the AST to a vector of methods.
- fn create_impl_from_item(&self, item: &Item) -> Vec<DefId> {
+ // Converts an implementation in the AST to a vector of items.
+ fn create_impl_from_item(&self, item: &Item) -> Vec<ImplOrTraitItemId> {
match item.node {
- ItemImpl(_, ref trait_refs, _, ref ast_methods) => {
- let mut methods: Vec<DefId> = ast_methods.iter().map(|ast_method| {
- local_def(ast_method.id)
- }).collect();
+ ItemImpl(_, ref trait_refs, _, ref ast_items) => {
+ let mut items: Vec<ImplOrTraitItemId> =
+ ast_items.iter()
+ .map(|ast_item| {
+ match *ast_item {
+ ast::MethodImplItem(ast_method) => {
+ MethodTraitItemId(
+ local_def(ast_method.id))
+ }
+ }
+ }).collect();
for trait_ref in trait_refs.iter() {
let ty_trait_ref = ty::node_id_to_trait_ref(
self.instantiate_default_methods(local_def(item.id),
&*ty_trait_ref,
- &mut methods);
+ &mut items);
}
- methods
+ items
}
_ => {
self.crate_context.tcx.sess.span_bug(item.span,
impls_seen: &mut HashSet<DefId>,
impl_def_id: DefId) {
let tcx = self.crate_context.tcx;
- let methods = csearch::get_impl_methods(&tcx.sess.cstore, impl_def_id);
+ let impl_items = csearch::get_impl_items(&tcx.sess.cstore,
+ impl_def_id);
// Make sure we don't visit the same implementation multiple times.
if !impls_seen.insert(impl_def_id) {
// Do a sanity check.
assert!(associated_traits.is_some());
- // Record all the trait methods.
+ // Record all the trait items.
for trait_ref in associated_traits.iter() {
self.add_trait_impl(trait_ref.def_id, impl_def_id);
}
// For any methods that use a default implementation, add them to
// the map. This is a bit unfortunate.
- for &method_def_id in methods.iter() {
- for &source in ty::method(tcx, method_def_id).provided_source.iter() {
- tcx.provided_method_sources.borrow_mut().insert(method_def_id, source);
+ for item_def_id in impl_items.iter() {
+ let impl_item = ty::impl_or_trait_item(tcx, item_def_id.def_id());
+ match impl_item {
+ ty::MethodTraitItem(ref method) => {
+ for &source in method.provided_source.iter() {
+ tcx.provided_method_sources
+ .borrow_mut()
+ .insert(item_def_id.def_id(), source);
+ }
+ }
}
}
- tcx.impl_methods.borrow_mut().insert(impl_def_id, methods);
+ tcx.impl_items.borrow_mut().insert(impl_def_id, impl_items);
}
// Adds implementations and traits from external crates to the coherence
Some(id) => id, None => { return }
};
- let impl_methods = tcx.impl_methods.borrow();
+ let impl_items = tcx.impl_items.borrow();
let trait_impls = match tcx.trait_impls.borrow().find_copy(&drop_trait) {
None => return, // No types with (new-style) dtors present.
Some(found_impls) => found_impls
};
for &impl_did in trait_impls.borrow().iter() {
- let methods = impl_methods.get(&impl_did);
- if methods.len() < 1 {
+ let items = impl_items.get(&impl_did);
+ if items.len() < 1 {
// We'll error out later. For now, just don't ICE.
continue;
}
- let method_def_id = *methods.get(0);
+ let method_def_id = *items.get(0);
let self_type = self.get_self_type_for_implementation(impl_did);
match ty::get(self_type.ty).sty {
ty::ty_enum(type_def_id, _) |
ty::ty_struct(type_def_id, _) |
- ty::ty_unboxed_closure(type_def_id) => {
- tcx.destructor_for_type.borrow_mut().insert(type_def_id,
- method_def_id);
- tcx.destructors.borrow_mut().insert(method_def_id);
+ ty::ty_unboxed_closure(type_def_id, _) => {
+ tcx.destructor_for_type
+ .borrow_mut()
+ .insert(type_def_id, method_def_id.def_id());
+ tcx.destructors
+ .borrow_mut()
+ .insert(method_def_id.def_id());
}
_ => {
// Destructors only work on nominal types.
use middle::resolve_lifetime;
use middle::subst;
use middle::subst::{Substs};
-use middle::ty::{ImplContainer, MethodContainer, TraitContainer};
+use middle::ty::{ImplContainer, ImplOrTraitItemContainer, TraitContainer};
use middle::ty::{Polytype};
use middle::ty;
use middle::ty_fold::TypeFolder;
match tcx.map.get(trait_id) {
ast_map::NodeItem(item) => {
match item.node {
- ast::ItemTrait(_, _, _, ref ms) => {
+ ast::ItemTrait(_, _, _, ref trait_items) => {
// For each method, construct a suitable ty::Method and
- // store it into the `tcx.methods` table:
- for m in ms.iter() {
- let ty_method = Rc::new(match m {
- &ast::Required(ref m) => {
- ty_method_of_trait_method(
- ccx,
- trait_id,
- &trait_def.generics,
- &m.id,
- &m.ident,
- &m.explicit_self,
- m.abi,
- &m.generics,
- &m.fn_style,
- &*m.decl)
- }
+ // store it into the `tcx.impl_or_trait_items` table:
+ for trait_item in trait_items.iter() {
+ match *trait_item {
+ ast::RequiredMethod(_) |
+ ast::ProvidedMethod(_) => {
+ let ty_method = Rc::new(match *trait_item {
+ ast::RequiredMethod(ref m) => {
+ ty_method_of_trait_method(
+ ccx,
+ trait_id,
+ &trait_def.generics,
+ &m.id,
+ &m.ident,
+ &m.explicit_self,
+ m.abi,
+ &m.generics,
+ &m.fn_style,
+ &*m.decl)
+ }
+ ast::ProvidedMethod(ref m) => {
+ ty_method_of_trait_method(
+ ccx,
+ trait_id,
+ &trait_def.generics,
+ &m.id,
+ &m.pe_ident(),
+ m.pe_explicit_self(),
+ m.pe_abi(),
+ m.pe_generics(),
+ &m.pe_fn_style(),
+ &*m.pe_fn_decl())
+ }
+ });
- &ast::Provided(ref m) => {
- ty_method_of_trait_method(
- ccx,
- trait_id,
- &trait_def.generics,
- &m.id,
- &m.pe_ident(),
- m.pe_explicit_self(),
- m.pe_abi(),
- m.pe_generics(),
- &m.pe_fn_style(),
- &*m.pe_fn_decl())
- }
- });
+ if ty_method.explicit_self ==
+ ty::StaticExplicitSelfCategory {
+ make_static_method_ty(ccx, &*ty_method);
+ }
- if ty_method.explicit_self ==
- ty::StaticExplicitSelfCategory {
- make_static_method_ty(ccx, &*ty_method);
+ tcx.impl_or_trait_items
+ .borrow_mut()
+ .insert(ty_method.def_id,
+ ty::MethodTraitItem(ty_method));
+ }
}
-
- tcx.methods.borrow_mut().insert(ty_method.def_id,
- ty_method);
}
// Add an entry mapping
- let method_def_ids = Rc::new(ms.iter().map(|m| {
- match m {
- &ast::Required(ref ty_method) => {
- local_def(ty_method.id)
+ let trait_item_def_ids =
+ Rc::new(trait_items.iter()
+ .map(|ti| {
+ match *ti {
+ ast::RequiredMethod(ref ty_method) => {
+ ty::MethodTraitItemId(local_def(
+ ty_method.id))
+ }
+ ast::ProvidedMethod(ref method) => {
+ ty::MethodTraitItemId(local_def(
+ method.id))
+ }
}
- &ast::Provided(ref method) => {
- local_def(method.id)
- }
- }
- }).collect());
+ }).collect());
let trait_def_id = local_def(trait_id);
- tcx.trait_method_def_ids.borrow_mut()
- .insert(trait_def_id, method_def_ids);
+ tcx.trait_item_def_ids.borrow_mut()
+ .insert(trait_def_id, trait_item_def_ids);
}
_ => {} // Ignore things that aren't traits.
}
}
fn convert_methods(ccx: &CrateCtxt,
- container: MethodContainer,
+ container: ImplOrTraitItemContainer,
ms: &[Gc<ast::Method>],
untransformed_rcvr_ty: ty::t,
rcvr_ty_generics: &ty::Generics,
- rcvr_visibility: ast::Visibility)
-{
+ rcvr_visibility: ast::Visibility) {
let tcx = ccx.tcx;
let mut seen_methods = HashSet::new();
for m in ms.iter() {
write_ty_to_tcx(tcx, m.id, fty);
- tcx.methods.borrow_mut().insert(mty.def_id, mty);
+ tcx.impl_or_trait_items
+ .borrow_mut()
+ .insert(mty.def_id, ty::MethodTraitItem(mty));
}
fn ty_of_method(ccx: &CrateCtxt,
- container: MethodContainer,
+ container: ImplOrTraitItemContainer,
m: &ast::Method,
untransformed_rcvr_ty: ty::t,
rcvr_ty_generics: &ty::Generics,
enum_definition.variants.as_slice(),
generics);
},
- ast::ItemImpl(ref generics, ref opt_trait_ref, selfty, ref ms) => {
+ ast::ItemImpl(ref generics,
+ ref opt_trait_ref,
+ selfty,
+ ref impl_items) => {
let ty_generics = ty_generics_for_type(ccx, generics);
let selfty = ccx.to_ty(&ExplicitRscope, &*selfty);
write_ty_to_tcx(tcx, it.id, selfty);
it.vis
};
- for method in ms.iter() {
- check_method_self_type(ccx,
- &BindingRscope::new(method.id),
- selfty,
- method.pe_explicit_self())
+ let mut methods = Vec::new();
+ for impl_item in impl_items.iter() {
+ match *impl_item {
+ ast::MethodImplItem(ref method) => {
+ check_method_self_type(ccx,
+ &BindingRscope::new(method.id),
+ selfty,
+ method.pe_explicit_self());
+ methods.push(*method);
+ }
+ }
}
convert_methods(ccx,
ImplContainer(local_def(it.id)),
- ms.as_slice(),
+ methods.as_slice(),
selfty,
&ty_generics,
parent_visibility);
0,
local_def(it.id));
match *trait_method {
- ast::Required(ref type_method) => {
+ ast::RequiredMethod(ref type_method) => {
let rscope = BindingRscope::new(type_method.id);
check_method_self_type(ccx,
&rscope,
self_type,
&type_method.explicit_self)
}
- ast::Provided(ref method) => {
+ ast::ProvidedMethod(ref method) => {
check_method_self_type(ccx,
&BindingRscope::new(method.id),
self_type,
fn ty_generics_for_type(ccx: &CrateCtxt,
generics: &ast::Generics)
- -> ty::Generics
-{
- ty_generics(ccx, subst::TypeSpace, &generics.lifetimes,
- &generics.ty_params, ty::Generics::empty())
+ -> ty::Generics {
+ ty_generics(ccx,
+ subst::TypeSpace,
+ &generics.lifetimes,
+ &generics.ty_params,
+ ty::Generics::empty(),
+ &generics.where_clause)
}
fn ty_generics_for_trait(ccx: &CrateCtxt,
trait_id: ast::NodeId,
substs: &subst::Substs,
generics: &ast::Generics)
- -> ty::Generics
-{
- let mut generics = ty_generics(ccx, subst::TypeSpace, &generics.lifetimes,
- &generics.ty_params, ty::Generics::empty());
+ -> ty::Generics {
+ let mut generics = ty_generics(ccx,
+ subst::TypeSpace,
+ &generics.lifetimes,
+ &generics.ty_params,
+ ty::Generics::empty(),
+ &generics.where_clause);
// Something of a hack: use the node id for the trait, also as
// the node id for the Self type parameter.
fn ty_generics_for_fn_or_method(ccx: &CrateCtxt,
generics: &ast::Generics,
base_generics: ty::Generics)
- -> ty::Generics
-{
+ -> ty::Generics {
let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
- ty_generics(ccx, subst::FnSpace, &early_lifetimes,
- &generics.ty_params, base_generics)
+ ty_generics(ccx,
+ subst::FnSpace,
+ &early_lifetimes,
+ &generics.ty_params,
+ base_generics,
+ &generics.where_clause)
}
// Add the Sized bound, unless the type parameter is marked as `Sized?`.
space: subst::ParamSpace,
lifetimes: &Vec<ast::LifetimeDef>,
types: &OwnedSlice<ast::TyParam>,
- base_generics: ty::Generics)
- -> ty::Generics
-{
+ base_generics: ty::Generics,
+ where_clause: &ast::WhereClause)
+ -> ty::Generics {
let mut result = base_generics;
for (i, l) in lifetimes.iter().enumerate() {
}
for (i, param) in types.iter().enumerate() {
- let def = get_or_create_type_parameter_def(ccx, space, param, i);
+ let def = get_or_create_type_parameter_def(ccx,
+ space,
+ param,
+ i,
+ where_clause);
debug!("ty_generics: def for type param: {}", def.repr(ccx.tcx));
result.types.push(space, def);
}
fn get_or_create_type_parameter_def(ccx: &CrateCtxt,
space: subst::ParamSpace,
param: &ast::TyParam,
- index: uint)
- -> ty::TypeParameterDef
- {
+ index: uint,
+ where_clause: &ast::WhereClause)
+ -> ty::TypeParameterDef {
match ccx.tcx.ty_param_defs.borrow().find(¶m.id) {
Some(d) => { return (*d).clone(); }
None => { }
¶m.bounds,
¶m.unbound,
param.ident,
- param.span));
+ param.span,
+ where_clause));
let default = param.default.map(|path| {
let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &*path);
let cur_idx = param_ty.idx;
def
}
- fn compute_bounds(
- ccx: &CrateCtxt,
- param_ty: ty::ParamTy,
- ast_bounds: &OwnedSlice<ast::TyParamBound>,
- unbound: &Option<ast::TyParamBound>,
- ident: ast::Ident,
- span: Span) -> ty::ParamBounds
- {
+ fn compute_bounds(ccx: &CrateCtxt,
+ param_ty: ty::ParamTy,
+ ast_bounds: &OwnedSlice<ast::TyParamBound>,
+ unbound: &Option<ast::TyParamBound>,
+ ident: ast::Ident,
+ span: Span,
+ where_clause: &ast::WhereClause)
+ -> ty::ParamBounds {
/*!
* Translate the AST's notion of ty param bounds (which are an
* enum consisting of a newtyped Ty or a region) to ty's
trait_bounds: Vec::new()
};
for ast_bound in ast_bounds.iter() {
- match *ast_bound {
- TraitTyParamBound(ref b) => {
- let ty = ty::mk_param(ccx.tcx, param_ty.space,
- param_ty.idx, param_ty.def_id);
- let trait_ref = instantiate_trait_ref(ccx, b, ty);
- if !ty::try_add_builtin_trait(
- ccx.tcx, trait_ref.def_id,
- &mut param_bounds.builtin_bounds) {
- // Must be a user-defined trait
- param_bounds.trait_bounds.push(trait_ref);
- }
- }
-
- StaticRegionTyParamBound => {
- param_bounds.builtin_bounds.add(ty::BoundStatic);
- }
-
- UnboxedFnTyParamBound(ref unboxed_function) => {
- let rscope = ExplicitRscope;
- let self_ty = ty::mk_param(ccx.tcx,
- param_ty.space,
- param_ty.idx,
- param_ty.def_id);
- let trait_ref =
- astconv::trait_ref_for_unboxed_function(ccx,
- &rscope,
- unboxed_function,
- Some(self_ty));
- param_bounds.trait_bounds.push(Rc::new(trait_ref));
- }
-
- OtherRegionTyParamBound(span) => {
- if !ccx.tcx.sess.features.issue_5723_bootstrap.get() {
- ccx.tcx.sess.span_err(
- span,
- "only the 'static lifetime is accepted here.");
- }
- }
+ compute_bound(ccx, &mut param_bounds, param_ty, ast_bound);
+ }
+ for predicate in where_clause.predicates.iter() {
+ let predicate_param_id = ccx.tcx
+ .def_map
+ .borrow()
+ .find(&predicate.id)
+ .expect("compute_bounds(): resolve \
+ didn't resolve the type \
+ parameter identifier in a \
+ `where` clause")
+ .def_id();
+ if param_ty.def_id != predicate_param_id {
+ continue
+ }
+ for bound in predicate.bounds.iter() {
+ compute_bound(ccx, &mut param_bounds, param_ty, bound);
}
}
param_bounds
}
+ /// Translates the AST's notion of a type parameter bound to
+ /// typechecking's notion of the same, and pushes the resulting bound onto
+ /// the appropriate section of `param_bounds`.
+ fn compute_bound(ccx: &CrateCtxt,
+ param_bounds: &mut ty::ParamBounds,
+ param_ty: ty::ParamTy,
+ ast_bound: &ast::TyParamBound) {
+ match *ast_bound {
+ TraitTyParamBound(ref b) => {
+ let ty = ty::mk_param(ccx.tcx, param_ty.space,
+ param_ty.idx, param_ty.def_id);
+ let trait_ref = instantiate_trait_ref(ccx, b, ty);
+ if !ty::try_add_builtin_trait(
+ ccx.tcx, trait_ref.def_id,
+ &mut param_bounds.builtin_bounds) {
+ // Must be a user-defined trait
+ param_bounds.trait_bounds.push(trait_ref);
+ }
+ }
+
+ StaticRegionTyParamBound => {
+ param_bounds.builtin_bounds.add(ty::BoundStatic);
+ }
+
+ UnboxedFnTyParamBound(ref unboxed_function) => {
+ let rscope = ExplicitRscope;
+ let self_ty = ty::mk_param(ccx.tcx,
+ param_ty.space,
+ param_ty.idx,
+ param_ty.def_id);
+ let trait_ref =
+ astconv::trait_ref_for_unboxed_function(ccx,
+ &rscope,
+ unboxed_function,
+ Some(self_ty));
+ param_bounds.trait_bounds.push(Rc::new(trait_ref));
+ }
+
+ OtherRegionTyParamBound(span) => {
+ if !ccx.tcx.sess.features.issue_5723_bootstrap.get() {
+ ccx.tcx.sess.span_err(
+ span,
+ "only the 'static lifetime is accepted here.");
+ }
+ }
+ }
+ }
+
fn check_bounds_compatible(tcx: &ty::ctxt,
param_bounds: &ty::ParamBounds,
ident: ast::Ident,
Ok(ty::mk_struct(tcx, a_id, substs))
}
- (&ty::ty_unboxed_closure(a_id), &ty::ty_unboxed_closure(b_id))
+ (&ty::ty_unboxed_closure(a_id, a_region),
+ &ty::ty_unboxed_closure(b_id, b_region))
if a_id == b_id => {
- Ok(ty::mk_unboxed_closure(tcx, a_id))
+ let region = if_ok!(this.regions(a_region, b_region));
+ Ok(ty::mk_unboxed_closure(tcx, a_id, region))
}
(&ty::ty_box(a_inner), &ty::ty_box(b_inner)) => {
},
_ => None
},
- ast_map::NodeMethod(..) => {
+ ast_map::NodeImplItem(..) |
+ ast_map::NodeTraitItem(..) => {
Some(FreeRegionsFromSameFn::new(fr1, fr2, scope_id))
},
_ => None
_ => None
}
}
- ast_map::NodeMethod(ref m) => {
- Some((m.pe_fn_decl(), m.pe_generics(), m.pe_fn_style(),
- m.pe_ident(), Some(m.pe_explicit_self().node), m.span))
+ ast_map::NodeImplItem(ref item) => {
+ match **item {
+ ast::MethodImplItem(ref m) => {
+ Some((m.pe_fn_decl(),
+ m.pe_generics(),
+ m.pe_fn_style(),
+ m.pe_ident(),
+ Some(m.pe_explicit_self().node),
+ m.span))
+ }
+ }
},
_ => None
},
let mut inputs = self.fn_decl.inputs.clone();
let mut output = self.fn_decl.output;
let mut ty_params = self.generics.ty_params.clone();
+ let where_clause = self.generics.where_clause.clone();
let mut kept_lifetimes = HashSet::new();
for sr in self.same_regions.iter() {
self.cur_anon.set(0);
&fresh_lifetimes,
&kept_lifetimes,
&all_region_names,
- ty_params);
+ ty_params,
+ where_clause);
let new_fn_decl = ast::FnDecl {
inputs: inputs,
output: output,
add: &Vec<ast::Lifetime>,
keep: &HashSet<ast::Name>,
remove: &HashSet<ast::Name>,
- ty_params: OwnedSlice<ast::TyParam>)
+ ty_params: OwnedSlice<ast::TyParam>,
+ where_clause: ast::WhereClause)
-> ast::Generics {
let mut lifetimes = Vec::new();
for lt in add.iter() {
}
for lt in generics.lifetimes.iter() {
if keep.contains(<.lifetime.name) ||
- !remove.contains(<.lifetime.name)
- {
+ !remove.contains(<.lifetime.name) {
lifetimes.push((*lt).clone());
}
}
ast::Generics {
lifetimes: lifetimes,
- ty_params: ty_params
+ ty_params: ty_params,
+ where_clause: where_clause,
}
}
},
_ => None
},
- ast_map::NodeMethod(m) => {
- taken.push_all(m.pe_generics().lifetimes.as_slice());
- Some(m.id)
- },
+ ast_map::NodeImplItem(ii) => {
+ match *ii {
+ ast::MethodImplItem(m) => {
+ taken.push_all(m.pe_generics().lifetimes.as_slice());
+ Some(m.id)
+ }
+ }
+ }
_ => None
},
None => None
let lang_items = lang_items::collect_language_items(&krate, &sess);
let resolve::CrateMap { def_map: def_map, .. } =
resolve::resolve_crate(&sess, &lang_items, &krate);
- let freevars_map = freevars::annotate_freevars(&def_map, &krate);
+ let (freevars_map, captures_map) = freevars::annotate_freevars(&def_map,
+ &krate);
let named_region_map = resolve_lifetime::krate(&sess, &krate);
let region_map = region::resolve_crate(&sess, &krate);
let stability_index = stability::Index::build(&krate);
- let tcx = ty::mk_ctxt(sess, def_map, named_region_map, ast_map,
- freevars_map, region_map, lang_items, stability_index);
+ let tcx = ty::mk_ctxt(sess,
+ def_map,
+ named_region_map,
+ ast_map,
+ freevars_map,
+ captures_map,
+ region_map,
+ lang_items,
+ stability_index);
let infcx = infer::new_infer_ctxt(&tcx);
let env = Env {krate: krate,
tcx: &tcx,
}
ast::ItemTrait(..) => {
- let methods = ty::trait_methods(tcx, did);
- for method in methods.iter() {
- self.add_constraints_from_sig(
- &method.fty.sig, self.covariant);
+ let trait_items = ty::trait_items(tcx, did);
+ for trait_item in trait_items.iter() {
+ match *trait_item {
+ ty::MethodTraitItem(ref method) => {
+ self.add_constraints_from_sig(&method.fty.sig,
+ self.covariant);
+ }
+ }
}
}
_ => cannot_happen!(),
}
}
- ast_map::NodeTraitMethod(..) => is_inferred = false,
- ast_map::NodeMethod(_) => is_inferred = false,
+ ast_map::NodeTraitItem(..) => is_inferred = false,
+ ast_map::NodeImplItem(..) => is_inferred = false,
_ => cannot_happen!(),
}
match ty::get(ty).sty {
ty::ty_nil | ty::ty_bot | ty::ty_bool |
ty::ty_char | ty::ty_int(_) | ty::ty_uint(_) |
- ty::ty_float(_) | ty::ty_str | ty::ty_unboxed_closure(..) => {
+ ty::ty_float(_) | ty::ty_str => {
/* leaf type -- noop */
}
+ ty::ty_unboxed_closure(_, region) => {
+ let contra = self.contravariant(variance);
+ self.add_constraints_from_region(region, contra);
+ }
+
ty::ty_rptr(region, ref mt) => {
let contra = self.contravariant(variance);
self.add_constraints_from_region(region, contra);
match tcx.map.find(self.node) {
Some(ast_map::NodeItem(..)) |
Some(ast_map::NodeForeignItem(..)) |
- Some(ast_map::NodeMethod(..)) |
- Some(ast_map::NodeTraitMethod(..)) |
+ Some(ast_map::NodeImplItem(..)) |
+ Some(ast_map::NodeTraitItem(..)) |
Some(ast_map::NodeVariant(..)) |
Some(ast_map::NodeStructCtor(..)) => {
return format!(
pub fn find_library(name: &str, os: abi::Os, search_paths: &[Path],
handler: &ErrorHandler) -> Path {
let (osprefix, osext) = match os {
- abi::OsWin32 => ("", "lib"), _ => ("lib", "a"),
+ abi::OsWindows => ("", "lib"), _ => ("lib", "a"),
};
// On Windows, static libraries sometimes show up as libfoo.a and other
// times show up as foo.lib
-a0:0:64-n32".to_string()
}
- abi::OsWin32 => {
+ abi::OsWindows => {
"e-p:32:32:32\
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-a0:0:64-n32".to_string()
}
- abi::OsWin32 => {
+ abi::OsWindows => {
"E-p:32:32:32\
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-a0:0:64-n32".to_string()
}
- abi::OsWin32 => {
+ abi::OsWindows => {
"e-p:32:32:32\
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
pub fn get_rpath_flags(config: RPathConfig) -> Vec<String> {
// No rpath on windows
- if config.os == abi::OsWin32 {
+ if config.os == abi::OsWindows {
return Vec::new();
}
lib: &Path) -> String {
use std::os;
- assert!(config.os != abi::OsWin32);
+ assert!(config.os != abi::OsWindows);
// Mac doesn't appear to support $ORIGIN
let prefix = match config.os {
abi::OsAndroid | abi::OsLinux | abi::OsFreebsd | abi::OsDragonfly
=> "$ORIGIN",
abi::OsMacos => "@loader_path",
- abi::OsWin32 | abi::OsiOS => unreachable!()
+ abi::OsWindows | abi::OsiOS => unreachable!()
};
let mut lib = (config.realpath)(&os::make_absolute(lib)).unwrap();
SawTyMethod.hash(self.st); visit::walk_ty_method(self, t, e)
}
- fn visit_trait_method(&mut self, t: &TraitMethod, e: E) {
- SawTraitMethod.hash(self.st); visit::walk_trait_method(self, t, e)
+ fn visit_trait_item(&mut self, t: &TraitItem, e: E) {
+ SawTraitMethod.hash(self.st); visit::walk_trait_item(self, t, e)
}
fn visit_struct_field(&mut self, s: &StructField, e: E) {
-n8:16:32".to_string()
}
- abi::OsWin32 => {
+ abi::OsWindows => {
"e-p:32:32-f64:64:64-i64:64:64-f80:32:32-n8:16:32".to_string()
}
s0:64:64-f80:128:128-n8:16:32:64".to_string()
}
- abi::OsWin32 => {
+ abi::OsWindows => {
// FIXME: Test this. Copied from linux (#2398)
"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
pub fn build_external_trait(tcx: &ty::ctxt, did: ast::DefId) -> clean::Trait {
let def = ty::lookup_trait_def(tcx, did);
- let methods = ty::trait_methods(tcx, did).clean();
+ let trait_items = ty::trait_items(tcx, did).clean();
let provided = ty::provided_trait_methods(tcx, did);
- let mut methods = methods.move_iter().map(|meth| {
- if provided.iter().any(|a| a.def_id == meth.def_id) {
- clean::Provided(meth)
+ let mut items = trait_items.move_iter().map(|trait_item| {
+ if provided.iter().any(|a| a.def_id == trait_item.def_id) {
+ clean::ProvidedMethod(trait_item)
} else {
- clean::Required(meth)
+ clean::RequiredMethod(trait_item)
}
});
let supertraits = ty::trait_supertraits(tcx, did);
clean::Trait {
generics: (&def.generics, subst::TypeSpace).clean(),
- methods: methods.collect(),
+ items: items.collect(),
parents: parents.collect()
}
}
let attrs = load_attrs(tcx, did);
let ty = ty::lookup_item_type(tcx, did);
- let methods = csearch::get_impl_methods(&tcx.sess.cstore,
- did).iter().filter_map(|did| {
- let method = ty::method(tcx, *did);
- if method.vis != ast::Public && associated_trait.is_none() {
- return None
- }
- let mut item = ty::method(tcx, *did).clean();
- item.inner = match item.inner.clone() {
- clean::TyMethodItem(clean::TyMethod {
- fn_style, decl, self_, generics
- }) => {
- clean::MethodItem(clean::Method {
- fn_style: fn_style,
- decl: decl,
- self_: self_,
- generics: generics,
- })
+ let trait_items = csearch::get_impl_items(&tcx.sess.cstore, did)
+ .iter()
+ .filter_map(|did| {
+ let did = did.def_id();
+ let impl_item = ty::impl_or_trait_item(tcx, did);
+ match impl_item {
+ ty::MethodTraitItem(method) => {
+ if method.vis != ast::Public && associated_trait.is_none() {
+ return None
+ }
+ let mut item = method.clean();
+ item.inner = match item.inner.clone() {
+ clean::TyMethodItem(clean::TyMethod {
+ fn_style, decl, self_, generics
+ }) => {
+ clean::MethodItem(clean::Method {
+ fn_style: fn_style,
+ decl: decl,
+ self_: self_,
+ generics: generics,
+ })
+ }
+ _ => fail!("not a tymethod"),
+ };
+ Some(item)
}
- _ => fail!("not a tymethod"),
- };
- Some(item)
+ }
}).collect();
return Some(clean::Item {
inner: clean::ImplItem(clean::Impl {
}),
for_: ty.ty.clean(),
generics: (&ty.generics, subst::TypeSpace).clean(),
- methods: methods,
+ items: trait_items,
}),
source: clean::Span::empty(),
name: None,
// determine if we should display the inner contents or
// the outer `mod` item for the source code.
- let where = {
+ let whence = {
let ctxt = super::ctxtkey.get().unwrap();
let cm = ctxt.sess().codemap();
let outer = cm.lookup_char_pos(self.where_outer.lo);
Item {
name: Some(name),
attrs: self.attrs.clean(),
- source: where.clean(),
+ source: whence.clean(),
visibility: self.vis.clean(),
stability: self.stab.clean(),
def_id: ast_util::local_def(self.id),
Item {
name: Some(self.name.clean()),
attrs: self.attrs.clean(),
- source: self.where.clean(),
+ source: self.whence.clean(),
visibility: self.vis.clean(),
stability: self.stab.clean(),
def_id: ast_util::local_def(self.id),
#[deriving(Clone, Encodable, Decodable)]
pub struct Trait {
- pub methods: Vec<TraitMethod>,
+ pub items: Vec<TraitItem>,
pub generics: Generics,
pub parents: Vec<Type>,
}
Item {
name: Some(self.name.clean()),
attrs: self.attrs.clean(),
- source: self.where.clean(),
+ source: self.whence.clean(),
def_id: ast_util::local_def(self.id),
visibility: self.vis.clean(),
stability: self.stab.clean(),
inner: TraitItem(Trait {
- methods: self.methods.clean(),
+ items: self.items.clean(),
generics: self.generics.clean(),
parents: self.parents.clean(),
}),
}
#[deriving(Clone, Encodable, Decodable)]
-pub enum TraitMethod {
- Required(Item),
- Provided(Item),
+pub enum TraitItem {
+ RequiredMethod(Item),
+ ProvidedMethod(Item),
}
-impl TraitMethod {
+impl TraitItem {
pub fn is_req(&self) -> bool {
match self {
- &Required(..) => true,
+ &RequiredMethod(..) => true,
_ => false,
}
}
pub fn is_def(&self) -> bool {
match self {
- &Provided(..) => true,
+ &ProvidedMethod(..) => true,
_ => false,
}
}
pub fn item<'a>(&'a self) -> &'a Item {
match *self {
- Required(ref item) => item,
- Provided(ref item) => item,
+ RequiredMethod(ref item) => item,
+ ProvidedMethod(ref item) => item,
}
}
}
-impl Clean<TraitMethod> for ast::TraitMethod {
- fn clean(&self) -> TraitMethod {
+impl Clean<TraitItem> for ast::TraitItem {
+ fn clean(&self) -> TraitItem {
match self {
- &ast::Required(ref t) => Required(t.clean()),
- &ast::Provided(ref t) => Provided(t.clean()),
+ &ast::RequiredMethod(ref t) => RequiredMethod(t.clean()),
+ &ast::ProvidedMethod(ref t) => ProvidedMethod(t.clean()),
+ }
+ }
+}
+
+#[deriving(Clone, Encodable, Decodable)]
+pub enum ImplItem {
+ MethodImplItem(Item),
+}
+
+impl Clean<ImplItem> for ast::ImplItem {
+ fn clean(&self) -> ImplItem {
+ match self {
+ &ast::MethodImplItem(ref t) => MethodImplItem(t.clean()),
}
}
}
}
}
+impl Clean<Item> for ty::ImplOrTraitItem {
+ fn clean(&self) -> Item {
+ match *self {
+ ty::MethodTraitItem(ref mti) => mti.clean(),
+ }
+ }
+}
+
/// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
/// type out of the AST/ty::ctxt given one of these, if more information is needed. Most importantly
/// it does not preserve mutability or boxes.
Item {
name: Some(self.name.clean()),
attrs: self.attrs.clean(),
- source: self.where.clean(),
+ source: self.whence.clean(),
def_id: ast_util::local_def(self.id),
visibility: self.vis.clean(),
stability: self.stab.clean(),
Item {
name: Some(self.name.clean()),
attrs: self.attrs.clean(),
- source: self.where.clean(),
+ source: self.whence.clean(),
def_id: ast_util::local_def(self.id),
visibility: self.vis.clean(),
stability: self.stab.clean(),
Item {
name: Some(self.name.clean()),
attrs: self.attrs.clean(),
- source: self.where.clean(),
+ source: self.whence.clean(),
visibility: self.vis.clean(),
stability: self.stab.clean(),
def_id: ast_util::local_def(self.id),
Item {
name: Some(self.name.clean()),
attrs: self.attrs.clean(),
- source: self.where.clean(),
+ source: self.whence.clean(),
def_id: ast_util::local_def(self.id.clone()),
visibility: self.vis.clean(),
stability: self.stab.clean(),
Item {
name: Some(self.name.clean()),
attrs: self.attrs.clean(),
- source: self.where.clean(),
+ source: self.whence.clean(),
def_id: ast_util::local_def(self.id),
visibility: self.vis.clean(),
stability: self.stab.clean(),
pub generics: Generics,
pub trait_: Option<Type>,
pub for_: Type,
- pub methods: Vec<Item>,
+ pub items: Vec<Item>,
pub derived: bool,
}
Item {
name: None,
attrs: self.attrs.clean(),
- source: self.where.clean(),
+ source: self.whence.clean(),
def_id: ast_util::local_def(self.id),
visibility: self.vis.clean(),
stability: self.stab.clean(),
generics: self.generics.clean(),
trait_: self.trait_.clean(),
for_: self.for_.clean(),
- methods: self.methods.clean(),
+ items: self.items.clean().move_iter().map(|ti| {
+ match ti {
+ MethodImplItem(i) => i,
+ }
+ }).collect(),
derived: detect_derived(self.attrs.as_slice()),
}),
}
Item {
name: Some(format!("{}!", self.name.clean())),
attrs: self.attrs.clean(),
- source: self.where.clean(),
+ source: self.whence.clean(),
visibility: ast::Public.clean(),
stability: self.stab.clean(),
def_id: ast_util::local_def(self.id),
inner: MacroItem(Macro {
- source: self.where.to_src(),
+ source: self.whence.to_src(),
}),
}
}
pub generics: ast::Generics,
pub attrs: Vec<ast::Attribute>,
pub fields: Vec<ast::StructField>,
- pub where: Span,
+ pub whence: Span,
}
pub struct Enum {
pub generics: ast::Generics,
pub attrs: Vec<ast::Attribute>,
pub id: NodeId,
- pub where: Span,
+ pub whence: Span,
pub name: Ident,
}
pub id: ast::NodeId,
pub vis: ast::Visibility,
pub stab: Option<attr::Stability>,
- pub where: Span,
+ pub whence: Span,
}
pub struct Function {
pub vis: ast::Visibility,
pub stab: Option<attr::Stability>,
pub fn_style: ast::FnStyle,
- pub where: Span,
+ pub whence: Span,
pub generics: ast::Generics,
}
pub name: Ident,
pub id: ast::NodeId,
pub attrs: Vec<ast::Attribute>,
- pub where: Span,
+ pub whence: Span,
pub vis: ast::Visibility,
pub stab: Option<attr::Stability>,
}
pub vis: ast::Visibility,
pub stab: Option<attr::Stability>,
pub id: ast::NodeId,
- pub where: Span,
+ pub whence: Span,
}
pub struct Trait {
pub name: Ident,
- pub methods: Vec<ast::TraitMethod>, //should be TraitMethod
+ pub items: Vec<ast::TraitItem>, //should be TraitItem
pub generics: ast::Generics,
pub parents: Vec<ast::TraitRef>,
pub attrs: Vec<ast::Attribute>,
pub id: ast::NodeId,
- pub where: Span,
+ pub whence: Span,
pub vis: ast::Visibility,
pub stab: Option<attr::Stability>,
}
pub generics: ast::Generics,
pub trait_: Option<ast::TraitRef>,
pub for_: ast::P<ast::Ty>,
- pub methods: Vec<Gc<ast::Method>>,
+ pub items: Vec<ast::ImplItem>,
pub attrs: Vec<ast::Attribute>,
- pub where: Span,
+ pub whence: Span,
pub vis: ast::Visibility,
pub stab: Option<attr::Stability>,
pub id: ast::NodeId,
pub name: Ident,
pub id: ast::NodeId,
pub attrs: Vec<ast::Attribute>,
- pub where: Span,
+ pub whence: Span,
pub stab: Option<attr::Stability>,
}
EnumItem(i)
},
TraitItem(mut i) => {
- fn vtrm<T: DocFolder>(this: &mut T, trm: TraitMethod) -> Option<TraitMethod> {
+ fn vtrm<T: DocFolder>(this: &mut T, trm: TraitItem)
+ -> Option<TraitItem> {
match trm {
- Required(it) => {
+ RequiredMethod(it) => {
match this.fold_item(it) {
- Some(x) => return Some(Required(x)),
+ Some(x) => return Some(RequiredMethod(x)),
None => return None,
}
},
- Provided(it) => {
+ ProvidedMethod(it) => {
match this.fold_item(it) {
- Some(x) => return Some(Provided(x)),
+ Some(x) => return Some(ProvidedMethod(x)),
None => return None,
}
},
}
}
- let mut foo = Vec::new(); swap(&mut foo, &mut i.methods);
- i.methods.extend(foo.move_iter().filter_map(|x| vtrm(self, x)));
+ let mut foo = Vec::new(); swap(&mut foo, &mut i.items);
+ i.items.extend(foo.move_iter().filter_map(|x| vtrm(self, x)));
TraitItem(i)
},
ImplItem(mut i) => {
- let mut foo = Vec::new(); swap(&mut foo, &mut i.methods);
- i.methods.extend(foo.move_iter().filter_map(|x| self.fold_item(x)));
+ let mut foo = Vec::new(); swap(&mut foo, &mut i.items);
+ i.items.extend(foo.move_iter()
+ .filter_map(|x| self.fold_item(x)));
ImplItem(i)
},
VariantItem(i) => {
it.name.get_ref().as_slice(),
t.generics,
parents));
- let required = t.methods.iter().filter(|m| m.is_req()).collect::<Vec<&clean::TraitMethod>>();
- let provided = t.methods.iter().filter(|m| !m.is_req()).collect::<Vec<&clean::TraitMethod>>();
-
- if t.methods.len() == 0 {
+ let required = t.items.iter()
+ .filter(|m| {
+ match **m {
+ clean::RequiredMethod(_) => true,
+ _ => false,
+ }
+ })
+ .collect::<Vec<&clean::TraitItem>>();
+ let provided = t.items.iter()
+ .filter(|m| {
+ match **m {
+ clean::ProvidedMethod(_) => true,
+ _ => false,
+ }
+ })
+ .collect::<Vec<&clean::TraitItem>>();
+
+ if t.items.len() == 0 {
try!(write!(w, "{{ }}"));
} else {
try!(write!(w, "{{\n"));
// Trait documentation
try!(document(w, it));
- fn meth(w: &mut fmt::Formatter, m: &clean::TraitMethod) -> fmt::Result {
+ fn trait_item(w: &mut fmt::Formatter, m: &clean::TraitItem)
+ -> fmt::Result {
try!(write!(w, "<h3 id='{}.{}' class='method'>{}<code>",
shortty(m.item()),
*m.item().name.get_ref(),
<div class='methods'>
"));
for m in required.iter() {
- try!(meth(w, *m));
+ try!(trait_item(w, *m));
}
try!(write!(w, "</div>"));
}
<div class='methods'>
"));
for m in provided.iter() {
- try!(meth(w, *m));
+ try!(trait_item(w, *m));
}
try!(write!(w, "</div>"));
}
None => {}
}
- fn docmeth(w: &mut fmt::Formatter, item: &clean::Item,
- dox: bool) -> fmt::Result {
+ fn doctraititem(w: &mut fmt::Formatter, item: &clean::Item, dox: bool)
+ -> fmt::Result {
try!(write!(w, "<h4 id='method.{}' class='method'>{}<code>",
*item.name.get_ref(),
ConciseStability(&item.stability)));
}
try!(write!(w, "<div class='impl-methods'>"));
- for meth in i.impl_.methods.iter() {
- try!(docmeth(w, meth, true));
+ for trait_item in i.impl_.items.iter() {
+ try!(doctraititem(w, trait_item, true));
}
fn render_default_methods(w: &mut fmt::Formatter,
t: &clean::Trait,
i: &clean::Impl) -> fmt::Result {
- for method in t.methods.iter() {
- let n = method.item().name.clone();
- match i.methods.iter().find(|m| { m.name == n }) {
+ for trait_item in t.items.iter() {
+ let n = trait_item.item().name.clone();
+ match i.items.iter().find(|m| { m.name == n }) {
Some(..) => continue,
None => {}
}
- try!(docmeth(w, method.item(), false));
+ try!(doctraititem(w, trait_item.item(), false));
}
Ok(())
}
fn parse_externs(matches: &getopts::Matches) -> Result<core::Externs, String> {
let mut externs = HashMap::new();
for arg in matches.opt_strs("extern").iter() {
- let mut parts = arg.as_slice().splitn('=', 1);
+ let mut parts = arg.as_slice().splitn(1, '=');
let name = match parts.next() {
Some(s) => s,
None => {
clean::ModuleItem(ref m)
if m.items.len() == 0 &&
i.doc_value().is_none() => None,
- clean::ImplItem(ref i) if i.methods.len() == 0 => None,
+ clean::ImplItem(ref i) if i.items.len() == 0 => None,
_ => {
self.retained.insert(i.def_id.node);
Some(i)
}
}
-#[cfg(target_os="win32")]
+#[cfg(target_os = "windows")]
+#[cfg(stage0, target_os = "win32")] // NOTE: Remove after snapshot
fn libname(mut n: String) -> String {
n.push_str(".dll");
n
n
}
-#[cfg(not(target_os="win32"), not(target_os="macos"))]
+#[cfg(not(stage0), not(target_os="windows"), not(target_os="macos"))]
+#[cfg(stage0, not(target_os="win32"), not(target_os="macos"))] // NOTE: Remove after snapshot
fn libname(n: String) -> String {
let mut i = String::from_str("lib");
i.push_str(n.as_slice());
use syntax::ast::Public;
use clean::{Crate, Item, ModuleItem, Module, StructItem, Struct, EnumItem, Enum};
-use clean::{ImplItem, Impl, TraitItem, Trait, TraitMethod, Provided, Required};
+use clean::{ImplItem, Impl, Trait, TraitItem, ProvidedMethod, RequiredMethod};
use clean::{ViewItemItem, PrimitiveItem};
#[deriving(Zero, Encodable, Decodable, PartialEq, Eq)]
match item.inner {
// Require explicit `pub` to be visible
StructItem(Struct { fields: ref subitems, .. }) |
- ImplItem(Impl { methods: ref subitems, trait_: None, .. }) => {
+ ImplItem(Impl { items: ref subitems, trait_: None, .. }) => {
let subcounts = subitems.iter().filter(|i| visible(*i))
.map(summarize_item)
.map(|s| s.val0())
.sum();
(item_counts + subcounts, None)
}
- TraitItem(Trait { methods: ref methods, .. }) => {
- fn extract_item<'a>(meth: &'a TraitMethod) -> &'a Item {
- match *meth {
- Provided(ref item) | Required(ref item) => item
+ TraitItem(Trait {
+ items: ref trait_items,
+ ..
+ }) => {
+ fn extract_item<'a>(trait_item: &'a TraitItem) -> &'a Item {
+ match *trait_item {
+ ProvidedMethod(ref item) |
+ RequiredMethod(ref item) => item
}
}
- let subcounts = methods.iter().map(extract_item)
- .map(summarize_item)
- .map(|s| s.val0())
- .sum();
+ let subcounts = trait_items.iter()
+ .map(extract_item)
+ .map(summarize_item)
+ .map(|s| s.val0())
+ .sum();
(item_counts + subcounts, None)
}
ModuleItem(Module { items: ref items, .. }) => {
attrs: item.attrs.iter().map(|x| *x).collect(),
generics: generics.clone(),
fields: sd.fields.iter().map(|x| (*x).clone()).collect(),
- where: item.span
+ whence: item.span
}
}
stab: self.stability(x.node.id),
id: x.node.id,
kind: x.node.kind.clone(),
- where: x.span,
+ whence: x.span,
});
}
Enum {
generics: params.clone(),
attrs: it.attrs.iter().map(|x| *x).collect(),
id: it.id,
- where: it.span,
+ whence: it.span,
}
}
attrs: item.attrs.iter().map(|x| *x).collect(),
decl: fd.clone(),
name: item.ident,
- where: item.span,
+ whence: item.span,
generics: gen.clone(),
fn_style: *fn_style,
}
name: item.ident,
id: item.id,
attrs: item.attrs.iter().map(|x| *x).collect(),
- where: item.span,
+ whence: item.span,
vis: item.vis,
stab: self.stability(item.id),
};
id: item.id,
name: item.ident,
attrs: item.attrs.iter().map(|x| *x).collect(),
- where: item.span,
+ whence: item.span,
vis: item.vis,
stab: self.stability(item.id),
};
om.statics.push(s);
},
- ast::ItemTrait(ref gen, _, ref tr, ref met) => {
+ ast::ItemTrait(ref gen, _, ref tr, ref items) => {
let t = Trait {
name: item.ident,
- methods: met.iter().map(|x| (*x).clone()).collect(),
+ items: items.iter().map(|x| (*x).clone()).collect(),
generics: gen.clone(),
parents: tr.iter().map(|x| (*x).clone()).collect(),
id: item.id,
attrs: item.attrs.iter().map(|x| *x).collect(),
- where: item.span,
+ whence: item.span,
vis: item.vis,
stab: self.stability(item.id),
};
om.traits.push(t);
},
- ast::ItemImpl(ref gen, ref tr, ty, ref meths) => {
+ ast::ItemImpl(ref gen, ref tr, ty, ref items) => {
let i = Impl {
generics: gen.clone(),
trait_: tr.clone(),
for_: ty,
- methods: meths.iter().map(|x| *x).collect(),
+ items: items.iter().map(|x| *x).collect(),
attrs: item.attrs.iter().map(|x| *x).collect(),
id: item.id,
- where: item.span,
+ whence: item.span,
vis: item.vis,
stab: self.stability(item.id),
};
id: item.id,
attrs: item.attrs.iter().map(|x| *x).collect(),
name: item.ident,
- where: item.span,
+ whence: item.span,
stab: self.stability(item.id),
}
}
#[cfg(target_os = "macos")]
#[cfg(target_os = "ios")]
-#[cfg(target_os = "win32")]
+#[cfg(target_os = "windows")]
+#[cfg(stage0, target_os = "win32")] // NOTE: Remove after snapshot
mod imp {
use core::prelude::*;
use collections::vec::Vec;
#[cfg(target_os = "linux")]
#[cfg(target_os = "freebsd")]
-#[cfg(target_os = "win32")]
+#[cfg(target_os = "windows")]
+#[cfg(stage0, target_os = "win32")] // NOTE: Remove after snapshot
#[link(name = "gcc_s")]
extern {}
unsafe fn target_record_sp_limit(limit: uint) {
asm!("movq $0, %fs:112" :: "r"(limit) :: "volatile")
}
- #[cfg(target_arch = "x86_64", target_os = "win32")] #[inline(always)]
+ #[cfg(target_arch = "x86_64", target_os = "windows")] #[inline(always)]
+ #[cfg(stage0, target_arch = "x86_64", target_os = "win32")] // NOTE: Remove after snapshot
unsafe fn target_record_sp_limit(limit: uint) {
// see: http://en.wikipedia.org/wiki/Win32_Thread_Information_Block
// store this inside of the "arbitrary data slot", but double the size
unsafe fn target_record_sp_limit(limit: uint) {
asm!("movl $0, %gs:48" :: "r"(limit) :: "volatile")
}
- #[cfg(target_arch = "x86", target_os = "win32")] #[inline(always)]
+ #[cfg(target_arch = "x86", target_os = "windows")] #[inline(always)]
+ #[cfg(stage0, target_arch = "x86", target_os = "win32")] // NOTE: Remove after snapshot
unsafe fn target_record_sp_limit(limit: uint) {
// see: http://en.wikipedia.org/wiki/Win32_Thread_Information_Block
// store this inside of the "arbitrary data slot"
asm!("movq %fs:112, $0" : "=r"(limit) ::: "volatile");
return limit;
}
- #[cfg(target_arch = "x86_64", target_os = "win32")] #[inline(always)]
+ #[cfg(target_arch = "x86_64", target_os = "windows")] #[inline(always)]
+ #[cfg(stage0, target_arch = "x86_64", target_os = "win32")] // NOTE: Remove after snapshot
unsafe fn target_get_sp_limit() -> uint {
let limit;
asm!("movq %gs:0x28, $0" : "=r"(limit) ::: "volatile");
asm!("movl %gs:48, $0" : "=r"(limit) ::: "volatile");
return limit;
}
- #[cfg(target_arch = "x86", target_os = "win32")] #[inline(always)]
+ #[cfg(target_arch = "x86", target_os = "windows")] #[inline(always)]
+ #[cfg(stage0, target_arch = "x86", target_os = "win32")] // NOTE: Remove after snapshot
unsafe fn target_get_sp_limit() -> uint {
let limit;
asm!("movl %fs:0x14, $0" : "=r"(limit) ::: "volatile");
#[link(name = "rt")]
extern {}
-#[cfg(target_os = "win32")]
+#[cfg(target_os = "windows")]
+#[cfg(stage0, target_os = "win32")] // NOTE: Remove after snapshot
#[link(name = "ws2_32")]
#[link(name = "psapi")]
#[link(name = "iphlpapi")]
use iter::Iterator;
use mem;
use option::{Option, Some, None};
-use slice::{ImmutableVector, MutableVector, Vector};
+use slice::{ImmutableSlice, MutableSlice, Slice};
use str::{Str, StrSlice};
use str;
use string::String;
use ptr::RawPtr;
use ptr;
use raw;
-use slice::Vector;
+use slice::Slice;
/// The type representing a foreign chunk of memory
pub struct CVec<T> {
}
}
-impl<T> Vector<T> for CVec<T> {
+impl<T> Slice<T> for CVec<T> {
/// View the stored data as a slice.
fn as_slice<'a>(&'a self) -> &'a [T] {
unsafe {
use prelude::*;
use super::HashSet;
- use slice::ImmutableEqVector;
+ use slice::ImmutablePartialEqSlice;
use collections::Collection;
#[test]
use os;
use path::{Path,GenericPath};
use result::*;
-use slice::{Vector,ImmutableVector};
+use slice::{Slice,ImmutableSlice};
use str;
use string::String;
use vec::Vec;
}
}
-#[cfg(target_os = "win32")]
+#[cfg(target_os = "windows")]
+#[cfg(stage0, target_os = "win32")] // NOTE: Remove after snapshot
pub mod dl {
use c_str::ToCStr;
use iter::Iterator;
use ops::Drop;
use option::{Some, None, Option};
use result::{Ok, Err};
-use slice::{ImmutableVector, MutableVector};
+use slice::{ImmutableSlice, MutableSlice};
use slice;
use vec::Vec;
use io;
use option::{None, Option, Some};
use result::{Ok, Err};
-use slice::{bytes, MutableVector, ImmutableVector};
+use slice::{bytes, MutableSlice, ImmutableSlice};
use str::StrSlice;
use super::{Reader, Writer, IoResult};
use vec::Vec;
use result::{Ok, Err};
use io;
use io::{IoError, IoResult, Reader};
-use slice::{ImmutableVector, Vector};
+use slice::{ImmutableSlice, Slice};
use ptr::RawPtr;
/// An iterator that reads a single byte on each iteration,
pub fn u64_from_be_bytes(data: &[u8], start: uint, size: uint) -> u64 {
use ptr::{copy_nonoverlapping_memory};
use mem::from_be64;
- use slice::MutableVector;
+ use slice::MutableSlice;
assert!(size <= 8u);
use result::{Err, Ok};
use rt::rtio::LocalIo;
use rt::rtio;
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
use string::String;
use vec::Vec;
use io;
use io::{Reader, Writer, Seek, Buffer, IoError, SeekStyle, IoResult};
use slice;
-use slice::{Vector, ImmutableVector, MutableVector};
+use slice::{Slice, ImmutableSlice, MutableSlice};
use vec::Vec;
static BUF_CAPACITY: uint = 128;
use boxed::Box;
use result::{Ok, Err, Result};
use rt::rtio;
-use slice::{Vector, MutableVector, ImmutableVector};
+use slice::{Slice, MutableSlice, ImmutableSlice};
use str::{Str, StrSlice};
use str;
use string::String;
use iter::Iterator;
use option::{Option, None, Some};
use str::StrSlice;
-use slice::{MutableCloneableVector, ImmutableVector, MutableVector};
+use slice::{MutableCloneableSlice, ImmutableSlice, MutableSlice};
pub type Port = u16;
use collections::MutableSeq;
use io::IoResult;
use iter::Iterator;
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
use result::{Ok,Err};
use io::net::addrinfo::get_host_addresses;
use io::net::ip::SocketAddr;
use io::{IoError, ConnectionFailed, InvalidInput};
use io::{Reader, Writer, Listener, Acceptor};
+use io::{standard_error, TimedOut};
use from_str::FromStr;
use kinds::Send;
use option::{None, Some, Option};
use rt::rtio::{IoFactory, LocalIo, RtioSocket, RtioTcpListener};
use rt::rtio::{RtioTcpAcceptor, RtioTcpStream};
use rt::rtio;
+use time::Duration;
/// A structure which represents a TCP stream between a local socket and a
/// remote socket.
}
/// Creates a TCP connection to a remote socket address, timing out after
- /// the specified number of milliseconds.
+ /// the specified duration.
///
/// This is the same as the `connect` method, except that if the timeout
/// specified (in milliseconds) elapses before a connection is made an error
///
/// Note that the `addr` argument may one day be split into a separate host
/// and port, similar to the API seen in `connect`.
+ ///
+ /// If a `timeout` with zero or negative duration is specified then
+ /// the function returns `Err`, with the error kind set to `TimedOut`.
#[experimental = "the timeout argument may eventually change types"]
pub fn connect_timeout(addr: SocketAddr,
- timeout_ms: u64) -> IoResult<TcpStream> {
+ timeout: Duration) -> IoResult<TcpStream> {
+ if timeout <= Duration::milliseconds(0) {
+ return Err(standard_error(TimedOut));
+ }
+
let SocketAddr { ip, port } = addr;
let addr = rtio::SocketAddr { ip: super::to_rtio(ip), port: port };
LocalIo::maybe_raise(|io| {
- io.tcp_connect(addr, Some(timeout_ms)).map(TcpStream::new)
+ io.tcp_connect(addr, Some(timeout.num_milliseconds() as u64)).map(TcpStream::new)
}).map_err(IoError::from_rtio_error)
}
/// # #![allow(unused_must_use)]
/// use std::io::timer;
/// use std::io::TcpStream;
+ /// use std::time::Duration;
///
/// let mut stream = TcpStream::connect("127.0.0.1", 34254).unwrap();
/// let stream2 = stream.clone();
///
/// spawn(proc() {
/// // close this stream after one second
- /// timer::sleep(1000);
+ /// timer::sleep(Duration::seconds(1));
/// let mut stream = stream2;
/// stream.close_read();
/// });
use c_str::ToCStr;
use clone::Clone;
use io::{Listener, Acceptor, Reader, Writer, IoResult, IoError};
+use io::{standard_error, TimedOut};
use kinds::Send;
use boxed::Box;
use rt::rtio::{IoFactory, LocalIo, RtioUnixListener};
use rt::rtio::{RtioUnixAcceptor, RtioPipe};
+use time::Duration;
/// A stream which communicates over a named pipe.
pub struct UnixStream {
///
/// This function is similar to `connect`, except that if `timeout_ms`
/// elapses the function will return an error of kind `TimedOut`.
+ ///
+ /// If a `timeout` with zero or negative duration is specified then
+ /// the function returns `Err`, with the error kind set to `TimedOut`.
#[experimental = "the timeout argument is likely to change types"]
pub fn connect_timeout<P: ToCStr>(path: &P,
- timeout_ms: u64) -> IoResult<UnixStream> {
+ timeout: Duration) -> IoResult<UnixStream> {
+ if timeout <= Duration::milliseconds(0) {
+ return Err(standard_error(TimedOut));
+ }
+
LocalIo::maybe_raise(|io| {
- let s = io.unix_connect(&path.to_c_str(), Some(timeout_ms));
+ let s = io.unix_connect(&path.to_c_str(), Some(timeout.num_milliseconds() as u64));
s.map(|p| UnixStream { obj: p })
}).map_err(IoError::from_rtio_error)
}
iotest!(fn connect_timeout_error() {
let addr = next_test_unix();
- assert!(UnixStream::connect_timeout(&addr, 100).is_err());
+ assert!(UnixStream::connect_timeout(&addr, Duration::milliseconds(100)).is_err());
})
iotest!(fn connect_timeout_success() {
let addr = next_test_unix();
let _a = UnixListener::bind(&addr).unwrap().listen().unwrap();
- assert!(UnixStream::connect_timeout(&addr, 100).is_ok());
+ assert!(UnixStream::connect_timeout(&addr, Duration::milliseconds(100)).is_ok());
+ })
+
+ iotest!(fn connect_timeout_zero() {
+ let addr = next_test_unix();
+ let _a = UnixListener::bind(&addr).unwrap().listen().unwrap();
+ assert!(UnixStream::connect_timeout(&addr, Duration::milliseconds(0)).is_err());
+ })
+
+ iotest!(fn connect_timeout_negative() {
+ let addr = next_test_unix();
+ let _a = UnixListener::bind(&addr).unwrap().listen().unwrap();
+ assert!(UnixStream::connect_timeout(&addr, Duration::milliseconds(-1)).is_err());
})
iotest!(fn close_readwrite_smoke() {
Ignored,
/// The specified file descriptor is inherited for the stream which it is
- /// specified for.
+ /// specified for. Ownership of the file descriptor is *not* taken, so the
+ /// caller must clean it up.
InheritFd(libc::c_int),
/// Creates a pipe for the specified file descriptor which will be created
#[cfg(test)]
mod tests {
+ extern crate native;
use io::process::{Command, Process};
use prelude::*;
assert!(!p.wait().unwrap().success());
return
}
- timer::sleep(100);
+ timer::sleep(Duration::milliseconds(100));
}
fail!("never saw the child go away");
})
assert!(Process::kill(id, 0).is_ok());
assert!(Process::kill(id, PleaseExitSignal).is_ok());
})
+
+ iotest!(fn dont_close_fd_on_command_spawn() {
+ use std::rt::rtio::{Truncate, Write};
+ use native::io::file;
+
+ let path = if cfg!(windows) {
+ Path::new("NUL")
+ } else {
+ Path::new("/dev/null")
+ };
+
+ let mut fdes = match file::open(&path.to_c_str(), Truncate, Write) {
+ Ok(f) => f,
+ Err(_) => fail!("failed to open file descriptor"),
+ };
+
+ let mut cmd = pwd_cmd();
+ let _ = cmd.stdout(InheritFd(fdes.fd()));
+ assert!(cmd.status().unwrap().success());
+ assert!(fdes.inner_write("extra write\n".as_bytes()).is_ok());
+ })
}
use boxed::Box;
use result::{Ok, Err};
use rt::rtio::{IoFactory, LocalIo, RtioSignal, Callback};
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
use vec::Vec;
/// Signals that can be sent and received
use comm::Empty;
use io::timer;
use super::{Listener, Interrupt};
+ use time::Duration;
fn sigint() {
unsafe {
let mut signal = Listener::new();
signal.register(Interrupt).unwrap();
sigint();
- timer::sleep(10);
+ timer::sleep(Duration::milliseconds(10));
match signal.rx.recv() {
Interrupt => (),
s => fail!("Expected Interrupt, got {:?}", s),
s1.register(Interrupt).unwrap();
s2.register(Interrupt).unwrap();
sigint();
- timer::sleep(10);
+ timer::sleep(Duration::milliseconds(10));
match s1.rx.recv() {
Interrupt => (),
s => fail!("Expected Interrupt, got {:?}", s),
s2.register(Interrupt).unwrap();
s2.unregister(Interrupt);
sigint();
- timer::sleep(10);
+ timer::sleep(Duration::milliseconds(10));
assert_eq!(s2.rx.try_recv(), Err(Empty));
}
}
use rt::local::Local;
use rt::task::Task;
use rt::rtio::{DontClose, IoFactory, LocalIo, RtioFileStream, RtioTTY};
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
use str::StrSlice;
use uint;
use io::process::*;
use rt::running_on_valgrind;
use str;
+ use time::Duration;
fn f() $b
*/
+// FIXME: These functions take Durations but only pass ms to the backend impls.
+
use comm::{Receiver, Sender, channel};
+use time::Duration;
use io::{IoResult, IoError};
use kinds::Send;
use boxed::Box;
/// # fn main() {}
/// # fn foo() {
/// use std::io::Timer;
+/// use std::time::Duration;
///
/// let mut timer = Timer::new().unwrap();
-/// timer.sleep(10); // block the task for awhile
+/// timer.sleep(Duration::milliseconds(10)); // block the task for awhile
///
-/// let timeout = timer.oneshot(10);
+/// let timeout = timer.oneshot(Duration::milliseconds(10));
/// // do some work
/// timeout.recv(); // wait for the timeout to expire
///
-/// let periodic = timer.periodic(10);
+/// let periodic = timer.periodic(Duration::milliseconds(10));
/// loop {
/// periodic.recv();
/// // this loop is only executed once every 10ms
/// # fn main() {}
/// # fn foo() {
/// use std::io::timer;
+/// use std::time::Duration;
///
/// // Put this task to sleep for 5 seconds
-/// timer::sleep(5000);
+/// timer::sleep(Duration::seconds(5));
/// # }
/// ```
pub struct Timer {
struct TimerCallback { tx: Sender<()> }
-/// Sleep the current task for `msecs` milliseconds.
-pub fn sleep(msecs: u64) {
+/// Sleep the current task for the specified duration.
+///
+/// When provided a zero or negative `duration`, the function will
+/// return immediately.
+pub fn sleep(duration: Duration) {
let timer = Timer::new();
let mut timer = timer.ok().expect("timer::sleep: could not create a Timer");
- timer.sleep(msecs)
+ timer.sleep(duration)
}
impl Timer {
}).map_err(IoError::from_rtio_error)
}
- /// Blocks the current task for `msecs` milliseconds.
+ /// Blocks the current task for the specified duration.
///
/// Note that this function will cause any other receivers for this timer to
/// be invalidated (the other end will be closed).
- pub fn sleep(&mut self, msecs: u64) {
- self.obj.sleep(msecs);
+ ///
+ /// When provided a zero or negative `duration`, the function will
+ /// return immediately.
+ pub fn sleep(&mut self, duration: Duration) {
+ // Short-circuit the timer backend for 0 duration
+ let ms = in_ms_u64(duration);
+ if ms == 0 { return }
+ self.obj.sleep(ms);
}
/// Creates a oneshot receiver which will have a notification sent when
- /// `msecs` milliseconds has elapsed.
+ /// the specified duration has elapsed.
///
/// This does *not* block the current task, but instead returns immediately.
///
///
/// ```rust
/// use std::io::Timer;
+ /// use std::time::Duration;
///
/// let mut timer = Timer::new().unwrap();
- /// let ten_milliseconds = timer.oneshot(10);
+ /// let ten_milliseconds = timer.oneshot(Duration::milliseconds(10));
///
/// for _ in range(0u, 100) { /* do work */ }
///
///
/// ```rust
/// use std::io::Timer;
+ /// use std::time::Duration;
///
/// // Incorrect, method chaining-style:
- /// let mut five_ms = Timer::new().unwrap().oneshot(5);
+ /// let mut five_ms = Timer::new().unwrap().oneshot(Duration::milliseconds(5));
/// // The timer object was destroyed, so this will always fail:
/// // five_ms.recv()
/// ```
- pub fn oneshot(&mut self, msecs: u64) -> Receiver<()> {
+ ///
+ /// When provided a zero or negative `duration`, the message will
+ /// be sent immediately.
+ pub fn oneshot(&mut self, duration: Duration) -> Receiver<()> {
let (tx, rx) = channel();
- self.obj.oneshot(msecs, box TimerCallback { tx: tx });
+ // Short-circuit the timer backend for 0 duration
+ if in_ms_u64(duration) != 0 {
+ self.obj.oneshot(in_ms_u64(duration), box TimerCallback { tx: tx });
+ } else {
+ tx.send(());
+ }
return rx
}
/// Creates a receiver which will have a continuous stream of notifications
- /// being sent every `msecs` milliseconds.
+ /// being sent each time the specified duration has elapsed.
///
/// This does *not* block the current task, but instead returns
/// immediately. The first notification will not be received immediately,
- /// but rather after `msec` milliseconds have passed.
+ /// but rather after the first duration.
///
/// Note that this invalidates any previous receiver which has been created
/// by this timer, and that the returned receiver will be invalidated once
///
/// ```rust
/// use std::io::Timer;
+ /// use std::time::Duration;
///
/// let mut timer = Timer::new().unwrap();
- /// let ten_milliseconds = timer.periodic(10);
+ /// let ten_milliseconds = timer.periodic(Duration::milliseconds(10));
///
/// for _ in range(0u, 100) { /* do work */ }
///
///
/// ```rust
/// use std::io::Timer;
+ /// use std::time::Duration;
///
/// // Incorrect, method chaining-style.
- /// let mut five_ms = Timer::new().unwrap().periodic(5);
+ /// let mut five_ms = Timer::new().unwrap().periodic(Duration::milliseconds(5));
/// // The timer object was destroyed, so this will always fail:
/// // five_ms.recv()
/// ```
- pub fn periodic(&mut self, msecs: u64) -> Receiver<()> {
+ ///
+ /// When provided a zero or negative `duration`, the messages will
+ /// be sent without delay.
+ pub fn periodic(&mut self, duration: Duration) -> Receiver<()> {
+ let ms = in_ms_u64(duration);
+ // FIXME: The backend implementations don't ever send a message
+ // if given a 0 ms duration. Temporarily using 1ms. It's
+ // not clear what use a 0ms period is anyway...
+ let ms = if ms == 0 { 1 } else { ms };
let (tx, rx) = channel();
- self.obj.period(msecs, box TimerCallback { tx: tx });
+ self.obj.period(ms, box TimerCallback { tx: tx });
return rx
}
}
}
}
+fn in_ms_u64(d: Duration) -> u64 {
+ let ms = d.num_milliseconds();
+ if ms < 0 { return 0 };
+ return ms as u64;
+}
+
#[cfg(test)]
mod test {
iotest!(fn test_io_timer_sleep_simple() {
let mut timer = Timer::new().unwrap();
- timer.sleep(1);
+ timer.sleep(Duration::milliseconds(1));
})
iotest!(fn test_io_timer_sleep_oneshot() {
let mut timer = Timer::new().unwrap();
- timer.oneshot(1).recv();
+ timer.oneshot(Duration::milliseconds(1)).recv();
})
iotest!(fn test_io_timer_sleep_oneshot_forget() {
let mut timer = Timer::new().unwrap();
- timer.oneshot(100000000000);
+ timer.oneshot(Duration::milliseconds(100000000));
})
iotest!(fn oneshot_twice() {
let mut timer = Timer::new().unwrap();
- let rx1 = timer.oneshot(10000);
- let rx = timer.oneshot(1);
+ let rx1 = timer.oneshot(Duration::milliseconds(10000));
+ let rx = timer.oneshot(Duration::milliseconds(1));
rx.recv();
assert_eq!(rx1.recv_opt(), Err(()));
})
iotest!(fn test_io_timer_oneshot_then_sleep() {
let mut timer = Timer::new().unwrap();
- let rx = timer.oneshot(100000000000);
- timer.sleep(1); // this should invalidate rx
+ let rx = timer.oneshot(Duration::milliseconds(100000000));
+ timer.sleep(Duration::milliseconds(1)); // this should invalidate rx
assert_eq!(rx.recv_opt(), Err(()));
})
iotest!(fn test_io_timer_sleep_periodic() {
let mut timer = Timer::new().unwrap();
- let rx = timer.periodic(1);
+ let rx = timer.periodic(Duration::milliseconds(1));
rx.recv();
rx.recv();
rx.recv();
iotest!(fn test_io_timer_sleep_periodic_forget() {
let mut timer = Timer::new().unwrap();
- timer.periodic(100000000000);
+ timer.periodic(Duration::milliseconds(100000000));
})
iotest!(fn test_io_timer_sleep_standalone() {
- sleep(1)
+ sleep(Duration::milliseconds(1))
})
iotest!(fn oneshot() {
let mut timer = Timer::new().unwrap();
- let rx = timer.oneshot(1);
+ let rx = timer.oneshot(Duration::milliseconds(1));
rx.recv();
assert!(rx.recv_opt().is_err());
- let rx = timer.oneshot(1);
+ let rx = timer.oneshot(Duration::milliseconds(1));
rx.recv();
assert!(rx.recv_opt().is_err());
})
iotest!(fn override() {
let mut timer = Timer::new().unwrap();
- let orx = timer.oneshot(100);
- let prx = timer.periodic(100);
- timer.sleep(1);
+ let orx = timer.oneshot(Duration::milliseconds(100));
+ let prx = timer.periodic(Duration::milliseconds(100));
+ timer.sleep(Duration::milliseconds(1));
assert_eq!(orx.recv_opt(), Err(()));
assert_eq!(prx.recv_opt(), Err(()));
- timer.oneshot(1).recv();
+ timer.oneshot(Duration::milliseconds(1)).recv();
})
iotest!(fn period() {
let mut timer = Timer::new().unwrap();
- let rx = timer.periodic(1);
+ let rx = timer.periodic(Duration::milliseconds(1));
rx.recv();
rx.recv();
- let rx2 = timer.periodic(1);
+ let rx2 = timer.periodic(Duration::milliseconds(1));
rx2.recv();
rx2.recv();
})
iotest!(fn sleep() {
let mut timer = Timer::new().unwrap();
- timer.sleep(1);
- timer.sleep(1);
+ timer.sleep(Duration::milliseconds(1));
+ timer.sleep(Duration::milliseconds(1));
})
iotest!(fn oneshot_fail() {
let mut timer = Timer::new().unwrap();
- let _rx = timer.oneshot(1);
+ let _rx = timer.oneshot(Duration::milliseconds(1));
fail!();
} #[should_fail])
iotest!(fn period_fail() {
let mut timer = Timer::new().unwrap();
- let _rx = timer.periodic(1);
+ let _rx = timer.periodic(Duration::milliseconds(1));
fail!();
} #[should_fail])
iotest!(fn closing_channel_during_drop_doesnt_kill_everything() {
// see issue #10375
let mut timer = Timer::new().unwrap();
- let timer_rx = timer.periodic(1000);
+ let timer_rx = timer.periodic(Duration::milliseconds(1000));
spawn(proc() {
let _ = timer_rx.recv_opt();
iotest!(fn reset_doesnt_switch_tasks() {
// similar test to the one above.
let mut timer = Timer::new().unwrap();
- let timer_rx = timer.periodic(1000);
+ let timer_rx = timer.periodic(Duration::milliseconds(1000));
spawn(proc() {
let _ = timer_rx.recv_opt();
});
- timer.oneshot(1);
+ timer.oneshot(Duration::milliseconds(1));
})
iotest!(fn reset_doesnt_switch_tasks2() {
// similar test to the one above.
let mut timer = Timer::new().unwrap();
- let timer_rx = timer.periodic(1000);
+ let timer_rx = timer.periodic(Duration::milliseconds(1000));
spawn(proc() {
let _ = timer_rx.recv_opt();
});
- timer.sleep(1);
+ timer.sleep(Duration::milliseconds(1));
})
iotest!(fn sender_goes_away_oneshot() {
let rx = {
let mut timer = Timer::new().unwrap();
- timer.oneshot(1000)
+ timer.oneshot(Duration::milliseconds(1000))
};
assert_eq!(rx.recv_opt(), Err(()));
})
iotest!(fn sender_goes_away_period() {
let rx = {
let mut timer = Timer::new().unwrap();
- timer.periodic(1000)
+ timer.periodic(Duration::milliseconds(1000))
};
assert_eq!(rx.recv_opt(), Err(()));
})
iotest!(fn receiver_goes_away_oneshot() {
let mut timer1 = Timer::new().unwrap();
- timer1.oneshot(1);
+ timer1.oneshot(Duration::milliseconds(1));
let mut timer2 = Timer::new().unwrap();
// while sleeping, the previous timer should fire and not have its
// callback do something terrible.
- timer2.sleep(2);
+ timer2.sleep(Duration::milliseconds(2));
})
iotest!(fn receiver_goes_away_period() {
let mut timer1 = Timer::new().unwrap();
- timer1.periodic(1);
+ timer1.periodic(Duration::milliseconds(1));
let mut timer2 = Timer::new().unwrap();
// while sleeping, the previous timer should fire and not have its
// callback do something terrible.
- timer2.sleep(2);
+ timer2.sleep(Duration::milliseconds(2));
+ })
+
+ iotest!(fn sleep_zero() {
+ let mut timer = Timer::new().unwrap();
+ timer.sleep(Duration::milliseconds(0));
+ })
+
+ iotest!(fn sleep_negative() {
+ let mut timer = Timer::new().unwrap();
+ timer.sleep(Duration::milliseconds(-1000000));
+ })
+
+ iotest!(fn oneshot_zero() {
+ let mut timer = Timer::new().unwrap();
+ let rx = timer.oneshot(Duration::milliseconds(0));
+ rx.recv();
+ })
+
+ iotest!(fn oneshot_negative() {
+ let mut timer = Timer::new().unwrap();
+ let rx = timer.oneshot(Duration::milliseconds(-1000000));
+ rx.recv();
+ })
+
+ iotest!(fn periodic_zero() {
+ let mut timer = Timer::new().unwrap();
+ let rx = timer.periodic(Duration::milliseconds(0));
+ rx.recv();
+ rx.recv();
+ rx.recv();
+ rx.recv();
})
+
+ iotest!(fn periodic_negative() {
+ let mut timer = Timer::new().unwrap();
+ let rx = timer.periodic(Duration::milliseconds(-1000000));
+ rx.recv();
+ rx.recv();
+ rx.recv();
+ rx.recv();
+ })
+
}
#[cfg(not(test))]
pub mod gc;
+pub mod time;
+
/* Common traits */
pub mod from_str;
use num::{ToStrRadix, FromStrRadix};
use num::strconv;
use option::Option;
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
use string::String;
pub use core::i16::{BITS, BYTES, MIN, MAX};
use num::{ToStrRadix, FromStrRadix};
use num::strconv;
use option::Option;
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
use string::String;
pub use core::i32::{BITS, BYTES, MIN, MAX};
use num::{ToStrRadix, FromStrRadix};
use num::strconv;
use option::Option;
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
use string::String;
pub use core::i64::{BITS, BYTES, MIN, MAX};
use num::{ToStrRadix, FromStrRadix};
use num::strconv;
use option::Option;
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
use string::String;
pub use core::i8::{BITS, BYTES, MIN, MAX};
use num::{ToStrRadix, FromStrRadix};
use num::strconv;
use option::Option;
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
use string::String;
pub use core::int::{BITS, BYTES, MIN, MAX};
use num;
use ops::{Add, Sub, Mul, Div, Rem, Neg};
use option::{None, Option, Some};
-use slice::{ImmutableVector, MutableVector};
+use slice::{ImmutableSlice, MutableSlice};
use std::cmp::{PartialOrd, PartialEq};
use str::StrSlice;
use string::String;
use num::{ToStrRadix, FromStrRadix};
use num::strconv;
use option::Option;
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
use string::String;
pub use core::u16::{BITS, BYTES, MIN, MAX};
use num::{ToStrRadix, FromStrRadix};
use num::strconv;
use option::Option;
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
use string::String;
pub use core::u32::{BITS, BYTES, MIN, MAX};
use num::{ToStrRadix, FromStrRadix};
use num::strconv;
use option::Option;
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
use string::String;
pub use core::u64::{BITS, BYTES, MIN, MAX};
use num::{ToStrRadix, FromStrRadix};
use num::strconv;
use option::Option;
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
use string::String;
pub use core::u8::{BITS, BYTES, MIN, MAX};
use num::{ToStrRadix, FromStrRadix};
use num::strconv;
use option::Option;
-use slice::ImmutableVector;
+use slice::ImmutableSlice;
use string::String;
pub use core::uint::{BITS, BYTES, MIN, MAX};
use ptr::RawPtr;
use ptr;
use result::{Err, Ok, Result};
-use slice::{Vector, ImmutableVector, MutableVector, ImmutableEqVector};
+use slice::{Slice, ImmutableSlice, MutableSlice, ImmutablePartialEqSlice};
use str::{Str, StrSlice, StrAllocating};
use string::String;
use sync::atomic::{AtomicInt, INIT_ATOMIC_INT, SeqCst};
use option::{None, Option};
use option;
use os::TMPBUF_SZ;
- use slice::{MutableVector, ImmutableVector};
+ use slice::{MutableSlice, ImmutableSlice};
use string::String;
use str::StrSlice;
use vec::Vec;
pub static EXE_EXTENSION: &'static str = "";
}
-#[cfg(target_os = "win32")]
+#[cfg(target_os = "windows")]
+#[cfg(stage0, target_os = "win32")] // NOTE: Remove after snapshot
pub mod consts {
pub use os::arch_consts::ARCH;
/// A string describing the specific operating system in use: in this
/// case, `win32`.
- pub static SYSNAME: &'static str = "win32";
+ pub static SYSNAME: &'static str = "windows";
/// Specifies the filename prefix used for shared libraries on this
/// platform: in this case, the empty string.
use str;
use str::{MaybeOwned, Str, StrSlice};
use string::String;
-use slice::Vector;
-use slice::{ImmutableEqVector, ImmutableVector};
+use slice::Slice;
+use slice::{ImmutablePartialEqSlice, ImmutableSlice};
use vec::Vec;
/// Typedef for POSIX file paths.
use option::{Option, None, Some};
use str::Str;
use str;
-use slice::{CloneableVector, Splits, Vector, VectorVector,
- ImmutableEqVector, ImmutableVector};
+use slice::{CloneableVector, Splits, Slice, VectorVector,
+ ImmutablePartialEqSlice, ImmutableSlice};
use vec::Vec;
use super::{BytesContainer, GenericPath, GenericPathUnsafe};
/// Returns a normalized byte vector representation of a path, by removing all empty
/// components, and unnecessary . and .. components.
- fn normalize<V: Vector<u8>+CloneableVector<u8>>(v: V) -> Vec<u8> {
+ fn normalize<V: Slice<u8>+CloneableVector<u8>>(v: V) -> Vec<u8> {
// borrowck is being very picky
let val = {
let is_abs = !v.as_slice().is_empty() && v.as_slice()[0] == SEP_BYTE;
use iter::{AdditiveIterator, DoubleEndedIterator, Extendable, Iterator, Map};
use mem;
use option::{Option, Some, None};
-use slice::{Vector, ImmutableVector};
+use slice::{Slice, ImmutableSlice};
use str::{CharSplits, Str, StrAllocating, StrVector, StrSlice};
use string::String;
use unicode::char::UnicodeChar;
#[doc(no_inline)] pub use tuple::{Tuple5, Tuple6, Tuple7, Tuple8};
#[doc(no_inline)] pub use tuple::{Tuple9, Tuple10, Tuple11, Tuple12};
#[doc(no_inline)] pub use slice::{CloneableVector, ImmutableCloneableVector};
-#[doc(no_inline)] pub use slice::{MutableCloneableVector, MutableOrdVector};
-#[doc(no_inline)] pub use slice::{ImmutableVector, MutableVector};
-#[doc(no_inline)] pub use slice::{ImmutableEqVector, ImmutableOrdVector};
-#[doc(no_inline)] pub use slice::{Vector, VectorVector};
-#[doc(no_inline)] pub use slice::MutableVectorAllocating;
+#[doc(no_inline)] pub use slice::{MutableCloneableSlice, MutableOrdSlice};
+#[doc(no_inline)] pub use slice::{ImmutableSlice, MutableSlice};
+#[doc(no_inline)] pub use slice::{ImmutablePartialEqSlice, ImmutableOrdSlice};
+#[doc(no_inline)] pub use slice::{Slice, VectorVector};
+#[doc(no_inline)] pub use slice::MutableSliceAllocating;
#[doc(no_inline)] pub use string::String;
#[doc(no_inline)] pub use vec::Vec;
use rand::Rng;
use result::{Ok};
use self::libc::{c_int, size_t};
- use slice::MutableVector;
+ use slice::MutableSlice;
/// A random number generator that retrieves randomness straight from
/// the operating system. Platform sources:
use rt::stack;
use self::libc::{DWORD, BYTE, LPCSTR, BOOL};
use self::libc::types::os::arch::extra::{LONG_PTR};
- use slice::MutableVector;
+ use slice::MutableSlice;
type HCRYPTPROV = LONG_PTR;
pub fn write(w: &mut Writer) -> IoResult<()> {
use iter::{Iterator, range};
use result;
- use slice::{MutableVector};
+ use slice::{MutableSlice};
extern {
fn backtrace(buf: *mut *mut libc::c_void,
use path::GenericPath;
use ptr::RawPtr;
use ptr;
- use slice::{ImmutableVector, MutableVector};
+ use slice::{ImmutableSlice, MutableSlice};
////////////////////////////////////////////////////////////////////////
// libbacktrace.h API
use path::Path;
use result::{Ok, Err};
use rt::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
- use slice::ImmutableVector;
+ use slice::ImmutableSlice;
use str::StrSlice;
use dynamic_lib::DynamicLibrary;
#[test]
fn task_abort_no_kill_runtime() {
use std::io::timer;
+ use time::Duration;
use mem;
let tb = TaskBuilder::new();
let rx = tb.try_future(proc() {});
mem::drop(rx);
- timer::sleep(1000);
+ timer::sleep(Duration::milliseconds(1000));
}
--- /dev/null
+// Copyright 2012-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.
+
+//! Temporal quantification
+
+#![experimental]
+
+use {fmt, i32};
+use ops::{Add, Sub, Mul, Div, Neg};
+use option::{Option, Some, None};
+use num;
+use num::{CheckedAdd, CheckedMul};
+use result::{Result, Ok, Err};
+
+
+/// `Duration`'s `days` component should have no more than this value.
+static MIN_DAYS: i32 = i32::MIN;
+/// `Duration`'s `days` component should have no less than this value.
+static MAX_DAYS: i32 = i32::MAX;
+
+/// The number of nanoseconds in seconds.
+static NANOS_PER_SEC: i32 = 1_000_000_000;
+/// The number of (non-leap) seconds in days.
+static SECS_PER_DAY: i32 = 86400;
+
+macro_rules! try_opt(
+ ($e:expr) => (match $e { Some(v) => v, None => return None })
+)
+
+
+// FIXME #16466: This could be represented as (i64 seconds, u32 nanos)
+/// ISO 8601 time duration with nanosecond precision.
+/// This also allows for the negative duration; see individual methods for details.
+#[deriving(PartialEq, Eq, PartialOrd, Ord)]
+pub struct Duration {
+ days: i32,
+ secs: u32, // Always < SECS_PER_DAY
+ nanos: u32, // Always < NANOS_PR_SECOND
+}
+
+/// The minimum possible `Duration`.
+pub static MIN: Duration = Duration { days: MIN_DAYS, secs: 0, nanos: 0 };
+/// The maximum possible `Duration`.
+pub static MAX: Duration = Duration { days: MAX_DAYS, secs: SECS_PER_DAY as u32 - 1,
+ nanos: NANOS_PER_SEC as u32 - 1 };
+
+impl Duration {
+ /// Makes a new `Duration` with given number of weeks.
+ /// Equivalent to `Duration::new(weeks * 7, 0, 0)` with overflow checks.
+ ///
+ /// Fails when the duration is out of bounds.
+ #[inline]
+ pub fn weeks(weeks: i32) -> Duration {
+ let days = weeks.checked_mul(&7).expect("Duration::weeks out of bounds");
+ Duration::days(days)
+ }
+
+ /// Makes a new `Duration` with given number of days.
+ /// Equivalent to `Duration::new(days, 0, 0)`.
+ #[inline]
+ pub fn days(days: i32) -> Duration {
+ Duration { days: days, secs: 0, nanos: 0 }
+ }
+
+ /// Makes a new `Duration` with given number of hours.
+ /// Equivalent to `Duration::new(0, hours * 3600, 0)` with overflow checks.
+ #[inline]
+ pub fn hours(hours: i32) -> Duration {
+ let (days, hours) = div_mod_floor(hours, (SECS_PER_DAY / 3600));
+ let secs = hours * 3600;
+ Duration { secs: secs as u32, ..Duration::days(days) }
+ }
+
+ /// Makes a new `Duration` with given number of minutes.
+ /// Equivalent to `Duration::new(0, mins * 60, 0)` with overflow checks.
+ #[inline]
+ pub fn minutes(mins: i32) -> Duration {
+ let (days, mins) = div_mod_floor(mins, (SECS_PER_DAY / 60));
+ let secs = mins * 60;
+ Duration { secs: secs as u32, ..Duration::days(days) }
+ }
+
+ /// Makes a new `Duration` with given number of seconds.
+ /// Equivalent to `Duration::new(0, secs, 0)`.
+ #[inline]
+ pub fn seconds(secs: i32) -> Duration {
+ let (days, secs) = div_mod_floor(secs, SECS_PER_DAY);
+ Duration { secs: secs as u32, ..Duration::days(days) }
+ }
+
+ /// Makes a new `Duration` with given number of milliseconds.
+ /// Equivalent to `Duration::new(0, 0, millis * 1_000_000)` with overflow checks.
+ #[inline]
+ pub fn milliseconds(millis: i32) -> Duration {
+ let (secs, millis) = div_mod_floor(millis, (NANOS_PER_SEC / 1_000_000));
+ let nanos = millis * 1_000_000;
+ Duration { nanos: nanos as u32, ..Duration::seconds(secs) }
+ }
+
+ /// Makes a new `Duration` with given number of microseconds.
+ /// Equivalent to `Duration::new(0, 0, micros * 1_000)` with overflow checks.
+ #[inline]
+ pub fn microseconds(micros: i32) -> Duration {
+ let (secs, micros) = div_mod_floor(micros, (NANOS_PER_SEC / 1_000));
+ let nanos = micros * 1_000;
+ Duration { nanos: nanos as u32, ..Duration::seconds(secs) }
+ }
+
+ /// Makes a new `Duration` with given number of nanoseconds.
+ /// Equivalent to `Duration::new(0, 0, nanos)`.
+ #[inline]
+ pub fn nanoseconds(nanos: i32) -> Duration {
+ let (secs, nanos) = div_mod_floor(nanos, NANOS_PER_SEC);
+ Duration { nanos: nanos as u32, ..Duration::seconds(secs) }
+ }
+
+ /// Returns a tuple of the number of days, (non-leap) seconds and
+ /// nanoseconds in the duration. Note that the number of seconds
+ /// and nanoseconds are always positive, so that for example
+ /// `-Duration::seconds(3)` has -1 days and 86,397 seconds.
+ #[inline]
+ fn to_tuple_64(&self) -> (i64, u32, u32) {
+ (self.days as i64, self.secs, self.nanos)
+ }
+
+ /// Negates the duration and returns a tuple like `to_tuple`.
+ /// This does not overflow and thus is internally used for several methods.
+ fn to_negated_tuple_64(&self) -> (i64, u32, u32) {
+ let mut days = -(self.days as i64);
+ let mut secs = -(self.secs as i32);
+ let mut nanos = -(self.nanos as i32);
+ if nanos < 0 {
+ nanos += NANOS_PER_SEC;
+ secs -= 1;
+ }
+ if secs < 0 {
+ secs += SECS_PER_DAY;
+ days -= 1;
+ }
+ (days, secs as u32, nanos as u32)
+ }
+
+ /// Returns the total number of whole weeks in the duration.
+ #[inline]
+ pub fn num_weeks(&self) -> i32 {
+ self.num_days() / 7
+ }
+
+ /// Returns the total number of whole days in the duration.
+ pub fn num_days(&self) -> i32 {
+ if self.days < 0 {
+ let negated = -*self;
+ -negated.days
+ } else {
+ self.days
+ }
+ }
+
+ /// Returns the total number of whole hours in the duration.
+ #[inline]
+ pub fn num_hours(&self) -> i64 {
+ self.num_seconds() / 3600
+ }
+
+ /// Returns the total number of whole minutes in the duration.
+ #[inline]
+ pub fn num_minutes(&self) -> i64 {
+ self.num_seconds() / 60
+ }
+
+ /// Returns the total number of whole seconds in the duration.
+ pub fn num_seconds(&self) -> i64 {
+ // cannot overflow, 2^32 * 86400 < 2^64
+ fn secs((days, secs, _): (i64, u32, u32)) -> i64 {
+ days as i64 * SECS_PER_DAY as i64 + secs as i64
+ }
+ if self.days < 0 {-secs(self.to_negated_tuple_64())} else {secs(self.to_tuple_64())}
+ }
+
+ /// Returns the total number of whole milliseconds in the duration.
+ pub fn num_milliseconds(&self) -> i64 {
+ // cannot overflow, 2^32 * 86400 * 1000 < 2^64
+ fn millis((days, secs, nanos): (i64, u32, u32)) -> i64 {
+ static MILLIS_PER_SEC: i64 = 1_000;
+ static NANOS_PER_MILLI: i64 = 1_000_000;
+ (days as i64 * MILLIS_PER_SEC * SECS_PER_DAY as i64 +
+ secs as i64 * MILLIS_PER_SEC +
+ nanos as i64 / NANOS_PER_MILLI)
+ }
+ if self.days < 0 {-millis(self.to_negated_tuple_64())} else {millis(self.to_tuple_64())}
+ }
+
+ /// Returns the total number of whole microseconds in the duration,
+ /// or `None` on the overflow (exceeding 2^63 microseconds in either directions).
+ pub fn num_microseconds(&self) -> Option<i64> {
+ fn micros((days, secs, nanos): (i64, u32, u32)) -> Option<i64> {
+ static MICROS_PER_SEC: i64 = 1_000_000;
+ static MICROS_PER_DAY: i64 = MICROS_PER_SEC * SECS_PER_DAY as i64;
+ static NANOS_PER_MICRO: i64 = 1_000;
+ let nmicros = try_opt!((days as i64).checked_mul(&MICROS_PER_DAY));
+ let nmicros = try_opt!(nmicros.checked_add(&(secs as i64 * MICROS_PER_SEC)));
+ let nmicros = try_opt!(nmicros.checked_add(&(nanos as i64 / NANOS_PER_MICRO as i64)));
+ Some(nmicros)
+ }
+ if self.days < 0 {
+ // the final negation won't overflow since we start with positive numbers.
+ micros(self.to_negated_tuple_64()).map(|micros| -micros)
+ } else {
+ micros(self.to_tuple_64())
+ }
+ }
+
+ /// Returns the total number of whole nanoseconds in the duration,
+ /// or `None` on the overflow (exceeding 2^63 nanoseconds in either directions).
+ pub fn num_nanoseconds(&self) -> Option<i64> {
+ fn nanos((days, secs, nanos): (i64, u32, u32)) -> Option<i64> {
+ static NANOS_PER_DAY: i64 = NANOS_PER_SEC as i64 * SECS_PER_DAY as i64;
+ let nnanos = try_opt!((days as i64).checked_mul(&NANOS_PER_DAY));
+ let nnanos = try_opt!(nnanos.checked_add(&(secs as i64 * NANOS_PER_SEC as i64)));
+ let nnanos = try_opt!(nnanos.checked_add(&(nanos as i64)));
+ Some(nnanos)
+ }
+ if self.days < 0 {
+ // the final negation won't overflow since we start with positive numbers.
+ nanos(self.to_negated_tuple_64()).map(|micros| -micros)
+ } else {
+ nanos(self.to_tuple_64())
+ }
+ }
+}
+
+impl num::Bounded for Duration {
+ #[inline] fn min_value() -> Duration { MIN }
+ #[inline] fn max_value() -> Duration { MAX }
+}
+
+impl num::Zero for Duration {
+ #[inline]
+ fn zero() -> Duration {
+ Duration { days: 0, secs: 0, nanos: 0 }
+ }
+
+ #[inline]
+ fn is_zero(&self) -> bool {
+ self.days == 0 && self.secs == 0 && self.nanos == 0
+ }
+}
+
+impl Neg<Duration> for Duration {
+ #[inline]
+ fn neg(&self) -> Duration {
+ let (days, secs, nanos) = self.to_negated_tuple_64();
+ Duration { days: days as i32, secs: secs, nanos: nanos } // FIXME can overflow
+ }
+}
+
+impl Add<Duration,Duration> for Duration {
+ fn add(&self, rhs: &Duration) -> Duration {
+ let mut days = self.days + rhs.days;
+ let mut secs = self.secs + rhs.secs;
+ let mut nanos = self.nanos + rhs.nanos;
+ if nanos >= NANOS_PER_SEC as u32 {
+ nanos -= NANOS_PER_SEC as u32;
+ secs += 1;
+ }
+ if secs >= SECS_PER_DAY as u32 {
+ secs -= SECS_PER_DAY as u32;
+ days += 1;
+ }
+ Duration { days: days, secs: secs, nanos: nanos }
+ }
+}
+
+impl num::CheckedAdd for Duration {
+ fn checked_add(&self, rhs: &Duration) -> Option<Duration> {
+ let mut days = try_opt!(self.days.checked_add(&rhs.days));
+ let mut secs = self.secs + rhs.secs;
+ let mut nanos = self.nanos + rhs.nanos;
+ if nanos >= NANOS_PER_SEC as u32 {
+ nanos -= NANOS_PER_SEC as u32;
+ secs += 1;
+ }
+ if secs >= SECS_PER_DAY as u32 {
+ secs -= SECS_PER_DAY as u32;
+ days = try_opt!(days.checked_add(&1));
+ }
+ Some(Duration { days: days, secs: secs, nanos: nanos })
+ }
+}
+
+impl Sub<Duration,Duration> for Duration {
+ fn sub(&self, rhs: &Duration) -> Duration {
+ let mut days = self.days - rhs.days;
+ let mut secs = self.secs as i32 - rhs.secs as i32;
+ let mut nanos = self.nanos as i32 - rhs.nanos as i32;
+ if nanos < 0 {
+ nanos += NANOS_PER_SEC;
+ secs -= 1;
+ }
+ if secs < 0 {
+ secs += SECS_PER_DAY;
+ days -= 1;
+ }
+ Duration { days: days, secs: secs as u32, nanos: nanos as u32 }
+ }
+}
+
+impl num::CheckedSub for Duration {
+ fn checked_sub(&self, rhs: &Duration) -> Option<Duration> {
+ let mut days = try_opt!(self.days.checked_sub(&rhs.days));
+ let mut secs = self.secs as i32 - rhs.secs as i32;
+ let mut nanos = self.nanos as i32 - rhs.nanos as i32;
+ if nanos < 0 {
+ nanos += NANOS_PER_SEC;
+ secs -= 1;
+ }
+ if secs < 0 {
+ secs += SECS_PER_DAY;
+ days = try_opt!(days.checked_sub(&1));
+ }
+ Some(Duration { days: days, secs: secs as u32, nanos: nanos as u32 })
+ }
+}
+
+impl Mul<i32,Duration> for Duration {
+ fn mul(&self, rhs: &i32) -> Duration {
+ /// Given `0 <= y < limit <= 2^30`,
+ /// returns `(h,l)` such that `x * y = h * limit + l` where `0 <= l < limit`.
+ fn mul_i64_u32_limit(x: i64, y: u32, limit: u32) -> (i64,u32) {
+ let y = y as i64;
+ let limit = limit as i64;
+ let (xh, xl) = div_mod_floor_64(x, limit);
+ let (h, l) = (xh * y, xl * y);
+ let (h_, l) = div_rem_64(l, limit);
+ (h + h_, l as u32)
+ }
+
+ let rhs = *rhs as i64;
+ let (secs1, nanos) = mul_i64_u32_limit(rhs, self.nanos, NANOS_PER_SEC as u32);
+ let (days1, secs1) = div_mod_floor_64(secs1, (SECS_PER_DAY as i64));
+ let (days2, secs2) = mul_i64_u32_limit(rhs, self.secs, SECS_PER_DAY as u32);
+ let mut days = self.days as i64 * rhs + days1 + days2;
+ let mut secs = secs1 as u32 + secs2;
+ if secs >= SECS_PER_DAY as u32 {
+ secs -= 1;
+ days += 1;
+ }
+ Duration { days: days as i32, secs: secs, nanos: nanos }
+ }
+}
+
+impl Div<i32,Duration> for Duration {
+ fn div(&self, rhs: &i32) -> Duration {
+ let (rhs, days, secs, nanos) = if *rhs < 0 {
+ let (days, secs, nanos) = self.to_negated_tuple_64();
+ (-(*rhs as i64), days, secs as i64, nanos as i64)
+ } else {
+ (*rhs as i64, self.days as i64, self.secs as i64, self.nanos as i64)
+ };
+
+ let (days, carry) = div_mod_floor_64(days, rhs);
+ let secs = secs + carry * SECS_PER_DAY as i64;
+ let (secs, carry) = div_mod_floor_64(secs, rhs);
+ let nanos = nanos + carry * NANOS_PER_SEC as i64;
+ let nanos = nanos / rhs;
+ Duration { days: days as i32, secs: secs as u32, nanos: nanos as u32 }
+ }
+}
+
+impl fmt::Show for Duration {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let hasdate = self.days != 0;
+ let hastime = (self.secs != 0 || self.nanos != 0) || !hasdate;
+
+ try!(write!(f, "P"));
+ if hasdate {
+ // technically speaking the negative part is not the valid ISO 8601,
+ // but we need to print it anyway.
+ try!(write!(f, "{}D", self.days));
+ }
+ if hastime {
+ if self.nanos == 0 {
+ try!(write!(f, "T{}S", self.secs));
+ } else if self.nanos % 1_000_000 == 0 {
+ try!(write!(f, "T{}.{:03}S", self.secs, self.nanos / 1_000_000));
+ } else if self.nanos % 1_000 == 0 {
+ try!(write!(f, "T{}.{:06}S", self.secs, self.nanos / 1_000));
+ } else {
+ try!(write!(f, "T{}.{:09}S", self.secs, self.nanos));
+ }
+ }
+ Ok(())
+ }
+}
+
+// Copied from libnum
+#[inline]
+fn div_mod_floor(this: i32, other: i32) -> (i32, i32) {
+ (div_floor(this, other), mod_floor(this, other))
+}
+
+#[inline]
+fn div_floor(this: i32, other: i32) -> i32 {
+ match div_rem(this, other) {
+ (d, r) if (r > 0 && other < 0)
+ || (r < 0 && other > 0) => d - 1,
+ (d, _) => d,
+ }
+}
+
+#[inline]
+fn mod_floor(this: i32, other: i32) -> i32 {
+ match this % other {
+ r if (r > 0 && other < 0)
+ || (r < 0 && other > 0) => r + other,
+ r => r,
+ }
+}
+
+#[inline]
+fn div_rem(this: i32, other: i32) -> (i32, i32) {
+ (this / other, this % other)
+}
+
+#[inline]
+fn div_mod_floor_64(this: i64, other: i64) -> (i64, i64) {
+ (div_floor_64(this, other), mod_floor_64(this, other))
+}
+
+#[inline]
+fn div_floor_64(this: i64, other: i64) -> i64 {
+ match div_rem_64(this, other) {
+ (d, r) if (r > 0 && other < 0)
+ || (r < 0 && other > 0) => d - 1,
+ (d, _) => d,
+ }
+}
+
+#[inline]
+fn mod_floor_64(this: i64, other: i64) -> i64 {
+ match this % other {
+ r if (r > 0 && other < 0)
+ || (r < 0 && other > 0) => r + other,
+ r => r,
+ }
+}
+
+#[inline]
+fn div_rem_64(this: i64, other: i64) -> (i64, i64) {
+ (this / other, this % other)
+}
+
+#[cfg(test)]
+mod tests {
+ use super::{Duration, MIN_DAYS, MAX_DAYS, MIN, MAX};
+ use {i32, i64};
+ use num::{Zero, CheckedAdd, CheckedSub};
+ use option::{Some, None};
+ use to_string::ToString;
+
+ #[test]
+ fn test_duration() {
+ let d: Duration = Zero::zero();
+ assert_eq!(d, Zero::zero());
+ assert!(Duration::seconds(1) != Zero::zero());
+ assert_eq!(Duration::seconds(1) + Duration::seconds(2), Duration::seconds(3));
+ assert_eq!(Duration::seconds(86399) + Duration::seconds(4),
+ Duration::days(1) + Duration::seconds(3));
+ assert_eq!(Duration::days(10) - Duration::seconds(1000), Duration::seconds(863000));
+ assert_eq!(Duration::days(10) - Duration::seconds(1000000), Duration::seconds(-136000));
+ assert_eq!(Duration::days(2) + Duration::seconds(86399) + Duration::nanoseconds(1234567890),
+ Duration::days(3) + Duration::nanoseconds(234567890));
+ assert_eq!(-Duration::days(3), Duration::days(-3));
+ assert_eq!(-(Duration::days(3) + Duration::seconds(70)),
+ Duration::days(-4) + Duration::seconds(86400-70));
+ }
+
+ #[test]
+ fn test_duration_num_days() {
+ let d: Duration = Zero::zero();
+ assert_eq!(d.num_days(), 0);
+ assert_eq!(Duration::days(1).num_days(), 1);
+ assert_eq!(Duration::days(-1).num_days(), -1);
+ assert_eq!(Duration::seconds(86399).num_days(), 0);
+ assert_eq!(Duration::seconds(86401).num_days(), 1);
+ assert_eq!(Duration::seconds(-86399).num_days(), 0);
+ assert_eq!(Duration::seconds(-86401).num_days(), -1);
+ assert_eq!(Duration::days(i32::MAX).num_days(), i32::MAX);
+ assert_eq!(Duration::days(i32::MIN).num_days(), i32::MIN);
+ assert_eq!(MAX.num_days(), MAX_DAYS);
+ assert_eq!(MIN.num_days(), MIN_DAYS);
+ }
+
+ #[test]
+ fn test_duration_num_seconds() {
+ let d: Duration = Zero::zero();
+ assert_eq!(d.num_seconds(), 0);
+ assert_eq!(Duration::seconds(1).num_seconds(), 1);
+ assert_eq!(Duration::seconds(-1).num_seconds(), -1);
+ assert_eq!(Duration::milliseconds(999).num_seconds(), 0);
+ assert_eq!(Duration::milliseconds(1001).num_seconds(), 1);
+ assert_eq!(Duration::milliseconds(-999).num_seconds(), 0);
+ assert_eq!(Duration::milliseconds(-1001).num_seconds(), -1);
+ assert_eq!(Duration::seconds(i32::MAX).num_seconds(), i32::MAX as i64);
+ assert_eq!(Duration::seconds(i32::MIN).num_seconds(), i32::MIN as i64);
+ assert_eq!(MAX.num_seconds(), (MAX_DAYS as i64 + 1) * 86400 - 1);
+ assert_eq!(MIN.num_seconds(), MIN_DAYS as i64 * 86400);
+ }
+
+ #[test]
+ fn test_duration_num_milliseconds() {
+ let d: Duration = Zero::zero();
+ assert_eq!(d.num_milliseconds(), 0);
+ assert_eq!(Duration::milliseconds(1).num_milliseconds(), 1);
+ assert_eq!(Duration::milliseconds(-1).num_milliseconds(), -1);
+ assert_eq!(Duration::microseconds(999).num_milliseconds(), 0);
+ assert_eq!(Duration::microseconds(1001).num_milliseconds(), 1);
+ assert_eq!(Duration::microseconds(-999).num_milliseconds(), 0);
+ assert_eq!(Duration::microseconds(-1001).num_milliseconds(), -1);
+ assert_eq!(Duration::milliseconds(i32::MAX).num_milliseconds(), i32::MAX as i64);
+ assert_eq!(Duration::milliseconds(i32::MIN).num_milliseconds(), i32::MIN as i64);
+ assert_eq!(MAX.num_milliseconds(), (MAX_DAYS as i64 + 1) * 86400_000 - 1);
+ assert_eq!(MIN.num_milliseconds(), MIN_DAYS as i64 * 86400_000);
+ }
+
+ #[test]
+ fn test_duration_num_microseconds() {
+ let d: Duration = Zero::zero();
+ assert_eq!(d.num_microseconds(), Some(0));
+ assert_eq!(Duration::microseconds(1).num_microseconds(), Some(1));
+ assert_eq!(Duration::microseconds(-1).num_microseconds(), Some(-1));
+ assert_eq!(Duration::nanoseconds(999).num_microseconds(), Some(0));
+ assert_eq!(Duration::nanoseconds(1001).num_microseconds(), Some(1));
+ assert_eq!(Duration::nanoseconds(-999).num_microseconds(), Some(0));
+ assert_eq!(Duration::nanoseconds(-1001).num_microseconds(), Some(-1));
+ assert_eq!(Duration::microseconds(i32::MAX).num_microseconds(), Some(i32::MAX as i64));
+ assert_eq!(Duration::microseconds(i32::MIN).num_microseconds(), Some(i32::MIN as i64));
+ assert_eq!(MAX.num_microseconds(), None);
+ assert_eq!(MIN.num_microseconds(), None);
+
+ // overflow checks
+ static MICROS_PER_DAY: i64 = 86400_000_000;
+ assert_eq!(Duration::days((i64::MAX / MICROS_PER_DAY) as i32).num_microseconds(),
+ Some(i64::MAX / MICROS_PER_DAY * MICROS_PER_DAY));
+ assert_eq!(Duration::days((i64::MIN / MICROS_PER_DAY) as i32).num_microseconds(),
+ Some(i64::MIN / MICROS_PER_DAY * MICROS_PER_DAY));
+ assert_eq!(Duration::days((i64::MAX / MICROS_PER_DAY + 1) as i32).num_microseconds(), None);
+ assert_eq!(Duration::days((i64::MIN / MICROS_PER_DAY - 1) as i32).num_microseconds(), None);
+ }
+
+ #[test]
+ fn test_duration_num_nanoseconds() {
+ let d: Duration = Zero::zero();
+ assert_eq!(d.num_nanoseconds(), Some(0));
+ assert_eq!(Duration::nanoseconds(1).num_nanoseconds(), Some(1));
+ assert_eq!(Duration::nanoseconds(-1).num_nanoseconds(), Some(-1));
+ assert_eq!(Duration::nanoseconds(i32::MAX).num_nanoseconds(), Some(i32::MAX as i64));
+ assert_eq!(Duration::nanoseconds(i32::MIN).num_nanoseconds(), Some(i32::MIN as i64));
+ assert_eq!(MAX.num_nanoseconds(), None);
+ assert_eq!(MIN.num_nanoseconds(), None);
+
+ // overflow checks
+ static NANOS_PER_DAY: i64 = 86400_000_000_000;
+ assert_eq!(Duration::days((i64::MAX / NANOS_PER_DAY) as i32).num_nanoseconds(),
+ Some(i64::MAX / NANOS_PER_DAY * NANOS_PER_DAY));
+ assert_eq!(Duration::days((i64::MIN / NANOS_PER_DAY) as i32).num_nanoseconds(),
+ Some(i64::MIN / NANOS_PER_DAY * NANOS_PER_DAY));
+ assert_eq!(Duration::days((i64::MAX / NANOS_PER_DAY + 1) as i32).num_nanoseconds(), None);
+ assert_eq!(Duration::days((i64::MIN / NANOS_PER_DAY - 1) as i32).num_nanoseconds(), None);
+ }
+
+ #[test]
+ fn test_duration_checked_ops() {
+ assert_eq!(Duration::days(MAX_DAYS).checked_add(&Duration::seconds(86399)),
+ Some(Duration::days(MAX_DAYS - 1) + Duration::seconds(86400+86399)));
+ assert!(Duration::days(MAX_DAYS).checked_add(&Duration::seconds(86400)).is_none());
+
+ assert_eq!(Duration::days(MIN_DAYS).checked_sub(&Duration::seconds(0)),
+ Some(Duration::days(MIN_DAYS)));
+ assert!(Duration::days(MIN_DAYS).checked_sub(&Duration::seconds(1)).is_none());
+ }
+
+ #[test]
+ fn test_duration_mul() {
+ let d: Duration = Zero::zero();
+ assert_eq!(d * i32::MAX, d);
+ assert_eq!(d * i32::MIN, d);
+ assert_eq!(Duration::nanoseconds(1) * 0, Zero::zero());
+ assert_eq!(Duration::nanoseconds(1) * 1, Duration::nanoseconds(1));
+ assert_eq!(Duration::nanoseconds(1) * 1_000_000_000, Duration::seconds(1));
+ assert_eq!(Duration::nanoseconds(1) * -1_000_000_000, -Duration::seconds(1));
+ assert_eq!(-Duration::nanoseconds(1) * 1_000_000_000, -Duration::seconds(1));
+ assert_eq!(Duration::nanoseconds(30) * 333_333_333,
+ Duration::seconds(10) - Duration::nanoseconds(10));
+ assert_eq!((Duration::nanoseconds(1) + Duration::seconds(1) + Duration::days(1)) * 3,
+ Duration::nanoseconds(3) + Duration::seconds(3) + Duration::days(3));
+ }
+
+ #[test]
+ fn test_duration_div() {
+ let d: Duration = Zero::zero();
+ assert_eq!(d / i32::MAX, d);
+ assert_eq!(d / i32::MIN, d);
+ assert_eq!(Duration::nanoseconds(123_456_789) / 1, Duration::nanoseconds(123_456_789));
+ assert_eq!(Duration::nanoseconds(123_456_789) / -1, -Duration::nanoseconds(123_456_789));
+ assert_eq!(-Duration::nanoseconds(123_456_789) / -1, Duration::nanoseconds(123_456_789));
+ assert_eq!(-Duration::nanoseconds(123_456_789) / 1, -Duration::nanoseconds(123_456_789));
+ }
+
+ #[test]
+ fn test_duration_fmt() {
+ let d: Duration = Zero::zero();
+ assert_eq!(d.to_string(), "PT0S".to_string());
+ assert_eq!(Duration::days(42).to_string(), "P42D".to_string());
+ assert_eq!(Duration::days(-42).to_string(), "P-42D".to_string());
+ assert_eq!(Duration::seconds(42).to_string(), "PT42S".to_string());
+ assert_eq!(Duration::milliseconds(42).to_string(), "PT0.042S".to_string());
+ assert_eq!(Duration::microseconds(42).to_string(), "PT0.000042S".to_string());
+ assert_eq!(Duration::nanoseconds(42).to_string(), "PT0.000000042S".to_string());
+ assert_eq!((Duration::days(7) + Duration::milliseconds(6543)).to_string(),
+ "P7DT6.543S".to_string());
+
+ // the format specifier should have no effect on `Duration`
+ assert_eq!(format!("{:30}", Duration::days(1) + Duration::milliseconds(2345)),
+ "P1DT2.345S".to_string());
+ }
+}
--- /dev/null
+// Copyright 2012-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.
+
+//! Temporal quantification.
+
+pub use self::duration::Duration;
+
+pub mod duration;
//!
//! ```no_run
//! use std::io::timer::Timer;
+//! use std::time::Duration;
//!
//! let (tx, rx) = channel::<int>();
//! let mut timer = Timer::new().unwrap();
-//! let timeout = timer.oneshot(10000);
+//! let timeout = timer.oneshot(Duration::seconds(10));
//!
//! loop {
//! select! {
//!
//! ```no_run
//! use std::io::timer::Timer;
+//! use std::time::Duration;
//!
//! let (tx, rx) = channel::<int>();
//! let mut timer = Timer::new().unwrap();
//!
//! loop {
-//! let timeout = timer.oneshot(5000);
+//! let timeout = timer.oneshot(Duration::seconds(5));
//!
//! select! {
//! val = rx.recv() => println!("Received {}", val),
use std::fmt;
#[deriving(PartialEq)]
-pub enum Os { OsWin32, OsMacos, OsLinux, OsAndroid, OsFreebsd, OsiOS,
+pub enum Os { OsWindows, OsMacos, OsLinux, OsAndroid, OsFreebsd, OsiOS,
OsDragonfly }
#[deriving(PartialEq, Eq, Hash, Encodable, Decodable, Clone)]
// Transform this ABI as appropriate for the requested os/arch
// combination.
Some(match (*self, os, arch) {
- (System, OsWin32, X86) => Stdcall,
+ (System, OsWindows, X86) => Stdcall,
(System, _, _) => C,
(me, _, _) => me,
})
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
OsLinux => "linux".fmt(f),
- OsWin32 => "win32".fmt(f),
+ OsWindows => "windows".fmt(f),
OsMacos => "macos".fmt(f),
OsiOS => "ios".fmt(f),
OsAndroid => "android".fmt(f),
assert_eq!(Stdcall.for_target(OsLinux, X86), Some(Stdcall));
assert_eq!(Stdcall.for_target(OsLinux, Arm), None);
assert_eq!(System.for_target(OsLinux, X86), Some(C));
- assert_eq!(System.for_target(OsWin32, X86), Some(Stdcall));
- assert_eq!(System.for_target(OsWin32, X86_64), Some(C));
- assert_eq!(System.for_target(OsWin32, Arm), Some(C));
- assert_eq!(Stdcall.for_target(OsWin32, X86), Some(Stdcall));
- assert_eq!(Stdcall.for_target(OsWin32, X86_64), Some(Stdcall));
+ assert_eq!(System.for_target(OsWindows, X86), Some(Stdcall));
+ assert_eq!(System.for_target(OsWindows, X86_64), Some(C));
+ assert_eq!(System.for_target(OsWindows, Arm), Some(C));
+ assert_eq!(Stdcall.for_target(OsWindows, X86), Some(Stdcall));
+ assert_eq!(Stdcall.for_target(OsWindows, X86_64), Some(Stdcall));
}
pub fn as_str<'a>(&'a self) -> &'a str {
self.name.as_str()
}
+
+ pub fn encode_with_hygiene(&self) -> String {
+ format!("\x00name_{:u},ctxt_{:u}\x00",
+ self.name.uint(),
+ self.ctxt)
+ }
}
impl Show for Ident {
pub struct Generics {
pub lifetimes: Vec<LifetimeDef>,
pub ty_params: OwnedSlice<TyParam>,
+ pub where_clause: WhereClause,
}
impl Generics {
}
}
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
+pub struct WhereClause {
+ pub id: NodeId,
+ pub predicates: Vec<WherePredicate>,
+}
+
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
+pub struct WherePredicate {
+ pub id: NodeId,
+ pub span: Span,
+ pub ident: Ident,
+ pub bounds: OwnedSlice<TyParamBound>,
+}
+
/// The set of MetaItems that define the compilation environment of the crate,
/// used to drive conditional compilation
-pub type CrateConfig = Vec<Gc<MetaItem>> ;
+pub type CrateConfig = Vec<Gc<MetaItem>>;
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
pub struct Crate {
// FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
ExprLoop(P<Block>, Option<Ident>),
ExprMatch(Gc<Expr>, Vec<Arm>),
- ExprFnBlock(P<FnDecl>, P<Block>),
+ ExprFnBlock(CaptureClause, P<FnDecl>, P<Block>),
ExprProc(P<FnDecl>, P<Block>),
- ExprUnboxedFn(P<FnDecl>, P<Block>),
+ ExprUnboxedFn(CaptureClause, UnboxedClosureKind, P<FnDecl>, P<Block>),
ExprBlock(P<Block>),
ExprAssign(Gc<Expr>, Gc<Expr>),
ExprParen(Gc<Expr>)
}
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
+pub enum CaptureClause {
+ CaptureByValue,
+ CaptureByRef,
+}
+
/// When the main rust parser encounters a syntax-extension invocation, it
/// parses the arguments to the invocation as a token-tree. This is a very
/// loose structure, such that all sorts of different AST-fragments can
/// doesn't have an implementation, just a signature) or provided (meaning it
/// has a default implementation).
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
-pub enum TraitMethod {
- Required(TypeMethod),
- Provided(Gc<Method>),
+pub enum TraitItem {
+ RequiredMethod(TypeMethod),
+ ProvidedMethod(Gc<Method>),
+}
+
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
+pub enum ImplItem {
+ MethodImplItem(Gc<Method>),
}
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
pub struct UnboxedFnTy {
+ pub kind: UnboxedClosureKind,
pub decl: P<FnDecl>,
}
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
pub enum ViewPath_ {
- /// `quux = foo::bar::baz`
+ /// `foo::bar::baz as quux`
///
/// or just
///
- /// `foo::bar::baz ` (with 'baz =' implicitly on the left)
+ /// `foo::bar::baz` (with `as baz` implicitly on the right)
ViewPathSimple(Ident, Path, NodeId),
/// `foo::bar::*`
Option<TyParamBound>, // (optional) default bound not required for Self.
// Currently, only Sized makes sense here.
Vec<TraitRef> ,
- Vec<TraitMethod>),
+ Vec<TraitItem>),
ItemImpl(Generics,
Option<TraitRef>, // (optional) trait this impl implements
P<Ty>, // self
- Vec<Gc<Method>>),
+ Vec<ImplItem>),
/// A macro invocation (which includes macro definition)
ItemMac(Mac),
}
ForeignItemStatic(P<Ty>, /* is_mutbl */ bool),
}
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
+pub enum UnboxedClosureKind {
+ FnUnboxedClosureKind,
+ FnMutUnboxedClosureKind,
+ FnOnceUnboxedClosureKind,
+}
+
/// The data we save and restore about an inlined item or method. This is not
/// part of the AST that we parse from a file, but it becomes part of the tree
/// that we trans.
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
pub enum InlinedItem {
IIItem(Gc<Item>),
- IIMethod(DefId /* impl id */, bool /* is provided */, Gc<Method>),
+ IITraitItem(DefId /* impl id */, InlinedTraitItem),
IIForeign(Gc<ForeignItem>),
}
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
+pub enum InlinedTraitItem {
+ ProvidedInlinedTraitItem(Gc<Method>),
+ RequiredInlinedTraitItem(Gc<Method>),
+}
+
#[cfg(test)]
mod test {
use serialize::json;
}
}
-impl MaybeFnLike for ast::TraitMethod {
+impl MaybeFnLike for ast::TraitItem {
fn is_fn_like(&self) -> bool {
- match *self { ast::Provided(_) => true, _ => false, }
+ match *self { ast::ProvidedMethod(_) => true, _ => false, }
}
}
match node {
ast_map::NodeItem(item) if item.is_fn_like() =>
Some(FnLikeCode(new(node))),
- ast_map::NodeTraitMethod(tm) if tm.is_fn_like() =>
+ ast_map::NodeTraitItem(tm) if tm.is_fn_like() =>
Some(FnLikeCode(new(node))),
- ast_map::NodeMethod(_) =>
+ ast_map::NodeImplItem(_) =>
Some(FnLikeCode(new(node))),
ast_map::NodeExpr(e) if e.is_fn_like() =>
Some(FnLikeCode(new(node))),
}),
_ => fail!("item FnLikeNode that is not fn-like"),
},
- ast_map::NodeTraitMethod(ref t) => match **t {
- ast::Provided(ref m) => method(&**m),
+ ast_map::NodeTraitItem(ref t) => match **t {
+ ast::ProvidedMethod(ref m) => method(&**m),
_ => fail!("trait method FnLikeNode that is not fn-like"),
},
- ast_map::NodeMethod(ref m) => method(&**m),
+ ast_map::NodeImplItem(ref ii) => {
+ match **ii {
+ ast::MethodImplItem(ref m) => method(&**m),
+ }
+ }
ast_map::NodeExpr(ref e) => match e.node {
- ast::ExprFnBlock(ref decl, ref block) =>
+ ast::ExprFnBlock(_, ref decl, ref block) =>
closure(ClosureParts::new(*decl, *block, e.id, e.span)),
ast::ExprProc(ref decl, ref block) =>
closure(ClosureParts::new(*decl, *block, e.id, e.span)),
pub enum Node {
NodeItem(Gc<Item>),
NodeForeignItem(Gc<ForeignItem>),
- NodeTraitMethod(Gc<TraitMethod>),
- NodeMethod(Gc<Method>),
+ NodeTraitItem(Gc<TraitItem>),
+ NodeImplItem(Gc<ImplItem>),
NodeVariant(P<Variant>),
NodeExpr(Gc<Expr>),
NodeStmt(Gc<Stmt>),
/// All the node types, with a parent ID.
EntryItem(NodeId, Gc<Item>),
EntryForeignItem(NodeId, Gc<ForeignItem>),
- EntryTraitMethod(NodeId, Gc<TraitMethod>),
- EntryMethod(NodeId, Gc<Method>),
+ EntryTraitItem(NodeId, Gc<TraitItem>),
+ EntryImplItem(NodeId, Gc<ImplItem>),
EntryVariant(NodeId, P<Variant>),
EntryExpr(NodeId, Gc<Expr>),
EntryStmt(NodeId, Gc<Stmt>),
struct InlinedParent {
path: Vec<PathElem> ,
- /// Required by NodeTraitMethod and NodeMethod.
+ /// RequiredMethod by NodeTraitItem and NodeImplItem.
def_id: DefId
}
Some(match *self {
EntryItem(id, _) => id,
EntryForeignItem(id, _) => id,
- EntryTraitMethod(id, _) => id,
- EntryMethod(id, _) => id,
+ EntryTraitItem(id, _) => id,
+ EntryImplItem(id, _) => id,
EntryVariant(id, _) => id,
EntryExpr(id, _) => id,
EntryStmt(id, _) => id,
Some(match *self {
EntryItem(_, p) => NodeItem(p),
EntryForeignItem(_, p) => NodeForeignItem(p),
- EntryTraitMethod(_, p) => NodeTraitMethod(p),
- EntryMethod(_, p) => NodeMethod(p),
+ EntryTraitItem(_, p) => NodeTraitItem(p),
+ EntryImplItem(_, p) => NodeImplItem(p),
EntryVariant(_, p) => NodeVariant(p),
EntryExpr(_, p) => NodeExpr(p),
EntryStmt(_, p) => NodeStmt(p),
}
}
NodeForeignItem(i) => PathName(i.ident.name),
- NodeMethod(m) => match m.node {
- MethDecl(ident, _, _, _, _, _, _, _) => PathName(ident.name),
- MethMac(_) => fail!("no path elem for {:?}", node)
+ NodeImplItem(ii) => {
+ match *ii {
+ MethodImplItem(ref m) => {
+ match m.node {
+ MethDecl(ident, _, _, _, _, _, _, _) => {
+ PathName(ident.name)
+ }
+ MethMac(_) => {
+ fail!("no path elem for {:?}", node)
+ }
+ }
+ }
+ }
},
- NodeTraitMethod(tm) => match *tm {
- Required(ref m) => PathName(m.ident.name),
- Provided(m) => match m.node {
+ NodeTraitItem(tm) => match *tm {
+ RequiredMethod(ref m) => PathName(m.ident.name),
+ ProvidedMethod(m) => match m.node {
MethDecl(ident, _, _, _, _, _, _, _) => {
PathName(ident.name)
}
let attrs = match node {
NodeItem(ref i) => Some(i.attrs.as_slice()),
NodeForeignItem(ref fi) => Some(fi.attrs.as_slice()),
- NodeTraitMethod(ref tm) => match **tm {
- Required(ref type_m) => Some(type_m.attrs.as_slice()),
- Provided(ref m) => Some(m.attrs.as_slice())
+ NodeTraitItem(ref tm) => match **tm {
+ RequiredMethod(ref type_m) => Some(type_m.attrs.as_slice()),
+ ProvidedMethod(ref m) => Some(m.attrs.as_slice())
},
- NodeMethod(ref m) => Some(m.attrs.as_slice()),
+ NodeImplItem(ref ii) => {
+ match **ii {
+ MethodImplItem(ref m) => Some(m.attrs.as_slice()),
+ }
+ }
NodeVariant(ref v) => Some(v.node.attrs.as_slice()),
// unit/tuple structs take the attributes straight from
// the struct definition.
/// the iterator will produce node id's for items with paths
/// such as `foo::bar::quux`, `bar::quux`, `other::bar::quux`, and
/// any other such items it can find in the map.
- pub fn nodes_matching_suffix<'a, S:Str>(&'a self, parts: &'a [S]) -> NodesMatchingSuffix<'a,S> {
- NodesMatchingSuffix { map: self,
- item_name: parts.last().unwrap(),
- where: parts.slice_to(parts.len() - 1),
- idx: 0 }
+ pub fn nodes_matching_suffix<'a, S:Str>(&'a self, parts: &'a [S])
+ -> NodesMatchingSuffix<'a,S> {
+ NodesMatchingSuffix {
+ map: self,
+ item_name: parts.last().unwrap(),
+ in_which: parts.slice_to(parts.len() - 1),
+ idx: 0,
+ }
}
pub fn opt_span(&self, id: NodeId) -> Option<Span> {
let sp = match self.find(id) {
Some(NodeItem(item)) => item.span,
Some(NodeForeignItem(foreign_item)) => foreign_item.span,
- Some(NodeTraitMethod(trait_method)) => {
+ Some(NodeTraitItem(trait_method)) => {
match *trait_method {
- Required(ref type_method) => type_method.span,
- Provided(ref method) => method.span,
+ RequiredMethod(ref type_method) => type_method.span,
+ ProvidedMethod(ref method) => method.span,
+ }
+ }
+ Some(NodeImplItem(ref impl_item)) => {
+ match **impl_item {
+ MethodImplItem(ref method) => method.span,
}
}
- Some(NodeMethod(method)) => method.span,
Some(NodeVariant(variant)) => variant.span,
Some(NodeExpr(expr)) => expr.span,
Some(NodeStmt(stmt)) => stmt.span,
pub struct NodesMatchingSuffix<'a, S> {
map: &'a Map,
item_name: &'a S,
- where: &'a [S],
+ in_which: &'a [S],
idx: NodeId,
}
impl<'a,S:Str> NodesMatchingSuffix<'a,S> {
/// Returns true only if some suffix of the module path for parent
- /// matches `self.where`.
+ /// matches `self.in_which`.
///
- /// In other words: let `[x_0,x_1,...,x_k]` be `self.where`;
+ /// In other words: let `[x_0,x_1,...,x_k]` be `self.in_which`;
/// returns true if parent's path ends with the suffix
/// `x_0::x_1::...::x_k`.
fn suffix_matches(&self, parent: NodeId) -> bool {
let mut cursor = parent;
- for part in self.where.iter().rev() {
+ for part in self.in_which.iter().rev() {
let (mod_id, mod_name) = match find_first_mod_parent(self.map, cursor) {
None => return false,
Some((node_id, name)) => (node_id, name),
let (p, name) = match self.map.find_entry(idx) {
Some(EntryItem(p, n)) => (p, n.name()),
Some(EntryForeignItem(p, n)) => (p, n.name()),
- Some(EntryTraitMethod(p, n)) => (p, n.name()),
- Some(EntryMethod(p, n)) => (p, n.name()),
+ Some(EntryTraitItem(p, n)) => (p, n.name()),
+ Some(EntryImplItem(p, n)) => (p, n.name()),
Some(EntryVariant(p, n)) => (p, n.name()),
_ => continue,
};
impl Named for Item { fn name(&self) -> Name { self.ident.name } }
impl Named for ForeignItem { fn name(&self) -> Name { self.ident.name } }
impl Named for Variant_ { fn name(&self) -> Name { self.name.name } }
-impl Named for TraitMethod {
+impl Named for TraitItem {
fn name(&self) -> Name {
match *self {
- Required(ref tm) => tm.ident.name,
- Provided(m) => m.name(),
+ RequiredMethod(ref tm) => tm.ident.name,
+ ProvidedMethod(m) => m.name(),
+ }
+ }
+}
+impl Named for ImplItem {
+ fn name(&self) -> Name {
+ match *self {
+ MethodImplItem(ref m) => m.name(),
}
}
}
assert_eq!(self.parent, i.id);
match i.node {
- ItemImpl(_, _, _, ref ms) => {
- for &m in ms.iter() {
- self.insert(m.id, EntryMethod(self.parent, m));
+ ItemImpl(_, _, _, ref impl_items) => {
+ for impl_item in impl_items.iter() {
+ match *impl_item {
+ MethodImplItem(m) => {
+ self.insert(m.id,
+ EntryImplItem(self.parent,
+ box(GC) *impl_item));
+ }
+ }
}
}
ItemEnum(ref enum_definition, _) => {
for tm in methods.iter() {
match *tm {
- Required(ref m) => {
- self.insert(m.id, EntryTraitMethod(self.parent,
+ RequiredMethod(ref m) => {
+ self.insert(m.id, EntryTraitItem(self.parent,
box(GC) (*tm).clone()));
}
- Provided(m) => {
- self.insert(m.id, EntryTraitMethod(self.parent,
- box(GC) Provided(m)));
+ ProvidedMethod(m) => {
+ self.insert(m.id, EntryTraitItem(self.parent,
+ box(GC) ProvidedMethod(m)));
}
}
}
let ii = fold(&mut cx);
match ii {
IIItem(_) => {}
- IIMethod(impl_did, is_provided, m) => {
- let entry = if is_provided {
- EntryTraitMethod(cx.parent, box(GC) Provided(m))
- } else {
- EntryMethod(cx.parent, m)
+ IITraitItem(impl_did, inlined_trait_item) => {
+ let (trait_item_id, entry) = match inlined_trait_item {
+ ProvidedInlinedTraitItem(m) => {
+ (m.id,
+ EntryTraitItem(cx.parent, box(GC) ProvidedMethod(m)))
+ }
+ RequiredInlinedTraitItem(m) => {
+ (m.id,
+ EntryImplItem(cx.parent, box(GC) MethodImplItem(m)))
+ }
};
- cx.insert(m.id, entry);
+ cx.insert(trait_item_id, entry);
def_id = impl_did;
}
IIForeign(i) => {
match *node {
NodeItem(a) => self.print_item(&*a),
NodeForeignItem(a) => self.print_foreign_item(&*a),
- NodeTraitMethod(a) => self.print_trait_method(&*a),
- NodeMethod(a) => self.print_method(&*a),
+ NodeTraitItem(a) => self.print_trait_method(&*a),
+ NodeImplItem(a) => self.print_impl_item(&*a),
NodeVariant(a) => self.print_variant(&*a),
NodeExpr(a) => self.print_expr(&*a),
NodeStmt(a) => self.print_stmt(&*a),
let path_str = map.path_to_str_with_ident(id, item.ident);
format!("foreign item {} (id={})", path_str, id)
}
- Some(NodeMethod(m)) => match m.node {
- MethDecl(ident, _, _, _, _, _, _, _) =>
- format!("method {} in {} (id={})",
- token::get_ident(ident),
- map.path_to_string(id), id),
- MethMac(ref mac) =>
- format!("method macro {} (id={})",
- pprust::mac_to_string(mac), id)
- },
- Some(NodeTraitMethod(ref tm)) => {
- let m = ast_util::trait_method_to_ty_method(&**tm);
+ Some(NodeImplItem(ref ii)) => {
+ match **ii {
+ MethodImplItem(ref m) => {
+ match m.node {
+ MethDecl(ident, _, _, _, _, _, _, _) =>
+ format!("method {} in {} (id={})",
+ token::get_ident(ident),
+ map.path_to_string(id), id),
+ MethMac(ref mac) =>
+ format!("method macro {} (id={})",
+ pprust::mac_to_string(mac), id)
+ }
+ }
+ }
+ }
+ Some(NodeTraitItem(ref tm)) => {
+ let m = ast_util::trait_item_to_ty_method(&**tm);
format!("method {} in {} (id={})",
token::get_ident(m.ident),
map.path_to_string(id), id)
token::gensym_ident(pretty.as_slice())
}
-/// extract a TypeMethod from a TraitMethod. if the TraitMethod is
+pub fn trait_method_to_ty_method(method: &Method) -> TypeMethod {
+ match method.node {
+ MethDecl(ident,
+ ref generics,
+ abi,
+ explicit_self,
+ fn_style,
+ decl,
+ _,
+ vis) => {
+ TypeMethod {
+ ident: ident,
+ attrs: method.attrs.clone(),
+ fn_style: fn_style,
+ decl: decl,
+ generics: generics.clone(),
+ explicit_self: explicit_self,
+ id: method.id,
+ span: method.span,
+ vis: vis,
+ abi: abi,
+ }
+ },
+ MethMac(_) => fail!("expected non-macro method declaration")
+ }
+}
+
+/// extract a TypeMethod from a TraitItem. if the TraitItem is
/// a default, pull out the useful fields to make a TypeMethod
//
// NB: to be used only after expansion is complete, and macros are gone.
-pub fn trait_method_to_ty_method(method: &TraitMethod) -> TypeMethod {
+pub fn trait_item_to_ty_method(method: &TraitItem) -> TypeMethod {
match *method {
- Required(ref m) => (*m).clone(),
- Provided(m) => {
- match m.node {
- MethDecl(ident,
- ref generics,
- abi,
- explicit_self,
- fn_style,
- decl,
- _,
- vis) => {
- TypeMethod {
- ident: ident,
- attrs: m.attrs.clone(),
- fn_style: fn_style,
- decl: decl,
- generics: generics.clone(),
- explicit_self: explicit_self,
- id: m.id,
- span: m.span,
- vis: vis,
- abi: abi,
- }
- },
- MethMac(_) => fail!("expected non-macro method declaration")
- }
-
- }
+ RequiredMethod(ref m) => (*m).clone(),
+ ProvidedMethod(ref m) => trait_method_to_ty_method(&**m),
}
}
-pub fn split_trait_methods(trait_methods: &[TraitMethod])
+pub fn split_trait_methods(trait_methods: &[TraitItem])
-> (Vec<TypeMethod> , Vec<Gc<Method>> ) {
let mut reqd = Vec::new();
let mut provd = Vec::new();
for trt_method in trait_methods.iter() {
match *trt_method {
- Required(ref tm) => reqd.push((*tm).clone()),
- Provided(m) => provd.push(m)
+ RequiredMethod(ref tm) => reqd.push((*tm).clone()),
+ ProvidedMethod(m) => provd.push(m)
}
};
(reqd, provd)
pub static as_prec: uint = 12u;
pub fn empty_generics() -> Generics {
- Generics {lifetimes: Vec::new(),
- ty_params: OwnedSlice::empty()}
+ Generics {
+ lifetimes: Vec::new(),
+ ty_params: OwnedSlice::empty(),
+ where_clause: WhereClause {
+ id: DUMMY_NODE_ID,
+ predicates: Vec::new(),
+ }
+ }
}
// ______________________________________________________________________
visit::walk_struct_def(self, struct_def, ());
}
- fn visit_trait_method(&mut self, tm: &ast::TraitMethod, _: ()) {
+ fn visit_trait_item(&mut self, tm: &ast::TraitItem, _: ()) {
match *tm {
- ast::Required(ref m) => self.operation.visit_id(m.id),
- ast::Provided(ref m) => self.operation.visit_id(m.id),
+ ast::RequiredMethod(ref m) => self.operation.visit_id(m.id),
+ ast::ProvidedMethod(ref m) => self.operation.visit_id(m.id),
}
- visit::walk_trait_method(self, tm, ());
+ visit::walk_trait_item(self, tm, ());
}
}
impl FromStr for CrateId {
fn from_str(s: &str) -> Option<CrateId> {
- let pieces: Vec<&str> = s.splitn('#', 1).collect();
+ let pieces: Vec<&str> = s.splitn(1, '#').collect();
let path = pieces.get(0).to_string();
if path.as_slice().starts_with("/") || path.as_slice().ends_with("/") ||
}
let path_pieces: Vec<&str> = path.as_slice()
- .rsplitn('/', 1)
+ .rsplitn(1, '/')
.collect();
let inferred_name = *path_pieces.get(0);
(inferred_name.to_string(), None)
} else {
let hash_pieces: Vec<&str> = pieces.get(1)
- .splitn(':', 1)
+ .splitn(1, ':')
.collect();
let (hash_name, hash_version) = if hash_pieces.len() == 1 {
("", *hash_pieces.get(0))
fn lambda_fn_decl(&self, span: Span,
fn_decl: P<ast::FnDecl>, blk: P<ast::Block>) -> Gc<ast::Expr> {
- self.expr(span, ast::ExprFnBlock(fn_decl, blk))
+ self.expr(span, ast::ExprFnBlock(ast::CaptureByRef, fn_decl, blk))
}
fn lambda(&self, span: Span, ids: Vec<ast::Ident> , blk: P<ast::Block>) -> Gc<ast::Expr> {
let fn_decl = self.fn_decl(
ids.iter().map(|id| self.arg(span, *id, self.ty_infer(span))).collect(),
self.ty_infer(span));
- self.expr(span, ast::ExprFnBlock(fn_decl, blk))
+ self.expr(span, ast::ExprFnBlock(ast::CaptureByRef, fn_decl, blk))
}
fn lambda0(&self, span: Span, blk: P<ast::Block>) -> Gc<ast::Expr> {
self.lambda(span, Vec::new(), blk)
methods: Vec<Gc<ast::Method>> ) -> Gc<ast::Item> {
let trait_path = self.path.to_path(cx, self.span, type_ident, generics);
- let Generics { mut lifetimes, ty_params } =
+ let Generics { mut lifetimes, ty_params, where_clause: _ } =
self.generics.to_generics(cx, self.span, type_ident, generics);
let mut ty_params = ty_params.into_vec();
}));
let trait_generics = Generics {
lifetimes: lifetimes,
- ty_params: OwnedSlice::from_vec(ty_params)
+ ty_params: OwnedSlice::from_vec(ty_params),
+ where_clause: ast::WhereClause {
+ id: ast::DUMMY_NODE_ID,
+ predicates: Vec::new(),
+ },
};
// Create the reference to the trait.
self.span,
ident,
(vec!(attr)).append(self.attributes.as_slice()),
- ast::ItemImpl(trait_generics, opt_trait_ref,
- self_type, methods))
+ ast::ItemImpl(trait_generics,
+ opt_trait_ref,
+ self_type,
+ methods.move_iter()
+ .map(|method| {
+ ast::MethodImplItem(method)
+ }).collect()))
}
fn expand_struct_def(&self,
cx.typaram(span, cx.ident_of(name), bounds, unbound, None)
}
-fn mk_generics(lifetimes: Vec<ast::LifetimeDef>, ty_params: Vec<ast::TyParam> ) -> Generics {
+fn mk_generics(lifetimes: Vec<ast::LifetimeDef>, ty_params: Vec<ast::TyParam>)
+ -> Generics {
Generics {
lifetimes: lifetimes,
- ty_params: OwnedSlice::from_vec(ty_params)
+ ty_params: OwnedSlice::from_vec(ty_params),
+ where_clause: ast::WhereClause {
+ id: ast::DUMMY_NODE_ID,
+ predicates: Vec::new(),
+ },
}
}
fld.cx.expr(e.span, ast::ExprForLoop(pat, head, body, opt_ident))
}
- ast::ExprFnBlock(fn_decl, block) => {
+ ast::ExprFnBlock(capture_clause, fn_decl, block) => {
let (rewritten_fn_decl, rewritten_block)
= expand_and_rename_fn_decl_and_block(&*fn_decl, block, fld);
- let new_node = ast::ExprFnBlock(rewritten_fn_decl, rewritten_block);
+ let new_node = ast::ExprFnBlock(capture_clause,
+ rewritten_fn_decl,
+ rewritten_block);
box(GC) ast::Expr{id:e.id, node: new_node, span: fld.new_span(e.span)}
}
fn to_source(&self) -> String;
}
+ // FIXME (Issue #16472): This should go away after ToToken impls
+ // are revised to go directly to token-trees.
+ trait ToSourceWithHygiene : ToSource {
+ // Takes a thing and generates a string containing rust code
+ // for it, encoding Idents as special byte sequences to
+ // maintain hygiene across serialization and deserialization.
+ fn to_source_with_hygiene(&self) -> String;
+ }
+
macro_rules! impl_to_source(
(Gc<$t:ty>, $pp:ident) => (
impl ToSource for Gc<$t> {
pprust::$pp(&**self)
}
}
+ impl ToSourceWithHygiene for Gc<$t> {
+ fn to_source_with_hygiene(&self) -> String {
+ pprust::with_hygiene::$pp(&**self)
+ }
+ }
);
($t:ty, $pp:ident) => (
impl ToSource for $t {
pprust::$pp(self)
}
}
+ impl ToSourceWithHygiene for $t {
+ fn to_source_with_hygiene(&self) -> String {
+ pprust::with_hygiene::$pp(self)
+ }
+ }
);
)
.to_string()
}
+ fn slice_to_source_with_hygiene<'a, T: ToSourceWithHygiene>(
+ sep: &'static str, xs: &'a [T]) -> String {
+ xs.iter()
+ .map(|i| i.to_source_with_hygiene())
+ .collect::<Vec<String>>()
+ .connect(sep)
+ .to_string()
+ }
+
macro_rules! impl_to_source_slice(
($t:ty, $sep:expr) => (
impl<'a> ToSource for &'a [$t] {
slice_to_source($sep, *self)
}
}
+
+ impl<'a> ToSourceWithHygiene for &'a [$t] {
+ fn to_source_with_hygiene(&self) -> String {
+ slice_to_source_with_hygiene($sep, *self)
+ }
+ }
)
)
}
}
+ impl ToSourceWithHygiene for ast::Ident {
+ fn to_source_with_hygiene(&self) -> String {
+ self.encode_with_hygiene()
+ }
+ }
+
impl_to_source!(ast::Ty, ty_to_string)
impl_to_source!(ast::Block, block_to_string)
impl_to_source!(ast::Arg, arg_to_string)
pprust::attribute_to_string(&dummy_spanned(*self))
}
}
+ impl ToSourceWithHygiene for ast::Attribute_ {
+ fn to_source_with_hygiene(&self) -> String {
+ self.to_source()
+ }
+ }
impl<'a> ToSource for &'a str {
fn to_source(&self) -> String {
pprust::lit_to_string(&lit)
}
}
+ impl<'a> ToSourceWithHygiene for &'a str {
+ fn to_source_with_hygiene(&self) -> String {
+ self.to_source()
+ }
+ }
impl ToSource for () {
fn to_source(&self) -> String {
"()".to_string()
}
}
+ impl ToSourceWithHygiene for () {
+ fn to_source_with_hygiene(&self) -> String {
+ self.to_source()
+ }
+ }
impl ToSource for bool {
fn to_source(&self) -> String {
pprust::lit_to_string(&lit)
}
}
+ impl ToSourceWithHygiene for bool {
+ fn to_source_with_hygiene(&self) -> String {
+ self.to_source()
+ }
+ }
impl ToSource for char {
fn to_source(&self) -> String {
pprust::lit_to_string(&lit)
}
}
+ impl ToSourceWithHygiene for char {
+ fn to_source_with_hygiene(&self) -> String {
+ self.to_source()
+ }
+ }
macro_rules! impl_to_source_int(
(signed, $t:ty, $tag:ident) => (
pprust::lit_to_string(&dummy_spanned(lit))
}
}
+ impl ToSourceWithHygiene for $t {
+ fn to_source_with_hygiene(&self) -> String {
+ self.to_source()
+ }
+ }
);
(unsigned, $t:ty, $tag:ident) => (
impl ToSource for $t {
pprust::lit_to_string(&dummy_spanned(lit))
}
}
+ impl ToSourceWithHygiene for $t {
+ fn to_source_with_hygiene(&self) -> String {
+ self.to_source()
+ }
+ }
);
)
($t:ty) => (
impl ToTokens for $t {
fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
- cx.parse_tts(self.to_source())
+ cx.parse_tts_with_hygiene(self.to_source_with_hygiene())
}
}
)
($t:ty) => (
impl<'a> ToTokens for $t {
fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
- cx.parse_tts(self.to_source())
+ cx.parse_tts_with_hygiene(self.to_source_with_hygiene())
}
}
)
fn parse_item(&self, s: String) -> Gc<ast::Item>;
fn parse_expr(&self, s: String) -> Gc<ast::Expr>;
fn parse_stmt(&self, s: String) -> Gc<ast::Stmt>;
- fn parse_tts(&self, s: String) -> Vec<ast::TokenTree> ;
+ fn parse_tts(&self, s: String) -> Vec<ast::TokenTree>;
+ }
+
+ trait ExtParseUtilsWithHygiene {
+ // FIXME (Issue #16472): This should go away after ToToken impls
+ // are revised to go directly to token-trees.
+ fn parse_tts_with_hygiene(&self, s: String) -> Vec<ast::TokenTree>;
}
impl<'a> ExtParseUtils for ExtCtxt<'a> {
}
}
+ impl<'a> ExtParseUtilsWithHygiene for ExtCtxt<'a> {
+
+ fn parse_tts_with_hygiene(&self, s: String) -> Vec<ast::TokenTree> {
+ use parse::with_hygiene::parse_tts_from_source_str;
+ parse_tts_from_source_str("<quote expansion>".to_string(),
+ s,
+ self.cfg(),
+ self.parse_sess())
+ }
+
+ }
+
}
pub fn expand_quote_tokens(cx: &mut ExtCtxt,
noop_fold_field(field, self)
}
+ fn fold_where_clause(&mut self, where_clause: &WhereClause)
+ -> WhereClause {
+ noop_fold_where_clause(where_clause, self)
+ }
+
+ fn fold_where_predicate(&mut self, where_predicate: &WherePredicate)
+ -> WherePredicate {
+ noop_fold_where_predicate(where_predicate, self)
+ }
+
// Helper methods:
fn map_exprs(&self, f: |Gc<Expr>| -> Gc<Expr>,
TyUnboxedFn(ref f) => {
TyUnboxedFn(box(GC) UnboxedFnTy {
decl: fld.fold_fn_decl(&*f.decl),
+ kind: f.kind,
})
}
TyTup(ref tys) => TyTup(tys.iter().map(|&ty| fld.fold_ty(ty)).collect()),
UnboxedFnTyParamBound(ref unboxed_function_type) => {
UnboxedFnTyParamBound(UnboxedFnTy {
decl: fld.fold_fn_decl(&*unboxed_function_type.decl),
+ kind: unboxed_function_type.kind,
})
}
OtherRegionTyParamBound(s) => OtherRegionTyParamBound(s)
}
pub fn noop_fold_generics<T: Folder>(generics: &Generics, fld: &mut T) -> Generics {
- Generics {ty_params: fld.fold_ty_params(generics.ty_params.as_slice()),
- lifetimes: fld.fold_lifetime_defs(generics.lifetimes.as_slice())}
+ Generics {
+ ty_params: fld.fold_ty_params(generics.ty_params.as_slice()),
+ lifetimes: fld.fold_lifetime_defs(generics.lifetimes.as_slice()),
+ where_clause: fld.fold_where_clause(&generics.where_clause),
+ }
+}
+
+pub fn noop_fold_where_clause<T: Folder>(
+ where_clause: &WhereClause,
+ fld: &mut T)
+ -> WhereClause {
+ WhereClause {
+ id: fld.new_id(where_clause.id),
+ predicates: where_clause.predicates.iter().map(|predicate| {
+ fld.fold_where_predicate(predicate)
+ }).collect(),
+ }
+}
+
+pub fn noop_fold_where_predicate<T: Folder>(
+ predicate: &WherePredicate,
+ fld: &mut T)
+ -> WherePredicate {
+ WherePredicate {
+ id: fld.new_id(predicate.id),
+ span: fld.new_span(predicate.span),
+ ident: fld.fold_ident(predicate.ident),
+ bounds: predicate.bounds.map(|x| {
+ fld.fold_ty_param_bound(x)
+ }),
+ }
}
pub fn noop_fold_struct_def<T: Folder>(struct_def: Gc<StructDef>,
let struct_def = folder.fold_struct_def(*struct_def);
ItemStruct(struct_def, folder.fold_generics(generics))
}
- ItemImpl(ref generics, ref ifce, ty, ref methods) => {
+ ItemImpl(ref generics, ref ifce, ty, ref impl_items) => {
ItemImpl(folder.fold_generics(generics),
ifce.as_ref().map(|p| folder.fold_trait_ref(p)),
folder.fold_ty(ty),
- methods.iter().flat_map(|x| folder.fold_method(*x).move_iter()).collect()
+ impl_items.iter()
+ .flat_map(|impl_item| {
+ match *impl_item {
+ MethodImplItem(x) => {
+ folder.fold_method(x)
+ .move_iter()
+ .map(|x| MethodImplItem(x))
+ }
+ }
+ }).collect()
)
}
ItemTrait(ref generics, ref unbound, ref traits, ref methods) => {
let methods = methods.iter().flat_map(|method| {
let r = match *method {
- Required(ref m) =>
- SmallVector::one(Required(folder.fold_type_method(m))).move_iter(),
- Provided(method) => {
+ RequiredMethod(ref m) => {
+ SmallVector::one(RequiredMethod(
+ folder.fold_type_method(m))).move_iter()
+ }
+ ProvidedMethod(method) => {
// the awkward collect/iter idiom here is because
// even though an iter and a map satisfy the same trait bound,
// they're not actually the same type, so the method arms
// don't unify.
- let methods : SmallVector<ast::TraitMethod> =
+ let methods : SmallVector<ast::TraitItem> =
folder.fold_method(method).move_iter()
- .map(|m| Provided(m)).collect();
+ .map(|m| ProvidedMethod(m)).collect();
methods.move_iter()
}
};
ExprMatch(folder.fold_expr(expr),
arms.iter().map(|x| folder.fold_arm(x)).collect())
}
- ExprFnBlock(ref decl, ref body) => {
- ExprFnBlock(folder.fold_fn_decl(&**decl),
+ ExprFnBlock(capture_clause, ref decl, ref body) => {
+ ExprFnBlock(capture_clause,
+ folder.fold_fn_decl(&**decl),
folder.fold_block(body.clone()))
}
ExprProc(ref decl, ref body) => {
ExprProc(folder.fold_fn_decl(&**decl),
folder.fold_block(body.clone()))
}
- ExprUnboxedFn(ref decl, ref body) => {
- ExprUnboxedFn(folder.fold_fn_decl(&**decl),
+ ExprUnboxedFn(capture_clause, kind, ref decl, ref body) => {
+ ExprUnboxedFn(capture_clause,
+ kind,
+ folder.fold_fn_decl(&**decl),
folder.fold_block(*body))
}
ExprBlock(ref blk) => ExprBlock(folder.fold_block(*blk)),
use parse::token::{str_to_ident};
use std::char;
+use std::fmt;
use std::mem::replace;
+use std::num;
use std::rc::Rc;
use std::str;
/* cached: */
pub peek_tok: token::Token,
pub peek_span: Span,
+
+ // FIXME (Issue #16472): This field should go away after ToToken impls
+ // are revised to go directly to token-trees.
+ /// Is \x00<name>,<ctxt>\x00 is interpreted as encoded ast::Ident?
+ read_embedded_ident: bool,
}
impl<'a> Reader for StringReader<'a> {
}
}
+// FIXME (Issue #16472): This function should go away after
+// ToToken impls are revised to go directly to token-trees.
+pub fn make_reader_with_embedded_idents<'b>(span_diagnostic: &'b SpanHandler,
+ filemap: Rc<codemap::FileMap>)
+ -> StringReader<'b> {
+ let mut sr = StringReader::new_raw(span_diagnostic, filemap);
+ sr.read_embedded_ident = true;
+ sr.advance_token();
+ sr
+}
+
impl<'a> StringReader<'a> {
/// For comments.rs, which hackily pokes into pos and curr
pub fn new_raw<'b>(span_diagnostic: &'b SpanHandler,
/* dummy values; not read */
peek_tok: token::EOF,
peek_span: codemap::DUMMY_SP,
+ read_embedded_ident: false,
};
sr.bump();
sr
})
}
+ // FIXME (Issue #16472): The scan_embedded_hygienic_ident function
+ // should go away after we revise the syntax::ext::quote::ToToken
+ // impls to go directly to token-trees instead of thing -> string
+ // -> token-trees. (The function is currently used to resolve
+ // Issues #15750 and #15962.)
+ //
+ // Since this function is only used for certain internal macros,
+ // and the functionality it provides is not exposed to end user
+ // programs, pnkfelix deliberately chose to write it in a way that
+ // favors rustc debugging effectiveness over runtime efficiency.
+
+ /// Scan through input of form \x00name_NNNNNN,ctxt_CCCCCCC\x00
+ /// whence: `NNNNNN` is a string of characters forming an integer
+ /// (the name) and `CCCCCCC` is a string of characters forming an
+ /// integer (the ctxt), separate by a comma and delimited by a
+ /// `\x00` marker.
+ #[inline(never)]
+ fn scan_embedded_hygienic_ident(&mut self) -> ast::Ident {
+ fn bump_expecting_char<'a,D:fmt::Show>(r: &mut StringReader<'a>,
+ c: char,
+ described_c: D,
+ whence: &str) {
+ match r.curr {
+ Some(r_c) if r_c == c => r.bump(),
+ Some(r_c) => fail!("expected {}, hit {}, {}", described_c, r_c, whence),
+ None => fail!("expected {}, hit EOF, {}", described_c, whence),
+ }
+ }
+
+ let whence = "while scanning embedded hygienic ident";
+
+ // skip over the leading `\x00`
+ bump_expecting_char(self, '\x00', "nul-byte", whence);
+
+ // skip over the "name_"
+ for c in "name_".chars() {
+ bump_expecting_char(self, c, c, whence);
+ }
+
+ let start_bpos = self.last_pos;
+ let base = 10;
+
+ // find the integer representing the name
+ self.scan_digits(base);
+ let encoded_name : u32 = self.with_str_from(start_bpos, |s| {
+ num::from_str_radix(s, 10).unwrap_or_else(|| {
+ fail!("expected digits representing a name, got `{}`, {}, range [{},{}]",
+ s, whence, start_bpos, self.last_pos);
+ })
+ });
+
+ // skip over the `,`
+ bump_expecting_char(self, ',', "comma", whence);
+
+ // skip over the "ctxt_"
+ for c in "ctxt_".chars() {
+ bump_expecting_char(self, c, c, whence);
+ }
+
+ // find the integer representing the ctxt
+ let start_bpos = self.last_pos;
+ self.scan_digits(base);
+ let encoded_ctxt : ast::SyntaxContext = self.with_str_from(start_bpos, |s| {
+ num::from_str_radix(s, 10).unwrap_or_else(|| {
+ fail!("expected digits representing a ctxt, got `{}`, {}", s, whence);
+ })
+ });
+
+ // skip over the `\x00`
+ bump_expecting_char(self, '\x00', "nul-byte", whence);
+
+ ast::Ident { name: ast::Name(encoded_name),
+ ctxt: encoded_ctxt, }
+ }
+
/// Scan through any digits (base `radix`) or underscores, and return how
/// many digits there were.
fn scan_digits(&mut self, radix: uint) -> uint {
return self.scan_number(c.unwrap());
}
+ if self.read_embedded_ident {
+ match (c.unwrap(), self.nextch(), self.nextnextch()) {
+ ('\x00', Some('n'), Some('a')) => {
+ let ast_ident = self.scan_embedded_hygienic_ident();
+ let is_mod_name = self.curr_is(':') && self.nextch_is(':');
+ return token::IDENT(ast_ident, is_mod_name);
+ }
+ _ => {}
+ }
+ }
+
match c.expect("next_token_inner called at EOF") {
// One-byte tokens.
';' => { self.bump(); return token::SEMI; }
maybe_aborted(p.parse_stmt(attrs),p)
}
+// Note: keep in sync with `with_hygiene::parse_tts_from_source_str`
+// until #16472 is resolved.
pub fn parse_tts_from_source_str(name: String,
source: String,
cfg: ast::CrateConfig,
maybe_aborted(p.parse_all_token_trees(),p)
}
+// Note: keep in sync with `with_hygiene::new_parser_from_source_str`
+// until #16472 is resolved.
// Create a new parser from a source string
pub fn new_parser_from_source_str<'a>(sess: &'a ParseSess,
cfg: ast::CrateConfig,
p
}
+// Note: keep this in sync with `with_hygiene::filemap_to_parser` until
+// #16472 is resolved.
/// Given a filemap and config, return a parser
pub fn filemap_to_parser<'a>(sess: &'a ParseSess,
filemap: Rc<FileMap>,
sess.span_diagnostic.cm.new_filemap(path, source)
}
+// Note: keep this in sync with `with_hygiene::filemap_to_tts` (apart
+// from the StringReader constructor), until #16472 is resolved.
/// Given a filemap, produce a sequence of token-trees
pub fn filemap_to_tts(sess: &ParseSess, filemap: Rc<FileMap>)
-> Vec<ast::TokenTree> {
Parser::new(sess, cfg, box trdr)
}
+// FIXME (Issue #16472): The `with_hygiene` mod should go away after
+// ToToken impls are revised to go directly to token-trees.
+pub mod with_hygiene {
+ use ast;
+ use codemap::FileMap;
+ use parse::parser::Parser;
+ use std::rc::Rc;
+ use super::ParseSess;
+ use super::{maybe_aborted, string_to_filemap, tts_to_parser};
+
+ // Note: keep this in sync with `super::parse_tts_from_source_str` until
+ // #16472 is resolved.
+ pub fn parse_tts_from_source_str(name: String,
+ source: String,
+ cfg: ast::CrateConfig,
+ sess: &ParseSess) -> Vec<ast::TokenTree> {
+ let mut p = new_parser_from_source_str(
+ sess,
+ cfg,
+ name,
+ source
+ );
+ p.quote_depth += 1u;
+ // right now this is re-creating the token trees from ... token trees.
+ maybe_aborted(p.parse_all_token_trees(),p)
+ }
+
+ // Note: keep this in sync with `super::new_parser_from_source_str` until
+ // #16472 is resolved.
+ // Create a new parser from a source string
+ fn new_parser_from_source_str<'a>(sess: &'a ParseSess,
+ cfg: ast::CrateConfig,
+ name: String,
+ source: String) -> Parser<'a> {
+ filemap_to_parser(sess, string_to_filemap(sess, source, name), cfg)
+ }
+
+ // Note: keep this in sync with `super::filemap_to_parserr` until
+ // #16472 is resolved.
+ /// Given a filemap and config, return a parser
+ fn filemap_to_parser<'a>(sess: &'a ParseSess,
+ filemap: Rc<FileMap>,
+ cfg: ast::CrateConfig) -> Parser<'a> {
+ tts_to_parser(sess, filemap_to_tts(sess, filemap), cfg)
+ }
+
+ // Note: keep this in sync with `super::filemap_to_tts` until
+ // #16472 is resolved.
+ /// Given a filemap, produce a sequence of token-trees
+ fn filemap_to_tts(sess: &ParseSess, filemap: Rc<FileMap>)
+ -> Vec<ast::TokenTree> {
+ // it appears to me that the cfg doesn't matter here... indeed,
+ // parsing tt's probably shouldn't require a parser at all.
+ use make_reader = super::lexer::make_reader_with_embedded_idents;
+ let cfg = Vec::new();
+ let srdr = make_reader(&sess.span_diagnostic, filemap);
+ let mut p1 = Parser::new(sess, cfg, box srdr);
+ p1.parse_all_token_trees()
+ }
+}
+
/// Abort if necessary
pub fn maybe_aborted<T>(result: T, mut p: Parser) -> T {
p.abort_if_errors();
ast::Generics{ // no idea on either of these:
lifetimes: Vec::new(),
ty_params: OwnedSlice::empty(),
+ where_clause: ast::WhereClause {
+ id: ast::DUMMY_NODE_ID,
+ predicates: Vec::new(),
+ }
},
ast::P(ast::Block {
view_items: Vec::new(),
use abi;
use ast::{BareFnTy, ClosureTy};
use ast::{StaticRegionTyParamBound, OtherRegionTyParamBound, TraitTyParamBound};
-use ast::{Provided, Public, FnStyle};
+use ast::{ProvidedMethod, Public, FnStyle};
use ast::{Mod, BiAdd, Arg, Arm, Attribute, BindByRef, BindByValue};
use ast::{BiBitAnd, BiBitOr, BiBitXor, Block};
use ast::{BlockCheckMode, UnBox};
+use ast::{CaptureByRef, CaptureByValue, CaptureClause};
use ast::{Crate, CrateConfig, Decl, DeclItem};
use ast::{DeclLocal, DefaultBlock, UnDeref, BiDiv, EMPTY_CTXT, EnumDef, ExplicitSelf};
use ast::{Expr, Expr_, ExprAddrOf, ExprMatch, ExprAgain};
use ast::{ExprVec, ExprVstore, ExprVstoreSlice};
use ast::{ExprVstoreMutSlice, ExprWhile, ExprForLoop, Field, FnDecl};
use ast::{ExprVstoreUniq, Once, Many};
+use ast::{FnUnboxedClosureKind, FnMutUnboxedClosureKind};
+use ast::{FnOnceUnboxedClosureKind};
use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod};
-use ast::{Ident, NormalFn, Inherited, Item, Item_, ItemStatic};
+use ast::{Ident, NormalFn, Inherited, ImplItem, Item, Item_, ItemStatic};
use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl};
use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy, Lit, Lit_};
use ast::{LitBool, LitChar, LitByte, LitBinary};
use ast::{LitNil, LitStr, LitInt, Local, LocalLet};
use ast::{MutImmutable, MutMutable, Mac_, MacInvocTT, Matcher, MatchNonterminal};
use ast::{MatchSeq, MatchTok, Method, MutTy, BiMul, Mutability};
+use ast::{MethodImplItem};
use ast::{NamedField, UnNeg, NoReturn, UnNot, P, Pat, PatEnum};
use ast::{PatIdent, PatLit, PatRange, PatRegion, PatStruct};
use ast::{PatTup, PatBox, PatWild, PatWildMulti, PatWildSingle};
-use ast::{BiRem, Required};
+use ast::{BiRem, RequiredMethod};
use ast::{RetStyle, Return, BiShl, BiShr, Stmt, StmtDecl};
use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField};
use ast::{StructVariantKind, BiSub};
use ast::StrStyle;
use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfValue};
-use ast::{TokenTree, TraitMethod, TraitRef, TTDelim, TTSeq, TTTok};
+use ast::{TokenTree, TraitItem, TraitRef, TTDelim, TTSeq, TTTok};
use ast::{TTNonterminal, TupleVariantKind, Ty, Ty_, TyBot, TyBox};
use ast::{TypeField, TyFixedLengthVec, TyClosure, TyProc, TyBareFn};
use ast::{TyTypeof, TyInfer, TypeMethod};
use ast::{TyNil, TyParam, TyParamBound, TyParen, TyPath, TyPtr, TyRptr};
use ast::{TyTup, TyU32, TyUnboxedFn, TyUniq, TyVec, UnUniq};
-use ast::{UnboxedFnTy, UnboxedFnTyParamBound, UnnamedField, UnsafeBlock};
+use ast::{UnboxedClosureKind, UnboxedFnTy, UnboxedFnTyParamBound};
+use ast::{UnnamedField, UnsafeBlock};
use ast::{UnsafeFn, ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse};
use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
-use ast::Visibility;
+use ast::{Visibility, WhereClause, WherePredicate};
use ast;
use ast_util::{as_prec, ident_to_path, lit_is_str, operator_prec};
use ast_util;
})
}
+ /// Parses an optional unboxed closure kind (`&:`, `&mut:`, or `:`).
+ pub fn parse_optional_unboxed_closure_kind(&mut self)
+ -> Option<UnboxedClosureKind> {
+ if self.token == token::BINOP(token::AND) &&
+ self.look_ahead(1, |t| {
+ token::is_keyword(keywords::Mut, t)
+ }) &&
+ self.look_ahead(2, |t| *t == token::COLON) {
+ self.bump();
+ self.bump();
+ self.bump();
+ return Some(FnMutUnboxedClosureKind)
+ }
+
+ if self.token == token::BINOP(token::AND) &&
+ self.look_ahead(1, |t| *t == token::COLON) {
+ self.bump();
+ self.bump();
+ return Some(FnUnboxedClosureKind)
+ }
+
+ if self.eat(&token::COLON) {
+ return Some(FnOnceUnboxedClosureKind)
+ }
+
+ return None
+ }
+
/// Parse a TyClosure type
pub fn parse_ty_closure(&mut self) -> Ty_ {
/*
Vec::new()
};
- let (is_unboxed, inputs) = if self.eat(&token::OROR) {
- (false, Vec::new())
+ let (optional_unboxed_closure_kind, inputs) = if self.eat(&token::OROR) {
+ (None, Vec::new())
} else {
self.expect_or();
- let is_unboxed = self.token == token::BINOP(token::AND) &&
- self.look_ahead(1, |t| {
- token::is_keyword(keywords::Mut, t)
- }) &&
- self.look_ahead(2, |t| *t == token::COLON);
- if is_unboxed {
- self.bump();
- self.bump();
- self.bump();
- }
+ let optional_unboxed_closure_kind =
+ self.parse_optional_unboxed_closure_kind();
let inputs = self.parse_seq_to_before_or(
&token::COMMA,
|p| p.parse_arg_general(false));
self.expect_or();
- (is_unboxed, inputs)
+ (optional_unboxed_closure_kind, inputs)
};
let (region, bounds) = {
variadic: false
});
- if is_unboxed {
- TyUnboxedFn(box(GC) UnboxedFnTy {
- decl: decl,
- })
- } else {
- TyClosure(box(GC) ClosureTy {
- fn_style: fn_style,
- onceness: onceness,
- bounds: bounds,
- decl: decl,
- lifetimes: lifetime_defs,
- }, region)
+ match optional_unboxed_closure_kind {
+ Some(unboxed_closure_kind) => {
+ TyUnboxedFn(box(GC) UnboxedFnTy {
+ kind: unboxed_closure_kind,
+ decl: decl,
+ })
+ }
+ None => {
+ TyClosure(box(GC) ClosureTy {
+ fn_style: fn_style,
+ onceness: onceness,
+ bounds: bounds,
+ decl: decl,
+ lifetimes: lifetime_defs,
+ }, region)
+ }
}
}
}
/// Parse the methods in a trait declaration
- pub fn parse_trait_methods(&mut self) -> Vec<TraitMethod> {
+ pub fn parse_trait_methods(&mut self) -> Vec<TraitItem> {
self.parse_unspanned_seq(
&token::LBRACE,
&token::RBRACE,
let style = p.parse_fn_style();
let ident = p.parse_ident();
- let generics = p.parse_generics();
+ let mut generics = p.parse_generics();
let (explicit_self, d) = p.parse_fn_decl_with_self(|p| {
// This is somewhat dubious; We don't want to allow argument
p.parse_arg_general(false)
});
+ p.parse_where_clause(&mut generics);
+
let hi = p.last_span.hi;
match p.token {
token::SEMI => {
p.bump();
debug!("parse_trait_methods(): parsing required method");
- Required(TypeMethod {
+ RequiredMethod(TypeMethod {
ident: ident,
attrs: attrs,
fn_style: style,
let (inner_attrs, body) =
p.parse_inner_attrs_and_block();
let attrs = attrs.append(inner_attrs.as_slice());
- Provided(box(GC) ast::Method {
+ ProvidedMethod(box(GC) ast::Method {
attrs: attrs,
id: ast::DUMMY_NODE_ID,
span: mk_sp(lo, hi),
ExprBlock(blk));
},
token::BINOP(token::OR) | token::OROR => {
- return self.parse_lambda_expr();
+ return self.parse_lambda_expr(CaptureByValue);
},
// FIXME #13626: Should be able to stick in
// token::SELF_KEYWORD_NAME
hi = self.last_span.hi;
},
_ => {
+ if self.eat_keyword(keywords::Ref) {
+ return self.parse_lambda_expr(CaptureByRef);
+ }
if self.eat_keyword(keywords::Proc) {
let decl = self.parse_proc_decl();
let body = self.parse_expr();
}
// `|args| expr`
- pub fn parse_lambda_expr(&mut self) -> Gc<Expr> {
+ pub fn parse_lambda_expr(&mut self, capture_clause: CaptureClause)
+ -> Gc<Expr> {
let lo = self.span.lo;
- let (decl, is_unboxed) = self.parse_fn_block_decl();
+ let (decl, optional_unboxed_closure_kind) =
+ self.parse_fn_block_decl();
let body = self.parse_expr();
let fakeblock = P(ast::Block {
view_items: Vec::new(),
span: body.span,
});
- if is_unboxed {
- self.mk_expr(lo, body.span.hi, ExprUnboxedFn(decl, fakeblock))
- } else {
- self.mk_expr(lo, body.span.hi, ExprFnBlock(decl, fakeblock))
+ match optional_unboxed_closure_kind {
+ Some(unboxed_closure_kind) => {
+ self.mk_expr(lo,
+ body.span.hi,
+ ExprUnboxedFn(capture_clause,
+ unboxed_closure_kind,
+ decl,
+ fakeblock))
+ }
+ None => {
+ self.mk_expr(lo,
+ body.span.hi,
+ ExprFnBlock(capture_clause, decl, fakeblock))
+ }
}
}
}
fn parse_unboxed_function_type(&mut self) -> UnboxedFnTy {
- let inputs = if self.eat(&token::OROR) {
- Vec::new()
- } else {
- self.expect_or();
+ let (optional_unboxed_closure_kind, inputs) =
+ if self.eat(&token::OROR) {
+ (None, Vec::new())
+ } else {
+ self.expect_or();
- if self.token == token::BINOP(token::AND) &&
- self.look_ahead(1, |t| {
- token::is_keyword(keywords::Mut, t)
- }) &&
- self.look_ahead(2, |t| *t == token::COLON) {
- self.bump();
- self.bump();
- self.bump();
- }
+ let optional_unboxed_closure_kind =
+ self.parse_optional_unboxed_closure_kind();
- let inputs = self.parse_seq_to_before_or(&token::COMMA,
- |p| {
- p.parse_arg_general(false)
- });
- self.expect_or();
- inputs
- };
+ let inputs = self.parse_seq_to_before_or(&token::COMMA,
+ |p| {
+ p.parse_arg_general(false)
+ });
+ self.expect_or();
+ (optional_unboxed_closure_kind, inputs)
+ };
let (return_style, output) = self.parse_ret_ty();
UnboxedFnTy {
output: output,
cf: return_style,
variadic: false,
- })
+ }),
+ kind: match optional_unboxed_closure_kind {
+ Some(kind) => kind,
+ None => FnMutUnboxedClosureKind,
+ },
}
}
}
}
- /// Parse a set of optional generic type parameter declarations
+ /// Parse a set of optional generic type parameter declarations. Where
+ /// clauses are not parsed here, and must be added later via
+ /// `parse_where_clause()`.
+ ///
/// matches generics = ( ) | ( < > ) | ( < typaramseq ( , )? > ) | ( < lifetimes ( , )? > )
/// | ( < lifetimes , typaramseq ( , )? > )
/// where typaramseq = ( typaram ) | ( typaram , typaramseq )
}
ty_param
});
- ast::Generics { lifetimes: lifetime_defs, ty_params: ty_params }
+ ast::Generics {
+ lifetimes: lifetime_defs,
+ ty_params: ty_params,
+ where_clause: WhereClause {
+ id: ast::DUMMY_NODE_ID,
+ predicates: Vec::new(),
+ }
+ }
} else {
ast_util::empty_generics()
}
}
}
+ /// Parses an optional `where` clause and places it in `generics`.
+ fn parse_where_clause(&mut self, generics: &mut ast::Generics) {
+ if !self.eat_keyword(keywords::Where) {
+ return
+ }
+
+ let mut parsed_something = false;
+ loop {
+ let lo = self.span.lo;
+ let ident = match self.token {
+ token::IDENT(..) => self.parse_ident(),
+ _ => break,
+ };
+ self.expect(&token::COLON);
+
+ let (_, bounds) = self.parse_ty_param_bounds(false);
+ let hi = self.span.hi;
+ let span = mk_sp(lo, hi);
+
+ if bounds.len() == 0 {
+ self.span_err(span,
+ "each predicate in a `where` clause must have \
+ at least one bound in it");
+ }
+
+ generics.where_clause.predicates.push(ast::WherePredicate {
+ id: ast::DUMMY_NODE_ID,
+ span: span,
+ ident: ident,
+ bounds: bounds,
+ });
+ parsed_something = true;
+
+ if !self.eat(&token::COMMA) {
+ break
+ }
+ }
+
+ if !parsed_something {
+ let last_span = self.last_span;
+ self.span_err(last_span,
+ "a `where` clause must have at least one predicate \
+ in it");
+ }
+ }
+
fn parse_fn_args(&mut self, named_args: bool, allow_variadic: bool)
-> (Vec<Arg> , bool) {
let sp = self.span;
}
// parse the |arg, arg| header on a lambda
- fn parse_fn_block_decl(&mut self) -> (P<FnDecl>, bool) {
- let (is_unboxed, inputs_captures) = {
+ fn parse_fn_block_decl(&mut self)
+ -> (P<FnDecl>, Option<UnboxedClosureKind>) {
+ let (optional_unboxed_closure_kind, inputs_captures) = {
if self.eat(&token::OROR) {
- (false, Vec::new())
+ (None, Vec::new())
} else {
self.expect(&token::BINOP(token::OR));
- let is_unboxed = self.token == token::BINOP(token::AND) &&
- self.look_ahead(1, |t| {
- token::is_keyword(keywords::Mut, t)
- }) &&
- self.look_ahead(2, |t| *t == token::COLON);
- if is_unboxed {
- self.bump();
- self.bump();
- self.bump();
- }
+ let optional_unboxed_closure_kind =
+ self.parse_optional_unboxed_closure_kind();
let args = self.parse_seq_to_before_end(
&token::BINOP(token::OR),
seq_sep_trailing_disallowed(token::COMMA),
|p| p.parse_fn_block_arg()
);
self.bump();
- (is_unboxed, args)
+ (optional_unboxed_closure_kind, args)
}
};
let output = if self.eat(&token::RARROW) {
output: output,
cf: Return,
variadic: false
- }), is_unboxed)
+ }), optional_unboxed_closure_kind)
}
/// Parses the `(arg, arg) -> return_type` header on a procedure.
/// Parse an item-position function declaration.
fn parse_item_fn(&mut self, fn_style: FnStyle, abi: abi::Abi) -> ItemInfo {
- let (ident, generics) = self.parse_fn_header();
+ let (ident, mut generics) = self.parse_fn_header();
let decl = self.parse_fn_decl(false);
+ self.parse_where_clause(&mut generics);
let (inner_attrs, body) = self.parse_inner_attrs_and_block();
(ident, ItemFn(decl, fn_style, abi, generics, body), Some(inner_attrs))
}
};
let fn_style = self.parse_fn_style();
let ident = self.parse_ident();
- let generics = self.parse_generics();
+ let mut generics = self.parse_generics();
let (explicit_self, decl) = self.parse_fn_decl_with_self(|p| {
p.parse_arg()
});
+ self.parse_where_clause(&mut generics);
let (inner_attrs, body) = self.parse_inner_attrs_and_block();
let new_attrs = attrs.append(inner_attrs.as_slice());
(ast::MethDecl(ident,
/// Parse trait Foo { ... }
fn parse_item_trait(&mut self) -> ItemInfo {
let ident = self.parse_ident();
- let tps = self.parse_generics();
+ let mut tps = self.parse_generics();
let sized = self.parse_for_sized();
// Parse traits, if necessary.
traits = Vec::new();
}
+ self.parse_where_clause(&mut tps);
+
let meths = self.parse_trait_methods();
(ident, ItemTrait(tps, sized, traits, meths), None)
}
+ fn parse_impl_items(&mut self) -> (Vec<ImplItem>, Vec<Attribute>) {
+ let mut impl_items = Vec::new();
+ self.expect(&token::LBRACE);
+ let (inner_attrs, next) = self.parse_inner_attrs_and_next();
+ let mut method_attrs = Some(next);
+ while !self.eat(&token::RBRACE) {
+ impl_items.push(MethodImplItem(self.parse_method(method_attrs)));
+ method_attrs = None;
+ }
+ (impl_items, inner_attrs)
+ }
+
/// Parses two variants (with the region/type params always optional):
/// impl<T> Foo { ... }
/// impl<T> ToString for ~[T] { ... }
fn parse_item_impl(&mut self) -> ItemInfo {
// First, parse type parameters if necessary.
- let generics = self.parse_generics();
+ let mut generics = self.parse_generics();
// Special case: if the next identifier that follows is '(', don't
// allow this to be parsed as a trait.
None
};
- let mut meths = Vec::new();
- self.expect(&token::LBRACE);
- let (inner_attrs, next) = self.parse_inner_attrs_and_next();
- let mut method_attrs = Some(next);
- while !self.eat(&token::RBRACE) {
- meths.push(self.parse_method(method_attrs));
- method_attrs = None;
- }
+ self.parse_where_clause(&mut generics);
+ let (impl_items, attrs) = self.parse_impl_items();
let ident = ast_util::impl_pretty_name(&opt_trait, &*ty);
- (ident, ItemImpl(generics, opt_trait, ty, meths), Some(inner_attrs))
+ (ident,
+ ItemImpl(generics, opt_trait, ty, impl_items),
+ Some(attrs))
}
/// Parse a::B<String,int>
/// Parse struct Foo { ... }
fn parse_item_struct(&mut self, is_virtual: bool) -> ItemInfo {
let class_name = self.parse_ident();
- let generics = self.parse_generics();
+ let mut generics = self.parse_generics();
let super_struct = if self.eat(&token::COLON) {
let ty = self.parse_ty(true);
None
};
+ self.parse_where_clause(&mut generics);
+
let mut fields: Vec<StructField>;
let is_tuple_like;
let lo = self.span.lo;
self.expect_keyword(keywords::Fn);
- let (ident, generics) = self.parse_fn_header();
+ let (ident, mut generics) = self.parse_fn_header();
let decl = self.parse_fn_decl(true);
+ self.parse_where_clause(&mut generics);
let hi = self.span.hi;
self.expect(&token::SEMI);
box(GC) ast::ForeignItem { ident: ident,
/// Parse type Foo = Bar;
fn parse_item_type(&mut self) -> ItemInfo {
let ident = self.parse_ident();
- let tps = self.parse_generics();
+ let mut tps = self.parse_generics();
+ self.parse_where_clause(&mut tps);
self.expect(&token::EQ);
let ty = self.parse_ty(true);
self.expect(&token::SEMI);
/// Parse an "enum" declaration
fn parse_item_enum(&mut self) -> ItemInfo {
let id = self.parse_ident();
- let generics = self.parse_generics();
+ let mut generics = self.parse_generics();
+ self.parse_where_clause(&mut generics);
self.expect(&token::LBRACE);
let enum_definition = self.parse_enum_def(&generics);
match self.token {
token::EQ => {
// x = foo::bar
+ // NOTE(stage0, #16461, pcwalton): Deprecate after snapshot.
self.bump();
let path_lo = self.span.lo;
path = vec!(self.parse_ident());
}
_ => ()
}
- let last = *path.get(path.len() - 1u);
+ let mut rename_to = *path.get(path.len() - 1u);
let path = ast::Path {
span: mk_sp(lo, self.span.hi),
global: false,
}
}).collect()
};
+ if self.eat_keyword(keywords::As) {
+ rename_to = self.parse_ident()
+ }
return box(GC) spanned(lo,
self.last_span.hi,
- ViewPathSimple(last, path, ast::DUMMY_NODE_ID));
+ ViewPathSimple(rename_to, path, ast::DUMMY_NODE_ID));
}
/// Parses a sequence of items. Stops when it finds program
(41, Proc, "proc");
(42, Box, "box");
(43, Const, "const");
+ (44, Where, "where");
'reserved:
- (44, Alignof, "alignof");
- (45, Be, "be");
- (46, Offsetof, "offsetof");
- (47, Priv, "priv");
- (48, Pure, "pure");
- (49, Sizeof, "sizeof");
- (50, Typeof, "typeof");
- (51, Unsized, "unsized");
- (52, Yield, "yield");
- (53, Do, "do");
+ (45, Alignof, "alignof");
+ (46, Be, "be");
+ (47, Offsetof, "offsetof");
+ (48, Priv, "priv");
+ (49, Pure, "pure");
+ (50, Sizeof, "sizeof");
+ (51, Typeof, "typeof");
+ (52, Unsized, "unsized");
+ (53, Yield, "yield");
+ (54, Do, "do");
}
}
// except according to those terms.
use abi;
-use ast::{P, StaticRegionTyParamBound, OtherRegionTyParamBound};
-use ast::{TraitTyParamBound, UnboxedFnTyParamBound, Required, Provided};
+use ast::{FnMutUnboxedClosureKind, FnOnceUnboxedClosureKind};
+use ast::{FnUnboxedClosureKind, MethodImplItem, P, OtherRegionTyParamBound};
+use ast::{StaticRegionTyParamBound, TraitTyParamBound, UnboxedClosureKind};
+use ast::{UnboxedFnTyParamBound, RequiredMethod, ProvidedMethod};
use ast;
use ast_util;
use owned_slice::OwnedSlice;
literals: Option<Vec<comments::Literal> >,
cur_cmnt_and_lit: CurrentCommentAndLiteral,
boxes: Vec<pp::Breaks>,
- ann: &'a PpAnn
+ ann: &'a PpAnn,
+ encode_idents_with_hygiene: bool,
}
pub fn rust_printer(writer: Box<io::Writer>) -> State<'static> {
cur_lit: 0
},
boxes: Vec::new(),
- ann: ann
+ ann: ann,
+ encode_idents_with_hygiene: false,
}
}
cur_lit: 0
},
boxes: Vec::new(),
- ann: ann
+ ann: ann,
+ encode_idents_with_hygiene: false,
}
}
}
}
}
+// FIXME (Issue #16472): the thing_to_string_impls macro should go away
+// after we revise the syntax::ext::quote::ToToken impls to go directly
+// to token-trees instea of thing -> string -> token-trees.
+
+macro_rules! thing_to_string_impls {
+ ($to_string:ident) => {
+
pub fn ty_to_string(ty: &ast::Ty) -> String {
- to_string(|s| s.print_type(ty))
+ $to_string(|s| s.print_type(ty))
}
pub fn pat_to_string(pat: &ast::Pat) -> String {
- to_string(|s| s.print_pat(pat))
+ $to_string(|s| s.print_pat(pat))
}
pub fn arm_to_string(arm: &ast::Arm) -> String {
- to_string(|s| s.print_arm(arm))
+ $to_string(|s| s.print_arm(arm))
}
pub fn expr_to_string(e: &ast::Expr) -> String {
- to_string(|s| s.print_expr(e))
+ $to_string(|s| s.print_expr(e))
}
pub fn lifetime_to_string(e: &ast::Lifetime) -> String {
- to_string(|s| s.print_lifetime(e))
+ $to_string(|s| s.print_lifetime(e))
}
pub fn tt_to_string(tt: &ast::TokenTree) -> String {
- to_string(|s| s.print_tt(tt))
+ $to_string(|s| s.print_tt(tt))
}
pub fn tts_to_string(tts: &[ast::TokenTree]) -> String {
- to_string(|s| s.print_tts(tts))
+ $to_string(|s| s.print_tts(tts))
}
pub fn stmt_to_string(stmt: &ast::Stmt) -> String {
- to_string(|s| s.print_stmt(stmt))
+ $to_string(|s| s.print_stmt(stmt))
}
pub fn item_to_string(i: &ast::Item) -> String {
- to_string(|s| s.print_item(i))
+ $to_string(|s| s.print_item(i))
}
pub fn generics_to_string(generics: &ast::Generics) -> String {
- to_string(|s| s.print_generics(generics))
+ $to_string(|s| s.print_generics(generics))
}
pub fn ty_method_to_string(p: &ast::TypeMethod) -> String {
- to_string(|s| s.print_ty_method(p))
+ $to_string(|s| s.print_ty_method(p))
}
pub fn method_to_string(p: &ast::Method) -> String {
- to_string(|s| s.print_method(p))
+ $to_string(|s| s.print_method(p))
}
pub fn fn_block_to_string(p: &ast::FnDecl) -> String {
- to_string(|s| s.print_fn_block_args(p, false))
+ $to_string(|s| s.print_fn_block_args(p, None))
}
pub fn path_to_string(p: &ast::Path) -> String {
- to_string(|s| s.print_path(p, false))
+ $to_string(|s| s.print_path(p, false))
}
pub fn ident_to_string(id: &ast::Ident) -> String {
- to_string(|s| s.print_ident(*id))
+ $to_string(|s| s.print_ident(*id))
}
pub fn fun_to_string(decl: &ast::FnDecl, fn_style: ast::FnStyle, name: ast::Ident,
opt_explicit_self: Option<ast::ExplicitSelf_>,
generics: &ast::Generics) -> String {
- to_string(|s| {
+ $to_string(|s| {
try!(s.print_fn(decl, Some(fn_style), abi::Rust,
name, generics, opt_explicit_self, ast::Inherited));
try!(s.end()); // Close the head box
}
pub fn block_to_string(blk: &ast::Block) -> String {
- to_string(|s| {
+ $to_string(|s| {
// containing cbox, will be closed by print-block at }
try!(s.cbox(indent_unit));
// head-ibox, will be closed by print-block after {
}
pub fn meta_item_to_string(mi: &ast::MetaItem) -> String {
- to_string(|s| s.print_meta_item(mi))
+ $to_string(|s| s.print_meta_item(mi))
}
pub fn attribute_to_string(attr: &ast::Attribute) -> String {
- to_string(|s| s.print_attribute(attr))
+ $to_string(|s| s.print_attribute(attr))
}
pub fn lit_to_string(l: &ast::Lit) -> String {
- to_string(|s| s.print_literal(l))
+ $to_string(|s| s.print_literal(l))
}
pub fn explicit_self_to_string(explicit_self: ast::ExplicitSelf_) -> String {
- to_string(|s| s.print_explicit_self(explicit_self, ast::MutImmutable).map(|_| {}))
+ $to_string(|s| s.print_explicit_self(explicit_self, ast::MutImmutable).map(|_| {}))
}
pub fn variant_to_string(var: &ast::Variant) -> String {
- to_string(|s| s.print_variant(var))
+ $to_string(|s| s.print_variant(var))
}
pub fn arg_to_string(arg: &ast::Arg) -> String {
- to_string(|s| s.print_arg(arg))
+ $to_string(|s| s.print_arg(arg))
}
pub fn mac_to_string(arg: &ast::Mac) -> String {
- to_string(|s| s.print_mac(arg))
+ $to_string(|s| s.print_mac(arg))
+}
+
+} }
+
+thing_to_string_impls!(to_string)
+
+// FIXME (Issue #16472): the whole `with_hygiene` mod should go away
+// after we revise the syntax::ext::quote::ToToken impls to go directly
+// to token-trees instea of thing -> string -> token-trees.
+
+pub mod with_hygiene {
+ use abi;
+ use ast;
+ use std::io::IoResult;
+ use super::indent_unit;
+
+ // This function is the trick that all the rest of the routines
+ // hang on.
+ pub fn to_string_hyg(f: |&mut super::State| -> IoResult<()>) -> String {
+ super::to_string(|s| {
+ s.encode_idents_with_hygiene = true;
+ f(s)
+ })
+ }
+
+ thing_to_string_impls!(to_string_hyg)
}
pub fn visibility_qualified(vis: ast::Visibility, s: &str) -> String {
ast::TyBareFn(f) => {
let generics = ast::Generics {
lifetimes: f.lifetimes.clone(),
- ty_params: OwnedSlice::empty()
+ ty_params: OwnedSlice::empty(),
+ where_clause: ast::WhereClause {
+ id: ast::DUMMY_NODE_ID,
+ predicates: Vec::new(),
+ },
};
try!(self.print_ty_fn(Some(f.abi),
None,
&None,
Some(&generics),
None,
- false));
+ None));
}
ast::TyClosure(f, ref region) => {
let generics = ast::Generics {
lifetimes: f.lifetimes.clone(),
- ty_params: OwnedSlice::empty()
+ ty_params: OwnedSlice::empty(),
+ where_clause: ast::WhereClause {
+ id: ast::DUMMY_NODE_ID,
+ predicates: Vec::new(),
+ },
};
try!(self.print_ty_fn(None,
Some('&'),
&f.bounds,
Some(&generics),
None,
- false));
+ None));
}
ast::TyProc(ref f) => {
let generics = ast::Generics {
lifetimes: f.lifetimes.clone(),
- ty_params: OwnedSlice::empty()
+ ty_params: OwnedSlice::empty(),
+ where_clause: ast::WhereClause {
+ id: ast::DUMMY_NODE_ID,
+ predicates: Vec::new(),
+ },
};
try!(self.print_ty_fn(None,
Some('~'),
&f.bounds,
Some(&generics),
None,
- false));
+ None));
}
ast::TyUnboxedFn(f) => {
try!(self.print_ty_fn(None,
&None,
None,
None,
- true));
+ Some(f.kind)));
}
ast::TyPath(ref path, ref bounds, _) => {
try!(self.print_bounded_path(path, bounds));
try!(space(&mut self.s));
try!(self.word_space("="));
try!(self.print_type(&**ty));
+ try!(self.print_where_clause(params));
try!(word(&mut self.s, ";"));
try!(self.end()); // end the outer ibox
}
item.span));
}
- ast::ItemImpl(ref generics, ref opt_trait, ref ty, ref methods) => {
+ ast::ItemImpl(ref generics,
+ ref opt_trait,
+ ref ty,
+ ref impl_items) => {
try!(self.head(visibility_qualified(item.vis,
"impl").as_slice()));
if generics.is_parameterized() {
}
try!(self.print_type(&**ty));
+ try!(self.print_where_clause(generics));
try!(space(&mut self.s));
try!(self.bopen());
try!(self.print_inner_attributes(item.attrs.as_slice()));
- for meth in methods.iter() {
- try!(self.print_method(&**meth));
+ for impl_item in impl_items.iter() {
+ match *impl_item {
+ ast::MethodImplItem(meth) => {
+ try!(self.print_method(&*meth));
+ }
+ }
}
try!(self.bclose(item.span));
}
try!(self.print_path(&trait_.path, false));
}
}
+ try!(self.print_where_clause(generics));
try!(word(&mut self.s, " "));
try!(self.bopen());
for meth in methods.iter() {
try!(self.head(visibility_qualified(visibility, "enum").as_slice()));
try!(self.print_ident(ident));
try!(self.print_generics(generics));
+ try!(self.print_where_clause(generics));
try!(space(&mut self.s));
self.print_variants(enum_definition.variants.as_slice(), span)
}
&None,
Some(&m.generics),
Some(m.explicit_self.node),
- false));
+ None));
word(&mut self.s, ";")
}
pub fn print_trait_method(&mut self,
- m: &ast::TraitMethod) -> IoResult<()> {
+ m: &ast::TraitItem) -> IoResult<()> {
match *m {
- Required(ref ty_m) => self.print_ty_method(ty_m),
- Provided(ref m) => self.print_method(&**m)
+ RequiredMethod(ref ty_m) => self.print_ty_method(ty_m),
+ ProvidedMethod(ref m) => self.print_method(&**m)
+ }
+ }
+
+ pub fn print_impl_item(&mut self, ii: &ast::ImplItem) -> IoResult<()> {
+ match *ii {
+ MethodImplItem(ref m) => self.print_method(&**m),
}
}
}
try!(self.bclose_(expr.span, indent_unit));
}
- ast::ExprFnBlock(ref decl, ref body) => {
+ ast::ExprFnBlock(capture_clause, ref decl, ref body) => {
+ try!(self.print_capture_clause(capture_clause));
+
// in do/for blocks we don't want to show an empty
// argument list, but at this point we don't know which
// we are inside.
//
// if !decl.inputs.is_empty() {
- try!(self.print_fn_block_args(&**decl, false));
+ try!(self.print_fn_block_args(&**decl, None));
try!(space(&mut self.s));
// }
// empty box to satisfy the close.
try!(self.ibox(0));
}
- ast::ExprUnboxedFn(ref decl, ref body) => {
+ ast::ExprUnboxedFn(capture_clause, kind, ref decl, ref body) => {
+ try!(self.print_capture_clause(capture_clause));
+
// in do/for blocks we don't want to show an empty
// argument list, but at this point we don't know which
// we are inside.
//
// if !decl.inputs.is_empty() {
- try!(self.print_fn_block_args(&**decl, true));
+ try!(self.print_fn_block_args(&**decl, Some(kind)));
try!(space(&mut self.s));
// }
}
pub fn print_ident(&mut self, ident: ast::Ident) -> IoResult<()> {
- word(&mut self.s, token::get_ident(ident).get())
+ if self.encode_idents_with_hygiene {
+ let encoded = ident.encode_with_hygiene();
+ word(&mut self.s, encoded.as_slice())
+ } else {
+ word(&mut self.s, token::get_ident(ident).get())
+ }
}
pub fn print_name(&mut self, name: ast::Name) -> IoResult<()> {
try!(self.nbsp());
try!(self.print_ident(name));
try!(self.print_generics(generics));
- self.print_fn_args_and_ret(decl, opt_explicit_self)
+ try!(self.print_fn_args_and_ret(decl, opt_explicit_self))
+ self.print_where_clause(generics)
}
pub fn print_fn_args(&mut self, decl: &ast::FnDecl,
}
}
- pub fn print_fn_block_args(&mut self,
- decl: &ast::FnDecl,
- is_unboxed: bool)
- -> IoResult<()> {
+ pub fn print_fn_block_args(
+ &mut self,
+ decl: &ast::FnDecl,
+ unboxed_closure_kind: Option<UnboxedClosureKind>)
+ -> IoResult<()> {
try!(word(&mut self.s, "|"));
- if is_unboxed {
- try!(self.word_space("&mut:"));
+ match unboxed_closure_kind {
+ None => {}
+ Some(FnUnboxedClosureKind) => try!(self.word_space("&:")),
+ Some(FnMutUnboxedClosureKind) => try!(self.word_space("&mut:")),
+ Some(FnOnceUnboxedClosureKind) => try!(self.word_space(":")),
}
try!(self.print_fn_args(decl, None));
try!(word(&mut self.s, "|"));
self.maybe_print_comment(decl.output.span.lo)
}
+ pub fn print_capture_clause(&mut self, capture_clause: ast::CaptureClause)
+ -> IoResult<()> {
+ match capture_clause {
+ ast::CaptureByValue => Ok(()),
+ ast::CaptureByRef => self.word_space("ref"),
+ }
+ }
+
pub fn print_proc_args(&mut self, decl: &ast::FnDecl) -> IoResult<()> {
try!(word(&mut self.s, "proc"));
try!(word(&mut self.s, "("));
&None,
None,
None,
- true)
+ Some(unboxed_function_type.kind))
}
OtherRegionTyParamBound(_) => Ok(())
})
Ok(())
}
- pub fn print_generics(&mut self,
- generics: &ast::Generics) -> IoResult<()> {
- let total = generics.lifetimes.len() + generics.ty_params.len();
- if total > 0 {
- try!(word(&mut self.s, "<"));
+ fn print_type_parameters(&mut self,
+ lifetimes: &[ast::LifetimeDef],
+ ty_params: &[ast::TyParam])
+ -> IoResult<()> {
+ let total = lifetimes.len() + ty_params.len();
+ let mut ints = Vec::new();
+ for i in range(0u, total) {
+ ints.push(i);
+ }
- let mut ints = Vec::new();
- for i in range(0u, total) {
- ints.push(i);
- }
-
- try!(self.commasep(
- Inconsistent, ints.as_slice(),
- |s, &idx| {
- if idx < generics.lifetimes.len() {
- let lifetime = generics.lifetimes.get(idx);
- s.print_lifetime_def(lifetime)
- } else {
- let idx = idx - generics.lifetimes.len();
- let param = generics.ty_params.get(idx);
- match param.unbound {
- Some(TraitTyParamBound(ref tref)) => {
- try!(s.print_trait_ref(tref));
- try!(s.word_space("?"));
- }
- _ => {}
- }
- try!(s.print_ident(param.ident));
- try!(s.print_bounds(&None,
- ¶m.bounds,
- false,
- false));
- match param.default {
- Some(ref default) => {
- try!(space(&mut s.s));
- try!(s.word_space("="));
- s.print_type(&**default)
- }
- _ => Ok(())
- }
+ self.commasep(Inconsistent, ints.as_slice(), |s, &idx| {
+ if idx < lifetimes.len() {
+ let lifetime = &lifetimes[idx];
+ s.print_lifetime_def(lifetime)
+ } else {
+ let idx = idx - lifetimes.len();
+ let param = &ty_params[idx];
+ match param.unbound {
+ Some(TraitTyParamBound(ref tref)) => {
+ try!(s.print_trait_ref(tref));
+ try!(s.word_space("?"));
}
- }));
+ _ => {}
+ }
+ try!(s.print_ident(param.ident));
+ try!(s.print_bounds(&None,
+ ¶m.bounds,
+ false,
+ false));
+ match param.default {
+ Some(ref default) => {
+ try!(space(&mut s.s));
+ try!(s.word_space("="));
+ s.print_type(&**default)
+ }
+ _ => Ok(())
+ }
+ }
+ })
+ }
+
+ pub fn print_generics(&mut self, generics: &ast::Generics)
+ -> IoResult<()> {
+ if generics.lifetimes.len() + generics.ty_params.len() > 0 {
+ try!(word(&mut self.s, "<"));
+ try!(self.print_type_parameters(generics.lifetimes.as_slice(),
+ generics.ty_params.as_slice()));
word(&mut self.s, ">")
} else {
Ok(())
}
}
+ pub fn print_where_clause(&mut self, generics: &ast::Generics)
+ -> IoResult<()> {
+ if generics.where_clause.predicates.len() == 0 {
+ return Ok(())
+ }
+
+ try!(space(&mut self.s));
+ try!(self.word_space("where"));
+
+ for (i, predicate) in generics.where_clause
+ .predicates
+ .iter()
+ .enumerate() {
+ if i != 0 {
+ try!(self.word_space(","));
+ }
+
+ try!(self.print_ident(predicate.ident));
+ try!(self.print_bounds(&None, &predicate.bounds, false, false));
+ }
+
+ Ok(())
+ }
+
pub fn print_meta_item(&mut self, item: &ast::MetaItem) -> IoResult<()> {
try!(self.ibox(indent_unit));
match item.node {
pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> IoResult<()> {
match vp.node {
ast::ViewPathSimple(ident, ref path, _) => {
+ try!(self.print_path(path, false));
+
// FIXME(#6993) can't compare identifiers directly here
- if path.segments.last().unwrap().identifier.name != ident.name {
- try!(self.print_ident(ident));
+ if path.segments.last().unwrap().identifier.name !=
+ ident.name {
try!(space(&mut self.s));
- try!(self.word_space("="));
+ try!(self.word_space("as"));
+ try!(self.print_ident(ident));
}
- self.print_path(path, false)
+
+ Ok(())
}
ast::ViewPathGlob(ref path, _) => {
opt_bounds: &Option<OwnedSlice<ast::TyParamBound>>,
generics: Option<&ast::Generics>,
opt_explicit_self: Option<ast::ExplicitSelf_>,
- is_unboxed: bool)
+ opt_unboxed_closure_kind:
+ Option<ast::UnboxedClosureKind>)
-> IoResult<()> {
try!(self.ibox(indent_unit));
try!(self.print_fn_style(fn_style));
try!(self.print_opt_abi_and_extern_if_nondefault(opt_abi));
try!(self.print_onceness(onceness));
- if !is_unboxed {
+ if opt_unboxed_closure_kind.is_none() {
try!(word(&mut self.s, "fn"));
}
}
match generics { Some(g) => try!(self.print_generics(g)), _ => () }
try!(zerobreak(&mut self.s));
- if is_unboxed || opt_sigil == Some('&') {
+ if opt_unboxed_closure_kind.is_some() || opt_sigil == Some('&') {
try!(word(&mut self.s, "|"));
} else {
try!(self.popen());
}
- if is_unboxed {
- try!(word(&mut self.s, "&mut"));
- try!(self.word_space(":"));
+ match opt_unboxed_closure_kind {
+ Some(ast::FnUnboxedClosureKind) => {
+ try!(word(&mut self.s, "&"));
+ try!(self.word_space(":"));
+ }
+ Some(ast::FnMutUnboxedClosureKind) => {
+ try!(word(&mut self.s, "&mut"));
+ try!(self.word_space(":"));
+ }
+ Some(ast::FnOnceUnboxedClosureKind) => {
+ try!(self.word_space(":"));
+ }
+ None => {}
}
try!(self.print_fn_args(decl, opt_explicit_self));
- if is_unboxed || opt_sigil == Some('&') {
+ if opt_unboxed_closure_kind.is_some() || opt_sigil == Some('&') {
try!(word(&mut self.s, "|"));
} else {
if decl.variadic {
}
}
+ match generics {
+ Some(generics) => try!(self.print_where_clause(generics)),
+ None => {}
+ }
+
self.end()
}
use abi::Abi;
use ast::*;
use ast;
+use ast_util;
use codemap::Span;
use parse;
use owned_slice::OwnedSlice;
FkMethod(_, generics, _) => {
(*generics).clone()
}
- FkFnBlock(..) => {
- Generics {
- lifetimes: Vec::new(),
- ty_params: OwnedSlice::empty(),
- }
- }
+ FkFnBlock(..) => ast_util::empty_generics(),
}
}
walk_fn(self, fk, fd, b, s, e)
}
fn visit_ty_method(&mut self, t: &TypeMethod, e: E) { walk_ty_method(self, t, e) }
- fn visit_trait_method(&mut self, t: &TraitMethod, e: E) { walk_trait_method(self, t, e) }
+ fn visit_trait_item(&mut self, t: &TraitItem, e: E) { walk_trait_item(self, t, e) }
fn visit_struct_def(&mut self, s: &StructDef, _: Ident, _: &Generics, _: NodeId, e: E) {
walk_struct_def(self, s, e)
}
match *item {
IIItem(i) => visitor.visit_item(&*i, env),
IIForeign(i) => visitor.visit_foreign_item(&*i, env),
- IIMethod(_, _, m) => walk_method_helper(visitor, &*m, env),
+ IITraitItem(_, iti) => {
+ match iti {
+ ProvidedInlinedTraitItem(m) => {
+ walk_method_helper(visitor, &*m, env)
+ }
+ RequiredInlinedTraitItem(m) => {
+ walk_method_helper(visitor, &*m, env)
+ }
+ }
+ }
}
}
ItemImpl(ref type_parameters,
ref trait_reference,
typ,
- ref methods) => {
+ ref impl_items) => {
visitor.visit_generics(type_parameters, env.clone());
match *trait_reference {
Some(ref trait_reference) => walk_trait_ref_helper(visitor,
None => ()
}
visitor.visit_ty(&*typ, env.clone());
- for method in methods.iter() {
- walk_method_helper(visitor, &**method, env.clone())
+ for impl_item in impl_items.iter() {
+ match *impl_item {
+ MethodImplItem(method) => {
+ walk_method_helper(visitor, &*method, env.clone())
+ }
+ }
}
}
ItemStruct(ref struct_definition, ref generics) => {
env.clone())
}
for method in methods.iter() {
- visitor.visit_trait_method(method, env.clone())
+ visitor.visit_trait_item(method, env.clone())
}
}
ItemMac(ref macro) => visitor.visit_mac(macro, env.clone()),
None => {}
}
}
- walk_lifetime_decls(visitor, &generics.lifetimes, env);
+ walk_lifetime_decls(visitor, &generics.lifetimes, env.clone());
+ for predicate in generics.where_clause.predicates.iter() {
+ visitor.visit_ident(predicate.span, predicate.ident, env.clone());
+ walk_ty_param_bounds(visitor, &predicate.bounds, env.clone());
+ }
}
pub fn walk_fn_decl<E: Clone, V: Visitor<E>>(visitor: &mut V,
}
}
-pub fn walk_trait_method<E: Clone, V: Visitor<E>>(visitor: &mut V,
- trait_method: &TraitMethod,
+pub fn walk_trait_item<E: Clone, V: Visitor<E>>(visitor: &mut V,
+ trait_method: &TraitItem,
env: E) {
match *trait_method {
- Required(ref method_type) => {
+ RequiredMethod(ref method_type) => {
visitor.visit_ty_method(method_type, env)
}
- Provided(ref method) => walk_method_helper(visitor, &**method, env),
+ ProvidedMethod(ref method) => walk_method_helper(visitor, &**method, env),
}
}
visitor.visit_arm(arm, env.clone())
}
}
- ExprFnBlock(ref function_declaration, ref body) => {
+ ExprFnBlock(_, ref function_declaration, ref body) => {
visitor.visit_fn(&FkFnBlock,
&**function_declaration,
&**body,
expression.id,
env.clone())
}
- ExprUnboxedFn(ref function_declaration, ref body) => {
+ ExprUnboxedFn(_, _, ref function_declaration, ref body) => {
visitor.visit_fn(&FkFnBlock,
&**function_declaration,
&**body,
use core::cmp::{Equal, Less, Greater};
use core::option::{Option, Some, None};
-use core::slice::ImmutableVector;
+use core::slice;
+use core::slice::ImmutableSlice;
use tables::normalization::{canonical_table, compatibility_table, composition_table};
fn bsearch_table<T>(c: char, r: &'static [(char, &'static [T])]) -> Option<&'static [T]> {
- match r.bsearch(|&(val, _)| {
+ match r.binary_search(|&(val, _)| {
if c == val { Equal }
else if val < c { Less }
else { Greater }
}) {
- Some(idx) => {
+ slice::Found(idx) => {
let (_, result) = r[idx];
Some(result)
}
- None => None
+ slice::NotFound(_) => None
}
}
match bsearch_table(a, composition_table) {
None => None,
Some(candidates) => {
- match candidates.bsearch(|&(val, _)| {
+ match candidates.binary_search(|&(val, _)| {
if b == val { Equal }
else if val < b { Less }
else { Greater }
}) {
- Some(idx) => {
+ slice::Found(idx) => {
let (_, result) = candidates[idx];
Some(result)
}
- None => None
+ slice::NotFound(_) => None
}
}
}
fn bsearch_range_table(c: char, r: &'static [(char,char)]) -> bool {
use core::cmp::{Equal, Less, Greater};
- use core::slice::ImmutableVector;
- use core::option::None;
- r.bsearch(|&(lo,hi)| {
+ use core::slice::ImmutableSlice;
+ r.binary_search(|&(lo,hi)| {
if lo <= c && c <= hi { Equal }
else if hi < c { Less }
else { Greater }
- }) != None
+ }).found().is_some()
}
pub mod general_category {
fn bsearch_range_value_table(c: char, r: &'static [(char, char, u8)]) -> u8 {
- use core::option::{Some, None};
use core::cmp::{Equal, Less, Greater};
- use core::slice::ImmutableVector;
- match r.bsearch(|&(lo, hi, _)| {
+ use core::slice::ImmutableSlice;
+ use core::slice;
+ match r.binary_search(|&(lo, hi, _)| {
if lo <= c && c <= hi { Equal }
else if hi < c { Less }
else { Greater }
}) {
- Some(idx) => {
+ slice::Found(idx) => {
let (_, _, result) = r[idx];
result
}
- None => 0
+ slice::NotFound(_) => 0
}
}
pub mod conversions {
use core::cmp::{Equal, Less, Greater};
- use core::slice::ImmutableVector;
+ use core::slice::ImmutableSlice;
use core::tuple::Tuple2;
use core::option::{Option, Some, None};
+ use core::slice;
pub fn to_lower(c: char) -> char {
match bsearch_case_table(c, LuLl_table) {
}
fn bsearch_case_table(c: char, table: &'static [(char, char)]) -> Option<uint> {
- table.bsearch(|&(key, _)| {
+ match table.binary_search(|&(key, _)| {
if c == key { Equal }
else if key < c { Less }
else { Greater }
- })
+ }) {
+ slice::Found(i) => Some(i),
+ slice::NotFound(_) => None,
+ }
}
static LuLl_table: &'static [(char, char)] = &[
pub mod charwidth {
use core::option::{Option, Some, None};
- use core::slice::ImmutableVector;
+ use core::slice::ImmutableSlice;
+ use core::slice;
fn bsearch_range_value_table(c: char, is_cjk: bool, r: &'static [(char, char, u8, u8)]) -> u8 {
use core::cmp::{Equal, Less, Greater};
- match r.bsearch(|&(lo, hi, _, _)| {
+ match r.binary_search(|&(lo, hi, _, _)| {
if lo <= c && c <= hi { Equal }
else if hi < c { Less }
else { Greater }
}) {
- Some(idx) => {
+ slice::Found(idx) => {
let (_, _, r_ncjk, r_cjk) = r[idx];
if is_cjk { r_cjk } else { r_ncjk }
}
- None => 1
+ slice::NotFound(_) => 1
}
}
}
pub mod grapheme {
- use core::option::{Some, None};
- use core::slice::ImmutableVector;
+ use core::slice::ImmutableSlice;
+ use core::slice;
#[allow(non_camel_case_types)]
#[deriving(Clone)]
fn bsearch_range_value_table(c: char, r: &'static [(char, char, GraphemeCat)]) -> GraphemeCat {
use core::cmp::{Equal, Less, Greater};
- match r.bsearch(|&(lo, hi, _)| {
+ match r.binary_search(|&(lo, hi, _)| {
if lo <= c && c <= hi { Equal }
else if hi < c { Less }
else { Greater }
}) {
- Some(idx) => {
+ slice::Found(idx) => {
let (_, _, cat) = r[idx];
cat
}
- None => GC_Any
+ slice::NotFound(_) => GC_Any
}
}
}
fn split_char_first(s: &str, c: char) -> (&str, &str) {
- let mut iter = s.splitn(c, 1);
+ let mut iter = s.splitn(1, c);
match (iter.next(), iter.next()) {
(Some(a), Some(b)) => (a, b),
use syntax::codemap::Span;
use syntax::ext::base::*;
use syntax::parse::token;
+use syntax::parse;
use rustc::plugin::Registry;
use std::gc::{Gc, GC};
#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
reg.register_macro("make_a_1", expand_make_a_1);
+ reg.register_macro("forged_ident", expand_forged_ident);
+ reg.register_macro("identity", expand_identity);
reg.register_syntax_extension(
token::intern("into_foo"),
ItemModifier(expand_into_foo));
MacExpr::new(quote_expr!(cx, 1i))
}
+// See Issue #15750
+fn expand_identity(cx: &mut ExtCtxt, _span: Span, tts: &[TokenTree])
+ -> Box<MacResult> {
+ // Parse an expression and emit it unchanged.
+ let mut parser = parse::new_parser_from_tts(cx.parse_sess(),
+ cx.cfg(), Vec::from_slice(tts));
+ let expr = parser.parse_expr();
+ MacExpr::new(quote_expr!(&mut *cx, $expr))
+}
+
fn expand_into_foo(cx: &mut ExtCtxt, sp: Span, attr: Gc<MetaItem>, it: Gc<Item>)
-> Gc<Item> {
box(GC) Item {
}
}
+fn expand_forged_ident(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult> {
+ use syntax::ext::quote::rt::*;
+
+ if !tts.is_empty() {
+ cx.span_fatal(sp, "forged_ident takes no arguments");
+ }
+
+ // Most of this is modelled after the expansion of the `quote_expr!`
+ // macro ...
+ let parse_sess = cx.parse_sess();
+ let cfg = cx.cfg();
+
+ // ... except this is where we inject a forged identifier,
+ // and deliberately do not call `cx.parse_tts_with_hygiene`
+ // (because we are testing that this will be *rejected*
+ // by the default parser).
+
+ let expr = {
+ let tt = cx.parse_tts("\x00name_2,ctxt_0\x00".to_string());
+ let mut parser = new_parser_from_tts(parse_sess, cfg, tt);
+ parser.parse_expr()
+ };
+ MacExpr::new(expr)
+}
+
pub fn foo() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-pub use bar = foo;
+pub use foo as bar;
mod foo {
pub fn frob() {}
// except according to those terms.
pub use sub_foo::Foo;
-pub use Baz = self::Bar;
+pub use self::Bar as Baz;
pub use sub_foo::Boz;
pub use sub_foo::Bort;
}
pub mod bar {
- pub use e = foo::reexported_a;
- pub use f = foo::reexported_b;
- pub use g = foo::reexported_c;
- pub use h = foo::reexported_d;
+ pub use foo::reexported_a as e;
+ pub use foo::reexported_b as f;
+ pub use foo::reexported_c as g;
+ pub use foo::reexported_d as h;
}
pub static a: int = 0;
--- /dev/null
+// 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.
+
+pub trait Equal {
+ fn equal(&self, other: &Self) -> bool;
+ fn equals<T,U>(&self, this: &T, that: &T, x: &U, y: &U) -> bool
+ where T: Eq, U: Eq;
+}
+
+impl<T> Equal for T where T: Eq {
+ fn equal(&self, other: &T) -> bool {
+ self == other
+ }
+ fn equals<U,X>(&self, this: &U, other: &U, x: &X, y: &X) -> bool
+ where U: Eq, X: Eq {
+ this == other && x == y
+ }
+}
+
+pub fn equal<T>(x: &T, y: &T) -> bool where T: Eq {
+ x == y
+}
+
// OF THE POSSIBILITY OF SUCH DAMAGE.
// FIXME(#13725) windows needs fixing.
-// ignore-win32
+// ignore-windows
// ignore-stage1
// ignore-cross-compile #12102
--- /dev/null
+// 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.
+
+// aux-build:macro_crate_test.rs
+// ignore-stage1
+// ignore-android
+// error-pattern: unknown start of token: \x00
+
+// Issue #15750 and #15962 : this test is checking that the standard
+// parser rejects embedded idents. pnkfelix did not want to attempt
+// to make a test file that itself used the embedded ident input form,
+// since he worrid that would be difficult to work with in many text
+// editors, so instead he made a macro that expands into the embedded
+// ident form.
+
+#![feature(phase)]
+
+#[phase(plugin)]
+extern crate macro_crate_test;
+
+fn main() {
+ let x = 0;
+ assert_eq!(3, forged_ident!());
+}
// except according to those terms.
// FIXME(#13725) windows needs fixing.
-// ignore-win32
+// ignore-windows
// ignore-stage1
#![feature(phase)]
// except according to those terms.
// FIXME(#13725) windows needs fixing.
-// ignore-win32
+// ignore-windows
// ignore-stage1
#![feature(phase)]
// except according to those terms.
// FIXME(#13725) windows needs fixing.
-// ignore-win32
+// ignore-windows
// ignore-stage1
#![feature(phase)]
--- /dev/null
+// 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.
+
+struct Foo {
+ x: int,
+}
+
+pub fn main() {
+ let mut this = &mut Foo {
+ x: 1,
+ };
+ let r = || {
+ let p = &this.x;
+ &mut this.x; //~ ERROR cannot borrow
+ };
+ r()
+}
+
--- /dev/null
+// 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.
+
+// Issue #16205.
+
+struct Foo {
+ a: [Box<int>, ..3],
+}
+
+fn main() {
+ let mut y = 1i;
+ let x = Some(&mut y);
+ for &a in x.iter() { //~ ERROR cannot move out
+ }
+
+ let f = Foo {
+ a: [box 3, box 4, box 5],
+ };
+ for &a in f.a.iter() { //~ ERROR cannot move out
+ }
+
+ let x = Some(box 1i);
+ for &a in x.iter() { //~ ERROR cannot move out
+ }
+}
+
// move, when the struct implements Drop.
// NoCopy
-use NP = std::kinds::marker::NoCopy;
+use std::kinds::marker::NoCopy as NP;
struct S { a: int, np: NP }
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(overloaded_calls)]
+
+fn a<F:|&: int, int| -> int>(mut f: F) {
+ let g = &mut f;
+ f(1, 2); //~ ERROR cannot borrow `f` as immutable
+ //~^ ERROR cannot borrow `f` as immutable
+}
+
+fn b<F:|&mut: int, int| -> int>(f: F) {
+ f(1, 2); //~ ERROR cannot borrow immutable argument
+}
+
+fn c<F:|: int, int| -> int>(f: F) {
+ f(1, 2);
+ f(1, 2); //~ ERROR use of moved value
+}
+
+fn main() {}
+
use bar::*;
mod bar {
- use import = self::fpriv;
+ use self::fpriv as import;
fn fpriv() {}
extern {
fn epriv();
// error-pattern:expected
-use baz = foo::{bar};
+use foo::{bar} as baz;
mod foo {
pub fn bar() {}
// error-pattern:expected
-use baz = foo::*;
+use foo::* as baz;
mod foo {
pub fn bar() {}
// the `--test` harness creates modules with these textual names, but
// they should be inaccessible from normal code.
-use x = __test; //~ ERROR unresolved import `__test`
-use y = __test_reexports; //~ ERROR unresolved import `__test_reexports`
+use __test as x; //~ ERROR unresolved import `__test`
+use __test_reexports as y; //~ ERROR unresolved import `__test_reexports`
#[test]
fn baz() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use x = m::f; //~ ERROR unresolved import `m::f`. There is no `f` in `m`
+use m::f as x; //~ ERROR unresolved import `m::f`. There is no `f` in `m`
mod m {}
extern crate libc;
-pub use x = extern_foo;
+pub use extern_foo as x;
extern {
fn extern_foo();
}
}
/// dox
pub mod public_interface {
- pub use foo = internal_impl::documented;
- pub use bar = internal_impl::undocumented1;
+ pub use internal_impl::documented as foo;
+ pub use internal_impl::undocumented1 as bar;
pub use internal_impl::{documented, undocumented2};
pub use internal_impl::globbed::*;
}
#![deny(unused_imports)]
#![allow(dead_code)]
-use cal = bar::c::cc;
+use bar::c::cc as cal;
use std::mem::*; // shouldn't get errors for not using
// everything imported
}
fn h() {
- use not_okay = self::n::OKAY;
+ use self::n::OKAY as not_okay;
let r = match (0,0) {
(0, not_okay) => 0,
//~^ ERROR static constant in pattern `not_okay` should have an uppercase name such as `NOT_OKAY`
//~^ NOTE: module `i` is private
pub mod foo {
- pub use foo = self::i::A;
+ pub use self::i::A as foo;
mod i {
pub struct A;
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(unboxed_closure_sugar, unboxed_closures, overloaded_calls)]
+
+use std::ops::FnMut;
+
+fn main() {
+ let mut f;
+ {
+ let c = 1;
+ let c_ref = &c;
+ f = |&mut: a: int, b: int| { a + b + *c_ref };
+ //~^ ERROR cannot infer an appropriate lifetime
+ }
+}
+
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(lang_items, overloaded_calls, unboxed_closures)]
+
+fn c<F:|: int, int| -> int>(f: F) -> int {
+ f(5, 6)
+}
+
+fn main() {
+ let z: int = 7;
+ assert_eq!(c(|&: x: int, y| x + y + z), 10);
+ //~^ ERROR failed to find an implementation
+}
+
use foo::bar; //~ ERROR unresolved import `foo::bar`. Maybe a missing `extern crate foo`?
-use x = bar::baz; //~ ERROR unresolved import `bar::baz`. There is no `baz` in `bar`
+use bar::baz as x; //~ ERROR unresolved import `bar::baz`. There is no `baz` in `bar`
mod bar {
struct bar;
--- /dev/null
+// 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.
+
+fn equal1<T>(_: &T, _: &T) -> bool where {
+//~^ ERROR a `where` clause must have at least one predicate in it
+ true
+}
+
+fn equal2<T>(_: &T, _: &T) -> bool where T: {
+//~^ ERROR each predicate in a `where` clause must have at least one bound
+ true
+}
+
+fn main() {
+}
+
--- /dev/null
+// 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.
+
+fn equal<T>(_: &T, _: &T) -> bool where int : Eq {
+ //~^ ERROR undeclared type parameter
+}
+
+fn main() {
+}
+
--- /dev/null
+// 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.
+
+fn equal<T>(_: &T, _: &T) -> bool where T : Eq {
+}
+
+struct Struct;
+
+fn main() {
+ equal(&Struct, &Struct)
+ //~^ ERROR failed to find an implementation of trait
+}
+
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-win32: FIXME #13256
+// ignore-windows: FIXME #13256
// ignore-android: FIXME(#10381)
// compile-flags:-g
// about UTF-32 character encoding and will print a rust char as only
// its numerical value.
-// ignore-win32: FIXME #13256
+// ignore-windows: FIXME #13256
// ignore-android: FIXME(#10381)
// compile-flags:-g
// about UTF-32 character encoding and will print a rust char as only
// its numerical value.
-// ignore-win32: FIXME #13256
+// ignore-windows: FIXME #13256
// ignore-android: FIXME(#10381)
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-win32: FIXME #13256
+// ignore-windows: FIXME #13256
// ignore-android: FIXME(#10381)
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-win32: FIXME #13256
+// ignore-windows: FIXME #13256
// ignore-android: FIXME(#10381)
// compile-flags:-g
--- /dev/null
+// Copyright 2013-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.
+
+// ignore-android: FIXME(#10381)
+// ignore-lldb
+
+// compile-flags:-g
+
+// gdb-command:break 'no-debug-attribute.rs':32
+// gdb-command:break 'no-debug-attribute.rs':38
+// gdb-command:run
+
+// gdb-command:info locals
+// gdb-check:No locals.
+// gdb-command:continue
+
+// gdb-command:info locals
+// gdb-check:abc = 10
+// gdb-command:continue
+
+#![allow(unused_variable)]
+
+fn function_with_debuginfo() {
+ let abc = 10u;
+ return (); // #break
+}
+
+#[no_debug]
+fn function_without_debuginfo() {
+ let abc = -57i32;
+ return (); // #break
+}
+
+fn main() {
+ function_without_debuginfo();
+ function_with_debuginfo();
+}
+
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-win32: FIXME #13256
+// ignore-windows: FIXME #13256
// ignore-android: FIXME(#10381)
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-win32: FIXME #13256
+// ignore-windows: FIXME #13256
// ignore-android: FIXME(#10381)
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-win32: FIXME #13256
+// ignore-windows: FIXME #13256
// ignore-android: FIXME(#10381)
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-win32: FIXME #13256
+// ignore-windows: FIXME #13256
// ignore-android: FIXME(#10381)
// compile-flags:-g
--- /dev/null
+-include ../tools.mk
+
+# Issue #15750, #15962 : This test ensures that our special embedded
+# ident syntax hack is not treated as legitimate input by the lexer in
+# normal mode.
+#
+# It is modelled after the `unicode-input/` test, since we need to
+# create files with syntax that can trip up normal text editting tools
+# (namely text with embedded nul-bytes).
+
+# This test attempts to run rustc itself from the compiled binary; but
+# that means that you need to set the LD_LIBRARY_PATH for rustc itself
+# while running create_and_compile, and that won't work for stage1.
+
+# FIXME ignore windows
+ifndef IS_WINDOWS
+ifeq ($(RUST_BUILD_STAGE),1)
+DOTEST=
+else
+DOTEST=dotest
+endif
+endif
+
+all: $(DOTEST)
+
+dotest:
+ $(RUSTC) create_and_compile.rs
+ $(call RUN,create_and_compile) "$(RUSTC)" "$(TMPDIR)"
--- /dev/null
+// 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.
+
+use std::os;
+use std::io::{File, Command};
+
+// creates broken.rs, which has the Ident \x00name_0,ctxt_0\x00
+// embedded within it, and then attempts to compile broken.rs with the
+// provided `rustc`
+
+fn main() {
+ let args = os::args();
+ let rustc = args[1].as_slice();
+ let tmpdir = Path::new(args[2].as_slice());
+
+ let main_file = tmpdir.join("broken.rs");
+ let _ = File::create(&main_file).unwrap()
+ .write_str("pub fn main() {
+ let \x00name_0,ctxt_0\x00 = 3i;
+ println!(\"{}\", \x00name_0,ctxt_0\x00);
+ }");
+
+ // rustc is passed to us with --out-dir and -L etc., so we
+ // can't exec it directly
+ let result = Command::new("sh")
+ .arg("-c")
+ .arg(format!("{} {}",
+ rustc,
+ main_file.as_str()
+ .unwrap()).as_slice())
+ .output().unwrap();
+ let err = String::from_utf8_lossy(result.error.as_slice());
+
+ // positive test so that this test will be updated when the
+ // compiler changes.
+ assert!(err.as_slice().contains("unknown start of token"))
+}
--- /dev/null
+// Copyright 2013-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.
+
+// aux-build:macro_crate_test.rs
+// ignore-stage1
+
+// Issue #15750: a macro that internally parses its input and then
+// uses `quote_expr!` to rearrange it should be hygiene-preserving.
+
+#![feature(phase)]
+
+#[phase(plugin)]
+extern crate macro_crate_test;
+
+fn main() {
+ let x = 3i;
+ assert_eq!(3, identity!(x));
+ assert_eq!(6, identity!(x+x));
+ let x = 4i;
+ assert_eq!(4, identity!(x));
+}
use std::hashmap::{HashMap, HashSet};
-use EBReader = rbml::reader;
-use EBWriter = rbml::writer;
+use rbml::reader as EBReader;
+use rbml::writer as EBWriter;
use std::cmp::Eq;
use std::cmp;
use std::io;
// except according to those terms.
// no-pretty-expanded FIXME #15189
-// ignore-win32 FIXME #13259
+// ignore-windows FIXME #13259
extern crate native;
use std::os;
--- /dev/null
+// 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.
+
+fn each<T>(x: &[T], f: |&T|) {
+ for val in x.iter() {
+ f(val)
+ }
+}
+
+fn main() {
+ let mut sum = 0u;
+ let elems = [ 1u, 2, 3, 4, 5 ];
+ each(elems, ref |val| sum += *val);
+ assert_eq!(sum, 15);
+}
+
--- /dev/null
+// 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.
+
+// ignore-test
+//
+// This is ignored because it depends on #16122.
+
+#![feature(overloaded_calls, unboxed_closures)]
+
+fn each<'a,T,F:|&mut: &'a T|>(x: &'a [T], mut f: F) {
+ for val in x.iter() {
+ f(val)
+ }
+}
+
+fn main() {
+ let mut sum = 0u;
+ let elems = [ 1u, 2, 3, 4, 5 ];
+ each(elems, ref |&mut: val: &uint| sum += *val);
+ assert_eq!(sum, 15);
+}
+
extern crate rustuv;
use std::io::{Process, Command};
+use std::time::Duration;
macro_rules! succeed( ($e:expr) => (
match $e { Ok(..) => {}, Err(e) => fail!("failure: {}", e) }
// Don't let this test time out, this should be quick
let (tx, rx1) = channel();
let mut t = timer::Timer::new().unwrap();
- let rx2 = t.oneshot(1000);
+ let rx2 = t.oneshot(Duration::milliseconds(1000));
spawn(proc() {
select! {
() = rx2.recv() => unsafe { libc::exit(1) },
#[cfg(target_os = "macos")]
mod hello;
-#[cfg(target_os = "win32")]
+#[cfg(target_os = "windows")]
+/* NOTE: Remove after snapshot */#[cfg(stage0, target_os = "win32")]
mod hello;
#[cfg(target_os = "freebsd")]
#![feature(macro_rules)]
-use s = std::num::strconv;
-use to_string = std::num::strconv::float_to_str_common;
+use std::num::strconv as s;
+use std::num::strconv::float_to_str_common as to_string;
macro_rules! t(($a:expr, $b:expr) => { { let (r, _) = $a; assert_eq!(r, $b.to_string()) } })
pub fn main() {
// Make sure that this view item is filtered out because otherwise it would
// trigger a compilation error
- #[cfg(not_present)] use foo = bar;
+ #[cfg(not_present)] use bar as foo;
}
// Issue 4691: Ensure that functional-struct-updates operates
// correctly and moves rather than copy when appropriate.
-use NP = std::kinds::marker::NoCopy;
+use std::kinds::marker::NoCopy as NP;
struct ncint { np: NP, v: int }
fn ncint(v: int) -> ncint { ncint { np: NP, v: v } }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-win32 TempDir may cause IoError on windows: #10462
+// ignore-windows TempDir may cause IoError on windows: #10462
#![feature(macro_rules)]
mod bar {
use foo::x;
- use z = foo::x;
+ use foo::x as z;
pub fn thing() { x(10); z(10); }
}
use foo::x;
-use z = foo::x;
+use foo::x as z;
mod foo {
pub fn x(y: int) { println!("{}", y); }
}
}
-#[cfg(target_os = "win32")]
+#[cfg(target_os = "windows")]
+/* NOTE: Remove after snapshot */#[cfg(stage0, target_os = "win32")]
mod m {
#[main]
#[cfg(target_arch = "x86")]
extern crate green;
extern crate rustuv;
+use std::time::Duration;
+
#[start]
fn start(argc: int, argv: *const *const u8) -> int {
green::start(argc, argv, rustuv::event_loop, main)
fn customtask() {
let mut timer = std::io::timer::Timer::new().unwrap();
- let periodic = timer.periodic(10);
+ let periodic = timer.periodic(Duration::milliseconds(10));
periodic.recv();
}
extern crate native;
use std::io::timer;
+use std::time::Duration;
#[start]
fn start(argc: int, argv: *const *const u8) -> int {
}
fn main() {
- timer::sleep(250);
+ timer::sleep(Duration::milliseconds(250));
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-win32: FIXME #13793
+// ignore-windows: FIXME #13793
fn main() {
match ("", 1u) {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-win32
+// ignore-windows
#![feature(link_args)]
--- /dev/null
+// 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.
+
+struct Empty;
+
+// This used to cause an ICE
+extern "C" fn ice(_a: Empty) {}
+
+fn main() {
+}
// except according to those terms.
-pub use local_alias = local;
+pub use local as local_alias;
mod local { }
use std::comm;
use std::io::timer::Timer;
+use std::time::Duration;
pub fn main() {
let (tx, rx) = channel();
spawn(proc (){
let mut timer = Timer::new().unwrap();
- timer.sleep(10);
+ timer.sleep(Duration::milliseconds(10));
tx.send(());
});
loop {
// aux-build:lang-item-public.rs
// ignore-android
-// ignore-win32 #13361
+// ignore-windows #13361
#![no_std]
// aux-build:linkage-visibility.rs
// ignore-android: FIXME(#10379)
-// ignore-win32: std::dynamic_lib does not work on win32 well
+// ignore-windows: std::dynamic_lib does not work on win32 well
extern crate foo = "linkage-visibility";
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-win32
+// ignore-windows
// ignore-android
// ignore-macos
// aux-build:linkage1.rs
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-win32
+// ignore-windows
// exec-env:RUST_LOG=debug
use std::cell::Cell;
// except according to those terms.
// ignore-android
-// ignore-win32
+// ignore-windows
// exec-env:RUST_LOG=debug
#![feature(phase)]
}
fn g() {
- use AHA = self::m::aha;
+ use self::m::aha as AHA;
let r = match (0,0) {
(0, AHA) => 0,
(x, y) => 1 + x + y,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-win32
+// ignore-windows
// ignore-android
// This test ensures that the 'detach' field on processes does the right thing.
}
}
-#[cfg(target_os = "win32")]
+#[cfg(target_os = "windows")]
+/* NOTE: Remove after snapshot */#[cfg(stage0, target_os = "win32")]
mod m {
#[cfg(target_arch = "x86")]
pub mod m {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-win32
+// ignore-windows
extern crate debug;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-win32
+// ignore-windows
// exec-env:RUST_LOG=debug
// regression test for issue #10405, make sure we don't call println! too soon.
use std::io::net::tcp::*;
use std::io::test::*;
use std::io;
+ use std::time::Duration;
fn f() $b
let mut v = Vec::new();
for _ in range(0u, 10000) {
- match TcpStream::connect_timeout(addr, 100) {
+ match TcpStream::connect_timeout(addr, Duration::milliseconds(100)) {
Ok(e) => v.push(e),
Err(ref e) if e.kind == io::TimedOut => return,
Err(e) => fail!("other error: {}", e),
let port = addr.port;
let _l = TcpListener::bind(host.as_slice(), port).unwrap().listen();
- assert!(TcpStream::connect_timeout(addr, 1000).is_ok());
+ assert!(TcpStream::connect_timeout(addr, Duration::milliseconds(1000)).is_ok());
})
iotest!(fn timeout_error() {
let addr = next_test_ip4();
- assert!(TcpStream::connect_timeout(addr, 1000).is_err());
+ assert!(TcpStream::connect_timeout(addr, Duration::milliseconds(1000)).is_err());
})
+
+ iotest!(fn connect_timeout_zero() {
+ let addr = next_test_ip4();
+ assert!(TcpStream::connect_timeout(addr, Duration::milliseconds(0)).is_err());
+ })
+
+ iotest!(fn connect_timeout_negative() {
+ let addr = next_test_ip4();
+ assert!(TcpStream::connect_timeout(addr, Duration::milliseconds(-1)).is_err());
+ })
+
use std::io::net::tcp::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener};
use std::task::TaskBuilder;
+use std::time::Duration;
#[start]
fn start(argc: int, argv: *const *const u8) -> int {
// This test has a chance to time out, try to not let it time out
spawn(proc() {
use std::io::timer;
- timer::sleep(30 * 1000);
+ timer::sleep(Duration::milliseconds(30 * 1000));
println!("timed out!");
unsafe { libc::exit(1) }
});
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-win32 TempDir may cause IoError on windows: #10463
+// ignore-windows TempDir may cause IoError on windows: #10463
// These tests are here to exercise the functionality of the `tempfile` module.
// One might expect these tests to be located in that module, but sadly they
// except according to those terms.
// compile-flags:--test
-// ignore-win32 #10872
+// ignore-windows #10872
// ignore-pretty: does not work well with `--test`
// Building as a test runner means that a synthetic main will be run,
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(lang_items, overloaded_calls, unboxed_closures)]
+
+fn a<F:|&: int, int| -> int>(f: F) -> int {
+ f(1, 2)
+}
+
+fn b<F:|&mut: int, int| -> int>(mut f: F) -> int {
+ f(3, 4)
+}
+
+fn c<F:|: int, int| -> int>(f: F) -> int {
+ f(5, 6)
+}
+
+fn main() {
+ let z: int = 7;
+ assert_eq!(a(|&: x: int, y| x + y + z), 10);
+ assert_eq!(b(|&mut: x: int, y| x + y + z), 14);
+ assert_eq!(c(|: x: int, y| x + y + z), 18);
+}
+
--- /dev/null
+// 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.
+
+// A battery of tests to ensure destructors of unboxed closure environments
+// run at the right times.
+
+#![feature(overloaded_calls, unboxed_closures)]
+
+static mut DROP_COUNT: uint = 0;
+
+fn drop_count() -> uint {
+ unsafe {
+ DROP_COUNT
+ }
+}
+
+struct Droppable {
+ x: int,
+}
+
+impl Droppable {
+ fn new() -> Droppable {
+ Droppable {
+ x: 1
+ }
+ }
+}
+
+impl Drop for Droppable {
+ fn drop(&mut self) {
+ unsafe {
+ DROP_COUNT += 1
+ }
+ }
+}
+
+fn a<F:|&: int, int| -> int>(f: F) -> int {
+ f(1, 2)
+}
+
+fn b<F:|&mut: int, int| -> int>(mut f: F) -> int {
+ f(3, 4)
+}
+
+fn c<F:|: int, int| -> int>(f: F) -> int {
+ f(5, 6)
+}
+
+fn test_fn() {
+ {
+ a(|&: a: int, b| { a + b });
+ }
+ assert_eq!(drop_count(), 0);
+
+ {
+ let z = &Droppable::new();
+ a(|&: a: int, b| { z; a + b });
+ assert_eq!(drop_count(), 0);
+ }
+ assert_eq!(drop_count(), 1);
+
+ {
+ let z = &Droppable::new();
+ let zz = &Droppable::new();
+ a(|&: a: int, b| { z; zz; a + b });
+ assert_eq!(drop_count(), 1);
+ }
+ assert_eq!(drop_count(), 3);
+}
+
+fn test_fn_mut() {
+ {
+ b(|&mut: a: int, b| { a + b });
+ }
+ assert_eq!(drop_count(), 3);
+
+ {
+ let z = &Droppable::new();
+ b(|&mut: a: int, b| { z; a + b });
+ assert_eq!(drop_count(), 3);
+ }
+ assert_eq!(drop_count(), 4);
+
+ {
+ let z = &Droppable::new();
+ let zz = &Droppable::new();
+ b(|&mut: a: int, b| { z; zz; a + b });
+ assert_eq!(drop_count(), 4);
+ }
+ assert_eq!(drop_count(), 6);
+}
+
+fn test_fn_once() {
+ {
+ c(|: a: int, b| { a + b });
+ }
+ assert_eq!(drop_count(), 6);
+
+ {
+ let z = Droppable::new();
+ c(|: a: int, b| { z; a + b });
+ assert_eq!(drop_count(), 7);
+ }
+ assert_eq!(drop_count(), 7);
+
+ {
+ let z = Droppable::new();
+ let zz = Droppable::new();
+ c(|: a: int, b| { z; zz; a + b });
+ assert_eq!(drop_count(), 9);
+ }
+ assert_eq!(drop_count(), 9);
+}
+
+fn main() {
+ test_fn();
+ test_fn_mut();
+ test_fn_once();
+}
+
--- /dev/null
+// 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.
+
+// Ensures that single-word environments work right in unboxed closures.
+// These take a different path in codegen.
+
+#![feature(overloaded_calls, unboxed_closures)]
+
+fn a<F:|&: int, int| -> int>(f: F) -> int {
+ f(1, 2)
+}
+
+fn b<F:|&mut: int, int| -> int>(mut f: F) -> int {
+ f(3, 4)
+}
+
+fn c<F:|: int, int| -> int>(f: F) -> int {
+ f(5, 6)
+}
+
+fn main() {
+ let z = 10;
+ assert_eq!(a(|&: x: int, y| x + y + z), 13);
+ assert_eq!(b(|&mut: x: int, y| x + y + z), 17);
+ assert_eq!(c(|: x: int, y| x + y + z), 21);
+}
+
use std::str;
-use x = zed::str;
+use zed::str as x;
mod baz {
- pub use x = std::str;
+ pub use std::str as x;
}
#[start]
--- /dev/null
+// 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.
+
+// aux-build:where_clauses_xc.rs
+
+extern crate where_clauses_xc;
+
+use where_clauses_xc::{Equal, equal};
+
+fn main() {
+ println!("{}", equal(&1i, &2i));
+ println!("{}", equal(&1i, &1i));
+ println!("{}", "hello".equal(&"hello"));
+ println!("{}", "hello".equals::<int,&str>(&1i, &1i, &"foo", &"bar"));
+}
+
--- /dev/null
+// 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.
+
+trait Equal {
+ fn equal(&self, other: &Self) -> bool;
+ fn equals<T,U>(&self, this: &T, that: &T, x: &U, y: &U) -> bool
+ where T: Eq, U: Eq;
+}
+
+impl<T> Equal for T where T: Eq {
+ fn equal(&self, other: &T) -> bool {
+ self == other
+ }
+ fn equals<U,X>(&self, this: &U, other: &U, x: &X, y: &X) -> bool
+ where U: Eq, X: Eq {
+ this == other && x == y
+ }
+}
+
+fn equal<T>(x: &T, y: &T) -> bool where T: Eq {
+ x == y
+}
+
+fn main() {
+ println!("{}", equal(&1i, &2i));
+ println!("{}", equal(&1i, &1i));
+ println!("{}", "hello".equal(&"hello"));
+ println!("{}", "hello".equals::<int,&str>(&1i, &1i, &"foo", &"bar"));
+}
+
extern crate xcrate_static_addresses;
-use other = xcrate_static_addresses;
+use xcrate_static_addresses as other;
pub fn main() {
other::verify_same(&other::global);