diff options
78 files changed, 1438 insertions, 1690 deletions
diff --git a/RELEASES.md b/RELEASES.md index 54fe87dc658..f8679431339 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,5 +1,223 @@ +Version 1.5.0 (2015-12-10) +========================== + +* ~700 changes, numerous bugfixes + +Highlights +---------- + +* Stabilized APIs: + [`BinaryHeap::from`], [`BinaryHeap::into_sorted_vec`], + [`BinaryHeap::into_vec`], [`Condvar::wait_timeout`], + [`FileTypeExt::is_block_device`], [`FileTypeExt::is_char_device`], + [`FileTypeExt::is_fifo`], [`FileTypeExt::is_socket`], + [`FileTypeExt`], [`Formatter::alternate`], [`Formatter::fill`], + [`Formatter::precision`], [`Formatter::sign_aware_zero_pad`], + [`Formatter::sign_minus`], [`Formatter::sign_plus`], + [`Formatter::width`], [`Iterator::cmp`], [`Iterator::eq`], + [`Iterator::ge`], [`Iterator::gt`], [`Iterator::le`], + [`Iterator::lt`], [`Iterator::ne`], [`Iterator::partial_cmp`], + [`Path::canonicalize`], [`Path::exists`], [`Path::is_dir`], + [`Path::is_file`], [`Path::metadata`], [`Path::read_dir`], + [`Path::read_link`], [`Path::symlink_metadata`], + [`Utf8Error::valid_up_to`], [`Vec::resize`], + [`VecDeque::as_mut_slices`], [`VecDeque::as_slices`], + [`VecDeque::insert`], [`VecDeque::shrink_to_fit`], + [`VecDeque::swap_remove_back`], [`VecDeque::swap_remove_front`], + [`slice::split_first_mut`], [`slice::split_first`], + [`slice::split_last_mut`], [`slice::split_last`], + [`char::from_u32_unchecked`], [`fs::canonicalize`], + [`str::MatchIndices`], [`str::RMatchIndices`], + [`str::match_indices`], [`str::rmatch_indices`], + [`str::slice_mut_unchecked`], [`string::ParseError`]. +* Rust applications hosted on crates.io can be installed locally to + `~/.cargo/bin` with the [`cargo install`] command. Among other + things this makes it easier to augment Cargo with new subcommands: + when a binary named e.g. `cargo-foo` is found in `$PATH` it can be + invoked as `cargo foo`. +* Crates with wildcard (`*`) dependencies will [emit warnings when + published][1.5w]. In 1.6 it will no longer be possible to publish + crates with wildcard dependencies. + +Breaking Changes +---------------- + +* The rules determining when a particular lifetime must outlive + a particular value (known as '[dropck]') have been [modified + to not rely on parametricity][1.5p]. +* [Implementations of `AsRef` and `AsMut` were added to `Box`, `Rc`, + and `Arc`][1.5a]. Because these smart pointer types implement + `Deref`, this causes breakage in cases where the interior type + contains methods of the same name. +* [Correct a bug in Rc/Arc][1.5c] that caused [dropck] to be unaware + that they could drop their content. Soundness fix. +* All method invocations are [properly checked][1.5wf1] for + [well-formedness][1.5wf2]. Soundness fix. +* Traits whose supertraits contain `Self` are [not object + safe][1.5o]. Soundness fix. +* Target specifications support a [`no_default_libraries`][1.5nd] + setting that controls whether `-nodefaultlibs` is passed to the + linker, and in turn the `is_like_windows` setting no longer affects + the `-nodefaultlibs` flag. +* `#[derive(Show)]`, long-deprecated, [has been removed][1.5ds]. +* The `#[inline]` and `#[repr]` attributes [can only appear + in valid locations][1.5at]. +* Native libraries linked from the local crate are [passed to + the linker before native libraries from upstream crates][1.5nl]. +* Two rarely-used attributes, `#[no_debug]` and + `#[omit_gdb_pretty_printer_section]` [are feature gated][1.5fg]. +* Negation of unsigned integers, which has been a warning for + several releases, [is now behind a feature gate and will + generate errors][1.5nu]. +* The parser accidentally accepted visibility modifiers on + enum variants, a bug [which has been fixed][1.5ev]. +* [A bug was fixed that allowed `use` statements to import unstable + features][1.5use]. + +Language +-------- + +* When evaluating expressions at compile-time that are not + compile-time constants (const-evaluating expressions in non-const + contexts), incorrect code such as overlong bitshifts and arithmetic + overflow will [generate a warning instead of an error][1.5ce], + delaying the error until runtime. This will allow the + const-evaluator to be expanded in the future backwards-compatibly. +* The `improper_ctypes` lint [no longer warns about using `isize` and + `usize` in FFI][1.5ict]. + +Libraries +--------- + +* `Arc<T>` and `Rc<T>` are [covariant with respect to `T` instead of + invariant][1.5c]. +* `Default` is [implemented for mutable slices][1.5d]. +* `FromStr` is [implemented for `SockAddrV4` and `SockAddrV6`][1.5s]. +* There are now `From` conversions [between floating point + types][1.5f] where the conversions are lossless. +* Thera are now `From` conversions [between integer types][1.5i] where + the conversions are lossless. +* [`fs::Metadata` implements `Clone`][1.5fs]. +* The `parse` method [accepts a leading "+" when parsing + integers][1.5pi]. +* [`AsMut` is implemented for `Vec`][1.5am]. +* The `clone_from` implementations for `String` and `BinaryHeap` [have + been optimized][1.5cf] and no longer rely on the default impl. +* The `extern "Rust"`, `extern "C"`, `unsafe extern "Rust"` and + `unsafe extern "C"` function types now [implement `Clone`, + `PartialEq`, `Eq`, `PartialOrd`, `Ord`, `Hash`, `fmt::Pointer`, and + `fmt::Debug` for up to 12 arguments][1.5fp]. +* [Dropping `Vec`s is much faster in unoptimized builds when the + element types don't implement `Drop`][1.5dv]. +* A bug that caused in incorrect behavior when [combining `VecDeque` + with zero-sized types][1.5vdz] was resolved. +* [`PartialOrd` for slices is faster][1.5po]. + +Miscellaneous +------------- + +* [Crate metadata size was reduced by 20%][1.5md]. +* [Improvements to code generation reduced the size of libcore by 3.3 + MB and rustc's memory usage by 18MB][1.5m]. +* [Improvements to deref translation increased performance in + unoptimized builds][1.5dr]. +* Various errors in trait resolution [are deduplicated to only be + reported once][1.5te]. +* Rust has preliminary [support for rumprun kernels][1.5rr]. +* Rust has preliminary [support for NetBSD on amd64][1.5na]. + +[1.5use]: https://github.com/rust-lang/rust/pull/28364 +[1.5po]: https://github.com/rust-lang/rust/pull/28436 +[1.5ev]: https://github.com/rust-lang/rust/pull/28442 +[1.5nu]: https://github.com/rust-lang/rust/pull/28468 +[1.5dr]: https://github.com/rust-lang/rust/pull/28491 +[1.5vdz]: https://github.com/rust-lang/rust/pull/28494 +[1.5md]: https://github.com/rust-lang/rust/pull/28521 +[1.5fg]: https://github.com/rust-lang/rust/pull/28522 +[1.5dv]: https://github.com/rust-lang/rust/pull/28531 +[1.5na]: https://github.com/rust-lang/rust/pull/28543 +[1.5fp]: https://github.com/rust-lang/rust/pull/28560 +[1.5rr]: https://github.com/rust-lang/rust/pull/28593 +[1.5cf]: https://github.com/rust-lang/rust/pull/28602 +[1.5nl]: https://github.com/rust-lang/rust/pull/28605 +[1.5te]: https://github.com/rust-lang/rust/pull/28645 +[1.5at]: https://github.com/rust-lang/rust/pull/28650 +[1.5am]: https://github.com/rust-lang/rust/pull/28663 +[1.5m]: https://github.com/rust-lang/rust/pull/28778 +[1.5ict]: https://github.com/rust-lang/rust/pull/28779 +[1.5a]: https://github.com/rust-lang/rust/pull/28811 +[1.5pi]: https://github.com/rust-lang/rust/pull/28826 +[1.5ce]: https://github.com/rust-lang/rfcs/blob/master/text/1229-compile-time-asserts.md +[1.5p]: https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md +[1.5i]: https://github.com/rust-lang/rust/pull/28921 +[1.5fs]: https://github.com/rust-lang/rust/pull/29021 +[1.5f]: https://github.com/rust-lang/rust/pull/29129 +[1.5ds]: https://github.com/rust-lang/rust/pull/29148 +[1.5s]: https://github.com/rust-lang/rust/pull/29190 +[1.5d]: https://github.com/rust-lang/rust/pull/29245 +[1.5o]: https://github.com/rust-lang/rust/pull/29259 +[1.5nd]: https://github.com/rust-lang/rust/pull/28578 +[1.5wf2]: https://github.com/rust-lang/rfcs/blob/master/text/1214-projections-lifetimes-and-wf.md +[1.5wf1]: https://github.com/rust-lang/rust/pull/28669 +[dropck]: https://doc.rust-lang.org/nightly/nomicon/dropck.html +[1.5c]: https://github.com/rust-lang/rust/pull/29110 +[1.5w]: https://github.com/rust-lang/rfcs/blob/master/text/1241-no-wildcard-deps.md +[`cargo install`]: https://github.com/rust-lang/rfcs/blob/master/text/1200-cargo-install.md +[`BinaryHeap::from`]: http://doc.rust-lang.org/nightly/std/convert/trait.From.html#method.from +[`BinaryHeap::into_sorted_vec`]: http://doc.rust-lang.org/nightly/std/collections/struct.BinaryHeap.html#method.into_sorted_vec +[`BinaryHeap::into_vec`]: http://doc.rust-lang.org/nightly/std/collections/struct.BinaryHeap.html#method.into_vec +[`Condvar::wait_timeout`]: http://doc.rust-lang.org/nightly/std/sync/struct.Condvar.html#method.wait_timeout +[`FileTypeExt::is_block_device`]: http://doc.rust-lang.org/nightly/std/os/unix/fs/trait.FileTypeExt.html#tymethod.is_block_device +[`FileTypeExt::is_char_device`]: http://doc.rust-lang.org/nightly/std/os/unix/fs/trait.FileTypeExt.html#tymethod.is_char_device +[`FileTypeExt::is_fifo`]: http://doc.rust-lang.org/nightly/std/os/unix/fs/trait.FileTypeExt.html#tymethod.is_fifo +[`FileTypeExt::is_socket`]: http://doc.rust-lang.org/nightly/std/os/unix/fs/trait.FileTypeExt.html#tymethod.is_socket +[`FileTypeExt`]: http://doc.rust-lang.org/nightly/std/os/unix/fs/trait.FileTypeExt.html +[`Formatter::alternate`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.alternate +[`Formatter::fill`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.fill +[`Formatter::precision`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.precision +[`Formatter::sign_aware_zero_pad`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.sign_aware_zero_pad +[`Formatter::sign_minus`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.sign_minus +[`Formatter::sign_plus`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.sign_plus +[`Formatter::width`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.width +[`Iterator::cmp`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.cmp +[`Iterator::eq`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.eq +[`Iterator::ge`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.ge +[`Iterator::gt`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.gt +[`Iterator::le`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.le +[`Iterator::lt`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.lt +[`Iterator::ne`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.ne +[`Iterator::partial_cmp`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.partial_cmp +[`Path::canonicalize`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.canonicalize +[`Path::exists`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.exists +[`Path::is_dir`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.is_dir +[`Path::is_file`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.is_file +[`Path::metadata`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.metadata +[`Path::read_dir`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.read_dir +[`Path::read_link`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.read_link +[`Path::symlink_metadata`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.symlink_metadata +[`Utf8Error::valid_up_to`]: http://doc.rust-lang.org/nightly/core/str/struct.Utf8Error.html#method.valid_up_to +[`Vec::resize`]: http://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.resize +[`VecDeque::as_mut_slices`]: http://doc.rust-lang.org/nightly/std/collections/struct.VecDeque.html#method.as_mut_slices +[`VecDeque::as_slices`]: http://doc.rust-lang.org/nightly/std/collections/struct.VecDeque.html#method.as_slices +[`VecDeque::insert`]: http://doc.rust-lang.org/nightly/std/collections/struct.VecDeque.html#method.insert +[`VecDeque::shrink_to_fit`]: http://doc.rust-lang.org/nightly/std/collections/struct.VecDeque.html#method.shrink_to_fit +[`VecDeque::swap_remove_back`]: http://doc.rust-lang.org/nightly/std/collections/struct.VecDeque.html#method.swap_remove_back +[`VecDeque::swap_remove_front`]: http://doc.rust-lang.org/nightly/std/collections/struct.VecDeque.html#method.swap_remove_front +[`slice::split_first_mut`]: http://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_first_mut +[`slice::split_first`]: http://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_first +[`slice::split_last_mut`]: http://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_last_mut +[`slice::split_last`]: http://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_last +[`char::from_u32_unchecked`]: http://doc.rust-lang.org/nightly/std/char/fn.from_u32_unchecked.html +[`fs::canonicalize`]: http://doc.rust-lang.org/nightly/std/fs/fn.canonicalize.html +[`str::MatchIndices`]: http://doc.rust-lang.org/nightly/std/str/struct.MatchIndices.html +[`str::RMatchIndices`]: http://doc.rust-lang.org/nightly/std/str/struct.RMatchIndices.html +[`str::match_indices`]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.match_indices +[`str::rmatch_indices`]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.rmatch_indices +[`str::slice_mut_unchecked`]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.slice_mut_unchecked +[`string::ParseError`]: http://doc.rust-lang.org/nightly/std/string/enum.ParseError.html + Version 1.4.0 (2015-10-29) -============================ +========================== * ~1200 changes, numerous bugfixes diff --git a/src/doc/book/enums.md b/src/doc/book/enums.md index 8ad4eeedd18..e17d3f762b9 100644 --- a/src/doc/book/enums.md +++ b/src/doc/book/enums.md @@ -1,7 +1,8 @@ % Enums -An `enum` in Rust is a type that represents data that could be one of -several possible variants: +An `enum` in Rust is a type that represents data that is one of +several possible variants. Each variant in the `enum` can optionally +have data associated with it: ```rust enum Message { @@ -12,9 +13,8 @@ enum Message { } ``` -Each variant can optionally have data associated with it. The syntax for -defining variants resembles the syntaxes used to define structs: you can -have variants with no data (like unit-like structs), variants with named +The syntax for defining variants resembles the syntaxes used to define structs: +you can have variants with no data (like unit-like structs), variants with named data, and variants with unnamed data (like tuple structs). Unlike separate struct definitions, however, an `enum` is a single type. A value of the enum can match any of the variants. For this reason, an @@ -41,7 +41,7 @@ let y: BoardGameTurn = BoardGameTurn::Move { squares: 1 }; Both variants are named `Move`, but since they’re scoped to the name of the enum, they can both be used without conflict. -A value of an enum type contains information about which variant it is, +A value of an `enum` type contains information about which variant it is, in addition to any data associated with that variant. This is sometimes referred to as a ‘tagged union’, since the data includes a ‘tag’ indicating what type it is. The compiler uses this information to @@ -67,7 +67,7 @@ equality yet, but we’ll find out in the [`traits`][traits] section. # Constructors as functions -An enum’s constructors can also be used like functions. For example: +An `enum` constructor can also be used like a function. For example: ```rust # enum Message { @@ -76,7 +76,7 @@ An enum’s constructors can also be used like functions. For example: let m = Message::Write("Hello, world".to_string()); ``` -Is the same as +is the same as ```rust # enum Message { diff --git a/src/doc/book/structs.md b/src/doc/book/structs.md index b51ad8e087d..1d70ee27869 100644 --- a/src/doc/book/structs.md +++ b/src/doc/book/structs.md @@ -9,7 +9,8 @@ let origin_x = 0; let origin_y = 0; ``` -A `struct` lets us combine these two into a single, unified datatype: +A `struct` lets us combine these two into a single, unified datatype with `x` +and `y` as field labels: ```rust struct Point { @@ -32,7 +33,7 @@ We can create an instance of our `struct` via `let`, as usual, but we use a `key value` style syntax to set each field. The order doesn’t need to be the same as in the original declaration. -Finally, because fields have names, we can access the field through dot +Finally, because fields have names, we can access them through dot notation: `origin.x`. The values in `struct`s are immutable by default, like other bindings in Rust. @@ -67,9 +68,8 @@ struct Point { Mutability is a property of the binding, not of the structure itself. If you’re used to field-level mutability, this may seem strange at first, but it -significantly simplifies things. It even lets you make things mutable for a short -time only: - +significantly simplifies things. It even lets you make things mutable on a temporary +basis: ```rust,ignore struct Point { @@ -82,7 +82,7 @@ fn main() { point.x = 5; - let point = point; // this new binding can’t change now + let point = point; // now immutable point.y = 6; // this causes an error } @@ -121,27 +121,24 @@ let point = Point3d { z: 1, x: 2, .. origin }; # Tuple structs Rust has another data type that’s like a hybrid between a [tuple][tuple] and a -`struct`, called a ‘tuple struct’. Tuple structs have a name, but -their fields don’t: +`struct`, called a ‘tuple struct’. Tuple structs have a name, but their fields +don't. They are declared with the `struct` keyword, and then with a name +followed by a tuple: + +[tuple]: primitive-types.html#tuples ```rust struct Color(i32, i32, i32); struct Point(i32, i32, i32); -``` -[tuple]: primitive-types.html#tuples - -These two will not be equal, even if they have the same values: - -```rust -# struct Color(i32, i32, i32); -# struct Point(i32, i32, i32); let black = Color(0, 0, 0); let origin = Point(0, 0, 0); ``` +Here, `black` and `origin` are not equal, even though they contain the same +values. -It is almost always better to use a `struct` than a tuple struct. We would write -`Color` and `Point` like this instead: +It is almost always better to use a `struct` than a tuple struct. We +would write `Color` and `Point` like this instead: ```rust struct Color { @@ -157,13 +154,14 @@ struct Point { } ``` -Now, we have actual names, rather than positions. Good names are important, -and with a `struct`, we have actual names. +Good names are important, and while values in a tuple struct can be +referenced with dot notation as well, a `struct` gives us actual names, +rather than positions. -There _is_ one case when a tuple struct is very useful, though, and that’s a -tuple struct with only one element. We call this the ‘newtype’ pattern, because -it allows you to create a new type, distinct from that of its contained value -and expressing its own semantic meaning: +There _is_ one case when a tuple struct is very useful, though, and that is when +it has only one element. We call this the ‘newtype’ pattern, because +it allows you to create a new type that is distinct from its contained value +and also expresses its own semantic meaning: ```rust struct Inches(i32); diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py index 2acee8a97f5..8362c239b65 100644 --- a/src/etc/htmldocck.py +++ b/src/etc/htmldocck.py @@ -104,6 +104,7 @@ checks if the given file does not exist, for example. """ +from __future__ import print_function import sys import os.path import re @@ -160,8 +161,13 @@ class CustomHTMLParser(HTMLParser): HTMLParser.close(self) return self.__builder.close() -Command = namedtuple('Command', 'negated cmd args lineno') +Command = namedtuple('Command', 'negated cmd args lineno context') +class FailedCheck(Exception): + pass + +class InvalidCheck(Exception): + pass def concat_multi_lines(f): """returns a generator out of the file object, which @@ -196,7 +202,7 @@ def concat_multi_lines(f): catenated = '' if lastline is not None: - raise RuntimeError('Trailing backslash in the end of file') + print_err(lineno, line, 'Trailing backslash at the end of the file') LINE_PATTERN = re.compile(r''' (?<=(?<!\S)@)(?P<negated>!?) @@ -216,9 +222,10 @@ def get_commands(template): cmd = m.group('cmd') args = m.group('args') if args and not args[:1].isspace(): - raise RuntimeError('Invalid template syntax at line {}'.format(lineno+1)) + print_err(lineno, line, 'Invalid template syntax') + continue args = shlex.split(args) - yield Command(negated=negated, cmd=cmd, args=args, lineno=lineno+1) + yield Command(negated=negated, cmd=cmd, args=args, lineno=lineno+1, context=line) def _flatten(node, acc): @@ -242,8 +249,7 @@ def normalize_xpath(path): elif path.startswith('.//'): return path else: - raise RuntimeError('Non-absolute XPath is not supported due to \ - the implementation issue.') + raise InvalidCheck('Non-absolute XPath is not supported due to implementation issues') class CachedFiles(object): @@ -259,41 +265,40 @@ class CachedFiles(object): self.last_path = path return path elif self.last_path is None: - raise RuntimeError('Tried to use the previous path in the first command') + raise InvalidCheck('Tried to use the previous path in the first command') else: return self.last_path def get_file(self, path): path = self.resolve_path(path) - try: + if path in self.files: return self.files[path] - except KeyError: - try: - with open(os.path.join(self.root, path)) as f: - data = f.read() - except Exception as e: - raise RuntimeError('Cannot open file {!r}: {}'.format(path, e)) - else: - self.files[path] = data - return data + + abspath = os.path.join(self.root, path) + if not(os.path.exists(abspath) and os.path.isfile(abspath)): + raise FailedCheck('File does not exist {!r}'.format(path)) + + with open(abspath) as f: + data = f.read() + self.files[path] = data + return data def get_tree(self, path): path = self.resolve_path(path) - try: + if path in self.trees: return self.trees[path] - except KeyError: - try: - f = open(os.path.join(self.root, path)) - except Exception as e: - raise RuntimeError('Cannot open file {!r}: {}'.format(path, e)) + + abspath = os.path.join(self.root, path) + if not(os.path.exists(abspath) and os.path.isfile(abspath)): + raise FailedCheck('File does not exist {!r}'.format(path)) + + with open(abspath) as f: try: - with f: - tree = ET.parse(f, CustomHTMLParser()) + tree = ET.parse(f, CustomHTMLParser()) except Exception as e: raise RuntimeError('Cannot parse an HTML file {!r}: {}'.format(path, e)) - else: - self.trees[path] = tree - return self.trees[path] + self.trees[path] = tree + return self.trees[path] def check_string(data, pat, regexp): @@ -311,14 +316,14 @@ def check_tree_attr(tree, path, attr, pat, regexp): path = normalize_xpath(path) ret = False for e in tree.findall(path): - try: + if attr in e.attrib: value = e.attrib[attr] - except KeyError: - continue else: - ret = check_string(value, pat, regexp) - if ret: - break + continue + + ret = check_string(value, pat, regexp) + if ret: + break return ret @@ -341,57 +346,84 @@ def check_tree_count(tree, path, count): path = normalize_xpath(path) return len(tree.findall(path)) == count +def stderr(*args): + print(*args, file=sys.stderr) -def check(target, commands): - cache = CachedFiles(target) - for c in commands: +def print_err(lineno, context, err, message=None): + global ERR_COUNT + ERR_COUNT += 1 + stderr("{}: {}".format(lineno, message or err)) + if message and err: + stderr("\t{}".format(err)) + + if context: + stderr("\t{}".format(context)) + +ERR_COUNT = 0 + +def check_command(c, cache): + try: + cerr = "" if c.cmd == 'has' or c.cmd == 'matches': # string test regexp = (c.cmd == 'matches') if len(c.args) == 1 and not regexp: # @has <path> = file existence try: cache.get_file(c.args[0]) ret = True - except RuntimeError: + except FailedCheck as err: + cerr = err.message ret = False elif len(c.args) == 2: # @has/matches <path> <pat> = string test + cerr = "`PATTERN` did not match" ret = check_string(cache.get_file(c.args[0]), c.args[1], regexp) elif len(c.args) == 3: # @has/matches <path> <pat> <match> = XML tree test + cerr = "`XPATH PATTERN` did not match" tree = cache.get_tree(c.args[0]) pat, sep, attr = c.args[1].partition('/@') if sep: # attribute - ret = check_tree_attr(cache.get_tree(c.args[0]), pat, attr, c.args[2], regexp) + tree = cache.get_tree(c.args[0]) + ret = check_tree_attr(tree, pat, attr, c.args[2], regexp) else: # normalized text pat = c.args[1] if pat.endswith('/text()'): pat = pat[:-7] ret = check_tree_text(cache.get_tree(c.args[0]), pat, c.args[2], regexp) else: - raise RuntimeError('Invalid number of @{} arguments \ - at line {}'.format(c.cmd, c.lineno)) + raise InvalidCheck('Invalid number of @{} arguments'.format(c.cmd)) elif c.cmd == 'count': # count test if len(c.args) == 3: # @count <path> <pat> <count> = count test ret = check_tree_count(cache.get_tree(c.args[0]), c.args[1], int(c.args[2])) else: - raise RuntimeError('Invalid number of @{} arguments \ - at line {}'.format(c.cmd, c.lineno)) - + raise InvalidCheck('Invalid number of @{} arguments'.format(c.cmd)) elif c.cmd == 'valid-html': - raise RuntimeError('Unimplemented @valid-html at line {}'.format(c.lineno)) + raise InvalidCheck('Unimplemented @valid-html') elif c.cmd == 'valid-links': - raise RuntimeError('Unimplemented @valid-links at line {}'.format(c.lineno)) - + raise InvalidCheck('Unimplemented @valid-links') else: - raise RuntimeError('Unrecognized @{} at line {}'.format(c.cmd, c.lineno)) + raise InvalidCheck('Unrecognized @{}'.format(c.cmd)) if ret == c.negated: - raise RuntimeError('@{}{} check failed at line {}'.format('!' if c.negated else '', - c.cmd, c.lineno)) + raise FailedCheck(cerr) + + except FailedCheck as err: + message = '@{}{} check failed'.format('!' if c.negated else '', c.cmd) + print_err(c.lineno, c.context, err.message, message) + except InvalidCheck as err: + print_err(c.lineno, c.context, err.message) + +def check(target, commands): + cache = CachedFiles(target) + for c in commands: + check_command(c, cache) if __name__ == '__main__': - if len(sys.argv) < 3: - print >>sys.stderr, 'Usage: {} <doc dir> <template>'.format(sys.argv[0]) + if len(sys.argv) != 3: + stderr('Usage: {} <doc dir> <template>'.format(sys.argv[0])) + raise SystemExit(1) + + check(sys.argv[1], get_commands(sys.argv[2])) + if ERR_COUNT: + stderr("\nEncountered {} errors".format(ERR_COUNT)) raise SystemExit(1) - else: - check(sys.argv[1], get_commands(sys.argv[2])) diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index f8483a8ed9b..9479d47943e 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -385,13 +385,6 @@ impl<T: ?Sized> Deref for Arc<T> { } impl<T: Clone> Arc<T> { - #[unstable(feature = "arc_make_unique", reason = "renamed to Arc::make_mut", - issue = "27718")] - #[rustc_deprecated(since = "1.4.0", reason = "renamed to Arc::make_mut")] - pub fn make_unique(this: &mut Self) -> &mut T { - Arc::make_mut(this) - } - /// Make a mutable reference into the given `Arc<T>` by cloning the inner /// data if the `Arc<T>` doesn't have one strong reference and no weak /// references. @@ -428,7 +421,7 @@ impl<T: Clone> Arc<T> { // weak count, there's no chance the ArcInner itself could be // deallocated. if this.inner().strong.compare_and_swap(1, 0, Acquire) != 1 { - // Another srong pointer exists; clone + // Another strong pointer exists; clone *this = Arc::new((**this).clone()); } else if this.inner().weak.load(Relaxed) != 1 { // Relaxed suffices in the above because this is fundamentally an diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 404c7522403..8f00605d33b 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -360,14 +360,6 @@ impl<T: ?Sized> Rc<T> { } impl<T: Clone> Rc<T> { - #[inline] - #[unstable(feature = "rc_make_unique", reason = "renamed to Rc::make_mut", - issue = "27718")] - #[rustc_deprecated(since = "1.4.0", reason = "renamed to Rc::make_mut")] - pub fn make_unique(&mut self) -> &mut T { - Rc::make_mut(self) - } - /// Make a mutable reference into the given `Rc<T>` by cloning the inner /// data if the `Rc<T>` doesn't have one strong reference and no weak /// references. diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index b8ca48ac75d..04cffeddc5f 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -230,26 +230,6 @@ impl<T: Ord> BinaryHeap<T> { BinaryHeap { data: Vec::with_capacity(capacity) } } - /// Creates a `BinaryHeap` from a vector. This is sometimes called - /// `heapifying` the vector. - /// - /// # Examples - /// - /// ``` - /// #![feature(binary_heap_extras)] - /// # #![allow(deprecated)] - /// - /// use std::collections::BinaryHeap; - /// let heap = BinaryHeap::from_vec(vec![9, 1, 2, 7, 3, 2]); - /// ``` - #[unstable(feature = "binary_heap_extras", - reason = "needs to be audited", - issue = "28147")] - #[rustc_deprecated(since = "1.5.0", reason = "use BinaryHeap::from instead")] - pub fn from_vec(vec: Vec<T>) -> BinaryHeap<T> { - BinaryHeap::from(vec) - } - /// Returns an iterator visiting all values in the underlying vector, in /// arbitrary order. /// diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 08b0a39d9b0..de9c8a2feaf 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -151,25 +151,14 @@ impl<K: Ord, V> BTreeMap<K, V> { #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] pub fn new() -> BTreeMap<K, V> { - // FIXME(Gankro): Tune this as a function of size_of<K/V>? - BTreeMap::with_b(6) - } - - /// Makes a new empty BTreeMap with the given B. - /// - /// B cannot be less than 2. - #[unstable(feature = "btree_b", - reason = "probably want this to be on the type, eventually", - issue = "27795")] - #[rustc_deprecated(since = "1.4.0", reason = "niche API")] - pub fn with_b(b: usize) -> BTreeMap<K, V> { - assert!(b > 1, "B must be greater than 1"); BTreeMap { length: 0, depth: 1, - root: Node::make_leaf_root(b), - b: b, + root: Node::make_leaf_root(6), + // FIXME(Gankro): Tune this as a function of size_of<K/V>? + b: 6, } + } /// Clears the map, removing all values. @@ -185,11 +174,9 @@ impl<K: Ord, V> BTreeMap<K, V> { /// assert!(a.is_empty()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[allow(deprecated)] pub fn clear(&mut self) { - let b = self.b; // avoid recursive destructors by manually traversing the tree - for _ in mem::replace(self, BTreeMap::with_b(b)) {} + for _ in mem::replace(self, BTreeMap::new()) {} } // Searching in a B-Tree is pretty straightforward. diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index 8d741f9e34a..a2c09c36795 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -98,18 +98,6 @@ impl<T: Ord> BTreeSet<T> { pub fn new() -> BTreeSet<T> { BTreeSet { map: BTreeMap::new() } } - - /// Makes a new BTreeSet with the given B. - /// - /// B cannot be less than 2. - #[unstable(feature = "btree_b", - reason = "probably want this to be on the type, eventually", - issue = "27795")] - #[rustc_deprecated(since = "1.4.0", reason = "niche API")] - #[allow(deprecated)] - pub fn with_b(b: usize) -> BTreeSet<T> { - BTreeSet { map: BTreeMap::with_b(b) } - } } impl<T> BTreeSet<T> { diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 6342ae5c816..9bb5ec80819 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -110,9 +110,6 @@ pub use core::slice::{Iter, IterMut}; pub use core::slice::{SplitMut, ChunksMut, Split}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut}; -#[unstable(feature = "ref_slice", issue = "27774")] -#[allow(deprecated)] -pub use core::slice::{bytes, mut_ref_slice, ref_slice}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::slice::{from_raw_parts, from_raw_parts_mut}; diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index a3c69182934..8c0b52f71f8 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -291,13 +291,23 @@ pub struct FromUtf8Error { pub struct FromUtf16Error(()); impl String { - /// Creates a new string buffer initialized with the empty string. + /// Creates a new empty `String`. + /// + /// Given that the `String` is empty, this will not allocate any initial + /// buffer. While that means that this initial operation is very + /// inexpensive, but may cause excessive allocation later, when you add + /// data. If you have an idea of how much data the `String` will hold, + /// consider the [`with_capacity()`] method to prevent excessive + /// re-allocation. + /// + /// [`with_capacity()`]: #method.with_capacity /// /// # Examples /// + /// Basic usage: + /// /// ``` - /// # #![allow(unused_mut)] - /// let mut s = String::new(); + /// let s = String::new(); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -305,12 +315,26 @@ impl String { String { vec: Vec::new() } } - /// Creates a new string buffer with the given capacity. - /// The string will be able to hold exactly `capacity` bytes without - /// reallocating. If `capacity` is 0, the string will not allocate. + /// Creates a new empty `String` with a particular capacity. + /// + /// `String`s have an internal buffer to hold their data. The capacity is + /// the length of that buffer, and can be queried with the [`capacity()`] + /// method. This method creates an empty `String`, but one with an initial + /// buffer that can hold `capacity` bytes. This is useful when you may be + /// appending a bunch of data to the `String`, reducing the number of + /// reallocations it needs to do. + /// + /// [`capacity()`]: #method.capacity + /// + /// If the given capacity is `0`, no allocation will occur, and this method + /// is identical to the [`new()`] method. + /// + /// [`new()`]: #method.new /// /// # Examples /// + /// Basic usage: + /// /// ``` /// let mut s = String::with_capacity(10); /// @@ -346,26 +370,30 @@ impl String { /// Converts a vector of bytes to a `String`. /// - /// A string slice (`&str`) is made of bytes (`u8`), and a vector of bytes - /// (`Vec<u8>`) is made of bytes, so this function converts between the + /// A string slice ([`&str`]) is made of bytes ([`u8`]), and a vector of bytes + /// ([`Vec<u8>`]) is made of bytes, so this function converts between the /// two. Not all byte slices are valid `String`s, however: `String` /// requires that it is valid UTF-8. `from_utf8()` checks to ensure that /// the bytes are valid UTF-8, and then does the conversion. /// + /// [`&str`]: ../primitive.str.html + /// [`u8`]: ../primitive.u8.html + /// [`Vec<u8>`]: ../vec/struct.Vec.html + /// /// If you are sure that the byte slice is valid UTF-8, and you don't want /// to incur the overhead of the validity check, there is an unsafe version - /// of this function, [`from_utf8_unchecked()`][fromutf8], which has the - /// same behavior but skips the check. + /// of this function, [`from_utf8_unchecked()`], which has the same behavior + /// but skips the check. /// - /// [fromutf8]: struct.String.html#method.from_utf8_unchecked + /// [`from_utf8_unchecked()`]: struct.String.html#method.from_utf8_unchecked /// /// This method will take care to not copy the vector, for efficiency's /// sake. /// /// If you need a `&str` instead of a `String`, consider - /// [`str::from_utf8()`][str]. + /// [`str::from_utf8()`]. /// - /// [str]: ../str/fn.from_utf8.html + /// [`str::from_utf8()`]: ../str/fn.from_utf8.html /// /// # Failure /// @@ -395,10 +423,10 @@ impl String { /// assert!(String::from_utf8(sparkle_heart).is_err()); /// ``` /// - /// See the docs for [`FromUtf8Error`][error] for more details on what you - /// can do with this error. + /// See the docs for [`FromUtf8Error`] for more details on what you can do + /// with this error. /// - /// [error]: struct.FromUtf8Error.html + /// [`FromUtf8Error`]: struct.FromUtf8Error.html #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn from_utf8(vec: Vec<u8>) -> Result<String, FromUtf8Error> { @@ -415,24 +443,28 @@ impl String { /// Converts a slice of bytes to a `String`, including invalid characters. /// - /// A string slice (`&str`) is made of bytes (`u8`), and a slice of bytes - /// (`&[u8]`) is made of bytes, so this function converts between the two. - /// Not all byte slices are valid string slices, however: `&str` requires - /// that it is valid UTF-8. During this conversion, `from_utf8_lossy()` - /// will replace any invalid UTF-8 sequences with + /// A string slice ([`&str`]) is made of bytes ([`u8`]), and a slice of + /// bytes ([`&[u8]`]) is made of bytes, so this function converts between + /// the two. Not all byte slices are valid string slices, however: [`&str`] + /// requires that it is valid UTF-8. During this conversion, + /// `from_utf8_lossy()` will replace any invalid UTF-8 sequences with /// `U+FFFD REPLACEMENT CHARACTER`, which looks like this: � /// + /// [`&str`]: ../primitive.str.html + /// [`u8`]: ../primitive.u8.html + /// [`&[u8]`]: ../primitive.slice.html + /// /// If you are sure that the byte slice is valid UTF-8, and you don't want /// to incur the overhead of the conversion, there is an unsafe version - /// of this function, [`from_utf8_unchecked()`][fromutf8], which has the - /// same behavior but skips the checks. + /// of this function, [`from_utf8_unchecked()`], which has the same behavior + /// but skips the checks. /// - /// [fromutf8]: struct.String.html#method.from_utf8_unchecked + /// [`from_utf8_unchecked()`]: struct.String.html#method.from_utf8_unchecked /// - /// If you need a `&str` instead of a `String`, consider - /// [`str::from_utf8()`][str]. + /// If you need a [`&str`] instead of a `String`, consider + /// [`str::from_utf8()`]. /// - /// [str]: ../str/fn.from_utf8.html + /// [`str::from_utf8()`]: ../str/fn.from_utf8.html /// /// # Examples /// @@ -576,12 +608,14 @@ impl String { /// /// # Examples /// + /// Basic usage: + /// /// ``` /// // 𝄞music /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, /// 0x0073, 0x0069, 0x0063]; - /// assert_eq!(String::from_utf16(v).unwrap(), - /// "𝄞music".to_string()); + /// assert_eq!(String::from("𝄞music"), + /// String::from_utf16(v).unwrap()); /// /// // 𝄞mu<invalid>ic /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, @@ -598,14 +632,16 @@ impl String { /// /// # Examples /// + /// Basic usage: + /// /// ``` /// // 𝄞mus<invalid>ic<invalid> /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, /// 0x0073, 0xDD1E, 0x0069, 0x0063, /// 0xD834]; /// - /// assert_eq!(String::from_utf16_lossy(v), - /// "𝄞mus\u{FFFD}ic\u{FFFD}".to_string()); + /// assert_eq!(String::from("𝄞mus\u{FFFD}ic\u{FFFD}"), + /// String::from_utf16_lossy(v)); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -617,13 +653,37 @@ impl String { /// /// # Safety /// - /// This is _very_ unsafe because: + /// This is highly unsafe, due to the number of invariants that aren't + /// checked: /// - /// * We call `Vec::from_raw_parts` to get a `Vec<u8>`. Therefore, this - /// function inherits all of its unsafety, see [its - /// documentation](../vec/struct.Vec.html#method.from_raw_parts) - /// for the invariants it expects, they also apply to this function. - /// * We assume that the `Vec` contains valid UTF-8. + /// * The memory at `ptr` needs to have been previously allocated by the + /// same allocator the standard library uses. + /// * `length` needs to be less than or equal to `capacity`. + /// * `capacity` needs to be the correct value. + /// + /// Violating these may cause problems like corrupting the allocator's + /// internal datastructures. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// use std::mem; + /// + /// unsafe { + /// let s = String::from("hello"); + /// let ptr = s.as_ptr(); + /// let len = s.len(); + /// let capacity = s.capacity(); + /// + /// mem::forget(s); + /// + /// let s = String::from_raw_parts(ptr as *mut _, len, capacity); + /// + /// assert_eq!(String::from("hello"), s); + /// } + /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts(buf: *mut u8, length: usize, capacity: usize) -> String { @@ -633,15 +693,16 @@ impl String { /// Converts a vector of bytes to a `String` without checking that the /// string contains valid UTF-8. /// - /// See the safe version, [`from_utf8()`][fromutf8], for more. + /// See the safe version, [`from_utf8()`], for more details. /// - /// [fromutf8]: struct.String.html#method.from_utf8 + /// [`from_utf8()`]: struct.String.html#method.from_utf8 /// /// # Safety /// - /// This function is unsafe because it does not check that the bytes passed to - /// it are valid UTF-8. If this constraint is violated, undefined behavior - /// results, as the rest of Rust assumes that `String`s are valid UTF-8. + /// This function is unsafe because it does not check that the bytes passed + /// to it are valid UTF-8. If this constraint is violated, it may cause + /// memory unsafety issues with future users of the `String`, as the rest of + /// the standard library assumes that `String`s are valid UTF-8. /// /// # Examples /// @@ -663,14 +724,19 @@ impl String { String { vec: bytes } } - /// Returns the underlying byte buffer, encoded as UTF-8. + /// Converts a `String` into a byte vector. + /// + /// This consumes the `String`, so we do not need to copy its contents. /// /// # Examples /// + /// Basic usage: + /// /// ``` /// let s = String::from("hello"); /// let bytes = s.into_bytes(); - /// assert_eq!(bytes, [104, 101, 108, 108, 111]); + /// + /// assert_eq!(&[104, 101, 108, 108, 111][..], &bytes[..]); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -687,14 +753,18 @@ impl String { self } - /// Pushes the given string onto this string buffer. + /// Appends a given string slice onto the end of this `String`. /// /// # Examples /// + /// Basic usage: + /// /// ``` /// let mut s = String::from("foo"); + /// /// s.push_str("bar"); - /// assert_eq!(s, "foobar"); + /// + /// assert_eq!("foobar", s); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -702,13 +772,15 @@ impl String { self.vec.extend_from_slice(string.as_bytes()) } - /// Returns the number of bytes that this string buffer can hold without - /// reallocating. + /// Returns this `String`'s capacity, in bytes. /// /// # Examples /// + /// Basic usage: + /// /// ``` /// let s = String::with_capacity(10); + /// /// assert!(s.capacity() >= 10); /// ``` #[inline] @@ -717,9 +789,16 @@ impl String { self.vec.capacity() } - /// Reserves capacity for at least `additional` more bytes to be inserted - /// in the given `String`. The collection may reserve more space to avoid - /// frequent reallocations. + /// Ensures that this `String`'s capacity is at least `additional` bytes + /// larger than its length. + /// + /// The capacity may be increased by more than `additional` bytes if it + /// chooses, to prevent frequent reallocations. + /// + /// If you do not want this "at least" behavior, see the [`reserve_exact()`] + /// method. + /// + /// [`reserve_exact()`]: #method.reserve_exact /// /// # Panics /// @@ -727,24 +806,46 @@ impl String { /// /// # Examples /// + /// Basic usage: + /// /// ``` /// let mut s = String::new(); + /// /// s.reserve(10); + /// /// assert!(s.capacity() >= 10); /// ``` + /// + /// This may not actually increase the capacity: + /// + /// ``` + /// let mut s = String::with_capacity(10); + /// s.push('a'); + /// s.push('b'); + /// + /// // s now has a length of 2 and a capacity of 10 + /// assert_eq!(2, s.len()); + /// assert_eq!(10, s.capacity()); + /// + /// // Since we already have an extra 8 capacity, calling this... + /// s.reserve(8); + /// + /// // ... doesn't actually increase. + /// assert_eq!(10, s.capacity()); + /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn reserve(&mut self, additional: usize) { self.vec.reserve(additional) } - /// Reserves the minimum capacity for exactly `additional` more bytes to be - /// inserted in the given `String`. Does nothing if the capacity is already - /// sufficient. + /// Ensures that this `String`'s capacity is `additional` bytes + /// larger than its length. /// - /// Note that the allocator may give the collection more space than it - /// requests. Therefore capacity can not be relied upon to be precisely - /// minimal. Prefer `reserve` if future insertions are expected. + /// Consider using the [`reserve()`] method unless you absolutely know + /// better than the allocator. + /// + /// [`reserve()`]: #method.reserve /// /// # Panics /// @@ -752,27 +853,53 @@ impl String { /// /// # Examples /// + /// Basic usage: + /// /// ``` /// let mut s = String::new(); + /// /// s.reserve_exact(10); + /// /// assert!(s.capacity() >= 10); /// ``` + /// + /// This may not actually increase the capacity: + /// + /// ``` + /// let mut s = String::with_capacity(10); + /// s.push('a'); + /// s.push('b'); + /// + /// // s now has a length of 2 and a capacity of 10 + /// assert_eq!(2, s.len()); + /// assert_eq!(10, s.capacity()); + /// + /// // Since we already have an extra 8 capacity, calling this... + /// s.reserve_exact(8); + /// + /// // ... doesn't actually increase. + /// assert_eq!(10, s.capacity()); + /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn reserve_exact(&mut self, additional: usize) { self.vec.reserve_exact(additional) } - /// Shrinks the capacity of this string buffer to match its length. + /// Shrinks the capacity of this `String` to match its length. /// /// # Examples /// + /// Basic usage: + /// /// ``` /// let mut s = String::from("foo"); + /// /// s.reserve(100); /// assert!(s.capacity() >= 100); + /// /// s.shrink_to_fit(); - /// assert_eq!(s.capacity(), 3); + /// assert_eq!(3, s.capacity()); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -780,16 +907,20 @@ impl String { self.vec.shrink_to_fit() } - /// Adds the given character to the end of the string. + /// Appends the given `char` to the end of this `String`. /// /// # Examples /// + /// Basic usage: + /// /// ``` /// let mut s = String::from("abc"); + /// /// s.push('1'); /// s.push('2'); /// s.push('3'); - /// assert_eq!(s, "abc123"); + /// + /// assert_eq!("abc123", s); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -815,13 +946,16 @@ impl String { } } - /// Works with the underlying buffer as a byte slice. + /// Returns a byte slice of this `String`'s contents. /// /// # Examples /// + /// Basic usage: + /// /// ``` /// let s = String::from("hello"); - /// assert_eq!(s.as_bytes(), [104, 101, 108, 108, 111]); + /// + /// assert_eq!(&[104, 101, 108, 108, 111], s.as_bytes()); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -829,19 +963,25 @@ impl String { &self.vec } - /// Shortens a string to the specified length. + /// Shortens this `String` to the specified length. /// /// # Panics /// - /// Panics if `new_len` > current length, - /// or if `new_len` is not a character boundary. + /// Panics if `new_len` > current length, or if `new_len` does not lie on a + /// [`char`] boundary. + /// + /// [`char`]: ../primitive.char.html /// /// # Examples /// + /// Basic usage: + /// /// ``` /// let mut s = String::from("hello"); + /// /// s.truncate(2); - /// assert_eq!(s, "he"); + /// + /// assert_eq!("he", s); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -851,15 +991,20 @@ impl String { } /// Removes the last character from the string buffer and returns it. - /// Returns `None` if this string buffer is empty. + /// + /// Returns `None` if this `String` is empty. /// /// # Examples /// + /// Basic usage: + /// /// ``` /// let mut s = String::from("foo"); + /// /// assert_eq!(s.pop(), Some('o')); /// assert_eq!(s.pop(), Some('o')); /// assert_eq!(s.pop(), Some('f')); + /// /// assert_eq!(s.pop(), None); /// ``` #[inline] @@ -877,23 +1022,25 @@ impl String { Some(ch) } - /// Removes the character from the string buffer at byte position `idx` and - /// returns it. - /// - /// # Warning + /// Removes a `char` from this `String` at a byte position and returns it. /// - /// This is an O(n) operation as it requires copying every element in the + /// This is an `O(n)` operation, as it requires copying every element in the /// buffer. /// /// # Panics /// - /// If `idx` does not lie on a character boundary, or if it is out of - /// bounds, then this function will panic. + /// Panics if `idx` is larger than the `String`'s length, or if it does not + /// lie on a [`char`] boundary. + /// + /// [`char`]: ../primitive.char.html /// /// # Examples /// + /// Basic usage: + /// /// ``` /// let mut s = String::from("foo"); + /// /// assert_eq!(s.remove(0), 'f'); /// assert_eq!(s.remove(1), 'o'); /// assert_eq!(s.remove(0), 'o'); @@ -915,17 +1062,31 @@ impl String { ch } - /// Inserts a character into the string buffer at byte position `idx`. + /// Inserts a character into this `String` at a byte position. /// - /// # Warning - /// - /// This is an O(n) operation as it requires copying every element in the + /// This is an `O(n)` operation as it requires copying every element in the /// buffer. /// /// # Panics /// - /// If `idx` does not lie on a character boundary or is out of bounds, then - /// this function will panic. + /// Panics if `idx` is larger than the `String`'s length, or if it does not + /// lie on a [`char`] boundary. + /// + /// [`char`]: ../primitive.char.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let mut s = String::with_capacity(3); + /// + /// s.insert(0, 'f'); + /// s.insert(1, 'o'); + /// s.insert(2, 'o'); + /// + /// assert_eq!("foo", s); + /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn insert(&mut self, idx: usize, ch: char) { @@ -947,18 +1108,26 @@ impl String { } } - /// Views the string buffer as a mutable sequence of bytes. + /// Returns a mutable reference to the contents of this `String`. /// - /// This is unsafe because it does not check - /// to ensure that the resulting string will be valid UTF-8. + /// # Safety + /// + /// This function is unsafe because it does not check that the bytes passed + /// to it are valid UTF-8. If this constraint is violated, it may cause + /// memory unsafety issues with future users of the `String`, as the rest of + /// the standard library assumes that `String`s are valid UTF-8. /// /// # Examples /// + /// Basic usage: + /// /// ``` /// let mut s = String::from("hello"); + /// /// unsafe { /// let vec = s.as_mut_vec(); - /// assert!(vec == &[104, 101, 108, 108, 111]); + /// assert_eq!(&[104, 101, 108, 108, 111][..], &vec[..]); + /// /// vec.reverse(); /// } /// assert_eq!(s, "olleh"); @@ -969,12 +1138,15 @@ impl String { &mut self.vec } - /// Returns the number of bytes in this string. + /// Returns the length of this `String`, in bytes. /// /// # Examples /// + /// Basic usage: + /// /// ``` - /// let a = "foo".to_string(); + /// let a = String::from("foo"); + /// /// assert_eq!(a.len(), 3); /// ``` #[inline] @@ -983,13 +1155,18 @@ impl String { self.vec.len() } - /// Returns true if the string contains no bytes + /// Returns `true` if this `String` has a length of zero. + /// + /// Returns `false` otherwise. /// /// # Examples /// + /// Basic usage: + /// /// ``` /// let mut v = String::new(); /// assert!(v.is_empty()); + /// /// v.push('a'); /// assert!(!v.is_empty()); /// ``` @@ -999,14 +1176,23 @@ impl String { self.len() == 0 } - /// Truncates the string, returning it to 0 length. + /// Truncates this `String`, removing all contents. + /// + /// While this means the `String` will have a length of zero, it does not + /// touch its capacity. /// /// # Examples /// + /// Basic usage: + /// /// ``` - /// let mut s = "foo".to_string(); + /// let mut s = String::from("foo"); + /// /// s.clear(); + /// /// assert!(s.is_empty()); + /// assert_eq!(0, s.len()); + /// assert_eq!(3, s.capacity()); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -1020,11 +1206,15 @@ impl String { /// /// # Panics /// - /// Panics if the starting point or end point are not on character boundaries, - /// or if they are out of bounds. + /// Panics if the starting point or end point do not lie on a [`char`] + /// boundary, or if they're out of bounds. + /// + /// [`char`]: ../primitive.char.html /// /// # Examples /// + /// Basic usage: + /// /// ``` /// let mut s = String::from("α is alpha, β is beta"); /// let beta_offset = s.find('β').unwrap_or(s.len()); @@ -1066,25 +1256,24 @@ impl String { } } - /// Converts the string into `Box<str>`. + /// Converts this `String` into a `Box<str>`. + /// + /// This will drop any excess capacity. + /// + /// # Examples /// - /// Note that this will drop any excess capacity. + /// Basic usage: + /// + /// ``` + /// let s = String::from("hello"); + /// + /// let b = s.into_boxed_str(); + /// ``` #[stable(feature = "box_str", since = "1.4.0")] pub fn into_boxed_str(self) -> Box<str> { let slice = self.vec.into_boxed_slice(); unsafe { mem::transmute::<Box<[u8]>, Box<str>>(slice) } } - - /// Converts the string into `Box<str>`. - /// - /// Note that this will drop any excess capacity. - #[unstable(feature = "box_str2", - reason = "recently added, matches RFC", - issue = "27785")] - #[rustc_deprecated(since = "1.4.0", reason = "renamed to `into_boxed_str`")] - pub fn into_boxed_slice(self) -> Box<str> { - self.into_boxed_str() - } } impl FromUtf8Error { diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index 53597f566b8..0ca4ce2dddf 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -1115,15 +1115,6 @@ impl<T> VecDeque<T> { self.pop_back() } - /// deprecated - #[unstable(feature = "deque_extras", - reason = "the naming of this function may be altered", - issue = "27788")] - #[rustc_deprecated(since = "1.5.0", reason = "renamed to swap_remove_back")] - pub fn swap_back_remove(&mut self, index: usize) -> Option<T> { - self.swap_remove_back(index) - } - /// Removes an element from anywhere in the `VecDeque` and returns it, /// replacing it with the first element. /// @@ -1158,15 +1149,6 @@ impl<T> VecDeque<T> { self.pop_front() } - /// deprecated - #[unstable(feature = "deque_extras", - reason = "the naming of this function may be altered", - issue = "27788")] - #[rustc_deprecated(since = "1.5.0", reason = "renamed to swap_remove_front")] - pub fn swap_front_remove(&mut self, index: usize) -> Option<T> { - self.swap_remove_front(index) - } - /// Inserts an element at `index` within the `VecDeque`. 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. @@ -2178,7 +2160,7 @@ mod tests { tester.push_front(i); } for i in 0..len { - assert_eq!(tester.swap_back_remove(i), Some(len * 2 - 1 - i)); + assert_eq!(tester.swap_remove_back(i), Some(len * 2 - 1 - i)); } } else { for i in 0..len * 2 { @@ -2186,7 +2168,7 @@ mod tests { } for i in 0..len { let idx = tester.len() - 1 - i; - assert_eq!(tester.swap_front_remove(idx), Some(len * 2 - 1 - i)); + assert_eq!(tester.swap_remove_front(idx), Some(len * 2 - 1 - i)); } } assert!(tester.tail < tester.cap()); diff --git a/src/libcollectionstest/binary_heap.rs b/src/libcollectionstest/binary_heap.rs index 303a0ce811d..cc4366e8ae4 100644 --- a/src/libcollectionstest/binary_heap.rs +++ b/src/libcollectionstest/binary_heap.rs @@ -14,7 +14,7 @@ use std::collections::BinaryHeap; fn test_iterator() { let data = vec![5, 9, 3]; let iterout = [9, 5, 3]; - let heap = BinaryHeap::from_vec(data); + let heap = BinaryHeap::from(data); let mut i = 0; for el in &heap { assert_eq!(*el, iterout[i]); @@ -26,7 +26,7 @@ fn test_iterator() { fn test_iterator_reverse() { let data = vec![5, 9, 3]; let iterout = vec![3, 5, 9]; - let pq = BinaryHeap::from_vec(data); + let pq = BinaryHeap::from(data); let v: Vec<_> = pq.iter().rev().cloned().collect(); assert_eq!(v, iterout); @@ -36,7 +36,7 @@ fn test_iterator_reverse() { fn test_move_iter() { let data = vec![5, 9, 3]; let iterout = vec![9, 5, 3]; - let pq = BinaryHeap::from_vec(data); + let pq = BinaryHeap::from(data); let v: Vec<_> = pq.into_iter().collect(); assert_eq!(v, iterout); @@ -45,7 +45,7 @@ fn test_move_iter() { #[test] fn test_move_iter_size_hint() { let data = vec![5, 9]; - let pq = BinaryHeap::from_vec(data); + let pq = BinaryHeap::from(data); let mut it = pq.into_iter(); @@ -63,7 +63,7 @@ fn test_move_iter_size_hint() { fn test_move_iter_reverse() { let data = vec![5, 9, 3]; let iterout = vec![3, 5, 9]; - let pq = BinaryHeap::from_vec(data); + let pq = BinaryHeap::from(data); let v: Vec<_> = pq.into_iter().rev().collect(); assert_eq!(v, iterout); @@ -74,7 +74,7 @@ fn test_peek_and_pop() { let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]; let mut sorted = data.clone(); sorted.sort(); - let mut heap = BinaryHeap::from_vec(data); + let mut heap = BinaryHeap::from(data); while !heap.is_empty() { assert_eq!(heap.peek().unwrap(), sorted.last().unwrap()); assert_eq!(heap.pop().unwrap(), sorted.pop().unwrap()); @@ -83,7 +83,7 @@ fn test_peek_and_pop() { #[test] fn test_push() { - let mut heap = BinaryHeap::from_vec(vec![2, 4, 9]); + let mut heap = BinaryHeap::from(vec![2, 4, 9]); assert_eq!(heap.len(), 3); assert!(*heap.peek().unwrap() == 9); heap.push(11); @@ -105,7 +105,7 @@ fn test_push() { #[test] fn test_push_unique() { - let mut heap = BinaryHeap::<Box<_>>::from_vec(vec![box 2, box 4, box 9]); + let mut heap = BinaryHeap::<Box<_>>::from(vec![box 2, box 4, box 9]); assert_eq!(heap.len(), 3); assert!(*heap.peek().unwrap() == box 9); heap.push(box 11); @@ -127,7 +127,7 @@ fn test_push_unique() { #[test] fn test_push_pop() { - let mut heap = BinaryHeap::from_vec(vec![5, 5, 2, 1, 3]); + let mut heap = BinaryHeap::from(vec![5, 5, 2, 1, 3]); assert_eq!(heap.len(), 5); assert_eq!(heap.push_pop(6), 6); assert_eq!(heap.len(), 5); @@ -141,7 +141,7 @@ fn test_push_pop() { #[test] fn test_replace() { - let mut heap = BinaryHeap::from_vec(vec![5, 5, 2, 1, 3]); + let mut heap = BinaryHeap::from(vec![5, 5, 2, 1, 3]); assert_eq!(heap.len(), 5); assert_eq!(heap.replace(6).unwrap(), 5); assert_eq!(heap.len(), 5); @@ -154,7 +154,7 @@ fn test_replace() { } fn check_to_vec(mut data: Vec<i32>) { - let heap = BinaryHeap::from_vec(data.clone()); + let heap = BinaryHeap::from(data.clone()); let mut v = heap.clone().into_vec(); v.sort(); data.sort(); diff --git a/src/libcollectionstest/btree/map.rs b/src/libcollectionstest/btree/map.rs index 846353cc4e7..dfb72d78d46 100644 --- a/src/libcollectionstest/btree/map.rs +++ b/src/libcollectionstest/btree/map.rs @@ -11,7 +11,6 @@ use std::collections::BTreeMap; use std::collections::Bound::{Excluded, Included, Unbounded, self}; use std::collections::btree_map::Entry::{Occupied, Vacant}; -use std::iter::range_inclusive; use std::rc::Rc; #[test] @@ -188,7 +187,7 @@ fn test_range() { for i in 0..size { for j in i..size { let mut kvs = map.range(Included(&i), Included(&j)).map(|(&k, &v)| (k, v)); - let mut pairs = range_inclusive(i, j).map(|i| (i, i)); + let mut pairs = (i..j+1).map(|i| (i, i)); for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) { assert_eq!(kv, pair); diff --git a/src/libcollectionstest/slice.rs b/src/libcollectionstest/slice.rs index 80dcd48fbfa..f86c016921e 100644 --- a/src/libcollectionstest/slice.rs +++ b/src/libcollectionstest/slice.rs @@ -867,17 +867,6 @@ fn test_vec_default() { } #[test] -fn test_bytes_set_memory() { - use std::slice::bytes::MutableByteVector; - - let mut values = [1,2,3,4,5]; - values[0..5].set_memory(0xAB); - assert!(values == [0xAB, 0xAB, 0xAB, 0xAB, 0xAB]); - values[2..4].set_memory(0xFF); - assert!(values == [0xAB, 0xAB, 0xFF, 0xFF, 0xAB]); -} - -#[test] #[should_panic] fn test_overflow_does_not_cause_segfault() { let mut v = vec![]; diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 959b6a97c5c..f063c6b0676 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -4750,87 +4750,3 @@ impl<T> ExactSizeIterator for Once<T> { pub fn once<T>(value: T) -> Once<T> { Once { inner: Some(value).into_iter() } } - -/// Functions for lexicographical ordering of sequences. -/// -/// Lexicographical ordering through `<`, `<=`, `>=`, `>` requires -/// that the elements implement both `PartialEq` and `PartialOrd`. -/// -/// If two sequences are equal up until the point where one ends, -/// the shorter sequence compares less. -#[rustc_deprecated(since = "1.4.0", reason = "use the equivalent methods on `Iterator` instead")] -#[unstable(feature = "iter_order_deprecated", reason = "needs review and revision", - issue = "27737")] -pub mod order { - use cmp; - use cmp::{Eq, Ord, PartialOrd, PartialEq}; - use option::Option; - use super::Iterator; - - /// Compare `a` and `b` for equality using `Eq` - pub fn equals<A, L, R>(a: L, b: R) -> bool where - A: Eq, - L: Iterator<Item=A>, - R: Iterator<Item=A>, - { - a.eq(b) - } - - /// Order `a` and `b` lexicographically using `Ord` - pub fn cmp<A, L, R>(a: L, b: R) -> cmp::Ordering where - A: Ord, - L: Iterator<Item=A>, - R: Iterator<Item=A>, - { - a.cmp(b) - } - - /// Order `a` and `b` lexicographically using `PartialOrd` - pub fn partial_cmp<L: Iterator, R: Iterator>(a: L, b: R) -> Option<cmp::Ordering> where - L::Item: PartialOrd<R::Item> - { - a.partial_cmp(b) - } - - /// Compare `a` and `b` for equality (Using partial equality, `PartialEq`) - pub fn eq<L: Iterator, R: Iterator>(a: L, b: R) -> bool where - L::Item: PartialEq<R::Item>, - { - a.eq(b) - } - - /// Compares `a` and `b` for nonequality (Using partial equality, `PartialEq`) - pub fn ne<L: Iterator, R: Iterator>(a: L, b: R) -> bool where - L::Item: PartialEq<R::Item>, - { - a.ne(b) - } - - /// Returns `a` < `b` lexicographically (Using partial order, `PartialOrd`) - pub fn lt<L: Iterator, R: Iterator>(a: L, b: R) -> bool where - L::Item: PartialOrd<R::Item>, - { - a.lt(b) - } - - /// Returns `a` <= `b` lexicographically (Using partial order, `PartialOrd`) - pub fn le<L: Iterator, R: Iterator>(a: L, b: R) -> bool where - L::Item: PartialOrd<R::Item>, - { - a.le(b) - } - - /// Returns `a` > `b` lexicographically (Using partial order, `PartialOrd`) - pub fn gt<L: Iterator, R: Iterator>(a: L, b: R) -> bool where - L::Item: PartialOrd<R::Item>, - { - a.gt(b) - } - - /// Returns `a` >= `b` lexicographically (Using partial order, `PartialOrd`) - pub fn ge<L: Iterator, R: Iterator>(a: L, b: R) -> bool where - L::Item: PartialOrd<R::Item>, - { - a.ge(b) - } -} diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 86f2e3bcec3..454e2b02b1c 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -153,12 +153,6 @@ pub mod option; pub mod raw; pub mod result; -#[cfg(stage0)] -#[path = "simd_old.rs"] -pub mod simd; -#[cfg(not(stage0))] -pub mod simd; - pub mod slice; pub mod str; pub mod hash; diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 359d15640f9..8af1022acdf 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -15,11 +15,9 @@ #![stable(feature = "rust1", since = "1.0.0")] -use prelude::v1::*; - use intrinsics; use mem; -use num::{Float, ParseFloatError}; +use num::Float; use num::FpCategory as Fp; #[stable(feature = "rust1", since = "1.0.0")] @@ -163,8 +161,6 @@ impl Float for f32 { #[inline] fn one() -> f32 { 1.0 } - from_str_radix_float_impl! { f32 } - /// Returns `true` if the number is NaN. #[inline] fn is_nan(self) -> bool { self != self } diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 1a6acc5f4ab..9486e4337bf 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -15,12 +15,10 @@ #![stable(feature = "rust1", since = "1.0.0")] -use prelude::v1::*; - use intrinsics; use mem; use num::FpCategory as Fp; -use num::{Float, ParseFloatError}; +use num::Float; #[stable(feature = "rust1", since = "1.0.0")] #[allow(missing_docs)] @@ -163,8 +161,6 @@ impl Float for f64 { #[inline] fn one() -> f64 { 1.0 } - from_str_radix_float_impl! { f64 } - /// Returns `true` if the number is NaN. #[inline] fn is_nan(self) -> bool { self != self } diff --git a/src/libcore/num/float_macros.rs b/src/libcore/num/float_macros.rs index 88c3b756793..b3adef53dab 100644 --- a/src/libcore/num/float_macros.rs +++ b/src/libcore/num/float_macros.rs @@ -18,144 +18,3 @@ macro_rules! assert_approx_eq { "{} is not approximately equal to {}", *a, *b); }) } - -macro_rules! from_str_radix_float_impl { - ($T:ty) => { - fn from_str_radix(src: &str, radix: u32) - -> Result<$T, ParseFloatError> { - use num::dec2flt::{pfe_empty, pfe_invalid}; - - // Special values - match src { - "inf" => return Ok(Float::infinity()), - "-inf" => return Ok(Float::neg_infinity()), - "NaN" => return Ok(Float::nan()), - _ => {}, - } - - let (is_positive, src) = match src.slice_shift_char() { - None => return Err(pfe_empty()), - Some(('-', "")) => return Err(pfe_empty()), - Some(('-', src)) => (false, src), - Some((_, _)) => (true, src), - }; - - // The significand to accumulate - let mut sig = if is_positive { 0.0 } else { -0.0 }; - // Necessary to detect overflow - let mut prev_sig = sig; - let mut cs = src.chars().enumerate(); - // Exponent prefix and exponent index offset - let mut exp_info = None::<(char, usize)>; - - // Parse the integer part of the significand - for (i, c) in cs.by_ref() { - match c.to_digit(radix) { - Some(digit) => { - // shift significand one digit left - sig = sig * (radix as $T); - - // add/subtract current digit depending on sign - if is_positive { - sig = sig + ((digit as isize) as $T); - } else { - sig = sig - ((digit as isize) as $T); - } - - // Detect overflow by comparing to last value, except - // if we've not seen any non-zero digits. - if prev_sig != 0.0 { - if is_positive && sig <= prev_sig - { return Ok(Float::infinity()); } - if !is_positive && sig >= prev_sig - { return Ok(Float::neg_infinity()); } - - // Detect overflow by reversing the shift-and-add process - if is_positive && (prev_sig != (sig - digit as $T) / radix as $T) - { return Ok(Float::infinity()); } - if !is_positive && (prev_sig != (sig + digit as $T) / radix as $T) - { return Ok(Float::neg_infinity()); } - } - prev_sig = sig; - }, - None => match c { - 'e' | 'E' | 'p' | 'P' => { - exp_info = Some((c, i + 1)); - break; // start of exponent - }, - '.' => { - break; // start of fractional part - }, - _ => { - return Err(pfe_invalid()) - }, - }, - } - } - - // If we are not yet at the exponent parse the fractional - // part of the significand - if exp_info.is_none() { - let mut power = 1.0; - for (i, c) in cs.by_ref() { - match c.to_digit(radix) { - Some(digit) => { - // Decrease power one order of magnitude - power = power / (radix as $T); - // add/subtract current digit depending on sign - sig = if is_positive { - sig + (digit as $T) * power - } else { - sig - (digit as $T) * power - }; - // Detect overflow by comparing to last value - if is_positive && sig < prev_sig - { return Ok(Float::infinity()); } - if !is_positive && sig > prev_sig - { return Ok(Float::neg_infinity()); } - prev_sig = sig; - }, - None => match c { - 'e' | 'E' | 'p' | 'P' => { - exp_info = Some((c, i + 1)); - break; // start of exponent - }, - _ => { - return Err(pfe_invalid()) - }, - }, - } - } - } - - // Parse and calculate the exponent - let exp = match exp_info { - Some((c, offset)) => { - let base = match c { - 'E' | 'e' if radix == 10 => 10.0, - 'P' | 'p' if radix == 16 => 2.0, - _ => return Err(pfe_invalid()), - }; - - // Parse the exponent as decimal integer - let src = &src[offset..]; - let (is_positive, exp) = match src.slice_shift_char() { - Some(('-', src)) => (false, src.parse::<usize>()), - Some(('+', src)) => (true, src.parse::<usize>()), - Some((_, _)) => (true, src.parse::<usize>()), - None => return Err(pfe_invalid()), - }; - - match (is_positive, exp) { - (true, Ok(exp)) => base.powi(exp as i32), - (false, Ok(exp)) => 1.0 / base.powi(exp as i32), - (_, Err(_)) => return Err(pfe_invalid()), - } - }, - None => 1.0, // no exponent - }; - - Ok(sig * exp) - } - } -} diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index e1e5c01adb7..4f3c1256709 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1771,12 +1771,6 @@ pub trait Float: Sized { #[unstable(feature = "float_extras", reason = "needs removal", issue = "27752")] fn one() -> Self; - /// Parses the string `s` with the radix `r` as a float. - #[unstable(feature = "float_from_str_radix", reason = "recently moved API", - issue = "27736")] - #[rustc_deprecated(since = "1.4.0", - reason = "unclear how useful or correct this is")] - fn from_str_radix(s: &str, r: u32) -> Result<Self, ParseFloatError>; /// Returns true if this value is NaN and false otherwise. #[stable(feature = "core", since = "1.6.0")] diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 209cebeaf1b..aca36d85626 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -154,7 +154,6 @@ use mem; use ops::FnOnce; use result::Result::{Ok, Err}; use result::Result; -use slice; // Note that this is not a lang item per se, but it has a hidden dependency on // `Iterator`, which is one. The compiler assumes that the `next` method of @@ -269,47 +268,11 @@ impl<T> Option<T> { } } - /// Converts from `Option<T>` to `&mut [T]` (without copying) - /// - /// # Examples - /// - /// ``` - /// #![feature(as_slice)] - /// # #![allow(deprecated)] - /// - /// let mut x = Some("Diamonds"); - /// { - /// let v = x.as_mut_slice(); - /// assert!(v == ["Diamonds"]); - /// v[0] = "Dirt"; - /// assert!(v == ["Dirt"]); - /// } - /// assert_eq!(x, Some("Dirt")); - /// ``` - #[inline] - #[unstable(feature = "as_slice", - reason = "waiting for mut conventions", - issue = "27776")] - #[rustc_deprecated(since = "1.4.0", reason = "niche API, unclear of usefulness")] - #[allow(deprecated)] - pub fn as_mut_slice(&mut self) -> &mut [T] { - match *self { - Some(ref mut x) => { - let result: &mut [T] = slice::mut_ref_slice(x); - result - } - None => { - let result: &mut [T] = &mut []; - result - } - } - } - ///////////////////////////////////////////////////////////////////////// // Getting to contained values ///////////////////////////////////////////////////////////////////////// - /// Unwraps an option, yielding the content of a `Some` + /// Unwraps an option, yielding the content of a `Some`. /// /// # Panics /// @@ -690,22 +653,6 @@ impl<T> Option<T> { pub fn take(&mut self) -> Option<T> { mem::replace(self, None) } - - /// Converts from `Option<T>` to `&[T]` (without copying) - #[inline] - #[unstable(feature = "as_slice", reason = "unsure of the utility here", - issue = "27776")] - #[rustc_deprecated(since = "1.4.0", reason = "niche API, unclear of usefulness")] - #[allow(deprecated)] - pub fn as_slice(&self) -> &[T] { - match *self { - Some(ref x) => slice::ref_slice(x), - None => { - let result: &[_] = &[]; - result - } - } - } } impl<'a, T: Clone> Option<&'a T> { diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 37c40f96b0f..015887e3772 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -240,7 +240,6 @@ use fmt; use iter::{Iterator, DoubleEndedIterator, FromIterator, ExactSizeIterator, IntoIterator}; use ops::FnOnce; use option::Option::{self, None, Some}; -use slice; /// `Result` is a type that represents either success (`Ok`) or failure (`Err`). /// @@ -406,58 +405,6 @@ impl<T, E> Result<T, E> { } } - /// Converts from `Result<T, E>` to `&[T]` (without copying) - #[inline] - #[unstable(feature = "as_slice", reason = "unsure of the utility here", - issue = "27776")] - #[rustc_deprecated(since = "1.4.0", reason = "niche API, unclear of usefulness")] - #[allow(deprecated)] - pub fn as_slice(&self) -> &[T] { - match *self { - Ok(ref x) => slice::ref_slice(x), - Err(_) => { - // work around lack of implicit coercion from fixed-size array to slice - let emp: &[_] = &[]; - emp - } - } - } - - /// Converts from `Result<T, E>` to `&mut [T]` (without copying) - /// - /// ``` - /// #![feature(as_slice)] - /// # #![allow(deprecated)] - /// - /// let mut x: Result<&str, u32> = Ok("Gold"); - /// { - /// let v = x.as_mut_slice(); - /// assert!(v == ["Gold"]); - /// v[0] = "Silver"; - /// assert!(v == ["Silver"]); - /// } - /// assert_eq!(x, Ok("Silver")); - /// - /// let mut x: Result<&str, u32> = Err(45); - /// assert!(x.as_mut_slice().is_empty()); - /// ``` - #[inline] - #[unstable(feature = "as_slice", - reason = "waiting for mut conventions", - issue = "27776")] - #[rustc_deprecated(since = "1.4.0", reason = "niche API, unclear of usefulness")] - #[allow(deprecated)] - pub fn as_mut_slice(&mut self) -> &mut [T] { - match *self { - Ok(ref mut x) => slice::mut_ref_slice(x), - Err(_) => { - // work around lack of implicit coercion from fixed-size array to slice - let emp: &mut [_] = &mut []; - emp - } - } - } - ///////////////////////////////////////////////////////////////////////// // Transforming contained values ///////////////////////////////////////////////////////////////////////// @@ -744,6 +691,8 @@ impl<T, E: fmt::Debug> Result<T, E> { /// Unwraps a result, yielding the content of an `Ok`. /// + /// # Panics + /// /// Panics if the value is an `Err`, with a panic message including the /// passed message, and the content of the `Err`. /// diff --git a/src/libcore/simd.rs b/src/libcore/simd.rs deleted file mode 100644 index 697f96ddefb..00000000000 --- a/src/libcore/simd.rs +++ /dev/null @@ -1,143 +0,0 @@ -// 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. - -//! SIMD vectors. -//! -//! These types can be used for accessing basic SIMD operations. Currently -//! comparison operators are not implemented. To use SSE3+, you must enable -//! the features, like `-C target-feature=sse3,sse4.1,sse4.2`, or a more -//! specific `target-cpu`. No other SIMD intrinsics or high-level wrappers are -//! provided beyond this module. -//! -//! # Stability Note -//! -//! These are all experimental. The interface may change entirely, without -//! warning. - -#![unstable(feature = "core_simd", - reason = "needs an RFC to flesh out the design", - issue = "27731")] -#![rustc_deprecated(since = "1.3.0", - reason = "use the external `simd` crate instead")] - -#![allow(non_camel_case_types)] -#![allow(missing_docs)] -#![allow(deprecated)] - -use ops::{Add, Sub, Mul, Div, Shl, Shr, BitAnd, BitOr, BitXor}; - -// FIXME(stage0): the contents of macro can be inlined. -// ABIs are verified as valid as soon as they are parsed, i.e. before -// `cfg` stripping. The `platform-intrinsic` ABI is new, so stage0 -// doesn't know about it, but it still errors out when it hits it -// (despite this being in a `cfg(not(stage0))` module). -macro_rules! argh { - () => { - extern "platform-intrinsic" { - fn simd_add<T>(x: T, y: T) -> T; - fn simd_sub<T>(x: T, y: T) -> T; - fn simd_mul<T>(x: T, y: T) -> T; - fn simd_div<T>(x: T, y: T) -> T; - fn simd_shl<T>(x: T, y: T) -> T; - fn simd_shr<T>(x: T, y: T) -> T; - fn simd_and<T>(x: T, y: T) -> T; - fn simd_or<T>(x: T, y: T) -> T; - fn simd_xor<T>(x: T, y: T) -> T; - } - } -} -argh!(); - -#[repr(simd)] -#[derive(Copy, Clone, Debug)] -#[repr(C)] -pub struct i8x16(pub i8, pub i8, pub i8, pub i8, - pub i8, pub i8, pub i8, pub i8, - pub i8, pub i8, pub i8, pub i8, - pub i8, pub i8, pub i8, pub i8); - -#[repr(simd)] -#[derive(Copy, Clone, Debug)] -#[repr(C)] -pub struct i16x8(pub i16, pub i16, pub i16, pub i16, - pub i16, pub i16, pub i16, pub i16); - -#[repr(simd)] -#[derive(Copy, Clone, Debug)] -#[repr(C)] -pub struct i32x4(pub i32, pub i32, pub i32, pub i32); - -#[repr(simd)] -#[derive(Copy, Clone, Debug)] -#[repr(C)] -pub struct i64x2(pub i64, pub i64); - -#[repr(simd)] -#[derive(Copy, Clone, Debug)] -#[repr(C)] -pub struct u8x16(pub u8, pub u8, pub u8, pub u8, - pub u8, pub u8, pub u8, pub u8, - pub u8, pub u8, pub u8, pub u8, - pub u8, pub u8, pub u8, pub u8); - -#[repr(simd)] -#[derive(Copy, Clone, Debug)] -#[repr(C)] -pub struct u16x8(pub u16, pub u16, pub u16, pub u16, - pub u16, pub u16, pub u16, pub u16); - -#[repr(simd)] -#[derive(Copy, Clone, Debug)] -#[repr(C)] -pub struct u32x4(pub u32, pub u32, pub u32, pub u32); - -#[repr(simd)] -#[derive(Copy, Clone, Debug)] -#[repr(C)] -pub struct u64x2(pub u64, pub u64); - -#[repr(simd)] -#[derive(Copy, Clone, Debug)] -#[repr(C)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); - -#[repr(simd)] -#[derive(Copy, Clone, Debug)] -#[repr(C)] -pub struct f64x2(pub f64, pub f64); - -macro_rules! impl_traits { - ($($trayt: ident, $method: ident, $func: ident: $($ty: ty),*;)*) => { - $($( - impl $trayt<$ty> for $ty { - type Output = Self; - fn $method(self, other: Self) -> Self { - unsafe { - $func(self, other) - } - } - } - )*)* - } -} - -impl_traits! { - Add, add, simd_add: u8x16, u16x8, u32x4, u64x2, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2; - Sub, sub, simd_sub: u8x16, u16x8, u32x4, u64x2, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2; - Mul, mul, simd_mul: u8x16, u16x8, u32x4, u64x2, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2; - - Div, div, simd_div: f32x4, f64x2; - - Shl, shl, simd_shl: u8x16, u16x8, u32x4, u64x2, i8x16, i16x8, i32x4, i64x2; - Shr, shr, simd_shr: u8x16, u16x8, u32x4, u64x2, i8x16, i16x8, i32x4, i64x2; - BitAnd, bitand, simd_and: u8x16, u16x8, u32x4, u64x2, i8x16, i16x8, i32x4, i64x2; - BitOr, bitor, simd_or: u8x16, u16x8, u32x4, u64x2, i8x16, i16x8, i32x4, i64x2; - BitXor, bitxor, simd_xor: u8x16, u16x8, u32x4, u64x2, i8x16, i16x8, i32x4, i64x2; -} diff --git a/src/libcore/simd_old.rs b/src/libcore/simd_old.rs deleted file mode 100644 index 7ecd08bea35..00000000000 --- a/src/libcore/simd_old.rs +++ /dev/null @@ -1,98 +0,0 @@ -// 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. - -//! SIMD vectors. -//! -//! These types can be used for accessing basic SIMD operations. Each of them -//! implements the standard arithmetic operator traits (Add, Sub, Mul, Div, -//! Rem, Shl, Shr) through compiler magic, rather than explicitly. Currently -//! comparison operators are not implemented. To use SSE3+, you must enable -//! the features, like `-C target-feature=sse3,sse4.1,sse4.2`, or a more -//! specific `target-cpu`. No other SIMD intrinsics or high-level wrappers are -//! provided beyond this module. -//! -//! ```rust -//! # #![feature(core_simd)] -//! fn main() { -//! use std::simd::f32x4; -//! let a = f32x4(40.0, 41.0, 42.0, 43.0); -//! let b = f32x4(1.0, 1.1, 3.4, 9.8); -//! println!("{:?}", a + b); -//! } -//! ``` -//! -//! # Stability Note -//! -//! These are all experimental. The interface may change entirely, without -//! warning. - -#![unstable(feature = "core_simd", - reason = "needs an RFC to flesh out the design")] - -#![allow(non_camel_case_types)] -#![allow(missing_docs)] - -#[simd] -#[derive(Copy, Clone, Debug)] -#[repr(C)] -pub struct i8x16(pub i8, pub i8, pub i8, pub i8, - pub i8, pub i8, pub i8, pub i8, - pub i8, pub i8, pub i8, pub i8, - pub i8, pub i8, pub i8, pub i8); - -#[simd] -#[derive(Copy, Clone, Debug)] -#[repr(C)] -pub struct i16x8(pub i16, pub i16, pub i16, pub i16, - pub i16, pub i16, pub i16, pub i16); - -#[simd] -#[derive(Copy, Clone, Debug)] -#[repr(C)] -pub struct i32x4(pub i32, pub i32, pub i32, pub i32); - -#[simd] -#[derive(Copy, Clone, Debug)] -#[repr(C)] -pub struct i64x2(pub i64, pub i64); - -#[simd] -#[derive(Copy, Clone, Debug)] -#[repr(C)] -pub struct u8x16(pub u8, pub u8, pub u8, pub u8, - pub u8, pub u8, pub u8, pub u8, - pub u8, pub u8, pub u8, pub u8, - pub u8, pub u8, pub u8, pub u8); - -#[simd] -#[derive(Copy, Clone, Debug)] -#[repr(C)] -pub struct u16x8(pub u16, pub u16, pub u16, pub u16, - pub u16, pub u16, pub u16, pub u16); - -#[simd] -#[derive(Copy, Clone, Debug)] -#[repr(C)] -pub struct u32x4(pub u32, pub u32, pub u32, pub u32); - -#[simd] -#[derive(Copy, Clone, Debug)] -#[repr(C)] -pub struct u64x2(pub u64, pub u64); - -#[simd] -#[derive(Copy, Clone, Debug)] -#[repr(C)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); - -#[simd] -#[derive(Copy, Clone, Debug)] -#[repr(C)] -pub struct f64x2(pub f64, pub f64); diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 70175086147..b17fac4d771 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -1380,24 +1380,6 @@ impl<'a, T> ExactSizeIterator for ChunksMut<'a, T> {} // Free functions // -/// Converts a reference to A into a slice of length 1 (without copying). -#[unstable(feature = "ref_slice", issue = "27774")] -#[rustc_deprecated(since = "1.5.0", reason = "unclear whether belongs in libstd")] -pub fn ref_slice<A>(s: &A) -> &[A] { - unsafe { - from_raw_parts(s, 1) - } -} - -/// Converts a reference to A into a slice of length 1 (without copying). -#[unstable(feature = "ref_slice", issue = "27774")] -#[rustc_deprecated(since = "1.5.0", reason = "unclear whether belongs in libstd")] -pub fn mut_ref_slice<A>(s: &mut A) -> &mut [A] { - unsafe { - from_raw_parts_mut(s, 1) - } -} - /// Forms a slice from a pointer and a length. /// /// The `len` argument is the number of **elements**, not the number of bytes. diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs index 9def44191db..ba308314e9e 100644 --- a/src/libcoretest/iter.rs +++ b/src/libcoretest/iter.rs @@ -830,18 +830,6 @@ fn test_range() { } #[test] -fn test_range_inclusive() { - assert!(range_inclusive(0, 5).collect::<Vec<isize>>() == - vec![0, 1, 2, 3, 4, 5]); - assert!(range_inclusive(0, 5).rev().collect::<Vec<isize>>() == - vec![5, 4, 3, 2, 1, 0]); - assert_eq!(range_inclusive(200, -5).count(), 0); - assert_eq!(range_inclusive(200, -5).rev().count(), 0); - assert_eq!(range_inclusive(200, 200).collect::<Vec<isize>>(), [200]); - assert_eq!(range_inclusive(200, 200).rev().collect::<Vec<isize>>(), [200]); -} - -#[test] fn test_range_step() { assert_eq!((0..20).step_by(5).collect::<Vec<isize>>(), [0, 5, 10, 15]); assert_eq!((20..0).step_by(-5).collect::<Vec<isize>>(), [20, 15, 10, 5]); diff --git a/src/libcoretest/lib.rs b/src/libcoretest/lib.rs index 20da4a86bf5..88f1835d2cc 100644 --- a/src/libcoretest/lib.rs +++ b/src/libcoretest/lib.rs @@ -43,6 +43,7 @@ #![feature(unboxed_closures)] #![feature(unicode)] #![feature(unique)] +#![feature(clone_from_slice)] extern crate core; extern crate test; diff --git a/src/libcoretest/num/flt2dec/mod.rs b/src/libcoretest/num/flt2dec/mod.rs index 309bf6d8192..65b233ee92f 100644 --- a/src/libcoretest/num/flt2dec/mod.rs +++ b/src/libcoretest/num/flt2dec/mod.rs @@ -10,7 +10,6 @@ use std::prelude::v1::*; use std::{str, mem, i16, f32, f64, fmt}; -use std::slice::bytes; use std::__rand as rand; use rand::{Rand, XorShiftRng}; use rand::distributions::{IndependentSample, Range}; @@ -101,7 +100,7 @@ fn check_exact<F, T>(mut f: F, v: T, vstr: &str, expected: &[u8], expectedk: i16 // check significant digits for i in 1..cut.unwrap_or(expected.len() - 1) { - bytes::copy_memory(&expected[..i], &mut expected_); + expected_.clone_from_slice(&expected[..i]); let mut expectedk_ = expectedk; if expected[i] >= b'5' { // check if this is a rounding-to-even case. @@ -148,7 +147,7 @@ fn check_exact<F, T>(mut f: F, v: T, vstr: &str, expected: &[u8], expectedk: i16 // check infinite zero digits if let Some(cut) = cut { for i in cut..expected.len()-1 { - bytes::copy_memory(&expected[..cut], &mut expected_); + expected_.clone_from_slice(&expected[..cut]); for c in &mut expected_[cut..i] { *c = b'0'; } try_exact!(f(&decoded) => &mut buf, &expected_[..i], expectedk; diff --git a/src/libcoretest/num/mod.rs b/src/libcoretest/num/mod.rs index 738761f3911..09f2e326503 100644 --- a/src/libcoretest/num/mod.rs +++ b/src/libcoretest/num/mod.rs @@ -55,35 +55,6 @@ mod tests { use core::num::Float; #[test] - fn from_str_issue7588() { - let u : Option<u8> = u8::from_str_radix("1000", 10).ok(); - assert_eq!(u, None); - let s : Option<i16> = i16::from_str_radix("80000", 10).ok(); - assert_eq!(s, None); - let s = "10000000000000000000000000000000000000000"; - let f : Option<f32> = f32::from_str_radix(s, 10).ok(); - assert_eq!(f, Some(Float::infinity())); - let fe : Option<f32> = f32::from_str_radix("1e40", 10).ok(); - assert_eq!(fe, Some(Float::infinity())); - } - - #[test] - fn test_from_str_radix_float() { - let x1 : Option<f64> = f64::from_str_radix("-123.456", 10).ok(); - assert_eq!(x1, Some(-123.456)); - let x2 : Option<f32> = f32::from_str_radix("123.456", 10).ok(); - assert_eq!(x2, Some(123.456)); - let x3 : Option<f32> = f32::from_str_radix("-0.0", 10).ok(); - assert_eq!(x3, Some(-0.0)); - let x4 : Option<f32> = f32::from_str_radix("0.0", 10).ok(); - assert_eq!(x4, Some(0.0)); - let x4 : Option<f32> = f32::from_str_radix("1.0", 10).ok(); - assert_eq!(x4, Some(1.0)); - let x5 : Option<f32> = f32::from_str_radix("-1.0", 10).ok(); - assert_eq!(x5, Some(-1.0)); - } - - #[test] fn test_int_from_str_overflow() { let mut i8_val: i8 = 127; assert_eq!("127".parse::<i8>().ok(), Some(i8_val)); diff --git a/src/librand/chacha.rs b/src/librand/chacha.rs index e2c157f98a6..cd099c69005 100644 --- a/src/librand/chacha.rs +++ b/src/librand/chacha.rs @@ -208,7 +208,6 @@ impl Rand for ChaChaRng { mod tests { use std::prelude::v1::*; - use core::iter::order; use {Rng, SeedableRng}; use super::ChaChaRng; @@ -217,8 +216,8 @@ mod tests { let s = ::test::rng().gen_iter::<u32>().take(8).collect::<Vec<u32>>(); let mut ra: ChaChaRng = SeedableRng::from_seed(&*s); let mut rb: ChaChaRng = SeedableRng::from_seed(&*s); - assert!(order::equals(ra.gen_ascii_chars().take(100), - rb.gen_ascii_chars().take(100))); + assert!(ra.gen_ascii_chars().take(100) + .eq(rb.gen_ascii_chars().take(100))); } #[test] @@ -226,8 +225,8 @@ mod tests { let seed: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7]; let mut ra: ChaChaRng = SeedableRng::from_seed(seed); let mut rb: ChaChaRng = SeedableRng::from_seed(seed); - assert!(order::equals(ra.gen_ascii_chars().take(100), - rb.gen_ascii_chars().take(100))); + assert!(ra.gen_ascii_chars().take(100) + .eq(rb.gen_ascii_chars().take(100))); } #[test] diff --git a/src/librand/isaac.rs b/src/librand/isaac.rs index 1f56a82eba8..dd99bc93ef3 100644 --- a/src/librand/isaac.rs +++ b/src/librand/isaac.rs @@ -544,7 +544,6 @@ impl Rand for Isaac64Rng { mod tests { use std::prelude::v1::*; - use core::iter::order; use {Rng, SeedableRng}; use super::{IsaacRng, Isaac64Rng}; @@ -553,16 +552,16 @@ mod tests { let s = ::test::rng().gen_iter::<u32>().take(256).collect::<Vec<u32>>(); let mut ra: IsaacRng = SeedableRng::from_seed(&s[..]); let mut rb: IsaacRng = SeedableRng::from_seed(&s[..]); - assert!(order::equals(ra.gen_ascii_chars().take(100), - rb.gen_ascii_chars().take(100))); + assert!(ra.gen_ascii_chars().take(100) + .eq(rb.gen_ascii_chars().take(100))); } #[test] fn test_rng_64_rand_seeded() { let s = ::test::rng().gen_iter::<u64>().take(256).collect::<Vec<u64>>(); let mut ra: Isaac64Rng = SeedableRng::from_seed(&s[..]); let mut rb: Isaac64Rng = SeedableRng::from_seed(&s[..]); - assert!(order::equals(ra.gen_ascii_chars().take(100), - rb.gen_ascii_chars().take(100))); + assert!(ra.gen_ascii_chars().take(100) + .eq(rb.gen_ascii_chars().take(100))); } #[test] @@ -570,16 +569,16 @@ mod tests { let seed: &[_] = &[1, 23, 456, 7890, 12345]; let mut ra: IsaacRng = SeedableRng::from_seed(seed); let mut rb: IsaacRng = SeedableRng::from_seed(seed); - assert!(order::equals(ra.gen_ascii_chars().take(100), - rb.gen_ascii_chars().take(100))); + assert!(ra.gen_ascii_chars().take(100) + .eq(rb.gen_ascii_chars().take(100))); } #[test] fn test_rng_64_seeded() { let seed: &[_] = &[1, 23, 456, 7890, 12345]; let mut ra: Isaac64Rng = SeedableRng::from_seed(seed); let mut rb: Isaac64Rng = SeedableRng::from_seed(seed); - assert!(order::equals(ra.gen_ascii_chars().take(100), - rb.gen_ascii_chars().take(100))); + assert!(ra.gen_ascii_chars().take(100) + .eq(rb.gen_ascii_chars().take(100))); } #[test] diff --git a/src/librand/reseeding.rs b/src/librand/reseeding.rs index 8ef94eb16f2..db5e0213726 100644 --- a/src/librand/reseeding.rs +++ b/src/librand/reseeding.rs @@ -122,7 +122,6 @@ impl Default for ReseedWithDefault { mod tests { use std::prelude::v1::*; - use core::iter::order; use super::{ReseedingRng, ReseedWithDefault}; use {SeedableRng, Rng}; @@ -167,8 +166,8 @@ mod tests { fn test_rng_seeded() { let mut ra: MyRng = SeedableRng::from_seed((ReseedWithDefault, 2)); let mut rb: MyRng = SeedableRng::from_seed((ReseedWithDefault, 2)); - assert!(order::equals(ra.gen_ascii_chars().take(100), - rb.gen_ascii_chars().take(100))); + assert!(ra.gen_ascii_chars().take(100) + .eq(rb.gen_ascii_chars().take(100))); } #[test] diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index d6932c7ca3c..9f75f9ebb9a 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -242,7 +242,7 @@ pub fn lookup_const_fn_by_id<'tcx>(tcx: &ty::ctxt<'tcx>, def_id: DefId) } } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] pub enum ConstVal { Float(f64), Int(i64), diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 4efa7bfac18..22a4ddd2f68 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -28,6 +28,7 @@ use middle::def; use middle::lang_items; use middle::ty::{self, Ty}; use middle::def_id::{DefId, DefIndex}; +use mir::repr::Mir; use session::Session; use session::search_paths::PathKind; use util::nodemap::{FnvHashMap, NodeMap, NodeSet}; @@ -100,6 +101,7 @@ pub enum InlinedItem { } /// A borrowed version of `hir::InlinedItem`. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] pub enum InlinedItemRef<'a> { Item(&'a hir::Item), TraitItem(DefId, &'a hir::TraitItem), @@ -216,6 +218,8 @@ pub trait CrateStore<'tcx> : Any { // misc. metadata fn maybe_get_item_ast(&'tcx self, tcx: &ty::ctxt<'tcx>, def: DefId) -> FoundAst<'tcx>; + fn maybe_get_item_mir(&self, tcx: &ty::ctxt<'tcx>, def: DefId) + -> Option<Mir<'tcx>>; // This is basically a 1-based range of ints, which is a little // silly - I may fix that. fn crates(&self) -> Vec<ast::CrateNum>; @@ -235,6 +239,7 @@ pub trait CrateStore<'tcx> : Any { item_symbols: &RefCell<NodeMap<String>>, link_meta: &LinkMeta, reachable: &NodeSet, + mir_map: &NodeMap<Mir<'tcx>>, krate: &hir::Crate) -> Vec<u8>; fn metadata_encoding_version(&self) -> &[u8]; } @@ -383,6 +388,9 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { // misc. metadata fn maybe_get_item_ast(&'tcx self, tcx: &ty::ctxt<'tcx>, def: DefId) -> FoundAst<'tcx> { unimplemented!() } + fn maybe_get_item_mir(&self, tcx: &ty::ctxt<'tcx>, def: DefId) + -> Option<Mir<'tcx>> { unimplemented!() } + // This is basically a 1-based range of ints, which is a little // silly - I may fix that. fn crates(&self) -> Vec<ast::CrateNum> { vec![] } @@ -404,6 +412,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { item_symbols: &RefCell<NodeMap<String>>, link_meta: &LinkMeta, reachable: &NodeSet, + mir_map: &NodeMap<Mir<'tcx>>, krate: &hir::Crate) -> Vec<u8> { vec![] } fn metadata_encoding_version(&self) -> &[u8] { unimplemented!() } } diff --git a/src/librustc/middle/ty/sty.rs b/src/librustc/middle/ty/sty.rs index 425a324c7e0..66b2a9d3ad0 100644 --- a/src/librustc/middle/ty/sty.rs +++ b/src/librustc/middle/ty/sty.rs @@ -10,6 +10,7 @@ //! This module contains TypeVariants and its major components +use middle::cstore; use middle::def_id::DefId; use middle::region; use middle::subst::{self, Substs}; @@ -26,6 +27,8 @@ use syntax::abi; use syntax::ast::{self, Name}; use syntax::parse::token::special_idents; +use serialize::{Decodable, Decoder}; + use rustc_front::hir; use self::FnOutput::*; @@ -233,7 +236,7 @@ pub enum TypeVariants<'tcx> { /// closure C wind up influencing the decisions we ought to make for /// closure C (which would then require fixed point iteration to /// handle). Plus it fixes an ICE. :P -#[derive(Clone, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct ClosureSubsts<'tcx> { /// Lifetime and type parameters from the enclosing function. /// These are separated out because trans wants to pass them around @@ -246,6 +249,23 @@ pub struct ClosureSubsts<'tcx> { pub upvar_tys: Vec<Ty<'tcx>> } +impl<'tcx> Decodable for &'tcx ClosureSubsts<'tcx> { + fn decode<S: Decoder>(s: &mut S) -> Result<&'tcx ClosureSubsts<'tcx>, S::Error> { + let closure_substs = try! { Decodable::decode(s) }; + let dummy_def_id: DefId = unsafe { mem::zeroed() }; + + cstore::tls::with_decoding_context(s, |dcx, _| { + // Intern the value + let ty = dcx.tcx().mk_closure_from_closure_substs(dummy_def_id, + Box::new(closure_substs)); + match ty.sty { + TyClosure(_, ref closure_substs) => Ok(&**closure_substs), + _ => unreachable!() + } + }) + } +} + #[derive(Clone, PartialEq, Eq, Hash)] pub struct TraitTy<'tcx> { pub principal: ty::PolyTraitRef<'tcx>, @@ -434,7 +454,7 @@ pub struct ClosureTy<'tcx> { pub sig: PolyFnSig<'tcx>, } -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub enum FnOutput<'tcx> { FnConverging(Ty<'tcx>), FnDiverging @@ -632,7 +652,7 @@ pub struct DebruijnIndex { /// /// [1] http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/ /// [2] http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/ -#[derive(Clone, PartialEq, Eq, Hash, Copy)] +#[derive(Clone, PartialEq, Eq, Hash, Copy, RustcEncodable, RustcDecodable)] pub enum Region { // Region bound in a type or fn declaration which will be // substituted 'early' -- that is, at the same time when type @@ -701,7 +721,7 @@ pub struct RegionVid { pub index: u32 } -#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct SkolemizedRegionVid { pub index: u32 } diff --git a/src/librustc/mir/repr.rs b/src/librustc/mir/repr.rs index d5d8da248e0..049063f73a5 100644 --- a/src/librustc/mir/repr.rs +++ b/src/librustc/mir/repr.rs @@ -13,6 +13,7 @@ use middle::def_id::DefId; use middle::subst::Substs; use middle::ty::{AdtDef, ClosureSubsts, FnOutput, Region, Ty}; use rustc_back::slice; +use rustc_data_structures::tuple_slice::TupleSlice; use rustc_front::hir::InlineAsm; use syntax::ast::Name; use syntax::codemap::Span; @@ -20,6 +21,7 @@ use std::fmt::{Debug, Formatter, Error}; use std::u32; /// Lowered representation of a single function. +#[derive(RustcEncodable, RustcDecodable)] pub struct Mir<'tcx> { /// List of basic blocks. References to basic block use a newtyped index type `BasicBlock` /// that indexes into this vector. @@ -70,13 +72,13 @@ impl<'tcx> Mir<'tcx> { /////////////////////////////////////////////////////////////////////////// // Mutability and borrow kinds -#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] pub enum Mutability { Mut, Not, } -#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] pub enum BorrowKind { /// Data must be immutable and is aliasable. Shared, @@ -127,6 +129,7 @@ pub enum BorrowKind { // A "variable" is a binding declared by the user as part of the fn // decl, a let, etc. +#[derive(RustcEncodable, RustcDecodable)] pub struct VarDecl<'tcx> { pub mutability: Mutability, pub name: Name, @@ -135,6 +138,7 @@ pub struct VarDecl<'tcx> { // A "temp" is a temporary that we place on the stack. They are // anonymous, always mutable, and have only a type. +#[derive(RustcEncodable, RustcDecodable)] pub struct TempDecl<'tcx> { pub ty: Ty<'tcx>, } @@ -150,6 +154,7 @@ pub struct TempDecl<'tcx> { // // there is only one argument, of type `(i32, u32)`, but two bindings // (`x` and `y`). +#[derive(RustcEncodable, RustcDecodable)] pub struct ArgDecl<'tcx> { pub ty: Ty<'tcx>, } @@ -161,7 +166,7 @@ pub struct ArgDecl<'tcx> { /// list of the `Mir`. /// /// (We use a `u32` internally just to save memory.) -#[derive(Copy, Clone, PartialEq, Eq)] +#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable)] pub struct BasicBlock(u32); impl BasicBlock { @@ -185,12 +190,13 @@ impl Debug for BasicBlock { /////////////////////////////////////////////////////////////////////////// // BasicBlock and Terminator -#[derive(Debug)] +#[derive(Debug, RustcEncodable, RustcDecodable)] pub struct BasicBlockData<'tcx> { pub statements: Vec<Statement<'tcx>>, pub terminator: Terminator<'tcx>, } +#[derive(RustcEncodable, RustcDecodable)] pub enum Terminator<'tcx> { /// block should have one successor in the graph; we jump there Goto { @@ -206,7 +212,7 @@ pub enum Terminator<'tcx> { /// jump to branch 0 if this lvalue evaluates to true If { cond: Operand<'tcx>, - targets: [BasicBlock; 2], + targets: (BasicBlock, BasicBlock), }, /// lvalue evaluates to some enum; jump depending on the branch @@ -254,7 +260,7 @@ pub enum Terminator<'tcx> { /// unwinding. Call { data: CallData<'tcx>, - targets: [BasicBlock; 2], + targets: (BasicBlock, BasicBlock), }, } @@ -264,12 +270,12 @@ impl<'tcx> Terminator<'tcx> { match *self { Goto { target: ref b } => slice::ref_slice(b), Panic { target: ref b } => slice::ref_slice(b), - If { cond: _, targets: ref b } => b, + If { cond: _, targets: ref b } => b.as_slice(), Switch { targets: ref b, .. } => b, SwitchInt { targets: ref b, .. } => b, Diverge => &[], Return => &[], - Call { data: _, targets: ref b } => b, + Call { data: _, targets: ref b } => b.as_slice(), } } @@ -278,17 +284,17 @@ impl<'tcx> Terminator<'tcx> { match *self { Goto { target: ref mut b } => slice::mut_ref_slice(b), Panic { target: ref mut b } => slice::mut_ref_slice(b), - If { cond: _, targets: ref mut b } => b, + If { cond: _, targets: ref mut b } => b.as_mut_slice(), Switch { targets: ref mut b, .. } => b, SwitchInt { targets: ref mut b, .. } => b, Diverge => &mut [], Return => &mut [], - Call { data: _, targets: ref mut b } => b, + Call { data: _, targets: ref mut b } => b.as_mut_slice(), } } } -#[derive(Debug)] +#[derive(Debug, RustcEncodable, RustcDecodable)] pub struct CallData<'tcx> { /// where the return value is written to pub destination: Lvalue<'tcx>, @@ -345,18 +351,19 @@ impl<'tcx> Debug for Terminator<'tcx> { /////////////////////////////////////////////////////////////////////////// // Statements +#[derive(RustcEncodable, RustcDecodable)] pub struct Statement<'tcx> { pub span: Span, pub kind: StatementKind<'tcx>, } -#[derive(Debug)] +#[derive(Debug, RustcEncodable, RustcDecodable)] pub enum StatementKind<'tcx> { Assign(Lvalue<'tcx>, Rvalue<'tcx>), Drop(DropKind, Lvalue<'tcx>), } -#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] pub enum DropKind { Free, // free a partially constructed box, should go away eventually Deep @@ -377,7 +384,7 @@ impl<'tcx> Debug for Statement<'tcx> { /// A path to a value; something that can be evaluated without /// changing or disturbing program state. -#[derive(Clone, PartialEq)] +#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)] pub enum Lvalue<'tcx> { /// local variable declared by the user Var(u32), @@ -403,13 +410,13 @@ pub enum Lvalue<'tcx> { /// or `*B` or `B[index]`. Note that it is parameterized because it is /// shared between `Constant` and `Lvalue`. See the aliases /// `LvalueProjection` etc below. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] pub struct Projection<'tcx, B, V> { pub base: B, pub elem: ProjectionElem<'tcx, V>, } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] pub enum ProjectionElem<'tcx, V> { Deref, Field(Field), @@ -447,7 +454,7 @@ pub type LvalueElem<'tcx> = ProjectionElem<'tcx,Operand<'tcx>>; /// Index into the list of fields found in a `VariantDef` -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct Field(u32); impl Field { @@ -523,7 +530,7 @@ impl<'tcx> Debug for Lvalue<'tcx> { // lvalue). They are intentionally limited to prevent rvalues from // being nested in one another. -#[derive(Clone, PartialEq)] +#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)] pub enum Operand<'tcx> { Consume(Lvalue<'tcx>), Constant(Constant<'tcx>), @@ -542,7 +549,7 @@ impl<'tcx> Debug for Operand<'tcx> { /////////////////////////////////////////////////////////////////////////// // Rvalues -#[derive(Clone)] +#[derive(Clone, RustcEncodable, RustcDecodable)] pub enum Rvalue<'tcx> { // x (either a move or copy, depending on type of x) Use(Operand<'tcx>), @@ -583,10 +590,10 @@ pub enum Rvalue<'tcx> { from_end: usize, }, - InlineAsm(&'tcx InlineAsm), + InlineAsm(InlineAsm), } -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] pub enum CastKind { Misc, @@ -604,7 +611,7 @@ pub enum CastKind { Unsize, } -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] pub enum AggregateKind<'tcx> { Vec, Tuple, @@ -612,7 +619,7 @@ pub enum AggregateKind<'tcx> { Closure(DefId, &'tcx ClosureSubsts<'tcx>), } -#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] pub enum BinOp { /// The `+` operator (addition) Add, @@ -648,7 +655,7 @@ pub enum BinOp { Gt, } -#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] pub enum UnOp { /// The `!` operator for logical inversion Not, @@ -684,14 +691,14 @@ impl<'tcx> Debug for Rvalue<'tcx> { // this does not necessarily mean that they are "==" in Rust -- in // particular one must be wary of `NaN`! -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] pub struct Constant<'tcx> { pub span: Span, pub ty: Ty<'tcx>, pub literal: Literal<'tcx>, } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] pub enum Literal<'tcx> { Item { def_id: DefId, diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index ac4f54b4b49..00d21d3c16e 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -8,8 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use middle::def_id::DefId; use middle::ty::Region; use mir::repr::*; +use rustc_data_structures::tuple_slice::TupleSlice; +use syntax::codemap::Span; pub trait Visitor<'tcx> { // Override these, and call `self.super_xxx` to revert back to the @@ -55,6 +58,18 @@ pub trait Visitor<'tcx> { self.super_constant(constant); } + fn visit_literal(&mut self, literal: &Literal<'tcx>) { + self.super_literal(literal); + } + + fn visit_def_id(&mut self, def_id: DefId) { + self.super_def_id(def_id); + } + + fn visit_span(&mut self, span: Span) { + self.super_span(span); + } + // The `super_xxx` methods comprise the default behavior and are // not meant to be overidden. @@ -73,6 +88,8 @@ pub trait Visitor<'tcx> { } fn super_statement(&mut self, block: BasicBlock, statement: &Statement<'tcx>) { + self.visit_span(statement.span); + match statement.kind { StatementKind::Assign(ref lvalue, ref rvalue) => { self.visit_assign(block, lvalue, rvalue); @@ -97,7 +114,7 @@ pub trait Visitor<'tcx> { Terminator::If { ref cond, ref targets } => { self.visit_operand(cond); - for &target in &targets[..] { + for &target in targets.as_slice() { self.visit_branch(block, target); } } @@ -126,7 +143,7 @@ pub trait Visitor<'tcx> { for arg in &data.args { self.visit_operand(arg); } - for &target in &targets[..] { + for &target in targets.as_slice() { self.visit_branch(block, target); } } @@ -217,7 +234,26 @@ pub trait Visitor<'tcx> { fn super_branch(&mut self, _source: BasicBlock, _target: BasicBlock) { } - fn super_constant(&mut self, _constant: &Constant<'tcx>) { + fn super_constant(&mut self, constant: &Constant<'tcx>) { + self.visit_span(constant.span); + self.visit_literal(&constant.literal); + } + + fn super_literal(&mut self, literal: &Literal<'tcx>) { + match *literal { + Literal::Item { def_id, .. } => { + self.visit_def_id(def_id); + }, + Literal::Value { .. } => { + // Nothing to do + } + } + } + + fn super_def_id(&mut self, _def_id: DefId) { + } + + fn super_span(&mut self, _span: Span) { } } @@ -244,3 +280,277 @@ pub enum LvalueContext { // Consumed as part of an operand Consume, } + +pub trait MutVisitor<'tcx> { + // Override these, and call `self.super_xxx` to revert back to the + // default behavior. + + fn visit_mir(&mut self, mir: &mut Mir<'tcx>) { + self.super_mir(mir); + } + + fn visit_basic_block_data(&mut self, + block: BasicBlock, + data: &mut BasicBlockData<'tcx>) { + self.super_basic_block_data(block, data); + } + + fn visit_statement(&mut self, + block: BasicBlock, + statement: &mut Statement<'tcx>) { + self.super_statement(block, statement); + } + + fn visit_assign(&mut self, + block: BasicBlock, + lvalue: &mut Lvalue<'tcx>, + rvalue: &mut Rvalue<'tcx>) { + self.super_assign(block, lvalue, rvalue); + } + + fn visit_terminator(&mut self, + block: BasicBlock, + terminator: &mut Terminator<'tcx>) { + self.super_terminator(block, terminator); + } + + fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>) { + self.super_rvalue(rvalue); + } + + fn visit_operand(&mut self, operand: &mut Operand<'tcx>) { + self.super_operand(operand); + } + + fn visit_lvalue(&mut self, + lvalue: &mut Lvalue<'tcx>, + context: LvalueContext) { + self.super_lvalue(lvalue, context); + } + + fn visit_branch(&mut self, source: BasicBlock, target: BasicBlock) { + self.super_branch(source, target); + } + + fn visit_constant(&mut self, constant: &mut Constant<'tcx>) { + self.super_constant(constant); + } + + fn visit_literal(&mut self, literal: &mut Literal<'tcx>) { + self.super_literal(literal); + } + + fn visit_def_id(&mut self, def_id: &mut DefId) { + self.super_def_id(def_id); + } + + fn visit_span(&mut self, span: &mut Span) { + self.super_span(span); + } + + // The `super_xxx` methods comprise the default behavior and are + // not meant to be overidden. + + fn super_mir(&mut self, mir: &mut Mir<'tcx>) { + for block in mir.all_basic_blocks() { + let data = mir.basic_block_data_mut(block); + self.visit_basic_block_data(block, data); + } + } + + fn super_basic_block_data(&mut self, + block: BasicBlock, + data: &mut BasicBlockData<'tcx>) { + for statement in &mut data.statements { + self.visit_statement(block, statement); + } + self.visit_terminator(block, &mut data.terminator); + } + + fn super_statement(&mut self, + block: BasicBlock, + statement: &mut Statement<'tcx>) { + self.visit_span(&mut statement.span); + + match statement.kind { + StatementKind::Assign(ref mut lvalue, ref mut rvalue) => { + self.visit_assign(block, lvalue, rvalue); + } + StatementKind::Drop(_, ref mut lvalue) => { + self.visit_lvalue(lvalue, LvalueContext::Drop); + } + } + } + + fn super_assign(&mut self, + _block: BasicBlock, + lvalue: &mut Lvalue<'tcx>, + rvalue: &mut Rvalue<'tcx>) { + self.visit_lvalue(lvalue, LvalueContext::Store); + self.visit_rvalue(rvalue); + } + + fn super_terminator(&mut self, + block: BasicBlock, + terminator: &mut Terminator<'tcx>) { + match *terminator { + Terminator::Goto { target } | + Terminator::Panic { target } => { + self.visit_branch(block, target); + } + + Terminator::If { ref mut cond, ref mut targets } => { + self.visit_operand(cond); + for &target in targets.as_slice() { + self.visit_branch(block, target); + } + } + + Terminator::Switch { ref mut discr, adt_def: _, ref targets } => { + self.visit_lvalue(discr, LvalueContext::Inspect); + for &target in targets { + self.visit_branch(block, target); + } + } + + Terminator::SwitchInt { ref mut discr, switch_ty: _, values: _, ref targets } => { + self.visit_lvalue(discr, LvalueContext::Inspect); + for &target in targets { + self.visit_branch(block, target); + } + } + + Terminator::Diverge | + Terminator::Return => { + } + + Terminator::Call { ref mut data, ref mut targets } => { + self.visit_lvalue(&mut data.destination, LvalueContext::Store); + self.visit_operand(&mut data.func); + for arg in &mut data.args { + self.visit_operand(arg); + } + for &target in targets.as_slice() { + self.visit_branch(block, target); + } + } + } + } + + fn super_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>) { + match *rvalue { + Rvalue::Use(ref mut operand) => { + self.visit_operand(operand); + } + + Rvalue::Repeat(ref mut value, ref mut len) => { + self.visit_operand(value); + self.visit_constant(len); + } + + Rvalue::Ref(r, bk, ref mut path) => { + self.visit_lvalue(path, LvalueContext::Borrow { + region: r, + kind: bk + }); + } + + Rvalue::Len(ref mut path) => { + self.visit_lvalue(path, LvalueContext::Inspect); + } + + Rvalue::Cast(_, ref mut operand, _) => { + self.visit_operand(operand); + } + + Rvalue::BinaryOp(_, ref mut lhs, ref mut rhs) => { + self.visit_operand(lhs); + self.visit_operand(rhs); + } + + Rvalue::UnaryOp(_, ref mut op) => { + self.visit_operand(op); + } + + Rvalue::Box(_) => { + } + + Rvalue::Aggregate(ref mut kind, ref mut operands) => { + match *kind { + AggregateKind::Closure(ref mut def_id, _) => { + self.visit_def_id(def_id); + } + _ => { /* nothing to do */ } + } + + for operand in &mut operands[..] { + self.visit_operand(operand); + } + } + + Rvalue::Slice { ref mut input, from_start, from_end } => { + self.visit_lvalue(input, LvalueContext::Slice { + from_start: from_start, + from_end: from_end, + }); + } + + Rvalue::InlineAsm(_) => { + } + } + } + + fn super_operand(&mut self, operand: &mut Operand<'tcx>) { + match *operand { + Operand::Consume(ref mut lvalue) => { + self.visit_lvalue(lvalue, LvalueContext::Consume); + } + Operand::Constant(ref mut constant) => { + self.visit_constant(constant); + } + } + } + + fn super_lvalue(&mut self, + lvalue: &mut Lvalue<'tcx>, + _context: LvalueContext) { + match *lvalue { + Lvalue::Var(_) | + Lvalue::Temp(_) | + Lvalue::Arg(_) | + Lvalue::ReturnPointer => { + } + Lvalue::Static(ref mut def_id) => { + self.visit_def_id(def_id); + } + Lvalue::Projection(ref mut proj) => { + self.visit_lvalue(&mut proj.base, LvalueContext::Projection); + } + } + } + + fn super_branch(&mut self, _source: BasicBlock, _target: BasicBlock) { + } + + fn super_constant(&mut self, constant: &mut Constant<'tcx>) { + self.visit_span(&mut constant.span); + self.visit_literal(&mut constant.literal); + } + + fn super_literal(&mut self, literal: &mut Literal<'tcx>) { + match *literal { + Literal::Item { ref mut def_id, .. } => { + self.visit_def_id(def_id); + }, + Literal::Value { .. } => { + // Nothing to do + } + } + } + + fn super_def_id(&mut self, _def_id: &mut DefId) { + } + + fn super_span(&mut self, _span: &mut Span) { + } +} diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 39b3842791f..0ea7cfa3902 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -42,6 +42,7 @@ pub mod snapshot_vec; pub mod transitive_relation; pub mod unify; pub mod fnv; +pub mod tuple_slice; // See comments in src/librustc/lib.rs #[doc(hidden)] diff --git a/src/librustc_data_structures/tuple_slice.rs b/src/librustc_data_structures/tuple_slice.rs new file mode 100644 index 00000000000..f157d82eda1 --- /dev/null +++ b/src/librustc_data_structures/tuple_slice.rs @@ -0,0 +1,60 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::slice; + +/// Allows to view uniform tuples as slices +pub trait TupleSlice<T> { + fn as_slice(&self) -> &[T]; + fn as_mut_slice(&mut self) -> &mut [T]; +} + +macro_rules! impl_tuple_slice { + ($tuple_type:ty, $size:expr) => { + impl<T> TupleSlice<T> for $tuple_type { + fn as_slice(&self) -> &[T] { + unsafe { + let ptr = &self.0 as *const T; + slice::from_raw_parts(ptr, $size) + } + } + + fn as_mut_slice(&mut self) -> &mut [T] { + unsafe { + let ptr = &mut self.0 as *mut T; + slice::from_raw_parts_mut(ptr, $size) + } + } + } + } +} + +impl_tuple_slice!((T,T), 2); +impl_tuple_slice!((T,T,T), 3); +impl_tuple_slice!((T,T,T,T), 4); +impl_tuple_slice!((T,T,T,T,T), 5); +impl_tuple_slice!((T,T,T,T,T,T), 6); +impl_tuple_slice!((T,T,T,T,T,T,T), 7); +impl_tuple_slice!((T,T,T,T,T,T,T,T), 8); + +#[test] +fn test_sliced_tuples() { + let t2 = (100i32, 101i32); + assert_eq!(t2.as_slice(), &[100i32, 101i32]); + + let t3 = (102i32, 103i32, 104i32); + assert_eq!(t3.as_slice(), &[102i32, 103i32, 104i32]); + + let t4 = (105i32, 106i32, 107i32, 108i32); + assert_eq!(t4.as_slice(), &[105i32, 106i32, 107i32, 108i32]); + + let t5 = (109i32, 110i32, 111i32, 112i32, 113i32); + assert_eq!(t5.as_slice(), &[109i32, 110i32, 111i32, 112i32, 113i32]); +} diff --git a/src/librustc_front/intravisit.rs b/src/librustc_front/intravisit.rs index e93f5cbd0fb..cb7c5be6529 100644 --- a/src/librustc_front/intravisit.rs +++ b/src/librustc_front/intravisit.rs @@ -10,7 +10,7 @@ //! HIR walker. Each overridden visit method has full control over what //! happens with its node, it can do its own traversal of the node's children, -//! call `visit::walk_*` to apply the default traversal algorithm, or prevent +//! call `intravisit::walk_*` to apply the default traversal algorithm, or prevent //! deeper traversal by doing nothing. //! //! When visiting the HIR, the contents of nested items are NOT visited @@ -45,7 +45,7 @@ pub enum FnKind<'a> { /// Each method of the Visitor trait is a hook to be potentially /// overridden. Each method's default implementation recursively visits /// the substructure of the input via the corresponding `walk` method; -/// e.g. the `visit_mod` method by default calls `visit::walk_mod`. +/// e.g. the `visit_mod` method by default calls `intravisit::walk_mod`. /// /// Note that this visitor does NOT visit nested items by default /// (this is why the module is called `intravisit`, to distinguish it diff --git a/src/librustc_metadata/common.rs b/src/librustc_metadata/common.rs index b6454a4c81a..5186c969133 100644 --- a/src/librustc_metadata/common.rs +++ b/src/librustc_metadata/common.rs @@ -120,7 +120,8 @@ enum_from_u32! { tag_tree = 0x51, - // GAP 0x52 + tag_mir = 0x52, + tag_table = 0x53, // GAP 0x54, 0x55 tag_table_def = 0x56, diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs index aae3a762c19..ad00ef29e5f 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -22,6 +22,7 @@ use middle::ty::{self, Ty}; use middle::def_id::{DefId, DefIndex}; use rustc::front::map as hir_map; +use rustc::mir::repr::Mir; use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet}; use std::cell::RefCell; @@ -421,6 +422,12 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { decoder::maybe_get_item_ast(&*cdata, tcx, def.index, decode_inlined_item) } + fn maybe_get_item_mir(&self, tcx: &ty::ctxt<'tcx>, def: DefId) + -> Option<Mir<'tcx>> { + let cdata = self.get_crate_data(def.krate); + decoder::maybe_get_item_mir(&*cdata, tcx, def.index) + } + fn crates(&self) -> Vec<ast::CrateNum> { let mut result = vec![]; @@ -473,6 +480,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { item_symbols: &RefCell<NodeMap<String>>, link_meta: &LinkMeta, reachable: &NodeSet, + mir_map: &NodeMap<Mir<'tcx>>, krate: &hir::Crate) -> Vec<u8> { let encode_inlined_item: encoder::EncodeInlinedItem = @@ -486,7 +494,8 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { link_meta: link_meta, cstore: self, encode_inlined_item: encode_inlined_item, - reachable: reachable + reachable: reachable, + mir_map: mir_map, }; encoder::encode_metadata(encode_params, krate) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index c139ec4f62a..d1917b29b9f 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -18,6 +18,7 @@ use cstore::{self, crate_metadata}; use common::*; use encoder::def_to_u64; use index; +use tls_context; use tydecode::TyDecoder; use rustc::back::svh::Svh; @@ -26,7 +27,7 @@ use rustc::util::nodemap::FnvHashMap; use rustc_front::hir; use middle::cstore::{LOCAL_CRATE, FoundAst, InlinedItem, LinkagePreference}; -use middle::cstore::{DefLike, DlDef, DlField, DlImpl}; +use middle::cstore::{DefLike, DlDef, DlField, DlImpl, tls}; use middle::def; use middle::def_id::{DefId, DefIndex}; use middle::lang_items; @@ -34,6 +35,9 @@ use middle::subst; use middle::ty::{ImplContainer, TraitContainer}; use middle::ty::{self, RegionEscape, Ty}; +use rustc::mir; +use rustc::mir::visit::MutVisitor; + use std::cell::{Cell, RefCell}; use std::io::prelude::*; use std::io; @@ -48,7 +52,7 @@ use syntax::parse::token::{IdentInterner, special_idents}; use syntax::parse::token; use syntax::ast; use syntax::abi; -use syntax::codemap; +use syntax::codemap::{self, Span}; use syntax::print::pprust; use syntax::ptr::P; @@ -783,6 +787,56 @@ pub fn maybe_get_item_ast<'tcx>(cdata: Cmd, tcx: &ty::ctxt<'tcx>, id: DefIndex, } } +pub fn maybe_get_item_mir<'tcx>(cdata: Cmd, + tcx: &ty::ctxt<'tcx>, + id: DefIndex) + -> Option<mir::repr::Mir<'tcx>> { + let item_doc = cdata.lookup_item(id); + + return reader::maybe_get_doc(item_doc, tag_mir as usize).map(|mir_doc| { + let dcx = tls_context::DecodingContext { + crate_metadata: cdata, + tcx: tcx, + }; + let mut decoder = reader::Decoder::new(mir_doc); + + let mut mir = tls::enter_decoding_context(&dcx, &mut decoder, |_, decoder| { + Decodable::decode(decoder).unwrap() + }); + + let mut def_id_and_span_translator = MirDefIdAndSpanTranslator { + crate_metadata: cdata, + codemap: tcx.sess.codemap(), + last_filemap_index_hint: Cell::new(0), + }; + + def_id_and_span_translator.visit_mir(&mut mir); + + mir + }); + + struct MirDefIdAndSpanTranslator<'cdata, 'codemap> { + crate_metadata: Cmd<'cdata>, + codemap: &'codemap codemap::CodeMap, + last_filemap_index_hint: Cell<usize> + } + + impl<'v, 'cdata, 'codemap> mir::visit::MutVisitor<'v> + for MirDefIdAndSpanTranslator<'cdata, 'codemap> + { + fn visit_def_id(&mut self, def_id: &mut DefId) { + *def_id = translate_def_id(self.crate_metadata, *def_id); + } + + fn visit_span(&mut self, span: &mut Span) { + *span = translate_span(self.crate_metadata, + self.codemap, + &self.last_filemap_index_hint, + *span); + } + } +} + fn get_explicit_self(item: rbml::Doc) -> ty::ExplicitSelfCategory { fn get_mutability(ch: u8) -> hir::Mutability { match ch as char { diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 448a64c93c1..a627eeb6880 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -30,6 +30,7 @@ use middle::ty::{self, Ty}; use rustc::back::svh::Svh; use rustc::front::map::{LinkedPath, PathElem, PathElems}; use rustc::front::map as ast_map; +use rustc::mir::repr::Mir; use rustc::session::config; use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet}; @@ -64,6 +65,7 @@ pub struct EncodeParams<'a, 'tcx: 'a> { pub cstore: &'a cstore::CStore, pub encode_inlined_item: EncodeInlinedItem<'a>, pub reachable: &'a NodeSet, + pub mir_map: &'a NodeMap<Mir<'tcx>>, } pub struct EncodeContext<'a, 'tcx: 'a> { @@ -76,6 +78,7 @@ pub struct EncodeContext<'a, 'tcx: 'a> { pub encode_inlined_item: RefCell<EncodeInlinedItem<'a>>, pub type_abbrevs: tyencode::abbrev_map<'tcx>, pub reachable: &'a NodeSet, + pub mir_map: &'a NodeMap<Mir<'tcx>>, } impl<'a, 'tcx> EncodeContext<'a,'tcx> { @@ -840,7 +843,24 @@ fn encode_inlined_item(ecx: &EncodeContext, ii: InlinedItemRef) { let mut eii = ecx.encode_inlined_item.borrow_mut(); let eii: &mut EncodeInlinedItem = &mut *eii; - eii(ecx, rbml_w, ii) + eii(ecx, rbml_w, ii); + + encode_mir(ecx, rbml_w, ii); +} + +fn encode_mir(ecx: &EncodeContext, rbml_w: &mut Encoder, ii: InlinedItemRef) { + let id = match ii { + InlinedItemRef::Item(item) => item.id, + InlinedItemRef::TraitItem(_, trait_item) => trait_item.id, + InlinedItemRef::ImplItem(_, impl_item) => impl_item.id, + InlinedItemRef::Foreign(foreign_item) => foreign_item.id + }; + + if let Some(mir) = ecx.mir_map.get(&id) { + rbml_w.start_tag(tag_mir as usize); + Encodable::encode(mir, rbml_w).unwrap(); + rbml_w.end_tag(); + } } const FN_FAMILY: char = 'f'; @@ -1884,6 +1904,7 @@ pub fn encode_metadata(parms: EncodeParams, krate: &hir::Crate) -> Vec<u8> { encode_inlined_item, link_meta, reachable, + mir_map, .. } = parms; let ecx = EncodeContext { @@ -1896,6 +1917,7 @@ pub fn encode_metadata(parms: EncodeParams, krate: &hir::Crate) -> Vec<u8> { encode_inlined_item: RefCell::new(encode_inlined_item), type_abbrevs: RefCell::new(FnvHashMap()), reachable: reachable, + mir_map: mir_map, }; let mut wr = Cursor::new(Vec::new()); diff --git a/src/librustc_mir/build/expr/as_lvalue.rs b/src/librustc_mir/build/expr/as_lvalue.rs index 697799efd14..1c96addcea0 100644 --- a/src/librustc_mir/build/expr/as_lvalue.rs +++ b/src/librustc_mir/build/expr/as_lvalue.rs @@ -69,7 +69,7 @@ impl<'a,'tcx> Builder<'a,'tcx> { this.cfg.terminate(block, Terminator::If { cond: Operand::Consume(lt), - targets: [success, failure], + targets: (success, failure), }); this.panic(failure); success.and(slice.index(idx)) diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 7f69b9a521f..2f57dd22454 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -40,7 +40,7 @@ impl<'a,'tcx> Builder<'a,'tcx> { this.in_scope(extent, block, |this| this.as_rvalue(block, value)) } ExprKind::InlineAsm { asm } => { - block.and(Rvalue::InlineAsm(asm)) + block.and(Rvalue::InlineAsm(asm.clone())) } ExprKind::Repeat { value, count } => { let value_operand = unpack!(block = this.as_operand(block, value)); diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index ac3e87e6b62..802c55ce764 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -53,7 +53,7 @@ impl<'a,'tcx> Builder<'a,'tcx> { let mut else_block = this.cfg.start_new_block(); this.cfg.terminate(block, Terminator::If { cond: operand, - targets: [then_block, else_block] + targets: (then_block, else_block) }); unpack!(then_block = this.into(destination, then_block, then_expr)); @@ -84,15 +84,15 @@ impl<'a,'tcx> Builder<'a,'tcx> { let lhs = unpack!(block = this.as_operand(block, lhs)); let blocks = match op { - LogicalOp::And => [else_block, false_block], - LogicalOp::Or => [true_block, else_block], + LogicalOp::And => (else_block, false_block), + LogicalOp::Or => (true_block, else_block), }; this.cfg.terminate(block, Terminator::If { cond: lhs, targets: blocks }); let rhs = unpack!(else_block = this.as_operand(else_block, rhs)); this.cfg.terminate(else_block, Terminator::If { cond: rhs, - targets: [true_block, false_block] + targets: (true_block, false_block) }); this.cfg.push_assign_constant( @@ -149,7 +149,7 @@ impl<'a,'tcx> Builder<'a,'tcx> { this.cfg.terminate(loop_block_end, Terminator::If { cond: cond, - targets: [body_block, exit_block] + targets: (body_block, exit_block) }); } else { body_block = loop_block; @@ -225,7 +225,7 @@ impl<'a,'tcx> Builder<'a,'tcx> { func: fun, args: args, }, - targets: [success, panic], + targets: (success, panic), }); success.unit() } diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 0248f2fc49a..f8385d58170 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -555,7 +555,7 @@ impl<'a,'tcx> Builder<'a,'tcx> { let cond = unpack!(block = self.as_operand(block, guard)); let otherwise = self.cfg.start_new_block(); self.cfg.terminate(block, Terminator::If { cond: cond, - targets: [arm_block, otherwise]}); + targets: (arm_block, otherwise)}); Some(otherwise) } else { self.cfg.terminate(block, Terminator::Goto { target: arm_block }); diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index 968514cd05c..7b329fc4d52 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -232,7 +232,7 @@ impl<'a,'tcx> Builder<'a,'tcx> { self.cfg.start_new_block()]; self.cfg.terminate(block, Terminator::If { cond: Operand::Consume(result), - targets: [target_blocks[0], target_blocks[1]] + targets: (target_blocks[0], target_blocks[1]) }); target_blocks @@ -252,7 +252,7 @@ impl<'a,'tcx> Builder<'a,'tcx> { let bool_ty = self.hir.bool_ty(); let eq_result = self.temp(bool_ty); let func = self.item_ref_operand(span, item_ref); - let call_blocks = [self.cfg.start_new_block(), self.diverge_cleanup()]; + let call_blocks = (self.cfg.start_new_block(), self.diverge_cleanup()); self.cfg.terminate(block, Terminator::Call { data: CallData { @@ -264,10 +264,10 @@ impl<'a,'tcx> Builder<'a,'tcx> { }); // check the result - self.cfg.terminate(call_blocks[0], + self.cfg.terminate(call_blocks.0, Terminator::If { cond: Operand::Consume(eq_result), - targets: [target_blocks[0], target_blocks[1]], + targets: (target_blocks[0], target_blocks[1]), }); target_blocks diff --git a/src/librustc_mir/transform/simplify_cfg.rs b/src/librustc_mir/transform/simplify_cfg.rs index 558276a13a8..d0c0afc80a6 100644 --- a/src/librustc_mir/transform/simplify_cfg.rs +++ b/src/librustc_mir/transform/simplify_cfg.rs @@ -96,9 +96,9 @@ impl SimplifyCfg { mem::swap(&mut terminator, &mut mir.basic_block_data_mut(bb).terminator); mir.basic_block_data_mut(bb).terminator = match terminator { - Terminator::If { ref targets, .. } if targets[0] == targets[1] => { + Terminator::If { ref targets, .. } if targets.0 == targets.1 => { changed = true; - Terminator::Goto { target: targets[0] } + Terminator::Goto { target: targets.0 } } Terminator::If { ref targets, cond: Operand::Constant(Constant { literal: Literal::Value { @@ -106,8 +106,11 @@ impl SimplifyCfg { }, .. }) } => { changed = true; - let target_idx = if cond { 0 } else { 1 }; - Terminator::Goto { target: targets[target_idx] } + if cond { + Terminator::Goto { target: targets.0 } + } else { + Terminator::Goto { target: targets.1 } + } } Terminator::SwitchInt { ref targets, .. } if targets.len() == 1 => { Terminator::Goto { target: targets[0] } diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index dde6e3935b2..838a5435d4f 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -2760,7 +2760,11 @@ fn register_method(ccx: &CrateContext, } } -pub fn write_metadata(cx: &SharedCrateContext, krate: &hir::Crate, reachable: &NodeSet) -> Vec<u8> { +pub fn write_metadata<'a, 'tcx>(cx: &SharedCrateContext<'a, 'tcx>, + krate: &hir::Crate, + reachable: &NodeSet, + mir_map: &MirMap<'tcx>) + -> Vec<u8> { use flate; let any_library = cx.sess() @@ -2773,9 +2777,13 @@ pub fn write_metadata(cx: &SharedCrateContext, krate: &hir::Crate, reachable: &N } let cstore = &cx.tcx().sess.cstore; - let metadata = cstore.encode_metadata( - cx.tcx(), cx.export_map(), cx.item_symbols(), cx.link_meta(), reachable, - krate); + let metadata = cstore.encode_metadata(cx.tcx(), + cx.export_map(), + cx.item_symbols(), + cx.link_meta(), + reachable, + mir_map, + krate); let mut compressed = cstore.metadata_encoding_version().to_vec(); compressed.extend_from_slice(&flate::deflate_bytes(&metadata)); @@ -3045,7 +3053,7 @@ pub fn trans_crate<'tcx>(tcx: &ty::ctxt<'tcx>, let reachable_symbol_ids = filter_reachable_ids(&shared_ccx); // Translate the metadata. - let metadata = write_metadata(&shared_ccx, krate, &reachable_symbol_ids); + let metadata = write_metadata(&shared_ccx, krate, &reachable_symbol_ids, mir_map); if shared_ccx.sess().trans_stats() { let stats = shared_ccx.stats(); diff --git a/src/librustc_trans/trans/mir/block.rs b/src/librustc_trans/trans/mir/block.rs index 3ce08fb2f60..b58b51f5a2b 100644 --- a/src/librustc_trans/trans/mir/block.rs +++ b/src/librustc_trans/trans/mir/block.rs @@ -39,7 +39,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { unimplemented!() } - mir::Terminator::If { ref cond, targets: [true_bb, false_bb] } => { + mir::Terminator::If { ref cond, targets: (true_bb, false_bb) } => { let cond = self.trans_operand(bcx, cond); let lltrue = self.llblock(true_bb); let llfalse = self.llblock(false_bb); diff --git a/src/librustc_trans/trans/mir/rvalue.rs b/src/librustc_trans/trans/mir/rvalue.rs index 17e4ec8e827..529e65dace0 100644 --- a/src/librustc_trans/trans/mir/rvalue.rs +++ b/src/librustc_trans/trans/mir/rvalue.rs @@ -120,7 +120,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { bcx } - mir::Rvalue::InlineAsm(inline_asm) => { + mir::Rvalue::InlineAsm(ref inline_asm) => { asm::trans_inline_asm(bcx, inline_asm) } diff --git a/src/librustc_unicode/char.rs b/src/librustc_unicode/char.rs index 3824dd0e436..455e2feee4c 100644 --- a/src/librustc_unicode/char.rs +++ b/src/librustc_unicode/char.rs @@ -386,9 +386,10 @@ impl char { /// Returns the number of 16-bit code units this `char` would need if /// encoded in UTF-16. /// - /// See the documentation for [`len_utf8()`][len_utf8] for more explanation - /// of this concept. This function is a mirror, but for UTF-16 instead of - /// UTF-8. + /// See the documentation for [`len_utf8()`] for more explanation of this + /// concept. This function is a mirror, but for UTF-16 instead of UTF-8. + /// + /// [`len_utf8()`]: #method.len_utf8 /// /// # Examples /// diff --git a/src/librustc_unicode/lib.rs b/src/librustc_unicode/lib.rs index e440b117186..8bde24d2b0c 100644 --- a/src/librustc_unicode/lib.rs +++ b/src/librustc_unicode/lib.rs @@ -48,8 +48,8 @@ pub mod char; #[allow(deprecated)] pub mod str { pub use u_str::{UnicodeStr, SplitWhitespace}; - pub use u_str::{utf8_char_width, is_utf16, Utf16Items, Utf16Item}; - pub use u_str::{utf16_items, Utf16Encoder}; + pub use u_str::{utf8_char_width, is_utf16}; + pub use u_str::{Utf16Encoder}; } // For use in libcollections, not re-exported in libstd. diff --git a/src/librustc_unicode/u_str.rs b/src/librustc_unicode/u_str.rs index 4d9f5d5fdd4..f65c05672f6 100644 --- a/src/librustc_unicode/u_str.rs +++ b/src/librustc_unicode/u_str.rs @@ -13,10 +13,8 @@ //! This module provides functionality to `str` that requires the Unicode //! methods provided by the unicode parts of the CharExt trait. -use char::{DecodeUtf16, decode_utf16}; use core::char; -use core::iter::{Cloned, Filter}; -use core::slice; +use core::iter::Filter; use core::str::Split; /// An iterator over the non-whitespace substrings of a string, @@ -127,97 +125,6 @@ pub fn is_utf16(v: &[u16]) -> bool { } } -/// An iterator that decodes UTF-16 encoded codepoints from a vector -/// of `u16`s. -#[rustc_deprecated(since = "1.4.0", reason = "renamed to `char::DecodeUtf16`")] -#[unstable(feature = "decode_utf16", reason = "not exposed in std", issue = "27830")] -#[allow(deprecated)] -#[derive(Clone)] -pub struct Utf16Items<'a> { - decoder: DecodeUtf16<Cloned<slice::Iter<'a, u16>>>, -} - -/// The possibilities for values decoded from a `u16` stream. -#[rustc_deprecated(since = "1.4.0", - reason = "`char::DecodeUtf16` uses `Result<char, u16>` instead")] -#[unstable(feature = "decode_utf16", reason = "not exposed in std", issue = "27830")] -#[allow(deprecated)] -#[derive(Copy, PartialEq, Eq, Clone, Debug)] -pub enum Utf16Item { - /// A valid codepoint. - ScalarValue(char), - /// An invalid surrogate without its pair. - LoneSurrogate(u16), -} - -#[allow(deprecated)] -impl Utf16Item { - /// Convert `self` to a `char`, taking `LoneSurrogate`s to the - /// replacement character (U+FFFD). - #[inline] - pub fn to_char_lossy(&self) -> char { - match *self { - Utf16Item::ScalarValue(c) => c, - Utf16Item::LoneSurrogate(_) => '\u{FFFD}', - } - } -} - -#[rustc_deprecated(since = "1.4.0", reason = "use `char::DecodeUtf16` instead")] -#[unstable(feature = "decode_utf16", reason = "not exposed in std", issue = "27830")] -#[allow(deprecated)] -impl<'a> Iterator for Utf16Items<'a> { - type Item = Utf16Item; - - fn next(&mut self) -> Option<Utf16Item> { - self.decoder.next().map(|result| { - match result { - Ok(c) => Utf16Item::ScalarValue(c), - Err(s) => Utf16Item::LoneSurrogate(s), - } - }) - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - self.decoder.size_hint() - } -} - -/// Create an iterator over the UTF-16 encoded codepoints in `v`, -/// returning invalid surrogates as `LoneSurrogate`s. -/// -/// # Examples -/// -/// ``` -/// #![feature(unicode, decode_utf16)] -/// # #![allow(deprecated)] -/// -/// extern crate rustc_unicode; -/// -/// use rustc_unicode::str::Utf16Item::{ScalarValue, LoneSurrogate}; -/// -/// fn main() { -/// // 𝄞mus<invalid>ic<invalid> -/// let v = [0xD834, 0xDD1E, 0x006d, 0x0075, -/// 0x0073, 0xDD1E, 0x0069, 0x0063, -/// 0xD834]; -/// -/// assert_eq!(rustc_unicode::str::utf16_items(&v).collect::<Vec<_>>(), -/// vec![ScalarValue('𝄞'), -/// ScalarValue('m'), ScalarValue('u'), ScalarValue('s'), -/// LoneSurrogate(0xDD1E), -/// ScalarValue('i'), ScalarValue('c'), -/// LoneSurrogate(0xD834)]); -/// } -/// ``` -#[rustc_deprecated(since = "1.4.0", reason = "renamed to `char::decode_utf16`")] -#[unstable(feature = "decode_utf16", reason = "not exposed in std", issue = "27830")] -#[allow(deprecated)] -pub fn utf16_items<'a>(v: &'a [u16]) -> Utf16Items<'a> { - Utf16Items { decoder: decode_utf16(v.iter().cloned()) } -} - /// Iterator adaptor for encoding `char`s to UTF-16. #[derive(Clone)] pub struct Utf16Encoder<I> { diff --git a/src/libstd/collections/hash/bench.rs b/src/libstd/collections/hash/bench.rs index ac21ae0f0aa..9fae9af2d54 100644 --- a/src/libstd/collections/hash/bench.rs +++ b/src/libstd/collections/hash/bench.rs @@ -14,7 +14,6 @@ extern crate test; use prelude::v1::*; use self::test::Bencher; -use iter::range_inclusive; #[bench] fn new_drop(b : &mut Bencher) { @@ -43,7 +42,7 @@ fn grow_by_insertion(b: &mut Bencher) { let mut m = HashMap::new(); - for i in range_inclusive(1, 1000) { + for i in 1..1001 { m.insert(i, i); } @@ -61,12 +60,12 @@ fn find_existing(b: &mut Bencher) { let mut m = HashMap::new(); - for i in range_inclusive(1, 1000) { + for i in 1..1001 { m.insert(i, i); } b.iter(|| { - for i in range_inclusive(1, 1000) { + for i in 1..1001 { m.contains_key(&i); } }); @@ -78,12 +77,12 @@ fn find_nonexisting(b: &mut Bencher) { let mut m = HashMap::new(); - for i in range_inclusive(1, 1000) { + for i in 1..1001 { m.insert(i, i); } b.iter(|| { - for i in range_inclusive(1001, 2000) { + for i in 1001..2001 { m.contains_key(&i); } }); @@ -95,7 +94,7 @@ fn hashmap_as_queue(b: &mut Bencher) { let mut m = HashMap::new(); - for i in range_inclusive(1, 1000) { + for i in 1..1001 { m.insert(i, i); } @@ -114,7 +113,7 @@ fn get_remove_insert(b: &mut Bencher) { let mut m = HashMap::new(); - for i in range_inclusive(1, 1000) { + for i in 1..1001 { m.insert(i, i); } diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 77c4149f992..38c080febf1 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1681,7 +1681,6 @@ mod test_map { use super::HashMap; use super::Entry::{Occupied, Vacant}; - use iter::range_inclusive; use cell::RefCell; use rand::{thread_rng, Rng}; @@ -1877,42 +1876,42 @@ mod test_map { for _ in 0..10 { assert!(m.is_empty()); - for i in range_inclusive(1, 1000) { + for i in 1..1001 { assert!(m.insert(i, i).is_none()); - for j in range_inclusive(1, i) { + for j in 1..i+1 { let r = m.get(&j); assert_eq!(r, Some(&j)); } - for j in range_inclusive(i+1, 1000) { + for j in i+1..1001 { let r = m.get(&j); assert_eq!(r, None); } } - for i in range_inclusive(1001, 2000) { + for i in 1001..2001 { assert!(!m.contains_key(&i)); } // remove forwards - for i in range_inclusive(1, 1000) { + for i in 1..1001 { assert!(m.remove(&i).is_some()); - for j in range_inclusive(1, i) { + for j in 1..i+1 { assert!(!m.contains_key(&j)); } - for j in range_inclusive(i+1, 1000) { + for j in i+1..1001 { assert!(m.contains_key(&j)); } } - for i in range_inclusive(1, 1000) { + for i in 1..1001 { assert!(!m.contains_key(&i)); } - for i in range_inclusive(1, 1000) { + for i in 1..1001 { assert!(m.insert(i, i).is_none()); } @@ -1920,11 +1919,11 @@ mod test_map { for i in (1..1001).rev() { assert!(m.remove(&i).is_some()); - for j in range_inclusive(i, 1000) { + for j in i..1001 { assert!(!m.contains_key(&j)); } - for j in range_inclusive(1, i-1) { + for j in 1..i { assert!(m.contains_key(&j)); } } diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 40fb450bea1..318ff410cba 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -211,18 +211,6 @@ impl CString { /// The only appropriate argument is a pointer obtained by calling /// `into_raw`. The length of the string will be recalculated /// using the pointer. - #[unstable(feature = "cstr_memory2", reason = "recently added", - issue = "27769")] - #[rustc_deprecated(since = "1.4.0", reason = "renamed to from_raw")] - pub unsafe fn from_ptr(ptr: *const c_char) -> CString { - CString::from_raw(ptr as *mut _) - } - - /// Retakes ownership of a CString that was transferred to C. - /// - /// The only appropriate argument is a pointer obtained by calling - /// `into_raw`. The length of the string will be recalculated - /// using the pointer. #[stable(feature = "cstr_memory", since = "1.4.0")] pub unsafe fn from_raw(ptr: *mut c_char) -> CString { let len = libc::strlen(ptr) + 1; // Including the NUL byte @@ -238,21 +226,6 @@ impl CString { /// this string. /// /// Failure to call `from_raw` will lead to a memory leak. - #[unstable(feature = "cstr_memory2", reason = "recently added", - issue = "27769")] - #[rustc_deprecated(since = "1.4.0", reason = "renamed to into_raw")] - pub fn into_ptr(self) -> *const c_char { - self.into_raw() as *const _ - } - - /// Transfers ownership of the string to a C caller. - /// - /// The pointer must be returned to Rust and reconstituted using - /// `from_raw` to be properly deallocated. Specifically, one - /// should *not* use the standard C `free` function to deallocate - /// this string. - /// - /// Failure to call `from_raw` will lead to a memory leak. #[stable(feature = "cstr_memory", since = "1.4.0")] pub fn into_raw(self) -> *mut c_char { Box::into_raw(self.inner) as *mut c_char diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index bfad2248359..25a05efd026 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -1178,85 +1178,6 @@ impl Iterator for WalkDir { } } -/// Utility methods for paths. -#[unstable(feature = "path_ext_deprecated", - reason = "The precise set of methods exposed on this trait may \ - change and some methods may be removed. For stable code, \ - see the std::fs::metadata function.", - issue = "27725")] -#[rustc_deprecated(since = "1.5.0", reason = "replaced with inherent methods")] -pub trait PathExt { - /// Gets information on the file, directory, etc at this path. - /// - /// Consult the `fs::metadata` documentation for more info. - /// - /// This call preserves identical runtime/error semantics with - /// `fs::metadata`. - fn metadata(&self) -> io::Result<Metadata>; - - /// Gets information on the file, directory, etc at this path. - /// - /// Consult the `fs::symlink_metadata` documentation for more info. - /// - /// This call preserves identical runtime/error semantics with - /// `fs::symlink_metadata`. - fn symlink_metadata(&self) -> io::Result<Metadata>; - - /// Returns the canonical form of a path, normalizing all components and - /// eliminate all symlinks. - /// - /// This call preserves identical runtime/error semantics with - /// `fs::canonicalize`. - fn canonicalize(&self) -> io::Result<PathBuf>; - - /// Reads the symlink at this path. - /// - /// For more information see `fs::read_link`. - fn read_link(&self) -> io::Result<PathBuf>; - - /// Reads the directory at this path. - /// - /// For more information see `fs::read_dir`. - fn read_dir(&self) -> io::Result<ReadDir>; - - /// Boolean value indicator whether the underlying file exists on the local - /// filesystem. Returns false in exactly the cases where `fs::metadata` - /// fails. - fn exists(&self) -> bool; - - /// Whether the underlying implementation (be it a file path, or something - /// else) points at a "regular file" on the FS. Will return false for paths - /// to non-existent locations or directories or other non-regular files - /// (named pipes, etc). Follows links when making this determination. - fn is_file(&self) -> bool; - - /// Whether the underlying implementation (be it a file path, or something - /// else) is pointing at a directory in the underlying FS. Will return - /// false for paths to non-existent locations or if the item is not a - /// directory (eg files, named pipes, etc). Follows links when making this - /// determination. - fn is_dir(&self) -> bool; -} - -#[allow(deprecated)] -#[unstable(feature = "path_ext_deprecated", issue = "27725")] -impl PathExt for Path { - fn metadata(&self) -> io::Result<Metadata> { metadata(self) } - fn symlink_metadata(&self) -> io::Result<Metadata> { symlink_metadata(self) } - fn canonicalize(&self) -> io::Result<PathBuf> { canonicalize(self) } - fn read_link(&self) -> io::Result<PathBuf> { read_link(self) } - fn read_dir(&self) -> io::Result<ReadDir> { read_dir(self) } - fn exists(&self) -> bool { metadata(self).is_ok() } - - fn is_file(&self) -> bool { - metadata(self).map(|s| s.is_file()).unwrap_or(false) - } - - fn is_dir(&self) -> bool { - metadata(self).map(|s| s.is_dir()).unwrap_or(false) - } -} - /// Changes the permissions found on a file or a directory. /// /// # Examples diff --git a/src/libstd/io/prelude.rs b/src/libstd/io/prelude.rs index f588ec60589..8772d0f5b09 100644 --- a/src/libstd/io/prelude.rs +++ b/src/libstd/io/prelude.rs @@ -22,6 +22,3 @@ #[stable(feature = "rust1", since = "1.0.0")] pub use super::{Read, Write, BufRead, Seek}; -#[allow(deprecated)] -#[unstable(feature = "path_ext_deprecated", issue = "27725")] -pub use fs::PathExt; diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 8e6c32ff2fc..c8b8caee84e 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -233,7 +233,6 @@ #![feature(const_fn)] #![feature(core_float)] #![feature(core_intrinsics)] -#![feature(core_simd)] #![feature(decode_utf16)] #![feature(drop_in_place)] #![feature(dropck_parametricity)] @@ -255,6 +254,7 @@ #![feature(rand)] #![feature(range_inclusive)] #![feature(raw)] +#![feature(repr_simd)] #![feature(reflect_marker)] #![feature(shared)] #![feature(slice_bytes)] @@ -334,9 +334,6 @@ pub use core::ptr; #[stable(feature = "rust1", since = "1.0.0")] pub use core::raw; #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated)] -pub use core::simd; -#[stable(feature = "rust1", since = "1.0.0")] pub use core::result; #[stable(feature = "rust1", since = "1.0.0")] pub use core::option; diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index c87becd741e..30bee80fbf6 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -18,7 +18,7 @@ use core::num; use intrinsics; use libc::c_int; -use num::{FpCategory, ParseFloatError}; +use num::FpCategory; #[stable(feature = "rust1", since = "1.0.0")] pub use core::f32::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON}; @@ -126,16 +126,6 @@ mod cmath { #[cfg(not(test))] #[lang = "f32"] impl f32 { - /// Parses a float as with a given radix - #[unstable(feature = "float_from_str_radix", reason = "recently moved API", - issue = "27736")] - #[rustc_deprecated(since = "1.4.0", - reason = "unclear how useful or correct this is")] - #[allow(deprecated)] - pub fn from_str_radix(s: &str, radix: u32) -> Result<f32, ParseFloatError> { - num::Float::from_str_radix(s, radix) - } - /// Returns `true` if this value is `NaN` and false otherwise. /// /// ``` @@ -1712,11 +1702,9 @@ mod tests { #[test] fn test_ldexp() { - // We have to use from_str until base-2 exponents - // are supported in floating-point literals - let f1: f32 = f32::from_str_radix("1p-123", 16).unwrap(); - let f2: f32 = f32::from_str_radix("1p-111", 16).unwrap(); - let f3: f32 = f32::from_str_radix("1.Cp-12", 16).unwrap(); + let f1 = 2.0f32.powi(-123); + let f2 = 2.0f32.powi(-111); + let f3 = 1.75 * 2.0f32.powi(-12); assert_eq!(f32::ldexp(1f32, -123), f1); assert_eq!(f32::ldexp(1f32, -111), f2); assert_eq!(f32::ldexp(1.75f32, -12), f3); @@ -1734,11 +1722,9 @@ mod tests { #[test] fn test_frexp() { - // We have to use from_str until base-2 exponents - // are supported in floating-point literals - let f1: f32 = f32::from_str_radix("1p-123", 16).unwrap(); - let f2: f32 = f32::from_str_radix("1p-111", 16).unwrap(); - let f3: f32 = f32::from_str_radix("1.Cp-123", 16).unwrap(); + let f1 = 2.0f32.powi(-123); + let f2 = 2.0f32.powi(-111); + let f3 = 1.75 * 2.0f32.powi(-123); let (x1, exp1) = f1.frexp(); let (x2, exp2) = f2.frexp(); let (x3, exp3) = f3.frexp(); diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index 6b9c753443b..d444b259445 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -18,7 +18,7 @@ use core::num; use intrinsics; use libc::c_int; -use num::{FpCategory, ParseFloatError}; +use num::FpCategory; #[stable(feature = "rust1", since = "1.0.0")] pub use core::f64::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON}; @@ -83,16 +83,6 @@ mod cmath { #[cfg(not(test))] #[lang = "f64"] impl f64 { - /// Parses a float as with a given radix - #[unstable(feature = "float_from_str_radix", reason = "recently moved API", - issue = "27736")] - #[rustc_deprecated(since = "1.4.0", - reason = "unclear how useful or correct this is")] - #[allow(deprecated)] - pub fn from_str_radix(s: &str, radix: u32) -> Result<f64, ParseFloatError> { - num::Float::from_str_radix(s, radix) - } - /// Returns `true` if this value is `NaN` and false otherwise. /// /// ``` @@ -1569,11 +1559,9 @@ mod tests { #[test] fn test_ldexp() { - // We have to use from_str until base-2 exponents - // are supported in floating-point literals - let f1: f64 = f64::from_str_radix("1p-123", 16).unwrap(); - let f2: f64 = f64::from_str_radix("1p-111", 16).unwrap(); - let f3: f64 = f64::from_str_radix("1.Cp-12", 16).unwrap(); + let f1 = 2.0f64.powi(-123); + let f2 = 2.0f64.powi(-111); + let f3 = 1.75 * 2.0f64.powi(-12); assert_eq!(f64::ldexp(1f64, -123), f1); assert_eq!(f64::ldexp(1f64, -111), f2); assert_eq!(f64::ldexp(1.75f64, -12), f3); @@ -1591,11 +1579,9 @@ mod tests { #[test] fn test_frexp() { - // We have to use from_str until base-2 exponents - // are supported in floating-point literals - let f1: f64 = f64::from_str_radix("1p-123", 16).unwrap(); - let f2: f64 = f64::from_str_radix("1p-111", 16).unwrap(); - let f3: f64 = f64::from_str_radix("1.Cp-123", 16).unwrap(); + let f1 = 2.0f64.powi(-123); + let f2 = 2.0f64.powi(-111); + let f3 = 1.75 * 2.0f64.powi(-123); let (x1, exp1) = f1.frexp(); let (x2, exp2) = f2.frexp(); let (x3, exp3) = f3.frexp(); diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index fd422d3b397..afeb4231aba 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -350,7 +350,7 @@ mod prim_slice { } /// ``` /// /// [`.as_ptr()`]: #method.as_ptr -/// [`len()`]: # method.len +/// [`len()`]: #method.len mod prim_str { } #[doc(primitive = "tuple")] diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 7ef504fba81..5e0368f35cc 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -16,7 +16,10 @@ use os::raw::{c_int, c_uint, c_ulong, c_long, c_longlong, c_ushort}; use os::raw::{c_char, c_short, c_ulonglong}; use libc::{wchar_t, size_t, c_void}; use ptr; -use simd; + +#[cfg_attr(not(stage0), repr(simd))] +#[repr(C)] +struct u64x2(u64, u64); pub use self::GET_FILEEX_INFO_LEVELS::*; pub use self::FILE_INFO_BY_HANDLE_CLASS::*; @@ -783,7 +786,7 @@ pub struct FLOATING_SAVE_AREA { #[cfg(target_arch = "x86_64")] #[repr(C)] pub struct CONTEXT { - _align_hack: [simd::u64x2; 0], // FIXME align on 16-byte + _align_hack: [u64x2; 0], // FIXME align on 16-byte pub P1Home: DWORDLONG, pub P2Home: DWORDLONG, pub P3Home: DWORDLONG, @@ -843,7 +846,7 @@ pub struct CONTEXT { #[cfg(target_arch = "x86_64")] #[repr(C)] pub struct M128A { - _align_hack: [simd::u64x2; 0], // FIXME align on 16-byte + _align_hack: [u64x2; 0], // FIXME align on 16-byte pub Low: c_ulonglong, pub High: c_longlong } @@ -851,7 +854,7 @@ pub struct M128A { #[cfg(target_arch = "x86_64")] #[repr(C)] pub struct FLOATING_SAVE_AREA { - _align_hack: [simd::u64x2; 0], // FIXME align on 16-byte + _align_hack: [u64x2; 0], // FIXME align on 16-byte _Dummy: [u8; 512] // FIXME: Fill this out } diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index 119429cc584..870247f7e82 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -13,6 +13,7 @@ #![unstable(feature = "thread_local_internals", issue = "0")] use cell::UnsafeCell; +use mem; // Sure wish we had macro hygiene, no? #[doc(hidden)] @@ -226,7 +227,21 @@ impl<T: 'static> LocalKey<T> { // just in case initialization fails. let value = (self.init)(); let ptr = slot.get(); - *ptr = Some(value); + + // note that this can in theory just be `*ptr = Some(value)`, but due to + // the compiler will currently codegen that pattern with something like: + // + // ptr::drop_in_place(ptr) + // ptr::write(ptr, Some(value)) + // + // Due to this pattern it's possible for the destructor of the value in + // `ptr` (e.g. if this is being recursively initialized) to re-access + // TLS, in which case there will be a `&` and `&mut` pointer to the same + // value (an aliasing violation). To avoid setting the "I'm running a + // destructor" flag we just use `mem::replace` which should sequence the + // operations a little differently and make this safe to call. + mem::replace(&mut *ptr, Some(value)); + (*ptr).as_ref().unwrap() } diff --git a/src/test/bench/shootout-mandelbrot.rs b/src/test/bench/shootout-mandelbrot.rs deleted file mode 100644 index 21ac23253c8..00000000000 --- a/src/test/bench/shootout-mandelbrot.rs +++ /dev/null @@ -1,209 +0,0 @@ -// The Computer Language Benchmarks Game -// http://benchmarksgame.alioth.debian.org/ -// -// contributed by the Rust Project Developers - -// Copyright (c) 2012-2014 The Rust Project Developers -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// - Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// - Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in -// the documentation and/or other materials provided with the -// distribution. -// -// - Neither the name of "The Computer Language Benchmarks Game" nor -// the name of "The Computer Language Shootout Benchmarks" nor the -// names of its contributors may be used to endorse or promote -// products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED -// OF THE POSSIBILITY OF SUCH DAMAGE. - -#![feature(core_simd, core)] - -// ignore-pretty very bad with line comments - -use std::env; -use std::io::prelude::*; -use std::io; -use std::simd::f64x2; -use std::sync::Arc; -use std::thread; - -const ITER: usize = 50; -const LIMIT: f64 = 2.0; -const WORKERS: usize = 16; - -fn mandelbrot<W: Write>(w: usize, mut out: W) -> io::Result<()> { - assert_eq!(WORKERS % 2, 0); - - // Ensure w and h are multiples of 8. - let w = (w + 7) / 8 * 8; - let h = w; - - let chunk_size = h / WORKERS; - - // Account for remainders in workload division, e.g. 1000 / 16 = 62.5 - let last_chunk_size = if h % WORKERS != 0 { - chunk_size + h % WORKERS - } else { - chunk_size - }; - - // precalc values - let inverse_w_doubled = 2.0 / w as f64; - let inverse_h_doubled = 2.0 / h as f64; - let v_inverses = f64x2(inverse_w_doubled, inverse_h_doubled); - let v_consts = f64x2(1.5, 1.0); - - // A lot of this code assumes this (so do other lang benchmarks) - assert_eq!(w, h); - let mut precalc_r = Vec::with_capacity(w); - let mut precalc_i = Vec::with_capacity(h); - - let precalc_futures = (0..WORKERS).map(|i| { - thread::spawn(move|| { - let mut rs = Vec::with_capacity(w / WORKERS); - let mut is = Vec::with_capacity(w / WORKERS); - - let start = i * chunk_size; - let end = if i == (WORKERS - 1) { - start + last_chunk_size - } else { - (i + 1) * chunk_size - }; - - // This assumes w == h - for x in start..end { - let xf = x as f64; - let xy = f64x2(xf, xf); - - let f64x2(r, i) = xy * v_inverses - v_consts; - rs.push(r); - is.push(i); - } - - (rs, is) - }) - }).collect::<Vec<_>>(); - - for res in precalc_futures { - let (rs, is) = res.join().unwrap(); - precalc_r.extend(rs); - precalc_i.extend(is); - } - - assert_eq!(precalc_r.len(), w); - assert_eq!(precalc_i.len(), h); - - let arc_init_r = Arc::new(precalc_r); - let arc_init_i = Arc::new(precalc_i); - - let data = (0..WORKERS).map(|i| { - let vec_init_r = arc_init_r.clone(); - let vec_init_i = arc_init_i.clone(); - - thread::spawn(move|| { - let mut res: Vec<u8> = Vec::with_capacity((chunk_size * w) / 8); - let init_r_slice = vec_init_r; - - let start = i * chunk_size; - let end = if i == (WORKERS - 1) { - start + last_chunk_size - } else { - (i + 1) * chunk_size - }; - - for &init_i in &vec_init_i[start..end] { - write_line(init_i, &init_r_slice, &mut res); - } - - res - }) - }).collect::<Vec<_>>(); - - try!(writeln!(&mut out, "P4\n{} {}", w, h)); - for res in data { - try!(out.write_all(&res.join().unwrap())); - } - out.flush() -} - -fn write_line(init_i: f64, vec_init_r: &[f64], res: &mut Vec<u8>) { - let v_init_i : f64x2 = f64x2(init_i, init_i); - let v_2 : f64x2 = f64x2(2.0, 2.0); - const LIMIT_SQUARED: f64 = LIMIT * LIMIT; - - for chunk_init_r in vec_init_r.chunks(8) { - let mut cur_byte = 0xff; - let mut i = 0; - - while i < 8 { - let v_init_r = f64x2(chunk_init_r[i], chunk_init_r[i + 1]); - let mut cur_r = v_init_r; - let mut cur_i = v_init_i; - let mut r_sq = v_init_r * v_init_r; - let mut i_sq = v_init_i * v_init_i; - - let mut b = 0; - for _ in 0..ITER { - let r = cur_r; - let i = cur_i; - - cur_i = v_2 * r * i + v_init_i; - cur_r = r_sq - i_sq + v_init_r; - - let f64x2(bit1, bit2) = r_sq + i_sq; - - if bit1 > LIMIT_SQUARED { - b |= 2; - if b == 3 { break; } - } - - if bit2 > LIMIT_SQUARED { - b |= 1; - if b == 3 { break; } - } - - r_sq = cur_r * cur_r; - i_sq = cur_i * cur_i; - } - - cur_byte = (cur_byte << 2) + b; - i += 2; - } - - res.push(cur_byte^!0); - } -} - -fn main() { - let mut args = env::args(); - let res = if args.len() < 2 { - println!("Test mode: do not dump the image because it's not utf8, \ - which interferes with the test runner."); - mandelbrot(1000, io::sink()) - } else { - mandelbrot(args.nth(1).unwrap().parse().unwrap(), io::stdout()) - }; - res.unwrap(); -} diff --git a/src/test/bench/shootout-spectralnorm.rs b/src/test/bench/shootout-spectralnorm.rs deleted file mode 100644 index a6c77eaf7c6..00000000000 --- a/src/test/bench/shootout-spectralnorm.rs +++ /dev/null @@ -1,123 +0,0 @@ -// The Computer Language Benchmarks Game -// http://benchmarksgame.alioth.debian.org/ -// -// contributed by the Rust Project Developers - -// Copyright (c) 2012-2014 The Rust Project Developers -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// - Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// - Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in -// the documentation and/or other materials provided with the -// distribution. -// -// - Neither the name of "The Computer Language Benchmarks Game" nor -// the name of "The Computer Language Shootout Benchmarks" nor the -// names of its contributors may be used to endorse or promote -// products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED -// OF THE POSSIBILITY OF SUCH DAMAGE. - -// no-pretty-expanded FIXME #15189 - -#![allow(non_snake_case)] -#![feature(unboxed_closures, iter_arith, core_simd, scoped)] - -use std::thread; -use std::env; -use std::simd::f64x2; - -fn main() { - let mut args = env::args(); - let answer = spectralnorm(if env::var_os("RUST_BENCH").is_some() { - 5500 - } else if args.len() < 2 { - 2000 - } else { - args.nth(1).unwrap().parse().unwrap() - }); - println!("{:.9}", answer); -} - -fn spectralnorm(n: usize) -> f64 { - assert!(n % 2 == 0, "only even lengths are accepted"); - let mut u = vec![1.0; n]; - let mut v = u.clone(); - let mut tmp = v.clone(); - for _ in 0..10 { - mult_AtAv(&u, &mut v, &mut tmp); - mult_AtAv(&v, &mut u, &mut tmp); - } - (dot(&u, &v) / dot(&v, &v)).sqrt() -} - -fn mult_AtAv(v: &[f64], out: &mut [f64], tmp: &mut [f64]) { - mult_Av(v, tmp); - mult_Atv(tmp, out); -} - -fn mult_Av(v: &[f64], out: &mut [f64]) { - parallel(out, |start, out| mult(v, out, start, |i, j| A(i, j))); -} - -fn mult_Atv(v: &[f64], out: &mut [f64]) { - parallel(out, |start, out| mult(v, out, start, |i, j| A(j, i))); -} - -fn mult<F>(v: &[f64], out: &mut [f64], start: usize, a: F) - where F: Fn(usize, usize) -> f64 { - for (i, slot) in out.iter_mut().enumerate().map(|(i, s)| (i + start, s)) { - let mut sum = f64x2(0.0, 0.0); - for (j, chunk) in v.chunks(2).enumerate().map(|(j, s)| (2 * j, s)) { - let top = f64x2(chunk[0], chunk[1]); - let bot = f64x2(a(i, j), a(i, j + 1)); - sum = sum + top / bot; - } - let f64x2(a, b) = sum; - *slot = a + b; - } -} - -fn A(i: usize, j: usize) -> f64 { - ((i + j) * (i + j + 1) / 2 + i + 1) as f64 -} - -fn dot(v: &[f64], u: &[f64]) -> f64 { - v.iter().zip(u).map(|(a, b)| *a * *b).sum() -} - - -// Executes a closure in parallel over the given mutable slice. The closure `f` -// is run in parallel and yielded the starting index within `v` as well as a -// sub-slice of `v`. -fn parallel<'a,T, F>(v: &mut [T], ref f: F) - where T: Send + Sync + 'a, - F: Fn(usize, &mut [T]) + Sync + 'a { - // FIXME: pick a more appropriate parallel factor - // FIXME: replace with thread::scoped when it exists again - let parallelism = 4; - let size = v.len() / parallelism + 1; - v.chunks_mut(size).enumerate().map(|(i, chunk)| { - f(i * size, chunk) - }).collect::<Vec<_>>(); -} diff --git a/src/test/compile-fail/feature-gate-simd-ffi.rs b/src/test/compile-fail/feature-gate-simd-ffi.rs index f7bd2fcbceb..31c055f229c 100644 --- a/src/test/compile-fail/feature-gate-simd-ffi.rs +++ b/src/test/compile-fail/feature-gate-simd-ffi.rs @@ -8,17 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(repr_simd, core_simd)] -#![allow(dead_code, deprecated)] +#![feature(repr_simd)] +#![allow(dead_code)] -use std::simd::f32x4; - -#[repr(simd)] #[derive(Copy, Clone)] #[repr(C)] struct LocalSimd(u8, u8); +#[repr(simd)] +#[derive(Copy, Clone)] +#[repr(C)] +struct LocalSimd(u8, u8); extern { - fn foo() -> f32x4; //~ ERROR use of SIMD type - fn bar(x: f32x4); //~ ERROR use of SIMD type - fn baz() -> LocalSimd; //~ ERROR use of SIMD type fn qux(x: LocalSimd); //~ ERROR use of SIMD type } diff --git a/src/test/compile-fail/issue-26656.rs b/src/test/compile-fail/issue-26656.rs new file mode 100644 index 00000000000..e5fa65498de --- /dev/null +++ b/src/test/compile-fail/issue-26656.rs @@ -0,0 +1,52 @@ +// 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. + +// Issue #26656: Verify that trait objects cannot bypass dropck. + +// Using this instead of Fn etc. to take HRTB out of the equation. +trait Trigger<B> { fn fire(&self, b: &mut B); } +impl<B: Button> Trigger<B> for () { + fn fire(&self, b: &mut B) { + b.push(); + } +} + +// Still unsound Zook +trait Button { fn push(&self); } +struct Zook<B> { button: B, trigger: Box<Trigger<B>+'static> } + +impl<B> Drop for Zook<B> { + fn drop(&mut self) { + self.trigger.fire(&mut self.button); + } +} + +// AND +struct Bomb { usable: bool } +impl Drop for Bomb { fn drop(&mut self) { self.usable = false; } } +impl Bomb { fn activate(&self) { assert!(self.usable) } } + +enum B<'a> { HarmlessButton, BigRedButton(&'a Bomb) } +impl<'a> Button for B<'a> { + fn push(&self) { + if let B::BigRedButton(borrowed) = *self { + borrowed.activate(); + } + } +} + +fn main() { + let (mut zook, ticking); + zook = Zook { button: B::HarmlessButton, + trigger: Box::new(()) }; + ticking = Bomb { usable: true }; + zook.button = B::BigRedButton(&ticking); + //~^ ERROR `ticking` does not live long enough +} diff --git a/src/test/debuginfo/simd.rs b/src/test/debuginfo/simd.rs index 24eb407612c..620e1a73b4d 100644 --- a/src/test/debuginfo/simd.rs +++ b/src/test/debuginfo/simd.rs @@ -43,9 +43,28 @@ #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] -#![feature(core_simd)] +#![feature(repr_simd)] -use std::simd::{i8x16, i16x8,i32x4,i64x2,u8x16,u16x8,u32x4,u64x2,f32x4,f64x2}; +#[repr(simd)] +struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8); +#[repr(simd)] +struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16); +#[repr(simd)] +struct i32x4(i32, i32, i32, i32); +#[repr(simd)] +struct i64x2(i64, i64); +#[repr(simd)] +struct u8x16(u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8); +#[repr(simd)] +struct u16x8(u16, u16, u16, u16, u16, u16, u16, u16); +#[repr(simd)] +struct u32x4(u32, u32, u32, u32); +#[repr(simd)] +struct u64x2(u64, u64); +#[repr(simd)] +struct f32x4(f32, f32, f32, f32); +#[repr(simd)] +struct f64x2(f64, f64); fn main() { diff --git a/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs b/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs index 405a3549cf1..562cfbe7a14 100644 --- a/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs +++ b/src/test/run-pass/method-mut-self-modifies-mut-slice-lvalue.rs @@ -12,8 +12,7 @@ // type is `&mut [u8]`, passes in a pointer to the lvalue and not a // temporary. Issue #19147. - -#![feature(slice_bytes)] +#![feature(clone_from_slice)] use std::slice; @@ -23,7 +22,7 @@ trait MyWriter { impl<'a> MyWriter for &'a mut [u8] { fn my_write(&mut self, buf: &[u8]) -> Result<(), ()> { - slice::bytes::copy_memory(buf, *self); + self.clone_from_slice(buf); let write_len = buf.len(); unsafe { diff --git a/src/test/run-pass/simd-issue-10604.rs b/src/test/run-pass/simd-issue-10604.rs deleted file mode 100644 index c3eef0f9c32..00000000000 --- a/src/test/run-pass/simd-issue-10604.rs +++ /dev/null @@ -1,17 +0,0 @@ -// 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. - -// pretty-expanded FIXME #23616 - -#![feature(core_simd)] - -pub fn main() { - let _o = None::<std::simd::i32x4>; -} diff --git a/src/test/run-pass/sync-send-iterators-in-libcore.rs b/src/test/run-pass/sync-send-iterators-in-libcore.rs index c4d070f8bfe..93178994815 100644 --- a/src/test/run-pass/sync-send-iterators-in-libcore.rs +++ b/src/test/run-pass/sync-send-iterators-in-libcore.rs @@ -14,11 +14,10 @@ #![feature(iter_empty)] #![feature(iter_once)] #![feature(iter_unfold)] -#![feature(range_inclusive)] #![feature(step_by)] #![feature(str_escape)] -use std::iter::{empty, once, range_inclusive, repeat}; +use std::iter::{empty, once, repeat}; fn is_sync<T>(_: T) where T: Sync {} fn is_send<T>(_: T) where T: Send {} @@ -98,7 +97,6 @@ fn main() { inspect(|_| ())); is_sync_send!((1..).step_by(2)); - is_sync_send!(range_inclusive(1, 1)); is_sync_send!((1..2).step_by(2)); is_sync_send!((1..2)); is_sync_send!((1..)); diff --git a/src/test/run-pass/tls-init-on-init.rs b/src/test/run-pass/tls-init-on-init.rs new file mode 100644 index 00000000000..195b814492a --- /dev/null +++ b/src/test/run-pass/tls-init-on-init.rs @@ -0,0 +1,51 @@ +// 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. + +#![feature(thread_local_state)] + +use std::thread::{self, LocalKeyState}; +use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; + +struct Foo { cnt: usize } + +thread_local!(static FOO: Foo = Foo::init()); + +static CNT: AtomicUsize = ATOMIC_USIZE_INIT; + +impl Foo { + fn init() -> Foo { + let cnt = CNT.fetch_add(1, Ordering::SeqCst); + if cnt == 0 { + FOO.with(|_| {}); + } + Foo { cnt: cnt } + } +} + +impl Drop for Foo { + fn drop(&mut self) { + if self.cnt == 1 { + FOO.with(|foo| assert_eq!(foo.cnt, 0)); + } else { + assert_eq!(self.cnt, 0); + match FOO.state() { + LocalKeyState::Valid => panic!("should not be in valid state"), + LocalKeyState::Uninitialized | + LocalKeyState::Destroyed => {} + } + } + } +} + +fn main() { + thread::spawn(|| { + FOO.with(|_| {}); + }).join().unwrap(); +} diff --git a/src/test/run-pass/while-let.rs b/src/test/run-pass/while-let.rs index efccff75a49..9ffba2c7999 100644 --- a/src/test/run-pass/while-let.rs +++ b/src/test/run-pass/while-let.rs @@ -14,7 +14,7 @@ use std::collections::BinaryHeap; fn make_pq() -> BinaryHeap<isize> { - BinaryHeap::from_vec(vec![1,2,3]) + BinaryHeap::from(vec![1,2,3]) } pub fn main() { |
