RUSTDOC_HTML_OPTS = $(RUSTDOC_HTML_OPTS_NO_CSS) --markdown-css rust.css
PANDOC_BASE_OPTS := --standalone --toc --number-sections
-PANDOC_TEX_OPTS = $(PANDOC_BASE_OPTS) --include-before-body=doc/version.tex \
- --from=markdown --include-before-body=doc/footer.tex --to=latex
+PANDOC_TEX_OPTS = $(PANDOC_BASE_OPTS) --from=markdown --to=latex \
+ --include-before-body=doc/version.tex \
+ --include-before-body=doc/footer.tex \
+ --include-in-header=doc/uptack.tex
PANDOC_EPUB_OPTS = $(PANDOC_BASE_OPTS) --to=epub
# The rustdoc executable...
@$(call E, pandoc: $@)
$(CFG_PANDOC) --from=html --to=latex $< --output=$@
+doc/uptack.tex: $(D)/uptack.tex | doc/
+ $(Q)cp $< $@
+
# HTML (rustdoc)
DOC_TARGETS += doc/not_found.html
doc/not_found.html: $(D)/not_found.md $(HTML_DEPS) | doc/
# PDF (md =(pandoc)=> tex =(pdflatex)=> pdf)
DOC_TARGETS += doc/$(1).tex
-doc/$(1).tex: $$(D)/$(1).md doc/footer.tex doc/version.tex | doc/
+doc/$(1).tex: $$(D)/$(1).md doc/uptack.tex doc/footer.tex doc/version.tex | doc/
@$$(call E, pandoc: $$@)
$$(CFG_PANDOC) $$(PANDOC_TEX_OPTS) $$< --output=$$@
######################################################################
# The version number
-CFG_RELEASE_NUM=0.13.0
+CFG_RELEASE_NUM=1.0.0
# An optional number to put after the label, e.g. '2' -> '-beta2'
CFG_BETA_CYCLE=
ifeq ($(CFG_RELEASE_CHANNEL),beta)
# The beta channel is temporarily called 'alpha'
CFG_RELEASE=$(CFG_RELEASE_NUM)-alpha$(CFG_BETA_CYCLE)
-# When building beta/nightly distributables just reuse the same "beta"
-# name so when we upload we'll always override the previous
-# nighly. This doesn't actually impact the version reported by rustc -
-# it's just for file naming.
-CFG_PACKAGE_VERS=alpha
+CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM)-alpha$(CFG_BETA_CYCLE)
endif
ifeq ($(CFG_RELEASE_CHANNEL),nightly)
CFG_RELEASE=$(CFG_RELEASE_NUM)-nightly
+# When building nightly distributables just reuse the same "nightly" name
+# so when we upload we'll always override the previous nighly. This
+# doesn't actually impact the version reported by rustc - it's just
+# for file naming.
CFG_PACKAGE_VERS=nightly
endif
ifeq ($(CFG_RELEASE_CHANNEL),dev)
extern crate test;
extern crate getopts;
-#[phase(plugin, link)] extern crate log;
+
+#[cfg(stage0)]
+#[phase(plugin, link)]
+extern crate log;
+
+#[cfg(not(stage0))]
+#[macro_use]
+extern crate log;
extern crate regex;
* [sprocketnes], an NES emulator with no GC, using modern Rust conventions
* The language's general-purpose [hash] function, SipHash-2-4. Bit twiddling, OO, macros
* The standard library's [HashMap], a sendable hash map in an OO style
-* The extra library's [json] module. Enums and pattern matching
+* The standard library's [json] module. Enums and pattern matching
[sprocketnes]: https://github.com/pcwalton/sprocketnes
[hash]: https://github.com/rust-lang/rust/blob/master/src/libstd/hash/mod.rs
~~~no_run
extern crate libc;
-use std::c_str::ToCStr;
+use std::ffi::CString;
use std::ptr;
#[link(name = "readline")]
}
fn main() {
- "[my-awesome-shell] $".with_c_str(|buf| {
- unsafe { rl_prompt = buf; }
- // get a line, process it
- unsafe { rl_prompt = ptr::null(); }
- });
+ let prompt = CString::from_slice(b"[my-awesome-shell] $");
+ unsafe { rl_prompt = prompt.as_ptr(); }
+ // get a line, process it
+ unsafe { rl_prompt = ptr::null(); }
}
~~~
# Interoperability with foreign code
-Rust guarantees that the layout of a `struct` is compatible with the platform's representation in C
-only if the `#[repr(C)]` attribute is applied to it. `#[repr(C, packed)]` can be used to lay out
-struct members without padding. `#[repr(C)]` can also be applied to an enum.
-
-Rust's owned boxes (`Box<T>`) use non-nullable pointers as handles which point to the contained
-object. However, they should not be manually created because they are managed by internal
-allocators. References can safely be assumed to be non-nullable pointers directly to the type.
-However, breaking the borrow checking or mutability rules is not guaranteed to be safe, so prefer
-using raw pointers (`*`) if that's needed because the compiler can't make as many assumptions about
-them.
-
-Vectors and strings share the same basic memory layout, and utilities are available in the `vec` and
-`str` modules for working with C APIs. However, strings are not terminated with `\0`. If you need a
-NUL-terminated string for interoperability with C, you should use the `c_str::to_c_str` function.
-
-The standard library includes type aliases and function definitions for the C standard library in
-the `libc` module, and Rust links against `libc` and `libm` by default.
+Rust guarantees that the layout of a `struct` is compatible with the platform's
+representation in C only if the `#[repr(C)]` attribute is applied to it.
+`#[repr(C, packed)]` can be used to lay out struct members without padding.
+`#[repr(C)]` can also be applied to an enum.
+
+Rust's owned boxes (`Box<T>`) use non-nullable pointers as handles which point
+to the contained object. However, they should not be manually created because
+they are managed by internal allocators. References can safely be assumed to be
+non-nullable pointers directly to the type. However, breaking the borrow
+checking or mutability rules is not guaranteed to be safe, so prefer using raw
+pointers (`*`) if that's needed because the compiler can't make as many
+assumptions about them.
+
+Vectors and strings share the same basic memory layout, and utilities are
+available in the `vec` and `str` modules for working with C APIs. However,
+strings are not terminated with `\0`. If you need a NUL-terminated string for
+interoperability with C, you should use the `CString` type in the `std::ffi`
+module.
+
+The standard library includes type aliases and function definitions for the C
+standard library in the `libc` module, and Rust links against `libc` and `libm`
+by default.
# The "nullable pointer optimization"
% The Rust Macros Guide
-<div class="unstable-feature">
-<b>Warning:</b> There are currently various problems with invoking macros, how
-they interact with their environment, and how they are used outside of the
-location in which they are defined. Macro definitions are likely to change
-slightly in the future. For this reason, they are hidden behind the
-<code>macro_rules</code> <a href="reference.html#compiler-features">feature
-attribute</a>.
-</div>
-
# Introduction
Functions are the primary tool that programmers can use to build abstractions.
the pattern in the above code:
~~~~
-# #![feature(macro_rules)]
# enum T { SpecialA(uint), SpecialB(uint) }
# fn f() -> uint {
# let input_1 = T::SpecialA(0);
# let input_2 = T::SpecialA(0);
-macro_rules! early_return(
+macro_rules! early_return {
($inp:expr $sp:path) => ( // invoke it like `(input_5 SpecialE)`
match $inp {
$sp(x) => { return x; }
_ => {}
}
);
-);
+}
// ...
early_return!(input_1 T::SpecialA);
// ...
## Invocation location
-A macro invocation may take the place of (and therefore expand to)
-an expression, an item, or a statement.
-The Rust parser will parse the macro invocation as a "placeholder"
-for whichever of those three nonterminals is appropriate for the location.
+A macro invocation may take the place of (and therefore expand to) an
+expression, item, statement, or pattern. The Rust parser will parse the macro
+invocation as a "placeholder" for whichever syntactic form is appropriate for
+the location.
At expansion time, the output of the macro will be parsed as whichever of the
three nonterminals it stands in for. This means that a single macro might,
instead of `*` to mean "at least one".
~~~~
-# #![feature(macro_rules)]
# enum T { SpecialA(uint),SpecialB(uint),SpecialC(uint),SpecialD(uint)}
# fn f() -> uint {
# let input_1 = T::SpecialA(0);
# let input_2 = T::SpecialA(0);
-macro_rules! early_return(
+macro_rules! early_return {
($inp:expr, [ $($sp:path)|+ ]) => (
match $inp {
$(
_ => {}
}
)
-);
+}
// ...
early_return!(input_1, [T::SpecialA|T::SpecialC|T::SpecialD]);
// ...
Now consider code like the following:
~~~~
-# #![feature(macro_rules)]
# enum T1 { Good1(T2, uint), Bad1}
# struct T2 { body: T3 }
# enum T3 { Good2(uint), Bad2}
can solve the problem:
~~~~
-# #![feature(macro_rules)]
-macro_rules! biased_match (
+macro_rules! biased_match {
// special case: `let (x) = ...` is illegal, so use `let x = ...` instead
( ($e:expr) ~ ($p:pat) else $err:stmt ;
binds $bind_res:ident
_ => { $err }
};
)
-);
+}
# enum T1 { Good1(T2, uint), Bad1}
# struct T2 { body: T3 }
pattern we want is clear:
~~~~
-# #![feature(macro_rules)]
# fn main() {}
-# macro_rules! b(
+# macro_rules! b {
( $( ($e:expr) ~ ($p:pat) else $err:stmt ; )*
binds $( $bind_res:ident ),*
)
-# => (0));
+# => (0) }
~~~~
However, it's not possible to directly expand to nested match statements. But
input patterns:
~~~~
-# #![feature(macro_rules)]
-# macro_rules! b(
+# macro_rules! b {
( binds $( $bind_res:ident ),* )
-# => (0));
+# => (0) }
# fn main() {}
~~~~
...and:
~~~~
-# #![feature(macro_rules)]
# fn main() {}
-# macro_rules! b(
+# macro_rules! b {
( ($e :expr) ~ ($p :pat) else $err :stmt ;
$( ($e_rest:expr) ~ ($p_rest:pat) else $err_rest:stmt ; )*
binds $( $bind_res:ident ),*
)
-# => (0));
+# => (0) }
~~~~
The resulting macro looks like this. Note that the separation into
piece of syntax (the `let`) which we only want to transcribe once.
~~~~
-# #![feature(macro_rules)]
# fn main() {
-macro_rules! biased_match_rec (
+macro_rules! biased_match_rec {
// Handle the first layer
( ($e :expr) ~ ($p :pat) else $err :stmt ;
$( ($e_rest:expr) ~ ($p_rest:pat) else $err_rest:stmt ; )*
);
// Produce the requested values
( binds $( $bind_res:ident ),* ) => ( ($( $bind_res ),*) )
-);
+}
// Wrap the whole thing in a `let`.
-macro_rules! biased_match (
+macro_rules! biased_match {
// special case: `let (x) = ...` is illegal, so use `let x = ...` instead
( $( ($e:expr) ~ ($p:pat) else $err:stmt ; )*
binds $bind_res:ident
binds $( $bind_res ),*
);
)
-);
+}
# enum T1 { Good1(T2, uint), Bad1}
will not clash. The following code will print "Hello!" only once:
~~~
-#![feature(macro_rules)]
-
-macro_rules! loop_x (
+macro_rules! loop_x {
($e: expr) => (
// $e will not interact with this 'x
'x: loop {
$e
}
);
-);
+}
fn main() {
'x: loop {
is visible to any subsequent code in the same module, which includes the body
of any subsequent child `mod` items.
-If a module has the `macro_escape` attribute, its macros are also visible in
-its parent module after the child's `mod` item. If the parent also has
-`macro_escape` then the macros will be visible in the grandparent after the
-parent's `mod` item, and so forth.
+If a module has the `macro_use` attribute, its macros are also visible in its
+parent module after the child's `mod` item. If the parent also has `macro_use`
+then the macros will be visible in the grandparent after the parent's `mod`
+item, and so forth.
-Independent of `macro_escape`, the `macro_export` attribute controls visibility
-between crates. Any `macro_rules!` definition with the `macro_export`
-attribute will be visible to other crates that have loaded this crate with
-`phase(plugin)`. There is currently no way for the importing crate to control
-which macros are imported.
+The `macro_use` attribute can also appear on `extern crate`. In this context
+it controls which macros are loaded from the external crate, e.g.
+
+```rust,ignore
+#[macro_use(foo, bar)]
+extern crate baz;
+```
+
+If the attribute is given simply as `#[macro_use]`, all macros are loaded. If
+there is no `#[macro_use]` attribute then no macros are loaded. Only macros
+defined with the `#[macro_export]` attribute may be loaded.
+
+To load a crate's macros *without* linking it into the output, use `#[no_link]`
+as well.
An example:
```rust
-# #![feature(macro_rules)]
-macro_rules! m1 (() => (()));
+macro_rules! m1 { () => (()) }
// visible here: m1
// visible here: m1
#[macro_export]
- macro_rules! m2 (() => (()));
+ macro_rules! m2 { () => (()) }
// visible here: m1, m2
}
// visible here: m1
-macro_rules! m3 (() => (()));
+macro_rules! m3 { () => (()) }
// visible here: m1, m3
-#[macro_escape]
+#[macro_use]
mod bar {
// visible here: m1, m3
- macro_rules! m4 (() => (()));
+ macro_rules! m4 { () => (()) }
// visible here: m1, m3, m4
}
# fn main() { }
```
-When this library is loaded with `#[phase(plugin)] extern crate`, only `m2`
-will be imported.
+When this library is loaded with `#[use_macros] extern crate`, only `m2` will
+be imported.
+
+The Rust Reference has a [listing of macro-related
+attributes](reference.html#macro--and-plugin-related-attributes).
+
+# The variable `$crate`
+
+A further difficulty occurs when a macro is used in multiple crates. Say that
+`mylib` defines
+
+```rust
+pub fn increment(x: uint) -> uint {
+ x + 1
+}
+
+#[macro_export]
+macro_rules! inc_a {
+ ($x:expr) => ( ::increment($x) )
+}
+
+#[macro_export]
+macro_rules! inc_b {
+ ($x:expr) => ( ::mylib::increment($x) )
+}
+# fn main() { }
+```
+
+`inc_a` only works within `mylib`, while `inc_b` only works outside the
+library. Furthermore, `inc_b` will break if the user imports `mylib` under
+another name.
+
+Rust does not (yet) have a hygiene system for crate references, but it does
+provide a simple workaround for this problem. Within a macro imported from a
+crate named `foo`, the special macro variable `$crate` will expand to `::foo`.
+By contrast, when a macro is defined and then used in the same crate, `$crate`
+will expand to nothing. This means we can write
+
+```rust
+#[macro_export]
+macro_rules! inc {
+ ($x:expr) => ( $crate::increment($x) )
+}
+# fn main() { }
+```
+
+to define a single macro that works both inside and outside our library. The
+function name will expand to either `::increment` or `::mylib::increment`.
+
+To keep this system simple and correct, `#[macro_use] extern crate ...` may
+only appear at the root of your crate, not inside `mod`. This ensures that
+`$crate` is a single identifier.
# A final note
```
Rust has a feature called 'lifetime elision,' which allows you to not write
-lifetime annotations in certain circumstances. This is one of them. Without
-eliding the lifetimes, `add_one` looks like this:
+lifetime annotations in certain circumstances. This is one of them. We will
+cover the others later. Without eliding the lifetimes, `add_one` looks like
+this:
```rust
fn add_one<'a>(num: &'a int) -> int {
also `Arc<T>`, which uses more expensive atomic instructions to be the
thread-safe counterpart of `Rc<T>`.
+## Lifetime Elision
+
+Earlier, we mentioned 'lifetime elision,' a feature of Rust which allows you to
+not write lifetime annotations in certain circumstances. All references have a
+lifetime, and so if you elide a lifetime (like `&T` instead of `&'a T`), Rust
+will do three things to determine what those lifetimes should be.
+
+When talking about lifetime elision, we use the term 'input lifetime' and
+'output lifetime'. An 'input liftime' is a lifetime associated with a parameter
+of a function, and an 'output lifetime' is a lifetime associated with the return
+value of a function. For example, this function has an input lifetime:
+
+```{rust,ignore}
+fn foo<'a>(bar: &'a str)
+```
+
+This one has an output lifetime:
+
+```{rust,ignore}
+fn foo<'a>() -> &'a str
+```
+
+This one has a lifetime in both positions:
+
+```{rust,ignore}
+fn foo<'a>(bar: &'a str) -> &'a str
+```
+
+Here are the three rules:
+
+* Each elided lifetime in a function's arguments becomes a distinct lifetime
+ parameter.
+
+* If there is exactly one input lifetime, elided or not, that lifetime is
+ assigned to all elided lifetimes in the return values of that function..
+
+* If there are multiple input lifetimes, but one of them is `&self` or `&mut
+ self`, the lifetime of `self` is assigned to all elided output lifetimes.
+
+Otherwise, it is an error to elide an output lifetime.
+
+### Examples
+
+Here are some examples of functions with elided lifetimes, and the version of
+what the elided lifetimes are expand to:
+
+```{rust,ignore}
+fn print(s: &str); // elided
+fn print<'a>(s: &'a str); // expanded
+
+fn debug(lvl: uint, s: &str); // elided
+fn debug<'a>(lvl: uint, s: &'a str); // expanded
+
+// In the preceeding example, `lvl` doesn't need a lifetime because it's not a
+// reference (`&`). Only things relating to references (such as a `struct`
+// which contains a reference) need lifetimes.
+
+fn substr(s: &str, until: uint) -> &str; // elided
+fn substr<'a>(s: &'a str, until: uint) -> &'a str; // expanded
+
+fn get_str() -> &str; // ILLEGAL, no inputs
+
+fn frob(s: &str, t: &str) -> &str; // ILLEGAL, two inputs
+
+fn get_mut(&mut self) -> &mut T; // elided
+fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded
+
+fn args<T:ToCStr>(&mut self, args: &[T]) -> &mut Command // elided
+fn args<'a, 'b, T:ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // expanded
+
+fn new(buf: &mut [u8]) -> BufWriter; // elided
+fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded
+```
+
# Related Resources
Coming Soon.
A plugin is a dynamic library crate with a designated "registrar" function that
registers extensions with `rustc`. Other crates can use these extensions by
-loading the plugin crate with `#[phase(plugin)] extern crate`. See the
+loading the plugin crate with `#[plugin] extern crate`. See the
[`rustc::plugin`](rustc/plugin/index.html) documentation for more about the
mechanics of defining and loading a plugin.
+Arguments passed as `#[plugin=...]` or `#[plugin(...)]` are not interpreted by
+rustc itself. They are provided to the plugin through the `Registry`'s [`args`
+method](rustc/plugin/registry/struct.Registry.html#method.args).
+
# Syntax extensions
Plugins can extend Rust's syntax in various ways. One kind of syntax extension
Then we can use `rn!()` like any other macro:
```ignore
-#![feature(phase)]
+#![feature(plugin)]
-#[phase(plugin)]
-extern crate roman_numerals;
+#[plugin] extern crate roman_numerals;
fn main() {
assert_eq!(rn!(MMXV), 2015);
Then code like
```ignore
-#[phase(plugin)]
-extern crate lint_plugin_test;
+#[plugin] extern crate lint_plugin_test;
fn lintme() { }
```
* Make the code in the `iter` loop do something simple, to assist in pinpointing
performance improvements (or regressions)
+## Gotcha: optimizations
+
There's another tricky part to writing benchmarks: benchmarks compiled with
optimizations activated can be dramatically changed by the optimizer so that
the benchmark is no longer benchmarking what one expects. For example, the
# struct X;
# impl X { fn iter<T, F>(&self, _: F) where F: FnMut() -> T {} } let b = X;
b.iter(|| {
- test::black_box(range(0u, 1000).fold(0, |old, new| old ^ new));
-});
+ let mut n = 1000_u32;
+
+ test::black_box(&mut n); // pretend to modify `n`
+
+ range(0, n).fold(0, |a, b| a ^ b)
+})
# }
```
test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured
```
+
+However, the optimizer can still modify a testcase in an undesirable manner
+even when using either of the above.
Bam! We build our project with `cargo build`, and run it with
`./target/hello_world`. This hasn't bought us a whole lot over our simple use
of `rustc`, but think about the future: when our project has more than one
-file, we would need to call `rustc` twice, and pass it a bunch of options to
+file, we would need to call `rustc` more than once, and pass it a bunch of options to
tell it to build everything together. With Cargo, as our project grows, we can
just `cargo build` and it'll work the right way.
```
Even though Rust functions can only return one value, a tuple _is_ one value,
-that happens to be made up of two. You can also see in this example how you
+that happens to be made up of more than one value. You can also see in this example how you
can destructure a pattern returned by a function, as well.
Tuples are a very simple data structure, and so are not often what you want.
| break | const | continue | crate | do |
| else | enum | extern | false | final |
| fn | for | if | impl | in |
-| let | loop | match | mod | move |
-| mut | offsetof | override | priv | pub |
-| pure | ref | return | sizeof | static |
-| self | struct | super | true | trait |
-| type | typeof | unsafe | unsized | use |
-| virtual | where | while | yield |
+| let | loop | macro | match | mod |
+| move | mut | offsetof | override | priv |
+| pub | pure | ref | return | sizeof |
+| static | self | struct | super | true |
+| trait | type | typeof | unsafe | unsized |
+| use | virtual | where | while | yield |
Each of these keywords has special meaning in its grammar, and all of them are
| non_special_token ;
```
-User-defined syntax extensions are called "macros", and the `macro_rules`
-syntax extension defines them. Currently, user-defined macros can expand to
-expressions, statements, items, or patterns.
+`macro_rules` allows users to define syntax extension in a declarative way. We
+call such extensions "macros by example" or simply "macros" — to be distinguished
+from the "procedural macros" defined in [compiler plugins][plugin].
+
+Currently, macros can expand to expressions, statements, items, or patterns.
(A `sep_token` is any token other than `*` and `+`. A `non_special_token` is
any token other than a delimiter or `$`.)
caller. Every control path in a diverging function must end with a `panic!()` or
a call to another diverging function on every control path. The `!` annotation
does *not* denote a type. Rather, the result type of a diverging function is a
-special type called $\bot$ ("bottom") that unifies with any type. Rust has no
-syntax for $\bot$.
+special type called ⊥ ("bottom") that unifies with any type. Rust has no
+syntax for ⊥.
It might be necessary to declare a diverging function because as mentioned
previously, the typechecker checks that every control path in a function ends
### Module-only attributes
-- `macro_escape` - macros defined in this module will be visible in the
- module's parent, after this module has been included.
- `no_implicit_prelude` - disable injecting `use std::prelude::*` in this
module.
- `path` - specifies the file to load the module from. `#[path="foo.rs"] mod
remove any padding between fields (note that this is very fragile and may
break platforms which require aligned access).
+### Macro- and plugin-related attributes
+
+- `macro_use` on a `mod` — macros defined in this module will be visible in the
+ module's parent, after this module has been included.
+
+- `macro_use` on an `extern crate` — load macros from this crate. An optional
+ list of names `#[macro_use(foo, bar)]` restricts the import to just those
+ macros named. The `extern crate` must appear at the crate root, not inside
+ `mod`, which ensures proper function of the [`$crate` macro
+ variable](guide-macros.html#the-variable-$crate).
+
+- `macro_reexport` on an `extern crate` — re-export the named macros.
+
+- `macro_export` - export a macro for cross-crate usage.
+
+- `plugin` on an `extern crate` — load this crate as a [compiler
+ plugin][plugin]. The `plugin` feature gate is required. Any arguments to
+ the attribute, e.g. `#[plugin=...]` or `#[plugin(...)]`, are provided to the
+ plugin.
+
+- `no_link` on an `extern crate` — even if we load this crate for macros or
+ compiler plugins, don't link it into the output.
+
+See the [macros guide](guide-macros.html#scoping-and-macro-import/export) for
+more information on macro scope.
+
+
### 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.
- `no_mangle` - on any item, do not apply the standard name mangling. Set the
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][plugin] 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.
- `simd` - on certain tuple structs, derive the arithmetic operators, which
lower to the target's SIMD instructions, if any; the `simd` feature gate
is necessary to use this attribute.
* `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.
-
* `non_ascii_idents` - The compiler supports the use of non-ascii identifiers,
but the implementation is a little rough around the
edges, so this can be seen as an experimental feature
closure as `once` is unlikely to be supported going forward. So
they are hidden behind this feature until they are to be removed.
-* `phase` - Usage of the `#[phase]` attribute allows loading compiler plugins
- for custom lints or syntax extensions. The implementation is
- considered unwholesome and in need of overhaul, and it is not clear
- what they will look like moving forward.
+* `plugin` - Usage of [compiler plugins][plugin] for custom lints or syntax extensions.
+ These depend on compiler internals and are subject to change.
-* `plugin_registrar` - Indicates that a crate has [compiler plugins][plugin] that it
- wants to load. As with `phase`, the implementation is
- in need of an overhaul, and it is not clear that plugins
- defined using this will continue to work.
+* `plugin_registrar` - Indicates that a crate provides [compiler plugins][plugin].
* `quote` - Allows use of the `quote_*!` family of macros, which are
implemented very poorly and will likely change significantly
```
-Patterns can also dereference pointers by using the `&`, `box` symbols,
-as appropriate. For example, these two matches on `x: &int` are equivalent:
+Patterns can also dereference pointers by using the `&`, `&mut` and `box`
+symbols, as appropriate. For example, these two matches on `x: &int` are
+equivalent:
```
# let x = &3i;
*TODO*.
-# Appendix: Influences and further references
-
-## Influences
-
-> The essential problem that must be solved in making a fault-tolerant
-> software system is therefore that of fault-isolation. Different programmers
-> will write different modules, some modules will be correct, others will have
-> errors. We do not want the errors in one module to adversely affect the
-> behaviour of a module which does not have any errors.
->
-> — Joe Armstrong
-
-> In our approach, all data is private to some process, and processes can
-> only communicate through communications channels. *Security*, as used
-> in this paper, is the property which guarantees that processes in a system
-> cannot affect each other except by explicit communication.
->
-> When security is absent, nothing which can be proven about a single module
-> in isolation can be guaranteed to hold when that module is embedded in a
-> system [...]
->
-> — Robert Strom and Shaula Yemini
-
-> Concurrent and applicative programming complement each other. The
-> ability to send messages on channels provides I/O without side effects,
-> while the avoidance of shared data helps keep concurrent processes from
-> colliding.
->
-> — Rob Pike
-
-Rust is not a particularly original language. It may however appear unusual by
-contemporary standards, as its design elements are drawn from a number of
-"historical" languages that have, with a few exceptions, fallen out of favour.
-Five prominent lineages contribute the most, though their influences have come
-and gone during the course of Rust's development:
-
-* The NIL (1981) and Hermes (1990) family. These languages were developed by
- Robert Strom, Shaula Yemini, David Bacon and others in their group at IBM
- Watson Research Center (Yorktown Heights, NY, USA).
-
-* The Erlang (1987) language, developed by Joe Armstrong, Robert Virding, Claes
- Wikström, Mike Williams and others in their group at the Ericsson Computer
- Science Laboratory (Älvsjö, Stockholm, Sweden) .
-
-* The Sather (1990) language, developed by Stephen Omohundro, Chu-Cheow Lim,
- Heinz Schmidt and others in their group at The International Computer
- Science Institute of the University of California, Berkeley (Berkeley, CA,
- USA).
-
-* The Newsqueak (1988), Alef (1995), and Limbo (1996) family. These
- languages were developed by Rob Pike, Phil Winterbottom, Sean Dorward and
- others in their group at Bell Labs Computing Sciences Research Center
- (Murray Hill, NJ, USA).
-
-* The Napier (1985) and Napier88 (1988) family. These languages were
- developed by Malcolm Atkinson, Ron Morrison and others in their group at
- the University of St. Andrews (St. Andrews, Fife, UK).
-
-Additional specific influences can be seen from the following languages:
-
-* The structural algebraic types and compilation manager of SML.
-* The attribute and assembly systems of C#.
-* The references and deterministic destructor system of C++.
-* The memory region systems of the ML Kit and Cyclone.
-* The typeclass system of Haskell.
-* The lexical identifier rule of Python.
-* The block syntax of Ruby.
+# Appendix: Influences
+
+Rust is not a particularly original language, with design elements coming from
+a wide range of sources. Some of these are listed below (including elements
+that have since been removed):
+
+* SML, OCaml: algebraic datatypes, pattern matching, type inference,
+ semicolon statement separation
+* C++: references, RAII, smart pointers, move semantics, monomorphisation,
+ memory model
+* ML Kit, Cyclone: region based memory management
+* Haskell (GHC): typeclasses, type families
+* Newsqueak, Alef, Limbo: channels, concurrency
+* Erlang: message passing, task failure, ~~linked task failure~~,
+ ~~lightweight concurrency~~
+* Swift: optional bindings
+* Scheme: hygienic macros
+* C#: attributes
+* Ruby: ~~block syntax~~
+* NIL, Hermes: ~~typestate~~
+* [Unicode Annex #31](http://www.unicode.org/reports/tr31/): identifier and
+ pattern syntax
[ffi]: guide-ffi.html
[plugin]: guide-plugin.html
--- /dev/null
+\usepackage{newunicodechar}
+\newunicodechar⊥{{$\bot$}}
<list name="type">
<item> type </item>
</list>
+ <list name="reserved">
+ <item> abstract </item>
+ <item> alignof </item>
+ <item> be </item>
+ <item> do </item>
+ <item> final </item>
+ <item> offsetof </item>
+ <item> override </item>
+ <item> priv </item>
+ <item> pure </item>
+ <item> sizeof </item>
+ <item> typeof </item>
+ <item> unsized </item>
+ <item> yield </item>
+ </list>
<list name="keywords">
<item> as </item>
- <item> break </item>
<item> box </item>
+ <item> break </item>
<item> const </item>
<item> continue </item>
<item> crate </item>
- <item> do </item>
- <item> drop </item>
<item> else </item>
<item> enum </item>
<item> extern </item>
<item> for </item>
<item> if </item>
<item> impl </item>
+ <item> in </item>
<item> let </item>
<item> loop </item>
<item> match </item>
<item> mod </item>
<item> move </item>
<item> mut </item>
- <item> priv </item>
<item> pub </item>
<item> ref </item>
<item> return </item>
<DetectSpaces/>
<keyword String="fn" attribute="Keyword" context="Function"/>
<keyword String="type" attribute="Keyword" context="Type"/>
+ <keyword String="reserved" attribute="Keyword" context="#stay"/>
<keyword String="keywords" attribute="Keyword" context="#stay"/>
<keyword String="types" attribute="Type" context="#stay"/>
<keyword String="traits" attribute="Trait" context="#stay"/>
" Maintainer: Patrick Walton <pcwalton@mozilla.com>
" Maintainer: Ben Blum <bblum@cs.cmu.edu>
" Maintainer: Chris Morgan <me@chrismorgan.info>
-" Last Change: July 18, 2014
+" Last Change: January 5, 2015
if version < 600
syntax clear
syn match rustMacroVariable "$\w\+"
" Reserved (but not yet used) keywords {{{2
-syn keyword rustReservedKeyword alignof be do offsetof priv pure sizeof typeof unsized yield abstract final override
+syn keyword rustReservedKeyword alignof be do offsetof priv pure sizeof typeof unsized yield abstract final override macro
" Built-in types {{{2
syn keyword rustType int uint float char bool u8 u16 u32 u64 f32
" Reexported core operators {{{3
syn keyword rustTrait Copy Send Sized Sync
-syn keyword rustTrait Add Sub Mul Div Rem Neg Not
-syn keyword rustTrait BitAnd BitOr BitXor
-syn keyword rustTrait Drop Deref DerefMut
-syn keyword rustTrait Shl Shr
-syn keyword rustTrait Index IndexMut
-syn keyword rustTrait Slice SliceMut
-syn keyword rustTrait Fn FnMut FnOnce
+syn keyword rustTrait Drop Fn FnMut FnOnce
" Reexported functions {{{3
-"syn keyword rustFunction range repeat
-"syn keyword rustFunction drop
-"syn keyword rustFunction from_str
+syn keyword rustFunction drop
" Reexported types and traits {{{3
-syn keyword rustTrait Ascii AsciiCast OwnedAsciiCast AsciiStr
-syn keyword rustTrait IntoBytes
-syn keyword rustTrait ToCStr
-syn keyword rustTrait Char UnicodeChar
+syn keyword rustTrait Box
+syn keyword rustTrait CharExt
syn keyword rustTrait Clone
syn keyword rustTrait PartialEq PartialOrd Eq Ord
-syn keyword rustEnum Ordering Equiv
-syn keyword rustEnumVariant Less Equal Greater
-syn keyword rustTrait FromIterator Extend ExactSizeIterator
-syn keyword rustTrait Iterator DoubleEndedIterator
-syn keyword rustTrait RandomAccessIterator CloneableIterator
-syn keyword rustTrait OrdIterator MutableDoubleEndedIterator
-syn keyword rustTrait ToPrimitive FromPrimitive
-syn keyword rustTrait Box
+syn keyword rustTrait DoubleEndedIterator
+syn keyword rustTrait ExactSizeIterator
+syn keyword rustTrait Iterator IteratorExt Extend
syn keyword rustEnum Option
syn keyword rustEnumVariant Some None
-syn keyword rustTrait GenericPath Path PosixPath WindowsPath
-syn keyword rustTrait RawPtr RawMutPtr
+syn keyword rustTrait PtrExt MutPtrExt
syn keyword rustEnum Result
syn keyword rustEnumVariant Ok Err
-syn keyword rustTrait Buffer Writer Reader Seek BufferPrelude
-syn keyword rustTrait Str StrVector StrPrelude
-syn keyword rustTrait IntoMaybeOwned StrAllocating UnicodeStrPrelude
-syn keyword rustTrait Tuple1 Tuple2 Tuple3 Tuple4
-syn keyword rustTrait Tuple5 Tuple6 Tuple7 Tuple8
-syn keyword rustTrait Tuple9 Tuple10 Tuple11 Tuple12
-syn keyword rustTrait SlicePrelude AsSlice CloneSlicePrelude
-syn keyword rustTrait VectorVector PartialEqSlicePrelude OrdSlicePrelude
-syn keyword rustTrait CloneSliceAllocPrelude OrdSliceAllocPrelude SliceAllocPrelude
-syn keyword rustTrait IntoString String ToString
+syn keyword rustTrait AsSlice
+syn keyword rustTrait SliceExt SliceConcatExt
+syn keyword rustTrait Str StrExt
+syn keyword rustTrait String ToString
syn keyword rustTrait Vec
-
-" Reexported runtime types {{{3
-"syn keyword rustFunction sync_channel channel
-syn keyword rustTrait SyncSender Sender Receiver
-"syn keyword rustFunction spawn
+" FIXME: remove when path reform lands
+syn keyword rustTrait Path GenericPath
+" FIXME: remove when I/O reform lands
+syn keyword rustTrait Buffer Writer Reader Seek BufferPrelude
+" FIXME: remove when range syntax lands
+syn keyword rustFunction range
" Other syntax {{{2
-
syn keyword rustSelf self
syn keyword rustBoolean true false
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(globs, phase, macro_rules)]
+#![feature(globs, plugin)]
extern crate syntax;
extern crate rustc;
-#[phase(link)]
extern crate regex;
-#[phase(link, plugin)]
+#[macro_use]
extern crate log;
use std::collections::HashMap;
assert!(rustc_tok.sp == antlr_tok.sp, "{} and {} have different spans", rustc_tok,
antlr_tok);
- macro_rules! matches (
+ macro_rules! matches {
( $($x:pat),+ ) => (
match rustc_tok.tok {
$($x => match antlr_tok.tok {
ref c => assert!(c == &antlr_tok.tok, "{} is not {}", rustc_tok, antlr_tok)
}
)
- );
+ }
matches!(
token::Literal(token::Byte(..), _),
}
}
-#[experimental = "Deref is experimental."]
+#[stable]
impl<T> Deref for Arc<T> {
type Target = T;
}
#[unsafe_destructor]
-#[experimental = "waiting on stability of Drop"]
+#[stable]
impl<T: Sync + Send> Drop for Arc<T> {
/// Drops the `Arc<T>`.
///
}
#[unsafe_destructor]
-#[experimental = "Weak pointers may not belong in this module."]
+#[stable]
impl<T: Sync + Send> Drop for Weak<T> {
/// Drops the `Weak<T>`.
///
}
#[stable]
-impl<Sized? T: PartialEq> PartialEq for Box<T> {
+impl<T: ?Sized + PartialEq> PartialEq for Box<T> {
#[inline]
fn eq(&self, other: &Box<T>) -> bool { PartialEq::eq(&**self, &**other) }
#[inline]
fn ne(&self, other: &Box<T>) -> bool { PartialEq::ne(&**self, &**other) }
}
#[stable]
-impl<Sized? T: PartialOrd> PartialOrd for Box<T> {
+impl<T: ?Sized + PartialOrd> PartialOrd for Box<T> {
#[inline]
fn partial_cmp(&self, other: &Box<T>) -> Option<Ordering> {
PartialOrd::partial_cmp(&**self, &**other)
fn gt(&self, other: &Box<T>) -> bool { PartialOrd::gt(&**self, &**other) }
}
#[stable]
-impl<Sized? T: Ord> Ord for Box<T> {
+impl<T: ?Sized + Ord> Ord for Box<T> {
#[inline]
fn cmp(&self, other: &Box<T>) -> Ordering {
Ord::cmp(&**self, &**other)
}
#[stable]}
-impl<Sized? T: Eq> Eq for Box<T> {}
+impl<T: ?Sized + Eq> Eq for Box<T> {}
-impl<S: hash::Writer, Sized? T: Hash<S>> Hash<S> for Box<T> {
+impl<S: hash::Writer, T: ?Sized + Hash<S>> Hash<S> for Box<T> {
#[inline]
fn hash(&self, state: &mut S) {
(**self).hash(state);
}
}
-impl<Sized? T: fmt::Show> fmt::Show for Box<T> {
+impl<T: ?Sized + fmt::Show> fmt::Show for Box<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
(**self).fmt(f)
}
}
}
-impl<Sized? T> Deref for Box<T> {
+#[stable]
+impl<T: ?Sized> Deref for Box<T> {
type Target = T;
fn deref(&self) -> &T { &**self }
}
-impl<Sized? T> DerefMut for Box<T> {
+#[stable]
+impl<T: ?Sized> DerefMut for Box<T> {
fn deref_mut(&mut self) -> &mut T { &mut **self }
}
#![feature(lang_items, phase, unsafe_destructor, default_type_params, old_orphan_check)]
#![feature(associated_types)]
+#[cfg(stage0)]
#[phase(plugin, link)]
extern crate core;
+
+#[cfg(not(stage0))]
+#[macro_use]
+extern crate core;
+
extern crate libc;
// Allow testing this library
-#[cfg(test)] #[phase(plugin, link)] extern crate std;
-#[cfg(test)] #[phase(plugin, link)] extern crate log;
+#[cfg(all(test, stage0))]
+#[phase(plugin, link)]
+extern crate std;
+
+#[cfg(all(test, not(stage0)))]
+#[macro_use]
+extern crate std;
+
+#[cfg(all(test, stage0))]
+#[phase(plugin, link)]
+extern crate log;
+
+#[cfg(all(test, not(stage0)))]
+#[macro_use]
+extern crate log;
// Heaps provided for low-level allocation strategies
}
}
-#[experimental = "Deref is experimental."]
+#[stable]
impl<T> Deref for Rc<T> {
type Target = T;
}
#[unsafe_destructor]
-#[experimental = "Drop is experimental."]
+#[stable]
impl<T> Drop for Rc<T> {
/// Drops the `Rc<T>`.
///
}
#[unsafe_destructor]
-#[experimental = "Weak pointers may not belong in this module."]
+#[stable]
impl<T> Drop for Weak<T> {
/// Drops the `Weak<T>`.
///
//! ```
#![allow(missing_docs)]
+#![stable]
use core::prelude::*;
}
/// `BinaryHeap` iterator.
+#[stable]
pub struct Iter <'a, T: 'a> {
iter: slice::Iter<'a, T>,
}
// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
+#[stable]
impl<'a, T> Clone for Iter<'a, T> {
fn clone(&self) -> Iter<'a, T> {
Iter { iter: self.iter.clone() }
impl<'a, T> ExactSizeIterator for Iter<'a, T> {}
/// An iterator that moves out of a `BinaryHeap`.
+#[stable]
pub struct IntoIter<T> {
iter: vec::IntoIter<T>,
}
impl<T> ExactSizeIterator for IntoIter<T> {}
/// An iterator that drains a `BinaryHeap`.
+#[unstable = "recent addition"]
pub struct Drain<'a, T: 'a> {
iter: vec::Drain<'a, T>,
}
#[stable]
/// A view into a single entry in a map, which may either be vacant or occupied.
-pub enum Entry<'a, Sized? Q:'a, K:'a, V:'a> {
+pub enum Entry<'a, Q: ?Sized +'a, K:'a, V:'a> {
/// A vacant Entry
Vacant(VacantEntry<'a, Q, K, V>),
/// An occupied Entry
#[stable]
/// A vacant Entry.
-pub struct VacantEntry<'a, Sized? Q:'a, K:'a, V:'a> {
+pub struct VacantEntry<'a, Q: ?Sized +'a, K:'a, V:'a> {
key: &'a Q,
stack: stack::SearchStack<'a, K, V, node::handle::Edge, node::handle::Leaf>,
}
/// assert_eq!(map.get(&2), None);
/// ```
#[stable]
- pub fn get<Sized? Q>(&self, key: &Q) -> Option<&V> where Q: BorrowFrom<K> + Ord {
+ pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&V> where Q: BorrowFrom<K> + Ord {
let mut cur_node = &self.root;
loop {
match Node::search(cur_node, key) {
/// assert_eq!(map.contains_key(&2), false);
/// ```
#[stable]
- pub fn contains_key<Sized? Q>(&self, key: &Q) -> bool where Q: BorrowFrom<K> + Ord {
+ pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool where Q: BorrowFrom<K> + Ord {
self.get(key).is_some()
}
/// ```
// See `get` for implementation notes, this is basically a copy-paste with mut's added
#[stable]
- pub fn get_mut<Sized? Q>(&mut self, key: &Q) -> Option<&mut V> where Q: BorrowFrom<K> + Ord {
+ pub fn get_mut<Q: ?Sized>(&mut self, key: &Q) -> Option<&mut V> where Q: BorrowFrom<K> + Ord {
// temp_node is a Borrowck hack for having a mutable value outlive a loop iteration
let mut temp_node = &mut self.root;
loop {
/// assert_eq!(map.remove(&1), None);
/// ```
#[stable]
- pub fn remove<Sized? Q>(&mut self, key: &Q) -> Option<V> where Q: BorrowFrom<K> + Ord {
+ pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V> where Q: BorrowFrom<K> + Ord {
// See `swap` for a more thorough description of the stuff going on in here
let mut stack = stack::PartialSearchStack::new(self);
loop {
}
#[stable]
-impl<K: Ord, Sized? Q, V> Index<Q> for BTreeMap<K, V>
+impl<K: Ord, Q: ?Sized, V> Index<Q> for BTreeMap<K, V>
where Q: BorrowFrom<K> + Ord
{
type Output = V;
}
#[stable]
-impl<K: Ord, Sized? Q, V> IndexMut<Q> for BTreeMap<K, V>
+impl<K: Ord, Q: ?Sized, V> IndexMut<Q> for BTreeMap<K, V>
where Q: BorrowFrom<K> + Ord
{
type Output = V;
#[stable]
impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> {}
-impl<'a, Sized? Q, K: Ord, V> Entry<'a, Q, K, V> {
+impl<'a, Q: ?Sized, K: Ord, V> Entry<'a, Q, K, V> {
#[unstable = "matches collection reform v2 specification, waiting for dust to settle"]
/// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant
pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, Q, K, V>> {
}
}
-impl<'a, Sized? Q: ToOwned<K>, K: Ord, V> VacantEntry<'a, Q, K, V> {
+impl<'a, Q: ?Sized + ToOwned<K>, K: Ord, V> VacantEntry<'a, Q, K, V> {
#[stable]
/// Sets the value of the entry with the VacantEntry's key,
/// and returns a mutable reference to it.
/// ```
/// The key must have the same ordering before or after `.to_owned()` is called.
#[stable]
- pub fn entry<'a, Sized? Q>(&'a mut self, mut key: &'a Q) -> Entry<'a, Q, K, V>
+ pub fn entry<'a, Q: ?Sized>(&'a mut self, mut key: &'a Q) -> Entry<'a, Q, K, V>
where Q: Ord + ToOwned<K>
{
// same basic logic of `swap` and `pop`, blended together
/// Searches for the given key in the node. If it finds an exact match,
/// `Found` will be yielded with the matching index. If it doesn't find an exact match,
/// `GoDown` will be yielded with the index of the subtree the key must lie in.
- pub fn search<Sized? Q, NodeRef: Deref<Target=Node<K, V>>>(node: NodeRef, key: &Q)
+ pub fn search<Q: ?Sized, NodeRef: Deref<Target=Node<K, V>>>(node: NodeRef, key: &Q)
-> SearchResult<NodeRef> where Q: BorrowFrom<K> + Ord {
// FIXME(Gankro): Tune when to search linear or binary based on B (and maybe K/V).
// For the B configured as of this writing (B = 6), binary search was *significantly*
}
}
- fn search_linear<Sized? Q>(&self, key: &Q) -> (bool, uint) where Q: BorrowFrom<K> + Ord {
+ fn search_linear<Q: ?Sized>(&self, key: &Q) -> (bool, uint) where Q: BorrowFrom<K> + Ord {
for (i, k) in self.keys().iter().enumerate() {
match key.cmp(BorrowFrom::borrow_from(k)) {
Greater => {},
/// assert_eq!(set.contains(&4), false);
/// ```
#[stable]
- pub fn contains<Sized? Q>(&self, value: &Q) -> bool where Q: BorrowFrom<T> + Ord {
+ pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool where Q: BorrowFrom<T> + Ord {
self.map.contains_key(value)
}
/// assert_eq!(set.remove(&2), false);
/// ```
#[stable]
- pub fn remove<Sized? Q>(&mut self, value: &Q) -> bool where Q: BorrowFrom<T> + Ord {
+ pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool where Q: BorrowFrom<T> + Ord {
self.map.remove(value).is_some()
}
}
// Backlinks over DList::prev are raw pointers that form a full chain in
// the reverse direction.
+#![stable]
+
use core::prelude::*;
use alloc::boxed::Box;
}
#[allow(deprecated)]
+ #[test]
fn test_append() {
{
let mut m = DList::new();
#![feature(associated_types)]
#![no_std]
-#[phase(plugin, link)] extern crate core;
+#[cfg(stage0)]
+#[phase(plugin, link)]
+extern crate core;
+
+#[cfg(not(stage0))]
+#[macro_use]
+extern crate core;
+
extern crate unicode;
extern crate alloc;
#[cfg(test)] extern crate test;
-#[cfg(test)] #[phase(plugin, link)] extern crate std;
-#[cfg(test)] #[phase(plugin, link)] extern crate log;
+#[cfg(all(test, stage0))]
+#[phase(plugin, link)]
+extern crate std;
+
+#[cfg(all(test, not(stage0)))]
+#[macro_use]
+extern crate std;
+#[cfg(all(test, stage0))]
+#[phase(plugin, link)]
+extern crate log;
+
+#[cfg(all(test, not(stage0)))]
+#[macro_use]
+extern crate log;
pub use binary_heap::BinaryHeap;
pub use bitv::Bitv;
pub use vec::Vec;
pub use vec_map::VecMap;
+// Needed for the vec! macro
+pub use alloc::boxed;
+
+#[cfg_attr(stage0, macro_escape)]
+#[cfg_attr(not(stage0), macro_use)]
mod macros;
pub mod binary_heap;
pub mod vec;
pub mod vec_map;
+#[stable]
pub mod bitv {
pub use bit::{Bitv, Iter};
}
+#[stable]
pub mod bitv_set {
pub use bit::{BitvSet, Union, Intersection, Difference, SymmetricDifference};
pub use bit::SetIter as Iter;
}
+#[stable]
pub mod btree_map {
pub use btree::map::*;
}
+#[stable]
pub mod btree_set {
pub use btree::set::*;
}
pub use core::iter::range;
pub use core::iter::{FromIterator, Extend, IteratorExt};
pub use core::iter::{Iterator, DoubleEndedIterator, RandomAccessIterator};
- pub use core::iter::{IteratorCloneExt, CloneIteratorExt};
- pub use core::iter::{IteratorOrdExt, MutableDoubleEndedIterator, ExactSizeIterator};
+ pub use core::iter::{ExactSizeIterator};
pub use core::kinds::{Copy, Send, Sized, Sync};
pub use core::mem::drop;
pub use core::ops::{Drop, Fn, FnMut, FnOnce};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![macro_escape]
-
/// Creates a `std::vec::Vec` containing the arguments.
+// NOTE: remove after the next snapshot
+#[cfg(stage0)]
macro_rules! vec {
($($e:expr),*) => ({
// leading _ to allow empty construction without a warning.
($($e:expr),+,) => (vec!($($e),+))
}
+/// Creates a `Vec` containing the arguments.
+#[cfg(not(stage0))]
+#[macro_export]
+macro_rules! vec {
+ ($($x:expr),*) => ({
+ let xs: $crate::boxed::Box<[_]> = box [$($x),*];
+ $crate::slice::SliceExt::into_vec(xs)
+ });
+ ($($x:expr,)*) => (vec![$($x),*])
+}
//! ends of the container. It also has `O(1)` indexing like a vector. The contained elements are
//! not required to be copyable, and the queue will be sendable if the contained type is sendable.
+#![stable]
+
use core::prelude::*;
use core::cmp::Ordering;
use core::default::Default;
use core::fmt;
-use core::iter::{self, FromIterator, RandomAccessIterator};
+use core::iter::{self, repeat, FromIterator, RandomAccessIterator};
use core::kinds::marker;
use core::mem;
use core::num::{Int, UnsignedInt};
use alloc::heap;
-static INITIAL_CAPACITY: uint = 8u; // 2^3
-static MINIMUM_CAPACITY: uint = 2u;
-
-// FIXME(conventions): implement shrink_to_fit. Awkward with the current design, but it should
-// be scrapped anyway. Defer to rewrite?
+static INITIAL_CAPACITY: uint = 7u; // 2^3 - 1
+static MINIMUM_CAPACITY: uint = 1u; // 2 - 1
/// `RingBuf` is a circular buffer, which can be used as a double-ended queue efficiently.
#[stable]
self.cap);
ptr::copy_memory(
self.ptr.offset(dst as int),
- self.ptr.offset(src as int) as *const T,
+ self.ptr.offset(src as int),
+ len);
+ }
+
+ /// Copies a contiguous block of memory len long from src to dst
+ #[inline]
+ unsafe fn copy_nonoverlapping(&self, dst: uint, src: uint, len: uint) {
+ debug_assert!(dst + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
+ self.cap);
+ debug_assert!(src + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
+ self.cap);
+ ptr::copy_nonoverlapping_memory(
+ self.ptr.offset(dst as int),
+ self.ptr.offset(src as int),
len);
}
}
#[stable]
pub fn with_capacity(n: uint) -> RingBuf<T> {
// +1 since the ringbuffer always leaves one space empty
- let cap = cmp::max(n + 1, MINIMUM_CAPACITY).next_power_of_two();
+ let cap = cmp::max(n + 1, MINIMUM_CAPACITY + 1).next_power_of_two();
+ assert!(cap > n, "capacity overflow");
let size = cap.checked_mul(mem::size_of::<T>())
.expect("capacity overflow");
// Nop
} else if self.head < oldcap - self.tail { // B
unsafe {
- ptr::copy_nonoverlapping_memory(
- self.ptr.offset(oldcap as int),
- self.ptr as *const T,
- self.head
- );
+ self.copy_nonoverlapping(oldcap, 0, self.head);
}
self.head += oldcap;
debug_assert!(self.head > self.tail);
} else { // C
+ let new_tail = count - (oldcap - self.tail);
+ unsafe {
+ self.copy_nonoverlapping(new_tail, self.tail, oldcap - self.tail);
+ }
+ self.tail = new_tail;
+ debug_assert!(self.head < self.tail);
+ }
+ debug_assert!(self.head < self.cap);
+ debug_assert!(self.tail < self.cap);
+ debug_assert!(self.cap.count_ones() == 1);
+ }
+ }
+
+ /// Shrinks the capacity of the ringbuf as much as possible.
+ ///
+ /// It will drop down as close as possible to the length but the allocator may still inform the
+ /// ringbuf that there is space for a few more elements.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::RingBuf;
+ ///
+ /// let mut buf = RingBuf::with_capacity(15);
+ /// buf.extend(range(0u, 4));
+ /// assert_eq!(buf.capacity(), 15);
+ /// buf.shrink_to_fit();
+ /// assert!(buf.capacity() >= 4);
+ /// ```
+ pub fn shrink_to_fit(&mut self) {
+ // +1 since the ringbuffer always leaves one space empty
+ // len + 1 can't overflow for an existing, well-formed ringbuf.
+ let target_cap = cmp::max(self.len() + 1, MINIMUM_CAPACITY + 1).next_power_of_two();
+ if target_cap < self.cap {
+ // There are three cases of interest:
+ // All elements are out of desired bounds
+ // Elements are contiguous, and head is out of desired bounds
+ // Elements are discontiguous, and tail is out of desired bounds
+ //
+ // At all other times, element positions are unaffected.
+ //
+ // Indicates that elements at the head should be moved.
+ let head_outside = self.head == 0 || self.head >= target_cap;
+ // Move elements from out of desired bounds (positions after target_cap)
+ if self.tail >= target_cap && head_outside {
+ // T H
+ // [. . . . . . . . o o o o o o o . ]
+ // T H
+ // [o o o o o o o . ]
+ unsafe {
+ self.copy_nonoverlapping(0, self.tail, self.len());
+ }
+ self.head = self.len();
+ self.tail = 0;
+ } else if self.tail != 0 && self.tail < target_cap && head_outside {
+ // T H
+ // [. . . o o o o o o o . . . . . . ]
+ // H T
+ // [o o . o o o o o ]
+ let len = self.wrap_index(self.head - target_cap);
+ unsafe {
+ self.copy_nonoverlapping(0, target_cap, len);
+ }
+ self.head = len;
+ debug_assert!(self.head < self.tail);
+ } else if self.tail >= target_cap {
+ // H T
+ // [o o o o o . . . . . . . . . o o ]
+ // H T
+ // [o o o o o . o o ]
+ debug_assert!(self.wrap_index(self.head - 1) < target_cap);
+ let len = self.cap - self.tail;
+ let new_tail = target_cap - len;
unsafe {
- ptr::copy_nonoverlapping_memory(
- self.ptr.offset((count - (oldcap - self.tail)) as int),
- self.ptr.offset(self.tail as int) as *const T,
- oldcap - self.tail
- );
+ self.copy_nonoverlapping(new_tail, self.tail, len);
}
- self.tail = count - (oldcap - self.tail);
+ self.tail = new_tail;
debug_assert!(self.head < self.tail);
}
+
+ if mem::size_of::<T>() != 0 {
+ let old = self.cap * mem::size_of::<T>();
+ let new_size = target_cap * mem::size_of::<T>();
+ unsafe {
+ self.ptr = heap::reallocate(self.ptr as *mut u8,
+ old,
+ new_size,
+ mem::min_align_of::<T>()) as *mut T;
+ if self.ptr.is_null() { ::alloc::oom() }
+ }
+ }
+ self.cap = target_cap;
debug_assert!(self.head < self.cap);
debug_assert!(self.tail < self.cap);
debug_assert!(self.cap.count_ones() == 1);
}
}
+ /// Shorten a ringbuf, dropping excess elements from the back.
+ ///
+ /// If `len` is greater than the ringbuf's current length, this has no
+ /// effect.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::RingBuf;
+ ///
+ /// let mut buf = RingBuf::new();
+ /// buf.push_back(5i);
+ /// buf.push_back(10i);
+ /// buf.push_back(15);
+ /// buf.truncate(1);
+ /// assert_eq!(buf.len(), 1);
+ /// assert_eq!(Some(&5), buf.get(0));
+ /// ```
+ #[unstable = "matches collection reform specification; waiting on panic semantics"]
+ pub fn truncate(&mut self, len: uint) {
+ for _ in range(len, self.len()) {
+ self.pop_back();
+ }
+ }
+
/// Returns a front-to-back iterator.
///
/// # Examples
self.tail <= self.head
}
+ /// Removes an element from anywhere in the ringbuf and returns it, replacing it with the last
+ /// element.
+ ///
+ /// This does not preserve ordering, but is O(1).
+ ///
+ /// Returns `None` if `index` is out of bounds.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::RingBuf;
+ ///
+ /// let mut buf = RingBuf::new();
+ /// assert_eq!(buf.swap_back_remove(0), None);
+ /// buf.push_back(5i);
+ /// buf.push_back(99);
+ /// buf.push_back(15);
+ /// buf.push_back(20);
+ /// buf.push_back(10);
+ /// assert_eq!(buf.swap_back_remove(1), Some(99));
+ /// ```
+ #[unstable = "the naming of this function may be altered"]
+ pub fn swap_back_remove(&mut self, index: uint) -> Option<T> {
+ let length = self.len();
+ if length > 0 && index < length - 1 {
+ self.swap(index, length - 1);
+ } else if index >= length {
+ return None;
+ }
+ self.pop_back()
+ }
+
+ /// Removes an element from anywhere in the ringbuf and returns it, replacing it with the first
+ /// element.
+ ///
+ /// This does not preserve ordering, but is O(1).
+ ///
+ /// Returns `None` if `index` is out of bounds.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::RingBuf;
+ ///
+ /// let mut buf = RingBuf::new();
+ /// assert_eq!(buf.swap_front_remove(0), None);
+ /// buf.push_back(15i);
+ /// buf.push_back(5);
+ /// buf.push_back(10);
+ /// buf.push_back(99);
+ /// buf.push_back(20i);
+ /// assert_eq!(buf.swap_front_remove(3), Some(99));
+ /// ```
+ #[unstable = "the naming of this function may be altered"]
+ pub fn swap_front_remove(&mut self, index: uint) -> Option<T> {
+ let length = self.len();
+ if length > 0 && index < length && index != 0 {
+ self.swap(index, 0);
+ } else if index >= length {
+ return None;
+ }
+ self.pop_front()
+ }
+
/// Inserts an element at position `i` within the ringbuf. Whichever
/// end is closer to the insertion point will be moved to make room,
/// and all the affected elements will be moved to new positions.
///
/// Panics if `i` is greater than ringbuf's length
///
- /// # Example
+ /// # Examples
/// ```rust
/// use std::collections::RingBuf;
///
/// room, and all the affected elements will be moved to new positions.
/// Returns `None` if `i` is out of bounds.
///
- /// # Example
+ /// # Examples
/// ```rust
/// use std::collections::RingBuf;
///
let distance_to_tail = i;
let distance_to_head = self.len() - i;
- let contiguous = self.tail <= self.head;
+ let contiguous = self.is_contiguous();
match (contiguous, distance_to_tail <= distance_to_head, idx >= self.tail) {
(true, true, _) => unsafe {
}
}
+impl<T: Clone> RingBuf<T> {
+ /// Modifies the ringbuf in-place so that `len()` is equal to new_len,
+ /// either by removing excess elements or by appending copies of a value to the back.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::RingBuf;
+ ///
+ /// let mut buf = RingBuf::new();
+ /// buf.push_back(5i);
+ /// buf.push_back(10i);
+ /// buf.push_back(15);
+ /// buf.resize(2, 0);
+ /// buf.resize(6, 20);
+ /// for (a, b) in [5, 10, 20, 20, 20, 20].iter().zip(buf.iter()) {
+ /// assert_eq!(a, b);
+ /// }
+ /// ```
+ #[unstable = "matches collection reform specification; waiting on panic semantics"]
+ pub fn resize(&mut self, new_len: uint, value: T) {
+ let len = self.len();
+
+ if new_len > len {
+ self.extend(repeat(value).take(new_len - len))
+ } else {
+ self.truncate(new_len);
+ }
+ }
+}
+
/// Returns the index in the underlying buffer for a given logical element index.
#[inline]
fn wrap_index(index: uint, size: uint) -> uint {
assert_eq!(ring.get_mut(2), None);
}
+ #[test]
+ fn test_swap_front_back_remove() {
+ fn test(back: bool) {
+ // This test checks that every single combination of tail position and length is tested.
+ // Capacity 15 should be large enough to cover every case.
+ let mut tester = RingBuf::with_capacity(15);
+ let usable_cap = tester.capacity();
+ let final_len = usable_cap / 2;
+
+ for len in range(0, final_len) {
+ let expected = if back {
+ range(0, len).collect()
+ } else {
+ range(0, len).rev().collect()
+ };
+ for tail_pos in range(0, usable_cap) {
+ tester.tail = tail_pos;
+ tester.head = tail_pos;
+ if back {
+ for i in range(0, len * 2) {
+ tester.push_front(i);
+ }
+ for i in range(0, len) {
+ assert_eq!(tester.swap_back_remove(i), Some(len * 2 - 1 - i));
+ }
+ } else {
+ for i in range(0, len * 2) {
+ tester.push_back(i);
+ }
+ for i in range(0, len) {
+ let idx = tester.len() - 1 - i;
+ assert_eq!(tester.swap_front_remove(idx), Some(len * 2 - 1 - i));
+ }
+ }
+ assert!(tester.tail < tester.cap);
+ assert!(tester.head < tester.cap);
+ assert_eq!(tester, expected);
+ }
+ }
+ }
+ test(true);
+ test(false);
+ }
+
#[test]
fn test_insert() {
// This test checks that every single combination of tail position, length, and
}
}
+ #[test]
+ fn test_shrink_to_fit() {
+ // This test checks that every single combination of head and tail position,
+ // is tested. Capacity 15 should be large enough to cover every case.
+
+ let mut tester = RingBuf::with_capacity(15);
+ // can't guarantee we got 15, so have to get what we got.
+ // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else
+ // this test isn't covering what it wants to
+ let cap = tester.capacity();
+ tester.reserve(63);
+ let max_cap = tester.capacity();
+
+ for len in range(0, cap + 1) {
+ // 0, 1, 2, .., len - 1
+ let expected = iter::count(0, 1).take(len).collect();
+ for tail_pos in range(0, max_cap + 1) {
+ tester.tail = tail_pos;
+ tester.head = tail_pos;
+ tester.reserve(63);
+ for i in range(0, len) {
+ tester.push_back(i);
+ }
+ tester.shrink_to_fit();
+ assert!(tester.capacity() <= cap);
+ assert!(tester.tail < tester.cap);
+ assert!(tester.head < tester.cap);
+ assert_eq!(tester, expected);
+ }
+ }
+ }
+
#[test]
fn test_front() {
let mut ring = RingBuf::new();
//! * Further iterators exist that split, chunk or permute the slice.
#![doc(primitive = "slice")]
+#![stable]
use alloc::boxed::Box;
use core::borrow::{BorrowFrom, BorrowFromMut, ToOwned};
////////////////////////////////////////////////////////////////////////////////
/// Allocating extension methods for slices.
-#[unstable = "needs associated types, may merge with other traits"]
-pub trait SliceExt for Sized? {
+#[stable]
+pub trait SliceExt {
+ #[stable]
type Item;
/// Sorts the slice, in place, using `compare` to compare
fn into_vec(self: Box<Self>) -> Vec<Self::Item>;
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<T> SliceExt for [T] {
type Item = T;
////////////////////////////////////////////////////////////////////////////////
#[unstable = "U should be an associated type"]
/// An extension trait for concatenating slices
-pub trait SliceConcatExt<Sized? T, U> for Sized? {
+pub trait SliceConcatExt<T: ?Sized, U> {
/// Flattens a slice of `T` into a single value `U`.
#[stable]
fn concat(&self) -> U;
dir: Direction,
}
+#[stable]
impl Iterator for ElementSwaps {
type Item = (uint, uint);
#[test]
fn test_show() {
- macro_rules! test_show_vec(
+ macro_rules! test_show_vec {
($x:expr, $x_str:expr) => ({
let (x, x_str) = ($x, $x_str);
assert_eq!(format!("{}", x), x_str);
assert_eq!(format!("{}", x.as_slice()), x_str);
})
- );
+ }
let empty: Vec<int> = vec![];
test_show_vec!(empty, "[]");
test_show_vec!(vec![1i], "[1]");
#[test]
fn test_vec_default() {
- macro_rules! t (
+ macro_rules! t {
($ty:ty) => {{
let v: $ty = Default::default();
assert!(v.is_empty());
}}
- );
+ }
t!(&[int]);
t!(Vec<int>);
//! is the same as `&[u8]`.
#![doc(primitive = "str")]
+#![stable]
use self::RecompositionState::*;
use self::DecompositionType::*;
use core::clone::Clone;
use core::iter::AdditiveIterator;
use core::iter::{range, Iterator, IteratorExt};
-use core::kinds::Sized;
use core::ops;
use core::option::Option::{self, Some, None};
use core::slice::AsSlice;
/// External iterator for a string's decomposition's characters.
/// Use with the `std::iter` module.
#[derive(Clone)]
+#[unstable]
pub struct Decompositions<'a> {
kind: DecompositionType,
iter: Chars<'a>,
sorted: bool
}
+#[stable]
impl<'a> Iterator for Decompositions<'a> {
type Item = char;
/// External iterator for a string's recomposition's characters.
/// Use with the `std::iter` module.
#[derive(Clone)]
+#[unstable]
pub struct Recompositions<'a> {
iter: Decompositions<'a>,
state: RecompositionState,
last_ccc: Option<u8>
}
+#[stable]
impl<'a> Iterator for Recompositions<'a> {
type Item = char;
/// External iterator for a string's UTF16 codeunits.
/// Use with the `std::iter` module.
#[derive(Clone)]
+#[unstable]
pub struct Utf16Units<'a> {
encoder: Utf16Encoder<Chars<'a>>
}
+#[stable]
impl<'a> Iterator for Utf16Units<'a> {
type Item = u16;
*/
/// Any string that can be represented as a slice.
-pub trait StrExt for Sized?: ops::Slice<uint, str> {
+#[stable]
+pub trait StrExt: ops::Slice<uint, str> {
/// Escapes each char in `s` with `char::escape_default`.
#[unstable = "return type may change to be an iterator"]
fn escape_default(&self) -> String {
}
}
+#[stable]
impl StrExt for str {}
#[cfg(test)]
#[test]
fn test_is_utf16() {
use unicode::str::is_utf16;
- macro_rules! pos ( ($($e:expr),*) => { { $(assert!(is_utf16($e));)* } });
+ macro_rules! pos {
+ ($($e:expr),*) => { { $(assert!(is_utf16($e));)* } }
+ }
// non-surrogates
pos!(&[0x0000],
&[0x0067, 0xd8ff, 0xddb7, 0x000f, 0xd900, 0xdc80]);
// negative tests
- macro_rules! neg ( ($($e:expr),*) => { { $(assert!(!is_utf16($e));)* } });
+ macro_rules! neg {
+ ($($e:expr),*) => { { $(assert!(!is_utf16($e));)* } }
+ }
neg!(
// surrogate + regular unit
let byte = unsafe_get(v, i);
i += 1;
- macro_rules! error(() => ({
+ macro_rules! error { () => ({
unsafe {
if subseqidx != i_ {
res.as_mut_vec().push_all(v[subseqidx..i_]);
subseqidx = i;
res.as_mut_vec().push_all(REPLACEMENT);
}
- }));
+ })}
if byte < 128u8 {
// subseqidx handles this
}
}
- /// Creates a `String` from a null-terminated `*const u8` buffer.
- ///
- /// This function is unsafe because we dereference memory until we find the
- /// NUL character, which is not guaranteed to be present. Additionally, the
- /// slice is not checked to see whether it contains valid UTF-8
- #[unstable = "just renamed from `mod raw`"]
- pub unsafe fn from_raw_buf(buf: *const u8) -> String {
- String::from_str(str::from_c_str(buf as *const i8))
- }
-
- /// Creates a `String` from a `*const u8` buffer of the given length.
- ///
- /// This function is unsafe because it blindly assumes the validity of the
- /// pointer `buf` for `len` bytes of memory. This function will copy the
- /// memory from `buf` into a new allocation (owned by the returned
- /// `String`).
- ///
- /// This function is also unsafe because it does not validate that the
- /// buffer is valid UTF-8 encoded data.
- #[unstable = "just renamed from `mod raw`"]
- pub unsafe fn from_raw_buf_len(buf: *const u8, len: uint) -> String {
- String::from_utf8_unchecked(Vec::from_raw_buf(buf, len))
- }
-
/// Converts a vector of bytes to a new `String` without checking if
/// it contains valid UTF-8. This is unsafe because it assumes that
/// the UTF-8-ness of the vector has already been validated.
}
}
-#[experimental = "waiting on FromIterator stabilization"]
+#[stable]
impl FromIterator<char> for String {
fn from_iter<I:Iterator<Item=char>>(iterator: I) -> String {
let mut buf = String::new();
}
}
-#[experimental = "waiting on FromIterator stabilization"]
+#[stable]
impl<'a> FromIterator<&'a str> for String {
fn from_iter<I:Iterator<Item=&'a str>>(iterator: I) -> String {
let mut buf = String::new();
}
}
-#[experimental = "waiting on Add stabilization"]
+#[unstable = "recent addition, needs more experience"]
impl<'a> Add<&'a str> for String {
type Output = String;
}
}
-#[experimental = "waiting on Deref stabilization"]
+#[stable]
impl ops::Deref for String {
type Target = str;
String::from_str("\u{FFFD}𐒋\u{FFFD}"));
}
- #[test]
- fn test_from_buf_len() {
- unsafe {
- let a = vec![65u8, 65, 65, 65, 65, 65, 65, 0];
- assert_eq!(String::from_raw_buf_len(a.as_ptr(), 3), String::from_str("AAA"));
- }
- }
-
- #[test]
- fn test_from_buf() {
- unsafe {
- let a = vec![65, 65, 65, 65, 65, 65, 65, 0];
- let b = a.as_ptr();
- let c = String::from_raw_buf(b);
- assert_eq!(c, String::from_str("AAAAAAA"));
- }
- }
-
#[test]
fn test_push_bytes() {
let mut s = String::from_str("ABC");
}
}
-#[experimental = "waiting on Deref stability"]
+#[stable]
impl<T> ops::Deref for Vec<T> {
type Target = [T];
fn deref<'a>(&'a self) -> &'a [T] { self.as_slice() }
}
-#[experimental = "waiting on DerefMut stability"]
+#[stable]
impl<T> ops::DerefMut for Vec<T> {
fn deref_mut<'a>(&'a mut self) -> &'a mut [T] { self.as_mut_slice() }
}
-#[experimental = "waiting on FromIterator stability"]
+#[stable]
impl<T> FromIterator<T> for Vec<T> {
#[inline]
fn from_iter<I:Iterator<Item=T>>(mut iterator: I) -> Vec<T> {
}
}
+#[unstable = "recent addition, needs more experience"]
impl<'a, T: Clone> Add<&'a [T]> for Vec<T> {
type Output = Vec<T>;
}
#[unsafe_destructor]
+#[stable]
impl<T> Drop for Vec<T> {
fn drop(&mut self) {
// This is (and should always remain) a no-op if the fields are
/// A clone-on-write vector
pub type CowVec<'a, T> = Cow<'a, Vec<T>, [T]>;
+#[unstable]
impl<'a, T> FromIterator<T> for CowVec<'a, T> where T: Clone {
fn from_iter<I: Iterator<Item=T>>(it: I) -> CowVec<'a, T> {
Cow::Owned(FromIterator::from_iter(it))
}
}
+#[stable]
impl<T> Iterator for IntoIter<T> {
type Item = T;
}
}
+#[stable]
impl<T> DoubleEndedIterator for IntoIter<T> {
#[inline]
fn next_back<'a>(&'a mut self) -> Option<T> {
}
}
+#[stable]
impl<T> ExactSizeIterator for IntoIter<T> {}
#[unsafe_destructor]
+#[stable]
impl<T> Drop for IntoIter<T> {
fn drop(&mut self) {
// destroy the remaining elements
marker: ContravariantLifetime<'a>,
}
+#[stable]
impl<'a, T> Iterator for Drain<'a, T> {
type Item = T;
}
}
+#[stable]
impl<'a, T> DoubleEndedIterator for Drain<'a, T> {
#[inline]
fn next_back(&mut self) -> Option<T> {
}
}
+#[stable]
impl<'a, T> ExactSizeIterator for Drain<'a, T> {}
#[unsafe_destructor]
+#[stable]
impl<'a, T> Drop for Drain<'a, T> {
fn drop(&mut self) {
// self.ptr == self.end == null if drop has already been called,
// Prevent the inner `Vec<T>` from attempting to deallocate memory.
#[unsafe_destructor]
-#[experimental]
+#[stable]
impl<'a, T> Drop for DerefVec<'a, T> {
fn drop(&mut self) {
self.x.len = 0;
unsafe impl Sync for AtomicBool {}
/// A signed integer type which can be safely shared between threads.
-#[stable]
+#[unstable = "awaiting int/uint conventions, may be renamed"]
pub struct AtomicInt {
v: UnsafeCell<int>,
}
unsafe impl Sync for AtomicInt {}
/// An unsigned integer type which can be safely shared between threads.
-#[stable]
+#[unstable = "awaiting int/uint conventions, may be renamed"]
pub struct AtomicUint {
v: UnsafeCell<uint>,
}
}
/// An `AtomicBool` initialized to `false`.
-#[unstable = "may be renamed, pending conventions for static initalizers"]
+#[stable]
pub const ATOMIC_BOOL_INIT: AtomicBool =
AtomicBool { v: UnsafeCell { value: 0 } };
/// An `AtomicInt` initialized to `0`.
-#[unstable = "may be renamed, pending conventions for static initalizers"]
+#[unstable = "awaiting int/uint conventions, may be renamed"]
pub const ATOMIC_INT_INIT: AtomicInt =
AtomicInt { v: UnsafeCell { value: 0 } };
/// An `AtomicUint` initialized to `0`.
-#[unstable = "may be renamed, pending conventions for static initalizers"]
+#[unstable = "awaiting int/uint conventions, may be renamed"]
pub const ATOMIC_UINT_INIT: AtomicUint =
AtomicUint { v: UnsafeCell { value: 0, } };
-/// Deprecated
-#[deprecated = "renamed to ATOMIC_BOOL_INIT"]
-pub const INIT_ATOMIC_BOOL: AtomicBool = ATOMIC_BOOL_INIT;
-/// Deprecated
-#[deprecated = "renamed to ATOMIC_INT_INIT"]
-pub const INIT_ATOMIC_INT: AtomicInt = ATOMIC_INT_INIT;
-/// Deprecated
-#[deprecated = "renamed to ATOMIC_UINT_INIT"]
-pub const INIT_ATOMIC_UINT: AtomicUint = ATOMIC_UINT_INIT;
-
// NB: Needs to be -1 (0b11111111...) to make fetch_nand work correctly
const UINT_TRUE: uint = -1;
}
}
+#[unstable = "awaiting int/uint conventions, types may change"]
impl AtomicInt {
/// Creates a new `AtomicInt`.
///
/// let atomic_forty_two = AtomicInt::new(42);
/// ```
#[inline]
- #[stable]
pub fn new(v: int) -> AtomicInt {
AtomicInt {v: UnsafeCell::new(v)}
}
/// let value = some_int.load(Ordering::Relaxed);
/// ```
#[inline]
- #[stable]
pub fn load(&self, order: Ordering) -> int {
unsafe { atomic_load(self.v.get() as *const int, order) }
}
///
/// Panics if `order` is `Acquire` or `AcqRel`.
#[inline]
- #[stable]
pub fn store(&self, val: int, order: Ordering) {
unsafe { atomic_store(self.v.get(), val, order); }
}
/// let value = some_int.swap(10, Ordering::Relaxed);
/// ```
#[inline]
- #[stable]
pub fn swap(&self, val: int, order: Ordering) -> int {
unsafe { atomic_swap(self.v.get(), val, order) }
}
/// let value = some_int.compare_and_swap(5, 10, Ordering::Relaxed);
/// ```
#[inline]
- #[stable]
pub fn compare_and_swap(&self, old: int, new: int, order: Ordering) -> int {
unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) }
}
/// assert_eq!(10, foo.load(Ordering::SeqCst));
/// ```
#[inline]
- #[stable]
pub fn fetch_add(&self, val: int, order: Ordering) -> int {
unsafe { atomic_add(self.v.get(), val, order) }
}
/// assert_eq!(-10, foo.load(Ordering::SeqCst));
/// ```
#[inline]
- #[stable]
pub fn fetch_sub(&self, val: int, order: Ordering) -> int {
unsafe { atomic_sub(self.v.get(), val, order) }
}
/// assert_eq!(0b101101, foo.fetch_and(0b110011, Ordering::SeqCst));
/// assert_eq!(0b100001, foo.load(Ordering::SeqCst));
#[inline]
- #[stable]
pub fn fetch_and(&self, val: int, order: Ordering) -> int {
unsafe { atomic_and(self.v.get(), val, order) }
}
/// assert_eq!(0b101101, foo.fetch_or(0b110011, Ordering::SeqCst));
/// assert_eq!(0b111111, foo.load(Ordering::SeqCst));
#[inline]
- #[stable]
pub fn fetch_or(&self, val: int, order: Ordering) -> int {
unsafe { atomic_or(self.v.get(), val, order) }
}
/// assert_eq!(0b101101, foo.fetch_xor(0b110011, Ordering::SeqCst));
/// assert_eq!(0b011110, foo.load(Ordering::SeqCst));
#[inline]
- #[stable]
pub fn fetch_xor(&self, val: int, order: Ordering) -> int {
unsafe { atomic_xor(self.v.get(), val, order) }
}
}
+#[unstable = "awaiting int/uint conventions, types may change"]
impl AtomicUint {
/// Creates a new `AtomicUint`.
///
/// let atomic_forty_two = AtomicUint::new(42u);
/// ```
#[inline]
- #[stable]
pub fn new(v: uint) -> AtomicUint {
AtomicUint { v: UnsafeCell::new(v) }
}
/// let value = some_uint.load(Ordering::Relaxed);
/// ```
#[inline]
- #[stable]
pub fn load(&self, order: Ordering) -> uint {
unsafe { atomic_load(self.v.get() as *const uint, order) }
}
///
/// Panics if `order` is `Acquire` or `AcqRel`.
#[inline]
- #[stable]
pub fn store(&self, val: uint, order: Ordering) {
unsafe { atomic_store(self.v.get(), val, order); }
}
/// let value = some_uint.swap(10, Ordering::Relaxed);
/// ```
#[inline]
- #[stable]
pub fn swap(&self, val: uint, order: Ordering) -> uint {
unsafe { atomic_swap(self.v.get(), val, order) }
}
/// let value = some_uint.compare_and_swap(5, 10, Ordering::Relaxed);
/// ```
#[inline]
- #[stable]
pub fn compare_and_swap(&self, old: uint, new: uint, order: Ordering) -> uint {
unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) }
}
/// assert_eq!(10, foo.load(Ordering::SeqCst));
/// ```
#[inline]
- #[stable]
pub fn fetch_add(&self, val: uint, order: Ordering) -> uint {
unsafe { atomic_add(self.v.get(), val, order) }
}
/// assert_eq!(0, foo.load(Ordering::SeqCst));
/// ```
#[inline]
- #[stable]
pub fn fetch_sub(&self, val: uint, order: Ordering) -> uint {
unsafe { atomic_sub(self.v.get(), val, order) }
}
/// assert_eq!(0b101101, foo.fetch_and(0b110011, Ordering::SeqCst));
/// assert_eq!(0b100001, foo.load(Ordering::SeqCst));
#[inline]
- #[stable]
pub fn fetch_and(&self, val: uint, order: Ordering) -> uint {
unsafe { atomic_and(self.v.get(), val, order) }
}
/// assert_eq!(0b101101, foo.fetch_or(0b110011, Ordering::SeqCst));
/// assert_eq!(0b111111, foo.load(Ordering::SeqCst));
#[inline]
- #[stable]
pub fn fetch_or(&self, val: uint, order: Ordering) -> uint {
unsafe { atomic_or(self.v.get(), val, order) }
}
/// assert_eq!(0b101101, foo.fetch_xor(0b110011, Ordering::SeqCst));
/// assert_eq!(0b011110, foo.load(Ordering::SeqCst));
#[inline]
- #[stable]
pub fn fetch_xor(&self, val: uint, order: Ordering) -> uint {
unsafe { atomic_xor(self.v.get(), val, order) }
}
use self::Cow::*;
/// A trait for borrowing data.
-pub trait BorrowFrom<Sized? Owned> for Sized? {
+#[old_orphan_check]
+pub trait BorrowFrom<Owned: ?Sized> {
/// Immutably borrow from an owned value.
fn borrow_from(owned: &Owned) -> &Self;
}
/// A trait for mutably borrowing data.
-pub trait BorrowFromMut<Sized? Owned> for Sized? : BorrowFrom<Owned> {
+#[old_orphan_check]
+pub trait BorrowFromMut<Owned: ?Sized> : BorrowFrom<Owned> {
/// Mutably borrow from an owned value.
fn borrow_from_mut(owned: &mut Owned) -> &mut Self;
}
-impl<Sized? T> BorrowFrom<T> for T {
+impl<T: ?Sized> BorrowFrom<T> for T {
fn borrow_from(owned: &T) -> &T { owned }
}
-impl<Sized? T> BorrowFromMut<T> for T {
+impl<T: ?Sized> BorrowFromMut<T> for T {
fn borrow_from_mut(owned: &mut T) -> &mut T { owned }
}
-impl<'a, Sized? T> BorrowFrom<&'a T> for T {
+impl<'a, T: ?Sized> BorrowFrom<&'a T> for T {
fn borrow_from<'b>(owned: &'b &'a T) -> &'b T { &**owned }
}
-impl<'a, Sized? T> BorrowFrom<&'a mut T> for T {
+impl<'a, T: ?Sized> BorrowFrom<&'a mut T> for T {
fn borrow_from<'b>(owned: &'b &'a mut T) -> &'b T { &**owned }
}
-impl<'a, Sized? T> BorrowFromMut<&'a mut T> for T {
+impl<'a, T: ?Sized> BorrowFromMut<&'a mut T> for T {
fn borrow_from_mut<'b>(owned: &'b mut &'a mut T) -> &'b mut T { &mut **owned }
}
-impl<'a, T, Sized? B> BorrowFrom<Cow<'a, T, B>> for B where B: ToOwned<T> {
+impl<'a, T, B: ?Sized> BorrowFrom<Cow<'a, T, B>> for B where B: ToOwned<T> {
fn borrow_from<'b>(owned: &'b Cow<'a, T, B>) -> &'b B {
&**owned
}
}
/// Trait for moving into a `Cow`
-pub trait IntoCow<'a, T, Sized? B> {
+#[old_orphan_check]
+pub trait IntoCow<'a, T, B: ?Sized> {
/// Moves `self` into `Cow`
fn into_cow(self) -> Cow<'a, T, B>;
}
-impl<'a, T, Sized? B> IntoCow<'a, T, B> for Cow<'a, T, B> where B: ToOwned<T> {
+impl<'a, T, B: ?Sized> IntoCow<'a, T, B> for Cow<'a, T, B> where B: ToOwned<T> {
fn into_cow(self) -> Cow<'a, T, B> {
self
}
}
/// A generalization of Clone to borrowed data.
-pub trait ToOwned<Owned> for Sized?: BorrowFrom<Owned> {
+#[old_orphan_check]
+pub trait ToOwned<Owned>: BorrowFrom<Owned> {
/// Create owned data from borrowed data, usually by copying.
fn to_owned(&self) -> Owned;
}
/// }
/// }
/// ```
-pub enum Cow<'a, T, Sized? B: 'a> where B: ToOwned<T> {
+pub enum Cow<'a, T, B: ?Sized + 'a> where B: ToOwned<T> {
/// Borrowed data.
Borrowed(&'a B),
}
#[stable]
-impl<'a, T, Sized? B> Clone for Cow<'a, T, B> where B: ToOwned<T> {
+impl<'a, T, B: ?Sized> Clone for Cow<'a, T, B> where B: ToOwned<T> {
fn clone(&self) -> Cow<'a, T, B> {
match *self {
Borrowed(b) => Borrowed(b),
}
}
-impl<'a, T, Sized? B> Cow<'a, T, B> where B: ToOwned<T> {
+impl<'a, T, B: ?Sized> Cow<'a, T, B> where B: ToOwned<T> {
/// Acquire a mutable reference to the owned form of the data.
///
/// Copies the data if it is not already owned.
}
}
-impl<'a, T, Sized? B> Deref for Cow<'a, T, B> where B: ToOwned<T> {
+#[stable]
+impl<'a, T, B: ?Sized> Deref for Cow<'a, T, B> where B: ToOwned<T> {
type Target = B;
fn deref(&self) -> &B {
}
#[stable]
-impl<'a, T, Sized? B> Eq for Cow<'a, T, B> where B: Eq + ToOwned<T> {}
+impl<'a, T, B: ?Sized> Eq for Cow<'a, T, B> where B: Eq + ToOwned<T> {}
#[stable]
-impl<'a, T, Sized? B> Ord for Cow<'a, T, B> where B: Ord + ToOwned<T> {
+impl<'a, T, B: ?Sized> Ord for Cow<'a, T, B> where B: Ord + ToOwned<T> {
#[inline]
fn cmp(&self, other: &Cow<'a, T, B>) -> Ordering {
Ord::cmp(&**self, &**other)
}
#[stable]
-impl<'a, 'b, T, U, Sized? B, Sized? C> PartialEq<Cow<'b, U, C>> for Cow<'a, T, B> where
+impl<'a, 'b, T, U, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, U, C>> for Cow<'a, T, B> where
B: PartialEq<C> + ToOwned<T>,
C: ToOwned<U>,
{
}
#[stable]
-impl<'a, T, Sized? B> PartialOrd for Cow<'a, T, B> where B: PartialOrd + ToOwned<T> {
+impl<'a, T, B: ?Sized> PartialOrd for Cow<'a, T, B> where B: PartialOrd + ToOwned<T> {
#[inline]
fn partial_cmp(&self, other: &Cow<'a, T, B>) -> Option<Ordering> {
PartialOrd::partial_cmp(&**self, &**other)
}
}
-impl<'a, T, Sized? B> fmt::Show for Cow<'a, T, B> where B: fmt::Show + ToOwned<T>, T: fmt::Show {
+impl<'a, T, B: ?Sized> fmt::Show for Cow<'a, T, B> where B: fmt::Show + ToOwned<T>, T: fmt::Show {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Borrowed(ref b) => fmt::Show::fmt(b, f),
_borrow: BorrowRef<'b>,
}
-#[unstable = "waiting for `Deref` to become stable"]
+#[stable]
impl<'b, T> Deref for Ref<'b, T> {
type Target = T;
_borrow: BorrowRefMut<'b>,
}
-#[unstable = "waiting for `Deref` to become stable"]
+#[stable]
impl<'b, T> Deref for RefMut<'b, T> {
type Target = T;
}
}
-#[unstable = "waiting for `DerefMut` to become stable"]
+#[stable]
impl<'b, T> DerefMut for RefMut<'b, T> {
#[inline]
fn deref_mut<'a>(&'a mut self) -> &'a mut T {
}
#[derive(Clone)]
+#[unstable]
enum EscapeUnicodeState {
Backslash,
Type,
}
#[derive(Clone)]
+#[unstable]
enum EscapeDefaultState {
Backslash(char),
Char(char),
}
#[stable]
-impl<'a, Sized? T> Clone for &'a T {
+impl<'a, T: ?Sized> Clone for &'a T {
/// Return a shallow copy of the reference.
#[inline]
fn clone(&self) -> &'a T { *self }
/// only if `a != b`.
#[lang="eq"]
#[stable]
-pub trait PartialEq<Sized? Rhs = Self> for Sized? {
+#[old_orphan_check]
+pub trait PartialEq<Rhs: ?Sized = Self> {
/// This method tests for `self` and `other` values to be equal, and is used by `==`.
#[stable]
fn eq(&self, other: &Rhs) -> bool;
/// - symmetric: `a == b` implies `b == a`; and
/// - transitive: `a == b` and `b == c` implies `a == c`.
#[stable]
-pub trait Eq for Sized?: PartialEq<Self> {
+pub trait Eq: PartialEq<Self> {
// FIXME #13101: this method is used solely by #[deriving] to
// assert that every component of a type implements #[deriving]
// itself, the current deriving infrastructure means doing this
/// - transitive, `a < b` and `b < c` implies `a < c`. The same must hold for
/// both `==` and `>`.
#[stable]
-pub trait Ord for Sized?: Eq + PartialOrd<Self> {
+pub trait Ord: Eq + PartialOrd<Self> {
/// This method returns an ordering between `self` and `other` values.
///
/// By convention, `self.cmp(&other)` returns the ordering matching
/// 5.11).
#[lang="ord"]
#[stable]
-pub trait PartialOrd<Sized? Rhs = Self> for Sized?: PartialEq<Rhs> {
+pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
/// This method returns an ordering between `self` and `other` values
/// if one exists.
#[stable]
// & pointers
#[stable]
- impl<'a, 'b, Sized? A, Sized? B> PartialEq<&'b B> for &'a A where A: PartialEq<B> {
+ impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b B> for &'a A where A: PartialEq<B> {
#[inline]
fn eq(&self, other: & &'b B) -> bool { PartialEq::eq(*self, *other) }
#[inline]
fn ne(&self, other: & &'b B) -> bool { PartialEq::ne(*self, *other) }
}
#[stable]
- impl<'a, 'b, Sized? A, Sized? B> PartialOrd<&'b B> for &'a A where A: PartialOrd<B> {
+ impl<'a, 'b, A: ?Sized, B: ?Sized> PartialOrd<&'b B> for &'a A where A: PartialOrd<B> {
#[inline]
fn partial_cmp(&self, other: &&'b B) -> Option<Ordering> {
PartialOrd::partial_cmp(*self, *other)
fn gt(&self, other: & &'b B) -> bool { PartialOrd::gt(*self, *other) }
}
#[stable]
- impl<'a, Sized? A> Ord for &'a A where A: Ord {
+ impl<'a, A: ?Sized> Ord for &'a A where A: Ord {
#[inline]
fn cmp(&self, other: & &'a A) -> Ordering { Ord::cmp(*self, *other) }
}
#[stable]
- impl<'a, Sized? A> Eq for &'a A where A: Eq {}
+ impl<'a, A: ?Sized> Eq for &'a A where A: Eq {}
// &mut pointers
#[stable]
- impl<'a, 'b, Sized? A, Sized? B> PartialEq<&'b mut B> for &'a mut A where A: PartialEq<B> {
+ impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b mut B> for &'a mut A where A: PartialEq<B> {
#[inline]
fn eq(&self, other: &&'b mut B) -> bool { PartialEq::eq(*self, *other) }
#[inline]
fn ne(&self, other: &&'b mut B) -> bool { PartialEq::ne(*self, *other) }
}
#[stable]
- impl<'a, 'b, Sized? A, Sized? B> PartialOrd<&'b mut B> for &'a mut A where A: PartialOrd<B> {
+ impl<'a, 'b, A: ?Sized, B: ?Sized> PartialOrd<&'b mut B> for &'a mut A where A: PartialOrd<B> {
#[inline]
fn partial_cmp(&self, other: &&'b mut B) -> Option<Ordering> {
PartialOrd::partial_cmp(*self, *other)
fn gt(&self, other: &&'b mut B) -> bool { PartialOrd::gt(*self, *other) }
}
#[stable]
- impl<'a, Sized? A> Ord for &'a mut A where A: Ord {
+ impl<'a, A: ?Sized> Ord for &'a mut A where A: Ord {
#[inline]
fn cmp(&self, other: &&'a mut A) -> Ordering { Ord::cmp(*self, *other) }
}
#[stable]
- impl<'a, Sized? A> Eq for &'a mut A where A: Eq {}
+ impl<'a, A: ?Sized> Eq for &'a mut A where A: Eq {}
#[stable]
- impl<'a, 'b, Sized? A, Sized? B> PartialEq<&'b mut B> for &'a A where A: PartialEq<B> {
+ impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b mut B> for &'a A where A: PartialEq<B> {
#[inline]
fn eq(&self, other: &&'b mut B) -> bool { PartialEq::eq(*self, *other) }
#[inline]
}
#[stable]
- impl<'a, 'b, Sized? A, Sized? B> PartialEq<&'b B> for &'a mut A where A: PartialEq<B> {
+ impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b B> for &'a mut A where A: PartialEq<B> {
#[inline]
fn eq(&self, other: &&'b B) -> bool { PartialEq::eq(*self, *other) }
#[inline]
use option::Option;
use option::Option::{Some, None};
use ops::{Deref, FnOnce};
-use result::Result::{Ok, Err};
+use result::Result::Ok;
use result;
use slice::SliceExt;
use slice;
use str::{self, StrExt, Utf8Error};
+// NOTE: for old macros; remove after the next snapshot
+#[cfg(stage0)] use result::Result::Err;
+
pub use self::num::radix;
pub use self::num::Radix;
pub use self::num::RadixFmt;
// This Adapter is needed to allow `self` (of type `&mut
// Self`) to be cast to a FormatWriter (below) without
// requiring a `Sized` bound.
- struct Adapter<'a,Sized? T:'a>(&'a mut T);
+ struct Adapter<'a,T: ?Sized +'a>(&'a mut T);
- impl<'a, Sized? T> Writer for Adapter<'a, T>
+ impl<'a, T: ?Sized> Writer for Adapter<'a, T>
where T: Writer
{
fn write_str(&mut self, s: &str) -> Result {
/// to this trait. There is not an explicit way of selecting this trait to be
/// used for formatting, it is only if no other format is specified.
#[unstable = "I/O and core have yet to be reconciled"]
-pub trait Show for Sized? {
+pub trait Show {
/// Formats the value using the given formatter.
fn fmt(&self, &mut Formatter) -> Result;
}
/// Format trait for the `o` character
#[unstable = "I/O and core have yet to be reconciled"]
-pub trait Octal for Sized? {
+pub trait Octal {
/// Formats the value using the given formatter.
fn fmt(&self, &mut Formatter) -> Result;
}
/// Format trait for the `b` character
#[unstable = "I/O and core have yet to be reconciled"]
-pub trait Binary for Sized? {
+pub trait Binary {
/// Formats the value using the given formatter.
fn fmt(&self, &mut Formatter) -> Result;
}
/// Format trait for the `x` character
#[unstable = "I/O and core have yet to be reconciled"]
-pub trait LowerHex for Sized? {
+pub trait LowerHex {
/// Formats the value using the given formatter.
fn fmt(&self, &mut Formatter) -> Result;
}
/// Format trait for the `X` character
#[unstable = "I/O and core have yet to be reconciled"]
-pub trait UpperHex for Sized? {
+pub trait UpperHex {
/// Formats the value using the given formatter.
fn fmt(&self, &mut Formatter) -> Result;
}
/// Format trait for the `p` character
#[unstable = "I/O and core have yet to be reconciled"]
-pub trait Pointer for Sized? {
+pub trait Pointer {
/// Formats the value using the given formatter.
fn fmt(&self, &mut Formatter) -> Result;
}
/// Format trait for the `e` character
#[unstable = "I/O and core have yet to be reconciled"]
-pub trait LowerExp for Sized? {
+pub trait LowerExp {
/// Formats the value using the given formatter.
fn fmt(&self, &mut Formatter) -> Result;
}
/// Format trait for the `E` character
#[unstable = "I/O and core have yet to be reconciled"]
-pub trait UpperExp for Sized? {
+pub trait UpperExp {
/// Formats the value using the given formatter.
fn fmt(&self, &mut Formatter) -> Result;
}
// Implementations of the core formatting traits
-impl<'a, Sized? T: Show> Show for &'a T {
+impl<'a, T: ?Sized + Show> Show for &'a T {
fn fmt(&self, f: &mut Formatter) -> Result { (**self).fmt(f) }
}
-impl<'a, Sized? T: Show> Show for &'a mut T {
+impl<'a, T: ?Sized + Show> Show for &'a mut T {
fn fmt(&self, f: &mut Formatter) -> Result { (**self).fmt(f) }
}
/// A hashable type. The `S` type parameter is an abstract hash state that is
/// used by the `Hash` to compute the hash. It defaults to
/// `std::hash::sip::SipState`.
-pub trait Hash<S = sip::SipState> for Sized? {
+pub trait Hash<S = sip::SipState> {
/// Computes the hash of a value.
fn hash(&self, state: &mut S);
}
/// containers like `HashMap`, which need a generic way hash multiple types.
pub trait Hasher<S> {
/// Compute the hash of a value.
- fn hash<Sized? T: Hash<S>>(&self, value: &T) -> u64;
+ fn hash<T: ?Sized + Hash<S>>(&self, value: &T) -> u64;
}
#[allow(missing_docs)]
}
-impl<'a, S: Writer, Sized? T: Hash<S>> Hash<S> for &'a T {
+impl<'a, S: Writer, T: ?Sized + Hash<S>> Hash<S> for &'a T {
#[inline]
fn hash(&self, state: &mut S) {
(**self).hash(state);
}
}
-impl<'a, S: Writer, Sized? T: Hash<S>> Hash<S> for &'a mut T {
+impl<'a, S: Writer, T: ?Sized + Hash<S>> Hash<S> for &'a mut T {
#[inline]
fn hash(&self, state: &mut S) {
(**self).hash(state);
}
}
-impl<'a, T, Sized? B, S> Hash<S> for Cow<'a, T, B> where B: Hash<S> + ToOwned<T> {
+impl<'a, T, B: ?Sized, S> Hash<S> for Cow<'a, T, B> where B: Hash<S> + ToOwned<T> {
#[inline]
fn hash(&self, state: &mut S) {
Hash::hash(&**self, state)
impl Hasher<SipState> for SipHasher {
#[inline]
- fn hash<Sized? T: Hash<SipState>>(&self, value: &T) -> u64 {
+ fn hash<T: ?Sized + Hash<SipState>>(&self, value: &T) -> u64 {
let mut state = SipState::new_with_keys(self.k0, self.k1);
value.hash(&mut state);
state.result()
/// Hashes a value using the SipHash algorithm.
#[inline]
-pub fn hash<Sized? T: Hash<SipState>>(value: &T) -> u64 {
+pub fn hash<T: ?Sized + Hash<SipState>>(value: &T) -> u64 {
let mut state = SipState::new();
value.hash(&mut state);
state.result()
/// Hashes a value with the SipHash algorithm with the provided keys.
#[inline]
-pub fn hash_with_keys<Sized? T: Hash<SipState>>(k0: u64, k1: u64, value: &T) -> u64 {
+pub fn hash_with_keys<T: ?Sized + Hash<SipState>>(k0: u64, k1: u64, value: &T) -> u64 {
let mut state = SipState::new_with_keys(k0, k1);
value.hash(&mut state);
state.result()
//!
//! This `for` loop syntax can be applied to any iterator over any type.
+#![stable]
+
use self::MinMaxResult::*;
use clone::Clone;
/// it wishes, either by returning `None` infinitely, or by doing something
/// else.
#[lang="iterator"]
-#[unstable = "just split up for object safety"]
+#[stable]
pub trait Iterator {
+ #[stable]
type Item;
/// Advance the iterator and return the next value. Return `None` when the end is reached.
+ #[stable]
fn next(&mut self) -> Option<Self::Item>;
/// Returns a lower and upper bound on the remaining length of the iterator.
/// An upper bound of `None` means either there is no known upper bound, or the upper bound
/// does not fit within a `uint`.
#[inline]
+ #[stable]
fn size_hint(&self) -> (uint, Option<uint>) { (0, None) }
}
/// Conversion from an `Iterator`
-#[unstable = "may be replaced by a more general conversion trait"]
+#[stable]
pub trait FromIterator<A> {
/// Build a container with elements from an external iterator.
fn from_iter<T: Iterator<Item=A>>(iterator: T) -> Self;
}
/// A type growable from an `Iterator` implementation
-#[unstable = "just renamed as part of collections reform"]
+#[stable]
pub trait Extend<A> {
/// Extend a container with the elements yielded by an arbitrary iterator
fn extend<T: Iterator<Item=A>>(&mut self, iterator: T);
}
-#[unstable = "new convention for extension traits"]
/// An extension trait providing numerous methods applicable to all iterators.
+#[stable]
pub trait IteratorExt: Iterator + Sized {
+ /// Counts the number of elements in this iterator.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let a = [1i, 2, 3, 4, 5];
+ /// let mut it = a.iter();
+ /// assert!(it.count() == 5);
+ /// ```
+ #[inline]
+ #[stable]
+ fn count(self) -> uint {
+ self.fold(0, |cnt, _x| cnt + 1)
+ }
+
+ /// Loops through the entire iterator, returning the last element of the
+ /// iterator.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let a = [1i, 2, 3, 4, 5];
+ /// assert!(a.iter().last().unwrap() == &5);
+ /// ```
+ #[inline]
+ #[stable]
+ fn last(mut self) -> Option< <Self as Iterator>::Item> {
+ let mut last = None;
+ for x in self { last = Some(x); }
+ last
+ }
+
+ /// Loops through `n` iterations, returning the `n`th element of the
+ /// iterator.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let a = [1i, 2, 3, 4, 5];
+ /// let mut it = a.iter();
+ /// assert!(it.nth(2).unwrap() == &3);
+ /// assert!(it.nth(2) == None);
+ /// ```
+ #[inline]
+ #[stable]
+ fn nth(&mut self, mut n: uint) -> Option< <Self as Iterator>::Item> {
+ for x in *self {
+ if n == 0 { return Some(x) }
+ n -= 1;
+ }
+ None
+ }
+
/// Chain this iterator with another, returning a new iterator that will
/// finish iterating over the current iterator, and then iterate
/// over the other specified iterator.
/// assert!(it.next().is_none());
/// ```
#[inline]
- #[unstable = "waiting for unboxed closures"]
+ #[stable]
fn map<B, F>(self, f: F) -> Map< <Self as Iterator>::Item, B, Self, F> where
F: FnMut(<Self as Iterator>::Item) -> B,
{
/// assert!(it.next().is_none());
/// ```
#[inline]
- #[unstable = "waiting for unboxed closures"]
+ #[stable]
fn filter<P>(self, predicate: P) -> Filter< <Self as Iterator>::Item, Self, P> where
P: FnMut(&<Self as Iterator>::Item) -> bool,
{
/// assert!(it.next().is_none());
/// ```
#[inline]
- #[unstable = "waiting for unboxed closures"]
+ #[stable]
fn filter_map<B, F>(self, f: F) -> FilterMap< <Self as Iterator>::Item, B, Self, F> where
F: FnMut(<Self as Iterator>::Item) -> Option<B>,
{
Peekable{iter: self, peeked: None}
}
- /// Creates an iterator that invokes the predicate on elements until it
- /// returns false. Once the predicate returns false, all further elements are
- /// yielded.
+ /// Creates an iterator that invokes the predicate on elements
+ /// until it returns false. Once the predicate returns false, that
+ /// element and all further elements are yielded.
///
/// # Example
///
/// assert!(it.next().is_none());
/// ```
#[inline]
- #[unstable = "waiting for unboxed closures"]
+ #[stable]
fn skip_while<P>(self, predicate: P) -> SkipWhile< <Self as Iterator>::Item, Self, P> where
P: FnMut(&<Self as Iterator>::Item) -> bool,
{
/// assert!(it.next().is_none());
/// ```
#[inline]
- #[unstable = "waiting for unboxed closures, may want to require peek"]
+ #[stable]
fn take_while<P>(self, predicate: P) -> TakeWhile< <Self as Iterator>::Item, Self, P> where
P: FnMut(&<Self as Iterator>::Item) -> bool,
{
/// assert!(it.next().is_none());
/// ```
#[inline]
- #[unstable = "waiting for unboxed closures"]
+ #[stable]
fn scan<St, B, F>(
self,
initial_state: St,
/// }
/// ```
#[inline]
- #[unstable = "waiting for unboxed closures"]
+ #[stable]
fn flat_map<B, U, F>(self, f: F) -> FlatMap< <Self as Iterator>::Item, B, Self, U, F> where
U: Iterator<Item=B>,
F: FnMut(<Self as Iterator>::Item) -> U,
/// println!("{}", sum);
/// ```
#[inline]
- #[unstable = "waiting for unboxed closures"]
+ #[stable]
fn inspect<F>(self, f: F) -> Inspect< <Self as Iterator>::Item, Self, F> where
F: FnMut(&<Self as Iterator>::Item),
{
/// assert!(a.as_slice() == b.as_slice());
/// ```
#[inline]
- #[unstable = "waiting for general conversion traits, just changed to take self by value"]
+ #[stable]
fn collect<B: FromIterator< <Self as Iterator>::Item>>(self) -> B {
FromIterator::from_iter(self)
}
(left, right)
}
- /// Loops through `n` iterations, returning the `n`th element of the
- /// iterator.
- ///
- /// # Example
- ///
- /// ```rust
- /// let a = [1i, 2, 3, 4, 5];
- /// let mut it = a.iter();
- /// assert!(it.nth(2).unwrap() == &3);
- /// assert!(it.nth(2) == None);
- /// ```
- #[inline]
- #[stable]
- fn nth(&mut self, mut n: uint) -> Option< <Self as Iterator>::Item> {
- for x in *self {
- if n == 0 { return Some(x) }
- n -= 1;
- }
- None
- }
-
- /// Loops through the entire iterator, returning the last element of the
- /// iterator.
- ///
- /// # Example
- ///
- /// ```rust
- /// let a = [1i, 2, 3, 4, 5];
- /// assert!(a.iter().last().unwrap() == &5);
- /// ```
- #[inline]
- #[unstable = "just changed to take self by value"]
- fn last(mut self) -> Option< <Self as Iterator>::Item> {
- let mut last = None;
- for x in self { last = Some(x); }
- last
- }
-
/// Performs a fold operation over the entire iterator, returning the
/// eventual state at the end of the iteration.
///
/// assert!(a.iter().fold(0, |a, &b| a + b) == 15);
/// ```
#[inline]
- #[unstable = "waiting for unboxed closures, just changed to take self by value"]
+ #[stable]
fn fold<B, F>(mut self, init: B, mut f: F) -> B where
F: FnMut(B, <Self as Iterator>::Item) -> B,
{
accum
}
- /// Counts the number of elements in this iterator.
- ///
- /// # Example
- ///
- /// ```rust
- /// let a = [1i, 2, 3, 4, 5];
- /// let mut it = a.iter();
- /// assert!(it.count() == 5);
- /// ```
- #[inline]
- #[unstable = "just changed to take self by value"]
- fn count(self) -> uint {
- self.fold(0, |cnt, _x| cnt + 1)
- }
-
/// Tests whether the predicate holds true for all elements in the iterator.
///
/// # Example
/// assert!(!a.iter().all(|x| *x > 2));
/// ```
#[inline]
- #[unstable = "waiting for unboxed closures, just changed to take self by value"]
+ #[stable]
fn all<F>(mut self, mut f: F) -> bool where F: FnMut(<Self as Iterator>::Item) -> bool {
for x in self { if !f(x) { return false; } }
true
/// assert!(!it.any(|x| *x == 3));
/// ```
#[inline]
- #[unstable = "waiting for unboxed closures"]
+ #[stable]
fn any<F>(&mut self, mut f: F) -> bool where F: FnMut(<Self as Iterator>::Item) -> bool {
for x in *self { if f(x) { return true; } }
false
///
/// Does not consume the iterator past the first found element.
#[inline]
- #[unstable = "waiting for unboxed closures"]
+ #[stable]
fn find<P>(&mut self, mut predicate: P) -> Option< <Self as Iterator>::Item> where
P: FnMut(&<Self as Iterator>::Item) -> bool,
{
/// Return the index of the first element satisfying the specified predicate
#[inline]
- #[unstable = "waiting for unboxed closures"]
+ #[stable]
fn position<P>(&mut self, mut predicate: P) -> Option<uint> where
P: FnMut(<Self as Iterator>::Item) -> bool,
{
None
}
+ /// Return the index of the last element satisfying the specified predicate
+ ///
+ /// If no element matches, None is returned.
+ #[inline]
+ #[stable]
+ fn rposition<P>(&mut self, mut predicate: P) -> Option<uint> where
+ P: FnMut(<Self as Iterator>::Item) -> bool,
+ Self: ExactSizeIterator + DoubleEndedIterator
+ {
+ let len = self.len();
+ for i in range(0, len).rev() {
+ if predicate(self.next_back().expect("rposition: incorrect ExactSizeIterator")) {
+ return Some(i);
+ }
+ }
+ None
+ }
+
+ /// Consumes the entire iterator to return the maximum element.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let a = [1i, 2, 3, 4, 5];
+ /// assert!(a.iter().max().unwrap() == &5);
+ /// ```
+ #[inline]
+ #[stable]
+ fn max(self) -> Option< <Self as Iterator>::Item> where
+ <Self as Iterator>::Item: Ord
+ {
+ self.fold(None, |max, x| {
+ match max {
+ None => Some(x),
+ Some(y) => Some(cmp::max(x, y))
+ }
+ })
+ }
+
+ /// Consumes the entire iterator to return the minimum element.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let a = [1i, 2, 3, 4, 5];
+ /// assert!(a.iter().min().unwrap() == &1);
+ /// ```
+ #[inline]
+ #[stable]
+ fn min(self) -> Option< <Self as Iterator>::Item> where
+ <Self as Iterator>::Item: Ord
+ {
+ self.fold(None, |min, x| {
+ match min {
+ None => Some(x),
+ Some(y) => Some(cmp::min(x, y))
+ }
+ })
+ }
+
+ /// `min_max` finds the minimum and maximum elements in the iterator.
+ ///
+ /// The return type `MinMaxResult` is an enum of three variants:
+ ///
+ /// - `NoElements` if the iterator is empty.
+ /// - `OneElement(x)` if the iterator has exactly one element.
+ /// - `MinMax(x, y)` is returned otherwise, where `x <= y`. Two
+ /// values are equal if and only if there is more than one
+ /// element in the iterator and all elements are equal.
+ ///
+ /// On an iterator of length `n`, `min_max` does `1.5 * n` comparisons,
+ /// and so is faster than calling `min` and `max` separately which does `2 * n` comparisons.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// use std::iter::MinMaxResult::{NoElements, OneElement, MinMax};
+ ///
+ /// let v: [int; 0] = [];
+ /// assert_eq!(v.iter().min_max(), NoElements);
+ ///
+ /// let v = [1i];
+ /// assert!(v.iter().min_max() == OneElement(&1));
+ ///
+ /// let v = [1i, 2, 3, 4, 5];
+ /// assert!(v.iter().min_max() == MinMax(&1, &5));
+ ///
+ /// let v = [1i, 2, 3, 4, 5, 6];
+ /// assert!(v.iter().min_max() == MinMax(&1, &6));
+ ///
+ /// let v = [1i, 1, 1, 1];
+ /// assert!(v.iter().min_max() == MinMax(&1, &1));
+ /// ```
+ #[unstable = "return type may change"]
+ fn min_max(mut self) -> MinMaxResult< <Self as Iterator>::Item> where
+ <Self as Iterator>::Item: Ord
+ {
+ let (mut min, mut max) = match self.next() {
+ None => return NoElements,
+ Some(x) => {
+ match self.next() {
+ None => return OneElement(x),
+ Some(y) => if x < y {(x, y)} else {(y,x)}
+ }
+ }
+ };
+
+ loop {
+ // `first` and `second` are the two next elements we want to look at.
+ // We first compare `first` and `second` (#1). The smaller one is then compared to
+ // current minimum (#2). The larger one is compared to current maximum (#3). This
+ // way we do 3 comparisons for 2 elements.
+ let first = match self.next() {
+ None => break,
+ Some(x) => x
+ };
+ let second = match self.next() {
+ None => {
+ if first < min {
+ min = first;
+ } else if first > max {
+ max = first;
+ }
+ break;
+ }
+ Some(x) => x
+ };
+ if first < second {
+ if first < min {min = first;}
+ if max < second {max = second;}
+ } else {
+ if second < min {min = second;}
+ if max < first {max = first;}
+ }
+ }
+
+ MinMax(min, max)
+ }
+
/// Return the element that gives the maximum value from the
/// specified function.
///
/// assert_eq!(*xs.iter().max_by(|x| x.abs()).unwrap(), -10);
/// ```
#[inline]
- #[unstable = "waiting for unboxed closures, just changed to take self by value"]
+ #[unstable = "may want to produce an Ordering directly; see #15311"]
fn max_by<B: Ord, F>(self, mut f: F) -> Option< <Self as Iterator>::Item> where
F: FnMut(&<Self as Iterator>::Item) -> B,
{
/// assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0);
/// ```
#[inline]
- #[unstable = "waiting for unboxed closures, just changed to take self by value"]
+ #[unstable = "may want to produce an Ordering directly; see #15311"]
fn min_by<B: Ord, F>(self, mut f: F) -> Option< <Self as Iterator>::Item> where
F: FnMut(&<Self as Iterator>::Item) -> B,
{
///
/// Loops through the entire iterator, collecting the first component of
/// each item into one new container, and the second component into another.
+ #[unstable = "recent addition"]
fn unzip<A, B, FromA, FromB>(mut self) -> (FromA, FromB) where
FromA: Default + Extend<A>,
FromB: Default + Extend<B>,
let mut ts: FromA = Default::default();
let mut us: FromB = Default::default();
- ts.extend(SizeHint(lo, hi));
- us.extend(SizeHint(lo, hi));
+ ts.extend(SizeHint(lo, hi));
+ us.extend(SizeHint(lo, hi));
+
+ for (t, u) in self {
+ ts.extend(Some(t).into_iter());
+ us.extend(Some(u).into_iter());
+ }
+
+ (ts, us)
+ }
+
+ /// Creates an iterator that clones the elements it yields. Useful for converting an
+ /// Iterator<&T> to an Iterator<T>.
+ #[unstable = "recent addition"]
+ fn cloned<T, D>(self) -> Cloned<Self> where
+ Self: Iterator<Item=D>,
+ D: Deref<Target=T>,
+ T: Clone,
+ {
+ Cloned { it: self }
+ }
+
+ /// Repeats an iterator endlessly
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// use std::iter::count;
+ ///
+ /// let a = count(1i,1i).take(1);
+ /// let mut cy = a.cycle();
+ /// assert_eq!(cy.next(), Some(1));
+ /// assert_eq!(cy.next(), Some(1));
+ /// ```
+ #[stable]
+ #[inline]
+ fn cycle(self) -> Cycle<Self> where Self: Clone {
+ Cycle{orig: self.clone(), iter: self}
+ }
- for (t, u) in self {
- ts.extend(Some(t).into_iter());
- us.extend(Some(u).into_iter());
+ /// Use an iterator to reverse a container in place.
+ #[experimental = "uncertain about placement or widespread use"]
+ fn reverse_in_place<'a, T: 'a>(&mut self) where
+ Self: Iterator<Item=&'a mut T> + DoubleEndedIterator
+ {
+ loop {
+ match (self.next(), self.next_back()) {
+ (Some(x), Some(y)) => mem::swap(x, y),
+ _ => break
+ }
}
-
- (ts, us)
}
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<I> IteratorExt for I where I: Iterator {}
/// A range iterator able to yield elements from both ends
///
/// A `DoubleEndedIterator` can be thought of as a deque in that `next()` and `next_back()` exhaust
/// elements from the *same* range, and do not work independently of each other.
-#[unstable = "recently split into two traits"]
+#[stable]
pub trait DoubleEndedIterator: Iterator {
/// Yield an element from the end of the range, returning `None` if the range is empty.
fn next_back(&mut self) -> Option< <Self as Iterator>::Item>;
}
-/// A double-ended iterator yielding mutable references
-#[experimental = "not widely used"]
-pub trait MutableDoubleEndedIterator {
- // FIXME: #5898: should be called `reverse`
- /// Use an iterator to reverse a container in-place
- fn reverse_(&mut self);
-}
-
-#[experimental = "trait is experimental"]
-impl<'a, T:'a, I> MutableDoubleEndedIterator for I where
- I: DoubleEndedIterator + Iterator<Item=&'a mut T>,
-{
- // FIXME: #5898: should be called `reverse`
- /// Use an iterator to reverse a container in-place
- fn reverse_(&mut self) {
- loop {
- match (self.next(), self.next_back()) {
- (Some(x), Some(y)) => mem::swap(x, y),
- _ => break
- }
- }
- }
-}
-
-
/// An object implementing random access indexing by `uint`
///
/// A `RandomAccessIterator` should be either infinite or a `DoubleEndedIterator`.
///
/// `Iterator::size_hint` *must* return the exact size of the iterator.
/// Note that the size must fit in `uint`.
-#[unstable = "could move DoubleEndedIterator bound onto rposition with method-level where clauses"]
-pub trait ExactSizeIterator: DoubleEndedIterator {
- /// Return the index of the last element satisfying the specified predicate
- ///
- /// If no element matches, None is returned.
- #[inline]
- fn rposition<P>(&mut self, mut predicate: P) -> Option<uint> where
- P: FnMut(<Self as Iterator>::Item) -> bool,
- {
- let len = self.len();
- for i in range(0, len).rev() {
- if predicate(self.next_back().expect("rposition: incorrect ExactSizeIterator")) {
- return Some(i);
- }
- }
- None
- }
-
+#[stable]
+pub trait ExactSizeIterator: Iterator {
#[inline]
/// Return the exact length of the iterator.
fn len(&self) -> uint {
// All adaptors that preserve the size of the wrapped iterator are fine
// Adaptors that may overflow in `size_hint` are not, i.e. `Chain`.
-#[unstable = "trait is unstable"]
+#[stable]
impl<I> ExactSizeIterator for Enumerate<I> where I: ExactSizeIterator {}
-#[unstable = "trait is unstable"]
+#[stable]
impl<A, I, F> ExactSizeIterator for Inspect<A, I, F> where
I: ExactSizeIterator + Iterator<Item=A>,
F: FnMut(&A),
{}
-#[unstable = "trait is unstable"]
-impl<I> ExactSizeIterator for Rev<I> where I: ExactSizeIterator {}
-#[unstable = "trait is unstable"]
+#[stable]
+impl<I> ExactSizeIterator for Rev<I> where I: ExactSizeIterator + DoubleEndedIterator {}
+#[stable]
impl<A, B, I, F> ExactSizeIterator for Map<A, B, I, F> where
I: ExactSizeIterator + Iterator<Item=A>,
F: FnMut(A) -> B,
{}
-#[unstable = "trait is unstable"]
+#[stable]
impl<A, B> ExactSizeIterator for Zip<A, B> where A: ExactSizeIterator, B: ExactSizeIterator {}
/// An double-ended iterator with the direction inverted
iter: T
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<I> Iterator for Rev<I> where I: DoubleEndedIterator {
type Item = <I as Iterator>::Item;
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<I> DoubleEndedIterator for Rev<I> where I: DoubleEndedIterator {
#[inline]
fn next_back(&mut self) -> Option< <I as Iterator>::Item> { self.iter.next() }
iter: &'a mut I,
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<'a, I> Iterator for ByRef<'a, I> where I: 'a + Iterator {
type Item = <I as Iterator>::Item;
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<'a, I> DoubleEndedIterator for ByRef<'a, I> where I: 'a + DoubleEndedIterator {
#[inline]
fn next_back(&mut self) -> Option< <I as Iterator>::Item> { self.iter.next_back() }
impl_multiplicative! { f32, 1.0 }
impl_multiplicative! { f64, 1.0 }
-/// A trait for iterators over elements which can be compared to one another.
-#[unstable = "recently renamed for new extension trait conventions"]
-pub trait IteratorOrdExt<A> {
- /// Consumes the entire iterator to return the maximum element.
- ///
- /// # Example
- ///
- /// ```rust
- /// let a = [1i, 2, 3, 4, 5];
- /// assert!(a.iter().max().unwrap() == &5);
- /// ```
- fn max(self) -> Option<A>;
-
- /// Consumes the entire iterator to return the minimum element.
- ///
- /// # Example
- ///
- /// ```rust
- /// let a = [1i, 2, 3, 4, 5];
- /// assert!(a.iter().min().unwrap() == &1);
- /// ```
- fn min(self) -> Option<A>;
-
- /// `min_max` finds the minimum and maximum elements in the iterator.
- ///
- /// The return type `MinMaxResult` is an enum of three variants:
- ///
- /// - `NoElements` if the iterator is empty.
- /// - `OneElement(x)` if the iterator has exactly one element.
- /// - `MinMax(x, y)` is returned otherwise, where `x <= y`. Two
- /// values are equal if and only if there is more than one
- /// element in the iterator and all elements are equal.
- ///
- /// On an iterator of length `n`, `min_max` does `1.5 * n` comparisons,
- /// and so is faster than calling `min` and `max` separately which does `2 * n` comparisons.
- ///
- /// # Example
- ///
- /// ```rust
- /// use std::iter::MinMaxResult::{NoElements, OneElement, MinMax};
- ///
- /// let v: [int; 0] = [];
- /// assert_eq!(v.iter().min_max(), NoElements);
- ///
- /// let v = [1i];
- /// assert!(v.iter().min_max() == OneElement(&1));
- ///
- /// let v = [1i, 2, 3, 4, 5];
- /// assert!(v.iter().min_max() == MinMax(&1, &5));
- ///
- /// let v = [1i, 2, 3, 4, 5, 6];
- /// assert!(v.iter().min_max() == MinMax(&1, &6));
- ///
- /// let v = [1i, 1, 1, 1];
- /// assert!(v.iter().min_max() == MinMax(&1, &1));
- /// ```
- fn min_max(self) -> MinMaxResult<A>;
-}
-
-#[unstable = "trait is unstable"]
-impl<T, I> IteratorOrdExt<T> for I where I: Iterator<Item=T>, T: Ord {
- #[inline]
- fn max(self) -> Option<T> {
- self.fold(None, |max, x| {
- match max {
- None => Some(x),
- Some(y) => Some(cmp::max(x, y))
- }
- })
- }
-
- #[inline]
- fn min(self) -> Option<T> {
- self.fold(None, |min, x| {
- match min {
- None => Some(x),
- Some(y) => Some(cmp::min(x, y))
- }
- })
- }
-
- fn min_max(mut self) -> MinMaxResult<T> {
- let (mut min, mut max) = match self.next() {
- None => return NoElements,
- Some(x) => {
- match self.next() {
- None => return OneElement(x),
- Some(y) => if x < y {(x, y)} else {(y,x)}
- }
- }
- };
-
- loop {
- // `first` and `second` are the two next elements we want to look at.
- // We first compare `first` and `second` (#1). The smaller one is then compared to
- // current minimum (#2). The larger one is compared to current maximum (#3). This
- // way we do 3 comparisons for 2 elements.
- let first = match self.next() {
- None => break,
- Some(x) => x
- };
- let second = match self.next() {
- None => {
- if first < min {
- min = first;
- } else if first > max {
- max = first;
- }
- break;
- }
- Some(x) => x
- };
- if first < second {
- if first < min {min = first;}
- if max < second {max = second;}
- } else {
- if second < min {min = second;}
- if max < first {max = first;}
- }
- }
-
- MinMax(min, max)
- }
-}
-
/// `MinMaxResult` is an enum returned by `min_max`. See `IteratorOrdExt::min_max` for more detail.
#[derive(Clone, PartialEq, Show)]
-#[unstable = "waiting on namespaced enum conventions"]
+#[unstable = "unclear whether such a fine-grained result is widely useful"]
pub enum MinMaxResult<T> {
/// Empty iterator
NoElements,
MinMax(T, T)
}
-#[stable]
impl<T: Clone> MinMaxResult<T> {
/// `into_option` creates an `Option` of type `(T,T)`. The returned `Option` has variant
/// `None` if and only if the `MinMaxResult` has variant `NoElements`. Otherwise variant
/// let r = MinMax(1i,2i);
/// assert_eq!(r.into_option(), Some((1,2)));
/// ```
+ #[unstable = "type is unstable"]
pub fn into_option(self) -> Option<(T,T)> {
match self {
NoElements => None,
}
}
-/// A trait for iterators that contain cloneable elements
-#[unstable = "recently renamed for extension trait conventions"]
-pub trait IteratorCloneExt<A> {
- /// Creates an iterator that clones the elements it yields. Useful for converting an
- /// Iterator<&T> to an Iterator<T>.
- fn cloned(self) -> Cloned<Self>;
-}
-
-#[unstable = "trait is unstable"]
-impl<T, D, I> IteratorCloneExt<T> for I where
- T: Clone,
- D: Deref<Target=T>,
- I: Iterator<Item=D>,
-{
- fn cloned(self) -> Cloned<I> {
- Cloned { it: self }
- }
-}
-
/// An iterator that clones the elements of an underlying iterator
+#[unstable = "recent addition"]
+#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+#[derive(Clone)]
pub struct Cloned<I> {
it: I,
}
+#[stable]
impl<T, D, I> Iterator for Cloned<I> where
T: Clone,
D: Deref<Target=T>,
}
}
+#[stable]
impl<T, D, I> DoubleEndedIterator for Cloned<I> where
T: Clone,
D: Deref<Target=T>,
}
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<T, D, I> ExactSizeIterator for Cloned<I> where
T: Clone,
D: Deref<Target=T>,
I: ExactSizeIterator + Iterator<Item=D>,
{}
-#[unstable = "recently renamed for extension trait conventions"]
-/// An extension trait for cloneable iterators.
-pub trait CloneIteratorExt {
- /// Repeats an iterator endlessly
- ///
- /// # Example
- ///
- /// ```rust
- /// use std::iter::{CloneIteratorExt, count};
- ///
- /// let a = count(1i,1i).take(1);
- /// let mut cy = a.cycle();
- /// assert_eq!(cy.next(), Some(1));
- /// assert_eq!(cy.next(), Some(1));
- /// ```
- #[stable]
- fn cycle(self) -> Cycle<Self>;
-}
-
-impl<I> CloneIteratorExt for I where I: Iterator + Clone {
- #[inline]
- fn cycle(self) -> Cycle<I> {
- Cycle{orig: self.clone(), iter: self}
- }
-}
-
/// An iterator that repeats endlessly
#[derive(Clone, Copy)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
iter: I,
}
+#[stable]
impl<I> Iterator for Cycle<I> where I: Clone + Iterator {
type Item = <I as Iterator>::Item;
flag: bool,
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<T, A, B> Iterator for Chain<A, B> where A: Iterator<Item=T>, B: Iterator<Item=T> {
type Item = T;
}
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<T, A, B> DoubleEndedIterator for Chain<A, B> where
A: DoubleEndedIterator + Iterator<Item=T>,
B: DoubleEndedIterator + Iterator<Item=T>,
b: B
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<T, U, A, B> Iterator for Zip<A, B> where
A: Iterator<Item = T>,
B: Iterator<Item = U>,
}
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<T, U, A, B> DoubleEndedIterator for Zip<A, B> where
- A: ExactSizeIterator + Iterator<Item=T>,
- B: ExactSizeIterator + Iterator<Item=U>,
+ A: ExactSizeIterator + Iterator<Item=T> + DoubleEndedIterator,
+ B: ExactSizeIterator + Iterator<Item=U> + DoubleEndedIterator,
{
#[inline]
fn next_back(&mut self) -> Option<(T, U)> {
}
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<A, B, I, F> Iterator for Map<A, B, I, F> where I: Iterator<Item=A>, F: FnMut(A) -> B {
type Item = B;
}
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<A, B, I, F> DoubleEndedIterator for Map<A, B, I, F> where
I: DoubleEndedIterator + Iterator<Item=A>,
F: FnMut(A) -> B,
}
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<A, I, P> Iterator for Filter<A, I, P> where I: Iterator<Item=A>, P: FnMut(&A) -> bool {
type Item = A;
}
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<A, I, P> DoubleEndedIterator for Filter<A, I, P> where
I: DoubleEndedIterator + Iterator<Item=A>,
P: FnMut(&A) -> bool,
}
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<A, B, I, F> Iterator for FilterMap<A, B, I, F> where
I: Iterator<Item=A>,
F: FnMut(A) -> Option<B>,
}
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<A, B, I, F> DoubleEndedIterator for FilterMap<A, B, I, F> where
I: DoubleEndedIterator + Iterator<Item=A>,
F: FnMut(A) -> Option<B>,
count: uint
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<I> Iterator for Enumerate<I> where I: Iterator {
type Item = (uint, <I as Iterator>::Item);
}
}
-#[unstable = "trait is unstable"]
-impl<I> DoubleEndedIterator for Enumerate<I> where I: ExactSizeIterator {
+#[stable]
+impl<I> DoubleEndedIterator for Enumerate<I> where
+ I: ExactSizeIterator + DoubleEndedIterator
+{
#[inline]
fn next_back(&mut self) -> Option<(uint, <I as Iterator>::Item)> {
match self.iter.next_back() {
peeked: Option<T>,
}
+#[stable]
impl<T, I> Iterator for Peekable<T, I> where I: Iterator<Item=T> {
type Item = T;
}
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<A, I, P> Iterator for SkipWhile<A, I, P> where I: Iterator<Item=A>, P: FnMut(&A) -> bool {
type Item = A;
}
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<A, I, P> Iterator for TakeWhile<A, I, P> where I: Iterator<Item=A>, P: FnMut(&A) -> bool {
type Item = A;
n: uint
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<I> Iterator for Skip<I> where I: Iterator {
type Item = <I as Iterator>::Item;
n: uint
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<I> Iterator for Take<I> where I: Iterator{
type Item = <I as Iterator>::Item;
/// An iterator to maintain state while iterating another iterator
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
-#[unstable = "waiting for unboxed closures"]
+#[stable]
pub struct Scan<A, B, I, St, F> where I: Iterator, F: FnMut(&mut St, A) -> Option<B> {
iter: I,
f: F,
}
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<A, B, I, St, F> Iterator for Scan<A, B, I, St, F> where
I: Iterator<Item=A>,
F: FnMut(&mut St, A) -> Option<B>,
/// and yields the elements of the produced iterators
///
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
-#[unstable = "waiting for unboxed closures"]
+#[stable]
pub struct FlatMap<A, B, I, U, F> where
I: Iterator<Item=A>,
U: Iterator<Item=B>,
}
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<A, B, I, U, F> Iterator for FlatMap<A, B, I, U, F> where
I: Iterator<Item=A>,
U: Iterator<Item=B>,
}
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<A, B, I, U, F> DoubleEndedIterator for FlatMap<A, B, I, U, F> where
I: DoubleEndedIterator + Iterator<Item=A>,
U: DoubleEndedIterator + Iterator<Item=B>,
done: bool
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<I> Iterator for Fuse<I> where I: Iterator {
type Item = <I as Iterator>::Item;
}
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<I> DoubleEndedIterator for Fuse<I> where I: DoubleEndedIterator {
#[inline]
fn next_back(&mut self) -> Option< <I as Iterator>::Item> {
}
}
-#[experimental = "seems marginal"]
impl<I> Fuse<I> {
/// Resets the fuse such that the next call to .next() or .next_back() will
/// call the underlying iterator again even if it previously returned None.
#[inline]
+ #[experimental = "seems marginal"]
pub fn reset_fuse(&mut self) {
self.done = false
}
/// An iterator that calls a function with a reference to each
/// element before yielding it.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
-#[unstable = "waiting for unboxed closures"]
+#[stable]
pub struct Inspect<A, I, F> where I: Iterator<Item=A>, F: FnMut(&A) {
iter: I,
f: F,
}
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<A, I, F> Iterator for Inspect<A, I, F> where I: Iterator<Item=A>, F: FnMut(&A) {
type Item = A;
}
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<A, I, F> DoubleEndedIterator for Inspect<A, I, F> where
I: DoubleEndedIterator + Iterator<Item=A>,
F: FnMut(&A),
}
}
-#[experimental]
+#[stable]
impl<A, St, F> Iterator for Unfold<A, St, F> where F: FnMut(&mut St) -> Option<A> {
type Item = A;
/// An infinite iterator starting at `start` and advancing by `step` with each
/// iteration
#[derive(Clone, Copy)]
-#[unstable = "may be renamed"]
+#[unstable = "may be renamed or replaced by range notation adapaters"]
pub struct Counter<A> {
/// The current state the counter is at (next value to be yielded)
state: A,
/// Creates a new counter with the specified start/step
#[inline]
-#[unstable = "may be renamed"]
+#[unstable = "may be renamed or replaced by range notation adapaters"]
pub fn count<A>(start: A, step: A) -> Counter<A> {
Counter{state: start, step: step}
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<A: Add<Output=A> + Clone> Iterator for Counter<A> {
type Item = A;
/// An iterator over the range [start, stop)
#[derive(Clone, Copy)]
-#[unstable = "may be refactored due to numerics reform or ops reform"]
+#[unstable = "will be replaced by range notation"]
pub struct Range<A> {
state: A,
stop: A,
/// }
/// ```
#[inline]
+#[unstable = "will be replaced by range notation"]
pub fn range<A: Int>(start: A, stop: A) -> Range<A> {
Range {
state: start,
}
// FIXME: #10414: Unfortunate type bound
-#[unstable = "trait is unstable"]
+#[unstable = "will be replaced by range notation"]
impl<A: Int + ToPrimitive> Iterator for Range<A> {
type Item = A;
/// `Int` is required to ensure the range will be the same regardless of
/// the direction it is consumed.
-#[unstable = "trait is unstable"]
+#[unstable = "will be replaced by range notation"]
impl<A: Int + ToPrimitive> DoubleEndedIterator for Range<A> {
#[inline]
fn next_back(&mut self) -> Option<A> {
/// An iterator over the range [start, stop]
#[derive(Clone)]
-#[unstable = "may be refactored due to numerics reform or ops reform"]
+#[unstable = "likely to be replaced by range notation and adapters"]
pub struct RangeInclusive<A> {
range: Range<A>,
done: bool,
/// Return an iterator over the range [start, stop]
#[inline]
-#[unstable = "may be refactored due to numerics reform or ops reform"]
+#[unstable = "likely to be replaced by range notation and adapters"]
pub fn range_inclusive<A: Int>(start: A, stop: A) -> RangeInclusive<A> {
RangeInclusive {
range: range(start, stop),
}
}
-#[unstable = "trait is unstable"]
+#[unstable = "likely to be replaced by range notation and adapters"]
impl<A: Int + ToPrimitive> Iterator for RangeInclusive<A> {
type Item = A;
}
}
-#[unstable = "trait is unstable"]
+#[unstable = "likely to be replaced by range notation and adapters"]
impl<A: Int + ToPrimitive> DoubleEndedIterator for RangeInclusive<A> {
#[inline]
fn next_back(&mut self) -> Option<A> {
/// An iterator over the range [start, stop) by `step`. It handles overflow by stopping.
#[derive(Clone)]
-#[unstable = "may be refactored due to numerics reform or ops reform"]
+#[unstable = "likely to be replaced by range notation and adapters"]
pub struct RangeStep<A> {
state: A,
stop: A,
/// Return an iterator over the range [start, stop) by `step`. It handles overflow by stopping.
#[inline]
-#[unstable = "may be refactored due to numerics reform or ops reform"]
+#[unstable = "likely to be replaced by range notation and adapters"]
pub fn range_step<A: Int>(start: A, stop: A, step: A) -> RangeStep<A> {
let rev = step < Int::zero();
RangeStep{state: start, stop: stop, step: step, rev: rev}
}
-#[unstable = "trait is unstable"]
+#[unstable = "likely to be replaced by range notation and adapters"]
impl<A: Int> Iterator for RangeStep<A> {
type Item = A;
/// An iterator over the range [start, stop] by `step`. It handles overflow by stopping.
#[derive(Clone)]
-#[unstable = "may be refactored due to numerics reform or ops reform"]
+#[unstable = "likely to be replaced by range notation and adapters"]
pub struct RangeStepInclusive<A> {
state: A,
stop: A,
/// Return an iterator over the range [start, stop] by `step`. It handles overflow by stopping.
#[inline]
-#[unstable = "may be refactored due to numerics reform or ops reform"]
+#[unstable = "likely to be replaced by range notation and adapters"]
pub fn range_step_inclusive<A: Int>(start: A, stop: A, step: A) -> RangeStepInclusive<A> {
let rev = step < Int::zero();
RangeStepInclusive {
}
}
-#[unstable = "trait is unstable"]
+#[unstable = "likely to be replaced by range notation and adapters"]
impl<A: Int> Iterator for RangeStepInclusive<A> {
type Item = A;
/// directions. The `steps_between` function provides a way to
/// compare two Step objects (it could be provided using `step()` and `Ord`,
/// but the implementation would be so inefficient as to be useless).
-#[unstable = "Trait is unstable."]
+#[unstable = "design of range notation/iteration is in flux"]
pub trait Step: Ord {
/// Change self to the next object.
fn step(&mut self);
element: A
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<A: Clone> Iterator for Repeat<A> {
type Item = A;
fn size_hint(&self) -> (uint, Option<uint>) { (uint::MAX, None) }
}
-#[unstable = "trait is unstable"]
+#[stable]
impl<A: Clone> DoubleEndedIterator for Repeat<A> {
#[inline]
fn next_back(&mut self) -> Option<A> { self.idx(0) }
///
/// If two sequences are equal up until the point where one ends,
/// the shorter sequence compares less.
-#[experimental = "likely to be removed after cmp reform"]
+#[unstable = "needs review and revision"]
pub mod order {
use cmp;
use cmp::{Eq, Ord, PartialOrd, PartialEq};
/// Types able to be transferred across task boundaries.
#[lang="send"]
-pub unsafe trait Send for Sized? : 'static {
+pub unsafe trait Send : 'static {
// empty.
}
/// Types with a constant size known at compile-time.
#[lang="sized"]
-pub trait Sized for Sized? {
+pub trait Sized {
// Empty.
}
/// Types that can be copied by simply copying bits (i.e. `memcpy`).
#[lang="copy"]
-pub trait Copy for Sized? {
+pub trait Copy {
// Empty.
}
/// reference; not doing this is undefined behaviour (for example,
/// `transmute`-ing from `&T` to `&mut T` is illegal).
#[lang="sync"]
-pub unsafe trait Sync for Sized? {
+pub unsafe trait Sync {
// Empty
}
/// for some lifetime `'a`, but not the other way around).
#[lang="covariant_type"]
#[derive(PartialEq, Eq, PartialOrd, Ord)]
- pub struct CovariantType<Sized? T>;
+ pub struct CovariantType<T: ?Sized>;
- impl<Sized? T> Copy for CovariantType<T> {}
- impl<Sized? T> Clone for CovariantType<T> {
+ impl<T: ?Sized> Copy for CovariantType<T> {}
+ impl<T: ?Sized> Clone for CovariantType<T> {
fn clone(&self) -> CovariantType<T> { *self }
}
/// arguments of type `U`, hence such a conversion is safe.
#[lang="contravariant_type"]
#[derive(PartialEq, Eq, PartialOrd, Ord)]
- pub struct ContravariantType<Sized? T>;
+ pub struct ContravariantType<T: ?Sized>;
- impl<Sized? T> Copy for ContravariantType<T> {}
- impl<Sized? T> Clone for ContravariantType<T> {
+ impl<T: ?Sized> Copy for ContravariantType<T> {}
+ impl<T: ?Sized> Clone for ContravariantType<T> {
fn clone(&self) -> ContravariantType<T> { *self }
}
/// interior mutability.
#[lang="invariant_type"]
#[derive(PartialEq, Eq, PartialOrd, Ord)]
- pub struct InvariantType<Sized? T>;
+ pub struct InvariantType<T: ?Sized>;
- impl<Sized? T> Copy for InvariantType<T> {}
- impl<Sized? T> Clone for InvariantType<T> {
+ impl<T: ?Sized> Copy for InvariantType<T> {}
+ impl<T: ?Sized> Clone for InvariantType<T> {
fn clone(&self) -> InvariantType<T> { *self }
}
#![feature(default_type_params, unboxed_closures, associated_types)]
#![deny(missing_docs)]
+#[cfg_attr(stage0, macro_escape)]
+#[cfg_attr(not(stage0), macro_use)]
mod macros;
-#[path = "num/float_macros.rs"] mod float_macros;
-#[path = "num/int_macros.rs"] mod int_macros;
-#[path = "num/uint_macros.rs"] mod uint_macros;
+#[path = "num/float_macros.rs"]
+#[cfg_attr(stage0, macro_escape)]
+#[cfg_attr(not(stage0), macro_use)]
+mod float_macros;
+
+#[path = "num/int_macros.rs"]
+#[cfg_attr(stage0, macro_escape)]
+#[cfg_attr(not(stage0), macro_use)]
+mod int_macros;
+
+#[path = "num/uint_macros.rs"]
+#[cfg_attr(stage0, macro_escape)]
+#[cfg_attr(not(stage0), macro_use)]
+mod uint_macros;
#[path = "num/int.rs"] pub mod int;
#[path = "num/i8.rs"] pub mod i8;
#[doc(hidden)]
mod core {
pub use panicking;
+ pub use fmt;
}
#[doc(hidden)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![macro_escape]
-
/// Entry point of task panic, for details, see std::macros
#[macro_export]
macro_rules! panic {
});
}
-/// Runtime assertion, for details see std::macros
+/// Ensure that a boolean expression is `true` at runtime.
+///
+/// This will invoke the `panic!` macro if the provided expression cannot be
+/// evaluated to `true` at runtime.
+///
+/// # Example
+///
+/// ```
+/// // the panic message for these assertions is the stringified value of the
+/// // expression given.
+/// assert!(true);
+/// # fn some_computation() -> bool { true }
+/// assert!(some_computation());
+///
+/// // assert with a custom message
+/// # let x = true;
+/// assert!(x, "x wasn't true!");
+/// # let a = 3i; let b = 27i;
+/// assert!(a + b == 30, "a = {}, b = {}", a, b);
+/// ```
#[macro_export]
macro_rules! assert {
($cond:expr) => (
panic!(concat!("assertion failed: ", stringify!($cond)))
}
);
- ($cond:expr, $($arg:tt)*) => (
+ ($cond:expr, $($arg:expr),+) => (
if !$cond {
- panic!($($arg)*)
+ panic!($($arg),+)
}
);
}
-/// Runtime assertion for equality, for details see std::macros
+/// Asserts that two expressions are equal to each other, testing equality in
+/// both directions.
+///
+/// On panic, this macro will print the values of the expressions.
+///
+/// # Example
+///
+/// ```
+/// let a = 3i;
+/// let b = 1i + 2i;
+/// assert_eq!(a, b);
+/// ```
#[macro_export]
macro_rules! assert_eq {
- ($cond1:expr, $cond2:expr) => ({
- let c1 = $cond1;
- let c2 = $cond2;
- if c1 != c2 || c2 != c1 {
- panic!("expressions not equal, left: {}, right: {}", c1, c2);
+ ($left:expr , $right:expr) => ({
+ match (&($left), &($right)) {
+ (left_val, right_val) => {
+ // check both directions of equality....
+ if !((*left_val == *right_val) &&
+ (*right_val == *left_val)) {
+ panic!("assertion failed: `(left == right) && (right == left)` \
+ (left: `{}`, right: `{}`)", *left_val, *right_val)
+ }
+ }
}
})
}
-/// Runtime assertion for equality, only without `--cfg ndebug`
+/// Ensure that a boolean expression is `true` at runtime.
+///
+/// This will invoke the `panic!` macro if the provided expression cannot be
+/// evaluated to `true` at runtime.
+///
+/// Unlike `assert!`, `debug_assert!` statements can be disabled by passing
+/// `--cfg ndebug` to the compiler. This makes `debug_assert!` useful for
+/// checks that are too expensive to be present in a release build but may be
+/// helpful during development.
+///
+/// # Example
+///
+/// ```
+/// // the panic message for these assertions is the stringified value of the
+/// // expression given.
+/// debug_assert!(true);
+/// # fn some_expensive_computation() -> bool { true }
+/// debug_assert!(some_expensive_computation());
+///
+/// // assert with a custom message
+/// # let x = true;
+/// debug_assert!(x, "x wasn't true!");
+/// # let a = 3i; let b = 27i;
+/// debug_assert!(a + b == 30, "a = {}, b = {}", a, b);
+/// ```
+#[macro_export]
+macro_rules! debug_assert {
+ ($($arg:tt)*) => (if cfg!(not(ndebug)) { assert!($($arg)*); })
+}
+
+/// Asserts that two expressions are equal to each other, testing equality in
+/// both directions.
+///
+/// On panic, this macro will print the values of the expressions.
+///
+/// Unlike `assert_eq!`, `debug_assert_eq!` statements can be disabled by
+/// passing `--cfg ndebug` to the compiler. This makes `debug_assert_eq!`
+/// useful for checks that are too expensive to be present in a release build
+/// but may be helpful during development.
+///
+/// # Example
+///
+/// ```
+/// let a = 3i;
+/// let b = 1i + 2i;
+/// debug_assert_eq!(a, b);
+/// ```
#[macro_export]
macro_rules! debug_assert_eq {
- ($($a:tt)*) => ({
- if cfg!(not(ndebug)) {
- assert_eq!($($a)*);
- }
- })
+ ($($arg:tt)*) => (if cfg!(not(ndebug)) { assert_eq!($($arg)*); })
}
-/// Runtime assertion, disableable at compile time with `--cfg ndebug`
+#[cfg(stage0)]
#[macro_export]
-macro_rules! debug_assert {
- ($($arg:tt)*) => (if cfg!(not(ndebug)) { assert!($($arg)*); })
+macro_rules! try {
+ ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) })
}
/// Short circuiting evaluation on Err
+///
+/// `libstd` contains a more general `try!` macro that uses `FromError`.
+#[cfg(not(stage0))]
#[macro_export]
macro_rules! try {
- ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) })
+ ($e:expr) => ({
+ use $crate::result::Result::{Ok, Err};
+
+ match $e {
+ Ok(e) => e,
+ Err(e) => return Err(e),
+ }
+ })
}
-/// Writing a formatted string into a writer
+/// Use the `format!` syntax to write data into a buffer of type `&mut Writer`.
+/// See `std::fmt` for more information.
+///
+/// # Example
+///
+/// ```
+/// # #![allow(unused_must_use)]
+///
+/// let mut w = Vec::new();
+/// write!(&mut w, "test");
+/// write!(&mut w, "formatted {}", "arguments");
+/// ```
#[macro_export]
macro_rules! write {
($dst:expr, $($arg:tt)*) => ((&mut *$dst).write_fmt(format_args!($($arg)*)))
}
-/// Writing a formatted string plus a newline into a writer
+/// Equivalent to the `write!` macro, except that a newline is appended after
+/// the message is written.
#[macro_export]
+#[stable]
macro_rules! writeln {
($dst:expr, $fmt:expr $($arg:tt)*) => (
write!($dst, concat!($fmt, "\n") $($arg)*)
)
}
+/// A utility macro for indicating unreachable code.
+///
+/// This is useful any time that the compiler can't determine that some code is unreachable. For
+/// example:
+///
+/// * Match arms with guard conditions.
+/// * Loops that dynamically terminate.
+/// * Iterators that dynamically terminate.
+///
+/// # Panics
+///
+/// This will always panic.
+///
+/// # Examples
+///
+/// Match arms:
+///
+/// ```rust
+/// fn foo(x: Option<int>) {
+/// match x {
+/// Some(n) if n >= 0 => println!("Some(Non-negative)"),
+/// Some(n) if n < 0 => println!("Some(Negative)"),
+/// Some(_) => unreachable!(), // compile error if commented out
+/// None => println!("None")
+/// }
+/// }
+/// ```
+///
+/// Iterators:
+///
+/// ```rust
+/// fn divide_by_three(x: u32) -> u32 { // one of the poorest implementations of x/3
+/// for i in std::iter::count(0_u32, 1) {
+/// if 3*i < i { panic!("u32 overflow"); }
+/// if x < 3*i { return i-1; }
+/// }
+/// unreachable!();
+/// }
+/// ```
#[macro_export]
-macro_rules! unreachable { () => (panic!("unreachable code")) }
+macro_rules! unreachable {
+ () => ({
+ panic!("internal error: entered unreachable code")
+ });
+ ($msg:expr) => ({
+ unreachable!("{}", $msg)
+ });
+ ($fmt:expr, $($arg:tt)*) => ({
+ panic!(concat!("internal error: entered unreachable code: ", $fmt), $($arg)*)
+ });
+}
+/// A standardised placeholder for marking unfinished code. It panics with the
+/// message `"not yet implemented"` when executed.
+#[macro_export]
+macro_rules! unimplemented {
+ () => (panic!("not yet implemented"))
+}
#[inline]
#[unstable = "this function may be removed in the future due to its \
questionable utility"]
-pub unsafe fn copy_lifetime<'a, Sized? S, Sized? T: 'a>(_ptr: &'a S,
+pub unsafe fn copy_lifetime<'a, S: ?Sized, T: ?Sized + 'a>(_ptr: &'a S,
ptr: &T) -> &'a T {
transmute(ptr)
}
#[inline]
#[unstable = "this function may be removed in the future due to its \
questionable utility"]
-pub unsafe fn copy_mut_lifetime<'a, Sized? S, Sized? T: 'a>(_ptr: &'a mut S,
+pub unsafe fn copy_mut_lifetime<'a, S: ?Sized, T: ?Sized + 'a>(_ptr: &'a mut S,
ptr: &mut T)
-> &'a mut T {
transmute(ptr)
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![macro_escape]
#![doc(hidden)]
macro_rules! assert_approx_eq {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![macro_escape]
#![doc(hidden)]
macro_rules! int_module { ($T:ty, $bits:expr) => (
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![macro_escape]
#![doc(hidden)]
macro_rules! uint_module { ($T:ty, $T_SIGNED:ty, $bits:expr) => (
//! See the documentation for each trait for a minimum implementation that prints
//! something to the screen.
+#![stable]
+
use clone::Clone;
use iter::{Step, Iterator,DoubleEndedIterator,ExactSizeIterator};
use kinds::Sized;
/// }
/// ```
#[lang="drop"]
+#[stable]
pub trait Drop {
/// The `drop` method, called when the value goes out of scope.
+ #[stable]
fn drop(&mut self);
}
/// }
/// ```
#[lang="add"]
+#[stable]
pub trait Add<RHS=Self> {
+ #[stable]
type Output;
/// The method for the `+` operator
+ #[stable]
fn add(self, rhs: RHS) -> Self::Output;
}
macro_rules! add_impl {
($($t:ty)*) => ($(
+ #[stable]
impl Add for $t {
type Output = $t;
/// }
/// ```
#[lang="sub"]
+#[stable]
pub trait Sub<RHS=Self> {
+ #[stable]
type Output;
/// The method for the `-` operator
+ #[stable]
fn sub(self, rhs: RHS) -> Self::Output;
}
macro_rules! sub_impl {
($($t:ty)*) => ($(
+ #[stable]
impl Sub for $t {
type Output = $t;
/// }
/// ```
#[lang="mul"]
+#[stable]
pub trait Mul<RHS=Self> {
+ #[stable]
type Output;
/// The method for the `*` operator
+ #[stable]
fn mul(self, rhs: RHS) -> Self::Output;
}
macro_rules! mul_impl {
($($t:ty)*) => ($(
+ #[stable]
impl Mul for $t {
type Output = $t;
/// }
/// ```
#[lang="div"]
+#[stable]
pub trait Div<RHS=Self> {
+ #[stable]
type Output;
/// The method for the `/` operator
+ #[stable]
fn div(self, rhs: RHS) -> Self::Output;
}
macro_rules! div_impl {
($($t:ty)*) => ($(
+ #[stable]
impl Div for $t {
type Output = $t;
/// }
/// ```
#[lang="rem"]
+#[stable]
pub trait Rem<RHS=Self> {
+ #[stable]
type Output = Self;
/// The method for the `%` operator
+ #[stable]
fn rem(self, rhs: RHS) -> Self::Output;
}
macro_rules! rem_impl {
($($t:ty)*) => ($(
+ #[stable]
impl Rem for $t {
type Output = $t;
macro_rules! rem_float_impl {
($t:ty, $fmod:ident) => {
+ #[stable]
impl Rem for $t {
type Output = $t;
/// }
/// ```
#[lang="neg"]
+#[stable]
pub trait Neg {
+ #[stable]
type Output;
/// The method for the unary `-` operator
+ #[stable]
fn neg(self) -> Self::Output;
}
macro_rules! neg_impl {
($($t:ty)*) => ($(
+ #[stable]
impl Neg for $t {
+ #[stable]
type Output = $t;
#[inline]
+ #[stable]
fn neg(self) -> $t { -self }
}
)*)
macro_rules! neg_uint_impl {
($t:ty, $t_signed:ty) => {
+ #[stable]
impl Neg for $t {
type Output = $t;
/// }
/// ```
#[lang="not"]
+#[stable]
pub trait Not {
+ #[stable]
type Output;
/// The method for the unary `!` operator
+ #[stable]
fn not(self) -> Self::Output;
}
macro_rules! not_impl {
($($t:ty)*) => ($(
+ #[stable]
impl Not for $t {
type Output = $t;
/// }
/// ```
#[lang="bitand"]
+#[stable]
pub trait BitAnd<RHS=Self> {
+ #[stable]
type Output;
/// The method for the `&` operator
+ #[stable]
fn bitand(self, rhs: RHS) -> Self::Output;
}
macro_rules! bitand_impl {
($($t:ty)*) => ($(
+ #[stable]
impl BitAnd for $t {
type Output = $t;
/// }
/// ```
#[lang="bitor"]
+#[stable]
pub trait BitOr<RHS=Self> {
+ #[stable]
type Output;
/// The method for the `|` operator
+ #[stable]
fn bitor(self, rhs: RHS) -> Self::Output;
}
macro_rules! bitor_impl {
($($t:ty)*) => ($(
+ #[stable]
impl BitOr for $t {
type Output = $t;
/// }
/// ```
#[lang="bitxor"]
+#[stable]
pub trait BitXor<RHS=Self> {
+ #[stable]
type Output;
/// The method for the `^` operator
+ #[stable]
fn bitxor(self, rhs: RHS) -> Self::Output;
}
macro_rules! bitxor_impl {
($($t:ty)*) => ($(
+ #[stable]
impl BitXor for $t {
type Output = $t;
/// }
/// ```
#[lang="shl"]
+#[stable]
pub trait Shl<RHS> {
+ #[stable]
type Output;
/// The method for the `<<` operator
+ #[stable]
fn shl(self, rhs: RHS) -> Self::Output;
}
macro_rules! shl_impl {
($($t:ty)*) => ($(
+ #[stable]
impl Shl<uint> for $t {
type Output = $t;
/// }
/// ```
#[lang="shr"]
+#[stable]
pub trait Shr<RHS> {
+ #[stable]
type Output;
/// The method for the `>>` operator
+ #[stable]
fn shr(self, rhs: RHS) -> Self::Output;
}
/// }
/// ```
#[lang="index"]
-pub trait Index<Sized? Index> for Sized? {
- type Sized? Output;
+pub trait Index<Index: ?Sized> {
+ type Output: ?Sized;
/// The method for the indexing (`Foo[Bar]`) operation
fn index<'a>(&'a self, index: &Index) -> &'a Self::Output;
/// }
/// ```
#[lang="index_mut"]
-pub trait IndexMut<Sized? Index> for Sized? {
- type Sized? Output;
+pub trait IndexMut<Index: ?Sized> {
+ type Output: ?Sized;
/// The method for the indexing (`Foo[Bar]`) operation
fn index_mut<'a>(&'a mut self, index: &Index) -> &'a mut Self::Output;
/// }
/// ```
#[lang="slice"]
-pub trait Slice<Sized? Idx, Sized? Result> for Sized? {
+pub trait Slice<Idx: ?Sized, Result: ?Sized> {
/// The method for the slicing operation foo[]
fn as_slice_<'a>(&'a self) -> &'a Result;
/// The method for the slicing operation foo[from..]
/// }
/// ```
#[lang="slice_mut"]
-pub trait SliceMut<Sized? Idx, Sized? Result> for Sized? {
+pub trait SliceMut<Idx: ?Sized, Result: ?Sized> {
/// The method for the slicing operation foo[]
fn as_mut_slice_<'a>(&'a mut self) -> &'a mut Result;
/// The method for the slicing operation foo[from..]
/// An unbounded range.
#[derive(Copy)]
#[lang="full_range"]
+#[unstable = "API still in development"]
pub struct FullRange;
/// A (half-open) range which is bounded at both ends.
#[derive(Copy)]
#[lang="range"]
+#[unstable = "API still in development"]
pub struct Range<Idx> {
/// The lower bound of the range (inclusive).
pub start: Idx,
// FIXME(#19391) needs a snapshot
//impl<Idx: Clone + Step<T=uint>> Iterator<Idx> for Range<Idx> {
+#[unstable = "API still in development"]
impl<Idx: Clone + Step> Iterator for Range<Idx> {
type Item = Idx;
}
}
+#[unstable = "API still in development"]
impl<Idx: Clone + Step> DoubleEndedIterator for Range<Idx> {
#[inline]
fn next_back(&mut self) -> Option<Idx> {
}
}
+#[unstable = "API still in development"]
impl<Idx: Clone + Step> ExactSizeIterator for Range<Idx> {}
/// A range which is only bounded below.
#[derive(Copy)]
#[lang="range_from"]
+#[unstable = "API still in development"]
pub struct RangeFrom<Idx> {
/// The lower bound of the range (inclusive).
pub start: Idx,
}
+#[unstable = "API still in development"]
impl<Idx: Clone + Step> Iterator for RangeFrom<Idx> {
type Item = Idx;
/// A range which is only bounded above.
#[derive(Copy)]
#[lang="range_to"]
+#[unstable = "API still in development"]
pub struct RangeTo<Idx> {
/// The upper bound of the range (exclusive).
pub end: Idx,
/// }
/// ```
#[lang="deref"]
-pub trait Deref for Sized? {
- type Sized? Target;
+#[stable]
+pub trait Deref {
+ #[stable]
+ type Target: ?Sized;
/// The method called to dereference a value
+ #[stable]
fn deref<'a>(&'a self) -> &'a Self::Target;
}
-impl<'a, Sized? T> Deref for &'a T {
+#[stable]
+impl<'a, T: ?Sized> Deref for &'a T {
type Target = T;
fn deref(&self) -> &T { *self }
}
-impl<'a, Sized? T> Deref for &'a mut T {
+#[stable]
+impl<'a, T: ?Sized> Deref for &'a mut T {
type Target = T;
fn deref(&self) -> &T { *self }
/// }
/// ```
#[lang="deref_mut"]
-pub trait DerefMut for Sized? : Deref {
+#[stable]
+pub trait DerefMut: Deref {
/// The method called to mutably dereference a value
+ #[stable]
fn deref_mut<'a>(&'a mut self) -> &'a mut <Self as Deref>::Target;
}
-impl<'a, Sized? T> DerefMut for &'a mut T {
+#[stable]
+impl<'a, T: ?Sized> DerefMut for &'a mut T {
fn deref_mut(&mut self) -> &mut T { *self }
}
/// A version of the call operator that takes an immutable receiver.
#[lang="fn"]
-pub trait Fn<Args,Result> for Sized? {
+#[unstable = "uncertain about variadic generics, input versus associated types"]
+pub trait Fn<Args,Result> {
/// This is called when the call operator is used.
extern "rust-call" fn call(&self, args: Args) -> Result;
}
/// A version of the call operator that takes a mutable receiver.
#[lang="fn_mut"]
-pub trait FnMut<Args,Result> for Sized? {
+#[unstable = "uncertain about variadic generics, input versus associated types"]
+pub trait FnMut<Args,Result> {
/// This is called when the call operator is used.
extern "rust-call" fn call_mut(&mut self, args: Args) -> Result;
}
/// A version of the call operator that takes a by-value receiver.
#[lang="fn_once"]
+#[unstable = "uncertain about variadic generics, input versus associated types"]
pub trait FnOnce<Args,Result> {
/// This is called when the call operator is used.
extern "rust-call" fn call_once(self, args: Args) -> Result;
}
-impl<Sized? F,A,R> FnMut<A,R> for F
- where F : Fn<A,R>
+impl<F: ?Sized, A, R> FnMut<A, R> for F
+ where F : Fn<A, R>
{
extern "rust-call" fn call_mut(&mut self, args: A) -> R {
self.call(args)
#[stable]
pub struct Iter<'a, A: 'a> { inner: Item<&'a A> }
+#[stable]
impl<'a, A> Iterator for Iter<'a, A> {
type Item = &'a A;
fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
}
+#[stable]
impl<'a, A> DoubleEndedIterator for Iter<'a, A> {
#[inline]
fn next_back(&mut self) -> Option<&'a A> { self.inner.next_back() }
}
+#[stable]
impl<'a, A> ExactSizeIterator for Iter<'a, A> {}
#[stable]
#[stable]
pub struct IterMut<'a, A: 'a> { inner: Item<&'a mut A> }
+#[stable]
impl<'a, A> Iterator for IterMut<'a, A> {
type Item = &'a mut A;
fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
}
+#[stable]
impl<'a, A> DoubleEndedIterator for IterMut<'a, A> {
#[inline]
fn next_back(&mut self) -> Option<&'a mut A> { self.inner.next_back() }
}
+#[stable]
impl<'a, A> ExactSizeIterator for IterMut<'a, A> {}
/// An iterator over the item contained inside an Option.
#[stable]
pub struct IntoIter<A> { inner: Item<A> }
+#[stable]
impl<A> Iterator for IntoIter<A> {
type Item = A;
fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
}
+#[stable]
impl<A> DoubleEndedIterator for IntoIter<A> {
#[inline]
fn next_back(&mut self) -> Option<A> { self.inner.next_back() }
}
+#[stable]
impl<A> ExactSizeIterator for IntoIter<A> {}
/////////////////////////////////////////////////////////////////////////////
pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
pub use iter::{Extend, IteratorExt};
pub use iter::{Iterator, DoubleEndedIterator};
-pub use iter::{IteratorCloneExt, CloneIteratorExt};
-pub use iter::{IteratorOrdExt, ExactSizeIterator};
+pub use iter::{ExactSizeIterator};
pub use option::Option::{self, Some, None};
pub use ptr::{PtrExt, MutPtrExt};
pub use result::Result::{self, Ok, Err};
use kinds::Copy;
use mem;
-use kinds::Sized;
/// The representation of a Rust slice
#[repr(C)]
/// This trait is meant to map equivalences between raw structs and their
/// corresponding rust values.
-pub trait Repr<T> for Sized? {
+pub trait Repr<T> {
/// This function "unwraps" a rust value (without consuming it) into its raw
/// struct representation. This can be used to read/write different values
/// for the struct. This is a safe method because by default it does not
//!
//! ```
//! # #![feature(macro_rules)]
-//! macro_rules! try(
+//! macro_rules! try {
//! ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) })
-//! );
+//! }
//! # fn main() { }
//! ```
//!
#[stable]
pub struct Iter<'a, T: 'a> { inner: Option<&'a T> }
+#[stable]
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
}
}
+#[stable]
impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
#[inline]
fn next_back(&mut self) -> Option<&'a T> { self.inner.take() }
}
+#[stable]
impl<'a, T> ExactSizeIterator for Iter<'a, T> {}
impl<'a, T> Clone for Iter<'a, T> {
#[stable]
pub struct IterMut<'a, T: 'a> { inner: Option<&'a mut T> }
+#[stable]
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
}
}
+#[stable]
impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
#[inline]
fn next_back(&mut self) -> Option<&'a mut T> { self.inner.take() }
}
+#[stable]
impl<'a, T> ExactSizeIterator for IterMut<'a, T> {}
/// An iterator over the value in a `Ok` variant of a `Result`.
#[stable]
pub struct IntoIter<T> { inner: Option<T> }
+#[stable]
impl<T> Iterator for IntoIter<T> {
type Item = T;
}
}
+#[stable]
impl<T> DoubleEndedIterator for IntoIter<T> {
#[inline]
fn next_back(&mut self) -> Option<T> { self.inner.take() }
}
+#[stable]
impl<T> ExactSizeIterator for IntoIter<T> {}
/////////////////////////////////////////////////////////////////////////////
/// Extension methods for slices.
#[allow(missing_docs)] // docs in libcollections
-pub trait SliceExt for Sized? {
+pub trait SliceExt {
type Item;
fn slice<'a>(&'a self, start: uint, end: uint) -> &'a [Self::Item];
/// Data that is viewable as a slice.
#[experimental = "will be replaced by slice syntax"]
-pub trait AsSlice<T> for Sized? {
+pub trait AsSlice<T> {
/// Work with `self` as a slice.
fn as_slice<'a>(&'a self) -> &'a [T];
}
}
#[experimental = "trait is experimental"]
-impl<'a, T, Sized? U: AsSlice<T>> AsSlice<T> for &'a U {
+impl<'a, T, U: ?Sized + AsSlice<T>> AsSlice<T> for &'a U {
#[inline(always)]
fn as_slice(&self) -> &[T] { AsSlice::as_slice(*self) }
}
#[experimental = "trait is experimental"]
-impl<'a, T, Sized? U: AsSlice<T>> AsSlice<T> for &'a mut U {
+impl<'a, T, U: ?Sized + AsSlice<T>> AsSlice<T> for &'a mut U {
#[inline(always)]
fn as_slice(&self) -> &[T] { AsSlice::as_slice(*self) }
}
// The shared definition of the `Iter` and `IterMut` iterators
macro_rules! iterator {
(struct $name:ident -> $ptr:ty, $elem:ty) => {
- #[experimental = "needs review"]
+ #[stable]
impl<'a, T> Iterator for $name<'a, T> {
type Item = $elem;
}
}
- #[experimental = "needs review"]
+ #[stable]
impl<'a, T> DoubleEndedIterator for $name<'a, T> {
#[inline]
fn next_back(&mut self) -> Option<$elem> {
iterator!{struct Iter -> *const T, &'a T}
-#[experimental = "needs review"]
+#[stable]
impl<'a, T> ExactSizeIterator for Iter<'a, T> {}
#[stable]
fn clone(&self) -> Iter<'a, T> { *self }
}
-#[experimental = "needs review"]
+#[experimental = "trait is experimental"]
impl<'a, T> RandomAccessIterator for Iter<'a, T> {
#[inline]
fn indexable(&self) -> uint {
iterator!{struct IterMut -> *mut T, &'a mut T}
-#[experimental = "needs review"]
+#[stable]
impl<'a, T> ExactSizeIterator for IterMut<'a, T> {}
/// An internal abstraction over the splitting iterators, so that
}
}
-#[experimental = "needs review"]
+#[stable]
impl<'a, T, P> Iterator for Split<'a, T, P> where P: FnMut(&T) -> bool {
type Item = &'a [T];
}
}
-#[experimental = "needs review"]
+#[stable]
impl<'a, T, P> DoubleEndedIterator for Split<'a, T, P> where P: FnMut(&T) -> bool {
#[inline]
fn next_back(&mut self) -> Option<&'a [T]> {
}
}
-#[experimental = "needs review"]
+#[stable]
impl<'a, T, P> Iterator for SplitMut<'a, T, P> where P: FnMut(&T) -> bool {
type Item = &'a mut [T];
}
}
-#[experimental = "needs review"]
+#[stable]
impl<'a, T, P> DoubleEndedIterator for SplitMut<'a, T, P> where
P: FnMut(&T) -> bool,
{
invert: bool
}
-#[experimental = "needs review"]
impl<T, I: SplitIter + Iterator<Item=T>> Iterator for GenericSplitN<I> {
type Item = T;
/// An iterator over subslices separated by elements that match a predicate
/// function, limited to a given number of splits.
+#[stable]
pub struct SplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool {
inner: GenericSplitN<Split<'a, T, P>>
}
/// An iterator over subslices separated by elements that match a
/// predicate function, limited to a given number of splits, starting
/// from the end of the slice.
+#[stable]
pub struct RSplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool {
inner: GenericSplitN<Split<'a, T, P>>
}
/// An iterator over subslices separated by elements that match a predicate
/// function, limited to a given number of splits.
+#[stable]
pub struct SplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool {
inner: GenericSplitN<SplitMut<'a, T, P>>
}
/// An iterator over subslices separated by elements that match a
/// predicate function, limited to a given number of splits, starting
/// from the end of the slice.
+#[stable]
pub struct RSplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool {
inner: GenericSplitN<SplitMut<'a, T, P>>
}
macro_rules! forward_iterator {
($name:ident: $elem:ident, $iter_of:ty) => {
+ #[stable]
impl<'a, $elem, P> Iterator for $name<'a, $elem, P> where
P: FnMut(&T) -> bool
{
/// An iterator over overlapping subslices of length `size`.
#[derive(Clone)]
-#[experimental = "needs review"]
+#[stable]
pub struct Windows<'a, T:'a> {
v: &'a [T],
size: uint
}
+#[stable]
impl<'a, T> Iterator for Windows<'a, T> {
type Item = &'a [T];
/// When the slice len is not evenly divided by the chunk size, the last slice
/// of the iteration will be the remainder.
#[derive(Clone)]
-#[experimental = "needs review"]
+#[stable]
pub struct Chunks<'a, T:'a> {
v: &'a [T],
size: uint
}
-#[experimental = "needs review"]
+#[stable]
impl<'a, T> Iterator for Chunks<'a, T> {
type Item = &'a [T];
}
}
-#[experimental = "needs review"]
+#[stable]
impl<'a, T> DoubleEndedIterator for Chunks<'a, T> {
#[inline]
fn next_back(&mut self) -> Option<&'a [T]> {
}
}
-#[experimental = "needs review"]
+#[experimental = "trait is experimental"]
impl<'a, T> RandomAccessIterator for Chunks<'a, T> {
#[inline]
fn indexable(&self) -> uint {
/// An iterator over a slice in (non-overlapping) mutable chunks (`size`
/// elements at a time). When the slice len is not evenly divided by the chunk
/// size, the last slice of the iteration will be the remainder.
-#[experimental = "needs review"]
+#[stable]
pub struct ChunksMut<'a, T:'a> {
v: &'a mut [T],
chunk_size: uint
}
-#[experimental = "needs review"]
+#[stable]
impl<'a, T> Iterator for ChunksMut<'a, T> {
type Item = &'a mut [T];
}
}
-#[experimental = "needs review"]
+#[stable]
impl<'a, T> DoubleEndedIterator for ChunksMut<'a, T> {
#[inline]
fn next_back(&mut self) -> Option<&'a mut [T]> {
/// not being able to provide a non-aliasing guarantee of the returned mutable
/// slice.
#[inline]
-#[unstable = "jshould be renamed to from_raw_parts_mut"]
+#[unstable = "should be renamed to from_raw_parts_mut"]
pub unsafe fn from_raw_mut_buf<'a, T>(p: &'a *mut T, len: uint) -> &'a mut [T] {
transmute(RawSlice { data: *p as *const T, len: len })
}
/// Operations on `[u8]`.
#[experimental = "needs review"]
pub mod bytes {
- use kinds::Sized;
use ptr;
use slice::SliceExt;
/// A trait for operations on mutable `[u8]`s.
- pub trait MutableByteVector for Sized? {
+ pub trait MutableByteVector {
/// Sets all bytes of the receiver to the given value.
fn set_memory(&mut self, value: u8);
}
/// Extension methods for slices containing integers.
#[experimental]
-pub trait IntSliceExt<U, S> for Sized? {
+pub trait IntSliceExt<U, S> {
/// Converts the slice to an immutable slice of unsigned integers with the same width.
fn as_unsigned<'a>(&'a self) -> &'a [U];
/// Converts the slice to an immutable slice of signed integers with the same width.
macro_rules! delegate_iter {
(exact $te:ty in $ti:ty) => {
delegate_iter!{$te in $ti}
+ #[stable]
impl<'a> ExactSizeIterator for $ti {
- #[inline]
- fn rposition<P>(&mut self, predicate: P) -> Option<uint> where P: FnMut($te) -> bool{
- self.0.rposition(predicate)
- }
#[inline]
fn len(&self) -> uint {
self.0.len()
}
};
($te:ty in $ti:ty) => {
+ #[stable]
impl<'a> Iterator for $ti {
type Item = $te;
self.0.size_hint()
}
}
+ #[stable]
impl<'a> DoubleEndedIterator for $ti {
#[inline]
fn next_back(&mut self) -> Option<$te> {
}
};
(pattern $te:ty in $ti:ty) => {
+ #[stable]
impl<'a, P: CharEq> Iterator for $ti {
type Item = $te;
self.0.size_hint()
}
}
+ #[stable]
impl<'a, P: CharEq> DoubleEndedIterator for $ti {
#[inline]
fn next_back(&mut self) -> Option<$te> {
}
};
(pattern forward $te:ty in $ti:ty) => {
+ #[stable]
impl<'a, P: CharEq> Iterator for $ti {
type Item = $te;
/// Errors which can occur when attempting to interpret a byte slice as a `str`.
#[derive(Copy, Eq, PartialEq, Clone)]
+#[unstable = "error enumeration recently added and definitions may be refined"]
pub enum Utf8Error {
/// An invalid byte was detected at the byte offset given.
///
///
/// Returns `Err` if the slice is not utf-8 with a description as to why the
/// provided slice is not utf-8.
+#[stable]
pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
try!(run_utf8_validation_iterator(&mut v.iter()));
Ok(unsafe { from_utf8_unchecked(v) })
/// # Panics
///
/// This function will panic if the string pointed to by `s` is not valid UTF-8.
-#[unstable = "may change location based on the outcome of the c_str module"]
+#[deprecated = "use std::ffi::c_str_to_bytes + str::from_utf8"]
pub unsafe fn from_c_str(s: *const i8) -> &'static str {
let s = s as *const u8;
let mut len = 0u;
impl<'a> CharEq for &'a [char] {
#[inline]
fn matches(&mut self, c: char) -> bool {
- self.iter().any(|&mut m| m.matches(c))
+ self.iter().any(|&m| { let mut m = m; m.matches(c) })
}
#[inline]
///
/// Created with the method `.chars()`.
#[derive(Clone, Copy)]
+#[stable]
pub struct Chars<'a> {
iter: slice::Iter<'a, u8>
}
}
}
+#[stable]
impl<'a> Iterator for Chars<'a> {
type Item = char;
}
}
+#[stable]
impl<'a> DoubleEndedIterator for Chars<'a> {
#[inline]
fn next_back(&mut self) -> Option<char> {
/// External iterator for a string's characters and their byte offsets.
/// Use with the `std::iter` module.
#[derive(Clone)]
+#[stable]
pub struct CharIndices<'a> {
front_offset: uint,
iter: Chars<'a>,
}
+#[stable]
impl<'a> Iterator for CharIndices<'a> {
type Item = (uint, char);
}
}
+#[stable]
impl<'a> DoubleEndedIterator for CharIndices<'a> {
#[inline]
fn next_back(&mut self) -> Option<(uint, char)> {
}
}
+#[stable]
impl<'a, Sep: CharEq> Iterator for CharSplits<'a, Sep> {
type Item = &'a str;
}
}
+#[stable]
impl<'a, Sep: CharEq> DoubleEndedIterator for CharSplits<'a, Sep> {
#[inline]
fn next_back(&mut self) -> Option<&'a str> {
}
}
+#[stable]
impl<'a, Sep: CharEq> Iterator for CharSplitsN<'a, Sep> {
type Item = &'a str;
/// An iterator over the start and end indices of the matches of a
/// substring within a larger string
#[derive(Clone)]
+#[unstable = "type may be removed"]
pub struct MatchIndices<'a> {
// constants
haystack: &'a str,
/// An iterator over the substrings of a string separated by a given
/// search string
#[derive(Clone)]
-#[unstable = "Type might get removed"]
+#[unstable = "type may be removed"]
pub struct SplitStr<'a> {
it: MatchIndices<'a>,
last_end: uint,
finished: bool
}
+#[stable]
impl<'a> Iterator for MatchIndices<'a> {
type Item = (uint, uint);
}
}
+#[stable]
impl<'a> Iterator for SplitStr<'a> {
type Item = &'a str;
let old = *iter;
// restore the iterator we had at the start of this codepoint.
- macro_rules! err (() => { {
+ macro_rules! err { () => {{
*iter = old;
return Err(Utf8Error::InvalidByte(whole.len() - iter.as_slice().len()))
- } });
- macro_rules! next ( () => {
+ }}}
+
+ macro_rules! next { () => {
match iter.next() {
Some(a) => *a,
// we needed data, but there was none: error!
None => return Err(Utf8Error::TooShort),
}
- });
+ }}
let first = match iter.next() {
Some(&b) => b,
Section: Trait implementations
*/
-#[allow(missing_docs)]
-pub mod traits {
+mod traits {
use cmp::{Ordering, Ord, PartialEq, PartialOrd, Eq};
use cmp::Ordering::{Less, Equal, Greater};
use iter::IteratorExt;
#[unstable = "Instead of taking this bound generically, this trait will be \
replaced with one of slicing syntax, deref coercions, or \
a more generic conversion trait"]
-pub trait Str for Sized? {
+pub trait Str {
/// Work with `self` as a slice.
fn as_slice<'a>(&'a self) -> &'a str;
}
fn as_slice<'a>(&'a self) -> &'a str { self }
}
-impl<'a, Sized? S> Str for &'a S where S: Str {
+impl<'a, S: ?Sized> Str for &'a S where S: Str {
#[inline]
fn as_slice(&self) -> &str { Str::as_slice(*self) }
}
/// Methods for string slices
#[allow(missing_docs)]
-pub trait StrExt for Sized? {
+pub trait StrExt {
// NB there are no docs here are they're all located on the StrExt trait in
// libcollections, not here.
fn default() -> &'a str { "" }
}
+#[stable]
impl<'a> Iterator for Lines<'a> {
type Item = &'a str;
fn next(&mut self) -> Option<&'a str> { self.inner.next() }
#[inline]
fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
-}
+
+#[stable]}
impl<'a> DoubleEndedIterator for Lines<'a> {
#[inline]
fn next_back(&mut self) -> Option<&'a str> { self.inner.next_back() }
-}
+
+#[stable]}
impl<'a> Iterator for LinesAny<'a> {
type Item = &'a str;
fn next(&mut self) -> Option<&'a str> { self.inner.next() }
#[inline]
fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
-}
+
+#[stable]}
impl<'a> DoubleEndedIterator for LinesAny<'a> {
#[inline]
fn next_back(&mut self) -> Option<&'a str> { self.inner.next_back() }
struct MyWriterHasher;
impl Hasher<MyWriter> for MyWriterHasher {
- fn hash<Sized? T: Hash<MyWriter>>(&self, value: &T) -> u64 {
+ fn hash<T: ?Sized + Hash<MyWriter>>(&self, value: &T) -> u64 {
let mut state = MyWriter { hash: 0 };
value.hash(&mut state);
state.hash
#[test]
fn test_reverse() {
let mut ys = [1i, 2, 3, 4, 5];
- ys.iter_mut().reverse_();
+ ys.iter_mut().reverse_in_place();
assert!(ys == [5, 4, 3, 2, 1]);
}
// <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(globs, unsafe_destructor, macro_rules, slicing_syntax, default_type_params)]
+#![feature(globs, unsafe_destructor, slicing_syntax, default_type_params)]
#![feature(unboxed_closures)]
extern crate core;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![macro_escape]
-
-macro_rules! int_module (($T:ty, $T_i:ident) => (
+macro_rules! int_module { ($T:ty, $T_i:ident) => (
#[cfg(test)]
mod tests {
use core::$T_i::*;
}
}
-));
+)}
use core::ops::{Add, Sub, Mul, Div, Rem};
use core::kinds::Copy;
+#[cfg_attr(stage0, macro_escape)]
+#[cfg_attr(not(stage0), macro_use)]
mod int_macros;
+
mod i8;
mod i16;
mod i32;
mod i64;
mod int;
+
+#[cfg_attr(stage0, macro_escape)]
+#[cfg_attr(not(stage0), macro_use)]
mod uint_macros;
+
mod u8;
mod u16;
mod u32;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![macro_escape]
-
-macro_rules! uint_module (($T:ty, $T_i:ident) => (
+macro_rules! uint_module { ($T:ty, $T_i:ident) => (
#[cfg(test)]
mod tests {
use core::$T_i::*;
assert!(5u.checked_div(0) == None);
}
}
-));
+
+)}
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/nightly/")]
-#![feature(phase, unboxed_closures)]
+#![feature(unboxed_closures, associated_types)]
-#[cfg(test)] #[phase(plugin, link)] extern crate log;
+#[cfg(test)] #[macro_use] extern crate log;
extern crate libc;
use libc::{c_void, size_t, c_int};
-use std::c_vec::CVec;
+use std::ops::Deref;
use std::ptr::Unique;
+use std::slice;
+
+pub struct Bytes {
+ ptr: Unique<u8>,
+ len: uint,
+}
+
+impl Deref for Bytes {
+ type Target = [u8];
+ fn deref(&self) -> &[u8] {
+ unsafe { slice::from_raw_mut_buf(&self.ptr.0, self.len) }
+ }
+}
+
+impl Drop for Bytes {
+ fn drop(&mut self) {
+ unsafe { libc::free(self.ptr.0 as *mut _); }
+ }
+}
#[link(name = "miniz", kind = "static")]
extern {
static TINFL_FLAG_PARSE_ZLIB_HEADER : c_int = 0x1; // parse zlib header and adler32 checksum
static TDEFL_WRITE_ZLIB_HEADER : c_int = 0x01000; // write zlib header and adler32 checksum
-fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<CVec<u8>> {
+fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<Bytes> {
unsafe {
let mut outsz : size_t = 0;
let res = tdefl_compress_mem_to_heap(bytes.as_ptr() as *const _,
&mut outsz,
flags);
if !res.is_null() {
- let res = Unique(res);
- Some(CVec::new_with_dtor(res.0 as *mut u8, outsz as uint, move|:| libc::free(res.0)))
+ let res = Unique(res as *mut u8);
+ Some(Bytes { ptr: res, len: outsz as uint })
} else {
None
}
}
/// Compress a buffer, without writing any sort of header on the output.
-pub fn deflate_bytes(bytes: &[u8]) -> Option<CVec<u8>> {
+pub fn deflate_bytes(bytes: &[u8]) -> Option<Bytes> {
deflate_bytes_internal(bytes, LZ_NORM)
}
/// Compress a buffer, using a header that zlib can understand.
-pub fn deflate_bytes_zlib(bytes: &[u8]) -> Option<CVec<u8>> {
+pub fn deflate_bytes_zlib(bytes: &[u8]) -> Option<Bytes> {
deflate_bytes_internal(bytes, LZ_NORM | TDEFL_WRITE_ZLIB_HEADER)
}
-fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<CVec<u8>> {
+fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<Bytes> {
unsafe {
let mut outsz : size_t = 0;
let res = tinfl_decompress_mem_to_heap(bytes.as_ptr() as *const _,
&mut outsz,
flags);
if !res.is_null() {
- let res = Unique(res);
- Some(CVec::new_with_dtor(res.0 as *mut u8, outsz as uint, move|:| libc::free(res.0)))
+ let res = Unique(res as *mut u8);
+ Some(Bytes { ptr: res, len: outsz as uint })
} else {
None
}
}
/// Decompress a buffer, without parsing any sort of header on the input.
-pub fn inflate_bytes(bytes: &[u8]) -> Option<CVec<u8>> {
+pub fn inflate_bytes(bytes: &[u8]) -> Option<Bytes> {
inflate_bytes_internal(bytes, 0)
}
/// Decompress a buffer that starts with a zlib header.
-pub fn inflate_bytes_zlib(bytes: &[u8]) -> Option<CVec<u8>> {
+pub fn inflate_bytes_zlib(bytes: &[u8]) -> Option<Bytes> {
inflate_bytes_internal(bytes, TINFL_FLAG_PARSE_ZLIB_HEADER)
}
html_root_url = "http://doc.rust-lang.org/nightly/",
html_playground_url = "http://play.rust-lang.org/")]
-#![feature(macro_rules, globs, slicing_syntax)]
+#![feature(globs, slicing_syntax)]
#![feature(associated_types)]
pub use self::Piece::*;
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/nightly/",
html_playground_url = "http://play.rust-lang.org/")]
-#![feature(globs, phase, slicing_syntax)]
+#![feature(globs, slicing_syntax)]
#![feature(unboxed_closures)]
#![deny(missing_docs)]
-#[cfg(test)] #[phase(plugin, link)] extern crate log;
+#[cfg(test)] #[macro_use] extern crate log;
use self::Name::*;
use self::HasArg::*;
mod tests {
use self::NodeLabels::*;
use super::{Id, Labeller, Nodes, Edges, GraphWalk, render};
- use super::LabelText::{mod, LabelStr, EscStr};
+ use super::LabelText::{self, LabelStr, EscStr};
use std::io::IoResult;
use std::borrow::IntoCow;
use std::iter::repeat;
// Note 2: Once Dynamically Sized Types (DST) lands, it might be
// reasonable to replace this with something like `enum MaybeOwned<'a,
-// Sized? U>{ Owned(Box<U>), Borrowed(&'a U) }`; and then `U` could be
+// U: ?Sized>{ Owned(Box<U>), Borrowed(&'a U) }`; and then `U` could be
// instantiated with `[T]` or `str`, etc. Of course, that would imply
// removing the `Growable` variant, which relates to note 1 above.
// Alternatively, we might add `MaybeOwned` for the general case but
//! # Examples
//!
//! ```
-//! #![feature(phase)]
-//! #[phase(plugin, link)] extern crate log;
+//! #[macro_use] extern crate log;
//!
//! fn main() {
//! debug!("this is a debug {}", "message");
use directive::LOG_LEVEL_NAMES;
+#[cfg_attr(stage0, macro_escape)]
+#[cfg_attr(not(stage0), macro_use)]
pub mod macros;
+
mod directive;
/// Maximum logging level of a module that can be specified. Common logging
//! Logging macros
-#![macro_escape]
-
/// The standard logging macro
///
/// This macro will generically log over a provided level (of type u32) with a
/// # Example
///
/// ```
-/// #![feature(phase)]
-/// #[phase(plugin, link)] extern crate log;
+/// #[macro_use] extern crate log;
///
/// fn main() {
/// log!(log::WARN, "this is a warning {}", "message");
/// # Example
///
/// ```
-/// #![feature(phase)]
-/// #[phase(plugin, link)] extern crate log;
+/// #[macro_use] extern crate log;
///
/// fn main() {
/// let error = 3u;
/// # Example
///
/// ```
-/// #![feature(phase)]
-/// #[phase(plugin, link)] extern crate log;
+/// #[macro_use] extern crate log;
///
/// fn main() {
/// let code = 3u;
/// # Example
///
/// ```
-/// #![feature(phase)]
-/// #[phase(plugin, link)] extern crate log;
+/// #[macro_use] extern crate log;
///
/// fn main() {
/// let ret = 3i;
/// # Example
///
/// ```
-/// #![feature(phase)]
-/// #[phase(plugin, link)] extern crate log;
+/// #[macro_use] extern crate log;
///
/// fn main() {
/// debug!("x = {x}, y = {y}", x=10i, y=20i);
/// # Example
///
/// ```
-/// #![feature(phase)]
-/// #[phase(plugin, link)] extern crate log;
+/// #[macro_use] extern crate log;
///
/// struct Point { x: int, y: int }
/// fn some_expensive_computation() -> Point { Point { x: 1, y: 2 } }
use core::prelude::*;
use core::num::Int;
-
use {Rng, SeedableRng, Rand};
const KEY_WORDS : uint = 8; // 8 words for the 256-bit key
///
/// [1]: D. J. Bernstein, [*ChaCha, a variant of
/// Salsa20*](http://cr.yp.to/chacha.html)
-
-#[derive(Copy)]
+#[derive(Copy, Clone)]
pub struct ChaChaRng {
buffer: [u32; STATE_WORDS], // Internal buffer of output
state: [u32; STATE_WORDS], // Initial state
0x11cfa18e, 0xd3c50049, 0x75c775f6, 0x434c6530,
0x2c5bad8f, 0x898881dc, 0x5f1c86d9, 0xc1f8e7f4));
}
+
+ #[test]
+ fn test_rng_clone() {
+ let seed : &[_] = &[0u32; 8];
+ let mut rng: ChaChaRng = SeedableRng::from_seed(seed);
+ let mut clone = rng.clone();
+ for _ in range(0u, 16) {
+ assert_eq!(rng.next_u64(), clone.next_u64());
+ }
+ }
}
// it doesn't do weird things to the RNG (so 0 maps to 0, 1 to
// 1, internally; modulo a modulo operation).
- macro_rules! t (
+ macro_rules! t {
($items:expr, $expected:expr) => {{
let mut items = $items;
let wc = WeightedChoice::new(items.as_mut_slice());
assert_eq!(wc.ind_sample(&mut rng), val)
}
}}
- );
+ }
t!(vec!(Weighted { weight: 1, item: 10i}), [10]);
#[test]
fn test_integers() {
let mut rng = ::test::rng();
- macro_rules! t (
+ macro_rules! t {
($($ty:ty),*) => {{
$(
let v: &[($ty, $ty)] = &[(0, 10),
}
)*
}}
- );
+ }
t!(i8, i16, i32, i64, int,
u8, u16, u32, u64, uint)
}
#[test]
fn test_floats() {
let mut rng = ::test::rng();
- macro_rules! t (
+ macro_rules! t {
($($ty:ty),*) => {{
$(
let v: &[($ty, $ty)] = &[(0.0, 100.0),
}
)*
}}
- );
+ }
t!(f32, f64)
}
let mut g = a;
let mut h = a;
- macro_rules! mix(
+ macro_rules! mix {
() => {{
a^=b<<11; d+=a; b+=c;
b^=c>>2; e+=b; c+=d;
g^=h<<8; b+=g; h+=a;
h^=a>>9; c+=h; a+=b;
}}
- );
+ }
for _ in range(0u, 4) {
mix!();
}
if use_rsl {
- macro_rules! memloop (
+ macro_rules! memloop {
($arr:expr) => {{
for i in range_step(0, RAND_SIZE as uint, 8) {
a+=$arr[i ]; b+=$arr[i+1];
self.mem[i+6]=g; self.mem[i+7]=h;
}
}}
- );
+ }
memloop!(self.rsl);
memloop!(self.mem);
static MIDPOINT: uint = (RAND_SIZE / 2) as uint;
- macro_rules! ind (($x:expr) => {
- self.mem[(($x >> 2) as uint & ((RAND_SIZE - 1) as uint))]
- });
+ macro_rules! ind {
+ ($x:expr) => ( self.mem[(($x >> 2) as uint & ((RAND_SIZE - 1) as uint))] )
+ }
let r = [(0, MIDPOINT), (MIDPOINT, 0)];
for &(mr_offset, m2_offset) in r.iter() {
- macro_rules! rngstepp(
+ macro_rules! rngstepp {
($j:expr, $shift:expr) => {{
- let base = $j;
- let mix = a << $shift as uint;
+ let base = $j;
+ let mix = a << $shift as uint;
- let x = self.mem[base + mr_offset];
- a = (a ^ mix) + self.mem[base + m2_offset];
- let y = ind!(x) + a + b;
- self.mem[base + mr_offset] = y;
+ let x = self.mem[base + mr_offset];
+ a = (a ^ mix) + self.mem[base + m2_offset];
+ let y = ind!(x) + a + b;
+ self.mem[base + mr_offset] = y;
- b = ind!(y >> RAND_SIZE_LEN as uint) + x;
- self.rsl[base + mr_offset] = b;
- }}
- );
- macro_rules! rngstepn(
+ b = ind!(y >> RAND_SIZE_LEN as uint) + x;
+ self.rsl[base + mr_offset] = b;
+ }}
+ }
+
+ macro_rules! rngstepn {
($j:expr, $shift:expr) => {{
- let base = $j;
- let mix = a >> $shift as uint;
+ let base = $j;
+ let mix = a >> $shift as uint;
- let x = self.mem[base + mr_offset];
- a = (a ^ mix) + self.mem[base + m2_offset];
- let y = ind!(x) + a + b;
- self.mem[base + mr_offset] = y;
+ let x = self.mem[base + mr_offset];
+ a = (a ^ mix) + self.mem[base + m2_offset];
+ let y = ind!(x) + a + b;
+ self.mem[base + mr_offset] = y;
- b = ind!(y >> RAND_SIZE_LEN as uint) + x;
- self.rsl[base + mr_offset] = b;
- }}
- );
+ b = ind!(y >> RAND_SIZE_LEN as uint) + x;
+ self.rsl[base + mr_offset] = b;
+ }}
+ }
for i in range_step(0u, MIDPOINT, 4) {
rngstepp!(i + 0, 13);
}
}
+// Cannot be derived because [u32; 256] does not implement Clone
+impl Clone for IsaacRng {
+ fn clone(&self) -> IsaacRng {
+ *self
+ }
+}
+
impl Rng for IsaacRng {
#[inline]
fn next_u32(&mut self) -> u32 {
/// of `rsl` as a seed, otherwise construct one algorithmically (not
/// randomly).
fn init(&mut self, use_rsl: bool) {
- macro_rules! init (
+ macro_rules! init {
($var:ident) => (
let mut $var = 0x9e3779b97f4a7c13;
)
- );
+ }
init!(a); init!(b); init!(c); init!(d);
init!(e); init!(f); init!(g); init!(h);
- macro_rules! mix(
+ macro_rules! mix {
() => {{
a-=e; f^=h>>9; h+=a;
b-=f; g^=a<<9; a+=b;
g-=c; d^=f>>17; f+=g;
h-=d; e^=g<<14; g+=h;
}}
- );
+ }
for _ in range(0u, 4) {
mix!();
}
if use_rsl {
- macro_rules! memloop (
+ macro_rules! memloop {
($arr:expr) => {{
for i in range(0, RAND_SIZE_64 / 8).map(|i| i * 8) {
a+=$arr[i ]; b+=$arr[i+1];
self.mem[i+6]=g; self.mem[i+7]=h;
}
}}
- );
+ }
memloop!(self.rsl);
memloop!(self.mem);
let mut b = self.b + self.c;
const MIDPOINT: uint = RAND_SIZE_64 / 2;
const MP_VEC: [(uint, uint); 2] = [(0,MIDPOINT), (MIDPOINT, 0)];
- macro_rules! ind (
+ macro_rules! ind {
($x:expr) => {
*self.mem.get_unchecked(($x as uint >> 3) & (RAND_SIZE_64 - 1))
}
- );
+ }
for &(mr_offset, m2_offset) in MP_VEC.iter() {
for base in range(0, MIDPOINT / 4).map(|i| i * 4) {
- macro_rules! rngstepp(
+ macro_rules! rngstepp {
($j:expr, $shift:expr) => {{
- let base = base + $j;
- let mix = a ^ (a << $shift as uint);
- let mix = if $j == 0 {!mix} else {mix};
-
- unsafe {
- let x = *self.mem.get_unchecked(base + mr_offset);
- a = mix + *self.mem.get_unchecked(base + m2_offset);
- let y = ind!(x) + a + b;
- *self.mem.get_unchecked_mut(base + mr_offset) = y;
-
- b = ind!(y >> RAND_SIZE_64_LEN) + x;
- *self.rsl.get_unchecked_mut(base + mr_offset) = b;
- }
- }}
- );
- macro_rules! rngstepn(
+ let base = base + $j;
+ let mix = a ^ (a << $shift as uint);
+ let mix = if $j == 0 {!mix} else {mix};
+
+ unsafe {
+ let x = *self.mem.get_unchecked(base + mr_offset);
+ a = mix + *self.mem.get_unchecked(base + m2_offset);
+ let y = ind!(x) + a + b;
+ *self.mem.get_unchecked_mut(base + mr_offset) = y;
+
+ b = ind!(y >> RAND_SIZE_64_LEN) + x;
+ *self.rsl.get_unchecked_mut(base + mr_offset) = b;
+ }
+ }}
+ }
+
+ macro_rules! rngstepn {
($j:expr, $shift:expr) => {{
- let base = base + $j;
- let mix = a ^ (a >> $shift as uint);
- let mix = if $j == 0 {!mix} else {mix};
-
- unsafe {
- let x = *self.mem.get_unchecked(base + mr_offset);
- a = mix + *self.mem.get_unchecked(base + m2_offset);
- let y = ind!(x) + a + b;
- *self.mem.get_unchecked_mut(base + mr_offset) = y;
-
- b = ind!(y >> RAND_SIZE_64_LEN) + x;
- *self.rsl.get_unchecked_mut(base + mr_offset) = b;
- }
- }}
- );
+ let base = base + $j;
+ let mix = a ^ (a >> $shift as uint);
+ let mix = if $j == 0 {!mix} else {mix};
+
+ unsafe {
+ let x = *self.mem.get_unchecked(base + mr_offset);
+ a = mix + *self.mem.get_unchecked(base + m2_offset);
+ let y = ind!(x) + a + b;
+ *self.mem.get_unchecked_mut(base + mr_offset) = y;
+
+ b = ind!(y >> RAND_SIZE_64_LEN) + x;
+ *self.rsl.get_unchecked_mut(base + mr_offset) = b;
+ }
+ }}
+ }
+
rngstepp!(0u, 21);
rngstepn!(1u, 5);
rngstepp!(2u, 12);
}
}
+// Cannot be derived because [u32; 256] does not implement Clone
+impl Clone for Isaac64Rng {
+ fn clone(&self) -> Isaac64Rng {
+ *self
+ }
+}
+
impl Rng for Isaac64Rng {
// FIXME #7771: having next_u32 like this should be unnecessary
#[inline]
}
}
+
#[cfg(test)]
mod test {
use std::prelude::v1::*;
596345674630742204, 9947027391921273664, 11788097613744130851,
10391409374914919106));
}
+
+ #[test]
+ fn test_rng_clone() {
+ let seed: &[_] = &[1, 23, 456, 7890, 12345];
+ let mut rng: Isaac64Rng = SeedableRng::from_seed(seed);
+ let mut clone = rng.clone();
+ for _ in range(0u, 16) {
+ assert_eq!(rng.next_u64(), clone.next_u64());
+ }
+ }
}
#![no_std]
#![experimental]
+#[cfg(stage0)]
#[phase(plugin, link)]
extern crate core;
-#[cfg(test)] #[phase(plugin, link)] extern crate std;
-#[cfg(test)] #[phase(plugin, link)] extern crate log;
+#[cfg(not(stage0))]
+#[macro_use]
+extern crate core;
+
+#[cfg(all(test, stage0))]
+#[phase(plugin, link)]
+extern crate std;
+
+#[cfg(all(test, not(stage0)))]
+#[macro_use]
+extern crate std;
+
+#[cfg(all(test, stage0))]
+#[phase(plugin, link)]
+extern crate log;
+
+#[cfg(all(test, not(stage0)))]
+#[macro_use]
+extern crate log;
use core::prelude::*;
/// println!("{}", rng.gen_weighted_bool(3));
/// ```
fn gen_weighted_bool(&mut self, n: uint) -> bool {
- n == 0 || self.gen_range(0, n) == 0
+ n <= 1 || self.gen_range(0, n) == 0
}
/// Return an iterator of random characters from the set A-Z,a-z,0-9.
/// RNGs"](http://www.jstatsoft.org/v08/i14/paper). *Journal of
/// Statistical Software*. Vol. 8 (Issue 14).
#[allow(missing_copy_implementations)]
+#[derive(Clone)]
pub struct XorShiftRng {
x: u32,
y: u32,
w: u32,
}
-impl Clone for XorShiftRng {
- fn clone(&self) -> XorShiftRng {
- XorShiftRng {
- x: self.x,
- y: self.y,
- z: self.z,
- w: self.w,
- }
- }
-}
-
impl XorShiftRng {
/// Creates a new XorShiftRng instance which is not seeded.
///
#[cfg(not(test))]
mod std {
pub use core::{option, fmt}; // panic!()
+ pub use core::clone; // derive Clone
pub use core::kinds;
}
extern crate serialize;
-#[phase(plugin, link)] extern crate log;
+#[cfg(stage0)]
+#[phase(plugin, link)]
+extern crate log;
+
+#[cfg(not(stage0))]
+#[macro_use]
+extern crate log;
+
#[cfg(test)] extern crate test;
pub use self::EbmlEncoderTag::*;
html_playground_url = "http://play.rust-lang.org/")]
#![allow(unknown_features)]
-#![feature(macro_rules, phase, slicing_syntax, globs)]
+#![feature(macro_rules, slicing_syntax, globs)]
#![feature(unboxed_closures)]
#![feature(associated_types)]
#![deny(missing_docs)]
extern crate serialize;
extern crate rbml;
extern crate collections;
-#[phase(plugin, link)] extern crate log;
-#[phase(plugin, link)] extern crate syntax;
+
+#[cfg(stage0)]
+#[phase(plugin, link)]
+extern crate log;
+
+#[cfg(not(stage0))]
+#[macro_use]
+extern crate log;
+
+#[cfg(stage0)]
+#[phase(plugin, link)]
+extern crate syntax;
+
+#[cfg(not(stage0))]
+#[macro_use]
+extern crate syntax;
extern crate "serialize" as rustc_serialize; // used by deriving
}
declare_lint! {
- RAW_POINTER_DERIVING,
+ RAW_POINTER_DERIVE,
Warn,
"uses of #[derive] with raw pointers are rarely correct"
}
-struct RawPtrDerivingVisitor<'a, 'tcx: 'a> {
+struct RawPtrDeriveVisitor<'a, 'tcx: 'a> {
cx: &'a Context<'a, 'tcx>
}
-impl<'a, 'tcx, 'v> Visitor<'v> for RawPtrDerivingVisitor<'a, 'tcx> {
+impl<'a, 'tcx, 'v> Visitor<'v> for RawPtrDeriveVisitor<'a, 'tcx> {
fn visit_ty(&mut self, ty: &ast::Ty) {
static MSG: &'static str = "use of `#[derive]` with a raw pointer";
if let ast::TyPtr(..) = ty.node {
- self.cx.span_lint(RAW_POINTER_DERIVING, ty.span, MSG);
+ self.cx.span_lint(RAW_POINTER_DERIVE, ty.span, MSG);
}
visit::walk_ty(self, ty);
}
fn visit_block(&mut self, _: &ast::Block) {}
}
-pub struct RawPointerDeriving {
+pub struct RawPointerDerive {
checked_raw_pointers: NodeSet,
}
-impl RawPointerDeriving {
- pub fn new() -> RawPointerDeriving {
- RawPointerDeriving {
+impl RawPointerDerive {
+ pub fn new() -> RawPointerDerive {
+ RawPointerDerive {
checked_raw_pointers: NodeSet::new(),
}
}
}
-impl LintPass for RawPointerDeriving {
+impl LintPass for RawPointerDerive {
fn get_lints(&self) -> LintArray {
- lint_array!(RAW_POINTER_DERIVING)
+ lint_array!(RAW_POINTER_DERIVE)
}
fn check_item(&mut self, cx: &Context, item: &ast::Item) {
if !self.checked_raw_pointers.insert(item.id) { return }
match item.node {
ast::ItemStruct(..) | ast::ItemEnum(..) => {
- let mut visitor = RawPtrDerivingVisitor { cx: cx };
+ let mut visitor = RawPtrDeriveVisitor { cx: cx };
visit::walk_item(&mut visitor, &*item);
}
_ => {}
"must_use",
"stable",
"unstable",
+
+ // FIXME: #19470 this shouldn't be needed forever
+ "old_orphan_check",
];
static CRATE_ATTRS: &'static [&'static str] = &[
}
pub fn register_builtin(&mut self, sess: Option<&Session>) {
- macro_rules! add_builtin ( ( $sess:ident, $($name:ident),*, ) => (
- {$(
- self.register_pass($sess, false, box builtin::$name as LintPassObject);
- )*}
- ));
-
- macro_rules! add_builtin_with_new ( ( $sess:ident, $($name:ident),*, ) => (
- {$(
- self.register_pass($sess, false, box builtin::$name::new() as LintPassObject);
- )*}
- ));
-
- macro_rules! add_lint_group ( ( $sess:ident, $name:expr, $($lint:ident),* ) => (
- self.register_group($sess, false, $name, vec![$(LintId::of(builtin::$lint)),*]);
- ));
+ macro_rules! add_builtin {
+ ($sess:ident, $($name:ident),*,) => (
+ {$(
+ self.register_pass($sess, false, box builtin::$name as LintPassObject);
+ )*}
+ )
+ }
+
+ macro_rules! add_builtin_with_new {
+ ($sess:ident, $($name:ident),*,) => (
+ {$(
+ self.register_pass($sess, false, box builtin::$name::new() as LintPassObject);
+ )*}
+ )
+ }
+
+ macro_rules! add_lint_group {
+ ($sess:ident, $name:expr, $($lint:ident),*) => (
+ self.register_group($sess, false, $name, vec![$(LintId::of(builtin::$lint)),*]);
+ )
+ }
add_builtin!(sess,
HardwiredLints,
add_builtin_with_new!(sess,
TypeLimits,
- RawPointerDeriving,
+ RawPointerDerive,
MissingDoc,
);
self.register_renamed("unknown_crate_type", "unknown_crate_types");
self.register_renamed("variant_size_difference", "variant_size_differences");
self.register_renamed("transmute_fat_ptr", "fat_ptr_transmutes");
+ self.register_renamed("raw_pointer_deriving", "raw_pointer_derive");
}
//! example) requires more effort. See `emit_lint` and `GatherNodeLevels`
//! in `context.rs`.
-#![macro_escape]
-
pub use self::Level::*;
pub use self::LintSource::*;
pub const tag_native_libraries_kind: uint = 0x8a;
pub const tag_plugin_registrar_fn: uint = 0x8b;
-pub const tag_exported_macros: uint = 0x8c;
-pub const tag_macro_def: uint = 0x8d;
+
+// GAP 0x8c, 0x8d
pub const tag_method_argument_names: uint = 0x8e;
pub const tag_method_argument_name: uint = 0x8f;
pub const tag_associated_type_name: uint = 0xb3;
pub const tag_polarity: uint = 0xb4;
+
+pub const tag_macro_defs: uint = 0xb5;
+pub const tag_macro_def: uint = 0xb6;
+pub const tag_macro_def_body: uint = 0xb7;
use session::{config, Session};
use session::search_paths::PathKind;
use metadata::cstore;
-use metadata::cstore::{CStore, CrateSource};
+use metadata::cstore::{CStore, CrateSource, MetadataBlob};
use metadata::decoder;
use metadata::loader;
use metadata::loader::CratePaths;
-use plugin::load::PluginMetadata;
use util::nodemap::FnvHashMap;
use std::rc::Rc;
use syntax::abi;
use syntax::attr;
use syntax::attr::AttrMetaMethods;
-use syntax::codemap::{Span};
+use syntax::codemap::{Span, mk_sp};
use syntax::diagnostic::SpanHandler;
+use syntax::parse;
use syntax::parse::token::InternedString;
use syntax::parse::token;
use syntax::visit;
use util::fs;
+use log;
-struct Env<'a> {
+pub struct CrateReader<'a> {
sess: &'a Session,
next_crate_num: ast::CrateNum,
}
-// Traverses an AST, reading all the information about use'd crates and extern
-// libraries necessary for later resolving, typechecking, linking, etc.
-pub fn read_crates(sess: &Session,
- krate: &ast::Crate) {
- let mut e = Env {
- sess: sess,
- next_crate_num: sess.cstore.next_crate_num(),
- };
- visit_crate(&e, krate);
- visit::walk_crate(&mut e, krate);
- dump_crates(&sess.cstore);
- warn_if_multiple_versions(sess.diagnostic(), &sess.cstore);
-
- for &(ref name, kind) in sess.opts.libs.iter() {
- register_native_lib(sess, None, name.clone(), kind);
- }
-}
-
-impl<'a, 'v> visit::Visitor<'v> for Env<'a> {
+impl<'a, 'v> visit::Visitor<'v> for CrateReader<'a> {
fn visit_view_item(&mut self, a: &ast::ViewItem) {
- visit_view_item(self, a);
+ self.process_view_item(a);
visit::walk_view_item(self, a);
}
fn visit_item(&mut self, a: &ast::Item) {
- visit_item(self, a);
+ self.process_item(a);
visit::walk_item(self, a);
}
}
}
}
-fn visit_crate(e: &Env, c: &ast::Crate) {
- for a in c.attrs.iter().filter(|m| m.name() == "link_args") {
- match a.value_str() {
- Some(ref linkarg) => e.sess.cstore.add_used_link_args(linkarg.get()),
- None => { /* fallthrough */ }
- }
- }
-}
-
fn should_link(i: &ast::ViewItem) -> bool {
- i.attrs.iter().all(|attr| {
- attr.name().get() != "phase" ||
- attr.meta_item_list().map_or(false, |phases| {
- attr::contains_name(phases[], "link")
- })
- })
-}
-
-fn visit_view_item(e: &mut Env, i: &ast::ViewItem) {
- if !should_link(i) {
- return;
- }
-
- match extract_crate_info(e, i) {
- Some(info) => {
- let (cnum, _, _) = resolve_crate(e,
- &None,
- info.ident[],
- info.name[],
- None,
- i.span,
- PathKind::Crate);
- e.sess.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
- }
- None => ()
- }
+ !attr::contains_name(i.attrs[], "no_link")
}
struct CrateInfo {
should_link: bool,
}
-fn extract_crate_info(e: &Env, i: &ast::ViewItem) -> Option<CrateInfo> {
- match i.node {
- ast::ViewItemExternCrate(ident, ref path_opt, id) => {
- let ident = token::get_ident(ident);
- debug!("resolving extern crate stmt. ident: {} path_opt: {}",
- ident, path_opt);
- let name = match *path_opt {
- Some((ref path_str, _)) => {
- let name = path_str.get().to_string();
- validate_crate_name(Some(e.sess), name[],
- Some(i.span));
- name
- }
- None => ident.get().to_string(),
- };
- Some(CrateInfo {
- ident: ident.get().to_string(),
- name: name,
- id: id,
- should_link: should_link(i),
- })
- }
- _ => None
- }
-}
-
pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option<Span>) {
let err = |&: s: &str| {
match (sp, sess) {
}
}
-fn visit_item(e: &Env, i: &ast::Item) {
- match i.node {
- ast::ItemForeignMod(ref fm) => {
- if fm.abi == abi::Rust || fm.abi == abi::RustIntrinsic {
- return;
- }
-
- // First, add all of the custom link_args attributes
- let link_args = i.attrs.iter()
- .filter_map(|at| if at.name() == "link_args" {
- Some(at)
- } else {
- None
- })
- .collect::<Vec<&ast::Attribute>>();
- for m in link_args.iter() {
- match m.value_str() {
- Some(linkarg) => e.sess.cstore.add_used_link_args(linkarg.get()),
- None => { /* fallthrough */ }
- }
- }
-
- // Next, process all of the #[link(..)]-style arguments
- let link_args = i.attrs.iter()
- .filter_map(|at| if at.name() == "link" {
- Some(at)
- } else {
- None
- })
- .collect::<Vec<&ast::Attribute>>();
- for m in link_args.iter() {
- match m.meta_item_list() {
- Some(items) => {
- let kind = items.iter().find(|k| {
- k.name() == "kind"
- }).and_then(|a| a.value_str());
- let kind = match kind {
- Some(k) => {
- if k == "static" {
- cstore::NativeStatic
- } else if e.sess.target.target.options.is_like_osx
- && k == "framework" {
- cstore::NativeFramework
- } else if k == "framework" {
- cstore::NativeFramework
- } else if k == "dylib" {
- cstore::NativeUnknown
- } else {
- e.sess.span_err(m.span,
- format!("unknown kind: `{}`",
- k)[]);
- cstore::NativeUnknown
- }
- }
- None => cstore::NativeUnknown
- };
- let n = items.iter().find(|n| {
- n.name() == "name"
- }).and_then(|a| a.value_str());
- let n = match n {
- Some(n) => n,
- None => {
- e.sess.span_err(m.span,
- "#[link(...)] specified without \
- `name = \"foo\"`");
- InternedString::new("foo")
- }
- };
- register_native_lib(e.sess, Some(m.span),
- n.get().to_string(), kind);
- }
- None => {}
- }
- }
- }
- _ => { }
- }
-}
-
fn register_native_lib(sess: &Session,
span: Option<Span>,
name: String,
sess.cstore.add_used_library(name, kind);
}
-fn existing_match(e: &Env, name: &str,
- hash: Option<&Svh>) -> Option<ast::CrateNum> {
- let mut ret = None;
- e.sess.cstore.iter_crate_data(|cnum, data| {
- if data.name != name { return }
+pub struct PluginMetadata<'a> {
+ sess: &'a Session,
+ metadata: PMDSource,
+ dylib: Option<Path>,
+ info: CrateInfo,
+ vi_span: Span,
+ target_only: bool,
+}
- match hash {
- Some(hash) if *hash == data.hash() => { ret = Some(cnum); return }
- Some(..) => return,
- None => {}
- }
+enum PMDSource {
+ Registered(Rc<cstore::crate_metadata>),
+ Owned(MetadataBlob),
+}
- // When the hash is None we're dealing with a top-level dependency in
- // which case we may have a specification on the command line for this
- // library. Even though an upstream library may have loaded something of
- // the same name, we have to make sure it was loaded from the exact same
- // location as well.
- //
- // We're also sure to compare *paths*, not actual byte slices. The
- // `source` stores paths which are normalized which may be different
- // from the strings on the command line.
- let source = e.sess.cstore.get_used_crate_source(cnum).unwrap();
- match e.sess.opts.externs.get(name) {
- Some(locs) => {
- let found = locs.iter().any(|l| {
- let l = fs::realpath(&Path::new(l[])).ok();
- l == source.dylib || l == source.rlib
- });
- if found {
- ret = Some(cnum);
- }
- }
- None => ret = Some(cnum),
+impl PMDSource {
+ pub fn as_slice<'a>(&'a self) -> &'a [u8] {
+ match *self {
+ PMDSource::Registered(ref cmd) => cmd.data(),
+ PMDSource::Owned(ref mdb) => mdb.as_slice(),
}
- });
- return ret;
+ }
}
-fn register_crate<'a>(e: &mut Env,
- root: &Option<CratePaths>,
- ident: &str,
- name: &str,
- span: Span,
- lib: loader::Library)
- -> (ast::CrateNum, Rc<cstore::crate_metadata>,
- cstore::CrateSource) {
- // Claim this crate number and cache it
- let cnum = e.next_crate_num;
- e.next_crate_num += 1;
-
- // Stash paths for top-most crate locally if necessary.
- let crate_paths = if root.is_none() {
- Some(CratePaths {
- ident: ident.to_string(),
- dylib: lib.dylib.clone(),
- rlib: lib.rlib.clone(),
- })
- } else {
- None
- };
- // Maintain a reference to the top most crate.
- let root = if root.is_some() { root } else { &crate_paths };
+impl<'a> CrateReader<'a> {
+ pub fn new(sess: &'a Session) -> CrateReader<'a> {
+ CrateReader {
+ sess: sess,
+ next_crate_num: sess.cstore.next_crate_num(),
+ }
+ }
- let cnum_map = resolve_crate_deps(e, root, lib.metadata.as_slice(), span);
+ // Traverses an AST, reading all the information about use'd crates and extern
+ // libraries necessary for later resolving, typechecking, linking, etc.
+ pub fn read_crates(&mut self, krate: &ast::Crate) {
+ self.process_crate(krate);
+ visit::walk_crate(self, krate);
- let loader::Library{ dylib, rlib, metadata } = lib;
+ if log_enabled!(log::DEBUG) {
+ dump_crates(&self.sess.cstore);
+ }
+ warn_if_multiple_versions(self.sess.diagnostic(), &self.sess.cstore);
- let cmeta = Rc::new( cstore::crate_metadata {
- name: name.to_string(),
- data: metadata,
- cnum_map: cnum_map,
- cnum: cnum,
- span: span,
- });
+ for &(ref name, kind) in self.sess.opts.libs.iter() {
+ register_native_lib(self.sess, None, name.clone(), kind);
+ }
+ }
- let source = cstore::CrateSource {
- dylib: dylib,
- rlib: rlib,
- cnum: cnum,
- };
+ fn process_crate(&self, c: &ast::Crate) {
+ for a in c.attrs.iter().filter(|m| m.name() == "link_args") {
+ match a.value_str() {
+ Some(ref linkarg) => self.sess.cstore.add_used_link_args(linkarg.get()),
+ None => { /* fallthrough */ }
+ }
+ }
+ }
- e.sess.cstore.set_crate_data(cnum, cmeta.clone());
- e.sess.cstore.add_used_crate_source(source.clone());
- (cnum, cmeta, source)
-}
+ fn process_view_item(&mut self, i: &ast::ViewItem) {
+ if !should_link(i) {
+ return;
+ }
-fn resolve_crate(e: &mut Env,
- root: &Option<CratePaths>,
- ident: &str,
- name: &str,
- hash: Option<&Svh>,
- span: Span,
- kind: PathKind)
- -> (ast::CrateNum, Rc<cstore::crate_metadata>,
- cstore::CrateSource) {
- match existing_match(e, name, hash) {
- None => {
- let mut load_ctxt = loader::Context {
- sess: e.sess,
- span: span,
- ident: ident,
- crate_name: name,
- hash: hash.map(|a| &*a),
- filesearch: e.sess.target_filesearch(kind),
- triple: e.sess.opts.target_triple[],
- root: root,
- rejected_via_hash: vec!(),
- rejected_via_triple: vec!(),
- should_match_name: true,
- };
- let library = load_ctxt.load_library_crate();
- register_crate(e, root, ident, name, span, library)
+ match self.extract_crate_info(i) {
+ Some(info) => {
+ let (cnum, _, _) = self.resolve_crate(&None,
+ info.ident[],
+ info.name[],
+ None,
+ i.span,
+ PathKind::Crate);
+ self.sess.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
+ }
+ None => ()
}
- Some(cnum) => (cnum,
- e.sess.cstore.get_crate_data(cnum),
- e.sess.cstore.get_used_crate_source(cnum).unwrap())
}
-}
-// Go through the crate metadata and load any crates that it references
-fn resolve_crate_deps(e: &mut Env,
+ fn extract_crate_info(&self, i: &ast::ViewItem) -> Option<CrateInfo> {
+ match i.node {
+ ast::ViewItemExternCrate(ident, ref path_opt, id) => {
+ let ident = token::get_ident(ident);
+ debug!("resolving extern crate stmt. ident: {} path_opt: {}",
+ ident, path_opt);
+ let name = match *path_opt {
+ Some((ref path_str, _)) => {
+ let name = path_str.get().to_string();
+ validate_crate_name(Some(self.sess), name[],
+ Some(i.span));
+ name
+ }
+ None => ident.get().to_string(),
+ };
+ Some(CrateInfo {
+ ident: ident.get().to_string(),
+ name: name,
+ id: id,
+ should_link: should_link(i),
+ })
+ }
+ _ => None
+ }
+ }
+
+ fn process_item(&self, i: &ast::Item) {
+ match i.node {
+ ast::ItemForeignMod(ref fm) => {
+ if fm.abi == abi::Rust || fm.abi == abi::RustIntrinsic {
+ return;
+ }
+
+ // First, add all of the custom link_args attributes
+ let link_args = i.attrs.iter()
+ .filter_map(|at| if at.name() == "link_args" {
+ Some(at)
+ } else {
+ None
+ })
+ .collect::<Vec<&ast::Attribute>>();
+ for m in link_args.iter() {
+ match m.value_str() {
+ Some(linkarg) => self.sess.cstore.add_used_link_args(linkarg.get()),
+ None => { /* fallthrough */ }
+ }
+ }
+
+ // Next, process all of the #[link(..)]-style arguments
+ let link_args = i.attrs.iter()
+ .filter_map(|at| if at.name() == "link" {
+ Some(at)
+ } else {
+ None
+ })
+ .collect::<Vec<&ast::Attribute>>();
+ for m in link_args.iter() {
+ match m.meta_item_list() {
+ Some(items) => {
+ let kind = items.iter().find(|k| {
+ k.name() == "kind"
+ }).and_then(|a| a.value_str());
+ let kind = match kind {
+ Some(k) => {
+ if k == "static" {
+ cstore::NativeStatic
+ } else if self.sess.target.target.options.is_like_osx
+ && k == "framework" {
+ cstore::NativeFramework
+ } else if k == "framework" {
+ cstore::NativeFramework
+ } else if k == "dylib" {
+ cstore::NativeUnknown
+ } else {
+ self.sess.span_err(m.span,
+ format!("unknown kind: `{}`",
+ k)[]);
+ cstore::NativeUnknown
+ }
+ }
+ None => cstore::NativeUnknown
+ };
+ let n = items.iter().find(|n| {
+ n.name() == "name"
+ }).and_then(|a| a.value_str());
+ let n = match n {
+ Some(n) => n,
+ None => {
+ self.sess.span_err(m.span,
+ "#[link(...)] specified without \
+ `name = \"foo\"`");
+ InternedString::new("foo")
+ }
+ };
+ register_native_lib(self.sess, Some(m.span),
+ n.get().to_string(), kind);
+ }
+ None => {}
+ }
+ }
+ }
+ _ => { }
+ }
+ }
+
+ fn existing_match(&self, name: &str,
+ hash: Option<&Svh>) -> Option<ast::CrateNum> {
+ let mut ret = None;
+ self.sess.cstore.iter_crate_data(|cnum, data| {
+ if data.name != name { return }
+
+ match hash {
+ Some(hash) if *hash == data.hash() => { ret = Some(cnum); return }
+ Some(..) => return,
+ None => {}
+ }
+
+ // When the hash is None we're dealing with a top-level dependency in
+ // which case we may have a specification on the command line for this
+ // library. Even though an upstream library may have loaded something of
+ // the same name, we have to make sure it was loaded from the exact same
+ // location as well.
+ //
+ // We're also sure to compare *paths*, not actual byte slices. The
+ // `source` stores paths which are normalized which may be different
+ // from the strings on the command line.
+ let source = self.sess.cstore.get_used_crate_source(cnum).unwrap();
+ match self.sess.opts.externs.get(name) {
+ Some(locs) => {
+ let found = locs.iter().any(|l| {
+ let l = fs::realpath(&Path::new(l[])).ok();
+ l == source.dylib || l == source.rlib
+ });
+ if found {
+ ret = Some(cnum);
+ }
+ }
+ None => ret = Some(cnum),
+ }
+ });
+ return ret;
+ }
+
+ fn register_crate(&mut self,
root: &Option<CratePaths>,
- cdata: &[u8], span : Span)
- -> cstore::cnum_map {
- debug!("resolving deps of external crate");
- // The map from crate numbers in the crate we're resolving to local crate
- // numbers
- decoder::get_crate_deps(cdata).iter().map(|dep| {
- debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash);
- let (local_cnum, _, _) = resolve_crate(e, root,
- dep.name[],
- dep.name[],
- Some(&dep.hash),
- span,
- PathKind::Dependency);
- (dep.cnum, local_cnum)
- }).collect()
-}
+ ident: &str,
+ name: &str,
+ span: Span,
+ lib: loader::Library)
+ -> (ast::CrateNum, Rc<cstore::crate_metadata>,
+ cstore::CrateSource) {
+ // Claim this crate number and cache it
+ let cnum = self.next_crate_num;
+ self.next_crate_num += 1;
+
+ // Stash paths for top-most crate locally if necessary.
+ let crate_paths = if root.is_none() {
+ Some(CratePaths {
+ ident: ident.to_string(),
+ dylib: lib.dylib.clone(),
+ rlib: lib.rlib.clone(),
+ })
+ } else {
+ None
+ };
+ // Maintain a reference to the top most crate.
+ let root = if root.is_some() { root } else { &crate_paths };
-pub struct PluginMetadataReader<'a> {
- env: Env<'a>,
-}
+ let cnum_map = self.resolve_crate_deps(root, lib.metadata.as_slice(), span);
+
+ let loader::Library{ dylib, rlib, metadata } = lib;
+
+ let cmeta = Rc::new( cstore::crate_metadata {
+ name: name.to_string(),
+ data: metadata,
+ cnum_map: cnum_map,
+ cnum: cnum,
+ span: span,
+ });
+
+ let source = cstore::CrateSource {
+ dylib: dylib,
+ rlib: rlib,
+ cnum: cnum,
+ };
+
+ self.sess.cstore.set_crate_data(cnum, cmeta.clone());
+ self.sess.cstore.add_used_crate_source(source.clone());
+ (cnum, cmeta, source)
+ }
-impl<'a> PluginMetadataReader<'a> {
- pub fn new(sess: &'a Session) -> PluginMetadataReader<'a> {
- PluginMetadataReader {
- env: Env {
- sess: sess,
- next_crate_num: sess.cstore.next_crate_num(),
+ fn resolve_crate(&mut self,
+ root: &Option<CratePaths>,
+ ident: &str,
+ name: &str,
+ hash: Option<&Svh>,
+ span: Span,
+ kind: PathKind)
+ -> (ast::CrateNum, Rc<cstore::crate_metadata>,
+ cstore::CrateSource) {
+ match self.existing_match(name, hash) {
+ None => {
+ let mut load_ctxt = loader::Context {
+ sess: self.sess,
+ span: span,
+ ident: ident,
+ crate_name: name,
+ hash: hash.map(|a| &*a),
+ filesearch: self.sess.target_filesearch(kind),
+ triple: self.sess.opts.target_triple[],
+ root: root,
+ rejected_via_hash: vec!(),
+ rejected_via_triple: vec!(),
+ should_match_name: true,
+ };
+ let library = load_ctxt.load_library_crate();
+ self.register_crate(root, ident, name, span, library)
}
+ Some(cnum) => (cnum,
+ self.sess.cstore.get_crate_data(cnum),
+ self.sess.cstore.get_used_crate_source(cnum).unwrap())
}
}
- pub fn read_plugin_metadata(&mut self,
- krate: &ast::ViewItem) -> PluginMetadata {
- let info = extract_crate_info(&self.env, krate).unwrap();
- let target_triple = self.env.sess.opts.target_triple[];
+ // Go through the crate metadata and load any crates that it references
+ fn resolve_crate_deps(&mut self,
+ root: &Option<CratePaths>,
+ cdata: &[u8], span : Span)
+ -> cstore::cnum_map {
+ debug!("resolving deps of external crate");
+ // The map from crate numbers in the crate we're resolving to local crate
+ // numbers
+ decoder::get_crate_deps(cdata).iter().map(|dep| {
+ debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash);
+ let (local_cnum, _, _) = self.resolve_crate(root,
+ dep.name[],
+ dep.name[],
+ Some(&dep.hash),
+ span,
+ PathKind::Dependency);
+ (dep.cnum, local_cnum)
+ }).collect()
+ }
+
+ pub fn read_plugin_metadata<'b>(&'b mut self,
+ vi: &'b ast::ViewItem) -> PluginMetadata<'b> {
+ let info = self.extract_crate_info(vi).unwrap();
+ let target_triple = self.sess.opts.target_triple[];
let is_cross = target_triple != config::host_triple();
let mut should_link = info.should_link && !is_cross;
+ let mut target_only = false;
+ let ident = info.ident.clone();
+ let name = info.name.clone();
let mut load_ctxt = loader::Context {
- sess: self.env.sess,
- span: krate.span,
- ident: info.ident[],
- crate_name: info.name[],
+ sess: self.sess,
+ span: vi.span,
+ ident: ident[],
+ crate_name: name[],
hash: None,
- filesearch: self.env.sess.host_filesearch(PathKind::Crate),
+ filesearch: self.sess.host_filesearch(PathKind::Crate),
triple: config::host_triple(),
root: &None,
rejected_via_hash: vec!(),
let library = match load_ctxt.maybe_load_library_crate() {
Some(l) => l,
None if is_cross => {
- // try loading from target crates (only valid if there are
- // no syntax extensions)
- load_ctxt.triple = target_triple;
- load_ctxt.filesearch = self.env.sess.target_filesearch(PathKind::Crate);
- let lib = load_ctxt.load_library_crate();
- if decoder::get_plugin_registrar_fn(lib.metadata.as_slice()).is_some() {
- let message = format!("crate `{}` contains a plugin_registrar fn but \
- only a version for triple `{}` could be found (need {})",
- info.ident, target_triple, config::host_triple());
- self.env.sess.span_err(krate.span, message[]);
- // need to abort now because the syntax expansion
- // code will shortly attempt to load and execute
- // code from the found library.
- self.env.sess.abort_if_errors();
- }
+ // Try loading from target crates. This will abort later if we try to
+ // load a plugin registrar function,
+ target_only = true;
should_link = info.should_link;
- lib
+
+ load_ctxt.triple = target_triple;
+ load_ctxt.filesearch = self.sess.target_filesearch(PathKind::Crate);
+ load_ctxt.load_library_crate()
}
None => { load_ctxt.report_load_errs(); unreachable!() },
};
- let macros = decoder::get_exported_macros(library.metadata.as_slice());
- let registrar = decoder::get_plugin_registrar_fn(library.metadata.as_slice()).map(|id| {
- decoder::get_symbol(library.metadata.as_slice(), id)
- });
- if library.dylib.is_none() && registrar.is_some() {
- let message = format!("plugin crate `{}` only found in rlib format, \
- but must be available in dylib format",
- info.ident);
- self.env.sess.span_err(krate.span, message[]);
- // No need to abort because the loading code will just ignore this
- // empty dylib.
- }
- let pc = PluginMetadata {
- lib: library.dylib.clone(),
- macros: macros,
- registrar_symbol: registrar,
+
+ let dylib = library.dylib.clone();
+ let register = should_link && self.existing_match(info.name[], None).is_none();
+ let metadata = if register {
+ // Register crate now to avoid double-reading metadata
+ let (_, cmd, _) = self.register_crate(&None, info.ident[],
+ info.name[], vi.span, library);
+ PMDSource::Registered(cmd)
+ } else {
+ // Not registering the crate; just hold on to the metadata
+ PMDSource::Owned(library.metadata)
};
- if should_link && existing_match(&self.env, info.name[],
- None).is_none() {
- // register crate now to avoid double-reading metadata
- register_crate(&mut self.env, &None, info.ident[],
- info.name[], krate.span, library);
+
+ PluginMetadata {
+ sess: self.sess,
+ metadata: metadata,
+ dylib: dylib,
+ info: info,
+ vi_span: vi.span,
+ target_only: target_only,
+ }
+ }
+}
+
+impl<'a> PluginMetadata<'a> {
+ /// Read exported macros
+ pub fn exported_macros(&self) -> Vec<ast::MacroDef> {
+ let imported_from = Some(token::intern(self.info.ident[]).ident());
+ let source_name = format!("<{} macros>", self.info.ident[]);
+ let mut macros = vec![];
+ decoder::each_exported_macro(self.metadata.as_slice(),
+ &*self.sess.cstore.intr,
+ |name, attrs, body| {
+ // NB: Don't use parse::parse_tts_from_source_str because it parses with
+ // quote_depth > 0.
+ let mut p = parse::new_parser_from_source_str(&self.sess.parse_sess,
+ self.sess.opts.cfg.clone(),
+ source_name.clone(),
+ body);
+ let lo = p.span.lo;
+ let body = p.parse_all_token_trees();
+ let span = mk_sp(lo, p.last_span.hi);
+ p.abort_if_errors();
+ macros.push(ast::MacroDef {
+ ident: name.ident(),
+ attrs: attrs,
+ id: ast::DUMMY_NODE_ID,
+ span: span,
+ imported_from: imported_from,
+ // overridden in plugin/load.rs
+ export: false,
+ use_locally: false,
+
+ body: body,
+ });
+ true
+ }
+ );
+ macros
+ }
+
+ /// Look for a plugin registrar. Returns library path and symbol name.
+ pub fn plugin_registrar(&self) -> Option<(Path, String)> {
+ if self.target_only {
+ // Need to abort before syntax expansion.
+ let message = format!("plugin crate `{}` is not available for triple `{}` \
+ (only found {})",
+ self.info.ident,
+ config::host_triple(),
+ self.sess.opts.target_triple);
+ self.sess.span_err(self.vi_span, message[]);
+ self.sess.abort_if_errors();
+ }
+
+ let registrar = decoder::get_plugin_registrar_fn(self.metadata.as_slice())
+ .map(|id| decoder::get_symbol(self.metadata.as_slice(), id));
+
+ match (self.dylib.as_ref(), registrar) {
+ (Some(dylib), Some(reg)) => Some((dylib.clone(), reg)),
+ (None, Some(_)) => {
+ let message = format!("plugin crate `{}` only found in rlib format, \
+ but must be available in dylib format",
+ self.info.ident);
+ self.sess.span_err(self.vi_span, message[]);
+ // No need to abort because the loading code will just ignore this
+ // empty dylib.
+ None
+ }
+ _ => None,
}
- pc
}
}
use util::nodemap::{FnvHashMap, NodeMap};
use std::cell::RefCell;
-use std::c_vec::CVec;
use std::rc::Rc;
+use flate::Bytes;
use syntax::ast;
use syntax::codemap::Span;
use syntax::parse::token::IdentInterner;
pub type cnum_map = FnvHashMap<ast::CrateNum, ast::CrateNum>;
pub enum MetadataBlob {
- MetadataVec(CVec<u8>),
+ MetadataVec(Bytes),
MetadataArchive(loader::ArchiveMetadata),
}
.map(|doc| FromPrimitive::from_u32(reader::doc_as_u32(doc)).unwrap())
}
-pub fn get_exported_macros(data: &[u8]) -> Vec<String> {
- let macros = reader::get_doc(rbml::Doc::new(data),
- tag_exported_macros);
- let mut result = Vec::new();
+pub fn each_exported_macro<F>(data: &[u8], intr: &IdentInterner, mut f: F) where
+ F: FnMut(ast::Name, Vec<ast::Attribute>, String) -> bool,
+{
+ let macros = reader::get_doc(rbml::Doc::new(data), tag_macro_defs);
reader::tagged_docs(macros, tag_macro_def, |macro_doc| {
- result.push(macro_doc.as_str().to_string());
- true
+ let name = item_name(intr, macro_doc);
+ let attrs = get_attributes(macro_doc);
+ let body = reader::get_doc(macro_doc, tag_macro_def_body);
+ f(name, attrs, body.as_str().to_string())
});
- result
}
pub fn get_dylib_dependency_formats(cdata: Cmd)
use syntax::diagnostic::SpanHandler;
use syntax::parse::token::special_idents;
use syntax::parse::token;
+use syntax::print::pprust;
use syntax::ptr::P;
use syntax::visit::Visitor;
use syntax::visit;
}
}
-/// Given a span, write the text of that span into the output stream
-/// as an exported macro
-fn encode_macro_def(ecx: &EncodeContext,
- rbml_w: &mut Encoder,
- span: &syntax::codemap::Span) {
- let def = ecx.tcx.sess.codemap().span_to_snippet(*span)
- .expect("Unable to find source for macro");
- rbml_w.start_tag(tag_macro_def);
- rbml_w.wr_str(def[]);
- rbml_w.end_tag();
-}
-
/// Serialize the text of the exported macros
-fn encode_macro_defs(ecx: &EncodeContext,
- krate: &ast::Crate,
- rbml_w: &mut Encoder) {
- rbml_w.start_tag(tag_exported_macros);
- for item in krate.exported_macros.iter() {
- encode_macro_def(ecx, rbml_w, &item.span);
+fn encode_macro_defs(rbml_w: &mut Encoder,
+ krate: &ast::Crate) {
+ rbml_w.start_tag(tag_macro_defs);
+ for def in krate.exported_macros.iter() {
+ rbml_w.start_tag(tag_macro_def);
+
+ encode_name(rbml_w, def.ident.name);
+ encode_attributes(rbml_w, def.attrs[]);
+
+ rbml_w.start_tag(tag_macro_def_body);
+ rbml_w.wr_str(pprust::tts_to_string(def.body[])[]);
+ rbml_w.end_tag();
+
+ rbml_w.end_tag();
}
rbml_w.end_tag();
}
// Encode macro definitions
i = rbml_w.writer.tell().unwrap();
- encode_macro_defs(&ecx, krate, &mut rbml_w);
+ encode_macro_defs(&mut rbml_w, krate);
stats.macro_defs_bytes = rbml_w.writer.tell().unwrap() - i;
// Encode the types of all unboxed closures in this crate.
use syntax::diagnostic::SpanHandler;
use util::fs;
-use std::c_str::ToCStr;
+use std::ffi::CString;
use std::cmp;
use std::collections::{HashMap, HashSet};
use std::io::fs::PathExtensions;
}
}
unsafe {
- let mb = filename.with_c_str(|buf| {
- llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf)
- });
+ let buf = CString::from_slice(filename.as_vec());
+ let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr());
if mb as int == 0 {
return Err(format!("error reading library: '{}'",
filename.display()))
while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
let mut name_buf = ptr::null();
let name_len = llvm::LLVMRustGetSectionName(si.llsi, &mut name_buf);
- let name = String::from_raw_buf_len(name_buf as *const u8,
- name_len as uint);
+ let name = slice::from_raw_buf(&(name_buf as *const u8),
+ name_len as uint).to_vec();
+ let name = String::from_utf8(name).unwrap();
debug!("get_metadata_section: name {}", name);
if read_meta_section_name(is_osx) == name {
let cbuf = llvm::LLVMGetSectionContents(si.llsi);
}
ast::PatBox(ref subpat) |
- ast::PatRegion(ref subpat) |
+ ast::PatRegion(ref subpat, _) |
ast::PatIdent(_, _, Some(ref subpat)) => {
let subpat_exit = self.pat(&**subpat, pred);
self.add_node(pat.id, &[subpat_exit])
}
}
- ty::ty_rptr(_, ty::mt { ty, .. }) => {
+ ty::ty_rptr(_, ty::mt { ty, mutbl }) => {
match ty.sty {
ty::ty_vec(_, Some(n)) => match ctor {
&Single => {
_ => {
assert_eq!(pats_len, 1);
- ast::PatRegion(pats.nth(0).unwrap())
+ ast::PatRegion(pats.nth(0).unwrap(), mutbl)
}
}
}
ast::PatTup(ref args) =>
Some(args.iter().map(|p| &**p).collect()),
- ast::PatBox(ref inner) | ast::PatRegion(ref inner) =>
+ ast::PatBox(ref inner) | ast::PatRegion(ref inner, _) =>
Some(vec![&**inner]),
ast::PatLit(ref expr) => {
"target type not found for const cast")
});
- macro_rules! define_casts(
+ macro_rules! define_casts {
($val:ident, {
$($ty_pat:pat => (
$intermediate_ty:ty,
},)*
_ => Err("can't cast this type".to_string())
})
- );
+ }
eval_const_expr_partial(tcx, &**base)
.and_then(|val| define_casts!(val, {
use super::region_inference::ConcreteFailure;
use super::region_inference::SubSupConflict;
use super::region_inference::SupSupConflict;
-use super::region_inference::ParamBoundFailure;
+use super::region_inference::GenericBoundFailure;
+use super::region_inference::GenericKind;
use super::region_inference::ProcessedErrors;
use super::region_inference::SameRegions;
sub: Region,
sup: Region);
- fn report_param_bound_failure(&self,
- origin: SubregionOrigin<'tcx>,
- param_ty: ty::ParamTy,
- sub: Region,
- sups: Vec<Region>);
+ fn report_generic_bound_failure(&self,
+ origin: SubregionOrigin<'tcx>,
+ kind: GenericKind<'tcx>,
+ sub: Region,
+ sups: Vec<Region>);
fn report_sub_sup_conflict(&self,
var_origin: RegionVariableOrigin,
self.report_concrete_failure(origin, sub, sup);
}
- ParamBoundFailure(origin, param_ty, sub, sups) => {
- self.report_param_bound_failure(origin, param_ty, sub, sups);
+ GenericBoundFailure(kind, param_ty, sub, sups) => {
+ self.report_generic_bound_failure(kind, param_ty, sub, sups);
}
SubSupConflict(var_origin,
found.user_string(self.tcx)))
}
- fn report_param_bound_failure(&self,
- origin: SubregionOrigin<'tcx>,
- param_ty: ty::ParamTy,
- sub: Region,
- _sups: Vec<Region>) {
-
+ fn report_generic_bound_failure(&self,
+ origin: SubregionOrigin<'tcx>,
+ bound_kind: GenericKind<'tcx>,
+ sub: Region,
+ _sups: Vec<Region>)
+ {
// FIXME: it would be better to report the first error message
// with the span of the parameter itself, rather than the span
// where the error was detected. But that span is not readily
// accessible.
+ let labeled_user_string = match bound_kind {
+ GenericKind::Param(ref p) =>
+ format!("the parameter type `{}`", p.user_string(self.tcx)),
+ GenericKind::Projection(ref p) =>
+ format!("the associated type `{}`", p.user_string(self.tcx)),
+ };
+
match sub {
ty::ReFree(ty::FreeRegion {bound_region: ty::BrNamed(..), ..}) => {
// Does the required lifetime have a nice name we can print?
self.tcx.sess.span_err(
origin.span(),
- format!(
- "the parameter type `{}` may not live long enough",
- param_ty.user_string(self.tcx))[]);
+ format!("{} may not live long enough", labeled_user_string)[]);
self.tcx.sess.span_help(
origin.span(),
format!(
"consider adding an explicit lifetime bound `{}: {}`...",
- param_ty.user_string(self.tcx),
+ bound_kind.user_string(self.tcx),
sub.user_string(self.tcx))[]);
}
// Does the required lifetime have a nice name we can print?
self.tcx.sess.span_err(
origin.span(),
- format!(
- "the parameter type `{}` may not live long enough",
- param_ty.user_string(self.tcx))[]);
+ format!("{} may not live long enough", labeled_user_string)[]);
self.tcx.sess.span_help(
origin.span(),
format!(
"consider adding an explicit lifetime bound `{}: 'static`...",
- param_ty.user_string(self.tcx))[]);
+ bound_kind.user_string(self.tcx))[]);
}
_ => {
self.tcx.sess.span_err(
origin.span(),
format!(
- "the parameter type `{}` may not live long enough",
- param_ty.user_string(self.tcx))[]);
+ "{} may not live long enough",
+ labeled_user_string)[]);
self.tcx.sess.span_help(
origin.span(),
format!(
- "consider adding an explicit lifetime bound to `{}`",
- param_ty.user_string(self.tcx))[]);
+ "consider adding an explicit lifetime bound for `{}`",
+ bound_kind.user_string(self.tcx))[]);
note_and_explain_region(
self.tcx,
- format!("the parameter type `{}` must be valid for ",
- param_ty.user_string(self.tcx))[],
+ format!("{} must be valid for ", labeled_user_string)[],
sub,
"...");
}
pub use self::fixup_err::*;
pub use middle::ty::IntVarValue;
pub use self::freshen::TypeFreshener;
+pub use self::region_inference::GenericKind;
use middle::subst;
use middle::subst::Substs;
cx.region_vars.commit(snapshot);
}
-pub fn verify_param_bound<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
- origin: SubregionOrigin<'tcx>,
- param_ty: ty::ParamTy,
- a: ty::Region,
- bs: Vec<ty::Region>) {
- debug!("verify_param_bound({}, {} <: {})",
- param_ty.repr(cx.tcx),
- a.repr(cx.tcx),
- bs.repr(cx.tcx));
-
- cx.region_vars.verify_param_bound(origin, param_ty, a, bs);
-}
-
pub fn mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
a_is_expected: bool,
origin: TypeOrigin,
value,
|br, _| self.next_region_var(LateBoundRegion(span, br, lbrct)))
}
+
+ /// See `verify_generic_bound` method in `region_inference`
+ pub fn verify_generic_bound(&self,
+ origin: SubregionOrigin<'tcx>,
+ kind: GenericKind<'tcx>,
+ a: ty::Region,
+ bs: Vec<ty::Region>) {
+ debug!("verify_generic_bound({}, {} <: {})",
+ kind.repr(self.tcx),
+ a.repr(self.tcx),
+ bs.repr(self.tcx));
+
+ self.region_vars.verify_generic_bound(origin, kind, a, bs);
+ }
}
impl<'tcx> TypeTrace<'tcx> {
use super::{RegionVariableOrigin, SubregionOrigin, TypeTrace, MiscVariable};
use middle::region;
-use middle::ty;
+use middle::ty::{self, Ty};
use middle::ty::{BoundRegion, FreeRegion, Region, RegionVid};
use middle::ty::{ReEmpty, ReStatic, ReInfer, ReFree, ReEarlyBound};
use middle::ty::{ReLateBound, ReScope, ReVar, ReSkolemized, BrFresh};
use middle::graph::{Direction, NodeIndex};
use util::common::indenter;
use util::nodemap::{FnvHashMap, FnvHashSet};
-use util::ppaux::Repr;
+use util::ppaux::{Repr, UserString};
use std::cell::{Cell, RefCell};
use std::cmp::Ordering::{self, Less, Greater, Equal};
// `b` are inference variables.
VerifyRegSubReg(SubregionOrigin<'tcx>, Region, Region),
- // VerifyParamBound(T, _, R, RS): The parameter type `T` must
- // outlive the region `R`. `T` is known to outlive `RS`. Therefore
- // verify that `R <= RS[i]` for some `i`. Inference variables may
- // be involved (but this verification step doesn't influence
- // inference).
- VerifyParamBound(ty::ParamTy, SubregionOrigin<'tcx>, Region, Vec<Region>),
+ // VerifyGenericBound(T, _, R, RS): The parameter type `T` (or
+ // associated type) must outlive the region `R`. `T` is known to
+ // outlive `RS`. Therefore verify that `R <= RS[i]` for some
+ // `i`. Inference variables may be involved (but this verification
+ // step doesn't influence inference).
+ VerifyGenericBound(GenericKind<'tcx>, SubregionOrigin<'tcx>, Region, Vec<Region>),
+}
+
+#[derive(Clone, Show, PartialEq, Eq)]
+pub enum GenericKind<'tcx> {
+ Param(ty::ParamTy),
+ Projection(ty::ProjectionTy<'tcx>),
}
#[derive(Copy, PartialEq, Eq, Hash)]
/// `o` requires that `a <= b`, but this does not hold
ConcreteFailure(SubregionOrigin<'tcx>, Region, Region),
- /// `ParamBoundFailure(p, s, a, bs)
+ /// `GenericBoundFailure(p, s, a, bs)
///
- /// The parameter type `p` must be known to outlive the lifetime
+ /// The parameter/assocated-type `p` must be known to outlive the lifetime
/// `a`, but it is only known to outlive `bs` (and none of the
/// regions in `bs` outlive `a`).
- ParamBoundFailure(SubregionOrigin<'tcx>, ty::ParamTy, Region, Vec<Region>),
+ GenericBoundFailure(SubregionOrigin<'tcx>, GenericKind<'tcx>, Region, Vec<Region>),
/// `SubSupConflict(v, sub_origin, sub_r, sup_origin, sup_r)`:
///
}
}
- pub fn verify_param_bound(&self,
- origin: SubregionOrigin<'tcx>,
- param_ty: ty::ParamTy,
- sub: Region,
- sups: Vec<Region>) {
- self.add_verify(VerifyParamBound(param_ty, origin, sub, sups));
+ /// See `Verify::VerifyGenericBound`
+ pub fn verify_generic_bound(&self,
+ origin: SubregionOrigin<'tcx>,
+ kind: GenericKind<'tcx>,
+ sub: Region,
+ sups: Vec<Region>) {
+ self.add_verify(VerifyGenericBound(kind, origin, sub, sups));
}
pub fn lub_regions(&self,
&mut result_set, r,
a, b);
}
- VerifyParamBound(_, _, a, ref bs) => {
+ VerifyGenericBound(_, _, a, ref bs) => {
for &b in bs.iter() {
consider_adding_bidirectional_edges(
&mut result_set, r,
errors.push(ConcreteFailure((*origin).clone(), sub, sup));
}
- VerifyParamBound(ref param_ty, ref origin, sub, ref sups) => {
+ VerifyGenericBound(ref kind, ref origin, sub, ref sups) => {
let sub = normalize(values, sub);
if sups.iter()
.map(|&sup| normalize(values, sup))
let sups = sups.iter().map(|&sup| normalize(values, sup))
.collect();
errors.push(
- ParamBoundFailure(
- (*origin).clone(), *param_ty, sub, sups));
+ GenericBoundFailure(
+ (*origin).clone(), kind.clone(), sub, sups));
}
}
}
VerifyRegSubReg(_, ref a, ref b) => {
format!("VerifyRegSubReg({}, {})", a.repr(tcx), b.repr(tcx))
}
- VerifyParamBound(_, ref p, ref a, ref bs) => {
- format!("VerifyParamBound({}, {}, {})",
+ VerifyGenericBound(_, ref p, ref a, ref bs) => {
+ format!("VerifyGenericBound({}, {}, {})",
p.repr(tcx), a.repr(tcx), bs.repr(tcx))
}
}
self.origin.repr(tcx))
}
}
+
+impl<'tcx> Repr<'tcx> for GenericKind<'tcx> {
+ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
+ match *self {
+ GenericKind::Param(ref p) => p.repr(tcx),
+ GenericKind::Projection(ref p) => p.repr(tcx),
+ }
+ }
+}
+
+impl<'tcx> UserString<'tcx> for GenericKind<'tcx> {
+ fn user_string(&self, tcx: &ty::ctxt<'tcx>) -> String {
+ match *self {
+ GenericKind::Param(ref p) => p.user_string(tcx),
+ GenericKind::Projection(ref p) => p.user_string(tcx),
+ }
+ }
+}
+
+impl<'tcx> GenericKind<'tcx> {
+ pub fn to_ty(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
+ match *self {
+ GenericKind::Param(ref p) =>
+ p.to_ty(tcx),
+ GenericKind::Projection(ref p) =>
+ ty::mk_projection(tcx, p.trait_ref.clone(), p.item_name),
+ }
+ }
+}
// However, it's not as simple as checking whether `T :
// Sized`, because even if `T : Sized` does not hold, that
// just means that `T` *may* not be sized. After all, even a
- // type parameter `Sized? T` could be bound to a sized
+ // type parameter `T: ?Sized` could be bound to a sized
// type. (Issue #20116)
//
// To handle this, we first check for "interior" type
// exhaustively checking all possible combinations. Here are some examples:
//
// ```
- // fn foo<T,U>() {
+ // fn foo<T, U>() {
// // T=int, U=int
// }
//
- // fn bar<Sized? T,U>() {
+ // fn bar<T: ?Sized, U>() {
// // T=int, U=int
// // T=[int], U=int
// }
//
- // fn baz<Sized? T, Sized?U>() {
+ // fn baz<T: ?Sized, U: ?Sized>() {
// // T=int, U=int
// // T=[int], U=int
// // T=int, U=[int]
}
}
- ast::PatBox(ref subpat) | ast::PatRegion(ref subpat) => {
- // @p1, ~p1, ref p1
+ ast::PatBox(ref subpat) | ast::PatRegion(ref subpat, _) => {
+ // box p1, &p1, &mut p1. we can ignore the mutability of
+ // PatRegion since that information is already contained
+ // in the type.
let subcmt = try!(self.cat_deref(pat, cmt, 0, false));
try!(self.cat_pattern_(subcmt, &**subpat, op));
}
use super::{Obligation, ObligationCause};
use super::util;
-use middle::subst::Subst;
+use middle::subst::{Subst};
use middle::ty::{self, Ty};
use middle::infer::InferCtxt;
use std::collections::HashSet;
}
#[allow(missing_copy_implementations)]
-pub enum OrphanCheckErr {
+pub enum OrphanCheckErr<'tcx> {
NoLocalInputType,
- UncoveredTypeParameter(ty::ParamTy),
+ UncoveredTy(Ty<'tcx>),
}
/// Checks the coherence orphan rules. `impl_def_id` should be the
/// def-id of a trait impl. To pass, either the trait must be local, or else
/// two conditions must be satisfied:
///
-/// 1. At least one of the input types must involve a local type.
-/// 2. All type parameters must be covered by a local type.
-pub fn orphan_check(tcx: &ty::ctxt,
- impl_def_id: ast::DefId)
- -> Result<(), OrphanCheckErr>
+/// 1. All type parameters in `Self` must be "covered" by some local type constructor.
+/// 2. Some local type must appear in `Self`.
+pub fn orphan_check<'tcx>(tcx: &ty::ctxt<'tcx>,
+ impl_def_id: ast::DefId)
+ -> Result<(), OrphanCheckErr<'tcx>>
{
debug!("impl_is_local({})", impl_def_id.repr(tcx));
return Ok(());
}
- // Check condition 1: at least one type must be local.
- if !trait_ref.input_types().iter().any(|&t| ty_reaches_local(tcx, t)) {
- return Err(OrphanCheckErr::NoLocalInputType);
+ // Otherwise, check that (1) all type parameters are covered.
+ let covered_params = type_parameters_covered_by_ty(tcx, trait_ref.self_ty());
+ let all_params = type_parameters_reachable_from_ty(trait_ref.self_ty());
+ for ¶m in all_params.difference(&covered_params) {
+ return Err(OrphanCheckErr::UncoveredTy(param));
}
- // Check condition 2: type parameters must be "covered" by a local type.
- let covered_params: HashSet<_> =
- trait_ref.input_types().iter()
- .flat_map(|&t| type_parameters_covered_by_ty(tcx, t).into_iter())
- .collect();
- let all_params: HashSet<_> =
- trait_ref.input_types().iter()
- .flat_map(|&t| type_parameters_reachable_from_ty(t).into_iter())
- .collect();
- for ¶m in all_params.difference(&covered_params) {
- return Err(OrphanCheckErr::UncoveredTypeParameter(param));
+ // And (2) some local type appears.
+ if !trait_ref.self_ty().walk().any(|t| ty_is_local_constructor(tcx, t)) {
+ return Err(OrphanCheckErr::NoLocalInputType);
}
return Ok(());
}
-fn ty_reaches_local<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
- ty.walk().any(|t| ty_is_local_constructor(tcx, t))
-}
-
fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
debug!("ty_is_local_constructor({})", ty.repr(tcx));
}
fn type_parameters_covered_by_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
- ty: Ty<'tcx>)
- -> HashSet<ty::ParamTy>
+ ty: Ty<'tcx>)
+ -> HashSet<Ty<'tcx>>
{
if ty_is_local_constructor(tcx, ty) {
type_parameters_reachable_from_ty(ty)
}
/// All type parameters reachable from `ty`
-fn type_parameters_reachable_from_ty<'tcx>(ty: Ty<'tcx>) -> HashSet<ty::ParamTy> {
+fn type_parameters_reachable_from_ty<'tcx>(ty: Ty<'tcx>) -> HashSet<Ty<'tcx>> {
ty.walk()
- .filter_map(|t| {
+ .filter(|&t| {
match t.sty {
- ty::ty_param(ref param_ty) => Some(param_ty.clone()),
- _ => None,
+ // FIXME(#20590) straighten story about projection types
+ ty::ty_projection(..) | ty::ty_param(..) => true,
+ _ => false,
}
})
.collect()
}
-
match impl_ty {
Some(ty) => (ty, impl_vtable.nested.to_vec()),
None => {
- selcx.tcx().sess.span_bug(
- obligation.cause.span,
- format!("impl `{}` did not contain projection for `{}`",
- impl_vtable.repr(selcx.tcx()),
- obligation.repr(selcx.tcx())).as_slice());
+ // This means that the impl is missing a
+ // definition for the associated type. This error
+ // ought to be reported by the type checker method
+ // `check_impl_items_against_trait`, so here we
+ // just return ty_err.
+ (selcx.tcx().types.err, vec!())
}
}
}
// Only keep those bounds that we haven't already
// seen. This is necessary to prevent infinite
// recursion in some cases. One common case is when
- // people define `trait Sized { }` rather than `trait
- // Sized for Sized? { }`.
+ // people define `trait Sized: Sized { }` rather than `trait
+ // Sized { }`.
predicates.retain(|r| self.visited.insert(r.clone()));
self.stack.push(StackEntry { position: 0,
!self.regions.is_empty_in(space)
}
+ pub fn is_empty(&self) -> bool {
+ self.types.is_empty() && self.regions.is_empty()
+ }
+
pub fn to_bounds(&self, tcx: &ty::ctxt<'tcx>, substs: &Substs<'tcx>)
-> GenericBounds<'tcx> {
GenericBounds {
return state.result();
fn helper<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh, state: &mut sip::SipState) {
- macro_rules! byte( ($b:expr) => { ($b as u8).hash(state) } );
- macro_rules! hash( ($e:expr) => { $e.hash(state) } );
+ macro_rules! byte { ($b:expr) => { ($b as u8).hash(state) } }
+ macro_rules! hash { ($e:expr) => { $e.hash(state) } }
let region = |&: state: &mut sip::SipState, r: Region| {
match r {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-//! Used by `rustc` when loading a plugin.
+//! Used by `rustc` when loading a plugin, or a crate with exported macros.
use session::Session;
-use metadata::creader::PluginMetadataReader;
+use metadata::creader::CrateReader;
use plugin::registry::Registry;
use std::mem;
use std::os;
use std::dynamic_lib::DynamicLibrary;
+use std::collections::HashSet;
use syntax::ast;
use syntax::attr;
+use syntax::codemap::Span;
+use syntax::parse::token;
+use syntax::ptr::P;
use syntax::visit;
use syntax::visit::Visitor;
-use syntax::ext::expand::ExportedMacros;
use syntax::attr::AttrMetaMethods;
-/// Plugin-related crate metadata.
-pub struct PluginMetadata {
- /// Source code of macros exported by the crate.
- pub macros: Vec<String>,
- /// Path to the shared library file.
- pub lib: Option<Path>,
- /// Symbol name of the plugin registrar function.
- pub registrar_symbol: Option<String>,
-}
-
/// Pointer to a registrar function.
pub type PluginRegistrarFun =
fn(&mut Registry);
+pub struct PluginRegistrar {
+ pub fun: PluginRegistrarFun,
+ pub args: P<ast::MetaItem>,
+}
+
/// Information about loaded plugins.
pub struct Plugins {
- /// Source code of exported macros.
- pub macros: Vec<ExportedMacros>,
+ /// Imported macros.
+ pub macros: Vec<ast::MacroDef>,
/// Registrars, as function pointers.
- pub registrars: Vec<PluginRegistrarFun>,
+ pub registrars: Vec<PluginRegistrar>,
}
struct PluginLoader<'a> {
sess: &'a Session,
- reader: PluginMetadataReader<'a>,
+ span_whitelist: HashSet<Span>,
+ reader: CrateReader<'a>,
plugins: Plugins,
}
fn new(sess: &'a Session) -> PluginLoader<'a> {
PluginLoader {
sess: sess,
- reader: PluginMetadataReader::new(sess),
+ reader: CrateReader::new(sess),
+ span_whitelist: HashSet::new(),
plugins: Plugins {
macros: vec!(),
registrars: vec!(),
pub fn load_plugins(sess: &Session, krate: &ast::Crate,
addl_plugins: Option<Plugins>) -> Plugins {
let mut loader = PluginLoader::new(sess);
+
+ // We need to error on `#[macro_use] extern crate` when it isn't at the
+ // crate root, because `$crate` won't work properly. Identify these by
+ // spans, because the crate map isn't set up yet.
+ for vi in krate.module.view_items.iter() {
+ loader.span_whitelist.insert(vi.span);
+ }
+
visit::walk_crate(&mut loader, krate);
let mut plugins = loader.plugins;
// note that macros aren't expanded yet, and therefore macros can't add plugins.
impl<'a, 'v> Visitor<'v> for PluginLoader<'a> {
fn visit_view_item(&mut self, vi: &ast::ViewItem) {
+ // We're only interested in `extern crate`.
match vi.node {
- ast::ViewItemExternCrate(name, _, _) => {
- let mut plugin_phase = false;
+ ast::ViewItemExternCrate(..) => (),
+ _ => return,
+ }
- for attr in vi.attrs.iter().filter(|a| a.check_name("phase")) {
- let phases = attr.meta_item_list().unwrap_or(&[]);
- if attr::contains_name(phases, "plugin") {
- plugin_phase = true;
+ // Parse the attributes relating to macro / plugin loading.
+ let mut plugin_attr = None;
+ let mut macro_selection = Some(HashSet::new()); // None => load all
+ let mut reexport = HashSet::new();
+ for attr in vi.attrs.iter() {
+ let mut used = true;
+ match attr.name().get() {
+ "phase" => {
+ self.sess.span_err(attr.span, "#[phase] is deprecated; use \
+ #[macro_use], #[plugin], and/or #[no_link]");
+ }
+ "plugin" => {
+ if plugin_attr.is_some() {
+ self.sess.span_err(attr.span, "#[plugin] specified multiple times");
+ }
+ plugin_attr = Some(attr.node.value.clone());
+ }
+ "macro_use" => {
+ let names = attr.meta_item_list();
+ if names.is_none() {
+ // no names => load all
+ macro_selection = None;
+ }
+ if let (Some(sel), Some(names)) = (macro_selection.as_mut(), names) {
+ for name in names.iter() {
+ if let ast::MetaWord(ref name) = name.node {
+ sel.insert(name.clone());
+ } else {
+ self.sess.span_err(name.span, "bad macro import");
+ }
+ }
}
- if attr::contains_name(phases, "syntax") {
- plugin_phase = true;
- self.sess.span_warn(attr.span,
- "phase(syntax) is a deprecated synonym for phase(plugin)");
+ }
+ "macro_reexport" => {
+ let names = match attr.meta_item_list() {
+ Some(names) => names,
+ None => {
+ self.sess.span_err(attr.span, "bad macro reexport");
+ continue;
+ }
+ };
+
+ for name in names.iter() {
+ if let ast::MetaWord(ref name) = name.node {
+ reexport.insert(name.clone());
+ } else {
+ self.sess.span_err(name.span, "bad macro reexport");
+ }
}
}
+ _ => used = false,
+ }
+ if used {
+ attr::mark_used(attr);
+ }
+ }
- if !plugin_phase { return; }
+ let mut macros = vec![];
+ let mut registrar = None;
- let PluginMetadata { macros, lib, registrar_symbol } =
- self.reader.read_plugin_metadata(vi);
+ let load_macros = match macro_selection.as_ref() {
+ Some(sel) => sel.len() != 0 || reexport.len() != 0,
+ None => true,
+ };
+ let load_registrar = plugin_attr.is_some();
- self.plugins.macros.push(ExportedMacros {
- crate_name: name,
- macros: macros,
- });
+ if load_macros && !self.span_whitelist.contains(&vi.span) {
+ self.sess.span_err(vi.span, "an `extern crate` loading macros must be at \
+ the crate root");
+ }
- match (lib, registrar_symbol) {
- (Some(lib), Some(symbol))
- => self.dylink_registrar(vi, lib, symbol),
- _ => (),
- }
+ if load_macros || load_registrar {
+ let pmd = self.reader.read_plugin_metadata(vi);
+ if load_macros {
+ macros = pmd.exported_macros();
+ }
+ if load_registrar {
+ registrar = pmd.plugin_registrar();
}
- _ => (),
+ }
+
+ for mut def in macros.into_iter() {
+ let name = token::get_ident(def.ident);
+ def.use_locally = match macro_selection.as_ref() {
+ None => true,
+ Some(sel) => sel.contains(&name),
+ };
+ def.export = reexport.contains(&name);
+ self.plugins.macros.push(def);
+ }
+
+ if let Some((lib, symbol)) = registrar {
+ let fun = self.dylink_registrar(vi, lib, symbol);
+ self.plugins.registrars.push(PluginRegistrar {
+ fun: fun,
+ args: plugin_attr.unwrap(),
+ });
}
}
+
fn visit_mac(&mut self, _: &ast::Mac) {
// bummer... can't see plugins inside macros.
// do nothing.
impl<'a> PluginLoader<'a> {
// Dynamically link a registrar function into the compiler process.
- fn dylink_registrar(&mut self, vi: &ast::ViewItem, path: Path, symbol: String) {
+ fn dylink_registrar(&mut self,
+ vi: &ast::ViewItem,
+ path: Path,
+ symbol: String) -> PluginRegistrarFun {
// Make sure the path contains a / or the linker will search for it.
let path = os::make_absolute(&path).unwrap();
Err(err) => self.sess.span_fatal(vi.span, err[])
};
- self.plugins.registrars.push(registrar);
-
// Intentionally leak the dynamic library. We can't ever unload it
// since the library can make things that will live arbitrarily long
// (e.g. an @-box cycle or a task).
mem::forget(lib);
+ registrar
}
}
}
//! To use a plugin while compiling another crate:
//!
//! ```rust
-//! #![feature(phase)]
+//! #![feature(plugin)]
//!
-//! #[phase(plugin)]
+//! #[plugin]
//! extern crate myplugin;
//! ```
//!
-//! If you also need the plugin crate available at runtime, use
-//! `phase(plugin, link)`.
+//! If you don't need the plugin crate available at runtime, use
+//! `#[no_link]` as well.
//!
//! See [the compiler plugin guide](../../guide-plugin.html)
//! for more examples.
//! Used by plugin crates to tell `rustc` about the plugins they provide.
use lint::{LintPassObject, LintId, Lint};
+use session::Session;
use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT};
-use syntax::ext::base::{IdentTT, LetSyntaxTT, Decorator, Modifier};
+use syntax::ext::base::{IdentTT, Decorator, Modifier, MacroRulesTT};
use syntax::ext::base::{MacroExpanderFn};
use syntax::codemap::Span;
use syntax::parse::token;
+use syntax::ptr::P;
use syntax::ast;
use std::collections::HashMap;
/// This struct has public fields and other methods for use by `rustc`
/// itself. They are not documented here, and plugin authors should
/// not use them.
-pub struct Registry {
+pub struct Registry<'a> {
+ /// Compiler session. Useful if you want to emit diagnostic messages
+ /// from the plugin registrar.
+ pub sess: &'a Session,
+
+ #[doc(hidden)]
+ pub args_hidden: Option<P<ast::MetaItem>>,
+
#[doc(hidden)]
pub krate_span: Span,
pub lint_groups: HashMap<&'static str, Vec<LintId>>,
}
-impl Registry {
+impl<'a> Registry<'a> {
#[doc(hidden)]
- pub fn new(krate: &ast::Crate) -> Registry {
+ pub fn new(sess: &'a Session, krate: &ast::Crate) -> Registry<'a> {
Registry {
+ sess: sess,
+ args_hidden: None,
krate_span: krate.span,
syntax_exts: vec!(),
lint_passes: vec!(),
}
}
+ /// Get the `#[plugin]` attribute used to load this plugin.
+ ///
+ /// This gives access to arguments passed via `#[plugin=...]` or
+ /// `#[plugin(...)]`.
+ pub fn args<'b>(&'b self) -> &'b P<ast::MetaItem> {
+ self.args_hidden.as_ref().expect("args not set")
+ }
+
/// Register a syntax extension of any kind.
///
/// This is the most general hook into `libsyntax`'s expansion behavior.
IdentTT(ext, _) => IdentTT(ext, Some(self.krate_span)),
Decorator(ext) => Decorator(ext),
Modifier(ext) => Modifier(ext),
- // there's probably a nicer way to signal this:
- LetSyntaxTT(_, _) => panic!("can't register a new LetSyntax!"),
+
+ MacroRulesTT => {
+ self.sess.err("plugin tried to register a new MacroRulesTT");
+ return;
+ }
}));
}
pub prints: Vec<PrintRequest>,
pub cg: CodegenOptions,
pub color: ColorConfig,
+ pub show_span: Option<String>,
pub externs: HashMap<String, Vec<String>>,
pub crate_name: Option<String>,
/// An optional name to use as the crate for std during std injection,
prints: Vec::new(),
cg: basic_codegen_options(),
color: Auto,
+ show_span: None,
externs: HashMap::new(),
crate_name: None,
alt_std_name: None,
BORROWCK_STATS,
NO_LANDING_PADS,
DEBUG_LLVM,
- SHOW_SPAN,
COUNT_TYPE_SIZES,
META_STATS,
GC,
("no-landing-pads", "omit landing pads for unwinding",
NO_LANDING_PADS),
("debug-llvm", "enable debug output from LLVM", DEBUG_LLVM),
- ("show-span", "show spans for compiler debugging", SHOW_SPAN),
("count-type-sizes", "count the sizes of aggregate types",
COUNT_TYPE_SIZES),
("meta-stats", "gather metadata statistics", META_STATS),
`flowgraph=<nodeid>` (graphviz formatted flowgraph for node), or
`everybody_loops` (all function bodies replaced with `loop {}`).",
"TYPE"),
+ opt::opt_u("", "show-span", "Show spans for compiler debugging", "expr|pat|ty"),
opt::flagopt("", "dep-info",
"Output dependency info to <filename> after compiling, \
in a format suitable for use by Makefiles", "FILENAME"),
prints: prints,
cg: cg,
color: color,
+ show_span: None,
externs: externs,
crate_name: crate_name,
alt_std_name: None,
pub fn no_landing_pads(&self) -> bool {
self.debugging_opt(config::NO_LANDING_PADS)
}
- pub fn show_span(&self) -> bool {
- self.debugging_opt(config::SHOW_SPAN)
+ pub fn unstable_options(&self) -> bool {
+ self.debugging_opt(config::UNSTABLE_OPTIONS)
}
pub fn print_enum_sizes(&self) -> bool {
self.debugging_opt(config::PRINT_ENUM_SIZES)
pub struct FnvState(u64);
impl Hasher<FnvState> for FnvHasher {
- fn hash<Sized? T: Hash<FnvState>>(&self, t: &T) -> u64 {
+ fn hash<T: ?Sized + Hash<FnvState>>(&self, t: &T) -> u64 {
let mut state = FnvState(0xcbf29ce484222325);
t.hash(&mut state);
let FnvState(ret) = state;
use syntax::owned_slice::OwnedSlice;
/// Produces a string suitable for debugging output.
-pub trait Repr<'tcx> for Sized? {
+pub trait Repr<'tcx> {
fn repr(&self, tcx: &ctxt<'tcx>) -> String;
}
}
}
-impl<'a, 'tcx, Sized? T:Repr<'tcx>> Repr<'tcx> for &'a T {
+impl<'a, 'tcx, T: ?Sized +Repr<'tcx>> Repr<'tcx> for &'a T {
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
Repr::repr(*self, tcx)
}
#![feature(unboxed_closures)]
#![feature(old_orphan_check)]
+#[cfg(stage0)]
#[phase(plugin, link)]
extern crate log;
+
+#[cfg(not(stage0))]
+#[macro_use]
+extern crate log;
+
extern crate syntax;
extern crate serialize;
// Sha-512 and Sha-256 use basically the same calculations which are implemented
// by these macros. Inlining the calculations seems to result in better generated code.
- macro_rules! schedule_round( ($t:expr) => (
+ macro_rules! schedule_round { ($t:expr) => (
w[$t] = sigma1(w[$t - 2]) + w[$t - 7] + sigma0(w[$t - 15]) + w[$t - 16];
)
- );
+ }
- macro_rules! sha2_round(
+ macro_rules! sha2_round {
($A:ident, $B:ident, $C:ident, $D:ident,
$E:ident, $F:ident, $G:ident, $H:ident, $K:ident, $t:expr) => (
{
$H += sum0($A) + maj($A, $B, $C);
}
)
- );
+ }
read_u32v_be(w.slice_mut(0, 16), data);
impl<'a, 'v> Visitor<'v> for StrictVersionHashVisitor<'a> {
- fn visit_mac(&mut self, macro: &Mac) {
+ fn visit_mac(&mut self, mac: &Mac) {
// macro invocations, namely macro_rules definitions,
// *can* appear as items, even in the expanded crate AST.
- if macro_name(macro).get() == "macro_rules" {
+ if macro_name(mac).get() == "macro_rules" {
// Pretty-printing definition to a string strips out
// surface artifacts (currently), such as the span
// information, yielding a content-based hash.
// trees might be faster. Implementing this is far
// easier in short term.
let macro_defn_as_string = pprust::to_string(|pp_state| {
- pp_state.print_mac(macro, token::Paren)
+ pp_state.print_mac(mac, token::Paren)
});
macro_defn_as_string.hash(self.st);
} else {
// invocation at this stage except `macro_rules!`.
panic!("reached macro somehow: {}",
pprust::to_string(|pp_state| {
- pp_state.print_mac(macro, token::Paren)
+ pp_state.print_mac(mac, token::Paren)
}));
}
- visit::walk_mac(self, macro);
+ visit::walk_mac(self, mac);
- fn macro_name(macro: &Mac) -> token::InternedString {
- match ¯o.node {
+ fn macro_name(mac: &Mac) -> token::InternedString {
+ match &mac.node {
&MacInvocTT(ref path, ref _tts, ref _stx_ctxt) => {
let s = path.segments[];
assert_eq!(s.len(), 1);
options: Default::default(),
};
- macro_rules! key (
+ macro_rules! key {
($key_name:ident) => ( {
let name = (stringify!($key_name)).replace("_", "-");
obj.find(name[]).map(|o| o.as_string()
)
);
} );
- );
+ }
key!(cpu);
key!(linker);
}
// this would use a match if stringify! were allowed in pattern position
- macro_rules! load_specific (
+ macro_rules! load_specific {
( $($name:ident),+ ) => (
{
let target = target.replace("-", "_");
}
}
)
- );
+ }
load_specific!(
x86_64_unknown_linux_gnu,
use syntax::visit::{Visitor, FnKind};
use syntax::ast::{FnDecl, Block, NodeId};
-macro_rules! if_ok {
- ($inp: expr) => (
- match $inp {
- Ok(v) => { v }
- Err(e) => { return Err(e); }
- }
- )
-}
-
pub mod doc;
pub mod check_loans;
#![feature(old_orphan_check)]
#![allow(non_camel_case_types)]
-#[phase(plugin, link)] extern crate log;
-#[phase(plugin, link)] extern crate syntax;
+#[cfg(stage0)]
+#[phase(plugin, link)]
+extern crate log;
+
+#[cfg(not(stage0))]
+#[macro_use]
+extern crate log;
+
+#[cfg(stage0)]
+#[phase(plugin, link)]
+extern crate syntax;
+
+#[cfg(not(stage0))]
+#[macro_use]
+extern crate syntax;
// for "clarity", rename the graphviz crate to dot; graphviz within `borrowck`
// refers to the borrowck-specific graphviz adapter traits.
use rustc::session::config::{self, Input, OutputFilenames};
use rustc::session::search_paths::PathKind;
use rustc::lint;
-use rustc::metadata::creader;
+use rustc::metadata::creader::CrateReader;
use rustc::middle::{stability, ty, reachable};
use rustc::middle::dependency_format;
use rustc::middle;
println!("{}", json::as_json(&krate));
}
- if sess.show_span() {
- syntax::show_span::run(sess.diagnostic(), &krate);
+ if let Some(ref s) = sess.opts.show_span {
+ syntax::show_span::run(sess.diagnostic(), s.as_slice(), &krate);
}
krate
// strip before expansion to allow macros to depend on
// configuration variables e.g/ in
//
- // #[macro_escape] #[cfg(foo)]
+ // #[macro_use] #[cfg(foo)]
// mod bar { macro_rules! baz!(() => {{}}) }
//
// baz! should not use this definition unless foo is enabled.
= time(time_passes, "plugin loading", (), |_|
plugin::load::load_plugins(sess, &krate, addl_plugins.take().unwrap()));
- let mut registry = Registry::new(&krate);
+ let mut registry = Registry::new(sess, &krate);
- time(time_passes, "plugin registration", (), |_| {
+ time(time_passes, "plugin registration", registrars, |registrars| {
if sess.features.borrow().rustc_diagnostic_macros {
registry.register_macro("__diagnostic_used",
diagnostics::plugin::expand_diagnostic_used);
diagnostics::plugin::expand_build_diagnostic_array);
}
- for ®istrar in registrars.iter() {
- registrar(&mut registry);
+ for registrar in registrars.into_iter() {
+ registry.args_hidden = Some(registrar.args);
+ (registrar.fun)(&mut registry);
}
});
}
let cfg = syntax::ext::expand::ExpansionConfig {
crate_name: crate_name.to_string(),
- deriving_hash_type_parameter: sess.features.borrow().default_type_params,
enable_quotes: sess.features.borrow().quote,
recursion_limit: sess.recursion_limit.get(),
};
let krate = ast_map.krate();
time(time_passes, "external crate/lib resolution", (), |_|
- creader::read_crates(&sess, krate));
+ CrateReader::new(&sess).read_crates(krate));
let lang_items = time(time_passes, "language item collection", (), |_|
middle::lang_items::collect_language_items(krate, &sess));
debug!("invoked with --parse-only, returning early from compile_input");
return true;
}
- if sess.show_span() {
+ if sess.opts.show_span.is_some() {
return true;
}
return sess.opts.debugging_opts & config::AST_JSON_NOEXPAND != 0;
extern crate rustc_resolve;
extern crate rustc_trans;
extern crate rustc_typeck;
-#[phase(plugin, link)] extern crate log;
-#[phase(plugin, link)] extern crate syntax;
extern crate serialize;
extern crate "rustc_llvm" as llvm;
+#[cfg(stage0)]
+#[phase(plugin, link)]
+extern crate log;
+
+#[cfg(not(stage0))]
+#[macro_use]
+extern crate log;
+
+#[cfg(stage0)]
+#[phase(plugin, link)]
+extern crate syntax;
+
+#[cfg(not(stage0))]
+#[macro_use]
+extern crate syntax;
+
pub use syntax::diagnostic;
use rustc_trans::back::link;
_ => early_error("multiple input filenames provided")
};
- let sess = build_session(sopts, input_file_path, descriptions);
+ let mut sess = build_session(sopts, input_file_path, descriptions);
let cfg = config::build_configuration(&sess);
if print_crate_info(&sess, Some(&input), &odir, &ofile) {
return
pretty::parse_pretty(&sess, a.as_slice(), false)
});
let pretty = if pretty.is_none() &&
- sess.debugging_opt(config::UNSTABLE_OPTIONS) {
+ sess.unstable_options() {
matches.opt_str("xpretty").map(|a| {
// extended with unstable pretty-print variants
pretty::parse_pretty(&sess, a.as_slice(), true)
None => {/* continue */ }
}
+ if sess.unstable_options() {
+ sess.opts.show_span = matches.opt_str("show-span");
+ }
+
let r = matches.opt_strs("Z");
if r.contains(&("ls".to_string())) {
match input {
// in general the pretty printer processes unexpanded code, so
// we override the default `fold_mac` method which panics.
- fn fold_mac(&mut self, _macro: ast::Mac) -> ast::Mac {
- fold::noop_fold_mac(_macro, self)
+ fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
+ fold::noop_fold_mac(mac, self)
}
}
use libc;
use ArchiveRef;
-use std::c_str::ToCStr;
+use std::ffi::CString;
use std::mem;
use std::raw;
/// raised.
pub fn open(dst: &Path) -> Option<ArchiveRO> {
unsafe {
- let ar = dst.with_c_str(|dst| {
- ::LLVMRustOpenArchive(dst)
- });
+ let s = CString::from_slice(dst.as_vec());
+ let ar = ::LLVMRustOpenArchive(s.as_ptr());
if ar.is_null() {
None
} else {
pub fn read<'a>(&'a self, file: &str) -> Option<&'a [u8]> {
unsafe {
let mut size = 0 as libc::size_t;
- let ptr = file.with_c_str(|file| {
- ::LLVMRustArchiveReadSection(self.ptr, file, &mut size)
- });
+ let file = CString::from_slice(file.as_bytes());
+ let ptr = ::LLVMRustArchiveReadSection(self.ptr, file.as_ptr(),
+ &mut size);
if ptr.is_null() {
None
} else {
#![feature(globs)]
#![feature(link_args)]
#![feature(unboxed_closures)]
+#![feature(old_orphan_check)]
extern crate libc;
pub use self::DiagnosticSeverity::*;
pub use self::Linkage::*;
-use std::c_str::ToCStr;
+use std::ffi::CString;
use std::cell::RefCell;
use std::{raw, mem};
use libc::{c_uint, c_ushort, uint64_t, c_int, size_t, c_char};
}
pub fn mk_target_data(string_rep: &str) -> TargetData {
+ let string_rep = CString::from_slice(string_rep.as_bytes());
TargetData {
- lltd: string_rep.with_c_str(|buf| {
- unsafe { LLVMCreateTargetData(buf) }
- })
+ lltd: unsafe { LLVMCreateTargetData(string_rep.as_ptr()) }
}
}
#![feature(globs, phase, slicing_syntax)]
#![feature(rustc_diagnostic_macros)]
#![feature(associated_types)]
+#![feature(old_orphan_check)]
-#[phase(plugin, link)] extern crate log;
-#[phase(plugin, link)] extern crate syntax;
+#[cfg(stage0)]
+#[phase(plugin, link)]
+extern crate log;
+
+#[cfg(not(stage0))]
+#[macro_use]
+extern crate log;
+
+#[cfg(stage0)]
+#[phase(plugin, link)]
+extern crate syntax;
+
+#[cfg(not(stage0))]
+#[macro_use]
+extern crate syntax;
extern crate rustc;
use libc;
use flate;
-use std::c_str::ToCStr;
+use std::ffi::CString;
use std::iter;
use std::mem;
use std::num::Int;
}
// Internalize everything but the reachable symbols of the current module
- let cstrs: Vec<::std::c_str::CString> =
- reachable.iter().map(|s| s.to_c_str()).collect();
- let arr: Vec<*const libc::c_char> = cstrs.iter().map(|c| c.as_ptr()).collect();
+ let cstrs: Vec<CString> = reachable.iter().map(|s| {
+ CString::from_slice(s.as_bytes())
+ }).collect();
+ let arr: Vec<*const i8> = cstrs.iter().map(|c| c.as_ptr()).collect();
let ptr = arr.as_ptr();
unsafe {
llvm::LLVMRustRunRestrictionPass(llmod,
unsafe {
let pm = llvm::LLVMCreatePassManager();
llvm::LLVMRustAddAnalysisPasses(tm, pm, llmod);
- "verify".with_c_str(|s| llvm::LLVMRustAddPass(pm, s));
+ llvm::LLVMRustAddPass(pm, "verify\0".as_ptr() as *const _);
let builder = llvm::LLVMPassManagerBuilderCreate();
llvm::LLVMPassManagerBuilderPopulateLTOPassManager(builder, pm,
/* RunInliner = */ True);
llvm::LLVMPassManagerBuilderDispose(builder);
- "verify".with_c_str(|s| llvm::LLVMRustAddPass(pm, s));
+ llvm::LLVMRustAddPass(pm, "verify\0".as_ptr() as *const _);
time(sess.time_passes(), "LTO passes", (), |()|
llvm::LLVMRunPassManager(pm, llmod));
use syntax::diagnostic;
use syntax::diagnostic::{Emitter, Handler, Level, mk_handler};
-use std::c_str::{ToCStr, CString};
+use std::ffi::{self, CString};
use std::io::Command;
use std::io::fs;
use std::iter::Unfold;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::channel;
use std::thread;
-use libc::{c_uint, c_int, c_void};
+use libc::{self, c_uint, c_int, c_void};
#[derive(Clone, Copy, PartialEq, PartialOrd, Ord, Eq)]
pub enum OutputType {
if cstr == ptr::null() {
handler.fatal(msg[]);
} else {
- let err = CString::new(cstr, true);
- let err = String::from_utf8_lossy(err.as_bytes());
+ let err = ffi::c_str_to_bytes(&cstr);
+ let err = String::from_utf8_lossy(err.as_slice()).to_string();
+ libc::free(cstr as *mut _);
handler.fatal(format!("{}: {}",
msg[],
err[])[]);
output: &Path,
file_type: llvm::FileType) {
unsafe {
- output.with_c_str(|output| {
- let result = llvm::LLVMRustWriteOutputFile(
- target, pm, m, output, file_type);
- if !result {
- llvm_err(handler, "could not write output".to_string());
- }
- })
+ let output = CString::from_slice(output.as_vec());
+ let result = llvm::LLVMRustWriteOutputFile(
+ target, pm, m, output.as_ptr(), file_type);
+ if !result {
+ llvm_err(handler, "could not write output".to_string());
+ }
}
}
let triple = sess.target.target.llvm_target[];
let tm = unsafe {
- triple.with_c_str(|t| {
- let cpu = match sess.opts.cg.target_cpu {
- Some(ref s) => s[],
- None => sess.target.target.options.cpu[]
- };
- cpu.with_c_str(|cpu| {
- target_feature(sess).with_c_str(|features| {
- llvm::LLVMRustCreateTargetMachine(
- t, cpu, features,
- code_model,
- reloc_model,
- opt_level,
- true /* EnableSegstk */,
- use_softfp,
- no_fp_elim,
- !any_library && reloc_model == llvm::RelocPIC,
- ffunction_sections,
- fdata_sections,
- )
- })
- })
- })
+ let triple = CString::from_slice(triple.as_bytes());
+ let cpu = match sess.opts.cg.target_cpu {
+ Some(ref s) => s.as_slice(),
+ None => sess.target.target.options.cpu.as_slice()
+ };
+ let cpu = CString::from_slice(cpu.as_bytes());
+ let features = CString::from_slice(target_feature(sess).as_bytes());
+ llvm::LLVMRustCreateTargetMachine(
+ triple.as_ptr(), cpu.as_ptr(), features.as_ptr(),
+ code_model,
+ reloc_model,
+ opt_level,
+ true /* EnableSegstk */,
+ use_softfp,
+ no_fp_elim,
+ !any_library && reloc_model == llvm::RelocPIC,
+ ffunction_sections,
+ fdata_sections,
+ )
};
if tm.is_null() {
match llvm::diagnostic::Diagnostic::unpack(info) {
llvm::diagnostic::Optimization(opt) => {
- let pass_name = CString::new(opt.pass_name, false);
- let pass_name = pass_name.as_str().expect("got a non-UTF8 pass name from LLVM");
+ let pass_name = str::from_utf8(ffi::c_str_to_bytes(&opt.pass_name))
+ .ok()
+ .expect("got a non-UTF8 pass name from LLVM");
let enabled = match cgcx.remark {
AllPasses => true,
SomePasses(ref v) => v.iter().any(|s| *s == pass_name),
if config.emit_no_opt_bc {
let ext = format!("{}.no-opt.bc", name_extra);
- output_names.with_extension(ext[]).with_c_str(|buf| {
- llvm::LLVMWriteBitcodeToFile(llmod, buf);
- })
+ let out = output_names.with_extension(ext.as_slice());
+ let out = CString::from_slice(out.as_vec());
+ llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
}
match config.opt_level {
// If we're verifying or linting, add them to the function pass
// manager.
let addpass = |&: pass: &str| {
- pass.with_c_str(|s| llvm::LLVMRustAddPass(fpm, s))
+ let pass = CString::from_slice(pass.as_bytes());
+ llvm::LLVMRustAddPass(fpm, pass.as_ptr())
};
if !config.no_verify { assert!(addpass("verify")); }
}
for pass in config.passes.iter() {
- pass.with_c_str(|s| {
- if !llvm::LLVMRustAddPass(mpm, s) {
- cgcx.handler.warn(format!("unknown pass {}, ignoring",
- *pass)[]);
- }
- })
+ let pass = CString::from_slice(pass.as_bytes());
+ if !llvm::LLVMRustAddPass(mpm, pass.as_ptr()) {
+ cgcx.handler.warn(format!("unknown pass {}, ignoring",
+ pass).as_slice());
+ }
}
// Finally, run the actual optimization passes
if config.emit_lto_bc {
let name = format!("{}.lto.bc", name_extra);
- output_names.with_extension(name[]).with_c_str(|buf| {
- llvm::LLVMWriteBitcodeToFile(llmod, buf);
- })
+ let out = output_names.with_extension(name.as_slice());
+ let out = CString::from_slice(out.as_vec());
+ llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
}
},
_ => {},
if config.emit_bc {
let ext = format!("{}.bc", name_extra);
- output_names.with_extension(ext[]).with_c_str(|buf| {
- llvm::LLVMWriteBitcodeToFile(llmod, buf);
- })
+ let out = output_names.with_extension(ext.as_slice());
+ let out = CString::from_slice(out.as_vec());
+ llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
}
time(config.time_passes, "codegen passes", (), |()| {
if config.emit_ir {
let ext = format!("{}.ll", name_extra);
- output_names.with_extension(ext[]).with_c_str(|output| {
- with_codegen(tm, llmod, config.no_builtins, |cpm| {
- llvm::LLVMRustPrintModule(cpm, llmod, output);
- })
+ let out = output_names.with_extension(ext.as_slice());
+ let out = CString::from_slice(out.as_vec());
+ with_codegen(tm, llmod, config.no_builtins, |cpm| {
+ llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr());
})
}
let mut llvm_args = Vec::new();
{
let mut add = |&mut : arg: &str| {
- let s = arg.to_c_str();
+ let s = CString::from_slice(arg.as_bytes());
llvm_args.push(s.as_ptr());
llvm_c_strs.push(s);
};
match opt {
llvm::CodeGenLevelDefault | llvm::CodeGenLevelAggressive => {
- "mergefunc".with_c_str(|s| llvm::LLVMRustAddPass(mpm, s));
+ llvm::LLVMRustAddPass(mpm, "mergefunc\0".as_ptr() as *const _);
}
_ => {}
};
extern crate libc;
extern crate rustc;
extern crate rustc_back;
-#[phase(plugin, link)] extern crate log;
-#[phase(plugin, link)] extern crate syntax;
extern crate serialize;
extern crate "rustc_llvm" as llvm;
+#[cfg(stage0)]
+#[phase(plugin, link)]
+extern crate log;
+
+#[cfg(not(stage0))]
+#[macro_use]
+extern crate log;
+
+#[cfg(stage0)]
+#[phase(plugin, link)]
+extern crate syntax;
+
+#[cfg(not(stage0))]
+#[macro_use]
+extern crate syntax;
+
pub use rustc::session;
pub use rustc::metadata;
pub use rustc::middle;
}
fn any_region_pat(m: &[Match], col: uint) -> bool {
- any_pat!(m, col, ast::PatRegion(_))
+ any_pat!(m, col, ast::PatRegion(..))
}
fn any_irrefutable_adt_pat(tcx: &ty::ctxt, m: &[Match], col: uint) -> bool {
let llbox = Load(bcx, val);
bcx = bind_irrefutable_pat(bcx, &**inner, llbox, cleanup_scope);
}
- ast::PatRegion(ref inner) => {
+ ast::PatRegion(ref inner, _) => {
let loaded_val = Load(bcx, val);
bcx = bind_irrefutable_pat(bcx, &**inner, loaded_val, cleanup_scope);
}
use trans::type_of;
use trans::type_::Type;
-use std::c_str::ToCStr;
-use std::string::String;
use syntax::ast;
+use std::ffi::CString;
use libc::{c_uint, c_char};
// Take an inline assembly expression and splat it out via LLVM
ast::AsmIntel => llvm::AD_Intel
};
- let r = ia.asm.get().with_c_str(|a| {
- constraints.with_c_str(|c| {
- InlineAsmCall(bcx,
- a,
- c,
- inputs[],
+ let asm = CString::from_slice(ia.asm.get().as_bytes());
+ let constraints = CString::from_slice(constraints.as_bytes());
+ let r = InlineAsmCall(bcx,
+ asm.as_ptr(),
+ constraints.as_ptr(),
+ inputs.as_slice(),
output_type,
ia.volatile,
ia.alignstack,
- dialect)
- })
- });
+ dialect);
// Again, based on how many outputs we have
if num_outputs == 1 {
use arena::TypedArena;
use libc::{c_uint, uint64_t};
-use std::c_str::ToCStr;
+use std::ffi::{self, CString};
use std::cell::{Cell, RefCell};
use std::collections::HashSet;
use std::mem;
use std::rc::Rc;
+use std::str;
use std::{i8, i16, i32, i64};
use syntax::abi::{Rust, RustCall, RustIntrinsic, Abi};
use syntax::ast_util::local_def;
pub fn decl_fn(ccx: &CrateContext, name: &str, cc: llvm::CallConv,
ty: Type, output: ty::FnOutput) -> ValueRef {
- let llfn: ValueRef = name.with_c_str(|buf| {
- unsafe {
- llvm::LLVMGetOrInsertFunction(ccx.llmod(), buf, ty.to_ref())
- }
- });
+ let buf = CString::from_slice(name.as_bytes());
+ let llfn: ValueRef = unsafe {
+ llvm::LLVMGetOrInsertFunction(ccx.llmod(), buf.as_ptr(), ty.to_ref())
+ };
// diverging functions may unwind, but can never return normally
if output == ty::FnDiverging {
None => ()
}
unsafe {
- let c = name.with_c_str(|buf| {
- llvm::LLVMAddGlobal(ccx.llmod(), ty.to_ref(), buf)
- });
+ let buf = CString::from_slice(name.as_bytes());
+ let c = llvm::LLVMAddGlobal(ccx.llmod(), ty.to_ref(), buf.as_ptr());
// Thread-local statics in some other crate need to *always* be linked
// against in a thread-local fashion, so we need to be sure to apply the
// thread-local attribute locally if it was present remotely. If we
}
pub fn set_split_stack(f: ValueRef) {
- "split-stack".with_c_str(|buf| {
- unsafe { llvm::LLVMAddFunctionAttrString(f, llvm::FunctionIndex as c_uint, buf); }
- })
+ unsafe {
+ llvm::LLVMAddFunctionAttrString(f, llvm::FunctionIndex as c_uint,
+ "split-stack\0".as_ptr() as *const _);
+ }
}
pub fn unset_split_stack(f: ValueRef) {
- "split-stack".with_c_str(|buf| {
- unsafe { llvm::LLVMRemoveFunctionAttrString(f, llvm::FunctionIndex as c_uint, buf); }
- })
+ unsafe {
+ llvm::LLVMRemoveFunctionAttrString(f, llvm::FunctionIndex as c_uint,
+ "split-stack\0".as_ptr() as *const _);
+ }
}
// Double-check that we never ask LLVM to declare the same symbol twice. It
// Structural comparison: a rather involved form of glue.
pub fn maybe_name_value(cx: &CrateContext, v: ValueRef, s: &str) {
if cx.sess().opts.cg.save_temps {
- s.with_c_str(|buf| {
- unsafe {
- llvm::LLVMSetValueName(v, buf)
- }
- })
+ let buf = CString::from_slice(s.as_bytes());
+ unsafe { llvm::LLVMSetValueName(v, buf.as_ptr()) }
}
}
unsafe { llvm::LLVMRustSetDLLExportStorageClass(llfn) }
}
- let llbb = "top".with_c_str(|buf| {
- unsafe {
- llvm::LLVMAppendBasicBlockInContext(ccx.llcx(), llfn, buf)
- }
- });
+ let llbb = unsafe {
+ llvm::LLVMAppendBasicBlockInContext(ccx.llcx(), llfn,
+ "top\0".as_ptr() as *const _)
+ };
let bld = ccx.raw_builder();
unsafe {
llvm::LLVMPositionBuilderAtEnd(bld, llbb);
};
let args = {
- let opaque_rust_main = "rust_main".with_c_str(|buf| {
- llvm::LLVMBuildPointerCast(bld, rust_main, Type::i8p(ccx).to_ref(), buf)
- });
+ let opaque_rust_main = llvm::LLVMBuildPointerCast(bld,
+ rust_main, Type::i8p(ccx).to_ref(),
+ "rust_main\0".as_ptr() as *const _);
vec!(
opaque_rust_main,
format!("Illegal null byte in export_name \
value: `{}`", sym)[]);
}
- let g = sym.with_c_str(|buf| {
- llvm::LLVMAddGlobal(ccx.llmod(), llty, buf)
- });
+ let buf = CString::from_slice(sym.as_bytes());
+ let g = llvm::LLVMAddGlobal(ccx.llmod(), llty,
+ buf.as_ptr());
if attr::contains_name(i.attrs[],
"thread_local") {
sect.get())[]);
}
unsafe {
- sect.get().with_c_str(|buf| {
- llvm::LLVMSetSection(v, buf);
- })
+ let buf = CString::from_slice(sect.get().as_bytes());
+ llvm::LLVMSetSection(v, buf.as_ptr());
}
},
None => ()
let name = format!("rust_metadata_{}_{}",
cx.link_meta().crate_name,
cx.link_meta().crate_hash);
- let llglobal = name.with_c_str(|buf| {
- unsafe {
- llvm::LLVMAddGlobal(cx.metadata_llmod(), val_ty(llconst).to_ref(), buf)
- }
- });
+ let buf = CString::from_vec(name.into_bytes());
+ let llglobal = unsafe {
+ llvm::LLVMAddGlobal(cx.metadata_llmod(), val_ty(llconst).to_ref(),
+ buf.as_ptr())
+ };
unsafe {
llvm::LLVMSetInitializer(llglobal, llconst);
let name = loader::meta_section_name(cx.sess().target.target.options.is_like_osx);
- name.with_c_str(|buf| {
- llvm::LLVMSetSection(llglobal, buf)
- });
+ let name = CString::from_slice(name.as_bytes());
+ llvm::LLVMSetSection(llglobal, name.as_ptr())
}
return metadata;
}
/// Find any symbols that are defined in one compilation unit, but not declared
/// in any other compilation unit. Give these symbols internal linkage.
fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<String>) {
- use std::c_str::CString;
-
unsafe {
let mut declared = HashSet::new();
continue
}
- let name = CString::new(llvm::LLVMGetValueName(val), false);
+ let name = ffi::c_str_to_bytes(&llvm::LLVMGetValueName(val))
+ .to_vec();
declared.insert(name);
}
}
continue
}
- let name = CString::new(llvm::LLVMGetValueName(val), false);
+ let name = ffi::c_str_to_bytes(&llvm::LLVMGetValueName(val))
+ .to_vec();
if !declared.contains(&name) &&
- !reachable.contains(name.as_str().unwrap()) {
+ !reachable.contains(str::from_utf8(name.as_slice()).unwrap()) {
llvm::SetLinkage(val, llvm::InternalLinkage);
}
}
use trans::type_::Type;
use util::nodemap::FnvHashMap;
use libc::{c_uint, c_char};
-use std::c_str::ToCStr;
+
+use std::ffi::CString;
use syntax::codemap::Span;
pub struct Builder<'a, 'tcx: 'a> {
if name.is_empty() {
llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), noname())
} else {
- name.with_c_str(|c| {
- llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), c)
- })
+ let name = CString::from_slice(name.as_bytes());
+ llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(),
+ name.as_ptr())
}
}
}
let comment_text = format!("{} {}", "#",
sanitized.replace("\n", "\n\t# "));
self.count_insn("inlineasm");
- let asm = comment_text.with_c_str(|c| {
- unsafe {
- llvm::LLVMConstInlineAsm(Type::func(&[], &Type::void(self.ccx)).to_ref(),
- c, noname(), False, False)
- }
- });
+ let comment_text = CString::from_vec(comment_text.into_bytes());
+ let asm = unsafe {
+ llvm::LLVMConstInlineAsm(Type::func(&[], &Type::void(self.ccx)).to_ref(),
+ comment_text.as_ptr(), noname(), False,
+ False)
+ };
self.call(asm, &[], None);
}
}
let bb: BasicBlockRef = llvm::LLVMGetInsertBlock(self.llbuilder);
let fn_: ValueRef = llvm::LLVMGetBasicBlockParent(bb);
let m: ModuleRef = llvm::LLVMGetGlobalParent(fn_);
- let t: ValueRef = "llvm.trap".with_c_str(|buf| {
- llvm::LLVMGetNamedFunction(m, buf)
- });
+ let p = "llvm.trap\0".as_ptr();
+ let t: ValueRef = llvm::LLVMGetNamedFunction(m, p as *const _);
assert!((t as int != 0));
let args: &[ValueRef] = &[];
self.count_insn("trap");
}
}
-trait ClassList for Sized? {
+trait ClassList {
fn is_pass_byval(&self) -> bool;
fn is_ret_bysret(&self) -> bool;
}
use arena::TypedArena;
use libc::{c_uint, c_char};
-use std::c_str::ToCStr;
+use std::ffi::CString;
use std::cell::{Cell, RefCell};
use std::vec::Vec;
use syntax::ast::Ident;
if self.llreturn.get().is_none() {
self.llreturn.set(Some(unsafe {
- "return".with_c_str(|buf| {
- llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(), self.llfn, buf)
- })
+ llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(), self.llfn,
+ "return\0".as_ptr() as *const _)
}))
}
opt_node_id: Option<ast::NodeId>)
-> Block<'a, 'tcx> {
unsafe {
- let llbb = name.with_c_str(|buf| {
- llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(),
- self.llfn,
- buf)
- });
+ let name = CString::from_slice(name.as_bytes());
+ let llbb = llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(),
+ self.llfn,
+ name.as_ptr());
BlockS::new(llbb, is_lpad, opt_node_id, self)
}
}
pub fn C_floating(s: &str, t: Type) -> ValueRef {
unsafe {
- s.with_c_str(|buf| llvm::LLVMConstRealOfString(t.to_ref(), buf))
+ let s = CString::from_slice(s.as_bytes());
+ llvm::LLVMConstRealOfString(t.to_ref(), s.as_ptr())
}
}
!null_terminated as Bool);
let gsym = token::gensym("str");
- let g = format!("str{}", gsym.uint()).with_c_str(|buf| {
- llvm::LLVMAddGlobal(cx.llmod(), val_ty(sc).to_ref(), buf)
- });
+ let buf = CString::from_vec(format!("str{}", gsym.uint()).into_bytes());
+ let g = llvm::LLVMAddGlobal(cx.llmod(), val_ty(sc).to_ref(), buf.as_ptr());
llvm::LLVMSetInitializer(g, sc);
llvm::LLVMSetGlobalConstant(g, True);
llvm::SetLinkage(g, llvm::InternalLinkage);
let lldata = C_bytes(cx, data);
let gsym = token::gensym("binary");
- let g = format!("binary{}", gsym.uint()).with_c_str(|buf| {
- llvm::LLVMAddGlobal(cx.llmod(), val_ty(lldata).to_ref(), buf)
- });
+ let name = format!("binary{}", gsym.uint());
+ let name = CString::from_vec(name.into_bytes());
+ let g = llvm::LLVMAddGlobal(cx.llmod(), val_ty(lldata).to_ref(),
+ name.as_ptr());
llvm::LLVMSetInitializer(g, lldata);
llvm::LLVMSetGlobalConstant(g, True);
llvm::SetLinkage(g, llvm::InternalLinkage);
use middle::ty::{self, Ty};
use util::ppaux::{Repr, ty_to_string};
-use std::c_str::ToCStr;
use std::iter::repeat;
use libc::c_uint;
use syntax::{ast, ast_util};
pub fn const_addr_of(cx: &CrateContext, cv: ValueRef, mutbl: ast::Mutability) -> ValueRef {
unsafe {
- let gv = "const".with_c_str(|name| {
- llvm::LLVMAddGlobal(cx.llmod(), val_ty(cv).to_ref(), name)
- });
+ let gv = llvm::LLVMAddGlobal(cx.llmod(), val_ty(cv).to_ref(),
+ "const\0".as_ptr() as *const _);
llvm::LLVMSetInitializer(gv, cv);
llvm::LLVMSetGlobalConstant(gv,
if mutbl == ast::MutImmutable {True} else {False});
use util::sha2::Sha256;
use util::nodemap::{NodeMap, NodeSet, DefIdMap, FnvHashMap, FnvHashSet};
+use std::ffi::CString;
use std::cell::{Cell, RefCell};
-use std::c_str::ToCStr;
use std::ptr;
use std::rc::Rc;
use syntax::ast;
unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {
let llcx = llvm::LLVMContextCreate();
- let llmod = mod_name.with_c_str(|buf| {
- llvm::LLVMModuleCreateWithNameInContext(buf, llcx)
- });
- sess.target
- .target
- .data_layout
- .with_c_str(|buf| {
- llvm::LLVMSetDataLayout(llmod, buf);
- });
- sess.target
- .target
- .llvm_target
- .with_c_str(|buf| {
- llvm::LLVMRustSetNormalizedTarget(llmod, buf);
- });
+ let mod_name = CString::from_slice(mod_name.as_bytes());
+ let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
+
+ let data_layout = sess.target.target.data_layout.as_slice();
+ let data_layout = CString::from_slice(data_layout.as_bytes());
+ llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr());
+
+ let llvm_target = sess.target.target.llvm_target.as_slice();
+ let llvm_target = CString::from_slice(llvm_target.as_bytes());
+ llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr());
(llcx, llmod)
}
}
fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef> {
- macro_rules! ifn (
+ macro_rules! ifn {
($name:expr fn() -> $ret:expr) => (
if *key == $name {
let f = base::decl_cdecl_fn(
return Some(f);
}
)
- );
- macro_rules! mk_struct (
+ }
+ macro_rules! mk_struct {
($($field_ty:expr),*) => (Type::struct_(ccx, &[$($field_ty),*], false))
- );
+ }
let i8p = Type::i8p(ccx);
let void = Type::void(ccx);
// Some intrinsics were introduced in later versions of LLVM, but they have
// fallbacks in libc or libm and such. Currently, all of these intrinsics
// were introduced in LLVM 3.4, so we case on that.
- macro_rules! compatible_ifn (
+ macro_rules! compatible_ifn {
($name:expr, $cname:ident ($($arg:expr),*) -> $ret:expr) => (
if unsafe { llvm::LLVMVersionMinor() >= 4 } {
// The `if key == $name` is already in ifn!
return Some(f);
}
)
- );
+ }
compatible_ifn!("llvm.copysign.f32", copysignf(t_f32, t_f32) -> t_f32);
compatible_ifn!("llvm.copysign.f64", copysign(t_f64, t_f64) -> t_f64);
use util::ppaux;
use libc::c_uint;
-use std::c_str::{CString, ToCStr};
+use std::ffi::CString;
use std::cell::{Cell, RefCell};
use std::ptr;
use std::rc::{Rc, Weak};
// for OS X to understand. For more info see #11352
// This can be overridden using --llvm-opts -dwarf-version,N.
if cx.sess().target.target.options.is_like_osx {
- "Dwarf Version".with_c_str(
- |s| llvm::LLVMRustAddModuleFlag(cx.llmod(), s, 2));
+ llvm::LLVMRustAddModuleFlag(cx.llmod(),
+ "Dwarf Version\0".as_ptr() as *const _,
+ 2)
}
// Prevent bitcode readers from deleting the debug info.
- "Debug Info Version".with_c_str(
- |s| llvm::LLVMRustAddModuleFlag(cx.llmod(), s,
- llvm::LLVMRustDebugMetadataVersion));
+ let ptr = "Debug Info Version\0".as_ptr();
+ llvm::LLVMRustAddModuleFlag(cx.llmod(), ptr as *const _,
+ llvm::LLVMRustDebugMetadataVersion);
};
}
namespace_node.mangled_name_of_contained_item(var_name[]);
let var_scope = namespace_node.scope;
- var_name.with_c_str(|var_name| {
- linkage_name.with_c_str(|linkage_name| {
- unsafe {
- llvm::LLVMDIBuilderCreateStaticVariable(DIB(cx),
- var_scope,
- var_name,
- linkage_name,
- file_metadata,
- line_number,
- type_metadata,
- is_local_to_unit,
- global,
- ptr::null_mut());
- }
- })
- });
+ let var_name = CString::from_slice(var_name.as_bytes());
+ let linkage_name = CString::from_slice(linkage_name.as_bytes());
+ unsafe {
+ llvm::LLVMDIBuilderCreateStaticVariable(DIB(cx),
+ var_scope,
+ var_name.as_ptr(),
+ linkage_name.as_ptr(),
+ file_metadata,
+ line_number,
+ type_metadata,
+ is_local_to_unit,
+ global,
+ ptr::null_mut());
+ }
}
/// Creates debug information for the given local variable.
let is_local_to_unit = is_node_local_to_unit(cx, fn_ast_id);
- let fn_metadata = function_name.with_c_str(|function_name| {
- linkage_name.with_c_str(|linkage_name| {
- unsafe {
- llvm::LLVMDIBuilderCreateFunction(
- DIB(cx),
- containing_scope,
- function_name,
- linkage_name,
- file_metadata,
- loc.line as c_uint,
- function_type_metadata,
- is_local_to_unit,
- true,
- scope_line as c_uint,
- FlagPrototyped as c_uint,
- cx.sess().opts.optimize != config::No,
- llfn,
- template_parameters,
- ptr::null_mut())
- }
- })
- });
+ let function_name = CString::from_slice(function_name.as_bytes());
+ let linkage_name = CString::from_slice(linkage_name.as_bytes());
+ let fn_metadata = unsafe {
+ llvm::LLVMDIBuilderCreateFunction(
+ DIB(cx),
+ containing_scope,
+ function_name.as_ptr(),
+ linkage_name.as_ptr(),
+ file_metadata,
+ loc.line as c_uint,
+ function_type_metadata,
+ is_local_to_unit,
+ true,
+ scope_line as c_uint,
+ FlagPrototyped as c_uint,
+ cx.sess().opts.optimize != config::No,
+ llfn,
+ template_parameters,
+ ptr::null_mut())
+ };
let scope_map = create_scope_map(cx,
fn_decl.inputs.as_slice(),
let ident = special_idents::type_self;
- let param_metadata = token::get_ident(ident).get()
- .with_c_str(|name| {
- unsafe {
- llvm::LLVMDIBuilderCreateTemplateTypeParameter(
- DIB(cx),
- file_metadata,
- name,
- actual_self_type_metadata,
- ptr::null_mut(),
- 0,
- 0)
- }
- });
+ let ident = token::get_ident(ident);
+ let name = CString::from_slice(ident.get().as_bytes());
+ let param_metadata = unsafe {
+ llvm::LLVMDIBuilderCreateTemplateTypeParameter(
+ DIB(cx),
+ file_metadata,
+ name.as_ptr(),
+ actual_self_type_metadata,
+ ptr::null_mut(),
+ 0,
+ 0)
+ };
template_params.push(param_metadata);
}
// Again, only create type information if full debuginfo is enabled
if cx.sess().opts.debuginfo == FullDebugInfo {
let actual_type_metadata = type_metadata(cx, actual_type, codemap::DUMMY_SP);
- let param_metadata = token::get_ident(ident).get()
- .with_c_str(|name| {
- unsafe {
- llvm::LLVMDIBuilderCreateTemplateTypeParameter(
- DIB(cx),
- file_metadata,
- name,
- actual_type_metadata,
- ptr::null_mut(),
- 0,
- 0)
- }
- });
+ let ident = token::get_ident(ident);
+ let name = CString::from_slice(ident.get().as_bytes());
+ let param_metadata = unsafe {
+ llvm::LLVMDIBuilderCreateTemplateTypeParameter(
+ DIB(cx),
+ file_metadata,
+ name.as_ptr(),
+ actual_type_metadata,
+ ptr::null_mut(),
+ 0,
+ 0)
+ };
template_params.push(param_metadata);
}
}
} else {
match abs_path.path_relative_from(work_dir) {
Some(ref p) if p.is_relative() => {
- // prepend "./" if necessary
- let dotdot = b"..";
- let prefix = [dotdot[0], ::std::path::SEP_BYTE];
- let mut path_bytes = p.as_vec().to_vec();
-
- if path_bytes.slice_to(2) != prefix &&
- path_bytes.slice_to(2) != dotdot {
- path_bytes.insert(0, prefix[0]);
- path_bytes.insert(1, prefix[1]);
- }
-
- path_bytes.to_c_str()
+ // prepend "./" if necessary
+ let dotdot = b"..";
+ let prefix: &[u8] = &[dotdot[0], ::std::path::SEP_BYTE];
+ let mut path_bytes = p.as_vec().to_vec();
+
+ if path_bytes.slice_to(2) != prefix &&
+ path_bytes.slice_to(2) != dotdot {
+ path_bytes.insert(0, prefix[0]);
+ path_bytes.insert(1, prefix[1]);
}
+
+ CString::from_vec(path_bytes)
+ }
_ => fallback_path(cx)
}
}
(option_env!("CFG_VERSION")).expect("CFG_VERSION"));
let compile_unit_name = compile_unit_name.as_ptr();
- return work_dir.as_vec().with_c_str(|work_dir| {
- producer.with_c_str(|producer| {
- "".with_c_str(|flags| {
- "".with_c_str(|split_name| {
- unsafe {
- llvm::LLVMDIBuilderCreateCompileUnit(
- debug_context(cx).builder,
- DW_LANG_RUST,
- compile_unit_name,
- work_dir,
- producer,
- cx.sess().opts.optimize != config::No,
- flags,
- 0,
- split_name)
- }
- })
- })
- })
- });
+ let work_dir = CString::from_slice(work_dir.as_vec());
+ let producer = CString::from_slice(producer.as_bytes());
+ let flags = "\0";
+ let split_name = "\0";
+ return unsafe {
+ llvm::LLVMDIBuilderCreateCompileUnit(
+ debug_context(cx).builder,
+ DW_LANG_RUST,
+ compile_unit_name,
+ work_dir.as_ptr(),
+ producer.as_ptr(),
+ cx.sess().opts.optimize != config::No,
+ flags.as_ptr() as *const _,
+ 0,
+ split_name.as_ptr() as *const _)
+ };
fn fallback_path(cx: &CrateContext) -> CString {
- cx.link_meta().crate_name.to_c_str()
+ CString::from_slice(cx.link_meta().crate_name.as_bytes())
}
}
CapturedVariable => (0, DW_TAG_auto_variable)
};
- let (var_alloca, var_metadata) = name.get().with_c_str(|name| {
- match variable_access {
- DirectVariable { alloca } => (
- alloca,
- unsafe {
- llvm::LLVMDIBuilderCreateLocalVariable(
- DIB(cx),
- dwarf_tag,
- scope_metadata,
- name,
- file_metadata,
- loc.line as c_uint,
- type_metadata,
- cx.sess().opts.optimize != config::No,
- 0,
- argument_index)
- }
- ),
- IndirectVariable { alloca, address_operations } => (
- alloca,
- unsafe {
- llvm::LLVMDIBuilderCreateComplexVariable(
- DIB(cx),
- dwarf_tag,
- scope_metadata,
- name,
- file_metadata,
- loc.line as c_uint,
- type_metadata,
- address_operations.as_ptr(),
- address_operations.len() as c_uint,
- argument_index)
- }
- )
- }
- });
+ let name = CString::from_slice(name.get().as_bytes());
+ let (var_alloca, var_metadata) = match variable_access {
+ DirectVariable { alloca } => (
+ alloca,
+ unsafe {
+ llvm::LLVMDIBuilderCreateLocalVariable(
+ DIB(cx),
+ dwarf_tag,
+ scope_metadata,
+ name.as_ptr(),
+ file_metadata,
+ loc.line as c_uint,
+ type_metadata,
+ cx.sess().opts.optimize != config::No,
+ 0,
+ argument_index)
+ }
+ ),
+ IndirectVariable { alloca, address_operations } => (
+ alloca,
+ unsafe {
+ llvm::LLVMDIBuilderCreateComplexVariable(
+ DIB(cx),
+ dwarf_tag,
+ scope_metadata,
+ name.as_ptr(),
+ file_metadata,
+ loc.line as c_uint,
+ type_metadata,
+ address_operations.as_ptr(),
+ address_operations.len() as c_uint,
+ argument_index)
+ }
+ )
+ };
set_debug_location(cx, DebugLocation::new(scope_metadata,
loc.line,
full_path
};
- let file_metadata =
- file_name.with_c_str(|file_name| {
- work_dir.with_c_str(|work_dir| {
- unsafe {
- llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name, work_dir)
- }
- })
- });
+ let file_name = CString::from_slice(file_name.as_bytes());
+ let work_dir = CString::from_slice(work_dir.as_bytes());
+ let file_metadata = unsafe {
+ llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name.as_ptr(),
+ work_dir.as_ptr())
+ };
let mut created_files = debug_context(cx).created_files.borrow_mut();
created_files.insert(full_path.to_string(), file_metadata);
}
fn diverging_type_metadata(cx: &CrateContext) -> DIType {
- "!".with_c_str(|name| {
- unsafe {
- llvm::LLVMDIBuilderCreateBasicType(
- DIB(cx),
- name,
- bytes_to_bits(0),
- bytes_to_bits(0),
- DW_ATE_unsigned)
- }
- })
+ unsafe {
+ llvm::LLVMDIBuilderCreateBasicType(
+ DIB(cx),
+ "!\0".as_ptr() as *const _,
+ bytes_to_bits(0),
+ bytes_to_bits(0),
+ DW_ATE_unsigned)
+ }
}
fn basic_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
let llvm_type = type_of::type_of(cx, t);
let (size, align) = size_and_align_of(cx, llvm_type);
- let ty_metadata = name.with_c_str(|name| {
- unsafe {
- llvm::LLVMDIBuilderCreateBasicType(
- DIB(cx),
- name,
- bytes_to_bits(size),
- bytes_to_bits(align),
- encoding)
- }
- });
+ let name = CString::from_slice(name.as_bytes());
+ let ty_metadata = unsafe {
+ llvm::LLVMDIBuilderCreateBasicType(
+ DIB(cx),
+ name.as_ptr(),
+ bytes_to_bits(size),
+ bytes_to_bits(align),
+ encoding)
+ };
return ty_metadata;
}
let pointer_llvm_type = type_of::type_of(cx, pointer_type);
let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type);
let name = compute_debuginfo_type_name(cx, pointer_type, false);
- let ptr_metadata = name.with_c_str(|name| {
- unsafe {
- llvm::LLVMDIBuilderCreatePointerType(
- DIB(cx),
- pointee_type_metadata,
- bytes_to_bits(pointer_size),
- bytes_to_bits(pointer_align),
- name)
- }
- });
+ let name = CString::from_slice(name.as_bytes());
+ let ptr_metadata = unsafe {
+ llvm::LLVMDIBuilderCreatePointerType(
+ DIB(cx),
+ pointee_type_metadata,
+ bytes_to_bits(pointer_size),
+ bytes_to_bits(pointer_align),
+ name.as_ptr())
+ };
return ptr_metadata;
}
let enumerators_metadata: Vec<DIDescriptor> = variants
.iter()
.map(|v| {
- token::get_name(v.name).get().with_c_str(|name| {
- unsafe {
- llvm::LLVMDIBuilderCreateEnumerator(
- DIB(cx),
- name,
- v.disr_val as u64)
- }
- })
+ let token = token::get_name(v.name);
+ let name = CString::from_slice(token.get().as_bytes());
+ unsafe {
+ llvm::LLVMDIBuilderCreateEnumerator(
+ DIB(cx),
+ name.as_ptr(),
+ v.disr_val as u64)
+ }
})
.collect();
codemap::DUMMY_SP);
let discriminant_name = get_enum_discriminant_name(cx, enum_def_id);
- let discriminant_type_metadata = discriminant_name.get().with_c_str(|name| {
- unsafe {
- llvm::LLVMDIBuilderCreateEnumerationType(
- DIB(cx),
- containing_scope,
- name,
- UNKNOWN_FILE_METADATA,
- UNKNOWN_LINE_NUMBER,
- bytes_to_bits(discriminant_size),
- bytes_to_bits(discriminant_align),
- create_DIArray(DIB(cx), enumerators_metadata[]),
- discriminant_base_type_metadata)
- }
- });
+ let name = CString::from_slice(discriminant_name.get().as_bytes());
+ let discriminant_type_metadata = unsafe {
+ llvm::LLVMDIBuilderCreateEnumerationType(
+ DIB(cx),
+ containing_scope,
+ name.as_ptr(),
+ UNKNOWN_FILE_METADATA,
+ UNKNOWN_LINE_NUMBER,
+ bytes_to_bits(discriminant_size),
+ bytes_to_bits(discriminant_align),
+ create_DIArray(DIB(cx), enumerators_metadata.as_slice()),
+ discriminant_base_type_metadata)
+ };
debug_context(cx).created_enum_disr_types
.borrow_mut()
.borrow()
.get_unique_type_id_as_string(unique_type_id);
- let enum_metadata = enum_name.with_c_str(|enum_name| {
- unique_type_id_str.with_c_str(|unique_type_id_str| {
- unsafe {
- llvm::LLVMDIBuilderCreateUnionType(
- DIB(cx),
- containing_scope,
- enum_name,
- UNKNOWN_FILE_METADATA,
- UNKNOWN_LINE_NUMBER,
- bytes_to_bits(enum_type_size),
- bytes_to_bits(enum_type_align),
- 0, // Flags
- ptr::null_mut(),
- 0, // RuntimeLang
- unique_type_id_str)
- }
- })
- });
+ let enum_name = CString::from_slice(enum_name.as_bytes());
+ let unique_type_id_str = CString::from_slice(unique_type_id_str.as_bytes());
+ let enum_metadata = unsafe {
+ llvm::LLVMDIBuilderCreateUnionType(
+ DIB(cx),
+ containing_scope,
+ enum_name.as_ptr(),
+ UNKNOWN_FILE_METADATA,
+ UNKNOWN_LINE_NUMBER,
+ bytes_to_bits(enum_type_size),
+ bytes_to_bits(enum_type_align),
+ 0, // Flags
+ ptr::null_mut(),
+ 0, // RuntimeLang
+ unique_type_id_str.as_ptr())
+ };
return create_and_register_recursive_type_forward_declaration(
cx,
ComputedMemberOffset => machine::llelement_offset(cx, composite_llvm_type, i)
};
- member_description.name.with_c_str(|member_name| {
- unsafe {
- llvm::LLVMDIBuilderCreateMemberType(
- DIB(cx),
- composite_type_metadata,
- member_name,
- UNKNOWN_FILE_METADATA,
- UNKNOWN_LINE_NUMBER,
- bytes_to_bits(member_size),
- bytes_to_bits(member_align),
- bytes_to_bits(member_offset),
- member_description.flags,
- member_description.type_metadata)
- }
- })
+ let member_name = CString::from_slice(member_description.name.as_bytes());
+ unsafe {
+ llvm::LLVMDIBuilderCreateMemberType(
+ DIB(cx),
+ composite_type_metadata,
+ member_name.as_ptr(),
+ UNKNOWN_FILE_METADATA,
+ UNKNOWN_LINE_NUMBER,
+ bytes_to_bits(member_size),
+ bytes_to_bits(member_align),
+ bytes_to_bits(member_offset),
+ member_description.flags,
+ member_description.type_metadata)
+ }
})
.collect();
let unique_type_id_str = debug_context(cx).type_map
.borrow()
.get_unique_type_id_as_string(unique_type_id);
+ let name = CString::from_slice(struct_type_name.as_bytes());
+ let unique_type_id = CString::from_slice(unique_type_id_str.as_bytes());
let metadata_stub = unsafe {
- struct_type_name.with_c_str(|name| {
- unique_type_id_str.with_c_str(|unique_type_id| {
- // LLVMDIBuilderCreateStructType() wants an empty array. A null
- // pointer will lead to hard to trace and debug LLVM assertions
- // later on in llvm/lib/IR/Value.cpp.
- let empty_array = create_DIArray(DIB(cx), &[]);
-
- llvm::LLVMDIBuilderCreateStructType(
- DIB(cx),
- containing_scope,
- name,
- UNKNOWN_FILE_METADATA,
- UNKNOWN_LINE_NUMBER,
- bytes_to_bits(struct_size),
- bytes_to_bits(struct_align),
- 0,
- ptr::null_mut(),
- empty_array,
- 0,
- ptr::null_mut(),
- unique_type_id)
- })
- })
+ // LLVMDIBuilderCreateStructType() wants an empty array. A null
+ // pointer will lead to hard to trace and debug LLVM assertions
+ // later on in llvm/lib/IR/Value.cpp.
+ let empty_array = create_DIArray(DIB(cx), &[]);
+
+ llvm::LLVMDIBuilderCreateStructType(
+ DIB(cx),
+ containing_scope,
+ name.as_ptr(),
+ UNKNOWN_FILE_METADATA,
+ UNKNOWN_LINE_NUMBER,
+ bytes_to_bits(struct_size),
+ bytes_to_bits(struct_align),
+ 0,
+ ptr::null_mut(),
+ empty_array,
+ 0,
+ ptr::null_mut(),
+ unique_type_id.as_ptr())
};
return metadata_stub;
}
}
- ast::PatBox(ref sub_pat) | ast::PatRegion(ref sub_pat) => {
+ ast::PatBox(ref sub_pat) | ast::PatRegion(ref sub_pat, _) => {
scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
}
None => ptr::null_mut()
};
let namespace_name = token::get_name(name);
- let scope = namespace_name.get().with_c_str(|namespace_name| {
- unsafe {
- llvm::LLVMDIBuilderCreateNameSpace(
- DIB(cx),
- parent_scope,
- namespace_name,
- // cannot reconstruct file ...
- ptr::null_mut(),
- // ... or line information, but that's not so important.
- 0)
- }
- });
+ let namespace_name = CString::from_slice(namespace_name
+ .get().as_bytes());
+ let scope = unsafe {
+ llvm::LLVMDIBuilderCreateNameSpace(
+ DIB(cx),
+ parent_scope,
+ namespace_name.as_ptr(),
+ // cannot reconstruct file ...
+ ptr::null_mut(),
+ // ... or line information, but that's not so important.
+ 0)
+ };
let node = Rc::new(NamespaceTreeNode {
name: name,
/// .debug_gdb_scripts global is referenced, so it isn't removed by the linker.
pub fn insert_reference_to_gdb_debug_scripts_section_global(ccx: &CrateContext) {
if needs_gdb_debug_scripts_section(ccx) {
- let empty = b"".to_c_str();
+ let empty = CString::from_slice(b"");
let gdb_debug_scripts_section_global =
get_or_insert_gdb_debug_scripts_section_global(ccx);
unsafe {
/// section.
fn get_or_insert_gdb_debug_scripts_section_global(ccx: &CrateContext)
-> llvm::ValueRef {
- let section_var_name = b"__rustc_debug_gdb_scripts_section__".to_c_str();
+ let section_var_name = b"__rustc_debug_gdb_scripts_section__\0";
let section_var = unsafe {
- llvm::LLVMGetNamedGlobal(ccx.llmod(), section_var_name.as_ptr())
+ llvm::LLVMGetNamedGlobal(ccx.llmod(),
+ section_var_name.as_ptr() as *const _)
};
if section_var == ptr::null_mut() {
- let section_name = b".debug_gdb_scripts".to_c_str();
+ let section_name = b".debug_gdb_scripts\0";
let section_contents = b"\x01gdb_load_rust_pretty_printers.py\0";
unsafe {
section_contents.len() as u64);
let section_var = llvm::LLVMAddGlobal(ccx.llmod(),
llvm_type.to_ref(),
- section_var_name.as_ptr());
- llvm::LLVMSetSection(section_var, section_name.as_ptr());
+ section_var_name.as_ptr()
+ as *const _);
+ llvm::LLVMSetSection(section_var, section_name.as_ptr() as *const _);
llvm::LLVMSetInitializer(section_var, C_bytes(ccx, section_contents));
llvm::LLVMSetGlobalConstant(section_var, llvm::True);
llvm::LLVMSetUnnamedAddr(section_var, llvm::True);
use trans::type_of::*;
use trans::type_of;
use middle::ty::{self, Ty};
-use middle::subst::{Substs};
+use middle::subst::Substs;
+
+use std::ffi::CString;
use std::cmp;
-use std::c_str::ToCStr;
use libc::c_uint;
use syntax::abi::{Cdecl, Aapcs, C, Win64, Abi};
use syntax::abi::{RustIntrinsic, Rust, RustCall, Stdcall, Fastcall, System};
};
unsafe {
// Declare a symbol `foo` with the desired linkage.
- let g1 = ident.get().with_c_str(|buf| {
- llvm::LLVMAddGlobal(ccx.llmod(), llty2.to_ref(), buf)
- });
+ let buf = CString::from_slice(ident.get().as_bytes());
+ let g1 = llvm::LLVMAddGlobal(ccx.llmod(), llty2.to_ref(),
+ buf.as_ptr());
llvm::SetLinkage(g1, linkage);
// Declare an internal global `extern_with_linkage_foo` which
// zero.
let mut real_name = "_rust_extern_with_linkage_".to_string();
real_name.push_str(ident.get());
- let g2 = real_name.with_c_str(|buf| {
- llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(), buf)
- });
+ let real_name = CString::from_vec(real_name.into_bytes());
+ let g2 = llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(),
+ real_name.as_ptr());
llvm::SetLinkage(g2, llvm::InternalLinkage);
llvm::LLVMSetInitializer(g2, g1);
g2
}
None => unsafe {
// Generate an external declaration.
- ident.get().with_c_str(|buf| {
- llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(), buf)
- })
+ let buf = CString::from_slice(ident.get().as_bytes());
+ llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(), buf.as_ptr())
}
}
}
// return r;
// }
- let the_block =
- "the block".with_c_str(
- |s| llvm::LLVMAppendBasicBlockInContext(ccx.llcx(), llwrapfn, s));
+ let ptr = "the block\0".as_ptr();
+ let the_block = llvm::LLVMAppendBasicBlockInContext(ccx.llcx(), llwrapfn,
+ ptr as *const _);
let builder = ccx.builder();
builder.position_at_end(the_block);
use util::ppaux;
use arena::TypedArena;
-use std::c_str::ToCStr;
use libc::c_uint;
+use std::ffi::CString;
use syntax::ast;
use syntax::parse::token;
let llalign = llalign_of(ccx, llty);
let name = mangle_internal_name_by_type_and_seq(ccx, t, "tydesc");
debug!("+++ declare_tydesc {} {}", ppaux::ty_to_string(ccx.tcx(), t), name);
- let gvar = name.with_c_str(|buf| {
- unsafe {
- llvm::LLVMAddGlobal(ccx.llmod(), ccx.tydesc_type().to_ref(), buf)
- }
- });
+ let buf = CString::from_slice(name.as_bytes());
+ let gvar = unsafe {
+ llvm::LLVMAddGlobal(ccx.llmod(), ccx.tydesc_type().to_ref(),
+ buf.as_ptr())
+ };
note_unique_llvm_symbol(ccx, name);
let ty_name = token::intern_and_get_ident(
use trans::type_::Type;
use llvm::ValueRef;
-pub trait LlvmRepr for Sized? {
+pub trait LlvmRepr {
fn llrepr(&self, ccx: &CrateContext) -> String;
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![macro_escape]
-
macro_rules! unpack_datum {
($bcx: ident, $inp: expr) => (
{
use middle::ty::MethodCall;
use util::ppaux::Repr;
-use std::c_str::ToCStr;
+use std::ffi::CString;
use std::rc::Rc;
use syntax::abi::{Rust, RustCall};
use syntax::parse::token;
unsafe {
let tbl = C_struct(ccx, components[], false);
let sym = token::gensym("vtable");
- let vt_gvar = format!("vtable{}", sym.uint()).with_c_str(|buf| {
- llvm::LLVMAddGlobal(ccx.llmod(), val_ty(tbl).to_ref(), buf)
- });
+ let buf = CString::from_vec(format!("vtable{}", sym.uint()).into_bytes());
+ let vt_gvar = llvm::LLVMAddGlobal(ccx.llmod(), val_ty(tbl).to_ref(),
+ buf.as_ptr());
llvm::LLVMSetInitializer(vt_gvar, tbl);
llvm::LLVMSetGlobalConstant(vt_gvar, llvm::True);
llvm::SetLinkage(vt_gvar, llvm::InternalLinkage);
pub use self::context::CrateContext;
pub use self::common::gensym_name;
-mod doc;
+#[cfg_attr(stage0, macro_escape)]
+#[cfg_attr(not(stage0), macro_use)]
mod macros;
+
+mod doc;
mod inline;
mod monomorphize;
mod controlflow;
use syntax::ast;
-use std::c_str::ToCStr;
+use std::ffi::CString;
use std::mem;
use std::cell::RefCell;
use std::iter::repeat;
}
pub fn named_struct(ccx: &CrateContext, name: &str) -> Type {
- ty!(name.with_c_str(|s| llvm::LLVMStructCreateNamed(ccx.llcx(), s)))
+ let name = CString::from_slice(name.as_bytes());
+ ty!(llvm::LLVMStructCreateNamed(ccx.llcx(), name.as_ptr()))
}
pub fn empty_struct(ccx: &CrateContext) -> Type {
supplied_ty_param_count)[]);
}
- if supplied_ty_param_count > required_ty_param_count
- && !this.tcx().sess.features.borrow().default_type_params {
- span_err!(this.tcx().sess, span, E0108,
- "default type parameters are experimental and possibly buggy");
- span_help!(this.tcx().sess, span,
- "add #![feature(default_type_params)] to the crate attributes to enable");
- }
-
let mut substs = Substs::new_type(types, regions);
match self_ty {
use syntax::ptr::P;
pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
- pat: &ast::Pat, expected: Ty<'tcx>) {
+ pat: &ast::Pat,
+ expected: Ty<'tcx>)
+{
let fcx = pcx.fcx;
let tcx = pcx.fcx.ccx.tcx;
check_expr(fcx, &**lt);
let expr_ty = fcx.expr_ty(&**lt);
fcx.write_ty(pat.id, expr_ty);
+
+ // somewhat surprising: in this case, the subtyping
+ // relation goes the opposite way as the other
+ // cases. Actually what we really want is not a subtyping
+ // relation at all but rather that there exists a LUB (so
+ // that they can be compared). However, in practice,
+ // constants are always scalars or strings. For scalars
+ // subtyping is irrelevant, and for strings `expr_ty` is
+ // type is `&'static str`, so if we say that
+ //
+ // &'static str <: expected
+ //
+ // that's equivalent to there existing a LUB.
demand::suptype(fcx, pat.span, expected, expr_ty);
}
ast::PatRange(ref begin, ref end) => {
let lhs_ty = fcx.expr_ty(&**begin);
let rhs_ty = fcx.expr_ty(&**end);
- if require_same_types(
- tcx, Some(fcx.infcx()), false, pat.span, lhs_ty, rhs_ty,
- || "mismatched types in range".to_string())
- && (ty::type_is_numeric(lhs_ty) || ty::type_is_char(rhs_ty)) {
+
+ let lhs_eq_rhs =
+ require_same_types(
+ tcx, Some(fcx.infcx()), false, pat.span, lhs_ty, rhs_ty,
+ || "mismatched types in range".to_string());
+
+ let numeric_or_char =
+ lhs_eq_rhs && (ty::type_is_numeric(lhs_ty) || ty::type_is_char(lhs_ty));
+
+ if numeric_or_char {
match valid_range_bounds(fcx.ccx, &**begin, &**end) {
Some(false) => {
span_err!(tcx.sess, begin.span, E0030,
}
} else {
span_err!(tcx.sess, begin.span, E0029,
- "only char and numeric types are allowed in range");
+ "only char and numeric types are allowed in range");
}
fcx.write_ty(pat.id, lhs_ty);
+
+ // subtyping doens't matter here, as the value is some kind of scalar
demand::eqtype(fcx, pat.span, expected, lhs_ty);
}
ast::PatEnum(..) | ast::PatIdent(..) if pat_is_const(&tcx.def_map, pat) => {
let const_did = tcx.def_map.borrow()[pat.id].clone().def_id();
let const_scheme = ty::lookup_item_type(tcx, const_did);
- fcx.write_ty(pat.id, const_scheme.ty);
- demand::suptype(fcx, pat.span, expected, const_scheme.ty);
+ assert!(const_scheme.generics.is_empty());
+ let const_ty = pcx.fcx.instantiate_type_scheme(pat.span,
+ &Substs::empty(),
+ &const_scheme.ty);
+ fcx.write_ty(pat.id, const_ty);
+
+ // FIXME(#20489) -- we should limit the types here to scalars or something!
+
+ // As with PatLit, what we really want here is that there
+ // exist a LUB, but for the cases that can occur, subtype
+ // is good enough.
+ demand::suptype(fcx, pat.span, expected, const_ty);
}
ast::PatIdent(bm, ref path, ref sub) if pat_is_binding(&tcx.def_map, pat) => {
let typ = fcx.local_ty(pat.span, pat.id);
ast::BindByRef(mutbl) => {
// if the binding is like
// ref x | ref const x | ref mut x
- // then the type of x is &M T where M is the mutability
- // and T is the expected type
+ // then `x` is assigned a value of type `&M T` where M is the mutability
+ // and T is the expected type.
let region_var = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
let mt = ty::mt { ty: expected, mutbl: mutbl };
let region_ty = ty::mk_rptr(tcx, tcx.mk_region(region_var), mt);
+
+ // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
+ // required. However, we use equality, which is stronger. See (*) for
+ // an explanation.
demand::eqtype(fcx, pat.span, region_ty, typ);
}
// otherwise the type of x is the expected type T
ast::BindByValue(_) => {
+ // As above, `T <: typeof(x)` is required but we
+ // use equality, see (*) below.
demand::eqtype(fcx, pat.span, expected, typ);
}
}
+
fcx.write_ty(pat.id, typ);
+ // if there are multiple arms, make sure they all agree on
+ // what the type of the binding `x` ought to be
let canon_id = pcx.map[path.node];
if canon_id != pat.id {
let ct = fcx.local_ty(pat.span, canon_id);
check_pat_struct(pcx, pat, path, fields.as_slice(), etc, expected);
}
ast::PatTup(ref elements) => {
- let element_tys: Vec<_> = range(0, elements.len()).map(|_| fcx.infcx()
- .next_ty_var()).collect();
+ let element_tys: Vec<_> =
+ range(0, elements.len()).map(|_| fcx.infcx().next_ty_var())
+ .collect();
let pat_ty = ty::mk_tup(tcx, element_tys.clone());
fcx.write_ty(pat.id, pat_ty);
demand::eqtype(fcx, pat.span, expected, pat_ty);
let uniq_ty = ty::mk_uniq(tcx, inner_ty);
if check_dereferencable(pcx, pat.span, expected, &**inner) {
- demand::suptype(fcx, pat.span, expected, uniq_ty);
+ // Here, `demand::subtype` is good enough, but I don't
+ // think any errors can be introduced by using
+ // `demand::eqtype`.
+ demand::eqtype(fcx, pat.span, expected, uniq_ty);
fcx.write_ty(pat.id, uniq_ty);
check_pat(pcx, &**inner, inner_ty);
} else {
check_pat(pcx, &**inner, tcx.types.err);
}
}
- ast::PatRegion(ref inner) => {
+ ast::PatRegion(ref inner, mutbl) => {
let inner_ty = fcx.infcx().next_ty_var();
- let mutbl =
+ // SNAP b2085d9 remove this `if`-`else` entirely after next snapshot
+ let mutbl = if mutbl == ast::MutImmutable {
ty::deref(fcx.infcx().shallow_resolve(expected), true)
- .map_or(ast::MutImmutable, |mt| mt.mutbl);
+ .map(|mt| mt.mutbl).unwrap_or(ast::MutImmutable)
+ } else {
+ mutbl
+ };
let mt = ty::mt { ty: inner_ty, mutbl: mutbl };
let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
let rptr_ty = ty::mk_rptr(tcx, tcx.mk_region(region), mt);
if check_dereferencable(pcx, pat.span, expected, &**inner) {
- demand::suptype(fcx, pat.span, expected, rptr_ty);
+ // `demand::subtype` would be good enough, but using
+ // `eqtype` turns out to be equally general. See (*)
+ // below for details.
+ demand::eqtype(fcx, pat.span, expected, rptr_ty);
fcx.write_ty(pat.id, rptr_ty);
check_pat(pcx, &**inner, inner_ty);
} else {
let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
ty::mk_slice(tcx, tcx.mk_region(region), ty::mt {
ty: inner_ty,
- mutbl: ty::deref(expected_ty, true)
- .map_or(ast::MutImmutable, |mt| mt.mutbl)
+ mutbl: ty::deref(expected_ty, true).map(|mt| mt.mutbl)
+ .unwrap_or(ast::MutImmutable)
})
}
};
fcx.write_ty(pat.id, pat_ty);
- demand::suptype(fcx, pat.span, expected, pat_ty);
+
+ // `demand::subtype` would be good enough, but using
+ // `eqtype` turns out to be equally general. See (*)
+ // below for details.
+ demand::eqtype(fcx, pat.span, expected, pat_ty);
for elt in before.iter() {
check_pat(pcx, &**elt, inner_ty);
}
ast::PatMac(_) => tcx.sess.bug("unexpanded macro")
}
+
+
+ // (*) In most of the cases above (literals and constants being
+ // the exception), we relate types using strict equality, evewn
+ // though subtyping would be sufficient. There are a few reasons
+ // for this, some of which are fairly subtle and which cost me
+ // (nmatsakis) an hour or two debugging to remember, so I thought
+ // I'd write them down this time.
+ //
+ // 1. Most importantly, there is no loss of expressiveness
+ // here. What we are saying is that the type of `x`
+ // becomes *exactly* what is expected. This might seem
+ // like it will cause errors in a case like this:
+ //
+ // ```
+ // fn foo<'x>(x: &'x int) {
+ // let a = 1;
+ // let mut z = x;
+ // z = &a;
+ // }
+ // ```
+ //
+ // The reason we might get an error is that `z` might be
+ // assigned a type like `&'x int`, and then we would have
+ // a problem when we try to assign `&a` to `z`, because
+ // the lifetime of `&a` (i.e., the enclosing block) is
+ // shorter than `'x`.
+ //
+ // HOWEVER, this code works fine. The reason is that the
+ // expected type here is whatever type the user wrote, not
+ // the initializer's type. In this case the user wrote
+ // nothing, so we are going to create a type variable `Z`.
+ // Then we will assign the type of the initializer (`&'x
+ // int`) as a subtype of `Z`: `&'x int <: Z`. And hence we
+ // will instantiate `Z` as a type `&'0 int` where `'0` is
+ // a fresh region variable, with the constraint that `'x :
+ // '0`. So basically we're all set.
+ //
+ // Note that there are two tests to check that this remains true
+ // (`regions-reassign-{match,let}-bound-pointer.rs`).
+ //
+ // 2. Things go horribly wrong if we use subtype. The reason for
+ // THIS is a fairly subtle case involving bound regions. See the
+ // `givens` field in `region_inference`, as well as the test
+ // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
+ // for details. Short version is that we must sometimes detect
+ // relationships between specific region variables and regions
+ // bound in a closure signature, and that detection gets thrown
+ // off when we substitute fresh region variables here to enable
+ // subtyping.
}
pub fn check_dereferencable<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
use super::write_call;
use middle::infer;
-use middle::ty::{mod, Ty};
+use middle::ty::{self, Ty};
use syntax::ast;
use syntax::codemap::Span;
use syntax::parse::token;
use syntax::codemap::Span;
use util::ppaux::Repr;
-// Requires that the two types unify, and prints an error message if they
-// don't.
+// Requires that the two types unify, and prints an error message if
+// they don't.
pub fn suptype<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
- expected: Ty<'tcx>, actual: Ty<'tcx>) {
- suptype_with_fn(fcx, sp, false, expected, actual,
+ ty_expected: Ty<'tcx>, ty_actual: Ty<'tcx>) {
+ suptype_with_fn(fcx, sp, false, ty_expected, ty_actual,
|sp, e, a, s| { fcx.report_mismatched_types(sp, e, a, s) })
}
+/// As `suptype`, but call `handle_err` if unification for subtyping fails.
pub fn suptype_with_fn<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
sp: Span,
b_is_expected: bool,
expected: Ty<'tcx>, actual: Ty<'tcx>) {
match infer::mk_eqty(fcx.infcx(), false, infer::Misc(sp), actual, expected) {
Ok(()) => { /* ok */ }
- Err(ref err) => {
- fcx.report_mismatched_types(sp, expected, actual, err);
- }
+ Err(ref err) => { fcx.report_mismatched_types(sp, expected, actual, err); }
}
}
fn assemble_extension_candidates_for_trait(&mut self,
trait_def_id: ast::DefId) {
- debug!("assemble_extension_candidates_for_trait: trait_def_id={}",
+ debug!("assemble_extension_candidates_for_trait(trait_def_id={})",
trait_def_id.repr(self.tcx()));
// Check whether `trait_def_id` defines a method with suitable name:
matching_index);
self.assemble_unboxed_closure_candidates(trait_def_id,
- method,
+ method.clone(),
matching_index);
+
+ self.assemble_where_clause_candidates(trait_def_id,
+ method,
+ matching_index);
}
fn assemble_extension_candidates_for_trait_impls(&mut self,
}
}
+ fn assemble_where_clause_candidates(&mut self,
+ trait_def_id: ast::DefId,
+ method_ty: Rc<ty::Method<'tcx>>,
+ method_index: uint)
+ {
+ debug!("assemble_where_clause_candidates(trait_def_id={})",
+ trait_def_id.repr(self.tcx()));
+
+ // Check whether there are any where-clauses pertaining to this trait.
+ let caller_predicates =
+ self.fcx.inh.param_env.caller_bounds.predicates.as_slice().to_vec();
+ for bound in traits::elaborate_predicates(self.tcx(), caller_predicates)
+ .filter_map(|p| p.to_opt_poly_trait_ref())
+ .filter(|b| b.def_id() == trait_def_id)
+ {
+ let xform_self_ty = self.xform_self_ty(&method_ty, bound.substs());
+
+ debug!("assemble_where_clause_candidates: bound={} xform_self_ty={}",
+ bound.repr(self.tcx()),
+ xform_self_ty.repr(self.tcx()));
+
+ self.extension_candidates.push(Candidate {
+ xform_self_ty: xform_self_ty,
+ method_ty: method_ty.clone(),
+ kind: WhereClauseCandidate(bound, method_index)
+ });
+ }
+ }
+
///////////////////////////////////////////////////////////////////////////
// THE ACTUAL SEARCH
match probe.kind {
InherentImplCandidate(impl_def_id, ref substs) |
ExtensionImplCandidate(impl_def_id, _, ref substs, _) => {
+ let selcx = &mut traits::SelectionContext::new(self.infcx(), self.fcx);
+ let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
+
// Check whether the impl imposes obligations we have to worry about.
let impl_generics = ty::lookup_item_type(self.tcx(), impl_def_id).generics;
let impl_bounds = impl_generics.to_bounds(self.tcx(), substs);
- // FIXME(#20378) assoc type normalization here?
-
- // Erase any late-bound regions bound in the impl
- // which appear in the bounds.
- let impl_bounds = self.erase_late_bound_regions(&ty::Binder(impl_bounds));
+ let traits::Normalized { value: impl_bounds,
+ obligations: norm_obligations } =
+ traits::normalize(selcx, cause.clone(), &impl_bounds);
// Convert the bounds into obligations.
let obligations =
- traits::predicates_for_generics(
- self.tcx(),
- traits::ObligationCause::misc(self.span, self.fcx.body_id),
- &impl_bounds);
+ traits::predicates_for_generics(self.tcx(),
+ cause.clone(),
+ &impl_bounds);
debug!("impl_obligations={}", obligations.repr(self.tcx()));
// Evaluate those obligations to see if they might possibly hold.
- let mut selcx = traits::SelectionContext::new(self.infcx(), self.fcx);
- obligations.all(|o| selcx.evaluate_obligation(o))
+ obligations.all(|o| selcx.evaluate_obligation(o)) &&
+ norm_obligations.iter().all(|o| selcx.evaluate_obligation(o))
}
ObjectCandidate(..) |
pub fn check_decl_initializer(fcx: &FnCtxt,
nid: ast::NodeId,
init: &ast::Expr)
- {
+{
let local_ty = fcx.local_ty(init.span, nid);
check_expr_coercable_to_type(fcx, init, local_ty)
}
use middle::traits;
use middle::ty::{ReScope};
use middle::ty::{self, Ty, MethodCall};
-use middle::infer;
+use middle::infer::{self, GenericKind};
use middle::pat_util;
use util::ppaux::{ty_to_string, Repr};
pub struct Rcx<'a, 'tcx: 'a> {
fcx: &'a FnCtxt<'a, 'tcx>,
- region_param_pairs: Vec<(ty::Region, ty::ParamTy)>,
+ region_bound_pairs: Vec<(ty::Region, GenericKind<'tcx>)>,
// id of innermost fn or loop
repeating_scope: ast::NodeId,
Rcx { fcx: fcx,
repeating_scope: initial_repeating_scope,
subject: subject,
- region_param_pairs: Vec::new() }
+ region_bound_pairs: Vec::new() }
}
pub fn tcx(&self) -> &'a ty::ctxt<'tcx> {
}
};
- let len = self.region_param_pairs.len();
+ let len = self.region_bound_pairs.len();
self.relate_free_regions(fn_sig[], body.id);
link_fn_args(self, CodeExtent::from_node_id(body.id), fn_decl.inputs[]);
self.visit_block(body);
self.visit_region_obligations(body.id);
- self.region_param_pairs.truncate(len);
+ self.region_bound_pairs.truncate(len);
}
fn visit_region_obligations(&mut self, node_id: ast::NodeId)
// relationship that arises here, but
// presently we do not.)
}
- regionmanip::RegionSubParamConstraint(_, r_a, p_b) => {
- debug!("RegionSubParamConstraint: {} <= {}",
- r_a.repr(tcx), p_b.repr(tcx));
+ regionmanip::RegionSubGenericConstraint(_, r_a, ref generic_b) => {
+ debug!("RegionSubGenericConstraint: {} <= {}",
+ r_a.repr(tcx), generic_b.repr(tcx));
- self.region_param_pairs.push((r_a, p_b));
+ self.region_bound_pairs.push((r_a, generic_b.clone()));
}
}
}
let o1 = infer::ReferenceOutlivesReferent(ty, origin.span());
rcx.fcx.mk_subr(o1, r_a, r_b);
}
- regionmanip::RegionSubParamConstraint(None, r_a, param_b) => {
- param_must_outlive(rcx, origin.clone(), r_a, param_b);
+ regionmanip::RegionSubGenericConstraint(None, r_a, ref generic_b) => {
+ generic_must_outlive(rcx, origin.clone(), r_a, generic_b);
}
- regionmanip::RegionSubParamConstraint(Some(ty), r_a, param_b) => {
+ regionmanip::RegionSubGenericConstraint(Some(ty), r_a, ref generic_b) => {
let o1 = infer::ReferenceOutlivesReferent(ty, origin.span());
- param_must_outlive(rcx, o1, r_a, param_b);
+ generic_must_outlive(rcx, o1, r_a, generic_b);
}
}
}
}
-fn param_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
- origin: infer::SubregionOrigin<'tcx>,
- region: ty::Region,
- param_ty: ty::ParamTy) {
+fn generic_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
+ origin: infer::SubregionOrigin<'tcx>,
+ region: ty::Region,
+ generic: &GenericKind<'tcx>) {
let param_env = &rcx.fcx.inh.param_env;
- debug!("param_must_outlive(region={}, param_ty={})",
+ debug!("param_must_outlive(region={}, generic={})",
region.repr(rcx.tcx()),
- param_ty.repr(rcx.tcx()));
+ generic.repr(rcx.tcx()));
// To start, collect bounds from user:
let mut param_bounds =
ty::required_region_bounds(rcx.tcx(),
- param_ty.to_ty(rcx.tcx()),
+ generic.to_ty(rcx.tcx()),
param_env.caller_bounds.predicates.as_slice().to_vec());
// Add in the default bound of fn body that applies to all in
// fn foo<'a, A>(x: &'a A) { x.bar() }
//
// The problem is that the type of `x` is `&'a A`. To be
- // well-formed, then, A must be lower-bounded by `'a`, but we
+ // well-formed, then, A must be lower-generic by `'a`, but we
// don't know that this holds from first principles.
- for &(ref r, ref p) in rcx.region_param_pairs.iter() {
- debug!("param_ty={} p={}",
- param_ty.repr(rcx.tcx()),
+ for &(ref r, ref p) in rcx.region_bound_pairs.iter() {
+ debug!("generic={} p={}",
+ generic.repr(rcx.tcx()),
p.repr(rcx.tcx()));
- if param_ty == *p {
+ if generic == p {
param_bounds.push(*r);
}
}
- // Inform region inference that this parameter type must be
- // properly bounded.
- infer::verify_param_bound(rcx.fcx.infcx(),
- origin,
- param_ty,
- region,
- param_bounds);
+ // Inform region inference that this generic must be properly
+ // bounded.
+ rcx.fcx.infcx().verify_generic_bound(origin,
+ generic.clone(),
+ region,
+ param_bounds);
}
pub use self::WfConstraint::*;
+use middle::infer::GenericKind;
use middle::subst::{ParamSpace, Subst, Substs};
use middle::ty::{self, Ty};
use middle::ty_fold::{TypeFolder};
pub enum WfConstraint<'tcx> {
RegionSubRegionConstraint(Option<Ty<'tcx>>, ty::Region, ty::Region),
- RegionSubParamConstraint(Option<Ty<'tcx>>, ty::Region, ty::ParamTy),
+ RegionSubGenericConstraint(Option<Ty<'tcx>>, ty::Region, GenericKind<'tcx>),
}
struct Wf<'a, 'tcx: 'a> {
ty::ty_projection(ref data) => {
// `<T as TraitRef<..>>::Name`
- // FIXME(#20303) -- gain ability to require that ty_projection : in-scope region,
- // like a type parameter
+ self.push_projection_constraint_from_top(data);
// this seems like a minimal requirement:
let trait_def = ty::lookup_trait_def(self.tcx, data.trait_ref.def_id);
self.push_param_constraint(region, opt_ty, param_ty);
}
+ /// Pushes a constraint that `projection_ty` must outlive the top region on the stack.
+ fn push_projection_constraint_from_top(&mut self,
+ projection_ty: &ty::ProjectionTy<'tcx>) {
+ let &(region, opt_ty) = self.stack.last().unwrap();
+ self.out.push(RegionSubGenericConstraint(
+ opt_ty, region, GenericKind::Projection(projection_ty.clone())));
+ }
+
/// Pushes a constraint that `region <= param_ty`, due to `opt_ty`
fn push_param_constraint(&mut self,
region: ty::Region,
opt_ty: Option<Ty<'tcx>>,
param_ty: ty::ParamTy) {
- self.out.push(RegionSubParamConstraint(opt_ty, region, param_ty));
+ self.out.push(RegionSubGenericConstraint(
+ opt_ty, region, GenericKind::Param(param_ty)));
}
fn accumulate_from_adt(&mut self,
}
impl<'tcx> Repr<'tcx> for WfConstraint<'tcx> {
- fn repr(&self, tcx: &ty::ctxt) -> String {
+ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
match *self {
- RegionSubRegionConstraint(_, r_a, r_b) => {
+ RegionSubRegionConstraint(_, ref r_a, ref r_b) => {
format!("RegionSubRegionConstraint({}, {})",
r_a.repr(tcx),
r_b.repr(tcx))
}
- RegionSubParamConstraint(_, r, p) => {
- format!("RegionSubParamConstraint({}, {})",
+ RegionSubGenericConstraint(_, ref r, ref p) => {
+ format!("RegionSubGenericConstraint({}, {})",
r.repr(tcx),
p.repr(tcx))
}
ast::ItemImpl(_, _, _, Some(_), _, _) => {
// "Trait" impl
debug!("coherence2::orphan check: trait impl {}", item.repr(self.tcx));
+ let trait_def_id = ty::impl_trait_ref(self.tcx, def_id).unwrap().def_id;
match traits::orphan_check(self.tcx, def_id) {
Ok(()) => { }
Err(traits::OrphanCheckErr::NoLocalInputType) => {
- span_err!(self.tcx.sess, item.span, E0117,
- "cannot provide an extension implementation \
- where both trait and type are not defined in this crate");
+ if !ty::has_attr(self.tcx, trait_def_id, "old_orphan_check") {
+ let self_ty = ty::lookup_item_type(self.tcx, def_id).ty;
+ span_err!(
+ self.tcx.sess, item.span, E0117,
+ "the type `{}` does not reference any \
+ types defined in this crate; \
+ only traits defined in the current crate can be \
+ implemented for arbitrary types",
+ self_ty.user_string(self.tcx));
+ }
}
- Err(traits::OrphanCheckErr::UncoveredTypeParameter(param_ty)) => {
- if !self.tcx.sess.features.borrow().old_orphan_check {
+ Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => {
+ if !ty::has_attr(self.tcx, trait_def_id, "old_orphan_check") {
self.tcx.sess.span_err(
item.span,
- format!("type parameter `{}` must also appear as a type parameter \
- of some type defined within this crate",
- param_ty.user_string(self.tcx)).as_slice());
+ format!(
+ "type parameter `{}` is not constrained by any local type; \
+ only traits defined in the current crate can be implemented \
+ for a type parameter",
+ param_ty.user_string(self.tcx)).as_slice());
self.tcx.sess.span_note(
item.span,
format!("for a limited time, you can add \
#![feature(unboxed_closures)]
#![allow(non_camel_case_types)]
-#[phase(plugin, link)] extern crate log;
-#[phase(plugin, link)] extern crate syntax;
+#[cfg(stage0)]
+#[phase(plugin, link)]
+extern crate log;
+
+#[cfg(not(stage0))]
+#[macro_use]
+extern crate log;
+
+#[cfg(stage0)]
+#[phase(plugin, link)]
+extern crate syntax;
+
+#[cfg(not(stage0))]
+#[macro_use]
+extern crate syntax;
extern crate arena;
extern crate rustc;
PatTup(ref elts) => format!("({})", elts.iter().map(|p| name_from_pat(&**p))
.collect::<Vec<String>>().connect(", ")),
PatBox(ref p) => name_from_pat(&**p),
- PatRegion(ref p) => name_from_pat(&**p),
+ PatRegion(ref p, _) => name_from_pat(&**p),
PatLit(..) => {
warn!("tried to get argument name from PatLit, \
which is silly in function arguments");
#[cfg(unix)]
mod imp {
+ use std::ffi::CString;
use libc;
- use std::c_str::ToCStr;
#[cfg(target_os = "linux")]
mod os {
impl Lock {
pub fn new(p: &Path) -> Lock {
- let fd = p.with_c_str(|s| unsafe {
- libc::open(s, libc::O_RDWR | libc::O_CREAT, libc::S_IRWXU)
- });
+ let buf = CString::from_slice(p.as_vec());
+ let fd = unsafe {
+ libc::open(buf.as_ptr(), libc::O_RDWR | libc::O_CREAT,
+ libc::S_IRWXU)
+ };
assert!(fd > 0);
let flock = os::flock {
l_start: 0,
}
}
+ // Special macro vars are like keywords
+ token::SpecialVarNt(_) => "kw-2",
+
token::Lifetime(..) => "lifetime",
token::DocComment(..) => "doccomment",
token::Underscore | token::Eof | token::Interpolated(..) |
use libc;
use std::ascii::AsciiExt;
-use std::c_str::ToCStr;
+use std::ffi::CString;
use std::cell::{RefCell, Cell};
use std::collections::HashMap;
use std::fmt;
let id = id.as_ref().map(|a| a.as_slice());
s.push_str(highlight::highlight(text.as_slice(), None, id)
.as_slice());
- let output = s.to_c_str();
+ let output = CString::from_vec(s.into_bytes());
hoedown_buffer_puts(ob, output.as_ptr());
})
}
extern fn header(ob: *mut hoedown_buffer, text: *const hoedown_buffer,
level: libc::c_int, opaque: *mut libc::c_void) {
// hoedown does this, we may as well too
- "\n".with_c_str(|p| unsafe { hoedown_buffer_puts(ob, p) });
+ unsafe { hoedown_buffer_puts(ob, "\n\0".as_ptr() as *const _); }
// Extract the text provided
let s = if text.is_null() {
"".to_string()
} else {
- unsafe {
- String::from_raw_buf_len((*text).data, (*text).size as uint)
- }
+ let s = unsafe {
+ slice::from_raw_buf(&(*text).data, (*text).size as uint)
+ };
+ str::from_utf8(s).unwrap().to_string()
};
// Transform the contents of the header into a hyphenated string
format!("{} ", sec)
});
- text.with_c_str(|p| unsafe { hoedown_buffer_puts(ob, p) });
+ let text = CString::from_vec(text.into_bytes());
+ unsafe { hoedown_buffer_puts(ob, text.as_ptr()) }
}
reset_headers();
cols += 1;
tmp /= 10;
}
- try!(write!(fmt, "<pre class='line-numbers'>"));
+ try!(write!(fmt, "<pre class=\"line-numbers\">"));
for i in range(1, lines + 1) {
- try!(write!(fmt, "<span id='{0}'>{0:1$}</span>\n", i, cols));
+ try!(write!(fmt, "<span id=\"{0}\">{0:1$}</span>\n", i, cols));
}
try!(write!(fmt, "</pre>"));
try!(write!(fmt, "{}", highlight::highlight(s.as_slice(), None, None)));
left: 0;
top: 0;
min-height: 100%;
+ z-index: -1;
}
.content, nav { max-width: 960px; }
overflow: auto;
padding-left: 0;
}
-.content pre.line-numbers { float: left; border: none; }
-.line-numbers span { color: #c67e2d; }
+.content pre.line-numbers {
+ float: left;
+ border: none;
+
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.line-numbers span { color: #c67e2d; cursor: pointer; }
.line-numbers .line-highlighted {
- background-color: #f6fdb0;
+ background-color: #f6fdb0 !important;
}
.content .highlighted {
.summary.Unmarked { background-color: #BBBBBB; }
:target { background: #FDFFD3; }
+.line-numbers :target { background-color: transparent; }
/* Code highlighting */
pre.rust .kw { color: #8959A8; }
resizeShortBlocks();
$(window).on('resize', resizeShortBlocks);
- function highlightSourceLines() {
+ function highlightSourceLines(ev) {
var i, from, to, match = window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/);
if (match) {
from = parseInt(match[1], 10);
if ($('#' + from).length === 0) {
return;
}
- $('#' + from)[0].scrollIntoView();
+ if (ev === null) $('#' + from)[0].scrollIntoView();
$('.line-numbers span').removeClass('line-highlighted');
for (i = from; i <= to; ++i) {
$('#' + i).addClass('line-highlighted');
}
}
}
- highlightSourceLines();
+ highlightSourceLines(null);
$(window).on('hashchange', highlightSourceLines);
$(document).on('keyup', function(e) {
$("#main > .docblock").before(wrapper);
});
+ $('pre.line-numbers').on('click', 'span', function() {
+ var prev_id = 0;
+
+ function set_fragment(name) {
+ if (history.replaceState) {
+ history.replaceState(null, null, '#' + name);
+ $(window).trigger('hashchange');
+ } else {
+ location.replace('#' + name);
+ }
+ }
+
+ return function(ev) {
+ var cur_id = parseInt(ev.target.id);
+
+ if (ev.shiftKey && prev_id) {
+ if (prev_id > cur_id) {
+ var tmp = prev_id;
+ prev_id = cur_id;
+ cur_id = tmp;
+ }
+
+ set_fragment(prev_id + '-' + cur_id);
+ } else {
+ prev_id = cur_id;
+
+ set_fragment(cur_id);
+ }
+ };
+ }());
+
}());
extern crate serialize;
extern crate syntax;
extern crate "test" as testing;
-#[phase(plugin, link)] extern crate log;
+
+#[cfg(stage0)]
+#[phase(plugin, link)]
+extern crate log;
+
+#[cfg(not(stage0))]
+#[macro_use]
+extern crate log;
extern crate "serialize" as rustc_serialize; // used by deriving
// reexported from `clean` so it can be easily updated with the mod itself
pub use clean::SCHEMA_VERSION;
+#[cfg_attr(stage0, macro_escape)]
+#[cfg_attr(not(stage0), macro_use)]
+pub mod externalfiles;
+
pub mod clean;
pub mod core;
pub mod doctree;
-#[macro_escape]
-pub mod externalfiles;
pub mod fold;
pub mod html {
pub mod highlight;
None);
// attach the crate's exported macros to the top-level module:
self.module.macros = krate.exported_macros.iter()
- .map(|it| self.visit_macro(&**it)).collect();
+ .map(|def| self.visit_macro(def)).collect();
self.module.is_crate = true;
}
}
// convert each exported_macro into a doc item
- fn visit_macro(&self, item: &ast::Item) -> Macro {
+ fn visit_macro(&self, def: &ast::MacroDef) -> Macro {
Macro {
- id: item.id,
- attrs: item.attrs.clone(),
- name: item.ident,
- whence: item.span,
- stab: self.stability(item.id),
+ id: def.id,
+ attrs: def.attrs.clone(),
+ name: def.ident,
+ whence: def.span,
+ stab: self.stability(def.id),
}
}
}
0123456789-_";
/// A trait for converting a value to base64 encoding.
-pub trait ToBase64 for Sized? {
+pub trait ToBase64 {
/// Converts the value of `self` to a base64 value following the specified
/// format configuration, returning the owned string.
fn to_base64(&self, config: Config) -> String;
}
/// A trait for converting from base64 encoded values.
-pub trait FromBase64 for Sized? {
+pub trait FromBase64 {
/// Converts the value of `self`, interpreted as base64 encoded data, into
/// an owned vector of bytes, returning the vector.
fn from_base64(&self) -> Result<Vec<u8>, FromBase64Error>;
use std::error;
/// A trait for converting a value to hexadecimal encoding
-pub trait ToHex for Sized? {
+pub trait ToHex {
/// Converts the value of `self` to a hex value, returning the owned
/// string.
fn to_hex(&self) -> String;
}
/// A trait for converting hexadecimal encoded values
-pub trait FromHex for Sized? {
+pub trait FromHex {
/// Converts the value of `self`, interpreted as hexadecimal encoded data,
/// into an owned vector of bytes, returning the vector.
fn from_hex(&self) -> Result<Vec<u8>, FromHexError>;
}
/// A trait for converting values to JSON
-pub trait ToJson for Sized? {
+pub trait ToJson {
/// Converts the value of `self` to an instance of JSON
fn to_json(&self) -> Json;
}
}
/// A trait for converting values to JSON
-pub trait ToJson for Sized? {
+pub trait ToJson {
/// Converts the value of `self` to an instance of JSON
fn to_json(&self) -> Json;
}
#[cfg(test)]
extern crate test;
+#[cfg(stage0)]
#[phase(plugin, link)]
extern crate log;
+
+#[cfg(not(stage0))]
+#[macro_use]
+extern crate log;
+
extern crate unicode;
extern crate collections;
fn error(&mut self, err: &str) -> Self::Error;
}
-pub trait Encodable for Sized? {
+pub trait Encodable {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error>;
}
}
}
-impl<'a, Sized? T: Encodable> Encodable for &'a T {
+impl<'a, T: ?Sized + Encodable> Encodable for &'a T {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
(**self).encode(s)
}
}
-impl<Sized? T: Encodable> Encodable for Box<T> {
+impl<T: ?Sized + Encodable> Encodable for Box<T> {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
(**self).encode(s)
}
fn error(&mut self, err: &str) -> E;
}
-pub trait Encodable<S:Encoder<E>, E> for Sized? {
+pub trait Encodable<S:Encoder<E>, E> {
fn encode(&self, s: &mut S) -> Result<(), E>;
}
}
}
-impl<'a, E, S: Encoder<E>, Sized? T: Encodable<S, E>> Encodable<S, E> for &'a T {
+impl<'a, E, S: Encoder<E>, T: ?Sized + Encodable<S, E>> Encodable<S, E> for &'a T {
fn encode(&self, s: &mut S) -> Result<(), E> {
(**self).encode(s)
}
}
-impl<E, S: Encoder<E>, Sized? T: Encodable<S, E>> Encodable<S, E> for Box<T> {
+impl<E, S: Encoder<E>, T: ?Sized + Encodable<S, E>> Encodable<S, E> for Box<T> {
fn encode(&self, s: &mut S) -> Result<(), E> {
(**self).encode(s)
}
#![unstable = "unsure about placement and naming"]
-use core::kinds::Sized;
use iter::IteratorExt;
use ops::FnMut;
use slice::SliceExt;
/// Extension methods for ASCII-subset only operations on string slices
#[experimental = "would prefer to do this in a more general way"]
-pub trait AsciiExt<T = Self> for Sized? {
+pub trait AsciiExt<T = Self> {
/// Check if within the ASCII range.
fn is_ascii(&self) -> bool;
fn to_ascii_lowercase(&self) -> T;
/// Check that two strings are an ASCII case-insensitive match.
- /// Same as `to_ascii_lowercase(a) == to_ascii_lower(b)`,
+ /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
/// but without allocating and copying temporary strings.
fn eq_ignore_ascii_case(&self, other: &Self) -> bool;
}
// except according to those terms.
#![experimental]
-#![macro_escape]
//! A typesafe bitmask flag generator.
+++ /dev/null
-// Copyright 2012 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.
-
-//! C-string manipulation and management
-//!
-//! This modules provides the basic methods for creating and manipulating
-//! null-terminated strings for use with FFI calls (back to C). Most C APIs require
-//! that the string being passed to them is null-terminated, and by default rust's
-//! string types are *not* null terminated.
-//!
-//! The other problem with translating Rust strings to C strings is that Rust
-//! strings can validly contain a null-byte in the middle of the string (0 is a
-//! valid Unicode codepoint). This means that not all Rust strings can actually be
-//! translated to C strings.
-//!
-//! # Creation of a C string
-//!
-//! A C string is managed through the `CString` type defined in this module. It
-//! "owns" the internal buffer of characters and will automatically deallocate the
-//! buffer when the string is dropped. The `ToCStr` trait is implemented for `&str`
-//! and `&[u8]`, but the conversions can fail due to some of the limitations
-//! explained above.
-//!
-//! This also means that currently whenever a C string is created, an allocation
-//! must be performed to place the data elsewhere (the lifetime of the C string is
-//! not tied to the lifetime of the original string/data buffer). If C strings are
-//! heavily used in applications, then caching may be advisable to prevent
-//! unnecessary amounts of allocations.
-//!
-//! Be carefull to remember that the memory is managed by C allocator API and not
-//! by Rust allocator API.
-//! That means that the CString pointers should be freed with C allocator API
-//! if you intend to do that on your own, as the behaviour if you free them with
-//! Rust's allocator API is not well defined
-//!
-//! An example of creating and using a C string would be:
-//!
-//! ```rust
-//! extern crate libc;
-//!
-//! use std::c_str::ToCStr;
-//!
-//! extern {
-//! fn puts(s: *const libc::c_char);
-//! }
-//!
-//! fn main() {
-//! let my_string = "Hello, world!";
-//!
-//! // Allocate the C string with an explicit local that owns the string. The
-//! // `c_buffer` pointer will be deallocated when `my_c_string` goes out of scope.
-//! let my_c_string = my_string.to_c_str();
-//! unsafe {
-//! puts(my_c_string.as_ptr());
-//! }
-//!
-//! // Don't save/return the pointer to the C string, the `c_buffer` will be
-//! // deallocated when this block returns!
-//! my_string.with_c_str(|c_buffer| {
-//! unsafe { puts(c_buffer); }
-//! });
-//! }
-//! ```
-
-use core::prelude::*;
-use libc;
-
-use cmp::Ordering;
-use fmt;
-use hash;
-use mem;
-use ptr;
-use slice::{self, IntSliceExt};
-use str;
-use string::String;
-use core::kinds::marker;
-
-/// The representation of a C String.
-///
-/// This structure wraps a `*libc::c_char`, and will automatically free the
-/// memory it is pointing to when it goes out of scope.
-#[allow(missing_copy_implementations)]
-pub struct CString {
- buf: *const libc::c_char,
- owns_buffer_: bool,
-}
-
-unsafe impl Send for CString { }
-unsafe impl Sync for CString { }
-
-impl Clone for CString {
- /// Clone this CString into a new, uniquely owned CString. For safety
- /// reasons, this is always a deep clone with the memory allocated
- /// with C's allocator API, rather than the usual shallow clone.
- fn clone(&self) -> CString {
- let len = self.len() + 1;
- let buf = unsafe { libc::malloc(len as libc::size_t) } as *mut libc::c_char;
- if buf.is_null() { ::alloc::oom() }
- unsafe { ptr::copy_nonoverlapping_memory(buf, self.buf, len); }
- CString { buf: buf as *const libc::c_char, owns_buffer_: true }
- }
-}
-
-impl PartialEq for CString {
- fn eq(&self, other: &CString) -> bool {
- // Check if the two strings share the same buffer
- if self.buf as uint == other.buf as uint {
- true
- } else {
- unsafe {
- libc::strcmp(self.buf, other.buf) == 0
- }
- }
- }
-}
-
-impl PartialOrd for CString {
- #[inline]
- fn partial_cmp(&self, other: &CString) -> Option<Ordering> {
- self.as_bytes().partial_cmp(other.as_bytes())
- }
-}
-
-impl Eq for CString {}
-
-impl<S: hash::Writer> hash::Hash<S> for CString {
- #[inline]
- fn hash(&self, state: &mut S) {
- self.as_bytes().hash(state)
- }
-}
-
-impl CString {
- /// Create a C String from a pointer, with memory managed by C's allocator
- /// API, so avoid calling it with a pointer to memory managed by Rust's
- /// allocator API, as the behaviour would not be well defined.
- ///
- ///# Panics
- ///
- /// Panics if `buf` is null
- pub unsafe fn new(buf: *const libc::c_char, owns_buffer: bool) -> CString {
- assert!(!buf.is_null());
- CString { buf: buf, owns_buffer_: owns_buffer }
- }
-
- /// Return a pointer to the NUL-terminated string data.
- ///
- /// `.as_ptr` returns an internal pointer into the `CString`, and
- /// may be invalidated when the `CString` falls out of scope (the
- /// destructor will run, freeing the allocation if there is
- /// one).
- ///
- /// ```rust
- /// use std::c_str::ToCStr;
- ///
- /// let foo = "some string";
- ///
- /// // right
- /// let x = foo.to_c_str();
- /// let p = x.as_ptr();
- ///
- /// // wrong (the CString will be freed, invalidating `p`)
- /// let p = foo.to_c_str().as_ptr();
- /// ```
- ///
- /// # Example
- ///
- /// ```rust
- /// extern crate libc;
- ///
- /// use std::c_str::ToCStr;
- ///
- /// fn main() {
- /// let c_str = "foo bar".to_c_str();
- /// unsafe {
- /// libc::puts(c_str.as_ptr());
- /// }
- /// }
- /// ```
- pub fn as_ptr(&self) -> *const libc::c_char {
- self.buf
- }
-
- /// Return a mutable pointer to the NUL-terminated string data.
- ///
- /// `.as_mut_ptr` returns an internal pointer into the `CString`, and
- /// may be invalidated when the `CString` falls out of scope (the
- /// destructor will run, freeing the allocation if there is
- /// one).
- ///
- /// ```rust
- /// use std::c_str::ToCStr;
- ///
- /// let foo = "some string";
- ///
- /// // right
- /// let mut x = foo.to_c_str();
- /// let p = x.as_mut_ptr();
- ///
- /// // wrong (the CString will be freed, invalidating `p`)
- /// let p = foo.to_c_str().as_mut_ptr();
- /// ```
- pub fn as_mut_ptr(&mut self) -> *mut libc::c_char {
- self.buf as *mut _
- }
-
- /// Returns whether or not the `CString` owns the buffer.
- pub fn owns_buffer(&self) -> bool {
- self.owns_buffer_
- }
-
- /// Converts the CString into a `&[u8]` without copying.
- /// Includes the terminating NUL byte.
- #[inline]
- pub fn as_bytes<'a>(&'a self) -> &'a [u8] {
- unsafe {
- slice::from_raw_buf(&self.buf, self.len() + 1).as_unsigned()
- }
- }
-
- /// Converts the CString into a `&[u8]` without copying.
- /// Does not include the terminating NUL byte.
- #[inline]
- pub fn as_bytes_no_nul<'a>(&'a self) -> &'a [u8] {
- unsafe {
- slice::from_raw_buf(&self.buf, self.len()).as_unsigned()
- }
- }
-
- /// Converts the CString into a `&str` without copying.
- /// Returns None if the CString is not UTF-8.
- #[inline]
- pub fn as_str<'a>(&'a self) -> Option<&'a str> {
- let buf = self.as_bytes_no_nul();
- str::from_utf8(buf).ok()
- }
-
- /// Return a CString iterator.
- pub fn iter<'a>(&'a self) -> CChars<'a> {
- CChars {
- ptr: self.buf,
- marker: marker::ContravariantLifetime,
- }
- }
-
- /// Unwraps the wrapped `*libc::c_char` from the `CString` wrapper.
- ///
- /// Any ownership of the buffer by the `CString` wrapper is
- /// forgotten, meaning that the backing allocation of this
- /// `CString` is not automatically freed if it owns the
- /// allocation. In this case, a user of `.unwrap()` should ensure
- /// the allocation is freed, to avoid leaking memory. You should
- /// use libc's memory allocator in this case.
- ///
- /// Prefer `.as_ptr()` when just retrieving a pointer to the
- /// string data, as that does not relinquish ownership.
- pub unsafe fn into_inner(mut self) -> *const libc::c_char {
- self.owns_buffer_ = false;
- self.buf
- }
-
- /// Return the number of bytes in the CString (not including the NUL
- /// terminator).
- #[inline]
- pub fn len(&self) -> uint {
- unsafe { libc::strlen(self.buf) as uint }
- }
-
- /// Returns if there are no bytes in this string
- #[inline]
- pub fn is_empty(&self) -> bool { self.len() == 0 }
-}
-
-impl Drop for CString {
- fn drop(&mut self) {
- if self.owns_buffer_ {
- unsafe {
- libc::free(self.buf as *mut libc::c_void)
- }
- }
- }
-}
-
-impl fmt::Show for CString {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- String::from_utf8_lossy(self.as_bytes_no_nul()).fmt(f)
- }
-}
-
-/// A generic trait for converting a value to a CString.
-pub trait ToCStr for Sized? {
- /// Copy the receiver into a CString.
- ///
- /// # Panics
- ///
- /// Panics the task if the receiver has an interior null.
- fn to_c_str(&self) -> CString;
-
- /// Unsafe variant of `to_c_str()` that doesn't check for nulls.
- unsafe fn to_c_str_unchecked(&self) -> CString;
-
- /// Work with a temporary CString constructed from the receiver.
- /// The provided `*libc::c_char` will be freed immediately upon return.
- ///
- /// # Example
- ///
- /// ```rust
- /// extern crate libc;
- ///
- /// use std::c_str::ToCStr;
- ///
- /// fn main() {
- /// let s = "PATH".with_c_str(|path| unsafe {
- /// libc::getenv(path)
- /// });
- /// }
- /// ```
- ///
- /// # Panics
- ///
- /// Panics the task if the receiver has an interior null.
- #[inline]
- fn with_c_str<T, F>(&self, f: F) -> T where
- F: FnOnce(*const libc::c_char) -> T,
- {
- let c_str = self.to_c_str();
- f(c_str.as_ptr())
- }
-
- /// Unsafe variant of `with_c_str()` that doesn't check for nulls.
- #[inline]
- unsafe fn with_c_str_unchecked<T, F>(&self, f: F) -> T where
- F: FnOnce(*const libc::c_char) -> T,
- {
- let c_str = self.to_c_str_unchecked();
- f(c_str.as_ptr())
- }
-}
-
-impl ToCStr for str {
- #[inline]
- fn to_c_str(&self) -> CString {
- self.as_bytes().to_c_str()
- }
-
- #[inline]
- unsafe fn to_c_str_unchecked(&self) -> CString {
- self.as_bytes().to_c_str_unchecked()
- }
-
- #[inline]
- fn with_c_str<T, F>(&self, f: F) -> T where
- F: FnOnce(*const libc::c_char) -> T,
- {
- self.as_bytes().with_c_str(f)
- }
-
- #[inline]
- unsafe fn with_c_str_unchecked<T, F>(&self, f: F) -> T where
- F: FnOnce(*const libc::c_char) -> T,
- {
- self.as_bytes().with_c_str_unchecked(f)
- }
-}
-
-impl ToCStr for String {
- #[inline]
- fn to_c_str(&self) -> CString {
- self.as_bytes().to_c_str()
- }
-
- #[inline]
- unsafe fn to_c_str_unchecked(&self) -> CString {
- self.as_bytes().to_c_str_unchecked()
- }
-
- #[inline]
- fn with_c_str<T, F>(&self, f: F) -> T where
- F: FnOnce(*const libc::c_char) -> T,
- {
- self.as_bytes().with_c_str(f)
- }
-
- #[inline]
- unsafe fn with_c_str_unchecked<T, F>(&self, f: F) -> T where
- F: FnOnce(*const libc::c_char) -> T,
- {
- self.as_bytes().with_c_str_unchecked(f)
- }
-}
-
-// The length of the stack allocated buffer for `vec.with_c_str()`
-const BUF_LEN: uint = 128;
-
-impl ToCStr for [u8] {
- fn to_c_str(&self) -> CString {
- let mut cs = unsafe { self.to_c_str_unchecked() };
- check_for_null(self, cs.as_mut_ptr());
- cs
- }
-
- unsafe fn to_c_str_unchecked(&self) -> CString {
- let self_len = self.len();
- let buf = libc::malloc(self_len as libc::size_t + 1) as *mut u8;
- if buf.is_null() { ::alloc::oom() }
-
- ptr::copy_memory(buf, self.as_ptr(), self_len);
- *buf.offset(self_len as int) = 0;
-
- CString::new(buf as *const libc::c_char, true)
- }
-
- fn with_c_str<T, F>(&self, f: F) -> T where
- F: FnOnce(*const libc::c_char) -> T,
- {
- unsafe { with_c_str(self, true, f) }
- }
-
- unsafe fn with_c_str_unchecked<T, F>(&self, f: F) -> T where
- F: FnOnce(*const libc::c_char) -> T,
- {
- with_c_str(self, false, f)
- }
-}
-
-impl<'a, Sized? T: ToCStr> ToCStr for &'a T {
- #[inline]
- fn to_c_str(&self) -> CString {
- (**self).to_c_str()
- }
-
- #[inline]
- unsafe fn to_c_str_unchecked(&self) -> CString {
- (**self).to_c_str_unchecked()
- }
-
- #[inline]
- fn with_c_str<T, F>(&self, f: F) -> T where
- F: FnOnce(*const libc::c_char) -> T,
- {
- (**self).with_c_str(f)
- }
-
- #[inline]
- unsafe fn with_c_str_unchecked<T, F>(&self, f: F) -> T where
- F: FnOnce(*const libc::c_char) -> T,
- {
- (**self).with_c_str_unchecked(f)
- }
-}
-
-// Unsafe function that handles possibly copying the &[u8] into a stack array.
-unsafe fn with_c_str<T, F>(v: &[u8], checked: bool, f: F) -> T where
- F: FnOnce(*const libc::c_char) -> T,
-{
- let c_str = if v.len() < BUF_LEN {
- let mut buf: [u8; BUF_LEN] = mem::uninitialized();
- slice::bytes::copy_memory(&mut buf, v);
- buf[v.len()] = 0;
-
- let buf = buf.as_mut_ptr();
- if checked {
- check_for_null(v, buf as *mut libc::c_char);
- }
-
- return f(buf as *const libc::c_char)
- } else if checked {
- v.to_c_str()
- } else {
- v.to_c_str_unchecked()
- };
-
- f(c_str.as_ptr())
-}
-
-#[inline]
-fn check_for_null(v: &[u8], buf: *mut libc::c_char) {
- for i in range(0, v.len()) {
- unsafe {
- let p = buf.offset(i as int);
- assert!(*p != 0);
- }
- }
-}
-
-/// External iterator for a CString's bytes.
-///
-/// Use with the `std::iter` module.
-#[allow(raw_pointer_deriving)]
-#[derive(Clone)]
-pub struct CChars<'a> {
- ptr: *const libc::c_char,
- marker: marker::ContravariantLifetime<'a>,
-}
-
-impl<'a> Iterator for CChars<'a> {
- type Item = libc::c_char;
-
- fn next(&mut self) -> Option<libc::c_char> {
- let ch = unsafe { *self.ptr };
- if ch == 0 {
- None
- } else {
- self.ptr = unsafe { self.ptr.offset(1) };
- Some(ch)
- }
- }
-}
-
-/// Parses a C "multistring", eg windows env values or
-/// the req->ptr result in a uv_fs_readdir() call.
-///
-/// Optionally, a `count` can be passed in, limiting the
-/// parsing to only being done `count`-times.
-///
-/// The specified closure is invoked with each string that
-/// is found, and the number of strings found is returned.
-pub unsafe fn from_c_multistring<F>(buf: *const libc::c_char,
- count: Option<uint>,
- mut f: F)
- -> uint where
- F: FnMut(&CString),
-{
-
- let mut curr_ptr: uint = buf as uint;
- let mut ctr = 0;
- let (limited_count, limit) = match count {
- Some(limit) => (true, limit),
- None => (false, 0)
- };
- while ((limited_count && ctr < limit) || !limited_count)
- && *(curr_ptr as *const libc::c_char) != 0 as libc::c_char {
- let cstr = CString::new(curr_ptr as *const libc::c_char, false);
- f(&cstr);
- curr_ptr += cstr.len() + 1;
- ctr += 1;
- }
- return ctr;
-}
-
-#[cfg(test)]
-mod tests {
- use prelude::v1::*;
- use super::*;
- use ptr;
- use thread::Thread;
- use libc;
-
- #[test]
- fn test_str_multistring_parsing() {
- unsafe {
- let input = b"zero\0one\0\0";
- let ptr = input.as_ptr();
- let expected = ["zero", "one"];
- let mut it = expected.iter();
- let result = from_c_multistring(ptr as *const libc::c_char, None, |c| {
- let cbytes = c.as_bytes_no_nul();
- assert_eq!(cbytes, it.next().unwrap().as_bytes());
- });
- assert_eq!(result, 2);
- assert!(it.next().is_none());
- }
- }
-
- #[test]
- fn test_str_to_c_str() {
- let c_str = "".to_c_str();
- unsafe {
- assert_eq!(*c_str.as_ptr().offset(0), 0);
- }
-
- let c_str = "hello".to_c_str();
- let buf = c_str.as_ptr();
- unsafe {
- assert_eq!(*buf.offset(0), 'h' as libc::c_char);
- assert_eq!(*buf.offset(1), 'e' as libc::c_char);
- assert_eq!(*buf.offset(2), 'l' as libc::c_char);
- assert_eq!(*buf.offset(3), 'l' as libc::c_char);
- assert_eq!(*buf.offset(4), 'o' as libc::c_char);
- assert_eq!(*buf.offset(5), 0);
- }
- }
-
- #[test]
- fn test_vec_to_c_str() {
- let b: &[u8] = &[];
- let c_str = b.to_c_str();
- unsafe {
- assert_eq!(*c_str.as_ptr().offset(0), 0);
- }
-
- let c_str = b"hello".to_c_str();
- let buf = c_str.as_ptr();
- unsafe {
- assert_eq!(*buf.offset(0), 'h' as libc::c_char);
- assert_eq!(*buf.offset(1), 'e' as libc::c_char);
- assert_eq!(*buf.offset(2), 'l' as libc::c_char);
- assert_eq!(*buf.offset(3), 'l' as libc::c_char);
- assert_eq!(*buf.offset(4), 'o' as libc::c_char);
- assert_eq!(*buf.offset(5), 0);
- }
-
- let c_str = b"foo\xFF".to_c_str();
- let buf = c_str.as_ptr();
- unsafe {
- assert_eq!(*buf.offset(0), 'f' as libc::c_char);
- assert_eq!(*buf.offset(1), 'o' as libc::c_char);
- assert_eq!(*buf.offset(2), 'o' as libc::c_char);
- assert_eq!(*buf.offset(3), 0xffu8 as libc::c_char);
- assert_eq!(*buf.offset(4), 0);
- }
- }
-
- #[test]
- fn test_unwrap() {
- let c_str = "hello".to_c_str();
- unsafe { libc::free(c_str.into_inner() as *mut libc::c_void) }
- }
-
- #[test]
- fn test_as_ptr() {
- let c_str = "hello".to_c_str();
- let len = unsafe { libc::strlen(c_str.as_ptr()) };
- assert_eq!(len, 5);
- }
-
- #[test]
- fn test_iterator() {
- let c_str = "".to_c_str();
- let mut iter = c_str.iter();
- assert_eq!(iter.next(), None);
-
- let c_str = "hello".to_c_str();
- let mut iter = c_str.iter();
- assert_eq!(iter.next(), Some('h' as libc::c_char));
- assert_eq!(iter.next(), Some('e' as libc::c_char));
- assert_eq!(iter.next(), Some('l' as libc::c_char));
- assert_eq!(iter.next(), Some('l' as libc::c_char));
- assert_eq!(iter.next(), Some('o' as libc::c_char));
- assert_eq!(iter.next(), None);
- }
-
- #[test]
- fn test_to_c_str_fail() {
- assert!(Thread::spawn(move|| { "he\x00llo".to_c_str() }).join().is_err());
- }
-
- #[test]
- fn test_to_c_str_unchecked() {
- unsafe {
- let c_string = "he\x00llo".to_c_str_unchecked();
- let buf = c_string.as_ptr();
- assert_eq!(*buf.offset(0), 'h' as libc::c_char);
- assert_eq!(*buf.offset(1), 'e' as libc::c_char);
- assert_eq!(*buf.offset(2), 0);
- assert_eq!(*buf.offset(3), 'l' as libc::c_char);
- assert_eq!(*buf.offset(4), 'l' as libc::c_char);
- assert_eq!(*buf.offset(5), 'o' as libc::c_char);
- assert_eq!(*buf.offset(6), 0);
- }
- }
-
- #[test]
- fn test_as_bytes() {
- let c_str = "hello".to_c_str();
- assert_eq!(c_str.as_bytes(), b"hello\0");
- let c_str = "".to_c_str();
- assert_eq!(c_str.as_bytes(), b"\0");
- let c_str = b"foo\xFF".to_c_str();
- assert_eq!(c_str.as_bytes(), b"foo\xFF\0");
- }
-
- #[test]
- fn test_as_bytes_no_nul() {
- let c_str = "hello".to_c_str();
- assert_eq!(c_str.as_bytes_no_nul(), b"hello");
- let c_str = "".to_c_str();
- let exp: &[u8] = &[];
- assert_eq!(c_str.as_bytes_no_nul(), exp);
- let c_str = b"foo\xFF".to_c_str();
- assert_eq!(c_str.as_bytes_no_nul(), b"foo\xFF");
- }
-
- #[test]
- fn test_as_str() {
- let c_str = "hello".to_c_str();
- assert_eq!(c_str.as_str(), Some("hello"));
- let c_str = "".to_c_str();
- assert_eq!(c_str.as_str(), Some(""));
- let c_str = b"foo\xFF".to_c_str();
- assert_eq!(c_str.as_str(), None);
- }
-
- #[test]
- #[should_fail]
- fn test_new_fail() {
- let _c_str = unsafe { CString::new(ptr::null(), false) };
- }
-
- #[test]
- fn test_clone() {
- let a = "hello".to_c_str();
- let b = a.clone();
- assert!(a == b);
- }
-
- #[test]
- fn test_clone_noleak() {
- fn foo<F>(f: F) where F: FnOnce(&CString) {
- let s = "test".to_string();
- let c = s.to_c_str();
- // give the closure a non-owned CString
- let mut c_ = unsafe { CString::new(c.as_ptr(), false) };
- f(&c_);
- // muck with the buffer for later printing
- unsafe { *c_.as_mut_ptr() = 'X' as libc::c_char }
- }
-
- let mut c_: Option<CString> = None;
- foo(|c| {
- c_ = Some(c.clone());
- c.clone();
- // force a copy, reading the memory
- c.as_bytes().to_vec();
- });
- let c_ = c_.unwrap();
- // force a copy, reading the memory
- c_.as_bytes().to_vec();
- }
-}
-
-#[cfg(test)]
-mod bench {
- extern crate test;
-
- use prelude::v1::*;
- use self::test::Bencher;
- use libc;
- use c_str::ToCStr;
-
- #[inline]
- fn check(s: &str, c_str: *const libc::c_char) {
- let s_buf = s.as_ptr();
- for i in range(0, s.len()) {
- unsafe {
- assert_eq!(
- *s_buf.offset(i as int) as libc::c_char,
- *c_str.offset(i as int));
- }
- }
- }
-
- static S_SHORT: &'static str = "Mary";
- static S_MEDIUM: &'static str = "Mary had a little lamb";
- static S_LONG: &'static str = "\
- Mary had a little lamb, Little lamb
- Mary had a little lamb, Little lamb
- Mary had a little lamb, Little lamb
- Mary had a little lamb, Little lamb
- Mary had a little lamb, Little lamb
- Mary had a little lamb, Little lamb";
-
- fn bench_to_string(b: &mut Bencher, s: &str) {
- b.iter(|| {
- let c_str = s.to_c_str();
- check(s, c_str.as_ptr());
- })
- }
-
- #[bench]
- fn bench_to_c_str_short(b: &mut Bencher) {
- bench_to_string(b, S_SHORT)
- }
-
- #[bench]
- fn bench_to_c_str_medium(b: &mut Bencher) {
- bench_to_string(b, S_MEDIUM)
- }
-
- #[bench]
- fn bench_to_c_str_long(b: &mut Bencher) {
- bench_to_string(b, S_LONG)
- }
-
- fn bench_to_c_str_unchecked(b: &mut Bencher, s: &str) {
- b.iter(|| {
- let c_str = unsafe { s.to_c_str_unchecked() };
- check(s, c_str.as_ptr())
- })
- }
-
- #[bench]
- fn bench_to_c_str_unchecked_short(b: &mut Bencher) {
- bench_to_c_str_unchecked(b, S_SHORT)
- }
-
- #[bench]
- fn bench_to_c_str_unchecked_medium(b: &mut Bencher) {
- bench_to_c_str_unchecked(b, S_MEDIUM)
- }
-
- #[bench]
- fn bench_to_c_str_unchecked_long(b: &mut Bencher) {
- bench_to_c_str_unchecked(b, S_LONG)
- }
-
- fn bench_with_c_str(b: &mut Bencher, s: &str) {
- b.iter(|| {
- s.with_c_str(|c_str_buf| check(s, c_str_buf))
- })
- }
-
- #[bench]
- fn bench_with_c_str_short(b: &mut Bencher) {
- bench_with_c_str(b, S_SHORT)
- }
-
- #[bench]
- fn bench_with_c_str_medium(b: &mut Bencher) {
- bench_with_c_str(b, S_MEDIUM)
- }
-
- #[bench]
- fn bench_with_c_str_long(b: &mut Bencher) {
- bench_with_c_str(b, S_LONG)
- }
-
- fn bench_with_c_str_unchecked(b: &mut Bencher, s: &str) {
- b.iter(|| {
- unsafe {
- s.with_c_str_unchecked(|c_str_buf| check(s, c_str_buf))
- }
- })
- }
-
- #[bench]
- fn bench_with_c_str_unchecked_short(b: &mut Bencher) {
- bench_with_c_str_unchecked(b, S_SHORT)
- }
-
- #[bench]
- fn bench_with_c_str_unchecked_medium(b: &mut Bencher) {
- bench_with_c_str_unchecked(b, S_MEDIUM)
- }
-
- #[bench]
- fn bench_with_c_str_unchecked_long(b: &mut Bencher) {
- bench_with_c_str_unchecked(b, S_LONG)
- }
-}
+++ /dev/null
-// Copyright 2012 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.
-
-//! Library to interface with chunks of memory allocated in C.
-//!
-//! It is often desirable to safely interface with memory allocated from C,
-//! encapsulating the unsafety into allocation and destruction time. Indeed,
-//! allocating memory externally is currently the only way to give Rust shared
-//! mut state with C programs that keep their own references; vectors are
-//! unsuitable because they could be reallocated or moved at any time, and
-//! importing C memory into a vector takes a one-time snapshot of the memory.
-//!
-//! This module simplifies the usage of such external blocks of memory. Memory
-//! is encapsulated into an opaque object after creation; the lifecycle of the
-//! memory can be optionally managed by Rust, if an appropriate destructor
-//! closure is provided. Safety is ensured by bounds-checking accesses, which
-//! are marshalled through get and set functions.
-//!
-//! There are three unsafe functions: the two constructors, and the
-//! unwrap method. The constructors are unsafe for the
-//! obvious reason (they act on a pointer that cannot be checked inside the
-//! method), but `unwrap()` is somewhat more subtle in its unsafety.
-//! It returns the contained pointer, but at the same time destroys the CVec
-//! without running its destructor. This can be used to pass memory back to
-//! C, but care must be taken that the ownership of underlying resources are
-//! handled correctly, i.e. that allocated memory is eventually freed
-//! if necessary.
-
-#![experimental]
-
-use kinds::Send;
-use mem;
-use ops::{Drop, FnOnce};
-use option::Option;
-use option::Option::{Some, None};
-use ptr::PtrExt;
-use ptr;
-use raw;
-use slice::AsSlice;
-use thunk::{Thunk};
-
-/// The type representing a foreign chunk of memory
-pub struct CVec<T> {
- base: *mut T,
- len: uint,
- dtor: Option<Thunk>,
-}
-
-#[unsafe_destructor]
-impl<T> Drop for CVec<T> {
- fn drop(&mut self) {
- match self.dtor.take() {
- None => (),
- Some(f) => f.invoke(())
- }
- }
-}
-
-impl<T> CVec<T> {
- /// Create a `CVec` from a raw pointer to a buffer with a given length.
- ///
- /// Panics if the given pointer is null. The returned vector will not attempt
- /// to deallocate the vector when dropped.
- ///
- /// # Arguments
- ///
- /// * base - A raw pointer to a buffer
- /// * len - The number of elements in the buffer
- pub unsafe fn new(base: *mut T, len: uint) -> CVec<T> {
- assert!(base != ptr::null_mut());
- CVec {
- base: base,
- len: len,
- dtor: None,
- }
- }
-
- /// Create a `CVec` from a foreign buffer, with a given length,
- /// and a function to run upon destruction.
- ///
- /// Panics if the given pointer is null.
- ///
- /// # Arguments
- ///
- /// * base - A foreign pointer to a buffer
- /// * len - The number of elements in the buffer
- /// * dtor - A fn to run when the value is destructed, useful
- /// for freeing the buffer, etc.
- pub unsafe fn new_with_dtor<F>(base: *mut T,
- len: uint,
- dtor: F)
- -> CVec<T>
- where F : FnOnce(), F : Send
- {
- assert!(base != ptr::null_mut());
- let dtor: Thunk = Thunk::new(dtor);
- CVec {
- base: base,
- len: len,
- dtor: Some(dtor)
- }
- }
-
- /// View the stored data as a mutable slice.
- pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
- unsafe {
- mem::transmute(raw::Slice { data: self.base as *const T, len: self.len })
- }
- }
-
- /// Retrieves an element at a given index, returning `None` if the requested
- /// index is greater than the length of the vector.
- pub fn get<'a>(&'a self, ofs: uint) -> Option<&'a T> {
- if ofs < self.len {
- Some(unsafe { &*self.base.offset(ofs as int) })
- } else {
- None
- }
- }
-
- /// Retrieves a mutable element at a given index, returning `None` if the
- /// requested index is greater than the length of the vector.
- pub fn get_mut<'a>(&'a mut self, ofs: uint) -> Option<&'a mut T> {
- if ofs < self.len {
- Some(unsafe { &mut *self.base.offset(ofs as int) })
- } else {
- None
- }
- }
-
- /// Unwrap the pointer without running the destructor
- ///
- /// This method retrieves the underlying pointer, and in the process
- /// destroys the CVec but without running the destructor. A use case
- /// would be transferring ownership of the buffer to a C function, as
- /// in this case you would not want to run the destructor.
- ///
- /// Note that if you want to access the underlying pointer without
- /// cancelling the destructor, you can simply call `transmute` on the return
- /// value of `get(0)`.
- pub unsafe fn into_inner(mut self) -> *mut T {
- self.dtor = None;
- self.base
- }
-
- /// Returns the number of items in this vector.
- pub fn len(&self) -> uint { self.len }
-
- /// Returns whether this vector is empty.
- pub fn is_empty(&self) -> bool { self.len() == 0 }
-}
-
-impl<T> AsSlice<T> for CVec<T> {
- /// View the stored data as a slice.
- fn as_slice<'a>(&'a self) -> &'a [T] {
- unsafe {
- mem::transmute(raw::Slice { data: self.base as *const T, len: self.len })
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
- use prelude::v1::*;
-
- use super::CVec;
- use libc;
- use ptr;
-
- fn malloc(n: uint) -> CVec<u8> {
- unsafe {
- let mem = ptr::Unique(libc::malloc(n as libc::size_t));
- if mem.0.is_null() { ::alloc::oom() }
-
- CVec::new_with_dtor(mem.0 as *mut u8,
- n,
- move|| { libc::free(mem.0 as *mut libc::c_void); })
- }
- }
-
- #[test]
- fn test_basic() {
- let mut cv = malloc(16);
-
- *cv.get_mut(3).unwrap() = 8;
- *cv.get_mut(4).unwrap() = 9;
- assert_eq!(*cv.get(3).unwrap(), 8);
- assert_eq!(*cv.get(4).unwrap(), 9);
- assert_eq!(cv.len(), 16);
- }
-
- #[test]
- #[should_fail]
- fn test_panic_at_null() {
- unsafe {
- CVec::new(ptr::null_mut::<u8>(), 9);
- }
- }
-
- #[test]
- fn test_overrun_get() {
- let cv = malloc(16);
-
- assert!(cv.get(17).is_none());
- }
-
- #[test]
- fn test_overrun_set() {
- let mut cv = malloc(16);
-
- assert!(cv.get_mut(17).is_none());
- }
-
- #[test]
- fn test_unwrap() {
- unsafe {
- let cv = CVec::new_with_dtor(1 as *mut int,
- 0,
- move|:| panic!("Don't run this destructor!"));
- let p = cv.into_inner();
- assert_eq!(p, 1 as *mut int);
- }
- }
-
-}
}
impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
- fn make_hash<Sized? X: Hash<S>>(&self, x: &X) -> SafeHash {
+ fn make_hash<X: ?Sized + Hash<S>>(&self, x: &X) -> SafeHash {
table::make_hash(&self.hasher, x)
}
/// Search for a key, yielding the index if it's found in the hashtable.
/// If you already have the hash for the key lying around, use
/// search_hashed.
- fn search<'a, Sized? Q>(&'a self, q: &Q) -> Option<FullBucketImm<'a, K, V>>
+ fn search<'a, Q: ?Sized>(&'a self, q: &Q) -> Option<FullBucketImm<'a, K, V>>
where Q: BorrowFrom<K> + Eq + Hash<S>
{
let hash = self.make_hash(q);
.into_option()
}
- fn search_mut<'a, Sized? Q>(&'a mut self, q: &Q) -> Option<FullBucketMut<'a, K, V>>
+ fn search_mut<'a, Q: ?Sized>(&'a mut self, q: &Q) -> Option<FullBucketMut<'a, K, V>>
where Q: BorrowFrom<K> + Eq + Hash<S>
{
let hash = self.make_hash(q);
#[stable]
/// Gets the given key's corresponding entry in the map for in-place manipulation.
/// Regardless of whether or not `to_owned()` has been called, the key must hash the same way.
- pub fn entry<'a, Sized? Q>(&'a mut self, key: &'a Q) -> Entry<'a, Q, K, V>
+ pub fn entry<'a, Q: ?Sized>(&'a mut self, key: &'a Q) -> Entry<'a, Q, K, V>
where Q: Eq + Hash<S> + ToOwned<K>
{
// Gotta resize now.
/// assert_eq!(map.get(&2), None);
/// ```
#[stable]
- pub fn get<Sized? Q>(&self, k: &Q) -> Option<&V>
+ pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
where Q: Hash<S> + Eq + BorrowFrom<K>
{
self.search(k).map(|bucket| bucket.into_refs().1)
/// assert_eq!(map.contains_key(&2), false);
/// ```
#[stable]
- pub fn contains_key<Sized? Q>(&self, k: &Q) -> bool
+ pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
where Q: Hash<S> + Eq + BorrowFrom<K>
{
self.search(k).is_some()
/// assert_eq!(map[1], "b");
/// ```
#[stable]
- pub fn get_mut<Sized? Q>(&mut self, k: &Q) -> Option<&mut V>
+ pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
where Q: Hash<S> + Eq + BorrowFrom<K>
{
self.search_mut(k).map(|bucket| bucket.into_mut_refs().1)
/// assert_eq!(map.remove(&1), None);
/// ```
#[stable]
- pub fn remove<Sized? Q>(&mut self, k: &Q) -> Option<V>
+ pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
where Q: Hash<S> + Eq + BorrowFrom<K>
{
if self.table.size() == 0 {
}
}
-fn search_entry_hashed<'a, K, V, Sized? Q>(table: &'a mut RawTable<K,V>, hash: SafeHash, k: &'a Q)
+fn search_entry_hashed<'a, K, V, Q: ?Sized>(table: &'a mut RawTable<K,V>, hash: SafeHash, k: &'a Q)
-> Entry<'a, Q, K, V>
where Q: Eq + ToOwned<K>
{
}
#[stable]
-impl<K: Hash<S> + Eq, Sized? Q, V, S, H: Hasher<S>> Index<Q> for HashMap<K, V, H>
+impl<K: Hash<S> + Eq, Q: ?Sized, V, S, H: Hasher<S>> Index<Q> for HashMap<K, V, H>
where Q: BorrowFrom<K> + Hash<S> + Eq
{
type Output = V;
}
#[stable]
-impl<K: Hash<S> + Eq, Sized? Q, V, S, H: Hasher<S>> IndexMut<Q> for HashMap<K, V, H>
+impl<K: Hash<S> + Eq, Q: ?Sized, V, S, H: Hasher<S>> IndexMut<Q> for HashMap<K, V, H>
where Q: BorrowFrom<K> + Hash<S> + Eq
{
type Output = V;
#[stable]
/// A view into a single empty location in a HashMap
-pub struct VacantEntry<'a, Sized? Q: 'a, K: 'a, V: 'a> {
+pub struct VacantEntry<'a, Q: ?Sized + 'a, K: 'a, V: 'a> {
hash: SafeHash,
key: &'a Q,
elem: VacantEntryState<K, V, &'a mut RawTable<K, V>>,
#[stable]
/// A view into a single location in a map, which may be vacant or occupied
-pub enum Entry<'a, Sized? Q: 'a, K: 'a, V: 'a> {
+pub enum Entry<'a, Q: ?Sized + 'a, K: 'a, V: 'a> {
/// An occupied Entry
Occupied(OccupiedEntry<'a, K, V>),
/// A vacant Entry
}
}
-impl<'a, Sized? Q, K, V> Entry<'a, Q, K, V> {
+impl<'a, Q: ?Sized, K, V> Entry<'a, Q, K, V> {
#[unstable = "matches collection reform v2 specification, waiting for dust to settle"]
/// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant
pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, Q, K, V>> {
}
}
-impl<'a, Sized? Q: 'a + ToOwned<K>, K: 'a, V: 'a> VacantEntry<'a, Q, K, V> {
+impl<'a, Q: ?Sized + 'a + ToOwned<K>, K: 'a, V: 'a> VacantEntry<'a, Q, K, V> {
#[stable]
/// Sets the value of the entry with the VacantEntry's key,
/// and returns a mutable reference to it
}
#[stable]
-impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> Extend<(K, V)> for HashMap<K, V, H> {
+impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> Extend<(K, V)> for HashMap<K, V, H> {
fn extend<T: Iterator<Item=(K, V)>>(&mut self, mut iter: T) {
for (k, v) in iter {
self.insert(k, v);
use fmt::Show;
use fmt;
use hash::{Hash, Hasher, RandomSipHasher};
-use iter::{Iterator, IteratorExt, IteratorCloneExt, FromIterator, Map, Chain, Extend};
+use iter::{Iterator, IteratorExt, FromIterator, Map, Chain, Extend};
use ops::{BitOr, BitAnd, BitXor, Sub};
use option::Option::{Some, None, self};
-use result::Result::{Ok, Err};
+
+// NOTE: for old macros; remove after the next snapshot
+#[cfg(stage0)] use result::Result::{Ok, Err};
use super::map::{self, HashMap, Keys, INITIAL_CAPACITY};
/// assert_eq!(set.contains(&4), false);
/// ```
#[stable]
- pub fn contains<Sized? Q>(&self, value: &Q) -> bool
+ pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool
where Q: BorrowFrom<T> + Hash<S> + Eq
{
self.map.contains_key(value)
/// assert_eq!(set.remove(&2), false);
/// ```
#[stable]
- pub fn remove<Sized? Q>(&mut self, value: &Q) -> bool
+ pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool
where Q: BorrowFrom<T> + Hash<S> + Eq
{
self.map.remove(value).is_some()
}
#[stable]
-impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> Extend<T> for HashSet<T, H> {
+impl<T: Eq + Hash<S>, S, H: Hasher<S>> Extend<T> for HashSet<T, H> {
fn extend<I: Iterator<Item=T>>(&mut self, mut iter: I) {
for k in iter {
self.insert(k);
/// We need to remove hashes of 0. That's reserved for empty buckets.
/// This function wraps up `hash_keyed` to be the only way outside this
/// module to generate a SafeHash.
-pub fn make_hash<Sized? T: Hash<S>, S, H: Hasher<S>>(hasher: &H, t: &T) -> SafeHash {
+pub fn make_hash<T: ?Sized + Hash<S>, S, H: Hasher<S>>(hasher: &H, t: &T) -> SafeHash {
// We need to avoid 0u64 in order to prevent collisions with
// EMPTY_HASH. We can maintain our precious uniform distribution
// of initial indexes by unconditionally setting the MSB,
//! }
//! ```
-#![experimental]
+#![stable]
pub use core_collections::{BinaryHeap, Bitv, BitvSet, BTreeMap, BTreeSet};
pub use core_collections::{DList, RingBuf, VecMap};
mod hash;
+#[stable]
pub mod hash_map {
//! A hashmap
pub use super::hash::map::*;
}
+#[stable]
pub mod hash_set {
//! A hashset
pub use super::hash::set::*;
use prelude::v1::*;
-use c_str::ToCStr;
+use ffi::CString;
use mem;
use os;
use str;
/// Lazily open a dynamic library. When passed None it gives a
/// handle to the calling process
- pub fn open<T: ToCStr>(filename: Option<T>)
- -> Result<DynamicLibrary, String> {
+ pub fn open(filename: Option<&Path>) -> Result<DynamicLibrary, String> {
unsafe {
- let mut filename = filename;
let maybe_library = dl::check_for_errors_in(|| {
- match filename.take() {
- Some(name) => dl::open_external(name),
+ match filename {
+ Some(name) => dl::open_external(name.as_vec()),
None => dl::open_internal()
}
});
// This function should have a lifetime constraint of 'a on
// T but that feature is still unimplemented
+ let raw_string = CString::from_slice(symbol.as_bytes());
let maybe_symbol_value = dl::check_for_errors_in(|| {
- symbol.with_c_str(|raw_string| {
- dl::symbol(self.handle, raw_string)
- })
+ dl::symbol(self.handle, raw_string.as_ptr())
});
// The value must not be constructed if there is an error so
fn test_loading_cosine() {
// The math library does not need to be loaded since it is already
// statically linked in
- let none: Option<Path> = None; // appease the typechecker
+ let none: Option<&Path> = None; // appease the typechecker
let libm = match DynamicLibrary::open(none) {
Err(error) => panic!("Could not load self as module: {}", error),
Ok(libm) => libm
target_os = "freebsd",
target_os = "dragonfly"))]
pub mod dl {
- use self::Rtld::*;
-
+ pub use self::Rtld::*;
use prelude::v1::*;
- use c_str::{CString, ToCStr};
+
+ use ffi::{self, CString};
+ use str;
use libc;
use ptr;
- pub unsafe fn open_external<T: ToCStr>(filename: T) -> *mut u8 {
- filename.with_c_str(|raw_name| {
- dlopen(raw_name, Lazy as libc::c_int) as *mut u8
- })
+ pub unsafe fn open_external(filename: &[u8]) -> *mut u8 {
+ let s = CString::from_slice(filename);
+ dlopen(s.as_ptr(), Lazy as libc::c_int) as *mut u8
}
pub unsafe fn open_internal() -> *mut u8 {
let ret = if ptr::null() == last_error {
Ok(result)
} else {
- Err(String::from_str(CString::new(last_error, false).as_str()
- .unwrap()))
+ let s = ffi::c_str_to_bytes(&last_error);
+ Err(str::from_utf8(s).unwrap().to_string())
};
ret
#[cfg(target_os = "windows")]
pub mod dl {
- use c_str::ToCStr;
use iter::IteratorExt;
use libc;
use ops::FnOnce;
use string::String;
use vec::Vec;
- pub unsafe fn open_external<T: ToCStr>(filename: T) -> *mut u8 {
+ pub unsafe fn open_external(filename: &[u8]) -> *mut u8 {
// Windows expects Unicode data
- let filename_cstr = filename.to_c_str();
- let filename_str = str::from_utf8(filename_cstr.as_bytes_no_nul()).unwrap();
+ let filename_str = str::from_utf8(filename).unwrap();
let mut filename_str: Vec<u16> = filename_str.utf16_units().collect();
filename_str.push(0);
LoadLibraryW(filename_str.as_ptr() as *const libc::c_void) as *mut u8
--- /dev/null
+// Copyright 2012 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 fmt;
+use iter::IteratorExt;
+use libc;
+use mem;
+use ops::Deref;
+use slice::{self, SliceExt, AsSlice};
+use string::String;
+use vec::Vec;
+
+/// A type representing a C-compatible string
+///
+/// This type serves the primary purpose of being able to generate a
+/// C-compatible string from a Rust byte slice or vector. An instance of this
+/// type is a static guarantee that the underlying bytes contain no interior 0
+/// bytes and the final byte is 0.
+///
+/// A `CString` is created from either a byte slice or a byte vector. After
+/// being created, a `CString` predominately inherits all of its methods from
+/// the `Deref` implementation to `[libc::c_char]`. Note that the underlying
+/// array is represented as an array of `libc::c_char` as opposed to `u8`. A
+/// `u8` slice can be obtained with the `as_bytes` method. Slices produced from
+/// a `CString` do *not* contain the trailing nul terminator unless otherwise
+/// specified.
+///
+/// # Example
+///
+/// ```no_run
+/// # extern crate libc;
+/// # fn main() {
+/// use std::ffi::CString;
+/// use libc;
+///
+/// extern {
+/// fn my_printer(s: *const libc::c_char);
+/// }
+///
+/// let to_print = "Hello, world!";
+/// let c_to_print = CString::from_slice(to_print.as_bytes());
+/// unsafe {
+/// my_printer(c_to_print.as_ptr());
+/// }
+/// # }
+/// ```
+#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+pub struct CString {
+ inner: Vec<libc::c_char>,
+}
+
+impl CString {
+ /// Create a new C-compatible string from a byte slice.
+ ///
+ /// This method will copy the data of the slice provided into a new
+ /// allocation, ensuring that there is a trailing 0 byte.
+ ///
+ /// # Panics
+ ///
+ /// This function will panic if there are any 0 bytes already in the slice
+ /// provided.
+ pub fn from_slice(v: &[u8]) -> CString {
+ CString::from_vec(v.to_vec())
+ }
+
+ /// Create a C-compatible string from a byte vector.
+ ///
+ /// This method will consume ownership of the provided vector, appending a 0
+ /// byte to the end after verifying that there are no interior 0 bytes.
+ ///
+ /// # Panics
+ ///
+ /// This function will panic if there are any 0 bytes already in the vector
+ /// provided.
+ pub fn from_vec(v: Vec<u8>) -> CString {
+ assert!(!v.iter().any(|&x| x == 0));
+ unsafe { CString::from_vec_unchecked(v) }
+ }
+
+ /// Create a C-compatibel string from a byte vector without checking for
+ /// interior 0 bytes.
+ ///
+ /// This method is equivalent to `from_vec` except that no runtime assertion
+ /// is made that `v` contains no 0 bytes.
+ pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
+ v.push(0);
+ CString { inner: mem::transmute(v) }
+ }
+
+ /// Create a view into this C string which includes the trailing nul
+ /// terminator at the end of the string.
+ pub fn as_slice_with_nul(&self) -> &[libc::c_char] { self.inner.as_slice() }
+
+ /// Similar to the `as_slice` method, but returns a `u8` slice instead of a
+ /// `libc::c_char` slice.
+ pub fn as_bytes(&self) -> &[u8] {
+ unsafe { mem::transmute(self.as_slice()) }
+ }
+
+ /// Equivalend to `as_slice_with_nul` except that the type returned is a
+ /// `u8` slice instead of a `libc::c_char` slice.
+ pub fn as_bytes_with_nul(&self) -> &[u8] {
+ unsafe { mem::transmute(self.as_slice_with_nul()) }
+ }
+}
+
+impl Deref for CString {
+ type Target = [libc::c_char];
+
+ fn deref(&self) -> &[libc::c_char] {
+ self.inner.slice_to(self.inner.len() - 1)
+ }
+}
+
+impl fmt::Show for CString {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ String::from_utf8_lossy(self.as_bytes()).fmt(f)
+ }
+}
+
+/// Interpret a C string as a byte slice.
+///
+/// This function will calculate the length of the C string provided, and it
+/// will then return a corresponding slice for the contents of the C string not
+/// including the nul terminator.
+///
+/// This function will tie the lifetime of the returned slice to the lifetime of
+/// the pointer provided. This is done to help prevent the slice from escaping
+/// the lifetime of the pointer itself. If a longer lifetime is needed, then
+/// `mem::copy_lifetime` should be used.
+///
+/// This function is unsafe because there is no guarantee of the validity of the
+/// pointer `raw` or a guarantee that a nul terminator will be found.
+///
+/// # Example
+///
+/// ```no_run
+/// # extern crate libc;
+/// # fn main() {
+/// use std::ffi;
+/// use std::str;
+/// use libc;
+///
+/// extern {
+/// fn my_string() -> *const libc::c_char;
+/// }
+///
+/// unsafe {
+/// let to_print = my_string();
+/// let slice = ffi::c_str_to_bytes(&to_print);
+/// println!("string returned: {}", str::from_utf8(slice).unwrap());
+/// }
+/// # }
+/// ```
+pub unsafe fn c_str_to_bytes<'a>(raw: &'a *const libc::c_char) -> &'a [u8] {
+ let len = libc::strlen(*raw);
+ slice::from_raw_buf(&*(raw as *const _ as *const *const u8), len as uint)
+}
+
+/// Interpret a C string as a byte slice with the nul terminator.
+///
+/// This function is identical to `from_raw_buf` except that the returned slice
+/// will include the nul terminator of the string.
+pub unsafe fn c_str_to_bytes_with_nul<'a>(raw: &'a *const libc::c_char) -> &'a [u8] {
+ let len = libc::strlen(*raw) + 1;
+ slice::from_raw_buf(&*(raw as *const _ as *const *const u8), len as uint)
+}
+
+#[cfg(test)]
+mod tests {
+ use prelude::v1::*;
+ use super::*;
+ use libc;
+ use mem;
+
+ #[test]
+ fn c_to_rust() {
+ let data = b"123\0";
+ let ptr = data.as_ptr() as *const libc::c_char;
+ unsafe {
+ assert_eq!(c_str_to_bytes(&ptr), b"123");
+ assert_eq!(c_str_to_bytes_with_nul(&ptr), b"123\0");
+ }
+ }
+
+ #[test]
+ fn simple() {
+ let s = CString::from_slice(b"1234");
+ assert_eq!(s.as_bytes(), b"1234");
+ assert_eq!(s.as_bytes_with_nul(), b"1234\0");
+ unsafe {
+ assert_eq!(s.as_slice(),
+ mem::transmute::<_, &[libc::c_char]>(b"1234"));
+ assert_eq!(s.as_slice_with_nul(),
+ mem::transmute::<_, &[libc::c_char]>(b"1234\0"));
+ }
+ }
+
+ #[should_fail] #[test]
+ fn build_with_zero1() { CString::from_slice(b"\0"); }
+ #[should_fail] #[test]
+ fn build_with_zero2() { CString::from_vec(vec![0]); }
+
+ #[test]
+ fn build_with_zero3() {
+ unsafe {
+ let s = CString::from_vec_unchecked(vec![0]);
+ assert_eq!(s.as_bytes(), b"\0");
+ }
+ }
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Utilities related to FFI bindings.
+
+#![unstable = "module just underwent fairly large reorganization and the dust \
+ still needs to settle"]
+
+pub use self::c_str::CString;
+pub use self::c_str::c_str_to_bytes;
+pub use self::c_str::c_str_to_bytes_with_nul;
+
+mod c_str;
impl Hasher<sip::SipState> for RandomSipHasher {
#[inline]
- fn hash<Sized? T: Hash<sip::SipState>>(&self, value: &T) -> u64 {
+ fn hash<T: ?Sized + Hash<sip::SipState>>(&self, value: &T) -> u64 {
self.hasher.hash(value)
}
}
use cmp;
use io::{Reader, Writer, Stream, Buffer, DEFAULT_BUF_SIZE, IoResult};
-use iter::ExactSizeIterator;
+use iter::{IteratorExt, ExactSizeIterator};
use ops::Drop;
use option::Option;
use option::Option::{Some, None};
-use result::Result::{Ok, Err};
+use result::Result::Ok;
use slice::{SliceExt};
use slice;
use vec::Vec;
+// NOTE: for old macros; remove after the next snapshot
+#[cfg(stage0)] use result::Result::Err;
+
/// Wraps a Reader and buffers input from it
///
/// It can be excessively inefficient to work directly with a `Reader`. For
pub mod pipe;
pub mod process;
pub mod stdio;
-pub mod test;
pub mod timer;
pub mod util;
+#[cfg_attr(stage0, macro_escape)]
+#[cfg_attr(not(stage0), macro_use)]
+pub mod test;
+
/// The default buffer size for various I/O operations
// libuv recommends 64k buffers to maximize throughput
// https://groups.google.com/forum/#!topic/libuv/oQO1HJAIDdA
fn write_fmt(&mut self, fmt: fmt::Arguments) -> IoResult<()> {
// Create a shim which translates a Writer to a fmt::Writer and saves
// off I/O errors. instead of discarding them
- struct Adaptor<'a, Sized? T:'a> {
+ struct Adaptor<'a, T: ?Sized +'a> {
inner: &'a mut T,
error: IoResult<()>,
}
- impl<'a, Sized? T: Writer> fmt::Writer for Adaptor<'a, T> {
+ impl<'a, T: ?Sized + Writer> fmt::Writer for Adaptor<'a, T> {
fn write_str(&mut self, s: &str) -> fmt::Result {
match self.inner.write(s.as_bytes()) {
Ok(()) => Ok(()),
/// `Some`. The `Some` contains the `IoResult` representing whether the
/// connection attempt was successful. A successful connection will be wrapped
/// in `Ok`. A failed connection is represented as an `Err`.
-pub struct IncomingConnections<'a, Sized? A:'a> {
+pub struct IncomingConnections<'a, A: ?Sized +'a> {
inc: &'a mut A,
}
-impl<'a, T, Sized? A: Acceptor<T>> Iterator for IncomingConnections<'a, A> {
+impl<'a, T, A: ?Sized + Acceptor<T>> Iterator for IncomingConnections<'a, A> {
type Item = IoResult<T>;
fn next(&mut self) -> Option<IoResult<T>> {
use prelude::v1::*;
-use c_str::ToCStr;
+use ffi::CString;
+use path::BytesContainer;
use io::{Listener, Acceptor, IoResult, TimedOut, standard_error};
use sys::pipe::UnixAcceptor as UnixAcceptorImp;
use sys::pipe::UnixListener as UnixListenerImp;
/// let mut stream = UnixStream::connect(&server);
/// stream.write(&[1, 2, 3]);
/// ```
- pub fn connect<P: ToCStr>(path: &P) -> IoResult<UnixStream> {
- UnixStreamImp::connect(&path.to_c_str(), None)
+ pub fn connect<P: BytesContainer>(path: P) -> IoResult<UnixStream> {
+ let path = CString::from_slice(path.container_as_bytes());
+ UnixStreamImp::connect(&path, None)
.map(|inner| UnixStream { inner: inner })
}
/// 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: Duration) -> IoResult<UnixStream> {
+ pub fn connect_timeout<P>(path: P, timeout: Duration)
+ -> IoResult<UnixStream>
+ where P: BytesContainer {
if timeout <= Duration::milliseconds(0) {
return Err(standard_error(TimedOut));
}
- UnixStreamImp::connect(&path.to_c_str(), Some(timeout.num_milliseconds() as u64))
+ let path = CString::from_slice(path.container_as_bytes());
+ UnixStreamImp::connect(&path, Some(timeout.num_milliseconds() as u64))
.map(|inner| UnixStream { inner: inner })
}
/// }
/// # }
/// ```
- pub fn bind<P: ToCStr>(path: &P) -> IoResult<UnixListener> {
- UnixListenerImp::bind(&path.to_c_str())
+ pub fn bind<P: BytesContainer>(path: P) -> IoResult<UnixListener> {
+ let path = CString::from_slice(path.container_as_bytes());
+ UnixListenerImp::bind(&path)
.map(|inner| UnixListener { inner: inner })
}
}
use prelude::v1::*;
-use c_str::{CString, ToCStr};
use collections::HashMap;
+use ffi::CString;
use fmt;
use hash::Hash;
use io::pipe::{PipeStream, PipePair};
use thread::Thread;
#[cfg(windows)] use std::hash::sip::SipState;
+#[cfg(windows)] use str;
/// Signal a process to exit, without forcibly killing it. Corresponds to
/// SIGTERM on unix platforms.
impl Hash for EnvKey {
fn hash(&self, state: &mut SipState) {
let &EnvKey(ref x) = self;
- match x.as_str() {
- Some(s) => for ch in s.chars() {
+ match str::from_utf8(x.as_bytes()) {
+ Ok(s) => for ch in s.chars() {
(ch as u8 as char).to_lowercase().hash(state);
},
- None => x.hash(state)
+ Err(..) => x.hash(state)
}
}
}
fn eq(&self, other: &EnvKey) -> bool {
let &EnvKey(ref x) = self;
let &EnvKey(ref y) = other;
- match (x.as_str(), y.as_str()) {
- (Some(xs), Some(ys)) => {
+ match (str::from_utf8(x.as_bytes()), str::from_utf8(y.as_bytes())) {
+ (Ok(xs), Ok(ys)) => {
if xs.len() != ys.len() {
return false
} else {
}
// FIXME (#12938): Until DST lands, we cannot decompose &str into & and str, so
-// we cannot usefully take ToCStr arguments by reference (without forcing an
+// we cannot usefully take BytesContainer arguments by reference (without forcing an
// additional & around &str). So we are instead temporarily adding an instance
-// for &Path, so that we can take ToCStr as owned. When DST lands, the &Path
-// instance should be removed, and arguments bound by ToCStr should be passed by
+// for &Path, so that we can take BytesContainer as owned. When DST lands, the &Path
+// instance should be removed, and arguments bound by BytesContainer should be passed by
// reference. (Here: {new, arg, args, env}.)
impl Command {
///
/// Builder methods are provided to change these defaults and
/// otherwise configure the process.
- pub fn new<T:ToCStr>(program: T) -> Command {
+ pub fn new<T: BytesContainer>(program: T) -> Command {
Command {
- program: program.to_c_str(),
+ program: CString::from_slice(program.container_as_bytes()),
args: Vec::new(),
env: None,
cwd: None,
}
/// Add an argument to pass to the program.
- pub fn arg<'a, T: ToCStr>(&'a mut self, arg: T) -> &'a mut Command {
- self.args.push(arg.to_c_str());
+ pub fn arg<'a, T: BytesContainer>(&'a mut self, arg: T) -> &'a mut Command {
+ self.args.push(CString::from_slice(arg.container_as_bytes()));
self
}
/// Add multiple arguments to pass to the program.
- pub fn args<'a, T: ToCStr>(&'a mut self, args: &[T]) -> &'a mut Command {
- self.args.extend(args.iter().map(|arg| arg.to_c_str()));;
+ pub fn args<'a, T: BytesContainer>(&'a mut self, args: &[T]) -> &'a mut Command {
+ self.args.extend(args.iter().map(|arg| {
+ CString::from_slice(arg.container_as_bytes())
+ }));
self
}
// Get a mutable borrow of the environment variable map for this `Command`.
- fn get_env_map<'a>(&'a mut self) -> &'a mut EnvMap {
+ fn get_env_map<'a>(&'a mut self) -> &'a mut EnvMap {
match self.env {
Some(ref mut map) => map,
None => {
// if the env is currently just inheriting from the parent's,
// materialize the parent's env into a hashtable.
- self.env = Some(os::env_as_bytes().into_iter()
- .map(|(k, v)| (EnvKey(k.to_c_str()),
- v.to_c_str()))
- .collect());
+ self.env = Some(os::env_as_bytes().into_iter().map(|(k, v)| {
+ (EnvKey(CString::from_slice(k.as_slice())),
+ CString::from_slice(v.as_slice()))
+ }).collect());
self.env.as_mut().unwrap()
}
}
///
/// Note that environment variable names are case-insensitive (but case-preserving) on Windows,
/// and case-sensitive on all other platforms.
- pub fn env<'a, T: ToCStr, U: ToCStr>(&'a mut self, key: T, val: U)
- -> &'a mut Command {
- self.get_env_map().insert(EnvKey(key.to_c_str()), val.to_c_str());
+ pub fn env<'a, T, U>(&'a mut self, key: T, val: U)
+ -> &'a mut Command
+ where T: BytesContainer, U: BytesContainer {
+ let key = EnvKey(CString::from_slice(key.container_as_bytes()));
+ let val = CString::from_slice(val.container_as_bytes());
+ self.get_env_map().insert(key, val);
self
}
/// Removes an environment variable mapping.
- pub fn env_remove<'a, T: ToCStr>(&'a mut self, key: T) -> &'a mut Command {
- self.get_env_map().remove(&EnvKey(key.to_c_str()));
+ pub fn env_remove<'a, T>(&'a mut self, key: T) -> &'a mut Command
+ where T: BytesContainer {
+ let key = EnvKey(CString::from_slice(key.container_as_bytes()));
+ self.get_env_map().remove(&key);
self
}
///
/// If the given slice contains multiple instances of an environment
/// variable, the *rightmost* instance will determine the value.
- pub fn env_set_all<'a, T: ToCStr, U: ToCStr>(&'a mut self, env: &[(T,U)])
- -> &'a mut Command {
- self.env = Some(env.iter().map(|&(ref k, ref v)| (EnvKey(k.to_c_str()), v.to_c_str()))
- .collect());
+ pub fn env_set_all<'a, T, U>(&'a mut self, env: &[(T,U)])
+ -> &'a mut Command
+ where T: BytesContainer, U: BytesContainer {
+ self.env = Some(env.iter().map(|&(ref k, ref v)| {
+ (EnvKey(CString::from_slice(k.container_as_bytes())),
+ CString::from_slice(v.container_as_bytes()))
+ }).collect());
self
}
/// Set the working directory for the child process.
pub fn cwd<'a>(&'a mut self, dir: &Path) -> &'a mut Command {
- self.cwd = Some(dir.to_c_str());
+ self.cwd = Some(CString::from_slice(dir.as_vec()));
self
}
/// non-utf8 data is lossily converted using the utf8 replacement
/// character.
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- try!(write!(f, "{}", String::from_utf8_lossy(self.program.as_bytes_no_nul())));
+ try!(write!(f, "{}", String::from_utf8_lossy(self.program.as_bytes())));
for arg in self.args.iter() {
- try!(write!(f, " '{}'", String::from_utf8_lossy(arg.as_bytes_no_nul())));
+ try!(write!(f, " '{}'", String::from_utf8_lossy(arg.as_bytes())));
}
Ok(())
}
#[test]
#[cfg(windows)]
fn env_map_keys_ci() {
- use c_str::ToCStr;
+ use ffi::CString;
use super::EnvKey;
let mut cmd = Command::new("");
cmd.env("path", "foo");
cmd.env("Path", "bar");
let env = &cmd.env.unwrap();
- let val = env.get(&EnvKey("PATH".to_c_str()));
- assert!(val.unwrap() == &"bar".to_c_str());
+ let val = env.get(&EnvKey(CString::from_slice(b"PATH")));
+ assert!(val.unwrap() == &CString::from_slice(b"bar"));
}
}
//! Temporary files and directories
-use io::{fs, IoResult};
+use io::{fs, IoError, IoErrorKind, IoResult};
use io;
-use libc;
+use iter::{IteratorExt, range};
use ops::Drop;
use option::Option;
use option::Option::{None, Some};
use os;
use path::{Path, GenericPath};
+use rand::{Rng, thread_rng};
use result::Result::{Ok, Err};
-use sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering};
+use str::StrExt;
+use string::String;
/// A wrapper for a path to temporary directory implementing automatic
/// scope-based deletion.
///
/// {
/// // create a temporary directory
-/// let tmpdir = match TempDir::new("mysuffix") {
+/// let tmpdir = match TempDir::new("myprefix") {
/// Ok(dir) => dir,
/// Err(e) => panic!("couldn't create temporary directory: {}", e)
/// };
/// }
/// {
/// // create a temporary directory, this time using a custom path
-/// let tmpdir = match TempDir::new_in(&Path::new("/tmp/best/custom/path"), "mysuffix") {
+/// let tmpdir = match TempDir::new_in(&Path::new("/tmp/best/custom/path"), "myprefix") {
/// Ok(dir) => dir,
/// Err(e) => panic!("couldn't create temporary directory: {}", e)
/// };
/// }
/// {
/// // create a temporary directory
-/// let tmpdir = match TempDir::new("mysuffix") {
+/// let tmpdir = match TempDir::new("myprefix") {
/// Ok(dir) => dir,
/// Err(e) => panic!("couldn't create temporary directory: {}", e)
/// };
disarmed: bool
}
+// How many times should we (re)try finding an unused random name? It should be
+// enough that an attacker will run out of luck before we run out of patience.
+const NUM_RETRIES: u32 = 1 << 31;
+// How many characters should we include in a random file name? It needs to
+// be enough to dissuade an attacker from trying to preemptively create names
+// of that length, but not so huge that we unnecessarily drain the random number
+// generator of entropy.
+const NUM_RAND_CHARS: uint = 12;
+
impl TempDir {
/// Attempts to make a temporary directory inside of `tmpdir` whose name
- /// will have the suffix `suffix`. The directory will be automatically
+ /// will have the prefix `prefix`. The directory will be automatically
/// deleted once the returned wrapper is destroyed.
///
/// If no directory can be created, `Err` is returned.
- pub fn new_in(tmpdir: &Path, suffix: &str) -> IoResult<TempDir> {
+ pub fn new_in(tmpdir: &Path, prefix: &str) -> IoResult<TempDir> {
if !tmpdir.is_absolute() {
let abs_tmpdir = try!(os::make_absolute(tmpdir));
- return TempDir::new_in(&abs_tmpdir, suffix);
+ return TempDir::new_in(&abs_tmpdir, prefix);
}
- static CNT: AtomicUint = ATOMIC_UINT_INIT;
-
- let mut attempts = 0u;
- loop {
- let filename =
- format!("rs-{}-{}-{}",
- unsafe { libc::getpid() },
- CNT.fetch_add(1, Ordering::SeqCst),
- suffix);
- let p = tmpdir.join(filename);
- match fs::mkdir(&p, io::USER_RWX) {
- Err(error) => {
- if attempts >= 1000 {
- return Err(error)
- }
- attempts += 1;
- }
- Ok(()) => return Ok(TempDir { path: Some(p), disarmed: false })
+ let mut rng = thread_rng();
+ for _ in range(0, NUM_RETRIES) {
+ let suffix: String = rng.gen_ascii_chars().take(NUM_RAND_CHARS).collect();
+ let leaf = if prefix.len() > 0 {
+ format!("{}.{}", prefix, suffix)
+ } else {
+ // If we're given an empty string for a prefix, then creating a
+ // directory starting with "." would lead to it being
+ // semi-invisible on some systems.
+ suffix
+ };
+ let path = tmpdir.join(leaf);
+ match fs::mkdir(&path, io::USER_RWX) {
+ Ok(_) => return Ok(TempDir { path: Some(path), disarmed: false }),
+ Err(IoError{kind:IoErrorKind::PathAlreadyExists,..}) => (),
+ Err(e) => return Err(e)
}
}
+
+ return Err(IoError{
+ kind: IoErrorKind::PathAlreadyExists,
+ desc:"Exhausted",
+ detail: None});
}
/// Attempts to make a temporary directory inside of `os::tmpdir()` whose
- /// name will have the suffix `suffix`. The directory will be automatically
+ /// name will have the prefix `prefix`. The directory will be automatically
/// deleted once the returned wrapper is destroyed.
///
/// If no directory can be created, `Err` is returned.
- pub fn new(suffix: &str) -> IoResult<TempDir> {
- TempDir::new_in(&os::tmpdir(), suffix)
+ pub fn new(prefix: &str) -> IoResult<TempDir> {
+ TempDir::new_in(&os::tmpdir(), prefix)
}
/// Unwrap the wrapped `std::path::Path` from the `TempDir` wrapper.
//! Various utility functions useful for writing I/O tests
-#![macro_escape]
-
use prelude::v1::*;
use libc;
//! and `format!`, also available to all Rust code.
#![crate_name = "std"]
-#![unstable]
+#![stable]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
#![reexport_test_harness_main = "test_main"]
-#[cfg(test)] #[phase(plugin, link)] extern crate log;
+#[cfg(all(test, stage0))]
+#[phase(plugin, link)]
+extern crate log;
-extern crate alloc;
-extern crate unicode;
+#[cfg(all(test, not(stage0)))]
+#[macro_use]
+extern crate log;
+
+#[cfg(stage0)]
+#[phase(plugin, link)]
+extern crate core;
+
+#[cfg(not(stage0))]
+#[macro_use]
+#[macro_reexport(assert, assert_eq, debug_assert, debug_assert_eq,
+ unreachable, unimplemented, write, writeln)]
extern crate core;
+
+#[cfg(stage0)]
+#[phase(plugin, link)]
+extern crate "collections" as core_collections;
+
+#[cfg(not(stage0))]
+#[macro_use]
+#[macro_reexport(vec)]
extern crate "collections" as core_collections;
+
extern crate "rand" as core_rand;
+extern crate alloc;
+extern crate unicode;
extern crate libc;
// Make std testable by not duplicating lang items. See #2912
/* Exported macros */
+#[cfg(stage0)]
+#[cfg_attr(stage0, macro_escape)]
+#[cfg_attr(not(stage0), macro_use)]
+pub mod macros_stage0;
+
+#[cfg(not(stage0))]
+#[cfg_attr(stage0, macro_escape)]
+#[cfg_attr(not(stage0), macro_use)]
pub mod macros;
+
+#[cfg_attr(stage0, macro_escape)]
+#[cfg_attr(not(stage0), macro_use)]
pub mod bitflags;
mod rtdeps;
/* Primitive types */
-#[path = "num/float_macros.rs"] mod float_macros;
-#[path = "num/int_macros.rs"] mod int_macros;
-#[path = "num/uint_macros.rs"] mod uint_macros;
+#[path = "num/float_macros.rs"]
+#[cfg_attr(stage0, macro_escape)]
+#[cfg_attr(not(stage0), macro_use)]
+mod float_macros;
+
+#[path = "num/int_macros.rs"]
+#[cfg_attr(stage0, macro_escape)]
+#[cfg_attr(not(stage0), macro_use)]
+mod int_macros;
+
+#[path = "num/uint_macros.rs"]
+#[cfg_attr(stage0, macro_escape)]
+#[cfg_attr(not(stage0), macro_use)]
+mod uint_macros;
#[path = "num/int.rs"] pub mod int;
#[path = "num/i8.rs"] pub mod i8;
/* Runtime and platform support */
+#[cfg_attr(stage0, macro_escape)]
+#[cfg_attr(not(stage0), macro_use)]
pub mod thread_local;
-pub mod c_str;
-pub mod c_vec;
+
pub mod dynamic_lib;
+pub mod ffi;
pub mod fmt;
pub mod io;
pub mod os;
//! library.
#![experimental]
-#![macro_escape]
/// The entry point for panic of Rust tasks.
///
($($arg:tt)*) => (::std::fmt::format(format_args!($($arg)*)))
}
-/// Use the `format!` syntax to write data into a buffer of type `&mut Writer`.
-/// See `std::fmt` for more information.
-///
-/// # Example
-///
-/// ```
-/// # #![allow(unused_must_use)]
-///
-/// let mut w = Vec::new();
-/// write!(&mut w, "test");
-/// write!(&mut w, "formatted {}", "arguments");
-/// ```
-#[macro_export]
-#[stable]
-macro_rules! write {
- ($dst:expr, $($arg:tt)*) => ((&mut *$dst).write_fmt(format_args!($($arg)*)))
-}
-
-/// Equivalent to the `write!` macro, except that a newline is appended after
-/// the message is written.
-#[macro_export]
-#[stable]
-macro_rules! writeln {
- ($dst:expr, $fmt:expr $($arg:tt)*) => (
- write!($dst, concat!($fmt, "\n") $($arg)*)
- )
-}
-
/// Equivalent to the `println!` macro except that a newline is not printed at
/// the end of the message.
#[macro_export]
#[macro_export]
macro_rules! try {
($expr:expr) => ({
+ use $crate::result::Result::{Ok, Err};
+
match $expr {
Ok(val) => val,
- Err(err) => return Err(::std::error::FromError::from_error(err))
+ Err(err) => return Err($crate::error::FromError::from_error(err)),
}
})
}
-/// Create a `std::vec::Vec` containing the arguments.
-#[macro_export]
-macro_rules! vec {
- ($($x:expr),*) => ({
- let xs: ::std::boxed::Box<[_]> = box [$($x),*];
- ::std::slice::SliceExt::into_vec(xs)
- });
- ($($x:expr,)*) => (vec![$($x),*])
-}
-
/// A macro to select an event from a number of receivers.
///
/// This macro is used to wait for the first event to occur on a number of
(
$($name:pat = $rx:ident.$meth:ident() => $code:expr),+
) => ({
- use std::sync::mpsc::Select;
+ use $crate::sync::mpsc::Select;
let sel = Select::new();
$( let mut $rx = sel.handle(&$rx); )+
unsafe {
--- /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.
+
+//! Standard library macros
+//!
+//! This modules contains a set of macros which are exported from the standard
+//! library. Each macro is available for use when linking against the standard
+//! library.
+
+#![experimental]
+
+/// The entry point for panic of Rust tasks.
+///
+/// This macro is used to inject panic into a Rust task, causing the task to
+/// unwind and panic entirely. Each task's panic can be reaped as the
+/// `Box<Any>` type, and the single-argument form of the `panic!` macro will be
+/// the value which is transmitted.
+///
+/// The multi-argument form of this macro panics with a string and has the
+/// `format!` syntax for building a string.
+///
+/// # Example
+///
+/// ```should_fail
+/// # #![allow(unreachable_code)]
+/// panic!();
+/// panic!("this is a terrible mistake!");
+/// panic!(4i); // panic with the value of 4 to be collected elsewhere
+/// panic!("this is a {} {message}", "fancy", message = "message");
+/// ```
+#[macro_export]
+macro_rules! panic {
+ () => ({
+ panic!("explicit panic")
+ });
+ ($msg:expr) => ({
+ // static requires less code at runtime, more constant data
+ static _FILE_LINE: (&'static str, uint) = (file!(), line!());
+ ::std::rt::begin_unwind($msg, &_FILE_LINE)
+ });
+ ($fmt:expr, $($arg:tt)*) => ({
+ // The leading _'s are to avoid dead code warnings if this is
+ // used inside a dead function. Just `#[allow(dead_code)]` is
+ // insufficient, since the user may have
+ // `#[forbid(dead_code)]` and which cannot be overridden.
+ static _FILE_LINE: (&'static str, uint) = (file!(), line!());
+ ::std::rt::begin_unwind_fmt(format_args!($fmt, $($arg)*), &_FILE_LINE)
+
+ });
+}
+
+/// Ensure that a boolean expression is `true` at runtime.
+///
+/// This will invoke the `panic!` macro if the provided expression cannot be
+/// evaluated to `true` at runtime.
+///
+/// # Example
+///
+/// ```
+/// // the panic message for these assertions is the stringified value of the
+/// // expression given.
+/// assert!(true);
+/// # fn some_computation() -> bool { true }
+/// assert!(some_computation());
+///
+/// // assert with a custom message
+/// # let x = true;
+/// assert!(x, "x wasn't true!");
+/// # let a = 3i; let b = 27i;
+/// assert!(a + b == 30, "a = {}, b = {}", a, b);
+/// ```
+#[macro_export]
+macro_rules! assert {
+ ($cond:expr) => (
+ if !$cond {
+ panic!(concat!("assertion failed: ", stringify!($cond)))
+ }
+ );
+ ($cond:expr, $($arg:expr),+) => (
+ if !$cond {
+ panic!($($arg),+)
+ }
+ );
+}
+
+/// Asserts that two expressions are equal to each other, testing equality in
+/// both directions.
+///
+/// On panic, this macro will print the values of the expressions.
+///
+/// # Example
+///
+/// ```
+/// let a = 3i;
+/// let b = 1i + 2i;
+/// assert_eq!(a, b);
+/// ```
+#[macro_export]
+macro_rules! assert_eq {
+ ($left:expr , $right:expr) => ({
+ match (&($left), &($right)) {
+ (left_val, right_val) => {
+ // check both directions of equality....
+ if !((*left_val == *right_val) &&
+ (*right_val == *left_val)) {
+ panic!("assertion failed: `(left == right) && (right == left)` \
+ (left: `{}`, right: `{}`)", *left_val, *right_val)
+ }
+ }
+ }
+ })
+}
+
+/// Ensure that a boolean expression is `true` at runtime.
+///
+/// This will invoke the `panic!` macro if the provided expression cannot be
+/// evaluated to `true` at runtime.
+///
+/// Unlike `assert!`, `debug_assert!` statements can be disabled by passing
+/// `--cfg ndebug` to the compiler. This makes `debug_assert!` useful for
+/// checks that are too expensive to be present in a release build but may be
+/// helpful during development.
+///
+/// # Example
+///
+/// ```
+/// // the panic message for these assertions is the stringified value of the
+/// // expression given.
+/// debug_assert!(true);
+/// # fn some_expensive_computation() -> bool { true }
+/// debug_assert!(some_expensive_computation());
+///
+/// // assert with a custom message
+/// # let x = true;
+/// debug_assert!(x, "x wasn't true!");
+/// # let a = 3i; let b = 27i;
+/// debug_assert!(a + b == 30, "a = {}, b = {}", a, b);
+/// ```
+#[macro_export]
+macro_rules! debug_assert {
+ ($($arg:tt)*) => (if cfg!(not(ndebug)) { assert!($($arg)*); })
+}
+
+/// Asserts that two expressions are equal to each other, testing equality in
+/// both directions.
+///
+/// On panic, this macro will print the values of the expressions.
+///
+/// Unlike `assert_eq!`, `debug_assert_eq!` statements can be disabled by
+/// passing `--cfg ndebug` to the compiler. This makes `debug_assert_eq!`
+/// useful for checks that are too expensive to be present in a release build
+/// but may be helpful during development.
+///
+/// # Example
+///
+/// ```
+/// let a = 3i;
+/// let b = 1i + 2i;
+/// debug_assert_eq!(a, b);
+/// ```
+#[macro_export]
+macro_rules! debug_assert_eq {
+ ($($arg:tt)*) => (if cfg!(not(ndebug)) { assert_eq!($($arg)*); })
+}
+
+/// A utility macro for indicating unreachable code.
+///
+/// This is useful any time that the compiler can't determine that some code is unreachable. For
+/// example:
+///
+/// * Match arms with guard conditions.
+/// * Loops that dynamically terminate.
+/// * Iterators that dynamically terminate.
+///
+/// # Panics
+///
+/// This will always panic.
+///
+/// # Examples
+///
+/// Match arms:
+///
+/// ```rust
+/// fn foo(x: Option<int>) {
+/// match x {
+/// Some(n) if n >= 0 => println!("Some(Non-negative)"),
+/// Some(n) if n < 0 => println!("Some(Negative)"),
+/// Some(_) => unreachable!(), // compile error if commented out
+/// None => println!("None")
+/// }
+/// }
+/// ```
+///
+/// Iterators:
+///
+/// ```rust
+/// fn divide_by_three(x: u32) -> u32 { // one of the poorest implementations of x/3
+/// for i in std::iter::count(0_u32, 1) {
+/// if 3*i < i { panic!("u32 overflow"); }
+/// if x < 3*i { return i-1; }
+/// }
+/// unreachable!();
+/// }
+/// ```
+#[macro_export]
+macro_rules! unreachable {
+ () => ({
+ panic!("internal error: entered unreachable code")
+ });
+ ($msg:expr) => ({
+ unreachable!("{}", $msg)
+ });
+ ($fmt:expr, $($arg:tt)*) => ({
+ panic!(concat!("internal error: entered unreachable code: ", $fmt), $($arg)*)
+ });
+}
+
+/// A standardised placeholder for marking unfinished code. It panics with the
+/// message `"not yet implemented"` when executed.
+#[macro_export]
+macro_rules! unimplemented {
+ () => (panic!("not yet implemented"))
+}
+
+/// Use the syntax described in `std::fmt` to create a value of type `String`.
+/// See `std::fmt` for more information.
+///
+/// # Example
+///
+/// ```
+/// format!("test");
+/// format!("hello {}", "world!");
+/// format!("x = {}, y = {y}", 10i, y = 30i);
+/// ```
+#[macro_export]
+#[stable]
+macro_rules! format {
+ ($($arg:tt)*) => (::std::fmt::format(format_args!($($arg)*)))
+}
+
+/// Use the `format!` syntax to write data into a buffer of type `&mut Writer`.
+/// See `std::fmt` for more information.
+///
+/// # Example
+///
+/// ```
+/// # #![allow(unused_must_use)]
+///
+/// let mut w = Vec::new();
+/// write!(&mut w, "test");
+/// write!(&mut w, "formatted {}", "arguments");
+/// ```
+#[macro_export]
+#[stable]
+macro_rules! write {
+ ($dst:expr, $($arg:tt)*) => ((&mut *$dst).write_fmt(format_args!($($arg)*)))
+}
+
+/// Equivalent to the `write!` macro, except that a newline is appended after
+/// the message is written.
+#[macro_export]
+#[stable]
+macro_rules! writeln {
+ ($dst:expr, $fmt:expr $($arg:tt)*) => (
+ write!($dst, concat!($fmt, "\n") $($arg)*)
+ )
+}
+
+/// Equivalent to the `println!` macro except that a newline is not printed at
+/// the end of the message.
+#[macro_export]
+#[stable]
+macro_rules! print {
+ ($($arg:tt)*) => (::std::io::stdio::print_args(format_args!($($arg)*)))
+}
+
+/// Macro for printing to a task's stdout handle.
+///
+/// Each task can override its stdout handle via `std::io::stdio::set_stdout`.
+/// The syntax of this macro is the same as that used for `format!`. For more
+/// information, see `std::fmt` and `std::io::stdio`.
+///
+/// # Example
+///
+/// ```
+/// println!("hello there!");
+/// println!("format {} arguments", "some");
+/// ```
+#[macro_export]
+#[stable]
+macro_rules! println {
+ ($($arg:tt)*) => (::std::io::stdio::println_args(format_args!($($arg)*)))
+}
+
+/// Helper macro for unwrapping `Result` values while returning early with an
+/// error if the value of the expression is `Err`. For more information, see
+/// `std::io`.
+#[macro_export]
+macro_rules! try {
+ ($expr:expr) => ({
+ match $expr {
+ Ok(val) => val,
+ Err(err) => return Err(::std::error::FromError::from_error(err))
+ }
+ })
+}
+
+/// Create a `std::vec::Vec` containing the arguments.
+#[macro_export]
+macro_rules! vec {
+ ($($x:expr),*) => ({
+ let xs: ::std::boxed::Box<[_]> = box [$($x),*];
+ ::std::slice::SliceExt::into_vec(xs)
+ });
+ ($($x:expr,)*) => (vec![$($x),*])
+}
+
+/// A macro to select an event from a number of receivers.
+///
+/// This macro is used to wait for the first event to occur on a number of
+/// receivers. It places no restrictions on the types of receivers given to
+/// this macro, this can be viewed as a heterogeneous select.
+///
+/// # Example
+///
+/// ```
+/// use std::thread::Thread;
+/// use std::sync::mpsc::channel;
+///
+/// let (tx1, rx1) = channel();
+/// let (tx2, rx2) = channel();
+/// # fn long_running_task() {}
+/// # fn calculate_the_answer() -> int { 42i }
+///
+/// Thread::spawn(move|| { long_running_task(); tx1.send(()) }).detach();
+/// Thread::spawn(move|| { tx2.send(calculate_the_answer()) }).detach();
+///
+/// select! (
+/// _ = rx1.recv() => println!("the long running task finished first"),
+/// answer = rx2.recv() => {
+/// println!("the answer was: {}", answer.unwrap());
+/// }
+/// )
+/// ```
+///
+/// For more information about select, see the `std::sync::mpsc::Select` structure.
+#[macro_export]
+#[experimental]
+macro_rules! select {
+ (
+ $($name:pat = $rx:ident.$meth:ident() => $code:expr),+
+ ) => ({
+ use std::sync::mpsc::Select;
+ let sel = Select::new();
+ $( let mut $rx = sel.handle(&$rx); )+
+ unsafe {
+ $( $rx.add(); )+
+ }
+ let ret = sel.wait();
+ $( if ret == $rx.id() { let $name = $rx.$meth(); $code } else )+
+ { unreachable!() }
+ })
+}
+
+// When testing the standard library, we link to the liblog crate to get the
+// logging macros. In doing so, the liblog crate was linked against the real
+// version of libstd, and uses a different std::fmt module than the test crate
+// uses. To get around this difference, we redefine the log!() macro here to be
+// just a dumb version of what it should be.
+#[cfg(test)]
+macro_rules! log {
+ ($lvl:expr, $($args:tt)*) => (
+ if log_enabled!($lvl) { println!($($args)*) }
+ )
+}
+
+/// Built-in macros to the compiler itself.
+///
+/// These macros do not have any corresponding definition with a `macro_rules!`
+/// macro, but are documented here. Their implementations can be found hardcoded
+/// into libsyntax itself.
+#[cfg(dox)]
+pub mod builtin {
+ /// The core macro for formatted string creation & output.
+ ///
+ /// This macro produces a value of type `fmt::Arguments`. This value can be
+ /// passed to the functions in `std::fmt` for performing useful functions.
+ /// All other formatting macros (`format!`, `write!`, `println!`, etc) are
+ /// proxied through this one.
+ ///
+ /// For more information, see the documentation in `std::fmt`.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// use std::fmt;
+ ///
+ /// let s = fmt::format(format_args!("hello {}", "world"));
+ /// assert_eq!(s, format!("hello {}", "world"));
+ ///
+ /// ```
+ #[macro_export]
+ macro_rules! format_args { ($fmt:expr $($args:tt)*) => ({
+ /* compiler built-in */
+ }) }
+
+ /// Inspect an environment variable at compile time.
+ ///
+ /// This macro will expand to the value of the named environment variable at
+ /// compile time, yielding an expression of type `&'static str`.
+ ///
+ /// If the environment variable is not defined, then a compilation error
+ /// will be emitted. To not emit a compile error, use the `option_env!`
+ /// macro instead.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let path: &'static str = env!("PATH");
+ /// println!("the $PATH variable at the time of compiling was: {}", path);
+ /// ```
+ #[macro_export]
+ macro_rules! env { ($name:expr) => ({ /* compiler built-in */ }) }
+
+ /// Optionally inspect an environment variable at compile time.
+ ///
+ /// If the named environment variable is present at compile time, this will
+ /// expand into an expression of type `Option<&'static str>` whose value is
+ /// `Some` of the value of the environment variable. If the environment
+ /// variable is not present, then this will expand to `None`.
+ ///
+ /// A compile time error is never emitted when using this macro regardless
+ /// of whether the environment variable is present or not.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let key: Option<&'static str> = option_env!("SECRET_KEY");
+ /// println!("the secret key might be: {}", key);
+ /// ```
+ #[macro_export]
+ macro_rules! option_env { ($name:expr) => ({ /* compiler built-in */ }) }
+
+ /// Concatenate literals into a static byte slice.
+ ///
+ /// This macro takes any number of comma-separated literal expressions,
+ /// yielding an expression of type `&'static [u8]` which is the
+ /// concatenation (left to right) of all the literals in their byte format.
+ ///
+ /// This extension currently only supports string literals, character
+ /// literals, and integers less than 256. The byte slice returned is the
+ /// utf8-encoding of strings and characters.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// let rust = bytes!("r", 'u', "st", 255);
+ /// assert_eq!(rust[1], b'u');
+ /// assert_eq!(rust[4], 255);
+ /// ```
+ #[macro_export]
+ macro_rules! bytes { ($($e:expr),*) => ({ /* compiler built-in */ }) }
+
+ /// Concatenate identifiers into one identifier.
+ ///
+ /// This macro takes any number of comma-separated identifiers, and
+ /// concatenates them all into one, yielding an expression which is a new
+ /// identifier. Note that hygiene makes it such that this macro cannot
+ /// capture local variables, and macros are only allowed in item,
+ /// statement or expression position, meaning this macro may be difficult to
+ /// use in some situations.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// #![feature(concat_idents)]
+ ///
+ /// # fn main() {
+ /// fn foobar() -> int { 23 }
+ ///
+ /// let f = concat_idents!(foo, bar);
+ /// println!("{}", f());
+ /// # }
+ /// ```
+ #[macro_export]
+ macro_rules! concat_idents {
+ ($($e:ident),*) => ({ /* compiler built-in */ })
+ }
+
+ /// Concatenates literals into a static string slice.
+ ///
+ /// This macro takes any number of comma-separated literals, yielding an
+ /// expression of type `&'static str` which represents all of the literals
+ /// concatenated left-to-right.
+ ///
+ /// Integer and floating point literals are stringified in order to be
+ /// concatenated.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// let s = concat!("test", 10i, 'b', true);
+ /// assert_eq!(s, "test10btrue");
+ /// ```
+ #[macro_export]
+ macro_rules! concat { ($($e:expr),*) => ({ /* compiler built-in */ }) }
+
+ /// A macro which expands to the line number on which it was invoked.
+ ///
+ /// The expanded expression has type `uint`, and the returned line is not
+ /// the invocation of the `line!()` macro itself, but rather the first macro
+ /// invocation leading up to the invocation of the `line!()` macro.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// let current_line = line!();
+ /// println!("defined on line: {}", current_line);
+ /// ```
+ #[macro_export]
+ macro_rules! line { () => ({ /* compiler built-in */ }) }
+
+ /// A macro which expands to the column number on which it was invoked.
+ ///
+ /// The expanded expression has type `uint`, and the returned column is not
+ /// the invocation of the `column!()` macro itself, but rather the first macro
+ /// invocation leading up to the invocation of the `column!()` macro.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// let current_col = column!();
+ /// println!("defined on column: {}", current_col);
+ /// ```
+ #[macro_export]
+ macro_rules! column { () => ({ /* compiler built-in */ }) }
+
+ /// A macro which expands to the file name from which it was invoked.
+ ///
+ /// The expanded expression has type `&'static str`, and the returned file
+ /// is not the invocation of the `file!()` macro itself, but rather the
+ /// first macro invocation leading up to the invocation of the `file!()`
+ /// macro.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// let this_file = file!();
+ /// println!("defined in file: {}", this_file);
+ /// ```
+ #[macro_export]
+ macro_rules! file { () => ({ /* compiler built-in */ }) }
+
+ /// A macro which stringifies its argument.
+ ///
+ /// This macro will yield an expression of type `&'static str` which is the
+ /// stringification of all the tokens passed to the macro. No restrictions
+ /// are placed on the syntax of the macro invocation itself.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// let one_plus_one = stringify!(1 + 1);
+ /// assert_eq!(one_plus_one, "1 + 1");
+ /// ```
+ #[macro_export]
+ macro_rules! stringify { ($t:tt) => ({ /* compiler built-in */ }) }
+
+ /// Includes a utf8-encoded file as a string.
+ ///
+ /// This macro will yield an expression of type `&'static str` which is the
+ /// contents of the filename specified. The file is located relative to the
+ /// current file (similarly to how modules are found),
+ ///
+ /// # Example
+ ///
+ /// ```rust,ignore
+ /// let secret_key = include_str!("secret-key.ascii");
+ /// ```
+ #[macro_export]
+ macro_rules! include_str { ($file:expr) => ({ /* compiler built-in */ }) }
+
+ /// Includes a file as a byte slice.
+ ///
+ /// This macro will yield an expression of type `&'static [u8]` which is
+ /// the contents of the filename specified. The file is located relative to
+ /// the current file (similarly to how modules are found),
+ ///
+ /// # Example
+ ///
+ /// ```rust,ignore
+ /// let secret_key = include_bytes!("secret-key.bin");
+ /// ```
+ #[macro_export]
+ macro_rules! include_bytes { ($file:expr) => ({ /* compiler built-in */ }) }
+
+ /// Deprecated alias for `include_bytes!()`.
+ #[macro_export]
+ macro_rules! include_bin { ($file:expr) => ({ /* compiler built-in */}) }
+
+ /// Expands to a string that represents the current module path.
+ ///
+ /// The current module path can be thought of as the hierarchy of modules
+ /// leading back up to the crate root. The first component of the path
+ /// returned is the name of the crate currently being compiled.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// mod test {
+ /// pub fn foo() {
+ /// assert!(module_path!().ends_with("test"));
+ /// }
+ /// }
+ ///
+ /// test::foo();
+ /// ```
+ #[macro_export]
+ macro_rules! module_path { () => ({ /* compiler built-in */ }) }
+
+ /// Boolean evaluation of configuration flags.
+ ///
+ /// In addition to the `#[cfg]` attribute, this macro is provided to allow
+ /// boolean expression evaluation of configuration flags. This frequently
+ /// leads to less duplicated code.
+ ///
+ /// The syntax given to this macro is the same syntax as the `cfg`
+ /// attribute.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// let my_directory = if cfg!(windows) {
+ /// "windows-specific-directory"
+ /// } else {
+ /// "unix-directory"
+ /// };
+ /// ```
+ #[macro_export]
+ macro_rules! cfg { ($cfg:tt) => ({ /* compiler built-in */ }) }
+}
// except according to those terms.
#![experimental]
-#![macro_escape]
#![doc(hidden)]
macro_rules! assert_approx_eq {
// except according to those terms.
#![experimental]
-#![macro_escape]
#![doc(hidden)]
macro_rules! int_module { ($T:ty) => (
// except according to those terms.
#![experimental]
-#![macro_escape]
#![doc(hidden)]
#![allow(unsigned_negation)]
use sync::atomic::{AtomicInt, ATOMIC_INT_INIT, Ordering};
use vec::Vec;
-#[cfg(unix)] use c_str::ToCStr;
+#[cfg(unix)] use ffi::{self, CString};
-#[cfg(unix)]
-pub use sys::ext as unix;
-#[cfg(windows)]
-pub use sys::ext as windows;
+#[cfg(unix)] pub use sys::ext as unix;
+#[cfg(windows)] pub use sys::ext as windows;
/// Get the number of cores available
pub fn num_cpus() -> uint {
///
/// Panics if `n` has any interior NULs.
pub fn getenv_as_bytes(n: &str) -> Option<Vec<u8>> {
- use c_str::CString;
-
unsafe {
with_env_lock(|| {
- let s = n.with_c_str(|buf| libc::getenv(buf));
+ let s = CString::from_slice(n.as_bytes());
+ let s = libc::getenv(s.as_ptr()) as *const _;
if s.is_null() {
None
} else {
- Some(CString::new(s as *const libc::c_char, false).as_bytes_no_nul().to_vec())
+ Some(ffi::c_str_to_bytes(&s).to_vec())
}
})
}
fn _setenv(n: &str, v: &[u8]) {
unsafe {
with_env_lock(|| {
- n.with_c_str(|nbuf| {
- v.with_c_str(|vbuf| {
- if libc::funcs::posix01::unistd::setenv(nbuf, vbuf, 1) != 0 {
- panic!(IoError::last_error());
- }
- })
- })
+ let k = CString::from_slice(n.as_bytes());
+ let v = CString::from_slice(v);
+ if libc::funcs::posix01::unistd::setenv(k.as_ptr(),
+ v.as_ptr(), 1) != 0 {
+ panic!(IoError::last_error());
+ }
})
}
}
fn _unsetenv(n: &str) {
unsafe {
with_env_lock(|| {
- n.with_c_str(|nbuf| {
- if libc::funcs::posix01::unistd::unsetenv(nbuf) != 0 {
- panic!(IoError::last_error());
- }
- })
+ let nbuf = CString::from_slice(n.as_bytes());
+ if libc::funcs::posix01::unistd::unsetenv(nbuf.as_ptr()) != 0 {
+ panic!(IoError::last_error());
+ }
})
}
}
#[cfg(target_os = "macos")]
unsafe fn load_argc_and_argv(argc: int,
argv: *const *const c_char) -> Vec<Vec<u8>> {
- use c_str::CString;
use iter::range;
range(0, argc as uint).map(|i| {
- CString::new(*argv.offset(i as int), false).as_bytes_no_nul().to_vec()
+ ffi::c_str_to_bytes(&*argv.offset(i as int)).to_vec()
}).collect()
}
// res
#[cfg(target_os = "ios")]
fn real_args_as_bytes() -> Vec<Vec<u8>> {
- use c_str::CString;
use iter::range;
use mem;
#![experimental]
use core::kinds::Sized;
-use c_str::CString;
+use ffi::CString;
use clone::Clone;
use fmt;
use iter::IteratorExt;
}
/// A trait that represents something bytes-like (e.g. a &[u8] or a &str)
-pub trait BytesContainer for Sized? {
+pub trait BytesContainer {
/// Returns a &[u8] representing the receiver
fn container_as_bytes<'a>(&'a self) -> &'a [u8];
/// Returns the receiver interpreted as a utf-8 string, if possible
impl BytesContainer for CString {
#[inline]
fn container_as_bytes<'a>(&'a self) -> &'a [u8] {
- self.as_bytes_no_nul()
+ self.as_bytes()
}
}
-impl<'a, Sized? T: BytesContainer> BytesContainer for &'a T {
+impl<'a, T: ?Sized + BytesContainer> BytesContainer for &'a T {
#[inline]
fn container_as_bytes(&self) -> &[u8] {
(**self).container_as_bytes()
fn contains_nul<T: BytesContainer>(v: &T) -> bool {
v.container_as_bytes().iter().any(|&x| x == 0)
}
-
-#[cfg(test)]
-mod tests {
- use prelude::v1::*;
- use c_str::ToCStr;
- use path::{WindowsPath, PosixPath};
-
- #[test]
- fn test_cstring() {
- let input = "/foo/bar/baz";
- let path: PosixPath = PosixPath::new(input.to_c_str());
- assert_eq!(path.as_vec(), input.as_bytes());
-
- let input = r"\foo\bar\baz";
- let path: WindowsPath = WindowsPath::new(input.to_c_str());
- assert_eq!(path.as_str().unwrap(), input);
- }
-}
//! POSIX file path handling
-use c_str::{CString, ToCStr};
use clone::Clone;
-use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
+use cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd};
use hash;
use io::Writer;
use iter::{AdditiveIterator, Extend};
use iter::{Iterator, IteratorExt, Map};
-use option::Option;
-use option::Option::{None, Some};
use kinds::Sized;
-use str::{FromStr, Str};
-use str;
-use slice::{Split, AsSlice, SliceConcatExt, SliceExt};
+use option::Option::{self, Some, None};
+use slice::{AsSlice, Split, SliceExt, SliceConcatExt};
+use str::{self, FromStr, StrExt};
use vec::Vec;
use super::{BytesContainer, GenericPath, GenericPathUnsafe};
}
}
-// FIXME (#12938): Until DST lands, we cannot decompose &str into & and str, so
-// we cannot usefully take ToCStr arguments by reference (without forcing an
-// additional & around &str). So we are instead temporarily adding an instance
-// for &Path, so that we can take ToCStr as owned. When DST lands, the &Path
-// instance should be removed, and arguments bound by ToCStr should be passed by
-// reference.
-
-impl ToCStr for Path {
- #[inline]
- fn to_c_str(&self) -> CString {
- // The Path impl guarantees no internal NUL
- unsafe { self.to_c_str_unchecked() }
- }
-
- #[inline]
- unsafe fn to_c_str_unchecked(&self) -> CString {
- self.as_vec().to_c_str_unchecked()
- }
-}
-
impl<S: hash::Writer> hash::Hash<S> for Path {
#[inline]
fn hash(&self, state: &mut S) {
/// Returns a normalized byte vector representation of a path, by removing all empty
/// components, and unnecessary . and .. components.
- fn normalize<Sized? V: AsSlice<u8>>(v: &V) -> Vec<u8> {
+ fn normalize<V: ?Sized + AsSlice<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;
t!(b"foo/\xFFbar", filename_display, "\u{FFFD}bar");
t!(b"/", filename_display, "");
- macro_rules! t(
+ macro_rules! t {
($path:expr, $exp:expr) => (
{
let path = Path::new($path);
assert!(mo.as_slice() == $exp);
}
)
- );
+ }
t!("foo", "foo");
t!(b"foo\x80", "foo\u{FFFD}");
#[test]
fn test_display() {
- macro_rules! t(
+ macro_rules! t {
($path:expr, $exp:expr, $expf:expr) => (
{
let path = Path::new($path);
assert!(f == $expf);
}
)
- );
+ }
t!(b"foo", "foo", "foo");
t!(b"foo/bar", "foo/bar", "bar");
#[test]
fn test_components() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $op:ident, $exp:expr) => (
{
let path = Path::new($path);
assert!(path.$op() == $exp);
}
);
- );
+ }
t!(v: b"a/b/c", filename, Some(b"c"));
t!(v: b"a/b/c\xFF", filename, Some(b"c\xFF"));
#[test]
fn test_push() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $join:expr) => (
{
let path = $path;
assert!(p1 == p2.join(join));
}
)
- );
+ }
t!(s: "a/b/c", "..");
t!(s: "/a/b/c", "d");
#[test]
fn test_push_path() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $push:expr, $exp:expr) => (
{
let mut p = Path::new($path);
assert!(p.as_str() == Some($exp));
}
)
- );
+ }
t!(s: "a/b/c", "d", "a/b/c/d");
t!(s: "/a/b/c", "d", "/a/b/c/d");
#[test]
fn test_push_many() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $push:expr, $exp:expr) => (
{
let mut p = Path::new($path);
assert!(p.as_vec() == $exp);
}
)
- );
+ }
t!(s: "a/b/c", ["d", "e"], "a/b/c/d/e");
t!(s: "a/b/c", ["d", "/e"], "/e");
#[test]
fn test_pop() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $left:expr, $right:expr) => (
{
let mut p = Path::new($path);
assert!(result == $right);
}
)
- );
+ }
t!(b: b"a/b/c", b"a/b", true);
t!(b: b"a", b".", true);
#[test]
fn test_join_path() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $join:expr, $exp:expr) => (
{
let path = Path::new($path);
assert!(res.as_str() == Some($exp));
}
)
- );
+ }
t!(s: "a/b/c", "..", "a/b");
t!(s: "/a/b/c", "d", "/a/b/c/d");
#[test]
fn test_join_many() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $join:expr, $exp:expr) => (
{
let path = Path::new($path);
assert!(res.as_vec() == $exp);
}
)
- );
+ }
t!(s: "a/b/c", ["d", "e"], "a/b/c/d/e");
t!(s: "a/b/c", ["..", "d"], "a/b/d");
#[test]
fn test_setters() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $set:ident, $with:ident, $arg:expr) => (
{
let path = $path;
assert!(p1 == p2.$with(arg));
}
)
- );
+ }
t!(v: b"a/b/c", set_filename, with_filename, b"d");
t!(v: b"/", set_filename, with_filename, b"foo");
#[test]
fn test_getters() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => (
{
let path = $path;
assert!(path.extension() == $ext);
}
)
- );
+ }
t!(v: Path::new(b"a/b/c"), Some(b"c"), b"a/b", Some(b"c"), None);
t!(v: Path::new(b"a/b/\xFF"), Some(b"\xFF"), b"a/b", Some(b"\xFF"), None);
#[test]
fn test_is_absolute() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $abs:expr, $rel:expr) => (
{
let path = Path::new($path);
assert_eq!(path.is_relative(), $rel);
}
)
- );
+ }
t!(s: "a/b/c", false, true);
t!(s: "/a/b/c", true, false);
t!(s: "a", false, true);
#[test]
fn test_is_ancestor_of() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $dest:expr, $exp:expr) => (
{
let path = Path::new($path);
assert_eq!(path.is_ancestor_of(&dest), $exp);
}
)
- );
+ }
t!(s: "a/b/c", "a/b/c/d", true);
t!(s: "a/b/c", "a/b/c", true);
#[test]
fn test_ends_with_path() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $child:expr, $exp:expr) => (
{
let path = Path::new($path);
assert_eq!(path.ends_with_path(&child), $exp);
}
)
- );
+ }
t!(s: "a/b/c", "c", true);
t!(s: "a/b/c", "d", false);
#[test]
fn test_path_relative_from() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $other:expr, $exp:expr) => (
{
let path = Path::new($path);
assert_eq!(res.as_ref().and_then(|x| x.as_str()), $exp);
}
)
- );
+ }
t!(s: "a/b/c", "a/b", Some("c"));
t!(s: "a/b/c", "a/b/d", Some("../c"));
#[test]
fn test_components_iter() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $exp:expr) => (
{
let path = Path::new($path);
assert_eq!(comps, exp)
}
)
- );
+ }
t!(b: b"a/b/c", [b"a", b"b", b"c"]);
t!(b: b"/\xFF/a/\x80", [b"\xFF", b"a", b"\x80"]);
#[test]
fn test_str_components() {
- macro_rules! t(
+ macro_rules! t {
(b: $arg:expr, $exp:expr) => (
{
let path = Path::new($arg);
assert_eq!(comps, exp);
}
)
- );
+ }
t!(b: b"a/b/c", [Some("a"), Some("b"), Some("c")]);
t!(b: b"/\xFF/a/\x80", [None, Some("a"), None]);
use self::PathPrefix::*;
use ascii::AsciiExt;
-use c_str::{CString, ToCStr};
use char::CharExt;
use clone::Clone;
-use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
+use cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd};
use hash;
use io::Writer;
use iter::{AdditiveIterator, Extend};
use iter::{Iterator, IteratorExt, Map, repeat};
use mem;
-use option::Option;
-use option::Option::{Some, None};
+use option::Option::{self, Some, None};
use slice::{SliceExt, SliceConcatExt};
use str::{SplitTerminator, FromStr, StrExt};
use string::{String, ToString};
}
}
-// FIXME (#12938): Until DST lands, we cannot decompose &str into & and str, so
-// we cannot usefully take ToCStr arguments by reference (without forcing an
-// additional & around &str). So we are instead temporarily adding an instance
-// for &Path, so that we can take ToCStr as owned. When DST lands, the &Path
-// instance should be removed, and arguments bound by ToCStr should be passed by
-// reference.
-
-impl ToCStr for Path {
- #[inline]
- fn to_c_str(&self) -> CString {
- // The Path impl guarantees no internal NUL
- unsafe { self.to_c_str_unchecked() }
- }
-
- #[inline]
- unsafe fn to_c_str_unchecked(&self) -> CString {
- self.as_vec().to_c_str_unchecked()
- }
-}
-
impl<S: hash::Writer> hash::Hash<S> for Path {
#[cfg(not(test))]
#[inline]
#[test]
fn test_parse_prefix() {
- macro_rules! t(
+ macro_rules! t {
($path:expr, $exp:expr) => (
{
let path = $path;
"parse_prefix(\"{}\"): expected {}, found {}", path, exp, res);
}
)
- );
+ }
t!("\\\\SERVER\\share\\foo", Some(UNCPrefix(6,5)));
t!("\\\\", None);
#[test]
fn test_display() {
- macro_rules! t(
+ macro_rules! t {
($path:expr, $exp:expr, $expf:expr) => (
{
let path = Path::new($path);
assert_eq!(f, $expf);
}
)
- );
+ }
t!("foo", "foo", "foo");
t!("foo\\bar", "foo\\bar", "bar");
#[test]
fn test_components() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $op:ident, $exp:expr) => (
{
let path = $path;
assert!(path.$op() == $exp);
}
)
- );
+ }
t!(v: b"a\\b\\c", filename, Some(b"c"));
t!(s: "a\\b\\c", filename_str, "c");
#[test]
fn test_push() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $join:expr) => (
{
let path = $path;
assert!(p1 == p2.join(join));
}
)
- );
+ }
t!(s: "a\\b\\c", "..");
t!(s: "\\a\\b\\c", "d");
#[test]
fn test_push_path() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $push:expr, $exp:expr) => (
{
let mut p = Path::new($path);
assert_eq!(p.as_str(), Some($exp));
}
)
- );
+ }
t!(s: "a\\b\\c", "d", "a\\b\\c\\d");
t!(s: "\\a\\b\\c", "d", "\\a\\b\\c\\d");
#[test]
fn test_push_many() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $push:expr, $exp:expr) => (
{
let mut p = Path::new($path);
assert_eq!(p.as_vec(), $exp);
}
)
- );
+ }
t!(s: "a\\b\\c", ["d", "e"], "a\\b\\c\\d\\e");
t!(s: "a\\b\\c", ["d", "\\e"], "\\e");
#[test]
fn test_pop() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $left:expr, $right:expr) => (
{
let pstr = $path;
assert!(result == $right);
}
)
- );
+ }
t!(s: "a\\b\\c", "a\\b", true);
t!(s: "a", ".", true);
#[test]
fn test_join_path() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $join:expr, $exp:expr) => (
{
let path = Path::new($path);
assert_eq!(res.as_str(), Some($exp));
}
)
- );
+ }
t!(s: "a\\b\\c", "..", "a\\b");
t!(s: "\\a\\b\\c", "d", "\\a\\b\\c\\d");
#[test]
fn test_join_many() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $join:expr, $exp:expr) => (
{
let path = Path::new($path);
assert_eq!(res.as_vec(), $exp);
}
)
- );
+ }
t!(s: "a\\b\\c", ["d", "e"], "a\\b\\c\\d\\e");
t!(s: "a\\b\\c", ["..", "d"], "a\\b\\d");
#[test]
fn test_with_helpers() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $op:ident, $arg:expr, $res:expr) => (
{
let pstr = $path;
pstr, stringify!($op), arg, exp, res.as_str().unwrap());
}
)
- );
+ }
t!(s: "a\\b\\c", with_filename, "d", "a\\b\\d");
t!(s: ".", with_filename, "foo", "foo");
#[test]
fn test_setters() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $set:ident, $with:ident, $arg:expr) => (
{
let path = $path;
assert!(p1 == p2.$with(arg));
}
)
- );
+ }
t!(v: b"a\\b\\c", set_filename, with_filename, b"d");
t!(v: b"\\", set_filename, with_filename, b"foo");
#[test]
fn test_getters() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => (
{
let path = $path;
assert!(path.extension() == $ext);
}
)
- );
+ }
t!(v: Path::new(b"a\\b\\c"), Some(b"c"), b"a\\b", Some(b"c"), None);
t!(s: Path::new("a\\b\\c"), Some("c"), Some("a\\b"), Some("c"), None);
#[test]
fn test_is_absolute() {
- macro_rules! t(
+ macro_rules! t {
($path:expr, $abs:expr, $vol:expr, $cwd:expr, $rel:expr) => (
{
let path = Path::new($path);
path.as_str().unwrap(), rel, b);
}
)
- );
+ }
t!("a\\b\\c", false, false, false, true);
t!("\\a\\b\\c", false, true, false, false);
t!("a", false, false, false, true);
#[test]
fn test_is_ancestor_of() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $dest:expr, $exp:expr) => (
{
let path = Path::new($path);
path.as_str().unwrap(), dest.as_str().unwrap(), exp, res);
}
)
- );
+ }
t!(s: "a\\b\\c", "a\\b\\c\\d", true);
t!(s: "a\\b\\c", "a\\b\\c", true);
#[test]
fn test_ends_with_path() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $child:expr, $exp:expr) => (
{
let path = Path::new($path);
assert_eq!(path.ends_with_path(&child), $exp);
}
);
- );
+ }
t!(s: "a\\b\\c", "c", true);
t!(s: "a\\b\\c", "d", false);
#[test]
fn test_path_relative_from() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $other:expr, $exp:expr) => (
{
let path = Path::new($path);
res.as_ref().and_then(|x| x.as_str()));
}
)
- );
+ }
t!(s: "a\\b\\c", "a\\b", Some("c"));
t!(s: "a\\b\\c", "a\\b\\d", Some("..\\c"));
#[test]
fn test_str_components() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $exp:expr) => (
{
let path = Path::new($path);
assert_eq!(comps, exp);
}
);
- );
+ }
t!(s: b"a\\b\\c", ["a", "b", "c"]);
t!(s: "a\\b\\c", ["a", "b", "c"]);
#[test]
fn test_components_iter() {
- macro_rules! t(
+ macro_rules! t {
(s: $path:expr, $exp:expr) => (
{
let path = Path::new($path);
assert_eq!(comps, exp);
}
)
- );
+ }
t!(s: "a\\b\\c", [b"a", b"b", b"c"]);
t!(s: ".", [b"."]);
#[test]
fn test_make_non_verbatim() {
- macro_rules! t(
+ macro_rules! t {
($path:expr, $exp:expr) => (
{
let path = Path::new($path);
assert!(make_non_verbatim(&path) == exp);
}
)
- );
+ }
t!(r"\a\b\c", Some(r"\a\b\c"));
t!(r"a\b\c", Some(r"a\b\c"));
//! pervasive that it would be obnoxious to import for every use, particularly
//! those that define methods on primitive types.
+#![stable]
+
#[stable]
pub mod v1;
#[stable] #[doc(no_inline)] pub use char::CharExt;
#[stable] #[doc(no_inline)] pub use clone::Clone;
#[stable] #[doc(no_inline)] pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
-#[stable] #[doc(no_inline)] pub use iter::CloneIteratorExt;
#[stable] #[doc(no_inline)] pub use iter::DoubleEndedIterator;
#[stable] #[doc(no_inline)] pub use iter::ExactSizeIterator;
#[stable] #[doc(no_inline)] pub use iter::{Iterator, IteratorExt, Extend};
-#[stable] #[doc(no_inline)] pub use iter::{IteratorCloneExt, IteratorOrdExt};
#[stable] #[doc(no_inline)] pub use option::Option::{self, Some, None};
#[stable] #[doc(no_inline)] pub use ptr::{PtrExt, MutPtrExt};
#[stable] #[doc(no_inline)] pub use result::Result::{self, Ok, Err};
/// The standard RNG. This is designed to be efficient on the current
/// platform.
-#[derive(Copy)]
+#[derive(Copy, Clone)]
pub struct StdRng {
rng: IsaacWordRng,
}
type ThreadRngInner = reseeding::ReseedingRng<StdRng, ThreadRngReseeder>;
/// The thread-local RNG.
+#[derive(Clone)]
pub struct ThreadRng {
rng: Rc<RefCell<ThreadRngInner>>,
}
use path::Path;
use rand::Rng;
use rand::reader::ReaderRng;
- use result::Result::{Ok, Err};
+ use result::Result::Ok;
use slice::SliceExt;
use mem;
use os::errno;
+ // NOTE: for old macros; remove after the next snapshot
+ #[cfg(stage0)] use result::Result::Err;
+
#[cfg(all(target_os = "linux",
any(target_arch = "x86_64",
target_arch = "x86",
mod imp {
use prelude::v1::*;
+ use libc;
use mem;
- use slice;
+ use ffi;
use sync::{StaticMutex, MUTEX_INIT};
}
unsafe fn load_argc_and_argv(argc: int, argv: *const *const u8) -> Vec<Vec<u8>> {
+ let argv = argv as *const *const libc::c_char;
range(0, argc as uint).map(|i| {
- let arg = *argv.offset(i as int);
- let mut len = 0u;
- while *arg.offset(len as int) != 0 {
- len += 1u;
- }
- slice::from_raw_buf(&arg, len).to_vec()
+ ffi::c_str_to_bytes(&*argv.offset(i as int)).to_vec()
}).collect()
}
use prelude::v1::*;
use os;
-use sync::atomic::{mod, Ordering};
+use sync::atomic::{self, Ordering};
pub use sys::backtrace::write;
//! These macros call functions which are only accessible in the `rt` module, so
//! they aren't defined anywhere outside of the `rt` module.
-#![macro_escape]
-
macro_rules! rterrln {
($fmt:expr $($arg:tt)*) => ( {
::rt::util::dumb_print(format_args!(concat!($fmt, "\n") $($arg)*))
pub mod backtrace;
// Internals
+#[cfg_attr(stage0, macro_escape)]
+#[cfg_attr(not(stage0), macro_use)]
mod macros;
// These should be refactored/moved/made private over time
use intrinsics;
use libc::c_void;
use mem;
-use sync::atomic::{mod, Ordering};
+use sync::atomic::{self, Ordering};
use sync::{Once, ONCE_INIT};
use rt::libunwind as uw;
use os;
use slice;
use str;
-use sync::atomic::{mod, Ordering};
+use sync::atomic::{self, Ordering};
/// Dynamically inquire about whether we're running under V.
/// You should usually not use this unless your test definitely
pub fn notify_all(&self) { unsafe { self.inner.inner.notify_all() } }
}
+#[stable]
impl Drop for Condvar {
fn drop(&mut self) {
unsafe { self.inner.inner.destroy() }
//! and/or blocking at all, but rather provide the necessary tools to build
//! other types of concurrent primitives.
-#![experimental]
+#![stable]
pub use alloc::arc::{Arc, Weak};
pub use core::atomic;
pub use self::mutex::{Mutex, MutexGuard, StaticMutex};
pub use self::mutex::MUTEX_INIT;
-pub use self::rwlock::{RWLock, StaticRWLock, RWLOCK_INIT};
-pub use self::rwlock::{RWLockReadGuard, RWLockWriteGuard};
+pub use self::rwlock::{RwLock, StaticRwLock, RW_LOCK_INIT};
+pub use self::rwlock::{RwLockReadGuard, RwLockWriteGuard};
pub use self::condvar::{Condvar, StaticCondvar, CONDVAR_INIT};
pub use self::once::{Once, ONCE_INIT};
pub use self::semaphore::{Semaphore, SemaphoreGuard};
//! }
//! ```
+#![stable]
+
// A description of how Rust's channel implementation works
//
// Channels are supposed to be the basic building block for all other
/// drop(rx);
/// assert_eq!(tx.send(1i).err().unwrap().0, 1);
/// ```
+ #[stable]
pub fn send(&self, t: T) -> Result<(), SendError<T>> {
let (new_inner, ret) = match *unsafe { self.inner() } {
Flavor::Oneshot(ref p) => {
// asleep (we're looking at it), so the receiver
// can't go away.
(*a.get()).send(t).ok().unwrap();
- token.signal();
+ token.signal();
(a, Ok(()))
}
}
}
#[unsafe_destructor]
+#[stable]
impl<T: Send> Drop for Sender<T> {
fn drop(&mut self) {
match *unsafe { self.inner_mut() } {
}
#[unsafe_destructor]
+#[stable]
impl<T: Send> Drop for SyncSender<T> {
fn drop(&mut self) {
unsafe { (*self.inner.get()).drop_chan(); }
}
}
-#[unstable]
+#[stable]
impl<'a, T: Send> Iterator for Iter<'a, T> {
type Item = T;
}
#[unsafe_destructor]
+#[stable]
impl<T: Send> Drop for Receiver<T> {
fn drop(&mut self) {
match *unsafe { self.inner_mut() } {
}
#[unsafe_destructor]
+#[stable]
impl<T: Send> Drop for Queue<T> {
fn drop(&mut self) {
unsafe {
}
#[unsafe_destructor]
+#[stable]
impl<T: Send> Drop for Mutex<T> {
fn drop(&mut self) {
// This is actually safe b/c we know that there is no further usage of
}
}
+#[stable]
impl<'mutex, T> Deref for MutexGuard<'mutex, T> {
type Target = T;
unsafe { &*self.__data.get() }
}
}
+#[stable]
impl<'mutex, T> DerefMut for MutexGuard<'mutex, T> {
fn deref_mut<'a>(&'a mut self) -> &'a mut T {
unsafe { &mut *self.__data.get() }
}
#[unsafe_destructor]
+#[stable]
impl<'a, T> Drop for MutexGuard<'a, T> {
#[inline]
fn drop(&mut self) {
unsafe { self.mutex.destroy() }
}
}
-
- /// Deprecated
- #[deprecated = "renamed to `call_once`"]
- pub fn doit<F>(&'static self, f: F) where F: FnOnce() { self.call_once(f) }
}
#[cfg(test)]
/// A type of error which can be returned whenever a lock is acquired.
///
-/// Both Mutexes and RWLocks are poisoned whenever a task fails while the lock
+/// Both Mutexes and RwLocks are poisoned whenever a task fails while the lock
/// is held. The precise semantics for when a lock is poisoned is documented on
/// each lock, but once a lock is poisoned then all future acquisitions will
/// return this error.
///
/// # Poisoning
///
-/// RWLocks, like Mutexes, will become poisoned on panics. Note, however, that
-/// an RWLock may only be poisoned if a panic occurs while it is locked
+/// RwLocks, like Mutexes, will become poisoned on panics. Note, however, that
+/// an RwLock may only be poisoned if a panic occurs while it is locked
/// exclusively (write mode). If a panic occurs in any reader, then the lock
/// will not be poisoned.
///
/// # Examples
///
/// ```
-/// use std::sync::RWLock;
+/// use std::sync::RwLock;
///
-/// let lock = RWLock::new(5i);
+/// let lock = RwLock::new(5i);
///
/// // many reader locks can be held at once
/// {
/// } // write lock is dropped here
/// ```
#[stable]
-pub struct RWLock<T> {
- inner: Box<StaticRWLock>,
+pub struct RwLock<T> {
+ inner: Box<StaticRwLock>,
data: UnsafeCell<T>,
}
-unsafe impl<T:'static+Send> Send for RWLock<T> {}
-unsafe impl<T> Sync for RWLock<T> {}
+unsafe impl<T:'static+Send> Send for RwLock<T> {}
+unsafe impl<T> Sync for RwLock<T> {}
-/// Structure representing a statically allocated RWLock.
+/// Structure representing a statically allocated RwLock.
///
/// This structure is intended to be used inside of a `static` and will provide
/// automatic global access as well as lazy initialization. The internal
-/// resources of this RWLock, however, must be manually deallocated.
+/// resources of this RwLock, however, must be manually deallocated.
///
/// # Example
///
/// ```
-/// use std::sync::{StaticRWLock, RWLOCK_INIT};
+/// use std::sync::{StaticRwLock, RW_LOCK_INIT};
///
-/// static LOCK: StaticRWLock = RWLOCK_INIT;
+/// static LOCK: StaticRwLock = RW_LOCK_INIT;
///
/// {
/// let _g = LOCK.read().unwrap();
/// }
/// unsafe { LOCK.destroy() } // free all resources
/// ```
-#[unstable = "may be merged with RWLock in the future"]
-pub struct StaticRWLock {
+#[unstable = "may be merged with RwLock in the future"]
+pub struct StaticRwLock {
lock: sys::RWLock,
poison: poison::Flag,
}
-unsafe impl Send for StaticRWLock {}
-unsafe impl Sync for StaticRWLock {}
+unsafe impl Send for StaticRwLock {}
+unsafe impl Sync for StaticRwLock {}
/// Constant initialization for a statically-initialized rwlock.
-#[unstable = "may be merged with RWLock in the future"]
-pub const RWLOCK_INIT: StaticRWLock = StaticRWLock {
+#[unstable = "may be merged with RwLock in the future"]
+pub const RW_LOCK_INIT: StaticRwLock = StaticRwLock {
lock: sys::RWLOCK_INIT,
poison: poison::FLAG_INIT,
};
/// dropped.
#[must_use]
#[stable]
-pub struct RWLockReadGuard<'a, T: 'a> {
- __lock: &'a StaticRWLock,
+pub struct RwLockReadGuard<'a, T: 'a> {
+ __lock: &'a StaticRwLock,
__data: &'a UnsafeCell<T>,
__marker: marker::NoSend,
}
/// dropped.
#[must_use]
#[stable]
-pub struct RWLockWriteGuard<'a, T: 'a> {
- __lock: &'a StaticRWLock,
+pub struct RwLockWriteGuard<'a, T: 'a> {
+ __lock: &'a StaticRwLock,
__data: &'a UnsafeCell<T>,
__poison: poison::Guard,
__marker: marker::NoSend,
}
-impl<T: Send + Sync> RWLock<T> {
- /// Creates a new instance of an RWLock which is unlocked and read to go.
+impl<T: Send + Sync> RwLock<T> {
+ /// Creates a new instance of an RwLock which is unlocked and read to go.
#[stable]
- pub fn new(t: T) -> RWLock<T> {
- RWLock { inner: box RWLOCK_INIT, data: UnsafeCell::new(t) }
+ pub fn new(t: T) -> RwLock<T> {
+ RwLock { inner: box RW_LOCK_INIT, data: UnsafeCell::new(t) }
}
/// Locks this rwlock with shared read access, blocking the current thread
///
/// # Failure
///
- /// This function will return an error if the RWLock is poisoned. An RWLock
+ /// This function will return an error if the RwLock is poisoned. An RwLock
/// is poisoned whenever a writer panics while holding an exclusive lock.
/// The failure will occur immediately after the lock has been acquired.
#[inline]
#[stable]
- pub fn read(&self) -> LockResult<RWLockReadGuard<T>> {
+ pub fn read(&self) -> LockResult<RwLockReadGuard<T>> {
unsafe { self.inner.lock.read() }
- RWLockReadGuard::new(&*self.inner, &self.data)
+ RwLockReadGuard::new(&*self.inner, &self.data)
}
/// Attempt to acquire this lock with shared read access.
///
/// # Failure
///
- /// This function will return an error if the RWLock is poisoned. An RWLock
+ /// This function will return an error if the RwLock is poisoned. An RwLock
/// is poisoned whenever a writer panics while holding an exclusive lock. An
/// error will only be returned if the lock would have otherwise been
/// acquired.
#[inline]
#[stable]
- pub fn try_read(&self) -> TryLockResult<RWLockReadGuard<T>> {
+ pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<T>> {
if unsafe { self.inner.lock.try_read() } {
- Ok(try!(RWLockReadGuard::new(&*self.inner, &self.data)))
+ Ok(try!(RwLockReadGuard::new(&*self.inner, &self.data)))
} else {
Err(TryLockError::WouldBlock)
}
///
/// # Failure
///
- /// This function will return an error if the RWLock is poisoned. An RWLock
+ /// This function will return an error if the RwLock is poisoned. An RwLock
/// is poisoned whenever a writer panics while holding an exclusive lock.
/// An error will be returned when the lock is acquired.
#[inline]
#[stable]
- pub fn write(&self) -> LockResult<RWLockWriteGuard<T>> {
+ pub fn write(&self) -> LockResult<RwLockWriteGuard<T>> {
unsafe { self.inner.lock.write() }
- RWLockWriteGuard::new(&*self.inner, &self.data)
+ RwLockWriteGuard::new(&*self.inner, &self.data)
}
/// Attempt to lock this rwlock with exclusive write access.
///
/// # Failure
///
- /// This function will return an error if the RWLock is poisoned. An RWLock
+ /// This function will return an error if the RwLock is poisoned. An RwLock
/// is poisoned whenever a writer panics while holding an exclusive lock. An
/// error will only be returned if the lock would have otherwise been
/// acquired.
#[inline]
#[stable]
- pub fn try_write(&self) -> TryLockResult<RWLockWriteGuard<T>> {
+ pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<T>> {
if unsafe { self.inner.lock.try_read() } {
- Ok(try!(RWLockWriteGuard::new(&*self.inner, &self.data)))
+ Ok(try!(RwLockWriteGuard::new(&*self.inner, &self.data)))
} else {
Err(TryLockError::WouldBlock)
}
}
#[unsafe_destructor]
-impl<T> Drop for RWLock<T> {
+#[stable]
+impl<T> Drop for RwLock<T> {
fn drop(&mut self) {
unsafe { self.inner.lock.destroy() }
}
unsafe impl Sync for Dummy {}
static DUMMY: Dummy = Dummy(UnsafeCell { value: () });
-impl StaticRWLock {
+impl StaticRwLock {
/// Locks this rwlock with shared read access, blocking the current thread
/// until it can be acquired.
///
- /// See `RWLock::read`.
+ /// See `RwLock::read`.
#[inline]
- #[unstable = "may be merged with RWLock in the future"]
- pub fn read(&'static self) -> LockResult<RWLockReadGuard<'static, ()>> {
+ #[unstable = "may be merged with RwLock in the future"]
+ pub fn read(&'static self) -> LockResult<RwLockReadGuard<'static, ()>> {
unsafe { self.lock.read() }
- RWLockReadGuard::new(self, &DUMMY.0)
+ RwLockReadGuard::new(self, &DUMMY.0)
}
/// Attempt to acquire this lock with shared read access.
///
- /// See `RWLock::try_read`.
+ /// See `RwLock::try_read`.
#[inline]
- #[unstable = "may be merged with RWLock in the future"]
+ #[unstable = "may be merged with RwLock in the future"]
pub fn try_read(&'static self)
- -> TryLockResult<RWLockReadGuard<'static, ()>> {
+ -> TryLockResult<RwLockReadGuard<'static, ()>> {
if unsafe { self.lock.try_read() } {
- Ok(try!(RWLockReadGuard::new(self, &DUMMY.0)))
+ Ok(try!(RwLockReadGuard::new(self, &DUMMY.0)))
} else {
Err(TryLockError::WouldBlock)
}
/// Lock this rwlock with exclusive write access, blocking the current
/// thread until it can be acquired.
///
- /// See `RWLock::write`.
+ /// See `RwLock::write`.
#[inline]
- #[unstable = "may be merged with RWLock in the future"]
- pub fn write(&'static self) -> LockResult<RWLockWriteGuard<'static, ()>> {
+ #[unstable = "may be merged with RwLock in the future"]
+ pub fn write(&'static self) -> LockResult<RwLockWriteGuard<'static, ()>> {
unsafe { self.lock.write() }
- RWLockWriteGuard::new(self, &DUMMY.0)
+ RwLockWriteGuard::new(self, &DUMMY.0)
}
/// Attempt to lock this rwlock with exclusive write access.
///
- /// See `RWLock::try_write`.
+ /// See `RwLock::try_write`.
#[inline]
- #[unstable = "may be merged with RWLock in the future"]
+ #[unstable = "may be merged with RwLock in the future"]
pub fn try_write(&'static self)
- -> TryLockResult<RWLockWriteGuard<'static, ()>> {
+ -> TryLockResult<RwLockWriteGuard<'static, ()>> {
if unsafe { self.lock.try_write() } {
- Ok(try!(RWLockWriteGuard::new(self, &DUMMY.0)))
+ Ok(try!(RwLockWriteGuard::new(self, &DUMMY.0)))
} else {
Err(TryLockError::WouldBlock)
}
/// active users of the lock, and this also doesn't prevent any future users
/// of this lock. This method is required to be called to not leak memory on
/// all platforms.
- #[unstable = "may be merged with RWLock in the future"]
+ #[unstable = "may be merged with RwLock in the future"]
pub unsafe fn destroy(&'static self) {
self.lock.destroy()
}
}
-impl<'rwlock, T> RWLockReadGuard<'rwlock, T> {
- fn new(lock: &'rwlock StaticRWLock, data: &'rwlock UnsafeCell<T>)
- -> LockResult<RWLockReadGuard<'rwlock, T>> {
+impl<'rwlock, T> RwLockReadGuard<'rwlock, T> {
+ fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
+ -> LockResult<RwLockReadGuard<'rwlock, T>> {
poison::map_result(lock.poison.borrow(), |_| {
- RWLockReadGuard {
+ RwLockReadGuard {
__lock: lock,
__data: data,
__marker: marker::NoSend,
})
}
}
-impl<'rwlock, T> RWLockWriteGuard<'rwlock, T> {
- fn new(lock: &'rwlock StaticRWLock, data: &'rwlock UnsafeCell<T>)
- -> LockResult<RWLockWriteGuard<'rwlock, T>> {
+impl<'rwlock, T> RwLockWriteGuard<'rwlock, T> {
+ fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
+ -> LockResult<RwLockWriteGuard<'rwlock, T>> {
poison::map_result(lock.poison.borrow(), |guard| {
- RWLockWriteGuard {
+ RwLockWriteGuard {
__lock: lock,
__data: data,
__poison: guard,
}
}
-impl<'rwlock, T> Deref for RWLockReadGuard<'rwlock, T> {
+#[stable]
+impl<'rwlock, T> Deref for RwLockReadGuard<'rwlock, T> {
type Target = T;
fn deref(&self) -> &T { unsafe { &*self.__data.get() } }
}
-impl<'rwlock, T> Deref for RWLockWriteGuard<'rwlock, T> {
+#[stable]
+impl<'rwlock, T> Deref for RwLockWriteGuard<'rwlock, T> {
type Target = T;
fn deref(&self) -> &T { unsafe { &*self.__data.get() } }
}
-impl<'rwlock, T> DerefMut for RWLockWriteGuard<'rwlock, T> {
+#[stable]
+impl<'rwlock, T> DerefMut for RwLockWriteGuard<'rwlock, T> {
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.__data.get() }
}
}
#[unsafe_destructor]
-impl<'a, T> Drop for RWLockReadGuard<'a, T> {
+#[stable]
+impl<'a, T> Drop for RwLockReadGuard<'a, T> {
fn drop(&mut self) {
unsafe { self.__lock.lock.read_unlock(); }
}
}
#[unsafe_destructor]
-impl<'a, T> Drop for RWLockWriteGuard<'a, T> {
+#[stable]
+impl<'a, T> Drop for RwLockWriteGuard<'a, T> {
fn drop(&mut self) {
self.__lock.poison.done(&self.__poison);
unsafe { self.__lock.lock.write_unlock(); }
use rand::{self, Rng};
use sync::mpsc::channel;
use thread::Thread;
- use sync::{Arc, RWLock, StaticRWLock, RWLOCK_INIT};
+ use sync::{Arc, RwLock, StaticRwLock, RW_LOCK_INIT};
#[test]
fn smoke() {
- let l = RWLock::new(());
+ let l = RwLock::new(());
drop(l.read().unwrap());
drop(l.write().unwrap());
drop((l.read().unwrap(), l.read().unwrap()));
#[test]
fn static_smoke() {
- static R: StaticRWLock = RWLOCK_INIT;
+ static R: StaticRwLock = RW_LOCK_INIT;
drop(R.read().unwrap());
drop(R.write().unwrap());
drop((R.read().unwrap(), R.read().unwrap()));
#[test]
fn frob() {
- static R: StaticRWLock = RWLOCK_INIT;
+ static R: StaticRwLock = RW_LOCK_INIT;
static N: uint = 10;
static M: uint = 1000;
#[test]
fn test_rw_arc_poison_wr() {
- let arc = Arc::new(RWLock::new(1i));
+ let arc = Arc::new(RwLock::new(1i));
let arc2 = arc.clone();
let _: Result<uint, _> = Thread::spawn(move|| {
let _lock = arc2.write().unwrap();
#[test]
fn test_rw_arc_poison_ww() {
- let arc = Arc::new(RWLock::new(1i));
+ let arc = Arc::new(RwLock::new(1i));
let arc2 = arc.clone();
let _: Result<uint, _> = Thread::spawn(move|| {
let _lock = arc2.write().unwrap();
#[test]
fn test_rw_arc_no_poison_rr() {
- let arc = Arc::new(RWLock::new(1i));
+ let arc = Arc::new(RwLock::new(1i));
let arc2 = arc.clone();
let _: Result<uint, _> = Thread::spawn(move|| {
let _lock = arc2.read().unwrap();
}
#[test]
fn test_rw_arc_no_poison_rw() {
- let arc = Arc::new(RWLock::new(1i));
+ let arc = Arc::new(RwLock::new(1i));
let arc2 = arc.clone();
let _: Result<uint, _> = Thread::spawn(move|| {
let _lock = arc2.read().unwrap();
#[test]
fn test_rw_arc() {
- let arc = Arc::new(RWLock::new(0i));
+ let arc = Arc::new(RwLock::new(0i));
let arc2 = arc.clone();
let (tx, rx) = channel();
#[test]
fn test_rw_arc_access_in_unwind() {
- let arc = Arc::new(RWLock::new(1i));
+ let arc = Arc::new(RwLock::new(1i));
let arc2 = arc.clone();
let _ = Thread::spawn(move|| -> () {
struct Unwinder {
- i: Arc<RWLock<int>>,
+ i: Arc<RwLock<int>>,
}
impl Drop for Unwinder {
fn drop(&mut self) {
}
#[unsafe_destructor]
+#[stable]
impl<'a> Drop for SemaphoreGuard<'a> {
fn drop(&mut self) {
self.sem.release();
use io::{self, IoError, IoResult};
use prelude::v1::*;
use sys::{last_error, retry};
-use c_str::CString;
+use ffi::CString;
use num::Int;
use path::BytesContainer;
use collections;
use self::SocketStatus::*;
use self::InAddr::*;
-use c_str::ToCStr;
+use ffi::CString;
+use ffi;
use io::net::addrinfo;
use io::net::ip::{SocketAddr, IpAddr, Ipv4Addr, Ipv6Addr};
use io::{IoResult, IoError};
use libc::{self, c_char, c_int};
-use c_str::CString;
use mem;
use num::Int;
use ptr::{self, null, null_mut};
+use str;
use sys::{self, retry, c, sock_t, last_error, last_net_error, last_gai_error, close_sock,
wrlen, msglen_t, os, wouldblock, set_nonblocking, timer, ms_to_timeval,
decode_error_detailed};
assert!(host.is_some() || servname.is_some());
- let c_host = host.map(|x| x.to_c_str());
+ let c_host = host.map(|x| CString::from_slice(x.as_bytes()));
let c_host = c_host.as_ref().map(|x| x.as_ptr()).unwrap_or(null());
- let c_serv = servname.map(|x| x.to_c_str());
+ let c_serv = servname.map(|x| CString::from_slice(x.as_bytes()));
let c_serv = c_serv.as_ref().map(|x| x.as_ptr()).unwrap_or(null());
let hint = hint.map(|hint| {
}
unsafe {
- Ok(CString::new(hostbuf.as_ptr(), false).as_str().unwrap().to_string())
+ Ok(str::from_utf8(ffi::c_str_to_bytes(&hostbuf.as_ptr()))
+ .unwrap().to_string())
}
}
/// to symbols. This is a bit of a hokey implementation as-is, but it works for
/// all unix platforms we support right now, so it at least gets the job done.
-use c_str::CString;
-use io::{IoResult, Writer};
+use prelude::v1::*;
+
+use ffi;
+use io::IoResult;
use libc;
use mem;
-use option::Option::{self, Some, None};
-use result::Result::{Ok, Err};
+use str;
use sync::{StaticMutex, MUTEX_INIT};
use sys_common::backtrace::*;
#[cfg(all(target_os = "ios", target_arch = "arm"))]
#[inline(never)]
pub fn write(w: &mut Writer) -> IoResult<()> {
- use iter::{IteratorExt, range};
use result;
- use slice::SliceExt;
extern {
fn backtrace(buf: *mut *mut libc::c_void,
output(w, idx,addr, None)
} else {
output(w, idx, addr, Some(unsafe {
- CString::new(info.dli_sname, false)
+ ffi::c_str_to_bytes(&info.dli_sname)
}))
}
}
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> {
- use iter::{Iterator, IteratorExt};
use os;
- use path::GenericPath;
- use ptr::PtrExt;
use ptr;
- use slice::SliceExt;
////////////////////////////////////////////////////////////////////////
// libbacktrace.h API
if ret == 0 || data.is_null() {
output(w, idx, addr, None)
} else {
- output(w, idx, addr, Some(unsafe { CString::new(data, false) }))
+ output(w, idx, addr, Some(unsafe { ffi::c_str_to_bytes(&data) }))
}
}
// Finally, after all that work above, we can emit a symbol.
fn output(w: &mut Writer, idx: int, addr: *mut libc::c_void,
- s: Option<CString>) -> IoResult<()> {
+ s: Option<&[u8]>) -> IoResult<()> {
try!(write!(w, " {:2}: {:2$} - ", idx, addr, HEX_WIDTH));
- match s.as_ref().and_then(|c| c.as_str()) {
+ match s.and_then(|s| str::from_utf8(s).ok()) {
Some(string) => try!(demangle(w, string)),
None => try!(write!(w, "<unknown>")),
}
use prelude::v1::*;
-use c_str::{CString, ToCStr};
+use ffi::{self, CString};
use io::{FilePermission, Write, UnstableFileStat, Open, FileAccess, FileMode};
use io::{IoResult, FileStat, SeekStyle};
use io::{Read, Truncate, SeekCur, SeekSet, ReadWrite, SeekEnd, Append};
}
}
+fn cstr(path: &Path) -> CString {
+ CString::from_slice(path.as_vec())
+}
+
pub fn open(path: &Path, fm: FileMode, fa: FileAccess) -> IoResult<FileDesc> {
let flags = match fm {
Open => 0,
libc::S_IRUSR | libc::S_IWUSR),
};
- let path = path.to_c_str();
+ let path = cstr(path);
match retry(|| unsafe { libc::open(path.as_ptr(), flags, mode) }) {
-1 => Err(super::last_error()),
fd => Ok(FileDesc::new(fd, true)),
}
pub fn mkdir(p: &Path, mode: uint) -> IoResult<()> {
- let p = p.to_c_str();
+ let p = cstr(p);
mkerr_libc(unsafe { libc::mkdir(p.as_ptr(), mode as libc::mode_t) })
}
use libc::{opendir, readdir_r, closedir};
fn prune(root: &CString, dirs: Vec<Path>) -> Vec<Path> {
- let root = unsafe { CString::new(root.as_ptr(), false) };
let root = Path::new(root);
dirs.into_iter().filter(|path| {
let mut buf = Vec::<u8>::with_capacity(size as uint);
let ptr = buf.as_mut_ptr() as *mut dirent_t;
- let p = p.to_c_str();
+ let p = CString::from_slice(p.as_vec());
let dir_ptr = unsafe {opendir(p.as_ptr())};
if dir_ptr as uint != 0 {
let mut entry_ptr = 0 as *mut dirent_t;
while unsafe { readdir_r(dir_ptr, ptr, &mut entry_ptr) == 0 } {
if entry_ptr.is_null() { break }
- let cstr = unsafe {
- CString::new(rust_list_dir_val(entry_ptr), false)
- };
- paths.push(Path::new(cstr));
+ paths.push(unsafe {
+ Path::new(ffi::c_str_to_bytes(&rust_list_dir_val(entry_ptr)))
+ });
}
assert_eq!(unsafe { closedir(dir_ptr) }, 0);
Ok(prune(&p, paths))
}
pub fn unlink(p: &Path) -> IoResult<()> {
- let p = p.to_c_str();
+ let p = cstr(p);
mkerr_libc(unsafe { libc::unlink(p.as_ptr()) })
}
pub fn rename(old: &Path, new: &Path) -> IoResult<()> {
- let old = old.to_c_str();
- let new = new.to_c_str();
+ let old = cstr(old);
+ let new = cstr(new);
mkerr_libc(unsafe {
libc::rename(old.as_ptr(), new.as_ptr())
})
}
pub fn chmod(p: &Path, mode: uint) -> IoResult<()> {
- let p = p.to_c_str();
+ let p = cstr(p);
mkerr_libc(retry(|| unsafe {
libc::chmod(p.as_ptr(), mode as libc::mode_t)
}))
}
pub fn rmdir(p: &Path) -> IoResult<()> {
- let p = p.to_c_str();
+ let p = cstr(p);
mkerr_libc(unsafe { libc::rmdir(p.as_ptr()) })
}
pub fn chown(p: &Path, uid: int, gid: int) -> IoResult<()> {
- let p = p.to_c_str();
+ let p = cstr(p);
mkerr_libc(retry(|| unsafe {
libc::chown(p.as_ptr(), uid as libc::uid_t, gid as libc::gid_t)
}))
}
pub fn readlink(p: &Path) -> IoResult<Path> {
- let c_path = p.to_c_str();
+ let c_path = cstr(p);
let p = c_path.as_ptr();
let mut len = unsafe { libc::pathconf(p as *mut _, libc::_PC_NAME_MAX) };
if len == -1 {
}
pub fn symlink(src: &Path, dst: &Path) -> IoResult<()> {
- let src = src.to_c_str();
- let dst = dst.to_c_str();
+ let src = cstr(src);
+ let dst = cstr(dst);
mkerr_libc(unsafe { libc::symlink(src.as_ptr(), dst.as_ptr()) })
}
pub fn link(src: &Path, dst: &Path) -> IoResult<()> {
- let src = src.to_c_str();
- let dst = dst.to_c_str();
+ let src = cstr(src);
+ let dst = cstr(dst);
mkerr_libc(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) })
}
}
pub fn stat(p: &Path) -> IoResult<FileStat> {
- let p = p.to_c_str();
+ let p = cstr(p);
let mut stat: libc::stat = unsafe { mem::zeroed() };
match unsafe { libc::stat(p.as_ptr(), &mut stat) } {
0 => Ok(mkstat(&stat)),
}
pub fn lstat(p: &Path) -> IoResult<FileStat> {
- let p = p.to_c_str();
+ let p = cstr(p);
let mut stat: libc::stat = unsafe { mem::zeroed() };
match unsafe { libc::lstat(p.as_ptr(), &mut stat) } {
0 => Ok(mkstat(&stat)),
}
pub fn utime(p: &Path, atime: u64, mtime: u64) -> IoResult<()> {
- let p = p.to_c_str();
+ let p = cstr(p);
let buf = libc::utimbuf {
actime: (atime / 1000) as libc::time_t,
modtime: (mtime / 1000) as libc::time_t,
#![allow(unused_unsafe)]
#![allow(unused_mut)]
-extern crate libc;
-
-use num;
-use num::{Int, SignedInt};
use prelude::v1::*;
+
+use ffi;
use io::{self, IoResult, IoError};
+use libc;
+use num::{Int, SignedInt};
+use num;
+use str;
use sys_common::mkerr_libc;
macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => (
}
pub fn last_gai_error(s: libc::c_int) -> IoError {
- use c_str::CString;
let mut err = decode_error(s);
err.detail = Some(unsafe {
- CString::new(gai_strerror(s), false).as_str().unwrap().to_string()
+ str::from_utf8(ffi::c_str_to_bytes(&gai_strerror(s))).unwrap().to_string()
});
err
}
use prelude::v1::*;
-use c_str::ToCStr;
use error::{FromError, Error};
+use ffi::{self, CString};
use fmt;
use io::{IoError, IoResult};
use libc::{self, c_int, c_char, c_void};
+use os::TMPBUF_SZ;
use os;
use path::{BytesContainer};
use ptr;
+use str;
use sys::fs::FileDesc;
-use os::TMPBUF_SZ;
-
const BUF_BYTES : uint = 2048u;
/// Returns the platform-specific value of errno
panic!("strerror_r failure");
}
- String::from_raw_buf(p as *const u8)
+ let p = p as *const _;
+ str::from_utf8(ffi::c_str_to_bytes(&p)).unwrap().to_string()
}
}
}
pub fn getcwd() -> IoResult<Path> {
- use c_str::CString;
-
let mut buf = [0 as c_char; BUF_BYTES];
unsafe {
if libc::getcwd(buf.as_mut_ptr(), buf.len() as libc::size_t).is_null() {
Err(IoError::last_error())
} else {
- Ok(Path::new(CString::new(buf.as_ptr(), false)))
+ Ok(Path::new(ffi::c_str_to_bytes(&buf.as_ptr())))
}
}
}
pub unsafe fn get_env_pairs() -> Vec<Vec<u8>> {
- use c_str::CString;
-
extern {
fn rust_env_pairs() -> *const *const c_char;
}
}
let mut result = Vec::new();
while *environ != 0 as *const _ {
- let env_pair =
- CString::new(*environ, false).as_bytes_no_nul().to_vec();
+ let env_pair = ffi::c_str_to_bytes(&*environ).to_vec();
result.push(env_pair);
environ = environ.offset(1);
}
}
pub fn chdir(p: &Path) -> IoResult<()> {
- p.with_c_str(|buf| {
- unsafe {
- match libc::chdir(buf) == (0 as c_int) {
- true => Ok(()),
- false => Err(IoError::last_error()),
- }
+ let p = CString::from_slice(p.as_vec());
+ unsafe {
+ match libc::chdir(p.as_ptr()) == (0 as c_int) {
+ true => Ok(()),
+ false => Err(IoError::last_error()),
}
- })
+ }
}
pub fn page_size() -> uint {
use prelude::v1::*;
+use ffi::CString;
use libc;
-use c_str::CString;
use mem;
use sync::{Arc, Mutex};
use sync::atomic::{AtomicBool, Ordering};
}
s.sun_family = libc::AF_UNIX as libc::sa_family_t;
for (slot, value) in s.sun_path.iter_mut().zip(addr.iter()) {
- *slot = value;
+ *slot = *value;
}
// count the null terminator
use prelude::v1::*;
use self::Req::*;
-use c_str::{CString, ToCStr};
use collections;
+use ffi::CString;
use hash::Hash;
use io::process::{ProcessExit, ExitStatus, ExitSignal};
use io::{self, IoResult, IoError, EndOfFile};
// We may use this in the child, so perform allocations before the
// fork
- let devnull = "/dev/null".to_c_str();
+ let devnull = b"/dev/null\0";
set_cloexec(output.fd());
} else {
libc::O_RDWR
};
- libc::open(devnull.as_ptr(), flags, 0)
+ libc::open(devnull.as_ptr() as *const _, flags, 0)
}
Some(obj) => {
let fd = obj.as_inner().fd();
use mem;
use os;
use ptr;
-use sync::atomic::{mod, Ordering};
+use sync::atomic::{self, Ordering};
use sync::mpsc::{channel, Sender, Receiver, TryRecvError};
use sys::c;
use sys::fs::FileDesc;
/// copy of that function in my mingw install (maybe it was broken?). Instead,
/// this takes the route of using StackWalk64 in order to walk the stack.
-use c_str::CString;
+use dynamic_lib::DynamicLibrary;
+use ffi;
use intrinsics;
use io::{IoResult, Writer};
use libc;
use option::Option::{Some, None};
use path::Path;
use result::Result::{Ok, Err};
-use sync::{StaticMutex, MUTEX_INIT};
use slice::SliceExt;
-use str::StrExt;
-use dynamic_lib::DynamicLibrary;
+use str::{self, StrExt};
+use sync::{StaticMutex, MUTEX_INIT};
use sys_common::backtrace::*;
if ret == libc::TRUE {
try!(write!(w, " - "));
- let cstr = unsafe { CString::new(info.Name.as_ptr(), false) };
- let bytes = cstr.as_bytes();
- match cstr.as_str() {
- Some(s) => try!(demangle(w, s)),
- None => try!(w.write(bytes[..bytes.len()-1])),
+ let ptr = info.Name.as_ptr() as *const libc::c_char;
+ let bytes = unsafe { ffi::c_str_to_bytes(&ptr) };
+ match str::from_utf8(bytes) {
+ Ok(s) => try!(demangle(w, s)),
+ Err(..) => try!(w.write(bytes[..bytes.len()-1])),
}
}
try!(w.write(&['\n' as u8]));
use intrinsics::{atomic_store_relaxed, transmute};
use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID};
use prelude::v1::*;
- use c_str::ToCStr;
+ use ffi::CString;
extern "system" {
fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
unsafe fn store_func(ptr: *mut uint, module: &str, symbol: &str, fallback: uint) {
let mut module: Vec<u16> = module.utf16_units().collect();
module.push(0);
- symbol.with_c_str(|symbol| {
- let handle = GetModuleHandleW(module.as_ptr());
- let func: uint = transmute(GetProcAddress(handle, symbol));
- atomic_store_relaxed(ptr, if func == 0 {
- fallback
- } else {
- func
- })
+ let symbol = CString::from_slice(symbol.as_bytes());
+ let handle = GetModuleHandleW(module.as_ptr());
+ let func: uint = transmute(GetProcAddress(handle, symbol.as_ptr()));
+ atomic_store_relaxed(ptr, if func == 0 {
+ fallback
+ } else {
+ func
})
}
use alloc::arc::Arc;
use libc::{self, c_int};
-use c_str::CString;
use mem;
use sys::os::fill_utf16_buf_and_decode;
use path;
use prelude::v1::*;
use libc;
-use c_str::CString;
+use ffi::CString;
+use io::{self, IoError, IoResult};
use mem;
use ptr;
-use sync::{Arc, Mutex};
+use str;
use sync::atomic::{AtomicBool, Ordering};
-use io::{self, IoError, IoResult};
+use sync::{Arc, Mutex};
use sys_common::{self, eof};
-use super::{c, os, timer, to_utf16, decode_error_detailed};
+use super::{c, os, timer, decode_error_detailed};
+
+fn to_utf16(c: &CString) -> IoResult<Vec<u16>> {
+ super::to_utf16(str::from_utf8(c.as_bytes()).ok())
+}
struct Event(libc::HANDLE);
}
pub fn connect(addr: &CString, timeout: Option<u64>) -> IoResult<UnixStream> {
- let addr = try!(to_utf16(addr.as_str()));
+ let addr = try!(to_utf16(addr));
let start = timer::now();
loop {
match UnixStream::try_connect(addr.as_ptr()) {
// Although we technically don't need the pipe until much later, we
// create the initial handle up front to test the validity of the name
// and such.
- let addr_v = try!(to_utf16(addr.as_str()));
+ let addr_v = try!(to_utf16(addr));
let ret = unsafe { pipe(addr_v.as_ptr(), true) };
if ret == libc::INVALID_HANDLE_VALUE {
Err(super::last_error())
// proceed in accepting new clients in the future
if self.inner.closed.load(Ordering::SeqCst) { return Err(eof()) }
- let name = try!(to_utf16(self.listener.name.as_str()));
+ let name = try!(to_utf16(&self.listener.name));
// Once we've got a "server handle", we need to wait for a client to
// connect. The ConnectNamedPipe function will block this thread until
impl Clone for UnixAcceptor {
fn clone(&self) -> UnixAcceptor {
- let name = to_utf16(self.listener.name.as_str()).ok().unwrap();
+ let name = to_utf16(&self.listener.name).ok().unwrap();
UnixAcceptor {
inner: self.inner.clone(),
event: Event::new(true, false).ok().unwrap(),
use prelude::v1::*;
+use collections;
+use ffi::CString;
+use hash::Hash;
+use io::fs::PathExtensions;
+use io::process::{ProcessExit, ExitStatus, ExitSignal};
+use io::{IoResult, IoError};
+use io;
use libc::{pid_t, c_void, c_int};
use libc;
-use c_str::{CString, ToCStr};
-use io;
use mem;
use os;
-use ptr;
-use io::process::{ProcessExit, ExitStatus, ExitSignal};
-use collections;
use path::BytesContainer;
-use hash::Hash;
-use io::{IoResult, IoError};
-
+use ptr;
+use str;
+use sys::fs::FileDesc;
use sys::fs;
use sys::{self, retry, c, wouldblock, set_nonblocking, ms_to_timeval, timer};
-use sys::fs::FileDesc;
use sys_common::helper_thread::Helper;
use sys_common::{AsInner, mkerr_libc, timeout};
-use io::fs::PathExtensions;
-
pub use sys_common::ProcessConfig;
/// A value representing a child process.
// Split the value and test each path to see if the
// program exists.
for path in os::split_paths(v.container_as_bytes()).into_iter() {
- let path = path.join(cfg.program().as_bytes_no_nul())
+ let path = path.join(cfg.program().as_bytes())
.with_extension(os::consts::EXE_EXTENSION);
if path.exists() {
- return Some(path.to_c_str())
+ return Some(CString::from_slice(path.as_vec()))
}
}
break
fn make_command_line(prog: &CString, args: &[CString]) -> String {
let mut cmd = String::new();
- append_arg(&mut cmd, prog.as_str()
+ append_arg(&mut cmd, str::from_utf8(prog.as_bytes()).ok()
.expect("expected program name to be utf-8 encoded"));
for arg in args.iter() {
cmd.push(' ');
- append_arg(&mut cmd, arg.as_str()
+ append_arg(&mut cmd, str::from_utf8(arg.as_bytes()).ok()
.expect("expected argument to be utf-8 encoded"));
}
return cmd;
{
match d {
Some(dir) => {
- let dir_str = dir.as_str()
+ let dir_str = str::from_utf8(dir.as_bytes()).ok()
.expect("expected workingdirectory to be utf-8 encoded");
let mut dir_str: Vec<u16> = dir_str.utf16_units().collect();
dir_str.push(0);
#[cfg(test)]
mod tests {
- use c_str::ToCStr;
+ use prelude::v1::*;
+ use str;
+ use ffi::CString;
+ use super::make_command_line;
#[test]
fn test_make_command_line() {
- use prelude::v1::*;
- use str;
- use c_str::CString;
- use super::make_command_line;
-
fn test_wrapper(prog: &str, args: &[&str]) -> String {
- make_command_line(&prog.to_c_str(),
+ make_command_line(&CString::from_slice(prog.as_bytes()),
args.iter()
- .map(|a| a.to_c_str())
+ .map(|a| CString::from_slice(a.as_bytes()))
.collect::<Vec<CString>>()
.as_slice())
}
}
#[unsafe_destructor]
+#[stable]
impl<T: Send> Drop for JoinGuard<T> {
fn drop(&mut self) {
if !self.joined {
//! will want to make use of some form of **interior mutability** through the
//! `Cell` or `RefCell` types.
-#![macro_escape]
#![stable]
use prelude::v1::*;
use cell::UnsafeCell;
+#[cfg_attr(stage0, macro_escape)]
+#[cfg_attr(not(stage0), macro_use)]
pub mod scoped;
// Sure wish we had macro hygiene, no?
//! });
//! ```
-#![macro_escape]
#![unstable = "scoped TLS has yet to have wide enough use to fully consider \
stabilizing its interface"]
use option::Option;
use option::Option::{Some, None};
use num::Int;
-use result::Result;
-use result::Result::{Ok, Err};
+use result::Result::Ok;
+
+// NOTE: for old macros; remove after the next snapshot
+#[cfg(stage0)] use result::Result::Err;
/// The number of nanoseconds in a microsecond.
const NANOS_PER_MICRO: i32 = 1000;
//! Operations on tuples
//!
-//! To access a single element of a tuple one can use the following
-//! methods:
+//! To access the _N_-th element of a tuple one can use `N` itself
+//! as a field of the tuple.
//!
-//! * `valN` - returns a value of _N_-th element
-//! * `refN` - returns a reference to _N_-th element
-//! * `mutN` - returns a mutable reference to _N_-th element
-//!
-//! Indexing starts from zero, so `val0` returns first value, `val1`
+//! Indexing starts from zero, so `0` returns first value, `1`
//! returns second value, and so on. In general, a tuple with _S_
-//! elements provides aforementioned methods suffixed with numbers
-//! from `0` to `S-1`. Traits which contain these methods are
-//! implemented for tuples with up to 12 elements.
+//! elements provides aforementioned fields from `0` to `S-1`.
//!
//! If every type inside a tuple implements one of the following
//! traits, then a tuple itself also implements it.
//!
//! # Examples
//!
+//! Accessing elements of a tuple at specified indices:
+//!
+//! ```
+//! let x = ("colorless", "green", "ideas", "sleep", "furiously");
+//! assert_eq!(x.3, "sleep");
+//!
+//! let v = (3i, 3i);
+//! let u = (1i, -5i);
+//! assert_eq!(v.0 * u.0 + v.1 * u.1, -12i);
+//! ```
+//!
//! Using traits implemented for tuples:
//!
//! ```
pub attrs: Vec<Attribute>,
pub config: CrateConfig,
pub span: Span,
- pub exported_macros: Vec<P<Item>>
+ pub exported_macros: Vec<MacroDef>,
}
pub type MetaItem = Spanned<MetaItem_>;
PatStruct(Path, Vec<Spanned<FieldPat>>, bool),
PatTup(Vec<P<Pat>>),
PatBox(P<Pat>),
- PatRegion(P<Pat>), // reference pattern
+ PatRegion(P<Pat>, Mutability), // reference pattern
PatLit(P<Expr>),
PatRange(P<Expr>, P<Expr>),
/// [a, b, ..i, y, z] is represented as:
match *self {
TtToken(_, token::DocComment(_)) => 2,
TtToken(_, token::SubstNt(..)) => 2,
+ TtToken(_, token::SpecialVarNt(..)) => 2,
TtToken(_, token::MatchNt(..)) => 3,
TtDelimited(_, ref delimed) => {
delimed.tts.len() + 2
TtToken(sp, token::Ident(name, name_st))];
v[index]
}
+ (&TtToken(sp, token::SpecialVarNt(var)), _) => {
+ let v = [TtToken(sp, token::Dollar),
+ TtToken(sp, token::Ident(token::str_to_ident(var.as_str()),
+ token::Plain))];
+ v[index]
+ }
(&TtToken(sp, token::MatchNt(name, kind, name_st, kind_st)), _) => {
let v = [TtToken(sp, token::SubstNt(name, name_st)),
TtToken(sp, token::Colon),
IIForeign(P<ForeignItem>),
}
+/// A macro definition, in this crate or imported from another.
+///
+/// Not parsed directly, but created on macro import or `macro_rules!` expansion.
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
+pub struct MacroDef {
+ pub ident: Ident,
+ pub attrs: Vec<Attribute>,
+ pub id: NodeId,
+ pub span: Span,
+ pub imported_from: Option<Ident>,
+ pub export: bool,
+ pub use_locally: bool,
+ pub body: Vec<TokenTree>,
+}
+
#[cfg(test)]
mod test {
use serialize::json;
PatEnum(_, Some(ref s)) | PatTup(ref s) => {
s.iter().all(|p| walk_pat_(&**p, it))
}
- PatBox(ref s) | PatRegion(ref s) => {
+ PatBox(ref s) | PatRegion(ref s, _) => {
walk_pat_(&**s, it)
}
PatVec(ref before, ref slice, ref after) => {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![macro_escape]
-
#[macro_export]
macro_rules! register_diagnostic {
($code:tt, $description:tt) => (__register_diagnostic! { $code, $description });
use codemap::{CodeMap, Span, ExpnId, ExpnInfo, NO_EXPANSION};
use ext;
use ext::expand;
+use ext::tt::macro_rules;
use parse;
use parse::parser;
use parse::token;
use std::collections::HashMap;
use std::rc::Rc;
-// new-style macro! tt code:
-//
-// MacResult, NormalTT, IdentTT
-//
-// also note that ast::Mac used to have a bunch of extraneous cases and
-// is now probably a redundant AST node, can be merged with
-// ast::MacInvocTT.
-
-pub struct MacroDef {
- pub name: String,
- pub ext: SyntaxExtension
-}
-
pub trait ItemDecorator {
fn expand(&self,
ecx: &mut ExtCtxt,
/// methods are spliced into the AST at the callsite of the macro (or
/// just into the compiler's internal macro table, for `make_def`).
pub trait MacResult {
- /// Attempt to define a new macro.
- // this should go away; the idea that a macro might expand into
- // either a macro definition or an expression, depending on what
- // the context wants, is kind of silly.
- fn make_def(&mut self) -> Option<MacroDef> {
- None
- }
/// Create an expression.
fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> {
None
///
IdentTT(Box<IdentMacroExpander + 'static>, Option<Span>),
- /// An ident macro that has two properties:
- /// - it adds a macro definition to the environment, and
- /// - the definition it adds doesn't introduce any new
- /// identifiers.
- ///
- /// `macro_rules!` is a LetSyntaxTT
- LetSyntaxTT(Box<IdentMacroExpander + 'static>, Option<Span>),
+ /// Represents `macro_rules!` itself.
+ MacroRulesTT,
}
pub type NamedSyntaxExtension = (Name, SyntaxExtension);
}
let mut syntax_expanders = SyntaxEnv::new();
- syntax_expanders.insert(intern("macro_rules"),
- LetSyntaxTT(box ext::tt::macro_rules::add_new_extension, None));
+ syntax_expanders.insert(intern("macro_rules"), MacroRulesTT);
syntax_expanders.insert(intern("fmt"),
builtin_normal_expander(
ext::fmt::expand_syntax_ext));
pub mod_path: Vec<ast::Ident> ,
pub trace_mac: bool,
- pub exported_macros: Vec<P<ast::Item>>,
+ pub exported_macros: Vec<ast::MacroDef>,
pub syntax_env: SyntaxEnv,
pub recursion_count: uint,
}
}
}
+
+ pub fn insert_macro(&mut self, def: ast::MacroDef) {
+ if def.export {
+ self.exported_macros.push(def.clone());
+ }
+ if def.use_locally {
+ let ext = macro_rules::compile(self, &def);
+ self.syntax_env.insert(def.ident.name, ext);
+ }
+ }
+
/// Emit `msg` attached to `sp`, and stop compilation immediately.
///
/// `span_err` should be strongly preferred where-ever possible:
cx, span, substr)
}
- macro_rules! md (
+ macro_rules! md {
($name:expr, $f:ident) => { {
let inline = cx.meta_word(span, InternedString::new("inline"));
let attrs = vec!(cx.attribute(span, inline));
})
}
} }
- );
+ }
let trait_def = TraitDef {
span: span,
push: F) where
F: FnOnce(P<Item>),
{
- macro_rules! md (
+ macro_rules! md {
($name:expr, $op:expr, $equal:expr) => { {
let inline = cx.meta_word(span, InternedString::new("inline"));
let attrs = vec!(cx.attribute(span, inline));
})
}
} }
- );
+ }
let ordering_ty = Literal(Path::new(vec!["std", "cmp", "Ordering"]));
let ret_ty = Literal(Path::new_(vec!["std", "option", "Option"],
&**variant,
self_arg_name,
ast::MutImmutable);
- (cx.pat(sp, ast::PatRegion(p)), idents)
+ (cx.pat(sp, ast::PatRegion(p, ast::MutImmutable)), idents)
};
// A single arm has form (&VariantK, &VariantK, ...) => BodyK
F: FnOnce(P<Item>),
{
- let (path, generics, args) = if cx.ecfg.deriving_hash_type_parameter {
- (Path::new_(vec!("std", "hash", "Hash"), None,
- vec!(box Literal(Path::new_local("__S"))), true),
- LifetimeBounds {
- lifetimes: Vec::new(),
- bounds: vec!(("__S",
- vec!(Path::new(vec!("std", "hash", "Writer"))))),
- },
- Path::new_local("__S"))
- } else {
- (Path::new(vec!("std", "hash", "Hash")),
- LifetimeBounds::empty(),
- Path::new(vec!("std", "hash", "sip", "SipState")))
+ let path = Path::new_(vec!("std", "hash", "Hash"), None,
+ vec!(box Literal(Path::new_local("__S"))), true);
+ let generics = LifetimeBounds {
+ lifetimes: Vec::new(),
+ bounds: vec!(("__S",
+ vec!(Path::new(vec!("std", "hash", "Writer"))))),
};
+ let args = Path::new_local("__S");
let inline = cx.meta_word(span, InternedString::new("inline"));
let attrs = vec!(cx.attribute(span, inline));
let hash_trait_def = TraitDef {
MetaNameValue(ref tname, _) |
MetaList(ref tname, _) |
MetaWord(ref tname) => {
- macro_rules! expand(($func:path) => ($func(cx, titem.span,
- &**titem, item,
- |i| push.call_mut((i,)))));
+ macro_rules! expand {
+ ($func:path) => ($func(cx, titem.span, &**titem, item,
+ |i| push.call_mut((i,))))
+ }
+
match tname.get() {
"Clone" => expand!(clone::expand_deriving_clone),
// <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 self::Either::*;
use ast::{Block, Crate, DeclLocal, ExprMac, PatMac};
use ast::{Local, Ident, MacInvocTT};
use visit;
use visit::Visitor;
-enum Either<L,R> {
- Left(L),
- Right(R)
-}
-
pub fn expand_type(t: P<ast::Ty>,
fld: &mut MacroExpander,
impl_ty: Option<P<ast::Ty>>)
if valid_ident {
fld.cx.mod_push(it.ident);
}
- let macro_escape = contains_macro_escape(new_attrs[]);
+ let macro_use = contains_macro_use(fld, new_attrs[]);
let result = with_exts_frame!(fld.cx.syntax_env,
- macro_escape,
+ macro_use,
noop_fold_item(it, fld));
if valid_ident {
fld.cx.mod_pop();
}
}
-// does this attribute list contain "macro_escape" ?
-fn contains_macro_escape(attrs: &[ast::Attribute]) -> bool {
- attr::contains_name(attrs, "macro_escape")
+// does this attribute list contain "macro_use" ?
+fn contains_macro_use(fld: &mut MacroExpander, attrs: &[ast::Attribute]) -> bool {
+ for attr in attrs.iter() {
+ let mut is_use = attr.check_name("macro_use");
+ if attr.check_name("macro_escape") {
+ fld.cx.span_warn(attr.span, "macro_escape is a deprecated synonym for macro_use");
+ is_use = true;
+ if let ast::AttrInner = attr.node.style {
+ fld.cx.span_help(attr.span, "consider an outer attribute, \
+ #[macro_use] mod ...");
+ }
+ };
+
+ if is_use {
+ match attr.node.value.node {
+ ast::MetaWord(..) => (),
+ _ => fld.cx.span_err(attr.span, "arguments to macro_use are not allowed here"),
+ }
+ return true;
+ }
+ }
+ false
}
// Support for item-position macro invocations, exactly the same
// logic as for expression-position macro invocations.
-pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander)
- -> SmallVector<P<ast::Item>> {
+pub fn expand_item_mac(it: P<ast::Item>,
+ fld: &mut MacroExpander) -> SmallVector<P<ast::Item>> {
let (extname, path_span, tts) = match it.node {
ItemMac(codemap::Spanned {
node: MacInvocTT(ref pth, ref tts, _),
let extnamestr = token::get_ident(extname);
let fm = fresh_mark();
- let def_or_items = {
- let mut expanded = match fld.cx.syntax_env.find(&extname.name) {
+ let items = {
+ let expanded = match fld.cx.syntax_env.find(&extname.name) {
None => {
fld.cx.span_err(path_span,
format!("macro undefined: '{}!'",
let marked_tts = mark_tts(tts[], fm);
expander.expand(fld.cx, it.span, it.ident, marked_tts)
}
- LetSyntaxTT(ref expander, span) => {
+ MacroRulesTT => {
if it.ident.name == parse::token::special_idents::invalid.name {
fld.cx.span_err(path_span,
- format!("macro {}! expects an ident argument",
- extnamestr.get())[]);
+ format!("macro_rules! expects an ident argument")[]);
return SmallVector::zero();
}
fld.cx.bt_push(ExpnInfo {
callee: NameAndSpan {
name: extnamestr.get().to_string(),
format: MacroBang,
- span: span
+ span: None,
}
});
- // DON'T mark before expansion:
- expander.expand(fld.cx, it.span, it.ident, tts)
+ // DON'T mark before expansion.
+
+ let def = ast::MacroDef {
+ ident: it.ident,
+ attrs: it.attrs.clone(),
+ id: ast::DUMMY_NODE_ID,
+ span: it.span,
+ imported_from: None,
+ export: attr::contains_name(it.attrs.as_slice(), "macro_export"),
+ use_locally: true,
+ body: tts,
+ };
+ fld.cx.insert_macro(def);
+
+ // macro_rules! has a side effect but expands to nothing.
+ fld.cx.bt_pop();
+ return SmallVector::zero();
}
_ => {
fld.cx.span_err(it.span,
}
};
- match expanded.make_def() {
- Some(def) => Left(def),
- None => Right(expanded.make_items())
- }
+ expanded.make_items()
};
- let items = match def_or_items {
- Left(MacroDef { name, ext }) => {
- // hidden invariant: this should only be possible as the
- // result of expanding a LetSyntaxTT, and thus doesn't
- // need to be marked. Not that it could be marked anyway.
- // create issue to recommend refactoring here?
- fld.cx.syntax_env.insert(intern(name[]), ext);
- if attr::contains_name(it.attrs[], "macro_export") {
- fld.cx.exported_macros.push(it);
- }
- SmallVector::zero()
- }
- Right(Some(items)) => {
+ let items = match items {
+ Some(items) => {
items.into_iter()
.map(|i| mark_item(i, fm))
.flat_map(|i| fld.fold_item(i).into_iter())
.collect()
}
- Right(None) => {
+ None => {
fld.cx.span_err(path_span,
format!("non-item macro in item position: {}",
extnamestr.get())[]);
}
/// Expand a stmt
-//
-// I don't understand why this returns a vector... it looks like we're
-// half done adding machinery to allow macros to expand into multiple statements.
fn expand_stmt(s: Stmt, fld: &mut MacroExpander) -> SmallVector<P<Stmt>> {
let (mac, style) = match s.node {
StmtMac(mac, style) => (mac, style),
ctxt: mtwt::apply_renames(self.renames, id.ctxt),
}
}
- fn fold_mac(&mut self, macro: ast::Mac) -> ast::Mac {
- fold::noop_fold_mac(macro, self)
+ fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
+ fold::noop_fold_mac(mac, self)
}
}
_ => unreachable!()
})
}
- fn fold_mac(&mut self, macro: ast::Mac) -> ast::Mac {
- fold::noop_fold_mac(macro, self)
+ fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
+ fold::noop_fold_mac(mac, self)
}
}
pub struct ExpansionConfig {
pub crate_name: String,
- pub deriving_hash_type_parameter: bool,
pub enable_quotes: bool,
pub recursion_limit: uint,
}
pub fn default(crate_name: String) -> ExpansionConfig {
ExpansionConfig {
crate_name: crate_name,
- deriving_hash_type_parameter: false,
enable_quotes: false,
recursion_limit: 64,
}
}
}
-pub struct ExportedMacros {
- pub crate_name: Ident,
- pub macros: Vec<String>,
-}
-
pub fn expand_crate(parse_sess: &parse::ParseSess,
cfg: ExpansionConfig,
// these are the macros being imported to this crate:
- imported_macros: Vec<ExportedMacros>,
+ imported_macros: Vec<ast::MacroDef>,
user_exts: Vec<NamedSyntaxExtension>,
c: Crate) -> Crate {
let mut cx = ExtCtxt::new(parse_sess, c.config.clone(), cfg);
let mut expander = MacroExpander::new(&mut cx);
- for ExportedMacros { crate_name, macros } in imported_macros.into_iter() {
- let name = format!("<{} macros>", token::get_ident(crate_name));
-
- for source in macros.into_iter() {
- let item = parse::parse_item_from_source_str(name.clone(),
- source,
- expander.cx.cfg(),
- expander.cx.parse_sess())
- .expect("expected a serialized item");
- expand_item_mac(item, &mut expander);
- }
+ for def in imported_macros.into_iter() {
+ expander.cx.insert_macro(def);
}
for (name, extension) in user_exts.into_iter() {
}
impl<'a, 'v> Visitor<'v> for MacroExterminator<'a> {
- fn visit_mac(&mut self, macro: &ast::Mac) {
- self.sess.span_diagnostic.span_bug(macro.span,
+ fn visit_mac(&mut self, mac: &ast::Mac) {
+ self.sess.span_diagnostic.span_bug(mac.span,
"macro exterminator: expected AST \
with no macro invocations");
}
#[cfg(test)]
mod test {
- use super::{pattern_bindings, expand_crate, contains_macro_escape};
+ use super::{pattern_bindings, expand_crate, contains_macro_use};
use super::{PatIdentFinder, IdentRenamer, PatIdentRenamer, ExpansionConfig};
use ast;
use ast::{Attribute_, AttrOuter, MetaWord, Name};
expand_crate(&sess,test_ecfg(),vec!(),vec!(),crate_ast);
}
- // macro_escape modules should allow macros to escape
+ // macro_use modules should allow macros to escape
#[test] fn macros_can_escape_flattened_mods_test () {
- let src = "#[macro_escape] mod foo {macro_rules! z (() => (3+4));}\
+ let src = "#[macro_use] mod foo {macro_rules! z (() => (3+4));}\
fn inty() -> int { z!() }".to_string();
let sess = parse::new_parse_sess();
let crate_ast = parse::parse_crate_from_source_str(
expand_crate(&sess, test_ecfg(), vec!(), vec!(), crate_ast);
}
- #[test] fn test_contains_flatten (){
- let attr1 = make_dummy_attr ("foo");
- let attr2 = make_dummy_attr ("bar");
- let escape_attr = make_dummy_attr ("macro_escape");
- let attrs1 = vec!(attr1.clone(), escape_attr, attr2.clone());
- assert_eq!(contains_macro_escape(attrs1[]),true);
- let attrs2 = vec!(attr1,attr2);
- assert_eq!(contains_macro_escape(attrs2[]),false);
- }
-
// make a MetaWord outer attribute with the given name
fn make_dummy_attr(s: &str) -> ast::Attribute {
Spanned {
*/
// FIXME: Move this trait to pprust and get rid of *_to_str?
- pub trait ToSource for Sized? {
+ pub trait ToSource {
// Takes a thing and generates a string containing rust code for it.
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 for Sized? : ToSource {
+ 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.
use ast::{Ident, TtDelimited, TtSequence, TtToken};
use ast;
use codemap::{Span, DUMMY_SP};
-use ext::base::{ExtCtxt, MacResult, MacroDef};
+use ext::base::{ExtCtxt, MacResult, SyntaxExtension};
use ext::base::{NormalTT, TTMacroExpander};
use ext::tt::macro_parser::{Success, Error, Failure};
use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal};
/// Make sure we don't have any tokens left to parse, so we don't
/// silently drop anything. `allow_semi` is so that "optional"
/// semicolons at the end of normal expressions aren't complained
- /// about e.g. the semicolon in `macro_rules! kapow( () => {
- /// panic!(); } )` doesn't get picked up by .parse_expr(), but it's
+ /// about e.g. the semicolon in `macro_rules! kapow { () => {
+ /// panic!(); } }` doesn't get picked up by .parse_expr(), but it's
/// allowed to be there.
fn ensure_complete_parse(&self, allow_semi: bool) {
let mut parser = self.parser.borrow_mut();
struct MacroRulesMacroExpander {
name: Ident,
+ imported_from: Option<Ident>,
lhses: Vec<Rc<NamedMatch>>,
rhses: Vec<Rc<NamedMatch>>,
}
generic_extension(cx,
sp,
self.name,
+ self.imported_from,
arg,
self.lhses[],
self.rhses[])
}
}
-struct MacroRulesDefiner {
- def: Option<MacroDef>
-}
-impl MacResult for MacroRulesDefiner {
- fn make_def(&mut self) -> Option<MacroDef> {
- Some(self.def.take().expect("empty MacroRulesDefiner"))
- }
-}
-
/// Given `lhses` and `rhses`, this is the new macro we create
fn generic_extension<'cx>(cx: &'cx ExtCtxt,
sp: Span,
name: Ident,
+ imported_from: Option<Ident>,
arg: &[ast::TokenTree],
lhses: &[Rc<NamedMatch>],
rhses: &[Rc<NamedMatch>])
};
// `None` is because we're not interpolating
let mut arg_rdr = new_tt_reader(&cx.parse_sess().span_diagnostic,
+ None,
None,
arg.iter()
.map(|x| (*x).clone())
// rhs has holes ( `$id` and `$(...)` that need filled)
let trncbr = new_tt_reader(&cx.parse_sess().span_diagnostic,
Some(named_matches),
+ imported_from,
rhs);
let p = Parser::new(cx.parse_sess(), cx.cfg(), box trncbr);
// Let the context choose how to interpret the result.
//
// Holy self-referential!
-/// This procedure performs the expansion of the
-/// macro_rules! macro. It parses the RHS and adds
-/// an extension to the current context.
-pub fn add_new_extension<'cx>(cx: &'cx mut ExtCtxt,
- sp: Span,
- name: Ident,
- arg: Vec<ast::TokenTree> )
- -> Box<MacResult+'cx> {
+/// Converts a `macro_rules!` invocation into a syntax extension.
+pub fn compile<'cx>(cx: &'cx mut ExtCtxt,
+ def: &ast::MacroDef) -> SyntaxExtension {
let lhs_nm = gensym_ident("lhs");
let rhs_nm = gensym_ident("rhs");
// Parse the macro_rules! invocation (`none` is for no interpolations):
let arg_reader = new_tt_reader(&cx.parse_sess().span_diagnostic,
None,
- arg.clone());
+ None,
+ def.body.clone());
let argument_map = parse_or_else(cx.parse_sess(),
cx.cfg(),
arg_reader,
// Extract the arguments:
let lhses = match *argument_map[lhs_nm] {
MatchedSeq(ref s, _) => /* FIXME (#2543) */ (*s).clone(),
- _ => cx.span_bug(sp, "wrong-structured lhs")
+ _ => cx.span_bug(def.span, "wrong-structured lhs")
};
let rhses = match *argument_map[rhs_nm] {
MatchedSeq(ref s, _) => /* FIXME (#2543) */ (*s).clone(),
- _ => cx.span_bug(sp, "wrong-structured rhs")
+ _ => cx.span_bug(def.span, "wrong-structured rhs")
};
let exp = box MacroRulesMacroExpander {
- name: name,
+ name: def.ident,
+ imported_from: def.imported_from,
lhses: lhses,
rhses: rhses,
};
- box MacroRulesDefiner {
- def: Some(MacroDef {
- name: token::get_ident(name).to_string(),
- ext: NormalTT(exp, Some(sp))
- })
- } as Box<MacResult+'cx>
+ NormalTT(exp, Some(def.span))
}
use diagnostic::SpanHandler;
use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal};
use parse::token::{Eof, DocComment, Interpolated, MatchNt, SubstNt};
-use parse::token::{Token, NtIdent};
+use parse::token::{Token, NtIdent, SpecialMacroVar};
use parse::token;
use parse::lexer::TokenAndSpan;
stack: Vec<TtFrame>,
/* for MBE-style macro transcription */
interpolations: HashMap<Ident, Rc<NamedMatch>>,
+ imported_from: Option<Ident>,
+
+ // Some => return imported_from as the next token
+ crate_name_next: Option<Span>,
repeat_idx: Vec<uint>,
repeat_len: Vec<uint>,
/* cached: */
/// should) be none.
pub fn new_tt_reader<'a>(sp_diag: &'a SpanHandler,
interp: Option<HashMap<Ident, Rc<NamedMatch>>>,
+ imported_from: Option<Ident>,
src: Vec<ast::TokenTree> )
-> TtReader<'a> {
let mut r = TtReader {
None => HashMap::new(),
Some(x) => x,
},
+ imported_from: imported_from,
+ crate_name_next: None,
repeat_idx: Vec::new(),
repeat_len: Vec::new(),
desugar_doc_comments: false,
sp: r.cur_span.clone(),
};
loop {
+ match r.crate_name_next.take() {
+ None => (),
+ Some(sp) => {
+ r.cur_span = sp;
+ r.cur_tok = token::Ident(r.imported_from.unwrap(), token::Plain);
+ return ret_val;
+ },
+ }
let should_pop = match r.stack.last() {
None => {
assert_eq!(ret_val.tok, token::Eof);
sep: None
});
}
+ TtToken(sp, token::SpecialVarNt(SpecialMacroVar::CrateMacroVar)) => {
+ r.stack.last_mut().unwrap().idx += 1;
+
+ if r.imported_from.is_some() {
+ r.cur_span = sp;
+ r.cur_tok = token::ModSep;
+ r.crate_name_next = Some(sp);
+ return ret_val;
+ }
+
+ // otherwise emit nothing and proceed to the next token
+ }
TtToken(sp, tok) => {
r.cur_span = sp;
r.cur_tok = tok;
// if you change this list without updating src/doc/reference.md, @cmr will be sad
static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
- ("globs", Active),
- ("macro_rules", Active),
+ ("globs", Accepted),
+ ("macro_rules", Accepted),
("struct_variant", Accepted),
("asm", Active),
("managed_boxes", Removed),
("non_ascii_idents", Active),
("thread_local", Active),
("link_args", Active),
- ("phase", Active),
+ ("phase", Active), // NOTE(stage0): switch to Removed after next snapshot
("plugin_registrar", Active),
("log_syntax", Active),
("trace_macros", Active),
("lang_items", Active),
("simd", Active),
- ("default_type_params", Active),
+ ("default_type_params", Accepted),
("quote", Active),
("link_llvm_intrinsics", Active),
("linkage", Active),
("import_shadowing", Active),
("advanced_slice_patterns", Active),
("tuple_indexing", Accepted),
- ("associated_types", Active),
+ ("associated_types", Accepted),
("visible_private_types", Active),
("slicing_syntax", Active),
("if_let", Accepted),
("while_let", Accepted),
+ ("plugin", Active),
+
// A temporary feature gate used to enable parser extensions needed
// to bootstrap fix for #5723.
("issue_5723_bootstrap", Accepted),
/// A set of features to be used by later passes.
#[derive(Copy)]
pub struct Features {
- pub default_type_params: bool,
pub unboxed_closures: bool,
pub rustc_diagnostic_macros: bool,
pub import_shadowing: bool,
impl Features {
pub fn new() -> Features {
Features {
- default_type_params: false,
unboxed_closures: false,
rustc_diagnostic_macros: false,
import_shadowing: false,
}
impl<'a, 'v> Visitor<'v> for MacroVisitor<'a> {
- fn visit_view_item(&mut self, i: &ast::ViewItem) {
- match i.node {
- ast::ViewItemExternCrate(..) => {
- for attr in i.attrs.iter() {
- if attr.name().get() == "phase"{
- self.context.gate_feature("phase", attr.span,
- "compile time crate loading is \
- experimental and possibly buggy");
- }
- }
- },
- _ => { }
- }
- visit::walk_view_item(self, i)
- }
-
- fn visit_mac(&mut self, macro: &ast::Mac) {
- let ast::MacInvocTT(ref path, _, _) = macro.node;
+ fn visit_mac(&mut self, mac: &ast::Mac) {
+ let ast::MacInvocTT(ref path, _, _) = mac.node;
let id = path.segments.last().unwrap().identifier;
- if id == token::str_to_ident("macro_rules") {
- self.context.gate_feature("macro_rules", path.span, "macro definitions are \
- not stable enough for use and are subject to change");
- }
-
- else if id == token::str_to_ident("asm") {
+ if id == token::str_to_ident("asm") {
self.context.gate_feature("asm", path.span, "inline assembly is not \
stable enough for use and is subject to change");
}
fn visit_view_item(&mut self, i: &ast::ViewItem) {
match i.node {
- ast::ViewItemUse(ref path) => {
- if let ast::ViewPathGlob(..) = path.node {
- self.gate_feature("globs", path.span,
- "glob import statements are \
- experimental and possibly buggy");
- }
- }
+ ast::ViewItemUse(..) => {}
ast::ViewItemExternCrate(..) => {
for attr in i.attrs.iter() {
- if attr.name().get() == "phase"{
- self.gate_feature("phase", attr.span,
- "compile time crate loading is \
- experimental and possibly buggy");
+ if attr.check_name("plugin") {
+ self.gate_feature("plugin", attr.span,
+ "compiler plugins are experimental \
+ and possibly buggy");
}
}
}
}
}
- ast::ItemImpl(_, polarity, _, _, _, ref items) => {
+ ast::ItemImpl(_, polarity, _, _, _, _) => {
match polarity {
ast::ImplPolarity::Negative => {
self.gate_feature("optin_builtin_traits",
removed in the future");
}
- for item in items.iter() {
- match *item {
- ast::MethodImplItem(_) => {}
- ast::TypeImplItem(ref typedef) => {
- self.gate_feature("associated_types",
- typedef.span,
- "associated types are \
- experimental")
- }
- }
+ if attr::contains_name(i.attrs[],
+ "old_orphan_check") {
+ self.gate_feature(
+ "old_orphan_check",
+ i.span,
+ "the new orphan check rules will eventually be strictly enforced");
}
}
visit::walk_item(self, i);
}
- fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) {
- match *trait_item {
- ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {}
- ast::TypeTraitItem(ref ti) => {
- self.gate_feature("associated_types",
- ti.ty_param.span,
- "associated types are experimental")
- }
- }
- }
-
fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
if attr::contains_name(i.attrs[], "linkage") {
self.gate_feature("linkage", i.span,
visit::walk_expr(self, e);
}
- fn visit_generics(&mut self, generics: &ast::Generics) {
- for type_parameter in generics.ty_params.iter() {
- match type_parameter.default {
- Some(ref ty) => {
- self.gate_feature("default_type_params", ty.span,
- "default type parameters are \
- experimental and possibly buggy");
- }
- None => {}
- }
- }
- visit::walk_generics(self, generics);
- }
-
fn visit_attribute(&mut self, attr: &ast::Attribute) {
if attr::contains_name(slice::ref_slice(attr), "lang") {
self.gate_feature("lang_items",
check(&mut cx, krate);
(Features {
- default_type_params: cx.has_feature("default_type_params"),
unboxed_closures: cx.has_feature("unboxed_closures"),
rustc_diagnostic_macros: cx.has_feature("rustc_diagnostic_macros"),
import_shadowing: cx.has_feature("import_shadowing"),
noop_fold_local(l, self)
}
- fn fold_mac(&mut self, _macro: Mac) -> Mac {
+ fn fold_mac(&mut self, _mac: Mac) -> Mac {
panic!("fold_mac disabled by default");
// NB: see note about macros above.
// if you really want a folder that
// works on macros, use this
// definition in your trait impl:
- // fold::noop_fold_mac(_macro, self)
+ // fold::noop_fold_mac(_mac, self)
}
fn fold_explicit_self(&mut self, es: ExplicitSelf) -> ExplicitSelf {
}
}
-pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, config, exported_macros, span}: Crate,
+pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, config, mut exported_macros, span}: Crate,
folder: &mut T) -> Crate {
let config = folder.fold_meta_items(config);
}, Vec::new(), span)
};
+ for def in exported_macros.iter_mut() {
+ def.id = folder.new_id(def.id);
+ }
+
Crate {
module: module,
attrs: attrs,
}
PatTup(elts) => PatTup(elts.move_map(|x| folder.fold_pat(x))),
PatBox(inner) => PatBox(folder.fold_pat(inner)),
- PatRegion(inner) => PatRegion(folder.fold_pat(inner)),
+ PatRegion(inner, mutbl) => PatRegion(folder.fold_pat(inner), mutbl),
PatRange(e1, e2) => {
PatRange(folder.fold_expr(e1), folder.fold_expr(e2))
},
fn fold_ident(&mut self, _: ast::Ident) -> ast::Ident {
token::str_to_ident("zz")
}
- fn fold_mac(&mut self, macro: ast::Mac) -> ast::Mac {
- fold::noop_fold_mac(macro, self)
+ fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
+ fold::noop_fold_mac(mac, self)
}
}
extern crate arena;
extern crate fmt_macros;
-#[phase(plugin, link)] extern crate log;
extern crate serialize;
extern crate term;
extern crate libc;
+#[cfg(stage0)]
+#[phase(plugin, link)]
+extern crate log;
+
+#[cfg(not(stage0))]
+#[macro_use]
+extern crate log;
+
extern crate "serialize" as rustc_serialize; // used by deriving
pub mod util {
use std::str;
use std::iter;
-pub mod lexer;
+#[cfg_attr(stage0, macro_escape)]
+#[cfg_attr(not(stage0), macro_use)]
pub mod parser;
+
+pub mod lexer;
pub mod token;
pub mod attr;
// Note: keep in sync with `with_hygiene::parse_tts_from_source_str`
// until #16472 is resolved.
+//
+// Warning: This parses with quote_depth > 0, which is not the default.
pub fn parse_tts_from_source_str(name: String,
source: String,
cfg: ast::CrateConfig,
pub fn tts_to_parser<'a>(sess: &'a ParseSess,
tts: Vec<ast::TokenTree>,
cfg: ast::CrateConfig) -> Parser<'a> {
- let trdr = lexer::new_tt_reader(&sess.span_diagnostic, None, tts);
+ let trdr = lexer::new_tt_reader(&sess.span_diagnostic, None, None, tts);
Parser::new(sess, cfg, box trdr)
}
// Note: keep this in sync with `super::parse_tts_from_source_str` until
// #16472 is resolved.
+ //
+ // Warning: This parses with quote_depth > 0, which is not the default.
pub fn parse_tts_from_source_str(name: String,
source: String,
cfg: ast::CrateConfig,
//!
//! Obsolete syntax that becomes too hard to parse can be removed.
-pub use self::ObsoleteSyntax::*;
-
use ast::{Expr, ExprTup};
use codemap::Span;
use parse::parser;
/// The specific types of unsupported syntax
#[derive(Copy, PartialEq, Eq, Hash)]
pub enum ObsoleteSyntax {
- ObsoleteOwnedType,
- ObsoleteOwnedExpr,
- ObsoleteOwnedPattern,
- ObsoleteOwnedVector,
- ObsoleteOwnedSelf,
- ObsoleteImportRenaming,
- ObsoleteSubsliceMatch,
- ObsoleteExternCrateRenaming,
- ObsoleteProcType,
- ObsoleteProcExpr,
- ObsoleteClosureType,
+ Sized,
+ ForSized,
+ OwnedType,
+ OwnedExpr,
+ OwnedPattern,
+ OwnedVector,
+ OwnedSelf,
+ ImportRenaming,
+ SubsliceMatch,
+ ExternCrateRenaming,
+ ProcType,
+ ProcExpr,
+ ClosureType,
}
pub trait ParserObsoleteMethods {
/// Reports an obsolete syntax non-fatal error.
fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax) {
let (kind_str, desc) = match kind {
- ObsoleteProcType => (
+ ObsoleteSyntax::ForSized => (
+ "for Sized?",
+ "no longer required. Traits (and their `Self` type) do not have the `Sized` bound \
+ by default",
+ ),
+ ObsoleteSyntax::ProcType => (
"the `proc` type",
"use unboxed closures instead",
),
- ObsoleteProcExpr => (
+ ObsoleteSyntax::ProcExpr => (
"`proc` expression",
"use a `move ||` expression instead",
),
- ObsoleteOwnedType => (
+ ObsoleteSyntax::OwnedType => (
"`~` notation for owned pointers",
"use `Box<T>` in `std::owned` instead"
),
- ObsoleteOwnedExpr => (
+ ObsoleteSyntax::OwnedExpr => (
"`~` notation for owned pointer allocation",
"use the `box` operator instead of `~`"
),
- ObsoleteOwnedPattern => (
+ ObsoleteSyntax::OwnedPattern => (
"`~` notation for owned pointer patterns",
"use the `box` operator instead of `~`"
),
- ObsoleteOwnedVector => (
+ ObsoleteSyntax::OwnedVector => (
"`~[T]` is no longer a type",
"use the `Vec` type instead"
),
- ObsoleteOwnedSelf => (
+ ObsoleteSyntax::OwnedSelf => (
"`~self` is no longer supported",
"write `self: Box<Self>` instead"
),
- ObsoleteImportRenaming => (
+ ObsoleteSyntax::ImportRenaming => (
"`use foo = bar` syntax",
"write `use bar as foo` instead"
),
- ObsoleteSubsliceMatch => (
+ ObsoleteSyntax::SubsliceMatch => (
"subslice match syntax",
"instead of `..xs`, write `xs..` in a pattern"
),
- ObsoleteExternCrateRenaming => (
+ ObsoleteSyntax::ExternCrateRenaming => (
"`extern crate foo = bar` syntax",
"write `extern crate bar as foo` instead"
),
- ObsoleteClosureType => (
+ ObsoleteSyntax::ClosureType => (
"`|uint| -> bool` closure type syntax",
"use unboxed closures instead, no type annotation needed"
- )
+ ),
+ ObsoleteSyntax::Sized => (
+ "`Sized? T` syntax for removing the `Sized` bound",
+ "write `T: ?Sized` instead"
+ ),
};
self.report(sp, kind, kind_str, desc);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![macro_escape]
-
pub use self::PathParsingMode::*;
use self::ItemOrViewItem::*;
use parse::common::{SeqSep, seq_sep_none, seq_sep_trailing_allowed};
use parse::lexer::{Reader, TokenAndSpan};
use parse::obsolete::*;
-use parse::token::{self, MatchNt, SubstNt, InternedString};
-use parse::token::{keywords, special_idents};
+use parse::token::{self, MatchNt, SubstNt, SpecialVarNt, InternedString};
+use parse::token::{keywords, special_idents, SpecialMacroVar};
use parse::{new_sub_parser_from_file, ParseSess};
use print::pprust;
use ptr::P;
let _ = self.parse_colon_then_ty_param_bounds(BoundParsingMode::Bare);
let _ = self.parse_ret_ty();
- self.obsolete(proc_span, ObsoleteProcType);
+ self.obsolete(proc_span, ObsoleteSyntax::ProcType);
TyInfer
}
let _ = self.parse_ret_ty();
- self.obsolete(ty_closure_span, ObsoleteClosureType);
+ self.obsolete(ty_closure_span, ObsoleteSyntax::ClosureType);
TyInfer
}
self.bump();
let last_span = self.last_span;
match self.token {
- token::OpenDelim(token::Bracket) => self.obsolete(last_span, ObsoleteOwnedVector),
- _ => self.obsolete(last_span, ObsoleteOwnedType)
+ token::OpenDelim(token::Bracket) => {
+ self.obsolete(last_span, ObsoleteSyntax::OwnedVector)
+ }
+ _ => self.obsolete(last_span, ObsoleteSyntax::OwnedType)
}
TyTup(vec![self.parse_ty()])
} else if self.check(&token::BinOp(token::Star)) {
let span = self.last_span;
let _ = self.parse_proc_decl();
let _ = self.parse_expr();
- return self.obsolete_expr(span, ObsoleteProcExpr);
+ return self.obsolete_expr(span, ObsoleteSyntax::ProcExpr);
}
if self.eat_keyword(keywords::If) {
return self.parse_if_expr();
op: repeat,
num_captures: name_num
}))
+ } else if p.token.is_keyword_allow_following_colon(keywords::Crate) {
+ p.bump();
+ TtToken(sp, SpecialVarNt(SpecialMacroVar::CrateMacroVar))
} else {
// A nonterminal that matches or not
let namep = match p.token { token::Ident(_, p) => p, _ => token::Plain };
let last_span = self.last_span;
match self.token {
token::OpenDelim(token::Bracket) => {
- self.obsolete(last_span, ObsoleteOwnedVector)
+ self.obsolete(last_span, ObsoleteSyntax::OwnedVector)
},
- _ => self.obsolete(last_span, ObsoleteOwnedExpr)
+ _ => self.obsolete(last_span, ObsoleteSyntax::OwnedExpr)
}
let e = self.parse_prefix_expr();
/// actually, this seems to be the main entry point for
/// parsing an arbitrary expression.
pub fn parse_assign_expr(&mut self) -> P<Expr> {
- let lo = self.span.lo;
let lhs = self.parse_binops();
+ self.parse_assign_expr_with(lhs)
+ }
+
+ pub fn parse_assign_expr_with(&mut self, lhs: P<Expr>) -> P<Expr> {
let restrictions = self.restrictions & RESTRICTION_NO_STRUCT_LITERAL;
match self.token {
token::Eq => {
self.bump();
let rhs = self.parse_expr_res(restrictions);
- self.mk_expr(lo, rhs.span.hi, ExprAssign(lhs, rhs))
+ self.mk_expr(lhs.span.lo, rhs.span.hi, ExprAssign(lhs, rhs))
}
token::BinOpEq(op) => {
self.bump();
token::Shr => BiShr
};
let rhs_span = rhs.span;
+ let span = lhs.span;
let assign_op = self.mk_assign_op(aop, lhs, rhs);
- self.mk_expr(lo, rhs_span.hi, assign_op)
+ self.mk_expr(span.lo, rhs_span.hi, assign_op)
}
_ => {
lhs
} else {
let _ = self.parse_pat();
let span = self.span;
- self.obsolete(span, ObsoleteSubsliceMatch);
+ self.obsolete(span, ObsoleteSyntax::SubsliceMatch);
}
continue
}
pat = PatBox(sub);
let last_span = self.last_span;
hi = last_span.hi;
- self.obsolete(last_span, ObsoleteOwnedPattern);
+ self.obsolete(last_span, ObsoleteSyntax::OwnedPattern);
return P(ast::Pat {
id: ast::DUMMY_NODE_ID,
node: pat,
})
}
token::BinOp(token::And) | token::AndAnd => {
- // parse &pat
+ // parse &pat and &mut pat
let lo = self.span.lo;
self.expect_and();
+ let mutability = if self.eat_keyword(keywords::Mut) {
+ ast::MutMutable
+ } else {
+ ast::MutImmutable
+ };
let sub = self.parse_pat();
- pat = PatRegion(sub);
+ pat = PatRegion(sub, mutability);
hi = self.last_span.hi;
return P(ast::Pat {
id: ast::DUMMY_NODE_ID,
&mut stmts,
&mut expr);
}
- StmtMac(macro, MacStmtWithoutBraces) => {
+ StmtMac(mac, MacStmtWithoutBraces) => {
// statement macro without braces; might be an
// expr depending on whether a semicolon follows
match self.token {
token::Semi => {
stmts.push(P(Spanned {
- node: StmtMac(macro,
+ node: StmtMac(mac,
MacStmtWithSemicolon),
span: span,
}));
_ => {
let e = self.mk_mac_expr(span.lo,
span.hi,
- macro.and_then(|m| m.node));
- let e =
- self.parse_dot_or_call_expr_with(e);
+ mac.and_then(|m| m.node));
+ let e = self.parse_dot_or_call_expr_with(e);
+ let e = self.parse_more_binops(e, 0);
+ let e = self.parse_assign_expr_with(e);
self.handle_expression_like_statement(
e,
ast::DUMMY_NODE_ID,
// unbound, and it may only be `Sized`. To avoid backtracking and other
// complications, we parse an ident, then check for `?`. If we find it,
// we use the ident as the unbound, otherwise, we use it as the name of
- // type param. Even worse, for now, we need to check for `?` before or
- // after the bound.
+ // type param. Even worse, we need to check for `?` before or after the
+ // bound.
let mut span = self.span;
let mut ident = self.parse_ident();
let mut unbound = None;
unbound = Some(tref);
span = self.span;
ident = self.parse_ident();
+ self.obsolete(span, ObsoleteSyntax::Sized);
}
let mut bounds = self.parse_colon_then_ty_param_bounds(BoundParsingMode::Modified);
self.bump();
drop(self.expect_self_ident());
let last_span = self.last_span;
- self.obsolete(last_span, ObsoleteOwnedSelf)
+ self.obsolete(last_span, ObsoleteSyntax::OwnedSelf)
}
SelfStatic
}
self.bump();
drop(self.expect_self_ident());
let last_span = self.last_span;
- self.obsolete(last_span, ObsoleteOwnedSelf);
+ self.obsolete(last_span, ObsoleteSyntax::OwnedSelf);
SelfStatic
} else {
SelfStatic
self.span_err(ty.span, "`virtual` structs have been removed from the language");
}
- self.parse_where_clause(&mut generics);
+ // There is a special case worth noting here, as reported in issue #17904.
+ // If we are parsing a tuple struct it is the case that the where clause
+ // should follow the field list. Like so:
+ //
+ // struct Foo<T>(T) where T: Copy;
+ //
+ // If we are parsing a normal record-style struct it is the case
+ // that the where clause comes before the body, and after the generics.
+ // So if we look ahead and see a brace or a where-clause we begin
+ // parsing a record style struct.
+ //
+ // Otherwise if we look ahead and see a paren we parse a tuple-style
+ // struct.
+
+ let (fields, ctor_id) = if self.token.is_keyword(keywords::Where) {
+ self.parse_where_clause(&mut generics);
+ if self.eat(&token::Semi) {
+ // If we see a: `struct Foo<T> where T: Copy;` style decl.
+ (Vec::new(), Some(ast::DUMMY_NODE_ID))
+ } else {
+ // If we see: `struct Foo<T> where T: Copy { ... }`
+ (self.parse_record_struct_body(&class_name), None)
+ }
+ // No `where` so: `struct Foo<T>;`
+ } else if self.eat(&token::Semi) {
+ (Vec::new(), Some(ast::DUMMY_NODE_ID))
+ // Record-style struct definition
+ } else if self.token == token::OpenDelim(token::Brace) {
+ let fields = self.parse_record_struct_body(&class_name);
+ (fields, None)
+ // Tuple-style struct definition with optional where-clause.
+ } else {
+ let fields = self.parse_tuple_struct_body(&class_name, &mut generics);
+ (fields, Some(ast::DUMMY_NODE_ID))
+ };
- let mut fields: Vec<StructField>;
- let is_tuple_like;
+ (class_name,
+ ItemStruct(P(ast::StructDef {
+ fields: fields,
+ ctor_id: ctor_id,
+ }), generics),
+ None)
+ }
+ pub fn parse_record_struct_body(&mut self, class_name: &ast::Ident) -> Vec<StructField> {
+ let mut fields = Vec::new();
if self.eat(&token::OpenDelim(token::Brace)) {
- // It's a record-like struct.
- is_tuple_like = false;
- fields = Vec::new();
while self.token != token::CloseDelim(token::Brace) {
fields.push(self.parse_struct_decl_field(true));
}
+
if fields.len() == 0 {
self.fatal(format!("unit-like struct definition should be \
- written as `struct {};`",
- token::get_ident(class_name))[]);
+ written as `struct {};`",
+ token::get_ident(class_name.clone()))[]);
}
+
self.bump();
- } else if self.check(&token::OpenDelim(token::Paren)) {
- // It's a tuple-like struct.
- is_tuple_like = true;
- fields = self.parse_unspanned_seq(
+ } else {
+ let token_str = self.this_token_to_string();
+ self.fatal(format!("expected `where`, or `{}` after struct \
+ name, found `{}`", "{",
+ token_str)[]);
+ }
+
+ fields
+ }
+
+ pub fn parse_tuple_struct_body(&mut self,
+ class_name: &ast::Ident,
+ generics: &mut ast::Generics)
+ -> Vec<StructField> {
+ // This is the case where we find `struct Foo<T>(T) where T: Copy;`
+ if self.check(&token::OpenDelim(token::Paren)) {
+ let fields = self.parse_unspanned_seq(
&token::OpenDelim(token::Paren),
&token::CloseDelim(token::Paren),
seq_sep_trailing_allowed(token::Comma),
|p| {
- let attrs = p.parse_outer_attributes();
- let lo = p.span.lo;
- let struct_field_ = ast::StructField_ {
- kind: UnnamedField(p.parse_visibility()),
- id: ast::DUMMY_NODE_ID,
- ty: p.parse_ty_sum(),
- attrs: attrs,
- };
- spanned(lo, p.span.hi, struct_field_)
- });
+ let attrs = p.parse_outer_attributes();
+ let lo = p.span.lo;
+ let struct_field_ = ast::StructField_ {
+ kind: UnnamedField(p.parse_visibility()),
+ id: ast::DUMMY_NODE_ID,
+ ty: p.parse_ty_sum(),
+ attrs: attrs,
+ };
+ spanned(lo, p.span.hi, struct_field_)
+ });
+
if fields.len() == 0 {
self.fatal(format!("unit-like struct definition should be \
- written as `struct {};`",
- token::get_ident(class_name))[]);
+ written as `struct {};`",
+ token::get_ident(class_name.clone()))[]);
}
+
+ self.parse_where_clause(generics);
self.expect(&token::Semi);
- } else if self.eat(&token::Semi) {
- // It's a unit-like struct.
- is_tuple_like = true;
- fields = Vec::new();
+ fields
+ // This is the case where we just see struct Foo<T> where T: Copy;
+ } else if self.token.is_keyword(keywords::Where) {
+ self.parse_where_clause(generics);
+ self.expect(&token::Semi);
+ Vec::new()
+ // This case is where we see: `struct Foo<T>;`
} else {
let token_str = self.this_token_to_string();
- self.fatal(format!("expected `{}`, `(`, or `;` after struct \
- name, found `{}`", "{",
- token_str)[])
+ self.fatal(format!("expected `where`, `{}`, `(`, or `;` after struct \
+ name, found `{}`", "{", token_str)[]);
}
-
- let _ = ast::DUMMY_NODE_ID; // FIXME: Workaround for crazy bug.
- let new_id = ast::DUMMY_NODE_ID;
- (class_name,
- ItemStruct(P(ast::StructDef {
- fields: fields,
- ctor_id: if is_tuple_like { Some(new_id) } else { None },
- }), generics),
- None)
}
/// Parse a structure field declaration
// re-jigged shortly in any case, so leaving the hacky version for now.
if self.eat_keyword(keywords::For) {
let span = self.span;
+
let mut ate_question = false;
if self.eat(&token::Question) {
ate_question = true;
"expected `?Sized` after `for` in trait item");
return None;
}
- let tref = Parser::trait_ref_from_ident(ident, span);
- Some(tref)
+ let _tref = Parser::trait_ref_from_ident(ident, span);
+
+ self.obsolete(span, ObsoleteSyntax::ForSized);
+
+ None
} else {
None
}
self.bump();
let path = self.parse_str();
let span = self.span;
- self.obsolete(span, ObsoleteExternCrateRenaming);
+ self.obsolete(span, ObsoleteSyntax::ExternCrateRenaming);
Some(path)
} else if self.eat_keyword(keywords::As) {
// skip the ident if there is one
fn parse_view_path(&mut self) -> P<ViewPath> {
let lo = self.span.lo;
+ // Allow a leading :: because the paths are absolute either way.
+ // This occurs with "use $crate::..." in macros.
+ self.eat(&token::ModSep);
+
if self.check(&token::OpenDelim(token::Brace)) {
// use {foo,bar}
let idents = self.parse_unspanned_seq(
path.push(id);
}
let span = mk_sp(path_lo, self.span.hi);
- self.obsolete(span, ObsoleteImportRenaming);
+ self.obsolete(span, ObsoleteSyntax::ImportRenaming);
let path = ast::Path {
span: span,
global: false,
Plain,
}
+#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Show, Copy)]
+pub enum SpecialMacroVar {
+ /// `$crate` will be filled in with the name of the crate a macro was
+ /// imported from, if any.
+ CrateMacroVar,
+}
+
+impl SpecialMacroVar {
+ pub fn as_str(self) -> &'static str {
+ match self {
+ SpecialMacroVar::CrateMacroVar => "crate",
+ }
+ }
+}
+
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Show, Copy)]
pub enum Lit {
Byte(ast::Name),
// In right-hand-sides of MBE macros:
/// A syntactic variable that will be filled in by macro expansion.
SubstNt(ast::Ident, IdentStyle),
+ /// A macro variable with special meaning.
+ SpecialVarNt(SpecialMacroVar),
// Junk. These carry no data because we don't really care about the data
// they *would* carry, and don't really want to allocate a new ident for
}
}
+ pub fn is_keyword_allow_following_colon(&self, kw: keywords::Keyword) -> bool {
+ match *self {
+ Ident(sid, _) => { kw.to_name() == sid.name }
+ _ => { false }
+ }
+ }
+
/// Returns `true` if the token is either a special identifier, or a strict
/// or reserved keyword.
#[allow(non_upper_case_globals)]
(56, Abstract, "abstract");
(57, Final, "final");
(58, Override, "override");
+ (59, Macro, "macro");
}
}
token::Comment => "/* */".to_string(),
token::Shebang(s) => format!("/* shebang: {}*/", s.as_str()),
+ token::SpecialVarNt(var) => format!("${}", var.as_str()),
+
token::Interpolated(ref nt) => match *nt {
token::NtExpr(ref e) => expr_to_string(&**e),
token::NtMeta(ref e) => meta_item_to_string(&**e),
span: codemap::Span) -> IoResult<()> {
try!(self.print_ident(ident));
try!(self.print_generics(generics));
- try!(self.print_where_clause(generics));
if ast_util::struct_def_is_tuple_like(struct_def) {
if !struct_def.fields.is_empty() {
try!(self.popen());
));
try!(self.pclose());
}
+ try!(self.print_where_clause(generics));
try!(word(&mut self.s, ";"));
try!(self.end());
self.end() // close the outer-box
} else {
+ try!(self.print_where_clause(generics));
try!(self.nbsp());
try!(self.bopen());
try!(self.hardbreak_if_not_bol());
try!(word(&mut self.s, "box "));
try!(self.print_pat(&**inner));
}
- ast::PatRegion(ref inner) => {
+ ast::PatRegion(ref inner, mutbl) => {
try!(word(&mut self.s, "&"));
+ if mutbl == ast::MutMutable {
+ try!(word(&mut self.s, "mut "));
+ }
try!(self.print_pat(&**inner));
}
ast::PatLit(ref e) => try!(self.print_expr(&**e)),
//! This module shows spans for all expressions in the crate
//! to help with compiler debugging.
+use std::str::FromStr;
+
use ast;
use diagnostic;
use visit;
use visit::Visitor;
+enum Mode {
+ Expression,
+ Pattern,
+ Type,
+}
+
+impl FromStr for Mode {
+ fn from_str(s: &str) -> Option<Mode> {
+ let mode = match s {
+ "expr" => Mode::Expression,
+ "pat" => Mode::Pattern,
+ "ty" => Mode::Type,
+ _ => return None
+ };
+ Some(mode)
+ }
+}
+
struct ShowSpanVisitor<'a> {
span_diagnostic: &'a diagnostic::SpanHandler,
+ mode: Mode,
}
impl<'a, 'v> Visitor<'v> for ShowSpanVisitor<'a> {
fn visit_expr(&mut self, e: &ast::Expr) {
- self.span_diagnostic.span_note(e.span, "expression");
+ if let Mode::Expression = self.mode {
+ self.span_diagnostic.span_note(e.span, "expression");
+ }
visit::walk_expr(self, e);
}
- fn visit_mac(&mut self, macro: &ast::Mac) {
- visit::walk_mac(self, macro);
+ fn visit_pat(&mut self, p: &ast::Pat) {
+ if let Mode::Pattern = self.mode {
+ self.span_diagnostic.span_note(p.span, "pattern");
+ }
+ visit::walk_pat(self, p);
+ }
+
+ fn visit_ty(&mut self, t: &ast::Ty) {
+ if let Mode::Type = self.mode {
+ self.span_diagnostic.span_note(t.span, "type");
+ }
+ visit::walk_ty(self, t);
+ }
+
+ fn visit_mac(&mut self, mac: &ast::Mac) {
+ visit::walk_mac(self, mac);
}
}
-pub fn run(span_diagnostic: &diagnostic::SpanHandler, krate: &ast::Crate) {
- let mut v = ShowSpanVisitor { span_diagnostic: span_diagnostic };
+pub fn run(span_diagnostic: &diagnostic::SpanHandler,
+ mode: &str,
+ krate: &ast::Crate) {
+ let mode = match mode.parse() {
+ Some(mode) => mode,
+ None => return
+ };
+ let mut v = ShowSpanVisitor {
+ span_diagnostic: span_diagnostic,
+ mode: mode,
+ };
visit::walk_crate(&mut v, krate);
}
Some((actual_crate_name, ast::CookedStr)),
ast::DUMMY_NODE_ID),
attrs: vec!(
- attr::mk_attr_outer(attr::mk_attr_id(), attr::mk_list_item(
- InternedString::new("phase"),
- vec!(
- attr::mk_word_item(InternedString::new("plugin")),
- attr::mk_word_item(InternedString::new("link")
- ))))),
+ attr::mk_attr_outer(attr::mk_attr_id(), attr::mk_word_item(
+ InternedString::new("macro_use")))),
vis: ast::Inherited,
span: DUMMY_SP
});
// don't add #![no_std] here, that will block the prelude injection later.
// Add it during the prelude injection instead.
- // Add #![feature(phase)] here, because we use #[phase] on extern crate std.
- let feat_phase_attr = attr::mk_attr_inner(attr::mk_attr_id(),
- attr::mk_list_item(
- InternedString::new("feature"),
- vec![attr::mk_word_item(InternedString::new("phase"))],
- ));
- // std_inject runs after feature checking so manually mark this attr
- attr::mark_used(&feat_phase_attr);
- krate.attrs.push(feat_phase_attr);
-
krate
}
}
(*vect).len()
}
- pub fn find<Sized? Q>(&self, val: &Q) -> Option<Name>
+ pub fn find<Q: ?Sized>(&self, val: &Q) -> Option<Name>
where Q: BorrowFrom<T> + Eq + Hash {
let map = self.map.borrow();
match (*map).get(val) {
self.vect.borrow().len()
}
- pub fn find<Sized? Q>(&self, val: &Q) -> Option<Name>
+ pub fn find<Q: ?Sized>(&self, val: &Q) -> Option<Name>
where Q: BorrowFrom<RcStr> + Eq + Hash {
match (*self.map.borrow()).get(val) {
Some(v) => Some(*v),
fn visit_explicit_self(&mut self, es: &'v ExplicitSelf) {
walk_explicit_self(self, es)
}
- fn visit_mac(&mut self, _macro: &'v Mac) {
+ fn visit_mac(&mut self, _mac: &'v Mac) {
panic!("visit_mac disabled by default");
// NB: see note about macros above.
// if you really want a visitor that
// works on macros, use this
// definition in your trait impl:
- // visit::walk_mac(self, _macro)
+ // visit::walk_mac(self, _mac)
}
fn visit_path(&mut self, path: &'v Path, _id: ast::NodeId) {
walk_path(self, path)
visitor.visit_trait_item(method)
}
}
- ItemMac(ref macro) => visitor.visit_mac(macro),
+ ItemMac(ref mac) => visitor.visit_mac(mac),
}
for attr in item.attrs.iter() {
visitor.visit_attribute(attr);
}
}
PatBox(ref subpattern) |
- PatRegion(ref subpattern) => {
+ PatRegion(ref subpattern, _) => {
visitor.visit_pat(&**subpattern)
}
PatIdent(_, ref pth1, ref optional_subpattern) => {
visitor.visit_pat(&**postpattern)
}
}
- PatMac(ref macro) => visitor.visit_mac(macro),
+ PatMac(ref mac) => visitor.visit_mac(mac),
}
}
StmtExpr(ref expression, _) | StmtSemi(ref expression, _) => {
visitor.visit_expr(&**expression)
}
- StmtMac(ref macro, _) => visitor.visit_mac(&**macro),
+ StmtMac(ref mac, _) => visitor.visit_mac(&**mac),
}
}
ExprRet(ref optional_expression) => {
walk_expr_opt(visitor, optional_expression)
}
- ExprMac(ref macro) => visitor.visit_mac(macro),
+ ExprMac(ref mac) => visitor.visit_mac(mac),
ExprParen(ref subexpression) => {
visitor.visit_expr(&**subexpression)
}
#![deny(missing_docs)]
-#[phase(plugin, link)] extern crate log;
+#[cfg(stage0)]
+#[phase(plugin, link)]
+extern crate log;
+
+#[cfg(not(stage0))]
+#[macro_use]
+extern crate log;
pub use terminfo::TerminfoTerminal;
#[cfg(windows)]
/// Parse a compiled terminfo entry, using long capability names if `longnames` is true
pub fn parse(file: &mut io::Reader, longnames: bool)
-> Result<Box<TermInfo>, String> {
- macro_rules! try( ($e:expr) => (
+ macro_rules! try { ($e:expr) => (
match $e {
Ok(e) => e,
Err(e) => return Err(format!("{}", e))
}
- ) );
+ ) }
let bnames;
let snames;
html_root_url = "http://doc.rust-lang.org/nightly/")]
#![allow(unknown_features)]
-#![feature(asm, macro_rules, phase, globs, slicing_syntax)]
+#![feature(asm, globs, slicing_syntax)]
#![feature(unboxed_closures, default_type_params)]
#![feature(old_orphan_check)]
}
/// Trait that provides simple descriptive statistics on a univariate set of numeric samples.
-pub trait Stats <T: FloatMath + FromPrimitive> for Sized? {
+pub trait Stats <T: FloatMath + FromPrimitive> {
/// Sum of the samples.
///
fn sum(&self) -> T {
let mut partials = vec![];
- for &mut x in self.iter() {
+ for &x in self.iter() {
+ let mut x = x;
let mut j = 0;
// This inner loop applies `hi`/`lo` summation to each
// partial so that the list of partial sums remains exact.
/// Methods for Unicode string slices
#[allow(missing_docs)] // docs in libcollections
-pub trait UnicodeStr for Sized? {
+pub trait UnicodeStr {
fn graphemes<'a>(&'a self, is_extended: bool) -> Graphemes<'a>;
fn grapheme_indices<'a>(&'a self, is_extended: bool) -> GraphemeIndices<'a>;
fn words<'a>(&'a self) -> Words<'a>;
-Subproject commit ec1fdb3b9d3b1fb9e1dae97a65dd3a13db9bfb23
+Subproject commit b820135911e17c7a46b901db56baa48e5155bf46
# If this file is modified, then llvm will be forcibly cleaned and then rebuilt.
# The actual contents of this file do not matter, but to trigger a change on the
# build bots then the contents should be changed so git updates the mtime.
-2015-01-03
+2015-01-05
// cross-crate scenario.
#![crate_type="lib"]
-#![feature(associated_types)]
pub trait Bar {
type T;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(default_type_params)]
-
pub struct Heap;
pub struct FakeHeap;
// no-prefer-dynamic
#![crate_type = "rlib"]
-#![feature(phase)]
-#[phase(plugin)] extern crate "issue-13560-1" as t1;
-#[phase(plugin, link)] extern crate "issue-13560-2" as t2;
+#[macro_use] #[no_link] extern crate "issue-13560-1" as t1;
+#[macro_use] extern crate "issue-13560-2" as t2;
// except according to those terms.
#![crate_type = "lib"]
-#![feature(associated_types)]
pub struct TreeBuilder<H>;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
pub trait T {
type C;
}
// except according to those terms.
#![allow(unused_imports)]
-#![feature(globs)]
extern crate issue_2316_a;
#![feature(lang_items)]
#[lang="sized"]
-pub trait Sized for Sized? {}
+pub trait Sized {}
#[lang="panic"]
fn panic(_: &(&'static str, &'static str, uint)) -> ! { loop {} }
fn baz() { }
pub fn test() {
- let none: Option<Path> = None; // appease the typechecker
+ let none: Option<&Path> = None; // appease the typechecker
let lib = DynamicLibrary::open(none).unwrap();
unsafe {
assert!(lib.symbol::<int>("foo").is_ok());
// force-host
-#![feature(phase, plugin_registrar)]
+#![feature(plugin_registrar)]
extern crate syntax;
// Load rustc as a plugin to get macros
-#[phase(plugin, link)]
+#[macro_use]
extern crate rustc;
use syntax::ast;
// force-host
-#![feature(phase, plugin_registrar)]
+#![feature(plugin_registrar)]
extern crate syntax;
// Load rustc as a plugin to get macros
-#[phase(plugin, link)]
+#[macro_use]
extern crate rustc;
use syntax::ast;
#![crate_name="lint_stability"]
#![crate_type = "lib"]
-#![feature(macro_rules)]
-#![macro_escape]
-
#[deprecated]
pub fn deprecated() {}
#[deprecated="text"]
pub struct LockedTupleStruct(pub int);
#[macro_export]
-macro_rules! macro_test(
+macro_rules! macro_test {
() => (deprecated());
-);
+}
#[macro_export]
-macro_rules! macro_test_arg(
+macro_rules! macro_test_arg {
($func:expr) => ($func);
-);
+}
#[macro_export]
-macro_rules! macro_test_arg_nested(
+macro_rules! macro_test_arg_nested {
($func:ident) => (macro_test_arg!($func()));
-);
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(phase)]
-#[phase(plugin, link)] extern crate log;
+#[macro_use] extern crate log;
pub fn foo<T>() {
fn death() -> int { panic!() }
--- /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.
+
+// force-host
+
+#![feature(plugin_registrar)]
+
+extern crate syntax;
+extern crate rustc;
+
+use syntax::parse::token;
+use syntax::ext::base::MacroRulesTT;
+use rustc::plugin::Registry;
+
+#[plugin_registrar]
+pub fn plugin_registrar(reg: &mut Registry) {
+ reg.register_syntax_extension(token::intern("bogus"), MacroRulesTT);
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
#[macro_export]
-macro_rules! make_a_5(
+macro_rules! make_a_5 {
() => (5)
-);
+}
--- /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 fn increment(x: uint) -> uint {
+ x + 1
+}
+
+#[macro_export]
+macro_rules! increment {
+ ($x:expr) => ($crate::increment($x))
+}
+
+pub fn check_local() {
+ assert_eq!(increment!(3), 4);
+}
// force-host
-#![feature(globs, plugin_registrar, macro_rules, quote)]
+#![feature(plugin_registrar, quote)]
extern crate syntax;
extern crate rustc;
use rustc::plugin::Registry;
#[macro_export]
-macro_rules! exported_macro (() => (2i));
+macro_rules! exported_macro { () => (2i) }
-macro_rules! unexported_macro (() => (3i));
+macro_rules! unexported_macro { () => (3i) }
#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
pub mod inner {
#[macro_export]
- macro_rules! foo(
+ macro_rules! foo {
() => (1)
- );
+ }
}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "dylib"]
+
+// Since we load a serialized macro with all its attributes, accidentally
+// re-exporting a `#[macro_export] macro_rules!` is something of a concern!
+//
+// We avoid it at the moment only because of the order in which we do things.
+
+#[macro_use] #[no_link]
+extern crate macro_reexport_1;
--- /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.
+
+#![crate_type = "dylib"]
+#[macro_export]
+macro_rules! reexported {
+ () => ( 3u )
+}
--- /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.
+
+#![crate_type = "dylib"]
+
+#[macro_reexport(reexported)]
+#[macro_use] #[no_link]
+extern crate macro_reexport_1;
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "dylib"]
+
+#[macro_reexport(reexported)]
+#[no_link]
+extern crate macro_reexport_1;
// <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(globs)]
pub use Foo::*;
pub fn foo() {}
}
}
-
-
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
use std::ops::Deref;
struct DerefWithHelper<H, T> {
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// force-host
+
+#![feature(plugin_registrar)]
+
+extern crate syntax;
+extern crate rustc;
+
+use std::borrow::ToOwned;
+use syntax::ast;
+use syntax::codemap::Span;
+use syntax::ext::build::AstBuilder;
+use syntax::ext::base::{TTMacroExpander, ExtCtxt, MacResult, MacExpr, NormalTT};
+use syntax::parse::token;
+use syntax::print::pprust;
+use syntax::ptr::P;
+use rustc::plugin::Registry;
+
+struct Expander {
+ args: P<ast::MetaItem>,
+}
+
+impl TTMacroExpander for Expander {
+ fn expand<'cx>(&self,
+ ecx: &'cx mut ExtCtxt,
+ sp: Span,
+ _: &[ast::TokenTree]) -> Box<MacResult+'cx> {
+
+ let attr = ecx.attribute(sp, self.args.clone());
+ let src = pprust::attribute_to_string(&attr);
+ let interned = token::intern_and_get_ident(src.as_slice());
+ MacExpr::new(ecx.expr_str(sp, interned))
+ }
+}
+
+#[plugin_registrar]
+pub fn plugin_registrar(reg: &mut Registry) {
+ let args = reg.args().clone();
+ reg.register_syntax_extension(token::intern("plugin_args"),
+ NormalTT(box Expander { args: args, }, None));
+}
//! should not affect the strict version hash (SVH) computation
//! (#14132).
-#![feature(macro_rules)]
-
#![crate_name = "a"]
macro_rules! three {
//! should not affect the strict version hash (SVH) computation
//! (#14132).
-#![feature(macro_rules)]
-
#![crate_name = "a"]
macro_rules! three {
//! should not affect the strict version hash (SVH) computation
//! (#14132).
-#![feature(macro_rules)]
-
#![crate_name = "a"]
macro_rules! three {
//! should not affect the strict version hash (SVH) computation
//! (#14132).
-#![feature(macro_rules)]
-
#![crate_name = "a"]
macro_rules! three {
//! should not affect the strict version hash (SVH) computation
//! (#14132).
-#![feature(macro_rules)]
-
#![crate_name = "a"]
macro_rules! three {
//! should not affect the strict version hash (SVH) computation
//! (#14132).
-#![feature(macro_rules)]
-
#![crate_name = "a"]
macro_rules! three {
//! should not affect the strict version hash (SVH) computation
//! (#14132).
-#![feature(macro_rules)]
-
#![crate_name = "a"]
macro_rules! three {
//! should not affect the strict version hash (SVH) computation
//! (#14132).
-#![feature(macro_rules)]
-
#![crate_name = "a"]
macro_rules! three {
//! should not affect the strict version hash (SVH) computation
//! (#14132).
-#![feature(macro_rules)]
-
#![crate_name = "a"]
macro_rules! three {
//! should not affect the strict version hash (SVH) computation
//! (#14132).
-#![feature(macro_rules)]
-
#![crate_name = "a"]
macro_rules! three {
//! should not affect the strict version hash (SVH) computation
//! (#14132).
-#![feature(macro_rules)]
-
#![crate_name = "a"]
macro_rules! three {
//! should not affect the strict version hash (SVH) computation
//! (#14132).
-#![feature(macro_rules)]
-
#![crate_name = "a"]
macro_rules! three {
//! should not affect the strict version hash (SVH) computation
//! (#14132).
-#![feature(macro_rules)]
-
#![crate_name = "a"]
macro_rules! three {
// force-host
#![crate_type = "dylib"]
-#![feature(plugin_registrar, quote, globs)]
+#![feature(plugin_registrar, quote)]
extern crate "syntax-extension-with-dll-deps-1" as other;
extern crate syntax;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
use std::cmp::PartialEq;
use std::ops::{Add, Sub, Mul};
// Test inherant trait impls work cross-crait.
-pub trait Bar<'a> for ?Sized : 'a {}
+pub trait Bar<'a> : 'a {}
impl<'a> Bar<'a> {
pub fn bar(&self) {}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[macro_export]
+macro_rules! macro_one { () => ("one") }
+
+#[macro_export]
+macro_rules! macro_two { () => ("two") }
// it hasn't been defined just yet. Make sure we don't explode.
#![no_std]
-#![feature(phase)]
#![crate_type = "rlib"]
-#[phase(plugin, link)]
+#[macro_use]
extern crate core;
struct A;
// ignore-lexer-test FIXME #15679
// Microbenchmarks for various functions in std and extra
-#![feature(macro_rules)]
#![feature(unboxed_closures)]
use std::io::File;
let argv = os::args();
let _tests = argv.slice(1, argv.len());
- macro_rules! bench (
+ macro_rules! bench {
($id:ident) =>
(maybe_run_test(argv.as_slice(),
stringify!($id).to_string(),
- $id)));
+ $id))
+ }
bench!(shift_push);
bench!(read_line);
// Create a channel: B->A
let (btx, brx) = channel();
- Thread::spawn(move|| {
+ let guard_a = Thread::spawn(move|| {
let (tx, rx) = (atx, brx);
for _ in range(0, n) {
tx.send(()).unwrap();
rx.recv().unwrap();
}
- }).detach();
+ });
- Thread::spawn(move|| {
+ let guard_b = Thread::spawn(move|| {
let (tx, rx) = (btx, arx);
for _ in range(0, n) {
rx.recv().unwrap();
tx.send(()).unwrap();
}
- }).detach();
+ });
+
+ guard_a.join().ok();
+ guard_b.join().ok();
}
for _ in range(0, m) {
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
-#![feature(associated_types, slicing_syntax)]
+#![feature(slicing_syntax)]
use std::cmp::min;
use std::io::{BufferedWriter, File};
// ignore-android see #10393 #13206
-#![feature(associated_types, slicing_syntax)]
+#![feature(slicing_syntax)]
use std::ascii::OwnedAsciiExt;
use std::iter::repeat;
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
-#![feature(macro_rules)]
#![feature(simd)]
#![allow(experimental)]
// no-pretty-expanded FIXME #15189
-#![feature(associated_types)]
-
use std::iter::repeat;
use std::sync::Arc;
use std::sync::mpsc::channel;
// ignore-stage1
// ignore-cross-compile #12102
-#![feature(macro_rules, phase, slicing_syntax)]
+#![feature(plugin, slicing_syntax)]
extern crate regex;
// ignore-android see #10393 #13206
-#![feature(associated_types, slicing_syntax, unboxed_closures)]
+#![feature(slicing_syntax, unboxed_closures)]
extern crate libc;
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// aux-build:macro_crate_test.rs
-// ignore-stage1
-
-#[phase(plugin)]
-//~^ ERROR compile time crate loading is experimental and possibly buggy
-extern crate macro_crate_test;
-
-fn main() {}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:macro_crate_test.rs
+// ignore-stage1
+
+#[plugin] #[no_link]
+//~^ ERROR compiler plugins are experimental and possibly buggy
+extern crate macro_crate_test;
+
+fn main() {}
// ignore-stage1
// compile-flags: -D lint-me
-#![feature(phase)]
+#![feature(plugin)]
-#[phase(plugin)]
+#[plugin] #[no_link]
extern crate lint_group_plugin_test;
fn lintme() { } //~ ERROR item is named 'lintme'
// aux-build:lint_plugin_test.rs
// ignore-stage1
-#![feature(phase)]
+#![feature(plugin)]
#![deny(test_lint)]
-#[phase(plugin)]
+#[plugin] #[no_link]
extern crate lint_plugin_test;
fn lintme() { } //~ ERROR item is named 'lintme'
// ignore-stage1
// compile-flags: -D test-lint
-#![feature(phase)]
+#![feature(plugin)]
-#[phase(plugin)]
+#[plugin] #[no_link]
extern crate lint_plugin_test;
fn lintme() { } //~ ERROR item is named 'lintme'
// aux-build:lint_plugin_test.rs
// ignore-stage1
-#![feature(phase)]
+#![feature(plugin)]
#![forbid(test_lint)]
-#[phase(plugin)]
+#[plugin] #[no_link]
extern crate lint_plugin_test;
fn lintme() { } //~ ERROR item is named 'lintme'
// ignore-stage1
// compile-flags: -F test-lint
-#![feature(phase)]
+#![feature(plugin)]
-#[phase(plugin)]
+#[plugin] #[no_link]
extern crate lint_plugin_test;
fn lintme() { } //~ ERROR item is named 'lintme'
// editors, so instead he made a macro that expands into the embedded
// ident form.
-#![feature(phase)]
+#![feature(plugin)]
-#[phase(plugin)]
+#[plugin] #[no_link]
extern crate macro_crate_test;
fn main() {
--- /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
+// ignore-android
+
+#[macro_use] #[no_link]
+extern crate macro_crate_test;
+
+fn main() {
+ macro_crate_test::foo();
+ //~^ ERROR failed to resolve. Use of undeclared type or module `macro_crate_test`
+ //~^^ ERROR unresolved name `macro_crate_test::foo`
+}
// ignore-android
// ignore-cross-compile gives a different error message
-#![feature(phase)]
-#[phase(plugin)] extern crate rlib_crate_test;
+#![feature(plugin)]
+#[plugin] #[no_link] extern crate rlib_crate_test;
//~^ ERROR: plugin crate `rlib_crate_test` only found in rlib format, but must be available in dylib format
fn main() {}
// ignore-stage1
// ignore-android
-#![feature(phase)]
-
-#[phase(plugin)]
+#[macro_use] #[no_link]
extern crate macro_crate_test;
fn main() {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(phase)]
-
-#[phase(plugin)]
+#[macro_use] #[no_link]
extern crate doesnt_exist; //~ ERROR can't find crate
fn main() {}
+++ /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
-// ignore-android
-
-#![feature(phase)]
-
-#[phase(plugin)]
-extern crate macro_crate_test;
-
-fn main() {
- macro_crate_test::foo();
- //~^ ERROR failed to resolve. Use of undeclared type or module `macro_crate_test`
- //~^^ ERROR unresolved name `macro_crate_test::foo`
-}
--- /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_MacroRulesTT.rs
+// ignore-stage1
+// ignore-android
+// error-pattern: plugin tried to register a new MacroRulesTT
+
+#![feature(plugin)]
+
+#[plugin] #[no_link]
+extern crate macro_crate_MacroRulesTT;
+
+fn main() { }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
+// ignore-stage1 (#20184)
// compile-flags: -C codegen-units=2
// error-pattern: build without -C codegen-units for more exact errors
// Test equality constraints in a where clause where the type being
// equated appears in a supertrait.
-#![feature(associated_types)]
-
pub trait Vehicle {
type Color;
// Test equality constraints in a where clause where the type being
// equated appears in a supertrait.
-#![feature(associated_types)]
-
pub trait Vehicle {
type Color;
// just propagate the error.
#![crate_type = "lib"]
-#![feature(associated_types, default_type_params, lang_items)]
+#![feature(lang_items)]
#![no_std]
#[lang="sized"]
-pub trait Sized for Sized? {
+pub trait Sized {
// Empty.
}
// Test equality constraints in a where clause where the type being
// equated appears in a supertrait.
-#![feature(associated_types)]
-
pub trait Vehicle {
type Color;
// Test equality constraints on associated types in a where clause.
-#![feature(associated_types)]
-
pub trait ToInt {
fn to_int(&self) -> int;
}
// Test equality constraints on associated types. Check that unsupported syntax
// does not ICE.
-#![feature(associated_types)]
-
pub trait Foo {
type A;
fn boo(&self) -> <Self as Foo>::A;
// Test equality constraints on associated types. Check we get an error when an
// equality constraint is used in a qualified path.
-#![feature(associated_types)]
-
pub trait Foo {
type A;
fn boo(&self) -> <Self as Foo>::A;
// Test equality constraints on associated types. Check we get type errors
// where we should.
-#![feature(associated_types)]
-
pub trait Foo {
type A;
fn boo(&self) -> <Self as Foo>::A;
// Check that an associated type cannot be bound in an expression path.
-#![feature(associated_types)]
-
trait Foo {
type A;
fn bar() -> int;
// Check testing of equality constraints in a higher-ranked context.
-#![feature(associated_types)]
-
pub trait TheTrait<T> {
type 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.
-
-trait Get {
- type Value; //~ ERROR associated types are experimental
- fn get(&self) -> Get::Value;
-}
-
-struct Struct {
- x: int,
-}
-
-impl Get for Struct {
- type Value = int; //~ ERROR associated types are experimental
- fn get(&self) -> int {
- self.x
- }
-}
-
-fn main() {
- let s = Struct {
- x: 100,
- };
- assert_eq!(s.get(), 100);
-}
-
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
trait Get {
type Value;
fn get(&self) -> <Self as Get>::Value;
fn main() {
}
-
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
trait Get {
type Value;
fn get(&self) -> <Self as Get>::Value;
fn main() {
}
-
// Check that the user gets an errror if they omit a binding from an
// object type.
-#![feature(associated_types)]
-
pub trait Foo {
type A;
type B;
--- /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.
+
+// Test that we report an error if the trait ref in an qualified type
+// uses invalid type arguments.
+
+trait Foo<T> {
+ type Bar;
+ fn get_bar(&self) -> Self::Bar;
+}
+
+fn f<T:Foo<int>>(t: &T) {
+ let u: <T as Foo<uint>>::Bar = t.get_bar();
+ //~^ ERROR the trait `Foo<uint>` is not implemented for the type `T`
+}
+
+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.
+
+// Test that we do not ICE when an impl is missing an associated type (and that we report
+// a useful error, of course).
+
+trait Trait {
+ type Type;
+}
+
+impl Trait for int {} //~ ERROR missing: `Type`
+
+fn main() {}
+
// Test that we reliably check the value of the associated type.
#![crate_type = "lib"]
-#![feature(associated_types)]
#![no_implicit_prelude]
use std::option::Option::{self, None, Some};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
trait Get {
type Value;
fn get(&self) -> <Self as Get>::Value;
fn main() {
}
-
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
// Check that we get an error when you use `<Self as Get>::Value` in
// the trait definition but `Self` does not, in fact, implement `Get`.
// Test that we have one and only one associated type per ref.
-#![feature(associated_types)]
-
pub trait Foo {
type A;
}
pub fn f2<T: Foo + Bar>(a: T, x: T::A) {} //~ERROR ambiguous associated type `A`
pub fn main() {}
-
// Test type checking of uses of associated types via sugary paths.
-#![feature(associated_types)]
-
pub trait Foo {
type A;
}
// Test you can't use a higher-ranked trait bound inside of a qualified
// path (just won't parse).
-#![feature(associated_types)]
-
pub trait Foo<T> {
type A;
// Check projection of an associated type out of a higher-ranked
// trait-bound in the context of a function body.
-#![feature(associated_types)]
-
pub trait Foo<T> {
type A;
// Check projection of an associated type out of a higher-ranked trait-bound
// in the context of a function signature.
-#![feature(associated_types)]
-
pub trait Foo<T> {
type A;
// Check projection of an associated type out of a higher-ranked trait-bound
// in the context of a struct definition.
-#![feature(associated_types)]
-
pub trait Foo<T> {
type A;
// Check projection of an associated type out of a higher-ranked trait-bound
// in the context of a method definition in a trait.
-#![feature(associated_types)]
-
pub trait Foo<T> {
type A;
// Check that an associated type cannot be bound in an expression path.
-#![feature(associated_types)]
-
trait Foo {
type A;
fn bar() -> int;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
trait Get {
- type Sized? Value;
+ type Value: ?Sized;
fn get(&self) -> <Self as Get>::Value;
}
fn main() {
}
-
// Test that binary operators consume their arguments
-#![feature(associated_types, default_type_params)]
-
use std::ops::{Add, Sub, Mul, Div, Rem, BitAnd, BitXor, BitOr, Shl, Shr};
fn add<A: Add<B, Output=()>, B>(lhs: A, rhs: B) {
// Test that move restrictions are enforced on overloaded binary operations
-#![feature(associated_types, default_type_params)]
-
use std::ops::Add;
fn double_move<T: Add<Output=()>>(x: T) {
// Test how overloaded deref interacts with borrows when DerefMut
// is implemented.
-#![feature(associated_types)]
-
use std::ops::{Deref, DerefMut};
struct Own<T> {
// Test how overloaded deref interacts with borrows when only
// Deref and not DerefMut is implemented.
-#![feature(associated_types)]
-
use std::ops::Deref;
struct Rc<T> {
// Test how overloaded deref interacts with borrows when DerefMut
// is implemented.
-#![feature(associated_types)]
-
use std::ops::{Deref, DerefMut};
struct Own<T> {
// Test how overloaded deref interacts with borrows when only
// Deref and not DerefMut is implemented.
-#![feature(associated_types)]
-
use std::ops::Deref;
struct Rc<T> {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
use std::ops::Add;
#[derive(Clone)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types, default_type_params)]
-
use std::ops::Add;
#[derive(Copy)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
use std::ops::Index;
struct MyVec<T> {
// Test that we still see borrowck errors of various kinds when using
// indexing and autoderef in combination.
-#![feature(associated_types)]
-
use std::ops::{Index, IndexMut};
struct Foo {
fn main() {
}
-
-
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
use std::ops::{Index, IndexMut};
struct Foo {
s[2] = 20;
//~^ ERROR cannot assign to immutable dereference (dereference is implicit, due to indexing)
}
-
-
// Test that the borrow checker prevents pointers to temporaries
// with statement lifetimes from escaping.
-#![feature(macro_rules)]
-
use std::ops::Drop;
static mut FLAGS: u64 = 0;
use lib::Remote;
impl<T> Remote for int { }
-//~^ ERROR cannot provide an extension implementation
+//~^ ERROR E0117
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.
+
+// aux-build:coherence-lib.rs
+
+extern crate "coherence-lib" as lib;
+use lib::Remote1;
+
+pub struct BigInt;
+
+impl Remote1<BigInt> for int { } //~ ERROR E0117
+
+fn main() { }
pub struct BigInt;
impl<T> Remote1<BigInt> for T { }
-//~^ ERROR type parameter `T` must also appear
+//~^ ERROR type parameter `T` is not constrained
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.
+
+// aux-build:coherence-lib.rs
+
+extern crate "coherence-lib" as lib;
+use lib::Remote1;
+
+pub struct BigInt;
+
+impl Remote1<BigInt> for Vec<int> { } //~ ERROR E0117
+
+fn main() { }
use trait_impl_conflict::Foo;
impl<A> Foo for A {
- //~^ ERROR E0117
+ //~^ ERROR type parameter `A` is not constrained
//~^^ ERROR E0119
}
+++ /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:coherence-lib.rs
-
-extern crate "coherence-lib" as lib;
-use lib::Remote1;
-
-struct Foo<T>(T);
-
-impl<T,U> Remote1<U> for Foo<T> { }
-//~^ ERROR type parameter `U` must also appear
-
-fn main() { }
extern crate "coherence-lib" as lib;
use lib::Remote;
-impl<T> Remote for T { } //~ ERROR E0117
+impl<T> Remote for T { } //~ ERROR type parameter `T` is not constrained
fn main() { }
impl TheTrait<uint> for int { } //~ ERROR E0117
-impl TheTrait<TheType> for int { }
+impl TheTrait<TheType> for int { } //~ ERROR E0117
impl TheTrait<int> for TheType { }
struct Foo;
impl<T> Remote for lib::Pair<T,Foo> { }
-//~^ ERROR type parameter `T` must also appear
+//~^ ERROR type parameter `T` is not constrained
fn main() { }
struct Local<T>(T);
impl<T,U> Remote for Pair<T,Local<U>> { }
-//~^ ERROR type parameter `T` must also appear
+//~^ ERROR type parameter `T` is not constrained
fn main() { }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
static A: uint = { 1u; 2 };
//~^ ERROR: blocks in constants are limited to items and tail expressions
--- /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.
+
+#[phase(blah)]
+//~^ ERROR #[phase] is deprecated
+extern crate foo;
+
+fn main() {}
impl Drop for int {
//~^ ERROR the Drop trait may only be implemented on structures
- //~^^ ERROR cannot provide an extension implementation
+ //~^^ ERROR E0117
fn drop(&mut self) {
println!("kaboom");
}
// Forbid assignment into a dynamically sized type.
-struct Fat<Sized? T> {
+struct Fat<T: ?Sized> {
f1: int,
f2: &'static str,
ptr: T
// Forbid assignment into a dynamically sized type.
-struct Fat<Sized? T> {
+struct Fat<T: ?Sized> {
f1: int,
f2: &'static str,
ptr: T
// Attempt to change the type as well as unsizing.
-struct Fat<Sized? T> {
+struct Fat<T: ?Sized> {
ptr: T
}
// Attempt to change the mutability as well as unsizing.
-struct Fat<Sized? T> {
+struct Fat<T: ?Sized> {
ptr: T
}
// Attempt to extend the lifetime as well as unsizing.
-struct Fat<Sized? T> {
+struct Fat<T: ?Sized> {
ptr: T
}
// Attempt to coerce from unsized to sized.
-struct Fat<Sized? T> {
+struct Fat<T: ?Sized> {
ptr: T
}
trait T {}
impl T for S {}
-struct Foo<Sized? T> {
+struct Foo<T: ?Sized> {
f: T
}
// because it would require stack allocation of an unsized temporary (*g in the
// test).
-struct Fat<Sized? T> {
+struct Fat<T: ?Sized> {
ptr: T
}
// Test that overloaded index expressions with DST result types
// can't be used as rvalues
-#![feature(associated_types)]
-
use std::ops::Index;
use std::fmt::Show;
// Test that we cannot create objects from unsized types.
-trait Foo for Sized? {}
+trait Foo {}
impl Foo for str {}
-fn test1<Sized? T: Foo>(t: &T) {
+fn test1<T: ?Sized + Foo>(t: &T) {
let u: &Foo = t;
//~^ ERROR `core::kinds::Sized` is not implemented for the type `T`
}
-fn test2<Sized? T: Foo>(t: &T) {
+fn test2<T: ?Sized + Foo>(t: &T) {
let v: &Foo = t as &Foo;
//~^ ERROR `core::kinds::Sized` is not implemented for the type `T`
}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:two_macros.rs
+// ignore-stage1
+
+#[macro_use()]
+extern crate two_macros;
+
+pub fn main() {
+ macro_two!(); //~ ERROR macro undefined
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(phase)]
#![deny(dead_code)]
#![allow(unreachable_code)]
-#[phase(link, plugin)] extern crate core;
+#[macro_use] extern crate core;
fn foo() { //~ ERROR function is never used
+++ /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:default_type_params_xc.rs
-
-#![deny(default_type_param_usage)]
-
-extern crate default_type_params_xc;
-
-pub struct FooAlloc;
-
-pub type VecFoo<T> = default_type_params_xc::FakeVec<T, FooAlloc>;
-//~^ ERROR: default type parameters are experimental
-
-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.
-
-struct Heap;
-
-struct Vec<T, A = Heap>; //~ ERROR: default type parameters are experimental
-
-fn main() {}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use std::*;
-//~^ ERROR: glob import statements are experimental
-
-fn main() {}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-macro_rules! foo(() => ());
-//~^ ERROR: macro definitions are not stable enough for use
-
-fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(default_type_params)]
-
struct Foo<A, B, C = (A, B)>;
impl<A, B, C = (A, B)> Foo<A, B, C> {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(default_type_params)]
-
struct Heap;
struct Vec<T, A = Heap>;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(default_type_params)]
-
struct Heap;
struct Vec<A = Heap, T>; //~ ERROR type parameters with a default must be trailing
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(default_type_params)]
-
struct Heap;
struct Vec<T, A = Heap>;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(default_type_params)]
-
struct Heap;
struct Vec<T, A = Heap>;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(default_type_params)]
-
// Ensure that we get an error and not an ICE for this problematic case.
struct Foo<T = Option<U>, U = bool>;
//~^ ERROR type parameters with a default cannot use forward declared identifiers
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(default_type_params)]
-
struct A;
struct B;
struct C;
// Make sure that globs only bring in public things.
-#![feature(globs)]
-
use bar::*;
mod bar {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
macro_rules! foo {
() => { break 'x; }
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
macro_rules! foo {
($e: expr) => { 'x: loop { $e } }
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
macro_rules! foo {
() => { break 'x; }
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
macro_rules! foo {
($e: expr) => { 'x: for _ in range(0,1) { $e } }
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
fn macros() {
macro_rules! foo{
($p:pat, $e:expr, $b:block) => {{
// error-pattern: unresolved name
-#![feature(globs)]
-
use module_of_many_things::*;
mod module_of_many_things {
// error-pattern: unresolved
-#![feature(globs)]
-
mod circ1 {
pub use circ2::f2;
pub fn f1() { println!("f1"); }
// Test that import shadowing using globs causes errors
#![no_implicit_prelude]
-#![feature(globs)]
use foo::*;
use bar::*; //~ERROR a type named `Baz` has already been imported in this module
// Test that import shadowing using globs causes errors
#![no_implicit_prelude]
-#![feature(globs)]
use foo::*;
use foo::*; //~ERROR a type named `Baz` has already been imported in this module
// Test that import shadowing using globs causes errors
#![no_implicit_prelude]
-#![feature(globs)]
use foo::Baz;
use bar::*; //~ERROR a type named `Baz` has already been imported in this module
// Test that import shadowing using globs causes errors
#![no_implicit_prelude]
-#![feature(globs)]
use foo::*;
use bar::Baz; //~ERROR a type named `Baz` has already been imported in this module
// Test that import shadowing using globs causes errors
#![no_implicit_prelude]
-#![feature(globs)]
use foo::Baz;
use bar::Baz; //~ERROR a type named `Baz` has already been imported in this module
// Test that import shadowing using globs causes errors
#![no_implicit_prelude]
-#![feature(globs)]
use qux::*;
use foo::*; //~ERROR a type named `Baz` has already been imported in this module
// Test that import shadowing using globs causes errors
#![no_implicit_prelude]
-#![feature(globs)]
use foo::*;
use qux::*; //~ERROR a type named `Baz` has already been imported in this module
// error-pattern: reached the recursion limit while auto-dereferencing
-#![feature(associated_types)]
-
use std::ops::Deref;
struct Foo;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
-macro_rules! recursive(
- () => (
- recursive!() //~ ERROR recursion limit reached while expanding the macro `recursive`
- )
- );
+macro_rules! recursive {
+ () => (recursive!()) //~ ERROR recursion limit reached while expanding the macro `recursive`
+}
fn main() {
recursive!()
// error-pattern:
-#![feature(macro_rules)]
-
macro_rules! foo{
() => {{
macro_rules! bar{() => (())}
// ignore-test
-#![feature(macro_rules)]
-
-macro_rules! f(() => (n))
+macro_rules! f { () => (n) }
fn main() -> (){
for n in range(0i, 1) {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
macro_rules! prob1 {
(0) => {
0
// Testing that we don't fail abnormally after hitting the errors
-#![feature(globs)]
-
use unresolved::*; //~ ERROR unresolved import `unresolved::*`. Maybe a missing `extern crate unres
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.
+
+struct Baz<U> where U: Eq(U); //This is parsed as the new Fn* style parenthesis syntax.
+struct Baz<U> where U: Eq(U) -> R; // Notice this parses as well.
+struct Baz<U>(U) where U: Eq; // This rightfully signals no error as well.
+struct Foo<T> where T: Copy, (T); //~ ERROR unexpected token in `where` clause
+struct Bar<T> { x: T } where T: Copy //~ ERROR expected item, found `where`
+
+fn main() {}
// except according to those terms.
#![feature(unboxed_closures)]
-#![feature(associated_types)]
use std::any::Any;
use std::intrinsics::TypeId;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
use std::ops::Deref;
struct MyPtr<'a>(&'a mut uint);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
fn add_state(op: <int as HasState>::State) {
//~^ ERROR the trait `HasState` is not implemented for the type `int`
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
trait Foo {
type Item;
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-pub trait Foo for Sized? { fn foo<T>(&self, ext_thing: &T); }
-pub trait Bar for Sized?: Foo { }
+pub trait Foo { fn foo<T>(&self, ext_thing: &T); }
+pub trait Bar: Foo { }
impl<T: Foo> Bar for T { }
pub struct Thing;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
trait From<Src> {
type Output;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
trait From<Src> {
type Result;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(globs)]
-
// ensures that 'use foo:*' doesn't import non-public item
use m1::*;
fn main() {
foo(); //~ ERROR: unresolved name
}
-
// ensures that 'use foo:*' doesn't import non-public 'use' statements in the
// module 'foo'
-#![feature(globs)]
-
use m1::*;
mod foo {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
// error-pattern: unexpected token
-macro_rules! e(
+macro_rules! e {
($inp:ident) => (
$nonexistent
);
-);
+}
fn main() {
e!(foo);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(globs)]
-
use self::*; //~ ERROR: unresolved import
fn main() {
}
-
// When denying at the crate level, be sure to not get random warnings from the
// injected intrinsics by the compiler.
-#![feature(globs)]
#![deny(missing_docs)]
#![allow(dead_code)]
#![allow(missing_copy_implementations)]
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(dead_code)]
+#![deny(raw_pointer_derive)]
+
+#[derive(Clone)]
+struct Foo {
+ x: *const int //~ ERROR use of `#[derive]` with a raw pointer
+}
+
+#[derive(Clone)]
+struct Bar(*mut int); //~ ERROR use of `#[derive]` with a raw pointer
+
+#[derive(Clone)]
+enum Baz {
+ A(*const int), //~ ERROR use of `#[derive]` with a raw pointer
+ B { x: *mut int } //~ ERROR use of `#[derive]` with a raw pointer
+}
+
+#[derive(Clone)]
+struct Buzz {
+ x: (*const int, //~ ERROR use of `#[derive]` with a raw pointer
+ *const uint) //~ ERROR use of `#[derive]` with a raw pointer
+}
+
+fn main() {}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![allow(dead_code)]
-#![deny(raw_pointer_deriving)]
-
-#[derive(Clone)]
-struct Foo {
- x: *const int //~ ERROR use of `#[derive]` with a raw pointer
-}
-
-#[derive(Clone)]
-struct Bar(*mut int); //~ ERROR use of `#[derive]` with a raw pointer
-
-#[derive(Clone)]
-enum Baz {
- A(*const int), //~ ERROR use of `#[derive]` with a raw pointer
- B { x: *mut int } //~ ERROR use of `#[derive]` with a raw pointer
-}
-
-#[derive(Clone)]
-struct Buzz {
- x: (*const int, //~ ERROR use of `#[derive]` with a raw pointer
- *const uint) //~ ERROR use of `#[derive]` with a raw pointer
-}
-
-fn main() {}
// aux-build:stability_cfg1.rs
// aux-build:stability_cfg2.rs
-#![feature(globs, phase)]
#![deny(unstable)]
#![deny(deprecated)]
#![deny(experimental)]
#![allow(dead_code)]
+#[macro_use]
+extern crate lint_stability; //~ ERROR: use of unmarked item
+
mod cross_crate {
extern crate stability_cfg1;
extern crate stability_cfg2; //~ ERROR: use of experimental item
- #[phase(plugin, link)]
- extern crate lint_stability; //~ ERROR: use of unmarked item
- use self::lint_stability::*;
+ use lint_stability::*;
fn test() {
let foo = MethodTester;
#![allow(unused_unsafe)]
#![allow(dead_code)]
#![deny(unsafe_blocks)]
-#![feature(macro_rules)]
-
unsafe fn allowed() {}
#[allow(unsafe_blocks)] fn also_allowed() { unsafe {} }
// aux-build:lint-unused-extern-crate.rs
-#![feature(globs)]
#![deny(unused_extern_crates)]
#![allow(unused_variables)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(globs)]
#![deny(unused_imports)]
#![allow(dead_code)]
//
// regression test for #8005
-#![feature(macro_rules)]
-
-macro_rules! test ( () => { fn foo() -> int { 1i; } } );
+macro_rules! test { () => { fn foo() -> int { 1i; } } }
//~^ ERROR not all control paths return a value
//~^^ HELP consider removing this semicolon
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:macro_crate_nonterminal.rs
+// ignore-stage1
+
+mod foo {
+ #[macro_use]
+ extern crate macro_crate_nonterminal; //~ ERROR must be at the crate root
+}
+
+fn main() {
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
macro_rules! ignored_item {
() => {
fn foo() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
-macro_rules! test ( ($nm:ident,
+macro_rules! test { ($nm:ident,
#[$a:meta],
- $i:item) => (mod $nm { #![$a] $i }); );
+ $i:item) => (mod $nm { #![$a] $i }); }
test!(a,
#[cfg(qux)],
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn macro() { //~ ERROR `macro` is a reserved keyword
+}
+
+pub fn main() {
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
-macro_rules! test ( ($a, $b) => (()); ); //~ ERROR Cannot transcribe
+macro_rules! test { ($a, $b) => (()); } //~ ERROR Cannot transcribe
fn main() {
test!()
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:macro_reexport_1.rs
+// aux-build:macro_non_reexport_2.rs
+// ignore-stage1
+
+#[macro_use] #[no_link]
+extern crate macro_non_reexport_2;
+
+fn main() {
+ assert_eq!(reexported!(), 3u); //~ ERROR macro undefined
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
-macro_rules! test ( ($nm:ident,
+macro_rules! test { ($nm:ident,
#[$a:meta],
- $i:item) => (mod $nm { #[$a] $i }); );
+ $i:item) => (mod $nm { #[$a] $i }); }
test!(a,
#[cfg(qux)],
--- /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.
+
+#[macro_reexport] //~ ERROR bad macro reexport
+extern crate std;
+
+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.
+
+#[macro_reexport="foo"] //~ ERROR bad macro reexport
+extern crate std;
+
+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.
+
+#[macro_reexport(foo="bar")] //~ ERROR bad macro reexport
+extern crate std;
+
+fn main() { }
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:macro_reexport_1.rs
+// ignore-stage1
+
+#[macro_reexport(reexported)]
+#[no_link]
+extern crate macro_reexport_1;
+
+fn main() {
+ assert_eq!(reexported!(), 3u); //~ ERROR macro undefined
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[macro_use(foo(bar))] //~ ERROR bad macro import
+extern crate std;
+
+fn main() {
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[macro_use(foo="bar")] //~ ERROR bad macro import
+extern crate std;
+
+fn main() {
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:two_macros.rs
+// ignore-stage1
+
+#[macro_use(macro_one)]
+extern crate two_macros;
+
+pub fn main() {
+ macro_two!(); //~ ERROR macro undefined
+}
fn main() {
assert!(1 == 2)
- assert!(3 == 4) //~ ERROR expected one of `.`, `;`, or `}`, found `assert`
+ assert!(3 == 4) //~ ERROR expected one of `.`, `;`, `}`, or an operator, found `assert`
println!("hello");
}
// forbid-output: in expansion of
-#![feature(macro_rules)]
-
-macro_rules! make_method ( ($name:ident) => (
- fn $name(&self) { }
-));
+macro_rules! make_method {
+ ($name:ident) => ( fn $name(&self) { } )
+}
struct S;
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:two_macros.rs
+// ignore-stage1
+
+extern crate two_macros;
+
+pub fn main() {
+ macro_two!(); //~ ERROR macro undefined
+}
--- /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.
+
+#[macro_use(foo, bar)] //~ ERROR arguments to macro_use are not allowed here
+mod foo {
+}
+
+fn main() {
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[plugin]
+#[plugin] //~ ERROR #[plugin] specified multiple times
+extern crate std;
+
+fn main() {}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ let foo = &mut 1i;
+
+ let &mut x = foo;
+ x += 1; //~ ERROR re-assignment of immutable variable
+
+ // explicitly mut-ify internals
+ let &mut mut x = foo;
+ x += 1;
+
+ // check borrowing is detected successfully
+ let &mut ref x = foo;
+ *foo += 1; //~ ERROR cannot assign to `*foo` because it is borrowed
+}
--- /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 main() {
+ let foo = &mut 1i;
+
+ // (separate lines to ensure the spans are accurate)
+
+ // SNAP b2085d9 uncomment this after the next snapshot
+ // NOTE(stage0) just in case tidy doesn't check snap's in tests
+ // let &_ // ~ ERROR expected `&mut int`, found `&_`
+ // = foo;
+ let &mut _ = foo;
+
+ let bar = &1i;
+ let &_ = bar;
+ let &mut _ //~ ERROR expected `&int`, found `&mut _`
+ = bar;
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(globs)]
-
// error-pattern:declaration of `None` shadows
use std::option::*;
// except according to those terms.
// aux-build:namespaced_enums.rs
-#![feature(globs)]
-
extern crate namespaced_enums;
mod m {
bar(); //~ ERROR unresolved name `bar`
m::bar(); //~ ERROR unresolved name `m::bar`
}
-
// <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(globs)]
mod m2 {
pub enum Foo {
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[no_link]
+extern crate libc;
+
+fn main() {
+ unsafe {
+ libc::abs(0); //~ ERROR Use of undeclared type or module `libc`
+ //~^ ERROR unresolved name `libc::abs`
+ }
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that we generate obsolete syntax errors around usages of `for Sized?`
+
+trait Foo for Sized? {} //~ ERROR obsolete syntax: for Sized?
+
+trait Bar for ?Sized {} //~ ERROR obsolete syntax: for Sized?
+
+fn main() { }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
-macro_rules! foo ( () => ( x ) );
+macro_rules! foo { () => ( x ) }
fn main() {
let foo!() = 2;
// Check we do the correct privacy checks when we import a name and there is an
// item with that name in both the value and type namespaces.
-#![feature(globs)]
#![allow(dead_code)]
#![allow(unused_imports)]
fn main() {
}
-
// Check we do the correct privacy checks when we import a name and there is an
// item with that name in both the value and type namespaces.
-#![feature(globs)]
#![allow(dead_code)]
#![allow(unused_imports)]
fn main() {
}
-
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(globs, lang_items)]
+#![feature(lang_items)]
#![no_std] // makes debugging this test *a lot* easier (during resolve)
#[lang="sized"]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(globs)]
#![no_std] // makes debugging this test *a lot* easier (during resolve)
// Test to make sure that globs don't leak in regular `use` statements.
}
#[start] fn main(_: int, _: *const *const u8) -> int { 3 }
-
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(globs)]
#![no_std] // makes debugging this test *a lot* easier (during resolve)
// Test to make sure that private items imported through globs remain private
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(globs, lang_items)]
+#![feature(lang_items)]
#![no_std] // makes debugging this test *a lot* easier (during resolve)
-#[lang = "sized"] pub trait Sized for Sized? {}
+#[lang = "sized"] pub trait Sized {}
#[lang="copy"] pub trait Copy {}
// Test to make sure that private items imported through globs remain private
// deeply nested types that will fail the `Send` check by overflow
// when the recursion limit is set very low.
-#![feature(macro_rules)]
#![allow(dead_code)]
#![recursion_limit="10"]
--- /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 X {}
+
+trait Iter {
+ type Item: X;
+
+ fn into_item(self) -> Self::Item;
+ fn as_item(&self) -> &Self::Item;
+}
+
+fn bad1<T: Iter>(v: T) -> Box<X+'static>
+{
+ let item = v.into_item();
+ box item //~ ERROR associated type `<T as Iter>::Item` may not live long enough
+}
+
+fn bad2<T: Iter>(v: T) -> Box<X+'static>
+ where Box<T::Item> : X
+{
+ let item = box v.into_item();
+ box item //~ ERROR associated type `<T as Iter>::Item` may not live long enough
+}
+
+fn bad3<'a, T: Iter>(v: T) -> Box<X+'a>
+{
+ let item = v.into_item();
+ box item //~ ERROR associated type `<T as Iter>::Item` may not live long enough
+}
+
+fn bad4<'a, T: Iter>(v: T) -> Box<X+'a>
+ where Box<T::Item> : X
+{
+ let item = box v.into_item();
+ box item //~ ERROR associated type `<T as Iter>::Item` may not live long enough
+}
+
+fn ok1<'a, T: Iter>(v: T) -> Box<X+'a>
+ where T::Item : 'a
+{
+ let item = v.into_item();
+ box item // OK, T::Item : 'a is declared
+}
+
+fn ok2<'a, T: Iter>(v: &T, w: &'a T::Item) -> Box<X+'a>
+ where T::Item : Clone
+{
+ let item = Clone::clone(w);
+ box item // OK, T::Item : 'a is implied
+}
+
+fn ok3<'a, T: Iter>(v: &'a T) -> Box<X+'a>
+ where T::Item : Clone + 'a
+{
+ let item = Clone::clone(v.as_item());
+ box item // OK, T::Item : 'a was declared
+}
+
+fn meh1<'a, T: Iter>(v: &'a T) -> Box<X+'a>
+ where T::Item : Clone
+{
+ // This case is kind of interesting. It's the same as `ok3` but
+ // without the explicit declaration. In principle, it seems like
+ // we ought to be able to infer that `T::Item : 'a` because we
+ // invoked `v.as_self()` which yielded a value of type `&'a
+ // T::Item`. But we're not that smart at present.
+
+ let item = Clone::clone(v.as_item());
+ box item //~ ERROR associated type `<T as Iter>::Item` may not live
+}
+
+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.
+
+
+trait X {}
+
+fn p1<T>(v: T) -> Box<X+'static>
+ where T : X
+{
+ box v //~ ERROR parameter type `T` may not live long enough
+}
+
+fn p2<T>(v: Box<T>) -> Box<X+'static>
+ where Box<T> : X
+{
+ box v //~ ERROR parameter type `T` may not live long enough
+}
+
+fn p3<'a,T>(v: T) -> Box<X+'a>
+ where T : X
+{
+ box v //~ ERROR parameter type `T` may not live long enough
+}
+
+fn p4<'a,T>(v: Box<T>) -> Box<X+'a>
+ where Box<T> : X
+{
+ box v //~ ERROR parameter type `T` may not live long enough
+}
+
+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 assert_send<T: Send>(_t: T) {}
+
+fn main() {
+ let line = String::new();
+ match [line.as_slice()] { //~ ERROR `line` does not live long enough
+ [ word ] => { assert_send(word); }
+ }
+}
--- /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 main() {
+ let a0 = 0u8;
+ let f = 1u8;
+ let mut a1 = &a0;
+ match (&a1,) {
+ (&ref b0,) => {
+ a1 = &f; //~ ERROR cannot assign
+ }
+ }
+}
#![feature(lang_items)]
#![no_std]
-#[lang="sized"] pub trait Sized for Sized? {}
+#[lang="sized"] pub trait Sized {}
// error-pattern:requires `start` lang_item
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
struct StateMachineIter<'a> {
statefn: &'a StateMachineFunc<'a>
}
println!("{}",it.next());
println!("{}",it.next());
}
-
// Issue #8380
-#![feature(globs)]
use std::sync::atomic::*;
use std::ptr;
// aux-build:svh-b.rs
// aux-build:svh-a-change-lit.rs
-#![feature(macro_rules)]
-
extern crate a;
extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
//~^ NOTE: perhaps this crate needs to be recompiled
// aux-build:svh-b.rs
// aux-build:svh-a-change-significant-cfg.rs
-#![feature(macro_rules)]
-
extern crate a;
extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
//~^ NOTE: perhaps this crate needs to be recompiled
// aux-build:svh-b.rs
// aux-build:svh-a-change-trait-bound.rs
-#![feature(macro_rules)]
-
extern crate a;
extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
//~^ NOTE: perhaps this crate needs to be recompiled
// aux-build:svh-b.rs
// aux-build:svh-a-change-type-arg.rs
-#![feature(macro_rules)]
-
extern crate a;
extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
//~^ NOTE: perhaps this crate needs to be recompiled
// aux-build:svh-b.rs
// aux-build:svh-a-change-type-ret.rs
-#![feature(macro_rules)]
-
extern crate a;
extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
//~^ NOTE: perhaps this crate needs to be recompiled
// aux-build:svh-b.rs
// aux-build:svh-a-change-type-static.rs
-#![feature(macro_rules)]
-
extern crate a;
extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
//~^ NOTE: perhaps this crate needs to be recompiled
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules, trace_macros)]
+#![feature(trace_macros)]
fn main() {
trace_macros!(); //~ ERROR trace_macros! accepts only `true` or `false`
use std::mem::transmute;
-fn a<T, Sized? U>(x: &[T]) -> &U {
+fn a<T, U: ?Sized>(x: &[T]) -> &U {
unsafe { transmute(x) } //~ ERROR transmute called on types with potentially different sizes
}
-fn b<Sized? T, Sized? U>(x: &T) -> &U {
+fn b<T: ?Sized, U: ?Sized>(x: &T) -> &U {
unsafe { transmute(x) } //~ ERROR transmute called on types with potentially different sizes
}
unsafe { transmute(x) }
}
-fn e<Sized? T, U>(x: &T) -> &U {
+fn e<T: ?Sized, U>(x: &T) -> &U {
unsafe { transmute(x) } //~ ERROR transmute called on types with potentially different sizes
}
-fn f<T, Sized? U>(x: &T) -> &U {
+fn f<T, U: ?Sized>(x: &T) -> &U {
unsafe { transmute(x) } //~ ERROR transmute called on types with potentially different sizes
}
use std::mem::transmute;
-struct Foo<Sized? T> {
+struct Foo<T: ?Sized> {
t: Box<T>
}
-impl<Sized? T> Foo<T> {
+impl<T: ?Sized> Foo<T> {
fn m(x: &T) -> &int where T : Sized {
// OK here, because T : Sized is in scope.
unsafe { transmute(x) }
// Test interaction between unboxed closure sugar and default type
// parameters (should be exactly as if angle brackets were used).
-#![feature(default_type_params, unboxed_closures)]
+#![feature(unboxed_closures)]
#![allow(dead_code)]
trait Foo<T,U,V=T> {
fn dummy(&self, t: T, u: U, v: V);
}
-trait Eq<Sized? X> for Sized? { }
-impl<Sized? X> Eq<X> for X { }
-fn eq<Sized? A,Sized? B>() where A : Eq<B> { }
+trait Eq<X: ?Sized> { }
+impl<X: ?Sized> Eq<X> for X { }
+fn eq<A: ?Sized,B: ?Sized>() where A : Eq<B> { }
fn test<'a,'b>() {
// Parens are equivalent to omitting default in angle.
fn dummy(&self, t: T, u: U);
}
-trait Eq<Sized? X> for Sized? { }
-impl<Sized? X> Eq<X> for X { }
-fn eq<Sized? A,Sized? B:Eq<A>>() { }
+trait Eq<X: ?Sized> { }
+impl<X: ?Sized> Eq<X> for X { }
+fn eq<A: ?Sized,B: ?Sized +Eq<A>>() { }
fn test<'a,'b>() {
// No errors expected:
fn dummy(&self, t: T, u: U);
}
-trait Eq<Sized? X> for Sized? { }
-impl<Sized? X> Eq<X> for X { }
-fn eq<Sized? A,Sized? B:Eq<A>>() { }
+trait Eq<X: ?Sized> { }
+impl<X: ?Sized> Eq<X> for X { }
+fn eq<A: ?Sized,B: ?Sized +Eq<A>>() { }
fn main() {
eq::< for<'a> Foo<(&'a int,), &'a int>,
// parameters (should be exactly as if angle brackets were used
// and regions omitted).
-#![feature(default_type_params, unboxed_closures)]
+#![feature(unboxed_closures)]
#![allow(dead_code)]
use std::kinds::marker;
fn dummy(&'a self) -> &'a (T,U);
}
-trait Eq<Sized? X> for Sized? { }
-impl<Sized? X> Eq<X> for X { }
-fn eq<Sized? A,Sized? B:Eq<A>>() { }
+trait Eq<X: ?Sized> { }
+impl<X: ?Sized> Eq<X> for X { }
+fn eq<A: ?Sized,B: ?Sized +Eq<A>>() { }
fn same_type<A,B:Eq<A>>(a: A, b: B) { }
// except according to those terms.
fn bar<T: Sized>() { }
-fn foo<Sized? T>() { bar::<T>() } //~ ERROR the trait `core::kinds::Sized` is not implemented
+fn foo<T: ?Sized>() { bar::<T>() } //~ ERROR the trait `core::kinds::Sized` is not implemented
fn main() { }
fn is_sized<T:Sized>() { }
-fn not_sized<Sized? T>() { }
+fn not_sized<T: ?Sized>() { }
enum Foo<U> { FooSome(U), FooNone }
fn foo1<T>() { not_sized::<Foo<T>>() } // Hunky dory.
-fn foo2<Sized? T>() { not_sized::<Foo<T>>() }
+fn foo2<T: ?Sized>() { not_sized::<Foo<T>>() }
//~^ ERROR the trait `core::kinds::Sized` is not implemented
//
// Not OK: `T` is not sized.
-enum Bar<Sized? U> { BarSome(U), BarNone }
-fn bar1<Sized? T>() { not_sized::<Bar<T>>() }
-fn bar2<Sized? T>() { is_sized::<Bar<T>>() }
+enum Bar<U: ?Sized> { BarSome(U), BarNone }
+fn bar1<T: ?Sized>() { not_sized::<Bar<T>>() }
+fn bar2<T: ?Sized>() { is_sized::<Bar<T>>() }
//~^ ERROR the trait `core::kinds::Sized` is not implemented
//
// Not OK: `Bar<T>` is not sized, but it should be.
struct S5<Y>;
-impl<Sized? X> S5<X> { //~ ERROR not implemented
+impl<X: ?Sized> S5<X> { //~ ERROR not implemented
}
fn main() { }
fn is_sized<T:Sized>() { }
-fn not_sized<Sized? T>() { }
+fn not_sized<T: ?Sized>() { }
struct Foo<T> { data: T }
fn foo1<T>() { not_sized::<Foo<T>>() } // Hunky dory.
-fn foo2<Sized? T>() { not_sized::<Foo<T>>() }
+fn foo2<T: ?Sized>() { not_sized::<Foo<T>>() }
//~^ ERROR the trait `core::kinds::Sized` is not implemented
//
// Not OK: `T` is not sized.
-struct Bar<Sized? T> { data: T }
-fn bar1<Sized? T>() { not_sized::<Bar<T>>() }
-fn bar2<Sized? T>() { is_sized::<Bar<T>>() }
+struct Bar<T: ?Sized> { data: T }
+fn bar1<T: ?Sized>() { not_sized::<Bar<T>>() }
+fn bar2<T: ?Sized>() { is_sized::<Bar<T>>() }
//~^ ERROR the trait `core::kinds::Sized` is not implemented
//
// Not OK: `Bar<T>` is not sized, but it should be.
// Test sized-ness checking in substitution in impls.
// impl - struct
-trait T3<Sized? Z> {
+trait T3<Z: ?Sized> {
}
struct S5<Y>;
-impl<Sized? X> T3<X> for S5<X> { //~ ERROR not implemented
+impl<X: ?Sized> T3<X> for S5<X> { //~ ERROR not implemented
}
fn main() { }
// impl - unbounded
trait T2<Z> {
}
-struct S4<Sized? Y>;
-impl<Sized? X> T2<X> for S4<X> {
+struct S4<Y: ?Sized>;
+impl<X: ?Sized> T2<X> for S4<X> {
//~^ ERROR `core::kinds::Sized` is not implemented for the type `X`
}
// Test syntax checks for `type` keyword.
-struct S1 for type; //~ ERROR expected `{`, `(`, or `;` after struct name, found `for`
+struct S1 for type; //~ ERROR expected `where`, `{`, `(`, or `;` after struct name, found `for`
pub fn main() {
}
// Unbounded.
-fn f1<Sized? X>(x: &X) {
+fn f1<X: ?Sized>(x: &X) {
f2::<X>(x);
//~^ ERROR the trait `core::kinds::Sized` is not implemented
}
}
// Bounded.
-trait T for Sized? {}
-fn f3<Sized? X: T>(x: &X) {
+trait T {}
+fn f3<X: ?Sized + T>(x: &X) {
f4::<X>(x);
//~^ ERROR the trait `core::kinds::Sized` is not implemented
}
}
// Test with unsized enum.
-enum E<Sized? X> {
+enum E<X: ?Sized> {
V(X),
}
fn f5<Y>(x: &Y) {}
-fn f6<Sized? X>(x: &X) {}
-fn f7<Sized? X>(x1: &E<X>, x2: &E<X>) {
+fn f6<X: ?Sized>(x: &X) {}
+fn f7<X: ?Sized>(x1: &E<X>, x2: &E<X>) {
f5(x1);
//~^ ERROR the trait `core::kinds::Sized` is not implemented
f6(x2); // ok
// Test with unsized struct.
-struct S<Sized? X> {
+struct S<X: ?Sized> {
x: X,
}
-fn f8<Sized? X>(x1: &S<X>, x2: &S<X>) {
+fn f8<X: ?Sized>(x1: &S<X>, x2: &S<X>) {
f5(x1);
//~^ ERROR the trait `core::kinds::Sized` is not implemented
f6(x2); // ok
}
// Test some tuples.
-fn f9<Sized? X>(x1: Box<S<X>>, x2: Box<E<X>>) {
+fn f9<X: ?Sized>(x1: Box<S<X>>, x2: Box<E<X>>) {
f5(&(*x1, 34i));
//~^ ERROR the trait `core::kinds::Sized` is not implemented
}
-fn f10<Sized? X>(x1: Box<S<X>>, x2: Box<E<X>>) {
+fn f10<X: ?Sized>(x1: Box<S<X>>, x2: Box<E<X>>) {
f5(&(32i, *x2));
//~^ ERROR the trait `core::kinds::Sized` is not implemented
}
// Test that bounds are sized-compatible.
trait T : Sized {}
-fn f<Sized? Y: T>() {
+fn f<Y: ?Sized + T>() {
//~^ERROR incompatible bounds on `Y`, bound `T` does not allow unsized type
}
// Test `Sized?` types not allowed in fields (except the last one).
-struct S1<Sized? X> {
+struct S1<X: ?Sized> {
f1: X, //~ ERROR `core::kinds::Sized` is not implemented
f2: int,
}
-struct S2<Sized? X> {
+struct S2<X: ?Sized> {
f: int,
g: X, //~ ERROR `core::kinds::Sized` is not implemented
h: int,
f: str, //~ ERROR `core::kinds::Sized` is not implemented
g: uint
}
-enum E<Sized? X> {
+enum E<X: ?Sized> {
V1(X, int), //~ERROR `core::kinds::Sized` is not implemented
}
-enum F<Sized? X> {
+enum F<X: ?Sized> {
V2{f1: X, f: int}, //~ERROR `core::kinds::Sized` is not implemented
}
// Test `Sized?` local variables.
-trait T for Sized? {}
+trait T {}
-fn f1<Sized? X>(x: &X) {
+fn f1<X: ?Sized>(x: &X) {
let _: X; // <-- this is OK, no bindings created, no initializer.
let _: (int, (X, int)); // same
let y: X; //~ERROR the trait `core::kinds::Sized` is not implemented
let y: (int, (X, int)); //~ERROR the trait `core::kinds::Sized` is not implemented
}
-fn f2<Sized? X: T>(x: &X) {
+fn f2<X: ?Sized + T>(x: &X) {
let y: X; //~ERROR the trait `core::kinds::Sized` is not implemented
let y: (int, (X, int)); //~ERROR the trait `core::kinds::Sized` is not implemented
}
-fn f3<Sized? X>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
+fn f3<X: ?Sized>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
let y: X = *x1; //~ERROR the trait `core::kinds::Sized` is not implemented
let y = *x2; //~ERROR the trait `core::kinds::Sized` is not implemented
let (y, z) = (*x3, 4i); //~ERROR the trait `core::kinds::Sized` is not implemented
}
-fn f4<Sized? X: T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
+fn f4<X: ?Sized + T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
let y: X = *x1; //~ERROR the trait `core::kinds::Sized` is not implemented
let y = *x2; //~ERROR the trait `core::kinds::Sized` is not implemented
let (y, z) = (*x3, 4i); //~ERROR the trait `core::kinds::Sized` is not implemented
}
-fn g1<Sized? X>(x: X) {} //~ERROR the trait `core::kinds::Sized` is not implemented
-fn g2<Sized? X: T>(x: X) {} //~ERROR the trait `core::kinds::Sized` is not implemented
+fn g1<X: ?Sized>(x: X) {} //~ERROR the trait `core::kinds::Sized` is not implemented
+fn g2<X: ?Sized + T>(x: X) {} //~ERROR the trait `core::kinds::Sized` is not implemented
pub fn main() {
}
// Test sized-ness checking in substitution in impls.
-trait T for Sized? {}
+trait T {}
// I would like these to fail eventually.
// impl - bounded
trait T1<Z: T> {
}
-struct S3<Sized? Y>;
-impl<Sized? X: T> T1<X> for S3<X> {
+struct S3<Y: ?Sized>;
+impl<X: ?Sized + T> T1<X> for S3<X> {
//~^ ERROR `core::kinds::Sized` is not implemented for the type `X`
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
fn macros() {
macro_rules! foo{
($p:pat, $e:expr, $b:block) => {{
// (In this case the mul method should take &f64 and not f64)
// See: #11450
-#![feature(associated_types, default_type_params)]
-
use std::ops::Mul;
struct Vec1 {
// lldb-command:continue
-#![feature(macro_rules)]
#![omit_gdb_pretty_printer_section]
macro_rules! trivial {
-#![feature(phase)]
#![no_std]
#![feature(globs)]
-#[phase(plugin, link)]
+#[macro_use]
extern crate "std" as std;
#[prelude_import]
use std::prelude::v1::*;
// Expanded pretty printing causes resolve conflicts.
// error-pattern:panic works
-#![feature(globs)]
use std::*;
// error-pattern:whatever
-#![feature(phase)]
-#[phase(plugin, link)] extern crate log;
+#[macro_use] extern crate log;
use std::os;
fn main() {
// error-pattern:whatever
-#![feature(phase)]
-#[phase(plugin, link)] extern crate log;
+#[macro_use] extern crate log;
use std::os;
use std::thread::Thread;
// error-pattern:whatever
-#![feature(phase)]
-#[phase(plugin, link)] extern crate log;
+#[macro_use] extern crate log;
use std::os;
fn main() {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(phase)]
-
-#[phase(plugin, link)]
+#[macro_use]
extern crate foo;
fn main() {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(phase)]
-
extern crate lib;
-#[phase(plugin, link)] extern crate log;
+#[macro_use] extern crate log;
fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
// minimal junk
#![no_std]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
// minimal junk
#![no_std]
// ignore-stage1
// ignore-android
// aux-build:issue_16723_multiple_items_syntax_ext.rs
-#![feature(phase)]
+#![feature(plugin)]
-#[phase(plugin)] extern crate issue_16723_multiple_items_syntax_ext;
+#[plugin] #[no_link] extern crate issue_16723_multiple_items_syntax_ext;
multiple_items!();
// ignore-stage1
// ignore-pretty
-#![feature(phase)]
+#![feature(plugin)]
-#[phase(plugin)]
+#[plugin] #[no_link]
extern crate lint_group_plugin_test;
fn lintme() { } //~ WARNING item is named 'lintme'
// ignore-stage1
// compile-flags: -A test-lint
-#![feature(phase)]
+#![feature(plugin)]
-#[phase(plugin)]
+#[plugin] #[no_link]
extern crate lint_plugin_test;
fn lintme() { }
// ignore-stage1
// ignore-pretty
-#![feature(phase)]
+#![feature(plugin)]
-#[phase(plugin)]
+#[plugin] #[no_link]
extern crate lint_plugin_test;
fn lintme() { } //~ WARNING item is named 'lintme'
// Issue #15750: a macro that internally parses its input and then
// uses `quote_expr!` to rearrange it should be hygiene-preserving.
-#![feature(phase)]
+#![feature(plugin)]
-#[phase(plugin)]
+#[plugin] #[no_link]
extern crate macro_crate_test;
fn main() {
// aux-build:plugin_crate_outlive_expansion_phase.rs
// ignore-stage1
-#![feature(phase)]
+#![feature(plugin)]
-#[phase(plugin)]
+#[plugin] #[no_link]
extern crate plugin_crate_outlive_expansion_phase;
pub fn main() {}
// aux-build:macro_crate_test.rs
// ignore-stage1
-#![feature(phase)]
+#![feature(plugin)]
-#[phase(plugin)]
+#[macro_use] #[plugin] #[no_link]
extern crate macro_crate_test;
#[into_foo]
+++ /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
-// ignore-cross-compile
-//
-// macro_crate_test will not compile on a cross-compiled target because
-// libsyntax is not compiled for it.
-
-#![feature(phase)]
-
-#[phase(plugin, link)]
-extern crate macro_crate_test;
-
-fn main() {
- assert_eq!(1, make_a_1!());
- macro_crate_test::foo();
-}
--- /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
+// ignore-cross-compile
+//
+// macro_crate_test will not compile on a cross-compiled target because
+// libsyntax is not compiled for it.
+
+#![feature(plugin)]
+
+#[plugin]
+extern crate macro_crate_test;
+
+fn main() {
+ assert_eq!(1, make_a_1!());
+ macro_crate_test::foo();
+}
// aux-build:roman_numerals.rs
// ignore-stage1
-#![feature(phase)]
+#![feature(plugin)]
-#[phase(plugin)]
+#[plugin] #[no_link]
extern crate roman_numerals;
pub fn main() {
// aux-build:syntax-extension-with-dll-deps-2.rs
// ignore-stage1
-#![feature(phase)]
+#![feature(plugin)]
-#[phase(plugin)]
+#[plugin] #[no_link]
extern crate "syntax-extension-with-dll-deps-2" as extension;
fn main() {
trait Trait {}
impl Trait for Foo {}
-struct Fat<Sized? T> {
+struct Fat<T: ?Sized> {
f: T
}
}
}
-struct Fat<Sized? T> {
+struct Fat<T: ?Sized> {
f: T
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
trait Foo {
type T;
}
let y: int = 44;
assert_eq!(x * 2, y);
}
-
// Test equality constraints on associated types in a where clause.
-#![feature(associated_types)]
-
pub trait Foo {
type A;
fn boo(&self) -> <Self as Foo>::A;
// Test equality constraints on associated types in a where clause.
-#![feature(associated_types)]
-
pub trait ToInt {
fn to_int(&self) -> int;
}
// Test that we are able to reference cross-crate traits that employ
// associated types.
-#![feature(associated_types)]
-
extern crate "associated-types-cc-lib" as bar;
use bar::Bar;
// `Target=[A]`, then the impl marked with `(*)` is seen to conflict
// with all the others.
-#![feature(associated_types, default_type_params)]
-
use std::ops::Deref;
-pub trait MyEq<Sized? U=Self> for Sized? {
+pub trait MyEq<U: ?Sized=Self> {
fn eq(&self, u: &U) -> bool;
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
trait SignedUnsigned {
type Opposite;
fn convert(self) -> Self::Opposite;
let x = get(22);
assert_eq!(22u, x);
}
-
// Test equality constraints on associated types inside of an object type
-#![feature(associated_types)]
-
pub trait Foo {
type A;
fn boo(&self) -> <Self as Foo>::A;
// ignore-pretty -- FIXME(#17362)
-#![feature(associated_types, lang_items, unboxed_closures)]
+#![feature(lang_items, unboxed_closures)]
#![no_implicit_prelude]
use std::kinds::Sized;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
trait Get {
type Value;
fn get(&self) -> &<Self as Get>::Value;
};
assert_eq!(*s.grab(), 100);
}
-
-
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
trait Get {
type Value;
fn get(&self) -> &<Self as Get>::Value;
};
assert_eq!(*grab(&s), 100);
}
-
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
trait Get {
type Value;
fn get(&self) -> &<Self as Get>::Value;
};
assert_eq!(*s.grab(), 100);
}
-
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
trait Get {
type Value;
fn get(&self) -> &<Self as Get>::Value;
};
assert_eq!(*Struct::grab(&s), 100);
}
-
// Test that we are able to have an impl that defines an associated type
// before the actual trait.
-#![feature(associated_types)]
impl X for f64 { type Y = int; }
trait X {type Y; }
fn main() {}
// Test that we normalize associated types that appear in bounds; if
// we didn't, the call to `self.split2()` fails to type check.
-#![feature(associated_types)]
-
struct Splits<'a, T, P>;
struct SplitsN<I>;
-trait SliceExt2 for Sized? {
+trait SliceExt2 {
type Item;
fn split2<'a, P>(&'a self, pred: P) -> Splits<'a, Self::Item, P>
// Test that we normalize associated types that appear in bounds; if
// we didn't, the call to `self.split2()` fails to type check.
-#![feature(associated_types)]
-
struct Splits<'a, T, P>;
struct SplitsN<I>;
-trait SliceExt2 for Sized? {
+trait SliceExt2 {
type Item;
fn split2<'a, P>(&'a self, pred: P) -> Splits<'a, Self::Item, P>
// this case, the `Result=Self` binding in the supertrait listing of
// `Int` was being ignored.
-#![feature(associated_types)]
-
trait Not {
type Result;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
trait Foo<T> {
type Bar;
fn get_bar() -> <Self as Foo<T>>::Bar;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
trait Get<T> {
fn get(&self) -> T;
}
// Test equality constraints on associated types in a where clause.
-#![feature(associated_types)]
-
pub trait Foo {
type A;
fn boo(&self) -> <Self as Foo>::A;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
trait Get {
type Value;
fn get(&self) -> &<Self as Get>::Value;
};
assert_eq!(*s.get(), 100);
}
-
// Test paths to associated types using the type-parameter-only sugar.
-#![feature(associated_types)]
-
pub trait Foo {
type A;
fn boo(&self) -> Self::A;
// ignore-pretty -- FIXME(#17362) pretty prints with `<<` which lexes wrong
-#![feature(associated_types, lang_items, unboxed_closures)]
+#![feature(lang_items, unboxed_closures)]
#![no_implicit_prelude]
use std::kinds::Sized;
// Check that we do not ICE when compiling this
// macro, which reuses the expression `$id`
-#![feature(macro_rules)]
-
struct Foo {
a: int
impl Foo {
fn elaborate_stm(&mut self, s: Box<Bar>) -> Box<Bar> {
- macro_rules! declare(
+ macro_rules! declare {
($id:expr, $rest:expr) => ({
self.check_id($id);
box Bar::Bar2($id, $rest)
})
- );
+ }
match s {
box Bar::Bar2(id, rest) => declare!(id, self.elaborate_stm(rest)),
_ => panic!()
extern crate libc;
-use std::c_str::ToCStr;
+use std::ffi::CString;
mod mlibc {
use libc::{c_char, c_long, c_longlong};
}
fn atol(s: String) -> int {
- s.as_slice().with_c_str(|x| unsafe { mlibc::atol(x) as int })
+ let c = CString::from_slice(s.as_bytes());
+ unsafe { mlibc::atol(c.as_ptr()) as int }
}
fn atoll(s: String) -> i64 {
- s.as_slice().with_c_str(|x| unsafe { mlibc::atoll(x) as i64 })
+ let c = CString::from_slice(s.as_bytes());
+ unsafe { mlibc::atoll(c.as_ptr()) as i64 }
}
pub fn main() {
// ignore-android (FIXME #11419)
// exec-env:RUST_LOG=info
-#![feature(phase)]
-
-#[phase(plugin, link)]
+#[macro_use]
extern crate log;
use log::{set_logger, Logger, LogRecord};
// check that cfg correctly chooses between the macro impls (see also
// cfg-macros-notfoo.rs)
-#![feature(macro_rules)]
-
#[cfg(foo)]
-#[macro_escape]
+#[macro_use]
mod foo {
macro_rules! bar {
() => { true }
}
#[cfg(not(foo))]
-#[macro_escape]
+#[macro_use]
mod foo {
macro_rules! bar {
() => { false }
// check that cfg correctly chooses between the macro impls (see also
// cfg-macros-foo.rs)
-#![feature(macro_rules)]
-
#[cfg(foo)]
-#[macro_escape]
+#[macro_use]
mod foo {
macro_rules! bar {
() => { true }
}
#[cfg(not(foo))]
-#[macro_escape]
+#[macro_use]
mod foo {
macro_rules! bar {
() => { false }
// Test that the lifetime of rvalues in for loops is extended
// to the for loop itself.
-#![feature(macro_rules)]
-
use std::ops::Drop;
static mut FLAGS: u64 = 0;
// statement or end of block, as appropriate given the temporary
// lifetime rules.
-#![feature(macro_rules)]
-
use std::ops::Drop;
static mut FLAGS: u64 = 0;
}
}
-macro_rules! end_of_block(
+macro_rules! end_of_block {
($pat:pat, $expr:expr) => (
{
println!("end_of_block({})", stringify!({let $pat = $expr;}));
check_flags(1);
}
)
-);
+}
-macro_rules! end_of_stmt(
+macro_rules! end_of_stmt {
($pat:pat, $expr:expr) => (
{
println!("end_of_stmt({})", stringify!($expr));
check_flags(0);
}
)
-);
+}
pub 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.
-
-// aux-build:coherence-lib.rs
-
-extern crate "coherence-lib" as lib;
-use lib::Remote1;
-
-pub struct BigInt;
-
-impl Remote1<BigInt> for int { }
-
-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.
-
-// aux-build:coherence-lib.rs
-
-extern crate "coherence-lib" as lib;
-use lib::Remote1;
-
-pub struct BigInt;
-
-impl Remote1<BigInt> for Vec<int> { }
-
-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.
+
+// aux-build:coherence-lib.rs
+
+extern crate "coherence-lib" as lib;
+use lib::Remote1;
+
+struct Foo<T>(T);
+
+impl<T,U> Remote1<U> for Foo<T> { }
+
+fn main() { }
// no-pretty-expanded
#![allow(unused_must_use, dead_code, deprecated)]
-#![feature(macro_rules)]
-
use std::io::MemWriter;
use std::fmt;
// compile-flags: --cfg ndebug
// exec-env:RUST_LOG=conditional-debug-macro-off=4
-#![feature(phase)]
-#[phase(plugin, link)]
+#[macro_use]
extern crate log;
pub fn main() {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
-macro_rules! assert_approx_eq(
+macro_rules! assert_approx_eq {
($a:expr, $b:expr) => ({
use std::num::Float;
let (a, b) = (&$a, &$b);
assert!((*a - *b).abs() < 1.0e-6,
"{} is not approximately equal to {}", *a, *b);
})
-);
+}
static A: int = -4 + 3;
static A2: uint = 3 + 3;
// General test that function items in static blocks
// can be generated with a macro.
-#![feature(macro_rules)]
-
struct MyType {
desc: &'static str,
data: uint,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
mod foo {
pub trait Value {
fn value(&self) -> uint;
// except according to those terms.
use std::{str, string};
-use std::c_str::ToCStr;
const A: [u8; 2] = ['h' as u8, 'i' as u8];
const B: &'static [u8; 2] = &A;
unsafe {
let foo = &A as *const u8;
assert_eq!(str::from_utf8_unchecked(&A), "hi");
- assert_eq!(String::from_raw_buf_len(foo, A.len()), "hi".to_string());
- assert_eq!(String::from_raw_buf_len(C, B.len()), "hi".to_string());
assert!(*C == A[0]);
assert!(*(&B[0] as *const u8) == A[0]);
-
- let bar = str::from_utf8_unchecked(&A).to_c_str();
- assert_eq!(bar.as_str(), "hi".to_c_str().as_str());
}
}
// memory, which makes for some *confusing* logs. That's why these are here
// instead of in std.
-#![feature(macro_rules)]
#![reexport_test_harness_main = "test_main"]
extern crate libc;
use std::sync::mpsc::channel;
use std::thread::Thread;
-macro_rules! succeed( ($e:expr) => (
+macro_rules! succeed { ($e:expr) => (
match $e { Ok(..) => {}, Err(e) => panic!("panic: {}", e) }
-) );
+) }
fn test_destroy_once() {
let mut p = sleeper();
--- /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 main() {
+ use ::std::mem;
+ mem::drop(2u);
+}
--- /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-pretty
+
+mod foo {
+ #![macro_escape] //~ WARNING macro_escape is a deprecated synonym for macro_use
+ //~^ HELP consider an outer attribute
+}
+
+fn main() {
+}
--- /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-pretty
+
+#[macro_escape] //~ WARNING macro_escape is a deprecated synonym for macro_use
+mod foo {
+}
+
+fn main() {
+}
+++ /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.
-
-#![feature(phase)]
-
-//~ WARNING phase(syntax) is a deprecated synonym for phase(plugin)
-#[phase(syntax, link)]
-extern crate log;
-
-fn main() {
- debug!("foo");
-}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
-macro_rules! define_vec (
+macro_rules! define_vec {
() => (
mod foo {
#[derive(PartialEq)]
pub struct bar;
}
)
-);
+}
define_vec!();
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
#[derive(Show)]
struct Unit;
// Test that a custom deref with a fat pointer return type does not ICE
-#![feature(associated_types)]
-
use std::ops::{Deref, DerefMut};
pub struct Arr {
// Test that a custom deref with a fat pointer return type does not ICE
-#![feature(associated_types)]
-
use std::ops::Deref;
pub struct Arr {
// Test that overloaded index expressions with DST result types
// work and don't ICE.
-#![feature(associated_types)]
-
use std::ops::Index;
use std::fmt::Show;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
macro_rules! check {
($m:ident, $t:ty, $v:expr) => {{
mod $m {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(default_type_params)]
-
#[derive(PartialEq)]
struct Bar;
struct Baz;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
use std::num::strconv::ExponentFormat::{ExpBin, ExpDec};
use std::num::strconv::SignificantDigits::DigMax;
use std::num::strconv::SignFormat::{SignAll, SignNeg};
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()); } });
+macro_rules! t {
+ ($a:expr, $b:expr) => { { let (r, _) = $a; assert_eq!(r, $b.to_string()); } }
+}
pub fn main() {
// Basic usage
-
// 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.
// Modified to not use export since it's going away. --pcw
-#![feature(globs)]
-
mod foo {
use foo::bar::*;
pub mod bar {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
use std::ops::{Deref, DerefMut};
// Generic unique/owned smaht pointer.
}
fn main() {}
-
// ignore-fast doesn't like extern crate
extern crate libc;
-use std::c_str::ToCStr;
+use std::ffi::CString;
mod mlibc {
use libc::{c_char, size_t};
fn strlen(str: String) -> uint {
// C string is terminated with a zero
- str.as_slice().with_c_str(|buf| {
- unsafe {
- mlibc::my_strlen(buf) as uint
- }
- })
+ let s = CString::from_slice(str.as_bytes());
+ unsafe {
+ mlibc::my_strlen(s.as_ptr()) as uint
+ }
}
pub fn main() {
// aux-build:default_type_params_xc.rs
-#![feature(default_type_params)]
-
extern crate default_type_params_xc;
struct Vec<T, A = default_type_params_xc::Heap>;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(default_type_params)]
-
struct Foo<A = (int, char)> {
a: A
}
// A test of the macro system. Can we do HTML literals?
-#![feature(macro_rules)]
-
/*
*/
use HTMLFragment::{tag, text};
-macro_rules! html (
+macro_rules! html {
( $($body:tt)* ) => (
parse_node!( []; []; $($body)* )
)
-);
+}
-macro_rules! parse_node (
+macro_rules! parse_node {
(
[:$head:ident ($(:$head_nodes:expr),*)
$(:$tags:ident ($(:$tag_nodes:expr),*))*];
);
( []; [:$e:expr]; ) => ( $e );
-);
+}
pub fn main() {
let _page = html! (
// ignore-pretty: pprust doesn't print hygiene output
-#![feature(macro_rules)]
-
macro_rules! loop_x {
($e: expr) => {
// $e shouldn't be able to interact with this 'x
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
macro_rules! loop_x {
($e: expr) => {
// $e shouldn't be able to interact with this 'x
// no-pretty-expanded unnecessary unsafe block generated
// ignore-lexer-test FIXME #15679
-#![feature(macro_rules)]
#![deny(warnings)]
#![allow(unused_must_use)]
}
}
-macro_rules! t(($a:expr, $b:expr) => { assert_eq!($a.as_slice(), $b) });
+macro_rules! t {
+ ($a:expr, $b:expr) => { assert_eq!($a.as_slice(), $b) }
+}
pub fn main() {
// Various edge cases without formats
-
// 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.
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(globs)]
-
use module_of_many_things::*;
use dug::too::greedily::and::too::deep::*;
-
// 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.
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(globs)]
#![allow(dead_assignment)]
use std::mem::*;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(globs)]
-
pub fn main() {
use std::mem::replace;
let mut x = 5i;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(globs, intrinsics)]
+#![feature(intrinsics)]
mod rusti {
extern "rust-intrinsic" {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(globs, macro_rules, intrinsics)]
+#![feature(intrinsics)]
-macro_rules! assert_approx_eq(
+macro_rules! assert_approx_eq {
($a:expr, $b:expr) => ({
use std::num::Float;
let (a, b) = (&$a, &$b);
assert!((*a - *b).abs() < 1.0e-6,
"{} is not approximately equal to {}", *a, *b);
})
-);
+}
mod rusti {
extern "rust-intrinsic" {
// when this bug was opened. The cases where the compiler
// panics before the fix have a comment.
-#![feature(default_type_params)]
-
use std::thunk::Thunk;
struct S {x:()}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
use std::slice;
pub struct PhfMapEntries<'a, T: 'a> {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
use std::ops::Deref;
struct Root {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(phase)]
-
-#[phase(plugin, link)] extern crate "std" as std2;
+#[macro_use] extern crate "std" as std2;
fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
trait Matcher {
fn next_match(&mut self) -> Option<(uint, uint)>;
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(default_type_params)]
-
pub type BigRat<T = int> = T;
fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(asm, macro_rules)]
+#![feature(asm)]
type History = Vec<&'static str>;
// ignore-pretty
-#![feature(macro_rules)]
-
-macro_rules! third(($e:expr)=>({let x = 2; $e[x]}));
+macro_rules! third {
+ ($e:expr) => ({let x = 2; $e[x]})
+}
fn main() {
let x = vec!(10u,11u,12u,13u);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
-macro_rules! inner (
- ($e:pat ) => ($e));
+macro_rules! inner {
+ ($e:pat ) => ($e)
+}
-macro_rules! outer (
- ($e:pat ) => (inner!($e)));
+macro_rules! outer {
+ ($e:pat ) => (inner!($e))
+}
fn main() {
let outer!(g1) = 13i;
// If `Index` used an associated type for its output, this test would
// work more smoothly.
-#![feature(associated_types, old_orphan_check)]
+#![feature(old_orphan_check)]
use std::ops::Index;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
trait MatrixRow {}
struct Mat;
// compile-flags:--test
// ignore-pretty turns out the pretty-printer doesn't handle gensym'd things...
-#![feature(globs)]
-
mod test {
use super::*;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types, unboxed_closures)]
+#![feature(unboxed_closures)]
use std::ops::{Deref, DerefMut};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
trait Person {
type string;
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(default_type_params, unboxed_closures)]
+#![feature(unboxed_closures)]
use std::thunk::Thunk;
--- /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<T> where T: Copy;
+struct Bar<T>(T) where T: Copy;
+struct Bleh<T, U>(T, U) where T: Copy, U: Sized;
+struct Baz<T> where T: Copy {
+ field: T
+}
+
+fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(default_type_params, unboxed_closures)]
+#![feature(unboxed_closures)]
use std::thunk::Thunk;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-pub trait Borrow<Sized? Borrowed> {
+pub trait Borrow<Borrowed: ?Sized> {
fn borrow(&self) -> &Borrowed;
}
// ignore-pretty -- FIXME(#17362) pretty prints as `Hash<<Self as Hasher...` which fails to parse
-#![feature(associated_types)]
-
pub trait Hasher {
type State;
// Test that a partially specified trait object with unspecified associated
// type does not ICE.
-#![feature(associated_types)]
-
trait Foo {
type A;
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
trait Trait<Input> {
type Output;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
trait Trait<Input> {
type Output;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
trait Base {}
trait AssocA {
type X: Base;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
trait PoolManager {
type C;
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
trait PoolManager {
type C;
}
// Test that `<Type as Trait>::Output` and `Self::Output` are accepted as type annotations in let
// bindings
-#![feature(associated_types)]
-
trait Int {
fn one() -> Self;
fn leading_zeros(self) -> uint;
// Check that associated types are `Sized`
-#![feature(associated_types)]
-
trait Trait {
type Output;
// aux-build:issue_20389.rs
-#![feature(associated_types)]
extern crate issue_20389;
struct Foo;
// aux-build:issue-2526.rs
-#![feature(globs)]
#![allow(unused_imports)]
extern crate issue_2526;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(default_type_params)]
-
use std::thread::Thread;
use std::sync::mpsc::Sender;
use std::thunk::Invoke;
// If `Mul` used an associated type for its output, this test would
// work more smoothly.
-#![feature(associated_types, default_type_params, old_orphan_check)]
+#![feature(old_orphan_check)]
use std::ops::Mul;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
-macro_rules! print_hd_tl (
+macro_rules! print_hd_tl {
($field_hd:ident, $($field_tl:ident),+) => ({
print!("{}", stringify!($field_hd));
print!("::[");
// FIXME: #9970
print!("{}", "]\n");
})
-);
+}
pub fn main() {
print_hd_tl!(x, y, z, w)
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
use std::default::Default;
pub struct X<T> {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
struct Element;
macro_rules! foo {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(globs)]
#![allow(unused_imports, dead_code)]
mod test1 {
// with different mutability in macro in two methods
#![allow(unused_variable)] // unused foobar_immut + foobar_mut
-#![feature(macro_rules)]
-
trait FooBar {}
struct Bar(i32);
struct Foo { bar: Bar }
fn get_mut(&mut self) -> &mut FooBar;
}
-macro_rules! generate_test(($type_:path, $slf:ident, $field:expr) => (
+macro_rules! generate_test { ($type_:path, $slf:ident, $field:expr) => (
impl Test for $type_ {
fn get_immut(&$slf) -> &FooBar {
&$field as &FooBar
&mut $field as &mut FooBar
}
}
-));
+)}
generate_test!(Foo, self, self.bar);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
-macro_rules! sty(
+macro_rules! sty {
($t:ty) => (stringify!($t))
-);
+}
-macro_rules! spath(
+macro_rules! spath {
($t:path) => (stringify!($t))
-);
+}
fn main() {
assert_eq!(sty!(int), "int");
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
// after fixing #9384 and implementing hygiene for match bindings,
// this now fails because the insertion of the 'y' into the match
// doesn't cause capture. Making this macro hygienic (as I've done)
B(uint)
}
-macro_rules! test(
+macro_rules! test {
($id:ident, $e:expr) => (
fn foo(t: T) -> int {
match t {
}
}
)
-);
+}
test!(y, 10 + (y as int));
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
-macro_rules! silly_macro(
+macro_rules! silly_macro {
() => (
pub mod Qux {
pub struct Foo { x : u8 }
pub fn bar(_foo : Foo) {}
}
);
-);
+}
silly_macro!();
// ignore-pretty
-#![feature(macro_rules)]
-
pub trait bomb { fn boom(&self, Ident); }
pub struct S;
pub struct Ident { name: uint }
-// macro_rules! int3( () => ( unsafe { asm!( "int3" ); } ) )
-macro_rules! int3( () => ( { } ) );
+// macro_rules! int3 { () => ( unsafe { asm!( "int3" ); } ) }
+macro_rules! int3 { () => ( { } ) }
fn Ident_new() -> Ident {
int3!();
// ignore-test #9737
-#![feature(macro_rules)]
-
-macro_rules! f((v: $x:expr) => ( println!("{}", $x) ))
+macro_rules! f {
+ (v: $x:expr) => ( println!("{}", $x) )
+}
fn main () {
let v = 5;
// ignore-test #9383
-#![feature(macro_rules)]
-
// shouldn't affect evaluation of $ex:
-macro_rules! bad_macro (($ex:expr) => ({(|_x| { $ex }) (9) }))
+macro_rules! bad_macro {
+ ($ex:expr) => ({(|_x| { $ex }) (9) })
+}
fn takes_x(_x : int) {
assert_eq!(bad_macro!(_x),8);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
// shouldn't affect evaluation of $ex:
-macro_rules! bad_macro (($ex:expr) => ({let _x = 9i; $ex}));
+macro_rules! bad_macro {
+ ($ex:expr) => ({let _x = 9i; $ex})
+}
+
pub fn main() {
let _x = 8i;
assert_eq!(bad_macro!(_x),8i)
// compile-flags:--cfg ndebug
// exec-env:RUST_LOG=logging-enabled-debug=debug
-#![feature(phase)]
-#[phase(plugin, link)]
+#[macro_use]
extern crate log;
pub fn main() {
// exec-env:RUST_LOG=logging-enabled=info
-#![feature(phase)]
-#[phase(plugin, link)]
+#[macro_use]
extern crate log;
pub fn main() {
// ignore-windows
// exec-env:RUST_LOG=debug
-#![feature(phase)]
-
-#[phase(plugin, link)]
+#[macro_use]
extern crate log;
use std::io::Command;
// ignore-pretty - token trees can't pretty print
-#![feature(macro_rules)]
-
pub fn main() {
- macro_rules! mylambda_tt(
+ macro_rules! mylambda_tt {
($x:ident, $body:expr) => ({
fn f($x: int) -> int { return $body; };
f
})
- );
+ }
assert!(mylambda_tt!(y, y * 2)(8) == 16);
}
// ignore-pretty - token trees can't pretty print
-#![feature(macro_rules)]
-
macro_rules! descriptions {
($name:ident is $desc:expr) => {
// Check that we will correctly expand attributes
// ignore-pretty - token trees can't pretty print
-#![feature(macro_rules)]
-
macro_rules! compiles_fine {
(#[$at:meta]) => {
// test that the different types of attributes work
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
macro_rules! do_block{
($val:block) => {$val}
}
// aux-build:macro_crate_def_only.rs
-#![feature(phase)]
-
-#[phase(plugin)]
+#[macro_use] #[no_link]
extern crate macro_crate_def_only;
pub 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.
+
+// aux-build:macro_crate_nonterminal.rs
+// ignore-stage1
+
+#[macro_use]
+extern crate "macro_crate_nonterminal" as new_name;
+
+pub fn main() {
+ new_name::check_local();
+ assert_eq!(increment!(5), 6);
+}
--- /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_nonterminal.rs
+// ignore-stage1
+
+#[macro_use]
+extern crate macro_crate_nonterminal;
+
+pub fn main() {
+ macro_crate_nonterminal::check_local();
+ assert_eq!(increment!(5), 6);
+}
--- /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 fn increment(x: uint) -> uint {
+ x + 1
+}
+
+#[macro_export]
+macro_rules! increment {
+ ($x:expr) => ({
+ use $crate::increment;
+ increment($x)
+ })
+}
+
+fn main() {
+ assert_eq!(increment!(3), 4);
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
macro_rules! foo2 {
() => {
"foo"
//aux-build:macro_export_inner_module.rs
//ignore-stage1
-#![feature(phase)]
-
-#[phase(plugin)]
+#[macro_use] #[no_link]
extern crate macro_export_inner_module;
pub fn main() {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
-macro_rules! overly_complicated (
+macro_rules! overly_complicated {
($fnname:ident, $arg:ident, $ty:ty, $body:block, $val:expr, $pat:pat, $res:path) =>
({
fn $fnname($arg: $ty) -> Option<$ty> $body
}
})
-);
+}
pub fn main() {
assert!(overly_complicated!(f, x, Option<uint>, { return Some(x); },
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
-macro_rules! four (
+macro_rules! four {
() => (4)
-);
+}
fn main() {
let _x: [u16; four!()];
// ignore-pretty - token trees can't pretty print
// compile-flags: --cfg foo
-#![feature(macro_rules)]
-
macro_rules! compiles_fine {
($at:meta) => {
#[cfg($at)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
struct A;
macro_rules! make_thirteen_method {() => (fn thirteen(&self)->int {13})}
// ignore-pretty - token trees can't pretty print
-#![feature(macro_rules)]
-
-macro_rules! make_foo(
+macro_rules! make_foo {
() => (
struct Foo;
fn bar(&self) {}
}
)
-);
+}
make_foo!();
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
-macro_rules! list (
+macro_rules! list {
( ($($id:ident),*) ) => (());
( [$($id:ident),*] ) => (());
( {$($id:ident),*} ) => (());
-);
+}
-macro_rules! tt_list (
+macro_rules! tt_list {
( ($($tt:tt),*) ) => (());
-);
+}
pub fn main() {
list!( () );
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
-macro_rules! higher_order (
+macro_rules! higher_order {
(subst $lhs:tt => $rhs:tt) => ({
- macro_rules! anon ( $lhs => $rhs );
+ macro_rules! anon { $lhs => $rhs }
anon!(1u, 2u, "foo")
});
-);
+}
fn main() {
let val = higher_order!(subst ($x:expr, $y:expr, $foo:expr) => (($x + $y, $foo)));
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
-macro_rules! mypat(
+macro_rules! mypat {
() => (
Some('y')
)
-);
+}
-macro_rules! char_x(
+macro_rules! char_x {
() => (
'x'
)
-);
+}
-macro_rules! some(
+macro_rules! some {
($x:pat) => (
Some($x)
)
-);
+}
-macro_rules! indirect(
+macro_rules! indirect {
() => (
some!(char_x!())
)
-);
+}
-macro_rules! ident_pat(
+macro_rules! ident_pat {
($x:ident) => (
$x
)
-);
+}
fn f(c: Option<char>) -> uint {
match c {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
mod m {
pub type t = int;
}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:macro_reexport_1.rs
+// aux-build:macro_reexport_2_no_use.rs
+// ignore-stage1
+
+#[macro_use] #[no_link]
+extern crate macro_reexport_2_no_use;
+
+fn main() {
+ assert_eq!(reexported!(), 3u);
+}
--- /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_reexport_1.rs
+// aux-build:macro_reexport_2.rs
+// ignore-stage1
+
+#[macro_use] #[no_link]
+extern crate macro_reexport_2;
+
+fn main() {
+ assert_eq!(reexported!(), 3u);
+}
// ignore-pretty - token trees can't pretty print
-#![feature(macro_rules)]
-
-macro_rules! myfn(
+macro_rules! myfn {
( $f:ident, ( $( $x:ident ),* ), $body:block ) => (
fn $f( $( $x : int),* ) -> int $body
)
-);
+}
myfn!(add, (a,b), { return a+b; } );
pub fn main() {
- macro_rules! mylet(
+ macro_rules! mylet {
($x:ident, $val:expr) => (
let $x = $val;
)
- );
+ }
mylet!(y, 8i*2);
assert_eq!(y, 16i);
assert_eq!(mult(2, add(4,4)), 16);
- macro_rules! actually_an_expr_macro (
+ macro_rules! actually_an_expr_macro {
() => ( 16i )
- );
+ }
assert_eq!({ actually_an_expr_macro!() }, 16i);
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:two_macros.rs
+// ignore-stage1
+
+#[macro_use]
+#[macro_use()]
+extern crate two_macros;
+
+pub fn main() {
+ macro_one!();
+ macro_two!();
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:two_macros.rs
+// ignore-stage1
+
+#[macro_use]
+extern crate two_macros;
+
+pub fn main() {
+ macro_one!();
+ macro_two!();
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:two_macros.rs
+// ignore-stage1
+
+#[macro_use(macro_one, macro_two)]
+extern crate two_macros;
+
+pub fn main() {
+ macro_one!();
+ macro_two!();
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:two_macros.rs
+// ignore-stage1
+
+#[macro_use(macro_two)]
+extern crate two_macros;
+
+pub fn main() {
+ macro_two!();
+}
// compile-flags: --cfg foo
-#![feature(macro_rules)]
-
#[cfg(foo)]
-macro_rules! foo( () => (1i) );
+macro_rules! foo { () => (1i) }
#[cfg(not(foo))]
-macro_rules! foo( () => (2i) );
+macro_rules! foo { () => (2i) }
pub fn main() {
assert_eq!(foo!(), 1i);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
#[cfg(foo)]
-macro_rules! foo( () => (1i) );
+macro_rules! foo { () => (1i) }
#[cfg(not(foo))]
-macro_rules! foo( () => (2i) );
+macro_rules! foo { () => (2i) }
pub fn main() {
assert_eq!(foo!(), 2i);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
use std::thread::Thread;
-macro_rules! expr (($e: expr) => { $e });
+macro_rules! expr { ($e: expr) => { $e } }
macro_rules! spawn {
($($code: tt)*) => {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
enum Foo {
B { b1: int, bb1: int},
}
-macro_rules! match_inside_expansion(
+macro_rules! match_inside_expansion {
() => (
match (Foo::B { b1:29 , bb1: 100}) {
Foo::B { b1:b2 , bb1:bb2 } => b2+bb2
}
)
-);
+}
pub fn main() {
assert_eq!(match_inside_expansion!(),129);
// ignore-test #9384
-#![feature(macro_rules)]
-
// shouldn't affect evaluation of $ex.
-macro_rules! bad_macro (($ex:expr) => (
+macro_rules! bad_macro { ($ex:expr) => (
{match 9 {_x => $ex}}
-))
+)}
fn main() {
match 8 {
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that we handle projection types which wind up important for
+// resolving methods. This test was reduced from a larger example; the
+// call to `foo()` at the end was failing to resolve because the
+// winnowing stage of method resolution failed to handle an associated
+// type projection.
+
+#![feature(associated_types)]
+
+trait Hasher {
+ type Output;
+ fn finish(&self) -> Self::Output;
+}
+
+trait Hash<H: Hasher> {
+ fn hash(&self, h: &mut H);
+}
+
+trait HashState {
+ type Wut: Hasher;
+ fn hasher(&self) -> Self::Wut;
+}
+
+struct SipHasher;
+impl Hasher for SipHasher {
+ type Output = u64;
+ fn finish(&self) -> u64 { 4 }
+}
+
+impl Hash<SipHasher> for int {
+ fn hash(&self, h: &mut SipHasher) {}
+}
+
+struct SipState;
+impl HashState for SipState {
+ type Wut = SipHasher;
+ fn hasher(&self) -> SipHasher { SipHasher }
+}
+
+struct Map<S> {
+ s: S,
+}
+
+impl<S> Map<S>
+ where S: HashState,
+ <S as HashState>::Wut: Hasher<Output=u64>,
+{
+ fn foo<K>(&self, k: K) where K: Hash< <S as HashState>::Wut> {}
+}
+
+fn foo<K: Hash<SipHasher>>(map: &Map<SipState>) {
+ map.foo(22);
+}
+
+fn main() {}
+
use std::kinds::Sized;
// Note: this must be generic for the problem to show up
-trait Foo<A> for ?Sized {
+trait Foo<A> {
fn foo(&self);
}
--- /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.
+
+// Test that we can use method notation to call methods based on a
+// where clause type, and not only type parameters.
+
+trait Foo {
+ fn foo(&self) -> int;
+}
+
+impl Foo for Option<int>
+{
+ fn foo(&self) -> int {
+ self.unwrap_or(22)
+ }
+}
+
+impl Foo for Option<uint>
+{
+ fn foo(&self) -> int {
+ self.unwrap_or(22) as int
+ }
+}
+
+fn check<T>(x: Option<T>) -> (int, int)
+ where Option<T> : Foo
+{
+ let y: Option<T> = None;
+ (x.foo(), y.foo())
+}
+
+fn main() {
+ assert_eq!(check(Some(23u)), (23i, 22i));
+ assert_eq!(check(Some(23i)), (23i, 22i));
+}
// <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(globs)]
pub use Foo::*;
use nest::{Bar, D, E, F};
// except according to those terms.
// aux-build:namespaced_enums.rs
-#![feature(globs)]
extern crate namespaced_enums;
// <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(globs)]
mod m2 {
pub enum Foo {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
-macro_rules! quote_tokens ( () => (()) );
+macro_rules! quote_tokens { () => (()) }
pub fn main() {
quote_tokens!();
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
use std::{option, mem};
// Iota-reduction is a rule in the Calculus of (Co-)Inductive Constructions,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
use std::mem;
enum E<T> { Thing(int, T), Nothing((), ((), ()), [i8; 0]) }
// Test that we can overload the `+` operator for points so that two
// points can be added, and a point can be added to an integer.
-#![feature(associated_types, default_type_params)]
-
use std::ops;
#[derive(Show,PartialEq,Eq)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
use std::cmp;
use std::ops;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
use std::cell::Cell;
use std::ops::{Deref, DerefMut};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
use std::ops::Deref;
struct DerefArray<'a, T:'a> {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
use std::rc::Rc;
use std::ops::Deref;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
use std::ops::Deref;
struct DerefWithHelper<H, T> {
// Tests that nested vtables work with overloaded calls.
-#![feature(default_type_params, unboxed_closures)]
+#![feature(unboxed_closures)]
use std::ops::Fn;
use std::ops::Add;
// ICE trigger
G(1i);
}
-
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
use std::cell::Cell;
use std::ops::{Deref, DerefMut};
use std::vec::Vec;
// Test overloading of the `[]` operator. In particular test that it
// takes its argument *by reference*.
-#![feature(associated_types)]
-
use std::ops::Index;
struct AssociationList<K,V> {
// Test overloaded indexing combined with autoderef.
-#![feature(associated_types)]
-
use std::ops::{Index, IndexMut};
struct Foo {
assert_eq!(f[1].get(), 5);
assert_eq!(f[1].get_from_ref(), 5);
}
-
// Test using overloaded indexing when the "map" is stored in a
// field. This caused problems at some point.
-#![feature(associated_types)]
-
use std::ops::Index;
struct Foo {
} };
assert_eq!(f.foo[1].get(), 2);
}
-
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
use std::ops::{Index, IndexMut};
struct Foo {
assert_eq!(f[1].get(), 5);
assert_eq!(f[1].get_from_ref(), 5);
}
-
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
trait Foo {
type T;
fn foo() -> Box<<Self as Foo>::T>;
--- /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.
+
+// Test parsing binary operators after macro invocations.
+
+#![feature(macro_rules)]
+
+macro_rules! id {
+ ($e: expr) => { $e }
+}
+
+fn foo() {
+ id!(1i) + 1;
+ id![1i] - 1;
+ id!(1i) * 1;
+ id![1i] / 1;
+ id!(1i) % 1;
+
+ id!(1i) & 1;
+ id![1i] | 1;
+ id!(1i) ^ 1;
+
+ let mut x = 1i;
+ id![x] = 2;
+ id!(x) += 1;
+
+ id!(1f64).clone();
+
+ id!([1i, 2, 3])[1];
+ id![drop](1i);
+
+ id!(true) && true;
+ id![true] || 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.
-
-
-#![feature(phase)]
-
-#[phase(plugin)]
-use std::mem;
-
-fn main() {}
-
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:plugin_args.rs
+// ignore-stage1
+
+#![feature(plugin)]
+
+#[no_link]
+#[plugin]
+extern crate plugin_args;
+
+fn main() {
+ assert_eq!(plugin_args!(), "#[plugin]");
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:plugin_args.rs
+// ignore-stage1
+
+#![feature(plugin)]
+
+#[no_link]
+#[plugin()]
+extern crate plugin_args;
+
+fn main() {
+ assert_eq!(plugin_args!(), "#[plugin()]");
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:plugin_args.rs
+// ignore-stage1
+
+#![feature(plugin)]
+
+#[no_link]
+#[plugin(hello(there), how(are="you"))]
+extern crate plugin_args;
+
+fn main() {
+ assert_eq!(plugin_args!(), "#[plugin(hello(there), how(are = \"you\"))]");
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:plugin_args.rs
+// ignore-stage1
+
+#![feature(plugin)]
+
+#[no_link]
+#[plugin="foobar"]
+extern crate plugin_args;
+
+fn main() {
+ assert_eq!(plugin_args!(), "#[plugin = \"foobar\"]");
+}
// Check we do the correct privacy checks when we import a name and there is an
// item with that name in both the value and type namespaces.
-#![feature(globs)]
#![allow(dead_code)]
#![allow(unused_imports)]
fn main() {
}
-
-
// 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.
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(globs)]
mod a {
pub fn f() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types, unsafe_destructor)]
+#![feature(unsafe_destructor)]
pub struct Foo<T>;
--- /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.
+
+// Check that the type checker permits us to reassign `z` which
+// started out with a longer lifetime and was reassigned to a shorter
+// one (it should infer to be the intersection).
+
+fn foo(x: &int) {
+ let a = 1;
+ let mut z = x;
+ z = &a;
+}
+
+pub fn main() {
+ foo(&1);
+}
--- /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.
+
+// Check that the type checker permits us to reassign `z` which
+// started out with a longer lifetime and was reassigned to a shorter
+// one (it should infer to be the intersection).
+
+fn foo(x: &int) {
+ let a = 1;
+ match x {
+ mut z => {
+ z = &a;
+ }
+ }
+}
+
+pub fn main() {
+ foo(&1);
+}
--- /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.
+
+// Test that this fairly specialized, but also reasonable, pattern
+// typechecks. The pattern involves regions bound in closures that
+// wind up related to inference variables.
+//
+// NB. Changes to the region implementatiosn have broken this pattern
+// a few times, but it happens to be used in the compiler so those
+// changes were caught. However, those uses in the compiler could
+// easily get changed or refactored away in the future.
+
+struct Ctxt<'tcx> {
+ x: &'tcx Vec<int>
+}
+
+struct Foo<'a,'tcx:'a> {
+ cx: &'a Ctxt<'tcx>,
+}
+
+impl<'a,'tcx> Foo<'a,'tcx> {
+ fn bother(&mut self) -> int {
+ self.elaborate_bounds(box |this| {
+ // (*) Here: type of `this` is `&'f0 Foo<&'f1, '_2>`,
+ // where `'f0` and `'f1` are fresh, free regions that
+ // result from the bound regions on the closure, and `'2`
+ // is a region inference variable created by the call. Due
+ // to the constraints on the type, we find that `'_2 : 'f1
+ // + 'f2` must hold (and can be assumed by the callee).
+ // Region inference has to do some clever stuff to avoid
+ // inferring `'_2` to be `'static` in this case, because
+ // it is created outside the closure but then related to
+ // regions bound by the closure itself. See the
+ // `region_inference.rs` file (and the `givens` field, in
+ // particular) for more details.
+ this.foo()
+ })
+ }
+
+ fn foo(&mut self) -> int {
+ 22
+ }
+
+ fn elaborate_bounds(
+ &mut self,
+ mut mk_cand: Box<for<'b> FnMut(&mut Foo<'b, 'tcx>) -> int>)
+ -> int
+ {
+ mk_cand(self)
+ }
+}
+
+fn main() {
+ let v = vec!();
+ let cx = Ctxt { x: &v };
+ let mut foo = Foo { cx: &cx };
+ assert_eq!(foo.bother(), 22); // just so the code is not dead, basically
+}
extern crate libc;
+use std::ffi::CString;
use std::io::TempDir;
-use std::c_str::ToCStr;
use std::io::fs::PathExtensions;
use std::io::fs;
use std::io;
let test_file = &old_path.join("temp.txt");
/* Write the temp input file */
- let ostream = test_file.with_c_str(|fromp| {
- "w+b".with_c_str(|modebuf| {
- libc::fopen(fromp, modebuf)
- })
- });
+ let fromp = CString::from_slice(test_file.as_vec());
+ let modebuf = CString::from_slice(b"w+b");
+ let ostream = libc::fopen(fromp.as_ptr(), modebuf.as_ptr());
assert!((ostream as uint != 0u));
let s = "hello".to_string();
- "hello".with_c_str(|buf| {
- let write_len = libc::fwrite(buf as *const libc::c_void,
- 1u as libc::size_t,
- (s.len() + 1u) as libc::size_t,
- ostream);
- assert_eq!(write_len, (s.len() + 1) as libc::size_t)
- });
+ let buf = CString::from_slice(b"hello");
+ let write_len = libc::fwrite(buf.as_ptr() as *mut _,
+ 1u as libc::size_t,
+ (s.len() + 1u) as libc::size_t,
+ ostream);
+ assert_eq!(write_len, (s.len() + 1) as libc::size_t);
assert_eq!(libc::fclose(ostream), (0u as libc::c_int));
let new_path = tmpdir.join_many(&["quux", "blat"]);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use std::ffi;
use std::io::process::{Command, ProcessOutput};
use std::os;
use std::rt::unwind::try;
let args = unsafe {
range(0, argc as uint).map(|i| {
- String::from_raw_buf(*argv.offset(i as int)).into_bytes()
+ let ptr = *argv.offset(i as int) as *const _;
+ ffi::c_str_to_bytes(&ptr).to_vec()
}).collect::<Vec<_>>()
};
let me = args[0].as_slice();
// exec-env:RUST_LOG=rust-log-filter/f.o
-#![feature(phase)]
-#[phase(plugin,link)]
+#[macro_use]
extern crate log;
use std::sync::mpsc::{channel, Sender, Receiver};
// except according to those terms.
-#![feature(associated_types, simd)]
+#![feature(simd)]
use std::ops;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
use std::mem::size_of;
#[derive(PartialEq, Show)]
// aux-build:svh-b.rs
// aux-build:svh-a-comment.rs
-#![feature(macro_rules)]
-
extern crate a;
extern crate b;
// aux-build:svh-b.rs
// aux-build:svh-a-doc.rs
-#![feature(macro_rules)]
-
extern crate a;
extern crate b;
// aux-build:svh-b.rs
// aux-build:svh-a-macro.rs
-#![feature(macro_rules)]
-
extern crate a;
extern crate b;
// aux-build:svh-b.rs
// aux-build:svh-a-no-change.rs
-#![feature(macro_rules)]
-
extern crate a;
extern crate b;
// aux-build:svh-b.rs
// aux-build:svh-a-redundant-cfg.rs
-#![feature(macro_rules)]
-
extern crate a;
extern crate b;
// aux-build:svh-b.rs
// aux-build:svh-a-whitespace.rs
-#![feature(macro_rules)]
-
extern crate a;
extern crate b;
// This test is brittle!
// ignore-pretty - the pretty tests lose path information, breaking include!
-#![feature(macro_rules)]
-
pub mod m1 {
pub mod m2 {
pub fn where_am_i() -> String {
}
}
-macro_rules! indirect_line( () => ( line!() ) );
+macro_rules! indirect_line { () => ( line!() ) }
pub fn main() {
- assert_eq!(line!(), 27);
+ assert_eq!(line!(), 25);
//assert!((column!() == 11));
- assert_eq!(indirect_line!(), 29);
+ assert_eq!(indirect_line!(), 27);
assert!((file!().ends_with("syntax-extension-source-utils.rs")));
assert_eq!(stringify!((2*3) + 5).to_string(), "( 2 * 3 ) + 5".to_string());
assert!(include!("syntax-extension-source-utils-files/includeme.\
// The Windows tests are wrapped in an extra module for some reason
assert!((m1::m2::where_am_i().as_slice().ends_with("m1::m2")));
- assert!(match (47, "( 2 * 3 ) + 5") {
+ assert!(match (45, "( 2 * 3 ) + 5") {
(line!(), stringify!((2*3) + 5)) => true,
_ => false
})
-
// 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.
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(globs)]
use alder::*;
// one test task to ensure that errors are timeouts, not file descriptor
// exhaustion.
-#![feature(macro_rules, globs)]
#![allow(experimental)]
#![reexport_test_harness_main = "test_main"]
// ignore-android needs extra network permissions
// exec-env:RUST_LOG=debug
-#![feature(phase)]
-#[phase(plugin, link)]
+#[macro_use]
extern crate log;
extern crate libc;
let path = {
let p = TempDir::new_in(&Path::new("."), "foobar").unwrap();
let p = p.path();
- assert!(p.as_vec().ends_with(b"foobar"));
+ assert!(p.as_str().unwrap().contains("foobar"));
p.clone()
};
assert!(!path.exists());
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(associated_types)]
-
use std::cmp::PartialEq;
use std::ops::{Add, Sub, Mul};
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:two_macros.rs
+// ignore-stage1
+
+#[macro_use(macro_one)]
+#[macro_use(macro_two)]
+extern crate two_macros;
+
+pub fn main() {
+ macro_one!();
+ macro_two!();
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
enum T {
A(int),
B(f64)
// doesn't cause capture. Making this macro hygienic (as I've done)
// could very well make this test case completely pointless....
-macro_rules! test(
+macro_rules! test {
($id1:ident, $id2:ident, $e:expr) => (
fn foo(a:T, b:T) -> T {
match (a, b) {
}
}
)
-);
+}
test!(x,y,x + y);
// Test syntax checks for `?Sized` syntax.
-trait T1 for ?Sized {}
-pub trait T2 for ?Sized {}
-trait T3<X: T1> for ?Sized: T2 {}
+trait T1 {}
+pub trait T2 {}
+trait T3<X: T1> : T2 {}
trait T4<X: ?Sized> {}
trait T5<X: ?Sized, Y> {}
trait T6<Y, X: ?Sized> {}
}
// Bounded.
-trait T for ?Sized {}
+trait T {}
fn f3<X: T+?Sized>(x: &X) {
f3::<X>(x);
}
}
// Self type.
-trait T2 for ?Sized {
+trait T2 {
fn f() -> Box<Self>;
}
struct S;
let _: Box<X> = T2::f();
}
-trait T3 for ?Sized {
+trait T3 {
fn f() -> Box<Self>;
}
impl T3 for S {
extern crate libc;
-use std::c_str::{CString, ToCStr};
+use std::ffi::{self, CString};
use libc::{c_char, c_int};
// ignore-fast doesn't like extern crate
unsafe fn check<T, F>(expected: &str, f: F) where F: FnOnce(*mut c_char) -> T {
let mut x = [0 as c_char; 50];
f(&mut x[0] as *mut c_char);
- let res = CString::new(&x[0], false);
- assert_eq!(expected, res.as_str().unwrap());
+ assert_eq!(expected.as_bytes(), ffi::c_str_to_bytes(&x.as_ptr()));
}
pub fn main() {
unsafe {
// Call with just the named parameter
- "Hello World\n".with_c_str(|c| {
- check("Hello World\n", |s| sprintf(s, c));
- });
+ let c = CString::from_slice(b"Hello World\n");
+ check("Hello World\n", |s| sprintf(s, c.as_ptr()));
// Call with variable number of arguments
- "%d %f %c %s\n".with_c_str(|c| {
- check("42 42.500000 a %d %f %c %s\n\n", |s| {
- sprintf(s, c, 42i, 42.5f64, 'a' as c_int, c);
- })
+ let c = CString::from_slice(b"%d %f %c %s\n");
+ check("42 42.500000 a %d %f %c %s\n\n", |s| {
+ sprintf(s, c.as_ptr(), 42i, 42.5f64, 'a' as c_int, c.as_ptr());
});
// Make a function pointer
- let x: unsafe extern "C" fn(*mut c_char, *const c_char, ...) -> c_int = sprintf;
+ let x: unsafe extern fn(*mut c_char, *const c_char, ...) -> c_int = sprintf;
// A function that takes a function pointer
- unsafe fn call(p: unsafe extern "C" fn(*mut c_char, *const c_char, ...) -> c_int) {
- // Call with just the named parameter via fn pointer
- "Hello World\n".with_c_str(|c| {
- check("Hello World\n", |s| p(s, c));
- });
+ unsafe fn call(p: unsafe extern fn(*mut c_char, *const c_char, ...) -> c_int) {
+ // Call with just the named parameter
+ let c = CString::from_slice(b"Hello World\n");
+ check("Hello World\n", |s| sprintf(s, c.as_ptr()));
// Call with variable number of arguments
- "%d %f %c %s\n".with_c_str(|c| {
- check("42 42.500000 a %d %f %c %s\n\n", |s| {
- p(s, c, 42i, 42.5f64, 'a' as c_int, c);
- })
+ let c = CString::from_slice(b"%d %f %c %s\n");
+ check("42 42.500000 a %d %f %c %s\n\n", |s| {
+ sprintf(s, c.as_ptr(), 42i, 42.5f64, 'a' as c_int, c.as_ptr());
});
}
--- /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)]
+#![no_std]
+
+extern crate "std" as other;
+
+#[macro_use]
+extern crate core;
+extern crate libc;
+
+#[macro_use]
+extern crate collections;
+
+use core::option::Option::Some;
+use core::slice::SliceExt;
+use collections::vec::Vec;
+
+// Issue #16806
+
+#[start]
+fn start(_argc: int, _argv: *const *const u8) -> int {
+ let x: Vec<u8> = vec![0, 1, 2];
+ match x.last() {
+ Some(&2) => (),
+ _ => panic!(),
+ }
+ 0
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(macro_rules)]
-
macro_rules! vec [
($($e:expr),*) => ({
let mut _temp = ::std::vec::Vec::new();